Update InviteButton to handle InviteResponse list

- Treat sendInvites() result as List<InviteResponse>
- Branch on InviteResponse.UserInvite vs EmailInvite
- Use isNullOrEmpty() to drive success/failure state transitions
- InviteResponseDeserializer added
- Retain loading > success/failure > content state flow with delays
This commit is contained in:
Hafiz 2025-06-17 19:18:35 -05:00 committed by Phillip Thelen
parent 8f8bb1a5de
commit ab8015b487
4 changed files with 63 additions and 5 deletions

View file

@ -15,6 +15,7 @@ import com.habitrpg.android.habitica.models.inventory.Equipment;
import com.habitrpg.android.habitica.models.inventory.Quest;
import com.habitrpg.android.habitica.models.inventory.QuestCollect;
import com.habitrpg.android.habitica.models.inventory.QuestDropItem;
import com.habitrpg.android.habitica.models.invitations.InviteResponse;
import com.habitrpg.android.habitica.models.members.Member;
import com.habitrpg.android.habitica.models.social.Challenge;
import com.habitrpg.android.habitica.models.social.ChatMessage;
@ -43,6 +44,7 @@ import com.habitrpg.android.habitica.utils.FAQArticleListDeserilializer;
import com.habitrpg.android.habitica.utils.FeedResponseDeserializer;
import com.habitrpg.android.habitica.utils.FindUsernameResultDeserializer;
import com.habitrpg.android.habitica.utils.GroupSerialization;
import com.habitrpg.android.habitica.utils.InviteResponseDeserializer;
import com.habitrpg.android.habitica.utils.MemberSerialization;
import com.habitrpg.android.habitica.utils.NotificationDeserializer;
import com.habitrpg.android.habitica.utils.OwnedItemListDeserializer;
@ -136,6 +138,7 @@ public class GSonFactoryCreator {
.registerTypeAdapter(assignedDetailsListType, new AssignedDetailsDeserializer())
.registerTypeAdapter(Quest.class, new QuestDeserializer())
.registerTypeAdapter(Member.class, new MemberSerialization())
.registerTypeAdapter(InviteResponse.class, new InviteResponseDeserializer())
.registerTypeAdapter(WorldState.class, new WorldStateSerialization())
.registerTypeAdapter(FindUsernameResult.class, new FindUsernameResultDeserializer())
.registerTypeAdapter(Notification.class, new NotificationDeserializer())

View file

@ -1,3 +1,13 @@
package com.habitrpg.android.habitica.models.invitations
class InviteResponse
sealed class InviteResponse {
data class UserInvite(
val id: String,
val name: String,
val inviter: String
) : InviteResponse()
data class EmailInvite(
val email: String
) : InviteResponse()
}

View file

@ -1,6 +1,7 @@
package com.habitrpg.android.habitica.ui.fragments.social.party
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -72,6 +73,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import java.util.UUID
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit
import kotlin.time.toDuration
@ -279,14 +281,25 @@ fun PartyInviteView(
inviteButtonState = LoadingButtonState.CONTENT
}
}) {
val responses = viewModel.sendInvites()
if ((responses?.size ?: 0) > 0) {
val responses: List<InviteResponse>? = viewModel.sendInvites()
if (!responses.isNullOrEmpty()) {
inviteButtonState = LoadingButtonState.SUCCESS
delay(2.toDuration(DurationUnit.SECONDS))
// we are not differentiating between user and email invites here, however in the event we do - we can handle it
responses.forEach { resp ->
when (resp) {
is InviteResponse.UserInvite -> {
// UserInvite is a UUID
}
is InviteResponse.EmailInvite -> {
// EmailInvite is an email address
}
}
}
delay(2.seconds)
dismiss()
} else {
inviteButtonState = LoadingButtonState.FAILED
delay(2.toDuration(DurationUnit.SECONDS))
delay(2.seconds)
inviteButtonState = LoadingButtonState.CONTENT
}
}

View file

@ -0,0 +1,32 @@
package com.habitrpg.android.habitica.utils
import com.google.gson.JsonDeserializer
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonElement
import com.google.gson.JsonParseException
import com.habitrpg.android.habitica.models.invitations.InviteResponse
import io.realm.RealmList
import java.lang.reflect.Type
class InviteResponseDeserializer : JsonDeserializer<InviteResponse> {
override fun deserialize(
json: JsonElement,
typeOfT: Type,
context: JsonDeserializationContext
): InviteResponse {
return when {
json.isJsonPrimitive && json.asJsonPrimitive.isString -> {
InviteResponse.EmailInvite(json.asString)
}
json.isJsonObject -> {
val obj = json.asJsonObject
InviteResponse.UserInvite(
id = obj["id"].asString,
name = obj["name"].asString,
inviter = obj["inviter"].asString
)
}
else -> throw JsonParseException("Unexpected InviteResponse: $json")
}
}
}