diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index 10ffc1745..1e3d6f3b4 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -1388,6 +1388,7 @@
Rescinded
Pending Invite
Input invalid
+ Can only contain letters a-z, numbers, hyphens, or underscores
- You
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/AccountPreferenceFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/AccountPreferenceFragment.kt
index 9ab7540ae..56962f668 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/AccountPreferenceFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/AccountPreferenceFragment.kt
@@ -426,7 +426,10 @@ class AccountPreferenceFragment :
it?.contains(" ") == false && it.length > 1 && it.length < 20 && !it.contains(regex)
}) {
lifecycleScope.launchCatching {
- userRepository.updateLoginName(it ?: "")
+ val user = userRepository.updateLoginName(it ?: "")
+ if (user == null) {
+ userRepository.retrieveUser(false, forced = true)
+ }
}
}
}
@@ -442,7 +445,7 @@ class AccountPreferenceFragment :
val editText = view?.findViewById(R.id.edit_text)
editText?.text = value
editText?.validator = validator
- editText?.errorText = getString(R.string.invalid_input)
+ editText?.errorText = getString(R.string.username_requirements)
view?.findViewById(R.id.input_layout)?.hint = title
context?.let { context ->
val dialog = HabiticaAlertDialog(context)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyInviteFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyInviteFragment.kt
index 77531f528..d88948a24 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyInviteFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyInviteFragment.kt
@@ -246,6 +246,10 @@ fun PartyInviteView(
inviteButtonState = LoadingButtonState.LOADING
scope.launchCatching({
inviteButtonState = LoadingButtonState.FAILED
+ scope.launchCatching {
+ delay(2.toDuration(DurationUnit.SECONDS))
+ inviteButtonState = LoadingButtonState.CONTENT
+ }
}) {
val responses = viewModel.sendInvites()
if (responses?.isNotEmpty() == true) {
@@ -254,6 +258,8 @@ fun PartyInviteView(
dismiss()
} else {
inviteButtonState = LoadingButtonState.FAILED
+ delay(2.toDuration(DurationUnit.SECONDS))
+ inviteButtonState = LoadingButtonState.CONTENT
}
}
})
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartySeekingFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartySeekingFragment.kt
index 26f202707..7f86191a0 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartySeekingFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartySeekingFragment.kt
@@ -4,6 +4,12 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.compose.animation.AnimatedContent
+import androidx.compose.animation.ExperimentalAnimationApi
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.with
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
@@ -131,6 +137,7 @@ class PartySeekingFragment : BaseFragment() {
}
}
+@OptIn(ExperimentalAnimationApi::class)
@Composable
fun InviteButton(
state : LoadingButtonState,
@@ -138,24 +145,31 @@ fun InviteButton(
modifier : Modifier = Modifier,
isAlreadyInvited: Boolean = false,
) {
- LoadingButton(state = state, onClick = onClick,
- type = if (isAlreadyInvited) LoadingButtonType.DESTRUCTIVE else LoadingButtonType.NORMAL,
- colors = ButtonDefaults.buttonColors(
- backgroundColor = if (isAlreadyInvited) HabiticaTheme.colors.errorBackground else HabiticaTheme.colors.tintedUiSub,
- contentColor = Color.White,
- ), modifier = modifier, successContent = {
- if (isAlreadyInvited) {
- Text(stringResource(R.string.rescinded))
+ AnimatedContent(
+ transitionSpec = { fadeIn(animationSpec = tween(220, delayMillis = 90)) with
+ fadeOut(animationSpec = tween(90)) },
+ targetState = isAlreadyInvited) {isInvited ->
+ if (isInvited) {
+ LoadingButton(state = state, onClick = onClick,
+ type = LoadingButtonType.DESTRUCTIVE,
+ colors = ButtonDefaults.buttonColors(
+ backgroundColor = HabiticaTheme.colors.errorBackground,
+ contentColor = Color.White,
+ ), modifier = modifier, successContent = {
+ Text(stringResource(R.string.rescinded))
+ }) {
+ Text(stringResource(R.string.rescind_invite))
+ }
} else {
- Text(stringResource(R.string.invited))
- }
- }) {
- if (isAlreadyInvited) {
- Text(stringResource(R.string.rescind_invite))
- } else {
- Text(stringResource(R.string.send_invite))
+ LoadingButton(state = state, onClick = onClick,
+ modifier = modifier, successContent = {
+ Text(stringResource(R.string.invited))
+ }) {
+ Text(stringResource(R.string.send_invite))
+ }
}
}
+
}
@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class)
@@ -233,7 +247,7 @@ fun PartySeekingView(
val response: Any? = if (isInvited) viewModel.rescindInvite(member) else viewModel.inviteUser(member)
if (response != null) {
viewModel.inviteStates[member.id] = Pair(isInvited, LoadingButtonState.SUCCESS)
- delay(4.toDuration(DurationUnit.SECONDS))
+ delay(2500.toDuration(DurationUnit.MILLISECONDS))
viewModel.inviteStates[member.id] = Pair(!isInvited, LoadingButtonState.CONTENT)
} else {
viewModel.inviteStates[member.id] = Pair(isInvited, LoadingButtonState.FAILED)