diff --git a/Habitica/build.gradle b/Habitica/build.gradle
index 3fe3b87af..5f2119b70 100644
--- a/Habitica/build.gradle
+++ b/Habitica/build.gradle
@@ -95,7 +95,6 @@ dependencies {
implementation 'com.google.firebase:firebase-messaging-ktx'
implementation 'com.google.firebase:firebase-config-ktx'
implementation 'com.google.firebase:firebase-perf-ktx'
- implementation 'com.google.android.gms:play-services-ads:22.4.0'
implementation "com.google.android.gms:play-services-auth:$play_auth_version"
implementation 'com.google.android.flexbox:flexbox:3.0.0'
implementation "com.google.android.gms:play-services-wearable:$play_wearables_version"
@@ -116,7 +115,7 @@ dependencies {
implementation "com.google.accompanist:accompanist-systemuicontroller:$accompanist_version"
implementation 'com.google.android.play:core:1.10.3'
- implementation 'androidx.activity:activity-compose:1.7.2'
+ implementation 'androidx.activity:activity-compose:1.8.0'
implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.animation:animation:$compose_version"
diff --git a/Habitica/google-services.json.example b/Habitica/google-services.json.example
index a75180c30..4df402da1 100644
--- a/Habitica/google-services.json.example
+++ b/Habitica/google-services.json.example
@@ -31,9 +31,6 @@
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
- },
- "ads_service": {
- "status": 2
}
}
},
@@ -62,9 +59,6 @@
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
- },
- "ads_service": {
- "status": 2
}
}
}
diff --git a/Habitica/res/drawable/snackbar_background_red.xml b/Habitica/res/drawable/snackbar_background_red.xml
index c03d995f3..097eab78b 100644
--- a/Habitica/res/drawable/snackbar_background_red.xml
+++ b/Habitica/res/drawable/snackbar_background_red.xml
@@ -1,6 +1,6 @@
-
+
-
\ No newline at end of file
+
diff --git a/Habitica/res/layout/activity_death.xml b/Habitica/res/layout/activity_death.xml
index 2b5e2dc04..e71fd04fd 100644
--- a/Habitica/res/layout/activity_death.xml
+++ b/Habitica/res/layout/activity_death.xml
@@ -1,9 +1,9 @@
+ android:layout_height="match_parent">
@@ -35,7 +35,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
- android:src="@drawable/death_ghost" />
+ android:src="@drawable/death_ghost"
+ android:importantForAccessibility="no" />
+ android:src="@drawable/ic_broken_heart"
+ android:importantForAccessibility="no" />
+ android:textStyle="bold" />
+ android:textSize="20sp" />
+ android:textSize="16sp" />
-
+ android:textStyle="bold" />
+ app:textColor="@color/text_primary" />
-
-
+
+
+ android:layout_height="65dp"
+ android:layout_marginTop="4dp"
+ android:layout_marginBottom="8dp"
+ android:paddingStart="24dp"
+ android:paddingEnd="18dp">
+
+
+
+
+
+
-
-
+ android:text="@string/faint_subscriber_description"
+ android:textColor="@color/text_teal" />
+ tools:text="@string/subscriber_benefit_used_faint" />
+ android:gravity="center_horizontal"
+ android:orientation="vertical"
+ android:paddingHorizontal="24dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="12dp">
+
+ android:textStyle="bold" />
+
+ android:textColor="@color/teal_1" />
+
+ android:paddingBottom="20dp" />
diff --git a/Habitica/res/layout/activity_notifications.xml b/Habitica/res/layout/activity_notifications.xml
index 5866b4e2e..59eb84eea 100644
--- a/Habitica/res/layout/activity_notifications.xml
+++ b/Habitica/res/layout/activity_notifications.xml
@@ -39,15 +39,73 @@
-
+ android:orientation="vertical">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Habitica/res/layout/class_spinner_dropdown_item_selected.xml b/Habitica/res/layout/class_spinner_dropdown_item_selected.xml
index 4c0222bb8..f3fdc92a2 100644
--- a/Habitica/res/layout/class_spinner_dropdown_item_selected.xml
+++ b/Habitica/res/layout/class_spinner_dropdown_item_selected.xml
@@ -4,7 +4,7 @@
android:layout_height="match_parent"
android:paddingTop="4dp"
android:paddingBottom="4dp"
- android:gravity="center_vertical|right">
+ android:gravity="center_vertical|end">
-
\ No newline at end of file
+
diff --git a/Habitica/res/layout/dialog_insufficient_currency.xml b/Habitica/res/layout/dialog_insufficient_currency.xml
index 048b23d47..c75e7da1b 100644
--- a/Habitica/res/layout/dialog_insufficient_currency.xml
+++ b/Habitica/res/layout/dialog_insufficient_currency.xml
@@ -9,10 +9,11 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
- android:scaleType="center" />
+ android:scaleType="center"
+ android:importantForAccessibility="no" />
-
\ No newline at end of file
+
diff --git a/Habitica/res/layout/fragment_bottomsheet_subscription.xml b/Habitica/res/layout/fragment_bottomsheet_subscription.xml
index f2ce1e397..33e06b3a5 100644
--- a/Habitica/res/layout/fragment_bottomsheet_subscription.xml
+++ b/Habitica/res/layout/fragment_bottomsheet_subscription.xml
@@ -24,7 +24,8 @@
android:layout_height="3dp"
android:layout_gravity="center_horizontal"
android:layout_margin="@dimen/spacing_large"
- android:src="@color/offset_background" />
+ android:src="@color/offset_background"
+ android:importantForAccessibility="no" />
+ android:src="@drawable/subscription_banner_image_left"
+ android:importantForAccessibility="no" />
+ android:src="@drawable/subscription_banner_image_right"
+ android:importantForAccessibility="no" />
@@ -116,7 +120,8 @@
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
- android:src="@drawable/separator_fancy" />
+ android:src="@drawable/separator_fancy"
+ android:importantForAccessibility="no" />
+ android:src="@drawable/separator_fancy"
+ android:importantForAccessibility="no" />
diff --git a/Habitica/res/layout/fragment_party_detail.xml b/Habitica/res/layout/fragment_party_detail.xml
index df7666e72..c787b2022 100644
--- a/Habitica/res/layout/fragment_party_detail.xml
+++ b/Habitica/res/layout/fragment_party_detail.xml
@@ -72,7 +72,8 @@
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:paddingStart="@dimen/spacing_medium">
+ android:paddingStart="@dimen/spacing_medium"
+ android:paddingEnd="0dp">
+ app:srcCompat="@drawable/ic_keyboard_arrow_right_gray_24dp"
+ android:importantForAccessibility="no" />
+ android:layout_alignParentBottom="false"
+ android:importantForAccessibility="no" />
+ android:layout_alignParentEnd="true"
+ android:importantForAccessibility="no" />
-
\ No newline at end of file
+
diff --git a/Habitica/res/layout/fragment_report_message.xml b/Habitica/res/layout/fragment_report_message.xml
index 2b446c2d3..4644159b3 100644
--- a/Habitica/res/layout/fragment_report_message.xml
+++ b/Habitica/res/layout/fragment_report_message.xml
@@ -18,7 +18,8 @@
android:layout_height="3dp"
android:layout_gravity="center_horizontal"
android:layout_margin="@dimen/spacing_large"
- android:src="@color/offset_background" />
+ android:src="@color/offset_background"
+ android:importantForAccessibility="no" />
-
\ No newline at end of file
+
diff --git a/Habitica/res/layout/fragment_setup_avatar.xml b/Habitica/res/layout/fragment_setup_avatar.xml
index 27d118f47..8862b49d6 100644
--- a/Habitica/res/layout/fragment_setup_avatar.xml
+++ b/Habitica/res/layout/fragment_setup_avatar.xml
@@ -23,7 +23,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/creator_hills_bg"
- android:layout_centerInParent="true" />
+ android:layout_centerInParent="true"
+ android:importantForAccessibility="no" />
-
\ No newline at end of file
+
diff --git a/Habitica/res/layout/no_notifications.xml b/Habitica/res/layout/no_notifications.xml
index 1e43abf54..0c98882e2 100644
--- a/Habitica/res/layout/no_notifications.xml
+++ b/Habitica/res/layout/no_notifications.xml
@@ -1,9 +1,7 @@
@@ -47,12 +47,14 @@
android:layout_width="wrap_content"
android:layout_height="24dp"
android:src="@drawable/flag_flap"
- android:layout_gravity="center_vertical" />
+ android:layout_gravity="center_vertical"
+ android:importantForAccessibility="no" />
-
\ No newline at end of file
+
diff --git a/Habitica/res/layout/snackbar_view.xml b/Habitica/res/layout/snackbar_view.xml
index fe2f8f56b..9dd48cc9c 100644
--- a/Habitica/res/layout/snackbar_view.xml
+++ b/Habitica/res/layout/snackbar_view.xml
@@ -38,8 +38,7 @@
android:layout_height="wrap_content"
tools:text="This is the Title"
android:gravity="center"
- style="@style/Title2"
- android:textSize="18sp"
+ android:textSize="16sp"
android:visibility="gone"
tools:visibility="visible"
android:textColor="@color/white"/>
@@ -49,8 +48,7 @@
android:layout_height="wrap_content"
tools:text="This is the Content"
android:gravity="center"
- style="@style/Body1"
- android:textSize="13sp"
+ android:textSize="14sp"
android:visibility="gone"
tools:visibility="visible"
android:textColor="@color/white"/>
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index f4d00d3e6..2ab90c761 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -1467,6 +1467,7 @@
Your %s broke
Subscribe to buy Gems with Gold and receive these other exclusive benefits!
Subscribers get Mystic Hourglasses to buy items in the Time Travelers Shop and these other exclusive benefits!
+ SUBSCRIBER BENEFIT
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
index f8af1b80a..b6bf0c52b 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
@@ -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>): Member? {
+ override suspend fun updateMember(
+ memberID: String,
+ updateData: Map>
+ ): 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): PostChatMessageResult? {
+ override suspend fun postGroupChat(
+ groupId: String,
+ message: Map
+ ): 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? {
+ override suspend fun getGroupMembers(
+ groupId: String,
+ includeAllPublicFields: Boolean?
+ ): List? {
return processResponse(apiService.getGroupMembers(groupId, includeAllPublicFields))
}
- override suspend fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?, lastId: String): List? {
+ override suspend fun getGroupMembers(
+ groupId: String,
+ includeAllPublicFields: Boolean?,
+ lastId: String
+ ): List? {
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): Void? {
+ override suspend fun flagMessage(
+ groupId: String,
+ mid: String,
+ data: MutableMap
+ ): 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): List? {
+ override suspend fun inviteToGroup(
+ groupId: String,
+ inviteData: Map
+ ): List? {
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? {
+ override suspend fun getGroupInvites(
+ groupId: String,
+ includeAllPublicFields: Boolean?
+ ): List? {
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? {
return process { apiService.getMemberAchievements(memberId, languageCode) }
}
- override suspend fun findUsernames(username: String, context: String?, id: String?): List? {
+ override suspend fun findUsernames(
+ username: String,
+ context: String?,
+ id: String?
+ ): List? {
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? {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AdHandler.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AdHandler.kt
index b39063d09..b7369d7c8 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AdHandler.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AdHandler.kt
@@ -7,14 +7,14 @@ import android.provider.Settings
import android.util.Log
import androidx.core.content.edit
import androidx.core.os.bundleOf
-import com.google.android.gms.ads.AdRequest
+/*import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.MobileAds
import com.google.android.gms.ads.OnUserEarnedRewardListener
import com.google.android.gms.ads.RequestConfiguration
import com.google.android.gms.ads.rewarded.RewardItem
import com.google.android.gms.ads.rewarded.RewardedAd
-import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback
+import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback*/
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.habitrpg.android.habitica.BuildConfig
@@ -63,8 +63,8 @@ fun String.md5(): String? {
}
}
-class AdHandler(val activity: Activity, val type: AdType, val rewardAction: (Boolean) -> Unit) : OnUserEarnedRewardListener {
- private var rewardedAd: RewardedAd? = null
+class AdHandler(val activity: Activity, val type: AdType, val rewardAction: (Boolean) -> Unit) {
+ //private var rewardedAd: RewardedAd? = null
companion object {
private enum class AdStatus {
@@ -111,16 +111,16 @@ class AdHandler(val activity: Activity, val type: AdType, val rewardAction: (Boo
val android_id: String =
Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
val deviceId: String = android_id.md5()?.uppercase() ?: ""
- val configuration = RequestConfiguration.Builder().setTestDeviceIds(listOf(deviceId)).build()
- MobileAds.setRequestConfiguration(configuration)
+ //val configuration = RequestConfiguration.Builder().setTestDeviceIds(listOf(deviceId)).build()
+ //MobileAds.setRequestConfiguration(configuration)
}
currentAdStatus = AdStatus.INITIALIZING
- MobileAds.initialize(context) {
+ /*MobileAds.initialize(context) {
currentAdStatus = AdStatus.READY
onComplete()
FirebaseCrashlytics.getInstance().recordException(Throwable("Ads Initialized"))
- }
+ }*/
}
fun whenAdsInitialized(context: Context, onComplete: () -> Unit) {
@@ -156,7 +156,7 @@ class AdHandler(val activity: Activity, val type: AdType, val rewardAction: (Boo
fun prepare(onComplete: ((Boolean) -> Unit)? = null) {
whenAdsInitialized(activity) {
- val adRequest = AdRequest.Builder()
+ /*val adRequest = AdRequest.Builder()
.build()
if (BuildConfig.DEBUG || BuildConfig.TESTING_LEVEL == "staff" || BuildConfig.TESTING_LEVEL == "alpha") {
@@ -184,7 +184,7 @@ class AdHandler(val activity: Activity, val type: AdType, val rewardAction: (Boo
onComplete?.invoke(true)
}
}
- )
+ )*/
}
}
@@ -209,22 +209,22 @@ class AdHandler(val activity: Activity, val type: AdType, val rewardAction: (Boo
}
private fun configureReward() {
- rewardedAd?.run { }
+ //rewardedAd?.run { }
}
private fun showRewardedAd() {
if (nextAdAllowedDate(type)?.after(Date()) == true) {
return
}
- if (rewardedAd != null) {
+ /*if (rewardedAd != null) {
rewardedAd?.show(activity, this)
setNextAllowedDate(type)
} else {
Log.d(TAG, "The rewarded ad wasn't ready yet.")
- }
+ }*/
}
- override fun onUserEarnedReward(rewardItem: RewardItem) {
+ /*override fun onUserEarnedReward(rewardItem: RewardItem) {
Analytics.sendEvent(
"adRewardEarned",
EventCategory.BEHAVIOUR,
@@ -240,5 +240,5 @@ class AdHandler(val activity: Activity, val type: AdType, val rewardAction: (Boo
)
)
rewardAction(true)
- }
+ }*/
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/FeedPetUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/FeedPetUseCase.kt
index d78f86ed5..4f9e8500d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/FeedPetUseCase.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/FeedPetUseCase.kt
@@ -14,7 +14,7 @@ import com.habitrpg.android.habitica.databinding.MountImageviewBinding
import com.habitrpg.android.habitica.models.inventory.Food
import com.habitrpg.android.habitica.models.inventory.Pet
import com.habitrpg.android.habitica.ui.activities.BaseActivity
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.BackgroundScene
import com.habitrpg.android.habitica.ui.views.SnackbarActivity
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/HatchPetUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/HatchPetUseCase.kt
index 4d7e7e3dc..00ff01e0e 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/HatchPetUseCase.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/HatchPetUseCase.kt
@@ -13,7 +13,7 @@ import com.habitrpg.android.habitica.databinding.PetImageviewBinding
import com.habitrpg.android.habitica.models.inventory.Egg
import com.habitrpg.android.habitica.models.inventory.HatchingPotion
import com.habitrpg.android.habitica.models.user.Items
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.BackgroundScene
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import com.habitrpg.common.habitica.extensions.layoutInflater
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ShareMountUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ShareMountUseCase.kt
index c95a12280..746b80ab4 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ShareMountUseCase.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ShareMountUseCase.kt
@@ -14,7 +14,7 @@ import androidx.savedstate.setViewTreeSavedStateRegistryOwner
import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.databinding.MountImageviewBinding
import com.habitrpg.android.habitica.ui.activities.BaseActivity
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.BackgroundScene
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import com.habitrpg.common.habitica.extensions.dpToPx
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/SharePetUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/SharePetUseCase.kt
index dc88669a1..6a74e54c0 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/SharePetUseCase.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/SharePetUseCase.kt
@@ -26,7 +26,7 @@ import com.habitrpg.android.habitica.databinding.PetImageviewBinding
import com.habitrpg.android.habitica.models.inventory.Food
import com.habitrpg.android.habitica.models.inventory.Pet
import com.habitrpg.android.habitica.ui.activities.BaseActivity
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.BackgroundScene
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import com.habitrpg.common.habitica.extensions.dpToPx
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ArmoireActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ArmoireActivity.kt
index d6abcc8bb..d1188c343 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ArmoireActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ArmoireActivity.kt
@@ -9,7 +9,6 @@ import android.widget.FrameLayout
import android.widget.RelativeLayout
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
-import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.data.InventoryRepository
@@ -24,16 +23,14 @@ import com.habitrpg.android.habitica.helpers.HitType
import com.habitrpg.android.habitica.helpers.ReviewManager
import com.habitrpg.android.habitica.ui.fragments.purchases.EventOutcomeSubscriptionBottomSheetFragment
import com.habitrpg.android.habitica.ui.fragments.purchases.EventOutcomeSubscriptionBottomSheetFragment.Companion.EVENT_ARMOIRE_OPENED
-import com.habitrpg.android.habitica.ui.fragments.purchases.SubscriptionBottomSheetFragment
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.ads.AdButton
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaBottomSheetDialog
-import com.habitrpg.android.habitica.ui.views.progress.HabiticaCircularProgressView
+import com.habitrpg.common.habitica.views.HabiticaCircularProgressView
import com.habitrpg.common.habitica.extensions.dpToPx
import com.habitrpg.common.habitica.extensions.loadImage
import com.habitrpg.common.habitica.helpers.Animations
import com.habitrpg.common.habitica.helpers.ExceptionHandler
-import com.habitrpg.common.habitica.helpers.MainNavigationController
import com.habitrpg.common.habitica.helpers.launchCatching
import com.plattysoft.leonids.ParticleSystem
import dagger.hilt.android.AndroidEntryPoint
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt
index 042a1d0ef..6c3250464 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt
@@ -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)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BirthdayActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BirthdayActivity.kt
index 5d8c53bdb..3617be509 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BirthdayActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BirthdayActivity.kt
@@ -65,7 +65,7 @@ import com.habitrpg.android.habitica.helpers.EventCategory
import com.habitrpg.android.habitica.helpers.HitType
import com.habitrpg.common.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.helpers.PurchaseHandler
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.CurrencyText
import com.habitrpg.android.habitica.ui.views.HabiticaButton
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt
index 2c42f7b15..5bec8dce8 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt
@@ -1,6 +1,5 @@
package com.habitrpg.android.habitica.ui.activities
-import android.content.Context
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.os.Bundle
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/DeathActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/DeathActivity.kt
index 0c6afb282..5f1dced3a 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/DeathActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/DeathActivity.kt
@@ -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
@@ -32,6 +51,8 @@ import com.habitrpg.common.habitica.extensions.fromHtml
import com.habitrpg.common.habitica.helpers.Animations
import com.habitrpg.common.habitica.helpers.ExceptionHandler
import com.habitrpg.common.habitica.helpers.launchCatching
+import com.habitrpg.common.habitica.theme.HabiticaTheme
+import com.habitrpg.common.habitica.views.HabiticaCircularProgressView
import com.plattysoft.leonids.ParticleSystem
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.MainScope
@@ -138,30 +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 {
- delay(300)
- binding.reviveSubscriberWrapper.startAnimation(Animations.fadeOutAnimation())
- }
- 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)
+ 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)
}
}
- finish()
}
}
binding.restartButton.setOnClickListener {
binding.restartButton.isEnabled = false
+ binding.restartButton.startAnimation(Animations.fadeOutAnimation())
lifecycleScope.launch(ExceptionHandler.coroutine()) {
val brokenItem = userRepository.revive()
if (brokenItem != null) {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
index 99b477d37..d736326b6 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
@@ -39,7 +39,7 @@ import com.habitrpg.android.habitica.models.user.Permission
import com.habitrpg.android.habitica.models.user.Stats
import com.habitrpg.android.habitica.ui.adapter.social.AchievementProfileAdapter
import com.habitrpg.android.habitica.ui.fragments.ReportBottomSheetFragment
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.AppHeaderView
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt
index 030f735ed..64a498f17 100755
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt
@@ -4,7 +4,6 @@ import android.app.NotificationChannel
import android.app.NotificationManager
import android.appwidget.AppWidgetManager
import android.content.ComponentName
-import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Configuration
@@ -18,7 +17,6 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.ActionBarDrawerToggle
-import androidx.appcompat.app.AlertDialog
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.height
@@ -30,14 +28,12 @@ import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.view.children
import androidx.core.view.setPadding
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.setViewTreeLifecycleOwner
import androidx.navigation.NavDestination
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
@@ -68,17 +64,17 @@ import com.habitrpg.android.habitica.interactors.CheckClassSelectionUseCase
import com.habitrpg.android.habitica.interactors.DisplayItemDropUseCase
import com.habitrpg.android.habitica.interactors.NotifyUserUseCase
import com.habitrpg.android.habitica.interactors.ShareAvatarUseCase
-import com.habitrpg.android.habitica.interactors.SharePetUseCase
import com.habitrpg.android.habitica.models.TutorialStep
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.models.user.UserQuestStatus
import com.habitrpg.android.habitica.ui.TutorialView
import com.habitrpg.android.habitica.ui.fragments.NavigationDrawerFragment
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.viewmodels.MainActivityViewModel
import com.habitrpg.android.habitica.ui.viewmodels.NotificationsViewModel
import com.habitrpg.android.habitica.ui.views.AppHeaderView
-import com.habitrpg.android.habitica.ui.views.ComposableAvatarView
+import com.habitrpg.common.habitica.views.ComposableAvatarView
import com.habitrpg.android.habitica.ui.views.GroupPlanMemberList
import com.habitrpg.android.habitica.ui.views.HabiticaButton
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
@@ -767,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
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/NotificationsActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/NotificationsActivity.kt
index 69282cbcf..9c3e2696d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/NotificationsActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/NotificationsActivity.kt
@@ -13,7 +13,10 @@ import android.widget.LinearLayout
import android.widget.RatingBar
import android.widget.TextView
import androidx.activity.viewModels
+import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
+import androidx.core.view.children
+import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.data.InventoryRepository
@@ -40,10 +43,13 @@ import com.habitrpg.common.habitica.models.notifications.NewStuffData
import com.habitrpg.common.habitica.models.notifications.PartyInvitationData
import com.habitrpg.common.habitica.models.notifications.QuestInvitationData
import com.habitrpg.common.habitica.models.notifications.UnallocatedPointsData
+import com.habitrpg.common.habitica.views.HabiticaCircularProgressView
import com.habitrpg.common.habitica.views.PixelArtView
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -74,6 +80,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
private var notifications: List = emptyList()
+ @OptIn(FlowPreview::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -87,17 +94,36 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
inflater = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as? LayoutInflater
+ binding.progressView.setContent {
+ HabiticaCircularProgressView(indicatorSize = 60.dp)
+ }
+
lifecycleScope.launchCatching {
- viewModel.getNotifications().collect {
+ viewModel.getNotifications()
+ .debounce(250)
+ .collect {
setNotifications(it)
viewModel.markNotificationsAsSeen(it)
}
}
+ lifecycleScope.launchCatching {
+ viewModel.getNotificationCount()
+ .collect {
+ binding.notificationsTitleBadge.text = it.toString()
+ }
+ }
+
binding.notificationsRefreshLayout.setOnRefreshListener(this)
lifecycleScope.launchCatching {
viewModel.refreshNotifications()
}
+
+ binding.dismissAllButton.setOnClickListener {
+ HapticFeedbackManager.tap(it)
+ viewModel.dismissAllNotifications(notifications)
+ setNotifications(emptyList())
+ }
}
override fun onSupportNavigateUp(): Boolean {
@@ -131,15 +157,18 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
binding.notificationItems.removeAllViewsInLayout()
binding.notificationItems.showDividers = LinearLayout.SHOW_DIVIDER_NONE
binding.notificationItems.addView(inflater?.inflate(R.layout.no_notifications, binding.notificationItems, false))
+ binding.progressView.isVisible = false
}
+
private fun displayNotificationsListView(notifications: List) {
binding.notificationItems.showDividers = LinearLayout.SHOW_DIVIDER_MIDDLE or LinearLayout.SHOW_DIVIDER_END
- val viewList = arrayListOf()
- createNotificationsHeaderView(notifications.count())?.let { viewList.add(it) }
lifecycleScope.launch(ExceptionHandler.coroutine()) {
- notifications.map {
+ val currentViews = mutableSetOf().apply {
+ addAll(binding.notificationItems.children)
+ }
+ notifications.forEach {
val item: View? = when (it.type) {
Notification.Type.NEW_CHAT_MESSAGE.type -> createNewChatMessageNotification(it)
Notification.Type.NEW_STUFF.type -> createNewStuffNotification(it)
@@ -154,30 +183,22 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
else -> null
}
- if (item != null) {
- viewList.add(item)
+ item?.let { view ->
+ if (!currentViews.removeIf { it.tag == view.tag }) {
+ binding.notificationItems.addView(view)
+ }
}
}
- updateNotificationsAndRefresh(viewList)
- }
- }
- private fun updateNotificationsAndRefresh(newItems: List) {
- val currentViews = (0 until binding.notificationItems.childCount).map {
- binding.notificationItems.getChildAt(it)
- }
- val viewsToRemove = currentViews - newItems
- viewsToRemove.forEach { binding.notificationItems.removeView(it) }
- val viewsToAdd = newItems - currentViews
- viewsToAdd.forEach {
- binding.notificationItems.addView(it)
- }
+ // Remove views that are no longer valid
+ currentViews.forEach { binding.notificationItems.removeView(it) }
- lifecycleScope.launch {
- delay(250)
- // Unnecessary but looks clean c:
- if (binding.notificationItems.visibility != View.VISIBLE) {
- binding.notificationItems.fadeInAnimation(200)
+ lifecycleScope.launch {
+ binding.progressView.isVisible = false
+ delay(250)
+ if (binding.notificationItems.visibility != View.VISIBLE) {
+ binding.notificationItems.fadeInAnimation(200)
+ }
}
}
}
@@ -194,22 +215,6 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
}
}
- private fun createNotificationsHeaderView(notificationCount: Int): View? {
- val header = inflater?.inflate(R.layout.notifications_header, binding.notificationItems, false)
-
- val badge = header?.findViewById(R.id.notifications_title_badge) as? TextView
- badge?.text = notificationCount.toString()
-
- val dismissAllButton = header?.findViewById(R.id.dismiss_all_button) as? Button
- dismissAllButton?.setOnClickListener {
- binding.root.flash()
- HapticFeedbackManager.tap(it)
- viewModel.dismissAllNotifications(notifications)
- }
-
- return header
- }
-
private fun createNewChatMessageNotification(notification: Notification): View? {
val data = notification.data as? NewChatMessageData
val stringId = if (viewModel.isPartyMessage(data)) R.string.new_msg_party else R.string.new_msg_guild
@@ -229,13 +234,16 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
)
}
+ private var baileyNewsNotification: Notification? = null
+
private suspend fun createNewStuffNotification(notification: Notification): View? = withContext(Dispatchers.IO) {
var baileyNotification = notification
val data = notification.data as? NewStuffData
val text = if (data?.title != null) {
fromHtml("" + getString(R.string.new_bailey_update) + "
" + data.title)
} else {
- baileyNotification = userRepository.getNewsNotification() ?: notification
+ baileyNotification = baileyNewsNotification ?: userRepository.getNewsNotification() ?: notification
+ baileyNewsNotification = baileyNotification
val baileyNewsData = baileyNotification.data as? NewStuffData
fromHtml("" + getString(R.string.new_bailey_update) + "
" + baileyNewsData?.title)
}
@@ -332,6 +340,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
textColor: Int? = null
): View? {
val item = inflater?.inflate(R.layout.notification_item, binding.notificationItems, false)
+ item?.tag = notification.id
val container = item?.findViewById(R.id.notification_item) as? View
container?.setOnClickListener {
@@ -345,7 +354,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
val dismissButton = item?.findViewById(R.id.dismiss_button) as? ImageView
dismissButton?.setOnClickListener {
- container?.flash()
+ it.flash()
HapticFeedbackManager.tap(it)
removeNotificationAndRefresh(notification)
viewModel.dismissNotification(notification)
@@ -444,6 +453,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
inviterId: String? = null
): View? {
val item = inflater?.inflate(R.layout.notification_item_actionable, binding.notificationItems, false)
+ item?.tag = notification.id
if (openable) {
val container = item?.findViewById(R.id.notification_item) as? View
@@ -463,7 +473,6 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
val acceptButton = item?.findViewById(R.id.accept_button) as? Button
acceptButton?.setOnClickListener {
- binding.root.flash()
HapticFeedbackManager.tap(it)
removeNotificationAndRefresh(notification)
viewModel.accept(notification.id)
@@ -471,7 +480,6 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
val rejectButton = item?.findViewById(R.id.reject_button) as? Button
rejectButton?.setOnClickListener {
- binding.root.flash()
HapticFeedbackManager.tap(it)
removeNotificationAndRefresh(notification)
viewModel.reject(notification.id)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt
index d707537a2..45dfb5e09 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt
@@ -50,7 +50,10 @@ import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.models.tasks.TaskGroupPlan
import com.habitrpg.android.habitica.ui.helpers.ToolbarColorHelper
import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.android.habitica.ui.theme.textPrimaryFor
+import com.habitrpg.android.habitica.ui.theme.windowBackgroundFor
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.viewmodels.TaskFormViewModel
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt
index 21b48a821..da31f90bc 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt
@@ -50,7 +50,13 @@ import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.common.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.helpers.TaskDescriptionBuilder
import com.habitrpg.android.habitica.models.members.Member
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.android.habitica.ui.theme.contentBackgroundFor
+import com.habitrpg.android.habitica.ui.theme.primaryBackgroundFor
+import com.habitrpg.android.habitica.ui.theme.textPrimaryFor
+import com.habitrpg.android.habitica.ui.theme.textSecondaryFor
+import com.habitrpg.android.habitica.ui.theme.windowBackgroundFor
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.viewmodels.BaseViewModel
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.CompletedAt
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
index 8f8cb3ca3..66a9209af 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
@@ -614,8 +614,8 @@ class NavigationDrawerFragment : DialogFragment() {
// set UP the drawer's list view with items and click listener
lifecycleScope.launchCatching {
- viewModel.getNotifications().collect {
- setNotificationsCount(it.count())
+ viewModel.getNotificationCount().collect {
+ setNotificationsCount(it)
}
}
lifecycleScope.launchCatching {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt
index 8ec32e4d8..5a3a81d16 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt
@@ -35,7 +35,8 @@ import com.habitrpg.common.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.models.inventory.Equipment
import com.habitrpg.android.habitica.ui.activities.BaseActivity
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.SegmentedControl
import com.habitrpg.android.habitica.ui.views.equipment.AvatarCustomizationOverviewView
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt
index 6bf194965..8822e9737 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt
@@ -33,7 +33,6 @@ import com.habitrpg.android.habitica.ui.views.CurrencyText
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaProgressDialog
import com.habitrpg.android.habitica.ui.views.insufficientCurrency.InsufficientGemsDialog
-import com.habitrpg.android.habitica.ui.views.insufficientCurrency.InsufficientHourglassesDialog
import com.habitrpg.android.habitica.ui.views.shops.PurchaseDialog
import com.habitrpg.common.habitica.helpers.ExceptionHandler
import com.habitrpg.common.habitica.helpers.RecyclerViewState
@@ -256,7 +255,7 @@ open class ShopFragment : BaseMainFragment()
alert.setMessage(getString(R.string.change_class_equipment_warning))
alert.addButton(R.string.choose_class, true) { _, _ ->
val dialog = HabiticaProgressDialog.show(
- context,
+ requireActivity(),
getString(R.string.changing_class_progress),
300
)
@@ -274,7 +273,7 @@ open class ShopFragment : BaseMainFragment()
alert.setTitle(getString(R.string.class_confirmation, classIdentifier))
alert.addButton(R.string.choose_class, true) { _, _ ->
val dialog = HabiticaProgressDialog.show(
- context,
+ requireActivity(),
getString(R.string.changing_class_progress),
300
)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/TimeTravelersShopFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/TimeTravelersShopFragment.kt
index 77217c3b9..035b224d2 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/TimeTravelersShopFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/TimeTravelersShopFragment.kt
@@ -4,9 +4,15 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.lifecycle.lifecycleScope
import com.habitrpg.android.habitica.models.shops.Shop
+import com.habitrpg.android.habitica.ui.fragments.purchases.EventOutcomeSubscriptionBottomSheetFragment
+import com.habitrpg.android.habitica.ui.fragments.purchases.SubscriptionBottomSheetFragment
import com.habitrpg.android.habitica.ui.views.CurrencyText
+import com.habitrpg.common.habitica.helpers.launchCatching
import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.delay
+import kotlin.time.Duration.Companion.seconds
@AndroidEntryPoint
class TimeTravelersShopFragment : ShopFragment() {
@@ -22,6 +28,17 @@ class TimeTravelersShopFragment : ShopFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initializeCurrencyViews()
+
+ lifecycleScope.launchCatching {
+ val user = userViewModel.user.value
+ if (user?.isSubscribed != true) {
+ delay(2.seconds)
+ val subscriptionBottomSheet = EventOutcomeSubscriptionBottomSheetFragment().apply {
+ eventType = EventOutcomeSubscriptionBottomSheetFragment.EVENT_HOURGLASS_SHOP_OPENED
+ }
+ activity?.supportFragmentManager?.let { subscriptionBottomSheet.show(it, SubscriptionBottomSheetFragment.TAG) }
+ }
+ }
}
override fun initializeCurrencyViews() {
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 5c4bffedd..617424412 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
@@ -488,7 +488,7 @@ class AccountPreferenceFragment :
}
private fun deleteAccount(password: String) {
- val dialog = context?.let { HabiticaProgressDialog.show(it, R.string.deleting_account) }
+ val dialog = activity?.let { HabiticaProgressDialog.show(it, R.string.deleting_account) }
lifecycleScope.launchCatching({ throwable ->
dialog?.dismiss()
if (throwable is HttpException && throwable.code() == 401) {
@@ -537,7 +537,7 @@ class AccountPreferenceFragment :
}
private fun resetAccount() {
- val dialog = context?.let { HabiticaProgressDialog.show(it, R.string.resetting_account) }
+ val dialog = activity?.let { HabiticaProgressDialog.show(it, R.string.resetting_account) }
lifecycleScope.launch(ExceptionHandler.coroutine()) {
userRepository.resetAccount()
dialog?.dismiss()
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/EventOutcomeSubscriptionBottomSheetFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/EventOutcomeSubscriptionBottomSheetFragment.kt
index d65faa732..a3edf23bd 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/EventOutcomeSubscriptionBottomSheetFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/EventOutcomeSubscriptionBottomSheetFragment.kt
@@ -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 {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GemsPurchaseFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GemsPurchaseFragment.kt
index 1c4a81e4d..72107e79c 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GemsPurchaseFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GemsPurchaseFragment.kt
@@ -28,7 +28,7 @@ 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.common.habitica.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
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/SubscriptionBottomSheetFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/SubscriptionBottomSheetFragment.kt
index 50cf0b65a..96b3a5b62 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/SubscriptionBottomSheetFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/SubscriptionBottomSheetFragment.kt
@@ -52,7 +52,7 @@ open class SubscriptionBottomSheetFragment : BottomSheetDialogFragment() {
lateinit var purchaseHandler: PurchaseHandler
private var selectedSubscriptionSku: ProductDetails? = null
- private var skus: List = emptyList()
+ internal var skus: List = emptyList()
private var user: User? = null
private var hasLoadedSubscriptionOptions: Boolean = false
@@ -112,7 +112,11 @@ open class SubscriptionBottomSheetFragment : BottomSheetDialogFragment() {
for (sku in subscriptions) {
updateButtonLabel(sku, sku.subscriptionOfferDetails?.firstOrNull()?.pricingPhases?.pricingPhaseList?.firstOrNull()?.formattedPrice ?: "")
}
- subscriptions.minByOrNull { it.subscriptionOfferDetails?.firstOrNull()?.pricingPhases?.pricingPhaseList?.firstOrNull()?.priceAmountMicros ?: 0 }?.let { selectSubscription(it) }
+ subscriptions
+ .filter { buttonForSku(it)?.isVisible == true }
+ .minByOrNull {
+ it.subscriptionOfferDetails?.firstOrNull()?.pricingPhases?.pricingPhaseList?.firstOrNull()?.priceAmountMicros ?: 0
+ }?.let { selectSubscription(it) }
hasLoadedSubscriptionOptions = true
updateSubscriptionInfo()
}
@@ -130,7 +134,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 +145,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)
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/SubscriptionFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/SubscriptionFragment.kt
index d7e513126..277977af5 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/SubscriptionFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/SubscriptionFragment.kt
@@ -28,7 +28,7 @@ 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.common.habitica.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
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt
index b8621fef8..efd25bc50 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt
@@ -33,7 +33,7 @@ import com.habitrpg.android.habitica.ui.activities.MainActivity
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemDialogFragment
import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.viewHolders.GroupMemberViewHolder
import com.habitrpg.android.habitica.ui.viewmodels.PartyViewModel
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
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 151e79347..b063de9a4 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
@@ -55,7 +55,8 @@ import com.habitrpg.android.habitica.databinding.FragmentComposeBinding
import com.habitrpg.common.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.models.invitations.InviteResponse
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.viewmodels.BaseViewModel
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.LoadingButtonState
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 39603f947..8e6d3f592 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
@@ -60,13 +60,14 @@ import com.habitrpg.android.habitica.helpers.HitType
import com.habitrpg.android.habitica.models.invitations.InviteResponse
import com.habitrpg.android.habitica.models.members.Member
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.viewmodels.BaseViewModel
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.LoadingButton
import com.habitrpg.android.habitica.ui.views.LoadingButtonState
import com.habitrpg.android.habitica.ui.views.LoadingButtonType
-import com.habitrpg.android.habitica.ui.views.progress.HabiticaCircularProgressView
+import com.habitrpg.common.habitica.views.HabiticaCircularProgressView
import com.habitrpg.android.habitica.ui.views.progress.HabiticaPullRefreshIndicator
import com.habitrpg.android.habitica.ui.views.social.PartySeekingListItem
import com.habitrpg.common.habitica.helpers.launchCatching
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/theme/HabiticaTheme.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/theme/HabiticaTheme.kt
index a376b49ba..766249a40 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/theme/HabiticaTheme.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/theme/HabiticaTheme.kt
@@ -1,222 +1,83 @@
package com.habitrpg.android.habitica.ui.theme
import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Shapes
-import androidx.compose.material.Typography
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.colorResource
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontFamily
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
-import com.google.accompanist.themeadapter.material.createMdcTheme
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.common.habitica.extensions.getThemeColor
+import com.habitrpg.common.habitica.theme.HabiticaColors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
+
@Composable
-fun HabiticaTheme(
- content: @Composable () -> Unit
-) {
- val context = LocalContext.current
- val layoutDirection = LocalLayoutDirection.current
- val (colors, _, _) = createMdcTheme(
- context = context,
- layoutDirection = layoutDirection,
- setTextColors = true
- )
- MaterialTheme(
- colors = colors ?: MaterialTheme.colors,
- typography = Typography(
- defaultFontFamily = FontFamily.Default,
- h1 = TextStyle(
- fontWeight = FontWeight.Medium,
- fontSize = 20.sp,
- letterSpacing = (0.05).sp
- ),
- h2 = TextStyle(
- fontWeight = FontWeight.Normal,
- fontSize = 28.sp,
- letterSpacing = (0.05).sp
- ),
- subtitle1 = TextStyle(
- fontWeight = FontWeight.Medium,
- fontSize = 16.sp
- ),
- subtitle2 = TextStyle(
- fontWeight = FontWeight.Normal,
- fontSize = 16.sp,
- letterSpacing = 0.1.sp
- ),
- body1 = TextStyle(
- fontWeight = FontWeight.Medium,
- fontSize = 14.sp,
- letterSpacing = 0.35.sp,
- lineHeight = 16.sp
- ),
- body2 = TextStyle(
- fontWeight = FontWeight.Normal,
- fontSize = 14.sp,
- letterSpacing = 0.2.sp,
- lineHeight = 16.sp
- ),
- button = TextStyle(
- fontWeight = FontWeight.Medium,
- fontSize = 14.sp,
- letterSpacing = 1.25.sp
- ),
- caption = TextStyle(
- fontWeight = FontWeight.Bold,
- fontSize = 12.sp
- ),
- overline = TextStyle(
- fontWeight = FontWeight.Medium,
- fontSize = 10.sp,
- letterSpacing = 1.5.sp
- )
- ),
- shapes = Shapes(
- RoundedCornerShape(4.dp),
- RoundedCornerShape(8.dp),
- RoundedCornerShape(12.dp)
- ),
- content = content
- )
+fun HabiticaColors.textPrimaryFor(task: Task?): Color {
+ return colorResource((if (isSystemInDarkTheme()) task?.extraExtraLightTaskColor else task?.extraDarkTaskColor) ?: R.color.text_primary)
}
-val Typography.caption1
- get() = caption
-val Typography.caption2
- get() = TextStyle(
- fontWeight = FontWeight.Medium,
- fontSize = 12.sp,
- letterSpacing = 0.4.sp
- )
-val Typography.caption3
- get() = TextStyle(
- fontWeight = FontWeight.Medium,
- fontSize = 12.sp,
- letterSpacing = 0.3.sp,
- lineHeight = 14.sp
- )
-val Typography.caption4
- get() = TextStyle(
- fontWeight = FontWeight.Normal,
- fontSize = 12.sp,
- letterSpacing = 0.35.sp
- )
-val Typography.subtitle3
- get() = TextStyle(
- fontWeight = FontWeight.Normal,
- fontSize = 16.sp,
- letterSpacing = 0.15.sp
- )
-
-object HabiticaTheme {
- val typography: Typography
- @Composable
- get() = MaterialTheme.typography
-
- val shapes: Shapes
- @Composable
- get() = MaterialTheme.shapes
-
- val colors: HabiticaColors
- @Composable
- get() {
- val context = LocalContext.current
- return HabiticaColors(
- windowBackground = Color(context.getThemeColor(R.attr.colorWindowBackground)),
- contentBackground = Color(context.getThemeColor(R.attr.colorContentBackground)),
- contentBackgroundOffset = Color(context.getThemeColor(R.attr.colorContentBackgroundOffset)),
- offsetBackground = Color(context.getThemeColor(R.attr.colorOffsetBackground)),
- textPrimary = Color(context.getThemeColor(R.attr.textColorPrimary)),
- textSecondary = Color(context.getThemeColor(R.attr.textColorSecondary)),
- textTertiary = Color(ContextCompat.getColor(context, R.color.text_ternary)),
- textQuad = Color(ContextCompat.getColor(context, R.color.text_quad)),
- textDimmed = Color(ContextCompat.getColor(context, R.color.text_dimmed)),
- tintedUiMain = Color(context.getThemeColor(R.attr.tintedUiMain)),
- tintedUiSub = Color(context.getThemeColor(R.attr.tintedUiSub)),
- tintedUiDetails = Color(context.getThemeColor(R.attr.tintedUiDetails)),
- pixelArtBackground = Color(context.getThemeColor(R.attr.colorContentBackground)),
- errorBackground = Color(ContextCompat.getColor(context, R.color.background_red)),
- errorColor = Color(ContextCompat.getColor(context, R.color.text_red)),
- successBackground = Color(ContextCompat.getColor(context, R.color.background_green)),
- successColor = Color(ContextCompat.getColor(context, R.color.text_green))
- )
- }
+@Composable
+fun HabiticaColors.textSecondaryFor(task: Task?): Color {
+ return colorResource((if (isSystemInDarkTheme()) task?.extraLightTaskColor else task?.lowSaturationTaskColor) ?: R.color.brand_sub_text)
}
-class HabiticaColors(
- val windowBackground: Color,
- val contentBackground: Color,
- val contentBackgroundOffset: Color,
- val offsetBackground: Color,
- val textPrimary: Color,
- val textSecondary: Color,
- val textTertiary: Color,
- val textQuad: Color,
- val textDimmed: Color,
- val tintedUiMain: Color,
- val tintedUiSub: Color,
- val tintedUiDetails: Color,
- val pixelArtBackground: Color,
- val errorBackground: Color,
- val errorColor: Color,
- val successBackground: Color,
- val successColor: Color
-) {
+@Composable
+fun HabiticaColors.primaryBackgroundFor(task: Task?): Color {
+ return colorResource((if (isSystemInDarkTheme()) task?.mediumTaskColor else task?.lightTaskColor) ?: R.color.brand_400)
+}
- @Composable
- fun textPrimaryFor(task: Task?): Color {
- return colorResource((if (isSystemInDarkTheme()) task?.extraExtraLightTaskColor else task?.extraDarkTaskColor) ?: R.color.text_primary)
- }
+@Composable
+fun HabiticaColors.windowBackgroundFor(task: Task?): Color {
+ return (if (isSystemInDarkTheme()) task?.extraExtraDarkTaskColor else task?.extraExtraLightTaskColor)?.let { colorResource(it) } ?: windowBackground
+}
- @Composable
- fun textSecondaryFor(task: Task?): Color {
- return colorResource((if (isSystemInDarkTheme()) task?.extraLightTaskColor else task?.lowSaturationTaskColor) ?: R.color.brand_sub_text)
- }
+@Composable
+fun HabiticaColors.contentBackgroundFor(task: Task?): Color {
+ return (if (isSystemInDarkTheme()) task?.darkestTaskColor else task?.lightestTaskColor)?.let { colorResource(it) } ?: windowBackground
+}
- @Composable
- fun primaryBackgroundFor(task: Task?): Color {
- return colorResource((if (isSystemInDarkTheme()) task?.mediumTaskColor else task?.lightTaskColor) ?: R.color.brand_400)
- }
-
- @Composable
- fun windowBackgroundFor(task: Task?): Color {
- return (if (isSystemInDarkTheme()) task?.extraExtraDarkTaskColor else task?.extraExtraLightTaskColor)?.let { colorResource(it) } ?: windowBackground
- }
-
- @Composable
- fun contentBackgroundFor(task: Task?): Color {
- return (if (isSystemInDarkTheme()) task?.darkestTaskColor else task?.lightestTaskColor)?.let { colorResource(it) } ?: windowBackground
- }
-
- @Composable
- fun pixelArtBackground(hasIcon: Boolean): Color {
- return if (isSystemInDarkTheme()) {
- colorResource(if (hasIcon) R.color.gray_200 else R.color.gray_5)
- } else {
- colorResource(if (hasIcon) R.color.content_background else R.color.content_background_offset)
- }
- }
-
- @Composable
- fun basicTextColor(): Color {
- return colorResource(R.color.gray200_gray400)
- }
-
- @Composable
- fun basicButtonColor(): Color {
- return colorResource(R.color.gray700_gray10)
+@Composable
+fun HabiticaColors.pixelArtBackground(hasIcon: Boolean): Color {
+ return if (isSystemInDarkTheme()) {
+ colorResource(if (hasIcon) R.color.gray_200 else R.color.gray_5)
+ } else {
+ colorResource(if (hasIcon) R.color.content_background else R.color.content_background_offset)
}
}
-class HabiticaTypography
+@Composable
+fun HabiticaColors.basicTextColor(): Color {
+ return colorResource(R.color.gray200_gray400)
+}
+
+@Composable
+fun HabiticaColors.basicButtonColor(): Color {
+ return colorResource(R.color.gray700_gray10)
+}
+
+val HabiticaTheme.colors: HabiticaColors
+ @Composable
+ get() {
+ val context = LocalContext.current
+ return HabiticaColors(
+ windowBackground = Color(context.getThemeColor(R.attr.colorWindowBackground)),
+ contentBackground = Color(context.getThemeColor(R.attr.colorContentBackground)),
+ contentBackgroundOffset = Color(context.getThemeColor(R.attr.colorContentBackgroundOffset)),
+ offsetBackground = Color(context.getThemeColor(R.attr.colorOffsetBackground)),
+ textPrimary = Color(context.getThemeColor(R.attr.textColorPrimary)),
+ textSecondary = Color(context.getThemeColor(R.attr.textColorSecondary)),
+ textTertiary = Color(ContextCompat.getColor(context, R.color.text_ternary)),
+ textQuad = Color(ContextCompat.getColor(context, R.color.text_quad)),
+ textDimmed = Color(ContextCompat.getColor(context, R.color.text_dimmed)),
+ tintedUiMain = Color(context.getThemeColor(R.attr.tintedUiMain)),
+ tintedUiSub = Color(context.getThemeColor(R.attr.tintedUiSub)),
+ tintedUiDetails = Color(context.getThemeColor(R.attr.tintedUiDetails)),
+ pixelArtBackground = Color(context.getThemeColor(R.attr.colorContentBackground)),
+ errorBackground = Color(ContextCompat.getColor(context, R.color.background_red)),
+ errorColor = Color(ContextCompat.getColor(context, R.color.text_red)),
+ successBackground = Color(ContextCompat.getColor(context, R.color.background_green)),
+ successColor = Color(ContextCompat.getColor(context, R.color.text_green))
+ )
+ }
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/NotificationsViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/NotificationsViewModel.kt
index e0e31108b..cd4819bba 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/NotificationsViewModel.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/NotificationsViewModel.kt
@@ -56,6 +56,7 @@ open class NotificationsViewModel @Inject constructor(
)
private var party: UserParty? = null
+ private var hasStats = false
private val customNotifications = MutableStateFlow>(emptyList())
@@ -63,6 +64,7 @@ open class NotificationsViewModel @Inject constructor(
userViewModel.user.observeForever {
if (it == null) return@observeForever
party = it.party
+ hasStats = it.hasClass
val notifications = convertInvitationsToNotifications(it)
if (it.flags?.newStuff == true) {
val notification = Notification()
@@ -89,7 +91,11 @@ open class NotificationsViewModel @Inject constructor(
}
fun getNotificationCount(): Flow {
- return getNotifications().map { it.count() }.distinctUntilChanged()
+ return getNotifications().map {
+ it.count { notification ->
+ (notification.type != Notification.Type.UNALLOCATED_STATS_POINTS.type) || hasStats
+ }
+ }.distinctUntilChanged()
}
fun allNotificationsSeen(): Flow {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt
index 3b8ee60de..91d88261b 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt
@@ -62,7 +62,11 @@ import com.habitrpg.android.habitica.models.user.Purchases
import com.habitrpg.android.habitica.models.user.Stats
import com.habitrpg.android.habitica.models.user.SubscriptionPlan
import com.habitrpg.android.habitica.models.user.User
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.basicButtonColor
+import com.habitrpg.android.habitica.ui.theme.basicTextColor
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
+import com.habitrpg.common.habitica.views.ComposableAvatarView
import com.habitrpg.shared.habitica.models.Avatar
import kotlin.random.Random
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt
index e0aaa96d0..54a47c8bc 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt
@@ -32,7 +32,8 @@ import androidx.compose.ui.unit.dp
import androidx.fragment.app.Fragment
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.habitrpg.android.habitica.R
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/GroupPlanMemberList.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/GroupPlanMemberList.kt
index ba1c772c6..85d8cb83b 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/GroupPlanMemberList.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/GroupPlanMemberList.kt
@@ -33,7 +33,9 @@ import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.models.user.Authentication
import com.habitrpg.android.habitica.models.user.Profile
import com.habitrpg.android.habitica.models.user.Stats
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
+import com.habitrpg.common.habitica.views.ComposableAvatarView
import kotlin.random.Random
@Composable
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaButton.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaButton.kt
index ff9d5b67b..35ec08438 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaButton.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaButton.kt
@@ -16,7 +16,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.common.habitica.theme.HabiticaTheme
@Composable
fun HabiticaButton(
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LabeledBar.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LabeledBar.kt
index 131f091fd..c50bdb5ca 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LabeledBar.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LabeledBar.kt
@@ -42,7 +42,8 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.habitrpg.android.habitica.R
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.common.habitica.helpers.NumberAbbreviator
import java.text.NumberFormat
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LoadingButton.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LoadingButton.kt
index 857ea896f..e8a94515d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LoadingButton.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LoadingButton.kt
@@ -51,7 +51,8 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.habitrpg.android.habitica.R
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/UserRow.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/UserRow.kt
index f44d7110b..98ece1432 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/UserRow.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/UserRow.kt
@@ -19,6 +19,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import com.habitrpg.common.habitica.views.ComposableAvatarView
import com.habitrpg.shared.habitica.models.Avatar
@Composable
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaProgressDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaProgressDialog.kt
index c9f9c3858..c81e9ac7b 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaProgressDialog.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaProgressDialog.kt
@@ -1,19 +1,40 @@
package com.habitrpg.android.habitica.ui.views.dialogs
import android.content.Context
-import com.habitrpg.android.habitica.R
+import androidx.appcompat.app.AppCompatActivity
+import androidx.compose.foundation.layout.size
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.unit.dp
+import androidx.fragment.app.FragmentActivity
+import androidx.lifecycle.setViewTreeLifecycleOwner
+import androidx.savedstate.setViewTreeSavedStateRegistryOwner
+import com.habitrpg.common.habitica.theme.HabiticaTheme
+import com.habitrpg.common.habitica.views.HabiticaCircularProgressView
import com.habitrpg.common.habitica.extensions.dpToPx
class HabiticaProgressDialog(context: Context) : HabiticaAlertDialog(context) {
companion object {
- fun show(context: Context, titleID: Int): HabiticaProgressDialog {
+ fun show(context: FragmentActivity, titleID: Int): HabiticaProgressDialog {
return show(context, context.getString(titleID))
}
- fun show(context: Context, title: String?, dialogWidth: Int = 300): HabiticaProgressDialog {
+ fun show(context: FragmentActivity, title: String?, dialogWidth: Int = 300): HabiticaProgressDialog {
val dialog = HabiticaProgressDialog(context)
- dialog.setAdditionalContentView(R.layout.circular_progress)
+ val composeView = ComposeView(context)
+ dialog.setAdditionalContentView(composeView)
+ composeView.setContent {
+ HabiticaTheme {
+ HabiticaCircularProgressView(Modifier.size(60.dp))
+ }
+ }
+ dialog.window?.let {
+ dialog.additionalContentView?.setViewTreeSavedStateRegistryOwner(context)
+ it.decorView.setViewTreeSavedStateRegistryOwner(context)
+ dialog.additionalContentView?.setViewTreeLifecycleOwner(context)
+ it.decorView.setViewTreeLifecycleOwner(context)
+ }
dialog.dialogWidth = dialogWidth.dpToPx(context)
dialog.setTitle(title)
dialog.enqueue()
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/equipment/EquipmentOverviewView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/equipment/EquipmentOverviewView.kt
index eb279bb5c..01d75e36f 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/equipment/EquipmentOverviewView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/equipment/EquipmentOverviewView.kt
@@ -26,8 +26,10 @@ import androidx.compose.ui.unit.dp
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.models.user.Outfit
import com.habitrpg.android.habitica.models.user.Preferences
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
-import com.habitrpg.android.habitica.ui.theme.caption2
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.android.habitica.ui.theme.pixelArtBackground
+import com.habitrpg.common.habitica.theme.HabiticaTheme
+import com.habitrpg.common.habitica.theme.caption2
import com.habitrpg.android.habitica.ui.views.PixelArtView
@Composable
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/preferences/PauseResumeDamageView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/preferences/PauseResumeDamageView.kt
index f994dc6d5..54661a7d1 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/preferences/PauseResumeDamageView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/preferences/PauseResumeDamageView.kt
@@ -14,7 +14,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.habitrpg.android.habitica.R
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.HabiticaButton
@Composable
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/progress/HabiticaPullRefreshIndicator.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/progress/HabiticaPullRefreshIndicator.kt
index 5f5462e04..b42dfa2ae 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/progress/HabiticaPullRefreshIndicator.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/progress/HabiticaPullRefreshIndicator.kt
@@ -23,7 +23,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
+import com.habitrpg.common.habitica.views.HabiticaCircularProgressView
import java.lang.Float.min
@OptIn(ExperimentalMaterialApi::class)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt
index 3ab9210c1..f9906a37c 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt
@@ -380,10 +380,7 @@ class PurchaseDialog(
}
parentActivity?.let { activity -> subscriptionBottomSheet.show(activity.supportFragmentManager, SubscriptionBottomSheetFragment.TAG) }
}
-
}
-
-
}
return
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/PartySeekingListItem.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/PartySeekingListItem.kt
index 9ffeae46e..a1cc051a5 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/PartySeekingListItem.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/PartySeekingListItem.kt
@@ -35,9 +35,10 @@ import com.habitrpg.android.habitica.models.user.ContributorInfo
import com.habitrpg.android.habitica.models.user.Profile
import com.habitrpg.android.habitica.models.user.Stats
import com.habitrpg.android.habitica.ui.fragments.social.party.InviteButton
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.ClassText
-import com.habitrpg.android.habitica.ui.views.ComposableAvatarView
+import com.habitrpg.common.habitica.views.ComposableAvatarView
import com.habitrpg.android.habitica.ui.views.ComposableUsernameLabel
import com.habitrpg.android.habitica.ui.views.LoadingButtonState
import com.habitrpg.common.habitica.extensions.toLocale
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountBottomSheet.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountBottomSheet.kt
index 555bba7b3..e861effd1 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountBottomSheet.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/MountBottomSheet.kt
@@ -49,7 +49,8 @@ import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.interactors.ShareMountUseCase
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.BackgroundScene
import com.habitrpg.android.habitica.ui.views.HabiticaButton
import com.habitrpg.common.habitica.helpers.launchCatching
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/PetBottomSheet.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/PetBottomSheet.kt
index c9a32f316..c263c4e79 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/PetBottomSheet.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stable/PetBottomSheet.kt
@@ -69,7 +69,8 @@ import com.habitrpg.android.habitica.interactors.ShareMountUseCase
import com.habitrpg.android.habitica.interactors.SharePetUseCase
import com.habitrpg.android.habitica.models.inventory.Food
import com.habitrpg.android.habitica.models.inventory.Pet
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.BackgroundScene
import com.habitrpg.android.habitica.ui.views.HabiticaButton
import com.habitrpg.android.habitica.ui.views.PixelArtView
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignedView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignedView.kt
index f2b2efe7f..0aa27fb8d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignedView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignedView.kt
@@ -27,7 +27,8 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.models.Assignable
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.CompletedAt
import com.habitrpg.android.habitica.ui.views.UserRow
import java.util.Date
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/HabitScoringButtonsView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/HabitScoringButtonsView.kt
index aa541f6a9..fa42706f7 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/HabitScoringButtonsView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/HabitScoringButtonsView.kt
@@ -39,7 +39,8 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.habitrpg.android.habitica.R
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.common.habitica.extensions.getThemeColor
@Composable
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskDifficultyButtons.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskDifficultyButtons.kt
index fbddfb3fc..2fc9e8690 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskDifficultyButtons.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskDifficultyButtons.kt
@@ -41,7 +41,8 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.habitrpg.android.habitica.R
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import com.habitrpg.common.habitica.extensions.getThemeColor
import com.habitrpg.common.habitica.extensions.nameRes
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskFormSelector.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskFormSelector.kt
index f68e13f18..c0f863476 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskFormSelector.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskFormSelector.kt
@@ -33,7 +33,8 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.habitrpg.android.habitica.R
-import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
+import com.habitrpg.android.habitica.ui.theme.colors
+import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.common.habitica.extensions.getThemeColor
data class LabeledValue(val label: String, val value: V)
diff --git a/build.gradle b/build.gradle
index bd4791315..0701b0b42 100644
--- a/build.gradle
+++ b/build.gradle
@@ -13,7 +13,7 @@ buildscript {
amplitude_version = '1.6.1'
appcompat_version = '1.6.1'
coil_version = '2.4.0'
- compose_version = '1.5.2'
+ compose_version = '1.5.4'
core_ktx_version = '1.12.0'
coroutines_version = '1.7.2'
daggerhilt_version = '2.47'
@@ -25,7 +25,7 @@ buildscript {
markwon_version = '4.6.2'
mockk_version = '1.13.4'
moshi_version = '1.15.0'
- navigation_version = '2.7.3'
+ navigation_version = '2.7.4'
okhttp_version = '4.11.0'
paging_version = '3.2.1'
play_wearables_version = '18.1.0'
diff --git a/common/build.gradle.kts b/common/build.gradle.kts
index dbda9921a..7616d45c0 100644
--- a/common/build.gradle.kts
+++ b/common/build.gradle.kts
@@ -37,6 +37,11 @@ android {
buildFeatures {
viewBinding = true
+ compose = true
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion = "1.5.3"
}
compileOptions {
@@ -84,7 +89,9 @@ android {
}
val core_ktx_version: String by rootExtra
+val accompanist_version: String by rootExtra
val appcompat_version: String by rootExtra
+val compose_version: String by rootExtra
val markwon_version: String by rootExtra
val coil_version: String by rootExtra
val mockk_version: String by rootExtra
@@ -111,7 +118,7 @@ dependencies {
implementation("androidx.recyclerview:recyclerview:1.3.1")
implementation("androidx.navigation:navigation-common-ktx:$navigation_version")
implementation("androidx.navigation:navigation-runtime-ktx:$navigation_version")
- implementation("com.google.android.material:material:1.9.0")
+ implementation("com.google.android.material:material:1.10.0")
testImplementation("io.mockk:mockk:$mockk_version")
testImplementation("io.mockk:mockk-android:$mockk_version")
@@ -124,6 +131,15 @@ dependencies {
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version")
+ implementation("androidx.activity:activity-compose:1.8.0")
+ implementation("androidx.compose.runtime:runtime-livedata:$compose_version")
+ implementation("androidx.compose.material:material:$compose_version")
+ implementation("androidx.compose.animation:animation:$compose_version")
+ implementation("androidx.compose.ui:ui-text-google-fonts:$compose_version")
+ implementation("androidx.compose.ui:ui-tooling:$compose_version")
+ implementation("androidx.compose.material3:material3:1.1.2")
+ implementation("com.google.accompanist:accompanist-themeadapter-material:$accompanist_version")
+
implementation(project(":shared"))
}
diff --git a/common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt b/common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt
index 16d3c152b..eadb59c66 100644
--- a/common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt
+++ b/common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt
@@ -4,12 +4,18 @@ import android.view.View
import android.view.ViewGroup
import android.view.animation.AlphaAnimation
import android.widget.ProgressBar
+import androidx.compose.foundation.layout.size
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.common.habitica.R
import com.habitrpg.common.habitica.databinding.EmptyItemBinding
import com.habitrpg.common.habitica.databinding.FailedItemBinding
+import com.habitrpg.common.habitica.theme.HabiticaTheme
+import com.habitrpg.common.habitica.views.HabiticaCircularProgressView
data class EmptyItem(
var title: String,
@@ -87,7 +93,12 @@ class RecyclerViewStateAdapter(val showLoadingAsEmpty: Boolean = false) : Recycl
animation1.duration = 300
animation1.startOffset = 500
animation1.fillAfter = true
- view.findViewById(R.id.loading_indicator).startAnimation(animation1)
+ view.findViewById(R.id.compose_view).startAnimation(animation1)
+ view.findViewById(R.id.compose_view).setContent {
+ HabiticaTheme {
+ HabiticaCircularProgressView(Modifier.size(60.dp))
+ }
+ }
object : RecyclerView.ViewHolder(view) {}
}
1 -> FailedViewHolder(parent.inflate(R.layout.failed_item))
diff --git a/common/src/main/java/com/habitrpg/common/habitica/theme/HabiticaTheme.kt b/common/src/main/java/com/habitrpg/common/habitica/theme/HabiticaTheme.kt
new file mode 100644
index 000000000..df2ef2192
--- /dev/null
+++ b/common/src/main/java/com/habitrpg/common/habitica/theme/HabiticaTheme.kt
@@ -0,0 +1,146 @@
+package com.habitrpg.common.habitica.theme
+
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Shapes
+import androidx.compose.material.Typography
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.google.accompanist.themeadapter.material.createMdcTheme
+
+@Composable
+fun HabiticaTheme(
+ content: @Composable () -> Unit
+) {
+ val context = LocalContext.current
+ val layoutDirection = LocalLayoutDirection.current
+ val (colors, _, _) = createMdcTheme(
+ context = context,
+ layoutDirection = layoutDirection,
+ setTextColors = true
+ )
+ MaterialTheme(
+ colors = colors ?: MaterialTheme.colors,
+ typography = Typography(
+ defaultFontFamily = FontFamily.Default,
+ h1 = TextStyle(
+ fontWeight = FontWeight.Medium,
+ fontSize = 20.sp,
+ letterSpacing = (0.05).sp
+ ),
+ h2 = TextStyle(
+ fontWeight = FontWeight.Normal,
+ fontSize = 28.sp,
+ letterSpacing = (0.05).sp
+ ),
+ subtitle1 = TextStyle(
+ fontWeight = FontWeight.Medium,
+ fontSize = 16.sp
+ ),
+ subtitle2 = TextStyle(
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ letterSpacing = 0.1.sp
+ ),
+ body1 = TextStyle(
+ fontWeight = FontWeight.Medium,
+ fontSize = 14.sp,
+ letterSpacing = 0.35.sp,
+ lineHeight = 16.sp
+ ),
+ body2 = TextStyle(
+ fontWeight = FontWeight.Normal,
+ fontSize = 14.sp,
+ letterSpacing = 0.2.sp,
+ lineHeight = 16.sp
+ ),
+ button = TextStyle(
+ fontWeight = FontWeight.Medium,
+ fontSize = 14.sp,
+ letterSpacing = 1.25.sp
+ ),
+ caption = TextStyle(
+ fontWeight = FontWeight.Bold,
+ fontSize = 12.sp
+ ),
+ overline = TextStyle(
+ fontWeight = FontWeight.Medium,
+ fontSize = 10.sp,
+ letterSpacing = 1.5.sp
+ )
+ ),
+ shapes = Shapes(
+ RoundedCornerShape(4.dp),
+ RoundedCornerShape(8.dp),
+ RoundedCornerShape(12.dp)
+ ),
+ content = content
+ )
+}
+
+val Typography.caption1
+ get() = caption
+val Typography.caption2
+ get() = TextStyle(
+ fontWeight = FontWeight.Medium,
+ fontSize = 12.sp,
+ letterSpacing = 0.4.sp
+ )
+val Typography.caption3
+ get() = TextStyle(
+ fontWeight = FontWeight.Medium,
+ fontSize = 12.sp,
+ letterSpacing = 0.3.sp,
+ lineHeight = 14.sp
+ )
+val Typography.caption4
+ get() = TextStyle(
+ fontWeight = FontWeight.Normal,
+ fontSize = 12.sp,
+ letterSpacing = 0.35.sp
+ )
+val Typography.subtitle3
+ get() = TextStyle(
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ letterSpacing = 0.15.sp
+ )
+
+object HabiticaTheme {
+ val typography: Typography
+ @Composable
+ get() = MaterialTheme.typography
+
+ val shapes: Shapes
+ @Composable
+ get() = MaterialTheme.shapes
+}
+
+class HabiticaColors(
+ val windowBackground: Color,
+ val contentBackground: Color,
+ val contentBackgroundOffset: Color,
+ val offsetBackground: Color,
+ val textPrimary: Color,
+ val textSecondary: Color,
+ val textTertiary: Color,
+ val textQuad: Color,
+ val textDimmed: Color,
+ val tintedUiMain: Color,
+ val tintedUiSub: Color,
+ val tintedUiDetails: Color,
+ val pixelArtBackground: Color,
+ val errorBackground: Color,
+ val errorColor: Color,
+ val successBackground: Color,
+ val successColor: Color
+)
+
+class HabiticaTypography
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ComposableAvatarView.kt b/common/src/main/java/com/habitrpg/common/habitica/views/ComposableAvatarView.kt
similarity index 93%
rename from Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ComposableAvatarView.kt
rename to common/src/main/java/com/habitrpg/common/habitica/views/ComposableAvatarView.kt
index 8739884aa..d4f3863fc 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ComposableAvatarView.kt
+++ b/common/src/main/java/com/habitrpg/common/habitica/views/ComposableAvatarView.kt
@@ -1,4 +1,4 @@
-package com.habitrpg.android.habitica.ui.views
+package com.habitrpg.common.habitica.views
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/progress/HabiticaCircularProgressView.kt b/common/src/main/java/com/habitrpg/common/habitica/views/HabiticaCircularProgressView.kt
similarity index 97%
rename from Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/progress/HabiticaCircularProgressView.kt
rename to common/src/main/java/com/habitrpg/common/habitica/views/HabiticaCircularProgressView.kt
index 58157c6e6..10167ed39 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/progress/HabiticaCircularProgressView.kt
+++ b/common/src/main/java/com/habitrpg/common/habitica/views/HabiticaCircularProgressView.kt
@@ -1,4 +1,4 @@
-package com.habitrpg.android.habitica.ui.views.progress
+package com.habitrpg.common.habitica.views
import androidx.compose.animation.core.CubicBezierEasing
import androidx.compose.animation.core.animateFloat
@@ -28,7 +28,7 @@ import androidx.compose.ui.res.colorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
-import com.habitrpg.android.habitica.R
+import com.habitrpg.common.habitica.R
@Composable
fun HabiticaCircularProgressView(
diff --git a/common/src/main/res/layout/loading_item.xml b/common/src/main/res/layout/loading_item.xml
index 87140c59c..a74cc4dfd 100644
--- a/common/src/main/res/layout/loading_item.xml
+++ b/common/src/main/res/layout/loading_item.xml
@@ -2,10 +2,10 @@
-
-
\ No newline at end of file
+
diff --git a/common/src/main/res/values/colors.xml b/common/src/main/res/values/colors.xml
index 3c0fa5f09..675b352d3 100644
--- a/common/src/main/res/values/colors.xml
+++ b/common/src/main/res/values/colors.xml
@@ -162,5 +162,14 @@
@color/gray_5
@color/gray_500
+ @color/red_100
+ @color/orange_100
+ @color/yellow_100
+ @color/green_100
+ @color/blue_100
+ @color/teal_100
+ @color/brand_300
+ #4D6033B5
+
#40BDA8FF
diff --git a/fastlane/changelog.txt b/fastlane/changelog.txt
index 875e671fa..bfed07418 100644
--- a/fastlane/changelog.txt
+++ b/fastlane/changelog.txt
@@ -1,9 +1,10 @@
New in 4.3:
-It’s easier than ever to party up with our newest feature: Look for Party and Find Members!
-- Solo players can let Party leaders know they want an invite by going to Menu > Party and tapping ‘Look for Party’
-- Party leaders can see players looking for Party by tapping ‘Find Members’ on the Party screen and send invites
-- Can gift Gems by username
-- Bailey notification will show title
-- Selecting a class is more consistent
-- Chat notifications open Party
-- Other various fixes
+
+- Pets just got cuter! Tap a Pet or Mount to see them in an environment that changes each month.
+- Pets bounce when fed
+- New Subscriber benefit: Buy one Armoire, get another free!
+- New Subscriber benefit: Get a second chance at life once a day when you run out of HP!
+- Tap your avatar to share your latest looks at any time
+- See answers to common Quest mechanic questions under your active Quest
+- Updated Quest interface
+- The Quest shop now shows a check by completed Quests
\ No newline at end of file
diff --git a/version.properties b/version.properties
index f08f21455..be18fb0af 100644
--- a/version.properties
+++ b/version.properties
@@ -1,2 +1,2 @@
NAME=4.3
-CODE=6681
\ No newline at end of file
+CODE=6731
\ No newline at end of file