mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-07-13 01:38:21 +00:00
tweaks
This commit is contained in:
parent
fd19fe6ede
commit
b3ec9a81a1
10 changed files with 262 additions and 144 deletions
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/confetti_container"
|
||||
|
|
@ -52,9 +52,9 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="@dimen/spacing_xlarge"
|
||||
android:gravity="center"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:text="@string/you_ran_out_of_health"
|
||||
android:textStyle="bold"
|
||||
android:paddingHorizontal="24dp" />
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loss_description"
|
||||
|
|
@ -64,9 +64,9 @@
|
|||
android:layout_marginVertical="@dimen/spacing_medium"
|
||||
android:gravity="center"
|
||||
android:lineSpacingExtra="4dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="20sp"
|
||||
android:paddingHorizontal="12dp" />
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -75,135 +75,128 @@
|
|||
android:gravity="center"
|
||||
android:text="@string/faint_broken_equipment"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="16sp"/>
|
||||
android:textSize="16sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/progress_view"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/restart_button"
|
||||
style="@style/HabiticaButton.Maroon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="69dp"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="@string/faint_button"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginHorizontal="24dp" />
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.habitrpg.android.habitica.ui.views.ads.AdButton
|
||||
android:id="@+id/ad_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
app:activeBackground="@drawable/ad_button_background_content"
|
||||
app:text="@string/watch_ad_to_hang_on"
|
||||
app:textColor="@color/text_primary"
|
||||
android:layout_marginHorizontal="24dp" />
|
||||
app:textColor="@color/text_primary" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/revive_subscriber_wrapper"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_large">
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="65dp"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingEnd="18dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="8dp">
|
||||
<TextView
|
||||
android:id="@+id/revive_subscriber_button"
|
||||
android:layout_marginBottom="@dimen/spacing_large"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:text="@string/subscriber_button_faint"
|
||||
android:textStyle="bold"
|
||||
android:background="@drawable/subscriber_benefit_button_bg"
|
||||
android:gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:backgroundTint="@null"
|
||||
android:textColor="@color/green_1"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:padding="0dp"/>
|
||||
android:layout_height="65dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingEnd="18dp">
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/revive_subscriber_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:background="@drawable/subscriber_benefit_button_bg"
|
||||
android:backgroundTint="@null" />
|
||||
|
||||
<TextView
|
||||
style="@style/Caption2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|end"
|
||||
android:background="@drawable/sub_perk_bg"
|
||||
android:paddingHorizontal="6dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:text="@string/sub_perk"
|
||||
android:textColor="@color/green_500" />
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
style="@style/Body1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/sub_perk_bg"
|
||||
android:textColor="@color/green_500"
|
||||
android:paddingHorizontal="6dp"
|
||||
android:paddingVertical="4dp"
|
||||
style="@style/Caption2"
|
||||
android:layout_gravity="top|end"
|
||||
android:text="@string/sub_perk"/>
|
||||
</FrameLayout>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/faint_subscriber_description"
|
||||
android:layout_marginHorizontal="42dp"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/text_teal"
|
||||
style="@style/Body1"
|
||||
/>
|
||||
android:text="@string/faint_subscriber_description"
|
||||
android:textColor="@color/text_teal" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subscriber_benefit_used_view"
|
||||
style="@style/Body1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="42dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="@dimen/spacing_large"
|
||||
android:gravity="center_horizontal"
|
||||
android:textColor="@color/text_teal"
|
||||
android:layout_marginHorizontal="42dp"
|
||||
tools:text="@string/subscriber_benefit_used_faint"
|
||||
style="@style/Body1"
|
||||
android:layout_marginBottom="@dimen/spacing_large"
|
||||
android:layout_marginTop="8dp"/>
|
||||
tools:text="@string/subscriber_benefit_used_faint" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/unsubbed_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_marginTop="@dimen/spacing_large"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:background="@drawable/subscribe_incentive_bg_topround"
|
||||
>
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="12dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/subscribe_modal_button"
|
||||
style="@style/HabiticaButton.White"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="69dp"
|
||||
android:padding="0dp"
|
||||
android:text="@string/subscribe_incentive_button_faint"
|
||||
android:textStyle="bold"
|
||||
style="@style/HabiticaButton.White"
|
||||
android:textColor="@color/teal_10"
|
||||
android:padding="0dp"/>
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
style="@style/Body1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="3dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/subscribe_incentive_text_faint"
|
||||
android:textColor="@color/teal_1"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
style="@style/Body1"
|
||||
android:layout_marginTop="3dp"/>
|
||||
android:textColor="@color/teal_1" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/snackbar_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="400dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:paddingBottom="20dp"/>
|
||||
android:paddingBottom="20dp" />
|
||||
</FrameLayout>
|
||||
|
|
|
|||
|
|
@ -155,7 +155,6 @@
|
|||
android:id="@+id/subscription3month"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:flagText="@string/save_20"
|
||||
app:gemCapText="@string/subscribe3month_gemcap"
|
||||
app:hourGlassCount="1"
|
||||
app:recurringText="@string/three_months" />
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:layout_marginEnd="3dp"
|
||||
android:layout_marginStart="@dimen/spacing_large"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
|
@ -89,4 +89,4 @@
|
|||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -114,7 +114,10 @@ class ApiClientImpl(
|
|||
|
||||
val calendar = GregorianCalendar()
|
||||
val timeZone = calendar.timeZone
|
||||
val timezoneOffset = -TimeUnit.MINUTES.convert(timeZone.getOffset(calendar.timeInMillis).toLong(), TimeUnit.MILLISECONDS)
|
||||
val timezoneOffset = -TimeUnit.MINUTES.convert(
|
||||
timeZone.getOffset(calendar.timeInMillis).toLong(),
|
||||
TimeUnit.MILLISECONDS
|
||||
)
|
||||
|
||||
val cacheSize: Long = 10 * 1024 * 1024 // 10 MB
|
||||
|
||||
|
|
@ -157,7 +160,8 @@ class ApiClientImpl(
|
|||
}
|
||||
|
||||
else -> {
|
||||
return@addNetworkInterceptor response.newBuilder().header("Cache-Control", "no-store").build()
|
||||
return@addNetworkInterceptor response.newBuilder()
|
||||
.header("Cache-Control", "no-store").build()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -208,7 +212,11 @@ class ApiClientImpl(
|
|||
return process { this.apiService.connectLocal(auth) }
|
||||
}
|
||||
|
||||
override suspend fun connectSocial(network: String, userId: String, accessToken: String): UserAuthResponse? {
|
||||
override suspend fun connectSocial(
|
||||
network: String,
|
||||
userId: String,
|
||||
accessToken: String
|
||||
): UserAuthResponse? {
|
||||
val auth = UserAuthSocial()
|
||||
auth.network = network
|
||||
val authResponse = UserAuthSocialTokens()
|
||||
|
|
@ -232,34 +240,51 @@ class ApiClientImpl(
|
|||
if (SocketTimeoutException::class.java.isAssignableFrom(throwableClass)) {
|
||||
return
|
||||
}
|
||||
|
||||
var isUserInputCall = false
|
||||
@Suppress("DEPRECATION")
|
||||
if (SocketException::class.java.isAssignableFrom(throwableClass) || SSLException::class.java.isAssignableFrom(throwableClass)) {
|
||||
this.showConnectionProblemDialog(R.string.internal_error_api)
|
||||
if (SocketException::class.java.isAssignableFrom(throwableClass)
|
||||
|| SSLException::class.java.isAssignableFrom(throwableClass)
|
||||
) {
|
||||
this.showConnectionProblemDialog(R.string.internal_error_api, isUserInputCall)
|
||||
} else if (throwableClass == SocketTimeoutException::class.java || UnknownHostException::class.java == throwableClass || IOException::class.java == throwableClass) {
|
||||
this.showConnectionProblemDialog(R.string.network_error_no_network_body)
|
||||
this.showConnectionProblemDialog(
|
||||
R.string.network_error_no_network_body,
|
||||
isUserInputCall
|
||||
)
|
||||
} else if (HttpException::class.java.isAssignableFrom(throwable.javaClass)) {
|
||||
val error = throwable as HttpException
|
||||
val res = getErrorResponse(error)
|
||||
val status = error.code()
|
||||
val requestUrl = error.response()?.raw()?.request?.url
|
||||
val path = requestUrl?.encodedPath?.removePrefix("/api/v4") ?: ""
|
||||
isUserInputCall = when {
|
||||
path.startsWith("/groups") && path.endsWith("invite") -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
if (res.message != null && res.message == "RECEIPT_ALREADY_USED") {
|
||||
return
|
||||
}
|
||||
if (error.response()?.raw()?.request?.url?.toString()?.endsWith("/user/push-devices") == true) {
|
||||
if (requestUrl?.toString()?.endsWith("/user/push-devices") == true) {
|
||||
// workaround for an error that sometimes displays that the user already has this push device
|
||||
return
|
||||
}
|
||||
|
||||
if (status in 400..499) {
|
||||
if (res.displayMessage.isNotEmpty()) {
|
||||
showConnectionProblemDialog("", res.displayMessage)
|
||||
showConnectionProblemDialog("", res.displayMessage, isUserInputCall)
|
||||
} else if (status == 401) {
|
||||
showConnectionProblemDialog(R.string.authentication_error_title, R.string.authentication_error_body)
|
||||
showConnectionProblemDialog(
|
||||
R.string.authentication_error_title,
|
||||
R.string.authentication_error_body,
|
||||
isUserInputCall
|
||||
)
|
||||
}
|
||||
} else if (status in 500..599) {
|
||||
this.showConnectionProblemDialog(R.string.internal_error_api)
|
||||
this.showConnectionProblemDialog(R.string.internal_error_api, isUserInputCall)
|
||||
} else {
|
||||
showConnectionProblemDialog(R.string.internal_error_api)
|
||||
showConnectionProblemDialog(R.string.internal_error_api, isUserInputCall)
|
||||
}
|
||||
} else if (JsonSyntaxException::class.java.isAssignableFrom(throwableClass)) {
|
||||
Analytics.logError("Json Error: " + lastAPICallURL + ", " + throwable.message)
|
||||
|
|
@ -268,7 +293,10 @@ class ApiClientImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun updateMember(memberID: String, updateData: Map<String, Map<String, Boolean>>): Member? {
|
||||
override suspend fun updateMember(
|
||||
memberID: String,
|
||||
updateData: Map<String, Map<String, Boolean>>
|
||||
): Member? {
|
||||
return process { apiService.updateUser(memberID, updateData) }
|
||||
}
|
||||
|
||||
|
|
@ -303,24 +331,41 @@ class ApiClientImpl(
|
|||
return this.hostConfig.userID.isNotEmpty() && hostConfig.apiKey.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun showConnectionProblemDialog(resourceMessageString: Int) {
|
||||
showConnectionProblemDialog(null, context.getString(resourceMessageString))
|
||||
private fun showConnectionProblemDialog(
|
||||
resourceMessageString: Int,
|
||||
isFromUserInput: Boolean
|
||||
) {
|
||||
showConnectionProblemDialog(null, context.getString(resourceMessageString), isFromUserInput)
|
||||
}
|
||||
|
||||
private fun showConnectionProblemDialog(resourceTitleString: Int, resourceMessageString: Int) {
|
||||
showConnectionProblemDialog(context.getString(resourceTitleString), context.getString(resourceMessageString))
|
||||
private fun showConnectionProblemDialog(
|
||||
resourceTitleString: Int,
|
||||
resourceMessageString: Int,
|
||||
isFromUserInput: Boolean
|
||||
) {
|
||||
showConnectionProblemDialog(
|
||||
context.getString(resourceTitleString),
|
||||
context.getString(resourceMessageString),
|
||||
isFromUserInput
|
||||
)
|
||||
}
|
||||
|
||||
private var erroredRequestCount = 0
|
||||
private fun showConnectionProblemDialog(
|
||||
resourceTitleString: String?,
|
||||
resourceMessageString: String
|
||||
resourceMessageString: String,
|
||||
isFromUserInput: Boolean
|
||||
) {
|
||||
erroredRequestCount += 1
|
||||
val application = (context as? HabiticaBaseApplication)
|
||||
?: (context.applicationContext as? HabiticaBaseApplication)
|
||||
application?.currentActivity?.get()
|
||||
?.showConnectionProblem(erroredRequestCount, resourceTitleString, resourceMessageString)
|
||||
?.showConnectionProblem(
|
||||
erroredRequestCount,
|
||||
resourceTitleString,
|
||||
resourceMessageString,
|
||||
isFromUserInput
|
||||
)
|
||||
}
|
||||
|
||||
private fun hideConnectionProblemDialog() {
|
||||
|
|
@ -378,7 +423,13 @@ class ApiClientImpl(
|
|||
}
|
||||
|
||||
override suspend fun purchaseItem(type: String, itemKey: String, purchaseQuantity: Int): Void? {
|
||||
return process { apiService.purchaseItem(type, itemKey, mapOf(Pair("quantity", purchaseQuantity))) }
|
||||
return process {
|
||||
apiService.purchaseItem(
|
||||
type,
|
||||
itemKey,
|
||||
mapOf(Pair("quantity", purchaseQuantity))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val lastSubscribeCall: Date? = null
|
||||
|
|
@ -506,7 +557,11 @@ class ApiClientImpl(
|
|||
|
||||
override suspend fun revive(): Items? = process { apiService.revive() }
|
||||
|
||||
override suspend fun useSkill(skillName: String, targetType: String, targetId: String): SkillResponse? {
|
||||
override suspend fun useSkill(
|
||||
skillName: String,
|
||||
targetType: String,
|
||||
targetId: String
|
||||
): SkillResponse? {
|
||||
return process { apiService.useSkill(skillName, targetType, targetId) }
|
||||
}
|
||||
|
||||
|
|
@ -562,22 +617,33 @@ class ApiClientImpl(
|
|||
return processResponse(apiService.leaveGroup(groupId, keepChallenges))
|
||||
}
|
||||
|
||||
override suspend fun postGroupChat(groupId: String, message: Map<String, String>): PostChatMessageResult? {
|
||||
override suspend fun postGroupChat(
|
||||
groupId: String,
|
||||
message: Map<String, String>
|
||||
): PostChatMessageResult? {
|
||||
return process { apiService.postGroupChat(groupId, message) }
|
||||
}
|
||||
|
||||
override suspend fun deleteMessage(groupId: String, messageId: String): Void? {
|
||||
return process { apiService.deleteMessage(groupId, messageId) }
|
||||
}
|
||||
|
||||
override suspend fun deleteInboxMessage(id: String): Void? {
|
||||
return process { apiService.deleteInboxMessage(id) }
|
||||
}
|
||||
|
||||
override suspend fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?): List<Member>? {
|
||||
override suspend fun getGroupMembers(
|
||||
groupId: String,
|
||||
includeAllPublicFields: Boolean?
|
||||
): List<Member>? {
|
||||
return processResponse(apiService.getGroupMembers(groupId, includeAllPublicFields))
|
||||
}
|
||||
|
||||
override suspend fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?, lastId: String): List<Member>? {
|
||||
override suspend fun getGroupMembers(
|
||||
groupId: String,
|
||||
includeAllPublicFields: Boolean?,
|
||||
lastId: String
|
||||
): List<Member>? {
|
||||
return processResponse(apiService.getGroupMembers(groupId, includeAllPublicFields, lastId))
|
||||
}
|
||||
|
||||
|
|
@ -589,7 +655,11 @@ class ApiClientImpl(
|
|||
return process { apiService.reportMember(mid, data) }
|
||||
}
|
||||
|
||||
override suspend fun flagMessage(groupId: String, mid: String, data: MutableMap<String, String>): Void? {
|
||||
override suspend fun flagMessage(
|
||||
groupId: String,
|
||||
mid: String,
|
||||
data: MutableMap<String, String>
|
||||
): Void? {
|
||||
return process { apiService.flagMessage(groupId, mid, data) }
|
||||
}
|
||||
|
||||
|
|
@ -601,7 +671,10 @@ class ApiClientImpl(
|
|||
return process { apiService.seenMessages(groupId) }
|
||||
}
|
||||
|
||||
override suspend fun inviteToGroup(groupId: String, inviteData: Map<String, Any>): List<InviteResponse>? {
|
||||
override suspend fun inviteToGroup(
|
||||
groupId: String,
|
||||
inviteData: Map<String, Any>
|
||||
): List<InviteResponse>? {
|
||||
return process { apiService.inviteToGroup(groupId, inviteData) }
|
||||
}
|
||||
|
||||
|
|
@ -609,7 +682,10 @@ class ApiClientImpl(
|
|||
return process { apiService.rejectGroupInvite(groupId) }
|
||||
}
|
||||
|
||||
override suspend fun getGroupInvites(groupId: String, includeAllPublicFields: Boolean?): List<Member>? {
|
||||
override suspend fun getGroupInvites(
|
||||
groupId: String,
|
||||
includeAllPublicFields: Boolean?
|
||||
): List<Member>? {
|
||||
return process { apiService.getGroupInvites(groupId, includeAllPublicFields) }
|
||||
}
|
||||
|
||||
|
|
@ -663,14 +739,21 @@ class ApiClientImpl(
|
|||
return process { apiService.retrievePartySeekingUsers(page) }
|
||||
}
|
||||
|
||||
override suspend fun getMember(memberId: String) = processResponse(apiService.getMember(memberId))
|
||||
override suspend fun getMemberWithUsername(username: String) = processResponse(apiService.getMemberWithUsername(username))
|
||||
override suspend fun getMember(memberId: String) =
|
||||
processResponse(apiService.getMember(memberId))
|
||||
|
||||
override suspend fun getMemberWithUsername(username: String) =
|
||||
processResponse(apiService.getMemberWithUsername(username))
|
||||
|
||||
override suspend fun getMemberAchievements(memberId: String): List<Achievement>? {
|
||||
return process { apiService.getMemberAchievements(memberId, languageCode) }
|
||||
}
|
||||
|
||||
override suspend fun findUsernames(username: String, context: String?, id: String?): List<FindUsernameResult>? {
|
||||
override suspend fun findUsernames(
|
||||
username: String,
|
||||
context: String?,
|
||||
id: String?
|
||||
): List<FindUsernameResult>? {
|
||||
return process { apiService.findUsernames(username, context, id) }
|
||||
}
|
||||
|
||||
|
|
@ -829,7 +912,14 @@ class ApiClientImpl(
|
|||
}
|
||||
|
||||
override suspend fun transferGems(giftedID: String, amount: Int): Void? {
|
||||
return process { apiService.transferGems(mapOf(Pair("toUserId", giftedID), Pair("gemAmount", amount))) }
|
||||
return process {
|
||||
apiService.transferGems(
|
||||
mapOf(
|
||||
Pair("toUserId", giftedID),
|
||||
Pair("gemAmount", amount)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getTeamPlans(): List<TeamPlan>? {
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ abstract class BaseActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
open fun showConnectionProblem(errorCount: Int, title: String?, message: String) {
|
||||
open fun showConnectionProblem(errorCount: Int, title: String?, message: String, isFromUserInput: Boolean) {
|
||||
val alert = HabiticaAlertDialog(this)
|
||||
alert.setTitle(title)
|
||||
alert.setMessage(message)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,25 @@ import android.os.Bundle
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.edit
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.habitrpg.android.habitica.HabiticaApplication
|
||||
|
|
@ -140,44 +159,59 @@ class DeathActivity : BaseActivity(), SnackbarActivity {
|
|||
binding.subscriberBenefitUsedView.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.reviveSubscriberButton.setOnClickListener {
|
||||
Analytics.sendEvent("second chance perk", EventCategory.BEHAVIOUR, HitType.EVENT)
|
||||
sharedPreferences.edit {
|
||||
putLong("last_sub_revive", Date().time)
|
||||
}
|
||||
lifecycleScope.launchCatching {
|
||||
binding.reviveSubscriberWrapper.startAnimation(Animations.fadeOutAnimation())
|
||||
binding.restartButton.startAnimation(Animations.fadeOutAnimation())
|
||||
binding.progressView.startAnimation(Animations.fadeInAnimation())
|
||||
binding.progressView.setContent {
|
||||
HabiticaTheme {
|
||||
HabiticaCircularProgressView()
|
||||
binding.reviveSubscriberButton.setContent {
|
||||
var isUsingBenefit by remember { mutableStateOf(false) }
|
||||
HabiticaTheme {
|
||||
if (isUsingBenefit) {
|
||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth().height(60.dp)) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
} else {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(60.dp)
|
||||
.clickable {
|
||||
isUsingBenefit = true
|
||||
Analytics.sendEvent(
|
||||
"second chance perk",
|
||||
EventCategory.BEHAVIOUR,
|
||||
HitType.EVENT
|
||||
)
|
||||
sharedPreferences.edit {
|
||||
putLong("last_sub_revive", Date().time)
|
||||
}
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser("stats.hp", 1)
|
||||
MainScope().launchCatching {
|
||||
delay(1000)
|
||||
(HabiticaBaseApplication.getInstance(this@DeathActivity)?.currentActivity?.get() as? SnackbarActivity)?.let { activity ->
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
activity.snackbarContainer(),
|
||||
getString(R.string.subscriber_benefit_success_faint),
|
||||
HabiticaSnackbar.SnackbarDisplayType.SUBSCRIBER_BENEFIT,
|
||||
isSubscriberBenefit = true,
|
||||
duration = 2500
|
||||
)
|
||||
}
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(stringResource(R.string.subscriber_button_faint),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
textAlign = TextAlign.Center)
|
||||
}
|
||||
}
|
||||
}
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser("stats.hp", 1)
|
||||
MainScope().launchCatching {
|
||||
delay(1000)
|
||||
(HabiticaBaseApplication.getInstance(this@DeathActivity)?.currentActivity?.get() as? SnackbarActivity)?.let {activity ->
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
activity.snackbarContainer(), getString(R.string.subscriber_benefit_success_faint), HabiticaSnackbar.SnackbarDisplayType.SUBSCRIBER_BENEFIT, isSubscriberBenefit = true, duration = 2500)
|
||||
}
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
binding.restartButton.setOnClickListener {
|
||||
binding.restartButton.isEnabled = false
|
||||
binding.reviveSubscriberWrapper.startAnimation(Animations.fadeOutAnimation())
|
||||
binding.restartButton.startAnimation(Animations.fadeOutAnimation())
|
||||
binding.progressView.startAnimation(Animations.fadeInAnimation())
|
||||
binding.progressView.setContent {
|
||||
HabiticaTheme {
|
||||
HabiticaCircularProgressView()
|
||||
}
|
||||
}
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
val brokenItem = userRepository.revive()
|
||||
if (brokenItem != null) {
|
||||
|
|
|
|||
|
|
@ -763,11 +763,11 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
|
|||
|
||||
private var errorJob: Job? = null
|
||||
|
||||
override fun showConnectionProblem(errorCount: Int, title: String?, message: String) {
|
||||
if (errorCount == 1) {
|
||||
override fun showConnectionProblem(errorCount: Int, title: String?, message: String, isFromUserInput: Boolean) {
|
||||
if (errorCount == 1 && !isFromUserInput) {
|
||||
showSnackbar(title = title, content = message, displayType = HabiticaSnackbar.SnackbarDisplayType.FAILURE)
|
||||
} else if (title != null) {
|
||||
super.showConnectionProblem(errorCount, title, message)
|
||||
super.showConnectionProblem(errorCount, title, message, isFromUserInput)
|
||||
} else {
|
||||
if (errorJob?.isCancelled == false) {
|
||||
// a new error resets the timer to hide the error message
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.habitrpg.android.habitica.ui.fragments.purchases
|
|||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import com.habitrpg.android.habitica.R
|
||||
|
||||
class EventOutcomeSubscriptionBottomSheetFragment : SubscriptionBottomSheetFragment() {
|
||||
|
|
@ -42,6 +43,7 @@ class EventOutcomeSubscriptionBottomSheetFragment : SubscriptionBottomSheetFragm
|
|||
binding.subscribeBenefits.text = getString(R.string.subscribe_hourglass_incentive_text)
|
||||
binding.subscriberBenefits.hideMysticHourglassBenefit()
|
||||
binding.subscription1month.visibility = View.GONE
|
||||
skus.firstOrNull { buttonForSku(it)?.isVisible == true }?.let { selectSubscription(it) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ open class SubscriptionBottomSheetFragment : BottomSheetDialogFragment() {
|
|||
lateinit var purchaseHandler: PurchaseHandler
|
||||
|
||||
private var selectedSubscriptionSku: ProductDetails? = null
|
||||
private var skus: List<ProductDetails> = emptyList()
|
||||
internal var skus: List<ProductDetails> = emptyList()
|
||||
|
||||
private var user: User? = null
|
||||
private var hasLoadedSubscriptionOptions: Boolean = false
|
||||
|
|
@ -130,7 +130,7 @@ open class SubscriptionBottomSheetFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun selectSubscription(sku: ProductDetails) {
|
||||
internal fun selectSubscription(sku: ProductDetails) {
|
||||
if (this.selectedSubscriptionSku != null) {
|
||||
val oldButton = buttonForSku(this.selectedSubscriptionSku)
|
||||
oldButton?.setIsSelected(false)
|
||||
|
|
@ -141,7 +141,7 @@ open class SubscriptionBottomSheetFragment : BottomSheetDialogFragment() {
|
|||
binding.subscribeButton.isEnabled = true
|
||||
}
|
||||
|
||||
private fun buttonForSku(sku: ProductDetails?): SubscriptionOptionView? {
|
||||
internal fun buttonForSku(sku: ProductDetails?): SubscriptionOptionView? {
|
||||
return buttonForSku(sku?.productId)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
NAME=4.3
|
||||
CODE=6701
|
||||
CODE=6711
|
||||
Loading…
Reference in a new issue