mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-05-20 12:49:02 +00:00
port more code to coroutines
This commit is contained in:
parent
bd4b04f86e
commit
cedc06f1e9
38 changed files with 495 additions and 472 deletions
|
|
@ -72,41 +72,38 @@ interface ApiService {
|
|||
suspend fun getContent(@Query("language") language: String?): HabitResponse<ContentResult>
|
||||
|
||||
@PUT("user/")
|
||||
fun updateUser(@Body updateDictionary: Map<String, Any>): Flowable<HabitResponse<User>>
|
||||
suspend fun updateUser(@Body updateDictionary: Map<String, Any>): HabitResponse<User>
|
||||
|
||||
@PUT("user/")
|
||||
fun registrationLanguage(@Header("Accept-Language") registrationLanguage: String): Flowable<HabitResponse<User>>
|
||||
|
||||
@GET("user/in-app-rewards")
|
||||
fun retrieveInAppRewards(): Flowable<HabitResponse<List<ShopItem>>>
|
||||
|
||||
@GET("user/inventory/buy")
|
||||
fun retrieveOldGearRewards(): Flowable<HabitResponse<List<ShopItem>>>
|
||||
suspend fun retrieveInAppRewards(): HabitResponse<List<ShopItem>>
|
||||
|
||||
@POST("user/equip/{type}/{key}")
|
||||
fun equipItem(@Path("type") type: String, @Path("key") itemKey: String): Flowable<HabitResponse<Items>>
|
||||
|
||||
@POST("user/buy/{key}")
|
||||
fun buyItem(@Path("key") itemKey: String, @Body quantity: Map<String, Int>): Flowable<HabitResponse<BuyResponse>>
|
||||
suspend fun buyItem(@Path("key") itemKey: String, @Body quantity: Map<String, Int>): HabitResponse<BuyResponse>
|
||||
|
||||
@POST("user/purchase/{type}/{key}")
|
||||
fun purchaseItem(
|
||||
suspend fun purchaseItem(
|
||||
@Path("type") type: String,
|
||||
@Path("key") itemKey: String,
|
||||
@Body quantity: Map<String, Int>
|
||||
): Flowable<HabitResponse<Void>>
|
||||
): HabitResponse<Void>
|
||||
|
||||
@POST("user/purchase-hourglass/{type}/{key}")
|
||||
fun purchaseHourglassItem(@Path("type") type: String, @Path("key") itemKey: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun purchaseHourglassItem(@Path("type") type: String, @Path("key") itemKey: String): HabitResponse<Void>
|
||||
|
||||
@POST("user/buy-mystery-set/{key}")
|
||||
fun purchaseMysterySet(@Path("key") itemKey: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun purchaseMysterySet(@Path("key") itemKey: String): HabitResponse<Void>
|
||||
|
||||
@POST("user/buy-quest/{key}")
|
||||
fun purchaseQuest(@Path("key") key: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun purchaseQuest(@Path("key") key: String): HabitResponse<Void>
|
||||
|
||||
@POST("user/buy-special-spell/{key}")
|
||||
fun purchaseSpecialSpell(@Path("key") key: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun purchaseSpecialSpell(@Path("key") key: String): HabitResponse<Void>
|
||||
|
||||
@POST("user/sell/{type}/{key}")
|
||||
fun sellItem(@Path("type") itemType: String, @Path("key") itemKey: String): Flowable<HabitResponse<User>>
|
||||
|
|
@ -124,7 +121,7 @@ interface ApiService {
|
|||
fun getTasks(@Query("type") type: String, @Query("dueDate") dueDate: String): Flowable<HabitResponse<TaskList>>
|
||||
|
||||
@POST("user/unlock")
|
||||
fun unlockPath(@Query("path") path: String): Flowable<HabitResponse<UnlockResponse>>
|
||||
suspend fun unlockPath(@Query("path") path: String): HabitResponse<UnlockResponse>
|
||||
|
||||
@GET("tasks/{id}")
|
||||
fun getTask(@Path("id") id: String): Flowable<HabitResponse<Task>>
|
||||
|
|
@ -183,14 +180,14 @@ interface ApiService {
|
|||
suspend fun revive(): HabitResponse<User>
|
||||
|
||||
@POST("user/class/cast/{skill}")
|
||||
fun useSkill(
|
||||
suspend fun useSkill(
|
||||
@Path("skill") skillName: String,
|
||||
@Query("targetType") targetType: String,
|
||||
@Query("targetId") targetId: String
|
||||
): Flowable<HabitResponse<SkillResponse>>
|
||||
): HabitResponse<SkillResponse>
|
||||
|
||||
@POST("user/class/cast/{skill}")
|
||||
fun useSkill(@Path("skill") skillName: String, @Query("targetType") targetType: String): Flowable<HabitResponse<SkillResponse>>
|
||||
suspend fun useSkill(@Path("skill") skillName: String, @Query("targetType") targetType: String): HabitResponse<SkillResponse>
|
||||
|
||||
@POST("user/change-class")
|
||||
suspend fun changeClass(): HabitResponse<User>
|
||||
|
|
@ -407,13 +404,13 @@ interface ApiService {
|
|||
fun deleteAccount(@Body body: Map<String, String>): Flowable<HabitResponse<Void>>
|
||||
|
||||
@GET("user/toggle-pinned-item/{pinType}/{path}")
|
||||
fun togglePinnedItem(@Path("pinType") pinType: String, @Path("path") path: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun togglePinnedItem(@Path("pinType") pinType: String, @Path("path") path: String): HabitResponse<Void>
|
||||
|
||||
@POST("user/reset-password")
|
||||
fun sendPasswordResetEmail(@Body data: Map<String, String>): Flowable<HabitResponse<Void>>
|
||||
|
||||
@PUT("user/auth/update-username")
|
||||
fun updateLoginName(@Body data: Map<String, String>): Flowable<HabitResponse<Void>>
|
||||
suspend fun updateLoginName(@Body data: Map<String, String>): HabitResponse<Void>
|
||||
|
||||
@POST("user/auth/verify-username")
|
||||
fun verifyUsername(@Body data: Map<String, String>): Flowable<HabitResponse<VerifyUsernameResponse>>
|
||||
|
|
|
|||
|
|
@ -58,25 +58,24 @@ interface ApiClient {
|
|||
fun setLanguageCode(languageCode: String)
|
||||
suspend fun getContent(language: String? = null): ContentResult?
|
||||
|
||||
fun updateUser(updateDictionary: Map<String, Any>): Flowable<User>
|
||||
suspend fun updateUser(updateDictionary: Map<String, Any>): User?
|
||||
|
||||
fun registrationLanguage(registrationLanguage: String): Flowable<User>
|
||||
|
||||
fun retrieveInAppRewards(): Flowable<List<ShopItem>>
|
||||
fun retrieveOldGear(): Flowable<List<ShopItem>>
|
||||
suspend fun retrieveInAppRewards(): List<ShopItem>?
|
||||
|
||||
fun equipItem(type: String, itemKey: String): Flowable<Items>
|
||||
|
||||
fun buyItem(itemKey: String, purchaseQuantity: Int): Flowable<BuyResponse>
|
||||
suspend fun buyItem(itemKey: String, purchaseQuantity: Int): BuyResponse?
|
||||
|
||||
fun purchaseItem(type: String, itemKey: String, purchaseQuantity: Int): Flowable<Void>
|
||||
suspend fun purchaseItem(type: String, itemKey: String, purchaseQuantity: Int): Void?
|
||||
|
||||
fun purchaseHourglassItem(type: String, itemKey: String): Flowable<Void>
|
||||
suspend fun purchaseHourglassItem(type: String, itemKey: String): Void?
|
||||
|
||||
fun purchaseMysterySet(itemKey: String): Flowable<Void>
|
||||
suspend fun purchaseMysterySet(itemKey: String): Void?
|
||||
|
||||
fun purchaseQuest(key: String): Flowable<Void>
|
||||
fun purchaseSpecialSpell(key: String): Flowable<Void>
|
||||
suspend fun purchaseQuest(key: String): Void?
|
||||
suspend fun purchaseSpecialSpell(key: String): Void?
|
||||
fun validateSubscription(request: PurchaseValidationRequest): Flowable<Any>
|
||||
fun validateNoRenewSubscription(request: PurchaseValidationRequest): Flowable<Any>
|
||||
suspend fun cancelSubscription(): Void?
|
||||
|
|
@ -89,7 +88,7 @@ interface ApiClient {
|
|||
fun getTasks(type: String): Flowable<TaskList>
|
||||
fun getTasks(type: String, dueDate: String): Flowable<TaskList>
|
||||
|
||||
fun unlockPath(path: String): Flowable<UnlockResponse>
|
||||
suspend fun unlockPath(path: String): UnlockResponse?
|
||||
|
||||
fun getTask(id: String): Flowable<Task>
|
||||
|
||||
|
|
@ -126,9 +125,9 @@ interface ApiClient {
|
|||
suspend fun sleep(): Boolean?
|
||||
suspend fun revive(): User?
|
||||
|
||||
fun useSkill(skillName: String, targetType: String, targetId: String): Flowable<SkillResponse>
|
||||
suspend fun useSkill(skillName: String, targetType: String, targetId: String): SkillResponse?
|
||||
|
||||
fun useSkill(skillName: String, targetType: String): Flowable<SkillResponse>
|
||||
suspend fun useSkill(skillName: String, targetType: String): SkillResponse?
|
||||
|
||||
suspend fun changeClass(className: String?): User?
|
||||
|
||||
|
|
@ -251,12 +250,12 @@ interface ApiClient {
|
|||
fun resetAccount(): Flowable<Void>
|
||||
fun deleteAccount(password: String): Flowable<Void>
|
||||
|
||||
fun togglePinnedItem(pinType: String, path: String): Flowable<Void>
|
||||
suspend fun togglePinnedItem(pinType: String, path: String): Void?
|
||||
|
||||
fun sendPasswordResetEmail(email: String): Flowable<Void>
|
||||
|
||||
fun updateLoginName(newLoginName: String, password: String): Flowable<Void>
|
||||
fun updateUsername(newLoginName: String): Flowable<Void>
|
||||
suspend fun updateLoginName(newLoginName: String, password: String): Void?
|
||||
suspend fun updateUsername(newLoginName: String): Void?
|
||||
|
||||
fun updateEmail(newEmail: String, password: String): Flowable<Void>
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ interface InventoryRepository : BaseRepository {
|
|||
fun getQuestContent(keys: List<String>): Flow<List<QuestContent>>
|
||||
|
||||
fun getEquipment(searchedKeys: List<String>): Flowable<out List<Equipment>>
|
||||
fun retrieveInAppRewards(): Flowable<List<ShopItem>>
|
||||
suspend fun retrieveInAppRewards(): List<ShopItem>?
|
||||
|
||||
fun getOwnedEquipment(type: String): Flowable<out List<Equipment>>
|
||||
fun getEquipmentType(type: String, set: String): Flowable<out List<Equipment>>
|
||||
|
|
@ -71,21 +71,21 @@ interface InventoryRepository : BaseRepository {
|
|||
|
||||
fun inviteToQuest(quest: QuestContent): Flowable<Quest>
|
||||
|
||||
fun buyItem(user: User?, id: String, value: Double, purchaseQuantity: Int): Flowable<BuyResponse>
|
||||
suspend fun buyItem(user: User?, id: String, value: Double, purchaseQuantity: Int): BuyResponse?
|
||||
|
||||
fun retrieveShopInventory(identifier: String): Flowable<Shop>
|
||||
fun retrieveMarketGear(): Flowable<Shop>
|
||||
|
||||
fun purchaseMysterySet(categoryIdentifier: String): Flowable<Void>
|
||||
suspend fun purchaseMysterySet(categoryIdentifier: String): Void?
|
||||
|
||||
fun purchaseHourglassItem(purchaseType: String, key: String): Flowable<Void>
|
||||
suspend fun purchaseHourglassItem(purchaseType: String, key: String): Void?
|
||||
|
||||
fun purchaseQuest(key: String): Flowable<Void>
|
||||
fun purchaseSpecialSpell(key: String): Flowable<Void>
|
||||
suspend fun purchaseQuest(key: String): Void?
|
||||
suspend fun purchaseSpecialSpell(key: String): Void?
|
||||
|
||||
fun purchaseItem(purchaseType: String, key: String, purchaseQuantity: Int): Flowable<Void>
|
||||
suspend fun purchaseItem(purchaseType: String, key: String, purchaseQuantity: Int): Void?
|
||||
|
||||
fun togglePinnedItem(item: ShopItem): Flowable<List<ShopItem>>
|
||||
suspend fun togglePinnedItem(item: ShopItem): List<ShopItem>?
|
||||
fun getItems(itemClass: Class<out Item>, keys: Array<String>): Flow<List<Item>>
|
||||
fun getItemsFlowable(itemClass: Class<out Item>): Flowable<out List<Item>>
|
||||
fun getItems(itemClass: Class<out Item>): Flow<List<Item>>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.habitrpg.android.habitica.data
|
||||
|
||||
import com.habitrpg.android.habitica.models.user.UserQuestStatus
|
||||
import com.habitrpg.android.habitica.models.Achievement
|
||||
import com.habitrpg.android.habitica.models.QuestAchievement
|
||||
import com.habitrpg.android.habitica.models.Skill
|
||||
|
|
@ -8,14 +7,14 @@ import com.habitrpg.android.habitica.models.TeamPlan
|
|||
import com.habitrpg.android.habitica.models.inventory.Customization
|
||||
import com.habitrpg.android.habitica.models.responses.SkillResponse
|
||||
import com.habitrpg.android.habitica.models.responses.UnlockResponse
|
||||
import com.habitrpg.shared.habitica.models.responses.VerifyUsernameResponse
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import com.habitrpg.shared.habitica.models.tasks.Attribute
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.user.Stats
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.models.user.UserQuestStatus
|
||||
import com.habitrpg.shared.habitica.models.responses.VerifyUsernameResponse
|
||||
import com.habitrpg.shared.habitica.models.tasks.Attribute
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface UserRepository : BaseRepository {
|
||||
|
|
@ -23,14 +22,14 @@ interface UserRepository : BaseRepository {
|
|||
fun getUserFlowable(): Flowable<User>
|
||||
fun getUser(userID: String): Flow<User?>
|
||||
|
||||
fun updateUser(updateData: Map<String, Any>): Flowable<User>
|
||||
fun updateUser(key: String, value: Any): Flowable<User>
|
||||
suspend fun updateUser(updateData: Map<String, Any>): User?
|
||||
suspend fun updateUser(key: String, value: Any): User?
|
||||
|
||||
suspend fun retrieveUser(withTasks: Boolean = false, forced: Boolean = false, overrideExisting: Boolean = false): User?
|
||||
|
||||
suspend fun revive(): User?
|
||||
|
||||
fun resetTutorial(): Maybe<User>
|
||||
suspend fun resetTutorial(): User?
|
||||
|
||||
suspend fun sleep(user: User): User?
|
||||
|
||||
|
|
@ -38,14 +37,14 @@ interface UserRepository : BaseRepository {
|
|||
|
||||
fun getSpecialItems(user: User): Flowable<out List<Skill>>
|
||||
|
||||
fun useSkill(key: String, target: String?, taskId: String): Flowable<SkillResponse>
|
||||
fun useSkill(key: String, target: String?): Flowable<SkillResponse>
|
||||
suspend fun useSkill(key: String, target: String?, taskId: String): SkillResponse?
|
||||
suspend fun useSkill(key: String, target: String?): SkillResponse?
|
||||
|
||||
suspend fun disableClasses(): User?
|
||||
suspend fun changeClass(selectedClass: String? = null): User?
|
||||
|
||||
fun unlockPath(path: String, price: Int): Flowable<UnlockResponse>
|
||||
fun unlockPath(customization: Customization): Flowable<UnlockResponse>
|
||||
suspend fun unlockPath(path: String, price: Int): UnlockResponse?
|
||||
suspend fun unlockPath(customization: Customization): UnlockResponse?
|
||||
|
||||
suspend fun runCron(tasks: MutableList<Task>)
|
||||
suspend fun runCron()
|
||||
|
|
@ -56,14 +55,14 @@ interface UserRepository : BaseRepository {
|
|||
|
||||
fun changeCustomDayStart(dayStartTime: Int): Flowable<User>
|
||||
|
||||
fun updateLanguage(languageCode: String): Flowable<User>
|
||||
suspend fun updateLanguage(languageCode: String): User?
|
||||
|
||||
suspend fun resetAccount(): User?
|
||||
fun deleteAccount(password: String): Flowable<Void>
|
||||
|
||||
fun sendPasswordResetEmail(email: String): Flowable<Void>
|
||||
|
||||
fun updateLoginName(newLoginName: String, password: String? = null): Maybe<User>
|
||||
suspend fun updateLoginName(newLoginName: String, password: String? = null): User?
|
||||
fun updateEmail(newEmail: String, password: String): Flowable<Void>
|
||||
fun updatePassword(oldPassword: String, newPassword: String, newPasswordConfirmation: String): Flowable<Void>
|
||||
fun verifyUsername(username: String): Flowable<VerifyUsernameResponse>
|
||||
|
|
@ -71,7 +70,7 @@ interface UserRepository : BaseRepository {
|
|||
fun allocatePoint(stat: Attribute): Flowable<Stats>
|
||||
fun bulkAllocatePoints(strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable<Stats>
|
||||
|
||||
fun useCustomization(type: String, category: String?, identifier: String): Flowable<User>
|
||||
suspend fun useCustomization(type: String, category: String?, identifier: String): User?
|
||||
fun retrieveAchievements(): Flowable<List<Achievement>>
|
||||
fun getAchievements(): Flow<List<Achievement>>
|
||||
fun getQuestAchievements(): Flow<List<QuestAchievement>>
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ class ApiClientImpl(
|
|||
return habitResponse.data
|
||||
}
|
||||
|
||||
suspend fun <T> handleSuspendCall(apiCall: suspend () -> HabitResponse<T>): T? {
|
||||
private suspend fun <T> process(apiCall: suspend () -> HabitResponse<T>): T? {
|
||||
try {
|
||||
return processResponse(apiCall())
|
||||
} catch (throwable: Throwable) {
|
||||
|
|
@ -280,14 +280,14 @@ class ApiClientImpl(
|
|||
}
|
||||
|
||||
override suspend fun retrieveUser(withTasks: Boolean): User? {
|
||||
val user = handleSuspendCall { apiService.getUser() }
|
||||
val user = process { apiService.getUser() }
|
||||
val tasks = getTasks()
|
||||
user?.tasks = tasks
|
||||
return user
|
||||
}
|
||||
|
||||
override suspend fun retrieveInboxMessages(uuid: String, page: Int): List<ChatMessage>? {
|
||||
return handleSuspendCall { apiService.getInboxMessages(uuid, page) }
|
||||
return process { apiService.getInboxMessages(uuid, page) }
|
||||
}
|
||||
|
||||
override fun retrieveInboxConversations(): Flowable<List<InboxConversation>> {
|
||||
|
|
@ -346,34 +346,30 @@ class ApiClientImpl(
|
|||
this.languageCode = languageCode
|
||||
}
|
||||
|
||||
override suspend fun getStatus(): Status? = handleSuspendCall { apiService.getStatus() }
|
||||
override suspend fun getStatus(): Status? = process { apiService.getStatus() }
|
||||
|
||||
override suspend fun getContent(language: String?): ContentResult? {
|
||||
return handleSuspendCall { apiService.getContent(language) }
|
||||
return process { apiService.getContent(language) }
|
||||
}
|
||||
|
||||
override fun updateUser(updateDictionary: Map<String, Any>): Flowable<User> {
|
||||
return apiService.updateUser(updateDictionary).compose(configureApiCallObserver())
|
||||
override suspend fun updateUser(updateDictionary: Map<String, Any>): User? {
|
||||
return process { apiService.updateUser(updateDictionary) }
|
||||
}
|
||||
|
||||
override fun registrationLanguage(registrationLanguage: String): Flowable<User> {
|
||||
return apiService.registrationLanguage(registrationLanguage).compose(configureApiCallObserver())
|
||||
}
|
||||
|
||||
override fun retrieveInAppRewards(): Flowable<List<ShopItem>> {
|
||||
return apiService.retrieveInAppRewards().compose(configureApiCallObserver())
|
||||
}
|
||||
|
||||
override fun retrieveOldGear(): Flowable<List<ShopItem>> {
|
||||
return apiService.retrieveOldGearRewards().compose(configureApiCallObserver())
|
||||
override suspend fun retrieveInAppRewards(): List<ShopItem>? {
|
||||
return process { apiService.retrieveInAppRewards() }
|
||||
}
|
||||
|
||||
override fun equipItem(type: String, itemKey: String): Flowable<Items> {
|
||||
return apiService.equipItem(type, itemKey).compose(configureApiCallObserver())
|
||||
}
|
||||
|
||||
override fun buyItem(itemKey: String, purchaseQuantity: Int): Flowable<BuyResponse> {
|
||||
return apiService.buyItem(itemKey, mapOf(Pair("quantity", purchaseQuantity))).compose(configureApiCallObserver())
|
||||
override suspend fun buyItem(itemKey: String, purchaseQuantity: Int): BuyResponse? {
|
||||
return process { apiService.buyItem(itemKey, mapOf(Pair("quantity", purchaseQuantity))) }
|
||||
}
|
||||
|
||||
override fun unlinkAllTasks(challengeID: String?, keepOption: String): Flowable<Void> {
|
||||
|
|
@ -384,8 +380,8 @@ class ApiClientImpl(
|
|||
return apiService.blockMember(userID).compose(configureApiCallObserver())
|
||||
}
|
||||
|
||||
override fun purchaseItem(type: String, itemKey: String, purchaseQuantity: Int): Flowable<Void> {
|
||||
return apiService.purchaseItem(type, itemKey, mapOf(Pair("quantity", purchaseQuantity))).compose(configureApiCallObserver())
|
||||
override suspend fun purchaseItem(type: String, itemKey: String, purchaseQuantity: Int): Void? {
|
||||
return process { apiService.purchaseItem(type, itemKey, mapOf(Pair("quantity", purchaseQuantity))) }
|
||||
}
|
||||
|
||||
override fun validateSubscription(request: PurchaseValidationRequest): Flowable<Any> {
|
||||
|
|
@ -400,20 +396,20 @@ class ApiClientImpl(
|
|||
return processResponse(apiService.cancelSubscription())
|
||||
}
|
||||
|
||||
override fun purchaseHourglassItem(type: String, itemKey: String): Flowable<Void> {
|
||||
return apiService.purchaseHourglassItem(type, itemKey).compose(configureApiCallObserver())
|
||||
override suspend fun purchaseHourglassItem(type: String, itemKey: String): Void? {
|
||||
return process { apiService.purchaseHourglassItem(type, itemKey) }
|
||||
}
|
||||
|
||||
override fun purchaseMysterySet(itemKey: String): Flowable<Void> {
|
||||
return apiService.purchaseMysterySet(itemKey).compose(configureApiCallObserver())
|
||||
override suspend fun purchaseMysterySet(itemKey: String): Void? {
|
||||
return process { apiService.purchaseMysterySet(itemKey) }
|
||||
}
|
||||
|
||||
override fun purchaseQuest(key: String): Flowable<Void> {
|
||||
return apiService.purchaseQuest(key).compose(configureApiCallObserver())
|
||||
override suspend fun purchaseQuest(key: String): Void? {
|
||||
return process { apiService.purchaseQuest(key) }
|
||||
}
|
||||
|
||||
override fun purchaseSpecialSpell(key: String): Flowable<Void> {
|
||||
return apiService.purchaseSpecialSpell(key).compose(configureApiCallObserver())
|
||||
override suspend fun purchaseSpecialSpell(key: String): Void? {
|
||||
return process { apiService.purchaseSpecialSpell(key) }
|
||||
}
|
||||
|
||||
override fun sellItem(itemType: String, itemKey: String): Flowable<User> {
|
||||
|
|
@ -433,7 +429,7 @@ class ApiClientImpl(
|
|||
return apiService.hatchPet(eggKey, hatchingPotionKey).compose(configureApiCallObserver())
|
||||
}
|
||||
|
||||
override suspend fun getTasks(): TaskList? = handleSuspendCall { apiService.getTasks() }
|
||||
override suspend fun getTasks(): TaskList? = process { apiService.getTasks() }
|
||||
|
||||
override fun getTasks(type: String): Flowable<TaskList> {
|
||||
return apiService.getTasks(type).compose(configureApiCallObserver())
|
||||
|
|
@ -443,8 +439,8 @@ class ApiClientImpl(
|
|||
return apiService.getTasks(type, dueDate).compose(configureApiCallObserver())
|
||||
}
|
||||
|
||||
override fun unlockPath(path: String): Flowable<UnlockResponse> {
|
||||
return apiService.unlockPath(path).compose(configureApiCallObserver())
|
||||
override suspend fun unlockPath(path: String): UnlockResponse? {
|
||||
return process { apiService.unlockPath(path) }
|
||||
}
|
||||
|
||||
override fun getTask(id: String): Flowable<Task> {
|
||||
|
|
@ -452,7 +448,7 @@ class ApiClientImpl(
|
|||
}
|
||||
|
||||
override suspend fun postTaskDirection(id: String, direction: String): TaskDirectionData? {
|
||||
return handleSuspendCall { apiService.postTaskDirection(id, direction) }
|
||||
return process { apiService.postTaskDirection(id, direction) }
|
||||
}
|
||||
|
||||
override fun bulkScoreTasks(data: List<Map<String, String>>): Flowable<BulkTaskScoringData> {
|
||||
|
|
@ -464,7 +460,7 @@ class ApiClientImpl(
|
|||
}
|
||||
|
||||
override suspend fun scoreChecklistItem(taskId: String, itemId: String): Task? {
|
||||
return handleSuspendCall { apiService.scoreChecklistItem(taskId, itemId) }
|
||||
return process { apiService.scoreChecklistItem(taskId, itemId) }
|
||||
}
|
||||
|
||||
override fun createTask(item: Task): Flowable<Task> {
|
||||
|
|
@ -495,20 +491,20 @@ class ApiClientImpl(
|
|||
return apiService.deleteTag(id).compose(configureApiCallObserver())
|
||||
}
|
||||
|
||||
override suspend fun sleep(): Boolean? = handleSuspendCall { apiService.sleep() }
|
||||
override suspend fun sleep(): Boolean? = process { apiService.sleep() }
|
||||
|
||||
override suspend fun revive(): User? = handleSuspendCall { apiService.revive() }
|
||||
override suspend fun revive(): User? = process { apiService.revive() }
|
||||
|
||||
override fun useSkill(skillName: String, targetType: String, targetId: String): Flowable<SkillResponse> {
|
||||
return apiService.useSkill(skillName, targetType, targetId).compose(configureApiCallObserver())
|
||||
suspend override fun useSkill(skillName: String, targetType: String, targetId: String): SkillResponse? {
|
||||
return process { apiService.useSkill(skillName, targetType, targetId) }
|
||||
}
|
||||
|
||||
override fun useSkill(skillName: String, targetType: String): Flowable<SkillResponse> {
|
||||
return apiService.useSkill(skillName, targetType).compose(configureApiCallObserver())
|
||||
suspend override fun useSkill(skillName: String, targetType: String): SkillResponse? {
|
||||
return process { apiService.useSkill(skillName, targetType) }
|
||||
}
|
||||
|
||||
override suspend fun changeClass(className: String?): User? {
|
||||
return handleSuspendCall {
|
||||
return process {
|
||||
if (className != null) {
|
||||
apiService.changeClass(className)
|
||||
} else {
|
||||
|
|
@ -517,7 +513,7 @@ class ApiClientImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun disableClasses(): User? = handleSuspendCall { apiService.disableClasses() }
|
||||
override suspend fun disableClasses(): User? = process { apiService.disableClasses() }
|
||||
|
||||
override fun markPrivateMessagesRead(): Flowable<Void> {
|
||||
// This is necessary, because the API call returns weird data.
|
||||
|
|
@ -650,7 +646,7 @@ class ApiClientImpl(
|
|||
}
|
||||
|
||||
override suspend fun postPrivateMessage(messageDetails: Map<String, String>): PostChatMessageResult? {
|
||||
return handleSuspendCall { apiService.postPrivateMessage(messageDetails) }
|
||||
return process { apiService.postPrivateMessage(messageDetails) }
|
||||
}
|
||||
|
||||
override fun retrieveShopIventory(identifier: String): Flowable<Shop> {
|
||||
|
|
@ -733,7 +729,7 @@ class ApiClientImpl(
|
|||
return apiService.runCron().compose(configureApiCallObserver())
|
||||
}
|
||||
|
||||
override suspend fun reroll(): User? = handleSuspendCall { apiService.reroll() }
|
||||
override suspend fun reroll(): User? = process { apiService.reroll() }
|
||||
|
||||
override fun resetAccount(): Flowable<Void> {
|
||||
return apiService.resetAccount().compose(configureApiCallObserver())
|
||||
|
|
@ -745,8 +741,8 @@ class ApiClientImpl(
|
|||
return apiService.deleteAccount(updateObject).compose(configureApiCallObserver())
|
||||
}
|
||||
|
||||
override fun togglePinnedItem(pinType: String, path: String): Flowable<Void> {
|
||||
return apiService.togglePinnedItem(pinType, path).compose(configureApiCallObserver())
|
||||
override suspend fun togglePinnedItem(pinType: String, path: String): Void? {
|
||||
return process { apiService.togglePinnedItem(pinType, path) }
|
||||
}
|
||||
|
||||
override fun sendPasswordResetEmail(email: String): Flowable<Void> {
|
||||
|
|
@ -755,17 +751,17 @@ class ApiClientImpl(
|
|||
return apiService.sendPasswordResetEmail(data).compose(configureApiCallObserver())
|
||||
}
|
||||
|
||||
override fun updateLoginName(newLoginName: String, password: String): Flowable<Void> {
|
||||
override suspend fun updateLoginName(newLoginName: String, password: String): Void? {
|
||||
val updateObject = HashMap<String, String>()
|
||||
updateObject["username"] = newLoginName
|
||||
updateObject["password"] = password
|
||||
return apiService.updateLoginName(updateObject).compose(configureApiCallObserver())
|
||||
return process { apiService.updateLoginName(updateObject) }
|
||||
}
|
||||
|
||||
override fun updateUsername(newLoginName: String): Flowable<Void> {
|
||||
override suspend fun updateUsername(newLoginName: String): Void? {
|
||||
val updateObject = HashMap<String, String>()
|
||||
updateObject["username"] = newLoginName
|
||||
return apiService.updateLoginName(updateObject).compose(configureApiCallObserver())
|
||||
return process { apiService.updateLoginName(updateObject) }
|
||||
}
|
||||
|
||||
override fun verifyUsername(username: String): Flowable<VerifyUsernameResponse> {
|
||||
|
|
@ -831,7 +827,7 @@ class ApiClientImpl(
|
|||
return apiService.retrieveMarketGear(languageCode).compose(configureApiCallObserver())
|
||||
}
|
||||
|
||||
override suspend fun getWorldState(): WorldState? = handleSuspendCall { apiService.worldState() }
|
||||
override suspend fun getWorldState(): WorldState? = process { apiService.worldState() }
|
||||
|
||||
companion object {
|
||||
fun createGsonFactory(): GsonConverterFactory {
|
||||
|
|
|
|||
|
|
@ -47,8 +47,12 @@ class InventoryRepositoryImpl(
|
|||
return localRepository.getInAppRewards()
|
||||
}
|
||||
|
||||
override fun retrieveInAppRewards(): Flowable<List<ShopItem>> {
|
||||
return apiClient.retrieveInAppRewards().doOnNext { localRepository.saveInAppRewards(it) }
|
||||
override suspend fun retrieveInAppRewards(): List<ShopItem>? {
|
||||
val rewards = apiClient.retrieveInAppRewards()
|
||||
if (rewards != null) {
|
||||
localRepository.saveInAppRewards(rewards)
|
||||
}
|
||||
return rewards
|
||||
}
|
||||
|
||||
override fun getOwnedEquipment(type: String): Flowable<out List<Equipment>> {
|
||||
|
|
@ -238,35 +242,32 @@ class InventoryRepositoryImpl(
|
|||
.doOnNext { localRepository.changeOwnedCount("quests", quest.key, userID, -1) }
|
||||
}
|
||||
|
||||
override fun buyItem(user: User?, id: String, value: Double, purchaseQuantity: Int): Flowable<BuyResponse> {
|
||||
return apiClient.buyItem(id, purchaseQuantity)
|
||||
.doOnNext { buyResponse ->
|
||||
if (user == null) {
|
||||
return@doOnNext
|
||||
}
|
||||
val copiedUser = localRepository.getUnmanagedCopy(user)
|
||||
if (buyResponse.items != null) {
|
||||
copiedUser.items = buyResponse.items
|
||||
}
|
||||
if (buyResponse.hp != null) {
|
||||
copiedUser.stats?.hp = buyResponse.hp
|
||||
}
|
||||
if (buyResponse.exp != null) {
|
||||
copiedUser.stats?.exp = buyResponse.exp
|
||||
}
|
||||
if (buyResponse.mp != null) {
|
||||
copiedUser.stats?.mp = buyResponse.mp
|
||||
}
|
||||
if (buyResponse.gp != null) {
|
||||
copiedUser.stats?.gp = buyResponse.gp
|
||||
} else {
|
||||
copiedUser.stats?.gp = copiedUser.stats?.gp ?: 0 - (value * purchaseQuantity)
|
||||
}
|
||||
if (buyResponse.lvl != null) {
|
||||
copiedUser.stats?.lvl = buyResponse.lvl
|
||||
}
|
||||
localRepository.save(copiedUser)
|
||||
}
|
||||
override suspend fun buyItem(user: User?, id: String, value: Double, purchaseQuantity: Int): BuyResponse? {
|
||||
val buyResponse = apiClient.buyItem(id, purchaseQuantity) ?: return null
|
||||
val foundUser = user ?: localRepository.getLiveUser(userID) ?: return buyResponse
|
||||
val copiedUser = localRepository.getUnmanagedCopy(foundUser)
|
||||
if (buyResponse.items != null) {
|
||||
copiedUser.items = buyResponse.items
|
||||
}
|
||||
if (buyResponse.hp != null) {
|
||||
copiedUser.stats?.hp = buyResponse.hp
|
||||
}
|
||||
if (buyResponse.exp != null) {
|
||||
copiedUser.stats?.exp = buyResponse.exp
|
||||
}
|
||||
if (buyResponse.mp != null) {
|
||||
copiedUser.stats?.mp = buyResponse.mp
|
||||
}
|
||||
if (buyResponse.gp != null) {
|
||||
copiedUser.stats?.gp = buyResponse.gp
|
||||
} else {
|
||||
copiedUser.stats?.gp = (copiedUser.stats?.gp ?: 0.0) - (value * purchaseQuantity)
|
||||
}
|
||||
if (buyResponse.lvl != null) {
|
||||
copiedUser.stats?.lvl = buyResponse.lvl
|
||||
}
|
||||
localRepository.save(copiedUser)
|
||||
return buyResponse
|
||||
}
|
||||
|
||||
override fun getAvailableLimitedItems(): Flowable<List<Item>> {
|
||||
|
|
@ -281,30 +282,30 @@ class InventoryRepositoryImpl(
|
|||
return apiClient.retrieveMarketGear()
|
||||
}
|
||||
|
||||
override fun purchaseMysterySet(categoryIdentifier: String): Flowable<Void> {
|
||||
override suspend fun purchaseMysterySet(categoryIdentifier: String): Void? {
|
||||
return apiClient.purchaseMysterySet(categoryIdentifier)
|
||||
}
|
||||
|
||||
override fun purchaseHourglassItem(purchaseType: String, key: String): Flowable<Void> {
|
||||
override suspend fun purchaseHourglassItem(purchaseType: String, key: String): Void? {
|
||||
return apiClient.purchaseHourglassItem(purchaseType, key)
|
||||
}
|
||||
|
||||
override fun purchaseQuest(key: String): Flowable<Void> {
|
||||
override suspend fun purchaseQuest(key: String): Void? {
|
||||
return apiClient.purchaseQuest(key)
|
||||
}
|
||||
|
||||
override fun purchaseSpecialSpell(key: String): Flowable<Void> {
|
||||
override suspend fun purchaseSpecialSpell(key: String): Void? {
|
||||
return apiClient.purchaseSpecialSpell(key)
|
||||
}
|
||||
|
||||
override fun purchaseItem(purchaseType: String, key: String, purchaseQuantity: Int): Flowable<Void> {
|
||||
override suspend fun purchaseItem(purchaseType: String, key: String, purchaseQuantity: Int): Void? {
|
||||
return apiClient.purchaseItem(purchaseType, key, purchaseQuantity)
|
||||
}
|
||||
|
||||
override fun togglePinnedItem(item: ShopItem): Flowable<List<ShopItem>> {
|
||||
return if (!item.isValid) {
|
||||
Flowable.empty()
|
||||
} else apiClient.togglePinnedItem(item.pinType ?: "", item.path ?: "")
|
||||
.flatMap { retrieveInAppRewards() }
|
||||
override suspend fun togglePinnedItem(item: ShopItem): List<ShopItem>? {
|
||||
if (item.isValid) {
|
||||
apiClient.togglePinnedItem(item.pinType ?: "", item.path ?: "")
|
||||
}
|
||||
return retrieveInAppRewards()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import io.reactivex.rxjava3.core.Maybe
|
|||
import io.reactivex.rxjava3.functions.BiFunction
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.Date
|
||||
import java.util.GregorianCalendar
|
||||
|
|
@ -51,24 +52,23 @@ class UserRepositoryImpl(
|
|||
|
||||
override fun getUser(userID: String): Flow<User?> = localRepository.getUser(userID)
|
||||
|
||||
private fun updateUser(userID: String, updateData: Map<String, Any>): Flowable<User> {
|
||||
return Flowable.zip(
|
||||
apiClient.updateUser(updateData),
|
||||
localRepository.getUserFlowable(userID).firstElement().toFlowable()
|
||||
) { newUser, user -> mergeUser(user, newUser) }
|
||||
private suspend fun updateUser(userID: String, updateData: Map<String, Any>): User? {
|
||||
val networkUser = apiClient.updateUser(updateData) ?: return null
|
||||
val oldUser = localRepository.getUser(userID).firstOrNull()
|
||||
return mergeUser(oldUser, networkUser)
|
||||
}
|
||||
|
||||
private fun updateUser(userID: String, key: String, value: Any): Flowable<User> {
|
||||
private suspend fun updateUser(userID: String, key: String, value: Any): User? {
|
||||
val updateData = HashMap<String, Any>()
|
||||
updateData[key] = value
|
||||
return updateUser(userID, updateData)
|
||||
}
|
||||
|
||||
override fun updateUser(updateData: Map<String, Any>): Flowable<User> {
|
||||
override suspend fun updateUser(updateData: Map<String, Any>): User? {
|
||||
return updateUser(userID, updateData)
|
||||
}
|
||||
|
||||
override fun updateUser(key: String, value: Any): Flowable<User> {
|
||||
override suspend fun updateUser(key: String, value: Any): User? {
|
||||
return updateUser(userID, key, value)
|
||||
}
|
||||
|
||||
|
|
@ -90,12 +90,11 @@ class UserRepositoryImpl(
|
|||
val calendar = GregorianCalendar()
|
||||
val timeZone = calendar.timeZone
|
||||
val offset = -TimeUnit.MINUTES.convert(timeZone.getOffset(calendar.timeInMillis).toLong(), TimeUnit.MILLISECONDS)
|
||||
/*if (offset.toInt() != user.preferences?.timezoneOffset ?: 0) {
|
||||
return@flatMap updateUser(user.id ?: "", "preferences.timezoneOffset", offset.toString())
|
||||
return if (offset.toInt() != (user.preferences?.timezoneOffset ?: 0)) {
|
||||
updateUser(user.id ?: "", "preferences.timezoneOffset", offset.toString())
|
||||
} else {
|
||||
return@flatMap Flowable.just(user)
|
||||
}*/
|
||||
return user
|
||||
user
|
||||
}
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
|
|
@ -106,17 +105,13 @@ class UserRepositoryImpl(
|
|||
return retrieveUser(false, true)
|
||||
}
|
||||
|
||||
override fun resetTutorial(): Maybe<User> {
|
||||
return localRepository.getTutorialSteps()
|
||||
.firstElement()
|
||||
.map<Map<String, Any>> { tutorialSteps ->
|
||||
val updateData = HashMap<String, Any>()
|
||||
for (step in tutorialSteps) {
|
||||
updateData[step.flagPath] = false
|
||||
}
|
||||
updateData
|
||||
}
|
||||
.flatMap { updateData -> updateUser(updateData).firstElement() }
|
||||
override suspend fun resetTutorial(): User? {
|
||||
val tutorialSteps = localRepository.getTutorialSteps().firstOrNull() ?: return null
|
||||
val updateData = HashMap<String, Any>()
|
||||
for (step in tutorialSteps) {
|
||||
updateData[step.flagPath] = false
|
||||
}
|
||||
return updateUser(updateData)
|
||||
}
|
||||
|
||||
override suspend fun sleep(user: User): User {
|
||||
|
|
@ -134,26 +129,26 @@ class UserRepositoryImpl(
|
|||
override fun getSpecialItems(user: User): Flowable<out List<Skill>> =
|
||||
localRepository.getSpecialItems(user)
|
||||
|
||||
override fun useSkill(key: String, target: String?, taskId: String): Flowable<SkillResponse> {
|
||||
return zipWithLiveUser(apiClient.useSkill(key, target ?: "", taskId)) { response, user ->
|
||||
response.hpDiff = (response.user?.stats?.hp ?: 0.0) - (user.stats?.hp ?: 0.0)
|
||||
response.expDiff =(response.user?.stats?.exp ?: 0.0) - (user.stats?.exp ?: 0.0)
|
||||
response.goldDiff = (response.user?.stats?.gp ?: 0.0) - (user.stats?.gp ?: 0.0)
|
||||
response.damage = (response.user?.party?.quest?.progress?.up ?: 0.0f) - (user.party?.quest?.progress?.up ?: 0.0f)
|
||||
response.user?.let { mergeUser(user, it) }
|
||||
response
|
||||
}
|
||||
override suspend fun useSkill(key: String, target: String?, taskId: String): SkillResponse? {
|
||||
val response = apiClient.useSkill(key, target ?: "", taskId) ?: return null
|
||||
val user = getLiveUser() ?: return response
|
||||
response.hpDiff = (response.user?.stats?.hp ?: 0.0) - (user.stats?.hp ?: 0.0)
|
||||
response.expDiff =(response.user?.stats?.exp ?: 0.0) - (user.stats?.exp ?: 0.0)
|
||||
response.goldDiff = (response.user?.stats?.gp ?: 0.0) - (user.stats?.gp ?: 0.0)
|
||||
response.damage = (response.user?.party?.quest?.progress?.up ?: 0.0f) - (user.party?.quest?.progress?.up ?: 0.0f)
|
||||
response.user?.let { mergeUser(user, it) }
|
||||
return response
|
||||
}
|
||||
|
||||
override fun useSkill(key: String, target: String?): Flowable<SkillResponse> {
|
||||
return zipWithLiveUser(apiClient.useSkill(key, target ?: "")) { response, user ->
|
||||
response.hpDiff = (response.user?.stats?.hp ?: 0.0) - (user.stats?.hp ?: 0.0)
|
||||
response.expDiff =(response.user?.stats?.exp ?: 0.0) - (user.stats?.exp ?: 0.0)
|
||||
response.goldDiff = (response.user?.stats?.gp ?: 0.0) - (user.stats?.gp ?: 0.0)
|
||||
response.damage = (response.user?.party?.quest?.progress?.up ?: 0.0f) - (user.party?.quest?.progress?.up ?: 0.0f)
|
||||
response.user?.let { mergeUser(user, it) }
|
||||
response
|
||||
}
|
||||
override suspend fun useSkill(key: String, target: String?): SkillResponse? {
|
||||
val response = apiClient.useSkill(key, target ?: "") ?: return null
|
||||
val user = getLiveUser() ?: return response
|
||||
response.hpDiff = (response.user?.stats?.hp ?: 0.0) - (user.stats?.hp ?: 0.0)
|
||||
response.expDiff =(response.user?.stats?.exp ?: 0.0) - (user.stats?.exp ?: 0.0)
|
||||
response.goldDiff = (response.user?.stats?.gp ?: 0.0) - (user.stats?.gp ?: 0.0)
|
||||
response.damage = (response.user?.party?.quest?.progress?.up ?: 0.0f) - (user.party?.quest?.progress?.up ?: 0.0f)
|
||||
response.user?.let { mergeUser(user, it) }
|
||||
return response
|
||||
}
|
||||
|
||||
override suspend fun disableClasses(): User? = apiClient.disableClasses()
|
||||
|
|
@ -163,20 +158,19 @@ class UserRepositoryImpl(
|
|||
return retrieveUser(false, forced = true)
|
||||
}
|
||||
|
||||
override fun unlockPath(customization: Customization): Flowable<UnlockResponse> {
|
||||
override suspend fun unlockPath(customization: Customization): UnlockResponse? {
|
||||
return unlockPath(customization.path, customization.price ?: 0)
|
||||
}
|
||||
|
||||
override fun unlockPath(path: String, price: Int): Flowable<UnlockResponse> {
|
||||
return zipWithLiveUser(apiClient.unlockPath(path)) { unlockResponse, copiedUser ->
|
||||
val user = localRepository.getUnmanagedCopy(copiedUser)
|
||||
user.preferences = unlockResponse.preferences
|
||||
user.purchased = unlockResponse.purchased
|
||||
user.items = unlockResponse.items
|
||||
user.balance = copiedUser.balance - (price / 4.0)
|
||||
localRepository.saveUser(copiedUser, false)
|
||||
unlockResponse
|
||||
}
|
||||
override suspend fun unlockPath(path: String, price: Int): UnlockResponse? {
|
||||
val unlockResponse = apiClient.unlockPath(path) ?: return null
|
||||
val user = localRepository.getUser(userID).firstOrNull() ?: return unlockResponse
|
||||
user.preferences = unlockResponse.preferences
|
||||
user.purchased = unlockResponse.purchased
|
||||
user.items = unlockResponse.items
|
||||
user.balance = user.balance - (price / 4.0)
|
||||
localRepository.saveUser(user, false)
|
||||
return unlockResponse
|
||||
}
|
||||
|
||||
override suspend fun runCron() {
|
||||
|
|
@ -204,9 +198,10 @@ class UserRepositoryImpl(
|
|||
return apiClient.changeCustomDayStart(updateObject)
|
||||
}
|
||||
|
||||
override fun updateLanguage(languageCode: String): Flowable<User> {
|
||||
return updateUser("preferences.language", languageCode)
|
||||
.doOnNext { apiClient.setLanguageCode(languageCode) }
|
||||
override suspend fun updateLanguage(languageCode: String): User? {
|
||||
val user = updateUser("preferences.language", languageCode)
|
||||
apiClient.setLanguageCode(languageCode)
|
||||
return user
|
||||
}
|
||||
|
||||
override suspend fun resetAccount(): User? {
|
||||
|
|
@ -220,21 +215,18 @@ class UserRepositoryImpl(
|
|||
override fun sendPasswordResetEmail(email: String): Flowable<Void> =
|
||||
apiClient.sendPasswordResetEmail(email)
|
||||
|
||||
override fun updateLoginName(newLoginName: String, password: String?): Maybe<User> {
|
||||
return (
|
||||
if (password != null && password.isNotEmpty()) {
|
||||
apiClient.updateLoginName(newLoginName.trim(), password.trim())
|
||||
} else {
|
||||
apiClient.updateUsername(newLoginName.trim())
|
||||
}
|
||||
).flatMapMaybe { localRepository.getUserFlowable(userID).firstElement() }
|
||||
.doOnNext { user ->
|
||||
localRepository.modify(user) { liveUser ->
|
||||
liveUser.authentication?.localAuthentication?.username = newLoginName
|
||||
liveUser.flags?.verifiedUsername = true
|
||||
}
|
||||
}
|
||||
.firstElement()
|
||||
override suspend fun updateLoginName(newLoginName: String, password: String?): User? {
|
||||
if (password != null && password.isNotEmpty()) {
|
||||
apiClient.updateLoginName(newLoginName.trim(), password.trim())
|
||||
} else {
|
||||
apiClient.updateUsername(newLoginName.trim())
|
||||
}
|
||||
val user = localRepository.getUser(userID).firstOrNull() ?: return null
|
||||
localRepository.modify(user) { liveUser ->
|
||||
liveUser.authentication?.localAuthentication?.username = newLoginName
|
||||
liveUser.flags?.verifiedUsername = true
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
override fun verifyUsername(username: String): Flowable<VerifyUsernameResponse> = apiClient.verifyUsername(username.trim())
|
||||
|
|
@ -250,7 +242,7 @@ class UserRepositoryImpl(
|
|||
apiClient.updatePassword(oldPassword.trim(), newPassword.trim(), newPasswordConfirmation.trim())
|
||||
|
||||
override fun allocatePoint(stat: Attribute): Flowable<Stats> {
|
||||
getLiveUser().firstElement().subscribe(
|
||||
getLiveUserFlowable().firstElement().subscribe(
|
||||
{ liveUser ->
|
||||
localRepository.executeTransaction {
|
||||
when (stat) {
|
||||
|
|
@ -324,7 +316,7 @@ class UserRepositoryImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override fun useCustomization(type: String, category: String?, identifier: String): Flowable<User> {
|
||||
override suspend fun useCustomization(type: String, category: String?, identifier: String): User? {
|
||||
if (appConfigManager.enableLocalChanges()) {
|
||||
localRepository.getUserFlowable(userID).firstElement().subscribe(
|
||||
{ liveUser ->
|
||||
|
|
@ -401,14 +393,19 @@ class UserRepositoryImpl(
|
|||
return localRepository.getTeamPlan(teamID)
|
||||
}
|
||||
|
||||
private fun getLiveUser(): Flowable<User> {
|
||||
private fun getLiveUserFlowable(): Flowable<User> {
|
||||
return localRepository.getUserFlowable(userID)
|
||||
.map { Optional(localRepository.getLiveObject(it)) }
|
||||
.filterMapEmpty()
|
||||
}
|
||||
|
||||
private suspend fun getLiveUser(): User? {
|
||||
val user = localRepository.getUser(userID).firstOrNull() ?: return null
|
||||
return localRepository.getLiveObject(user)
|
||||
}
|
||||
|
||||
private fun <T : Any> zipWithLiveUser(flowable: Flowable<T>, mergeFunc: BiFunction<T, User, T>): Flowable<T> {
|
||||
return Flowable.zip(flowable, getLiveUser().firstElement().toFlowable(), mergeFunc)
|
||||
return Flowable.zip(flowable, getLiveUserFlowable().firstElement().toFlowable(), mergeFunc)
|
||||
}
|
||||
|
||||
private fun mergeUser(oldUser: User?, newUser: User): User {
|
||||
|
|
|
|||
|
|
@ -10,11 +10,12 @@ import com.habitrpg.android.habitica.models.social.Group
|
|||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.models.user.UserQuestStatus
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.RealmResults
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface UserLocalRepository : BaseLocalRepository {
|
||||
|
||||
fun getTutorialSteps(): Flowable<List<TutorialStep>>
|
||||
suspend fun getTutorialSteps(): Flow<RealmResults<TutorialStep>>
|
||||
|
||||
fun getUser(userID: String): Flow<User?>
|
||||
fun getUserFlowable(userID: String): Flowable<User>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.habitrpg.android.habitica.data.local.implementation
|
||||
|
||||
import com.habitrpg.android.habitica.data.local.UserLocalRepository
|
||||
import com.habitrpg.android.habitica.models.user.UserQuestStatus
|
||||
import com.habitrpg.android.habitica.extensions.filterMap
|
||||
import com.habitrpg.android.habitica.models.Achievement
|
||||
import com.habitrpg.android.habitica.models.QuestAchievement
|
||||
|
|
@ -12,6 +11,7 @@ import com.habitrpg.android.habitica.models.TutorialStep
|
|||
import com.habitrpg.android.habitica.models.social.ChatMessage
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.models.user.UserQuestStatus
|
||||
import hu.akarnokd.rxjava3.bridge.RxJavaBridge
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.Realm
|
||||
|
|
@ -21,7 +21,8 @@ import kotlinx.coroutines.flow.emptyFlow
|
|||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), UserLocalRepository {
|
||||
class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||
UserLocalRepository {
|
||||
override fun getUserQuestStatus(userID: String): Flowable<UserQuestStatus> {
|
||||
return getUserFlowable(userID)
|
||||
.map { it.party?.id ?: "" }
|
||||
|
|
@ -39,7 +40,8 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
.map {
|
||||
when {
|
||||
it.quest?.members?.find { questMember -> questMember.key == userID } === null -> UserQuestStatus.NO_QUEST
|
||||
it.quest?.progress?.collect?.isNotEmpty() ?: false -> UserQuestStatus.QUEST_COLLECT
|
||||
it.quest?.progress?.collect?.isNotEmpty()
|
||||
?: false -> UserQuestStatus.QUEST_COLLECT
|
||||
it.quest?.progress?.hp ?: 0.0 > 0.0 -> UserQuestStatus.QUEST_BOSS
|
||||
else -> UserQuestStatus.QUEST_UNKNOWN
|
||||
}
|
||||
|
|
@ -48,25 +50,24 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
|
||||
override fun getAchievements(): Flow<List<Achievement>> {
|
||||
return realm.where(Achievement::class.java)
|
||||
.sort("index")
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
.sort("index")
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getQuestAchievements(userID: String): Flow<List<QuestAchievement>> {
|
||||
return realm.where(User::class.java)
|
||||
.equalTo("id", userID)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded && it.size > 0 }
|
||||
.map { it.first()?.questAchievements ?: emptyList() }
|
||||
.equalTo("id", userID)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded && it.size > 0 }
|
||||
.map { it.first()?.questAchievements ?: emptyList() }
|
||||
}
|
||||
|
||||
override fun getTutorialSteps(): Flowable<List<TutorialStep>> = RxJavaBridge.toV3Flowable(
|
||||
realm.where(TutorialStep::class.java).findAll().asFlowable()
|
||||
override suspend fun getTutorialSteps() =
|
||||
realm.where(TutorialStep::class.java).findAll().toFlow()
|
||||
.filter { it.isLoaded }.map { it }
|
||||
)
|
||||
|
||||
override fun getUser(userID: String): Flow<User?> {
|
||||
if (realm.isClosed) return emptyFlow()
|
||||
|
|
@ -82,11 +83,11 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
if (realm.isClosed) return Flowable.empty()
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(User::class.java)
|
||||
.equalTo("id", userID)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isValid && !realmObject.isEmpty() }
|
||||
.map { users -> users.first() })
|
||||
.equalTo("id", userID)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isValid && !realmObject.isEmpty() }
|
||||
.map { users -> users.first() })
|
||||
}
|
||||
|
||||
override fun saveUser(user: User, overrideExisting: Boolean) {
|
||||
|
|
@ -127,10 +128,10 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
|
||||
override fun getTeamPlans(userID: String): Flow<List<TeamPlan>> {
|
||||
return realm.where(TeamPlan::class.java)
|
||||
.equalTo("userID", userID)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
.equalTo("userID", userID)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getTeamPlan(teamID: String): Flowable<Group> {
|
||||
|
|
@ -146,7 +147,8 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
}
|
||||
|
||||
override fun getSkills(user: User): Flowable<out List<Skill>> {
|
||||
val habitClass = if (user.preferences?.disableClasses == true) "none" else user.stats?.habitClass
|
||||
val habitClass =
|
||||
if (user.preferences?.disableClasses == true) "none" else user.stats?.habitClass
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Skill::class.java)
|
||||
.equalTo("habitClass", habitClass)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import com.habitrpg.android.habitica.BuildConfig
|
|||
import com.habitrpg.android.habitica.proxy.AnalyticsManager
|
||||
import io.reactivex.rxjava3.functions.Consumer
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.internal.http2.ConnectionShutdownException
|
||||
import retrofit2.HttpException
|
||||
import java.io.EOFException
|
||||
|
|
@ -53,3 +55,7 @@ class ExceptionHandler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun CoroutineScope.launchCatching(function: suspend CoroutineScope.() -> Unit) {
|
||||
launch((ExceptionHandler.coroutine()), block = function)
|
||||
}
|
||||
|
|
@ -501,6 +501,10 @@ open class Task : RealmObject, BaseMainObject, Parcelable, BaseTask {
|
|||
return daysOfMonth
|
||||
}
|
||||
|
||||
fun canEdit(userID: String): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Task> {
|
||||
override fun createFromParcel(source: Parcel): Task = Task(source)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import com.habitrpg.android.habitica.helpers.AdHandler
|
|||
import com.habitrpg.android.habitica.helpers.AdType
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
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
|
||||
|
|
@ -26,6 +25,7 @@ import com.habitrpg.common.habitica.extensions.dpToPx
|
|||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.common.habitica.helpers.Animations
|
||||
import com.plattysoft.leonids.ParticleSystem
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -80,22 +80,20 @@ class ArmoireActivity : BaseActivity() {
|
|||
Log.d("AdHandler", "Giving Armoire")
|
||||
val user = userViewModel.user.value ?: return@AdHandler
|
||||
val currentGold = user.stats?.gp ?: return@AdHandler
|
||||
compositeSubscription.add(
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser("stats.gp", currentGold + 100)
|
||||
.flatMap { inventoryRepository.buyItem(user, "armoire", 100.0, 1) }
|
||||
.subscribe({
|
||||
configure(
|
||||
it.armoire["type"] ?: "",
|
||||
it.armoire["dropKey"] ?: "",
|
||||
it.armoire["dropText"] ?: "",
|
||||
it.armoire["value"] ?: ""
|
||||
)
|
||||
binding.adButton.state = AdButton.State.UNAVAILABLE
|
||||
binding.adButton.visibility = View.INVISIBLE
|
||||
hasAnimatedChanges = false
|
||||
gold = null
|
||||
}, ExceptionHandler.rx())
|
||||
)
|
||||
val buyResponse = inventoryRepository.buyItem(user, "armoire", 100.0, 1) ?: return@launch
|
||||
configure(
|
||||
buyResponse.armoire["type"] ?: "",
|
||||
buyResponse.armoire["dropKey"] ?: "",
|
||||
buyResponse.armoire["dropText"] ?: "",
|
||||
buyResponse.armoire["value"] ?: ""
|
||||
)
|
||||
binding.adButton.state = AdButton.State.UNAVAILABLE
|
||||
binding.adButton.visibility = View.INVISIBLE
|
||||
hasAnimatedChanges = false
|
||||
gold = null
|
||||
}
|
||||
}
|
||||
handler.prepare {
|
||||
if (it && binding.adButton.state == AdButton.State.LOADING) {
|
||||
|
|
|
|||
|
|
@ -57,11 +57,10 @@ class DeathActivity: BaseActivity() {
|
|||
return@AdHandler
|
||||
}
|
||||
Log.d("AdHandler", "Reviving user")
|
||||
compositeSubscription.add(
|
||||
userRepository.updateUser("stats.hp", 1).subscribe({
|
||||
finish()
|
||||
}, ExceptionHandler.rx())
|
||||
)
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser("stats.hp", 1)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
handler.prepare {
|
||||
if (it && binding.adButton.state == AdButton.State.LOADING) {
|
||||
|
|
|
|||
|
|
@ -209,17 +209,10 @@ class SetupActivity : BaseActivity(), ViewPager.OnPageChangeListener {
|
|||
additionalData["status"] = "completed"
|
||||
AmplitudeManager.sendEvent("setup", AmplitudeManager.EVENT_CATEGORY_BEHAVIOUR, AmplitudeManager.EVENT_HITTYPE_EVENT, additionalData)
|
||||
|
||||
compositeSubscription.add(
|
||||
userRepository.updateUser("flags.welcomed", true).subscribe(
|
||||
{
|
||||
if (!compositeSubscription.isDisposed) {
|
||||
compositeSubscription.dispose()
|
||||
}
|
||||
startMainActivity()
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser("flags.welcomed", true)
|
||||
startMainActivity()
|
||||
}
|
||||
return
|
||||
}
|
||||
this.user = user
|
||||
|
|
@ -238,11 +231,10 @@ class SetupActivity : BaseActivity(), ViewPager.OnPageChangeListener {
|
|||
}
|
||||
|
||||
private fun confirmNames(displayName: String, username: String) {
|
||||
compositeSubscription.add(
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser("profile.name", displayName)
|
||||
.flatMap { userRepository.updateLoginName(username).toFlowable() }
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
userRepository.updateLoginName(username)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ViewPageAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT), IconPagerAdapter {
|
||||
|
|
|
|||
|
|
@ -114,13 +114,12 @@ class VerifyUsernameActivity : BaseActivity() {
|
|||
|
||||
private fun confirmNames() {
|
||||
binding.confirmUsernameButton.isClickable = false
|
||||
compositeSubscription.add(
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser("profile.name", binding.displayNameEditText.text.toString())
|
||||
.flatMap { userRepository.updateLoginName(binding.usernameEditText.text.toString()).toFlowable() }
|
||||
.doOnComplete { showConfirmationAndFinish() }
|
||||
.doOnEach { binding.confirmUsernameButton.isClickable = true }
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
userRepository.updateLoginName(binding.usernameEditText.text.toString())
|
||||
showConfirmationAndFinish()
|
||||
binding.confirmUsernameButton.isClickable = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun showConfirmationAndFinish() {
|
||||
|
|
|
|||
|
|
@ -18,11 +18,8 @@ import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
|||
import com.habitrpg.android.habitica.ui.views.shops.PurchaseDialog
|
||||
import com.habitrpg.common.habitica.extensions.dpToPx
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.shared.habitica.models.Avatar
|
||||
import com.habitrpg.common.habitica.views.AvatarView
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import com.habitrpg.shared.habitica.models.Avatar
|
||||
import java.util.Date
|
||||
import java.util.EnumMap
|
||||
import kotlin.math.min
|
||||
|
|
@ -46,7 +43,7 @@ class CustomizationRecyclerViewAdapter() : androidx.recyclerview.widget.Recycler
|
|||
var ownedCustomizations: List<String> = listOf()
|
||||
private var pinnedItemKeys: List<String> = ArrayList()
|
||||
|
||||
private val selectCustomizationEvents = PublishSubject.create<Customization>()
|
||||
var onCustomizationSelected: ((Customization) -> Unit)? = null
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
|
|
@ -152,10 +149,6 @@ class CustomizationRecyclerViewAdapter() : androidx.recyclerview.widget.Recycler
|
|||
this.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun getSelectCustomizationEvents(): Flowable<Customization> {
|
||||
return selectCustomizationEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
|
||||
fun setPinnedItemKeys(pinnedItemKeys: List<String>) {
|
||||
this.pinnedItemKeys = pinnedItemKeys
|
||||
if (customizationList.size > 0) this.notifyDataSetChanged()
|
||||
|
|
@ -234,7 +227,7 @@ class CustomizationRecyclerViewAdapter() : androidx.recyclerview.widget.Recycler
|
|||
alert.setMessage(customization?.notes)
|
||||
alert.addButton(R.string.equip, true) { _, _ ->
|
||||
customization?.let {
|
||||
selectCustomizationEvents.onNext(it)
|
||||
onCustomizationSelected?.invoke(it)
|
||||
}
|
||||
}
|
||||
alert.addButton(R.string.close, false) { _, _ ->
|
||||
|
|
@ -243,7 +236,7 @@ class CustomizationRecyclerViewAdapter() : androidx.recyclerview.widget.Recycler
|
|||
alert.show()
|
||||
} else {
|
||||
customization?.let {
|
||||
selectCustomizationEvents.onNext(it)
|
||||
onCustomizationSelected?.invoke(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@ internal class CustomizationSetupAdapter : RecyclerView.Adapter<CustomizationSet
|
|||
|
||||
private val equipGearEventSubject = PublishSubject.create<String>()
|
||||
val equipGearEvents: Flowable<String> = equipGearEventSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
private val updateUserEventsSubject = PublishSubject.create<Map<String, Any>>()
|
||||
val updateUserEvents: Flowable<Map<String, Any>> = updateUserEventsSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
var onUpdateUser: ((Map<String, Any>) -> Unit)? = null
|
||||
|
||||
fun setCustomizationList(newCustomizationList: List<SetupCustomization>) {
|
||||
this.customizationList = newCustomizationList
|
||||
|
|
@ -128,7 +127,7 @@ internal class CustomizationSetupAdapter : RecyclerView.Adapter<CustomizationSet
|
|||
val updateData = HashMap<String, Any>()
|
||||
val updatePath = "preferences." + selectedCustomization.path
|
||||
updateData[updatePath] = selectedCustomization.key
|
||||
updateUserEventsSubject.onNext(updateData)
|
||||
onUpdateUser?.invoke(updateData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,13 @@ import android.webkit.WebChromeClient
|
|||
import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.databinding.FragmentNewsBinding
|
||||
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class NewsFragment : BaseMainFragment<FragmentNewsBinding>() {
|
||||
|
||||
|
|
@ -75,6 +77,8 @@ class NewsFragment : BaseMainFragment<FragmentNewsBinding>() {
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
compositeSubscription.add(userRepository.updateUser("flags.newStuff", false).subscribeWithErrorHandler({}))
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser("flags.newStuff", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,23 +5,25 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository
|
||||
import com.habitrpg.android.habitica.databinding.FragmentStatsBinding
|
||||
import com.habitrpg.android.habitica.extensions.addOkButton
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.android.habitica.extensions.setScaledPadding
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.UserStatComputer
|
||||
import com.habitrpg.shared.habitica.models.tasks.Attribute
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.user.Stats
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.android.habitica.ui.views.stats.BulkAllocateStatsDialog
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.shared.habitica.models.tasks.Attribute
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.min
|
||||
|
||||
|
|
@ -131,8 +133,9 @@ class StatsFragment : BaseMainFragment<FragmentStatsBinding>() {
|
|||
}
|
||||
|
||||
binding?.automaticAllocationSwitch?.setOnCheckedChangeListener { _, isChecked ->
|
||||
userRepository.updateUser("preferences.automaticAllocation", isChecked)
|
||||
.subscribe({}, ExceptionHandler.rx())
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser("preferences.automaticAllocation", isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
binding?.strengthStatsView?.allocateAction = { allocatePoint(Attribute.STRENGTH) }
|
||||
|
|
@ -159,12 +162,12 @@ class StatsFragment : BaseMainFragment<FragmentStatsBinding>() {
|
|||
}
|
||||
|
||||
private fun changeAutoAllocationMode(allocationMode: String) {
|
||||
compositeSubscription.add(
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser(
|
||||
"preferences.allocationMode",
|
||||
allocationMode
|
||||
).subscribe({}, ExceptionHandler.rx())
|
||||
)
|
||||
)
|
||||
}
|
||||
binding?.distributeEvenlyButton?.isChecked = allocationMode == Stats.AUTO_ALLOCATE_FLAT
|
||||
binding?.distributeClassButton?.isChecked = allocationMode == Stats.AUTO_ALLOCATE_CLASSBASED
|
||||
binding?.distributeTaskButton?.isChecked = allocationMode == Stats.AUTO_ALLOCATE_TASKBASED
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.habitrpg.android.habitica.databinding.BottomSheetBackgroundsFilterBin
|
|||
import com.habitrpg.android.habitica.databinding.FragmentRefreshRecyclerviewBinding
|
||||
import com.habitrpg.android.habitica.extensions.setTintWith
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.CustomizationFilter
|
||||
import com.habitrpg.android.habitica.models.inventory.Customization
|
||||
import com.habitrpg.android.habitica.models.user.OwnedCustomization
|
||||
|
|
@ -79,18 +80,20 @@ class AvatarCustomizationFragment :
|
|||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
showsBackButton = true
|
||||
compositeSubscription.add(
|
||||
adapter.getSelectCustomizationEvents()
|
||||
.flatMap { customization ->
|
||||
adapter.onCustomizationSelected = { customization ->
|
||||
lifecycleScope.launchCatching {
|
||||
if (customization.type == "background") {
|
||||
userRepository.unlockPath(customization)
|
||||
//TODO: .flatMap { userRepository.retrieveUser(false, true, true) }
|
||||
userRepository.retrieveUser(false, true, true)
|
||||
} else {
|
||||
userRepository.useCustomization(customization.type ?: "", customization.category, customization.identifier ?: "")
|
||||
userRepository.useCustomization(
|
||||
customization.type ?: "",
|
||||
customization.category,
|
||||
customization.identifier ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
}
|
||||
|
||||
compositeSubscription.add(
|
||||
this.inventoryRepository.getInAppRewards()
|
||||
|
|
|
|||
|
|
@ -20,11 +20,12 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.databinding.FragmentComposeScrollingBinding
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
|
|
@ -89,10 +90,9 @@ class AvatarOverviewFragment : BaseMainFragment<FragmentComposeScrollingBinding>
|
|||
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
|
||||
val newSize: String = if (position == 0) "slim" else "broad"
|
||||
|
||||
compositeSubscription.add(
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser("preferences.size", newSize)
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>) { /* no-on */
|
||||
|
|
|
|||
|
|
@ -19,8 +19,9 @@ import com.habitrpg.android.habitica.databinding.FragmentItemsBinding
|
|||
import com.habitrpg.android.habitica.extensions.addCloseButton
|
||||
import com.habitrpg.android.habitica.extensions.observeOnce
|
||||
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.interactors.HatchPetUseCase
|
||||
import com.habitrpg.android.habitica.models.inventory.Egg
|
||||
import com.habitrpg.android.habitica.models.inventory.Food
|
||||
|
|
@ -28,7 +29,6 @@ import com.habitrpg.android.habitica.models.inventory.HatchingPotion
|
|||
import com.habitrpg.android.habitica.models.inventory.Item
|
||||
import com.habitrpg.android.habitica.models.inventory.QuestContent
|
||||
import com.habitrpg.android.habitica.models.inventory.SpecialItem
|
||||
import com.habitrpg.android.habitica.models.responses.SkillResponse
|
||||
import com.habitrpg.android.habitica.models.user.OwnedItem
|
||||
import com.habitrpg.android.habitica.models.user.OwnedPet
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
|
|
@ -44,7 +44,6 @@ import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
|||
import com.habitrpg.android.habitica.ui.views.dialogs.OpenedMysteryitemDialog
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.common.habitica.helpers.EmptyItem
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
|
@ -322,16 +321,10 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
if (specialItem == null || memberID == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val observable: Flowable<SkillResponse> =
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.useSkill(specialItem.key, specialItem.target, memberID)
|
||||
|
||||
compositeSubscription.add(
|
||||
observable.subscribe(
|
||||
{ this.displaySpecialItemResult(specialItem) },
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
displaySpecialItemResult(specialItem)
|
||||
}
|
||||
}
|
||||
|
||||
private fun displaySpecialItemResult(specialItem: SpecialItem?) {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import com.habitrpg.common.habitica.extensions.dpToPx
|
|||
import com.habitrpg.common.habitica.extensions.layoutInflater
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.activities.FixCharacterValuesActivity
|
||||
import com.habitrpg.android.habitica.ui.fragments.preferences.HabiticaAccountDialog.AccountUpdateConfirmed
|
||||
|
|
@ -256,8 +257,9 @@ class AccountPreferenceFragment :
|
|||
private fun updateUser(path: String, value: String?, title: String) {
|
||||
showSingleEntryDialog(value, title) {
|
||||
if (value != it) {
|
||||
userRepository.updateUser(path, it ?: "")
|
||||
.subscribe({}, ExceptionHandler.rx())
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser(path, it ?: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -388,8 +390,9 @@ class AccountPreferenceFragment :
|
|||
|
||||
private fun showLoginNameDialog() {
|
||||
showSingleEntryDialog(user?.username, getString(R.string.username)) {
|
||||
userRepository.updateLoginName(it ?: "")
|
||||
.subscribe({}, ExceptionHandler.rx())
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateLoginName(it ?: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -478,8 +481,11 @@ class AccountPreferenceFragment :
|
|||
dialog.setTitle(R.string.confirm_username_title)
|
||||
dialog.setMessage(R.string.confirm_username_description)
|
||||
dialog.addButton(R.string.confirm, true) { _, _ ->
|
||||
userRepository.updateLoginName(user?.authentication?.localAuthentication?.username ?: "")
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateLoginName(
|
||||
user?.authentication?.localAuthentication?.username ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
dialog.addCancelButton()
|
||||
dialog.show()
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ package com.habitrpg.android.habitica.ui.fragments.preferences
|
|||
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.CheckBoxPreference
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
|
||||
class EmailNotificationsPreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
|
@ -73,7 +74,12 @@ class EmailNotificationsPreferencesFragment : BasePreferencesFragment(), SharedP
|
|||
else -> null
|
||||
}
|
||||
if (pathKey != null) {
|
||||
compositeSubscription.add(userRepository.updateUser("preferences.emailNotifications.$pathKey", sharedPreferences.getBoolean(key, false)).subscribe({ }, ExceptionHandler.rx()))
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser(
|
||||
"preferences.emailNotifications.$pathKey",
|
||||
sharedPreferences.getBoolean(key, false)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.habitrpg.android.habitica.helpers.AppConfigManager
|
|||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.SoundManager
|
||||
import com.habitrpg.android.habitica.helpers.TaskAlarmManager
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.helpers.notifications.PushNotificationManager
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.prefs.TimePreference
|
||||
|
|
@ -207,7 +208,9 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
"usePushNotifications" -> {
|
||||
val usePushNotifications = sharedPreferences.getBoolean(key, true)
|
||||
pushNotificationsPreference?.isEnabled = usePushNotifications
|
||||
userRepository.updateUser("preferences.pushNotifications.unsubscribeFromAll", !usePushNotifications).subscribe()
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser("preferences.pushNotifications.unsubscribeFromAll", !usePushNotifications)
|
||||
}
|
||||
if (usePushNotifications) {
|
||||
pushNotificationManager.addPushDeviceUsingStoredToken()
|
||||
} else {
|
||||
|
|
@ -217,7 +220,9 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
"useEmails" -> {
|
||||
val useEmailNotifications = sharedPreferences.getBoolean(key, true)
|
||||
emailNotificationsPreference?.isEnabled = useEmailNotifications
|
||||
userRepository.updateUser("preferences.emailNotifications.unsubscribeFromAll", !useEmailNotifications).subscribe()
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser("preferences.emailNotifications.unsubscribeFromAll", !useEmailNotifications)
|
||||
}
|
||||
}
|
||||
"cds_time" -> {
|
||||
val timeval = sharedPreferences.getString("cds_time", "0") ?: "0"
|
||||
|
|
@ -238,10 +243,10 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
if (user?.preferences?.language == languageHelper.languageCode) {
|
||||
return
|
||||
}
|
||||
|
||||
userRepository.updateLanguage(languageHelper.languageCode ?: "en")
|
||||
.subscribe({ reloadContent(false) }, ExceptionHandler.rx())
|
||||
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateLanguage(languageHelper.languageCode ?: "en")
|
||||
reloadContent(false)
|
||||
}
|
||||
val intent = Intent(activity, MainActivity::class.java)
|
||||
this.startActivity(intent)
|
||||
activity?.finishAffinity()
|
||||
|
|
@ -249,10 +254,9 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
"audioTheme" -> {
|
||||
val newAudioTheme = sharedPreferences.getString(key, "off")
|
||||
if (newAudioTheme != null) {
|
||||
compositeSubscription.add(
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser("preferences.sound", newAudioTheme)
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
}
|
||||
soundManager.soundTheme = newAudioTheme
|
||||
soundManager.preloadAllFiles()
|
||||
}
|
||||
|
|
@ -265,8 +269,12 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
val activity = activity as? PrefsActivity ?: return
|
||||
activity.reload()
|
||||
}
|
||||
"dailyDueDefaultView" -> userRepository.updateUser("preferences.dailyDueDefaultView", sharedPreferences.getBoolean(key, false))
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
"dailyDueDefaultView" -> lifecycleScope.launchCatching {
|
||||
userRepository.updateUser(
|
||||
"preferences.dailyDueDefaultView",
|
||||
sharedPreferences.getBoolean(key, false)
|
||||
)
|
||||
}
|
||||
"server_url" -> {
|
||||
apiClient.updateServerUrl(sharedPreferences.getString(key, ""))
|
||||
findPreference<Preference>(key)?.summary = sharedPreferences.getString(key, "")
|
||||
|
|
@ -282,10 +290,9 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
"disablePMs" -> {
|
||||
val isDisabled = sharedPreferences.getBoolean("disablePMs", false)
|
||||
if (user?.inbox?.optOut != isDisabled) {
|
||||
compositeSubscription.add(
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser("inbox.optOut", isDisabled)
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
"launch_screen" -> {
|
||||
|
|
@ -390,7 +397,12 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
} else if (newValue == false && currentIds.contains(team.id)) {
|
||||
currentIds.remove(team.id)
|
||||
}
|
||||
userRepository.updateUser("preferences.tasks.mirrorGroupTasks", currentIds).subscribe({}, ExceptionHandler.rx())
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser(
|
||||
"preferences.tasks.mirrorGroupTasks",
|
||||
currentIds
|
||||
)
|
||||
}
|
||||
true
|
||||
}
|
||||
groupCategory?.addPreference(newPreference)
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ package com.habitrpg.android.habitica.ui.fragments.preferences
|
|||
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.CheckBoxPreference
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
|
||||
class PushNotificationsPreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
|
@ -75,7 +76,9 @@ class PushNotificationsPreferencesFragment : BasePreferencesFragment(), SharedPr
|
|||
else -> null
|
||||
}
|
||||
if (pathKey != null) {
|
||||
compositeSubscription.add(userRepository.updateUser("preferences.pushNotifications.$pathKey", sharedPreferences.getBoolean(key, false)).subscribe({ }, ExceptionHandler.rx()))
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser("preferences.pushNotifications.$pathKey", sharedPreferences.getBoolean(key, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.habitrpg.android.habitica.R
|
||||
|
|
@ -15,6 +16,7 @@ import com.habitrpg.android.habitica.data.SetupCustomizationRepository
|
|||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.databinding.FragmentSetupAvatarBinding
|
||||
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.SetupCustomization
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.activities.SetupActivity
|
||||
|
|
@ -56,7 +58,11 @@ class AvatarSetupFragment : BaseFragment<FragmentSetupAvatarBinding>() {
|
|||
|
||||
this.adapter = CustomizationSetupAdapter()
|
||||
this.adapter?.userSize = this.user?.preferences?.size ?: "slim"
|
||||
adapter?.updateUserEvents?.flatMap { userRepository.updateUser(it) }?.subscribeWithErrorHandler {}?.let { compositeSubscription.add(it) }
|
||||
adapter?.onUpdateUser = {
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser(it)
|
||||
}
|
||||
}
|
||||
adapter?.equipGearEvents?.flatMap { inventoryRepository.equip("equipped", it) }?.subscribeWithErrorHandler {}?.let { compositeSubscription.add(it) }
|
||||
|
||||
this.adapter?.user = this.user
|
||||
|
|
@ -185,7 +191,9 @@ class AvatarSetupFragment : BaseFragment<FragmentSetupAvatarBinding>() {
|
|||
updateData["preferences.hair.bangs"] = chooseRandomKey(customizationRepository.getCustomizations(SetupCustomizationRepository.CATEGORY_HAIR, SetupCustomizationRepository.SUBCATEGORY_BANGS, user), false)
|
||||
updateData["preferences.hair.flower"] = chooseRandomKey(customizationRepository.getCustomizations(SetupCustomizationRepository.CATEGORY_EXTRAS, SetupCustomizationRepository.SUBCATEGORY_FLOWER, user), true)
|
||||
updateData["preferences.chair"] = chooseRandomKey(customizationRepository.getCustomizations(SetupCustomizationRepository.CATEGORY_EXTRAS, SetupCustomizationRepository.SUBCATEGORY_WHEELCHAIR, user), true)
|
||||
compositeSubscription.add(userRepository.updateUser(updateData).subscribeWithErrorHandler({}))
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.updateUser(updateData)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ReturnCount")
|
||||
|
|
@ -215,4 +223,4 @@ class AvatarSetupFragment : BaseFragment<FragmentSetupAvatarBinding>() {
|
|||
params?.marginStart = location[0] + px
|
||||
binding?.customizationDrawer?.binding?.caretView?.layoutParams = params
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import com.habitrpg.android.habitica.components.UserComponent
|
|||
import com.habitrpg.android.habitica.databinding.FragmentSkillsBinding
|
||||
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.Skill
|
||||
import com.habitrpg.android.habitica.models.responses.SkillResponse
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
|
|
@ -161,16 +162,15 @@ class SkillsFragment : BaseMainFragment<FragmentSkillsBinding>() {
|
|||
if (skill == null) {
|
||||
return
|
||||
}
|
||||
val observable: Flowable<SkillResponse> = if (taskId != null) {
|
||||
userRepository.useSkill(skill.key, skill.target, taskId)
|
||||
} else {
|
||||
userRepository.useSkill(skill.key, skill.target)
|
||||
lifecycleScope.launchCatching {
|
||||
val skillResponse = if (taskId != null) {
|
||||
userRepository.useSkill(skill.key, skill.target, taskId)
|
||||
} else {
|
||||
userRepository.useSkill(skill.key, skill.target)
|
||||
}
|
||||
if (skillResponse != null) {
|
||||
displaySkillResult(skill, skillResponse)
|
||||
}
|
||||
}
|
||||
compositeSubscription.add(
|
||||
observable.subscribe(
|
||||
{ skillResponse -> this.displaySkillResult(skill, skillResponse) },
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,16 +6,18 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.FAQRepository
|
||||
import com.habitrpg.android.habitica.databinding.FragmentSupportMainBinding
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
|
|
@ -59,9 +61,11 @@ class SupportMainFragment : BaseMainFragment<FragmentSupportMainBinding>() {
|
|||
}
|
||||
|
||||
binding?.resetTutorialButton?.setOnClickListener {
|
||||
userRepository.resetTutorial().subscribe({
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.resetTutorial()
|
||||
activity?.showSnackbar(null, null, getString(R.string.tutorial_reset_confirmation), displayType = HabiticaSnackbar.SnackbarDisplayType.SUCCESS)
|
||||
}, ExceptionHandler.rx())
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.shops.ShopItem
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import com.habitrpg.android.habitica.ui.activities.SkillMemberActivity
|
||||
|
|
@ -22,7 +23,6 @@ import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter
|
|||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import io.reactivex.rxjava3.functions.Consumer
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() {
|
||||
|
|
@ -35,7 +35,9 @@ class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() {
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
compositeSubscription.add(inventoryRepository.retrieveInAppRewards().subscribe({ }, ExceptionHandler.rx()))
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.retrieveInAppRewards()
|
||||
}
|
||||
return super.onCreateView(inflater, container, savedInstanceState)
|
||||
}
|
||||
|
||||
|
|
@ -97,13 +99,9 @@ class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() {
|
|||
binding?.refreshLayout?.isRefreshing = true
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.retrieveUser(withTasks = true, forced = true)
|
||||
}
|
||||
compositeSubscription.add(
|
||||
inventoryRepository.retrieveInAppRewards()
|
||||
.doOnTerminate {
|
||||
binding?.refreshLayout?.isRefreshing = false
|
||||
}.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
binding?.refreshLayout?.isRefreshing = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun setGridSpanCount(width: Int) {
|
||||
|
|
@ -122,21 +120,19 @@ class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() {
|
|||
|
||||
private val cardSelectedResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
userRepository.useSkill(
|
||||
selectedCard?.key ?: "",
|
||||
"member",
|
||||
it.data?.getStringExtra("member_id") ?: ""
|
||||
)
|
||||
.subscribeWithErrorHandler(
|
||||
Consumer {
|
||||
val activity = (activity as? MainActivity) ?: return@Consumer
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
activity.snackbarContainer,
|
||||
context?.getString(R.string.sent_card, selectedCard?.text),
|
||||
HabiticaSnackbar.SnackbarDisplayType.BLUE
|
||||
)
|
||||
}
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.useSkill(
|
||||
selectedCard?.key ?: "",
|
||||
"member",
|
||||
it.data?.getStringExtra("member_id") ?: ""
|
||||
)
|
||||
val activity = (activity as? MainActivity) ?: return@launchCatching
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
activity.snackbarContainer,
|
||||
context?.getString(R.string.sent_card, selectedCard?.text),
|
||||
HabiticaSnackbar.SnackbarDisplayType.BLUE
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@ package com.habitrpg.android.habitica.ui.viewmodels
|
|||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class BaseViewModel(initializeComponent: Boolean = true) : ViewModel() {
|
||||
|
|
@ -38,9 +40,8 @@ abstract class BaseViewModel(initializeComponent: Boolean = true) : ViewModel()
|
|||
internal val disposable = CompositeDisposable()
|
||||
|
||||
fun updateUser(path: String, value: Any) {
|
||||
disposable.add(
|
||||
viewModelScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser(path, value)
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,12 @@ import com.habitrpg.android.habitica.models.members.Member
|
|||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainUserViewModel(private val providedUserID: String, val userRepository: UserRepository, val socialRepository: SocialRepository) {
|
||||
|
||||
|
|
@ -59,16 +61,14 @@ class MainUserViewModel(private val providedUserID: String, val userRepository:
|
|||
internal val disposable = CompositeDisposable()
|
||||
|
||||
fun updateUser(path: String, value: Any) {
|
||||
disposable.add(
|
||||
MainScope().launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser(path, value)
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateUser(data: Map<String, Any>) {
|
||||
disposable.add(
|
||||
MainScope().launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser(data)
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.databinding.DialogHatchPetButtonBinding
|
||||
import com.habitrpg.android.habitica.databinding.DialogPetSuggestHatchBinding
|
||||
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.interactors.HatchPetUseCase
|
||||
import com.habitrpg.android.habitica.models.inventory.Animal
|
||||
import com.habitrpg.android.habitica.models.inventory.Egg
|
||||
|
|
@ -22,7 +24,6 @@ import com.habitrpg.android.habitica.ui.activities.MainActivity
|
|||
import com.habitrpg.common.habitica.extensions.DataBindingUtils
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
|
@ -140,21 +141,16 @@ class PetSuggestHatchDialog(context: Context) : HabiticaAlertDialog(context) {
|
|||
val activity = (getActivity() as? MainActivity) ?: return@addButton
|
||||
val thisPotion = potion ?: return@addButton
|
||||
val thisEgg = egg ?: return@addButton
|
||||
var observable: Flowable<Any> = Flowable.just("")
|
||||
if (!hasEgg) {
|
||||
observable = observable.flatMap { activity.inventoryRepository.purchaseItem("eggs", thisEgg.key, 1) }
|
||||
lifecycleScope.launchCatching {
|
||||
if (!hasEgg) {
|
||||
activity.inventoryRepository.purchaseItem("eggs", thisEgg.key, 1)
|
||||
}
|
||||
if (!hasPotion) {
|
||||
activity.inventoryRepository.purchaseItem("hatchingPotions", thisPotion.key, 1)
|
||||
}
|
||||
activity.userRepository.retrieveUser(true, forced = true)
|
||||
hatchPet(thisPotion, thisEgg)
|
||||
}
|
||||
if (!hasPotion) {
|
||||
observable = observable.flatMap { activity.inventoryRepository.purchaseItem("hatchingPotions", thisPotion.key, 1) }
|
||||
}
|
||||
observable
|
||||
.subscribe(
|
||||
{
|
||||
// TODO: activity.userRepository.retrieveUser(true, forced = true)
|
||||
hatchPet(thisPotion, thisEgg)
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import android.widget.TextView
|
|||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.firebase.analytics.FirebaseAnalytics
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
|
|
@ -23,6 +24,7 @@ import com.habitrpg.android.habitica.helpers.AppConfigManager
|
|||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.HapticFeedbackManager
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.shops.Shop
|
||||
import com.habitrpg.android.habitica.models.shops.ShopItem
|
||||
import com.habitrpg.android.habitica.models.user.OwnedItem
|
||||
|
|
@ -38,7 +40,6 @@ import com.habitrpg.android.habitica.ui.views.insufficientCurrency.InsufficientG
|
|||
import com.habitrpg.android.habitica.ui.views.insufficientCurrency.InsufficientHourglassesDialog
|
||||
import com.habitrpg.android.habitica.ui.views.insufficientCurrency.InsufficientSubscriberGemsDialog
|
||||
import com.habitrpg.android.habitica.ui.views.tasks.form.StepperValueFormView
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -254,7 +255,12 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop
|
|||
priceLabel = buyButton.findViewById(R.id.priceLabel)
|
||||
priceLabel.animationDuration = 0L
|
||||
buyLabel = buyButton.findViewById(R.id.buy_label)
|
||||
pinButton.setOnClickListener { inventoryRepository.togglePinnedItem(shopItem).subscribe({ isPinned = !this.isPinned }, ExceptionHandler.rx()) }
|
||||
pinButton.setOnClickListener {
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.togglePinnedItem(shopItem)
|
||||
isPinned = !isPinned
|
||||
}
|
||||
}
|
||||
|
||||
shopItem = item
|
||||
|
||||
|
|
@ -357,30 +363,31 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop
|
|||
)
|
||||
HapticFeedbackManager.tap(contentView)
|
||||
val snackbarText = arrayOf("")
|
||||
val observable: Flowable<Any>
|
||||
val observable: (suspend () -> Unit)
|
||||
if (shopIdentifier != null && shopIdentifier == Shop.TIME_TRAVELERS_SHOP || "mystery_set" == shopItem.purchaseType || shopItem.currency == "hourglasses") {
|
||||
observable = if (shopItem.purchaseType == "gear") {
|
||||
inventoryRepository.purchaseMysterySet(shopItem.key).cast(Any::class.java)
|
||||
{ inventoryRepository.purchaseMysterySet(shopItem.key) }
|
||||
} else {
|
||||
inventoryRepository.purchaseHourglassItem(shopItem.purchaseType, shopItem.key).cast(Any::class.java)
|
||||
{ inventoryRepository.purchaseHourglassItem(shopItem.purchaseType, shopItem.key) }
|
||||
}
|
||||
// TODO: } else if (shopItem.purchaseType == "fortify") {
|
||||
// observable = userRepository.reroll().cast(Any::class.java)
|
||||
} else if (shopItem.purchaseType == "fortify") {
|
||||
observable = { userRepository.reroll() }
|
||||
} else if (shopItem.purchaseType == "quests" && shopItem.currency == "gold") {
|
||||
observable = inventoryRepository.purchaseQuest(shopItem.key).cast(Any::class.java)
|
||||
observable = { inventoryRepository.purchaseQuest(shopItem.key) }
|
||||
} else if (shopItem.purchaseType == "debuffPotion") {
|
||||
observable = userRepository.useSkill(shopItem.key, null).cast(Any::class.java)
|
||||
observable = { userRepository.useSkill(shopItem.key, null) }
|
||||
} else if (shopItem.purchaseType == "customization" || shopItem.purchaseType == "background" || shopItem.purchaseType == "backgrounds" || shopItem.purchaseType == "customizationSet") {
|
||||
observable = userRepository.unlockPath(item.unlockPath ?: "${item.pinType}.${item.key}" ?: "", item.value).cast(Any::class.java)
|
||||
observable = { userRepository.unlockPath(item.unlockPath ?: "${item.pinType}.${item.key}" ?: "", item.value) }
|
||||
} else if (shopItem.purchaseType == "debuffPotion") {
|
||||
observable = userRepository.useSkill(shopItem.key, null).cast(Any::class.java)
|
||||
observable = { userRepository.useSkill(shopItem.key, null) }
|
||||
} else if (shopItem.purchaseType == "card") {
|
||||
purchaseCardAction?.invoke(shopItem)
|
||||
dismiss()
|
||||
return
|
||||
} else if ("gold" == shopItem.currency && "gem" != shopItem.key) {
|
||||
observable = inventoryRepository.buyItem(user, shopItem.key, shopItem.value.toDouble(), quantity).map { buyResponse ->
|
||||
if (shopItem.key == "armoire" && configManager.enableNewArmoire()) {
|
||||
observable = {
|
||||
val buyResponse = inventoryRepository.buyItem(user, shopItem.key, shopItem.value.toDouble(), quantity)
|
||||
if (shopItem.key == "armoire" && configManager.enableNewArmoire() && buyResponse != null) {
|
||||
MainNavigationController.navigate(
|
||||
R.id.armoireActivity,
|
||||
ArmoireActivityDirections.openArmoireActivity(
|
||||
|
|
@ -391,45 +398,34 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop
|
|||
).arguments
|
||||
)
|
||||
}
|
||||
buyResponse
|
||||
}
|
||||
} else {
|
||||
observable = inventoryRepository.purchaseItem(shopItem.purchaseType, shopItem.key, quantity).cast(Any::class.java)
|
||||
observable = { inventoryRepository.purchaseItem(shopItem.purchaseType, shopItem.key, quantity) }
|
||||
}
|
||||
val subscription = observable
|
||||
.doOnNext {
|
||||
val text = if (snackbarText[0].isNotEmpty()) {
|
||||
snackbarText[0]
|
||||
} else {
|
||||
context.getString(R.string.successful_purchase, shopItem.text)
|
||||
}
|
||||
val rightTextColor = when (item.currency) {
|
||||
"gold" -> ContextCompat.getColor(context, R.color.text_yellow)
|
||||
"gems" -> ContextCompat.getColor(context, R.color.text_green)
|
||||
"hourglasses" -> ContextCompat.getColor(context, R.color.text_brand)
|
||||
else -> 0
|
||||
}
|
||||
((application?.currentActivity?.get() ?: getActivity() ?: ownerActivity) as? SnackbarActivity)?.showSnackbar(
|
||||
content = text,
|
||||
rightIcon = priceLabel.compoundDrawables[0],
|
||||
rightTextColor = rightTextColor,
|
||||
rightText = "-" + priceLabel.text
|
||||
)
|
||||
lifecycleScope.launchCatching {
|
||||
observable()
|
||||
val text = if (snackbarText[0].isNotEmpty()) {
|
||||
snackbarText[0]
|
||||
} else {
|
||||
context.getString(R.string.successful_purchase, shopItem.text)
|
||||
}
|
||||
// TODO: .flatMap { userRepository.retrieveUser(withTasks = false, forced = true) }
|
||||
.flatMap { inventoryRepository.retrieveInAppRewards() }
|
||||
.subscribe({
|
||||
if (item.isTypeGear || item.currency == "hourglasses") {
|
||||
onGearPurchased?.invoke(item)
|
||||
}
|
||||
}) { throwable ->
|
||||
if (throwable.javaClass.isAssignableFrom(retrofit2.HttpException::class.java)) {
|
||||
val error = throwable as retrofit2.HttpException
|
||||
if (error.code() == 401 && shopItem.currency == "gems") {
|
||||
MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", false)))
|
||||
}
|
||||
}
|
||||
val rightTextColor = when (item.currency) {
|
||||
"gold" -> ContextCompat.getColor(context, R.color.text_yellow)
|
||||
"gems" -> ContextCompat.getColor(context, R.color.text_green)
|
||||
"hourglasses" -> ContextCompat.getColor(context, R.color.text_brand)
|
||||
else -> 0
|
||||
}
|
||||
((application?.currentActivity?.get() ?: getActivity() ?: ownerActivity) as? SnackbarActivity)?.showSnackbar(
|
||||
content = text,
|
||||
rightIcon = priceLabel.compoundDrawables[0],
|
||||
rightTextColor = rightTextColor,
|
||||
rightText = "-" + priceLabel.text
|
||||
)
|
||||
inventoryRepository.retrieveInAppRewards()
|
||||
if (item.isTypeGear || item.currency == "hourglasses") {
|
||||
onGearPurchased?.invoke(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayPurchaseConfirmationDialog(quantity: Int) {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ kotlin {
|
|||
sourceSets {
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
|
||||
implementation("io.realm.kotlin:library-base:1.0.2")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ actual class PlatformLogger actual constructor() {
|
|||
Log.i(tag, message)
|
||||
}
|
||||
|
||||
actual fun logWarning(tag: String, message: String) {
|
||||
Log.w(tag, message)
|
||||
}
|
||||
|
||||
actual fun logError(tag: String, message: String) {
|
||||
Log.e(tag, message)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ expect class PlatformLogger() {
|
|||
|
||||
fun logDebug(tag: String, message: String)
|
||||
fun logInfo(tag: String, message: String)
|
||||
fun logWarning(tag: String, message: String)
|
||||
fun logError(tag: String, message: String)
|
||||
fun logError(tag: String, message: String, exception: Throwable)
|
||||
}
|
||||
|
||||
enum class LogLevel {
|
||||
ERROR, INFO, DEBUG
|
||||
ERROR, INFO, WARNING, DEBUG
|
||||
}
|
||||
|
||||
class HLogger {
|
||||
|
|
@ -26,6 +27,7 @@ class HLogger {
|
|||
when (level) {
|
||||
LogLevel.ERROR -> platformLogger.logError(tag, message)
|
||||
LogLevel.INFO -> platformLogger.logInfo(tag, message)
|
||||
LogLevel.WARNING -> platformLogger.logWarning(tag, message)
|
||||
LogLevel.DEBUG -> platformLogger.logDebug(tag, message)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,18 +5,22 @@ actual class PlatformLogger {
|
|||
get() = true
|
||||
|
||||
actual fun logDebug(tag: String, message: String) {
|
||||
println("[DEBUG] $tag: $message")
|
||||
println("[🟢] $tag: $message")
|
||||
}
|
||||
|
||||
actual fun logInfo(tag: String, message: String) {
|
||||
println("[INFO] $tag: $message")
|
||||
println("[🟡] $tag: $message")
|
||||
}
|
||||
|
||||
actual fun logWarning(tag: String, message: String) {
|
||||
println("[🟠] $tag: $message")
|
||||
}
|
||||
|
||||
actual fun logError(tag: String, message: String) {
|
||||
println("[ERROR] $tag: $message")
|
||||
println("[🔴] $tag: $message")
|
||||
}
|
||||
|
||||
actual fun logError(tag: String, message: String, exception: Throwable) {
|
||||
println("[ERROR] $tag: $message\n${exception.getStackTrace().joinToString("\n")}")
|
||||
println("[🔴] $tag: $message\n${exception.getStackTrace().joinToString("\n")}")
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue