Improve event display

This commit is contained in:
Phillip Thelen 2023-01-11 15:44:48 +01:00
parent 1b81f0ce2f
commit b199c2ea73
16 changed files with 93 additions and 35 deletions

View file

@ -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"

View file

@ -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 */

View file

@ -131,7 +131,7 @@ interface ApiClient {
suspend fun disableClasses(): User?
suspend fun markPrivateMessagesRead(): Void?
suspend fun markPrivateMessagesRead()
/* Group API */

View file

@ -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>)

View file

@ -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>? {

View file

@ -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

View file

@ -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

View file

@ -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) -> {

View file

@ -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")
}

View file

@ -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 {

View file

@ -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)

View file

@ -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)

View file

@ -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() {
}

View file

@ -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())

View file

@ -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) {

View file

@ -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
}