From f464e61b9a2aa638c8a56886dc157666e2e67b3f Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Wed, 22 Jun 2022 11:50:42 +0200 Subject: [PATCH] Implement fainting --- wearos/src/main/AndroidManifest.xml | 3 ++ .../wearos/habitica/MainApplication.kt | 22 ++++++++ .../wearos/habitica/models/user/User.kt | 2 + .../habitica/ui/activities/BaseActivity.kt | 8 +++ .../habitica/ui/activities/FaintActivity.kt | 38 ++++++++++++++ .../habitica/ui/activities/RYAActivity.kt | 17 +++++++ .../habitica/ui/activities/StatsActivity.kt | 6 +-- .../habitica/ui/viewmodels/FaintViewModel.kt | 15 ++++++ .../habitica/ui/viewmodels/RYAViewModel.kt | 13 +++++ .../habitica/ui/views/CircularProgressView.kt | 43 ++++++++-------- .../main/res/drawable-mdpi/broken_heart.png | Bin 0 -> 2343 bytes .../main/res/drawable-xhdpi/broken_heart.png | Bin 0 -> 4357 bytes .../main/res/drawable-xxhdpi/broken_heart.png | Bin 0 -> 6104 bytes wearos/src/main/res/layout/activity_faint.xml | 47 ++++++++++++++++++ wearos/src/main/res/layout/activity_rya.xml | 7 +++ wearos/src/main/res/layout/activity_stats.xml | 6 +-- wearos/src/main/res/values/attrs.xml | 2 +- wearos/src/main/res/values/strings.xml | 3 ++ wearos/src/main/res/values/styles.xml | 25 +++++++++- 19 files changed, 226 insertions(+), 31 deletions(-) create mode 100644 wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/FaintActivity.kt create mode 100644 wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/RYAActivity.kt create mode 100644 wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/FaintViewModel.kt create mode 100644 wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/RYAViewModel.kt create mode 100644 wearos/src/main/res/drawable-mdpi/broken_heart.png create mode 100644 wearos/src/main/res/drawable-xhdpi/broken_heart.png create mode 100644 wearos/src/main/res/drawable-xxhdpi/broken_heart.png create mode 100644 wearos/src/main/res/layout/activity_faint.xml create mode 100644 wearos/src/main/res/layout/activity_rya.xml diff --git a/wearos/src/main/AndroidManifest.xml b/wearos/src/main/AndroidManifest.xml index a4f5654b2..69aefbe0f 100644 --- a/wearos/src/main/AndroidManifest.xml +++ b/wearos/src/main/AndroidManifest.xml @@ -40,9 +40,12 @@ + + + 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 2a1938abd..79a1a37cc 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/MainApplication.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/MainApplication.kt @@ -1,17 +1,39 @@ package com.habitrpg.wearos.habitica import android.app.Application +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.UserRepository +import com.habitrpg.wearos.habitica.ui.activities.BaseActivity +import com.habitrpg.wearos.habitica.ui.activities.FaintActivity import dagger.hilt.android.HiltAndroidApp +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import javax.inject.Inject @HiltAndroidApp class MainApplication : Application() { + + @Inject lateinit var userRepository: UserRepository + override fun onCreate() { super.onCreate() HabiticaIconsHelper.init(this) MarkdownParser.setup(this) setupCoil() + + MainScope().launch { + userRepository.getUser().onEach { + if (it.isDead && BaseActivity.currentActivityClassName != FaintActivity::class.java.name) { + val intent = Intent(this@MainApplication, FaintActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + startActivity(intent) + } + }.collect() + } } } \ 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 4a3dca5ab..6941ab48e 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 @@ -5,6 +5,8 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) class User: Avatar { + val isDead: Boolean + get() = (stats?.hp ?: 0.0) <= 0.0 override val currentMount: String? get() = items?.currentMount override val currentPet: String? diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/BaseActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/BaseActivity.kt index c42da762e..85f019de4 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/BaseActivity.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/BaseActivity.kt @@ -13,6 +13,9 @@ import com.habitrpg.wearos.habitica.ui.viewmodels.BaseViewModel import com.habitrpg.wearos.habitica.ui.views.IndeterminateProgressView abstract class BaseActivity : ComponentActivity() { + companion object { + var currentActivityClassName: String? = null + } private lateinit var wrapperBinding: ActivityWrapperBinding protected lateinit var binding: B abstract val viewModel: VM @@ -35,6 +38,11 @@ abstract class BaseActivity : ComponentActivi } } + override fun onResume() { + super.onResume() + currentActivityClassName = this.localClassName + } + fun startAnimatingProgress() { if (progressView == null) { progressView = IndeterminateProgressView(this) diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/FaintActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/FaintActivity.kt new file mode 100644 index 000000000..0f1ad2d6b --- /dev/null +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/FaintActivity.kt @@ -0,0 +1,38 @@ +package com.habitrpg.wearos.habitica.ui.activities + +import android.os.Bundle +import androidx.activity.viewModels +import androidx.lifecycle.lifecycleScope +import com.habitrpg.android.habitica.databinding.ActivityFaintBinding +import com.habitrpg.wearos.habitica.ui.viewmodels.FaintViewModel +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.launch + +@AndroidEntryPoint +class FaintActivity: BaseActivity() { + override val viewModel: FaintViewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + binding = ActivityFaintBinding.inflate(layoutInflater) + super.onCreate(savedInstanceState) + binding.continueButton.setOnClickListener { + binding.continueButton.isEnabled = false + startAnimatingProgress() + lifecycleScope.launch(CoroutineExceptionHandler { _, _ -> + stopAnimatingProgress() + binding.continueButton.isEnabled = true + }) { + viewModel.revive() + finish() + } + } + + binding.hpBar.setPercentageValues(0f, 50f) + } + + override fun onResume() { + super.onResume() + binding.hpBar.animateProgress(50f, 2000) + } +} \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/RYAActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/RYAActivity.kt new file mode 100644 index 000000000..79eeb3a91 --- /dev/null +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/RYAActivity.kt @@ -0,0 +1,17 @@ +package com.habitrpg.wearos.habitica.ui.activities + +import android.os.Bundle +import androidx.activity.viewModels +import com.habitrpg.android.habitica.databinding.ActivityRyaBinding +import com.habitrpg.wearos.habitica.ui.viewmodels.RYAViewModel +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class RYAActivity: BaseActivity() { + override val viewModel: RYAViewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + binding = ActivityRyaBinding.inflate(layoutInflater) + super.onCreate(savedInstanceState) + } +} \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/StatsActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/StatsActivity.kt index 39426f2fc..a6fe343c0 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/StatsActivity.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/StatsActivity.kt @@ -38,16 +38,16 @@ class StatsActivity : BaseActivity() { } private fun updateBarViews(stats: Stats) { - binding.hpBar.setPercentageValues(stats.hp?.toInt() ?: 0, stats.maxHealth ?: 0) + binding.hpBar.setPercentageValues(stats.hp?.toFloat() ?: 0f, stats.maxHealth?.toFloat() ?: 0f) binding.hpBar.animateProgress() - binding.expBar.setPercentageValues(stats.exp?.toInt() ?: 0, stats.toNextLevel ?: 0) + binding.expBar.setPercentageValues(stats.exp?.toFloat() ?: 0f, stats.toNextLevel?.toFloat() ?: 0f) binding.expBar.animateProgress() if ((stats.lvl ?: 0) < 10) { binding.mpBar.visibility = View.GONE } else { - binding.mpBar.setPercentageValues(stats.mp?.toInt() ?: 0, stats.maxMP ?: 0) + binding.mpBar.setPercentageValues(stats.mp?.toFloat() ?: 0f, stats.maxMP?.toFloat() ?: 0f) binding.mpBar.animateProgress() } } diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/FaintViewModel.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/FaintViewModel.kt new file mode 100644 index 000000000..93d03195f --- /dev/null +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/FaintViewModel.kt @@ -0,0 +1,15 @@ +package com.habitrpg.wearos.habitica.ui.viewmodels + +import com.habitrpg.wearos.habitica.data.repositories.UserRepository +import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class FaintViewModel @Inject constructor(userRepository: UserRepository, + exceptionBuilder: ExceptionHandlerBuilder +) : BaseViewModel(userRepository, exceptionBuilder) { + suspend fun revive() { + userRepository.revive() + } +} diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/RYAViewModel.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/RYAViewModel.kt new file mode 100644 index 000000000..b09aa2db8 --- /dev/null +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/RYAViewModel.kt @@ -0,0 +1,13 @@ +package com.habitrpg.wearos.habitica.ui.viewmodels + +import com.habitrpg.wearos.habitica.data.repositories.UserRepository +import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class RYAViewModel @Inject constructor(userRepository: UserRepository, + exceptionBuilder: ExceptionHandlerBuilder +) : BaseViewModel(userRepository, exceptionBuilder) { + +} diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/views/CircularProgressView.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/views/CircularProgressView.kt index f48981fce..8b0a895c3 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/views/CircularProgressView.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/views/CircularProgressView.kt @@ -3,12 +3,15 @@ package com.habitrpg.wearos.habitica.ui.views import android.animation.PropertyValuesHolder import android.animation.ValueAnimator import android.content.Context -import android.graphics.* +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.RectF import android.util.AttributeSet import android.view.View import android.view.animation.AccelerateDecelerateInterpolator import com.habitrpg.android.habitica.R - +import com.habitrpg.common.habitica.extensions.dpToPx class CircularProgressView( context: Context?, @@ -16,31 +19,34 @@ class CircularProgressView( ) : View(context, attrs) { private val ovalSpace = RectF() private var ovalSize = (resources.displayMetrics.heightPixels / 2) - private var currentPercentage = 55 - private var PERCENTAGE_DIVIDER = 180 + private var currentPercentage = 55f + private var PERCENTAGE_DIVIDER = 180f private val ARC_FULL_ROTATION_DEGREE = 360 val attributes = context?.theme?.obtainStyledAttributes( attrs, R.styleable.CircularProgressView, 0, 0 ) - private val offset = attributes?.getInt(R.styleable.CircularProgressView_offset, 0) + private val offset = attributes?.getDimension(R.styleable.CircularProgressView_offset, 0f)?.toInt() private val backgroundArcColor = attributes?.getColor(R.styleable.CircularProgressView_backgroundArcColor, 0) ?: Color.GRAY private var fillArcColor = attributes?.getColor(R.styleable.CircularProgressView_arcFillColor, 0) ?: Color.GRAY - + set(value) { + field = value + fillArcPaint.color = fillArcColor + } private val parentArcPaint = Paint().apply { style = Paint.Style.STROKE isAntiAlias = true color = backgroundArcColor - strokeWidth = 10f + strokeWidth = 5f.dpToPx(context) } private var fillArcPaint = Paint().apply { style = Paint.Style.STROKE isAntiAlias = true color = fillArcColor - strokeWidth = 10f + strokeWidth = 5f.dpToPx(context) strokeCap = Paint.Cap.ROUND } @@ -82,36 +88,29 @@ class CircularProgressView( fun setBarColor(barColor: Int) { fillArcColor = context?.resources?.getColor(barColor, null) ?: backgroundArcColor - fillArcPaint = Paint().apply { - style = Paint.Style.STROKE - isAntiAlias = true - color = fillArcColor - strokeWidth = 10f - strokeCap = Paint.Cap.ROUND - } } - fun setPercentageValues(currentValue: Int, maxValue: Int) { + fun setPercentageValues(currentValue: Float, maxValue: Float) { currentPercentage = currentValue PERCENTAGE_DIVIDER = maxValue } - fun animateProgress() { - val currentPercent: Int = currentPercentage + fun animateProgress(startValue: Float = 0f, animationDuration: Long = 1000) { + val currentPercent = currentPercentage val valuesHolder = PropertyValuesHolder.ofFloat( PERCENTAGE_VALUE_HOLDER, - 1f, + startValue, currentPercent.toFloat() ) val animator = ValueAnimator().apply { setValues(valuesHolder) - duration = 1000 + duration = animationDuration interpolator = AccelerateDecelerateInterpolator() addUpdateListener { val percentage = it.getAnimatedValue(PERCENTAGE_VALUE_HOLDER) as Float - currentPercentage = percentage.toInt() + currentPercentage = percentage invalidate() } } @@ -122,6 +121,6 @@ class CircularProgressView( const val PERCENTAGE_VALUE_HOLDER = "percentage" } - private fun getCurrentAngleToFill() = if(currentPercentage > 0) {(ARC_FULL_ROTATION_DEGREE.toFloat() * (currentPercentage.toFloat() / PERCENTAGE_DIVIDER.toFloat()))} else {1f} + private fun getCurrentAngleToFill() = if(currentPercentage > 0) {(ARC_FULL_ROTATION_DEGREE.toFloat() * (currentPercentage / PERCENTAGE_DIVIDER))} else {1f} } diff --git a/wearos/src/main/res/drawable-mdpi/broken_heart.png b/wearos/src/main/res/drawable-mdpi/broken_heart.png new file mode 100644 index 0000000000000000000000000000000000000000..cee972753d924f37fa5055aef37e0390f87ba212 GIT binary patch literal 2343 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 literal 0 HcmV?d00001 diff --git a/wearos/src/main/res/drawable-xxhdpi/broken_heart.png b/wearos/src/main/res/drawable-xxhdpi/broken_heart.png new file mode 100644 index 0000000000000000000000000000000000000000..8793117b6745363ea3ba2b92fccb46c9a56ddc18 GIT binary patch literal 6104 zcmV;}7bob6P)mSCAAbQ4%SIlGB)?;Fz*}k?gdkowSLY#<7w z&jJfbzZniGTtpK5Jw+rz7Hj!WCA(X*VpaK<=y~UejZl-00&Vh`|k@yALVt+W(V=h z7qz#S>UArLKu+}b?ko6wub?1x{ZxM*=w>iM))zuS$YSMFkS@j z;AtaUt}1H=O9i$q5HJ3sMR-amZkl#M*lIhL0&%0ANIoCn4+kz0E#&iicb`8$1ZBW& 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 eE%%ZUHRJb(!cgI8TYv}v0000 + + + + + + +