mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-04-14 19:56:32 +00:00
Remove RxJava from all repositories
This commit is contained in:
parent
cedc06f1e9
commit
c4a482eac8
141 changed files with 3548 additions and 3652 deletions
|
|
@ -204,9 +204,6 @@
|
|||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||
<activity android:name=".ui.activities.GemPurchaseActivity"
|
||||
android:screenOrientation="unspecified" />
|
||||
<activity android:name=".ui.activities.VerifyUsernameActivity"
|
||||
android:screenOrientation="unspecified"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
<receiver android:name=".receivers.NotificationPublisher" />
|
||||
|
||||
<receiver android:name=".receivers.TaskReceiver" android:enabled="true" android:exported="true">
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment,
|
|||
@Test
|
||||
fun canHatchPetWithEggs() {
|
||||
val slot = CapturingSlot<HatchPetUseCase.RequestValues>()
|
||||
every { hatchPetUseCase.observable(capture(slot)) } returns mockk(relaxed = true)
|
||||
every { hatchPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true)
|
||||
fragment.itemType = "eggs"
|
||||
launchFragment()
|
||||
screen {
|
||||
|
|
@ -142,7 +142,7 @@ internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment,
|
|||
childWith<ItemItem> { withDescendant { withText("Wolf") } }.click()
|
||||
KView { withText(R.string.hatch_with_potion) }.click()
|
||||
KView { withText("Shade") }.click()
|
||||
verify { hatchPetUseCase.observable(any()) }
|
||||
verify { hatchPetUseCase.callInteractor(any()) }
|
||||
slot.captured.egg.key shouldBe "Wolf"
|
||||
slot.captured.potion.key shouldBe "Shade"
|
||||
}
|
||||
|
|
@ -152,7 +152,7 @@ internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment,
|
|||
@Test
|
||||
fun canHatchPetWithPotions() {
|
||||
val slot = CapturingSlot<HatchPetUseCase.RequestValues>()
|
||||
every { hatchPetUseCase.observable(capture(slot)) } returns mockk(relaxed = true)
|
||||
every { hatchPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true)
|
||||
fragment.itemType = "hatchingPotions"
|
||||
launchFragment()
|
||||
screen {
|
||||
|
|
@ -160,7 +160,7 @@ internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment,
|
|||
childWith<ItemItem> { withDescendant { withText("Shade") } }.click()
|
||||
KView { withText(R.string.hatch_egg) }.click()
|
||||
KView { withText("Wolf") }.click()
|
||||
verify { hatchPetUseCase.observable(any()) }
|
||||
verify { hatchPetUseCase.callInteractor(any()) }
|
||||
slot.captured.egg.key shouldBe "Wolf"
|
||||
slot.captured.potion.key shouldBe "Shade"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ internal class PetDetailRecyclerFragmentTest :
|
|||
@Test
|
||||
fun canFeedPet() {
|
||||
val slot = CapturingSlot<FeedPetUseCase.RequestValues>()
|
||||
every { feedPetUseCase.observable(capture(slot)) } returns mockk(relaxed = true)
|
||||
every { feedPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true)
|
||||
every {
|
||||
inventoryRepository.getPets(
|
||||
any(),
|
||||
|
|
@ -92,7 +92,7 @@ internal class PetDetailRecyclerFragmentTest :
|
|||
childWith<PetItem> { withContentDescription("Skeleton Cactus") }.click()
|
||||
KView { withText(R.string.feed) }.click()
|
||||
KView { withText("Meat") }.click()
|
||||
verify { feedPetUseCase.observable(any()) }
|
||||
verify { feedPetUseCase.callInteractor(any()) }
|
||||
slot.captured.pet.key shouldBe "Cactus-Skeleton"
|
||||
slot.captured.food.key shouldBe "Meat"
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ internal class PetDetailRecyclerFragmentTest :
|
|||
@Test
|
||||
fun canUseSaddle() {
|
||||
val slot = CapturingSlot<FeedPetUseCase.RequestValues>()
|
||||
every { feedPetUseCase.observable(capture(slot)) } returns mockk(relaxed = true)
|
||||
every { feedPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true)
|
||||
every {
|
||||
inventoryRepository.getPets(
|
||||
any(),
|
||||
|
|
@ -122,7 +122,7 @@ internal class PetDetailRecyclerFragmentTest :
|
|||
recycler {
|
||||
childWith<PetItem> { withContentDescription("Shade Fox") }.click()
|
||||
KView { withText(R.string.use_saddle) }.click()
|
||||
verify { feedPetUseCase.observable(any()) }
|
||||
verify { feedPetUseCase.callInteractor(any()) }
|
||||
slot.captured.pet.key shouldBe "Fox-Shade"
|
||||
slot.captured.food.key shouldBe "Saddle"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import com.habitrpg.shared.habitica.models.responses.FeedResponse
|
|||
import com.habitrpg.shared.habitica.models.responses.Status
|
||||
import com.habitrpg.shared.habitica.models.responses.TaskDirectionData
|
||||
import com.habitrpg.shared.habitica.models.responses.VerifyUsernameResponse
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.GET
|
||||
|
|
@ -60,7 +59,7 @@ interface ApiService {
|
|||
@GET("inbox/messages")
|
||||
suspend fun getInboxMessages(@Query("conversation") uuid: String, @Query("page") page: Int): HabitResponse<List<ChatMessage>>
|
||||
@GET("inbox/conversations")
|
||||
fun getInboxConversations(): Flowable<HabitResponse<List<InboxConversation>>>
|
||||
suspend fun getInboxConversations(): HabitResponse<List<InboxConversation>>
|
||||
|
||||
@GET("tasks/user")
|
||||
suspend fun getTasks(): HabitResponse<TaskList>
|
||||
|
|
@ -75,13 +74,13 @@ interface ApiService {
|
|||
suspend fun updateUser(@Body updateDictionary: Map<String, Any>): HabitResponse<User>
|
||||
|
||||
@PUT("user/")
|
||||
fun registrationLanguage(@Header("Accept-Language") registrationLanguage: String): Flowable<HabitResponse<User>>
|
||||
suspend fun registrationLanguage(@Header("Accept-Language") registrationLanguage: String): HabitResponse<User>
|
||||
|
||||
@GET("user/in-app-rewards")
|
||||
suspend fun retrieveInAppRewards(): HabitResponse<List<ShopItem>>
|
||||
|
||||
@POST("user/equip/{type}/{key}")
|
||||
fun equipItem(@Path("type") type: String, @Path("key") itemKey: String): Flowable<HabitResponse<Items>>
|
||||
suspend fun equipItem(@Path("type") type: String, @Path("key") itemKey: String): HabitResponse<Items>
|
||||
|
||||
@POST("user/buy/{key}")
|
||||
suspend fun buyItem(@Path("key") itemKey: String, @Body quantity: Map<String, Int>): HabitResponse<BuyResponse>
|
||||
|
|
@ -106,72 +105,72 @@ interface ApiService {
|
|||
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>>
|
||||
suspend fun sellItem(@Path("type") itemType: String, @Path("key") itemKey: String): HabitResponse<User>
|
||||
|
||||
@POST("user/feed/{pet}/{food}")
|
||||
fun feedPet(@Path("pet") petKey: String, @Path("food") foodKey: String): Flowable<HabitResponse<FeedResponse>>
|
||||
suspend fun feedPet(@Path("pet") petKey: String, @Path("food") foodKey: String): HabitResponse<FeedResponse>
|
||||
|
||||
@POST("user/hatch/{egg}/{hatchingPotion}")
|
||||
fun hatchPet(@Path("egg") eggKey: String, @Path("hatchingPotion") hatchingPotionKey: String): Flowable<HabitResponse<Items>>
|
||||
suspend fun hatchPet(@Path("egg") eggKey: String, @Path("hatchingPotion") hatchingPotionKey: String): HabitResponse<Items>
|
||||
|
||||
@GET("tasks/user")
|
||||
fun getTasks(@Query("type") type: String): Flowable<HabitResponse<TaskList>>
|
||||
suspend fun getTasks(@Query("type") type: String): HabitResponse<TaskList>
|
||||
|
||||
@GET("tasks/user")
|
||||
fun getTasks(@Query("type") type: String, @Query("dueDate") dueDate: String): Flowable<HabitResponse<TaskList>>
|
||||
suspend fun getTasks(@Query("type") type: String, @Query("dueDate") dueDate: String): HabitResponse<TaskList>
|
||||
|
||||
@POST("user/unlock")
|
||||
suspend fun unlockPath(@Query("path") path: String): HabitResponse<UnlockResponse>
|
||||
|
||||
@GET("tasks/{id}")
|
||||
fun getTask(@Path("id") id: String): Flowable<HabitResponse<Task>>
|
||||
suspend fun getTask(@Path("id") id: String): HabitResponse<Task>
|
||||
|
||||
@POST("tasks/{id}/score/{direction}")
|
||||
suspend fun postTaskDirection(@Path("id") id: String, @Path("direction") direction: String): HabitResponse<TaskDirectionData>
|
||||
@POST("tasks/bulk-score")
|
||||
fun bulkScoreTasks(@Body data: List<Map<String, String>>): Flowable<HabitResponse<BulkTaskScoringData>>
|
||||
suspend fun bulkScoreTasks(@Body data: List<Map<String, String>>): HabitResponse<BulkTaskScoringData>
|
||||
|
||||
@POST("tasks/{id}/move/to/{position}")
|
||||
fun postTaskNewPosition(@Path("id") id: String, @Path("position") position: Int): Flowable<HabitResponse<List<String>>>
|
||||
suspend fun postTaskNewPosition(@Path("id") id: String, @Path("position") position: Int): HabitResponse<List<String>>
|
||||
|
||||
@POST("tasks/{taskId}/checklist/{itemId}/score")
|
||||
suspend fun scoreChecklistItem(@Path("taskId") taskId: String, @Path("itemId") itemId: String): HabitResponse<Task>
|
||||
|
||||
@POST("tasks/user")
|
||||
fun createTask(@Body item: Task): Flowable<HabitResponse<Task>>
|
||||
suspend fun createTask(@Body item: Task): HabitResponse<Task>
|
||||
|
||||
@POST("tasks/user")
|
||||
fun createTasks(@Body tasks: List<Task>): Flowable<HabitResponse<List<Task>>>
|
||||
suspend fun createTasks(@Body tasks: List<Task>): HabitResponse<List<Task>>
|
||||
|
||||
@PUT("tasks/{id}")
|
||||
fun updateTask(@Path("id") id: String, @Body item: Task): Flowable<HabitResponse<Task>>
|
||||
suspend fun updateTask(@Path("id") id: String, @Body item: Task): HabitResponse<Task>
|
||||
|
||||
@DELETE("tasks/{id}")
|
||||
fun deleteTask(@Path("id") id: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun deleteTask(@Path("id") id: String): HabitResponse<Void>
|
||||
|
||||
@POST("tags")
|
||||
fun createTag(@Body tag: Tag): Flowable<HabitResponse<Tag>>
|
||||
suspend fun createTag(@Body tag: Tag): HabitResponse<Tag>
|
||||
|
||||
@PUT("tags/{id}")
|
||||
fun updateTag(@Path("id") id: String, @Body tag: Tag): Flowable<HabitResponse<Tag>>
|
||||
suspend fun updateTag(@Path("id") id: String, @Body tag: Tag): HabitResponse<Tag>
|
||||
|
||||
@DELETE("tags/{id}")
|
||||
fun deleteTag(@Path("id") id: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun deleteTag(@Path("id") id: String): HabitResponse<Void>
|
||||
|
||||
@POST("user/auth/local/register")
|
||||
fun registerUser(@Body auth: UserAuth): Flowable<HabitResponse<UserAuthResponse>>
|
||||
suspend fun registerUser(@Body auth: UserAuth): HabitResponse<UserAuthResponse>
|
||||
|
||||
@POST("user/auth/local/login")
|
||||
fun connectLocal(@Body auth: UserAuth): Flowable<HabitResponse<UserAuthResponse>>
|
||||
suspend fun connectLocal(@Body auth: UserAuth): HabitResponse<UserAuthResponse>
|
||||
|
||||
@POST("user/auth/social")
|
||||
fun connectSocial(@Body auth: UserAuthSocial): Flowable<HabitResponse<UserAuthResponse>>
|
||||
suspend fun connectSocial(@Body auth: UserAuthSocial): HabitResponse<UserAuthResponse>
|
||||
|
||||
@DELETE("user/auth/social/{network}")
|
||||
fun disconnectSocial(@Path("network") network: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun disconnectSocial(@Path("network") network: String): HabitResponse<Void>
|
||||
|
||||
@POST("user/auth/apple")
|
||||
fun loginApple(@Body auth: Map<String, Any>): Flowable<HabitResponse<UserAuthResponse>>
|
||||
suspend fun loginApple(@Body auth: Map<String, Any>): HabitResponse<UserAuthResponse>
|
||||
|
||||
@POST("user/sleep")
|
||||
suspend fun sleep(): HabitResponse<Boolean>
|
||||
|
|
@ -199,12 +198,12 @@ interface ApiService {
|
|||
suspend fun disableClasses(): HabitResponse<User>
|
||||
|
||||
@POST("user/mark-pms-read")
|
||||
fun markPrivateMessagesRead(): Flowable<Void>
|
||||
suspend fun markPrivateMessagesRead(): Void
|
||||
|
||||
/* Group API */
|
||||
|
||||
@GET("groups")
|
||||
fun listGroups(@Query("type") type: String): Flowable<HabitResponse<List<Group>>>
|
||||
suspend fun listGroups(@Query("type") type: String): HabitResponse<List<Group>>
|
||||
|
||||
@GET("groups/{gid}")
|
||||
suspend fun getGroup(@Path("gid") groupId: String): HabitResponse<Group>
|
||||
|
|
@ -228,13 +227,13 @@ interface ApiService {
|
|||
suspend fun leaveGroup(@Path("gid") groupId: String, @Query("keepChallenges") keepChallenges: String): HabitResponse<Void>
|
||||
|
||||
@POST("groups/{gid}/chat")
|
||||
fun postGroupChat(@Path("gid") groupId: String, @Body message: Map<String, String>): Flowable<HabitResponse<PostChatMessageResult>>
|
||||
suspend fun postGroupChat(@Path("gid") groupId: String, @Body message: Map<String, String>): HabitResponse<PostChatMessageResult>
|
||||
|
||||
@DELETE("groups/{gid}/chat/{messageId}")
|
||||
fun deleteMessage(@Path("gid") groupId: String, @Path("messageId") messageId: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun deleteMessage(@Path("gid") groupId: String, @Path("messageId") messageId: String): HabitResponse<Void>
|
||||
|
||||
@DELETE("inbox/messages/{messageId}")
|
||||
fun deleteInboxMessage(@Path("messageId") messageId: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun deleteInboxMessage(@Path("messageId") messageId: String): HabitResponse<Void>
|
||||
|
||||
@GET("groups/{gid}/members")
|
||||
suspend fun getGroupMembers(
|
||||
|
|
@ -251,59 +250,59 @@ interface ApiService {
|
|||
|
||||
// Like returns the full chat list
|
||||
@POST("groups/{gid}/chat/{mid}/like")
|
||||
fun likeMessage(@Path("gid") groupId: String, @Path("mid") mid: String): Flowable<HabitResponse<ChatMessage>>
|
||||
suspend fun likeMessage(@Path("gid") groupId: String, @Path("mid") mid: String): HabitResponse<ChatMessage>
|
||||
|
||||
@POST("groups/{gid}/chat/{mid}/flag")
|
||||
fun flagMessage(
|
||||
suspend fun flagMessage(
|
||||
@Path("gid") groupId: String,
|
||||
@Path("mid") mid: String,
|
||||
@Body data: Map<String, String>
|
||||
): Flowable<HabitResponse<Void>>
|
||||
): HabitResponse<Void>
|
||||
|
||||
@POST("groups/{gid}/chat/seen")
|
||||
fun seenMessages(@Path("gid") groupId: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun seenMessages(@Path("gid") groupId: String): HabitResponse<Void>
|
||||
|
||||
@POST("groups/{gid}/invite")
|
||||
fun inviteToGroup(@Path("gid") groupId: String, @Body inviteData: Map<String, Any>): Flowable<HabitResponse<List<Void>>>
|
||||
suspend fun inviteToGroup(@Path("gid") groupId: String, @Body inviteData: Map<String, Any>): HabitResponse<List<Void>>
|
||||
|
||||
@POST("groups/{gid}/reject-invite")
|
||||
fun rejectGroupInvite(@Path("gid") groupId: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun rejectGroupInvite(@Path("gid") groupId: String): HabitResponse<Void>
|
||||
|
||||
@POST("groups/{gid}/quests/accept")
|
||||
fun acceptQuest(@Path("gid") groupId: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun acceptQuest(@Path("gid") groupId: String): HabitResponse<Void>
|
||||
|
||||
@POST("groups/{gid}/quests/reject")
|
||||
fun rejectQuest(@Path("gid") groupId: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun rejectQuest(@Path("gid") groupId: String): HabitResponse<Void>
|
||||
|
||||
@POST("groups/{gid}/quests/cancel")
|
||||
fun cancelQuest(@Path("gid") groupId: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun cancelQuest(@Path("gid") groupId: String): HabitResponse<Void>
|
||||
|
||||
@POST("groups/{gid}/quests/force-start")
|
||||
fun forceStartQuest(@Path("gid") groupId: String, @Body group: Group): Flowable<HabitResponse<Quest>>
|
||||
suspend fun forceStartQuest(@Path("gid") groupId: String, @Body group: Group): HabitResponse<Quest>
|
||||
|
||||
@POST("groups/{gid}/quests/invite/{questKey}")
|
||||
fun inviteToQuest(@Path("gid") groupId: String, @Path("questKey") questKey: String): Flowable<HabitResponse<Quest>>
|
||||
suspend fun inviteToQuest(@Path("gid") groupId: String, @Path("questKey") questKey: String): HabitResponse<Quest>
|
||||
|
||||
@POST("groups/{gid}/quests/abort")
|
||||
fun abortQuest(@Path("gid") groupId: String): Flowable<HabitResponse<Quest>>
|
||||
suspend fun abortQuest(@Path("gid") groupId: String): HabitResponse<Quest>
|
||||
|
||||
@POST("groups/{gid}/quests/leave")
|
||||
fun leaveQuest(@Path("gid") groupId: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun leaveQuest(@Path("gid") groupId: String): HabitResponse<Void>
|
||||
|
||||
@POST("/iap/android/verify")
|
||||
fun validatePurchase(@Body request: PurchaseValidationRequest): Flowable<HabitResponse<PurchaseValidationResult>>
|
||||
suspend fun validatePurchase(@Body request: PurchaseValidationRequest): HabitResponse<PurchaseValidationResult>
|
||||
|
||||
@POST("/iap/android/subscribe")
|
||||
fun validateSubscription(@Body request: PurchaseValidationRequest): Flowable<HabitResponse<Void>>
|
||||
suspend fun validateSubscription(@Body request: PurchaseValidationRequest): HabitResponse<Void>
|
||||
|
||||
@GET("/iap/android/subscribe/cancel")
|
||||
suspend fun cancelSubscription(): HabitResponse<Void>
|
||||
|
||||
@POST("/iap/android/norenew-subscribe")
|
||||
fun validateNoRenewSubscription(@Body request: PurchaseValidationRequest): Flowable<HabitResponse<Void>>
|
||||
suspend fun validateNoRenewSubscription(@Body request: PurchaseValidationRequest): HabitResponse<Void>
|
||||
|
||||
@POST("user/custom-day-start")
|
||||
fun changeCustomDayStart(@Body updateObject: Map<String, Any>): Flowable<HabitResponse<User>>
|
||||
suspend fun changeCustomDayStart(@Body updateObject: Map<String, Any>): HabitResponse<User>
|
||||
|
||||
// Members URL
|
||||
@GET("members/{mid}")
|
||||
|
|
@ -313,128 +312,128 @@ interface ApiService {
|
|||
suspend fun getMemberWithUsername(@Path("username") username: String): HabitResponse<Member>
|
||||
|
||||
@GET("members/{mid}/achievements")
|
||||
fun getMemberAchievements(@Path("mid") memberId: String, @Query("lang") language: String?): Flowable<HabitResponse<List<Achievement>>>
|
||||
suspend fun getMemberAchievements(@Path("mid") memberId: String, @Query("lang") language: String?): HabitResponse<List<Achievement>>
|
||||
|
||||
@POST("members/send-private-message")
|
||||
suspend fun postPrivateMessage(@Body messageDetails: Map<String, String>): HabitResponse<PostChatMessageResult>
|
||||
|
||||
@GET("members/find/{username}")
|
||||
fun findUsernames(
|
||||
suspend fun findUsernames(
|
||||
@Path("username") username: String,
|
||||
@Query("context") context: String?,
|
||||
@Query("id") id: String?
|
||||
): Flowable<HabitResponse<List<FindUsernameResult>>>
|
||||
): HabitResponse<List<FindUsernameResult>>
|
||||
|
||||
@POST("members/flag-private-message/{mid}")
|
||||
fun flagInboxMessage(@Path("mid") mid: String, @Body data: Map<String, String>): Flowable<HabitResponse<Void>>
|
||||
suspend fun flagInboxMessage(@Path("mid") mid: String, @Body data: Map<String, String>): HabitResponse<Void>
|
||||
|
||||
@GET("shops/{identifier}")
|
||||
fun retrieveShopInventory(@Path("identifier") identifier: String, @Query("lang") language: String?): Flowable<HabitResponse<Shop>>
|
||||
suspend fun retrieveShopInventory(@Path("identifier") identifier: String, @Query("lang") language: String?): HabitResponse<Shop>
|
||||
|
||||
@GET("shops/market-gear")
|
||||
fun retrieveMarketGear(@Query("lang") language: String?): Flowable<HabitResponse<Shop>>
|
||||
suspend fun retrieveMarketGear(@Query("lang") language: String?): HabitResponse<Shop>
|
||||
|
||||
// Push notifications
|
||||
@POST("user/push-devices")
|
||||
fun addPushDevice(@Body pushDeviceData: Map<String, String>): Flowable<HabitResponse<List<Void>>>
|
||||
suspend fun addPushDevice(@Body pushDeviceData: Map<String, String>): HabitResponse<List<Void>>
|
||||
|
||||
@DELETE("user/push-devices/{regId}")
|
||||
fun deletePushDevice(@Path("regId") regId: String): Flowable<HabitResponse<List<Void>>>
|
||||
suspend fun deletePushDevice(@Path("regId") regId: String): HabitResponse<List<Void>>
|
||||
|
||||
/* challenges api */
|
||||
|
||||
@GET("challenges/user")
|
||||
fun getUserChallenges(@Query("page") page: Int?, @Query("member") memberOnly: Boolean): Flowable<HabitResponse<List<Challenge>>>
|
||||
suspend fun getUserChallenges(@Query("page") page: Int?, @Query("member") memberOnly: Boolean): HabitResponse<List<Challenge>>
|
||||
|
||||
@GET("challenges/user")
|
||||
fun getUserChallenges(@Query("page") page: Int?): Flowable<HabitResponse<List<Challenge>>>
|
||||
suspend fun getUserChallenges(@Query("page") page: Int?): HabitResponse<List<Challenge>>
|
||||
|
||||
@GET("tasks/challenge/{challengeId}")
|
||||
fun getChallengeTasks(@Path("challengeId") challengeId: String): Flowable<HabitResponse<TaskList>>
|
||||
suspend fun getChallengeTasks(@Path("challengeId") challengeId: String): HabitResponse<TaskList>
|
||||
|
||||
@GET("challenges/{challengeId}")
|
||||
fun getChallenge(@Path("challengeId") challengeId: String): Flowable<HabitResponse<Challenge>>
|
||||
suspend fun getChallenge(@Path("challengeId") challengeId: String): HabitResponse<Challenge>
|
||||
|
||||
@POST("challenges/{challengeId}/join")
|
||||
fun joinChallenge(@Path("challengeId") challengeId: String): Flowable<HabitResponse<Challenge>>
|
||||
suspend fun joinChallenge(@Path("challengeId") challengeId: String): HabitResponse<Challenge>
|
||||
|
||||
@POST("challenges/{challengeId}/leave")
|
||||
fun leaveChallenge(@Path("challengeId") challengeId: String, @Body body: LeaveChallengeBody): Flowable<HabitResponse<Void>>
|
||||
suspend fun leaveChallenge(@Path("challengeId") challengeId: String, @Body body: LeaveChallengeBody): HabitResponse<Void>
|
||||
|
||||
@POST("challenges")
|
||||
fun createChallenge(@Body challenge: Challenge): Flowable<HabitResponse<Challenge>>
|
||||
suspend fun createChallenge(@Body challenge: Challenge): HabitResponse<Challenge>
|
||||
|
||||
@POST("tasks/challenge/{challengeId}")
|
||||
fun createChallengeTasks(@Path("challengeId") challengeId: String, @Body tasks: List<Task>): Flowable<HabitResponse<List<Task>>>
|
||||
suspend fun createChallengeTasks(@Path("challengeId") challengeId: String, @Body tasks: List<Task>): HabitResponse<List<Task>>
|
||||
|
||||
@POST("tasks/challenge/{challengeId}")
|
||||
fun createChallengeTask(@Path("challengeId") challengeId: String, @Body task: Task): Flowable<HabitResponse<Task>>
|
||||
suspend fun createChallengeTask(@Path("challengeId") challengeId: String, @Body task: Task): HabitResponse<Task>
|
||||
|
||||
@PUT("challenges/{challengeId}")
|
||||
fun updateChallenge(@Path("challengeId") challengeId: String, @Body challenge: Challenge): Flowable<HabitResponse<Challenge>>
|
||||
suspend fun updateChallenge(@Path("challengeId") challengeId: String, @Body challenge: Challenge): HabitResponse<Challenge>
|
||||
|
||||
@DELETE("challenges/{challengeId}")
|
||||
fun deleteChallenge(@Path("challengeId") challengeId: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun deleteChallenge(@Path("challengeId") challengeId: String): HabitResponse<Void>
|
||||
|
||||
// DEBUG: These calls only work on a local development server
|
||||
|
||||
@POST("debug/add-ten-gems")
|
||||
fun debugAddTenGems(): Flowable<HabitResponse<Void>>
|
||||
suspend fun debugAddTenGems(): HabitResponse<Void>
|
||||
|
||||
// Notifications
|
||||
@POST("notifications/{notificationId}/read")
|
||||
fun readNotification(@Path("notificationId") notificationId: String): Flowable<HabitResponse<List<Any>>>
|
||||
suspend fun readNotification(@Path("notificationId") notificationId: String): HabitResponse<List<Any>>
|
||||
|
||||
@POST("notifications/read")
|
||||
fun readNotifications(@Body notificationIds: Map<String, List<String>>): Flowable<HabitResponse<List<Any>>>
|
||||
suspend fun readNotifications(@Body notificationIds: Map<String, List<String>>): HabitResponse<List<Any>>
|
||||
|
||||
@POST("notifications/see")
|
||||
fun seeNotifications(@Body notificationIds: Map<String, List<String>>): Flowable<HabitResponse<List<Any>>>
|
||||
suspend fun seeNotifications(@Body notificationIds: Map<String, List<String>>): HabitResponse<List<Any>>
|
||||
|
||||
@POST("user/open-mystery-item")
|
||||
fun openMysteryItem(): Flowable<HabitResponse<Equipment>>
|
||||
suspend fun openMysteryItem(): HabitResponse<Equipment>
|
||||
|
||||
@POST("cron")
|
||||
fun runCron(): Flowable<HabitResponse<Void>>
|
||||
suspend fun runCron(): HabitResponse<Void>
|
||||
|
||||
@POST("user/reset")
|
||||
fun resetAccount(): Flowable<HabitResponse<Void>>
|
||||
suspend fun resetAccount(): HabitResponse<Void>
|
||||
|
||||
@HTTP(method = "DELETE", path = "user", hasBody = true)
|
||||
fun deleteAccount(@Body body: Map<String, String>): Flowable<HabitResponse<Void>>
|
||||
suspend fun deleteAccount(@Body body: Map<String, String>): HabitResponse<Void>
|
||||
|
||||
@GET("user/toggle-pinned-item/{pinType}/{path}")
|
||||
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>>
|
||||
suspend fun sendPasswordResetEmail(@Body data: Map<String, String>): HabitResponse<Void>
|
||||
|
||||
@PUT("user/auth/update-username")
|
||||
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>>
|
||||
suspend fun verifyUsername(@Body data: Map<String, String>): HabitResponse<VerifyUsernameResponse>
|
||||
|
||||
@PUT("user/auth/update-email")
|
||||
fun updateEmail(@Body data: Map<String, String>): Flowable<HabitResponse<Void>>
|
||||
suspend fun updateEmail(@Body data: Map<String, String>): HabitResponse<Void>
|
||||
|
||||
@PUT("user/auth/update-password")
|
||||
fun updatePassword(@Body data: Map<String, String>): Flowable<HabitResponse<Void>>
|
||||
suspend fun updatePassword(@Body data: Map<String, String>): HabitResponse<Void>
|
||||
|
||||
@POST("user/allocate")
|
||||
fun allocatePoint(@Query("stat") stat: String): Flowable<HabitResponse<Stats>>
|
||||
suspend fun allocatePoint(@Query("stat") stat: String): HabitResponse<Stats>
|
||||
|
||||
@POST("user/allocate-bulk")
|
||||
fun bulkAllocatePoints(@Body stats: Map<String, Map<String, Int>>): Flowable<HabitResponse<Stats>>
|
||||
suspend fun bulkAllocatePoints(@Body stats: Map<String, Map<String, Int>>): HabitResponse<Stats>
|
||||
|
||||
@POST("members/transfer-gems")
|
||||
fun transferGems(@Body data: Map<String, Any>): Flowable<HabitResponse<Void>>
|
||||
suspend fun transferGems(@Body data: Map<String, Any>): HabitResponse<Void>
|
||||
|
||||
@POST("tasks/unlink-all/{challengeID}")
|
||||
fun unlinkAllTasks(@Path("challengeID") challengeID: String?, @Query("keep") keepOption: String): Flowable<HabitResponse<Void>>
|
||||
suspend fun unlinkAllTasks(@Path("challengeID") challengeID: String?, @Query("keep") keepOption: String): HabitResponse<Void>
|
||||
|
||||
@POST("user/block/{userID}")
|
||||
fun blockMember(@Path("userID") userID: String): Flowable<HabitResponse<List<String>>>
|
||||
suspend fun blockMember(@Path("userID") userID: String): HabitResponse<List<String>>
|
||||
|
||||
@POST("user/reroll")
|
||||
suspend fun reroll(): HabitResponse<User>
|
||||
|
|
@ -442,7 +441,7 @@ interface ApiService {
|
|||
// Team Plans
|
||||
|
||||
@GET("group-plans")
|
||||
fun getTeamPlans(): Flowable<HabitResponse<List<TeamPlan>>>
|
||||
suspend fun getTeamPlans(): HabitResponse<List<TeamPlan>>
|
||||
|
||||
@GET("tasks/group/{groupID}")
|
||||
suspend fun getTeamPlanTasks(@Path("groupID") groupId: String): HabitResponse<TaskList>
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
package com.habitrpg.android.habitica.api;
|
||||
|
||||
import com.habitrpg.shared.habitica.models.responses.MaintenanceResponse;
|
||||
|
||||
import io.reactivex.rxjava3.core.Flowable;
|
||||
import retrofit2.http.GET;
|
||||
|
||||
public interface MaintenanceApiService {
|
||||
|
||||
@GET("maintenance-android.json")
|
||||
Flowable<MaintenanceResponse> getMaintenanceStatus();
|
||||
|
||||
@GET("deprecation-android.json")
|
||||
Flowable<MaintenanceResponse> getDepricationStatus();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.habitrpg.android.habitica.api
|
||||
|
||||
import com.habitrpg.shared.habitica.models.responses.MaintenanceResponse
|
||||
import retrofit2.http.GET
|
||||
|
||||
interface MaintenanceApiService {
|
||||
@GET("maintenance-android.json")
|
||||
suspend fun getMaintenanceStatus(): MaintenanceResponse?
|
||||
|
||||
@GET("deprecation-android.json")
|
||||
suspend fun getDepricationStatus(): MaintenanceResponse?
|
||||
}
|
||||
|
|
@ -40,7 +40,6 @@ import com.habitrpg.android.habitica.ui.activities.SkillTasksActivity;
|
|||
import com.habitrpg.android.habitica.ui.activities.TaskFormActivity;
|
||||
import com.habitrpg.android.habitica.ui.activities.TaskSummaryActivity;
|
||||
import com.habitrpg.android.habitica.ui.activities.TaskSummaryViewModel;
|
||||
import com.habitrpg.android.habitica.ui.activities.VerifyUsernameActivity;
|
||||
import com.habitrpg.android.habitica.ui.adapter.social.challenges.ChallengeTasksRecyclerViewAdapter;
|
||||
import com.habitrpg.android.habitica.ui.adapter.tasks.DailiesRecyclerViewHolder;
|
||||
import com.habitrpg.android.habitica.ui.adapter.tasks.HabitsRecyclerViewAdapter;
|
||||
|
|
@ -293,8 +292,6 @@ public interface UserComponent {
|
|||
|
||||
void inject(ChallengeDetailFragment challengeDetailFragment);
|
||||
|
||||
void inject(VerifyUsernameActivity verifyUsernameActivity);
|
||||
|
||||
void inject(GroupViewModel viewModel);
|
||||
|
||||
void inject(NotificationsViewModel viewModel);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import com.habitrpg.android.habitica.models.user.Items
|
|||
import com.habitrpg.android.habitica.models.user.Stats
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.common.habitica.api.HostConfig
|
||||
import com.habitrpg.common.habitica.models.HabitResponse
|
||||
import com.habitrpg.common.habitica.models.PurchaseValidationRequest
|
||||
import com.habitrpg.common.habitica.models.PurchaseValidationResult
|
||||
import com.habitrpg.common.habitica.models.auth.UserAuthResponse
|
||||
|
|
@ -36,8 +35,6 @@ import com.habitrpg.shared.habitica.models.responses.FeedResponse
|
|||
import com.habitrpg.shared.habitica.models.responses.Status
|
||||
import com.habitrpg.shared.habitica.models.responses.TaskDirectionData
|
||||
import com.habitrpg.shared.habitica.models.responses.VerifyUsernameResponse
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.FlowableTransformer
|
||||
import retrofit2.HttpException
|
||||
|
||||
interface ApiClient {
|
||||
|
|
@ -52,19 +49,19 @@ interface ApiClient {
|
|||
|
||||
/* challenges api */
|
||||
|
||||
fun getUserChallenges(page: Int, memberOnly: Boolean): Flowable<List<Challenge>>
|
||||
suspend fun getUserChallenges(page: Int, memberOnly: Boolean): List<Challenge>?
|
||||
|
||||
suspend fun getWorldState(): WorldState?
|
||||
fun setLanguageCode(languageCode: String)
|
||||
var languageCode: String?
|
||||
suspend fun getContent(language: String? = null): ContentResult?
|
||||
|
||||
suspend fun updateUser(updateDictionary: Map<String, Any>): User?
|
||||
|
||||
fun registrationLanguage(registrationLanguage: String): Flowable<User>
|
||||
suspend fun registrationLanguage(registrationLanguage: String): User?
|
||||
|
||||
suspend fun retrieveInAppRewards(): List<ShopItem>?
|
||||
|
||||
fun equipItem(type: String, itemKey: String): Flowable<Items>
|
||||
suspend fun equipItem(type: String, itemKey: String): Items?
|
||||
|
||||
suspend fun buyItem(itemKey: String, purchaseQuantity: Int): BuyResponse?
|
||||
|
||||
|
|
@ -76,51 +73,51 @@ interface ApiClient {
|
|||
|
||||
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 validateSubscription(request: PurchaseValidationRequest): Any?
|
||||
suspend fun validateNoRenewSubscription(request: PurchaseValidationRequest): Any?
|
||||
suspend fun cancelSubscription(): Void?
|
||||
|
||||
fun sellItem(itemType: String, itemKey: String): Flowable<User>
|
||||
suspend fun sellItem(itemType: String, itemKey: String): User?
|
||||
|
||||
fun feedPet(petKey: String, foodKey: String): Flowable<FeedResponse>
|
||||
suspend fun feedPet(petKey: String, foodKey: String): FeedResponse?
|
||||
|
||||
fun hatchPet(eggKey: String, hatchingPotionKey: String): Flowable<Items>
|
||||
fun getTasks(type: String): Flowable<TaskList>
|
||||
fun getTasks(type: String, dueDate: String): Flowable<TaskList>
|
||||
suspend fun hatchPet(eggKey: String, hatchingPotionKey: String): Items?
|
||||
suspend fun getTasks(type: String): TaskList?
|
||||
suspend fun getTasks(type: String, dueDate: String): TaskList?
|
||||
|
||||
suspend fun unlockPath(path: String): UnlockResponse?
|
||||
|
||||
fun getTask(id: String): Flowable<Task>
|
||||
suspend fun getTask(id: String): Task?
|
||||
|
||||
suspend fun postTaskDirection(id: String, direction: String): TaskDirectionData?
|
||||
fun bulkScoreTasks(data: List<Map<String, String>>): Flowable<BulkTaskScoringData>
|
||||
suspend fun bulkScoreTasks(data: List<Map<String, String>>): BulkTaskScoringData?
|
||||
|
||||
fun postTaskNewPosition(id: String, position: Int): Flowable<List<String>>
|
||||
suspend fun postTaskNewPosition(id: String, position: Int): List<String>?
|
||||
|
||||
suspend fun scoreChecklistItem(taskId: String, itemId: String): Task?
|
||||
|
||||
fun createTask(item: Task): Flowable<Task>
|
||||
suspend fun createTask(item: Task): Task?
|
||||
|
||||
fun createTasks(tasks: List<Task>): Flowable<List<Task>>
|
||||
suspend fun createTasks(tasks: List<Task>): List<Task>?
|
||||
|
||||
fun updateTask(id: String, item: Task): Flowable<Task>
|
||||
suspend fun updateTask(id: String, item: Task): Task?
|
||||
|
||||
fun deleteTask(id: String): Flowable<Void>
|
||||
suspend fun deleteTask(id: String): Void?
|
||||
|
||||
fun createTag(tag: Tag): Flowable<Tag>
|
||||
suspend fun createTag(tag: Tag): Tag?
|
||||
|
||||
fun updateTag(id: String, tag: Tag): Flowable<Tag>
|
||||
suspend fun updateTag(id: String, tag: Tag): Tag?
|
||||
|
||||
fun deleteTag(id: String): Flowable<Void>
|
||||
suspend fun deleteTag(id: String): Void?
|
||||
|
||||
fun registerUser(username: String, email: String, password: String, confirmPassword: String): Flowable<UserAuthResponse>
|
||||
suspend fun registerUser(username: String, email: String, password: String, confirmPassword: String): UserAuthResponse?
|
||||
|
||||
fun connectUser(username: String, password: String): Flowable<UserAuthResponse>
|
||||
suspend fun connectUser(username: String, password: String): UserAuthResponse?
|
||||
|
||||
fun connectSocial(network: String, userId: String, accessToken: String): Flowable<UserAuthResponse>
|
||||
fun disconnectSocial(network: String): Flowable<Void>
|
||||
suspend fun connectSocial(network: String, userId: String, accessToken: String): UserAuthResponse?
|
||||
suspend fun disconnectSocial(network: String): Void?
|
||||
|
||||
fun loginApple(authToken: String): Flowable<UserAuthResponse>
|
||||
suspend fun loginApple(authToken: String): UserAuthResponse?
|
||||
|
||||
suspend fun sleep(): Boolean?
|
||||
suspend fun revive(): User?
|
||||
|
|
@ -133,11 +130,11 @@ interface ApiClient {
|
|||
|
||||
suspend fun disableClasses(): User?
|
||||
|
||||
fun markPrivateMessagesRead(): Flowable<Void>
|
||||
suspend fun markPrivateMessagesRead(): Void?
|
||||
|
||||
/* Group API */
|
||||
|
||||
fun listGroups(type: String): Flowable<List<Group>>
|
||||
suspend fun listGroups(type: String): List<Group>?
|
||||
|
||||
suspend fun getGroup(groupId: String): Group?
|
||||
|
||||
|
|
@ -151,83 +148,83 @@ interface ApiClient {
|
|||
|
||||
suspend fun leaveGroup(groupId: String, keepChallenges: String): Void?
|
||||
|
||||
fun postGroupChat(groupId: String, message: Map<String, String>): Flowable<PostChatMessageResult>
|
||||
suspend fun postGroupChat(groupId: String, message: Map<String, String>): PostChatMessageResult?
|
||||
|
||||
fun deleteMessage(groupId: String, messageId: String): Flowable<Void>
|
||||
fun deleteInboxMessage(id: String): Flowable<Void>
|
||||
suspend fun deleteMessage(groupId: String, messageId: String): Void?
|
||||
suspend fun deleteInboxMessage(id: String): Void?
|
||||
|
||||
suspend fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?): List<Member>?
|
||||
|
||||
suspend fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?, lastId: String): List<Member>?
|
||||
|
||||
// Like returns the full chat list
|
||||
fun likeMessage(groupId: String, mid: String): Flowable<ChatMessage>
|
||||
suspend fun likeMessage(groupId: String, mid: String): ChatMessage?
|
||||
|
||||
fun flagMessage(groupId: String, mid: String, data: MutableMap<String, String>): Flowable<Void>
|
||||
fun flagInboxMessage(mid: String, data: MutableMap<String, String>): Flowable<Void>
|
||||
suspend fun flagMessage(groupId: String, mid: String, data: MutableMap<String, String>): Void?
|
||||
suspend fun flagInboxMessage(mid: String, data: MutableMap<String, String>): Void?
|
||||
|
||||
fun seenMessages(groupId: String): Flowable<Void>
|
||||
suspend fun seenMessages(groupId: String): Void?
|
||||
|
||||
fun inviteToGroup(groupId: String, inviteData: Map<String, Any>): Flowable<List<Void>>
|
||||
suspend fun inviteToGroup(groupId: String, inviteData: Map<String, Any>): List<Void>?
|
||||
|
||||
fun rejectGroupInvite(groupId: String): Flowable<Void>
|
||||
suspend fun rejectGroupInvite(groupId: String): Void?
|
||||
|
||||
fun acceptQuest(groupId: String): Flowable<Void>
|
||||
suspend fun acceptQuest(groupId: String): Void?
|
||||
|
||||
fun rejectQuest(groupId: String): Flowable<Void>
|
||||
suspend fun rejectQuest(groupId: String): Void?
|
||||
|
||||
fun cancelQuest(groupId: String): Flowable<Void>
|
||||
suspend fun cancelQuest(groupId: String): Void?
|
||||
|
||||
fun forceStartQuest(groupId: String, group: Group): Flowable<Quest>
|
||||
suspend fun forceStartQuest(groupId: String, group: Group): Quest?
|
||||
|
||||
fun inviteToQuest(groupId: String, questKey: String): Flowable<Quest>
|
||||
suspend fun inviteToQuest(groupId: String, questKey: String): Quest?
|
||||
|
||||
fun abortQuest(groupId: String): Flowable<Quest>
|
||||
suspend fun abortQuest(groupId: String): Quest?
|
||||
|
||||
fun leaveQuest(groupId: String): Flowable<Void>
|
||||
suspend fun leaveQuest(groupId: String): Void?
|
||||
|
||||
fun validatePurchase(request: PurchaseValidationRequest): Flowable<PurchaseValidationResult>
|
||||
suspend fun validatePurchase(request: PurchaseValidationRequest): PurchaseValidationResult?
|
||||
|
||||
fun changeCustomDayStart(updateObject: Map<String, Any>): Flowable<User>
|
||||
suspend fun changeCustomDayStart(updateObject: Map<String, Any>): User?
|
||||
|
||||
// Members URL
|
||||
suspend fun getMember(memberId: String): Member?
|
||||
suspend fun getMemberWithUsername(username: String): Member?
|
||||
|
||||
fun getMemberAchievements(memberId: String): Flowable<List<Achievement>>
|
||||
suspend fun getMemberAchievements(memberId: String): List<Achievement>?
|
||||
|
||||
suspend fun postPrivateMessage(messageDetails: Map<String, String>): PostChatMessageResult?
|
||||
|
||||
fun retrieveShopIventory(identifier: String): Flowable<Shop>
|
||||
suspend fun retrieveShopIventory(identifier: String): Shop?
|
||||
|
||||
// Push notifications
|
||||
fun addPushDevice(pushDeviceData: Map<String, String>): Flowable<List<Void>>
|
||||
suspend fun addPushDevice(pushDeviceData: Map<String, String>): List<Void>?
|
||||
|
||||
fun deletePushDevice(regId: String): Flowable<List<Void>>
|
||||
suspend fun deletePushDevice(regId: String): List<Void>?
|
||||
|
||||
fun getChallengeTasks(challengeId: String): Flowable<TaskList>
|
||||
suspend fun getChallengeTasks(challengeId: String): TaskList?
|
||||
|
||||
fun getChallenge(challengeId: String): Flowable<Challenge>
|
||||
suspend fun getChallenge(challengeId: String): Challenge?
|
||||
|
||||
fun joinChallenge(challengeId: String): Flowable<Challenge>
|
||||
suspend fun joinChallenge(challengeId: String): Challenge?
|
||||
|
||||
fun leaveChallenge(challengeId: String, body: LeaveChallengeBody): Flowable<Void>
|
||||
suspend fun leaveChallenge(challengeId: String, body: LeaveChallengeBody): Void?
|
||||
|
||||
fun createChallenge(challenge: Challenge): Flowable<Challenge>
|
||||
suspend fun createChallenge(challenge: Challenge): Challenge?
|
||||
|
||||
fun createChallengeTasks(challengeId: String, tasks: List<Task>): Flowable<List<Task>>
|
||||
fun createChallengeTask(challengeId: String, task: Task): Flowable<Task>
|
||||
fun updateChallenge(challenge: Challenge): Flowable<Challenge>
|
||||
fun deleteChallenge(challengeId: String): Flowable<Void>
|
||||
suspend fun createChallengeTasks(challengeId: String, tasks: List<Task>): List<Task>?
|
||||
suspend fun createChallengeTask(challengeId: String, task: Task): Task?
|
||||
suspend fun updateChallenge(challenge: Challenge): Challenge?
|
||||
suspend fun deleteChallenge(challengeId: String): Void?
|
||||
|
||||
// DEBUG: These calls only work on a local development server
|
||||
|
||||
fun debugAddTenGems(): Flowable<Void>
|
||||
suspend fun debugAddTenGems(): Void?
|
||||
|
||||
// Notifications
|
||||
fun readNotification(notificationId: String): Flowable<List<Any>>
|
||||
fun readNotifications(notificationIds: Map<String, List<String>>): Flowable<List<Any>>
|
||||
fun seeNotifications(notificationIds: Map<String, List<String>>): Flowable<List<Any>>
|
||||
suspend fun readNotification(notificationId: String): List<Any>?
|
||||
suspend fun readNotifications(notificationIds: Map<String, List<String>>): List<Any>?
|
||||
suspend fun seeNotifications(notificationIds: Map<String, List<String>>): List<Any>?
|
||||
|
||||
fun getErrorResponse(throwable: HttpException): ErrorResponse
|
||||
|
||||
|
|
@ -237,42 +234,40 @@ interface ApiClient {
|
|||
|
||||
suspend fun retrieveUser(withTasks: Boolean = false): User?
|
||||
suspend fun retrieveInboxMessages(uuid: String, page: Int): List<ChatMessage>?
|
||||
fun retrieveInboxConversations(): Flowable<List<InboxConversation>>
|
||||
suspend fun retrieveInboxConversations(): List<InboxConversation>?
|
||||
|
||||
fun <T : Any> configureApiCallObserver(): FlowableTransformer<HabitResponse<T>, T>
|
||||
suspend fun openMysteryItem(): Equipment?
|
||||
|
||||
fun openMysteryItem(): Flowable<Equipment>
|
||||
|
||||
fun runCron(): Flowable<Void>
|
||||
suspend fun runCron(): Void?
|
||||
|
||||
suspend fun reroll(): User?
|
||||
|
||||
fun resetAccount(): Flowable<Void>
|
||||
fun deleteAccount(password: String): Flowable<Void>
|
||||
suspend fun resetAccount(): Void?
|
||||
suspend fun deleteAccount(password: String): Void?
|
||||
|
||||
suspend fun togglePinnedItem(pinType: String, path: String): Void?
|
||||
|
||||
fun sendPasswordResetEmail(email: String): Flowable<Void>
|
||||
suspend fun sendPasswordResetEmail(email: String): Void?
|
||||
|
||||
suspend fun updateLoginName(newLoginName: String, password: String): Void?
|
||||
suspend fun updateUsername(newLoginName: String): Void?
|
||||
|
||||
fun updateEmail(newEmail: String, password: String): Flowable<Void>
|
||||
suspend fun updateEmail(newEmail: String, password: String): Void?
|
||||
|
||||
fun updatePassword(oldPassword: String, newPassword: String, newPasswordConfirmation: String): Flowable<Void>
|
||||
suspend fun updatePassword(oldPassword: String, newPassword: String, newPasswordConfirmation: String): Void?
|
||||
|
||||
fun allocatePoint(stat: String): Flowable<Stats>
|
||||
suspend fun allocatePoint(stat: String): Stats?
|
||||
|
||||
fun bulkAllocatePoints(strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable<Stats>
|
||||
suspend fun bulkAllocatePoints(strength: Int, intelligence: Int, constitution: Int, perception: Int): Stats?
|
||||
|
||||
fun retrieveMarketGear(): Flowable<Shop>
|
||||
fun verifyUsername(username: String): Flowable<VerifyUsernameResponse>
|
||||
suspend fun retrieveMarketGear(): Shop?
|
||||
suspend fun verifyUsername(username: String): VerifyUsernameResponse?
|
||||
fun updateServerUrl(newAddress: String?)
|
||||
fun findUsernames(username: String, context: String?, id: String?): Flowable<List<FindUsernameResult>>
|
||||
suspend fun findUsernames(username: String, context: String?, id: String?): List<FindUsernameResult>?
|
||||
|
||||
fun transferGems(giftedID: String, amount: Int): Flowable<Void>
|
||||
fun unlinkAllTasks(challengeID: String?, keepOption: String): Flowable<Void>
|
||||
fun blockMember(userID: String): Flowable<List<String>>
|
||||
fun getTeamPlans(): Flowable<List<TeamPlan>>
|
||||
suspend fun transferGems(giftedID: String, amount: Int): Void?
|
||||
suspend fun unlinkAllTasks(challengeID: String?, keepOption: String): Void?
|
||||
suspend fun blockMember(userID: String): List<String>?
|
||||
suspend fun getTeamPlans(): List<TeamPlan>?
|
||||
suspend fun getTeamPlanTasks(teamID: String): TaskList?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,18 +4,18 @@ import com.habitrpg.android.habitica.models.social.Challenge
|
|||
import com.habitrpg.android.habitica.models.social.ChallengeMembership
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.tasks.TaskList
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ChallengeRepository : BaseRepository {
|
||||
|
||||
fun retrieveChallenges(page: Int = 0, memberOnly: Boolean): Flowable<List<Challenge>>
|
||||
fun getChallenges(): Flowable<out List<Challenge>>
|
||||
fun getChallenge(challengeId: String): Flowable<Challenge>
|
||||
fun getChallengeTasks(challengeId: String): Flowable<out List<Task>>
|
||||
suspend fun retrieveChallenges(page: Int = 0, memberOnly: Boolean): List<Challenge>?
|
||||
fun getChallenges(): Flow<List<Challenge>>
|
||||
fun getChallenge(challengeId: String): Flow<Challenge>
|
||||
fun getChallengeTasks(challengeId: String): Flow<List<Task>>
|
||||
|
||||
fun retrieveChallenge(challengeID: String): Flowable<Challenge>
|
||||
fun retrieveChallengeTasks(challengeID: String): Flowable<TaskList>
|
||||
fun createChallenge(challenge: Challenge, taskList: List<Task>): Flowable<Challenge>
|
||||
suspend fun retrieveChallenge(challengeID: String): Challenge?
|
||||
suspend fun retrieveChallengeTasks(challengeID: String): TaskList?
|
||||
suspend fun createChallenge(challenge: Challenge, taskList: List<Task>): Challenge?
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -26,22 +26,22 @@ interface ChallengeRepository : BaseRepository {
|
|||
* @param removedTaskList tasks that has be to be removed
|
||||
* @return Observable with the updated challenge
|
||||
*/
|
||||
fun updateChallenge(
|
||||
suspend fun updateChallenge(
|
||||
challenge: Challenge,
|
||||
fullTaskList: List<Task>,
|
||||
addedTaskList: List<Task>,
|
||||
updatedTaskList: List<Task>,
|
||||
removedTaskList: List<String>
|
||||
): Flowable<Challenge>
|
||||
): Challenge?
|
||||
|
||||
fun deleteChallenge(challengeId: String): Flowable<Void>
|
||||
fun getUserChallenges(userId: String? = null): Flowable<out List<Challenge>>
|
||||
suspend fun deleteChallenge(challengeId: String): Void?
|
||||
fun getUserChallenges(userId: String? = null): Flow<List<Challenge>>
|
||||
|
||||
fun leaveChallenge(challenge: Challenge, keepTasks: String): Flowable<Void>
|
||||
suspend fun leaveChallenge(challenge: Challenge, keepTasks: String): Void?
|
||||
|
||||
fun joinChallenge(challenge: Challenge): Flowable<Challenge>
|
||||
suspend fun joinChallenge(challenge: Challenge): Challenge?
|
||||
|
||||
fun getChallengepMembership(id: String): Flowable<ChallengeMembership>
|
||||
fun getChallengeMemberships(): Flowable<out List<ChallengeMembership>>
|
||||
fun isChallengeMember(challengeID: String): Flowable<Boolean>
|
||||
fun getChallengepMembership(id: String): Flow<ChallengeMembership>
|
||||
fun getChallengeMemberships(): Flow<List<ChallengeMembership>>
|
||||
fun isChallengeMember(challengeID: String): Flow<Boolean>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ package com.habitrpg.android.habitica.data
|
|||
|
||||
import com.habitrpg.android.habitica.models.ContentResult
|
||||
import com.habitrpg.android.habitica.models.WorldState
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ContentRepository: BaseRepository {
|
||||
suspend fun retrieveContent(forced: Boolean = false): ContentResult?
|
||||
|
||||
suspend fun retrieveWorldState(): WorldState?
|
||||
fun getWorldState(): Flowable<WorldState>
|
||||
fun getWorldState(): Flow<WorldState>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package com.habitrpg.android.habitica.data
|
||||
|
||||
import com.habitrpg.android.habitica.models.inventory.Customization
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface CustomizationRepository : BaseRepository {
|
||||
fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flowable<out List<Customization>>
|
||||
fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flow<List<Customization>>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package com.habitrpg.android.habitica.data
|
||||
|
||||
import com.habitrpg.android.habitica.models.FAQArticle
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface FAQRepository : BaseRepository {
|
||||
fun getArticles(): Flowable<out List<FAQArticle>>
|
||||
fun getArticle(position: Int): Flowable<FAQArticle>
|
||||
fun getArticles(): Flow<List<FAQArticle>>
|
||||
fun getArticle(position: Int): Flow<FAQArticle>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,15 +18,14 @@ import com.habitrpg.android.habitica.models.user.OwnedMount
|
|||
import com.habitrpg.android.habitica.models.user.OwnedPet
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.shared.habitica.models.responses.FeedResponse
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface InventoryRepository : BaseRepository {
|
||||
|
||||
fun getArmoireRemainingCount(): Long
|
||||
|
||||
fun getInAppRewards(): Flowable<out List<ShopItem>>
|
||||
fun getOwnedEquipment(): Flowable<out List<Equipment>>
|
||||
fun getInAppRewards(): Flow<List<ShopItem>>
|
||||
fun getOwnedEquipment(): Flow<List<Equipment>>
|
||||
|
||||
fun getMounts(): Flow<List<Mount>>
|
||||
|
||||
|
|
@ -38,18 +37,18 @@ interface InventoryRepository : BaseRepository {
|
|||
fun getQuestContent(key: String): Flow<QuestContent?>
|
||||
fun getQuestContent(keys: List<String>): Flow<List<QuestContent>>
|
||||
|
||||
fun getEquipment(searchedKeys: List<String>): Flowable<out List<Equipment>>
|
||||
fun getEquipment(searchedKeys: List<String>): Flow<List<Equipment>>
|
||||
suspend fun retrieveInAppRewards(): List<ShopItem>?
|
||||
|
||||
fun getOwnedEquipment(type: String): Flowable<out List<Equipment>>
|
||||
fun getEquipmentType(type: String, set: String): Flowable<out List<Equipment>>
|
||||
fun getOwnedEquipment(type: String): Flow<List<Equipment>>
|
||||
fun getEquipmentType(type: String, set: String): Flow<List<Equipment>>
|
||||
|
||||
fun getOwnedItems(itemType: String, includeZero: Boolean = false): Flow<List<OwnedItem>>
|
||||
fun getOwnedItems(includeZero: Boolean = false): Flowable<Map<String, OwnedItem>>
|
||||
fun getOwnedItems(includeZero: Boolean = false): Flow<Map<String, OwnedItem>>
|
||||
|
||||
fun getEquipment(key: String): Flowable<Equipment>
|
||||
fun getEquipment(key: String): Flow<Equipment>
|
||||
|
||||
fun openMysteryItem(user: User?): Flowable<Equipment>
|
||||
suspend fun openMysteryItem(user: User?): Equipment?
|
||||
|
||||
fun saveEquipment(equipment: Equipment)
|
||||
fun getMounts(type: String?, group: String?, color: String?): Flow<List<Mount>>
|
||||
|
|
@ -57,24 +56,24 @@ interface InventoryRepository : BaseRepository {
|
|||
|
||||
fun updateOwnedEquipment(user: User)
|
||||
|
||||
fun changeOwnedCount(type: String, key: String, amountToAdd: Int)
|
||||
suspend fun changeOwnedCount(type: String, key: String, amountToAdd: Int)
|
||||
|
||||
fun sellItem(type: String, key: String): Flowable<User>
|
||||
fun sellItem(item: OwnedItem): Flowable<User>
|
||||
suspend fun sellItem(type: String, key: String): User?
|
||||
suspend fun sellItem(item: OwnedItem): User?
|
||||
|
||||
fun equipGear(equipment: String, asCostume: Boolean): Flowable<Items>
|
||||
fun equip(type: String, key: String): Flowable<Items>
|
||||
suspend fun equipGear(equipment: String, asCostume: Boolean): Items?
|
||||
suspend fun equip(type: String, key: String): Items?
|
||||
|
||||
fun feedPet(pet: Pet, food: Food): Flowable<FeedResponse>
|
||||
suspend fun feedPet(pet: Pet, food: Food): FeedResponse?
|
||||
|
||||
fun hatchPet(egg: Egg, hatchingPotion: HatchingPotion, successFunction: () -> Unit): Flowable<Items>
|
||||
suspend fun hatchPet(egg: Egg, hatchingPotion: HatchingPotion, successFunction: () -> Unit): Items?
|
||||
|
||||
fun inviteToQuest(quest: QuestContent): Flowable<Quest>
|
||||
suspend fun inviteToQuest(quest: QuestContent): Quest?
|
||||
|
||||
suspend fun buyItem(user: User?, id: String, value: Double, purchaseQuantity: Int): BuyResponse?
|
||||
|
||||
fun retrieveShopInventory(identifier: String): Flowable<Shop>
|
||||
fun retrieveMarketGear(): Flowable<Shop>
|
||||
suspend fun retrieveShopInventory(identifier: String): Shop?
|
||||
suspend fun retrieveMarketGear(): Shop?
|
||||
|
||||
suspend fun purchaseMysterySet(categoryIdentifier: String): Void?
|
||||
|
||||
|
|
@ -87,9 +86,8 @@ interface InventoryRepository : BaseRepository {
|
|||
|
||||
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>>
|
||||
fun getLatestMysteryItem(): Flowable<Equipment>
|
||||
fun getItem(type: String, key: String): Flowable<Item>
|
||||
fun getAvailableLimitedItems(): Flowable<List<Item>>
|
||||
fun getLatestMysteryItem(): Flow<Equipment>
|
||||
fun getItem(type: String, key: String): Flow<Item>
|
||||
fun getAvailableLimitedItems(): Flow<List<Item>>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,35 +10,34 @@ import com.habitrpg.android.habitica.models.social.Group
|
|||
import com.habitrpg.android.habitica.models.social.GroupMembership
|
||||
import com.habitrpg.android.habitica.models.social.InboxConversation
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.RealmResults
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface SocialRepository : BaseRepository {
|
||||
fun getPublicGuilds(): Flowable<out List<Group>>
|
||||
fun getPublicGuilds(): Flow<List<Group>>
|
||||
|
||||
fun getUserGroups(type: String?): Flow<List<Group>>
|
||||
suspend fun retrieveGroupChat(groupId: String): List<ChatMessage>?
|
||||
fun getGroupChat(groupId: String): Flowable<out List<ChatMessage>>
|
||||
fun getGroupChat(groupId: String): Flow<out List<ChatMessage>>
|
||||
|
||||
fun markMessagesSeen(seenGroupId: String)
|
||||
suspend fun markMessagesSeen(seenGroupId: String)
|
||||
|
||||
fun flagMessage(
|
||||
suspend fun flagMessage(
|
||||
chatMessageID: String,
|
||||
additionalInfo: String,
|
||||
groupID: String? = null
|
||||
): Flowable<Void>
|
||||
): Void?
|
||||
|
||||
fun likeMessage(chatMessage: ChatMessage): Flowable<ChatMessage>
|
||||
suspend fun likeMessage(chatMessage: ChatMessage): ChatMessage?
|
||||
|
||||
fun deleteMessage(chatMessage: ChatMessage): Flowable<Void>
|
||||
suspend fun deleteMessage(chatMessage: ChatMessage): Void?
|
||||
|
||||
fun postGroupChat(
|
||||
suspend fun postGroupChat(
|
||||
groupId: String,
|
||||
messageObject: HashMap<String, String>
|
||||
): Flowable<PostChatMessageResult>
|
||||
): PostChatMessageResult?
|
||||
|
||||
fun postGroupChat(groupId: String, message: String): Flowable<PostChatMessageResult>
|
||||
suspend fun postGroupChat(groupId: String, message: String): PostChatMessageResult?
|
||||
|
||||
suspend fun retrieveGroup(id: String): Group?
|
||||
fun getGroup(id: String?): Flow<Group?>
|
||||
|
|
@ -64,12 +63,12 @@ interface SocialRepository : BaseRepository {
|
|||
leaderCreateChallenge: Boolean?
|
||||
): Group?
|
||||
|
||||
fun retrieveGroups(type: String): Flowable<List<Group>>
|
||||
fun getGroups(type: String): Flowable<out List<Group>>
|
||||
suspend fun retrieveGroups(type: String): List<Group>?
|
||||
fun getGroups(type: String): Flow<List<Group>>
|
||||
|
||||
fun getInboxMessages(replyToUserID: String?): Flow<RealmResults<ChatMessage>>
|
||||
suspend fun retrieveInboxMessages(uuid: String, page: Int): List<ChatMessage>?
|
||||
fun retrieveInboxConversations(): Flowable<List<InboxConversation>>
|
||||
suspend fun retrieveInboxConversations(): List<InboxConversation>?
|
||||
fun getInboxConversations(): Flow<RealmResults<InboxConversation>>
|
||||
suspend fun postPrivateMessage(
|
||||
recipientId: String,
|
||||
|
|
@ -82,42 +81,42 @@ interface SocialRepository : BaseRepository {
|
|||
suspend fun getGroupMembers(id: String): Flow<List<Member>>
|
||||
suspend fun retrievePartyMembers(id: String, includeAllPublicFields: Boolean): List<Member>?
|
||||
|
||||
fun inviteToGroup(id: String, inviteData: Map<String, Any>): Flowable<List<Void>>
|
||||
suspend fun inviteToGroup(id: String, inviteData: Map<String, Any>): List<Void>?
|
||||
|
||||
suspend fun retrieveMember(userId: String?): Member?
|
||||
suspend fun retrieveMemberWithUsername(username: String?): Member?
|
||||
|
||||
fun findUsernames(
|
||||
suspend fun findUsernames(
|
||||
username: String,
|
||||
context: String? = null,
|
||||
id: String? = null
|
||||
): Flowable<List<FindUsernameResult>>
|
||||
): List<FindUsernameResult>?
|
||||
|
||||
fun markPrivateMessagesRead(user: User?): Flowable<Void>
|
||||
suspend fun markPrivateMessagesRead(user: User?): Void?
|
||||
|
||||
fun markSomePrivateMessagesAsRead(user: User?, messages: List<ChatMessage>)
|
||||
|
||||
suspend fun transferGroupOwnership(groupID: String, userID: String): Group?
|
||||
suspend fun removeMemberFromGroup(groupID: String, userID: String): List<Member>?
|
||||
|
||||
fun acceptQuest(user: User?, partyId: String = "party"): Flowable<Void>
|
||||
fun rejectQuest(user: User?, partyId: String = "party"): Flowable<Void>
|
||||
suspend fun acceptQuest(user: User?, partyId: String = "party"): Void?
|
||||
suspend fun rejectQuest(user: User?, partyId: String = "party"): Void?
|
||||
|
||||
fun leaveQuest(partyId: String): Flowable<Void>
|
||||
suspend fun leaveQuest(partyId: String): Void?
|
||||
|
||||
fun cancelQuest(partyId: String): Flowable<Void>
|
||||
suspend fun cancelQuest(partyId: String): Void?
|
||||
|
||||
fun abortQuest(partyId: String): Flowable<Quest>
|
||||
suspend fun abortQuest(partyId: String): Quest?
|
||||
|
||||
fun rejectGroupInvite(groupId: String): Flowable<Void>
|
||||
suspend fun rejectGroupInvite(groupId: String): Void?
|
||||
|
||||
fun forceStartQuest(party: Group): Flowable<Quest>
|
||||
suspend fun forceStartQuest(party: Group): Quest?
|
||||
|
||||
fun getMemberAchievements(userId: String?): Flowable<List<Achievement>>
|
||||
suspend fun getMemberAchievements(userId: String?): List<Achievement>?
|
||||
|
||||
fun transferGems(giftedID: String, amount: Int): Flowable<Void>
|
||||
suspend fun transferGems(giftedID: String, amount: Int): Void?
|
||||
|
||||
fun getGroupMembership(id: String): Flow<GroupMembership?>
|
||||
fun getGroupMemberships(): Flowable<out List<GroupMembership>>
|
||||
fun blockMember(userID: String): Flowable<List<String>>
|
||||
fun getGroupMemberships(): Flow<List<GroupMembership>>
|
||||
suspend fun blockMember(userID: String): List<String>?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
package com.habitrpg.android.habitica.data
|
||||
|
||||
import com.habitrpg.android.habitica.models.Tag
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface TagRepository : BaseRepository {
|
||||
|
||||
fun getTags(): Flowable<out List<Tag>>
|
||||
fun getTags(userId: String): Flowable<out List<Tag>>
|
||||
fun getTags(): Flow<List<Tag>>
|
||||
fun getTags(userId: String): Flow<List<Tag>>
|
||||
|
||||
fun createTag(tag: Tag): Flowable<Tag>
|
||||
fun updateTag(tag: Tag): Flowable<Tag>
|
||||
fun deleteTag(id: String): Flowable<Void>
|
||||
suspend fun createTag(tag: Tag): Tag?
|
||||
suspend fun updateTag(tag: Tag): Tag?
|
||||
suspend fun deleteTag(id: String): Void?
|
||||
|
||||
fun createTags(tags: Collection<Tag>): Single<List<Tag>>
|
||||
fun updateTags(tags: Collection<Tag>): Single<List<Tag>>
|
||||
fun deleteTags(tagIds: Collection<String>): Single<List<Void>>
|
||||
suspend fun createTags(tags: Collection<Tag>): List<Tag>
|
||||
suspend fun updateTags(tags: Collection<Tag>): List<Tag>
|
||||
suspend fun deleteTags(tagIds: Collection<String>): List<Void>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,19 +8,15 @@ import com.habitrpg.android.habitica.models.user.User
|
|||
import com.habitrpg.shared.habitica.models.responses.TaskScoringResult
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.shared.habitica.models.tasks.TasksOrder
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Maybe
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.util.Date
|
||||
|
||||
interface TaskRepository : BaseRepository {
|
||||
fun getTasks(taskType: TaskType, userID: String? = null, includedGroupIDs: Array<String>): Flow<List<Task>>
|
||||
fun getTasksFlowable(taskType: TaskType, userID: String? = null, includedGroupIDs: Array<String>): Flowable<out List<Task>>
|
||||
fun saveTasks(userId: String, order: TasksOrder, tasks: TaskList)
|
||||
|
||||
suspend fun retrieveTasks(userId: String, tasksOrder: TasksOrder): TaskList?
|
||||
fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): Flowable<TaskList>
|
||||
suspend fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): TaskList?
|
||||
|
||||
suspend fun taskChecked(
|
||||
user: User?,
|
||||
|
|
@ -40,12 +36,12 @@ interface TaskRepository : BaseRepository {
|
|||
|
||||
fun getTask(taskId: String): Flow<Task>
|
||||
fun getTaskCopy(taskId: String): Flow<Task>
|
||||
fun createTask(task: Task, force: Boolean = false): Flowable<Task>
|
||||
fun updateTask(task: Task, force: Boolean = false): Maybe<Task>?
|
||||
fun deleteTask(taskId: String): Flowable<Void>
|
||||
suspend fun createTask(task: Task, force: Boolean = false): Task?
|
||||
suspend fun updateTask(task: Task, force: Boolean = false): Task?
|
||||
suspend fun deleteTask(taskId: String): Void?
|
||||
fun saveTask(task: Task)
|
||||
|
||||
fun createTasks(newTasks: List<Task>): Flowable<List<Task>>
|
||||
suspend fun createTasks(newTasks: List<Task>): List<Task>?
|
||||
|
||||
fun markTaskCompleted(taskId: String, isCompleted: Boolean)
|
||||
|
||||
|
|
@ -53,7 +49,7 @@ interface TaskRepository : BaseRepository {
|
|||
|
||||
fun swapTaskPosition(firstPosition: Int, secondPosition: Int)
|
||||
|
||||
fun updateTaskPosition(taskType: TaskType, taskID: String, newPosition: Int): Maybe<List<String>>
|
||||
suspend fun updateTaskPosition(taskType: TaskType, taskID: String, newPosition: Int): List<String>?
|
||||
|
||||
fun getUnmanagedTask(taskid: String): Flow<Task>
|
||||
|
||||
|
|
@ -65,10 +61,10 @@ interface TaskRepository : BaseRepository {
|
|||
|
||||
fun getTaskCopies(tasks: List<Task>): List<Task>
|
||||
|
||||
fun retrieveDailiesFromDate(date: Date): Flowable<TaskList>
|
||||
fun retrieveCompletedTodos(userId: String? = null): Flowable<TaskList>
|
||||
fun syncErroredTasks(): Single<List<Task>>
|
||||
fun unlinkAllTasks(challengeID: String?, keepOption: String): Flowable<Void>
|
||||
fun getTasksForChallenge(challengeID: String?): Flowable<out List<Task>>
|
||||
fun bulkScoreTasks(data: List<Map<String, String>>): Flowable<BulkTaskScoringData>
|
||||
suspend fun retrieveDailiesFromDate(date: Date): TaskList?
|
||||
suspend fun retrieveCompletedTodos(userId: String? = null): TaskList?
|
||||
suspend fun syncErroredTasks(): List<Task>?
|
||||
suspend fun unlinkAllTasks(challengeID: String?, keepOption: String): Void?
|
||||
fun getTasksForChallenge(challengeID: String?): Flow<out List<Task>>
|
||||
suspend fun bulkScoreTasks(data: List<Map<String, String>>): BulkTaskScoringData?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package com.habitrpg.android.habitica.data
|
||||
|
||||
import com.habitrpg.android.habitica.models.TutorialStep
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface TutorialRepository : BaseRepository {
|
||||
|
||||
fun getTutorialStep(key: String): Flowable<TutorialStep>
|
||||
fun getTutorialSteps(keys: List<String>): Flowable<out List<TutorialStep>>
|
||||
fun getTutorialStep(key: String): Flow<TutorialStep>
|
||||
fun getTutorialSteps(keys: List<String>): Flow<out List<TutorialStep>>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,10 @@ 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 kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface UserRepository : BaseRepository {
|
||||
fun getUser(): Flow<User?>
|
||||
fun getUserFlowable(): Flowable<User>
|
||||
fun getUser(userID: String): Flow<User?>
|
||||
|
||||
suspend fun updateUser(updateData: Map<String, Any>): User?
|
||||
|
|
@ -33,9 +31,9 @@ interface UserRepository : BaseRepository {
|
|||
|
||||
suspend fun sleep(user: User): User?
|
||||
|
||||
fun getSkills(user: User): Flowable<out List<Skill>>
|
||||
fun getSkills(user: User): Flow<List<Skill>>
|
||||
|
||||
fun getSpecialItems(user: User): Flowable<out List<Skill>>
|
||||
fun getSpecialItems(user: User): Flow<List<Skill>>
|
||||
|
||||
suspend fun useSkill(key: String, target: String?, taskId: String): SkillResponse?
|
||||
suspend fun useSkill(key: String, target: String?): SkillResponse?
|
||||
|
|
@ -49,37 +47,37 @@ interface UserRepository : BaseRepository {
|
|||
suspend fun runCron(tasks: MutableList<Task>)
|
||||
suspend fun runCron()
|
||||
|
||||
fun readNotification(id: String): Flowable<List<Any>>
|
||||
fun readNotifications(notificationIds: Map<String, List<String>>): Flowable<List<Any>>
|
||||
fun seeNotifications(notificationIds: Map<String, List<String>>): Flowable<List<Any>>
|
||||
suspend fun readNotification(id: String): List<Any>?
|
||||
suspend fun readNotifications(notificationIds: Map<String, List<String>>): List<Any>?
|
||||
suspend fun seeNotifications(notificationIds: Map<String, List<String>>): List<Any>?
|
||||
|
||||
fun changeCustomDayStart(dayStartTime: Int): Flowable<User>
|
||||
suspend fun changeCustomDayStart(dayStartTime: Int): User?
|
||||
|
||||
suspend fun updateLanguage(languageCode: String): User?
|
||||
|
||||
suspend fun resetAccount(): User?
|
||||
fun deleteAccount(password: String): Flowable<Void>
|
||||
suspend fun deleteAccount(password: String): Void?
|
||||
|
||||
fun sendPasswordResetEmail(email: String): Flowable<Void>
|
||||
suspend fun sendPasswordResetEmail(email: String): Void?
|
||||
|
||||
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>
|
||||
suspend fun updateEmail(newEmail: String, password: String): Void?
|
||||
suspend fun updatePassword(oldPassword: String, newPassword: String, newPasswordConfirmation: String): Void?
|
||||
suspend fun verifyUsername(username: String): VerifyUsernameResponse?
|
||||
|
||||
fun allocatePoint(stat: Attribute): Flowable<Stats>
|
||||
fun bulkAllocatePoints(strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable<Stats>
|
||||
suspend fun allocatePoint(stat: Attribute): Stats?
|
||||
suspend fun bulkAllocatePoints(strength: Int, intelligence: Int, constitution: Int, perception: Int): Stats?
|
||||
|
||||
suspend fun useCustomization(type: String, category: String?, identifier: String): User?
|
||||
fun retrieveAchievements(): Flowable<List<Achievement>>
|
||||
suspend fun retrieveAchievements(): List<Achievement>?
|
||||
fun getAchievements(): Flow<List<Achievement>>
|
||||
fun getQuestAchievements(): Flow<List<QuestAchievement>>
|
||||
|
||||
fun getUserQuestStatus(): Flowable<UserQuestStatus>
|
||||
fun getUserQuestStatus(): Flow<UserQuestStatus>
|
||||
|
||||
suspend fun reroll(): User?
|
||||
fun retrieveTeamPlans(): Flowable<List<TeamPlan>>
|
||||
suspend fun retrieveTeamPlans(): List<TeamPlan>?
|
||||
fun getTeamPlans(): Flow<List<TeamPlan>>
|
||||
suspend fun retrieveTeamPlan(teamID: String): Group?
|
||||
fun getTeamPlan(teamID: String): Flowable<Group>
|
||||
fun getTeamPlan(teamID: String): Flow<Group>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,11 +51,7 @@ import com.habitrpg.shared.habitica.models.responses.FeedResponse
|
|||
import com.habitrpg.shared.habitica.models.responses.Status
|
||||
import com.habitrpg.shared.habitica.models.responses.TaskDirectionData
|
||||
import com.habitrpg.shared.habitica.models.responses.VerifyUsernameResponse
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.FlowableTransformer
|
||||
import io.reactivex.rxjava3.functions.Consumer
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import okhttp3.Cache
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
|
|
@ -87,17 +83,6 @@ class ApiClientImpl(
|
|||
// I think we don't need the ApiClientImpl anymore we could just use ApiService
|
||||
private lateinit var apiService: ApiService
|
||||
|
||||
private val apiCallTransformer = FlowableTransformer<HabitResponse<Any>, Any> { observable ->
|
||||
observable
|
||||
.filter { it.data != null }
|
||||
.map { habitResponse ->
|
||||
processResponse(habitResponse)
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnError(this)
|
||||
}
|
||||
|
||||
private fun <T> processResponse(habitResponse: HabitResponse<T>): T? {
|
||||
habitResponse.notifications?.let {
|
||||
notificationsManager.setNotifications(it)
|
||||
|
|
@ -114,7 +99,7 @@ class ApiClientImpl(
|
|||
return null
|
||||
}
|
||||
|
||||
private var languageCode: String? = null
|
||||
override var languageCode: String? = null
|
||||
private var lastAPICallURL: String? = null
|
||||
private var hadError = false
|
||||
|
||||
|
|
@ -186,28 +171,28 @@ class ApiClientImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override fun registerUser(
|
||||
override suspend fun registerUser(
|
||||
username: String,
|
||||
email: String,
|
||||
password: String,
|
||||
confirmPassword: String
|
||||
): Flowable<UserAuthResponse> {
|
||||
): UserAuthResponse? {
|
||||
val auth = UserAuth()
|
||||
auth.username = username
|
||||
auth.password = password
|
||||
auth.confirmPassword = confirmPassword
|
||||
auth.email = email
|
||||
return this.apiService.registerUser(auth).compose(configureApiCallObserver())
|
||||
return process { this.apiService.registerUser(auth) }
|
||||
}
|
||||
|
||||
override fun connectUser(username: String, password: String): Flowable<UserAuthResponse> {
|
||||
override suspend fun connectUser(username: String, password: String): UserAuthResponse? {
|
||||
val auth = UserAuth()
|
||||
auth.username = username
|
||||
auth.password = password
|
||||
return this.apiService.connectLocal(auth).compose(configureApiCallObserver())
|
||||
return process { this.apiService.connectLocal(auth) }
|
||||
}
|
||||
|
||||
override fun connectSocial(network: String, userId: String, accessToken: String): Flowable<UserAuthResponse> {
|
||||
override suspend fun connectSocial(network: String, userId: String, accessToken: String): UserAuthResponse? {
|
||||
val auth = UserAuthSocial()
|
||||
auth.network = network
|
||||
val authResponse = UserAuthSocialTokens()
|
||||
|
|
@ -215,15 +200,15 @@ class ApiClientImpl(
|
|||
authResponse.access_token = accessToken
|
||||
auth.authResponse = authResponse
|
||||
|
||||
return this.apiService.connectSocial(auth).compose(configureApiCallObserver())
|
||||
return process { this.apiService.connectSocial(auth) }
|
||||
}
|
||||
|
||||
override fun disconnectSocial(network: String): Flowable<Void> {
|
||||
return this.apiService.disconnectSocial(network).compose(configureApiCallObserver())
|
||||
override suspend fun disconnectSocial(network: String): Void? {
|
||||
return process { this.apiService.disconnectSocial(network) }
|
||||
}
|
||||
|
||||
override fun loginApple(authToken: String): Flowable<UserAuthResponse> {
|
||||
return apiService.loginApple(mapOf(Pair("code", authToken))).compose(configureApiCallObserver())
|
||||
override suspend fun loginApple(authToken: String): UserAuthResponse? {
|
||||
return process { apiService.loginApple(mapOf(Pair("code", authToken))) }
|
||||
}
|
||||
|
||||
override fun accept(throwable: Throwable) {
|
||||
|
|
@ -290,8 +275,8 @@ class ApiClientImpl(
|
|||
return process { apiService.getInboxMessages(uuid, page) }
|
||||
}
|
||||
|
||||
override fun retrieveInboxConversations(): Flowable<List<InboxConversation>> {
|
||||
return apiService.getInboxConversations().compose(configureApiCallObserver())
|
||||
override suspend fun retrieveInboxConversations(): List<InboxConversation>? {
|
||||
return process { apiService.getInboxConversations() }
|
||||
}
|
||||
|
||||
override fun hasAuthenticationKeys(): Boolean {
|
||||
|
|
@ -330,11 +315,6 @@ class ApiClientImpl(
|
|||
See here for more info: http://blog.danlew.net/2015/03/02/dont-break-the-chain/
|
||||
*/
|
||||
|
||||
override fun <T : Any> configureApiCallObserver(): FlowableTransformer<HabitResponse<T>, T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return apiCallTransformer as FlowableTransformer<HabitResponse<T>, T>
|
||||
}
|
||||
|
||||
override fun updateAuthenticationCredentials(userID: String?, apiToken: String?) {
|
||||
this.hostConfig.userID = userID ?: ""
|
||||
this.hostConfig.apiKey = apiToken ?: ""
|
||||
|
|
@ -342,10 +322,6 @@ class ApiClientImpl(
|
|||
Amplitude.getInstance().userId = this.hostConfig.userID
|
||||
}
|
||||
|
||||
override fun setLanguageCode(languageCode: String) {
|
||||
this.languageCode = languageCode
|
||||
}
|
||||
|
||||
override suspend fun getStatus(): Status? = process { apiService.getStatus() }
|
||||
|
||||
override suspend fun getContent(language: String?): ContentResult? {
|
||||
|
|
@ -356,40 +332,40 @@ class ApiClientImpl(
|
|||
return process { apiService.updateUser(updateDictionary) }
|
||||
}
|
||||
|
||||
override fun registrationLanguage(registrationLanguage: String): Flowable<User> {
|
||||
return apiService.registrationLanguage(registrationLanguage).compose(configureApiCallObserver())
|
||||
override suspend fun registrationLanguage(registrationLanguage: String): User? {
|
||||
return process { apiService.registrationLanguage(registrationLanguage) }
|
||||
}
|
||||
|
||||
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 suspend fun equipItem(type: String, itemKey: String): Items? {
|
||||
return process { apiService.equipItem(type, itemKey) }
|
||||
}
|
||||
|
||||
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> {
|
||||
return apiService.unlinkAllTasks(challengeID, keepOption).compose(configureApiCallObserver())
|
||||
override suspend fun unlinkAllTasks(challengeID: String?, keepOption: String): Void? {
|
||||
return process { apiService.unlinkAllTasks(challengeID, keepOption) }
|
||||
}
|
||||
|
||||
override fun blockMember(userID: String): Flowable<List<String>> {
|
||||
return apiService.blockMember(userID).compose(configureApiCallObserver())
|
||||
override suspend fun blockMember(userID: String): List<String>? {
|
||||
return process { apiService.blockMember(userID) }
|
||||
}
|
||||
|
||||
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> {
|
||||
return apiService.validateSubscription(request).compose(configureApiCallObserver())
|
||||
override suspend fun validateSubscription(request: PurchaseValidationRequest): Any? {
|
||||
return process { apiService.validateSubscription(request) }
|
||||
}
|
||||
|
||||
override fun validateNoRenewSubscription(request: PurchaseValidationRequest): Flowable<Any> {
|
||||
return apiService.validateNoRenewSubscription(request).compose(configureApiCallObserver())
|
||||
override suspend fun validateNoRenewSubscription(request: PurchaseValidationRequest): Any? {
|
||||
return process { apiService.validateNoRenewSubscription(request) }
|
||||
}
|
||||
|
||||
override suspend fun cancelSubscription(): Void? {
|
||||
|
|
@ -412,83 +388,80 @@ class ApiClientImpl(
|
|||
return process { apiService.purchaseSpecialSpell(key) }
|
||||
}
|
||||
|
||||
override fun sellItem(itemType: String, itemKey: String): Flowable<User> {
|
||||
return apiService.sellItem(itemType, itemKey).compose(configureApiCallObserver())
|
||||
override suspend fun sellItem(itemType: String, itemKey: String): User? {
|
||||
return process { apiService.sellItem(itemType, itemKey) }
|
||||
}
|
||||
|
||||
override fun feedPet(petKey: String, foodKey: String): Flowable<FeedResponse> {
|
||||
return apiService.feedPet(petKey, foodKey)
|
||||
.map {
|
||||
it.data?.message = it.message
|
||||
it
|
||||
}
|
||||
.compose(configureApiCallObserver())
|
||||
override suspend fun feedPet(petKey: String, foodKey: String): FeedResponse? {
|
||||
val response = apiService.feedPet(petKey, foodKey)
|
||||
response.data?.message = response.message
|
||||
return process { response }
|
||||
}
|
||||
|
||||
override fun hatchPet(eggKey: String, hatchingPotionKey: String): Flowable<Items> {
|
||||
return apiService.hatchPet(eggKey, hatchingPotionKey).compose(configureApiCallObserver())
|
||||
override suspend fun hatchPet(eggKey: String, hatchingPotionKey: String): Items? {
|
||||
return process { apiService.hatchPet(eggKey, hatchingPotionKey) }
|
||||
}
|
||||
|
||||
override suspend fun getTasks(): TaskList? = process { apiService.getTasks() }
|
||||
|
||||
override fun getTasks(type: String): Flowable<TaskList> {
|
||||
return apiService.getTasks(type).compose(configureApiCallObserver())
|
||||
override suspend fun getTasks(type: String): TaskList? {
|
||||
return process { apiService.getTasks(type) }
|
||||
}
|
||||
|
||||
override fun getTasks(type: String, dueDate: String): Flowable<TaskList> {
|
||||
return apiService.getTasks(type, dueDate).compose(configureApiCallObserver())
|
||||
override suspend fun getTasks(type: String, dueDate: String): TaskList? {
|
||||
return process { apiService.getTasks(type, dueDate) }
|
||||
}
|
||||
|
||||
override suspend fun unlockPath(path: String): UnlockResponse? {
|
||||
return process { apiService.unlockPath(path) }
|
||||
}
|
||||
|
||||
override fun getTask(id: String): Flowable<Task> {
|
||||
return apiService.getTask(id).compose(configureApiCallObserver())
|
||||
override suspend fun getTask(id: String): Task? {
|
||||
return process { apiService.getTask(id) }
|
||||
}
|
||||
|
||||
override suspend fun postTaskDirection(id: String, direction: String): TaskDirectionData? {
|
||||
return process { apiService.postTaskDirection(id, direction) }
|
||||
}
|
||||
|
||||
override fun bulkScoreTasks(data: List<Map<String, String>>): Flowable<BulkTaskScoringData> {
|
||||
return apiService.bulkScoreTasks(data).compose(configureApiCallObserver())
|
||||
override suspend fun bulkScoreTasks(data: List<Map<String, String>>): BulkTaskScoringData? {
|
||||
return process { apiService.bulkScoreTasks(data) }
|
||||
}
|
||||
|
||||
override fun postTaskNewPosition(id: String, position: Int): Flowable<List<String>> {
|
||||
return apiService.postTaskNewPosition(id, position).compose(configureApiCallObserver())
|
||||
override suspend fun postTaskNewPosition(id: String, position: Int): List<String>? {
|
||||
return process { apiService.postTaskNewPosition(id, position) }
|
||||
}
|
||||
|
||||
override suspend fun scoreChecklistItem(taskId: String, itemId: String): Task? {
|
||||
return process { apiService.scoreChecklistItem(taskId, itemId) }
|
||||
}
|
||||
|
||||
override fun createTask(item: Task): Flowable<Task> {
|
||||
return apiService.createTask(item).compose(configureApiCallObserver())
|
||||
override suspend fun createTask(item: Task): Task? {
|
||||
return process { apiService.createTask(item) }
|
||||
}
|
||||
|
||||
override fun createTasks(tasks: List<Task>): Flowable<List<Task>> {
|
||||
return apiService.createTasks(tasks).compose(configureApiCallObserver())
|
||||
override suspend fun createTasks(tasks: List<Task>): List<Task>? {
|
||||
return process { apiService.createTasks(tasks) }
|
||||
}
|
||||
|
||||
override fun updateTask(id: String, item: Task): Flowable<Task> {
|
||||
return apiService.updateTask(id, item).compose(configureApiCallObserver())
|
||||
override suspend fun updateTask(id: String, item: Task): Task? {
|
||||
return process { apiService.updateTask(id, item) }
|
||||
}
|
||||
|
||||
override fun deleteTask(id: String): Flowable<Void> {
|
||||
return apiService.deleteTask(id).compose(configureApiCallObserver())
|
||||
override suspend fun deleteTask(id: String): Void? {
|
||||
return process { apiService.deleteTask(id) }
|
||||
}
|
||||
|
||||
override fun createTag(tag: Tag): Flowable<Tag> {
|
||||
return apiService.createTag(tag).compose(configureApiCallObserver())
|
||||
override suspend fun createTag(tag: Tag): Tag? {
|
||||
return process { apiService.createTag(tag) }
|
||||
}
|
||||
|
||||
override fun updateTag(id: String, tag: Tag): Flowable<Tag> {
|
||||
return apiService.updateTag(id, tag).compose(configureApiCallObserver())
|
||||
override suspend fun updateTag(id: String, tag: Tag): Tag? {
|
||||
return process { apiService.updateTag(id, tag) }
|
||||
}
|
||||
|
||||
override fun deleteTag(id: String): Flowable<Void> {
|
||||
return apiService.deleteTag(id).compose(configureApiCallObserver())
|
||||
override suspend fun deleteTag(id: String): Void? {
|
||||
return process { apiService.deleteTag(id) }
|
||||
}
|
||||
|
||||
override suspend fun sleep(): Boolean? = process { apiService.sleep() }
|
||||
|
|
@ -515,16 +488,12 @@ class ApiClientImpl(
|
|||
|
||||
override suspend fun disableClasses(): User? = process { apiService.disableClasses() }
|
||||
|
||||
override fun markPrivateMessagesRead(): Flowable<Void> {
|
||||
// This is necessary, because the API call returns weird data.
|
||||
override suspend fun markPrivateMessagesRead(): Void {
|
||||
return apiService.markPrivateMessagesRead()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnError(this)
|
||||
}
|
||||
|
||||
override fun listGroups(type: String): Flowable<List<Group>> {
|
||||
return apiService.listGroups(type).compose(configureApiCallObserver())
|
||||
override suspend fun listGroups(type: String): List<Group>? {
|
||||
return process { apiService.listGroups(type) }
|
||||
}
|
||||
|
||||
override suspend fun getGroup(groupId: String): Group? {
|
||||
|
|
@ -555,15 +524,15 @@ class ApiClientImpl(
|
|||
return processResponse(apiService.leaveGroup(groupId, keepChallenges))
|
||||
}
|
||||
|
||||
override fun postGroupChat(groupId: String, message: Map<String, String>): Flowable<PostChatMessageResult> {
|
||||
return apiService.postGroupChat(groupId, message).compose(configureApiCallObserver())
|
||||
override suspend fun postGroupChat(groupId: String, message: Map<String, String>): PostChatMessageResult? {
|
||||
return process { apiService.postGroupChat(groupId, message) }
|
||||
}
|
||||
|
||||
override fun deleteMessage(groupId: String, messageId: String): Flowable<Void> {
|
||||
return apiService.deleteMessage(groupId, messageId).compose(configureApiCallObserver())
|
||||
override suspend fun deleteMessage(groupId: String, messageId: String): Void? {
|
||||
return process { apiService.deleteMessage(groupId, messageId) }
|
||||
}
|
||||
override fun deleteInboxMessage(id: String): Flowable<Void> {
|
||||
return apiService.deleteInboxMessage(id).compose(configureApiCallObserver())
|
||||
override suspend fun deleteInboxMessage(id: String): Void? {
|
||||
return process { apiService.deleteInboxMessage(id) }
|
||||
}
|
||||
|
||||
override suspend fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?): List<Member>? {
|
||||
|
|
@ -574,181 +543,181 @@ class ApiClientImpl(
|
|||
return processResponse(apiService.getGroupMembers(groupId, includeAllPublicFields, lastId))
|
||||
}
|
||||
|
||||
override fun likeMessage(groupId: String, mid: String): Flowable<ChatMessage> {
|
||||
return apiService.likeMessage(groupId, mid).compose(configureApiCallObserver())
|
||||
override suspend fun likeMessage(groupId: String, mid: String): ChatMessage? {
|
||||
return process { apiService.likeMessage(groupId, mid) }
|
||||
}
|
||||
|
||||
override fun flagMessage(groupId: String, mid: String, data: MutableMap<String, String>): Flowable<Void> {
|
||||
return apiService.flagMessage(groupId, mid, data).compose(configureApiCallObserver())
|
||||
override suspend fun flagMessage(groupId: String, mid: String, data: MutableMap<String, String>): Void? {
|
||||
return process { apiService.flagMessage(groupId, mid, data) }
|
||||
}
|
||||
|
||||
override fun flagInboxMessage(mid: String, data: MutableMap<String, String>): Flowable<Void> {
|
||||
return apiService.flagInboxMessage(mid, data).compose(configureApiCallObserver())
|
||||
override suspend fun flagInboxMessage(mid: String, data: MutableMap<String, String>): Void? {
|
||||
return process { apiService.flagInboxMessage(mid, data) }
|
||||
}
|
||||
|
||||
override fun seenMessages(groupId: String): Flowable<Void> {
|
||||
return apiService.seenMessages(groupId).compose(configureApiCallObserver())
|
||||
override suspend fun seenMessages(groupId: String): Void? {
|
||||
return process { apiService.seenMessages(groupId) }
|
||||
}
|
||||
|
||||
override fun inviteToGroup(groupId: String, inviteData: Map<String, Any>): Flowable<List<Void>> {
|
||||
return apiService.inviteToGroup(groupId, inviteData).compose(configureApiCallObserver())
|
||||
override suspend fun inviteToGroup(groupId: String, inviteData: Map<String, Any>): List<Void>? {
|
||||
return process { apiService.inviteToGroup(groupId, inviteData) }
|
||||
}
|
||||
|
||||
override fun rejectGroupInvite(groupId: String): Flowable<Void> {
|
||||
return apiService.rejectGroupInvite(groupId).compose(configureApiCallObserver())
|
||||
override suspend fun rejectGroupInvite(groupId: String): Void? {
|
||||
return process { apiService.rejectGroupInvite(groupId) }
|
||||
}
|
||||
|
||||
override fun acceptQuest(groupId: String): Flowable<Void> {
|
||||
return apiService.acceptQuest(groupId).compose(configureApiCallObserver())
|
||||
override suspend fun acceptQuest(groupId: String): Void? {
|
||||
return process { apiService.acceptQuest(groupId) }
|
||||
}
|
||||
|
||||
override fun rejectQuest(groupId: String): Flowable<Void> {
|
||||
return apiService.rejectQuest(groupId).compose(configureApiCallObserver())
|
||||
override suspend fun rejectQuest(groupId: String): Void? {
|
||||
return process { apiService.rejectQuest(groupId) }
|
||||
}
|
||||
|
||||
override fun cancelQuest(groupId: String): Flowable<Void> {
|
||||
return apiService.cancelQuest(groupId).compose(configureApiCallObserver())
|
||||
override suspend fun cancelQuest(groupId: String): Void? {
|
||||
return process { apiService.cancelQuest(groupId) }
|
||||
}
|
||||
|
||||
override fun forceStartQuest(groupId: String, group: Group): Flowable<Quest> {
|
||||
return apiService.forceStartQuest(groupId, group).compose(configureApiCallObserver())
|
||||
override suspend fun forceStartQuest(groupId: String, group: Group): Quest? {
|
||||
return process { apiService.forceStartQuest(groupId, group) }
|
||||
}
|
||||
|
||||
override fun inviteToQuest(groupId: String, questKey: String): Flowable<Quest> {
|
||||
return apiService.inviteToQuest(groupId, questKey).compose(configureApiCallObserver())
|
||||
override suspend fun inviteToQuest(groupId: String, questKey: String): Quest? {
|
||||
return process { apiService.inviteToQuest(groupId, questKey) }
|
||||
}
|
||||
|
||||
override fun abortQuest(groupId: String): Flowable<Quest> {
|
||||
return apiService.abortQuest(groupId).compose(configureApiCallObserver())
|
||||
override suspend fun abortQuest(groupId: String): Quest? {
|
||||
return process { apiService.abortQuest(groupId) }
|
||||
}
|
||||
|
||||
override fun leaveQuest(groupId: String): Flowable<Void> {
|
||||
return apiService.leaveQuest(groupId).compose(configureApiCallObserver())
|
||||
override suspend fun leaveQuest(groupId: String): Void? {
|
||||
return process { apiService.leaveQuest(groupId) }
|
||||
}
|
||||
|
||||
override fun validatePurchase(request: PurchaseValidationRequest): Flowable<PurchaseValidationResult> {
|
||||
return apiService.validatePurchase(request).compose(configureApiCallObserver())
|
||||
override suspend fun validatePurchase(request: PurchaseValidationRequest): PurchaseValidationResult? {
|
||||
return process { apiService.validatePurchase(request) }
|
||||
}
|
||||
|
||||
override fun changeCustomDayStart(updateObject: Map<String, Any>): Flowable<User> {
|
||||
return apiService.changeCustomDayStart(updateObject).compose(configureApiCallObserver())
|
||||
override suspend fun changeCustomDayStart(updateObject: Map<String, Any>): User? {
|
||||
return process { apiService.changeCustomDayStart(updateObject) }
|
||||
}
|
||||
|
||||
override suspend fun getMember(memberId: String) = processResponse(apiService.getMember(memberId))
|
||||
override suspend fun getMemberWithUsername(username: String) = processResponse(apiService.getMemberWithUsername(username))
|
||||
|
||||
override fun getMemberAchievements(memberId: String): Flowable<List<Achievement>> {
|
||||
return apiService.getMemberAchievements(memberId, languageCode).compose(configureApiCallObserver())
|
||||
override suspend fun getMemberAchievements(memberId: String): List<Achievement>? {
|
||||
return process { apiService.getMemberAchievements(memberId, languageCode) }
|
||||
}
|
||||
|
||||
override fun findUsernames(username: String, context: String?, id: String?): Flowable<List<FindUsernameResult>> {
|
||||
return apiService.findUsernames(username, context, id).compose(configureApiCallObserver())
|
||||
override suspend fun findUsernames(username: String, context: String?, id: String?): List<FindUsernameResult>? {
|
||||
return process { apiService.findUsernames(username, context, id) }
|
||||
}
|
||||
|
||||
override suspend fun postPrivateMessage(messageDetails: Map<String, String>): PostChatMessageResult? {
|
||||
return process { apiService.postPrivateMessage(messageDetails) }
|
||||
}
|
||||
|
||||
override fun retrieveShopIventory(identifier: String): Flowable<Shop> {
|
||||
return apiService.retrieveShopInventory(identifier, languageCode).compose(configureApiCallObserver())
|
||||
override suspend fun retrieveShopIventory(identifier: String): Shop? {
|
||||
return process { apiService.retrieveShopInventory(identifier, languageCode) }
|
||||
}
|
||||
|
||||
override fun addPushDevice(pushDeviceData: Map<String, String>): Flowable<List<Void>> {
|
||||
return apiService.addPushDevice(pushDeviceData).compose(configureApiCallObserver())
|
||||
override suspend fun addPushDevice(pushDeviceData: Map<String, String>): List<Void>? {
|
||||
return process { apiService.addPushDevice(pushDeviceData) }
|
||||
}
|
||||
|
||||
override fun deletePushDevice(regId: String): Flowable<List<Void>> {
|
||||
return apiService.deletePushDevice(regId).compose(configureApiCallObserver())
|
||||
override suspend fun deletePushDevice(regId: String): List<Void>? {
|
||||
return process { apiService.deletePushDevice(regId) }
|
||||
}
|
||||
|
||||
override fun getUserChallenges(page: Int, memberOnly: Boolean): Flowable<List<Challenge>> {
|
||||
override suspend fun getUserChallenges(page: Int, memberOnly: Boolean): List<Challenge>? {
|
||||
return if (memberOnly) {
|
||||
apiService.getUserChallenges(page, memberOnly).compose(configureApiCallObserver())
|
||||
process { apiService.getUserChallenges(page, memberOnly) }
|
||||
} else {
|
||||
apiService.getUserChallenges(page).compose(configureApiCallObserver())
|
||||
process { apiService.getUserChallenges(page) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getChallengeTasks(challengeId: String): Flowable<TaskList> {
|
||||
return apiService.getChallengeTasks(challengeId).compose(configureApiCallObserver())
|
||||
override suspend fun getChallengeTasks(challengeId: String): TaskList? {
|
||||
return process { apiService.getChallengeTasks(challengeId) }
|
||||
}
|
||||
|
||||
override fun getChallenge(challengeId: String): Flowable<Challenge> {
|
||||
return apiService.getChallenge(challengeId).compose(configureApiCallObserver())
|
||||
override suspend fun getChallenge(challengeId: String): Challenge? {
|
||||
return process { apiService.getChallenge(challengeId) }
|
||||
}
|
||||
|
||||
override fun joinChallenge(challengeId: String): Flowable<Challenge> {
|
||||
return apiService.joinChallenge(challengeId).compose(configureApiCallObserver())
|
||||
override suspend fun joinChallenge(challengeId: String): Challenge? {
|
||||
return process { apiService.joinChallenge(challengeId) }
|
||||
}
|
||||
|
||||
override fun leaveChallenge(challengeId: String, body: LeaveChallengeBody): Flowable<Void> {
|
||||
return apiService.leaveChallenge(challengeId, body).compose(configureApiCallObserver())
|
||||
override suspend fun leaveChallenge(challengeId: String, body: LeaveChallengeBody): Void? {
|
||||
return process { apiService.leaveChallenge(challengeId, body) }
|
||||
}
|
||||
|
||||
override fun createChallenge(challenge: Challenge): Flowable<Challenge> {
|
||||
return apiService.createChallenge(challenge).compose(configureApiCallObserver())
|
||||
override suspend fun createChallenge(challenge: Challenge): Challenge? {
|
||||
return process { apiService.createChallenge(challenge) }
|
||||
}
|
||||
|
||||
override fun createChallengeTasks(challengeId: String, tasks: List<Task>): Flowable<List<Task>> {
|
||||
return apiService.createChallengeTasks(challengeId, tasks).compose(configureApiCallObserver())
|
||||
override suspend fun createChallengeTasks(challengeId: String, tasks: List<Task>): List<Task>? {
|
||||
return process { apiService.createChallengeTasks(challengeId, tasks) }
|
||||
}
|
||||
|
||||
override fun createChallengeTask(challengeId: String, task: Task): Flowable<Task> {
|
||||
return apiService.createChallengeTask(challengeId, task).compose(configureApiCallObserver())
|
||||
override suspend fun createChallengeTask(challengeId: String, task: Task): Task? {
|
||||
return process { apiService.createChallengeTask(challengeId, task) }
|
||||
}
|
||||
|
||||
override fun updateChallenge(challenge: Challenge): Flowable<Challenge> {
|
||||
return apiService.updateChallenge(challenge.id ?: "", challenge).compose(configureApiCallObserver())
|
||||
override suspend fun updateChallenge(challenge: Challenge): Challenge? {
|
||||
return process { apiService.updateChallenge(challenge.id ?: "", challenge) }
|
||||
}
|
||||
|
||||
override fun deleteChallenge(challengeId: String): Flowable<Void> {
|
||||
return apiService.deleteChallenge(challengeId).compose(configureApiCallObserver())
|
||||
override suspend fun deleteChallenge(challengeId: String): Void? {
|
||||
return process { apiService.deleteChallenge(challengeId) }
|
||||
}
|
||||
|
||||
override fun debugAddTenGems(): Flowable<Void> {
|
||||
return apiService.debugAddTenGems().compose(configureApiCallObserver())
|
||||
override suspend fun debugAddTenGems(): Void? {
|
||||
return process { apiService.debugAddTenGems() }
|
||||
}
|
||||
|
||||
override fun readNotification(notificationId: String): Flowable<List<Any>> {
|
||||
return apiService.readNotification(notificationId).compose(configureApiCallObserver())
|
||||
override suspend fun readNotification(notificationId: String): List<Any>? {
|
||||
return process { apiService.readNotification(notificationId) }
|
||||
}
|
||||
|
||||
override fun readNotifications(notificationIds: Map<String, List<String>>): Flowable<List<Any>> {
|
||||
return apiService.readNotifications(notificationIds).compose(configureApiCallObserver())
|
||||
override suspend fun readNotifications(notificationIds: Map<String, List<String>>): List<Any>? {
|
||||
return process { apiService.readNotifications(notificationIds) }
|
||||
}
|
||||
|
||||
override fun seeNotifications(notificationIds: Map<String, List<String>>): Flowable<List<Any>> {
|
||||
return apiService.seeNotifications(notificationIds).compose(configureApiCallObserver())
|
||||
override suspend fun seeNotifications(notificationIds: Map<String, List<String>>): List<Any>? {
|
||||
return process { apiService.seeNotifications(notificationIds) }
|
||||
}
|
||||
|
||||
override fun openMysteryItem(): Flowable<Equipment> {
|
||||
return apiService.openMysteryItem().compose(configureApiCallObserver())
|
||||
override suspend fun openMysteryItem(): Equipment? {
|
||||
return process { apiService.openMysteryItem() }
|
||||
}
|
||||
|
||||
override fun runCron(): Flowable<Void> {
|
||||
return apiService.runCron().compose(configureApiCallObserver())
|
||||
override suspend fun runCron(): Void? {
|
||||
return process { apiService.runCron() }
|
||||
}
|
||||
|
||||
override suspend fun reroll(): User? = process { apiService.reroll() }
|
||||
|
||||
override fun resetAccount(): Flowable<Void> {
|
||||
return apiService.resetAccount().compose(configureApiCallObserver())
|
||||
override suspend fun resetAccount(): Void? {
|
||||
return process { apiService.resetAccount() }
|
||||
}
|
||||
|
||||
override fun deleteAccount(password: String): Flowable<Void> {
|
||||
override suspend fun deleteAccount(password: String): Void? {
|
||||
val updateObject = HashMap<String, String>()
|
||||
updateObject["password"] = password
|
||||
return apiService.deleteAccount(updateObject).compose(configureApiCallObserver())
|
||||
return process { apiService.deleteAccount(updateObject) }
|
||||
}
|
||||
|
||||
override suspend fun togglePinnedItem(pinType: String, path: String): Void? {
|
||||
return process { apiService.togglePinnedItem(pinType, path) }
|
||||
}
|
||||
|
||||
override fun sendPasswordResetEmail(email: String): Flowable<Void> {
|
||||
override suspend fun sendPasswordResetEmail(email: String): Void? {
|
||||
val data = HashMap<String, String>()
|
||||
data["email"] = email
|
||||
return apiService.sendPasswordResetEmail(data).compose(configureApiCallObserver())
|
||||
return process { apiService.sendPasswordResetEmail(data) }
|
||||
}
|
||||
|
||||
override suspend fun updateLoginName(newLoginName: String, password: String): Void? {
|
||||
|
|
@ -764,55 +733,55 @@ class ApiClientImpl(
|
|||
return process { apiService.updateLoginName(updateObject) }
|
||||
}
|
||||
|
||||
override fun verifyUsername(username: String): Flowable<VerifyUsernameResponse> {
|
||||
override suspend fun verifyUsername(username: String): VerifyUsernameResponse? {
|
||||
val updateObject = HashMap<String, String>()
|
||||
updateObject["username"] = username
|
||||
return this.apiService.verifyUsername(updateObject).compose(configureApiCallObserver())
|
||||
return process { this.apiService.verifyUsername(updateObject) }
|
||||
}
|
||||
|
||||
override fun updateEmail(newEmail: String, password: String): Flowable<Void> {
|
||||
override suspend fun updateEmail(newEmail: String, password: String): Void? {
|
||||
val updateObject = HashMap<String, String>()
|
||||
updateObject["newEmail"] = newEmail
|
||||
if (password.isNotBlank()) {
|
||||
updateObject["password"] = password
|
||||
}
|
||||
return apiService.updateEmail(updateObject).compose(configureApiCallObserver())
|
||||
return process { apiService.updateEmail(updateObject) }
|
||||
}
|
||||
|
||||
override fun updatePassword(
|
||||
override suspend fun updatePassword(
|
||||
oldPassword: String,
|
||||
newPassword: String,
|
||||
newPasswordConfirmation: String
|
||||
): Flowable<Void> {
|
||||
): Void? {
|
||||
val updateObject = HashMap<String, String>()
|
||||
updateObject["password"] = oldPassword
|
||||
updateObject["newPassword"] = newPassword
|
||||
updateObject["confirmPassword"] = newPasswordConfirmation
|
||||
return apiService.updatePassword(updateObject).compose(configureApiCallObserver())
|
||||
return process { apiService.updatePassword(updateObject) }
|
||||
}
|
||||
|
||||
override fun allocatePoint(stat: String): Flowable<Stats> {
|
||||
return apiService.allocatePoint(stat).compose(configureApiCallObserver())
|
||||
override suspend fun allocatePoint(stat: String): Stats? {
|
||||
return process { apiService.allocatePoint(stat) }
|
||||
}
|
||||
|
||||
override fun transferGems(giftedID: String, amount: Int): Flowable<Void> {
|
||||
return apiService.transferGems(mapOf(Pair("toUserId", giftedID), Pair("gemAmount", amount))).compose(configureApiCallObserver())
|
||||
override suspend fun transferGems(giftedID: String, amount: Int): Void? {
|
||||
return process { apiService.transferGems(mapOf(Pair("toUserId", giftedID), Pair("gemAmount", amount))) }
|
||||
}
|
||||
|
||||
override fun getTeamPlans(): Flowable<List<TeamPlan>> {
|
||||
return apiService.getTeamPlans().compose(configureApiCallObserver())
|
||||
override suspend fun getTeamPlans(): List<TeamPlan>? {
|
||||
return process { apiService.getTeamPlans() }
|
||||
}
|
||||
|
||||
override suspend fun getTeamPlanTasks(teamID: String): TaskList? {
|
||||
return processResponse(apiService.getTeamPlanTasks(teamID))
|
||||
}
|
||||
|
||||
override fun bulkAllocatePoints(
|
||||
override suspend fun bulkAllocatePoints(
|
||||
strength: Int,
|
||||
intelligence: Int,
|
||||
constitution: Int,
|
||||
perception: Int
|
||||
): Flowable<Stats> {
|
||||
): Stats? {
|
||||
val body = HashMap<String, Map<String, Int>>()
|
||||
val stats = HashMap<String, Int>()
|
||||
stats["str"] = strength
|
||||
|
|
@ -820,11 +789,11 @@ class ApiClientImpl(
|
|||
stats["con"] = constitution
|
||||
stats["per"] = perception
|
||||
body["stats"] = stats
|
||||
return apiService.bulkAllocatePoints(body).compose(configureApiCallObserver())
|
||||
return process { apiService.bulkAllocatePoints(body) }
|
||||
}
|
||||
|
||||
override fun retrieveMarketGear(): Flowable<Shop> {
|
||||
return apiService.retrieveMarketGear(languageCode).compose(configureApiCallObserver())
|
||||
override suspend fun retrieveMarketGear(): Shop? {
|
||||
return process { apiService.retrieveMarketGear(languageCode) }
|
||||
}
|
||||
|
||||
override suspend fun getWorldState(): WorldState? = process { apiService.worldState() }
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ import com.habitrpg.android.habitica.models.tasks.Task
|
|||
import com.habitrpg.android.habitica.models.tasks.TaskList
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.shared.habitica.models.tasks.TasksOrder
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import retrofit2.HttpException
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class ChallengeRepositoryImpl(
|
||||
localRepository: ChallengeLocalRepository,
|
||||
|
|
@ -19,47 +18,42 @@ class ChallengeRepositoryImpl(
|
|||
userID: String
|
||||
) : BaseRepositoryImpl<ChallengeLocalRepository>(localRepository, apiClient, userID), ChallengeRepository {
|
||||
|
||||
override fun isChallengeMember(challengeID: String): Flowable<Boolean> {
|
||||
override fun isChallengeMember(challengeID: String): Flow<Boolean> {
|
||||
return localRepository.isChallengeMember(userID, challengeID)
|
||||
}
|
||||
|
||||
override fun getChallengepMembership(id: String): Flowable<ChallengeMembership> {
|
||||
override fun getChallengepMembership(id: String): Flow<ChallengeMembership> {
|
||||
return localRepository.getChallengeMembership(userID, id)
|
||||
}
|
||||
|
||||
override fun getChallengeMemberships(): Flowable<out List<ChallengeMembership>> {
|
||||
override fun getChallengeMemberships(): Flow<List<ChallengeMembership>> {
|
||||
return localRepository.getChallengeMemberships(userID)
|
||||
}
|
||||
|
||||
override fun getChallenge(challengeId: String): Flowable<Challenge> {
|
||||
override fun getChallenge(challengeId: String): Flow<Challenge> {
|
||||
return localRepository.getChallenge(challengeId)
|
||||
}
|
||||
|
||||
override fun getChallengeTasks(challengeId: String): Flowable<out List<Task>> {
|
||||
override fun getChallengeTasks(challengeId: String): Flow<List<Task>> {
|
||||
return localRepository.getTasks(challengeId)
|
||||
}
|
||||
|
||||
override fun retrieveChallenge(challengeID: String): Flowable<Challenge> {
|
||||
return apiClient.getChallenge(challengeID).doOnNext {
|
||||
localRepository.save(it)
|
||||
}
|
||||
.doOnError {
|
||||
if (it is HttpException && it.code() == 404) {
|
||||
localRepository.getChallenge(challengeID).firstElement().subscribe { challenge ->
|
||||
localRepository.delete(challenge)
|
||||
}
|
||||
}
|
||||
}
|
||||
override suspend fun retrieveChallenge(challengeID: String): Challenge? {
|
||||
val challenge = apiClient.getChallenge(challengeID) ?: return null
|
||||
localRepository.save(challenge)
|
||||
return challenge
|
||||
}
|
||||
|
||||
override fun retrieveChallengeTasks(challengeID: String): Flowable<TaskList> {
|
||||
return apiClient.getChallengeTasks(challengeID).doOnNext { tasks ->
|
||||
override suspend fun retrieveChallengeTasks(challengeID: String): TaskList? {
|
||||
val tasks = apiClient.getChallengeTasks(challengeID)
|
||||
if (tasks != null) {
|
||||
val taskList = tasks.tasks.values.toList()
|
||||
taskList.forEach {
|
||||
it.userId = challengeID
|
||||
}
|
||||
localRepository.save(taskList)
|
||||
}
|
||||
return tasks
|
||||
}
|
||||
|
||||
private fun getTaskOrders(taskList: List<Task>): TasksOrder {
|
||||
|
|
@ -81,75 +75,81 @@ class ChallengeRepositoryImpl(
|
|||
return tasksOrder
|
||||
}
|
||||
|
||||
private fun addChallengeTasks(challenge: Challenge, addedTaskList: List<Task>): Flowable<Challenge> {
|
||||
return when {
|
||||
addedTaskList.count() == 1 -> apiClient.createChallengeTask(challenge.id ?: "", addedTaskList[0]).map { challenge }
|
||||
addedTaskList.count() > 1 -> apiClient.createChallengeTasks(challenge.id ?: "", addedTaskList).map { challenge }
|
||||
else -> Flowable.just(challenge)
|
||||
private suspend fun addChallengeTasks(challenge: Challenge, addedTaskList: List<Task>) {
|
||||
when {
|
||||
addedTaskList.count() == 1 -> apiClient.createChallengeTask(challenge.id ?: "", addedTaskList[0])
|
||||
addedTaskList.count() > 1 -> apiClient.createChallengeTasks(challenge.id ?: "", addedTaskList)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createChallenge(challenge: Challenge, taskList: List<Task>): Flowable<Challenge> {
|
||||
override suspend fun createChallenge(challenge: Challenge, taskList: List<Task>): Challenge? {
|
||||
challenge.tasksOrder = getTaskOrders(taskList)
|
||||
|
||||
return apiClient.createChallenge(challenge).flatMap {
|
||||
addChallengeTasks(it, taskList)
|
||||
val createdChallenge = apiClient.createChallenge(challenge)
|
||||
if (createdChallenge != null) {
|
||||
addChallengeTasks(createdChallenge, taskList)
|
||||
}
|
||||
return createdChallenge
|
||||
}
|
||||
|
||||
override fun updateChallenge(
|
||||
override suspend fun updateChallenge(
|
||||
challenge: Challenge,
|
||||
fullTaskList: List<Task>,
|
||||
addedTaskList: List<Task>,
|
||||
updatedTaskList: List<Task>,
|
||||
removedTaskList: List<String>
|
||||
): Flowable<Challenge> {
|
||||
|
||||
var flowable: Flowable<*> = Flowable.just("")
|
||||
|
||||
): Challenge? {
|
||||
updatedTaskList
|
||||
.map { localRepository.getUnmanagedCopy(it) }
|
||||
.forEach { task ->
|
||||
flowable = flowable.flatMap { apiClient.updateTask(task.id ?: "", task) }
|
||||
apiClient.updateTask(task.id ?: "", task)
|
||||
}
|
||||
|
||||
removedTaskList.forEach { task ->
|
||||
flowable = flowable.flatMap { apiClient.deleteTask(task) }
|
||||
apiClient.deleteTask(task)
|
||||
}
|
||||
if (addedTaskList.isNotEmpty()) {
|
||||
flowable = flowable.flatMap { addChallengeTasks(challenge, addedTaskList) }
|
||||
addChallengeTasks(challenge, addedTaskList)
|
||||
}
|
||||
|
||||
challenge.tasksOrder = getTaskOrders(fullTaskList)
|
||||
|
||||
return flowable.flatMap { apiClient.updateChallenge(challenge) }
|
||||
.doOnNext { localRepository.save(challenge) }
|
||||
val updatedChallenges = apiClient.updateChallenge(challenge)
|
||||
if (updatedChallenges != null) {
|
||||
localRepository.save(updatedChallenges)
|
||||
}
|
||||
return updatedChallenges
|
||||
}
|
||||
|
||||
override fun deleteChallenge(challengeId: String): Flowable<Void> {
|
||||
override suspend fun deleteChallenge(challengeId: String): Void? {
|
||||
return apiClient.deleteChallenge(challengeId)
|
||||
}
|
||||
|
||||
override fun getChallenges(): Flowable<out List<Challenge>> {
|
||||
override fun getChallenges(): Flow<List<Challenge>> {
|
||||
return localRepository.challenges
|
||||
}
|
||||
|
||||
override fun getUserChallenges(userId: String?): Flowable<out List<Challenge>> {
|
||||
override fun getUserChallenges(userId: String?): Flow<List<Challenge>> {
|
||||
return localRepository.getUserChallenges(userId ?: userID)
|
||||
}
|
||||
|
||||
override fun retrieveChallenges(page: Int, memberOnly: Boolean): Flowable<List<Challenge>> {
|
||||
return apiClient.getUserChallenges(page, memberOnly)
|
||||
.doOnNext { localRepository.saveChallenges(it, page == 0, memberOnly, userID) }
|
||||
override suspend fun retrieveChallenges(page: Int, memberOnly: Boolean): List<Challenge>? {
|
||||
val challenges = apiClient.getUserChallenges(page, memberOnly)
|
||||
if (challenges != null) {
|
||||
localRepository.saveChallenges(challenges, page == 0, memberOnly, userID)
|
||||
}
|
||||
return challenges
|
||||
}
|
||||
|
||||
override fun leaveChallenge(challenge: Challenge, keepTasks: String): Flowable<Void> {
|
||||
return apiClient.leaveChallenge(challenge.id ?: "", LeaveChallengeBody(keepTasks))
|
||||
.doOnNext { localRepository.setParticipating(userID, challenge.id ?: "", false) }
|
||||
override suspend fun leaveChallenge(challenge: Challenge, keepTasks: String): Void? {
|
||||
apiClient.leaveChallenge(challenge.id ?: "", LeaveChallengeBody(keepTasks))
|
||||
localRepository.setParticipating(userID, challenge.id ?: "", false)
|
||||
return null
|
||||
}
|
||||
|
||||
override fun joinChallenge(challenge: Challenge): Flowable<Challenge> {
|
||||
return apiClient.joinChallenge(challenge.id ?: "")
|
||||
.doOnNext { localRepository.setParticipating(userID, challenge.id ?: "", true) }
|
||||
override suspend fun joinChallenge(challenge: Challenge): Challenge? {
|
||||
val returnedChallenge = apiClient.joinChallenge(challenge.id ?: "") ?: return null
|
||||
localRepository.setParticipating(userID, returnedChallenge.id ?: "", true)
|
||||
return returnedChallenge
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import com.habitrpg.android.habitica.helpers.AprilFoolsHandler
|
|||
import com.habitrpg.android.habitica.models.ContentResult
|
||||
import com.habitrpg.android.habitica.models.WorldState
|
||||
import com.habitrpg.android.habitica.models.inventory.SpecialItem
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.RealmList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.util.Date
|
||||
|
||||
class ContentRepositoryImpl<T : ContentLocalRepository>(
|
||||
|
|
@ -52,7 +52,7 @@ class ContentRepositoryImpl<T : ContentLocalRepository>(
|
|||
return null
|
||||
}
|
||||
|
||||
override fun getWorldState(): Flowable<WorldState> {
|
||||
override fun getWorldState(): Flow<WorldState> {
|
||||
return localRepository.getWorldState()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.habitrpg.android.habitica.data.ApiClient
|
|||
import com.habitrpg.android.habitica.data.CustomizationRepository
|
||||
import com.habitrpg.android.habitica.data.local.CustomizationLocalRepository
|
||||
import com.habitrpg.android.habitica.models.inventory.Customization
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class CustomizationRepositoryImpl(
|
||||
localRepository: CustomizationLocalRepository,
|
||||
|
|
@ -12,7 +12,7 @@ class CustomizationRepositoryImpl(
|
|||
userID: String
|
||||
) : BaseRepositoryImpl<CustomizationLocalRepository>(localRepository, apiClient, userID), CustomizationRepository {
|
||||
|
||||
override fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flowable<out List<Customization>> {
|
||||
override fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flow<List<Customization>> {
|
||||
return localRepository.getCustomizations(type, category, onlyAvailable)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ import com.habitrpg.android.habitica.data.ApiClient
|
|||
import com.habitrpg.android.habitica.data.FAQRepository
|
||||
import com.habitrpg.android.habitica.data.local.FAQLocalRepository
|
||||
import com.habitrpg.android.habitica.models.FAQArticle
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class FAQRepositoryImpl(localRepository: FAQLocalRepository, apiClient: ApiClient, userID: String) : BaseRepositoryImpl<FAQLocalRepository>(localRepository, apiClient, userID), FAQRepository {
|
||||
override fun getArticle(position: Int): Flowable<FAQArticle> {
|
||||
override fun getArticle(position: Int): Flow<FAQArticle> {
|
||||
return localRepository.getArticle(position)
|
||||
}
|
||||
|
||||
override fun getArticles(): Flowable<out List<FAQArticle>> {
|
||||
override fun getArticles(): Flow<List<FAQArticle>> {
|
||||
return localRepository.articles
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ import com.habitrpg.android.habitica.models.user.OwnedMount
|
|||
import com.habitrpg.android.habitica.models.user.OwnedPet
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.shared.habitica.models.responses.FeedResponse
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
|
||||
class InventoryRepositoryImpl(
|
||||
localRepository: InventoryLocalRepository,
|
||||
|
|
@ -35,7 +35,7 @@ class InventoryRepositoryImpl(
|
|||
|
||||
override fun getQuestContent(key: String) = localRepository.getQuestContent(key)
|
||||
|
||||
override fun getEquipment(searchedKeys: List<String>): Flowable<out List<Equipment>> {
|
||||
override fun getEquipment(searchedKeys: List<String>): Flow<List<Equipment>> {
|
||||
return localRepository.getEquipment(searchedKeys)
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ class InventoryRepositoryImpl(
|
|||
return localRepository.getArmoireRemainingCount()
|
||||
}
|
||||
|
||||
override fun getInAppRewards(): Flowable<out List<ShopItem>> {
|
||||
override fun getInAppRewards(): Flow<List<ShopItem>> {
|
||||
return localRepository.getInAppRewards()
|
||||
}
|
||||
|
||||
|
|
@ -55,15 +55,15 @@ class InventoryRepositoryImpl(
|
|||
return rewards
|
||||
}
|
||||
|
||||
override fun getOwnedEquipment(type: String): Flowable<out List<Equipment>> {
|
||||
override fun getOwnedEquipment(type: String): Flow<List<Equipment>> {
|
||||
return localRepository.getOwnedEquipment(type)
|
||||
}
|
||||
|
||||
override fun getOwnedEquipment(): Flowable<out List<Equipment>> {
|
||||
override fun getOwnedEquipment(): Flow<List<Equipment>> {
|
||||
return localRepository.getOwnedEquipment()
|
||||
}
|
||||
|
||||
override fun getEquipmentType(type: String, set: String): Flowable<out List<Equipment>> {
|
||||
override fun getEquipmentType(type: String, set: String): Flow<List<Equipment>> {
|
||||
return localRepository.getEquipmentType(type, set)
|
||||
}
|
||||
|
||||
|
|
@ -71,36 +71,31 @@ class InventoryRepositoryImpl(
|
|||
return localRepository.getOwnedItems(itemType, userID, includeZero)
|
||||
}
|
||||
|
||||
override fun getOwnedItems(includeZero: Boolean): Flowable<Map<String, OwnedItem>> {
|
||||
override fun getOwnedItems(includeZero: Boolean): Flow<Map<String, OwnedItem>> {
|
||||
return localRepository.getOwnedItems(userID, includeZero)
|
||||
}
|
||||
|
||||
override fun getItems(itemClass: Class<out Item>, keys: Array<String>): Flow<List<Item>> {
|
||||
return localRepository.getItemsFlowable(itemClass, keys)
|
||||
}
|
||||
|
||||
override fun getItemsFlowable(itemClass: Class<out Item>): Flowable<out List<Item>> {
|
||||
return localRepository.getItemsFlowable(itemClass)
|
||||
return localRepository.getItems(itemClass, keys)
|
||||
}
|
||||
|
||||
override fun getItems(itemClass: Class<out Item>): Flow<List<Item>> {
|
||||
return localRepository.getItems(itemClass)
|
||||
}
|
||||
|
||||
override fun getEquipment(key: String): Flowable<Equipment> {
|
||||
override fun getEquipment(key: String): Flow<Equipment> {
|
||||
return localRepository.getEquipment(key)
|
||||
}
|
||||
|
||||
override fun openMysteryItem(user: User?): Flowable<Equipment> {
|
||||
return apiClient.openMysteryItem()
|
||||
.flatMap { localRepository.getEquipment(it.key ?: "").firstElement().toFlowable() }
|
||||
.doOnNext { itemData ->
|
||||
val liveEquipment = localRepository.getLiveObject(itemData)
|
||||
localRepository.executeTransaction {
|
||||
liveEquipment?.owned = true
|
||||
}
|
||||
localRepository.decrementMysteryItemCount(user)
|
||||
}
|
||||
override suspend fun openMysteryItem(user: User?): Equipment? {
|
||||
val item = apiClient.openMysteryItem()
|
||||
val equipment = localRepository.getEquipment(item?.key ?: "").firstOrNull() ?: return null
|
||||
val liveEquipment = localRepository.getLiveObject(equipment)
|
||||
localRepository.executeTransaction {
|
||||
liveEquipment?.owned = true
|
||||
}
|
||||
localRepository.decrementMysteryItemCount(user)
|
||||
return equipment
|
||||
}
|
||||
|
||||
override fun saveEquipment(equipment: Equipment) {
|
||||
|
|
@ -135,44 +130,42 @@ class InventoryRepositoryImpl(
|
|||
localRepository.updateOwnedEquipment(user)
|
||||
}
|
||||
|
||||
override fun changeOwnedCount(type: String, key: String, amountToAdd: Int) {
|
||||
override suspend fun changeOwnedCount(type: String, key: String, amountToAdd: Int) {
|
||||
localRepository.changeOwnedCount(type, key, userID, amountToAdd)
|
||||
}
|
||||
|
||||
override fun sellItem(type: String, key: String): Flowable<User> {
|
||||
return localRepository.getOwnedItem(userID, type, key, true)
|
||||
.flatMap { item -> sellItem(item) }
|
||||
override suspend fun sellItem(type: String, key: String): User? {
|
||||
val item = localRepository.getOwnedItem(userID, type, key, true).firstOrNull() ?: return null
|
||||
return sellItem(item)
|
||||
}
|
||||
|
||||
override fun sellItem(item: OwnedItem): Flowable<User> {
|
||||
return localRepository.getItem(item.itemType ?: "", item.key ?: "")
|
||||
.flatMap { newItem -> sellItem(newItem, item) }
|
||||
override suspend fun sellItem(ownedItem: OwnedItem): User? {
|
||||
val item = localRepository.getItem(ownedItem.itemType ?: "", ownedItem.key ?: "").firstOrNull() ?: return null
|
||||
return sellItem(item, ownedItem)
|
||||
}
|
||||
|
||||
override fun getLatestMysteryItem(): Flowable<Equipment> {
|
||||
override fun getLatestMysteryItem(): Flow<Equipment> {
|
||||
return localRepository.getLatestMysteryItem()
|
||||
}
|
||||
|
||||
override fun getItem(type: String, key: String): Flowable<Item> {
|
||||
override fun getItem(type: String, key: String): Flow<Item> {
|
||||
return localRepository.getItem(type, key)
|
||||
}
|
||||
|
||||
private fun sellItem(item: Item, ownedItem: OwnedItem): Flowable<User> {
|
||||
private suspend fun sellItem(item: Item, ownedItem: OwnedItem): User? {
|
||||
localRepository.executeTransaction {
|
||||
val liveItem = localRepository.getLiveObject(ownedItem)
|
||||
liveItem?.numberOwned = (liveItem?.numberOwned ?: 0) - 1
|
||||
}
|
||||
return apiClient.sellItem(item.type, item.key)
|
||||
.map { user ->
|
||||
localRepository.soldItem(userID, user)
|
||||
}
|
||||
val user = apiClient.sellItem(item.type, item.key) ?: return null
|
||||
return localRepository.soldItem(userID, user)
|
||||
}
|
||||
|
||||
override fun equipGear(equipment: String, asCostume: Boolean): Flowable<Items> {
|
||||
override suspend fun equipGear(equipment: String, asCostume: Boolean): Items? {
|
||||
return equip(if (asCostume) "costume" else "equipped", equipment)
|
||||
}
|
||||
|
||||
override fun equip(type: String, key: String): Flowable<Items> {
|
||||
override suspend fun equip(type: String, key: String): Items? {
|
||||
val liveUser = localRepository.getLiveUser(userID)
|
||||
|
||||
if (liveUser != null) {
|
||||
|
|
@ -199,47 +192,45 @@ class InventoryRepositoryImpl(
|
|||
}
|
||||
}
|
||||
}
|
||||
return apiClient.equipItem(type, key)
|
||||
.doOnNext { items ->
|
||||
if (liveUser == null) return@doOnNext
|
||||
localRepository.modify(liveUser) { liveUser ->
|
||||
val newEquipped = items.gear?.equipped
|
||||
val oldEquipped = liveUser.items?.gear?.equipped
|
||||
val newCostume = items.gear?.costume
|
||||
val oldCostume = liveUser.items?.gear?.costume
|
||||
newEquipped?.let { equipped -> oldEquipped?.updateWith(equipped) }
|
||||
newCostume?.let { costume -> oldCostume?.updateWith(costume) }
|
||||
liveUser.items?.currentMount = items.currentMount
|
||||
liveUser.items?.currentPet = items.currentPet
|
||||
liveUser.balance = liveUser.balance
|
||||
}
|
||||
}
|
||||
val items = apiClient.equipItem(type, key) ?: return null
|
||||
if (liveUser == null) return null
|
||||
localRepository.modify(liveUser) { liveUser ->
|
||||
val newEquipped = items.gear?.equipped
|
||||
val oldEquipped = liveUser.items?.gear?.equipped
|
||||
val newCostume = items.gear?.costume
|
||||
val oldCostume = liveUser.items?.gear?.costume
|
||||
newEquipped?.let { equipped -> oldEquipped?.updateWith(equipped) }
|
||||
newCostume?.let { costume -> oldCostume?.updateWith(costume) }
|
||||
liveUser.items?.currentMount = items.currentMount
|
||||
liveUser.items?.currentPet = items.currentPet
|
||||
liveUser.balance = liveUser.balance
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
override fun feedPet(pet: Pet, food: Food): Flowable<FeedResponse> {
|
||||
return apiClient.feedPet(pet.key ?: "", food.key)
|
||||
.doOnNext { feedResponse ->
|
||||
localRepository.feedPet(food.key, pet.key ?: "", feedResponse.value ?: 0, userID)
|
||||
}
|
||||
override suspend fun feedPet(pet: Pet, food: Food): FeedResponse? {
|
||||
val feedResponse = apiClient.feedPet(pet.key ?: "", food.key) ?: return null
|
||||
localRepository.feedPet(food.key, pet.key ?: "", feedResponse.value ?: 0, userID)
|
||||
return feedResponse
|
||||
}
|
||||
|
||||
override fun hatchPet(egg: Egg, hatchingPotion: HatchingPotion, successFunction: () -> Unit): Flowable<Items> {
|
||||
override suspend fun hatchPet(egg: Egg, hatchingPotion: HatchingPotion, successFunction: () -> Unit): Items? {
|
||||
if (appConfigManager.enableLocalChanges()) {
|
||||
localRepository.hatchPet(egg.key, hatchingPotion.key, userID)
|
||||
successFunction()
|
||||
}
|
||||
return apiClient.hatchPet(egg.key, hatchingPotion.key)
|
||||
.doOnNext {
|
||||
localRepository.save(it, userID)
|
||||
if (!appConfigManager.enableLocalChanges()) {
|
||||
successFunction()
|
||||
}
|
||||
}
|
||||
val items = apiClient.hatchPet(egg.key, hatchingPotion.key) ?: return null
|
||||
localRepository.save(items, userID)
|
||||
if (!appConfigManager.enableLocalChanges()) {
|
||||
successFunction()
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
override fun inviteToQuest(quest: QuestContent): Flowable<Quest> {
|
||||
return apiClient.inviteToQuest("party", quest.key)
|
||||
.doOnNext { localRepository.changeOwnedCount("quests", quest.key, userID, -1) }
|
||||
override suspend fun inviteToQuest(quest: QuestContent): Quest? {
|
||||
val newQuest = apiClient.inviteToQuest("party", quest.key)
|
||||
localRepository.changeOwnedCount("quests", quest.key, userID, -1)
|
||||
return newQuest
|
||||
}
|
||||
|
||||
override suspend fun buyItem(user: User?, id: String, value: Double, purchaseQuantity: Int): BuyResponse? {
|
||||
|
|
@ -270,15 +261,15 @@ class InventoryRepositoryImpl(
|
|||
return buyResponse
|
||||
}
|
||||
|
||||
override fun getAvailableLimitedItems(): Flowable<List<Item>> {
|
||||
override fun getAvailableLimitedItems(): Flow<List<Item>> {
|
||||
return localRepository.getAvailableLimitedItems()
|
||||
}
|
||||
|
||||
override fun retrieveShopInventory(identifier: String): Flowable<Shop> {
|
||||
override suspend fun retrieveShopInventory(identifier: String): Shop? {
|
||||
return apiClient.retrieveShopIventory(identifier)
|
||||
}
|
||||
|
||||
override fun retrieveMarketGear(): Flowable<Shop> {
|
||||
override suspend fun retrieveMarketGear(): Shop? {
|
||||
return apiClient.retrieveMarketGear()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import com.habitrpg.android.habitica.BuildConfig
|
|||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.data.local.SocialLocalRepository
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.models.Achievement
|
||||
import com.habitrpg.android.habitica.models.inventory.Quest
|
||||
import com.habitrpg.android.habitica.models.members.Member
|
||||
|
|
@ -15,7 +14,6 @@ import com.habitrpg.android.habitica.models.social.Group
|
|||
import com.habitrpg.android.habitica.models.social.GroupMembership
|
||||
import com.habitrpg.android.habitica.models.social.InboxConversation
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
|
|
@ -38,13 +36,13 @@ class SocialRepositoryImpl(
|
|||
return retrievePartyMembers(groupID, true)
|
||||
}
|
||||
|
||||
override fun blockMember(userID: String): Flowable<List<String>> {
|
||||
override suspend fun blockMember(userID: String): List<String>? {
|
||||
return apiClient.blockMember(userID)
|
||||
}
|
||||
|
||||
override fun getGroupMembership(id: String) = localRepository.getGroupMembership(userID, id)
|
||||
|
||||
override fun getGroupMemberships(): Flowable<out List<GroupMembership>> {
|
||||
override fun getGroupMemberships(): Flow<List<GroupMembership>> {
|
||||
return localRepository.getGroupMemberships(userID)
|
||||
}
|
||||
|
||||
|
|
@ -54,18 +52,18 @@ class SocialRepositoryImpl(
|
|||
return messages
|
||||
}
|
||||
|
||||
override fun getGroupChat(groupId: String): Flowable<out List<ChatMessage>> {
|
||||
override fun getGroupChat(groupId: String): Flow<List<ChatMessage>> {
|
||||
return localRepository.getGroupChat(groupId)
|
||||
}
|
||||
|
||||
override fun markMessagesSeen(seenGroupId: String) {
|
||||
apiClient.seenMessages(seenGroupId).subscribe({ }, ExceptionHandler.rx())
|
||||
override suspend fun markMessagesSeen(seenGroupId: String) {
|
||||
apiClient.seenMessages(seenGroupId)
|
||||
}
|
||||
|
||||
override fun flagMessage(chatMessageID: String, additionalInfo: String, groupID: String?): Flowable<Void> {
|
||||
override suspend fun flagMessage(chatMessageID: String, additionalInfo: String, groupID: String?): Void? {
|
||||
return when {
|
||||
chatMessageID.isBlank() -> Flowable.empty()
|
||||
userID == BuildConfig.ANDROID_TESTING_UUID -> Flowable.empty()
|
||||
chatMessageID.isBlank() -> return null
|
||||
userID == BuildConfig.ANDROID_TESTING_UUID -> return null
|
||||
else -> {
|
||||
val data = mutableMapOf<String, String>()
|
||||
data["comment"] = additionalInfo
|
||||
|
|
@ -78,38 +76,36 @@ class SocialRepositoryImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override fun likeMessage(chatMessage: ChatMessage): Flowable<ChatMessage> {
|
||||
override suspend fun likeMessage(chatMessage: ChatMessage): ChatMessage? {
|
||||
if (chatMessage.id.isBlank()) {
|
||||
return Flowable.empty()
|
||||
return null
|
||||
}
|
||||
val liked = chatMessage.userLikesMessage(userID)
|
||||
if (chatMessage.isManaged) {
|
||||
localRepository.likeMessage(chatMessage, userID, !liked)
|
||||
}
|
||||
return apiClient.likeMessage(chatMessage.groupId ?: "", chatMessage.id)
|
||||
.map {
|
||||
it.groupId = chatMessage.groupId
|
||||
it
|
||||
}
|
||||
val message = apiClient.likeMessage(chatMessage.groupId ?: "", chatMessage.id)
|
||||
message?.groupId = chatMessage.groupId
|
||||
return null
|
||||
}
|
||||
|
||||
override fun deleteMessage(chatMessage: ChatMessage): Flowable<Void> {
|
||||
return if (chatMessage.isInboxMessage) {
|
||||
override suspend fun deleteMessage(chatMessage: ChatMessage): Void? {
|
||||
if (chatMessage.isInboxMessage) {
|
||||
apiClient.deleteInboxMessage(chatMessage.id)
|
||||
} else {
|
||||
apiClient.deleteMessage(chatMessage.groupId ?: "", chatMessage.id)
|
||||
}.doOnNext { localRepository.deleteMessage(chatMessage.id) }
|
||||
}
|
||||
localRepository.deleteMessage(chatMessage.id)
|
||||
return null
|
||||
}
|
||||
|
||||
override fun postGroupChat(groupId: String, messageObject: HashMap<String, String>): Flowable<PostChatMessageResult> {
|
||||
return apiClient.postGroupChat(groupId, messageObject)
|
||||
.map { postChatMessageResult ->
|
||||
postChatMessageResult.message.groupId = groupId
|
||||
postChatMessageResult
|
||||
}
|
||||
override suspend fun postGroupChat(groupId: String, messageObject: HashMap<String, String>): PostChatMessageResult? {
|
||||
val result = apiClient.postGroupChat(groupId, messageObject)
|
||||
result?.message?.groupId = groupId
|
||||
return result
|
||||
}
|
||||
|
||||
override fun postGroupChat(groupId: String, message: String): Flowable<PostChatMessageResult> {
|
||||
override suspend fun postGroupChat(groupId: String, message: String): PostChatMessageResult? {
|
||||
val messageObject = HashMap<String, String>()
|
||||
messageObject["message"] = message
|
||||
return postGroupChat(groupId, messageObject)
|
||||
|
|
@ -189,17 +185,16 @@ class SocialRepositoryImpl(
|
|||
return apiClient.updateGroup(copiedGroup.id, copiedGroup)
|
||||
}
|
||||
|
||||
override fun retrieveGroups(type: String): Flowable<List<Group>> {
|
||||
return apiClient.listGroups(type)
|
||||
.doOnNext { groups ->
|
||||
if ("guilds" == type) {
|
||||
val memberships = groups.map {
|
||||
GroupMembership(userID, it.id)
|
||||
}
|
||||
localRepository.saveGroupMemberships(userID, memberships)
|
||||
}
|
||||
localRepository.save(groups)
|
||||
override suspend fun retrieveGroups(type: String): List<Group>? {
|
||||
val groups = apiClient.listGroups(type) ?: return null
|
||||
if ("guilds" == type) {
|
||||
val memberships = groups.map {
|
||||
GroupMembership(userID, it.id)
|
||||
}
|
||||
localRepository.saveGroupMemberships(userID, memberships)
|
||||
}
|
||||
localRepository.save(groups)
|
||||
return groups
|
||||
}
|
||||
|
||||
override fun getGroups(type: String) = localRepository.getGroups(type)
|
||||
|
|
@ -219,14 +214,14 @@ class SocialRepositoryImpl(
|
|||
return messages
|
||||
}
|
||||
|
||||
override fun retrieveInboxConversations(): Flowable<List<InboxConversation>> {
|
||||
return apiClient.retrieveInboxConversations().doOnNext { conversations ->
|
||||
localRepository.saveInboxConversations(userID, conversations)
|
||||
}
|
||||
override suspend fun retrieveInboxConversations(): List<InboxConversation>? {
|
||||
val conversations = apiClient.retrieveInboxConversations() ?: return null
|
||||
localRepository.saveInboxConversations(userID, conversations)
|
||||
return conversations
|
||||
}
|
||||
|
||||
override suspend fun postPrivateMessage(recipientId: String, messageObject: HashMap<String, String>): List<ChatMessage>? {
|
||||
val message = apiClient.postPrivateMessage(messageObject)
|
||||
apiClient.postPrivateMessage(messageObject)
|
||||
return retrieveInboxMessages(recipientId, 0)
|
||||
}
|
||||
|
||||
|
|
@ -246,7 +241,7 @@ class SocialRepositoryImpl(
|
|||
return members
|
||||
}
|
||||
|
||||
override fun inviteToGroup(id: String, inviteData: Map<String, Any>): Flowable<List<Void>> = apiClient.inviteToGroup(id, inviteData)
|
||||
override suspend fun inviteToGroup(id: String, inviteData: Map<String, Any>) = apiClient.inviteToGroup(id, inviteData)
|
||||
|
||||
override suspend fun retrieveMember(userId: String?): Member? {
|
||||
return if (userId == null) {
|
||||
|
|
@ -264,11 +259,11 @@ class SocialRepositoryImpl(
|
|||
return retrieveMember(username)
|
||||
}
|
||||
|
||||
override fun findUsernames(username: String, context: String?, id: String?): Flowable<List<FindUsernameResult>> {
|
||||
override suspend fun findUsernames(username: String, context: String?, id: String?): List<FindUsernameResult>? {
|
||||
return apiClient.findUsernames(username, context, id)
|
||||
}
|
||||
|
||||
override fun markPrivateMessagesRead(user: User?): Flowable<Void> {
|
||||
override suspend fun markPrivateMessagesRead(user: User?): Void? {
|
||||
if (user?.isManaged == true) {
|
||||
localRepository.modify(user) {
|
||||
it.inbox?.hasUserSeenInbox = true
|
||||
|
|
@ -298,57 +293,57 @@ class SocialRepositoryImpl(
|
|||
|
||||
override fun getUserGroups(type: String?) = localRepository.getUserGroups(userID, type)
|
||||
|
||||
override fun acceptQuest(user: User?, partyId: String): Flowable<Void> {
|
||||
return apiClient.acceptQuest(partyId)
|
||||
.doOnNext {
|
||||
user?.let {
|
||||
localRepository.updateRSVPNeeded(it, false)
|
||||
}
|
||||
override suspend fun acceptQuest(user: User?, partyId: String): Void? {
|
||||
apiClient.acceptQuest(partyId)
|
||||
user?.let {
|
||||
localRepository.updateRSVPNeeded(it, false)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun rejectQuest(user: User?, partyId: String): Flowable<Void> {
|
||||
return apiClient.rejectQuest(partyId)
|
||||
.doOnNext { _ ->
|
||||
user?.let {
|
||||
localRepository.updateRSVPNeeded(it, false)
|
||||
}
|
||||
override suspend fun rejectQuest(user: User?, partyId: String): Void? {
|
||||
apiClient.rejectQuest(partyId)
|
||||
user?.let {
|
||||
localRepository.updateRSVPNeeded(it, false)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun leaveQuest(partyId: String): Flowable<Void> {
|
||||
override suspend fun leaveQuest(partyId: String): Void? {
|
||||
return apiClient.leaveQuest(partyId)
|
||||
}
|
||||
|
||||
override fun cancelQuest(partyId: String): Flowable<Void> {
|
||||
return apiClient.cancelQuest(partyId)
|
||||
.doOnNext { localRepository.removeQuest(partyId) }
|
||||
override suspend fun cancelQuest(partyId: String): Void? {
|
||||
apiClient.cancelQuest(partyId)
|
||||
localRepository.removeQuest(partyId)
|
||||
return null
|
||||
}
|
||||
|
||||
override fun abortQuest(partyId: String): Flowable<Quest> {
|
||||
return apiClient.abortQuest(partyId)
|
||||
.doOnNext { localRepository.removeQuest(partyId) }
|
||||
override suspend fun abortQuest(partyId: String): Quest? {
|
||||
val quest = apiClient.abortQuest(partyId)
|
||||
localRepository.removeQuest(partyId)
|
||||
return quest
|
||||
}
|
||||
|
||||
override fun rejectGroupInvite(groupId: String): Flowable<Void> {
|
||||
return apiClient.rejectGroupInvite(groupId)
|
||||
.doOnNext {
|
||||
localRepository.rejectGroupInvitation(userID, groupId)
|
||||
}
|
||||
override suspend fun rejectGroupInvite(groupId: String): Void? {
|
||||
apiClient.rejectGroupInvite(groupId)
|
||||
localRepository.rejectGroupInvitation(userID, groupId)
|
||||
return null
|
||||
}
|
||||
|
||||
override fun forceStartQuest(party: Group): Flowable<Quest> {
|
||||
return apiClient.forceStartQuest(party.id, localRepository.getUnmanagedCopy(party))
|
||||
.doOnNext { localRepository.setQuestActivity(party, true) }
|
||||
override suspend fun forceStartQuest(party: Group): Quest? {
|
||||
val quest = apiClient.forceStartQuest(party.id, localRepository.getUnmanagedCopy(party))
|
||||
localRepository.setQuestActivity(party, true)
|
||||
return quest
|
||||
}
|
||||
|
||||
override fun getMemberAchievements(userId: String?): Flowable<List<Achievement>> {
|
||||
override suspend fun getMemberAchievements(userId: String?): List<Achievement>? {
|
||||
return if (userId == null) {
|
||||
Flowable.empty()
|
||||
null
|
||||
} else apiClient.getMemberAchievements(userId)
|
||||
}
|
||||
|
||||
override fun transferGems(giftedID: String, amount: Int): Flowable<Void> {
|
||||
override suspend fun transferGems(giftedID: String, amount: Int): Void? {
|
||||
return apiClient.transferGems(giftedID, amount)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,58 +4,53 @@ import com.habitrpg.android.habitica.data.ApiClient
|
|||
import com.habitrpg.android.habitica.data.TagRepository
|
||||
import com.habitrpg.android.habitica.data.local.TagLocalRepository
|
||||
import com.habitrpg.android.habitica.models.Tag
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class TagRepositoryImpl(localRepository: TagLocalRepository, apiClient: ApiClient, userID: String) : BaseRepositoryImpl<TagLocalRepository>(localRepository, apiClient, userID), TagRepository {
|
||||
|
||||
override fun getTags(): Flowable<out List<Tag>> {
|
||||
override fun getTags(): Flow<List<Tag>> {
|
||||
return getTags(userID)
|
||||
}
|
||||
|
||||
override fun getTags(userId: String): Flowable<out List<Tag>> {
|
||||
override fun getTags(userId: String): Flow<List<Tag>> {
|
||||
return localRepository.getTags(userId)
|
||||
}
|
||||
|
||||
override fun createTag(tag: Tag): Flowable<Tag> {
|
||||
return apiClient.createTag(tag)
|
||||
.doOnNext {
|
||||
it.userId = userID
|
||||
localRepository.save(it)
|
||||
}
|
||||
override suspend fun createTag(tag: Tag): Tag? {
|
||||
val savedTag = apiClient.createTag(tag) ?: return null
|
||||
savedTag.userId = userID
|
||||
localRepository.save(savedTag)
|
||||
return savedTag
|
||||
}
|
||||
|
||||
override fun updateTag(tag: Tag): Flowable<Tag> {
|
||||
return apiClient.updateTag(tag.id, tag)
|
||||
.doOnNext {
|
||||
it.userId = userID
|
||||
localRepository.save(it)
|
||||
}
|
||||
override suspend fun updateTag(tag: Tag): Tag? {
|
||||
val savedTag = apiClient.updateTag(tag.id, tag) ?: return null
|
||||
savedTag.userId = userID
|
||||
localRepository.save(savedTag)
|
||||
return savedTag
|
||||
}
|
||||
|
||||
override fun deleteTag(id: String): Flowable<Void> {
|
||||
return apiClient.deleteTag(id)
|
||||
.doOnNext {
|
||||
localRepository.deleteTag(id)
|
||||
}
|
||||
override suspend fun deleteTag(id: String): Void? {
|
||||
apiClient.deleteTag(id)
|
||||
localRepository.deleteTag(id)
|
||||
return null
|
||||
}
|
||||
|
||||
override fun createTags(tags: Collection<Tag>): Single<List<Tag>> {
|
||||
return Flowable.defer { Flowable.fromIterable(tags) }
|
||||
.filter { tag -> tag.name.isNotEmpty() }
|
||||
.flatMap { this.createTag(it) }
|
||||
.toList()
|
||||
override suspend fun createTags(tags: Collection<Tag>): List<Tag> {
|
||||
return tags.mapNotNull {
|
||||
createTag(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateTags(tags: Collection<Tag>): Single<List<Tag>> {
|
||||
return Flowable.defer { Flowable.fromIterable(tags) }
|
||||
.flatMap { this.updateTag(it) }
|
||||
.toList()
|
||||
override suspend fun updateTags(tags: Collection<Tag>): List<Tag> {
|
||||
return tags.mapNotNull {
|
||||
updateTag(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun deleteTags(tagIds: Collection<String>): Single<List<Void>> {
|
||||
return Flowable.defer { Flowable.fromIterable(tagIds) }
|
||||
.flatMap { this.deleteTag(it) }
|
||||
.toList()
|
||||
override suspend fun deleteTags(tagIds: Collection<String>): List<Void> {
|
||||
return tagIds.mapNotNull {
|
||||
deleteTag(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import com.habitrpg.android.habitica.data.ApiClient
|
|||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.data.local.TaskLocalRepository
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.interactors.ScoreTaskLocallyInteractor
|
||||
import com.habitrpg.android.habitica.models.BaseMainObject
|
||||
import com.habitrpg.android.habitica.models.responses.BulkTaskScoringData
|
||||
|
|
@ -20,9 +20,7 @@ import com.habitrpg.shared.habitica.models.responses.TaskDirectionData
|
|||
import com.habitrpg.shared.habitica.models.responses.TaskScoringResult
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.shared.habitica.models.tasks.TasksOrder
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Maybe
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
|
@ -43,9 +41,6 @@ class TaskRepositoryImpl(
|
|||
override fun getTasks(taskType: TaskType, userID: String?, includedGroupIDs: Array<String>): Flow<List<Task>> =
|
||||
this.localRepository.getTasks(taskType, userID ?: this.userID, includedGroupIDs)
|
||||
|
||||
override fun getTasksFlowable(taskType: TaskType, userID: String?, includedGroupIDs: Array<String>): Flowable<out List<Task>> =
|
||||
this.localRepository.getTasksFlowable(taskType, userID ?: this.userID, includedGroupIDs)
|
||||
|
||||
override fun saveTasks(userId: String, order: TasksOrder, tasks: TaskList) {
|
||||
localRepository.saveTasks(userId, order, tasks)
|
||||
}
|
||||
|
|
@ -56,18 +51,18 @@ class TaskRepositoryImpl(
|
|||
return tasks
|
||||
}
|
||||
|
||||
override fun retrieveCompletedTodos(userId: String?): Flowable<TaskList> {
|
||||
return this.apiClient.getTasks("completedTodos")
|
||||
.doOnNext { taskList ->
|
||||
val tasks = taskList.tasks
|
||||
this.localRepository.saveCompletedTodos(userId ?: this.userID, tasks.values)
|
||||
}
|
||||
override suspend fun retrieveCompletedTodos(userId: String?): TaskList? {
|
||||
val taskList = this.apiClient.getTasks("completedTodos") ?: return null
|
||||
val tasks = taskList.tasks
|
||||
this.localRepository.saveCompletedTodos(userId ?: this.userID, tasks.values)
|
||||
return taskList
|
||||
}
|
||||
|
||||
override fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): Flowable<TaskList> {
|
||||
override suspend fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): TaskList? {
|
||||
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.US)
|
||||
return this.apiClient.getTasks("dailys", formatter.format(dueDate))
|
||||
.doOnNext { res -> this.localRepository.saveTasks(userId, tasksOrder, res) }
|
||||
val taskList = this.apiClient.getTasks("dailys", formatter.format(dueDate)) ?: return null
|
||||
this.localRepository.saveTasks(userId, tasksOrder, taskList)
|
||||
return taskList
|
||||
}
|
||||
|
||||
@Suppress("ReturnCount")
|
||||
|
|
@ -120,7 +115,7 @@ class TaskRepositoryImpl(
|
|||
return result
|
||||
}
|
||||
|
||||
override fun bulkScoreTasks(data: List<Map<String, String>>): Flowable<BulkTaskScoringData> {
|
||||
override suspend fun bulkScoreTasks(data: List<Map<String, String>>): BulkTaskScoringData? {
|
||||
return apiClient.bulkScoreTasks(data)
|
||||
}
|
||||
|
||||
|
|
@ -212,10 +207,10 @@ class TaskRepositoryImpl(
|
|||
|
||||
override fun getTaskCopy(taskId: String) = localRepository.getTaskCopy(taskId)
|
||||
|
||||
override fun createTask(task: Task, force: Boolean): Flowable<Task> {
|
||||
override suspend fun createTask(task: Task, force: Boolean): Task? {
|
||||
val now = Date().time
|
||||
if (lastTaskAction > now - 500 && !force) {
|
||||
return Flowable.empty()
|
||||
return null
|
||||
}
|
||||
lastTaskAction = now
|
||||
|
||||
|
|
@ -228,61 +223,56 @@ class TaskRepositoryImpl(
|
|||
}
|
||||
localRepository.saveSyncronous(task)
|
||||
|
||||
return apiClient.createTask(task)
|
||||
.map { task1 ->
|
||||
task1.dateCreated = Date()
|
||||
task1
|
||||
}
|
||||
.doOnNext {
|
||||
it.tags = task.tags
|
||||
localRepository.save(it)
|
||||
}
|
||||
.doOnError {
|
||||
task.hasErrored = true
|
||||
task.isSaving = false
|
||||
localRepository.saveSyncronous(task)
|
||||
}
|
||||
val savedTask = apiClient.createTask(task)
|
||||
savedTask?.dateCreated = Date()
|
||||
if (savedTask != null) {
|
||||
savedTask.tags = task.tags
|
||||
localRepository.save(savedTask)
|
||||
} else {
|
||||
task.hasErrored = true
|
||||
task.isSaving = false
|
||||
localRepository.saveSyncronous(task)
|
||||
}
|
||||
return savedTask
|
||||
}
|
||||
|
||||
@Suppress("ReturnCount")
|
||||
override fun updateTask(task: Task, force: Boolean): Maybe<Task> {
|
||||
override suspend fun updateTask(task: Task, force: Boolean): Task? {
|
||||
val now = Date().time
|
||||
if ((lastTaskAction > now - 500 && !force) || !task.isValid) {
|
||||
return Maybe.just(task)
|
||||
return task
|
||||
}
|
||||
lastTaskAction = now
|
||||
val id = task.id ?: return Maybe.just(task)
|
||||
val id = task.id ?: return task
|
||||
val unmanagedTask = localRepository.getUnmanagedCopy(task)
|
||||
unmanagedTask.isSaving = true
|
||||
unmanagedTask.hasErrored = false
|
||||
localRepository.saveSyncronous(unmanagedTask)
|
||||
return apiClient.updateTask(id, unmanagedTask).singleElement()
|
||||
.map { task1 ->
|
||||
task1.position = task.position
|
||||
task1.id = task.id
|
||||
task1
|
||||
}
|
||||
.doOnSuccess {
|
||||
it.tags = task.tags
|
||||
localRepository.save(it)
|
||||
}
|
||||
.doOnError {
|
||||
unmanagedTask.hasErrored = true
|
||||
unmanagedTask.isSaving = false
|
||||
localRepository.saveSyncronous(unmanagedTask)
|
||||
}
|
||||
val savedTask = apiClient.updateTask(id, unmanagedTask)
|
||||
savedTask?.position = task.position
|
||||
savedTask?.id = task.id
|
||||
if (savedTask != null) {
|
||||
savedTask.tags = task.tags
|
||||
localRepository.save(savedTask)
|
||||
} else {
|
||||
unmanagedTask.hasErrored = true
|
||||
unmanagedTask.isSaving = false
|
||||
localRepository.saveSyncronous(unmanagedTask)
|
||||
}
|
||||
return savedTask
|
||||
}
|
||||
|
||||
override fun deleteTask(taskId: String): Flowable<Void> {
|
||||
return apiClient.deleteTask(taskId)
|
||||
.doOnNext { localRepository.deleteTask(taskId) }
|
||||
override suspend fun deleteTask(taskId: String): Void? {
|
||||
apiClient.deleteTask(taskId) ?: return null
|
||||
localRepository.deleteTask(taskId)
|
||||
return null
|
||||
}
|
||||
|
||||
override fun saveTask(task: Task) {
|
||||
localRepository.save(task)
|
||||
}
|
||||
|
||||
override fun createTasks(newTasks: List<Task>): Flowable<List<Task>> = apiClient.createTasks(newTasks)
|
||||
override suspend fun createTasks(newTasks: List<Task>) = apiClient.createTasks(newTasks)
|
||||
|
||||
override fun markTaskCompleted(taskId: String, isCompleted: Boolean) {
|
||||
localRepository.markTaskCompleted(taskId, isCompleted)
|
||||
|
|
@ -296,19 +286,24 @@ class TaskRepositoryImpl(
|
|||
localRepository.swapTaskPosition(firstPosition, secondPosition)
|
||||
}
|
||||
|
||||
override fun updateTaskPosition(taskType: TaskType, taskID: String, newPosition: Int): Maybe<List<String>> {
|
||||
return apiClient.postTaskNewPosition(taskID, newPosition).firstElement()
|
||||
.doOnSuccess { localRepository.updateTaskPositions(it) }
|
||||
override suspend fun updateTaskPosition(taskType: TaskType, taskID: String, newPosition: Int): List<String>? {
|
||||
val positions = apiClient.postTaskNewPosition(taskID, newPosition) ?: return null
|
||||
localRepository.updateTaskPositions(positions)
|
||||
return positions
|
||||
}
|
||||
|
||||
override fun getUnmanagedTask(taskid: String) = getTask(taskid).map { localRepository.getUnmanagedCopy(it) }
|
||||
|
||||
override fun updateTaskInBackground(task: Task) {
|
||||
updateTask(task).subscribe({ }, ExceptionHandler.rx())
|
||||
MainScope().launchCatching {
|
||||
updateTask(task)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createTaskInBackground(task: Task) {
|
||||
createTask(task).subscribe({ }, ExceptionHandler.rx())
|
||||
MainScope().launchCatching {
|
||||
createTask(task)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTaskCopies(userId: String): Flow<List<Task>> =
|
||||
|
|
@ -316,29 +311,27 @@ class TaskRepositoryImpl(
|
|||
|
||||
override fun getTaskCopies(tasks: List<Task>): List<Task> = localRepository.getUnmanagedCopy(tasks)
|
||||
|
||||
override fun retrieveDailiesFromDate(date: Date): Flowable<TaskList> {
|
||||
override suspend fun retrieveDailiesFromDate(date: Date): TaskList? {
|
||||
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.US)
|
||||
return apiClient.getTasks("dailys", formatter.format(date))
|
||||
}
|
||||
|
||||
override fun syncErroredTasks(): Single<List<Task>> {
|
||||
return localRepository.getErroredTasks(userID).firstElement()
|
||||
.flatMapPublisher { Flowable.fromIterable(it) }
|
||||
.map { localRepository.getUnmanagedCopy(it) }
|
||||
.flatMap {
|
||||
return@flatMap if (it.isCreating) {
|
||||
createTask(it, true)
|
||||
} else {
|
||||
updateTask(it, true).toFlowable()
|
||||
}
|
||||
}.toList()
|
||||
override suspend fun syncErroredTasks(): List<Task>? {
|
||||
val tasks = localRepository.getErroredTasks(userID).firstOrNull()
|
||||
return tasks?.map { localRepository.getUnmanagedCopy(it) }?.mapNotNull {
|
||||
if (it.isCreating) {
|
||||
createTask(it, true)
|
||||
} else {
|
||||
updateTask(it, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun unlinkAllTasks(challengeID: String?, keepOption: String): Flowable<Void> {
|
||||
override suspend fun unlinkAllTasks(challengeID: String?, keepOption: String): Void? {
|
||||
return apiClient.unlinkAllTasks(challengeID, keepOption)
|
||||
}
|
||||
|
||||
override fun getTasksForChallenge(challengeID: String?): Flowable<out List<Task>> {
|
||||
override fun getTasksForChallenge(challengeID: String?): Flow<List<Task>> {
|
||||
return localRepository.getTasksForChallenge(challengeID, userID)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.habitrpg.android.habitica.data.ApiClient
|
|||
import com.habitrpg.android.habitica.data.TutorialRepository
|
||||
import com.habitrpg.android.habitica.data.local.TutorialLocalRepository
|
||||
import com.habitrpg.android.habitica.models.TutorialStep
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class TutorialRepositoryImpl(
|
||||
localRepository: TutorialLocalRepository,
|
||||
|
|
@ -12,9 +12,9 @@ class TutorialRepositoryImpl(
|
|||
userID: String
|
||||
) : BaseRepositoryImpl<TutorialLocalRepository>(localRepository, apiClient, userID), TutorialRepository {
|
||||
|
||||
override fun getTutorialStep(key: String): Flowable<TutorialStep> =
|
||||
override fun getTutorialStep(key: String): Flow<TutorialStep> =
|
||||
localRepository.getTutorialStep(key)
|
||||
|
||||
override fun getTutorialSteps(keys: List<String>): Flowable<out List<TutorialStep>> =
|
||||
override fun getTutorialSteps(keys: List<String>): Flow<List<TutorialStep>> =
|
||||
localRepository.getTutorialSteps(keys)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,9 @@ import com.habitrpg.android.habitica.data.ApiClient
|
|||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.data.local.UserLocalRepository
|
||||
import com.habitrpg.android.habitica.extensions.filterMapEmpty
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.models.Achievement
|
||||
import com.habitrpg.android.habitica.models.QuestAchievement
|
||||
import com.habitrpg.android.habitica.models.Skill
|
||||
import com.habitrpg.android.habitica.models.TeamPlan
|
||||
import com.habitrpg.android.habitica.models.inventory.Customization
|
||||
import com.habitrpg.android.habitica.models.responses.SkillResponse
|
||||
|
|
@ -21,17 +18,10 @@ 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.android.habitica.proxy.AnalyticsManager
|
||||
import com.habitrpg.common.habitica.extensions.Optional
|
||||
import com.habitrpg.shared.habitica.models.responses.TaskDirection
|
||||
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 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
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
|
@ -48,8 +38,6 @@ class UserRepositoryImpl(
|
|||
private var lastSync: Date? = null
|
||||
|
||||
override fun getUser(): Flow<User?> = getUser(userID)
|
||||
override fun getUserFlowable(): Flowable<User> = localRepository.getUserFlowable(userID)
|
||||
|
||||
override fun getUser(userID: String): Flow<User?> = localRepository.getUser(userID)
|
||||
|
||||
private suspend fun updateUser(userID: String, updateData: Map<String, Any>): User? {
|
||||
|
|
@ -123,11 +111,9 @@ class UserRepositoryImpl(
|
|||
return user
|
||||
}
|
||||
|
||||
override fun getSkills(user: User): Flowable<out List<Skill>> =
|
||||
localRepository.getSkills(user)
|
||||
override fun getSkills(user: User) = localRepository.getSkills(user)
|
||||
|
||||
override fun getSpecialItems(user: User): Flowable<out List<Skill>> =
|
||||
localRepository.getSpecialItems(user)
|
||||
override fun getSpecialItems(user: User) = localRepository.getSpecialItems(user)
|
||||
|
||||
override suspend fun useSkill(key: String, target: String?, taskId: String): SkillResponse? {
|
||||
val response = apiClient.useSkill(key, target ?: "", taskId) ?: return null
|
||||
|
|
@ -177,8 +163,8 @@ class UserRepositoryImpl(
|
|||
runCron(ArrayList())
|
||||
}
|
||||
|
||||
override fun readNotification(id: String): Flowable<List<Any>> = apiClient.readNotification(id)
|
||||
override fun getUserQuestStatus(): Flowable<UserQuestStatus> {
|
||||
override suspend fun readNotification(id: String) = apiClient.readNotification(id)
|
||||
override fun getUserQuestStatus(): Flow<UserQuestStatus> {
|
||||
return localRepository.getUserQuestStatus(userID)
|
||||
}
|
||||
|
||||
|
|
@ -186,13 +172,11 @@ class UserRepositoryImpl(
|
|||
return apiClient.reroll()
|
||||
}
|
||||
|
||||
override fun readNotifications(notificationIds: Map<String, List<String>>): Flowable<List<Any>> =
|
||||
apiClient.readNotifications(notificationIds)
|
||||
override suspend fun readNotifications(notificationIds: Map<String, List<String>>) = apiClient.readNotifications(notificationIds)
|
||||
|
||||
override fun seeNotifications(notificationIds: Map<String, List<String>>): Flowable<List<Any>> =
|
||||
apiClient.seeNotifications(notificationIds)
|
||||
override suspend fun seeNotifications(notificationIds: Map<String, List<String>>) = apiClient.seeNotifications(notificationIds)
|
||||
|
||||
override fun changeCustomDayStart(dayStartTime: Int): Flowable<User> {
|
||||
override suspend fun changeCustomDayStart(dayStartTime: Int): User? {
|
||||
val updateObject = HashMap<String, Any>()
|
||||
updateObject["dayStart"] = dayStartTime
|
||||
return apiClient.changeCustomDayStart(updateObject)
|
||||
|
|
@ -200,7 +184,7 @@ class UserRepositoryImpl(
|
|||
|
||||
override suspend fun updateLanguage(languageCode: String): User? {
|
||||
val user = updateUser("preferences.language", languageCode)
|
||||
apiClient.setLanguageCode(languageCode)
|
||||
apiClient.languageCode = languageCode
|
||||
return user
|
||||
}
|
||||
|
||||
|
|
@ -209,11 +193,9 @@ class UserRepositoryImpl(
|
|||
return retrieveUser(withTasks = true, forced = true)
|
||||
}
|
||||
|
||||
override fun deleteAccount(password: String): Flowable<Void> =
|
||||
apiClient.deleteAccount(password)
|
||||
override suspend fun deleteAccount(password: String) = apiClient.deleteAccount(password)
|
||||
|
||||
override fun sendPasswordResetEmail(email: String): Flowable<Void> =
|
||||
apiClient.sendPasswordResetEmail(email)
|
||||
override suspend fun sendPasswordResetEmail(email: String) = apiClient.sendPasswordResetEmail(email)
|
||||
|
||||
override suspend fun updateLoginName(newLoginName: String, password: String?): User? {
|
||||
if (password != null && password.isNotEmpty()) {
|
||||
|
|
@ -229,35 +211,32 @@ class UserRepositoryImpl(
|
|||
return user
|
||||
}
|
||||
|
||||
override fun verifyUsername(username: String): Flowable<VerifyUsernameResponse> = apiClient.verifyUsername(username.trim())
|
||||
override suspend fun verifyUsername(username: String) = apiClient.verifyUsername(username.trim())
|
||||
|
||||
override fun updateEmail(newEmail: String, password: String): Flowable<Void> =
|
||||
apiClient.updateEmail(newEmail.trim(), password)
|
||||
override suspend fun updateEmail(newEmail: String, password: String) = apiClient.updateEmail(newEmail.trim(), password)
|
||||
|
||||
override fun updatePassword(
|
||||
override suspend fun updatePassword(
|
||||
oldPassword: String,
|
||||
newPassword: String,
|
||||
newPasswordConfirmation: String
|
||||
): Flowable<Void> =
|
||||
apiClient.updatePassword(oldPassword.trim(), newPassword.trim(), newPasswordConfirmation.trim())
|
||||
) = apiClient.updatePassword(oldPassword.trim(), newPassword.trim(), newPasswordConfirmation.trim())
|
||||
|
||||
override fun allocatePoint(stat: Attribute): Flowable<Stats> {
|
||||
getLiveUserFlowable().firstElement().subscribe(
|
||||
{ liveUser ->
|
||||
localRepository.executeTransaction {
|
||||
when (stat) {
|
||||
Attribute.STRENGTH -> liveUser.stats?.strength = liveUser.stats?.strength?.inc()
|
||||
Attribute.INTELLIGENCE -> liveUser.stats?.intelligence = liveUser.stats?.intelligence?.inc()
|
||||
Attribute.CONSTITUTION -> liveUser.stats?.constitution = liveUser.stats?.constitution?.inc()
|
||||
Attribute.PERCEPTION -> liveUser.stats?.per = liveUser.stats?.per?.inc()
|
||||
}
|
||||
liveUser.stats?.points = liveUser.stats?.points?.dec()
|
||||
override suspend fun allocatePoint(stat: Attribute): Stats? {
|
||||
val liveUser = getLiveUser()
|
||||
if (liveUser != null) {
|
||||
localRepository.executeTransaction {
|
||||
when (stat) {
|
||||
Attribute.STRENGTH -> liveUser.stats?.strength = liveUser.stats?.strength?.inc()
|
||||
Attribute.INTELLIGENCE -> liveUser.stats?.intelligence = liveUser.stats?.intelligence?.inc()
|
||||
Attribute.CONSTITUTION -> liveUser.stats?.constitution = liveUser.stats?.constitution?.inc()
|
||||
Attribute.PERCEPTION -> liveUser.stats?.per = liveUser.stats?.per?.inc()
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
return zipWithLiveUser(apiClient.allocatePoint(stat.value)) { stats, user ->
|
||||
localRepository.modify(user) { liveUser ->
|
||||
liveUser.stats?.points = liveUser.stats?.points?.dec()
|
||||
}
|
||||
}
|
||||
val stats = apiClient.allocatePoint(stat.value) ?: return null
|
||||
if (liveUser != null) {
|
||||
localRepository.executeTransaction {
|
||||
liveUser.stats?.strength = stats.strength
|
||||
liveUser.stats?.constitution = stats.constitution
|
||||
liveUser.stats?.per = stats.per
|
||||
|
|
@ -265,17 +244,24 @@ class UserRepositoryImpl(
|
|||
liveUser.stats?.points = stats.points
|
||||
liveUser.stats?.mp = stats.mp
|
||||
}
|
||||
stats
|
||||
}
|
||||
return stats
|
||||
}
|
||||
|
||||
override fun bulkAllocatePoints(
|
||||
override suspend fun bulkAllocatePoints(
|
||||
strength: Int,
|
||||
intelligence: Int,
|
||||
constitution: Int,
|
||||
perception: Int
|
||||
): Flowable<Stats> =
|
||||
zipWithLiveUser(apiClient.bulkAllocatePoints(strength, intelligence, constitution, perception)) { stats, user ->
|
||||
): Stats? {
|
||||
val stats = apiClient.bulkAllocatePoints(
|
||||
strength,
|
||||
intelligence,
|
||||
constitution,
|
||||
perception
|
||||
) ?: return null
|
||||
val user = getLiveUser()
|
||||
if (user != null) {
|
||||
localRepository.modify(user) { liveUser ->
|
||||
liveUser.stats?.strength = stats.strength
|
||||
liveUser.stats?.constitution = stats.constitution
|
||||
|
|
@ -284,63 +270,54 @@ class UserRepositoryImpl(
|
|||
liveUser.stats?.points = stats.points
|
||||
liveUser.stats?.mp = stats.mp
|
||||
}
|
||||
stats
|
||||
}
|
||||
return stats
|
||||
}
|
||||
|
||||
override suspend fun runCron(tasks: MutableList<Task>) {
|
||||
withContext(Dispatchers.Main) {
|
||||
var observable: Maybe<Any> = localRepository.getUserFlowable(userID).firstElement()
|
||||
.filter { it.needsCron }
|
||||
.map { user ->
|
||||
localRepository.modify(user) { liveUser ->
|
||||
liveUser.needsCron = false
|
||||
liveUser.lastCron = Date()
|
||||
}
|
||||
user
|
||||
}
|
||||
if (tasks.isNotEmpty()) {
|
||||
val scoringList = mutableListOf<Map<String, String>>()
|
||||
for (task in tasks) {
|
||||
val map = mutableMapOf<String, String>()
|
||||
map["id"] = task.id ?: ""
|
||||
map["direction"] = TaskDirection.UP.text
|
||||
scoringList.add(map)
|
||||
}
|
||||
observable = observable.flatMap { taskRepository.bulkScoreTasks(scoringList).firstElement() }
|
||||
val user = getLiveUser()
|
||||
if (user != null) {
|
||||
localRepository.modify(user) { liveUser ->
|
||||
liveUser.needsCron = false
|
||||
liveUser.lastCron = Date()
|
||||
}
|
||||
observable.flatMap { apiClient.runCron().firstElement() }
|
||||
// .flatMap {
|
||||
// this.retrieveUser(withTasks = true, forced = true)
|
||||
// }
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
}
|
||||
if (tasks.isNotEmpty()) {
|
||||
val scoringList = mutableListOf<Map<String, String>>()
|
||||
for (task in tasks) {
|
||||
val map = mutableMapOf<String, String>()
|
||||
map["id"] = task.id ?: ""
|
||||
map["direction"] = TaskDirection.UP.text
|
||||
scoringList.add(map)
|
||||
}
|
||||
taskRepository.bulkScoreTasks(scoringList)
|
||||
}
|
||||
apiClient.runCron()
|
||||
}
|
||||
|
||||
override suspend fun useCustomization(type: String, category: String?, identifier: String): User? {
|
||||
if (appConfigManager.enableLocalChanges()) {
|
||||
localRepository.getUserFlowable(userID).firstElement().subscribe(
|
||||
{ liveUser ->
|
||||
localRepository.modify(liveUser) { user ->
|
||||
when (type) {
|
||||
"skin" -> user.preferences?.skin = identifier
|
||||
"shirt" -> user.preferences?.shirt = identifier
|
||||
"hair" -> {
|
||||
when (category) {
|
||||
"color" -> user.preferences?.hair?.color = identifier
|
||||
"flower" -> user.preferences?.hair?.flower = identifier.toInt()
|
||||
"mustache" -> user.preferences?.hair?.mustache = identifier.toInt()
|
||||
"beard" -> user.preferences?.hair?.beard = identifier.toInt()
|
||||
"bangs" -> user.preferences?.hair?.bangs = identifier.toInt()
|
||||
"base" -> user.preferences?.hair?.base = identifier.toInt()
|
||||
}
|
||||
val liveUser = getLiveUser()
|
||||
if (liveUser != null) {
|
||||
localRepository.modify(liveUser) { user ->
|
||||
when (type) {
|
||||
"skin" -> user.preferences?.skin = identifier
|
||||
"shirt" -> user.preferences?.shirt = identifier
|
||||
"hair" -> {
|
||||
when (category) {
|
||||
"color" -> user.preferences?.hair?.color = identifier
|
||||
"flower" -> user.preferences?.hair?.flower = identifier.toInt()
|
||||
"mustache" -> user.preferences?.hair?.mustache = identifier.toInt()
|
||||
"beard" -> user.preferences?.hair?.beard = identifier.toInt()
|
||||
"bangs" -> user.preferences?.hair?.bangs = identifier.toInt()
|
||||
"base" -> user.preferences?.hair?.base = identifier.toInt()
|
||||
}
|
||||
"background" -> user.preferences?.background = identifier
|
||||
"chair" -> user.preferences?.chair = identifier
|
||||
}
|
||||
"background" -> user.preferences?.background = identifier
|
||||
"chair" -> user.preferences?.chair = identifier
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
var updatePath = "preferences.$type"
|
||||
if (category != null) {
|
||||
|
|
@ -349,10 +326,10 @@ class UserRepositoryImpl(
|
|||
return updateUser(updatePath, identifier)
|
||||
}
|
||||
|
||||
override fun retrieveAchievements(): Flowable<List<Achievement>> {
|
||||
return apiClient.getMemberAchievements(userID).doOnNext {
|
||||
localRepository.save(it)
|
||||
}
|
||||
override suspend fun retrieveAchievements(): List<Achievement>? {
|
||||
val achievements = apiClient.getMemberAchievements(userID) ?: return null
|
||||
localRepository.save(achievements)
|
||||
return achievements
|
||||
}
|
||||
|
||||
override fun getAchievements(): Flow<List<Achievement>> {
|
||||
|
|
@ -363,11 +340,11 @@ class UserRepositoryImpl(
|
|||
return localRepository.getQuestAchievements(userID)
|
||||
}
|
||||
|
||||
override fun retrieveTeamPlans(): Flowable<List<TeamPlan>> {
|
||||
return apiClient.getTeamPlans().doOnNext { teams ->
|
||||
teams.forEach { it.userID = userID }
|
||||
localRepository.save(teams)
|
||||
}
|
||||
override suspend fun retrieveTeamPlans(): List<TeamPlan>? {
|
||||
val teams = apiClient.getTeamPlans() ?: return null
|
||||
teams.forEach { it.userID = userID }
|
||||
localRepository.save(teams)
|
||||
return teams
|
||||
}
|
||||
|
||||
override fun getTeamPlans(): Flow<List<TeamPlan>> {
|
||||
|
|
@ -389,25 +366,15 @@ class UserRepositoryImpl(
|
|||
return team
|
||||
}
|
||||
|
||||
override fun getTeamPlan(teamID: String): Flowable<Group> {
|
||||
override fun getTeamPlan(teamID: String): Flow<Group> {
|
||||
return localRepository.getTeamPlan(teamID)
|
||||
}
|
||||
|
||||
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, getLiveUserFlowable().firstElement().toFlowable(), mergeFunc)
|
||||
}
|
||||
|
||||
private fun mergeUser(oldUser: User?, newUser: User): User {
|
||||
if (oldUser == null || !oldUser.isValid) {
|
||||
return oldUser ?: newUser
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@ package com.habitrpg.android.habitica.data.local
|
|||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChallengeMembership
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ChallengeLocalRepository : BaseLocalRepository {
|
||||
|
||||
val challenges: Flowable<out List<Challenge>>
|
||||
fun getChallenge(id: String): Flowable<Challenge>
|
||||
fun getTasks(challengeID: String): Flowable<out List<Task>>
|
||||
val challenges: Flow<List<Challenge>>
|
||||
fun getChallenge(id: String): Flow<Challenge>
|
||||
fun getTasks(challengeID: String): Flow<List<Task>>
|
||||
|
||||
fun getUserChallenges(userId: String): Flowable<out List<Challenge>>
|
||||
fun getUserChallenges(userId: String): Flow<List<Challenge>>
|
||||
|
||||
fun setParticipating(userID: String, challengeID: String, isParticipating: Boolean)
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ interface ChallengeLocalRepository : BaseLocalRepository {
|
|||
memberOnly: Boolean,
|
||||
userID: String
|
||||
)
|
||||
fun getChallengeMembership(userId: String, id: String): Flowable<ChallengeMembership>
|
||||
fun getChallengeMemberships(userId: String): Flowable<out List<ChallengeMembership>>
|
||||
fun isChallengeMember(userID: String, challengeID: String): Flowable<Boolean>
|
||||
fun getChallengeMembership(userId: String, id: String): Flow<ChallengeMembership>
|
||||
fun getChallengeMemberships(userId: String): Flow<List<ChallengeMembership>>
|
||||
fun isChallengeMember(userID: String, challengeID: String): Flow<Boolean>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ package com.habitrpg.android.habitica.data.local
|
|||
import com.habitrpg.android.habitica.models.ContentResult
|
||||
import com.habitrpg.android.habitica.models.WorldState
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ContentLocalRepository : BaseLocalRepository {
|
||||
fun saveContent(contentResult: ContentResult)
|
||||
fun saveWorldState(worldState: WorldState)
|
||||
fun getWorldState(): Flowable<WorldState>
|
||||
fun getWorldState(): Flow<WorldState>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package com.habitrpg.android.habitica.data.local
|
||||
|
||||
import com.habitrpg.android.habitica.models.inventory.Customization
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface CustomizationLocalRepository : ContentLocalRepository {
|
||||
fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flowable<out List<Customization>>
|
||||
fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flow<List<Customization>>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package com.habitrpg.android.habitica.data.local
|
||||
|
||||
import com.habitrpg.android.habitica.models.FAQArticle
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface FAQLocalRepository : ContentLocalRepository {
|
||||
fun getArticle(position: Int): Flowable<FAQArticle>
|
||||
fun getArticle(position: Int): Flow<FAQArticle>
|
||||
|
||||
val articles: Flowable<out List<FAQArticle>>
|
||||
val articles: Flow<List<FAQArticle>>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,13 +11,12 @@ import com.habitrpg.android.habitica.models.user.OwnedItem
|
|||
import com.habitrpg.android.habitica.models.user.OwnedMount
|
||||
import com.habitrpg.android.habitica.models.user.OwnedPet
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface InventoryLocalRepository : ContentLocalRepository {
|
||||
|
||||
fun getArmoireRemainingCount(): Long
|
||||
fun getOwnedEquipment(): Flowable<out List<Equipment>>
|
||||
fun getOwnedEquipment(): Flow<List<Equipment>>
|
||||
|
||||
fun getMounts(): Flow<List<Mount>>
|
||||
|
||||
|
|
@ -27,31 +26,29 @@ interface InventoryLocalRepository : ContentLocalRepository {
|
|||
|
||||
fun getOwnedPets(userID: String): Flow<List<OwnedPet>>
|
||||
|
||||
fun getInAppRewards(): Flowable<out List<ShopItem>>
|
||||
fun getInAppRewards(): Flow<List<ShopItem>>
|
||||
fun getQuestContent(key: String): Flow<QuestContent?>
|
||||
fun getQuestContent(keys: List<String>): Flow<List<QuestContent>>
|
||||
|
||||
fun getEquipment(searchedKeys: List<String>): Flowable<out List<Equipment>>
|
||||
fun getEquipment(searchedKeys: List<String>): Flow<List<Equipment>>
|
||||
|
||||
fun getOwnedEquipment(type: String): Flowable<out List<Equipment>>
|
||||
fun getOwnedEquipment(type: String): Flow<List<Equipment>>
|
||||
|
||||
fun getItemsFlowable(itemClass: Class<out Item>, keys: Array<String>): Flow<List<Item>>
|
||||
fun getItemsFlowable(itemClass: Class<out Item>): Flowable<out List<Item>>
|
||||
fun getOwnedItems(itemType: String, userID: String, includeZero: Boolean): Flow<List<OwnedItem>>
|
||||
fun getOwnedItems(userID: String, includeZero: Boolean): Flowable<Map<String, OwnedItem>>
|
||||
fun getEquipmentType(type: String, set: String): Flowable<out List<Equipment>>
|
||||
fun getOwnedItems(userID: String, includeZero: Boolean): Flow<Map<String, OwnedItem>>
|
||||
fun getEquipmentType(type: String, set: String): Flow<List<Equipment>>
|
||||
|
||||
fun getEquipment(key: String): Flowable<Equipment>
|
||||
fun getEquipment(key: String): Flow<Equipment>
|
||||
fun getMounts(type: String?, group: String?, color: String?): Flow<List<Mount>>
|
||||
fun getPets(type: String?, group: String?, color: String?): Flow<List<Pet>>
|
||||
|
||||
fun updateOwnedEquipment(user: User)
|
||||
|
||||
fun changeOwnedCount(type: String, key: String, userID: String, amountToAdd: Int)
|
||||
suspend fun changeOwnedCount(type: String, key: String, userID: String, amountToAdd: Int)
|
||||
fun changeOwnedCount(item: OwnedItem, amountToAdd: Int?)
|
||||
|
||||
fun getItem(type: String, key: String): Flowable<Item>
|
||||
fun getOwnedItem(userID: String, type: String, key: String, includeZero: Boolean): Flowable<OwnedItem>
|
||||
fun getItem(type: String, key: String): Flow<Item>
|
||||
fun getOwnedItem(userID: String, type: String, key: String, includeZero: Boolean): Flow<OwnedItem>
|
||||
|
||||
fun decrementMysteryItemCount(user: User?)
|
||||
fun saveInAppRewards(onlineItems: List<ShopItem>)
|
||||
|
|
@ -59,12 +56,14 @@ interface InventoryLocalRepository : ContentLocalRepository {
|
|||
fun hatchPet(eggKey: String, potionKey: String, userID: String)
|
||||
fun unhatchPet(eggKey: String, potionKey: String, userID: String)
|
||||
fun feedPet(foodKey: String, petKey: String, feedValue: Int, userID: String)
|
||||
fun getLatestMysteryItem(): Flowable<Equipment>
|
||||
fun getLatestMysteryItem(): Flow<Equipment>
|
||||
fun soldItem(userID: String, updatedUser: User): User
|
||||
fun getAvailableLimitedItems(): Flowable<List<Item>>
|
||||
fun getAvailableLimitedItems(): Flow<List<Item>>
|
||||
|
||||
fun save(items: Items, userID: String)
|
||||
|
||||
fun getLiveObject(obj: OwnedItem): OwnedItem?
|
||||
fun getItems(itemClass: Class<out Item>): Flow<List<Item>>
|
||||
fun getItems(itemClass: Class<out Item>, keys: Array<String>): Flow<List<Item>>
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,20 +6,19 @@ import com.habitrpg.android.habitica.models.social.Group
|
|||
import com.habitrpg.android.habitica.models.social.GroupMembership
|
||||
import com.habitrpg.android.habitica.models.social.InboxConversation
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.RealmResults
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface SocialLocalRepository : BaseLocalRepository {
|
||||
fun getPublicGuilds(): Flowable<out List<Group>>
|
||||
fun getPublicGuilds(): Flow<List<Group>>
|
||||
|
||||
fun getUserGroups(userID: String, type: String?): Flow<List<Group>>
|
||||
fun getGroups(type: String): Flowable<out List<Group>>
|
||||
fun getGroups(type: String): Flow<List<Group>>
|
||||
|
||||
fun getGroup(id: String): Flow<Group?>
|
||||
fun saveGroup(group: Group)
|
||||
|
||||
fun getGroupChat(groupId: String): Flowable<out List<ChatMessage>>
|
||||
fun getGroupChat(groupId: String): Flow<List<ChatMessage>>
|
||||
|
||||
fun deleteMessage(id: String)
|
||||
|
||||
|
|
@ -41,7 +40,7 @@ interface SocialLocalRepository : BaseLocalRepository {
|
|||
fun doesGroupExist(id: String): Boolean
|
||||
fun updateMembership(userId: String, id: String, isMember: Boolean)
|
||||
fun getGroupMembership(userId: String, id: String): Flow<GroupMembership?>
|
||||
fun getGroupMemberships(userId: String): Flowable<out List<GroupMembership>>
|
||||
fun getGroupMemberships(userId: String): Flow<List<GroupMembership>>
|
||||
fun rejectGroupInvitation(userID: String, groupID: String)
|
||||
|
||||
fun getInboxMessages(userId: String, replyToUserID: String?): Flow<RealmResults<ChatMessage>>
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ package com.habitrpg.android.habitica.data.local
|
|||
|
||||
import com.habitrpg.android.habitica.models.Tag
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface TagLocalRepository : BaseLocalRepository {
|
||||
fun getTags(userId: String): Flowable<out List<Tag>>
|
||||
fun getTags(userId: String): Flow<List<Tag>>
|
||||
|
||||
fun deleteTag(tagID: String)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,14 +5,12 @@ import com.habitrpg.android.habitica.models.tasks.TaskList
|
|||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.shared.habitica.models.tasks.TasksOrder
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface TaskLocalRepository : BaseLocalRepository {
|
||||
|
||||
fun getTasks(taskType: TaskType, userID: String, includedGroupIDs: Array<String>): Flow<List<Task>>
|
||||
fun getTasksFlowable(taskType: TaskType, userID: String, includedGroupIDs: Array<String>): Flowable<out List<Task>>
|
||||
fun getTasks(userId: String): Flow<List<Task>>
|
||||
|
||||
fun saveTasks(ownerID: String, tasksOrder: TasksOrder, tasks: TaskList)
|
||||
|
|
@ -26,14 +24,13 @@ interface TaskLocalRepository : BaseLocalRepository {
|
|||
|
||||
fun swapTaskPosition(firstPosition: Int, secondPosition: Int)
|
||||
|
||||
fun getTaskAtPosition(taskType: String, position: Int): Flowable<Task>
|
||||
fun getTaskAtPosition(taskType: String, position: Int): Flow<Task>
|
||||
|
||||
fun updateIsdue(daily: TaskList): Maybe<TaskList>
|
||||
|
||||
fun updateTaskPositions(taskOrder: List<String>)
|
||||
fun saveCompletedTodos(userId: String, tasks: MutableCollection<Task>)
|
||||
fun getErroredTasks(userID: String): Flowable<out List<Task>>
|
||||
fun getUserFlowable(userID: String): Flowable<User>
|
||||
fun getErroredTasks(userID: String): Flow<List<Task>>
|
||||
fun getUser(userID: String): Flow<User>
|
||||
fun getTasksForChallenge(challengeID: String?, userID: String?): Flowable<out List<Task>>
|
||||
fun getTasksForChallenge(challengeID: String?, userID: String?): Flow<List<Task>>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package com.habitrpg.android.habitica.data.local
|
||||
|
||||
import com.habitrpg.android.habitica.models.TutorialStep
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface TutorialLocalRepository : BaseLocalRepository {
|
||||
|
||||
fun getTutorialStep(key: String): Flowable<TutorialStep>
|
||||
fun getTutorialSteps(keys: List<String>): Flowable<out List<TutorialStep>>
|
||||
fun getTutorialStep(key: String): Flow<TutorialStep>
|
||||
fun getTutorialSteps(keys: List<String>): Flow<List<TutorialStep>>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ 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 io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.RealmResults
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
|
|
@ -18,18 +17,16 @@ interface UserLocalRepository : BaseLocalRepository {
|
|||
suspend fun getTutorialSteps(): Flow<RealmResults<TutorialStep>>
|
||||
|
||||
fun getUser(userID: String): Flow<User?>
|
||||
fun getUserFlowable(userID: String): Flowable<User>
|
||||
|
||||
fun saveUser(user: User, overrideExisting: Boolean = true)
|
||||
|
||||
fun saveMessages(messages: List<ChatMessage>)
|
||||
|
||||
fun getSkills(user: User): Flowable<out List<Skill>>
|
||||
fun getSkills(user: User): Flow<List<Skill>>
|
||||
|
||||
fun getSpecialItems(user: User): Flowable<out List<Skill>>
|
||||
fun getSpecialItems(user: User): Flow<List<Skill>>
|
||||
fun getAchievements(): Flow<List<Achievement>>
|
||||
fun getQuestAchievements(userID: String): Flow<List<QuestAchievement>>
|
||||
fun getUserQuestStatus(userID: String): Flowable<UserQuestStatus>
|
||||
fun getUserQuestStatus(userID: String): Flow<UserQuestStatus>
|
||||
fun getTeamPlans(userID: String): Flow<List<TeamPlan>>
|
||||
fun getTeamPlan(teamID: String): Flowable<Group>
|
||||
fun getTeamPlan(teamID: String): Flow<Group>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,84 +1,79 @@
|
|||
package com.habitrpg.android.habitica.data.local.implementation
|
||||
|
||||
import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository
|
||||
import com.habitrpg.android.habitica.extensions.filterMap
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChallengeMembership
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import hu.akarnokd.rxjava3.bridge.RxJavaBridge
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.Realm
|
||||
import io.realm.Sort
|
||||
import io.realm.kotlin.toFlow
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), ChallengeLocalRepository {
|
||||
|
||||
override fun isChallengeMember(userID: String, challengeID: String): Flowable<Boolean> = RxJavaBridge.toV3Flowable(
|
||||
realm.where(ChallengeMembership::class.java)
|
||||
override fun isChallengeMember(userID: String, challengeID: String): Flow<Boolean> = realm.where(ChallengeMembership::class.java)
|
||||
.equalTo("userID", userID)
|
||||
.equalTo("challengeID", challengeID)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
).map { it.count() > 0 }
|
||||
.map { it.count() > 0 }
|
||||
|
||||
override fun getChallengeMembership(userId: String, id: String): Flowable<ChallengeMembership> = RxJavaBridge.toV3Flowable(
|
||||
realm.where(ChallengeMembership::class.java)
|
||||
override fun getChallengeMembership(userId: String, id: String) = realm.where(ChallengeMembership::class.java)
|
||||
.equalTo("userID", userId)
|
||||
.equalTo("challengeID", id)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
).filterMap { it.first() }
|
||||
.map { it.first() }
|
||||
.filterNotNull()
|
||||
|
||||
override fun getChallengeMemberships(userId: String): Flowable<out List<ChallengeMembership>> = RxJavaBridge.toV3Flowable(
|
||||
realm.where(ChallengeMembership::class.java)
|
||||
override fun getChallengeMemberships(userId: String) = realm.where(ChallengeMembership::class.java)
|
||||
.equalTo("userID", userId)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
|
||||
override fun getChallenge(id: String): Flowable<Challenge> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Challenge::class.java)
|
||||
override fun getChallenge(id: String): Flow<Challenge> {
|
||||
return realm.where(Challenge::class.java)
|
||||
.equalTo("id", id)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isNotEmpty() }
|
||||
.map { it.first() }
|
||||
)
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getTasks(challengeID: String): Flowable<out List<Task>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Task::class.java)
|
||||
override fun getTasks(challengeID: String): Flow<List<Task>> {
|
||||
return realm.where(Task::class.java)
|
||||
.equalTo("userId", challengeID)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { realmObject -> realmObject.isLoaded }
|
||||
)
|
||||
}
|
||||
|
||||
override val challenges: Flowable<out List<Challenge>>
|
||||
get() = RxJavaBridge.toV3Flowable(
|
||||
realm.where(Challenge::class.java)
|
||||
override val challenges: Flow<List<Challenge>>
|
||||
get() = realm.where(Challenge::class.java)
|
||||
.isNotNull("name")
|
||||
.sort("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
|
||||
override fun getUserChallenges(userId: String): Flowable<out List<Challenge>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(ChallengeMembership::class.java)
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun getUserChallenges(userId: String): Flow<List<Challenge>> {
|
||||
return realm.where(ChallengeMembership::class.java)
|
||||
.equalTo("userID", userId)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
.flatMap { it ->
|
||||
.flatMapLatest { it ->
|
||||
val ids = it.map {
|
||||
return@map it.challengeID
|
||||
}.toTypedArray()
|
||||
|
|
@ -91,7 +86,7 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
|
|||
.endGroup()
|
||||
.sort("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,12 @@ import com.habitrpg.android.habitica.models.ContentResult
|
|||
import com.habitrpg.android.habitica.models.WorldState
|
||||
import com.habitrpg.android.habitica.models.inventory.Quest
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import hu.akarnokd.rxjava3.bridge.RxJavaBridge
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.Realm
|
||||
import io.realm.kotlin.toFlow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
open class RealmContentLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), ContentLocalRepository {
|
||||
|
||||
|
|
@ -34,14 +37,13 @@ open class RealmContentLocalRepository(realm: Realm) : RealmBaseLocalRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override fun getWorldState(): Flowable<WorldState> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(WorldState::class.java)
|
||||
override fun getWorldState(): Flow<WorldState> {
|
||||
return realm.where(WorldState::class.java)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded && it.size > 0 }
|
||||
.map { it.first() }
|
||||
)
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun saveWorldState(worldState: WorldState) {
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@ package com.habitrpg.android.habitica.data.local.implementation
|
|||
|
||||
import com.habitrpg.android.habitica.data.local.CustomizationLocalRepository
|
||||
import com.habitrpg.android.habitica.models.inventory.Customization
|
||||
import hu.akarnokd.rxjava3.bridge.RxJavaBridge
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.Realm
|
||||
import io.realm.kotlin.toFlow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import java.util.Date
|
||||
|
||||
class RealmCustomizationLocalRepository(realm: Realm) : RealmContentLocalRepository(realm), CustomizationLocalRepository {
|
||||
|
||||
override fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flowable<out List<Customization>> {
|
||||
override fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flow<List<Customization>> {
|
||||
var query = realm.where(Customization::class.java)
|
||||
.equalTo("type", type)
|
||||
.equalTo("category", category)
|
||||
|
|
@ -28,13 +29,10 @@ class RealmCustomizationLocalRepository(realm: Realm) : RealmContentLocalReposit
|
|||
.endGroup()
|
||||
.endGroup()
|
||||
}
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
query
|
||||
return query
|
||||
.sort("customizationSet")
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
.map { it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,27 +2,27 @@ package com.habitrpg.android.habitica.data.local.implementation
|
|||
|
||||
import com.habitrpg.android.habitica.data.local.FAQLocalRepository
|
||||
import com.habitrpg.android.habitica.models.FAQArticle
|
||||
import hu.akarnokd.rxjava3.bridge.RxJavaBridge
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.Realm
|
||||
import io.realm.kotlin.toFlow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class RealmFAQLocalRepository(realm: Realm) : RealmContentLocalRepository(realm), FAQLocalRepository {
|
||||
override fun getArticle(position: Int): Flowable<FAQArticle> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(FAQArticle::class.java)
|
||||
override fun getArticle(position: Int): Flow<FAQArticle> {
|
||||
return realm.where(FAQArticle::class.java)
|
||||
.equalTo("position", position)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded && it.count() > 0 }
|
||||
.map { it.first() }
|
||||
)
|
||||
.map { it.firstOrNull() }
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override val articles: Flowable<out List<FAQArticle>>
|
||||
get() = RxJavaBridge.toV3Flowable(
|
||||
realm.where(FAQArticle::class.java)
|
||||
override val articles: Flow<List<FAQArticle>>
|
||||
get() = realm.where(FAQArticle::class.java)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.habitrpg.android.habitica.data.local.implementation
|
||||
|
||||
import com.habitrpg.android.habitica.data.local.InventoryLocalRepository
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.models.inventory.Egg
|
||||
import com.habitrpg.android.habitica.models.inventory.Equipment
|
||||
import com.habitrpg.android.habitica.models.inventory.Food
|
||||
|
|
@ -17,44 +16,44 @@ import com.habitrpg.android.habitica.models.user.OwnedItem
|
|||
import com.habitrpg.android.habitica.models.user.OwnedMount
|
||||
import com.habitrpg.android.habitica.models.user.OwnedPet
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import hu.akarnokd.rxjava3.bridge.RxJavaBridge
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmObject
|
||||
import io.realm.Sort
|
||||
import io.realm.kotlin.toFlow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(realm), InventoryLocalRepository {
|
||||
class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(realm),
|
||||
InventoryLocalRepository {
|
||||
override fun getQuestContent(keys: List<String>): Flow<List<QuestContent>> {
|
||||
return realm.where(QuestContent::class.java)
|
||||
.`in`("key", keys.toTypedArray())
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
.`in`("key", keys.toTypedArray())
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getQuestContent(key: String): Flow<QuestContent?> {
|
||||
return realm.where(QuestContent::class.java).equalTo("key", key)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { content -> content.isLoaded && content.isValid && !content.isEmpty() }
|
||||
.map { content -> content.first() }
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { content -> content.isLoaded && content.isValid && !content.isEmpty() }
|
||||
.map { content -> content.first() }
|
||||
}
|
||||
|
||||
override fun getEquipment(searchedKeys: List<String>): Flowable<out List<Equipment>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Equipment::class.java)
|
||||
.`in`("key", searchedKeys.toTypedArray())
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
override fun getEquipment(searchedKeys: List<String>): Flow<out List<Equipment>> {
|
||||
return realm.where(Equipment::class.java)
|
||||
.`in`("key", searchedKeys.toTypedArray())
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getArmoireRemainingCount(): Long {
|
||||
|
|
@ -68,39 +67,37 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
.count()
|
||||
}
|
||||
|
||||
override fun getOwnedEquipment(type: String): Flowable<out List<Equipment>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Equipment::class.java)
|
||||
.equalTo("type", type)
|
||||
.equalTo("owned", true)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
override fun getOwnedEquipment(type: String): Flow<out List<Equipment>> {
|
||||
return realm.where(Equipment::class.java)
|
||||
.equalTo("type", type)
|
||||
.equalTo("owned", true)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getOwnedEquipment(): Flowable<out List<Equipment>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Equipment::class.java)
|
||||
.equalTo("owned", true)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
override fun getOwnedEquipment(): Flow<out List<Equipment>> {
|
||||
return realm.where(Equipment::class.java)
|
||||
.equalTo("owned", true)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getEquipmentType(type: String, set: String): Flowable<out List<Equipment>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Equipment::class.java)
|
||||
.equalTo("type", type)
|
||||
.equalTo("gearSet", set)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
override fun getEquipmentType(type: String, set: String): Flow<out List<Equipment>> {
|
||||
return realm.where(Equipment::class.java)
|
||||
.equalTo("type", type)
|
||||
.equalTo("gearSet", set)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getOwnedItems(itemType: String, userID: String, includeZero: Boolean): Flow<List<OwnedItem>> {
|
||||
override fun getOwnedItems(
|
||||
itemType: String,
|
||||
userID: String,
|
||||
includeZero: Boolean
|
||||
): Flow<List<OwnedItem>> {
|
||||
return queryUser(userID).map {
|
||||
val items = when (itemType) {
|
||||
"eggs" -> it?.items?.eggs
|
||||
|
|
@ -118,56 +115,49 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override fun getItemsFlowable(itemClass: Class<out Item>, keys: Array<String>): Flow<List<Item>> {
|
||||
return realm.where(itemClass).`in`("key", keys).findAll().toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getItemsFlowable(itemClass: Class<out Item>): Flowable<out List<Item>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(itemClass).findAll().asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
}
|
||||
|
||||
override fun getItems(itemClass: Class<out Item>): Flow<List<Item>> {
|
||||
return realm.where(itemClass).findAll().toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getOwnedItems(userID: String, includeZero: Boolean): Flowable<Map<String, OwnedItem>> {
|
||||
return queryUserFlowable(userID).map {
|
||||
val items = HashMap<String, OwnedItem>()
|
||||
it.items?.eggs?.forEach { items[it.key + "-" + it.itemType] = it }
|
||||
it.items?.food?.forEach { items[it.key + "-" + it.itemType] = it }
|
||||
it.items?.hatchingPotions?.forEach { items[it.key + "-" + it.itemType] = it }
|
||||
it.items?.quests?.forEach { items[it.key + "-" + it.itemType] = it }
|
||||
if (includeZero) {
|
||||
items
|
||||
} else {
|
||||
items.filter { it.value.numberOwned > 0 }
|
||||
}
|
||||
}
|
||||
override fun getItems(itemClass: Class<out Item>, keys: Array<String>): Flow<List<Item>> {
|
||||
return realm.where(itemClass).`in`("key", keys).findAll().toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getEquipment(key: String): Flowable<Equipment> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Equipment::class.java)
|
||||
.equalTo("key", key)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isNotEmpty() }
|
||||
.map { it.first() }
|
||||
.cast(Equipment::class.java)
|
||||
)
|
||||
override fun getOwnedItems(userID: String, includeZero: Boolean): Flow<Map<String, OwnedItem>> {
|
||||
return queryUser(userID)
|
||||
.filterNotNull()
|
||||
.map {
|
||||
val items = HashMap<String, OwnedItem>()
|
||||
it.items?.eggs?.forEach { items[it.key + "-" + it.itemType] = it }
|
||||
it.items?.food?.forEach { items[it.key + "-" + it.itemType] = it }
|
||||
it.items?.hatchingPotions?.forEach { items[it.key + "-" + it.itemType] = it }
|
||||
it.items?.quests?.forEach { items[it.key + "-" + it.itemType] = it }
|
||||
if (includeZero) {
|
||||
items
|
||||
} else {
|
||||
items.filter { it.value.numberOwned > 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEquipment(key: String): Flow<Equipment> {
|
||||
return realm.where(Equipment::class.java)
|
||||
.equalTo("key", key)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isNotEmpty() }
|
||||
.map { it.first() }
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getMounts(): Flow<List<Mount>> {
|
||||
return realm.where(Mount::class.java)
|
||||
.sort("type", Sort.ASCENDING, "animal", Sort.ASCENDING)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
.sort("type", Sort.ASCENDING, "animal", Sort.ASCENDING)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getMounts(type: String?, group: String?, color: String?): Flow<List<Mount>> {
|
||||
|
|
@ -183,8 +173,8 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
query = query.equalTo("color", color)
|
||||
}
|
||||
return query.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getOwnedMounts(userID: String): Flow<List<OwnedMount>> {
|
||||
|
|
@ -198,10 +188,10 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
|
||||
override fun getPets(): Flow<List<Pet>> {
|
||||
return realm.where(Pet::class.java)
|
||||
.sort("type", Sort.ASCENDING, "animal", Sort.ASCENDING)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
.sort("type", Sort.ASCENDING, "animal", Sort.ASCENDING)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getPets(type: String?, group: String?, color: String?): Flow<List<Pet>> {
|
||||
|
|
@ -217,15 +207,15 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
query = query.equalTo("color", color)
|
||||
}
|
||||
return query.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getOwnedPets(userID: String): Flow<List<OwnedPet>> {
|
||||
return realm.where(User::class.java)
|
||||
.equalTo("id", userID)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.equalTo("id", userID)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded && it.isValid && !it.isEmpty() }
|
||||
.map {
|
||||
it.first()?.items?.pets?.filter {
|
||||
|
|
@ -237,8 +227,16 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
override fun updateOwnedEquipment(user: User) {
|
||||
}
|
||||
|
||||
override fun changeOwnedCount(type: String, key: String, userID: String, amountToAdd: Int) {
|
||||
getOwnedItem(userID, type, key, true).firstElement().subscribe({ changeOwnedCount(it, amountToAdd) }, ExceptionHandler.rx())
|
||||
override suspend fun changeOwnedCount(
|
||||
type: String,
|
||||
key: String,
|
||||
userID: String,
|
||||
amountToAdd: Int
|
||||
) {
|
||||
val item = getOwnedItem(userID, type, key, true).firstOrNull()
|
||||
if (item != null) {
|
||||
changeOwnedCount(item, amountToAdd)
|
||||
}
|
||||
}
|
||||
|
||||
override fun changeOwnedCount(item: OwnedItem, amountToAdd: Int?) {
|
||||
|
|
@ -248,29 +246,36 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override fun getOwnedItem(userID: String, type: String, key: String, includeZero: Boolean): Flowable<OwnedItem> {
|
||||
return queryUserFlowable(userID).map {
|
||||
var items = (
|
||||
when (type) {
|
||||
"eggs" -> it.items?.eggs
|
||||
"hatchingPotions" -> it.items?.hatchingPotions
|
||||
"food" -> it.items?.food
|
||||
"quests" -> it.items?.quests
|
||||
else -> emptyList()
|
||||
} ?: emptyList()
|
||||
)
|
||||
items = items.filter { it.key == key }
|
||||
if (includeZero) {
|
||||
items
|
||||
} else {
|
||||
items.filter { it.numberOwned > 0 }
|
||||
override fun getOwnedItem(
|
||||
userID: String,
|
||||
type: String,
|
||||
key: String,
|
||||
includeZero: Boolean
|
||||
): Flow<OwnedItem> {
|
||||
return queryUser(userID)
|
||||
.filterNotNull()
|
||||
.map {
|
||||
var items = (
|
||||
when (type) {
|
||||
"eggs" -> it.items?.eggs
|
||||
"hatchingPotions" -> it.items?.hatchingPotions
|
||||
"food" -> it.items?.food
|
||||
"quests" -> it.items?.quests
|
||||
else -> emptyList()
|
||||
} ?: emptyList()
|
||||
)
|
||||
items = items.filter { it.key == key }
|
||||
if (includeZero) {
|
||||
items
|
||||
} else {
|
||||
items.filter { it.numberOwned > 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
.filter { it.isNotEmpty() }
|
||||
.map { it.first() }
|
||||
}
|
||||
|
||||
override fun getItem(type: String, key: String): Flowable<Item> {
|
||||
override fun getItem(type: String, key: String): Flow<Item> {
|
||||
val itemClass: Class<out RealmObject> = when (type) {
|
||||
"eggs" -> Egg::class.java
|
||||
"hatchingPotions" -> HatchingPotion::class.java
|
||||
|
|
@ -279,14 +284,12 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
"special" -> SpecialItem::class.java
|
||||
else -> Egg::class.java
|
||||
}
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(itemClass).equalTo("key", key)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isNotEmpty() }
|
||||
.map { it.first() }
|
||||
.cast(Item::class.java)
|
||||
)
|
||||
return realm.where(itemClass).equalTo("key", key)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isNotEmpty() }
|
||||
.map { it.firstOrNull() as? Item }
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun decrementMysteryItemCount(user: User?) {
|
||||
|
|
@ -301,18 +304,17 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
item.numberOwned = item.numberOwned - 1
|
||||
}
|
||||
if (liveUser?.isValid == true) {
|
||||
liveUser.purchased?.plan?.mysteryItemCount = (user.purchased?.plan?.mysteryItemCount ?: 0) - 1
|
||||
liveUser.purchased?.plan?.mysteryItemCount =
|
||||
(user.purchased?.plan?.mysteryItemCount ?: 0) - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getInAppRewards(): Flowable<out List<ShopItem>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(ShopItem::class.java)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
override fun getInAppRewards(): Flow<List<ShopItem>> {
|
||||
return realm.where(ShopItem::class.java)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun saveInAppRewards(onlineItems: List<ShopItem>) {
|
||||
|
|
@ -333,7 +335,8 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
newPet.trained = 5
|
||||
val user = realm.where(User::class.java).equalTo("id", userID).findFirst() ?: return
|
||||
val egg = user.items?.eggs?.firstOrNull { it.key == eggKey } ?: return
|
||||
val hatchingPotion = user.items?.hatchingPotions?.firstOrNull { it.key == potionKey } ?: return
|
||||
val hatchingPotion =
|
||||
user.items?.hatchingPotions?.firstOrNull { it.key == potionKey } ?: return
|
||||
executeTransaction {
|
||||
egg.numberOwned -= 1
|
||||
hatchingPotion.numberOwned -= 1
|
||||
|
|
@ -344,7 +347,8 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
override fun getLiveObject(obj: OwnedItem): OwnedItem? {
|
||||
if (isClosed) return null
|
||||
if (!obj.isManaged) return obj
|
||||
return realm.where(OwnedItem::class.java).equalTo("key", obj.key).equalTo("itemType", obj.itemType).findFirst()
|
||||
return realm.where(OwnedItem::class.java).equalTo("key", obj.key)
|
||||
.equalTo("itemType", obj.itemType).findFirst()
|
||||
}
|
||||
|
||||
override fun save(items: Items, userID: String) {
|
||||
|
|
@ -359,7 +363,8 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
val pet = realm.where(OwnedPet::class.java).equalTo("key", "$eggKey-$potionKey").findFirst()
|
||||
val user = realm.where(User::class.java).equalTo("id", userID).findFirst() ?: return
|
||||
val egg = user.items?.eggs?.firstOrNull { it.key == eggKey } ?: return
|
||||
val hatchingPotion = user.items?.hatchingPotions?.firstOrNull { it.key == potionKey } ?: return
|
||||
val hatchingPotion =
|
||||
user.items?.hatchingPotions?.firstOrNull { it.key == potionKey } ?: return
|
||||
executeTransaction {
|
||||
egg.numberOwned += 1
|
||||
hatchingPotion.numberOwned += 1
|
||||
|
|
@ -384,21 +389,19 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override fun getLatestMysteryItem(): Flowable<Equipment> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Equipment::class.java)
|
||||
.contains("key", "mystery_2")
|
||||
.sort("mystery", Sort.DESCENDING)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded && it.size > 0 }
|
||||
.map {
|
||||
val format = SimpleDateFormat("yyyyMM", Locale.US)
|
||||
it.first {
|
||||
it.key?.contains(format.format(Date())) == true
|
||||
}
|
||||
override fun getLatestMysteryItem(): Flow<Equipment> {
|
||||
return realm.where(Equipment::class.java)
|
||||
.contains("key", "mystery_2")
|
||||
.sort("mystery", Sort.DESCENDING)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded && it.size > 0 }
|
||||
.map {
|
||||
val format = SimpleDateFormat("yyyyMM", Locale.US)
|
||||
it.first {
|
||||
it.key?.contains(format.format(Date())) == true
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun soldItem(userID: String, updatedUser: User): User {
|
||||
|
|
@ -418,32 +421,42 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
return user
|
||||
}
|
||||
|
||||
override fun getAvailableLimitedItems(): Flowable<List<Item>> {
|
||||
return Flowable.combineLatest(
|
||||
realm.where(Egg::class.java)
|
||||
.lessThan("event.start", Date())
|
||||
.greaterThan("event.end", Date())
|
||||
.findAll().asFlowable(),
|
||||
realm.where(Food::class.java)
|
||||
.lessThan("event.start", Date())
|
||||
.greaterThan("event.end", Date())
|
||||
.findAll().asFlowable(),
|
||||
realm.where(HatchingPotion::class.java)
|
||||
.lessThan("event.start", Date())
|
||||
.greaterThan("event.end", Date())
|
||||
.findAll().asFlowable(),
|
||||
realm.where(QuestContent::class.java)
|
||||
.lessThan("event.start", Date())
|
||||
.greaterThan("event.end", Date())
|
||||
.findAll().asFlowable(),
|
||||
{ eggs, food, potions, quests ->
|
||||
override fun getAvailableLimitedItems(): Flow<List<Item>> {
|
||||
return realm.where(Egg::class.java)
|
||||
.lessThan("event.start", Date())
|
||||
.greaterThan("event.end", Date())
|
||||
.findAll().toFlow()
|
||||
.map {
|
||||
val items = mutableListOf<Item>()
|
||||
items.addAll(eggs)
|
||||
items.addAll(food)
|
||||
items.addAll(potions)
|
||||
items.addAll(quests)
|
||||
items.addAll(it)
|
||||
items
|
||||
}
|
||||
.combine(
|
||||
realm.where(Food::class.java)
|
||||
.lessThan("event.start", Date())
|
||||
.greaterThan("event.end", Date())
|
||||
.findAll().toFlow()
|
||||
) { items, food ->
|
||||
items.addAll(food)
|
||||
items
|
||||
}
|
||||
.combine(
|
||||
realm.where(HatchingPotion::class.java)
|
||||
.lessThan("event.start", Date())
|
||||
.greaterThan("event.end", Date())
|
||||
.findAll().toFlow()
|
||||
) { items, food ->
|
||||
items.addAll(food)
|
||||
items
|
||||
}
|
||||
.combine(
|
||||
realm.where(QuestContent::class.java)
|
||||
.lessThan("event.start", Date())
|
||||
.greaterThan("event.end", Date())
|
||||
.findAll().toFlow()
|
||||
) { items, food ->
|
||||
items.addAll(food)
|
||||
items
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ import com.habitrpg.android.habitica.models.social.Group
|
|||
import com.habitrpg.android.habitica.models.social.GroupMembership
|
||||
import com.habitrpg.android.habitica.models.social.InboxConversation
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import hu.akarnokd.rxjava3.bridge.RxJavaBridge
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.Realm
|
||||
import io.realm.Sort
|
||||
import io.realm.kotlin.toFlow
|
||||
|
|
@ -30,13 +28,11 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
|||
.filter { it.isLoaded && it.isNotEmpty() }
|
||||
.map { it.first() }
|
||||
|
||||
override fun getGroupMemberships(userId: String): Flowable<out List<GroupMembership>> = RxJavaBridge.toV3Flowable(
|
||||
realm.where(GroupMembership::class.java)
|
||||
override fun getGroupMemberships(userId: String): Flow<List<GroupMembership>> = realm.where(GroupMembership::class.java)
|
||||
.equalTo("userID", userId)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
|
||||
override fun updateMembership(userId: String, id: String, isMember: Boolean) {
|
||||
if (isMember) {
|
||||
|
|
@ -123,16 +119,14 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
|||
}
|
||||
}
|
||||
|
||||
override fun getPublicGuilds(): Flowable<out List<Group>> = RxJavaBridge.toV3Flowable(
|
||||
realm.where(Group::class.java)
|
||||
override fun getPublicGuilds() = realm.where(Group::class.java)
|
||||
.equalTo("type", "guild")
|
||||
.equalTo("privacy", "public")
|
||||
.notEqualTo("id", Group.TAVERN_ID)
|
||||
.sort("memberCount", Sort.DESCENDING)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun getUserGroups(userID: String, type: String?) = realm.where(GroupMembership::class.java)
|
||||
|
|
@ -155,14 +149,12 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
|||
.toFlow()
|
||||
}
|
||||
|
||||
override fun getGroups(type: String): Flowable<out List<Group>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Group::class.java)
|
||||
override fun getGroups(type: String): Flow<List<Group>> {
|
||||
return realm.where(Group::class.java)
|
||||
.equalTo("type", type)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
}
|
||||
|
||||
override fun getGroup(id: String): Flow<Group?> {
|
||||
|
|
@ -174,15 +166,13 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
|||
.map { groups -> groups.first() }
|
||||
}
|
||||
|
||||
override fun getGroupChat(groupId: String): Flowable<out List<ChatMessage>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(ChatMessage::class.java)
|
||||
override fun getGroupChat(groupId: String): Flow<List<ChatMessage>> {
|
||||
return realm.where(ChatMessage::class.java)
|
||||
.equalTo("groupId", groupId)
|
||||
.sort("timestamp", Sort.DESCENDING)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
}
|
||||
|
||||
override fun deleteMessage(id: String) {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ package com.habitrpg.android.habitica.data.local.implementation
|
|||
|
||||
import com.habitrpg.android.habitica.data.local.TagLocalRepository
|
||||
import com.habitrpg.android.habitica.models.Tag
|
||||
import hu.akarnokd.rxjava3.bridge.RxJavaBridge
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.Realm
|
||||
import io.realm.kotlin.toFlow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class RealmTagLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), TagLocalRepository {
|
||||
override fun deleteTag(tagID: String) {
|
||||
|
|
@ -12,9 +12,7 @@ class RealmTagLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), T
|
|||
executeTransaction { tags.deleteAllFromRealm() }
|
||||
}
|
||||
|
||||
override fun getTags(userId: String): Flowable<out List<Tag>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Tag::class.java).equalTo("userId", userId).findAll().asFlowable()
|
||||
)
|
||||
override fun getTags(userId: String): Flow<List<Tag>> {
|
||||
return realm.where(Tag::class.java).equalTo("userId", userId).findAll().toFlow()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import com.habitrpg.android.habitica.models.tasks.TaskList
|
|||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.shared.habitica.models.tasks.TasksOrder
|
||||
import hu.akarnokd.rxjava3.bridge.RxJavaBridge
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Maybe
|
||||
import io.realm.Realm
|
||||
|
|
@ -30,13 +29,6 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getTasksFlowable(taskType: TaskType, userID: String, includedGroupIDs: Array<String>): Flowable<out List<Task>> {
|
||||
if (realm.isClosed) return Flowable.empty()
|
||||
return RxJavaBridge.toV3Flowable(findTasks(taskType, userID, includedGroupIDs)
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded })
|
||||
}
|
||||
|
||||
private fun findTasks(
|
||||
taskType: TaskType,
|
||||
ownerID: String,
|
||||
|
|
@ -226,16 +218,13 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
}
|
||||
}
|
||||
|
||||
override fun getTaskAtPosition(taskType: String, position: Int): Flowable<Task> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Task::class.java).equalTo("typeValue", taskType).equalTo("position", position)
|
||||
override fun getTaskAtPosition(taskType: String, position: Int): Flow<Task> {
|
||||
return realm.where(Task::class.java).equalTo("typeValue", taskType).equalTo("position", position)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isNotEmpty() }
|
||||
.map { it.first() }
|
||||
.filter { realmObject -> realmObject.isLoaded }
|
||||
.cast(Task::class.java)
|
||||
)
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun updateIsdue(daily: TaskList): Maybe<TaskList> {
|
||||
|
|
@ -258,27 +247,14 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
}
|
||||
}
|
||||
|
||||
override fun getErroredTasks(userID: String): Flowable<out List<Task>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Task::class.java)
|
||||
override fun getErroredTasks(userID: String): Flow<List<Task>> {
|
||||
return realm.where(Task::class.java)
|
||||
.equalTo("userId", userID)
|
||||
.equalTo("hasErrored", true)
|
||||
.sort("position")
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
).retry(1)
|
||||
}
|
||||
|
||||
override fun getUserFlowable(userID: String): Flowable<User> {
|
||||
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() }
|
||||
)
|
||||
}
|
||||
|
||||
override fun getUser(userID: String): Flow<User> {
|
||||
|
|
@ -291,15 +267,12 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getTasksForChallenge(challengeID: String?, userID: String?): Flowable<out List<Task>> {
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Task::class.java)
|
||||
override fun getTasksForChallenge(challengeID: String?, userID: String?): Flow<List<Task>> {
|
||||
return realm.where(Task::class.java)
|
||||
.equalTo("challengeID", challengeID)
|
||||
.equalTo("userId", userID)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
.retry(1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,31 +2,32 @@ package com.habitrpg.android.habitica.data.local.implementation
|
|||
|
||||
import com.habitrpg.android.habitica.data.local.TutorialLocalRepository
|
||||
import com.habitrpg.android.habitica.models.TutorialStep
|
||||
import hu.akarnokd.rxjava3.bridge.RxJavaBridge
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.Realm
|
||||
import io.realm.kotlin.toFlow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class RealmTutorialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), TutorialLocalRepository {
|
||||
|
||||
override fun getTutorialStep(key: String): Flowable<TutorialStep> {
|
||||
if (realm.isClosed) return Flowable.empty()
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(TutorialStep::class.java).equalTo("identifier", key)
|
||||
override fun getTutorialStep(key: String): Flow<TutorialStep> {
|
||||
if (realm.isClosed) return emptyFlow()
|
||||
return realm.where(TutorialStep::class.java).equalTo("identifier", key)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isValid && realmObject.isNotEmpty() }
|
||||
.map { steps -> steps.first() }
|
||||
)
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getTutorialSteps(keys: List<String>): Flowable<out List<TutorialStep>> {
|
||||
if (realm.isClosed) return Flowable.empty()
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(TutorialStep::class.java)
|
||||
override fun getTutorialSteps(keys: List<String>): Flow<out List<TutorialStep>> {
|
||||
if (realm.isClosed) return emptyFlow()
|
||||
return realm.where(TutorialStep::class.java)
|
||||
.`in`("identifier", keys.toTypedArray())
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,36 +13,40 @@ 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
|
||||
import io.realm.kotlin.toFlow
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||
UserLocalRepository {
|
||||
override fun getUserQuestStatus(userID: String): Flowable<UserQuestStatus> {
|
||||
return getUserFlowable(userID)
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun getUserQuestStatus(userID: String): Flow<UserQuestStatus> {
|
||||
return getUser(userID)
|
||||
.filterNotNull()
|
||||
.map { it.party?.id ?: "" }
|
||||
.distinctUntilChanged()
|
||||
.filter { it.isNotBlank() }
|
||||
.flatMap {
|
||||
RxJavaBridge.toV3Flowable(
|
||||
.flatMapLatest {
|
||||
realm.where(Group::class.java)
|
||||
.equalTo("id", it)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { groups -> groups.size > 0 }
|
||||
).filterMap { it.first() }
|
||||
.map { it.firstOrNull() }
|
||||
.filterNotNull()
|
||||
}
|
||||
.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?.hp ?: 0.0 > 0.0 -> UserQuestStatus.QUEST_BOSS
|
||||
(it.quest?.progress?.hp ?: 0.0) > 0.0 -> UserQuestStatus.QUEST_BOSS
|
||||
else -> UserQuestStatus.QUEST_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
|
@ -79,17 +83,6 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
.map { users -> users.first() }
|
||||
}
|
||||
|
||||
override fun getUserFlowable(userID: String): Flowable<User> {
|
||||
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() })
|
||||
}
|
||||
|
||||
override fun saveUser(user: User, overrideExisting: Boolean) {
|
||||
if (realm.isClosed) return
|
||||
val oldUser = realm.where(User::class.java)
|
||||
|
|
@ -134,45 +127,40 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getTeamPlan(teamID: String): Flowable<Group> {
|
||||
if (realm.isClosed) return Flowable.empty()
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Group::class.java)
|
||||
override fun getTeamPlan(teamID: String): Flow<Group> {
|
||||
if (realm.isClosed) return emptyFlow()
|
||||
return realm.where(Group::class.java)
|
||||
.equalTo("id", teamID)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isValid && !realmObject.isEmpty() }
|
||||
.map { teams -> teams.first() }
|
||||
)
|
||||
.map { teams -> teams.firstOrNull() }
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getSkills(user: User): Flowable<out List<Skill>> {
|
||||
override fun getSkills(user: User): Flow<List<Skill>> {
|
||||
val habitClass =
|
||||
if (user.preferences?.disableClasses == true) "none" else user.stats?.habitClass
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Skill::class.java)
|
||||
return realm.where(Skill::class.java)
|
||||
.equalTo("habitClass", habitClass)
|
||||
.sort("lvl")
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
}
|
||||
|
||||
override fun getSpecialItems(user: User): Flowable<out List<Skill>> {
|
||||
override fun getSpecialItems(user: User): Flow<List<Skill>> {
|
||||
val specialItems = user.items?.special
|
||||
val ownedItems = ArrayList<String>()
|
||||
for (key in listOf("snowball", "shinySeed", "seafoam", "spookySparkles")) {
|
||||
if (specialItems?.firstOrNull() { it.key == key }?.numberOwned ?: 0 > 0) {
|
||||
if ((specialItems?.firstOrNull { it.key == key }?.numberOwned ?: 0) > 0) {
|
||||
ownedItems.add(key)
|
||||
}
|
||||
}
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Skill::class.java)
|
||||
return realm.where(Skill::class.java)
|
||||
.`in`("key", ownedItems.toTypedArray())
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.habitrpg.android.habitica.models.promotions.HabiticaPromotion
|
|||
import com.habitrpg.android.habitica.models.promotions.HabiticaWebPromotion
|
||||
import com.habitrpg.android.habitica.models.promotions.getHabiticaPromotionFromKey
|
||||
import com.habitrpg.common.habitica.helpers.AppTestingLevel
|
||||
import kotlinx.coroutines.MainScope
|
||||
|
||||
class AppConfigManager(contentRepository: ContentRepository?): com.habitrpg.common.habitica.helpers.AppConfigManager() {
|
||||
|
||||
|
|
@ -19,12 +20,11 @@ class AppConfigManager(contentRepository: ContentRepository?): com.habitrpg.comm
|
|||
|
||||
init {
|
||||
try {
|
||||
contentRepository?.getWorldState()?.subscribe(
|
||||
{
|
||||
worldState = it
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
MainScope().launchCatching {
|
||||
contentRepository?.getWorldState()?.collect {
|
||||
worldState = it
|
||||
}
|
||||
}
|
||||
} catch (_: java.lang.IllegalStateException) {
|
||||
// pass
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ class ExceptionHandler {
|
|||
}
|
||||
}
|
||||
|
||||
fun CoroutineScope.launchCatching(function: suspend CoroutineScope.() -> Unit) {
|
||||
launch((ExceptionHandler.coroutine()), block = function)
|
||||
fun CoroutineScope.launchCatching(errorHandler: ((Throwable) -> Unit)? = null, function: suspend CoroutineScope.() -> Unit) {
|
||||
launch((ExceptionHandler.coroutine {
|
||||
errorHandler?.invoke(it)
|
||||
}), block = function)
|
||||
}
|
||||
|
|
@ -3,56 +3,50 @@ package com.habitrpg.android.habitica.helpers
|
|||
import android.content.Context
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.common.habitica.models.Notification
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import com.habitrpg.common.habitica.models.Notification
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.Date
|
||||
|
||||
interface NotificationsManager {
|
||||
val displayNotificationEvents: Flowable<Notification>
|
||||
val displayNotificationEvents: Flow<Notification>
|
||||
var apiClient: WeakReference<ApiClient>?
|
||||
|
||||
fun setNotifications(current: List<Notification>)
|
||||
fun getNotifications(): Flowable<List<Notification>>
|
||||
fun getNotifications(): Flow<List<Notification>>
|
||||
fun getNotification(id: String): Notification?
|
||||
fun dismissTaskNotification(context: Context, task: Task)
|
||||
}
|
||||
|
||||
class MainNotificationsManager: NotificationsManager {
|
||||
private val displayNotificationSubject = PublishSubject.create<Notification>()
|
||||
|
||||
private val seenNotifications: MutableMap<String, Boolean>
|
||||
override var apiClient: WeakReference<ApiClient>? = null
|
||||
private val notifications: BehaviorSubject<List<Notification>>
|
||||
|
||||
private var lastNotificationHandling: Date? = null
|
||||
|
||||
override val displayNotificationEvents: Flowable<Notification>
|
||||
get() {
|
||||
return displayNotificationSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
val _notifications = MutableStateFlow<List<Notification>?>(null)
|
||||
val _displaynotificationEvents = MutableStateFlow<Notification?>(null)
|
||||
override val displayNotificationEvents: Flow<Notification> = _displaynotificationEvents.filterNotNull()
|
||||
|
||||
init {
|
||||
this.seenNotifications = HashMap()
|
||||
this.notifications = BehaviorSubject.create()
|
||||
}
|
||||
|
||||
override fun setNotifications(current: List<Notification>) {
|
||||
this.notifications.onNext(current)
|
||||
_notifications.value = current
|
||||
this.handlePopupNotifications(current)
|
||||
}
|
||||
|
||||
override fun getNotifications(): Flowable<List<Notification>> {
|
||||
return this.notifications.startWithArray(emptyList())
|
||||
.toFlowable(BackpressureStrategy.LATEST)
|
||||
override fun getNotifications(): Flow<List<Notification>> {
|
||||
return _notifications.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getNotification(id: String): Notification? {
|
||||
return this.notifications.value?.find { it.id == id }
|
||||
return _notifications.value?.find { it.id == id }
|
||||
}
|
||||
|
||||
override fun dismissTaskNotification(context: Context, task: Task) {
|
||||
|
|
@ -109,7 +103,7 @@ class MainNotificationsManager: NotificationsManager {
|
|||
}
|
||||
|
||||
if (notificationDisplayed) {
|
||||
displayNotificationSubject.onNext(it)
|
||||
_displaynotificationEvents.value = it
|
||||
this.seenNotifications[it.id] = true
|
||||
readNotification(it)
|
||||
}
|
||||
|
|
@ -119,7 +113,8 @@ class MainNotificationsManager: NotificationsManager {
|
|||
}
|
||||
|
||||
private fun readNotification(notification: Notification) {
|
||||
apiClient?.get()?.readNotification(notification.id)
|
||||
?.subscribe({ }, ExceptionHandler.rx())
|
||||
MainScope().launchCatching {
|
||||
apiClient?.get()?.readNotification(notification.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,10 +72,13 @@ class PurchaseHandler(
|
|||
val mostRecentSub = findMostRecentSubscription(purchases)
|
||||
val plan = userViewModel.user.value?.purchased?.plan
|
||||
for (purchase in purchases) {
|
||||
if (plan?.isActive == true && PurchaseTypes.allSubscriptionTypes.contains(purchase.skus.firstOrNull())) {
|
||||
if (plan?.isActive == true && PurchaseTypes.allSubscriptionTypes.contains(
|
||||
purchase.skus.firstOrNull()
|
||||
)
|
||||
) {
|
||||
if ((plan.additionalData?.data?.orderId == purchase.orderId &&
|
||||
((plan.dateTerminated != null) == purchase.isAutoRenewing)) ||
|
||||
mostRecentSub?.orderId != purchase.orderId
|
||||
((plan.dateTerminated != null) == purchase.isAutoRenewing)) ||
|
||||
mostRecentSub?.orderId != purchase.orderId
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
|
@ -138,8 +141,8 @@ class PurchaseHandler(
|
|||
billingClient.endConnection()
|
||||
}
|
||||
|
||||
fun queryPurchases(){
|
||||
if (billingClientState == BillingClientState.READY){
|
||||
fun queryPurchases() {
|
||||
if (billingClientState == BillingClientState.READY) {
|
||||
billingClient.queryPurchasesAsync(
|
||||
BillingClient.SkuType.SUBS,
|
||||
this@PurchaseHandler
|
||||
|
|
@ -185,7 +188,12 @@ class PurchaseHandler(
|
|||
return skuDetailsResult.skuDetailsList
|
||||
}
|
||||
|
||||
fun purchase(activity: Activity, skuDetails: SkuDetails, recipient: String? = null, isSaleGemPurchase: Boolean = false) {
|
||||
fun purchase(
|
||||
activity: Activity,
|
||||
skuDetails: SkuDetails,
|
||||
recipient: String? = null,
|
||||
isSaleGemPurchase: Boolean = false
|
||||
) {
|
||||
this.isSaleGemPurchase = isSaleGemPurchase
|
||||
recipient?.let {
|
||||
addGift(skuDetails.sku, it)
|
||||
|
|
@ -216,41 +224,50 @@ class PurchaseHandler(
|
|||
when {
|
||||
PurchaseTypes.allGemTypes.contains(sku) -> {
|
||||
val validationRequest = buildValidationRequest(purchase)
|
||||
apiClient.validatePurchase(validationRequest).subscribe({
|
||||
processedPurchase(purchase)
|
||||
val gift = removeGift(sku)
|
||||
CoroutineScope(Dispatchers.IO).launch(ExceptionHandler.coroutine()) {
|
||||
consume(purchase)
|
||||
MainScope().launchCatching {
|
||||
try {
|
||||
apiClient.validatePurchase(validationRequest)
|
||||
processedPurchase(purchase)
|
||||
val gift = removeGift(sku)
|
||||
CoroutineScope(Dispatchers.IO).launch(ExceptionHandler.coroutine()) {
|
||||
consume(purchase)
|
||||
}
|
||||
displayConfirmationDialog(purchase, gift?.second)
|
||||
} catch (throwable: Throwable) {
|
||||
handleError(throwable, purchase)
|
||||
}
|
||||
displayConfirmationDialog(purchase, gift?.second)
|
||||
}) { throwable: Throwable ->
|
||||
handleError(throwable, purchase)
|
||||
}
|
||||
}
|
||||
PurchaseTypes.allSubscriptionNoRenewTypes.contains(sku) -> {
|
||||
val validationRequest = buildValidationRequest(purchase)
|
||||
apiClient.validateNoRenewSubscription(validationRequest).subscribe({
|
||||
processedPurchase(purchase)
|
||||
val gift = removeGift(sku)
|
||||
CoroutineScope(Dispatchers.IO).launch(ExceptionHandler.coroutine()) {
|
||||
consume(purchase)
|
||||
MainScope().launchCatching {
|
||||
try {
|
||||
apiClient.validateNoRenewSubscription(validationRequest)
|
||||
processedPurchase(purchase)
|
||||
val gift = removeGift(sku)
|
||||
CoroutineScope(Dispatchers.IO).launch(ExceptionHandler.coroutine()) {
|
||||
consume(purchase)
|
||||
}
|
||||
displayConfirmationDialog(purchase, gift?.second)
|
||||
} catch (throwable: Throwable) {
|
||||
handleError(throwable, purchase)
|
||||
}
|
||||
displayConfirmationDialog(purchase, gift?.second)
|
||||
}) { throwable: Throwable ->
|
||||
handleError(throwable, purchase)
|
||||
}
|
||||
}
|
||||
PurchaseTypes.allSubscriptionTypes.contains(sku) -> {
|
||||
val validationRequest = buildValidationRequest(purchase)
|
||||
apiClient.validateSubscription(validationRequest).subscribe({
|
||||
processedPurchase(purchase)
|
||||
analyticsManager.logEvent("user_subscribed", bundleOf(Pair("sku", sku)))
|
||||
CoroutineScope(Dispatchers.IO).launch(ExceptionHandler.coroutine()) {
|
||||
acknowledgePurchase(purchase)
|
||||
MainScope().launchCatching {
|
||||
try {
|
||||
apiClient.validateSubscription(validationRequest)
|
||||
processedPurchase(purchase)
|
||||
analyticsManager.logEvent("user_subscribed", bundleOf(Pair("sku", sku)))
|
||||
CoroutineScope(Dispatchers.IO).launch(ExceptionHandler.coroutine()) {
|
||||
acknowledgePurchase(purchase)
|
||||
}
|
||||
displayConfirmationDialog(purchase)
|
||||
} catch (throwable: Throwable) {
|
||||
handleError(throwable, purchase)
|
||||
}
|
||||
displayConfirmationDialog(purchase)
|
||||
}) { throwable: Throwable ->
|
||||
handleError(throwable, purchase)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -320,7 +337,8 @@ class PurchaseHandler(
|
|||
}
|
||||
|
||||
private fun findMostRecentSubscription(purchasesList: List<Purchase>): Purchase? {
|
||||
val purchases = purchasesList.filter { it.isAcknowledged }.sortedByDescending { it.purchaseTime }
|
||||
val purchases =
|
||||
purchasesList.filter { it.isAcknowledged }.sortedByDescending { it.purchaseTime }
|
||||
var fallback: Purchase? = null
|
||||
// If there is a subscription that is still active, prioritise that. Otherwise return the most recent one.
|
||||
for (purchase in purchases) {
|
||||
|
|
@ -380,18 +398,29 @@ class PurchaseHandler(
|
|||
val message = when {
|
||||
PurchaseTypes.allSubscriptionNoRenewTypes.contains(sku) -> {
|
||||
title = context.getString(R.string.gift_confirmation_title)
|
||||
context.getString(R.string.gift_confirmation_text_sub, giftedTo, durationString(sku))
|
||||
context.getString(
|
||||
R.string.gift_confirmation_text_sub,
|
||||
giftedTo,
|
||||
durationString(sku)
|
||||
)
|
||||
}
|
||||
PurchaseTypes.allSubscriptionTypes.contains(sku) -> {
|
||||
if (sku == PurchaseTypes.Subscription1Month) {
|
||||
context.getString(R.string.subscription_confirmation)
|
||||
} else {
|
||||
context.getString(R.string.subscription_confirmation_multiple, durationString(sku))
|
||||
context.getString(
|
||||
R.string.subscription_confirmation_multiple,
|
||||
durationString(sku)
|
||||
)
|
||||
}
|
||||
}
|
||||
PurchaseTypes.allGemTypes.contains(sku) && giftedTo != null -> {
|
||||
title = context.getString(R.string.gift_confirmation_title)
|
||||
context.getString(R.string.gift_confirmation_text_gems_new, giftedTo, gemAmountString(sku))
|
||||
context.getString(
|
||||
R.string.gift_confirmation_text_gems_new,
|
||||
giftedTo,
|
||||
gemAmountString(sku)
|
||||
)
|
||||
}
|
||||
PurchaseTypes.allGemTypes.contains(sku) && giftedTo == null -> {
|
||||
context.getString(R.string.gem_purchase_confirmation, gemAmountString(sku))
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class UserStatComputer {
|
|||
var stats: String? = null
|
||||
}
|
||||
|
||||
fun computeClassBonus(equipmentList: List<Equipment>, user: Avatar): List<StatsRow> {
|
||||
fun computeClassBonus(equipmentList: List<Equipment>?, user: Avatar): List<StatsRow> {
|
||||
val skillRows = ArrayList<StatsRow>()
|
||||
|
||||
var strAttributes = 0f
|
||||
|
|
@ -39,7 +39,7 @@ class UserStatComputer {
|
|||
var perClassBonus = 0f
|
||||
|
||||
// Summarize stats and fill equipment table
|
||||
for (i in equipmentList) {
|
||||
for (i in equipmentList ?: emptyList()) {
|
||||
val strength = i.str
|
||||
val intelligence = i._int
|
||||
val constitution = i.con
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@ import com.google.firebase.messaging.FirebaseMessaging
|
|||
import com.google.firebase.messaging.RemoteMessage
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.helpers.AmplitudeManager
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import kotlinx.coroutines.MainScope
|
||||
|
||||
class PushNotificationManager(
|
||||
var apiClient: ApiClient,
|
||||
|
|
@ -51,14 +52,18 @@ class PushNotificationManager(
|
|||
val pushDeviceData = HashMap<String, String>()
|
||||
pushDeviceData["regId"] = this.refreshedToken
|
||||
pushDeviceData["type"] = "android"
|
||||
apiClient.addPushDevice(pushDeviceData).subscribe({ }, ExceptionHandler.rx())
|
||||
MainScope().launchCatching {
|
||||
apiClient.addPushDevice(pushDeviceData)
|
||||
}
|
||||
}
|
||||
|
||||
fun removePushDeviceUsingStoredToken() {
|
||||
if (this.refreshedToken.isEmpty() || !userHasPushDevice()) {
|
||||
return
|
||||
}
|
||||
apiClient.deletePushDevice(this.refreshedToken).subscribe({ }, ExceptionHandler.rx())
|
||||
MainScope().launchCatching {
|
||||
apiClient.deletePushDevice(refreshedToken)
|
||||
}
|
||||
}
|
||||
|
||||
private fun userHasPushDevice(): Boolean {
|
||||
|
|
|
|||
|
|
@ -6,27 +6,21 @@ import android.os.Bundle
|
|||
import com.habitrpg.android.habitica.executors.PostExecutionThread
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.activities.ClassSelectionActivity
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import javax.inject.Inject
|
||||
|
||||
class CheckClassSelectionUseCase @Inject constructor(postExecutionThread: PostExecutionThread) : UseCase<CheckClassSelectionUseCase.RequestValues, Void>(postExecutionThread) {
|
||||
class CheckClassSelectionUseCase @Inject constructor(postExecutionThread: PostExecutionThread) : FlowUseCase<CheckClassSelectionUseCase.RequestValues, Unit>() {
|
||||
|
||||
override fun buildUseCaseObservable(requestValues: RequestValues): Flowable<Void> {
|
||||
return Flowable.defer {
|
||||
val user = requestValues.user
|
||||
|
||||
if (requestValues.currentClass == null) {
|
||||
if (user?.stats?.lvl ?: 0 >= 9 &&
|
||||
user?.preferences?.disableClasses != true &&
|
||||
user?.flags?.classSelected != true
|
||||
) {
|
||||
displayClassSelectionActivity(true, null, requestValues.activity)
|
||||
}
|
||||
} else {
|
||||
displayClassSelectionActivity(requestValues.isInitialSelection, requestValues.currentClass, requestValues.activity)
|
||||
override suspend fun run(requestValues: RequestValues) {
|
||||
val user = requestValues.user
|
||||
if (requestValues.currentClass == null) {
|
||||
if ((user?.stats?.lvl ?: 0) >= 9 &&
|
||||
user?.preferences?.disableClasses != true &&
|
||||
user?.flags?.classSelected != true
|
||||
) {
|
||||
displayClassSelectionActivity(true, null, requestValues.activity)
|
||||
}
|
||||
|
||||
Flowable.empty()
|
||||
} else {
|
||||
displayClassSelectionActivity(requestValues.isInitialSelection, requestValues.currentClass, requestValues.activity)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,5 +43,5 @@ class CheckClassSelectionUseCase @Inject constructor(postExecutionThread: PostEx
|
|||
val isInitialSelection: Boolean,
|
||||
val currentClass: String?,
|
||||
val activity: Activity
|
||||
) : UseCase.RequestValues
|
||||
) : FlowUseCase.RequestValues
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,9 @@ package com.habitrpg.android.habitica.interactors
|
|||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.executors.PostExecutionThread
|
||||
import com.habitrpg.android.habitica.helpers.SoundManager
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.shared.habitica.models.responses.TaskScoringResult
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.delay
|
||||
|
|
@ -15,32 +13,35 @@ import kotlinx.coroutines.launch
|
|||
import javax.inject.Inject
|
||||
|
||||
class DisplayItemDropUseCase @Inject
|
||||
constructor(private val soundManager: SoundManager, postExecutionThread: PostExecutionThread) : UseCase<DisplayItemDropUseCase.RequestValues, Void>(postExecutionThread) {
|
||||
constructor(private val soundManager: SoundManager):
|
||||
FlowUseCase<DisplayItemDropUseCase.RequestValues, Unit>() {
|
||||
|
||||
override fun buildUseCaseObservable(requestValues: RequestValues): Flowable<Void> {
|
||||
return Flowable.defer {
|
||||
val data = requestValues.data
|
||||
val snackbarText = StringBuilder(data?.drop?.dialog ?: "")
|
||||
override suspend fun run(requestValues: RequestValues) {
|
||||
val data = requestValues.data
|
||||
val snackbarText = StringBuilder(data?.drop?.dialog ?: "")
|
||||
|
||||
if ((data?.questItemsFound ?: 0) > 0 && requestValues.showQuestItems) {
|
||||
if (snackbarText.isNotEmpty())
|
||||
snackbarText.append('\n')
|
||||
snackbarText.append(requestValues.context.getString(R.string.quest_items_found, data!!.questItemsFound))
|
||||
}
|
||||
|
||||
if (snackbarText.isNotEmpty()) {
|
||||
MainScope().launch(context = Dispatchers.Main) {
|
||||
delay(3000L)
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
requestValues.snackbarTargetView,
|
||||
snackbarText, HabiticaSnackbar.SnackbarDisplayType.DROP, true
|
||||
)
|
||||
soundManager.loadAndPlayAudio(SoundManager.SoundItemDrop)
|
||||
}
|
||||
}
|
||||
|
||||
Flowable.empty()
|
||||
if ((data?.questItemsFound ?: 0) > 0 && requestValues.showQuestItems) {
|
||||
if (snackbarText.isNotEmpty())
|
||||
snackbarText.append('\n')
|
||||
snackbarText.append(
|
||||
requestValues.context.getString(
|
||||
R.string.quest_items_found,
|
||||
data!!.questItemsFound
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (snackbarText.isNotEmpty()) {
|
||||
MainScope().launch(context = Dispatchers.Main) {
|
||||
delay(3000L)
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
requestValues.snackbarTargetView,
|
||||
snackbarText, HabiticaSnackbar.SnackbarDisplayType.DROP, true
|
||||
)
|
||||
soundManager.loadAndPlayAudio(SoundManager.SoundItemDrop)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
class RequestValues(
|
||||
|
|
@ -48,5 +49,5 @@ constructor(private val soundManager: SoundManager, postExecutionThread: PostExe
|
|||
val context: AppCompatActivity,
|
||||
val snackbarTargetView: ViewGroup,
|
||||
val showQuestItems: Boolean
|
||||
) : UseCase.RequestValues
|
||||
) : FlowUseCase.RequestValues
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,75 +7,75 @@ import android.view.View
|
|||
import android.widget.FrameLayout
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository
|
||||
import com.habitrpg.android.habitica.executors.PostExecutionThread
|
||||
import com.habitrpg.android.habitica.models.inventory.Food
|
||||
import com.habitrpg.android.habitica.models.inventory.Pet
|
||||
import com.habitrpg.shared.habitica.models.responses.FeedResponse
|
||||
import com.habitrpg.android.habitica.ui.activities.BaseActivity
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.common.habitica.views.PixelArtView
|
||||
import com.habitrpg.android.habitica.ui.views.SnackbarActivity
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.common.habitica.views.PixelArtView
|
||||
import com.habitrpg.shared.habitica.models.responses.FeedResponse
|
||||
import javax.inject.Inject
|
||||
|
||||
class FeedPetUseCase @Inject
|
||||
constructor(
|
||||
private val inventoryRepository: InventoryRepository,
|
||||
postExecutionThread: PostExecutionThread
|
||||
) : UseCase<FeedPetUseCase.RequestValues, FeedResponse>(postExecutionThread) {
|
||||
override fun buildUseCaseObservable(requestValues: FeedPetUseCase.RequestValues): Flowable<FeedResponse> {
|
||||
return inventoryRepository.feedPet(requestValues.pet, requestValues.food)
|
||||
.doOnNext { feedResponse ->
|
||||
(requestValues.context as? SnackbarActivity)?.showSnackbar(content = feedResponse.message)
|
||||
if (feedResponse.value == -1) {
|
||||
val mountWrapper =
|
||||
View.inflate(
|
||||
requestValues.context,
|
||||
R.layout.pet_imageview,
|
||||
null
|
||||
) as? FrameLayout
|
||||
val mountImageView =
|
||||
mountWrapper?.findViewById(R.id.pet_imageview) as? PixelArtView
|
||||
) : FlowUseCase<FeedPetUseCase.RequestValues, FeedResponse?>() {
|
||||
override suspend fun run(requestValues: FeedPetUseCase.RequestValues): FeedResponse? {
|
||||
val feedResponse = inventoryRepository.feedPet(requestValues.pet, requestValues.food)
|
||||
(requestValues.context as? SnackbarActivity)?.showSnackbar(content = feedResponse?.message)
|
||||
if (feedResponse?.value == -1) {
|
||||
val mountWrapper =
|
||||
View.inflate(
|
||||
requestValues.context,
|
||||
R.layout.pet_imageview,
|
||||
null
|
||||
) as? FrameLayout
|
||||
val mountImageView =
|
||||
mountWrapper?.findViewById(R.id.pet_imageview) as? PixelArtView
|
||||
|
||||
mountImageView?.loadImage("Mount_Icon_" + requestValues.pet.key)
|
||||
val dialog = HabiticaAlertDialog(requestValues.context)
|
||||
dialog.setTitle(
|
||||
requestValues.context.getString(
|
||||
R.string.evolved_pet_title,
|
||||
requestValues.pet.text
|
||||
)
|
||||
mountImageView?.loadImage("Mount_Icon_" + requestValues.pet.key)
|
||||
val dialog = HabiticaAlertDialog(requestValues.context)
|
||||
dialog.setTitle(
|
||||
requestValues.context.getString(
|
||||
R.string.evolved_pet_title,
|
||||
requestValues.pet.text
|
||||
)
|
||||
)
|
||||
dialog.setAdditionalContentView(mountWrapper)
|
||||
dialog.addButton(R.string.onwards, true)
|
||||
dialog.addButton(R.string.share, false) { hatchingDialog, _ ->
|
||||
val message =
|
||||
requestValues.context.getString(
|
||||
R.string.share_raised,
|
||||
requestValues.pet.text
|
||||
)
|
||||
dialog.setAdditionalContentView(mountWrapper)
|
||||
dialog.addButton(R.string.onwards, true)
|
||||
dialog.addButton(R.string.share, false) { hatchingDialog, _ ->
|
||||
val message =
|
||||
requestValues.context.getString(
|
||||
R.string.share_raised,
|
||||
requestValues.pet.text
|
||||
)
|
||||
val mountImageSideLength = 99
|
||||
val sharedImage = Bitmap.createBitmap(
|
||||
mountImageSideLength,
|
||||
mountImageSideLength,
|
||||
Bitmap.Config.ARGB_8888
|
||||
)
|
||||
val canvas = Canvas(sharedImage)
|
||||
mountImageView?.drawable?.setBounds(
|
||||
0,
|
||||
0,
|
||||
mountImageSideLength,
|
||||
mountImageSideLength
|
||||
)
|
||||
mountImageView?.drawable?.draw(canvas)
|
||||
(requestValues.context as? BaseActivity)?.shareContent("raisedPet", message, sharedImage)
|
||||
hatchingDialog.dismiss()
|
||||
}
|
||||
dialog.enqueue()
|
||||
}
|
||||
val mountImageSideLength = 99
|
||||
val sharedImage = Bitmap.createBitmap(
|
||||
mountImageSideLength,
|
||||
mountImageSideLength,
|
||||
Bitmap.Config.ARGB_8888
|
||||
)
|
||||
val canvas = Canvas(sharedImage)
|
||||
mountImageView?.drawable?.setBounds(
|
||||
0,
|
||||
0,
|
||||
mountImageSideLength,
|
||||
mountImageSideLength
|
||||
)
|
||||
mountImageView?.drawable?.draw(canvas)
|
||||
(requestValues.context as? BaseActivity)?.shareContent(
|
||||
"raisedPet",
|
||||
message,
|
||||
sharedImage
|
||||
)
|
||||
hatchingDialog.dismiss()
|
||||
}
|
||||
dialog.enqueue()
|
||||
}
|
||||
return feedResponse
|
||||
}
|
||||
|
||||
class RequestValues(val pet: Pet, val food: Food, val context: Context) :
|
||||
UseCase.RequestValues
|
||||
FlowUseCase.RequestValues
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,24 +7,21 @@ import android.view.View
|
|||
import android.widget.FrameLayout
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository
|
||||
import com.habitrpg.android.habitica.executors.PostExecutionThread
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.inventory.Egg
|
||||
import com.habitrpg.android.habitica.models.inventory.HatchingPotion
|
||||
import com.habitrpg.android.habitica.models.user.Items
|
||||
import com.habitrpg.android.habitica.ui.activities.BaseActivity
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.common.habitica.views.PixelArtView
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.MainScope
|
||||
import javax.inject.Inject
|
||||
|
||||
class HatchPetUseCase @Inject
|
||||
constructor(
|
||||
private val inventoryRepository: InventoryRepository,
|
||||
postExecutionThread: PostExecutionThread
|
||||
) : UseCase<HatchPetUseCase.RequestValues, Items>(postExecutionThread) {
|
||||
override fun buildUseCaseObservable(requestValues: RequestValues): Flowable<Items> {
|
||||
private val inventoryRepository: InventoryRepository) : FlowUseCase<HatchPetUseCase.RequestValues, Items?>() {
|
||||
override suspend fun run(requestValues: RequestValues): Items? {
|
||||
return inventoryRepository.hatchPet(requestValues.egg, requestValues.potion) {
|
||||
val petWrapper = View.inflate(requestValues.context, R.layout.pet_imageview, null) as? FrameLayout
|
||||
val petImageView = petWrapper?.findViewById(R.id.pet_imageview) as? PixelArtView
|
||||
|
|
@ -36,8 +33,9 @@ constructor(
|
|||
dialog.setTitle(requestValues.context.getString(R.string.hatched_pet_title, potionName, eggName))
|
||||
dialog.setAdditionalContentView(petWrapper)
|
||||
dialog.addButton(R.string.equip, true) { _, _ ->
|
||||
inventoryRepository.equip("pet", requestValues.egg.key + "-" + requestValues.potion.key)
|
||||
.subscribe({}, ExceptionHandler.rx())
|
||||
MainScope().launchCatching {
|
||||
inventoryRepository.equip("pet", requestValues.egg.key + "-" + requestValues.potion.key)
|
||||
}
|
||||
}
|
||||
dialog.addButton(R.string.share, false) { hatchingDialog, _ ->
|
||||
val message = requestValues.context.getString(R.string.share_hatched, potionName, eggName)
|
||||
|
|
@ -54,5 +52,5 @@ constructor(
|
|||
}
|
||||
}
|
||||
|
||||
class RequestValues(val potion: HatchingPotion, val egg: Egg, val context: Context) : UseCase.RequestValues
|
||||
class RequestValues(val potion: HatchingPotion, val egg: Egg, val context: Context) : FlowUseCase.RequestValues
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,97 +4,94 @@ import android.graphics.Bitmap
|
|||
import android.view.ViewGroup
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.databinding.DialogLevelup10Binding
|
||||
import com.habitrpg.android.habitica.executors.PostExecutionThread
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.SoundManager
|
||||
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.common.habitica.views.AvatarView
|
||||
import com.habitrpg.android.habitica.ui.activities.BaseActivity
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import com.habitrpg.common.habitica.views.AvatarView
|
||||
import kotlinx.coroutines.MainScope
|
||||
import javax.inject.Inject
|
||||
|
||||
class LevelUpUseCase @Inject
|
||||
constructor(
|
||||
private val soundManager: SoundManager,
|
||||
postExecutionThread: PostExecutionThread,
|
||||
private val checkClassSelectionUseCase: CheckClassSelectionUseCase
|
||||
) : UseCase<LevelUpUseCase.RequestValues, Stats>(postExecutionThread) {
|
||||
) : FlowUseCase<LevelUpUseCase.RequestValues, Stats?>() {
|
||||
|
||||
override fun buildUseCaseObservable(requestValues: RequestValues): Flowable<Stats> {
|
||||
return Flowable.defer {
|
||||
soundManager.loadAndPlayAudio(SoundManager.SoundLevelUp)
|
||||
override suspend fun run(requestValues: RequestValues): Stats? {
|
||||
soundManager.loadAndPlayAudio(SoundManager.SoundLevelUp)
|
||||
val suppressedModals = requestValues.user.preferences?.suppressModals
|
||||
|
||||
val suppressedModals = requestValues.user.preferences?.suppressModals
|
||||
if (requestValues.newLevel == 10) {
|
||||
val binding = DialogLevelup10Binding.inflate(requestValues.activity.layoutInflater)
|
||||
binding.healerIconView.setImageBitmap(HabiticaIconsHelper.imageOfHealerLightBg())
|
||||
binding.mageIconView.setImageBitmap(HabiticaIconsHelper.imageOfMageLightBg())
|
||||
binding.rogueIconView.setImageBitmap(HabiticaIconsHelper.imageOfRogueLightBg())
|
||||
binding.warriorIconView.setImageBitmap(HabiticaIconsHelper.imageOfWarriorLightBg())
|
||||
|
||||
if (requestValues.newLevel == 10) {
|
||||
val binding = DialogLevelup10Binding.inflate(requestValues.activity.layoutInflater)
|
||||
binding.healerIconView.setImageBitmap(HabiticaIconsHelper.imageOfHealerLightBg())
|
||||
binding.mageIconView.setImageBitmap(HabiticaIconsHelper.imageOfMageLightBg())
|
||||
binding.rogueIconView.setImageBitmap(HabiticaIconsHelper.imageOfRogueLightBg())
|
||||
binding.warriorIconView.setImageBitmap(HabiticaIconsHelper.imageOfWarriorLightBg())
|
||||
|
||||
val alert = HabiticaAlertDialog(requestValues.activity)
|
||||
alert.setTitle(requestValues.activity.getString(R.string.levelup_header, requestValues.newLevel))
|
||||
alert.setAdditionalContentView(binding.root)
|
||||
alert.addButton(R.string.select_class, true) { _, _ ->
|
||||
val alert = HabiticaAlertDialog(requestValues.activity)
|
||||
alert.setTitle(requestValues.activity.getString(R.string.levelup_header, requestValues.newLevel))
|
||||
alert.setAdditionalContentView(binding.root)
|
||||
alert.addButton(R.string.select_class, true) { _, _ ->
|
||||
MainScope().launchCatching {
|
||||
showClassSelection(requestValues)
|
||||
}
|
||||
alert.addButton(R.string.not_now, false)
|
||||
alert.isCelebratory = true
|
||||
|
||||
if (!requestValues.activity.isFinishing) {
|
||||
alert.enqueue()
|
||||
}
|
||||
} else {
|
||||
if (suppressedModals?.levelUp == true) {
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
requestValues.snackbarTargetView,
|
||||
requestValues.activity.getString(R.string.levelup_header, requestValues.newLevel),
|
||||
HabiticaSnackbar.SnackbarDisplayType.SUCCESS, true
|
||||
)
|
||||
return@defer Flowable.just<Stats>(requestValues.user.stats)
|
||||
}
|
||||
val customView = requestValues.activity.layoutInflater.inflate(R.layout.dialog_levelup, null)
|
||||
if (customView != null) {
|
||||
val dialogAvatarView = customView.findViewById<AvatarView>(R.id.avatarView)
|
||||
dialogAvatarView.setAvatar(requestValues.user)
|
||||
}
|
||||
|
||||
val message = requestValues.activity.getString(R.string.share_levelup, requestValues.newLevel)
|
||||
val avatarView = AvatarView(requestValues.activity, showBackground = true, showMount = true, showPet = true)
|
||||
avatarView.setAvatar(requestValues.user)
|
||||
var sharedImage: Bitmap? = null
|
||||
avatarView.onAvatarImageReady { image ->
|
||||
sharedImage = image
|
||||
}
|
||||
|
||||
val alert = HabiticaAlertDialog(requestValues.activity)
|
||||
alert.setTitle(requestValues.activity.getString(R.string.levelup_header, requestValues.newLevel))
|
||||
alert.setAdditionalContentView(customView)
|
||||
alert.addButton(R.string.onwards, true) { _, _ ->
|
||||
showClassSelection(requestValues)
|
||||
}
|
||||
alert.addButton(R.string.share, false) { _, _ ->
|
||||
requestValues.activity.shareContent("levelup", message, sharedImage)
|
||||
}
|
||||
alert.isCelebratory = true
|
||||
|
||||
if (!requestValues.activity.isFinishing) {
|
||||
alert.enqueue()
|
||||
}
|
||||
}
|
||||
alert.addButton(R.string.not_now, false)
|
||||
alert.isCelebratory = true
|
||||
|
||||
Flowable.just(requestValues.user.stats!!)
|
||||
if (!requestValues.activity.isFinishing) {
|
||||
alert.enqueue()
|
||||
}
|
||||
} else {
|
||||
if (suppressedModals?.levelUp == true) {
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
requestValues.snackbarTargetView,
|
||||
requestValues.activity.getString(R.string.levelup_header, requestValues.newLevel),
|
||||
HabiticaSnackbar.SnackbarDisplayType.SUCCESS, true
|
||||
)
|
||||
return requestValues.user.stats
|
||||
}
|
||||
val customView = requestValues.activity.layoutInflater.inflate(R.layout.dialog_levelup, null)
|
||||
if (customView != null) {
|
||||
val dialogAvatarView = customView.findViewById<AvatarView>(R.id.avatarView)
|
||||
dialogAvatarView.setAvatar(requestValues.user)
|
||||
}
|
||||
|
||||
val message = requestValues.activity.getString(R.string.share_levelup, requestValues.newLevel)
|
||||
val avatarView = AvatarView(requestValues.activity, showBackground = true, showMount = true, showPet = true)
|
||||
avatarView.setAvatar(requestValues.user)
|
||||
var sharedImage: Bitmap? = null
|
||||
avatarView.onAvatarImageReady { image ->
|
||||
sharedImage = image
|
||||
}
|
||||
|
||||
val alert = HabiticaAlertDialog(requestValues.activity)
|
||||
alert.setTitle(requestValues.activity.getString(R.string.levelup_header, requestValues.newLevel))
|
||||
alert.setAdditionalContentView(customView)
|
||||
alert.addButton(R.string.onwards, true) { _, _ ->
|
||||
MainScope().launchCatching {
|
||||
showClassSelection(requestValues)
|
||||
}
|
||||
}
|
||||
alert.addButton(R.string.share, false) { _, _ ->
|
||||
requestValues.activity.shareContent("levelup", message, sharedImage)
|
||||
}
|
||||
alert.isCelebratory = true
|
||||
|
||||
if (!requestValues.activity.isFinishing) {
|
||||
alert.enqueue()
|
||||
}
|
||||
}
|
||||
return requestValues.user.stats
|
||||
}
|
||||
|
||||
private fun showClassSelection(requestValues: RequestValues) {
|
||||
checkClassSelectionUseCase.observable(CheckClassSelectionUseCase.RequestValues(requestValues.user, true, null, requestValues.activity))
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
private suspend fun showClassSelection(requestValues: RequestValues) {
|
||||
checkClassSelectionUseCase.callInteractor(CheckClassSelectionUseCase.RequestValues(requestValues.user, true, null, requestValues.activity))
|
||||
}
|
||||
|
||||
class RequestValues(
|
||||
|
|
@ -102,7 +99,7 @@ constructor(
|
|||
val level: Int?,
|
||||
val activity: BaseActivity,
|
||||
val snackbarTargetView: ViewGroup
|
||||
) : UseCase.RequestValues {
|
||||
) : FlowUseCase.RequestValues {
|
||||
val newLevel: Int = level ?: 0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.core.util.Pair
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.executors.PostExecutionThread
|
||||
import com.habitrpg.android.habitica.models.user.Stats
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.activities.BaseActivity
|
||||
|
|
@ -21,39 +20,30 @@ import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
|||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType
|
||||
import com.habitrpg.shared.habitica.extensions.round
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
class NotifyUserUseCase @Inject
|
||||
constructor(
|
||||
postExecutionThread: PostExecutionThread,
|
||||
private val levelUpUseCase: LevelUpUseCase,
|
||||
private val userRepository: UserRepository
|
||||
) : UseCase<NotifyUserUseCase.RequestValues, Stats>(postExecutionThread) {
|
||||
) : FlowUseCase<NotifyUserUseCase.RequestValues, Stats?>() {
|
||||
|
||||
override fun buildUseCaseObservable(requestValues: RequestValues): Flowable<Stats> {
|
||||
return Flowable.defer {
|
||||
if (requestValues.user == null) {
|
||||
return@defer Flowable.empty<Stats>()
|
||||
}
|
||||
val stats = requestValues.user.stats
|
||||
|
||||
val pair = getNotificationAndAddStatsToUser(requestValues.context, requestValues.xp, requestValues.hp, requestValues.gold, requestValues.mp, requestValues.questDamage, requestValues.user)
|
||||
val view = pair.first
|
||||
val type = pair.second
|
||||
if (view != null && type != null) {
|
||||
HabiticaSnackbar.showSnackbar(requestValues.snackbarTargetView, null, null, view, type)
|
||||
}
|
||||
if (requestValues.hasLeveledUp == true) {
|
||||
return@defer levelUpUseCase.observable(LevelUpUseCase.RequestValues(requestValues.user, requestValues.level, requestValues.context, requestValues.snackbarTargetView))
|
||||
// TODO: .flatMap { userRepository.retrieveUser(true) }
|
||||
.flatMap { userRepository.getUserFlowable().firstElement().toFlowable() }
|
||||
.map { it.stats }
|
||||
} else {
|
||||
return@defer Flowable.just(stats)
|
||||
}
|
||||
override suspend fun run(requestValues: RequestValues): Stats? {
|
||||
if (requestValues.user == null) {
|
||||
return null
|
||||
}
|
||||
val pair = getNotificationAndAddStatsToUser(requestValues.context, requestValues.xp, requestValues.hp, requestValues.gold, requestValues.mp, requestValues.questDamage, requestValues.user)
|
||||
val view = pair.first
|
||||
val type = pair.second
|
||||
if (view != null && type != null) {
|
||||
HabiticaSnackbar.showSnackbar(requestValues.snackbarTargetView, null, null, view, type)
|
||||
}
|
||||
if (requestValues.hasLeveledUp == true) {
|
||||
levelUpUseCase.callInteractor(LevelUpUseCase.RequestValues(requestValues.user, requestValues.level, requestValues.context, requestValues.snackbarTargetView))
|
||||
userRepository.retrieveUser(true)
|
||||
}
|
||||
return requestValues.user.stats
|
||||
}
|
||||
|
||||
class RequestValues(
|
||||
|
|
@ -67,7 +57,7 @@ constructor(
|
|||
val questDamage: Double?,
|
||||
val hasLeveledUp: Boolean?,
|
||||
val level: Int?
|
||||
) : UseCase.RequestValues
|
||||
) : FlowUseCase.RequestValues
|
||||
|
||||
companion object {
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ abstract class UseCase<Q : UseCase.RequestValues?, T: Any> protected constructor
|
|||
|
||||
abstract class FlowUseCase<Q : FlowUseCase.RequestValues?, T> {
|
||||
protected abstract suspend fun run(requestValues: Q): T
|
||||
suspend fun observable(requestValues: Q): T {
|
||||
return withContext(Dispatchers.IO) {
|
||||
suspend fun callInteractor(requestValues: Q): T {
|
||||
return withContext(Dispatchers.Main) {
|
||||
run(requestValues)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import com.habitrpg.android.habitica.data.SocialRepository
|
|||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.interactors.NotifyUserUseCase
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import kotlinx.coroutines.MainScope
|
||||
|
|
@ -65,15 +66,20 @@ class LocalNotificationActionReceiver : BroadcastReceiver() {
|
|||
}
|
||||
context?.getString(R.string.reject_party_invite) -> {
|
||||
groupID?.let {
|
||||
socialRepository.rejectGroupInvite(it)
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
MainScope().launchCatching {
|
||||
socialRepository.rejectGroupInvite(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
context?.getString(R.string.accept_quest_invite) -> {
|
||||
socialRepository.acceptQuest(user).subscribe({ }, ExceptionHandler.rx())
|
||||
MainScope().launchCatching {
|
||||
socialRepository.acceptQuest(user)
|
||||
}
|
||||
}
|
||||
context?.getString(R.string.reject_quest_invite) -> {
|
||||
socialRepository.rejectQuest(user).subscribe({ }, ExceptionHandler.rx())
|
||||
MainScope().launchCatching {
|
||||
socialRepository.rejectQuest(user)
|
||||
}
|
||||
}
|
||||
context?.getString(R.string.accept_guild_invite) -> {
|
||||
groupID?.let {
|
||||
|
|
@ -84,21 +90,20 @@ class LocalNotificationActionReceiver : BroadcastReceiver() {
|
|||
}
|
||||
context?.getString(R.string.reject_guild_invite) -> {
|
||||
groupID?.let {
|
||||
socialRepository.rejectGroupInvite(it)
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
MainScope().launchCatching {
|
||||
socialRepository.rejectGroupInvite(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
context?.getString(R.string.group_message_reply) -> {
|
||||
groupID?.let {
|
||||
getMessageText(context?.getString(R.string.group_message_reply))?.let { message ->
|
||||
socialRepository.postGroupChat(it, message).subscribe(
|
||||
{
|
||||
context?.let { c ->
|
||||
NotificationManagerCompat.from(c).cancel(it.hashCode())
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
MainScope().launchCatching {
|
||||
socialRepository.postGroupChat(it, message)
|
||||
context?.let { c ->
|
||||
NotificationManagerCompat.from(c).cancel(it.hashCode())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,13 +15,12 @@ import com.habitrpg.android.habitica.R
|
|||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.extensions.withImmutableFlag
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.TaskAlarmManager
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import io.reactivex.rxjava3.functions.BiFunction
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.Random
|
||||
|
|
@ -57,26 +56,20 @@ class NotificationPublisher : BroadcastReceiver() {
|
|||
}
|
||||
val checkDailies = intent.getBooleanExtra(CHECK_DAILIES, false)
|
||||
if (checkDailies) {
|
||||
taskRepository.getTasksFlowable(TaskType.DAILY, null, emptyArray()).firstElement().zipWith(
|
||||
userRepository.getUserFlowable().firstElement(),
|
||||
BiFunction<List<Task>, User, Pair<List<Task>, User>> { tasks, user ->
|
||||
return@BiFunction Pair(tasks, user)
|
||||
MainScope().launchCatching {
|
||||
val tasks = taskRepository.getTasks(TaskType.DAILY, null, emptyArray()).firstOrNull()
|
||||
val user = userRepository.getUser().firstOrNull()
|
||||
var showNotifications = false
|
||||
for (task in tasks ?: emptyList()) {
|
||||
if (task.checkIfDue()) {
|
||||
showNotifications = true
|
||||
break
|
||||
}
|
||||
}
|
||||
).subscribe(
|
||||
{ pair ->
|
||||
var showNotifications = false
|
||||
for (task in pair.first) {
|
||||
if (task.checkIfDue()) {
|
||||
showNotifications = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (showNotifications) {
|
||||
notify(intent, buildNotification(wasInactive, pair.second.authentication?.timestamps?.createdAt))
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
if (showNotifications) {
|
||||
notify(intent, buildNotification(wasInactive, user?.authentication?.timestamps?.createdAt))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
notify(intent, buildNotification(wasInactive))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ 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.android.habitica.helpers.launchCatching
|
||||
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
|
||||
|
|
@ -25,6 +26,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.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
|
@ -115,7 +117,9 @@ class ArmoireActivity : BaseActivity() {
|
|||
finish()
|
||||
}
|
||||
binding.equipButton.setOnClickListener {
|
||||
equipmentKey?.let { it1 -> inventoryRepository.equip("equipped", it1).subscribe({}, ExceptionHandler.rx()) }
|
||||
equipmentKey?.let { it1 ->
|
||||
MainScope().launchCatching { inventoryRepository.equip("equipped", it1) }
|
||||
}
|
||||
finish()
|
||||
}
|
||||
binding.dropRateButton.setOnClickListener {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import com.habitrpg.android.habitica.data.UserRepository
|
|||
import com.habitrpg.android.habitica.extensions.updateStatusBarColor
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.NotificationsManager
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.interactors.ShowNotificationInteractor
|
||||
import com.habitrpg.android.habitica.proxy.AnalyticsManager
|
||||
import com.habitrpg.android.habitica.ui.helpers.ToolbarColorHelper
|
||||
|
|
@ -36,7 +37,6 @@ import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
|||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.common.habitica.extensions.isUsingNightModeResources
|
||||
import com.habitrpg.common.habitica.helpers.LanguageHelper
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
|
@ -66,8 +66,6 @@ abstract class BaseActivity : AppCompatActivity() {
|
|||
return (getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater).inflate(layoutResId ?: 0, null)
|
||||
}
|
||||
|
||||
var compositeSubscription = CompositeDisposable()
|
||||
|
||||
private val habiticaApplication: HabiticaApplication
|
||||
get() = application as HabiticaApplication
|
||||
|
||||
|
|
@ -95,17 +93,15 @@ abstract class BaseActivity : AppCompatActivity() {
|
|||
getLayoutResId()?.let {
|
||||
setContentView(getContentView(it))
|
||||
}
|
||||
compositeSubscription = CompositeDisposable()
|
||||
compositeSubscription.add(notificationsManager.displayNotificationEvents.subscribe(
|
||||
{
|
||||
if (ShowNotificationInteractor(this, lifecycleScope).handleNotification(it)) {
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.retrieveUser(false, true)
|
||||
lifecycleScope.launchCatching {
|
||||
notificationsManager.displayNotificationEvents.collect {
|
||||
if (ShowNotificationInteractor(this@BaseActivity, lifecycleScope).handleNotification(it)) {
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.retrieveUser(false, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRestart() {
|
||||
|
|
@ -212,10 +208,6 @@ abstract class BaseActivity : AppCompatActivity() {
|
|||
|
||||
override fun onDestroy() {
|
||||
destroyed = true
|
||||
|
||||
if (!compositeSubscription.isDisposed) {
|
||||
compositeSubscription.dispose()
|
||||
}
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import com.habitrpg.android.habitica.databinding.ActivityCreateChallengeBinding
|
|||
import com.habitrpg.android.habitica.extensions.addCloseButton
|
||||
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.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
|
|
@ -38,7 +39,6 @@ import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
|||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaProgressDialog
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
|
|
@ -52,8 +52,10 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
|
||||
@Inject
|
||||
internal lateinit var challengeRepository: ChallengeRepository
|
||||
|
||||
@Inject
|
||||
internal lateinit var socialRepository: SocialRepository
|
||||
|
||||
@Inject
|
||||
internal lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
|
|
@ -69,6 +71,7 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
private val removedTasks = HashMap<String, Task>()
|
||||
|
||||
override var overrideModernHeader: Boolean? = true
|
||||
|
||||
// Add {*} Items
|
||||
private lateinit var addHabit: Task
|
||||
private lateinit var addDaily: Task
|
||||
|
|
@ -130,37 +133,34 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
savingInProgress = true
|
||||
val dialog = HabiticaProgressDialog.show(this, R.string.saving)
|
||||
|
||||
val observable: Flowable<Challenge> = if (editMode) {
|
||||
updateChallenge()
|
||||
} else {
|
||||
createChallenge()
|
||||
}
|
||||
lifecycleScope.launchCatching({
|
||||
dialog?.dismiss()
|
||||
savingInProgress = false
|
||||
ExceptionHandler.reportError(it)
|
||||
}) {
|
||||
val challenge = if (editMode) {
|
||||
updateChallenge()
|
||||
} else {
|
||||
createChallenge()
|
||||
}
|
||||
|
||||
compositeSubscription.add(
|
||||
observable
|
||||
.flatMap {
|
||||
challengeId = it.id
|
||||
challengeRepository.retrieveChallenges(0, true)
|
||||
challengeId = challenge?.id
|
||||
challengeRepository.retrieveChallenges(0, true)
|
||||
|
||||
dialog?.dismiss()
|
||||
savingInProgress = false
|
||||
finish()
|
||||
if (!editMode) {
|
||||
lifecycleScope.launch(context = Dispatchers.Main) {
|
||||
delay(500L)
|
||||
MainNavigationController.navigate(
|
||||
ChallengesOverviewFragmentDirections.openChallengeDetail(
|
||||
challengeId ?: ""
|
||||
)
|
||||
)
|
||||
}
|
||||
.subscribe(
|
||||
{
|
||||
dialog?.dismiss()
|
||||
savingInProgress = false
|
||||
finish()
|
||||
if (!editMode) {
|
||||
lifecycleScope.launch(context = Dispatchers.Main) {
|
||||
delay(500L)
|
||||
MainNavigationController.navigate(ChallengesOverviewFragmentDirections.openChallengeDetail(challengeId ?: ""))
|
||||
}
|
||||
}
|
||||
},
|
||||
{ throwable ->
|
||||
dialog?.dismiss()
|
||||
savingInProgress = false
|
||||
ExceptionHandler.reportError(throwable)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else if (item.itemId == android.R.id.home) {
|
||||
finish()
|
||||
return true
|
||||
|
|
@ -229,13 +229,11 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
openTaskDisabled = false,
|
||||
taskActionsDisabled = true
|
||||
).also { challengeTasks = it }
|
||||
compositeSubscription.add(
|
||||
challengeTasks.taskOpenEvents.subscribe {
|
||||
if (it.isValid) {
|
||||
openNewTaskActivity(it.type, it)
|
||||
}
|
||||
challengeTasks.onTaskOpen = {
|
||||
if (it.isValid) {
|
||||
openNewTaskActivity(it.type, it)
|
||||
}
|
||||
)
|
||||
}
|
||||
locationAdapter = GroupArrayAdapter(this)
|
||||
|
||||
if (bundle != null) {
|
||||
|
|
@ -339,7 +337,8 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
|
||||
locationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
val groups = socialRepository.getUserGroups("guild").firstOrNull()?.toMutableList() ?: return@launch
|
||||
val groups = socialRepository.getUserGroups("guild").firstOrNull()?.toMutableList()
|
||||
?: return@launch
|
||||
val partyID = userRepository.getUser().firstOrNull()?.party?.id
|
||||
val party = if (partyID?.isNotBlank() == true) {
|
||||
socialRepository.retrieveGroup(partyID)
|
||||
|
|
@ -360,13 +359,20 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
binding.challengeLocationSpinner.adapter = locationAdapter
|
||||
binding.challengeLocationSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(adapterView: AdapterView<*>, view: View?, i: Int, l: Long) {
|
||||
checkPrizeAndMinimumForTavern()
|
||||
}
|
||||
binding.challengeLocationSpinner.onItemSelectedListener =
|
||||
object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(
|
||||
adapterView: AdapterView<*>,
|
||||
view: View?,
|
||||
i: Int,
|
||||
l: Long
|
||||
) {
|
||||
checkPrizeAndMinimumForTavern()
|
||||
}
|
||||
|
||||
override fun onNothingSelected(adapterView: AdapterView<*>) { /* no-on */ }
|
||||
}
|
||||
override fun onNothingSelected(adapterView: AdapterView<*>) { /* no-on */
|
||||
}
|
||||
}
|
||||
binding.createChallengePrize.setOnKeyListener { _, _, _ ->
|
||||
checkPrizeAndMinimumForTavern()
|
||||
|
||||
|
|
@ -380,21 +386,17 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
taskList.add(addReward)
|
||||
|
||||
challengeTasks.setTasks(taskList)
|
||||
compositeSubscription.add(
|
||||
challengeTasks.addItemObservable().subscribe(
|
||||
{ t ->
|
||||
when (t.text) {
|
||||
addHabit.text -> openNewTaskActivity(TaskType.HABIT, null)
|
||||
addDaily.text -> openNewTaskActivity(TaskType.DAILY, null)
|
||||
addTodo.text -> openNewTaskActivity(TaskType.TODO, null)
|
||||
addReward.text -> openNewTaskActivity(TaskType.REWARD, null)
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
challengeTasks.onTaskOpen = { t ->
|
||||
when (t.text) {
|
||||
addHabit.text -> openNewTaskActivity(TaskType.HABIT, null)
|
||||
addDaily.text -> openNewTaskActivity(TaskType.DAILY, null)
|
||||
addTodo.text -> openNewTaskActivity(TaskType.TODO, null)
|
||||
addReward.text -> openNewTaskActivity(TaskType.REWARD, null)
|
||||
}
|
||||
}
|
||||
|
||||
binding.createChallengeTaskList.addOnItemTouchListener(object : androidx.recyclerview.widget.RecyclerView.SimpleOnItemTouchListener() {
|
||||
binding.createChallengeTaskList.addOnItemTouchListener(object :
|
||||
androidx.recyclerview.widget.RecyclerView.SimpleOnItemTouchListener() {
|
||||
override fun onInterceptTouchEvent(
|
||||
rv: androidx.recyclerview.widget.RecyclerView,
|
||||
e: MotionEvent
|
||||
|
|
@ -404,13 +406,14 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
}
|
||||
})
|
||||
binding.createChallengeTaskList.adapter = challengeTasks
|
||||
binding.createChallengeTaskList.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this)
|
||||
binding.createChallengeTaskList.layoutManager =
|
||||
androidx.recyclerview.widget.LinearLayoutManager(this)
|
||||
}
|
||||
|
||||
private fun fillControlsByChallenge() {
|
||||
challengeId?.let {
|
||||
challengeRepository.getChallenge(it).subscribe(
|
||||
{ challenge ->
|
||||
lifecycleScope.launchCatching {
|
||||
challengeRepository.getChallenge(it).collect { challenge ->
|
||||
groupID = challenge.groupId
|
||||
editMode = true
|
||||
binding.createChallengeTitle.setText(challenge.name)
|
||||
|
|
@ -428,17 +431,15 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
checkPrizeAndMinimumForTavern()
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
challengeRepository.getChallengeTasks(it).subscribe(
|
||||
{ tasks ->
|
||||
}
|
||||
}
|
||||
lifecycleScope.launchCatching {
|
||||
challengeRepository.getChallengeTasks(it).collect { tasks ->
|
||||
tasks.forEach { task ->
|
||||
addOrUpdateTaskInList(task, true)
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -460,16 +461,17 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
newTaskResult.launch(intent)
|
||||
}
|
||||
|
||||
private val newTaskResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
val task = it.data?.getParcelableExtra<Task>(TaskFormActivity.PARCELABLE_TASK)
|
||||
if (task != null) {
|
||||
addOrUpdateTaskInList(task)
|
||||
private val newTaskResult =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
val task = it.data?.getParcelableExtra<Task>(TaskFormActivity.PARCELABLE_TASK)
|
||||
if (task != null) {
|
||||
addOrUpdateTaskInList(task)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createChallenge(): Flowable<Challenge> {
|
||||
private suspend fun createChallenge(): Challenge? {
|
||||
val c = challengeData
|
||||
|
||||
val taskList = challengeTasks.taskList
|
||||
|
|
@ -481,7 +483,7 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
return challengeRepository.createChallenge(c, taskList)
|
||||
}
|
||||
|
||||
private fun updateChallenge(): Flowable<Challenge> {
|
||||
private suspend fun updateChallenge(): Challenge? {
|
||||
val c = challengeData
|
||||
|
||||
val taskList = challengeTasks.taskList
|
||||
|
|
@ -528,7 +530,8 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
return editText.text.toString()
|
||||
}
|
||||
|
||||
private class GroupArrayAdapter(context: Context) : ArrayAdapter<Group>(context, android.R.layout.simple_spinner_item) {
|
||||
private class GroupArrayAdapter(context: Context) :
|
||||
ArrayAdapter<Group>(context, android.R.layout.simple_spinner_item) {
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val checkedTextView = super.getView(position, convertView, parent) as? TextView
|
||||
|
|
@ -537,7 +540,8 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val checkedTextView = super.getDropDownView(position, convertView, parent) as? AppCompatCheckedTextView
|
||||
val checkedTextView =
|
||||
super.getDropDownView(position, convertView, parent) as? AppCompatCheckedTextView
|
||||
checkedTextView?.text = getItem(position)?.name
|
||||
return checkedTextView ?: View(context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.habitrpg.android.habitica.extensions.addCancelButton
|
|||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.UserStatComputer
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.Achievement
|
||||
import com.habitrpg.android.habitica.models.inventory.Equipment
|
||||
import com.habitrpg.android.habitica.models.members.Member
|
||||
|
|
@ -39,10 +40,10 @@ import com.habitrpg.common.habitica.extensions.loadImage
|
|||
import com.habitrpg.common.habitica.helpers.RecyclerViewState
|
||||
import com.habitrpg.common.habitica.helpers.setMarkdown
|
||||
import com.habitrpg.common.habitica.views.PixelArtView
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
import java.text.SimpleDateFormat
|
||||
import javax.inject.Inject
|
||||
|
|
@ -54,8 +55,10 @@ class FullProfileActivity : BaseActivity() {
|
|||
|
||||
@Inject
|
||||
lateinit var inventoryRepository: InventoryRepository
|
||||
|
||||
@Inject
|
||||
lateinit var apiClient: ApiClient
|
||||
|
||||
@Inject
|
||||
lateinit var socialRepository: SocialRepository
|
||||
|
||||
|
|
@ -91,7 +94,12 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
avatarWithBars = AvatarWithBarsViewModel(this, binding.avatarWithBars)
|
||||
|
||||
binding.avatarWithBars.root.setBackgroundColor(ContextCompat.getColor(this, R.color.transparent))
|
||||
binding.avatarWithBars.root.setBackgroundColor(
|
||||
ContextCompat.getColor(
|
||||
this,
|
||||
R.color.transparent
|
||||
)
|
||||
)
|
||||
binding.avatarWithBars.hpBar.barBackgroundColor = getThemeColor(R.color.window_background)
|
||||
binding.avatarWithBars.xpBar.barBackgroundColor = getThemeColor(R.color.window_background)
|
||||
binding.avatarWithBars.mpBar.barBackgroundColor = getThemeColor(R.color.window_background)
|
||||
|
|
@ -100,13 +108,24 @@ class FullProfileActivity : BaseActivity() {
|
|||
binding.attributesCardView.setOnClickListener { toggleAttributeDetails() }
|
||||
|
||||
binding.sendMessageButton.setOnClickListener { showSendMessageToUserDialog() }
|
||||
binding.giftGemsButton.setOnClickListener { MainNavigationController.navigate(R.id.giftGemsActivity, bundleOf(Pair("userID", userID), Pair("username", null))) }
|
||||
binding.giftSubscriptionButton.setOnClickListener { MainNavigationController.navigate(R.id.giftSubscriptionActivity, bundleOf(Pair("userID", userID), Pair("username", null))) }
|
||||
binding.giftGemsButton.setOnClickListener {
|
||||
MainNavigationController.navigate(
|
||||
R.id.giftGemsActivity,
|
||||
bundleOf(Pair("userID", userID), Pair("username", null))
|
||||
)
|
||||
}
|
||||
binding.giftSubscriptionButton.setOnClickListener {
|
||||
MainNavigationController.navigate(
|
||||
R.id.giftSubscriptionActivity,
|
||||
bundleOf(Pair("userID", userID), Pair("username", null))
|
||||
)
|
||||
}
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.getUser()
|
||||
.collect {
|
||||
blocks = it?.inbox?.blocks ?: listOf()
|
||||
binding.blockedDisclaimerView.visibility = if (isUserBlocked()) View.VISIBLE else View.GONE
|
||||
binding.blockedDisclaimerView.visibility =
|
||||
if (isUserBlocked()) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -139,22 +158,26 @@ class FullProfileActivity : BaseActivity() {
|
|||
true
|
||||
}
|
||||
R.id.copy_username -> {
|
||||
val clipboard = this.getSystemService(Context.CLIPBOARD_SERVICE) as? android.content.ClipboardManager
|
||||
val clipboard =
|
||||
this.getSystemService(Context.CLIPBOARD_SERVICE) as? android.content.ClipboardManager
|
||||
val clip = android.content.ClipData.newPlainText(username, username)
|
||||
clipboard?.setPrimaryClip(clip)
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
this@FullProfileActivity.binding.scrollView.getChildAt(0) as ViewGroup,
|
||||
String.format(getString(R.string.username_copied), userDisplayName), SnackbarDisplayType.NORMAL
|
||||
String.format(getString(R.string.username_copied), userDisplayName),
|
||||
SnackbarDisplayType.NORMAL
|
||||
)
|
||||
true
|
||||
}
|
||||
R.id.copy_userid -> {
|
||||
val clipboard = this.getSystemService(Context.CLIPBOARD_SERVICE) as? android.content.ClipboardManager
|
||||
val clipboard =
|
||||
this.getSystemService(Context.CLIPBOARD_SERVICE) as? android.content.ClipboardManager
|
||||
val clip = android.content.ClipData.newPlainText(userID, userID)
|
||||
clipboard?.setPrimaryClip(clip)
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
this@FullProfileActivity.binding.scrollView.getChildAt(0) as ViewGroup,
|
||||
String.format(getString(R.string.id_copied), userDisplayName), SnackbarDisplayType.NORMAL
|
||||
String.format(getString(R.string.id_copied), userDisplayName),
|
||||
SnackbarDisplayType.NORMAL
|
||||
)
|
||||
true
|
||||
}
|
||||
|
|
@ -171,17 +194,11 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
private fun useBlock() {
|
||||
compositeSubscription.add(
|
||||
socialRepository.blockMember(userID).subscribe(
|
||||
{
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.retrieveUser()
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
lifecycleScope.launchCatching {
|
||||
socialRepository.blockMember(userID)
|
||||
userRepository.retrieveUser()
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showBlockDialog() {
|
||||
|
|
@ -199,7 +216,10 @@ class FullProfileActivity : BaseActivity() {
|
|||
finish()
|
||||
MainScope().launch(context = Dispatchers.Main) {
|
||||
delay(500L)
|
||||
MainNavigationController.navigate(R.id.inboxMessageListFragment, bundleOf(Pair("username", username), Pair("userID", userID)))
|
||||
MainNavigationController.navigate(
|
||||
R.id.inboxMessageListFragment,
|
||||
bundleOf(Pair("username", username), Pair("userID", userID))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -226,22 +246,33 @@ class FullProfileActivity : BaseActivity() {
|
|||
binding.blurbTextView.movementMethod = LinkMovementMethod.getInstance()
|
||||
}
|
||||
|
||||
user.authentication?.timestamps?.createdAt?.let { binding.joinedView.text = dateFormatter.format(it) }
|
||||
user.authentication?.timestamps?.lastLoggedIn?.let { binding.lastLoginView.text = dateFormatter.format(it) }
|
||||
user.authentication?.timestamps?.createdAt?.let {
|
||||
binding.joinedView.text = dateFormatter.format(it)
|
||||
}
|
||||
user.authentication?.timestamps?.lastLoggedIn?.let {
|
||||
binding.lastLoginView.text = dateFormatter.format(it)
|
||||
}
|
||||
binding.totalCheckinsView.text = user.loginIncentives.toString()
|
||||
|
||||
avatarWithBars?.updateData(user)
|
||||
|
||||
compositeSubscription.add(loadItemDataByOutfit(user.equipped).subscribe({ gear -> this.gotGear(gear, user) }, ExceptionHandler.rx()))
|
||||
lifecycleScope.launchCatching {
|
||||
loadItemDataByOutfit(user.equipped).collect { gear -> gotGear(gear, user) }
|
||||
}
|
||||
|
||||
if (user.preferences?.costume == true) {
|
||||
compositeSubscription.add(loadItemDataByOutfit(user.costume).subscribe({ this.gotCostume(it) }, ExceptionHandler.rx()))
|
||||
lifecycleScope.launchCatching {
|
||||
loadItemDataByOutfit(user.costume).collect { gotCostume(it) }
|
||||
}
|
||||
} else {
|
||||
binding.costumeCard.visibility = View.GONE
|
||||
}
|
||||
|
||||
// Load the members achievements now
|
||||
compositeSubscription.add(socialRepository.getMemberAchievements(this.userID).subscribe({ this.fillAchievements(it) }, ExceptionHandler.rx()))
|
||||
lifecycleScope.launchCatching {
|
||||
val achievements = socialRepository.getMemberAchievements(userID)
|
||||
fillAchievements(achievements)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePetsMountsView(user: Member) {
|
||||
|
|
@ -252,9 +283,9 @@ class FullProfileActivity : BaseActivity() {
|
|||
if (user.currentMount?.isNotBlank() == true) binding.currentMountDrawee.loadImage("Mount_Icon_" + user.currentMount)
|
||||
}
|
||||
|
||||
// endregion
|
||||
// endregion
|
||||
|
||||
// region Attributes
|
||||
// region Attributes
|
||||
|
||||
private fun fillAchievements(achievements: List<Achievement>?) {
|
||||
if (achievements == null) {
|
||||
|
|
@ -262,23 +293,36 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
val items = ArrayList<Any>()
|
||||
|
||||
fillAchievements(R.string.basic_achievements, achievements.filter { it.category == "basic" }, items)
|
||||
fillAchievements(R.string.seasonal_achievements, achievements.filter { it.category == "seasonal" }, items)
|
||||
fillAchievements(R.string.special_achievements, achievements.filter { it.category == "special" }, items)
|
||||
fillAchievements(
|
||||
R.string.basic_achievements,
|
||||
achievements.filter { it.category == "basic" },
|
||||
items
|
||||
)
|
||||
fillAchievements(
|
||||
R.string.seasonal_achievements,
|
||||
achievements.filter { it.category == "seasonal" },
|
||||
items
|
||||
)
|
||||
fillAchievements(
|
||||
R.string.special_achievements,
|
||||
achievements.filter { it.category == "special" },
|
||||
items
|
||||
)
|
||||
|
||||
val adapter = AchievementProfileAdapter()
|
||||
adapter.setItemList(items)
|
||||
|
||||
val layoutManager = androidx.recyclerview.widget.GridLayoutManager(this, 3)
|
||||
layoutManager.spanSizeLookup = object : androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return if (adapter.getItemViewType(position) == 0) {
|
||||
layoutManager.spanCount
|
||||
} else {
|
||||
1
|
||||
layoutManager.spanSizeLookup =
|
||||
object : androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return if (adapter.getItemViewType(position) == 0) {
|
||||
layoutManager.spanCount
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.achievementGroupList.layoutManager = layoutManager
|
||||
binding.achievementGroupList.adapter = adapter
|
||||
|
||||
|
|
@ -292,7 +336,9 @@ class FullProfileActivity : BaseActivity() {
|
|||
) {
|
||||
// Order by ID first
|
||||
val achievementList = ArrayList(achievements)
|
||||
achievementList.sortWith { achievement, t1 -> achievement.index.toDouble().compareTo(t1.index.toDouble()) }
|
||||
achievementList.sortWith { achievement, t1 ->
|
||||
achievement.index.toDouble().compareTo(t1.index.toDouble())
|
||||
}
|
||||
|
||||
targetList.add(getString(labelID))
|
||||
targetList.addAll(achievementList)
|
||||
|
|
@ -318,8 +364,14 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun addEquipmentRow(table: TableLayout, gearKey: String?, text: String?, stats: String?) {
|
||||
val gearRow = layoutInflater.inflate(R.layout.profile_gear_tablerow, table, false) as? TableRow
|
||||
private fun addEquipmentRow(
|
||||
table: TableLayout,
|
||||
gearKey: String?,
|
||||
text: String?,
|
||||
stats: String?
|
||||
) {
|
||||
val gearRow =
|
||||
layoutInflater.inflate(R.layout.profile_gear_tablerow, table, false) as? TableRow
|
||||
|
||||
val draweeView = gearRow?.findViewById<PixelArtView>(R.id.gear_drawee)
|
||||
|
||||
|
|
@ -348,7 +400,7 @@ class FullProfileActivity : BaseActivity() {
|
|||
)
|
||||
}
|
||||
|
||||
private fun loadItemDataByOutfit(outfit: Outfit?): Flowable<out List<Equipment>> {
|
||||
private fun loadItemDataByOutfit(outfit: Outfit?): Flow<List<Equipment>> {
|
||||
val outfitList = ArrayList<String>()
|
||||
if (outfit != null) {
|
||||
outfitList.add(outfit.armor)
|
||||
|
|
@ -381,7 +433,15 @@ class FullProfileActivity : BaseActivity() {
|
|||
if (row is UserStatComputer.EquipmentRow) {
|
||||
addEquipmentRow(binding.equipmentTableLayout, row.gearKey, row.text, row.stats)
|
||||
} else if (row is UserStatComputer.AttributeRow) {
|
||||
addAttributeRow(getString(row.labelId), row.strVal, row.intVal, row.conVal, row.perVal, row.roundDown, row.summary)
|
||||
addAttributeRow(
|
||||
getString(row.labelId),
|
||||
row.strVal,
|
||||
row.intVal,
|
||||
row.conVal,
|
||||
row.perVal,
|
||||
row.roundDown,
|
||||
row.summary
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -400,7 +460,11 @@ class FullProfileActivity : BaseActivity() {
|
|||
val buffs = stats.buffs
|
||||
|
||||
addAttributeRow(
|
||||
getString(R.string.profile_allocated), stats.strength?.toFloat() ?: 0f, stats.intelligence?.toFloat() ?: 0f, stats.constitution?.toFloat() ?: 0f, stats.per?.toFloat() ?: 0f,
|
||||
getString(R.string.profile_allocated),
|
||||
stats.strength?.toFloat() ?: 0f,
|
||||
stats.intelligence?.toFloat() ?: 0f,
|
||||
stats.constitution?.toFloat() ?: 0f,
|
||||
stats.per?.toFloat() ?: 0f,
|
||||
roundDown = true,
|
||||
isSummary = false
|
||||
)
|
||||
|
|
@ -408,11 +472,23 @@ class FullProfileActivity : BaseActivity() {
|
|||
getString(R.string.buffs),
|
||||
buffs?.str
|
||||
?: 0f,
|
||||
buffs?._int ?: 0f, buffs?.con ?: 0f, buffs?.per ?: 0f, roundDown = true, isSummary = false
|
||||
buffs?._int ?: 0f,
|
||||
buffs?.con ?: 0f,
|
||||
buffs?.per ?: 0f,
|
||||
roundDown = true,
|
||||
isSummary = false
|
||||
)
|
||||
|
||||
// Summary row
|
||||
addAttributeRow("", attributeStrSum, attributeIntSum, attributeConSum, attributePerSum, roundDown = false, isSummary = true)
|
||||
addAttributeRow(
|
||||
"",
|
||||
attributeStrSum,
|
||||
attributeIntSum,
|
||||
attributeConSum,
|
||||
attributePerSum,
|
||||
roundDown = false,
|
||||
isSummary = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun addAttributeRow(
|
||||
|
|
@ -424,7 +500,11 @@ class FullProfileActivity : BaseActivity() {
|
|||
roundDown: Boolean,
|
||||
isSummary: Boolean
|
||||
) {
|
||||
val tableRow = layoutInflater.inflate(R.layout.profile_attributetablerow, binding.attributesTableLayout, false) as? TableRow ?: return
|
||||
val tableRow = layoutInflater.inflate(
|
||||
R.layout.profile_attributetablerow,
|
||||
binding.attributesTableLayout,
|
||||
false
|
||||
) as? TableRow ?: return
|
||||
val keyTextView = tableRow.findViewById<TextView>(R.id.tv_attribute_type)
|
||||
keyTextView?.text = label
|
||||
|
||||
|
|
@ -475,9 +555,9 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
// endregion
|
||||
|
||||
// region Navigation
|
||||
// region Navigation
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
finish()
|
||||
|
|
@ -488,9 +568,9 @@ class FullProfileActivity : BaseActivity() {
|
|||
finish()
|
||||
}
|
||||
|
||||
// endregion
|
||||
// endregion
|
||||
|
||||
// region BaseActivity-Overrides
|
||||
// region BaseActivity-Overrides
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_full_profile
|
||||
|
|
@ -517,5 +597,5 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
// endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,10 +75,9 @@ class HabitButtonWidgetActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
adapter = SkillTasksRecyclerViewAdapter()
|
||||
adapter?.getTaskSelectionEvents()?.subscribe(
|
||||
{ task -> taskSelected(task.id) },
|
||||
ExceptionHandler.rx()
|
||||
)?.let { compositeSubscription.add(it) }
|
||||
adapter?.onTaskSelection = {
|
||||
taskSelected(it.id)
|
||||
}
|
||||
binding.recyclerView.adapter = adapter
|
||||
|
||||
CoroutineScope(Dispatchers.Main + job).launch(ExceptionHandler.coroutine()) {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import com.habitrpg.android.habitica.extensions.updateStatusBarColor
|
|||
import com.habitrpg.android.habitica.helpers.AmplitudeManager
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.AuthenticationViewModel
|
||||
|
|
@ -81,14 +82,15 @@ class LoginActivity : BaseActivity() {
|
|||
showValidationError(getString(R.string.password_too_short, configManager.minimumPasswordLength()))
|
||||
return@OnClickListener
|
||||
}
|
||||
apiClient.registerUser(username, email, password, confirmPassword)
|
||||
.subscribe(
|
||||
{ handleAuthResponse(it) },
|
||||
{
|
||||
hideProgress()
|
||||
ExceptionHandler.reportError(it)
|
||||
}
|
||||
)
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine {
|
||||
hideProgress()
|
||||
ExceptionHandler.reportError(it)
|
||||
}) {
|
||||
val response = apiClient.registerUser(username, email, password, confirmPassword)
|
||||
if (response != null) {
|
||||
handleAuthResponse(response)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val username: String = binding.username.text.toString().trim { it <= ' ' }
|
||||
val password: String = binding.password.text.toString()
|
||||
|
|
@ -97,14 +99,15 @@ class LoginActivity : BaseActivity() {
|
|||
return@OnClickListener
|
||||
}
|
||||
Log.d("LoginActivity", ": $username, $password")
|
||||
apiClient.connectUser(username, password).subscribe(
|
||||
{ handleAuthResponse(it) },
|
||||
{
|
||||
hideProgress()
|
||||
ExceptionHandler.reportError(it)
|
||||
Log.d("LoginActivity", ": ${it.message}", it)
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine {
|
||||
hideProgress()
|
||||
ExceptionHandler.reportError(it)
|
||||
}) {
|
||||
val response = apiClient.connectUser(username, password)
|
||||
if (response != null) {
|
||||
handleAuthResponse(response)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -450,7 +453,10 @@ class LoginActivity : BaseActivity() {
|
|||
alertDialog.setMessage(R.string.forgot_password_description)
|
||||
alertDialog.setAdditionalContentView(input)
|
||||
alertDialog.addButton(R.string.send, true) { _, _ ->
|
||||
userRepository.sendPasswordResetEmail(input.text.toString()).subscribe({ showPasswordEmailConfirmation() }, ExceptionHandler.rx())
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.sendPasswordResetEmail(input.text.toString())
|
||||
showPasswordEmailConfirmation()
|
||||
}
|
||||
}
|
||||
alertDialog.addCancelButton()
|
||||
alertDialog.show()
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import androidx.navigation.NavDestination
|
|||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import com.google.android.gms.wearable.Wearable
|
||||
import com.google.android.material.composethemeadapter.MdcTheme
|
||||
import com.google.firebase.perf.FirebasePerformance
|
||||
import com.habitrpg.android.habitica.BuildConfig
|
||||
import com.habitrpg.android.habitica.R
|
||||
|
|
@ -33,7 +32,6 @@ import com.habitrpg.android.habitica.data.TaskRepository
|
|||
import com.habitrpg.android.habitica.databinding.ActivityMainBinding
|
||||
import com.habitrpg.android.habitica.extensions.hideKeyboard
|
||||
import com.habitrpg.android.habitica.extensions.observeOnce
|
||||
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
||||
import com.habitrpg.android.habitica.extensions.updateStatusBarColor
|
||||
import com.habitrpg.android.habitica.helpers.AmplitudeManager
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
|
|
@ -41,6 +39,7 @@ import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
|||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.NotificationOpenHandler
|
||||
import com.habitrpg.android.habitica.helpers.SoundManager
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.interactors.CheckClassSelectionUseCase
|
||||
import com.habitrpg.android.habitica.interactors.DisplayItemDropUseCase
|
||||
import com.habitrpg.android.habitica.interactors.NotifyUserUseCase
|
||||
|
|
@ -154,11 +153,11 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
|
|||
viewModel.user.observe(this) {
|
||||
setUserData(it)
|
||||
}
|
||||
compositeSubscription.add(
|
||||
userRepository.getUserQuestStatus().subscribeWithErrorHandler {
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.getUserQuestStatus().collect {
|
||||
userQuestStatus = it
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
val drawerLayout = findViewById<DrawerLayout>(R.id.drawer_layout)
|
||||
drawerFragment = supportFragmentManager.findFragmentById(R.id.navigation_drawer) as? NavigationDrawerFragment
|
||||
|
|
@ -383,7 +382,7 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
|
|||
if (user != null) {
|
||||
val preferences = user.preferences
|
||||
|
||||
preferences?.language?.let { apiClient.setLanguageCode(it) }
|
||||
preferences?.language?.let { apiClient.languageCode = it }
|
||||
if (preferences?.language != viewModel.preferenceLanguage) {
|
||||
viewModel.preferenceLanguage = preferences?.language
|
||||
}
|
||||
|
|
@ -392,11 +391,6 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
|
|||
displayDeathDialogIfNeeded()
|
||||
YesterdailyDialog.showDialogIfNeeded(this, user.id, userRepository, taskRepository)
|
||||
|
||||
if (user.flags?.verifiedUsername == false && isActivityVisible) {
|
||||
val intent = Intent(this, VerifyUsernameActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
val quest = user.party?.quest
|
||||
if (quest?.completed?.isNotBlank() == true) {
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
|
|
@ -447,22 +441,35 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
|
|||
UserQuestStatus.QUEST_BOSS -> data.questDamage
|
||||
else -> 0.0
|
||||
}
|
||||
compositeSubscription.add(
|
||||
notifyUserUseCase.observable(
|
||||
lifecycleScope.launchCatching {
|
||||
notifyUserUseCase.callInteractor(
|
||||
NotifyUserUseCase.RequestValues(
|
||||
this, snackbarContainer,
|
||||
viewModel.user.value, data.experienceDelta, data.healthDelta, data.goldDelta, data.manaDelta, damageValue, data.hasLeveledUp, data.level
|
||||
this@MainActivity,
|
||||
snackbarContainer,
|
||||
viewModel.user.value,
|
||||
data.experienceDelta,
|
||||
data.healthDelta,
|
||||
data.goldDelta,
|
||||
data.manaDelta,
|
||||
damageValue,
|
||||
data.hasLeveledUp,
|
||||
data.level
|
||||
)
|
||||
)
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val showItemsFound = userQuestStatus == UserQuestStatus.QUEST_COLLECT
|
||||
compositeSubscription.add(
|
||||
displayItemDropUseCase.observable(DisplayItemDropUseCase.RequestValues(data, this, snackbarContainer, showItemsFound))
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
lifecycleScope.launchCatching {
|
||||
displayItemDropUseCase.callInteractor(
|
||||
DisplayItemDropUseCase.RequestValues(
|
||||
data,
|
||||
this@MainActivity,
|
||||
snackbarContainer,
|
||||
showItemsFound
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private var lastDeathDialogDisplay = 0L
|
||||
|
|
|
|||
|
|
@ -5,15 +5,14 @@ import android.os.Bundle
|
|||
import android.text.method.LinkMovementMethod
|
||||
import android.view.View
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.api.MaintenanceApiService
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.databinding.ActivityMaintenanceBinding
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.common.habitica.helpers.setMarkdown
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import javax.inject.Inject
|
||||
|
||||
class MaintenanceActivity : BaseActivity() {
|
||||
|
|
@ -66,19 +65,12 @@ class MaintenanceActivity : BaseActivity() {
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (!isDeprecationNotice) {
|
||||
compositeSubscription.add(
|
||||
this.maintenanceService.maintenanceStatus
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{ maintenanceResponse ->
|
||||
if (maintenanceResponse.activeMaintenance == false) {
|
||||
finish()
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
lifecycleScope.launchCatching {
|
||||
val maintenanceResponse = maintenanceService.getMaintenanceStatus()
|
||||
if (maintenanceResponse?.activeMaintenance == false) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.habitrpg.android.habitica.data.SocialRepository
|
|||
import com.habitrpg.android.habitica.databinding.ActivityNotificationsBinding
|
||||
import com.habitrpg.android.habitica.extensions.fromHtml
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.inventory.QuestContent
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.NotificationsViewModel
|
||||
import com.habitrpg.common.habitica.models.Notification
|
||||
|
|
@ -65,15 +66,12 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
|
|||
|
||||
inflater = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as? LayoutInflater
|
||||
|
||||
compositeSubscription.add(
|
||||
viewModel.getNotifications().subscribe(
|
||||
{
|
||||
this.setNotifications(it)
|
||||
viewModel.markNotificationsAsSeen(it)
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
lifecycleScope.launchCatching {
|
||||
viewModel.getNotifications().collect {
|
||||
setNotifications(it)
|
||||
viewModel.markNotificationsAsSeen(it)
|
||||
}
|
||||
}
|
||||
|
||||
binding.notificationsRefreshLayout.setOnRefreshListener(this)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,16 +8,18 @@ import android.os.Bundle
|
|||
import android.view.View
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.navArgs
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.databinding.ActivityReportMessageBinding
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.common.habitica.helpers.setMarkdown
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class ReportMessageActivity : BaseActivity() {
|
||||
|
|
@ -94,12 +96,11 @@ class ReportMessageActivity : BaseActivity() {
|
|||
}
|
||||
isReporting = true
|
||||
messageID?.let {
|
||||
socialRepository.flagMessage(it, binding.additionalInfoEdittext.text.toString(), groupID)
|
||||
.doOnError { isReporting = false }
|
||||
.subscribe(
|
||||
{ finish() },
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine {
|
||||
isReporting = false
|
||||
}) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import com.habitrpg.android.habitica.data.TaskRepository
|
|||
import com.habitrpg.android.habitica.databinding.ActivitySetupBinding
|
||||
import com.habitrpg.android.habitica.helpers.AmplitudeManager
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.fragments.setup.AvatarSetupFragment
|
||||
import com.habitrpg.android.habitica.ui.fragments.setup.TaskSetupFragment
|
||||
|
|
@ -84,10 +85,9 @@ class SetupActivity : BaseActivity(), ViewPager.OnPageChangeListener {
|
|||
val currentDeviceLanguage = Locale.getDefault().language
|
||||
for (language in resources.getStringArray(R.array.LanguageValues)) {
|
||||
if (language == currentDeviceLanguage) {
|
||||
compositeSubscription.add(
|
||||
lifecycleScope.launchCatching {
|
||||
apiClient.registrationLanguage(currentDeviceLanguage)
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,9 @@ class SetupActivity : BaseActivity(), ViewPager.OnPageChangeListener {
|
|||
this.completedSetup = true
|
||||
createdTasks = true
|
||||
newTasks?.let {
|
||||
this.taskRepository.createTasks(it).subscribe({ onUserReceived(user) }, ExceptionHandler.rx())
|
||||
lifecycleScope.launchCatching {
|
||||
taskRepository.createTasks(it)
|
||||
}
|
||||
}
|
||||
} else if (binding.viewPager.currentItem == 0) {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.habitrpg.android.habitica.components.UserComponent
|
|||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.databinding.ActivitySkillMembersBinding
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.ui.adapter.social.PartyMemberRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
|
|
@ -50,15 +51,14 @@ class SkillMemberActivity : BaseActivity() {
|
|||
private fun loadMemberList() {
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(this)
|
||||
viewAdapter = PartyMemberRecyclerViewAdapter()
|
||||
viewAdapter?.getUserClickedEvents()?.subscribe(
|
||||
{ userId ->
|
||||
viewAdapter?.onUserClicked = {
|
||||
lifecycleScope.launchCatching {
|
||||
val resultIntent = Intent()
|
||||
resultIntent.putExtra("member_id", userId)
|
||||
resultIntent.putExtra("member_id", it)
|
||||
setResult(Activity.RESULT_OK, resultIntent)
|
||||
finish()
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)?.let { compositeSubscription.add(it) }
|
||||
}
|
||||
}
|
||||
binding.recyclerView.adapter = viewAdapter
|
||||
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
|
|
|
|||
|
|
@ -13,11 +13,10 @@ import com.habitrpg.android.habitica.R
|
|||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.databinding.ActivitySkillTasksBinding
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import com.habitrpg.android.habitica.ui.fragments.skills.SkillTasksRecyclerViewFragment
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
|
|
@ -60,7 +59,9 @@ class SkillTasksActivity : BaseActivity() {
|
|||
1 -> TaskType.DAILY
|
||||
else -> TaskType.TODO
|
||||
}
|
||||
compositeSubscription.add(fragment.getTaskSelectionEvents().subscribe({ task -> taskSelected(task) }, ExceptionHandler.rx()))
|
||||
fragment.onTaskSelection = {
|
||||
taskSelected(it)
|
||||
}
|
||||
viewFragmentsDictionary.put(position, fragment)
|
||||
return fragment
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import android.content.SharedPreferences
|
|||
import android.content.res.ColorStateList
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.view.Menu
|
||||
|
|
@ -33,6 +34,7 @@ import com.habitrpg.android.habitica.extensions.OnChangeTextWatcher
|
|||
import com.habitrpg.android.habitica.extensions.addCancelButton
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.TaskAlarmManager
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.Tag
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
|
|
@ -47,6 +49,7 @@ import com.habitrpg.shared.habitica.models.tasks.HabitResetOption
|
|||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import io.realm.RealmList
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Date
|
||||
import javax.inject.Inject
|
||||
|
|
@ -56,16 +59,22 @@ class TaskFormActivity : BaseActivity() {
|
|||
private lateinit var binding: ActivityTaskFormBinding
|
||||
private var userScrolled: Boolean = false
|
||||
private var isSaving: Boolean = false
|
||||
|
||||
@Inject
|
||||
lateinit var taskRepository: TaskRepository
|
||||
|
||||
@Inject
|
||||
lateinit var tagRepository: TagRepository
|
||||
|
||||
@Inject
|
||||
lateinit var taskAlarmManager: TaskAlarmManager
|
||||
|
||||
@Inject
|
||||
lateinit var challengeRepository: ChallengeRepository
|
||||
|
||||
@Inject
|
||||
lateinit var sharedPreferences: SharedPreferences
|
||||
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
|
|
@ -135,18 +144,23 @@ class TaskFormActivity : BaseActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (forcedTheme == "yellow") {
|
||||
binding.taskDifficultyButtons.textTintColor = ContextCompat.getColor(this, R.color.text_yellow)
|
||||
binding.habitScoringButtons.textTintColor = ContextCompat.getColor(this, R.color.text_yellow)
|
||||
binding.taskDifficultyButtons.textTintColor =
|
||||
ContextCompat.getColor(this, R.color.text_yellow)
|
||||
binding.habitScoringButtons.textTintColor =
|
||||
ContextCompat.getColor(this, R.color.text_yellow)
|
||||
} else if (forcedTheme == "taskform") {
|
||||
binding.taskDifficultyButtons.textTintColor = ContextCompat.getColor(this, R.color.text_brand_neon)
|
||||
binding.habitScoringButtons.textTintColor = ContextCompat.getColor(this, R.color.text_brand_neon)
|
||||
binding.taskDifficultyButtons.textTintColor =
|
||||
ContextCompat.getColor(this, R.color.text_brand_neon)
|
||||
binding.habitScoringButtons.textTintColor =
|
||||
ContextCompat.getColor(this, R.color.text_brand_neon)
|
||||
}
|
||||
|
||||
setSupportActionBar(binding.toolbar)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
tintColor = getThemeColor(R.attr.taskFormTint)
|
||||
val upperTintColor = if (forcedTheme == "taskform") getThemeColor(R.attr.taskFormTint) else getThemeColor(R.attr.colorAccent)
|
||||
val upperTintColor =
|
||||
if (forcedTheme == "taskform") getThemeColor(R.attr.taskFormTint) else getThemeColor(R.attr.colorAccent)
|
||||
supportActionBar?.setBackgroundDrawable(ColorDrawable(upperTintColor))
|
||||
binding.upperTextWrapper.setBackgroundColor(upperTintColor)
|
||||
|
||||
|
|
@ -155,19 +169,17 @@ class TaskFormActivity : BaseActivity() {
|
|||
taskType = TaskType.from(bundle.getString(TASK_TYPE_KEY)) ?: TaskType.HABIT
|
||||
preselectedTags = bundle.getStringArrayList(SELECTED_TAGS_KEY)
|
||||
|
||||
compositeSubscription.add(
|
||||
lifecycleScope.launchCatching {
|
||||
tagRepository.getTags()
|
||||
.map { tagRepository.getUnmanagedCopy(it) }
|
||||
.subscribe(
|
||||
{
|
||||
tags = it
|
||||
setTagViews()
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
.collect {
|
||||
tags = it
|
||||
setTagViews()
|
||||
}
|
||||
}
|
||||
userViewModel.user.observe(this) {
|
||||
usesTaskAttributeStats = it?.preferences?.allocationMode == "taskbased" && it.preferences?.automaticAllocation == true
|
||||
usesTaskAttributeStats =
|
||||
it?.preferences?.allocationMode == "taskbased" && it.preferences?.automaticAllocation == true
|
||||
configureForm()
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +200,8 @@ class TaskFormActivity : BaseActivity() {
|
|||
binding.statConstitutionButton.setOnClickListener { selectedStat = Attribute.CONSTITUTION }
|
||||
binding.statPerceptionButton.setOnClickListener { selectedStat = Attribute.PERCEPTION }
|
||||
binding.scrollView.setOnTouchListener { view, event ->
|
||||
userScrolled = view == binding.scrollView && (event.action == MotionEvent.ACTION_SCROLL || event.action == MotionEvent.ACTION_MOVE)
|
||||
userScrolled =
|
||||
view == binding.scrollView && (event.action == MotionEvent.ACTION_SCROLL || event.action == MotionEvent.ACTION_MOVE)
|
||||
return@setOnTouchListener false
|
||||
}
|
||||
binding.scrollView.setOnScrollChangeListener { _: NestedScrollView?, _: Int, _: Int, _: Int, _: Int ->
|
||||
|
|
@ -202,31 +215,33 @@ class TaskFormActivity : BaseActivity() {
|
|||
taskId != null -> {
|
||||
isCreating = false
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
val task = taskRepository.getUnmanagedTask(taskId).firstOrNull() ?: return@launch
|
||||
val task =
|
||||
taskRepository.getUnmanagedTask(taskId).firstOrNull() ?: return@launch
|
||||
if (!task.isValid) return@launch
|
||||
this@TaskFormActivity.task = task
|
||||
initialTaskInstance = task
|
||||
// tintColor = ContextCompat.getColor(this, it.mediumTaskColor)
|
||||
fillForm(task)
|
||||
task.challengeID?.let { challengeID ->
|
||||
compositeSubscription.add(
|
||||
challengeRepository.retrieveChallenge(challengeID)
|
||||
.subscribe(
|
||||
{ challenge ->
|
||||
this@TaskFormActivity.challenge = challenge
|
||||
binding.challengeNameView.text = getString(R.string.challenge_task_name, challenge.name)
|
||||
binding.challengeNameView.visibility = View.VISIBLE
|
||||
disableEditingForUneditableFieldsInChallengeTask()
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
lifecycleScope.launchCatching {
|
||||
val challenge = challengeRepository.retrieveChallenge(challengeID)
|
||||
?: return@launchCatching
|
||||
this@TaskFormActivity.challenge = challenge
|
||||
binding.challengeNameView.text =
|
||||
getString(R.string.challenge_task_name, challenge.name)
|
||||
binding.challengeNameView.visibility = View.VISIBLE
|
||||
disableEditingForUneditableFieldsInChallengeTask()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bundle.containsKey(PARCELABLE_TASK) -> {
|
||||
isCreating = false
|
||||
task = bundle.getParcelable(PARCELABLE_TASK, Task::class.java)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
task = bundle.getParcelable(PARCELABLE_TASK, Task::class.java)
|
||||
} else {
|
||||
task = bundle.getParcelable(PARCELABLE_TASK)
|
||||
}
|
||||
task?.let { fillForm(it) }
|
||||
}
|
||||
else -> {
|
||||
|
|
@ -249,7 +264,8 @@ class TaskFormActivity : BaseActivity() {
|
|||
|
||||
override fun loadTheme(sharedPreferences: SharedPreferences, forced: Boolean) {
|
||||
super.loadTheme(sharedPreferences, forced)
|
||||
val upperTintColor = if (forcedTheme == "taskform") getThemeColor(R.attr.taskFormTint) else getThemeColor(R.attr.colorAccent)
|
||||
val upperTintColor =
|
||||
if (forcedTheme == "taskform") getThemeColor(R.attr.taskFormTint) else getThemeColor(R.attr.colorAccent)
|
||||
window.statusBarColor = upperTintColor
|
||||
}
|
||||
|
||||
|
|
@ -275,8 +291,8 @@ class TaskFormActivity : BaseActivity() {
|
|||
alert.dismiss()
|
||||
}
|
||||
alert.setOnDismissListener {
|
||||
isDiscardCancelled = true
|
||||
}
|
||||
isDiscardCancelled = true
|
||||
}
|
||||
alert.show()
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
|
|
@ -315,13 +331,15 @@ class TaskFormActivity : BaseActivity() {
|
|||
binding.habitScoringButtons.visibility = habitViewsVisibility
|
||||
binding.habitResetStreakTitleView.visibility = habitViewsVisibility
|
||||
binding.habitResetStreakButtons.visibility = habitViewsVisibility
|
||||
(binding.habitAdjustNegativeStreakView.parent as ViewGroup).visibility = habitViewsVisibility
|
||||
(binding.habitAdjustNegativeStreakView.parent as ViewGroup).visibility =
|
||||
habitViewsVisibility
|
||||
if (taskType == TaskType.HABIT) {
|
||||
binding.habitScoringButtons.isPositive = true
|
||||
binding.habitScoringButtons.isNegative = false
|
||||
}
|
||||
|
||||
val habitDailyVisibility = if (taskType == TaskType.DAILY || taskType == TaskType.HABIT) View.VISIBLE else View.GONE
|
||||
val habitDailyVisibility =
|
||||
if (taskType == TaskType.DAILY || taskType == TaskType.HABIT) View.VISIBLE else View.GONE
|
||||
binding.adjustStreakTitleView.visibility = habitDailyVisibility
|
||||
binding.adjustStreakWrapper.visibility = habitDailyVisibility
|
||||
if (taskType == TaskType.HABIT) {
|
||||
|
|
@ -332,13 +350,18 @@ class TaskFormActivity : BaseActivity() {
|
|||
binding.adjustStreakTitleView.text = getString(R.string.adjust_streak)
|
||||
}
|
||||
|
||||
val todoDailyViewsVisibility = if (taskType == TaskType.DAILY || taskType == TaskType.TODO) View.VISIBLE else View.GONE
|
||||
val todoDailyViewsVisibility =
|
||||
if (taskType == TaskType.DAILY || taskType == TaskType.TODO) View.VISIBLE else View.GONE
|
||||
|
||||
binding.checklistTitleView.visibility = if (isChallengeTask) View.GONE else todoDailyViewsVisibility
|
||||
binding.checklistContainer.visibility = if (isChallengeTask) View.GONE else todoDailyViewsVisibility
|
||||
binding.checklistTitleView.visibility =
|
||||
if (isChallengeTask) View.GONE else todoDailyViewsVisibility
|
||||
binding.checklistContainer.visibility =
|
||||
if (isChallengeTask) View.GONE else todoDailyViewsVisibility
|
||||
|
||||
binding.remindersTitleView.visibility = if (isChallengeTask) View.GONE else todoDailyViewsVisibility
|
||||
binding.remindersContainer.visibility = if (isChallengeTask) View.GONE else todoDailyViewsVisibility
|
||||
binding.remindersTitleView.visibility =
|
||||
if (isChallengeTask) View.GONE else todoDailyViewsVisibility
|
||||
binding.remindersContainer.visibility =
|
||||
if (isChallengeTask) View.GONE else todoDailyViewsVisibility
|
||||
binding.remindersContainer.taskType = taskType
|
||||
binding.remindersContainer.firstDayOfWeek = firstDayOfWeek
|
||||
|
||||
|
|
@ -405,12 +428,15 @@ class TaskFormActivity : BaseActivity() {
|
|||
binding.habitScoringButtons.isPositive = task.up ?: false
|
||||
binding.habitScoringButtons.isNegative = task.down ?: false
|
||||
task.frequency?.let {
|
||||
binding.habitResetStreakButtons.selectedResetOption = HabitResetOption.from(it) ?: HabitResetOption.DAILY
|
||||
binding.habitResetStreakButtons.selectedResetOption =
|
||||
HabitResetOption.from(it) ?: HabitResetOption.DAILY
|
||||
}
|
||||
binding.habitAdjustPositiveStreakView.setText((task.counterUp ?: 0).toString())
|
||||
binding.habitAdjustNegativeStreakView.setText((task.counterDown ?: 0).toString())
|
||||
(binding.habitAdjustPositiveStreakView.parent as ViewGroup).visibility = if (task.up == true) View.VISIBLE else View.GONE
|
||||
(binding.habitAdjustNegativeStreakView.parent as ViewGroup).visibility = if (task.down == true) View.VISIBLE else View.GONE
|
||||
(binding.habitAdjustPositiveStreakView.parent as ViewGroup).visibility =
|
||||
if (task.up == true) View.VISIBLE else View.GONE
|
||||
(binding.habitAdjustNegativeStreakView.parent as ViewGroup).visibility =
|
||||
if (task.down == true) View.VISIBLE else View.GONE
|
||||
if (task.up != true && task.down != true) {
|
||||
binding.adjustStreakTitleView.visibility = View.GONE
|
||||
binding.adjustStreakWrapper.visibility = View.GONE
|
||||
|
|
@ -440,13 +466,24 @@ class TaskFormActivity : BaseActivity() {
|
|||
private fun setSelectedAttribute(attributeName: Attribute) {
|
||||
if (!usesTaskAttributeStats) return
|
||||
configureStatsButton(binding.statStrengthButton, attributeName == Attribute.STRENGTH)
|
||||
configureStatsButton(binding.statIntelligenceButton, attributeName == Attribute.INTELLIGENCE)
|
||||
configureStatsButton(binding.statConstitutionButton, attributeName == Attribute.CONSTITUTION)
|
||||
configureStatsButton(
|
||||
binding.statIntelligenceButton,
|
||||
attributeName == Attribute.INTELLIGENCE
|
||||
)
|
||||
configureStatsButton(
|
||||
binding.statConstitutionButton,
|
||||
attributeName == Attribute.CONSTITUTION
|
||||
)
|
||||
configureStatsButton(binding.statPerceptionButton, attributeName == Attribute.PERCEPTION)
|
||||
}
|
||||
|
||||
private fun configureStatsButton(button: TextView, isSelected: Boolean) {
|
||||
button.background.setTint(if (isSelected) tintColor else ContextCompat.getColor(this, R.color.taskform_gray))
|
||||
button.background.setTint(
|
||||
if (isSelected) tintColor else ContextCompat.getColor(
|
||||
this,
|
||||
R.color.taskform_gray
|
||||
)
|
||||
)
|
||||
val textColorID = if (isSelected) R.color.window_background else R.color.text_secondary
|
||||
button.setTextColor(ContextCompat.getColor(this, textColorID))
|
||||
if (isSelected) {
|
||||
|
|
@ -578,7 +615,11 @@ class TaskFormActivity : BaseActivity() {
|
|||
alert.setTitle(R.string.are_you_sure)
|
||||
alert.addButton(R.string.delete_task, true) { _, _ ->
|
||||
if (task?.isValid != true) return@addButton
|
||||
task?.id?.let { taskRepository.deleteTask(it).subscribe({ }, ExceptionHandler.rx()) }
|
||||
task?.id?.let {
|
||||
lifecycleScope.launchCatching {
|
||||
taskRepository.deleteTask(it)
|
||||
}
|
||||
}
|
||||
finish()
|
||||
}
|
||||
alert.addCancelButton()
|
||||
|
|
@ -586,52 +627,46 @@ class TaskFormActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
private fun showChallengeDeleteTask() {
|
||||
compositeSubscription.add(
|
||||
taskRepository.getTasksForChallenge(task?.challengeID).firstElement().subscribe(
|
||||
{ tasks ->
|
||||
val taskCount = tasks.size
|
||||
val alert = HabiticaAlertDialog(this)
|
||||
alert.setTitle(getString(R.string.delete_challenge_task_title))
|
||||
alert.setMessage(getString(R.string.delete_challenge_task_description, taskCount, challenge?.name ?: ""))
|
||||
alert.addButton(R.string.leave_delete_task, isPrimary = true, isDestructive = true) { _, _ ->
|
||||
challenge?.let {
|
||||
compositeSubscription.add(
|
||||
challengeRepository.leaveChallenge(it, "keep-all")
|
||||
.flatMap { taskRepository.deleteTask(task?.id ?: "") }
|
||||
.subscribe(
|
||||
{
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
finish()
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
alert.addButton(getString(R.string.leave_delete_x_tasks, taskCount), isPrimary = false, isDestructive = true) { _, _ ->
|
||||
challenge?.let {
|
||||
compositeSubscription.add(
|
||||
challengeRepository.leaveChallenge(it, "remove-all")
|
||||
.subscribe(
|
||||
{
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
finish()
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
alert.setExtraCloseButtonVisibility(View.VISIBLE)
|
||||
alert.show()
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
lifecycleScope.launchCatching {
|
||||
val tasks = taskRepository.getTasksForChallenge(task?.challengeID).firstOrNull() ?: return@launchCatching
|
||||
val taskCount = tasks.size
|
||||
val alert = HabiticaAlertDialog(this@TaskFormActivity)
|
||||
alert.setTitle(getString(R.string.delete_challenge_task_title))
|
||||
alert.setMessage(
|
||||
getString(
|
||||
R.string.delete_challenge_task_description,
|
||||
taskCount,
|
||||
challenge?.name ?: ""
|
||||
)
|
||||
)
|
||||
)
|
||||
alert.addButton(
|
||||
R.string.leave_delete_task,
|
||||
isPrimary = true,
|
||||
isDestructive = true
|
||||
) { _, _ ->
|
||||
challenge?.let {
|
||||
lifecycleScope.launchCatching {
|
||||
challengeRepository.leaveChallenge(it, "keep-all")
|
||||
taskRepository.deleteTask(task?.id ?: "")
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
alert.addButton(
|
||||
getString(R.string.leave_delete_x_tasks, taskCount),
|
||||
isPrimary = false,
|
||||
isDestructive = true
|
||||
) { _, _ ->
|
||||
challenge?.let {
|
||||
lifecycleScope.launchCatching {
|
||||
challengeRepository.leaveChallenge(it, "remove-all")
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
alert.setExtraCloseButtonVisibility(View.VISIBLE)
|
||||
alert.show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showBrokenChallengeDialog() {
|
||||
|
|
@ -639,43 +674,40 @@ class TaskFormActivity : BaseActivity() {
|
|||
if (!task.isValid) {
|
||||
return
|
||||
}
|
||||
compositeSubscription.add(
|
||||
taskRepository.getTasksForChallenge(task.challengeID).subscribe(
|
||||
{ tasks ->
|
||||
lifecycleScope.launchCatching {
|
||||
val tasks = taskRepository.getTasksForChallenge(task.challengeID).firstOrNull() ?: return@launchCatching
|
||||
val taskCount = tasks.size
|
||||
val dialog = HabiticaAlertDialog(this)
|
||||
val dialog = HabiticaAlertDialog(this@TaskFormActivity)
|
||||
dialog.setTitle(R.string.broken_challenge)
|
||||
dialog.setMessage(this.getString(R.string.broken_challenge_description, taskCount))
|
||||
dialog.addButton(this.getString(R.string.keep_x_tasks, taskCount), true) { _, _ ->
|
||||
taskRepository.unlinkAllTasks(task.challengeID, "keep-all")
|
||||
.subscribe(
|
||||
{
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
finish()
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
dialog.setMessage(
|
||||
getString(
|
||||
R.string.broken_challenge_description,
|
||||
taskCount
|
||||
)
|
||||
)
|
||||
dialog.addButton(
|
||||
getString(R.string.keep_x_tasks, taskCount),
|
||||
true
|
||||
) { _, _ ->
|
||||
lifecycleScope.launchCatching {
|
||||
taskRepository.unlinkAllTasks(task.challengeID, "keep-all")
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
}
|
||||
dialog.addButton(this.getString(R.string.delete_x_tasks, taskCount), false, true) { _, _ ->
|
||||
dialog.addButton(
|
||||
getString(R.string.delete_x_tasks, taskCount),
|
||||
false,
|
||||
true
|
||||
) { _, _ ->
|
||||
lifecycleScope.launchCatching {
|
||||
|
||||
taskRepository.unlinkAllTasks(task.challengeID, "remove-all")
|
||||
.subscribe(
|
||||
{
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
finish()
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
}
|
||||
dialog.setExtraCloseButtonVisibility(View.VISIBLE)
|
||||
dialog.show()
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun disableEditingForUneditableFieldsInChallengeTask() {
|
||||
|
|
|
|||
|
|
@ -1,135 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.databinding.ActivityVerifyUsernameBinding
|
||||
import com.habitrpg.android.habitica.extensions.OnChangeTextWatcher
|
||||
import com.habitrpg.android.habitica.extensions.runDelayed
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class VerifyUsernameActivity : BaseActivity() {
|
||||
private lateinit var binding: ActivityVerifyUsernameBinding
|
||||
|
||||
private val displayNameVerificationEvents = PublishSubject.create<String>()
|
||||
private val usernameVerificationEvents = PublishSubject.create<String>()
|
||||
|
||||
private val checkmarkIcon: Drawable by lazy {
|
||||
BitmapDrawable(resources, HabiticaIconsHelper.imageOfCheckmark(ContextCompat.getColor(this, R.color.text_green), 1f))
|
||||
}
|
||||
private val alertIcon: Drawable by lazy {
|
||||
BitmapDrawable(resources, HabiticaIconsHelper.imageOfAlertIcon())
|
||||
}
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_verify_username
|
||||
}
|
||||
|
||||
override fun getContentView(layoutResId: Int?): View {
|
||||
binding = ActivityVerifyUsernameBinding.inflate(layoutInflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun injectActivity(component: UserComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding.wikiTextView.movementMethod = LinkMovementMethod.getInstance()
|
||||
binding.footerTextView.movementMethod = LinkMovementMethod.getInstance()
|
||||
|
||||
binding.confirmUsernameButton.setOnClickListener { confirmNames() }
|
||||
|
||||
binding.displayNameEditText.addTextChangedListener(
|
||||
OnChangeTextWatcher { p0, _, _, _ ->
|
||||
displayNameVerificationEvents.onNext(p0.toString())
|
||||
}
|
||||
)
|
||||
binding.usernameEditText.addTextChangedListener(
|
||||
OnChangeTextWatcher { p0, _, _, _ ->
|
||||
usernameVerificationEvents.onNext(p0.toString())
|
||||
}
|
||||
)
|
||||
|
||||
compositeSubscription.add(
|
||||
Flowable.combineLatest(
|
||||
displayNameVerificationEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
.map { it.length in 1..30 }
|
||||
.doOnNext {
|
||||
if (it) {
|
||||
binding.displayNameEditText.setCompoundDrawablesWithIntrinsicBounds(null, null, checkmarkIcon, null)
|
||||
binding.issuesTextView.visibility = View.GONE
|
||||
} else {
|
||||
binding.displayNameEditText.setCompoundDrawablesWithIntrinsicBounds(null, null, alertIcon, null)
|
||||
binding.issuesTextView.visibility = View.VISIBLE
|
||||
binding.issuesTextView.text = getString(R.string.display_name_length_error)
|
||||
}
|
||||
},
|
||||
usernameVerificationEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
.throttleLast(1, TimeUnit.SECONDS)
|
||||
.flatMap { userRepository.verifyUsername(binding.usernameEditText.text.toString()) }
|
||||
.doOnNext {
|
||||
if (it.isUsable) {
|
||||
binding.usernameEditText.setCompoundDrawablesWithIntrinsicBounds(null, null, checkmarkIcon, null)
|
||||
binding.issuesTextView.visibility = View.GONE
|
||||
} else {
|
||||
binding.usernameEditText.setCompoundDrawablesWithIntrinsicBounds(null, null, alertIcon, null)
|
||||
binding.issuesTextView.visibility = View.VISIBLE
|
||||
binding.issuesTextView.text = it.issues.joinToString("\n")
|
||||
}
|
||||
}
|
||||
) { displayNameUsable, usernameUsable -> displayNameUsable && usernameUsable.isUsable }
|
||||
.subscribe(
|
||||
{
|
||||
binding.confirmUsernameButton.isEnabled = it
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
val user = userRepository.getUser().firstOrNull()
|
||||
binding.displayNameEditText.setText(user?.profile?.name)
|
||||
displayNameVerificationEvents.onNext(user?.profile?.name ?: "")
|
||||
binding.usernameEditText.setText(user?.authentication?.localAuthentication?.username)
|
||||
usernameVerificationEvents.onNext(user?.username ?: "")
|
||||
}
|
||||
}
|
||||
|
||||
private fun confirmNames() {
|
||||
binding.confirmUsernameButton.isClickable = false
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
userRepository.updateUser("profile.name", binding.displayNameEditText.text.toString())
|
||||
userRepository.updateLoginName(binding.usernameEditText.text.toString())
|
||||
showConfirmationAndFinish()
|
||||
binding.confirmUsernameButton.isClickable = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun showConfirmationAndFinish() {
|
||||
HabiticaSnackbar.showSnackbar(binding.snackbarView, getString(R.string.username_confirmed), HabiticaSnackbar.SnackbarDisplayType.SUCCESS)
|
||||
runDelayed(3, TimeUnit.SECONDS) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
moveTaskToBack(true)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,14 +8,11 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.databinding.SkillTaskItemCardBinding
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import java.util.UUID
|
||||
|
||||
class SkillTasksRecyclerViewAdapter : BaseRecyclerViewAdapter<Task, SkillTasksRecyclerViewAdapter.TaskViewHolder>() {
|
||||
|
||||
private val taskSelectionEvents = PublishSubject.create<Task>()
|
||||
var onTaskSelection: ((Task) -> Unit)? = null
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
val task = getItem(position)
|
||||
|
|
@ -35,10 +32,6 @@ class SkillTasksRecyclerViewAdapter : BaseRecyclerViewAdapter<Task, SkillTasksRe
|
|||
holder.bindHolder(data[position])
|
||||
}
|
||||
|
||||
fun getTaskSelectionEvents(): Flowable<Task> {
|
||||
return taskSelectionEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
|
||||
inner class TaskViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
|
||||
private val binding = SkillTaskItemCardBinding.bind(itemView)
|
||||
var task: Task? = null
|
||||
|
|
@ -63,7 +56,7 @@ class SkillTasksRecyclerViewAdapter : BaseRecyclerViewAdapter<Task, SkillTasksRe
|
|||
override fun onClick(v: View) {
|
||||
if (v == itemView) {
|
||||
task?.let {
|
||||
taskSelectionEvents.onNext(it)
|
||||
onTaskSelection?.invoke(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ import com.habitrpg.android.habitica.R
|
|||
import com.habitrpg.android.habitica.databinding.GearListItemBinding
|
||||
import com.habitrpg.android.habitica.models.inventory.Equipment
|
||||
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
|
||||
class EquipmentRecyclerViewAdapter : BaseRecyclerViewAdapter<Equipment, EquipmentRecyclerViewAdapter.GearViewHolder>() {
|
||||
|
||||
|
|
@ -22,7 +21,7 @@ class EquipmentRecyclerViewAdapter : BaseRecyclerViewAdapter<Equipment, Equipmen
|
|||
var isCostume: Boolean? = null
|
||||
var type: String? = null
|
||||
|
||||
val equipEvents: PublishSubject<String> = PublishSubject.create()
|
||||
var onEquip: ((String) -> Unit)? = null
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GearViewHolder {
|
||||
val view = LayoutInflater.from(parent.context).inflate(R.layout.gear_list_item, parent, false)
|
||||
|
|
@ -45,7 +44,7 @@ class EquipmentRecyclerViewAdapter : BaseRecyclerViewAdapter<Equipment, Equipmen
|
|||
itemView.setOnClickListener {
|
||||
val key = gear?.key
|
||||
if (key != null) {
|
||||
equipEvents.onNext(key)
|
||||
onEquip?.invoke(key)
|
||||
equippedGear = if (key == equippedGear) {
|
||||
type + "_base_0"
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -24,9 +24,6 @@ import com.habitrpg.android.habitica.ui.menu.BottomSheetMenuItem
|
|||
import com.habitrpg.android.habitica.ui.views.dialogs.DetailDialog
|
||||
import com.habitrpg.common.habitica.extensions.layoutInflater
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
|
@ -46,31 +43,14 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter<OwnedI
|
|||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private val sellItemEvents = PublishSubject.create<OwnedItem>()
|
||||
private val questInvitationEvents = PublishSubject.create<QuestContent>()
|
||||
private val openMysteryItemEvents = PublishSubject.create<Item>()
|
||||
private val startHatchingSubject = PublishSubject.create<Item>()
|
||||
private val hatchPetSubject = PublishSubject.create<Pair<HatchingPotion, Egg>>()
|
||||
private val feedPetSubject = PublishSubject.create<Food>()
|
||||
private val createNewPartySubject = PublishSubject.create<Boolean>()
|
||||
private val useSpecialSubject = PublishSubject.create<SpecialItem>()
|
||||
|
||||
fun getSellItemFlowable(): Flowable<OwnedItem> {
|
||||
return sellItemEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
|
||||
fun getQuestInvitationFlowable(): Flowable<QuestContent> {
|
||||
return questInvitationEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
fun getOpenMysteryItemFlowable(): Flowable<Item> {
|
||||
return openMysteryItemEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
|
||||
val startHatchingEvents: Flowable<Item> = startHatchingSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
val hatchPetEvents: Flowable<Pair<HatchingPotion, Egg>> = hatchPetSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
val feedPetEvents: Flowable<Food> = feedPetSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
val startNewPartyEvents: Flowable<Boolean> = createNewPartySubject.toFlowable(BackpressureStrategy.DROP)
|
||||
val useSpecialEvents: Flowable<SpecialItem> = useSpecialSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
var onSellItem: ((OwnedItem) -> Unit)? = null
|
||||
var onQuestInvitation: ((QuestContent) -> Unit)? = null
|
||||
var onOpenMysteryItem: ((Item) -> Unit)? = null
|
||||
var onStartHatching: ((Item) -> Unit)? = null
|
||||
var onHatchPet: ((HatchingPotion, Egg) -> Unit)? = null
|
||||
var onFeedPet: ((Food) -> Unit)? = null
|
||||
var onCreateNewParty: (() -> Unit)? = null
|
||||
var onUseSpecialItem: ((SpecialItem) -> Unit)? = null
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
|
||||
return ItemViewHolder(ItemItemBinding.inflate(context.layoutInflater, parent, false))
|
||||
|
|
@ -188,12 +168,12 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter<OwnedI
|
|||
menu.setSelectionRunnable { index ->
|
||||
item?.let { selectedItem ->
|
||||
if (!(selectedItem is QuestContent || selectedItem is SpecialItem) && index == 0) {
|
||||
ownedItem?.let { selectedOwnedItem -> sellItemEvents.onNext(selectedOwnedItem) }
|
||||
ownedItem?.let { selectedOwnedItem -> onSellItem?.invoke(selectedOwnedItem) }
|
||||
return@let
|
||||
}
|
||||
when (selectedItem) {
|
||||
is Egg -> item?.let { startHatchingSubject.onNext(it) }
|
||||
is HatchingPotion -> startHatchingSubject.onNext(selectedItem)
|
||||
is Egg -> item?.let { onStartHatching?.invoke(it) }
|
||||
is HatchingPotion -> onStartHatching?.invoke(selectedItem)
|
||||
is QuestContent -> {
|
||||
if (index == 0) {
|
||||
val dialog = DetailDialog(context)
|
||||
|
|
@ -201,17 +181,17 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter<OwnedI
|
|||
dialog.show()
|
||||
} else {
|
||||
if (user?.hasParty == true) {
|
||||
questInvitationEvents.onNext(selectedItem)
|
||||
onQuestInvitation?.invoke(selectedItem)
|
||||
} else {
|
||||
createNewPartySubject.onNext(true)
|
||||
onCreateNewParty?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
is SpecialItem ->
|
||||
if (item?.key != "inventory_present") {
|
||||
useSpecialSubject.onNext(selectedItem)
|
||||
onUseSpecialItem?.invoke(selectedItem)
|
||||
} else {
|
||||
openMysteryItemEvents.onNext(selectedItem)
|
||||
onOpenMysteryItem?.invoke(selectedItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -224,17 +204,17 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter<OwnedI
|
|||
item?.let { firstItem ->
|
||||
if (firstItem is Egg) {
|
||||
(hatchingItem as? HatchingPotion)?.let { potion ->
|
||||
hatchPetSubject.onNext(Pair(potion, firstItem))
|
||||
onHatchPet?.invoke(potion, firstItem)
|
||||
}
|
||||
} else if (firstItem is HatchingPotion) {
|
||||
(hatchingItem as? Egg)?.let { egg ->
|
||||
hatchPetSubject.onNext(Pair(firstItem, egg))
|
||||
onHatchPet?.invoke(firstItem, egg)
|
||||
}
|
||||
}
|
||||
return@let
|
||||
}
|
||||
} else if (isFeeding) {
|
||||
feedPetSubject.onNext(item as Food?)
|
||||
(item as Food?)?.let { onFeedPet?.invoke(it) }
|
||||
fragment?.dismiss()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,10 @@ import com.habitrpg.android.habitica.models.inventory.StableSection
|
|||
import com.habitrpg.android.habitica.models.user.OwnedMount
|
||||
import com.habitrpg.android.habitica.ui.viewHolders.MountViewHolder
|
||||
import com.habitrpg.android.habitica.ui.viewHolders.SectionViewHolder
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
|
||||
class MountDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter<androidx.recyclerview.widget.RecyclerView.ViewHolder>() {
|
||||
var onEquip: ((String) -> Unit)? = null
|
||||
private var ownedMounts: Map<String, OwnedMount>? = null
|
||||
|
||||
private val equipEvents = PublishSubject.create<String>()
|
||||
|
|
@ -27,14 +26,10 @@ class MountDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Ada
|
|||
this.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun getEquipFlowable(): Flowable<String> {
|
||||
return equipEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder =
|
||||
when (viewType) {
|
||||
1 -> SectionViewHolder(parent)
|
||||
else -> MountViewHolder(parent, equipEvents)
|
||||
else -> MountViewHolder(parent, onEquip)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import android.view.ViewGroup
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.databinding.CanHatchItemBinding
|
||||
import com.habitrpg.android.habitica.extensions.inflate
|
||||
import com.habitrpg.common.habitica.helpers.Animations
|
||||
import com.habitrpg.android.habitica.models.inventory.Animal
|
||||
import com.habitrpg.android.habitica.models.inventory.Egg
|
||||
import com.habitrpg.android.habitica.models.inventory.Food
|
||||
|
|
@ -16,15 +15,16 @@ import com.habitrpg.android.habitica.models.inventory.StableSection
|
|||
import com.habitrpg.android.habitica.models.user.OwnedItem
|
||||
import com.habitrpg.android.habitica.models.user.OwnedMount
|
||||
import com.habitrpg.android.habitica.models.user.OwnedPet
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.android.habitica.ui.viewHolders.PetViewHolder
|
||||
import com.habitrpg.android.habitica.ui.viewHolders.SectionViewHolder
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.PetSuggestHatchDialog
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.common.habitica.helpers.Animations
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
|
||||
class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter<androidx.recyclerview.widget.RecyclerView.ViewHolder>() {
|
||||
var onFeed: ((Pet, Food?) -> Unit)? = null
|
||||
var onEquip: ((String) -> Unit)? = null
|
||||
private var existingMounts: List<Mount>? = null
|
||||
private var ownedPets: Map<String, OwnedPet>? = null
|
||||
private var ownedMounts: Map<String, OwnedMount>? = null
|
||||
|
|
@ -45,12 +45,6 @@ class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapt
|
|||
this.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun getEquipFlowable(): Flowable<String> {
|
||||
return equipEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
|
||||
var feedFlowable: Flowable<Pair<Pet, Food?>> = feedEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
|
||||
var animalIngredientsRetriever: ((Animal, ((Pair<Egg?, HatchingPotion?>) -> Unit)) -> Unit)? = null
|
||||
|
||||
private fun canRaiseToMount(pet: Pet): Boolean {
|
||||
|
|
@ -74,7 +68,7 @@ class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapt
|
|||
when (viewType) {
|
||||
1 -> SectionViewHolder(parent)
|
||||
2 -> CanHatchViewHolder(parent, animalIngredientsRetriever)
|
||||
else -> PetViewHolder(parent, equipEvents, feedEvents, animalIngredientsRetriever)
|
||||
else -> PetViewHolder(parent, onEquip, onFeed, animalIngredientsRetriever)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(
|
||||
|
|
|
|||
|
|
@ -25,16 +25,13 @@ import com.habitrpg.android.habitica.ui.viewHolders.PetViewHolder
|
|||
import com.habitrpg.android.habitica.ui.viewHolders.SectionViewHolder
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.common.habitica.views.PixelArtView
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
|
||||
class StableRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
var shopSpriteSuffix: String? = null
|
||||
private var eggs: Map<String, Egg> = mapOf()
|
||||
var animalIngredientsRetriever: ((Animal, ((Pair<Egg?, HatchingPotion?>) -> Unit)) -> Unit)? = null
|
||||
private val feedEvents = PublishSubject.create<Pair<Pet, Food?>>()
|
||||
var onFeed: ((Pet, Food?) -> Unit)? = null
|
||||
var itemType: String? = null
|
||||
var currentPet: String? = null
|
||||
set(value) {
|
||||
|
|
@ -46,16 +43,13 @@ class StableRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
|||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
private val equipEvents = PublishSubject.create<String>()
|
||||
var onEquip: ((String) -> Unit)? = null
|
||||
private var existingMounts: List<Mount>? = null
|
||||
private var ownedMounts: Map<String, OwnedMount>? = null
|
||||
private var ownedItems: Map<String, OwnedItem>? = null
|
||||
private var ownsSaddles: Boolean = false
|
||||
private var itemList: List<Any> = ArrayList()
|
||||
|
||||
fun getEquipFlowable(): Flowable<String> {
|
||||
return equipEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
|
||||
private fun canRaiseToMount(pet: Pet): Boolean {
|
||||
if (pet.type == "special") return false
|
||||
|
|
@ -101,8 +95,8 @@ class StableRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
|||
1 -> SectionViewHolder(parent)
|
||||
4 -> StableViewHolder(parent.inflate(R.layout.pet_overview_item))
|
||||
5 -> StableViewHolder(parent.inflate(R.layout.mount_overview_item))
|
||||
2 -> PetViewHolder(parent, equipEvents, feedEvents, animalIngredientsRetriever)
|
||||
3 -> MountViewHolder(parent, equipEvents)
|
||||
2 -> PetViewHolder(parent, onEquip, onFeed, animalIngredientsRetriever)
|
||||
3 -> MountViewHolder(parent, onEquip)
|
||||
else -> StableHeaderViewHolder(parent)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,9 +12,6 @@ import com.habitrpg.android.habitica.extensions.inflate
|
|||
import com.habitrpg.android.habitica.extensions.setTintWith
|
||||
import com.habitrpg.android.habitica.models.SetupCustomization
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
|
||||
internal class CustomizationSetupAdapter : RecyclerView.Adapter<CustomizationSetupAdapter.CustomizationViewHolder>() {
|
||||
|
||||
|
|
@ -22,8 +19,7 @@ internal class CustomizationSetupAdapter : RecyclerView.Adapter<CustomizationSet
|
|||
var user: User? = null
|
||||
private var customizationList: List<SetupCustomization> = emptyList()
|
||||
|
||||
private val equipGearEventSubject = PublishSubject.create<String>()
|
||||
val equipGearEvents: Flowable<String> = equipGearEventSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
var onEquipGear: ((String) -> Unit)? = null
|
||||
var onUpdateUser: ((Map<String, Any>) -> Unit)? = null
|
||||
|
||||
fun setCustomizationList(newCustomizationList: List<SetupCustomization>) {
|
||||
|
|
@ -122,7 +118,7 @@ internal class CustomizationSetupAdapter : RecyclerView.Adapter<CustomizationSet
|
|||
} else {
|
||||
selectedCustomization.key
|
||||
}
|
||||
key?.let { equipGearEventSubject.onNext(it) }
|
||||
key?.let { onEquipGear?.invoke(it) }
|
||||
} else {
|
||||
val updateData = HashMap<String, Any>()
|
||||
val updatePath = "preferences." + selectedCustomization.path
|
||||
|
|
|
|||
|
|
@ -6,15 +6,12 @@ import com.habitrpg.android.habitica.extensions.inflate
|
|||
import com.habitrpg.android.habitica.models.members.Member
|
||||
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.viewHolders.GroupMemberViewHolder
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
|
||||
class PartyMemberRecyclerViewAdapter : BaseRecyclerViewAdapter<Member, GroupMemberViewHolder>() {
|
||||
|
||||
var leaderID: String? = null
|
||||
|
||||
private val userClickedEvents = PublishSubject.create<String>()
|
||||
var onUserClicked: ((String) -> Unit)? = null
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GroupMemberViewHolder {
|
||||
return GroupMemberViewHolder(parent.inflate(R.layout.party_member))
|
||||
|
|
@ -23,11 +20,7 @@ class PartyMemberRecyclerViewAdapter : BaseRecyclerViewAdapter<Member, GroupMemb
|
|||
override fun onBindViewHolder(holder: GroupMemberViewHolder, position: Int) {
|
||||
holder.bind(data[position], leaderID, null)
|
||||
holder.onClickEvent = {
|
||||
userClickedEvents.onNext(data[position].id ?: "")
|
||||
onUserClicked?.invoke(data[position].id ?: "")
|
||||
}
|
||||
}
|
||||
|
||||
fun getUserClickedEvents(): Flowable<String> {
|
||||
return userClickedEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ import com.habitrpg.android.habitica.ui.viewHolders.tasks.RewardViewHolder
|
|||
import com.habitrpg.android.habitica.ui.viewHolders.tasks.TodoViewHolder
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.TasksViewModel
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
|
||||
class ChallengeTasksRecyclerViewAdapter(
|
||||
viewModel: TasksViewModel,
|
||||
|
|
@ -30,13 +27,11 @@ class ChallengeTasksRecyclerViewAdapter(
|
|||
private val taskActionsDisabled: Boolean
|
||||
) : BaseTasksRecyclerViewAdapter<BindableViewHolder<Task>>(TaskType.HABIT, viewModel, layoutResource, newContext, userID) {
|
||||
|
||||
private val addItemSubject = PublishSubject.create<Task>()
|
||||
|
||||
val taskList: MutableList<Task>
|
||||
get() = content?.map { t -> t }?.toMutableList() ?: mutableListOf()
|
||||
|
||||
private var taskOpenEventsSubject = PublishSubject.create<Task>()
|
||||
val taskOpenEvents: Flowable<Task> = taskOpenEventsSubject.toFlowable(BackpressureStrategy.LATEST)
|
||||
var onAddItem: ((Task) -> Unit)? = null
|
||||
var onTaskOpen: ((Task) -> Unit)? = null
|
||||
|
||||
override fun injectThis(component: UserComponent) {
|
||||
component.inject(this)
|
||||
|
|
@ -50,14 +45,10 @@ class ChallengeTasksRecyclerViewAdapter(
|
|||
TaskType.DAILY -> TYPE_DAILY
|
||||
TaskType.TODO -> TYPE_TODO
|
||||
TaskType.REWARD -> TYPE_REWARD
|
||||
else -> if (addItemSubject.hasObservers() && task?.id == "addtask") TYPE_ADD_ITEM else TYPE_HEADER
|
||||
else -> if (task?.id == "addtask") TYPE_ADD_ITEM else TYPE_HEADER
|
||||
}
|
||||
}
|
||||
|
||||
fun addItemObservable(): Flowable<Task> {
|
||||
return addItemSubject.toFlowable(BackpressureStrategy.BUFFER)
|
||||
}
|
||||
|
||||
fun addTaskUnder(taskToAdd: Task, taskAbove: Task?): Int {
|
||||
val position = content?.indexOfFirst { t -> t.id == taskAbove?.id } ?: 0
|
||||
|
||||
|
|
@ -70,18 +61,18 @@ class ChallengeTasksRecyclerViewAdapter(
|
|||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindableViewHolder<Task> {
|
||||
val viewHolder: BindableViewHolder<Task> = when (viewType) {
|
||||
TYPE_HABIT -> HabitViewHolder(getContentView(parent, R.layout.habit_item_card), { _, _ -> }, { }, { task ->
|
||||
taskOpenEventsSubject.onNext(task)
|
||||
onTaskOpen?.invoke(task)
|
||||
}, null)
|
||||
TYPE_DAILY -> DailyViewHolder(getContentView(parent, R.layout.daily_item_card), { _, _ -> }, { _, _ -> }, { }, { task ->
|
||||
taskOpenEventsSubject.onNext(task)
|
||||
onTaskOpen?.invoke(task)
|
||||
}, null)
|
||||
TYPE_TODO -> TodoViewHolder(getContentView(parent, R.layout.todo_item_card), { _, _ -> }, { _, _ -> }, { }, { task ->
|
||||
taskOpenEventsSubject.onNext(task)
|
||||
onTaskOpen?.invoke(task)
|
||||
}, null)
|
||||
TYPE_REWARD -> RewardViewHolder(getContentView(parent, R.layout.reward_item_card), { _, _ -> }, { }, { task ->
|
||||
taskOpenEventsSubject.onNext(task)
|
||||
onTaskOpen?.invoke(task)
|
||||
}, null)
|
||||
TYPE_ADD_ITEM -> AddItemViewHolder(getContentView(parent, R.layout.challenge_add_task_item), addItemSubject)
|
||||
TYPE_ADD_ITEM -> AddItemViewHolder(getContentView(parent, R.layout.challenge_add_task_item), onAddItem)
|
||||
else -> DividerViewHolder(getContentView(parent, R.layout.challenge_task_divider))
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +104,7 @@ class ChallengeTasksRecyclerViewAdapter(
|
|||
|
||||
inner class AddItemViewHolder internal constructor(
|
||||
itemView: View,
|
||||
private val callback: PublishSubject<Task>
|
||||
private val callback: ((Task) -> Unit)?
|
||||
) : BindableViewHolder<Task>(itemView) {
|
||||
|
||||
private val addBtn: Button = itemView.findViewById(R.id.btn_add_task)
|
||||
|
|
@ -121,7 +112,7 @@ class ChallengeTasksRecyclerViewAdapter(
|
|||
|
||||
init {
|
||||
addBtn.isClickable = true
|
||||
addBtn.setOnClickListener { newTask?.let { callback.onNext(it) } }
|
||||
addBtn.setOnClickListener { newTask?.let { callback?.invoke(it) } }
|
||||
}
|
||||
|
||||
override fun bind(
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.habitrpg.android.habitica.components.UserComponent
|
|||
import com.habitrpg.android.habitica.data.InventoryRepository
|
||||
import com.habitrpg.android.habitica.databinding.FragmentRefreshRecyclerviewBinding
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.ui.adapter.AchievementsAdapter
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
|
@ -167,12 +168,8 @@ class AchievementsFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding
|
|||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
compositeSubscription.add(
|
||||
userRepository.retrieveAchievements().subscribe(
|
||||
{
|
||||
},
|
||||
ExceptionHandler.rx(), { binding?.refreshLayout?.isRefreshing = false }
|
||||
)
|
||||
)
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.retrieveAchievements()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,19 +4,21 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.TutorialRepository
|
||||
import com.habitrpg.android.habitica.helpers.AmplitudeManager
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.functions.Consumer
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.toDuration
|
||||
|
||||
abstract class BaseDialogFragment<VB : ViewBinding> : BottomSheetDialogFragment() {
|
||||
|
||||
|
|
@ -68,21 +70,19 @@ abstract class BaseDialogFragment<VB : ViewBinding> : BottomSheetDialogFragment(
|
|||
|
||||
private fun showTutorialIfNeeded() {
|
||||
if (view != null) {
|
||||
if (this.tutorialStepIdentifier != null) {
|
||||
compositeSubscription.add(
|
||||
tutorialRepository.getTutorialStep(this.tutorialStepIdentifier ?: "").firstElement()
|
||||
.delay(1, TimeUnit.SECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
Consumer { step ->
|
||||
if (step.isValid && step.isManaged && step.shouldDisplay) {
|
||||
val mainActivity = activity as? MainActivity ?: return@Consumer
|
||||
mainActivity.displayTutorialStep(step, tutorialTexts, tutorialCanBeDeferred)
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
tutorialStepIdentifier?.let { identifier ->
|
||||
lifecycleScope.launchCatching {
|
||||
val step = tutorialRepository.getTutorialStep(identifier).firstOrNull()
|
||||
delay(1.toDuration(DurationUnit.SECONDS))
|
||||
if (step?.isValid == true && step.isManaged && step.shouldDisplay) {
|
||||
val mainActivity = activity as? MainActivity ?: return@launchCatching
|
||||
mainActivity.displayTutorialStep(
|
||||
step,
|
||||
tutorialTexts,
|
||||
tutorialCanBeDeferred
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,17 +5,20 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.TutorialRepository
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.proxy.AnalyticsManager
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.toDuration
|
||||
|
||||
abstract class BaseFragment<VB : ViewBinding> : Fragment() {
|
||||
|
||||
|
|
@ -72,21 +75,18 @@ abstract class BaseFragment<VB : ViewBinding> : Fragment() {
|
|||
|
||||
private fun showTutorialIfNeeded() {
|
||||
tutorialStepIdentifier?.let { identifier ->
|
||||
compositeSubscription.add(
|
||||
tutorialRepository.getTutorialStep(identifier)
|
||||
.firstElement()
|
||||
.delay(1, TimeUnit.SECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{ step ->
|
||||
if (step.isValid && step.isManaged && step.shouldDisplay) {
|
||||
val mainActivity = activity as? MainActivity ?: return@subscribe
|
||||
mainActivity.displayTutorialStep(step, tutorialTexts, tutorialCanBeDeferred)
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
lifecycleScope.launchCatching {
|
||||
val step = tutorialRepository.getTutorialStep(identifier).firstOrNull()
|
||||
delay(1.toDuration(DurationUnit.SECONDS))
|
||||
if (step?.isValid == true && step.isManaged && step.shouldDisplay) {
|
||||
val mainActivity = activity as? MainActivity ?: return@launchCatching
|
||||
mainActivity.displayTutorialStep(
|
||||
step,
|
||||
tutorialTexts,
|
||||
tutorialCanBeDeferred
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ import com.habitrpg.android.habitica.databinding.DrawerMainBinding
|
|||
import com.habitrpg.android.habitica.extensions.getMinuteOrSeconds
|
||||
import com.habitrpg.android.habitica.extensions.getRemainingString
|
||||
import com.habitrpg.android.habitica.extensions.getShortRemainingString
|
||||
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
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.WorldStateEvent
|
||||
import com.habitrpg.android.habitica.models.inventory.Item
|
||||
import com.habitrpg.android.habitica.models.promotions.HabiticaPromotion
|
||||
|
|
@ -47,11 +47,11 @@ import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
|||
import com.habitrpg.android.habitica.ui.viewmodels.NotificationsViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
|
@ -68,16 +68,22 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
|
||||
@Inject
|
||||
lateinit var socialRepository: SocialRepository
|
||||
|
||||
@Inject
|
||||
lateinit var inventoryRepository: InventoryRepository
|
||||
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
|
||||
@Inject
|
||||
lateinit var configManager: AppConfigManager
|
||||
|
||||
@Inject
|
||||
lateinit var contentRepository: ContentRepository
|
||||
|
||||
@Inject
|
||||
lateinit var sharedPreferences: SharedPreferences
|
||||
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
|
|
@ -101,7 +107,10 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
val context = context
|
||||
adapter = if (context != null) {
|
||||
NavigationDrawerAdapter(context.getThemeColor(R.attr.colorPrimary), context.getThemeColor(R.attr.colorPrimaryOffset))
|
||||
NavigationDrawerAdapter(
|
||||
context.getThemeColor(R.attr.colorPrimary),
|
||||
context.getThemeColor(R.attr.colorPrimaryOffset)
|
||||
)
|
||||
} else {
|
||||
NavigationDrawerAdapter(0, 0)
|
||||
}
|
||||
|
|
@ -130,8 +139,10 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
binding = DrawerMainBinding.bind(view)
|
||||
|
||||
binding?.recyclerView?.adapter = adapter
|
||||
binding?.recyclerView?.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
|
||||
(binding?.recyclerView?.itemAnimator as? SimpleItemAnimator)?.supportsChangeAnimations = false
|
||||
binding?.recyclerView?.layoutManager =
|
||||
androidx.recyclerview.widget.LinearLayoutManager(context)
|
||||
(binding?.recyclerView?.itemAnimator as? SimpleItemAnimator)?.supportsChangeAnimations =
|
||||
false
|
||||
initializeMenuItems()
|
||||
|
||||
subscriptions?.add(
|
||||
|
|
@ -154,26 +165,25 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
)
|
||||
)
|
||||
|
||||
subscriptions?.add(
|
||||
Flowable.combineLatest(
|
||||
contentRepository.getWorldState(), inventoryRepository.getAvailableLimitedItems()
|
||||
) { state, items ->
|
||||
return@combineLatest Pair(state, items)
|
||||
}.subscribe(
|
||||
{ pair ->
|
||||
lifecycleScope.launchCatching {
|
||||
contentRepository.getWorldState()
|
||||
.combine(
|
||||
inventoryRepository.getAvailableLimitedItems()
|
||||
) { state, items -> Pair(state, items) }
|
||||
.collect { pair ->
|
||||
val gearEvent = pair.first.events.firstOrNull { it.gear }
|
||||
createUpdatingJob("seasonal", {
|
||||
gearEvent?.isCurrentlyActive == true || pair.second.isNotEmpty()
|
||||
}, {
|
||||
val diff = (gearEvent?.end?.time ?: 0) - Date().time
|
||||
if (diff < (1.toDuration(DurationUnit.HOURS).inWholeMilliseconds)) 1.toDuration(DurationUnit.SECONDS) else 1.toDuration(DurationUnit.MINUTES)
|
||||
if (diff < (1.toDuration(DurationUnit.HOURS).inWholeMilliseconds)) 1.toDuration(
|
||||
DurationUnit.SECONDS
|
||||
) else 1.toDuration(DurationUnit.MINUTES)
|
||||
}) {
|
||||
updateSeasonalMenuEntries(gearEvent, pair.second)
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
userViewModel.user.observe(viewLifecycleOwner) {
|
||||
if (it != null) {
|
||||
|
|
@ -181,8 +191,22 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
binding?.messagesButtonWrapper?.setOnClickListener { setSelection(R.id.inboxFragment, null, true, preventReselection = false) }
|
||||
binding?.settingsButtonWrapper?.setOnClickListener { setSelection(R.id.prefsActivity, null, true, preventReselection = false) }
|
||||
binding?.messagesButtonWrapper?.setOnClickListener {
|
||||
setSelection(
|
||||
R.id.inboxFragment,
|
||||
null,
|
||||
true,
|
||||
preventReselection = false
|
||||
)
|
||||
}
|
||||
binding?.settingsButtonWrapper?.setOnClickListener {
|
||||
setSelection(
|
||||
R.id.prefsActivity,
|
||||
null,
|
||||
true,
|
||||
preventReselection = false
|
||||
)
|
||||
}
|
||||
binding?.notificationsButtonWrapper?.setOnClickListener { startNotificationsActivity() }
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +243,8 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
shop.pillText = context?.getString(R.string.open)
|
||||
if (gearEvent?.isCurrentlyActive == true) {
|
||||
shop.isVisible = true
|
||||
shop.subtitle = context?.getString(R.string.open_for, gearEvent.end?.getShortRemainingString())
|
||||
shop.subtitle =
|
||||
context?.getString(R.string.open_for, gearEvent.end?.getShortRemainingString())
|
||||
} else {
|
||||
shop.isVisible = false
|
||||
}
|
||||
|
|
@ -228,7 +253,10 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
|
||||
private fun updateUser(user: User) {
|
||||
binding?.avatarView?.setOnClickListener {
|
||||
MainNavigationController.navigate(R.id.openProfileActivity, bundleOf(Pair("userID", user.id)))
|
||||
MainNavigationController.navigate(
|
||||
R.id.openProfileActivity,
|
||||
bundleOf(Pair("userID", user.id))
|
||||
)
|
||||
}
|
||||
|
||||
setMessagesCount(user.inbox)
|
||||
|
|
@ -289,7 +317,8 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
val daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff)
|
||||
if (daysDiff <= 30) {
|
||||
context?.let {
|
||||
subscriptionItem?.subtitle = user.purchased?.plan?.dateTerminated?.getRemainingString(it.resources)
|
||||
subscriptionItem?.subtitle =
|
||||
user.purchased?.plan?.dateTerminated?.getRemainingString(it.resources)
|
||||
subscriptionItem?.subtitleTextColor = when {
|
||||
daysDiff <= 2 -> ContextCompat.getColor(it, R.color.red_100)
|
||||
daysDiff <= 7 -> ContextCompat.getColor(it, R.color.brand_400)
|
||||
|
|
@ -337,36 +366,182 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
private fun initializeMenuItems() {
|
||||
val items = ArrayList<HabiticaDrawerItem>()
|
||||
context?.let { context ->
|
||||
items.add(HabiticaDrawerItem(R.id.tasksFragment, SIDEBAR_TASKS, context.getString(R.string.sidebar_tasks)))
|
||||
items.add(HabiticaDrawerItem(R.id.skillsFragment, SIDEBAR_SKILLS, context.getString(R.string.sidebar_skills)))
|
||||
items.add(HabiticaDrawerItem(R.id.statsFragment, SIDEBAR_STATS, context.getString(R.string.sidebar_stats)))
|
||||
items.add(HabiticaDrawerItem(R.id.achievementsFragment, SIDEBAR_ACHIEVEMENTS, context.getString(R.string.sidebar_achievements)))
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.tasksFragment,
|
||||
SIDEBAR_TASKS,
|
||||
context.getString(R.string.sidebar_tasks)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.skillsFragment,
|
||||
SIDEBAR_SKILLS,
|
||||
context.getString(R.string.sidebar_skills)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.statsFragment,
|
||||
SIDEBAR_STATS,
|
||||
context.getString(R.string.sidebar_stats)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.achievementsFragment,
|
||||
SIDEBAR_ACHIEVEMENTS,
|
||||
context.getString(R.string.sidebar_achievements)
|
||||
)
|
||||
)
|
||||
|
||||
items.add(HabiticaDrawerItem(0, SIDEBAR_INVENTORY, context.getString(R.string.sidebar_shops), isHeader = true))
|
||||
items.add(HabiticaDrawerItem(R.id.marketFragment, SIDEBAR_SHOPS_MARKET, context.getString(R.string.market)))
|
||||
items.add(HabiticaDrawerItem(R.id.questShopFragment, SIDEBAR_SHOPS_QUEST, context.getString(R.string.questShop)))
|
||||
val seasonalShopEntry = HabiticaDrawerItem(R.id.seasonalShopFragment, SIDEBAR_SHOPS_SEASONAL, context.getString(R.string.seasonalShop))
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
0,
|
||||
SIDEBAR_INVENTORY,
|
||||
context.getString(R.string.sidebar_shops),
|
||||
isHeader = true
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.marketFragment,
|
||||
SIDEBAR_SHOPS_MARKET,
|
||||
context.getString(R.string.market)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.questShopFragment,
|
||||
SIDEBAR_SHOPS_QUEST,
|
||||
context.getString(R.string.questShop)
|
||||
)
|
||||
)
|
||||
val seasonalShopEntry = HabiticaDrawerItem(
|
||||
R.id.seasonalShopFragment,
|
||||
SIDEBAR_SHOPS_SEASONAL,
|
||||
context.getString(R.string.seasonalShop)
|
||||
)
|
||||
seasonalShopEntry.isVisible = false
|
||||
items.add(seasonalShopEntry)
|
||||
items.add(HabiticaDrawerItem(R.id.timeTravelersShopFragment, SIDEBAR_SHOPS_TIMETRAVEL, context.getString(R.string.timeTravelers)))
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.timeTravelersShopFragment,
|
||||
SIDEBAR_SHOPS_TIMETRAVEL,
|
||||
context.getString(R.string.timeTravelers)
|
||||
)
|
||||
)
|
||||
|
||||
items.add(HabiticaDrawerItem(0, SIDEBAR_INVENTORY, context.getString(R.string.sidebar_section_inventory), isHeader = true))
|
||||
items.add(HabiticaDrawerItem(R.id.avatarOverviewFragment, SIDEBAR_AVATAR, context.getString(R.string.sidebar_avatar_equipment)))
|
||||
items.add(HabiticaDrawerItem(R.id.itemsFragment, SIDEBAR_ITEMS, context.getString(R.string.sidebar_items)))
|
||||
items.add(HabiticaDrawerItem(R.id.stableFragment, SIDEBAR_STABLE, context.getString(R.string.sidebar_stable)))
|
||||
items.add(HabiticaDrawerItem(R.id.gemPurchaseActivity, SIDEBAR_GEMS, context.getString(R.string.sidebar_gems)))
|
||||
items.add(HabiticaDrawerItem(R.id.subscriptionPurchaseActivity, SIDEBAR_SUBSCRIPTION, context.getString(R.string.sidebar_subscription)))
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
0,
|
||||
SIDEBAR_INVENTORY,
|
||||
context.getString(R.string.sidebar_section_inventory),
|
||||
isHeader = true
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.avatarOverviewFragment,
|
||||
SIDEBAR_AVATAR,
|
||||
context.getString(R.string.sidebar_avatar_equipment)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.itemsFragment,
|
||||
SIDEBAR_ITEMS,
|
||||
context.getString(R.string.sidebar_items)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.stableFragment,
|
||||
SIDEBAR_STABLE,
|
||||
context.getString(R.string.sidebar_stable)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.gemPurchaseActivity,
|
||||
SIDEBAR_GEMS,
|
||||
context.getString(R.string.sidebar_gems)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.subscriptionPurchaseActivity,
|
||||
SIDEBAR_SUBSCRIPTION,
|
||||
context.getString(R.string.sidebar_subscription)
|
||||
)
|
||||
)
|
||||
|
||||
items.add(HabiticaDrawerItem(0, SIDEBAR_SOCIAL, context.getString(R.string.sidebar_section_social), isHeader = true))
|
||||
items.add(HabiticaDrawerItem(R.id.partyFragment, SIDEBAR_PARTY, context.getString(R.string.sidebar_party)))
|
||||
items.add(HabiticaDrawerItem(R.id.tavernFragment, SIDEBAR_TAVERN, context.getString(R.string.sidebar_tavern)))
|
||||
items.add(HabiticaDrawerItem(R.id.guildOverviewFragment, SIDEBAR_GUILDS, context.getString(R.string.sidebar_guilds)))
|
||||
items.add(HabiticaDrawerItem(R.id.challengesOverviewFragment, SIDEBAR_CHALLENGES, context.getString(R.string.sidebar_challenges)))
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
0,
|
||||
SIDEBAR_SOCIAL,
|
||||
context.getString(R.string.sidebar_section_social),
|
||||
isHeader = true
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.partyFragment,
|
||||
SIDEBAR_PARTY,
|
||||
context.getString(R.string.sidebar_party)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.tavernFragment,
|
||||
SIDEBAR_TAVERN,
|
||||
context.getString(R.string.sidebar_tavern)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.guildOverviewFragment,
|
||||
SIDEBAR_GUILDS,
|
||||
context.getString(R.string.sidebar_guilds)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.challengesOverviewFragment,
|
||||
SIDEBAR_CHALLENGES,
|
||||
context.getString(R.string.sidebar_challenges)
|
||||
)
|
||||
)
|
||||
|
||||
items.add(HabiticaDrawerItem(0, SIDEBAR_ABOUT_HEADER, context.getString(R.string.sidebar_about), isHeader = true))
|
||||
items.add(HabiticaDrawerItem(R.id.newsFragment, SIDEBAR_NEWS, context.getString(R.string.sidebar_news)))
|
||||
items.add(HabiticaDrawerItem(R.id.supportMainFragment, SIDEBAR_HELP, context.getString(R.string.sidebar_help)))
|
||||
items.add(HabiticaDrawerItem(R.id.aboutFragment, SIDEBAR_ABOUT, context.getString(R.string.sidebar_about)))
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
0,
|
||||
SIDEBAR_ABOUT_HEADER,
|
||||
context.getString(R.string.sidebar_about),
|
||||
isHeader = true
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.newsFragment,
|
||||
SIDEBAR_NEWS,
|
||||
context.getString(R.string.sidebar_news)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.supportMainFragment,
|
||||
SIDEBAR_HELP,
|
||||
context.getString(R.string.sidebar_help)
|
||||
)
|
||||
)
|
||||
items.add(
|
||||
HabiticaDrawerItem(
|
||||
R.id.aboutFragment,
|
||||
SIDEBAR_ABOUT,
|
||||
context.getString(R.string.sidebar_about)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val promoItem = HabiticaDrawerItem(R.id.subscriptionPurchaseActivity, SIDEBAR_PROMO)
|
||||
|
|
@ -375,7 +550,8 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
items.add(promoItem)
|
||||
|
||||
if (configManager.showSubscriptionBanner()) {
|
||||
val item = HabiticaDrawerItem(R.id.subscriptionPurchaseActivity, SIDEBAR_SUBSCRIPTION_PROMO)
|
||||
val item =
|
||||
HabiticaDrawerItem(R.id.subscriptionPurchaseActivity, SIDEBAR_SUBSCRIPTION_PROMO)
|
||||
item.itemViewType = 2
|
||||
items.add(item)
|
||||
}
|
||||
|
|
@ -421,14 +597,15 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private val notificationClickResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
(activity as? MainActivity)?.notificationsViewModel?.click(
|
||||
it.data?.getStringExtra("notificationId") ?: "",
|
||||
MainNavigationController
|
||||
)
|
||||
private val notificationClickResult =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
(activity as? MainActivity)?.notificationsViewModel?.click(
|
||||
it.data?.getStringExtra("notificationId") ?: "",
|
||||
MainNavigationController
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Users of this fragment must call this method to set UP the navigation drawer interactions.
|
||||
|
|
@ -448,22 +625,22 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
this.drawerLayout?.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START)
|
||||
// set UP the drawer's list view with items and click listener
|
||||
|
||||
subscriptions?.add(
|
||||
viewModel.getNotificationCount().subscribeWithErrorHandler {
|
||||
lifecycleScope.launchCatching {
|
||||
viewModel.getNotificationCount().collect {
|
||||
setNotificationsCount(it)
|
||||
}
|
||||
)
|
||||
subscriptions?.add(
|
||||
viewModel.allNotificationsSeen().subscribeWithErrorHandler {
|
||||
}
|
||||
lifecycleScope.launchCatching {
|
||||
viewModel.allNotificationsSeen().collect {
|
||||
setNotificationsSeen(it)
|
||||
}
|
||||
)
|
||||
subscriptions?.add(
|
||||
viewModel.getHasPartyNotification().subscribeWithErrorHandler {
|
||||
}
|
||||
lifecycleScope.launchCatching {
|
||||
viewModel.getHasPartyNotification().collect {
|
||||
val partyMenuItem = getItemWithIdentifier(SIDEBAR_PARTY)
|
||||
partyMenuItem?.showBubble = it
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun openDrawer() {
|
||||
|
|
@ -590,15 +767,20 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
}
|
||||
if (promotedItem == null) return@let
|
||||
promotedItem.pillText = context?.getString(R.string.sale)
|
||||
promotedItem.pillBackground = context?.let { activePromo.pillBackgroundDrawable(it) }
|
||||
promotedItem.pillBackground =
|
||||
context?.let { activePromo.pillBackgroundDrawable(it) }
|
||||
createUpdatingJob(activePromo.promoType.name, {
|
||||
activePromo.isActive
|
||||
}, {
|
||||
val diff = (activePromo.endDate.time - Date().time).toDuration(DurationUnit.SECONDS)
|
||||
val diff =
|
||||
(activePromo.endDate.time - Date().time).toDuration(DurationUnit.SECONDS)
|
||||
1.toDuration(diff.getMinuteOrSeconds())
|
||||
}) {
|
||||
if (activePromo.isActive) {
|
||||
promotedItem.subtitle = context?.getString(R.string.sale_ends_in, activePromo.endDate.getShortRemainingString())
|
||||
promotedItem.subtitle = context?.getString(
|
||||
R.string.sale_ends_in,
|
||||
activePromo.endDate.getShortRemainingString()
|
||||
)
|
||||
updateItem(promotedItem)
|
||||
} else {
|
||||
promotedItem.subtitle = null
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.habitrpg.android.habitica.data.InventoryRepository
|
|||
import com.habitrpg.android.habitica.databinding.FragmentStatsBinding
|
||||
import com.habitrpg.android.habitica.extensions.addOkButton
|
||||
import com.habitrpg.android.habitica.extensions.setScaledPadding
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.UserStatComputer
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.user.Stats
|
||||
|
|
@ -24,6 +23,7 @@ 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 kotlinx.coroutines.flow.firstOrNull
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.min
|
||||
|
||||
|
|
@ -181,9 +181,9 @@ class StatsFragment : BaseMainFragment<FragmentStatsBinding>() {
|
|||
}
|
||||
|
||||
private fun allocatePoint(stat: Attribute) {
|
||||
compositeSubscription.add(
|
||||
userRepository.allocatePoint(stat).subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
lifecycleScope.launchCatching {
|
||||
userRepository.allocatePoint(stat)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateAttributePoints(user: User) {
|
||||
|
|
@ -263,74 +263,68 @@ class StatsFragment : BaseMainFragment<FragmentStatsBinding>() {
|
|||
outfitList.add(thisOutfit.weapon)
|
||||
}
|
||||
|
||||
compositeSubscription.add(
|
||||
inventoryRepository.getEquipment(outfitList).firstElement()
|
||||
.retry(1)
|
||||
.subscribe(
|
||||
{
|
||||
val levelStat = min((user.stats?.lvl ?: 0) / 2.0f, 50f).toInt()
|
||||
lifecycleScope.launchCatching {
|
||||
val equipment = inventoryRepository.getEquipment(outfitList).firstOrNull()
|
||||
val levelStat = min((user.stats?.lvl ?: 0) / 2.0f, 50f).toInt()
|
||||
|
||||
totalStrength = levelStat
|
||||
totalIntelligence = levelStat
|
||||
totalConstitution = levelStat
|
||||
totalPerception = levelStat
|
||||
totalStrength = levelStat
|
||||
totalIntelligence = levelStat
|
||||
totalConstitution = levelStat
|
||||
totalPerception = levelStat
|
||||
|
||||
binding?.strengthStatsView?.levelValue = levelStat
|
||||
binding?.intelligenceStatsView?.levelValue = levelStat
|
||||
binding?.constitutionStatsView?.levelValue = levelStat
|
||||
binding?.perceptionStatsView?.levelValue = levelStat
|
||||
binding?.strengthStatsView?.levelValue = levelStat
|
||||
binding?.intelligenceStatsView?.levelValue = levelStat
|
||||
binding?.constitutionStatsView?.levelValue = levelStat
|
||||
binding?.perceptionStatsView?.levelValue = levelStat
|
||||
|
||||
totalStrength += user.stats?.buffs?.str?.toInt() ?: 0
|
||||
totalIntelligence += user.stats?.buffs?._int?.toInt() ?: 0
|
||||
totalConstitution += user.stats?.buffs?.con?.toInt() ?: 0
|
||||
totalPerception += user.stats?.buffs?.per?.toInt() ?: 0
|
||||
binding?.strengthStatsView?.buffValue = user.stats?.buffs?.str?.toInt() ?: 0
|
||||
binding?.intelligenceStatsView?.buffValue =
|
||||
user.stats?.buffs?._int?.toInt() ?: 0
|
||||
binding?.constitutionStatsView?.buffValue =
|
||||
user.stats?.buffs?.con?.toInt() ?: 0
|
||||
binding?.perceptionStatsView?.buffValue =
|
||||
user.stats?.buffs?.per?.toInt() ?: 0
|
||||
totalStrength += user.stats?.buffs?.str?.toInt() ?: 0
|
||||
totalIntelligence += user.stats?.buffs?._int?.toInt() ?: 0
|
||||
totalConstitution += user.stats?.buffs?.con?.toInt() ?: 0
|
||||
totalPerception += user.stats?.buffs?.per?.toInt() ?: 0
|
||||
binding?.strengthStatsView?.buffValue = user.stats?.buffs?.str?.toInt() ?: 0
|
||||
binding?.intelligenceStatsView?.buffValue =
|
||||
user.stats?.buffs?._int?.toInt() ?: 0
|
||||
binding?.constitutionStatsView?.buffValue =
|
||||
user.stats?.buffs?.con?.toInt() ?: 0
|
||||
binding?.perceptionStatsView?.buffValue =
|
||||
user.stats?.buffs?.per?.toInt() ?: 0
|
||||
|
||||
totalStrength += user.stats?.strength ?: 0
|
||||
totalIntelligence += user.stats?.intelligence ?: 0
|
||||
totalConstitution += user.stats?.constitution ?: 0
|
||||
totalPerception += user.stats?.per ?: 0
|
||||
binding?.strengthStatsView?.allocatedValue = user.stats?.strength ?: 0
|
||||
binding?.intelligenceStatsView?.allocatedValue =
|
||||
user.stats?.intelligence ?: 0
|
||||
binding?.constitutionStatsView?.allocatedValue =
|
||||
user.stats?.constitution ?: 0
|
||||
binding?.perceptionStatsView?.allocatedValue = user.stats?.per ?: 0
|
||||
val userStatComputer = UserStatComputer()
|
||||
val statsRows = userStatComputer.computeClassBonus(it, user)
|
||||
totalStrength += user.stats?.strength ?: 0
|
||||
totalIntelligence += user.stats?.intelligence ?: 0
|
||||
totalConstitution += user.stats?.constitution ?: 0
|
||||
totalPerception += user.stats?.per ?: 0
|
||||
binding?.strengthStatsView?.allocatedValue = user.stats?.strength ?: 0
|
||||
binding?.intelligenceStatsView?.allocatedValue =
|
||||
user.stats?.intelligence ?: 0
|
||||
binding?.constitutionStatsView?.allocatedValue =
|
||||
user.stats?.constitution ?: 0
|
||||
binding?.perceptionStatsView?.allocatedValue = user.stats?.per ?: 0
|
||||
val userStatComputer = UserStatComputer()
|
||||
val statsRows = userStatComputer.computeClassBonus(equipment, user)
|
||||
|
||||
var strength = 0
|
||||
var intelligence = 0
|
||||
var constitution = 0
|
||||
var perception = 0
|
||||
var strength = 0
|
||||
var intelligence = 0
|
||||
var constitution = 0
|
||||
var perception = 0
|
||||
|
||||
for (row in statsRows) {
|
||||
if (row.javaClass == UserStatComputer.AttributeRow::class.java) {
|
||||
val attributeRow = row as UserStatComputer.AttributeRow
|
||||
strength += attributeRow.strVal.toInt()
|
||||
intelligence += attributeRow.intVal.toInt()
|
||||
constitution += attributeRow.conVal.toInt()
|
||||
perception += attributeRow.perVal.toInt()
|
||||
}
|
||||
}
|
||||
for (row in statsRows) {
|
||||
if (row.javaClass == UserStatComputer.AttributeRow::class.java) {
|
||||
val attributeRow = row as UserStatComputer.AttributeRow
|
||||
strength += attributeRow.strVal.toInt()
|
||||
intelligence += attributeRow.intVal.toInt()
|
||||
constitution += attributeRow.conVal.toInt()
|
||||
perception += attributeRow.perVal.toInt()
|
||||
}
|
||||
}
|
||||
|
||||
totalStrength += strength
|
||||
totalIntelligence += intelligence
|
||||
totalConstitution += constitution
|
||||
totalPerception += perception
|
||||
binding?.strengthStatsView?.equipmentValue = strength
|
||||
binding?.intelligenceStatsView?.equipmentValue = intelligence
|
||||
binding?.constitutionStatsView?.equipmentValue = constitution
|
||||
binding?.perceptionStatsView?.equipmentValue = perception
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
totalStrength += strength
|
||||
totalIntelligence += intelligence
|
||||
totalConstitution += constitution
|
||||
totalPerception += perception
|
||||
binding?.strengthStatsView?.equipmentValue = strength
|
||||
binding?.intelligenceStatsView?.equipmentValue = intelligence
|
||||
binding?.constitutionStatsView?.equipmentValue = constitution
|
||||
binding?.perceptionStatsView?.equipmentValue = perception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,10 +39,9 @@ import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
|||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaBottomSheetDialog
|
||||
import com.habitrpg.common.habitica.extensions.dpToPx
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.kotlin.combineLatest
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -71,8 +70,8 @@ class AvatarCustomizationFragment :
|
|||
internal var adapter: CustomizationRecyclerViewAdapter = CustomizationRecyclerViewAdapter()
|
||||
internal var layoutManager: FlexboxLayoutManager = FlexboxLayoutManager(activity, ROW)
|
||||
|
||||
private val currentFilter = BehaviorSubject.create<CustomizationFilter>()
|
||||
private val ownedCustomizations = PublishSubject.create<List<OwnedCustomization>>()
|
||||
private val currentFilter = MutableStateFlow<CustomizationFilter>(CustomizationFilter(false, type != "background"))
|
||||
private val ownedCustomizations = MutableStateFlow<List<OwnedCustomization>>(emptyList())
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
|
@ -95,11 +94,11 @@ class AvatarCustomizationFragment :
|
|||
}
|
||||
}
|
||||
|
||||
compositeSubscription.add(
|
||||
this.inventoryRepository.getInAppRewards()
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.getInAppRewards()
|
||||
.map { rewards -> rewards.map { it.key } }
|
||||
.subscribe({ adapter.setPinnedItemKeys(it) }, ExceptionHandler.rx())
|
||||
)
|
||||
.collect { adapter.setPinnedItemKeys(it) }
|
||||
}
|
||||
|
||||
return super.onCreateView(inflater, container, savedInstanceState)
|
||||
}
|
||||
|
|
@ -127,7 +126,6 @@ class AvatarCustomizationFragment :
|
|||
this.loadCustomizations()
|
||||
|
||||
userViewModel.user.observe(viewLifecycleOwner) { updateUser(it) }
|
||||
currentFilter.onNext(CustomizationFilter(false, type != "background"))
|
||||
|
||||
binding?.recyclerView?.doOnLayout {
|
||||
adapter.columnCount = it.width / (80.dpToPx(context))
|
||||
|
|
@ -182,15 +180,13 @@ class AvatarCustomizationFragment :
|
|||
|
||||
private fun loadCustomizations() {
|
||||
val type = this.type ?: return
|
||||
compositeSubscription.add(
|
||||
lifecycleScope.launchCatching {
|
||||
customizationRepository.getCustomizations(type, category, false)
|
||||
.combineLatest(
|
||||
currentFilter.toFlowable(BackpressureStrategy.DROP),
|
||||
ownedCustomizations.toFlowable(BackpressureStrategy.DROP)
|
||||
)
|
||||
.subscribe(
|
||||
{ (customizations, filter, ownedCustomizations) ->
|
||||
adapter.ownedCustomizations = ownedCustomizations.map { it.key + "_" + it.type + "_" + it.category }
|
||||
.combine(currentFilter) { customizations, filter -> Pair(customizations, filter) }
|
||||
.combine(ownedCustomizations) { pair, ownedCustomizations -> Triple(pair.first, pair.second, ownedCustomizations) }
|
||||
.collect { (customizations, filter, ownedCustomizations) ->
|
||||
adapter.ownedCustomizations =
|
||||
ownedCustomizations.map { it.key + "_" + it.type + "_" + it.category }
|
||||
if (filter.isFiltering) {
|
||||
val displayedCustomizations = mutableListOf<Customization>()
|
||||
for (customization in customizations) {
|
||||
|
|
@ -213,13 +209,15 @@ class AvatarCustomizationFragment :
|
|||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (type == "hair" && (category == "beard" || category == "mustache")) {
|
||||
val otherCategory = if (category == "mustache") "beard" else "mustache"
|
||||
compositeSubscription.add(customizationRepository.getCustomizations(type, otherCategory, true).subscribe({ adapter.additionalSetItems = it }, ExceptionHandler.rx()))
|
||||
lifecycleScope.launchCatching {
|
||||
customizationRepository.getCustomizations(type, otherCategory, true).collect {
|
||||
adapter.additionalSetItems = it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +234,7 @@ class AvatarCustomizationFragment :
|
|||
fun updateUser(user: User?) {
|
||||
if (user == null) return
|
||||
this.updateActiveCustomization(user)
|
||||
ownedCustomizations.onNext(user.purchased?.customizations?.filter { it.type == this.type && it.purchased })
|
||||
ownedCustomizations.value = user.purchased?.customizations?.filter { it.type == this.type && it.purchased } ?: emptyList()
|
||||
this.adapter.userSize = user.preferences?.size
|
||||
this.adapter.hairColor = user.preferences?.hair?.color
|
||||
this.adapter.gemBalance = user.gemCount
|
||||
|
|
@ -286,17 +284,17 @@ class AvatarCustomizationFragment :
|
|||
binding.showMeWrapper.check(if (filter.onlyPurchased) R.id.show_purchased_button else R.id.show_all_button)
|
||||
binding.showMeWrapper.setOnCheckedChangeListener { _, checkedId ->
|
||||
filter.onlyPurchased = checkedId == R.id.show_purchased_button
|
||||
currentFilter.onNext(filter)
|
||||
currentFilter.value = filter
|
||||
}
|
||||
binding.clearButton.setOnClickListener {
|
||||
currentFilter.onNext(CustomizationFilter(false, type != "background"))
|
||||
currentFilter.value = CustomizationFilter(false, type != "background")
|
||||
dialog.dismiss()
|
||||
}
|
||||
if (type == "background") {
|
||||
binding.sortByWrapper.check(if (filter.ascending) R.id.oldest_button else R.id.newest_button)
|
||||
binding.sortByWrapper.setOnCheckedChangeListener { _, checkedId ->
|
||||
filter.ascending = checkedId == R.id.oldest_button
|
||||
currentFilter.onNext(filter)
|
||||
currentFilter.value = filter
|
||||
}
|
||||
configureMonthFilterButton(binding.januaryButton, 1, filter)
|
||||
configureMonthFilterButton(binding.febuaryButton, 2, filter)
|
||||
|
|
@ -333,7 +331,7 @@ class AvatarCustomizationFragment :
|
|||
button.typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL)
|
||||
filter.months.add(identifier)
|
||||
}
|
||||
currentFilter.onNext(filter)
|
||||
currentFilter.value = filter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,12 +12,13 @@ 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.FragmentRefreshRecyclerviewBinding
|
||||
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.ui.adapter.inventory.EquipmentRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.common.habitica.helpers.EmptyItem
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import com.habitrpg.common.habitica.helpers.EmptyItem
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -45,10 +46,11 @@ class EquipmentDetailFragment :
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
compositeSubscription.add(
|
||||
this.adapter.equipEvents.flatMapMaybe { key -> inventoryRepository.equipGear(key, isCostume ?: false).firstElement() }
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
adapter.onEquip = {
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.equipGear(it, isCostume ?: false)
|
||||
}
|
||||
}
|
||||
return super.onCreateView(inflater, container, savedInstanceState)
|
||||
}
|
||||
|
||||
|
|
@ -82,7 +84,11 @@ class EquipmentDetailFragment :
|
|||
binding?.recyclerView?.addItemDecoration(DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL))
|
||||
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
|
||||
|
||||
type?.let { type -> inventoryRepository.getOwnedEquipment(type).subscribe({ this.adapter.data = it }, ExceptionHandler.rx()) }
|
||||
type?.let { type ->
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.getOwnedEquipment(type).collect { adapter.data = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ import com.habitrpg.android.habitica.data.UserRepository
|
|||
import com.habitrpg.android.habitica.databinding.FragmentItemsDialogBinding
|
||||
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.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.interactors.FeedPetUseCase
|
||||
import com.habitrpg.android.habitica.interactors.HatchPetUseCase
|
||||
import com.habitrpg.android.habitica.models.inventory.Egg
|
||||
|
|
@ -183,69 +183,53 @@ class ItemDialogFragment : BaseDialogFragment<FragmentItemsDialogBinding>() {
|
|||
adapter?.feedingPet = this.feedingPet
|
||||
}
|
||||
binding?.recyclerView?.adapter = adapter
|
||||
|
||||
adapter?.let { adapter ->
|
||||
compositeSubscription.add(
|
||||
adapter.getSellItemFlowable()
|
||||
.flatMap { item -> inventoryRepository.sellItem(item) }
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
|
||||
compositeSubscription.add(
|
||||
adapter.getQuestInvitationFlowable()
|
||||
.flatMap { quest -> inventoryRepository.inviteToQuest(quest) }
|
||||
.subscribe(
|
||||
{
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
socialRepository.retrieveGroup("party")
|
||||
if (isModal) {
|
||||
dismiss()
|
||||
} else {
|
||||
MainNavigationController.navigate(R.id.partyFragment)
|
||||
}
|
||||
}
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
compositeSubscription.add(
|
||||
adapter.getOpenMysteryItemFlowable()
|
||||
.flatMap { inventoryRepository.openMysteryItem(user) }
|
||||
.doOnNext {
|
||||
val activity = activity as? MainActivity
|
||||
if (activity != null) {
|
||||
val dialog = OpenedMysteryitemDialog(activity)
|
||||
dialog.isCelebratory = true
|
||||
dialog.setTitle(R.string.mystery_item_title)
|
||||
dialog.binding.iconView.loadImage("shop_${it.key}")
|
||||
dialog.binding.titleView.text = it.text
|
||||
dialog.binding.descriptionView.text = it.notes
|
||||
dialog.addButton(R.string.equip, true) { _, _ ->
|
||||
inventoryRepository.equip("equipped", it.key ?: "").subscribe({}, ExceptionHandler.rx())
|
||||
}
|
||||
dialog.addCloseButton()
|
||||
dialog.enqueue()
|
||||
adapter?.onSellItem = {
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.sellItem(it)
|
||||
}
|
||||
}
|
||||
adapter?.onQuestInvitation = {
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.inviteToQuest(it)
|
||||
MainNavigationController.navigate(R.id.partyFragment)
|
||||
}
|
||||
}
|
||||
adapter?.onOpenMysteryItem = {
|
||||
lifecycleScope.launchCatching {
|
||||
val item = inventoryRepository.openMysteryItem(user) ?: return@launchCatching
|
||||
val activity = activity as? MainActivity
|
||||
if (activity != null) {
|
||||
val dialog = OpenedMysteryitemDialog(activity)
|
||||
dialog.isCelebratory = true
|
||||
dialog.setTitle(R.string.mystery_item_title)
|
||||
dialog.binding.iconView.loadImage("shop_${it.key}")
|
||||
dialog.binding.titleView.text = item.text
|
||||
dialog.binding.descriptionView.text = item.notes
|
||||
dialog.addButton(R.string.equip, true) { _, _ ->
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.equip("equipped", it.key)
|
||||
}
|
||||
}
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
compositeSubscription.add(adapter.hatchPetEvents.subscribeWithErrorHandler { hatchPet(it.first, it.second) })
|
||||
compositeSubscription.add(adapter.feedPetEvents.subscribeWithErrorHandler { feedPet(it) })
|
||||
dialog.addCloseButton()
|
||||
dialog.enqueue()
|
||||
}
|
||||
}
|
||||
}
|
||||
adapter?.onHatchPet = { pet, egg -> hatchPet(pet, egg) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun feedPet(food: Food) {
|
||||
val pet = feedingPet ?: return
|
||||
val activity = activity ?: return
|
||||
parentSubscription?.add(
|
||||
feedPetUseCase.observable(
|
||||
lifecycleScope.launchCatching {
|
||||
feedPetUseCase.callInteractor(
|
||||
FeedPetUseCase.RequestValues(
|
||||
pet, food,
|
||||
activity
|
||||
)
|
||||
).subscribeWithErrorHandler {}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
|
@ -267,14 +251,14 @@ class ItemDialogFragment : BaseDialogFragment<FragmentItemsDialogBinding>() {
|
|||
private fun hatchPet(potion: HatchingPotion, egg: Egg) {
|
||||
dismiss()
|
||||
val activity = activity ?: return
|
||||
parentSubscription?.add(
|
||||
hatchPetUseCase.observable(
|
||||
activity.lifecycleScope.launchCatching {
|
||||
hatchPetUseCase.callInteractor(
|
||||
HatchPetUseCase.RequestValues(
|
||||
potion, egg,
|
||||
activity
|
||||
)
|
||||
).subscribeWithErrorHandler {}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadItems() {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import com.habitrpg.android.habitica.data.UserRepository
|
|||
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.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
|
|
@ -141,50 +140,42 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
adapter = ItemRecyclerAdapter(context)
|
||||
}
|
||||
binding?.recyclerView?.adapter = adapter
|
||||
adapter?.useSpecialEvents?.subscribeWithErrorHandler { onSpecialItemSelected(it) }?.let { compositeSubscription.add(it) }
|
||||
adapter?.let { adapter ->
|
||||
compositeSubscription.add(
|
||||
adapter.getSellItemFlowable()
|
||||
.flatMap { item -> inventoryRepository.sellItem(item) }
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
|
||||
compositeSubscription.add(
|
||||
adapter.getQuestInvitationFlowable()
|
||||
.flatMap { quest -> inventoryRepository.inviteToQuest(quest) }
|
||||
//.flatMap { socialRepository.retrieveGroup("party") }
|
||||
.subscribe(
|
||||
{
|
||||
MainNavigationController.navigate(R.id.partyFragment)
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
compositeSubscription.add(
|
||||
adapter.getOpenMysteryItemFlowable()
|
||||
.flatMap { inventoryRepository.openMysteryItem(user) }
|
||||
.doOnNext {
|
||||
val activity = activity as? MainActivity
|
||||
if (activity != null) {
|
||||
val dialog = OpenedMysteryitemDialog(activity)
|
||||
dialog.isCelebratory = true
|
||||
dialog.setTitle(R.string.mystery_item_title)
|
||||
dialog.binding.iconView.loadImage("shop_${it.key}")
|
||||
dialog.binding.titleView.text = it.text
|
||||
dialog.binding.descriptionView.text = it.notes
|
||||
dialog.addButton(R.string.equip, true) { _, _ ->
|
||||
inventoryRepository.equip("equipped", it.key ?: "").subscribe({}, ExceptionHandler.rx())
|
||||
}
|
||||
dialog.addCloseButton()
|
||||
dialog.enqueue()
|
||||
adapter?.onUseSpecialItem = { onSpecialItemSelected(it) }
|
||||
adapter?.onSellItem = {
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.sellItem(it)
|
||||
}
|
||||
}
|
||||
adapter?.onQuestInvitation = {
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.inviteToQuest(it)
|
||||
MainNavigationController.navigate(R.id.partyFragment)
|
||||
}
|
||||
}
|
||||
adapter?.onOpenMysteryItem = {
|
||||
lifecycleScope.launchCatching {
|
||||
val item = inventoryRepository.openMysteryItem(user) ?: return@launchCatching
|
||||
val activity = activity as? MainActivity
|
||||
if (activity != null) {
|
||||
val dialog = OpenedMysteryitemDialog(activity)
|
||||
dialog.isCelebratory = true
|
||||
dialog.setTitle(R.string.mystery_item_title)
|
||||
dialog.binding.iconView.loadImage("shop_${it.key}")
|
||||
dialog.binding.titleView.text = item.text
|
||||
dialog.binding.descriptionView.text = item.notes
|
||||
dialog.addButton(R.string.equip, true) { _, _ ->
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.equip("equipped", it.key)
|
||||
}
|
||||
}
|
||||
.subscribe({ }, ExceptionHandler.rx())
|
||||
)
|
||||
compositeSubscription.add(adapter.startHatchingEvents.subscribeWithErrorHandler { showHatchingDialog(it) })
|
||||
compositeSubscription.add(adapter.hatchPetEvents.subscribeWithErrorHandler { hatchPet(it.first, it.second) })
|
||||
compositeSubscription.addAll(adapter.startNewPartyEvents.subscribeWithErrorHandler { createNewParty() })
|
||||
dialog.addCloseButton()
|
||||
dialog.enqueue()
|
||||
}
|
||||
}
|
||||
}
|
||||
adapter?.onStartHatching = { showHatchingDialog(it) }
|
||||
adapter?.onHatchPet = { pet, egg -> hatchPet(pet, egg) }
|
||||
adapter?.onCreateNewParty = { createNewParty() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -218,14 +209,14 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
|
||||
private fun hatchPet(potion: HatchingPotion, egg: Egg) {
|
||||
(activity as? BaseActivity)?.let {
|
||||
compositeSubscription.add(
|
||||
hatchPetUseCase.observable(
|
||||
lifecycleScope.launchCatching {
|
||||
hatchPetUseCase.callInteractor(
|
||||
HatchPetUseCase.RequestValues(
|
||||
potion, egg,
|
||||
it
|
||||
)
|
||||
).subscribeWithErrorHandler {}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.habitrpg.android.habitica.data.SocialRepository
|
|||
import com.habitrpg.android.habitica.databinding.FragmentRefreshRecyclerviewBinding
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.shops.Shop
|
||||
import com.habitrpg.android.habitica.models.shops.ShopCategory
|
||||
import com.habitrpg.android.habitica.models.shops.ShopItem
|
||||
|
|
@ -26,8 +27,8 @@ import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
|||
import com.habitrpg.android.habitica.ui.views.CurrencyViews
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.common.habitica.helpers.RecyclerViewState
|
||||
import io.reactivex.rxjava3.kotlin.combineLatest
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -180,62 +181,48 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
|
|||
Shop.SEASONAL_SHOP -> "seasonal"
|
||||
else -> ""
|
||||
}
|
||||
compositeSubscription.add(
|
||||
this.inventoryRepository.retrieveShopInventory(shopUrl)
|
||||
.map { shop1 ->
|
||||
if (shop1.identifier == Shop.MARKET) {
|
||||
val user = userViewModel.user.value
|
||||
val specialCategory = ShopCategory()
|
||||
specialCategory.text = getString(R.string.special)
|
||||
if (user?.isValid == true && user.purchased?.plan?.isActive == true) {
|
||||
val item = ShopItem.makeGemItem(context?.resources)
|
||||
item.limitedNumberLeft = user.purchased?.plan?.numberOfGemsLeft
|
||||
specialCategory.items.add(item)
|
||||
}
|
||||
specialCategory.items.add(ShopItem.makeFortifyItem(context?.resources))
|
||||
shop1.categories.add(specialCategory)
|
||||
}
|
||||
when (shop1.identifier) {
|
||||
Shop.TIME_TRAVELERS_SHOP -> {
|
||||
formatTimeTravelersShop(shop1)
|
||||
}
|
||||
Shop.SEASONAL_SHOP -> {
|
||||
shop1.categories.sortWith(
|
||||
compareBy<ShopCategory> { it.items.size != 1 }
|
||||
.thenBy { it.items.firstOrNull()?.currency != "gold" }
|
||||
.thenByDescending { it.items.firstOrNull()?.event?.end }
|
||||
)
|
||||
shop1
|
||||
}
|
||||
else -> {
|
||||
shop1
|
||||
}
|
||||
}
|
||||
lifecycleScope.launchCatching({
|
||||
binding?.recyclerView?.state = RecyclerViewState.FAILED
|
||||
}) {
|
||||
val shop1 = inventoryRepository.retrieveShopInventory(shopUrl) ?: return@launchCatching
|
||||
if (shop1.identifier == Shop.MARKET) {
|
||||
val user = userViewModel.user.value
|
||||
val specialCategory = ShopCategory()
|
||||
specialCategory.text = getString(R.string.special)
|
||||
if (user?.isValid == true && user.purchased?.plan?.isActive == true) {
|
||||
val item = ShopItem.makeGemItem(context?.resources)
|
||||
item.limitedNumberLeft = user.purchased?.plan?.numberOfGemsLeft
|
||||
specialCategory.items.add(item)
|
||||
}
|
||||
.subscribe(
|
||||
{
|
||||
this.shop = it
|
||||
this.adapter?.setShop(it)
|
||||
},
|
||||
{
|
||||
binding?.recyclerView?.state = RecyclerViewState.FAILED
|
||||
ExceptionHandler.reportError(it)
|
||||
},
|
||||
{
|
||||
binding?.refreshLayout?.isRefreshing = false
|
||||
}
|
||||
)
|
||||
)
|
||||
specialCategory.items.add(ShopItem.makeFortifyItem(context?.resources))
|
||||
shop1.categories.add(specialCategory)
|
||||
}
|
||||
when (shop1.identifier) {
|
||||
Shop.TIME_TRAVELERS_SHOP -> {
|
||||
formatTimeTravelersShop(shop1)
|
||||
}
|
||||
Shop.SEASONAL_SHOP -> {
|
||||
shop1.categories.sortWith(
|
||||
compareBy<ShopCategory> { it.items.size != 1 }
|
||||
.thenBy { it.items.firstOrNull()?.currency != "gold" }
|
||||
.thenByDescending { it.items.firstOrNull()?.event?.end }
|
||||
)
|
||||
}
|
||||
}
|
||||
shop = shop1
|
||||
adapter?.setShop(shop1)
|
||||
binding?.refreshLayout?.isRefreshing = false
|
||||
}
|
||||
|
||||
compositeSubscription.add(
|
||||
this.inventoryRepository.getOwnedItems()
|
||||
.subscribe({ adapter?.setOwnedItems(it) }, ExceptionHandler.rx())
|
||||
)
|
||||
compositeSubscription.add(
|
||||
this.inventoryRepository.getInAppRewards()
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.getOwnedItems()
|
||||
.collect { adapter?.setOwnedItems(it) }
|
||||
}
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.getInAppRewards()
|
||||
.map { rewards -> rewards.map { it.key } }
|
||||
.subscribe({ adapter?.setPinnedItemKeys(it) }, ExceptionHandler.rx())
|
||||
)
|
||||
.collect { adapter?.setPinnedItemKeys(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatTimeTravelersShop(shop: Shop): Shop {
|
||||
|
|
@ -264,29 +251,22 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
|
|||
}
|
||||
|
||||
private fun loadMarketGear() {
|
||||
compositeSubscription.add(
|
||||
inventoryRepository.retrieveMarketGear()
|
||||
.combineLatest(
|
||||
inventoryRepository.getOwnedEquipment().map { equipment -> equipment.map { it.key } }
|
||||
)
|
||||
.map { (shop, equipment) ->
|
||||
for (category in shop.categories) {
|
||||
lifecycleScope.launchCatching {
|
||||
val shop = inventoryRepository.retrieveMarketGear()
|
||||
inventoryRepository.getOwnedEquipment()
|
||||
.map { equipment -> equipment.map { it.key } }
|
||||
.collect { equipment ->
|
||||
for (category in shop?.categories ?: emptyList()) {
|
||||
val items = category.items.asSequence().filter {
|
||||
!equipment.contains(it.key)
|
||||
}.sortedBy { it.locked }.toList()
|
||||
category.items.clear()
|
||||
category.items.addAll(items)
|
||||
}
|
||||
shop
|
||||
gearCategories = shop?.categories
|
||||
adapter?.gearCategories = shop?.categories ?: mutableListOf()
|
||||
}
|
||||
.subscribe(
|
||||
{
|
||||
this.gearCategories = it.categories
|
||||
adapter?.gearCategories = it.categories
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun injectFragment(component: UserComponent) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.habitrpg.android.habitica.data.InventoryRepository
|
|||
import com.habitrpg.android.habitica.databinding.FragmentRefreshRecyclerviewBinding
|
||||
import com.habitrpg.android.habitica.extensions.getTranslatedType
|
||||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.inventory.Mount
|
||||
import com.habitrpg.android.habitica.models.inventory.StableSection
|
||||
import com.habitrpg.android.habitica.models.user.OwnedMount
|
||||
|
|
@ -97,13 +98,12 @@ class MountDetailRecyclerFragment :
|
|||
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
|
||||
this.loadItems()
|
||||
|
||||
adapter?.getEquipFlowable()?.flatMap { key -> inventoryRepository.equip("mount", key) }
|
||||
?.subscribe(
|
||||
{
|
||||
adapter?.currentMount = it.currentMount
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)?.let { compositeSubscription.add(it) }
|
||||
adapter?.onEquip = {
|
||||
lifecycleScope.launchCatching {
|
||||
val items = inventoryRepository.equip("mount", it)
|
||||
adapter?.currentMount = items?.currentMount
|
||||
}
|
||||
}
|
||||
}
|
||||
userViewModel.user.observe(viewLifecycleOwner) { adapter?.currentMount = it?.currentMount }
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.habitrpg.android.habitica.databinding.FragmentRefreshRecyclerviewBind
|
|||
import com.habitrpg.android.habitica.extensions.getTranslatedType
|
||||
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.FeedPetUseCase
|
||||
import com.habitrpg.android.habitica.models.inventory.Egg
|
||||
import com.habitrpg.android.habitica.models.inventory.Food
|
||||
|
|
@ -124,23 +125,19 @@ class PetDetailRecyclerFragment :
|
|||
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
|
||||
this.loadItems()
|
||||
|
||||
compositeSubscription.add(
|
||||
adapter.getEquipFlowable()
|
||||
.flatMap { key -> inventoryRepository.equip("pet", key) }
|
||||
.subscribe(
|
||||
{
|
||||
adapter.currentPet = it.currentPet
|
||||
},
|
||||
ExceptionHandler.rx()
|
||||
)
|
||||
)
|
||||
adapter.onEquip = {
|
||||
lifecycleScope.launchCatching {
|
||||
val items = inventoryRepository.equip("pet", it)
|
||||
adapter.currentPet = items?.currentPet
|
||||
}
|
||||
}
|
||||
userViewModel.user.observe(viewLifecycleOwner) { adapter.currentPet = it?.currentPet }
|
||||
compositeSubscription.add(adapter.feedFlowable.subscribe({
|
||||
adapter.onFeed = { pet, food ->
|
||||
showFeedingDialog(
|
||||
it.first,
|
||||
it.second
|
||||
pet,
|
||||
food
|
||||
)
|
||||
}, ExceptionHandler.rx()))
|
||||
}
|
||||
|
||||
view.post { setGridSpanCount(view.width) }
|
||||
}
|
||||
|
|
@ -179,10 +176,9 @@ class PetDetailRecyclerFragment :
|
|||
return@map mountMap
|
||||
}.collect { adapter.setOwnedMounts(it) }
|
||||
}
|
||||
compositeSubscription.add(
|
||||
inventoryRepository.getOwnedItems(true)
|
||||
.subscribe({ adapter.setOwnedItems(it) }, ExceptionHandler.rx())
|
||||
)
|
||||
lifecycleScope.launchCatching {
|
||||
inventoryRepository.getOwnedItems(true).collect { adapter.setOwnedItems(it) }
|
||||
}
|
||||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
val mounts = inventoryRepository.getMounts(
|
||||
animalType,
|
||||
|
|
@ -231,14 +227,14 @@ class PetDetailRecyclerFragment :
|
|||
private fun showFeedingDialog(pet: Pet, food: Food?) {
|
||||
if (food != null) {
|
||||
val context = activity ?: context ?: return
|
||||
compositeSubscription.add(
|
||||
feedPetUseCase.observable(
|
||||
lifecycleScope.launchCatching {
|
||||
feedPetUseCase.callInteractor(
|
||||
FeedPetUseCase.RequestValues(
|
||||
pet, food,
|
||||
context
|
||||
)
|
||||
).subscribeWithErrorHandler {}
|
||||
)
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
val fragment = ItemDialogFragment()
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue