mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-04-14 19:56:32 +00:00
Improve event display
This commit is contained in:
parent
1b81f0ce2f
commit
b199c2ea73
16 changed files with 93 additions and 35 deletions
|
|
@ -17,6 +17,11 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/promo_compose_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
<RelativeLayout
|
||||
android:id="@+id/promo_banner"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ interface ApiService {
|
|||
suspend fun disableClasses(): HabitResponse<User>
|
||||
|
||||
@POST("user/mark-pms-read")
|
||||
suspend fun markPrivateMessagesRead(): Void
|
||||
suspend fun markPrivateMessagesRead(): Void?
|
||||
|
||||
/* Group API */
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ interface ApiClient {
|
|||
|
||||
suspend fun disableClasses(): User?
|
||||
|
||||
suspend fun markPrivateMessagesRead(): Void?
|
||||
suspend fun markPrivateMessagesRead()
|
||||
|
||||
/* Group API */
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ interface SocialRepository : BaseRepository {
|
|||
|
||||
fun getUserGroups(type: String?): Flow<List<Group>>
|
||||
suspend fun retrieveGroupChat(groupId: String): List<ChatMessage>?
|
||||
fun getGroupChat(groupId: String): Flow<out List<ChatMessage>>
|
||||
fun getGroupChat(groupId: String): Flow<List<ChatMessage>>
|
||||
|
||||
suspend fun markMessagesSeen(seenGroupId: String)
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ interface SocialRepository : BaseRepository {
|
|||
id: String? = null
|
||||
): List<FindUsernameResult>?
|
||||
|
||||
suspend fun markPrivateMessagesRead(user: User?): Void?
|
||||
suspend fun markPrivateMessagesRead(user: User?)
|
||||
|
||||
fun markSomePrivateMessagesAsRead(user: User?, messages: List<ChatMessage>)
|
||||
|
||||
|
|
|
|||
|
|
@ -499,8 +499,8 @@ class ApiClientImpl(
|
|||
|
||||
override suspend fun disableClasses(): User? = process { apiService.disableClasses() }
|
||||
|
||||
override suspend fun markPrivateMessagesRead(): Void {
|
||||
return apiService.markPrivateMessagesRead()
|
||||
override suspend fun markPrivateMessagesRead() {
|
||||
apiService.markPrivateMessagesRead()
|
||||
}
|
||||
|
||||
override suspend fun listGroups(type: String): List<Group>? {
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ class SocialRepositoryImpl(
|
|||
return apiClient.findUsernames(username, context, id)
|
||||
}
|
||||
|
||||
override suspend fun markPrivateMessagesRead(user: User?): Void? {
|
||||
override suspend fun markPrivateMessagesRead(user: User?) {
|
||||
if (user?.isManaged == true) {
|
||||
localRepository.modify(user) {
|
||||
it.inbox?.hasUserSeenInbox = true
|
||||
|
|
|
|||
|
|
@ -20,9 +20,11 @@ import com.habitrpg.android.habitica.models.user.UserQuestStatus
|
|||
import com.habitrpg.android.habitica.proxy.AnalyticsManager
|
||||
import com.habitrpg.shared.habitica.models.responses.TaskDirection
|
||||
import com.habitrpg.shared.habitica.models.tasks.Attribute
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.Date
|
||||
import java.util.GregorianCalendar
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
|
@ -65,7 +67,9 @@ class UserRepositoryImpl(
|
|||
if (forced || this.lastSync == null || Date().time - (this.lastSync?.time ?: 0) > 180000) {
|
||||
val user = apiClient.retrieveUser(withTasks) ?: return null
|
||||
lastSync = Date()
|
||||
localRepository.saveUser(user)
|
||||
withContext(Dispatchers.Main) {
|
||||
localRepository.saveUser(user)
|
||||
}
|
||||
if (withTasks) {
|
||||
val id = user.id
|
||||
val tasksOrder = user.tasksOrder
|
||||
|
|
|
|||
|
|
@ -426,11 +426,17 @@ class PurchaseHandler(
|
|||
}
|
||||
}
|
||||
|
||||
private val displayedConfirmations = mutableListOf<String>()
|
||||
|
||||
private fun displayConfirmationDialog(purchase: Purchase, giftedTo: String? = null) {
|
||||
CoroutineScope(Dispatchers.Main).launch(ExceptionHandler.coroutine()) {
|
||||
if (displayedConfirmations.contains(purchase.orderId)) {
|
||||
return
|
||||
}
|
||||
displayedConfirmations.add(purchase.orderId)
|
||||
CoroutineScope(Dispatchers.Main).launchCatching {
|
||||
val application = (context as? HabiticaBaseApplication)
|
||||
?: (context.applicationContext as? HabiticaBaseApplication) ?: return@launch
|
||||
val sku = purchase.products.firstOrNull() ?: return@launch
|
||||
?: (context.applicationContext as? HabiticaBaseApplication) ?: return@launchCatching
|
||||
val sku = purchase.products.firstOrNull() ?: return@launchCatching
|
||||
var title = context.getString(R.string.successful_purchase_generic)
|
||||
val message = when {
|
||||
PurchaseTypes.allSubscriptionNoRenewTypes.contains(sku) -> {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,11 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.android.billingclient.api.ProductDetails
|
||||
|
|
@ -26,7 +31,9 @@ import com.habitrpg.android.habitica.ui.activities.GiftGemsActivity
|
|||
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
|
||||
import com.habitrpg.android.habitica.ui.fragments.PromoInfoFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard
|
||||
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.android.habitica.ui.views.promo.BirthdayBanner
|
||||
import com.habitrpg.common.habitica.extensions.isUsingNightModeResources
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -92,6 +99,17 @@ class GemsPurchaseFragment : BaseFragment<FragmentGemPurchaseBinding>() {
|
|||
binding?.promoBanner?.visibility = View.GONE
|
||||
}
|
||||
|
||||
val birthdayEventEnd = appConfigManager.getBirthdayEvent()?.end
|
||||
if (birthdayEventEnd != null) {
|
||||
binding?.promoComposeView?.setContent {
|
||||
HabiticaTheme {
|
||||
BirthdayBanner(endDate = birthdayEventEnd, Modifier.padding(horizontal = 20.dp).clip(HabiticaTheme.shapes.medium)
|
||||
.padding(bottom = 20.dp))
|
||||
}
|
||||
}
|
||||
binding?.promoComposeView?.isVisible = true
|
||||
}
|
||||
|
||||
AmplitudeManager.sendNavigationEvent("gem screen")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.android.billingclient.api.ProductDetails
|
||||
|
|
@ -26,7 +31,9 @@ import com.habitrpg.android.habitica.models.user.User
|
|||
import com.habitrpg.android.habitica.ui.activities.GiftSubscriptionActivity
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
|
||||
import com.habitrpg.android.habitica.ui.fragments.PromoInfoFragment
|
||||
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.android.habitica.ui.views.promo.BirthdayBanner
|
||||
import com.habitrpg.android.habitica.ui.views.subscriptions.SubscriptionOptionView
|
||||
import com.habitrpg.common.habitica.extensions.isUsingNightModeResources
|
||||
import com.habitrpg.common.habitica.extensions.layoutInflater
|
||||
|
|
@ -87,6 +94,17 @@ class SubscriptionFragment : BaseFragment<FragmentSubscriptionBinding>() {
|
|||
binding?.promoBanner?.visibility = View.GONE
|
||||
}
|
||||
|
||||
val birthdayEventEnd = appConfigManager.getBirthdayEvent()?.end
|
||||
if (birthdayEventEnd != null) {
|
||||
binding?.promoComposeView?.setContent {
|
||||
HabiticaTheme {
|
||||
BirthdayBanner(endDate = birthdayEventEnd, Modifier.padding(horizontal = 20.dp).clip(HabiticaTheme.shapes.medium)
|
||||
.padding(bottom = 10.dp))
|
||||
}
|
||||
}
|
||||
binding?.promoComposeView?.isVisible = true
|
||||
}
|
||||
|
||||
binding?.refreshLayout?.setOnRefreshListener { refresh() }
|
||||
|
||||
lifecycleScope.launchCatching {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import com.habitrpg.android.habitica.helpers.MainNavigationController
|
|||
import java.util.Date
|
||||
|
||||
@Composable
|
||||
fun BirthdayBanner(endDate: Date) {
|
||||
fun BirthdayBanner(endDate: Date, modifier: Modifier = Modifier) {
|
||||
var value by remember { mutableStateOf(0) }
|
||||
|
||||
DisposableEffect(Unit) {
|
||||
|
|
@ -50,7 +50,7 @@ fun BirthdayBanner(endDate: Date) {
|
|||
}
|
||||
}
|
||||
Column(
|
||||
Modifier
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
MainNavigationController.navigate(R.id.birthdayActivity)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import com.habitrpg.android.habitica.extensions.fromHtml
|
|||
import com.habitrpg.android.habitica.models.inventory.QuestContent
|
||||
import com.habitrpg.android.habitica.models.shops.ShopItem
|
||||
import com.habitrpg.common.habitica.extensions.dpToPx
|
||||
import com.habitrpg.common.habitica.extensions.loadGif
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.common.habitica.views.PixelArtView
|
||||
|
||||
|
|
@ -29,7 +28,7 @@ abstract class PurchaseDialogContent @JvmOverloads constructor(
|
|||
|
||||
open fun setItem(item: ShopItem) {
|
||||
if (item.path?.contains("timeTravelBackgrounds") == true) {
|
||||
imageView.loadGif(item.imageName?.replace("icon_", ""))
|
||||
imageView.loadImage(item.imageName?.replace("icon_", ""))
|
||||
val params = imageView.layoutParams
|
||||
params.height = 147.dpToPx(context)
|
||||
params.width = 140.dpToPx(context)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,13 @@ fun AssignedView(
|
|||
color = color,
|
||||
extraContent = {
|
||||
completedAt[assignable.id]?.let { CompletedAt(completedAt = it) }
|
||||
},
|
||||
endContent = {
|
||||
completedAt[assignable.id]?.let {
|
||||
if (showEditButton) {
|
||||
UndoTaskCompletion()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -80,4 +87,8 @@ fun AssignedView(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun UndoTaskCompletion() {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.habitrpg.common.habitica.BuildConfig
|
|||
fun Application.setupCoil() {
|
||||
var builder = ImageLoader.Builder(this)
|
||||
.allowHardware(false)
|
||||
.crossfade(false)
|
||||
.components {
|
||||
if (Build.VERSION.SDK_INT >= 28) {
|
||||
add(ImageDecoderDecoder.Factory())
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.habitrpg.common.habitica.extensions
|
|||
|
||||
import android.content.Context
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import android.view.animation.Animation
|
||||
|
|
@ -13,7 +14,6 @@ import coil.imageLoader
|
|||
import coil.request.ImageRequest
|
||||
import com.habitrpg.android.habitica.extensions.setTintWith
|
||||
import com.habitrpg.common.habitica.R
|
||||
import com.habitrpg.common.habitica.extensions.DataBindingUtils.BASE_IMAGE_URL
|
||||
import com.habitrpg.common.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.common.habitica.views.PixelArtView
|
||||
import java.util.Collections
|
||||
|
|
@ -26,30 +26,22 @@ fun PixelArtView.loadImage(imageName: String?, imageFormat: String? = null) {
|
|||
return
|
||||
}
|
||||
tag = fullname
|
||||
bitmap = null
|
||||
setImageDrawable(null)
|
||||
DataBindingUtils.loadImage(context, imageName, imageFormat) {
|
||||
if (tag == fullname) {
|
||||
bitmap = it.toBitmap()
|
||||
if (fullname.endsWith("gif")) {
|
||||
setImageDrawable(it)
|
||||
if (it is Animatable) {
|
||||
it.start()
|
||||
}
|
||||
} else {
|
||||
bitmap = it.toBitmap()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun PixelArtView.loadGif(
|
||||
imageName: String?,
|
||||
builder: ImageRequest.Builder.() -> Unit = {}
|
||||
) {
|
||||
if (imageName != null) {
|
||||
val fullname = BASE_IMAGE_URL + DataBindingUtils.getFullFilename(imageName)
|
||||
val request = ImageRequest.Builder(context)
|
||||
.data(fullname)
|
||||
.target(this)
|
||||
.apply(builder)
|
||||
.build()
|
||||
context.imageLoader.enqueue(request)
|
||||
}
|
||||
}
|
||||
|
||||
object DataBindingUtils {
|
||||
|
||||
fun loadImage(context: Context, imageName: String, imageResult: (Drawable) -> Unit) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import android.graphics.Matrix
|
|||
import android.graphics.PointF
|
||||
import android.graphics.Rect
|
||||
import android.graphics.RectF
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.text.TextUtils
|
||||
import android.util.AttributeSet
|
||||
|
|
@ -170,6 +171,9 @@ class AvatarView : FrameLayout {
|
|||
result.isFilterBitmap = false
|
||||
super.onSuccess(result)
|
||||
imageView.setImageDrawable(result)
|
||||
if (result is Animatable) {
|
||||
result.start()
|
||||
}
|
||||
val bounds = getLayerBounds(layerKey, layerName, result)
|
||||
imageView.imageMatrix = avatarMatrix
|
||||
val layoutParams = imageView.layoutParams as? LayoutParams
|
||||
|
|
@ -288,7 +292,7 @@ class AvatarView : FrameLayout {
|
|||
|
||||
val hair = prefs.hair
|
||||
if (!hasVisualBuffs) {
|
||||
if (!TextUtils.isEmpty(prefs.chair)) {
|
||||
if (prefs.chair?.isNotBlank() == true && prefs.chair != "chair_none") {
|
||||
layerMap[LayerType.CHAIR] = prefs.chair
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue