diff --git a/Habitica/res/layout/mount_imageview.xml b/Habitica/res/layout/mount_imageview.xml
index c30b027f0..9153b9409 100644
--- a/Habitica/res/layout/mount_imageview.xml
+++ b/Habitica/res/layout/mount_imageview.xml
@@ -1,10 +1,17 @@
+ android:layout_width="match_parent" android:layout_height="124dp"
+ android:layout_gravity="center"
+ android:background="@drawable/layout_rounded_bg_content"
+ android:clipToPadding="true"
+ android:clipChildren="true">
+
diff --git a/Habitica/res/layout/pet_imageview.xml b/Habitica/res/layout/pet_imageview.xml
index 8fecaeab1..267823adb 100644
--- a/Habitica/res/layout/pet_imageview.xml
+++ b/Habitica/res/layout/pet_imageview.xml
@@ -1,10 +1,22 @@
+ android:layout_width="match_parent"
+ android:layout_height="124dp"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_gravity="center"
+ android:background="@drawable/layout_rounded_bg_content"
+ android:clipToPadding="true"
+ android:clipChildren="true">
+
+ android:layout_gravity="center"
+ android:layout_marginTop="12dp"
+ tools:background="@color/red_10"
+ />
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/AlertDialogExtensions.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/AlertDialogExtensions.kt
index be53e7026..6309d4e2d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/AlertDialogExtensions.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/AlertDialogExtensions.kt
@@ -13,14 +13,14 @@ fun HabiticaAlertDialog.addOkButton(
fun HabiticaAlertDialog.addCloseButton(
isPrimary: Boolean = false,
- listener: ((DialogInterface, Int) -> Unit)? = null
+ listener: ((HabiticaAlertDialog, Int) -> Unit)? = null
) {
this.addButton(R.string.close, isPrimary, false, true, listener)
}
fun HabiticaAlertDialog.addCancelButton(
isPrimary: Boolean = false,
- listener: ((DialogInterface, Int) -> Unit)? = null
+ listener: ((HabiticaAlertDialog, Int) -> Unit)? = null
) {
this.addButton(R.string.cancel, isPrimary, false, true, listener)
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/FeedPetUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/FeedPetUseCase.kt
index e51610671..d78f86ed5 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/FeedPetUseCase.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/FeedPetUseCase.kt
@@ -3,48 +3,63 @@ package com.habitrpg.android.habitica.interactors
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
-import android.graphics.drawable.BitmapDrawable
-import android.view.View
-import android.widget.FrameLayout
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.lifecycle.setViewTreeLifecycleOwner
+import androidx.savedstate.setViewTreeSavedStateRegistryOwner
+import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.data.InventoryRepository
+import com.habitrpg.android.habitica.databinding.MountImageviewBinding
import com.habitrpg.android.habitica.models.inventory.Food
import com.habitrpg.android.habitica.models.inventory.Pet
import com.habitrpg.android.habitica.ui.activities.BaseActivity
+import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.views.BackgroundScene
import com.habitrpg.android.habitica.ui.views.SnackbarActivity
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
-import com.habitrpg.android.habitica.ui.views.stable.MountView
-import com.habitrpg.common.habitica.extensions.loadImage
-import com.habitrpg.common.habitica.views.PixelArtView
+import com.habitrpg.common.habitica.extensions.dpToPx
+import com.habitrpg.common.habitica.extensions.layoutInflater
+import com.habitrpg.common.habitica.helpers.launchCatching
import com.habitrpg.shared.habitica.models.responses.FeedResponse
+import kotlinx.coroutines.MainScope
import javax.inject.Inject
class FeedPetUseCase @Inject
constructor(
private val inventoryRepository: InventoryRepository
) : UseCase() {
- override suspend fun run(requestValues: FeedPetUseCase.RequestValues): FeedResponse? {
+ override suspend fun run(requestValues: RequestValues): FeedResponse? {
val feedResponse = inventoryRepository.feedPet(requestValues.pet, requestValues.food)
(requestValues.context as? SnackbarActivity)?.showSnackbar(content = feedResponse?.message)
if (feedResponse?.value == -1) {
- val mountWrapper =
- View.inflate(
- requestValues.context,
- R.layout.mount_imageview,
- null
- ) as? FrameLayout
- val mountImageView =
- mountWrapper?.findViewById(R.id.mount_imageview) as? MountView
+ val mountWrapper = MountImageviewBinding.inflate(requestValues.context.layoutInflater)
- mountImageView?.setMount("Mount_Icon_" + requestValues.pet.key)
+ mountWrapper.mountImageview.setMount(requestValues.pet.key)
+ val currentActivity =
+ HabiticaBaseApplication.getInstance(requestValues.context)?.currentActivity?.get()
val dialog = HabiticaAlertDialog(requestValues.context)
+ if (currentActivity != null) {
+ mountWrapper.backgroundView.setContent {
+ HabiticaTheme {
+ BackgroundScene(Modifier.clip(HabiticaTheme.shapes.large))
+ }
+ }
+ dialog.window?.let {
+ mountWrapper.root.setViewTreeSavedStateRegistryOwner(currentActivity)
+ it.decorView.setViewTreeSavedStateRegistryOwner(currentActivity)
+ mountWrapper.root.setViewTreeLifecycleOwner(currentActivity)
+ it.decorView.setViewTreeLifecycleOwner(currentActivity)
+ }
+ }
dialog.setTitle(
requestValues.context.getString(
R.string.evolved_pet_title,
requestValues.pet.text
)
)
- dialog.setAdditionalContentView(mountWrapper)
+ dialog.isCelebratory = true
+ dialog.setAdditionalContentView(mountWrapper.root)
dialog.addButton(R.string.onwards, true)
dialog.addButton(R.string.share, false) { hatchingDialog, _ ->
val message =
@@ -52,19 +67,11 @@ constructor(
R.string.share_raised,
requestValues.pet.text
)
- val mountImageSideLength = 99
- val sharedImage = Bitmap.createBitmap(
- mountImageSideLength,
- mountImageSideLength,
- Bitmap.Config.ARGB_8888
- )
- val canvas = Canvas(sharedImage)
- mountImageView?.draw(canvas)
- (requestValues.context as? BaseActivity)?.shareContent(
- "raisedPet",
- message,
- sharedImage
- )
+ MainScope().launchCatching {
+ ShareMountUseCase().callInteractor(ShareMountUseCase.RequestValues(
+ requestValues.pet.key, message, requestValues.context
+ ))
+ }
hatchingDialog.dismiss()
}
dialog.enqueue()
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/HatchPetUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/HatchPetUseCase.kt
index f6b64bf9f..4d7e7e3dc 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/HatchPetUseCase.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/HatchPetUseCase.kt
@@ -1,21 +1,24 @@
package com.habitrpg.android.habitica.interactors
import android.content.Context
-import android.graphics.Bitmap
-import android.graphics.Canvas
-import android.graphics.drawable.BitmapDrawable
import android.view.View
-import android.widget.FrameLayout
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.lifecycle.setViewTreeLifecycleOwner
+import androidx.savedstate.setViewTreeSavedStateRegistryOwner
+import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.data.InventoryRepository
+import com.habitrpg.android.habitica.databinding.PetImageviewBinding
import com.habitrpg.android.habitica.models.inventory.Egg
import com.habitrpg.android.habitica.models.inventory.HatchingPotion
import com.habitrpg.android.habitica.models.user.Items
-import com.habitrpg.android.habitica.ui.activities.BaseActivity
+import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.views.BackgroundScene
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
+import com.habitrpg.common.habitica.extensions.layoutInflater
import com.habitrpg.common.habitica.extensions.loadImage
import com.habitrpg.common.habitica.helpers.launchCatching
-import com.habitrpg.common.habitica.views.PixelArtView
import kotlinx.coroutines.MainScope
import javax.inject.Inject
@@ -25,29 +28,58 @@ constructor(
) : UseCase() {
override suspend fun run(requestValues: RequestValues): Items? {
return inventoryRepository.hatchPet(requestValues.egg, requestValues.potion) {
- val petWrapper = View.inflate(requestValues.context, R.layout.pet_imageview, null) as? FrameLayout
- val petImageView = petWrapper?.findViewById(R.id.pet_imageview) as? PixelArtView
-
- petImageView?.loadImage("stable_Pet-" + requestValues.egg.key + "-" + requestValues.potion.key)
+ val petWrapper = PetImageviewBinding.inflate(requestValues.context.layoutInflater)
+ val petKey = requestValues.egg.key + "-" + requestValues.potion.key
+ petWrapper.petImageview.loadImage("stable_Pet-" + petKey)
val potionName = requestValues.potion.text
val eggName = requestValues.egg.text
+ val currentActivity =
+ HabiticaBaseApplication.getInstance(requestValues.context)?.currentActivity?.get()
val dialog = HabiticaAlertDialog(requestValues.context)
- dialog.setTitle(requestValues.context.getString(R.string.hatched_pet_title, potionName, eggName))
- dialog.setAdditionalContentView(petWrapper)
+ if (currentActivity != null) {
+ petWrapper.backgroundView.setContent {
+ HabiticaTheme {
+ BackgroundScene(Modifier.clip(HabiticaTheme.shapes.large))
+ }
+ }
+ dialog.window?.let {
+ petWrapper.root.setViewTreeSavedStateRegistryOwner(currentActivity)
+ it.decorView.setViewTreeSavedStateRegistryOwner(currentActivity)
+ petWrapper.root.setViewTreeLifecycleOwner(currentActivity)
+ it.decorView.setViewTreeLifecycleOwner(currentActivity)
+ }
+ }
+ dialog.isCelebratory = true
+ dialog.setTitle(
+ requestValues.context.getString(
+ R.string.hatched_pet_title,
+ potionName,
+ eggName
+ )
+ )
+ dialog.setAdditionalContentView(petWrapper.root)
dialog.addButton(R.string.equip, true) { _, _ ->
MainScope().launchCatching {
- inventoryRepository.equip("pet", requestValues.egg.key + "-" + requestValues.potion.key)
+ inventoryRepository.equip(
+ "pet",
+ requestValues.egg.key + "-" + requestValues.potion.key
+ )
}
}
dialog.addButton(R.string.share, false) { hatchingDialog, _ ->
- val message = requestValues.context.getString(R.string.share_hatched, potionName, eggName)
- val petImageSideLength = 140
- val sharedImage = Bitmap.createBitmap(petImageSideLength, petImageSideLength, Bitmap.Config.ARGB_8888)
- val canvas = Canvas(sharedImage)
- petImageView?.drawable?.setBounds(0, 0, petImageSideLength, petImageSideLength)
- val bitmap = (petImageView?.drawable as? BitmapDrawable)?.bitmap ?: petImageView?.bitmap ?: return@addButton
- canvas.drawBitmap(bitmap, 0f, 0f, null)
- (requestValues.context as? BaseActivity)?.shareContent("hatchedPet", message, sharedImage)
+ MainScope().launchCatching {
+ SharePetUseCase().callInteractor(
+ SharePetUseCase.RequestValues(
+ petKey,
+ requestValues.context.getString(
+ R.string.share_hatched,
+ potionName,
+ eggName
+ ),
+ requestValues.context
+ )
+ )
+ }
hatchingDialog.dismiss()
}
dialog.setExtraCloseButtonVisibility(View.VISIBLE)
@@ -55,5 +87,6 @@ constructor(
}
}
- class RequestValues(val potion: HatchingPotion, val egg: Egg, val context: Context) : UseCase.RequestValues
+ class RequestValues(val potion: HatchingPotion, val egg: Egg, val context: Context) :
+ UseCase.RequestValues
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ShareAvatarUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ShareAvatarUseCase.kt
index ae313dca1..a5ce03667 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ShareAvatarUseCase.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ShareAvatarUseCase.kt
@@ -7,8 +7,7 @@ import com.habitrpg.common.habitica.views.AvatarView
import com.habitrpg.shared.habitica.models.Avatar
import javax.inject.Inject
-class ShareAvatarUseCase @Inject
-constructor() : UseCase() {
+class ShareAvatarUseCase @Inject constructor() : UseCase() {
override suspend fun run(requestValues: RequestValues) {
val avatarView = AvatarView(requestValues.activity, showBackground = true, showMount = true, showPet = true)
avatarView.setAvatar(requestValues.avatar)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ShareMountUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ShareMountUseCase.kt
new file mode 100644
index 000000000..9da41a678
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ShareMountUseCase.kt
@@ -0,0 +1,72 @@
+package com.habitrpg.android.habitica.interactors
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.core.view.doOnNextLayout
+import androidx.lifecycle.setViewTreeLifecycleOwner
+import androidx.savedstate.setViewTreeSavedStateRegistryOwner
+import com.habitrpg.android.habitica.HabiticaBaseApplication
+import com.habitrpg.android.habitica.databinding.MountImageviewBinding
+import com.habitrpg.android.habitica.ui.activities.BaseActivity
+import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.views.BackgroundScene
+import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
+import com.habitrpg.common.habitica.extensions.dpToPx
+import com.habitrpg.common.habitica.extensions.layoutInflater
+import com.habitrpg.common.habitica.extensions.loadImage
+import kotlinx.coroutines.delay
+
+class ShareMountUseCase: UseCase() {
+ class RequestValues(val mountKey: String, val message: String, val context: Context) :
+ UseCase.RequestValues
+
+ override suspend fun run(requestValues: RequestValues) {
+ val mountWrapper = MountImageviewBinding.inflate(requestValues.context.layoutInflater)
+ val width = if (mountWrapper.root.width > 0) mountWrapper.root.width else 300.dpToPx(requestValues.context)
+ val height = 124.dpToPx(requestValues.context)
+ mountWrapper.root.layout(0, 0, width, height)
+ mountWrapper.mountImageview.setMount(requestValues.mountKey)
+ val currentActivity =
+ HabiticaBaseApplication.getInstance(requestValues.context)?.currentActivity?.get()
+ // Add the view to the decorView so that it can be layouted
+ (currentActivity?.window?.decorView as? ViewGroup)?.addView(mountWrapper.root)
+ if (currentActivity != null) {
+ mountWrapper.backgroundView.setContent {
+ HabiticaTheme {
+ BackgroundScene(Modifier.clip(HabiticaTheme.shapes.large))
+ }
+ }
+ mountWrapper.root.setViewTreeSavedStateRegistryOwner(currentActivity)
+ mountWrapper.root.setViewTreeLifecycleOwner(currentActivity)
+ }
+ mountWrapper.backgroundView.layout(0, 0, width, height)
+ mountWrapper.mountImageview.layout(0, 0, width, height)
+ val sharedImage = Bitmap.createBitmap(
+ width,
+ height,
+ Bitmap.Config.ARGB_8888
+ )
+ val canvas = Canvas(sharedImage)
+ var attempts = 0
+ while (!mountWrapper.mountImageview.hasLoadedImages && attempts < 200) {
+ delay(100)
+ attempts++
+ }
+ // Draw it to the canvas once it's layouted
+ mountWrapper.root.doOnNextLayout {
+ mountWrapper.root.draw(canvas)
+ ((requestValues.context as? BaseActivity) ?: HabiticaBaseApplication.getInstance(
+ requestValues.context
+ )?.currentActivity?.get())?.shareContent("pet", requestValues.message, sharedImage)
+ currentActivity?.toolbar?.removeView(mountWrapper.root)
+ }
+ // trigger layout
+ val m = FrameLayout.LayoutParams(width, height)
+ mountWrapper.root.layoutParams = m
+ }
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/SharePetUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/SharePetUseCase.kt
new file mode 100644
index 000000000..a0b392bca
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/SharePetUseCase.kt
@@ -0,0 +1,81 @@
+package com.habitrpg.android.habitica.interactors
+
+import android.app.Activity
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Rect
+import android.os.Build
+import android.os.Handler
+import android.view.PixelCopy
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import androidx.annotation.RequiresApi
+import androidx.appcompat.widget.Toolbar
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.platform.findViewTreeCompositionContext
+import androidx.core.view.doOnNextLayout
+import androidx.core.view.isVisible
+import androidx.lifecycle.setViewTreeLifecycleOwner
+import androidx.savedstate.setViewTreeSavedStateRegistryOwner
+import com.habitrpg.android.habitica.HabiticaBaseApplication
+import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.databinding.PetImageviewBinding
+import com.habitrpg.android.habitica.models.inventory.Food
+import com.habitrpg.android.habitica.models.inventory.Pet
+import com.habitrpg.android.habitica.ui.activities.BaseActivity
+import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.views.BackgroundScene
+import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
+import com.habitrpg.common.habitica.extensions.dpToPx
+import com.habitrpg.common.habitica.extensions.layoutInflater
+import com.habitrpg.common.habitica.extensions.loadImage
+import kotlinx.coroutines.delay
+
+class SharePetUseCase: UseCase() {
+ class RequestValues(val petKey: String, val message: String, val context: Context) :
+ UseCase.RequestValues
+
+ override suspend fun run(requestValues: RequestValues) {
+ val petWrapper = PetImageviewBinding.inflate(requestValues.context.layoutInflater)
+ petWrapper.petImageview.loadImage("stable_Pet-" + requestValues.petKey)
+ petWrapper.root.visibility = View.INVISIBLE
+ val currentActivity =
+ HabiticaBaseApplication.getInstance(requestValues.context)?.currentActivity?.get()
+ (currentActivity?.window?.decorView as? ViewGroup)?.addView(petWrapper.root)
+ if (currentActivity != null) {
+ petWrapper.backgroundView.setContent {
+ HabiticaTheme {
+ BackgroundScene(Modifier.clip(HabiticaTheme.shapes.large))
+ }
+ }
+ petWrapper.backgroundView.setParentCompositionContext(currentActivity.toolbar?.findViewTreeCompositionContext())
+ petWrapper.root.setViewTreeSavedStateRegistryOwner(currentActivity)
+ petWrapper.root.setViewTreeLifecycleOwner(currentActivity)
+ }
+ val width = if (petWrapper.root.width > 0) petWrapper.root.width else 300.dpToPx(requestValues.context)
+ val height = 124.dpToPx(requestValues.context)
+ val sharedImage = Bitmap.createBitmap(
+ width,
+ height,
+ Bitmap.Config.ARGB_8888
+ )
+ val canvas = Canvas(sharedImage)
+ var attempts = 0
+ while (petWrapper.petImageview.bitmap == null && attempts < 200) {
+ delay(100)
+ attempts++
+ }
+ petWrapper.root.doOnNextLayout {
+ petWrapper.root.draw(canvas)
+ ((requestValues.context as? BaseActivity) ?: HabiticaBaseApplication.getInstance(
+ requestValues.context
+ )?.currentActivity?.get())?.shareContent("pet", requestValues.message, sharedImage)
+ currentActivity?.toolbar?.removeView(petWrapper.root)
+ }
+ val m = FrameLayout.LayoutParams(width, height)
+ petWrapper.root.layoutParams = m
+ }
+}
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 d93f9a4cc..cb36d2fcc 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
@@ -18,6 +18,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.ActionBarDrawerToggle
+import androidx.appcompat.app.AlertDialog
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.height
@@ -29,12 +30,14 @@ import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.view.children
import androidx.core.view.setPadding
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.setViewTreeLifecycleOwner
import androidx.navigation.NavDestination
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
@@ -65,6 +68,7 @@ import com.habitrpg.android.habitica.interactors.CheckClassSelectionUseCase
import com.habitrpg.android.habitica.interactors.DisplayItemDropUseCase
import com.habitrpg.android.habitica.interactors.NotifyUserUseCase
import com.habitrpg.android.habitica.interactors.ShareAvatarUseCase
+import com.habitrpg.android.habitica.interactors.SharePetUseCase
import com.habitrpg.android.habitica.models.TutorialStep
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.models.user.UserQuestStatus
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BackgroundScene.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BackgroundScene.kt
index 68b596bf8..c9edb3bbb 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BackgroundScene.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BackgroundScene.kt
@@ -44,10 +44,10 @@ private fun getBackgroundPainter(): ImageBitmap {
}
@Composable
-fun BackgroundScene() {
+fun BackgroundScene(modifier: Modifier = Modifier) {
val image = getBackgroundPainter()
Canvas(
- modifier = Modifier
+ modifier = modifier
.height(124.dp)
.fillMaxWidth()
.zIndex(1f), onDraw = {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.kt
index d479f8438..48520c4d4 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.kt
@@ -15,6 +15,7 @@ import androidx.core.view.ViewCompat
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.databinding.SnackbarViewBinding
import com.habitrpg.common.habitica.helpers.Animations
import com.plattysoft.leonids.ParticleSystem
@@ -28,18 +29,27 @@ class HabiticaSnackbar
*/
private constructor(parent: ViewGroup, content: View, callback: ContentViewCallback) :
BaseTransientBottomBar(parent, content, callback) {
+ val binding: SnackbarViewBinding = SnackbarViewBinding.bind(content)
fun setTitle(title: CharSequence?): HabiticaSnackbar {
- val textView = view.findViewById(R.id.snackbar_title) as? TextView
- textView?.text = title
- textView?.visibility = if (title != null) View.VISIBLE else View.GONE
+ binding.snackbarTitle.text = title
+ binding.snackbarTitle.visibility = if (title != null) View.VISIBLE else View.GONE
return this
}
fun setText(text: CharSequence?): HabiticaSnackbar {
- val textView = view.findViewById(R.id.snackbar_text) as? TextView
- textView?.text = text
- textView?.visibility = if (text != null) View.VISIBLE else View.GONE
+ binding.snackbarText.text = text
+ binding.snackbarText.visibility = if (text != null) View.VISIBLE else View.GONE
+ return this
+ }
+
+ fun setTitleColor(color: Int): HabiticaSnackbar {
+ binding.snackbarTitle.setTextColor(color)
+ return this
+ }
+
+ fun setTextColor(color: Int): HabiticaSnackbar {
+ binding.snackbarText.setTextColor(color)
return this
}
@@ -47,20 +57,16 @@ private constructor(parent: ViewGroup, content: View, callback: ContentViewCallb
if (icon == null) {
return this
}
- val rightView = view.findViewById(R.id.rightView)
- rightView.visibility = View.VISIBLE
- val rightIconView = view.findViewById(R.id.rightIconView)
- rightIconView.setImageDrawable(icon)
- val rightTextView = view.findViewById(R.id.rightTextView)
- rightTextView.setTextColor(textColor)
- rightTextView.text = text
+ binding.rightView.visibility = View.VISIBLE
+ binding.rightIconView.setImageDrawable(icon)
+ binding.rightTextView.setTextColor(textColor)
+ binding.rightTextView.text = text
return this
}
fun setLeftIcon(image: Drawable?): HabiticaSnackbar {
- val imageView = view.findViewById(R.id.leftImageView)
- imageView.setImageDrawable(image)
- imageView.visibility = if (image != null) View.VISIBLE else View.GONE
+ binding.leftImageView.setImageDrawable(image)
+ binding.leftImageView.visibility = if (image != null) View.VISIBLE else View.GONE
return this
}
@@ -70,16 +76,14 @@ private constructor(parent: ViewGroup, content: View, callback: ContentViewCallb
}
fun setBackgroundResource(resourceId: Int): HabiticaSnackbar {
- val snackbarView = view.findViewById(R.id.snackbar_view)
- snackbarView.setBackgroundResource(resourceId)
+ binding.snackbarView.setBackgroundResource(resourceId)
view.setBackgroundColor(ContextCompat.getColor(context, R.color.transparent))
return this
}
private fun setSpecialView(specialView: View?): HabiticaSnackbar {
if (specialView != null) {
- val snackbarView = view.findViewById(R.id.content_container) as? LinearLayout
- snackbarView?.addView(specialView)
+ binding.contentContainer.addView(specialView)
}
return this
}
@@ -261,14 +265,14 @@ private constructor(parent: ViewGroup, content: View, callback: ContentViewCallb
SnackbarDisplayType.FAILURE_BLUE, SnackbarDisplayType.BLUE -> snackbar.setBackgroundResource(
R.drawable.snackbar_background_blue
)
-
SnackbarDisplayType.DROP, SnackbarDisplayType.NORMAL -> snackbar.setBackgroundResource(
R.drawable.snackbar_background_gray
)
-
SnackbarDisplayType.SUCCESS -> snackbar.setBackgroundResource(R.drawable.snackbar_background_green)
SnackbarDisplayType.SUBSCRIBER_BENEFIT -> {
snackbar.setBackgroundResource(R.drawable.subscriber_benefit_snackbar_bg)
+ snackbar.setTitleColor(ContextCompat.getColor(container.context, R.color.green_1))
+ snackbar.setTextColor(ContextCompat.getColor(container.context, R.color.green_1))
}
}
@@ -291,15 +295,15 @@ private constructor(parent: ViewGroup, content: View, callback: ContentViewCallb
{
ParticleSystem(
container,
- 200,
+ 300,
ContextCompat.getDrawable(container.context, R.drawable.confetti_subs),
- 500L
+ 800L
)
.setFadeOut(200L)
.setSpeedRange(0.05f, 0.2f)
.setScaleRange(0.8f, 1.2f)
.setRotationSpeedRange(134f, 164f)
- .emit(snackbar.getView(), 150, 500)
+ .emit(snackbar.getView(), 200, 600)
}, 500L
)
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/PetSuggestHatchDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/PetSuggestHatchDialog.kt
index 9eec10ad2..f9de0e4e9 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/PetSuggestHatchDialog.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/PetSuggestHatchDialog.kt
@@ -7,6 +7,7 @@ import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toBitmap
import androidx.lifecycle.lifecycleScope
+import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.DialogHatchPetButtonBinding
import com.habitrpg.android.habitica.databinding.DialogPetSuggestHatchBinding
@@ -168,7 +169,7 @@ class PetSuggestHatchDialog(context: Context) : HabiticaAlertDialog(context) {
binding.currencyView.currency = "gems"
binding.currencyView.setTextColor(ContextCompat.getColor(context, R.color.white))
addButton(binding.root, true) { _, _ ->
- val activity = (getActivity() as? MainActivity) ?: return@addButton
+ val activity = (getActivity() as? MainActivity) ?: (HabiticaBaseApplication.getInstance(context)?.currentActivity?.get() as? MainActivity) ?: return@addButton
if ((userViewModel.user.value?.gemCount ?: hatchPrice) < hatchPrice) {
InsufficientGemsDialog(activity, hatchPrice).show()
Analytics.sendEvent("show insufficient gems modal", EventCategory.BEHAVIOUR, HitType.EVENT, mapOf("reason" to "pet suggest modal"))
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountBottomSheet.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountBottomSheet.kt
index 08dc3e4f3..78a865311 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountBottomSheet.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountBottomSheet.kt
@@ -39,6 +39,7 @@ import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.StrokeCap
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.imageResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@@ -47,9 +48,12 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.interactors.ShareMountUseCase
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.BackgroundScene
import com.habitrpg.android.habitica.ui.views.HabiticaButton
+import com.habitrpg.common.habitica.helpers.launchCatching
+import kotlinx.coroutines.MainScope
import java.util.Calendar
import kotlin.math.sin
@@ -146,6 +150,25 @@ fun MountBottomSheet(
.zIndex(2f)
)
}
+ val context = LocalContext.current
+ HabiticaButton(
+ background = HabiticaTheme.colors.tintedUiSub,
+ color = Color.White,
+ contentPadding = PaddingValues(12.dp),
+ modifier = Modifier.padding(bottom = 16.dp),
+ onClick = {
+ MainScope().launchCatching {
+ ShareMountUseCase().callInteractor(
+ ShareMountUseCase.RequestValues(
+ mount.key,
+ "",
+ context
+ ))
+ }
+ onDismiss()
+ }) {
+ Text(stringResource(id = R.string.share))
+ }
HabiticaButton(
background = HabiticaTheme.colors.tintedUiSub,
color = Color.White,
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountView.kt
index 68c66e2f2..d6045af30 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountView.kt
@@ -15,6 +15,10 @@ class MountView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : FrameLayout(context, attrs) {
+ val hasLoadedImages: Boolean
+ get() {
+ return bodyView.bitmap != null && headView.bitmap != null
+ }
private val bodyView: PixelArtView = PixelArtView(context)
private val headView: PixelArtView = PixelArtView(context)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/PetBottomSheet.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/PetBottomSheet.kt
index 4f1b3b338..c9a32f316 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/PetBottomSheet.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/PetBottomSheet.kt
@@ -65,6 +65,8 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.interactors.ShareMountUseCase
+import com.habitrpg.android.habitica.interactors.SharePetUseCase
import com.habitrpg.android.habitica.models.inventory.Food
import com.habitrpg.android.habitica.models.inventory.Pet
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
@@ -75,6 +77,7 @@ import com.habitrpg.common.habitica.extensions.getThemeColor
import com.habitrpg.common.habitica.helpers.MainNavigationController
import com.habitrpg.common.habitica.helpers.launchCatching
import com.habitrpg.shared.habitica.models.responses.FeedResponse
+import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlin.math.sin
@@ -310,6 +313,25 @@ fun PetBottomSheet(
}
}
}
+ val context = LocalContext.current
+ HabiticaButton(
+ background = HabiticaTheme.colors.tintedUiSub,
+ color = Color.White,
+ contentPadding = PaddingValues(12.dp),
+ modifier = Modifier.padding(bottom = 16.dp),
+ onClick = {
+ MainScope().launchCatching {
+ SharePetUseCase().callInteractor(
+ SharePetUseCase.RequestValues(
+ pet.key,
+ "",
+ context
+ ))
+ }
+ onDismiss()
+ }) {
+ Text(stringResource(id = R.string.share))
+ }
HabiticaButton(
background = HabiticaTheme.colors.tintedUiSub,
color = Color.White,
diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/LoginViewModel.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/LoginViewModel.kt
index 488fbe2d4..86a50db88 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/LoginViewModel.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/LoginViewModel.kt
@@ -154,16 +154,6 @@ class LoginViewModel @Inject constructor(
}
}
- fun login(username: String, password: String, onResult: (Boolean) -> Unit) {
- viewModelScope.launch(exceptionBuilder.userFacing(this)) {
- val response = apiClient.loginLocal(UserAuth(username, password)).responseData
- handleAuthResponse(response)
- onResult(response?.id != null)
- }.invokeOnCompletion {
- onResult(it == null)
- }
- }
-
companion object {
private const val REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR = 1001
}