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

View file

@ -1,3 +1,13 @@
package com.habitrpg.android.habitica.models.invitations 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 package com.habitrpg.android.habitica.ui.fragments.social.party
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -72,6 +73,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import java.util.UUID import java.util.UUID
import javax.inject.Inject import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit import kotlin.time.DurationUnit
import kotlin.time.toDuration import kotlin.time.toDuration
@ -279,14 +281,25 @@ fun PartyInviteView(
inviteButtonState = LoadingButtonState.CONTENT inviteButtonState = LoadingButtonState.CONTENT
} }
}) { }) {
val responses = viewModel.sendInvites() val responses: List<InviteResponse>? = viewModel.sendInvites()
if ((responses?.size ?: 0) > 0) { if (!responses.isNullOrEmpty()) {
inviteButtonState = LoadingButtonState.SUCCESS 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() dismiss()
} else { } else {
inviteButtonState = LoadingButtonState.FAILED inviteButtonState = LoadingButtonState.FAILED
delay(2.toDuration(DurationUnit.SECONDS)) delay(2.seconds)
inviteButtonState = LoadingButtonState.CONTENT 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")
}
}
}