From e66c95bda0985783efb61ddcbd146a61c82678ec Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Fri, 6 Jul 2018 00:10:17 +0200 Subject: [PATCH] Update to RxJava 2, RxAndroid 2 and Realm 5 --- Habitica/build.gradle | 8 +- .../habitica/HabiticaPurchaseVerifier.java | 4 +- .../android/habitica/api/ApiService.java | 198 ++-- .../habitica/api/MaintenanceApiService.java | 6 +- .../android/habitica/data/ApiClient.java | 260 ----- .../android/habitica/data/ApiClient.kt | 241 ++++ .../android/habitica/data/BaseRepository.java | 15 - .../android/habitica/data/BaseRepository.kt | 13 + .../habitica/data/ChallengeRepository.java | 22 +- .../habitica/data/ContentRepository.java | 8 +- .../data/CustomizationRepository.java | 4 +- .../android/habitica/data/FAQRepository.java | 4 +- .../habitica/data/InventoryRepository.java | 68 +- .../data/SetupCustomizationRepository.java | 4 +- .../android/habitica/data/SocialRepository.kt | 71 +- .../android/habitica/data/TagRepository.java | 25 - .../android/habitica/data/TagRepository.kt | 23 + .../android/habitica/data/TaskRepository.kt | 41 +- .../habitica/data/TutorialRepository.kt | 7 +- .../android/habitica/data/UserRepository.kt | 64 +- .../data/implementation/ApiClientImpl.java | 1031 ----------------- .../data/implementation/ApiClientImpl.kt | 788 +++++++++++++ .../implementation/BaseRepositoryImpl.java | 39 - .../data/implementation/BaseRepositoryImpl.kt | 25 + .../ChallengeRepositoryImpl.java | 143 --- .../implementation/ChallengeRepositoryImpl.kt | 111 ++ .../implementation/ContentRepositoryImpl.kt | 21 +- .../CustomizationRepositoryImpl.java | 21 - .../CustomizationRepositoryImpl.kt | 16 + .../implementation/FAQRepositoryImpl.java | 21 - .../data/implementation/FAQRepositoryImpl.kt | 17 + .../implementation/InventoryRepositoryImpl.kt | 116 +- .../SetupCustomizationRepositoryImpl.java | 183 --- .../SetupCustomizationRepositoryImpl.kt | 162 +++ .../implementation/SocialRepositoryImpl.kt | 124 +- .../implementation/TagRepositoryImpl.java | 65 -- .../data/implementation/TagRepositoryImpl.kt | 52 + .../data/implementation/TaskRepositoryImpl.kt | 95 +- .../implementation/TutorialRepositoryImpl.kt | 7 +- .../data/implementation/UserRepositoryImpl.kt | 89 +- .../data/local/ChallengeLocalRepository.java | 23 - .../data/local/ChallengeLocalRepository.kt | 21 + .../local/CustomizationLocalRepository.java | 10 - .../local/CustomizationLocalRepository.kt | 10 + .../data/local/FAQLocalRepository.java | 11 - .../habitica/data/local/FAQLocalRepository.kt | 11 + .../data/local/InventoryLocalRepository.kt | 43 +- .../data/local/SocialLocalRepository.kt | 15 +- .../data/local/TagLocalRepository.java | 14 - .../habitica/data/local/TagLocalRepository.kt | 12 + .../data/local/TaskLocalRepository.kt | 15 +- .../data/local/TutorialLocalRepository.kt | 7 +- .../data/local/UserLocalRepository.kt | 15 +- .../RealmChallengeLocalRepository.java | 77 -- .../RealmChallengeLocalRepository.kt | 67 ++ .../RealmContentLocalRepository.kt | 2 +- .../RealmCustomizationLocalRepository.java | 47 - .../RealmCustomizationLocalRepository.kt | 40 + .../RealmFAQLocalRepository.java | 23 - .../implementation/RealmFAQLocalRepository.kt | 16 + .../RealmInventoryLocalRepository.java | 315 ----- .../RealmInventoryLocalRepository.kt | 256 ++++ .../RealmSocialLocalRepository.kt | 53 +- .../RealmTagLocalRepository.java | 33 - .../implementation/RealmTagLocalRepository.kt | 24 + .../RealmTaskLocalRepository.kt | 42 +- .../RealmTutorialLocalRepository.kt | 12 +- .../RealmUserLocalRepository.kt | 38 +- .../executors/PostExecutionThread.java | 3 +- .../android/habitica/executors/UIThread.java | 4 +- .../extensions/ViewHolder-Extensions.kt | 8 + .../habitica/helpers/QrCodeManager.java | 2 +- .../habitica/helpers/RxErrorHandler.java | 11 +- .../habitica/helpers/SoundFileLoader.kt | 18 +- .../android/habitica/helpers/SoundManager.kt | 19 +- .../habitica/helpers/TaskAlarmManager.kt | 15 +- .../interactors/BuyRewardUseCase.java | 4 +- .../CheckClassSelectionUseCase.java | 9 +- .../interactors/ChecklistCheckUseCase.java | 4 +- .../interactors/DailyCheckUseCase.java | 4 +- .../interactors/DisplayItemDropUseCase.java | 8 +- .../interactors/HabitScoreUseCase.java | 4 +- .../habitica/interactors/LevelUpUseCase.java | 10 +- .../habitica/interactors/NotifyUserUseCase.kt | 10 +- .../interactors/TodoCheckUseCase.java | 4 +- .../android/habitica/interactors/UseCase.java | 8 +- .../android/habitica/modules/ApiModule.java | 6 +- .../habitica/modules/RepositoryModule.java | 4 +- .../LocalNotificationActionReceiver.java | 2 +- .../habitica/ui/activities/BaseActivity.java | 16 +- .../activities/ChallengeDetailActivity.java | 6 +- .../ui/activities/ClassSelectionActivity.java | 6 +- .../activities/CreateChallengeActivity.java | 8 +- .../activities/FixCharacterValuesActivity.kt | 8 +- .../ui/activities/FullProfileActivity.java | 4 +- .../activities/HabitButtonWidgetActivity.java | 2 +- .../habitica/ui/activities/LoginActivity.java | 16 +- .../habitica/ui/activities/MainActivity.java | 9 +- .../habitica/ui/activities/SetupActivity.java | 8 +- .../ui/activities/SkillMemberActivity.java | 4 +- .../ui/activities/TaskFormActivity.java | 4 +- .../CustomizationRecyclerViewAdapter.kt | 31 +- .../adapter/FAQOverviewRecyclerAdapter.java | 9 +- .../ui/adapter/NavigationDrawerAdapter.kt | 21 +- .../SkillTasksRecyclerViewAdapter.java | 10 +- .../inventory/EquipmentRecyclerViewAdapter.kt | 10 +- .../inventory/ItemRecyclerAdapter.java | 13 +- .../inventory/MountDetailRecyclerAdapter.java | 9 +- .../inventory/PetDetailRecyclerAdapter.java | 9 +- .../adapter/inventory/ShopRecyclerAdapter.kt | 11 - .../social/ChatRecyclerViewAdapter.java | 40 +- .../PartyMemberRecyclerViewAdapter.java | 9 +- .../ChallengeTasksRecyclerViewAdapter.java | 13 +- .../tasks/BaseTasksRecyclerViewAdapter.kt | 22 +- .../RealmBaseTasksRecyclerViewAdapter.kt | 2 +- .../habitica/ui/fragments/BaseFragment.kt | 20 +- .../ui/fragments/NavigationDrawerFragment.kt | 19 +- .../habitica/ui/fragments/StatsFragment.kt | 21 +- .../AvatarCustomizationFragment.kt | 19 +- .../customization/AvatarOverviewFragment.kt | 8 +- .../equipment/EquipmentDetailFragment.kt | 8 +- .../equipment/EquipmentOverviewFragment.kt | 7 +- .../inventory/items/ItemRecyclerFragment.java | 2 +- .../fragments/inventory/shops/ShopFragment.kt | 21 +- .../stable/MountDetailRecyclerFragment.java | 2 +- .../stable/PetDetailRecyclerFragment.kt | 13 +- .../stable/StableRecyclerFragment.java | 13 +- .../AuthenticationPreferenceFragment.kt | 6 +- .../preferences/BasePreferencesFragment.kt | 10 +- .../preferences/PreferencesFragment.kt | 12 +- .../preferences/ProfilePreferencesFragment.kt | 8 +- .../SkillTasksRecyclerViewFragment.java | 6 +- .../ui/fragments/skills/SkillsFragment.kt | 14 +- .../ui/fragments/social/ChatListFragment.kt | 36 +- .../social/GroupInformationFragment.kt | 24 +- .../ui/fragments/social/GuildFragment.java | 2 - .../ui/fragments/social/InboxFragment.kt | 8 +- .../social/InboxMessageListFragment.kt | 31 +- .../social/PublicGuildsFragment.java | 4 +- .../fragments/social/QuestDetailFragment.java | 2 +- .../fragments/social/TavernDetailFragment.kt | 54 +- .../ui/fragments/social/TavernFragment.kt | 2 - .../ChallengeDetailDialogHolder.java | 2 +- .../ChallengeFilterDialogHolder.java | 2 +- .../challenges/ChallengeListFragment.java | 6 +- .../ChallengesOverviewFragment.java | 2 +- .../social/party/PartyDetailFragment.java | 2 +- .../fragments/social/party/PartyFragment.java | 5 +- .../social/party/PartyMemberListFragment.java | 2 +- .../tasks/RewardsRecyclerviewFragment.kt | 8 +- .../tasks/TaskRecyclerViewFragment.kt | 20 +- .../ui/fragments/tasks/TasksFragment.kt | 11 +- .../viewHolders/tasks/BaseTaskViewHolder.java | 217 ---- .../viewHolders/tasks/BaseTaskViewHolder.kt | 161 +++ .../tasks/ChecklistedViewHolder.java | 180 --- .../tasks/ChecklistedViewHolder.kt | 170 +++ .../ui/viewHolders/tasks/DailyViewHolder.java | 57 - .../ui/viewHolders/tasks/DailyViewHolder.kt | 45 + .../ui/viewHolders/tasks/HabitViewHolder.java | 125 -- .../ui/viewHolders/tasks/HabitViewHolder.kt | 107 ++ .../viewHolders/tasks/RewardViewHolder.java | 94 -- .../ui/viewHolders/tasks/RewardViewHolder.kt | 86 ++ .../ui/viewHolders/tasks/TodoViewHolder.java | 45 - .../ui/viewHolders/tasks/TodoViewHolder.kt | 35 + .../habitica/ui/views/NPCBannerView.kt | 12 +- .../habitica/ui/views/shops/PurchaseDialog.kt | 24 +- .../ui/views/social/QuestProgressView.kt | 25 +- .../ui/views/stats/BulkAllocateStatsDialog.kt | 11 +- .../ui/views/tasks/TaskFilterDialog.java | 6 +- .../yesterdailies/YesterdailyDialog.java | 19 +- .../habitrpg/android/habitica/utils/Action.kt | 10 + .../widget/HabitButtonWidgetProvider.java | 2 +- .../widget/HabitButtonWidgetService.java | 2 +- .../habitica/widget/TaskListFactory.java | 12 +- .../widget/TaskListWidgetProvider.java | 2 +- build.gradle | 4 +- seeds-sdk/build.gradle | 4 +- 177 files changed, 3580 insertions(+), 4228 deletions(-) delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/BaseRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/BaseRepository.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/TagRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/TagRepository.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/BaseRepositoryImpl.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/BaseRepositoryImpl.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/CustomizationRepositoryImpl.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/CustomizationRepositoryImpl.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/FAQRepositoryImpl.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/FAQRepositoryImpl.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TagRepositoryImpl.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TagRepositoryImpl.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/CustomizationLocalRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/CustomizationLocalRepository.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/FAQLocalRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/FAQLocalRepository.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TagLocalRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TagLocalRepository.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmChallengeLocalRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmChallengeLocalRepository.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmCustomizationLocalRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmCustomizationLocalRepository.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmFAQLocalRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmFAQLocalRepository.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTagLocalRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTagLocalRepository.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/utils/Action.kt diff --git a/Habitica/build.gradle b/Habitica/build.gradle index 8bdcb3cd1..cabd65237 100644 --- a/Habitica/build.gradle +++ b/Habitica/build.gradle @@ -50,7 +50,7 @@ dependencies { exclude module: 'okhttp' } implementation 'com.squareup.retrofit2:converter-gson:2.4.0' - implementation 'com.squareup.retrofit2:adapter-rxjava:2.4.0' + implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' //Crash Logging releaseImplementation('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') { transitive = true @@ -91,8 +91,8 @@ dependencies { // lodash/underscore implementation 'com.github.javadev:underscore:1.34' //RxJava - implementation 'io.reactivex:rxandroid:1.2.1' - implementation 'io.reactivex:rxjava:1.3.8' + implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' + implementation 'io.reactivex.rxjava2:rxjava:2.1.16' //Analytics implementation 'com.amplitude:android-sdk:2.18.1' // Fresco Image Management Library @@ -123,7 +123,7 @@ dependencies { implementation 'com.google.android.gms:play-services-auth:11.4.2' implementation 'org.apmem.tools:layouts:1.10@aar' implementation 'com.roughike:bottom-bar:2.3.1' - implementation 'io.realm:android-adapters:2.1.1' + implementation 'io.realm:android-adapters:3.0.0' implementation(project(':seeds-sdk')) { exclude group: 'com.google.android.gms' exclude group: 'com.android.support', module: 'multidex' diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java b/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java index 6ab0e0f69..777cee640 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java @@ -78,7 +78,7 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier { Seeds.sharedInstance().recordSeedsIAPEvent(purchase.sku, 19.99); } }, throwable -> { - if (throwable.getClass().equals(retrofit2.adapter.rxjava.HttpException.class)) { + if (throwable.getClass().equals(retrofit2.adapter.rxjava2.HttpException.class)) { HttpException error = (HttpException)throwable; ErrorResponse res = apiClient.getErrorResponse((HttpException) throwable); if (error.code() == 401) { @@ -107,7 +107,7 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier { EventBus.getDefault().post(new UserSubscribedEvent()); }, throwable -> { - if (throwable.getClass().equals(retrofit2.adapter.rxjava.HttpException.class)) { + if (throwable.getClass().equals(retrofit2.adapter.rxjava2.HttpException.class)) { HttpException error = (HttpException) throwable; ErrorResponse res = apiClient.getErrorResponse((HttpException) throwable); if (error.code() == 401) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java b/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java index cc6addf31..b9def5ce5 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java @@ -36,6 +36,7 @@ import com.habitrpg.android.habitica.models.user.User; import java.util.List; import java.util.Map; +import io.reactivex.Flowable; import retrofit2.http.Body; import retrofit2.http.DELETE; import retrofit2.http.GET; @@ -45,7 +46,6 @@ import retrofit2.http.POST; import retrofit2.http.PUT; import retrofit2.http.Path; import retrofit2.http.Query; -import rx.Observable; /** @@ -53,314 +53,314 @@ import rx.Observable; */ public interface ApiService { @GET("status") - Observable> getStatus(); + Flowable> getStatus(); @GET("content") - Observable> getContent(@Query("language") String language); + Flowable> getContent(@Query("language") String language); /* user API */ @GET("user/") - Observable> getUser(); + Flowable> getUser(); @PUT("user/") - Observable> updateUser(@Body Map updateDictionary); + Flowable> updateUser(@Body Map updateDictionary); @PUT("user/") - Observable> registrationLanguage(@Header("Accept-Language") String registrationLanguage); + Flowable> registrationLanguage(@Header("Accept-Language") String registrationLanguage); @GET("inbox/messages") - Observable>> getInboxMessages(); + Flowable>> getInboxMessages(); @GET("user/in-app-rewards") - Observable>> retrieveInAppRewards(); + Flowable>> retrieveInAppRewards(); @GET("user/inventory/buy") - Observable>> retrieveOldGearRewards(); + Flowable>> retrieveOldGearRewards(); @POST("user/equip/{type}/{key}") - Observable> equipItem(@Path("type") String type, @Path("key") String itemKey); + Flowable> equipItem(@Path("type") String type, @Path("key") String itemKey); @POST("user/buy/{key}") - Observable> buyItem(@Path("key") String itemKey); + Flowable> buyItem(@Path("key") String itemKey); @POST("user/purchase/{type}/{key}") - Observable> purchaseItem(@Path("type") String type, @Path("key") String itemKey); + Flowable> purchaseItem(@Path("type") String type, @Path("key") String itemKey); @POST("user/purchase-hourglass/{type}/{key}") - Observable> purchaseHourglassItem(@Path("type") String type, @Path("key") String itemKey); + Flowable> purchaseHourglassItem(@Path("type") String type, @Path("key") String itemKey); @POST("user/buy-mystery-set/{key}") - Observable> purchaseMysterySet(@Path("key") String itemKey); + Flowable> purchaseMysterySet(@Path("key") String itemKey); @POST("user/buy-quest/{key}") - Observable> purchaseQuest(@Path("key") String key); + Flowable> purchaseQuest(@Path("key") String key); @POST("user/sell/{type}/{key}") - Observable> sellItem(@Path("type") String itemType, @Path("key") String itemKey); + Flowable> sellItem(@Path("type") String itemType, @Path("key") String itemKey); @POST("user/feed/{pet}/{food}") - Observable> feedPet(@Path("pet") String petKey, @Path("food") String foodKey); + Flowable> feedPet(@Path("pet") String petKey, @Path("food") String foodKey); @POST("user/hatch/{egg}/{hatchingPotion}") - Observable> hatchPet(@Path("egg") String eggKey, @Path("hatchingPotion") String hatchingPotionKey); + Flowable> hatchPet(@Path("egg") String eggKey, @Path("hatchingPotion") String hatchingPotionKey); @GET("tasks/user") - Observable> getTasks(); + Flowable> getTasks(); @GET("tasks/user") - Observable> getTasks(@Query("type") String type); + Flowable> getTasks(@Query("type") String type); @GET("tasks/user") - Observable> getTasks(@Query("type") String type, @Query("dueDate") String dueDate); + Flowable> getTasks(@Query("type") String type, @Query("dueDate") String dueDate); @POST("user/unlock") - Observable> unlockPath(@Query("path") String path); + Flowable> unlockPath(@Query("path") String path); @GET("tasks/{id}") - Observable> getTask(@Path("id") String id); + Flowable> getTask(@Path("id") String id); @POST("tasks/{id}/score/{direction}") - Observable> postTaskDirection(@Path("id") String id, @Path("direction") String direction); + Flowable> postTaskDirection(@Path("id") String id, @Path("direction") String direction); @POST("tasks/{id}/move/to/{position}") - Observable>> postTaskNewPosition(@Path("id") String id, @Path("position") int position); + Flowable>> postTaskNewPosition(@Path("id") String id, @Path("position") int position); @POST("tasks/{taskId}/checklist/{itemId}/score") - Observable> scoreChecklistItem(@Path("taskId") String taskId, @Path("itemId") String itemId); + Flowable> scoreChecklistItem(@Path("taskId") String taskId, @Path("itemId") String itemId); @POST("tasks/user") - Observable> createTask(@Body Task item); + Flowable> createTask(@Body Task item); @POST("tasks/user") - Observable>> createTasks(@Body List tasks); + Flowable>> createTasks(@Body List tasks); @PUT("tasks/{id}") - Observable> updateTask(@Path("id") String id, @Body Task item); + Flowable> updateTask(@Path("id") String id, @Body Task item); @DELETE("tasks/{id}") - Observable> deleteTask(@Path("id") String id); + Flowable> deleteTask(@Path("id") String id); @POST("tags") - Observable> createTag(@Body Tag tag); + Flowable> createTag(@Body Tag tag); @PUT("tags/{id}") - Observable> updateTag(@Path("id") String id, @Body Tag tag); + Flowable> updateTag(@Path("id") String id, @Body Tag tag); @DELETE("tags/{id}") - Observable> deleteTag(@Path("id") String id); + Flowable> deleteTag(@Path("id") String id); @POST("user/auth/local/register") - Observable> registerUser(@Body UserAuth auth); + Flowable> registerUser(@Body UserAuth auth); @POST("user/auth/local/login") - Observable> connectLocal(@Body UserAuth auth); + Flowable> connectLocal(@Body UserAuth auth); @POST("user/auth/social") - Observable> connectSocial(@Body UserAuthSocial auth); + Flowable> connectSocial(@Body UserAuthSocial auth); @POST("user/sleep") - Observable> sleep(); + Flowable> sleep(); @POST("user/revive") - Observable> revive(); + Flowable> revive(); @POST("user/class/cast/{skill}") - Observable> useSkill(@Path("skill") String skillName, @Query("targetType") String targetType, @Query("targetId") String targetId); + Flowable> useSkill(@Path("skill") String skillName, @Query("targetType") String targetType, @Query("targetId") String targetId); @POST("user/class/cast/{skill}") - Observable> useSkill(@Path("skill") String skillName, @Query("targetType") String targetType); + Flowable> useSkill(@Path("skill") String skillName, @Query("targetType") String targetType); @POST("user/change-class") - Observable> changeClass(); + Flowable> changeClass(); @POST("user/change-class") - Observable> changeClass(@Query("class") String className); + Flowable> changeClass(@Query("class") String className); @POST("user/disable-classes") - Observable> disableClasses(); + Flowable> disableClasses(); @POST("user/mark-pms-read") - Observable markPrivateMessagesRead(); + Flowable markPrivateMessagesRead(); /* Group API */ @GET("groups") - Observable>> listGroups(@Query("type") String type); + Flowable>> listGroups(@Query("type") String type); @GET("groups/{gid}") - Observable> getGroup(@Path("gid") String groupId); + Flowable> getGroup(@Path("gid") String groupId); @PUT("groups/{id}") - Observable> updateGroup(@Path("id") String id, @Body Group item); + Flowable> updateGroup(@Path("id") String id, @Body Group item); @GET("groups/{gid}/chat") - Observable>> listGroupChat(@Path("gid") String groupId); + Flowable>> listGroupChat(@Path("gid") String groupId); @POST("groups/{gid}/join") - Observable> joinGroup(@Path("gid") String groupId); + Flowable> joinGroup(@Path("gid") String groupId); @POST("groups/{gid}/leave") - Observable> leaveGroup(@Path("gid") String groupId); + Flowable> leaveGroup(@Path("gid") String groupId); @POST("groups/{gid}/chat") - Observable> postGroupChat(@Path("gid") String groupId, @Body Map message); + Flowable> postGroupChat(@Path("gid") String groupId, @Body Map message); @DELETE("groups/{gid}/chat/{messageId}") - Observable> deleteMessage(@Path("gid") String groupId, @Path("messageId") String messageId); + Flowable> deleteMessage(@Path("gid") String groupId, @Path("messageId") String messageId); @GET("groups/{gid}/members") - Observable>> getGroupMembers(@Path("gid") String groupId, @Query("includeAllPublicFields") Boolean includeAllPublicFields); + Flowable>> getGroupMembers(@Path("gid") String groupId, @Query("includeAllPublicFields") Boolean includeAllPublicFields); @GET("groups/{gid}/members") - Observable>> getGroupMembers(@Path("gid") String groupId, @Query("includeAllPublicFields") Boolean includeAllPublicFields, @Query("lastId") String lastId); + Flowable>> getGroupMembers(@Path("gid") String groupId, @Query("includeAllPublicFields") Boolean includeAllPublicFields, @Query("lastId") String lastId); // Like returns the full chat list @POST("groups/{gid}/chat/{mid}/like") - Observable> likeMessage(@Path("gid") String groupId, @Path("mid") String mid); + Flowable> likeMessage(@Path("gid") String groupId, @Path("mid") String mid); @POST("groups/{gid}/chat/{mid}/flag") - Observable> flagMessage(@Path("gid") String groupId, @Path("mid") String mid); + Flowable> flagMessage(@Path("gid") String groupId, @Path("mid") String mid); @POST("groups/{gid}/chat/seen") - Observable> seenMessages(@Path("gid") String groupId); + Flowable> seenMessages(@Path("gid") String groupId); @POST("groups/{gid}/invite") - Observable>> inviteToGroup(@Path("gid") String groupId, @Body Map inviteData); + Flowable>> inviteToGroup(@Path("gid") String groupId, @Body Map inviteData); @POST("groups/{gid}/reject-invite") - Observable> rejectGroupInvite(@Path("gid") String groupId); + Flowable> rejectGroupInvite(@Path("gid") String groupId); @POST("groups/{gid}/quests/accept") - Observable> acceptQuest(@Path("gid") String groupId); + Flowable> acceptQuest(@Path("gid") String groupId); @POST("groups/{gid}/quests/reject") - Observable> rejectQuest(@Path("gid") String groupId); + Flowable> rejectQuest(@Path("gid") String groupId); @POST("groups/{gid}/quests/cancel") - Observable> cancelQuest(@Path("gid") String groupId); + Flowable> cancelQuest(@Path("gid") String groupId); @POST("groups/{gid}/quests/force-start") - Observable> forceStartQuest(@Path("gid") String groupId, @Body Group group); + Flowable> forceStartQuest(@Path("gid") String groupId, @Body Group group); @POST("groups/{gid}/quests/invite/{questKey}") - Observable> inviteToQuest(@Path("gid") String groupId, @Path("questKey") String questKey); + Flowable> inviteToQuest(@Path("gid") String groupId, @Path("questKey") String questKey); @POST("groups/{gid}/quests/abort") - Observable> abortQuest(@Path("gid") String groupId); + Flowable> abortQuest(@Path("gid") String groupId); @POST("groups/{gid}/quests/leave") - Observable> leaveQuest(@Path("gid") String groupId); + Flowable> leaveQuest(@Path("gid") String groupId); @POST("/iap/android/verify") - Observable> validatePurchase(@Body PurchaseValidationRequest request); + Flowable> validatePurchase(@Body PurchaseValidationRequest request); @POST("/iap/android/subscribe") - Observable> validateSubscription(@Body SubscriptionValidationRequest request); + Flowable> validateSubscription(@Body SubscriptionValidationRequest request); @POST("user/custom-day-start") - Observable> changeCustomDayStart(@Body Map updateObject); + Flowable> changeCustomDayStart(@Body Map updateObject); //Members URL @GET("members/{mid}") - Observable> getMember(@Path("mid") String memberId); + Flowable> getMember(@Path("mid") String memberId); @GET("members/{mid}/achievements") - Observable> getMemberAchievements(@Path("mid") String memberId); + Flowable> getMemberAchievements(@Path("mid") String memberId); @POST("members/send-private-message") - Observable> postPrivateMessage(@Body Map messageDetails); + Flowable> postPrivateMessage(@Body Map messageDetails); @GET("shops/{identifier}") - Observable> retrieveShopInventory(@Path("identifier") String identifier); + Flowable> retrieveShopInventory(@Path("identifier") String identifier); @GET("shops/market-gear") - Observable> retrieveMarketGear(); + Flowable> retrieveMarketGear(); //Push notifications @POST("user/push-devices") - Observable>> addPushDevice(@Body Map pushDeviceData); + Flowable>> addPushDevice(@Body Map pushDeviceData); @DELETE("user/push-devices/{regId}") - Observable>> deletePushDevice(@Path("regId") String regId); + Flowable>> deletePushDevice(@Path("regId") String regId); /* challenges api */ @GET("challenges/user") - Observable>> getUserChallenges(); + Flowable>> getUserChallenges(); @GET("tasks/challenge/{challengeId}") - Observable> getChallengeTasks(@Path("challengeId") String challengeId); + Flowable> getChallengeTasks(@Path("challengeId") String challengeId); @GET("challenges/{challengeId}") - Observable> getChallenge(@Path("challengeId") String challengeId); + Flowable> getChallenge(@Path("challengeId") String challengeId); @POST("challenges/{challengeId}/join") - Observable> joinChallenge(@Path("challengeId") String challengeId); + Flowable> joinChallenge(@Path("challengeId") String challengeId); @POST("challenges/{challengeId}/leave") - Observable> leaveChallenge(@Path("challengeId") String challengeId, @Body LeaveChallengeBody body); + Flowable> leaveChallenge(@Path("challengeId") String challengeId, @Body LeaveChallengeBody body); @POST("challenges") - Observable> createChallenge(@Body Challenge challenge); + Flowable> createChallenge(@Body Challenge challenge); @POST("tasks/challenge/{challengeId}") - Observable>> createChallengeTasks(@Path("challengeId") String challengeId, @Body List tasks); + Flowable>> createChallengeTasks(@Path("challengeId") String challengeId, @Body List tasks); @PUT("challenges/{challengeId}") - Observable> updateChallenge(@Path("challengeId") String challengeId, @Body Challenge challenge); + Flowable> updateChallenge(@Path("challengeId") String challengeId, @Body Challenge challenge); @DELETE("challenges/{challengeId}") - Observable> deleteChallenge(@Path("challengeId") String challengeId); + Flowable> deleteChallenge(@Path("challengeId") String challengeId); //DEBUG: These calls only work on a local development server @POST("debug/add-ten-gems") - Observable> debugAddTenGems(); + Flowable> debugAddTenGems(); // Notifications @POST("notifications/{notificationId}/read") - Observable> readNotification(@Path("notificationId") String notificationId); + Flowable> readNotification(@Path("notificationId") String notificationId); @POST("user/open-mystery-item") - Observable> openMysteryItem(); + Flowable> openMysteryItem(); @POST("cron") - Observable> runCron(); + Flowable> runCron(); @POST("user/reset") - Observable> resetAccount(); + Flowable> resetAccount(); @HTTP(method = "DELETE", path = "user", hasBody = true) - Observable> deleteAccount(@Body Map body); + Flowable> deleteAccount(@Body Map body); @GET("user/toggle-pinned-item/{pinType}/{path}") - Observable> togglePinnedItem(@Path("pinType") String pinType,@Path("path") String path); + Flowable> togglePinnedItem(@Path("pinType") String pinType,@Path("path") String path); @POST("user/reset-password") - Observable> sendPasswordResetEmail(@Body Map data); + Flowable> sendPasswordResetEmail(@Body Map data); @PUT("user/auth/update-username") - Observable> updateLoginName(@Body Map data); + Flowable> updateLoginName(@Body Map data); @PUT("user/auth/update-email") - Observable> updateEmail(@Body Map data); + Flowable> updateEmail(@Body Map data); @PUT("user/auth/update-password") - Observable> updatePassword(@Body Map data); + Flowable> updatePassword(@Body Map data); @POST("user/allocate") - Observable> allocatePoint(@Query("stat") String stat); + Flowable> allocatePoint(@Query("stat") String stat); @POST("user/allocate-bulk") - Observable> bulkAllocatePoints(@Body Map> stats); + Flowable> bulkAllocatePoints(@Body Map> stats); @GET("world-state") - Observable> getWorldState(); + Flowable> getWorldState(); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/api/MaintenanceApiService.java b/Habitica/src/main/java/com/habitrpg/android/habitica/api/MaintenanceApiService.java index 03b5c5df0..90c51c8eb 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/api/MaintenanceApiService.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/api/MaintenanceApiService.java @@ -3,15 +3,15 @@ package com.habitrpg.android.habitica.api; import com.habitrpg.android.habitica.models.responses.HabitResponse; import com.habitrpg.android.habitica.models.responses.MaintenanceResponse; +import io.reactivex.Flowable; import retrofit2.http.GET; -import rx.Observable; public interface MaintenanceApiService { @GET("maintenance-android.json") - Observable> getMaintenanceStatus(); + Flowable> getMaintenanceStatus(); @GET("deprecation-android.json") - Observable> getDepricationStatus(); + Flowable> getDepricationStatus(); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.java deleted file mode 100644 index 7fe9912a3..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.java +++ /dev/null @@ -1,260 +0,0 @@ -package com.habitrpg.android.habitica.data; - -import android.support.annotation.Nullable; - -import com.habitrpg.android.habitica.models.AchievementResult; -import com.habitrpg.android.habitica.models.ContentResult; -import com.habitrpg.android.habitica.models.LeaveChallengeBody; -import com.habitrpg.android.habitica.models.PurchaseValidationRequest; -import com.habitrpg.android.habitica.models.PurchaseValidationResult; -import com.habitrpg.android.habitica.models.SubscriptionValidationRequest; -import com.habitrpg.android.habitica.models.Tag; -import com.habitrpg.android.habitica.models.WorldState; -import com.habitrpg.android.habitica.models.auth.UserAuthResponse; -import com.habitrpg.android.habitica.models.inventory.Equipment; -import com.habitrpg.android.habitica.models.inventory.Quest; -import com.habitrpg.android.habitica.models.members.Member; -import com.habitrpg.android.habitica.models.responses.BuyResponse; -import com.habitrpg.android.habitica.models.responses.ErrorResponse; -import com.habitrpg.android.habitica.models.responses.FeedResponse; -import com.habitrpg.android.habitica.models.responses.HabitResponse; -import com.habitrpg.android.habitica.models.responses.PostChatMessageResult; -import com.habitrpg.android.habitica.models.responses.SkillResponse; -import com.habitrpg.android.habitica.models.responses.Status; -import com.habitrpg.android.habitica.models.responses.TaskDirectionData; -import com.habitrpg.android.habitica.models.responses.UnlockResponse; -import com.habitrpg.android.habitica.models.shops.Shop; -import com.habitrpg.android.habitica.models.shops.ShopItem; -import com.habitrpg.android.habitica.models.social.Challenge; -import com.habitrpg.android.habitica.models.social.ChatMessage; -import com.habitrpg.android.habitica.models.social.Group; -import com.habitrpg.android.habitica.models.tasks.Task; -import com.habitrpg.android.habitica.models.tasks.TaskList; -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 java.util.List; -import java.util.Map; - -import retrofit2.HttpException; -import rx.Observable; - - -public interface ApiClient { - void setLanguageCode(String languageCode); - - Observable getStatus(); - - Observable getContent(); - Observable getContent(String language); - - /* user API */ - - Observable getUser(); - - Observable updateUser(Map updateDictionary); - - Observable registrationLanguage(String registrationLanguage); - - Observable> retrieveInAppRewards(); - Observable> retrieveOldGear(); - - Observable equipItem(String type, String itemKey); - - Observable buyItem(String itemKey); - - Observable purchaseItem(String type, String itemKey); - - Observable purchaseHourglassItem(String type, String itemKey); - - Observable purchaseMysterySet(String itemKey); - - Observable purchaseQuest(String key); - Observable validateSubscription(SubscriptionValidationRequest request); - - Observable sellItem(String itemType, String itemKey); - - Observable feedPet(String petKey, String foodKey); - - Observable hatchPet(String eggKey, String hatchingPotionKey); - - - Observable getTasks(); - Observable getTasks(String type); - Observable getTasks(String type, String dueDate); - - - Observable unlockPath(String path); - - Observable getTask(String id); - - Observable postTaskDirection(String id, String direction); - - Observable> postTaskNewPosition(String id, int position); - - Observable scoreChecklistItem(String taskId, String itemId); - - Observable createTask(Task item); - - Observable> createTasks(List tasks); - - Observable updateTask(String id, Task item); - - Observable deleteTask(String id); - - - Observable createTag(Tag tag); - - Observable updateTag(String id, Tag tag); - - Observable deleteTag(String id); - - Observable registerUser(String username, String email, String password, String confirmPassword); - - Observable connectUser(String username, String password); - - Observable connectSocial(String network, String userId, String accessToken); - Observable sleep(); - - Observable revive(); - - Observable useSkill(String skillName, String targetType, String targetId); - - Observable useSkill(String skillName, String targetType); - - Observable changeClass(); - - Observable changeClass(String className); - - Observable disableClasses(); - - Observable markPrivateMessagesRead(); - - /* Group API */ - - Observable> listGroups(String type); - - Observable getGroup(String groupId); - - Observable updateGroup(String id, Group item); - - Observable> listGroupChat(String groupId); - - Observable joinGroup(String groupId); - - Observable leaveGroup(String groupId); - - Observable postGroupChat(String groupId, Map message); - - Observable deleteMessage(String groupId, String messageId); - - Observable> getGroupMembers(String groupId, Boolean includeAllPublicFields); - - Observable> getGroupMembers(String groupId, Boolean includeAllPublicFields, String lastId); - - // Like returns the full chat list - Observable likeMessage(String groupId, String mid); - - Observable flagMessage(String groupId, String mid); - - Observable seenMessages(String groupId); - - Observable> inviteToGroup(String groupId, Map inviteData); - - Observable rejectGroupInvite(String groupId); - - Observable acceptQuest(String groupId); - - Observable rejectQuest(String groupId); - - Observable cancelQuest(String groupId); - - Observable forceStartQuest(String groupId, Group group); - - Observable inviteToQuest(String groupId,String questKey); - - Observable abortQuest(String groupId); - - Observable leaveQuest(String groupId); - - Observable validatePurchase(PurchaseValidationRequest request); - - Observable changeCustomDayStart(Map updateObject); - - //Members URL - Observable getMember(String memberId); - - Observable getMemberAchievements(String memberId); - - Observable postPrivateMessage(Map messageDetails); - - Observable retrieveShopIventory(String identifier); - - //Push notifications - Observable> addPushDevice(Map pushDeviceData); - - Observable> deletePushDevice(String regId); - - /* challenges api */ - - Observable> getUserChallenges(); - - Observable getChallengeTasks(String challengeId); - - Observable getChallenge(String challengeId); - - Observable joinChallenge(String challengeId); - - Observable leaveChallenge(String challengeId, LeaveChallengeBody body); - - - Observable createChallenge(Challenge challenge); - - Observable> createChallengeTasks(String challengeId, List tasks); - Observable updateChallenge(Challenge challenge); - Observable deleteChallenge(String challengeId); - - //DEBUG: These calls only work on a local development server - - Observable debugAddTenGems(); - - // Notifications - Observable readNotification(String notificationId); - - ErrorResponse getErrorResponse(HttpException throwable); - - void updateAuthenticationCredentials(@Nullable String userID, @Nullable String apiToken); - - boolean hasAuthenticationKeys(); - - Observable retrieveUser(boolean withTasks); - Observable> retrieveInboxMessages(); - - Observable.Transformer, T> configureApiCallObserver(); - - Observable openMysteryItem(); - - Observable runCron(); - - Observable resetAccount(); - Observable deleteAccount(String password); - - Observable togglePinnedItem(String pinType, String path); - - Observable sendPasswordResetEmail(String email); - - Observable updateLoginName(String newLoginName, String password); - - Observable updateEmail(String newEmail, String password); - - Observable updatePassword(String newPassword, String oldPassword, String oldPasswordConfirmation); - - Observable allocatePoint(String stat); - - Observable bulkAllocatePoints(int strength, int intelligence, int constitution, int perception); - - Observable retrieveMarketGear(); - - Observable getWorldState(); -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt new file mode 100644 index 000000000..8771fcefd --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt @@ -0,0 +1,241 @@ +package com.habitrpg.android.habitica.data + +import com.habitrpg.android.habitica.models.* +import com.habitrpg.android.habitica.models.auth.UserAuthResponse +import com.habitrpg.android.habitica.models.inventory.Equipment +import com.habitrpg.android.habitica.models.inventory.Quest +import com.habitrpg.android.habitica.models.members.Member +import com.habitrpg.android.habitica.models.responses.* +import com.habitrpg.android.habitica.models.shops.Shop +import com.habitrpg.android.habitica.models.shops.ShopItem +import com.habitrpg.android.habitica.models.social.Challenge +import com.habitrpg.android.habitica.models.social.ChatMessage +import com.habitrpg.android.habitica.models.social.Group +import com.habitrpg.android.habitica.models.tasks.Task +import com.habitrpg.android.habitica.models.tasks.TaskList +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 io.reactivex.Flowable +import io.reactivex.FlowableTransformer +import io.reactivex.ObservableTransformer +import retrofit2.HttpException + + +interface ApiClient { + + val status: Flowable + + val content: Flowable + + /* user API */ + + val user: Flowable + + + val tasks: Flowable + + /* challenges api */ + + val userChallenges: Flowable> + + val worldState: Flowable + fun setLanguageCode(languageCode: String) + fun getContent(language: String): Flowable + + fun updateUser(updateDictionary: Map): Flowable + + fun registrationLanguage(registrationLanguage: String): Flowable + + fun retrieveInAppRewards(): Flowable> + fun retrieveOldGear(): Flowable> + + fun equipItem(type: String, itemKey: String): Flowable + + fun buyItem(itemKey: String): Flowable + + fun purchaseItem(type: String, itemKey: String): Flowable + + fun purchaseHourglassItem(type: String, itemKey: String): Flowable + + fun purchaseMysterySet(itemKey: String): Flowable + + fun purchaseQuest(key: String): Flowable + fun validateSubscription(request: SubscriptionValidationRequest): Flowable + + fun sellItem(itemType: String, itemKey: String): Flowable + + fun feedPet(petKey: String, foodKey: String): Flowable + + fun hatchPet(eggKey: String, hatchingPotionKey: String): Flowable + fun getTasks(type: String): Flowable + fun getTasks(type: String, dueDate: String): Flowable + + + fun unlockPath(path: String): Flowable + + fun getTask(id: String): Flowable + + fun postTaskDirection(id: String, direction: String): Flowable + + fun postTaskNewPosition(id: String, position: Int): Flowable> + + fun scoreChecklistItem(taskId: String, itemId: String): Flowable + + fun createTask(item: Task): Flowable + + fun createTasks(tasks: List): Flowable> + + fun updateTask(id: String, item: Task): Flowable + + fun deleteTask(id: String): Flowable + + + fun createTag(tag: Tag): Flowable + + fun updateTag(id: String, tag: Tag): Flowable + + fun deleteTag(id: String): Flowable + + fun registerUser(username: String, email: String, password: String, confirmPassword: String): Flowable + + fun connectUser(username: String, password: String): Flowable + + fun connectSocial(network: String, userId: String, accessToken: String): Flowable + fun sleep(): Flowable + + fun revive(): Flowable + + fun useSkill(skillName: String, targetType: String, targetId: String): Flowable + + fun useSkill(skillName: String, targetType: String): Flowable + + fun changeClass(): Flowable + + fun changeClass(className: String): Flowable + + fun disableClasses(): Flowable + + fun markPrivateMessagesRead(): Flowable + + /* Group API */ + + fun listGroups(type: String): Flowable> + + fun getGroup(groupId: String): Flowable + + fun updateGroup(id: String, item: Group): Flowable + + fun listGroupChat(groupId: String): Flowable> + + fun joinGroup(groupId: String): Flowable + + fun leaveGroup(groupId: String): Flowable + + fun postGroupChat(groupId: String, message: Map): Flowable + + fun deleteMessage(groupId: String, messageId: String): Flowable + + fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?): Flowable> + + fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?, lastId: String): Flowable> + + // Like returns the full chat list + fun likeMessage(groupId: String, mid: String): Flowable + + fun flagMessage(groupId: String, mid: String): Flowable + + fun seenMessages(groupId: String): Flowable + + fun inviteToGroup(groupId: String, inviteData: Map): Flowable> + + fun rejectGroupInvite(groupId: String): Flowable + + fun acceptQuest(groupId: String): Flowable + + fun rejectQuest(groupId: String): Flowable + + fun cancelQuest(groupId: String): Flowable + + fun forceStartQuest(groupId: String, group: Group): Flowable + + fun inviteToQuest(groupId: String, questKey: String): Flowable + + fun abortQuest(groupId: String): Flowable + + fun leaveQuest(groupId: String): Flowable + + fun validatePurchase(request: PurchaseValidationRequest): Flowable + + fun changeCustomDayStart(updateObject: Map): Flowable + + //Members URL + fun getMember(memberId: String): Flowable + + fun getMemberAchievements(memberId: String): Flowable + + fun postPrivateMessage(messageDetails: Map): Flowable + + fun retrieveShopIventory(identifier: String): Flowable + + //Push notifications + fun addPushDevice(pushDeviceData: Map): Flowable> + + fun deletePushDevice(regId: String): Flowable> + + fun getChallengeTasks(challengeId: String): Flowable + + fun getChallenge(challengeId: String): Flowable + + fun joinChallenge(challengeId: String): Flowable + + fun leaveChallenge(challengeId: String, body: LeaveChallengeBody): Flowable + + + fun createChallenge(challenge: Challenge): Flowable + + fun createChallengeTasks(challengeId: String, tasks: List): Flowable> + fun updateChallenge(challenge: Challenge): Flowable + fun deleteChallenge(challengeId: String): Flowable + + //DEBUG: These calls only work on a local development server + + fun debugAddTenGems(): Flowable + + // Notifications + fun readNotification(notificationId: String): Flowable> + + fun getErrorResponse(throwable: HttpException): ErrorResponse + + fun updateAuthenticationCredentials(userID: String?, apiToken: String?) + + fun hasAuthenticationKeys(): Boolean + + fun retrieveUser(withTasks: Boolean): Flowable + fun retrieveInboxMessages(): Flowable> + + fun configureApiCallObserver(): FlowableTransformer, T> + + fun openMysteryItem(): Flowable + + fun runCron(): Flowable + + fun resetAccount(): Flowable + fun deleteAccount(password: String): Flowable + + fun togglePinnedItem(pinType: String, path: String): Flowable + + fun sendPasswordResetEmail(email: String): Flowable + + fun updateLoginName(newLoginName: String, password: String): Flowable + + fun updateEmail(newEmail: String, password: String): Flowable + + fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable + + fun allocatePoint(stat: String): Flowable + + fun bulkAllocatePoints(strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable + + fun retrieveMarketGear(): Flowable +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/BaseRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/BaseRepository.java deleted file mode 100644 index 9d93ff24c..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/BaseRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.habitrpg.android.habitica.data; - -import java.util.List; - -import io.realm.RealmObject; - -public interface BaseRepository { - - void close(); - - T getUnmanagedCopy(T object); - List getUnmanagedCopy(List list); - - boolean isClosed(); -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/BaseRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/BaseRepository.kt new file mode 100644 index 000000000..cb3a2215d --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/BaseRepository.kt @@ -0,0 +1,13 @@ +package com.habitrpg.android.habitica.data + +import io.realm.RealmObject + +interface BaseRepository { + + val isClosed: Boolean + + fun close() + + fun getUnmanagedCopy(obj: T): T + fun getUnmanagedCopy(list: List): List +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.java index 3119eef17..abe1d2fa8 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.java @@ -8,14 +8,14 @@ import com.habitrpg.android.habitica.models.user.User; import java.util.List; +import io.reactivex.Flowable; import io.realm.RealmResults; -import rx.Observable; public interface ChallengeRepository extends BaseRepository { - Observable getChallenge(String challengeId); - Observable getChallengeTasks(String challengeId); + Flowable getChallenge(String challengeId); + Flowable getChallengeTasks(String challengeId); - Observable createChallenge(Challenge challenge, List taskList); + Flowable createChallenge(Challenge challenge, List taskList); /** * @@ -26,16 +26,16 @@ public interface ChallengeRepository extends BaseRepository { * @param removedTaskList tasks that has be to be removed * @return Observable with the updated challenge */ - Observable updateChallenge(Challenge challenge, List fullTaskList, + Flowable updateChallenge(Challenge challenge, List fullTaskList, List addedTaskList, List updatedTaskList, List removedTaskList); - Observable deleteChallenge(String challengeId); + Flowable deleteChallenge(String challengeId); - Observable> getChallenges(); - Observable> getUserChallenges(String userId); + Flowable> getChallenges(); + Flowable> getUserChallenges(String userId); - Observable> retrieveChallenges(User user); + Flowable> retrieveChallenges(User user); - Observable leaveChallenge(Challenge challenge, LeaveChallengeBody leaveChallengeBody); + Flowable leaveChallenge(Challenge challenge, LeaveChallengeBody leaveChallengeBody); - Observable joinChallenge(Challenge challenge); + Flowable joinChallenge(Challenge challenge); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ContentRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ContentRepository.java index 7703a1489..0fb731d7d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ContentRepository.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ContentRepository.java @@ -3,12 +3,12 @@ package com.habitrpg.android.habitica.data; import com.habitrpg.android.habitica.models.ContentResult; import com.habitrpg.android.habitica.models.WorldState; -import rx.Observable; +import io.reactivex.Flowable; public interface ContentRepository extends BaseRepository { - Observable retrieveContent(); - Observable retrieveContent(boolean forced); + Flowable retrieveContent(); + Flowable retrieveContent(boolean forced); - Observable retrieveWorldState(); + Flowable retrieveWorldState(); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/CustomizationRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/CustomizationRepository.java index 8d747fc3a..aea031088 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/CustomizationRepository.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/CustomizationRepository.java @@ -2,9 +2,9 @@ package com.habitrpg.android.habitica.data; import com.habitrpg.android.habitica.models.inventory.Customization; +import io.reactivex.Flowable; import io.realm.RealmResults; -import rx.Observable; public interface CustomizationRepository extends ContentRepository { - Observable> getCustomizations(String type, String category, boolean onlyAvailable); + Flowable> getCustomizations(String type, String category, boolean onlyAvailable); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/FAQRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/FAQRepository.java index a9d8da98d..95ca24fe6 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/FAQRepository.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/FAQRepository.java @@ -2,10 +2,10 @@ package com.habitrpg.android.habitica.data; import com.habitrpg.android.habitica.models.FAQArticle; +import io.reactivex.Flowable; import io.realm.RealmResults; -import rx.Observable; public interface FAQRepository extends BaseRepository { - Observable> getArticles(); + Flowable> getArticles(); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/InventoryRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/InventoryRepository.java index e39af4d95..cda99983c 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/InventoryRepository.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/InventoryRepository.java @@ -21,72 +21,72 @@ import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Map; +import io.reactivex.Flowable; import io.realm.RealmResults; -import rx.Observable; public interface InventoryRepository extends ContentRepository { - Observable getQuestContent(String key); + Flowable getQuestContent(String key); - Observable> getItems(List searchedKeys); + Flowable> getItems(List searchedKeys); long getArmoireRemainingCount(); - Observable> getInAppRewards(); - Observable> retrieveInAppRewards(); + Flowable> getInAppRewards(); + Flowable> retrieveInAppRewards(); - Observable> getOwnedEquipment(@NotNull String type); - Observable> getOwnedEquipment(); + Flowable> getOwnedEquipment(@NotNull String type); + Flowable> getOwnedEquipment(); - Observable> getOwnedItems(Class itemClass, User user); - Observable> getOwnedItems(@NotNull User user); + Flowable> getOwnedItems(Class itemClass, User user); + Flowable> getOwnedItems(@NotNull User user); - Observable getEquipment(String key); + Flowable getEquipment(String key); - Observable openMysteryItem(User user); + Flowable openMysteryItem(User user); void saveEquipment(Equipment equipment); - Observable> getMounts(); - Observable> getMounts(@NotNull String type, @NotNull String group); + Flowable> getMounts(); + Flowable> getMounts(@NotNull String type, @NotNull String group); - Observable> getOwnedMounts(); - Observable> getOwnedMounts(@NotNull String animalType, @NotNull String animalGroup); + Flowable> getOwnedMounts(); + Flowable> getOwnedMounts(@NotNull String animalType, @NotNull String animalGroup); - Observable> getPets(); - Observable> getPets(@NotNull String type, @NotNull String group); + Flowable> getPets(); + Flowable> getPets(@NotNull String type, @NotNull String group); - Observable> getOwnedPets(); - Observable> getOwnedPets(@NotNull String type, @NotNull String group); + Flowable> getOwnedPets(); + Flowable> getOwnedPets(@NotNull String type, @NotNull String group); void updateOwnedEquipment(User user); void changeOwnedCount(String type, String key, int amountToAdd); - Observable sellItem(User user, String type, String key); - Observable sellItem(User user, Item item); + Flowable sellItem(User user, String type, String key); + Flowable sellItem(User user, Item item); - Observable equipGear(User user, String equipment, boolean asCostume); - Observable equip(User user, String type, String key); + Flowable equipGear(User user, String equipment, boolean asCostume); + Flowable equip(User user, String type, String key); - Observable feedPet(Pet pet, Food food); + Flowable feedPet(Pet pet, Food food); - Observable hatchPet(Egg egg, HatchingPotion hatchingPotion); + Flowable hatchPet(Egg egg, HatchingPotion hatchingPotion); - Observable inviteToQuest(QuestContent quest); + Flowable inviteToQuest(QuestContent quest); - Observable buyItem(User user, String id, double value); + Flowable buyItem(User user, String id, double value); - Observable retrieveShopInventory(String identifier); - Observable retrieveMarketGear(); + Flowable retrieveShopInventory(String identifier); + Flowable retrieveMarketGear(); - Observable purchaseMysterySet(String categoryIdentifier); + Flowable purchaseMysterySet(String categoryIdentifier); - Observable purchaseHourglassItem(String purchaseType, String key); + Flowable purchaseHourglassItem(String purchaseType, String key); - Observable purchaseQuest(String key); + Flowable purchaseQuest(String key); - Observable purchaseItem(String purchaseType, String key); + Flowable purchaseItem(String purchaseType, String key); - Observable> togglePinnedItem(ShopItem item); + Flowable> togglePinnedItem(ShopItem item); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/SetupCustomizationRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/SetupCustomizationRepository.java index 01e9a75b1..ba58ad315 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/SetupCustomizationRepository.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/SetupCustomizationRepository.java @@ -8,6 +8,6 @@ import java.util.List; public interface SetupCustomizationRepository { - public List getCustomizations(String type, User user); - public List getCustomizations(String type, String subtype, User user); + List getCustomizations(String type, User user); + List getCustomizations(String type, String subtype, User user); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt index 6986b50a2..cd0454985 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt @@ -8,69 +8,68 @@ import com.habitrpg.android.habitica.models.social.Challenge 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 java.util.HashMap - +import io.reactivex.Flowable +import io.reactivex.Single import io.realm.RealmResults -import rx.Observable +import java.util.* interface SocialRepository : BaseRepository { - fun getPublicGuilds(): Observable> + fun getPublicGuilds(): Flowable> - fun getUserChallenges(): Observable> + fun getUserChallenges(): Flowable> - fun getUserGroups(): Observable> - fun retrieveGroupChat(groupId: String): Observable> - fun getGroupChat(groupId: String): Observable> + fun getUserGroups(): Flowable> + fun retrieveGroupChat(groupId: String): Single> + fun getGroupChat(groupId: String): Flowable> fun markMessagesSeen(seenGroupId: String) - fun flagMessage(chatMessage: ChatMessage): Observable + fun flagMessage(chatMessage: ChatMessage): Flowable - fun likeMessage(chatMessage: ChatMessage): Observable + fun likeMessage(chatMessage: ChatMessage): Flowable - fun deleteMessage(chatMessage: ChatMessage): Observable + fun deleteMessage(chatMessage: ChatMessage): Flowable - fun postGroupChat(groupId: String, messageObject: HashMap): Observable - fun postGroupChat(groupId: String, message: String): Observable + fun postGroupChat(groupId: String, messageObject: HashMap): Flowable + fun postGroupChat(groupId: String, message: String): Flowable - fun retrieveGroup(id: String): Observable - fun getGroup(id: String?): Observable + fun retrieveGroup(id: String): Flowable + fun getGroup(id: String?): Flowable - fun leaveGroup(id: String?): Observable + fun leaveGroup(id: String?): Flowable - fun joinGroup(id: String?): Observable + fun joinGroup(id: String?): Flowable - fun updateGroup(group: Group?, name: String?, description: String?, leader: String?, privacy: String?): Observable + fun updateGroup(group: Group?, name: String?, description: String?, leader: String?, privacy: String?): Flowable - fun retrieveGroups(type: String): Observable> - fun getGroups(type: String): Observable> + fun retrieveGroups(type: String): Flowable> + fun getGroups(type: String): Flowable> - fun postPrivateMessage(messageObject: HashMap): Observable - fun postPrivateMessage(recipientId: String, message: String): Observable + fun postPrivateMessage(messageObject: HashMap): Flowable + fun postPrivateMessage(recipientId: String, message: String): Flowable - fun getGroupMembers(id: String): Observable> - fun retrieveGroupMembers(id: String, includeAllPublicFields: Boolean): Observable> + fun getGroupMembers(id: String): Flowable> + fun retrieveGroupMembers(id: String, includeAllPublicFields: Boolean): Flowable> - fun inviteToGroup(id: String, inviteData: Map): Observable> + fun inviteToGroup(id: String, inviteData: Map): Flowable> - fun getMember(userId: String?): Observable + fun getMember(userId: String?): Flowable - fun markPrivateMessagesRead(user: User?): Observable + fun markPrivateMessagesRead(user: User?): Flowable - fun acceptQuest(user: User, partyId: String): Observable - fun rejectQuest(user: User, partyId: String): Observable + fun acceptQuest(user: User, partyId: String): Flowable + fun rejectQuest(user: User, partyId: String): Flowable - fun leaveQuest(partyId: String?): Observable + fun leaveQuest(partyId: String?): Flowable - fun cancelQuest(partyId: String?): Observable + fun cancelQuest(partyId: String?): Flowable - fun abortQuest(partyId: String?): Observable + fun abortQuest(partyId: String?): Flowable - fun rejectGroupInvite(groupId: String): Observable + fun rejectGroupInvite(groupId: String): Flowable - fun forceStartQuest(party: Group): Observable + fun forceStartQuest(party: Group): Flowable - fun getMemberAchievements(userId: String?): Observable + fun getMemberAchievements(userId: String?): Flowable } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/TagRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/TagRepository.java deleted file mode 100644 index 9151f9d61..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/TagRepository.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.habitrpg.android.habitica.data; - -import com.habitrpg.android.habitica.models.Tag; - -import java.util.Collection; -import java.util.List; - -import io.realm.RealmResults; -import rx.Observable; - -public interface TagRepository extends BaseRepository { - - Observable> getTags(String userId); - - Observable createTag(Tag tag); - Observable updateTag(Tag tag); - Observable deleteTag(String id); - - - Observable createTags(Collection tags); - Observable updateTags(Collection tags); - Observable> deleteTags(Collection tagIds); - - void removeOldTags(List onlineTags, String userID); -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/TagRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/TagRepository.kt new file mode 100644 index 000000000..af07ad6f6 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/TagRepository.kt @@ -0,0 +1,23 @@ +package com.habitrpg.android.habitica.data + +import com.habitrpg.android.habitica.models.Tag + +import io.reactivex.Flowable +import io.reactivex.Single +import io.realm.RealmResults + +interface TagRepository : BaseRepository { + + fun getTags(userId: String): Flowable> + + fun createTag(tag: Tag): Flowable + fun updateTag(tag: Tag): Flowable + fun deleteTag(id: String): Flowable + + + fun createTags(tags: Collection): Single> + fun updateTags(tags: Collection): Single> + fun deleteTags(tagIds: Collection): Single> + + fun removeOldTags(onlineTags: List, userID: String) +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/TaskRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/TaskRepository.kt index e77eed619..c82c9002b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/TaskRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/TaskRepository.kt @@ -6,31 +6,32 @@ import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.android.habitica.models.tasks.TaskList import com.habitrpg.android.habitica.models.tasks.TasksOrder import com.habitrpg.android.habitica.models.user.User +import io.reactivex.Flowable +import io.reactivex.Maybe import io.realm.Realm import io.realm.RealmResults -import rx.Observable import java.util.* interface TaskRepository : BaseRepository { - fun getTasks(taskType: String, userID: String): Observable> - fun getTasks(userId: String): Observable> + fun getTasks(taskType: String, userID: String): Flowable> + fun getTasks(userId: String): Flowable> fun saveTasks(userId: String, order: TasksOrder, tasks: TaskList) - fun retrieveTasks(userId: String, tasksOrder: TasksOrder): Observable - fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): Observable + fun retrieveTasks(userId: String, tasksOrder: TasksOrder): Flowable + fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): Flowable - fun taskChecked(user: User?, task: Task, up: Boolean, force: Boolean): Observable - fun taskChecked(user: User?, taskId: String, up: Boolean, force: Boolean): Observable - fun scoreChecklistItem(taskId: String, itemId: String): Observable + fun taskChecked(user: User?, task: Task, up: Boolean, force: Boolean): Flowable + fun taskChecked(user: User?, taskId: String, up: Boolean, force: Boolean): Maybe + fun scoreChecklistItem(taskId: String, itemId: String): Flowable - fun getTask(taskId: String): Observable - fun getTaskCopy(taskId: String): Observable - fun createTask(task: Task): Observable - fun updateTask(task: Task): Observable - fun deleteTask(taskId: String): Observable + fun getTask(taskId: String): Flowable + fun getTaskCopy(taskId: String): Flowable + fun createTask(task: Task): Flowable + fun updateTask(task: Task): Maybe? + fun deleteTask(taskId: String): Flowable fun saveTask(task: Task) - fun createTasks(newTasks: List): Observable> + fun createTasks(newTasks: List): Flowable> fun markTaskCompleted(taskId: String, isCompleted: Boolean) @@ -40,18 +41,18 @@ interface TaskRepository : BaseRepository { fun swapTaskPosition(firstPosition: Int, secondPosition: Int) - fun updateTaskPosition(taskType: String, oldPosition: Int, newPosition: Int): Observable> + fun updateTaskPosition(taskType: String, oldPosition: Int, newPosition: Int): Maybe> - fun getUnmanagedTask(taskid: String): Observable + fun getUnmanagedTask(taskid: String): Flowable fun updateTaskInBackground(task: Task) fun createTaskInBackground(task: Task) - fun getTaskCopies(userId: String): Observable> + fun getTaskCopies(userId: String): Flowable> - fun getTaskCopies(tasks: List): Observable> + fun getTaskCopies(tasks: List): Flowable> - fun updateDailiesIsDue(date: Date): Observable - fun retrieveCompletedTodos(userId: String): Observable + fun updateDailiesIsDue(date: Date): Flowable + fun retrieveCompletedTodos(userId: String): Flowable } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/TutorialRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/TutorialRepository.kt index 2d5a70119..3bf5b3dfc 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/TutorialRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/TutorialRepository.kt @@ -1,13 +1,12 @@ package com.habitrpg.android.habitica.data import com.habitrpg.android.habitica.models.TutorialStep - +import io.reactivex.Flowable import io.realm.RealmResults -import rx.Observable interface TutorialRepository : BaseRepository { - fun getTutorialStep(key: String): Observable - fun getTutorialSteps(keys: List): Observable> + fun getTutorialStep(key: String): Flowable + fun getTutorialSteps(keys: List): Flowable> } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt index 73af7edfb..411097104 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt @@ -9,65 +9,65 @@ import com.habitrpg.android.habitica.models.social.ChatMessage import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.android.habitica.models.user.Stats import com.habitrpg.android.habitica.models.user.User +import io.reactivex.Flowable import io.realm.RealmResults -import rx.Observable interface UserRepository : BaseRepository { - fun getUser(): Observable - fun getInboxOverviewList(): Observable> + fun getUser(): Flowable + fun getInboxOverviewList(): Flowable> - fun getUser(userID: String): Observable - fun updateUser(user: User?, updateData: Map): Observable - fun updateUser(user: User?, key: String, value: Any): Observable + fun getUser(userID: String): Flowable + fun updateUser(user: User?, updateData: Map): Flowable + fun updateUser(user: User?, key: String, value: Any): Flowable - fun retrieveUser(withTasks: Boolean): Observable - fun retrieveUser(withTasks: Boolean = false, forced: Boolean = false): Observable + fun retrieveUser(withTasks: Boolean): Flowable + fun retrieveUser(withTasks: Boolean = false, forced: Boolean = false): Flowable - fun getInboxMessages(replyToUserID: String?): Observable> - fun retrieveInboxMessages(): Observable> + fun getInboxMessages(replyToUserID: String?): Flowable> + fun retrieveInboxMessages(): Flowable> - fun revive(user: User): Observable + fun revive(user: User): Flowable fun resetTutorial(user: User?) - fun sleep(user: User): Observable + fun sleep(user: User): Flowable - fun getSkills(user: User): Observable> + fun getSkills(user: User): Flowable> - fun getSpecialItems(user: User): Observable> + fun getSpecialItems(user: User): Flowable> - fun useSkill(user: User?, key: String, target: String, taskId: String): Observable + fun useSkill(user: User?, key: String, target: String, taskId: String): Flowable - fun useSkill(user: User?, key: String, target: String): Observable + fun useSkill(user: User?, key: String, target: String): Flowable - fun changeClass(): Observable + fun changeClass(): Flowable - fun disableClasses(): Observable + fun disableClasses(): Flowable - fun changeClass(selectedClass: String): Observable + fun changeClass(selectedClass: String): Flowable - fun unlockPath(user: User, customization: Customization): Observable - fun unlockPath(user: User, set: CustomizationSet): Observable + fun unlockPath(user: User, customization: Customization): Flowable + fun unlockPath(user: User, set: CustomizationSet): Flowable fun runCron(tasks: MutableList) fun runCron() - fun readNotification(id: String): Observable> + fun readNotification(id: String): Flowable> - fun changeCustomDayStart(dayStartTime: Int): Observable + fun changeCustomDayStart(dayStartTime: Int): Flowable - fun updateLanguage(user: User?, languageCode: String): Observable + fun updateLanguage(user: User?, languageCode: String): Flowable - fun resetAccount(): Observable - fun deleteAccount(password: String): Observable + fun resetAccount(): Flowable + fun deleteAccount(password: String): Flowable - fun sendPasswordResetEmail(email: String): Observable + fun sendPasswordResetEmail(email: String): Flowable - fun updateLoginName(newLoginName: String, password: String): Observable - fun updateEmail(newEmail: String, password: String): Observable - fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Observable + fun updateLoginName(newLoginName: String, password: String): Flowable + fun updateEmail(newEmail: String, password: String): Flowable + fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable - fun allocatePoint(user: User?, @Stats.StatsTypes stat: String): Observable + fun allocatePoint(user: User?, @Stats.StatsTypes stat: String): Flowable - fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Observable + fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java deleted file mode 100644 index da958fd50..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java +++ /dev/null @@ -1,1031 +0,0 @@ -package com.habitrpg.android.habitica.data.implementation; - -import android.content.Context; -import android.support.v7.app.AlertDialog; -import android.util.Log; - -import com.amplitude.api.Amplitude; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonSyntaxException; -import com.google.gson.reflect.TypeToken; -import com.habitrpg.android.habitica.BuildConfig; -import com.habitrpg.android.habitica.HabiticaBaseApplication; -import com.habitrpg.android.habitica.R; -import com.habitrpg.android.habitica.api.ApiService; -import com.habitrpg.android.habitica.api.HostConfig; -import com.habitrpg.android.habitica.api.Server; -import com.habitrpg.android.habitica.data.ApiClient; -import com.habitrpg.android.habitica.events.ShowConnectionProblemEvent; -import com.habitrpg.android.habitica.helpers.PopupNotificationsManager; -import com.habitrpg.android.habitica.models.AchievementResult; -import com.habitrpg.android.habitica.models.ContentResult; -import com.habitrpg.android.habitica.models.FAQArticle; -import com.habitrpg.android.habitica.models.LeaveChallengeBody; -import com.habitrpg.android.habitica.models.PurchaseValidationRequest; -import com.habitrpg.android.habitica.models.PurchaseValidationResult; -import com.habitrpg.android.habitica.models.Skill; -import com.habitrpg.android.habitica.models.SubscriptionValidationRequest; -import com.habitrpg.android.habitica.models.Tag; -import com.habitrpg.android.habitica.models.TutorialStep; -import com.habitrpg.android.habitica.models.WorldState; -import com.habitrpg.android.habitica.models.auth.UserAuth; -import com.habitrpg.android.habitica.models.auth.UserAuthResponse; -import com.habitrpg.android.habitica.models.auth.UserAuthSocial; -import com.habitrpg.android.habitica.models.auth.UserAuthSocialTokens; -import com.habitrpg.android.habitica.models.inventory.Customization; -import com.habitrpg.android.habitica.models.inventory.Egg; -import com.habitrpg.android.habitica.models.inventory.Equipment; -import com.habitrpg.android.habitica.models.inventory.Food; -import com.habitrpg.android.habitica.models.inventory.HatchingPotion; -import com.habitrpg.android.habitica.models.inventory.Mount; -import com.habitrpg.android.habitica.models.inventory.Pet; -import com.habitrpg.android.habitica.models.inventory.Quest; -import com.habitrpg.android.habitica.models.inventory.QuestCollect; -import com.habitrpg.android.habitica.models.inventory.QuestContent; -import com.habitrpg.android.habitica.models.inventory.QuestDropItem; -import com.habitrpg.android.habitica.models.members.Member; -import com.habitrpg.android.habitica.models.responses.BuyResponse; -import com.habitrpg.android.habitica.models.responses.ErrorResponse; -import com.habitrpg.android.habitica.models.responses.FeedResponse; -import com.habitrpg.android.habitica.models.responses.HabitResponse; -import com.habitrpg.android.habitica.models.responses.PostChatMessageResult; -import com.habitrpg.android.habitica.models.responses.SkillResponse; -import com.habitrpg.android.habitica.models.responses.Status; -import com.habitrpg.android.habitica.models.responses.TaskDirectionData; -import com.habitrpg.android.habitica.models.responses.UnlockResponse; -import com.habitrpg.android.habitica.models.shops.Shop; -import com.habitrpg.android.habitica.models.shops.ShopItem; -import com.habitrpg.android.habitica.models.social.Challenge; -import com.habitrpg.android.habitica.models.social.ChatMessage; -import com.habitrpg.android.habitica.models.social.Group; -import com.habitrpg.android.habitica.models.tasks.Task; -import com.habitrpg.android.habitica.models.tasks.TaskList; -import com.habitrpg.android.habitica.models.user.Items; -import com.habitrpg.android.habitica.models.user.Purchases; -import com.habitrpg.android.habitica.models.user.Stats; -import com.habitrpg.android.habitica.models.user.User; -import com.habitrpg.android.habitica.proxy.CrashlyticsProxy; -import com.habitrpg.android.habitica.utils.BooleanAsIntAdapter; -import com.habitrpg.android.habitica.utils.ChallengeDeserializer; -import com.habitrpg.android.habitica.utils.ChallengeListDeserializer; -import com.habitrpg.android.habitica.utils.ChatMessageDeserializer; -import com.habitrpg.android.habitica.utils.ChatMessageListDeserializer; -import com.habitrpg.android.habitica.utils.ContentDeserializer; -import com.habitrpg.android.habitica.utils.CustomizationDeserializer; -import com.habitrpg.android.habitica.utils.DateDeserializer; -import com.habitrpg.android.habitica.utils.EggListDeserializer; -import com.habitrpg.android.habitica.utils.EquipmentListDeserializer; -import com.habitrpg.android.habitica.utils.FAQArticleListDeserilializer; -import com.habitrpg.android.habitica.utils.FeedResponseDeserializer; -import com.habitrpg.android.habitica.utils.FoodListDeserializer; -import com.habitrpg.android.habitica.utils.GroupSerialization; -import com.habitrpg.android.habitica.utils.HatchingPotionListDeserializer; -import com.habitrpg.android.habitica.utils.MemberSerialization; -import com.habitrpg.android.habitica.utils.MountListDeserializer; -import com.habitrpg.android.habitica.utils.MountMapDeserializer; -import com.habitrpg.android.habitica.utils.PetListDeserializer; -import com.habitrpg.android.habitica.utils.PetMapDeserializer; -import com.habitrpg.android.habitica.utils.PurchasedDeserializer; -import com.habitrpg.android.habitica.utils.QuestCollectDeserializer; -import com.habitrpg.android.habitica.utils.QuestDeserializer; -import com.habitrpg.android.habitica.utils.QuestDropItemsListSerialization; -import com.habitrpg.android.habitica.utils.QuestListDeserializer; -import com.habitrpg.android.habitica.utils.SkillDeserializer; -import com.habitrpg.android.habitica.utils.TaskListDeserializer; -import com.habitrpg.android.habitica.utils.TaskSerializer; -import com.habitrpg.android.habitica.utils.TaskTagDeserializer; -import com.habitrpg.android.habitica.utils.TutorialStepListDeserializer; -import com.habitrpg.android.habitica.utils.UserDeserializer; -import com.habitrpg.android.habitica.utils.WorldStateSerialization; - -import org.greenrobot.eventbus.EventBus; - -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.net.UnknownHostException; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import javax.net.ssl.SSLException; - -import io.realm.RealmList; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.ResponseBody; -import okhttp3.logging.HttpLoggingInterceptor; -import retrofit2.Converter; -import retrofit2.HttpException; -import retrofit2.Retrofit; -import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; -import retrofit2.converter.gson.GsonConverterFactory; -import rx.Observable; -import rx.android.schedulers.AndroidSchedulers; -import rx.functions.Action1; -import rx.functions.Func1; -import rx.schedulers.Schedulers; - - -public class ApiClientImpl implements Action1, ApiClient { - private static final String TAG = "ApiClientImpl"; - private final GsonConverterFactory gsonConverter; - private final HostConfig hostConfig; - private final Retrofit retrofitAdapter; - private final PopupNotificationsManager popupNotificationsManager; - - private CrashlyticsProxy crashlyticsProxy; - private Context context; - - // I think we don't need the ApiClientImpl anymore we could just use ApiService - private final ApiService apiService; - - private final Observable.Transformer apiCallTransformer = - observable -> ((Observable) observable) - .map(new Func1() { - @Override - public Object call(HabitResponse habitResponse) { - if (habitResponse.notifications != null) { - popupNotificationsManager.showNotificationDialog(habitResponse.notifications); - } - return habitResponse.getData(); - } - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .doOnError(this); - private AlertDialog displayedAlert; - private String languageCode; - private String lastAPICallURL; - - //private OnHabitsAPIResult mResultListener; - //private HostConfig mConfig; - public ApiClientImpl(GsonConverterFactory gsonConverter, HostConfig hostConfig, CrashlyticsProxy crashlyticsProxy, PopupNotificationsManager popupNotificationsManager, Context context) { - this.gsonConverter = gsonConverter; - this.hostConfig = hostConfig; - this.context = context; - this.crashlyticsProxy = crashlyticsProxy; - this.popupNotificationsManager = popupNotificationsManager; - this.popupNotificationsManager.setApiClient(this); - - HabiticaBaseApplication.getComponent().inject(this); - crashlyticsProxy.setUserIdentifier(this.hostConfig.getUser()); - crashlyticsProxy.setUserName(this.hostConfig.getUser()); - Amplitude.getInstance().setUserId(this.hostConfig.getUser()); - - HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); - if (BuildConfig.DEBUG) { - logging.setLevel(HttpLoggingInterceptor.Level.BODY); - } - - String userAgent = System.getProperty("http.agent"); - - OkHttpClient client = new OkHttpClient.Builder() - .addInterceptor(logging) - .addNetworkInterceptor(chain -> { - Request original = chain.request(); - Request.Builder builder = original.newBuilder(); - if (this.hostConfig.getUser() != null) { - builder = builder - .header("x-api-key", this.hostConfig.getApi()) - .header("x-api-user", this.hostConfig.getUser()); - } - builder = builder.header("x-client", "habitica-android"); - if (userAgent != null) { - builder = builder.header("user-agent", userAgent); - } - if (!BuildConfig.STAGING_KEY.isEmpty()) { - builder = builder.header("Authorization", "Basic " + BuildConfig.STAGING_KEY); - } - Request request = builder.method(original.method(), original.body()) - .build(); - lastAPICallURL = original.url().toString(); - return chain.proceed(request); - }) - .readTimeout(120, TimeUnit.SECONDS) - .build(); - - Server server = new Server(this.hostConfig.getAddress()); - - retrofitAdapter = new Retrofit.Builder() - .client(client) - .baseUrl(server.toString()) - .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) - .addConverterFactory(gsonConverter) - .build(); - - this.apiService = retrofitAdapter.create(ApiService.class); - } - - public static GsonConverterFactory createGsonFactory() { - Type taskTagClassListType = new TypeToken>() {}.getType(); - Type skillListType = new TypeToken>() {}.getType(); - Type customizationListType = new TypeToken>() {}.getType(); - Type tutorialStepListType = new TypeToken>() {}.getType(); - Type faqArticleListType = new TypeToken>() {}.getType(); - Type itemDataListType = new TypeToken>() {}.getType(); - Type eggListType = new TypeToken>() {}.getType(); - Type foodListType = new TypeToken>() {}.getType(); - Type hatchingPotionListType = new TypeToken>() {}.getType(); - Type questContentListType = new TypeToken>() {}.getType(); - Type petMapType = new TypeToken>() {}.getType(); - Type mountMapType = new TypeToken>() {}.getType(); - Type petListType = new TypeToken>() {}.getType(); - Type mountListType = new TypeToken>() {}.getType(); - Type questCollectListType = new TypeToken>() {}.getType(); - Type chatMessageListType = new TypeToken>() {}.getType(); - Type challengeListType = new TypeToken>() {}.getType(); - Type challengeRealmListType = new TypeToken>() {}.getType(); - Type questDropItemListType = new TypeToken>() {}.getType(); - - //Exclusion strategy needed for DBFlow https://github.com/Raizlabs/DBFlow/issues/121 - Gson gson = new GsonBuilder() - .registerTypeAdapter(taskTagClassListType, new TaskTagDeserializer()) - .registerTypeAdapter(Boolean.class, new BooleanAsIntAdapter()) - .registerTypeAdapter(boolean.class, new BooleanAsIntAdapter()) - .registerTypeAdapter(skillListType, new SkillDeserializer()) - .registerTypeAdapter(TaskList.class, new TaskListDeserializer()) - .registerTypeAdapter(Purchases.class, new PurchasedDeserializer()) - .registerTypeAdapter(customizationListType, new CustomizationDeserializer()) - .registerTypeAdapter(tutorialStepListType, new TutorialStepListDeserializer()) - .registerTypeAdapter(faqArticleListType, new FAQArticleListDeserilializer()) - .registerTypeAdapter(Group.class, new GroupSerialization()) - .registerTypeAdapter(Date.class, new DateDeserializer()) - .registerTypeAdapter(itemDataListType, new EquipmentListDeserializer()) - .registerTypeAdapter(eggListType, new EggListDeserializer()) - .registerTypeAdapter(foodListType, new FoodListDeserializer()) - .registerTypeAdapter(hatchingPotionListType, new HatchingPotionListDeserializer()) - .registerTypeAdapter(questContentListType, new QuestListDeserializer()) - .registerTypeAdapter(petListType, new PetListDeserializer()) - .registerTypeAdapter(mountListType, new MountListDeserializer()) - .registerTypeAdapter(petMapType, new PetMapDeserializer()) - .registerTypeAdapter(mountMapType, new MountMapDeserializer()) - .registerTypeAdapter(ChatMessage.class, new ChatMessageDeserializer()) - .registerTypeAdapter(Task.class, new TaskSerializer()) - .registerTypeAdapter(ContentResult.class, new ContentDeserializer()) - .registerTypeAdapter(FeedResponse.class, new FeedResponseDeserializer()) - .registerTypeAdapter(Challenge.class, new ChallengeDeserializer()) - .registerTypeAdapter(User.class, new UserDeserializer()) - .registerTypeAdapter(questCollectListType, new QuestCollectDeserializer()) - .registerTypeAdapter(chatMessageListType, new ChatMessageListDeserializer()) - .registerTypeAdapter(challengeListType, new ChallengeListDeserializer()) - .registerTypeAdapter(challengeRealmListType, new ChallengeListDeserializer()) - .registerTypeAdapter(questDropItemListType, new QuestDropItemsListSerialization()) - .registerTypeAdapter(Quest.class, new QuestDeserializer()) - .registerTypeAdapter(Member.class, new MemberSerialization()) - .registerTypeAdapter(WorldState.class, new WorldStateSerialization()) - .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - .create(); - return GsonConverterFactory.create(gson); - } - - public Observable registerUser(String username, String email, String password, String confirmPassword) { - UserAuth auth = new UserAuth(); - auth.setUsername(username); - auth.setPassword(password); - auth.setConfirmPassword(confirmPassword); - auth.setEmail(email); - return this.apiService.registerUser(auth).compose(configureApiCallObserver()); - } - - public Observable connectUser(String username, String password) { - UserAuth auth = new UserAuth(); - auth.setUsername(username); - auth.setPassword(password); - return this.apiService.connectLocal(auth).compose(configureApiCallObserver()); - } - - public Observable connectSocial(String network, String userId, String accessToken) { - UserAuthSocial auth = new UserAuthSocial(); - auth.setNetwork(network); - UserAuthSocialTokens authResponse = new UserAuthSocialTokens(); - authResponse.setClient_id(userId); - authResponse.setAccess_token(accessToken); - auth.setAuthResponse(authResponse); - - return this.apiService.connectSocial(auth).compose(configureApiCallObserver()); - } - - @Override - public void call(Throwable throwable) { - final Class throwableClass = throwable.getClass(); - if (SocketException.class.isAssignableFrom(throwableClass) || SSLException.class.isAssignableFrom(throwableClass)) { - this.showConnectionProblemDialog(R.string.internal_error_api); - } else if (throwableClass.equals(SocketTimeoutException.class) || UnknownHostException.class.equals(throwableClass)) { - this.showConnectionProblemDialog(R.string.network_error_no_network_body); - } else if (throwableClass.equals(retrofit2.adapter.rxjava.HttpException.class)) { - HttpException error = (HttpException) throwable; - ErrorResponse res = getErrorResponse(error); - int status = error.code(); - - if (error.response().raw().request().url().toString().endsWith("/user/push-devices")) { - //workaround for an error that sometimes displays that the user already has this push device - return; - } - - if (status >= 400 && status < 500) { - if (res != null && res.getDisplayMessage().length() > 0) { - showConnectionProblemDialog("", res.getDisplayMessage()); - } else if (status == 401) { - showConnectionProblemDialog(R.string.authentication_error_title, R.string.authentication_error_body); - } - } else if (status >= 500 && status < 600) { - this.showConnectionProblemDialog(R.string.internal_error_api); - } else { - showConnectionProblemDialog(R.string.internal_error_api); - } - } else if (JsonSyntaxException.class.isAssignableFrom(throwableClass)) { - crashlyticsProxy.log("Json Error: " + lastAPICallURL + ", " + throwable.getMessage()); - } else { - crashlyticsProxy.logException(throwable); - } - } - - public ErrorResponse getErrorResponse(HttpException error) { - ResponseBody errorResponse = error.response().errorBody(); - if (errorResponse == null) { - return new ErrorResponse(); - } - Converter errorConverter = - gsonConverter - .responseBodyConverter(ErrorResponse.class, new Annotation[0], retrofitAdapter); - try { - return (ErrorResponse) errorConverter.convert(errorResponse); - } catch (IOException e) { - return new ErrorResponse(); - } - } - - public Observable retrieveUser(boolean withTasks) { - - Observable userObservable = this.getUser(); - - if (withTasks) { - Observable tasksObservable = this.getTasks(); - - userObservable = Observable.zip(userObservable, tasksObservable, - (habitRPGUser, tasks) -> { - habitRPGUser.tasks = tasks; - return habitRPGUser; - }); - } - return userObservable; - } - - public Observable> retrieveInboxMessages() { - return apiService.getInboxMessages().compose(configureApiCallObserver()); - } - - public boolean hasAuthenticationKeys() { - return this.hostConfig.getUser() != null; - } - - private void showConnectionProblemDialog(final int resourceMessageString) { - showConnectionProblemDialog(R.string.network_error_title, resourceMessageString); - } - - private void showConnectionProblemDialog(final int resourceTitleString, final int resourceMessageString) { - showConnectionProblemDialog(context.getString(resourceTitleString), context.getString(resourceMessageString)); - } - - private void showConnectionProblemDialog(final String resourceTitleString, final String resourceMessageString) { - ShowConnectionProblemEvent event = new ShowConnectionProblemEvent(resourceTitleString, resourceMessageString); - EventBus.getDefault().post(event); - if (BuildConfig.DEBUG) { - Log.d(TAG, "showConnectionProblemDialog: " + resourceTitleString + " " + resourceMessageString); - } - } - - /* - This function is used with Observer.compose to reuse transformers across the application. - See here for more info: http://blog.danlew.net/2015/03/02/dont-break-the-chain/ - */ - - @SuppressWarnings("unchecked") - public Observable.Transformer, T> configureApiCallObserver() { - return (Observable.Transformer, T>) apiCallTransformer; - } - - public void updateAuthenticationCredentials(String userID, String apiToken) { - this.hostConfig.setUser(userID); - this.hostConfig.setApi(apiToken); - if (crashlyticsProxy != null) { - crashlyticsProxy.setUserIdentifier(this.hostConfig.getUser()); - crashlyticsProxy.setUserName(this.hostConfig.getUser()); - } - Amplitude.getInstance().setUserId(this.hostConfig.getUser()); - } - - @Override - public void setLanguageCode(String languageCode) { - this.languageCode = languageCode; - } - - @Override - public Observable getStatus() { - return apiService.getStatus().compose(configureApiCallObserver()); - } - - @Override - public Observable getContent(String language) { - return apiService.getContent(language).compose(configureApiCallObserver()); - } - - @Override - public Observable getUser() { - return apiService.getUser().compose(configureApiCallObserver()); - } - - @Override - public Observable updateUser(Map updateDictionary) { - return apiService.updateUser(updateDictionary).compose(configureApiCallObserver()); - } - - @Override - public Observable registrationLanguage(String registrationLanguage) { - return apiService.registrationLanguage(registrationLanguage).compose(configureApiCallObserver()); - } - - @Override - public Observable> retrieveInAppRewards() { - return apiService.retrieveInAppRewards().compose(configureApiCallObserver()); - } - - @Override - public Observable> retrieveOldGear() { - return apiService.retrieveOldGearRewards().compose(configureApiCallObserver()); - } - - @Override - public Observable equipItem(String type, String itemKey) { - if (itemKey == null) { - return Observable.just(null); - } - return apiService.equipItem(type, itemKey).compose(configureApiCallObserver()); - } - - @Override - public Observable buyItem(String itemKey) { - if (itemKey == null) { - return Observable.just(null); - } - return apiService.buyItem(itemKey).compose(configureApiCallObserver()); - } - - @Override - public Observable purchaseItem(String type, String itemKey) { - if (itemKey == null) { - return Observable.just(null); - } - return apiService.purchaseItem(type, itemKey).compose(configureApiCallObserver()); - } - - @Override - public Observable validateSubscription(SubscriptionValidationRequest request) { - return apiService.validateSubscription(request).map(habitResponse -> { - if (habitResponse.notifications != null) { - popupNotificationsManager.showNotificationDialog(habitResponse.notifications); - } - return habitResponse.getData(); - }); - } - - @Override - public Observable purchaseHourglassItem(String type, String itemKey) { - if (itemKey == null) { - return Observable.just(null); - } - return apiService.purchaseHourglassItem(type, itemKey).compose(configureApiCallObserver()); - } - - @Override - public Observable purchaseMysterySet(String itemKey) { - if (itemKey == null) { - return Observable.just(null); - } - return apiService.purchaseMysterySet(itemKey).compose(configureApiCallObserver()); - } - - @Override - public Observable purchaseQuest(String key) { - if (key == null) { - return Observable.just(null); - } - return apiService.purchaseQuest(key).compose(configureApiCallObserver()); - } - - @Override - public Observable sellItem(String itemType, String itemKey) { - if (itemKey == null) { - return Observable.just(null); - } - return apiService.sellItem(itemType, itemKey).compose(configureApiCallObserver()); - } - - @Override - public Observable feedPet(String petKey, String foodKey) { - return apiService.feedPet(petKey, foodKey).compose(configureApiCallObserver()); - } - - @Override - public Observable hatchPet(String eggKey, String hatchingPotionKey) { - return apiService.hatchPet(eggKey, hatchingPotionKey).compose(configureApiCallObserver()); - } - - @Override - public Observable getTasks() { - return apiService.getTasks().compose(configureApiCallObserver()); - } - - @Override - public Observable getTasks(String type) { - return apiService.getTasks(type).compose(configureApiCallObserver()); - } - - - @Override - public Observable getTasks(String type, String dueDate) { - return apiService.getTasks(type, dueDate).compose(configureApiCallObserver()); - } - - - @Override - public Observable unlockPath(String path) { - if (path == null) { - return Observable.just(null); - } - return apiService.unlockPath(path).compose(configureApiCallObserver()); - } - - @Override - public Observable getTask(String id) { - return apiService.getTask(id).compose(configureApiCallObserver()); - } - - @Override - public Observable postTaskDirection(String id, String direction) { - return apiService.postTaskDirection(id, direction).compose(configureApiCallObserver()); - } - - @Override - public Observable> postTaskNewPosition(String id, int position) { - return apiService.postTaskNewPosition(id, position).compose(configureApiCallObserver()); - } - - @Override - public Observable scoreChecklistItem(String taskId, String itemId) { - return apiService.scoreChecklistItem(taskId, itemId).compose(configureApiCallObserver()); - } - - @Override - public Observable createTask(Task item) { - return apiService.createTask(item).compose(configureApiCallObserver()); - } - - @Override - public Observable> createTasks(List tasks) { - return apiService.createTasks(tasks).compose(configureApiCallObserver()); - } - - @Override - public Observable updateTask(String id, Task item) { - return apiService.updateTask(id, item).compose(configureApiCallObserver()); - } - - @Override - public Observable deleteTask(String id) { - return apiService.deleteTask(id).compose(configureApiCallObserver()); - } - - @Override - public Observable createTag(Tag tag) { - return apiService.createTag(tag).compose(configureApiCallObserver()); - } - - @Override - public Observable updateTag(String id, Tag tag) { - return apiService.updateTag(id, tag).compose(configureApiCallObserver()); - } - - @Override - public Observable deleteTag(String id) { - return apiService.deleteTag(id).compose(configureApiCallObserver()); - } - - @Override - public Observable sleep() { - return apiService.sleep().compose(configureApiCallObserver()); - } - - @Override - public Observable revive() { - return apiService.revive().compose(configureApiCallObserver()); - } - - @Override - public Observable useSkill(String skillName, String targetType, String targetId) { - return apiService.useSkill(skillName, targetType, targetId).compose(configureApiCallObserver()); - } - - @Override - public Observable useSkill(String skillName, String targetType) { - return apiService.useSkill(skillName, targetType).compose(configureApiCallObserver()); - } - - @Override - public Observable changeClass() { - return apiService.changeClass().compose(configureApiCallObserver()); - } - - @Override - public Observable changeClass(String className) { - return apiService.changeClass(className).compose(configureApiCallObserver()); - } - - @Override - public Observable disableClasses() { - return apiService.disableClasses().compose(configureApiCallObserver()); - } - - @Override - public Observable markPrivateMessagesRead() { - //This is necessary, because the API call returns weird data. - return apiService.markPrivateMessagesRead() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .doOnError(this); - } - - @Override - public Observable> listGroups(String type) { - return apiService.listGroups(type).compose(configureApiCallObserver()); - } - - @Override - public Observable getGroup(String groupId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.getGroup(groupId).compose(configureApiCallObserver()); - } - - @Override - public Observable updateGroup(String id, Group item) { - if (id == null) { - return Observable.just(null); - } - return apiService.updateGroup(id, item).compose(configureApiCallObserver()); - } - - @Override - public Observable> listGroupChat(String groupId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.listGroupChat(groupId).compose(configureApiCallObserver()); - } - - @Override - public Observable joinGroup(String groupId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.joinGroup(groupId).compose(configureApiCallObserver()); - } - - @Override - public Observable leaveGroup(String groupId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.leaveGroup(groupId).compose(configureApiCallObserver()); - } - - @Override - public Observable postGroupChat(String groupId, Map message) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.postGroupChat(groupId, message).compose(configureApiCallObserver()); - } - - @Override - public Observable deleteMessage(String groupId, String messageId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.deleteMessage(groupId, messageId).compose(configureApiCallObserver()); - } - - @Override - public Observable> getGroupMembers(String groupId, Boolean includeAllPublicFields) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.getGroupMembers(groupId, includeAllPublicFields).compose(configureApiCallObserver()); - } - - @Override - public Observable> getGroupMembers(String groupId, Boolean includeAllPublicFields, String lastId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.getGroupMembers(groupId, includeAllPublicFields, lastId).compose(configureApiCallObserver()); - } - - @Override - public Observable likeMessage(String groupId, String mid) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.likeMessage(groupId, mid).compose(configureApiCallObserver()); - } - - @Override - public Observable flagMessage(String groupId, String mid) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.flagMessage(groupId, mid).compose(configureApiCallObserver()); - } - - @Override - public Observable seenMessages(String groupId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.seenMessages(groupId).compose(configureApiCallObserver()); - } - - @Override - public Observable> inviteToGroup(String groupId, Map inviteData) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.inviteToGroup(groupId, inviteData).compose(configureApiCallObserver()); - } - - @Override - public Observable rejectGroupInvite(String groupId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.rejectGroupInvite(groupId).compose(configureApiCallObserver()); - } - - @Override - public Observable acceptQuest(String groupId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.acceptQuest(groupId).compose(configureApiCallObserver()); - } - - @Override - public Observable rejectQuest(String groupId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.rejectQuest(groupId).compose(configureApiCallObserver()); - } - - @Override - public Observable cancelQuest(String groupId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.cancelQuest(groupId).compose(configureApiCallObserver()); - } - - @Override - public Observable forceStartQuest(String groupId, Group group) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.forceStartQuest(groupId, group).compose(configureApiCallObserver()); - } - - @Override - public Observable inviteToQuest(String groupId, String questKey) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.inviteToQuest(groupId, questKey).compose(configureApiCallObserver()); - } - - @Override - public Observable abortQuest(String groupId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.abortQuest(groupId).compose(configureApiCallObserver()); - } - - @Override - public Observable leaveQuest(String groupId) { - if (groupId == null) { - return Observable.just(null); - } - return apiService.leaveQuest(groupId).compose(configureApiCallObserver()); - } - - @Override - public Observable validatePurchase(PurchaseValidationRequest request) { - return apiService.validatePurchase(request).map(habitResponse -> { - if (habitResponse.notifications != null) { - popupNotificationsManager.showNotificationDialog(habitResponse.notifications); - } - return habitResponse.getData(); - }); - } - - @Override - public Observable changeCustomDayStart(Map updateObject) { - return apiService.changeCustomDayStart(updateObject).compose(configureApiCallObserver()); - } - - @Override - public Observable getMember(String memberId) { - return apiService.getMember(memberId).compose(configureApiCallObserver()); - } - - @Override - public Observable getMemberAchievements(String memberId) { - return apiService.getMemberAchievements(memberId).compose(configureApiCallObserver()); - } - - @Override - public Observable postPrivateMessage(Map messageDetails) { - return apiService.postPrivateMessage(messageDetails).compose(configureApiCallObserver()); - } - - @Override - public Observable retrieveShopIventory(String identifier) { - return apiService.retrieveShopInventory(identifier).compose(configureApiCallObserver()); - } - - @Override - public Observable> addPushDevice(Map pushDeviceData) { - return apiService.addPushDevice(pushDeviceData).compose(configureApiCallObserver()); - } - - @Override - public Observable> deletePushDevice(String regId) { - return apiService.deletePushDevice(regId).compose(configureApiCallObserver()); - } - - @Override - public Observable> getUserChallenges() { - return apiService.getUserChallenges().compose(configureApiCallObserver()); - } - - @Override - public Observable getChallengeTasks(String challengeId) { - return apiService.getChallengeTasks(challengeId).compose(configureApiCallObserver()); - } - - @Override - public Observable getChallenge(String challengeId) { - return apiService.getChallenge(challengeId).compose(configureApiCallObserver()); - } - - @Override - public Observable joinChallenge(String challengeId) { - return apiService.joinChallenge(challengeId).compose(configureApiCallObserver()); - } - - @Override - public Observable leaveChallenge(String challengeId, LeaveChallengeBody body) { - return apiService.leaveChallenge(challengeId, body).compose(configureApiCallObserver()); - } - - - @Override - public Observable createChallenge(Challenge challenge) { - return apiService.createChallenge(challenge).compose(configureApiCallObserver()); - } - - @Override - public Observable> createChallengeTasks(String challengeId, List tasks) { - return apiService.createChallengeTasks(challengeId, tasks).compose(configureApiCallObserver()); - } - - @Override - public Observable updateChallenge(Challenge challenge) { - return apiService.updateChallenge(challenge.id, challenge).compose(configureApiCallObserver()); - } - - @Override - public Observable deleteChallenge(String challengeId) { - return apiService.deleteChallenge(challengeId).compose(configureApiCallObserver()); - } - - @Override - public Observable debugAddTenGems() { - return apiService.debugAddTenGems().compose(configureApiCallObserver()); - } - - @Override - public Observable readNotification(String notificationId) { - return apiService.readNotification(notificationId).compose(configureApiCallObserver()); - } - - public Observable getContent() { - return apiService.getContent(languageCode).compose(configureApiCallObserver()); - } - - - @Override - public Observable openMysteryItem() { - return apiService.openMysteryItem().compose(configureApiCallObserver()); - } - - @Override - public Observable runCron() { - return apiService.runCron().compose(configureApiCallObserver()); - } - - @Override - public Observable resetAccount() { - return apiService.resetAccount().compose(configureApiCallObserver()); - } - - @Override - public Observable deleteAccount(String password) { - Map updateObject = new HashMap<>(); - updateObject.put("password", password); - return apiService.deleteAccount(updateObject).compose(configureApiCallObserver()); - } - - @Override - public Observable togglePinnedItem(String pinType, String path) { - if (pinType == null || path == null) { - return Observable.just(null); - } - return apiService.togglePinnedItem(pinType, path).compose(configureApiCallObserver()); - } - - @Override - public Observable sendPasswordResetEmail(String email) { - Map data = new HashMap<>(); - data.put("email", email); - return apiService.sendPasswordResetEmail(data).compose(configureApiCallObserver()); - } - - @Override - public Observable updateLoginName(String newLoginName, String password) { - Map updateObject = new HashMap<>(); - updateObject.put("username", newLoginName); - updateObject.put("password", password); - return apiService.updateLoginName(updateObject).compose(configureApiCallObserver()); - } - - @Override - public Observable updateEmail(String newEmail, String password) { - Map updateObject = new HashMap<>(); - updateObject.put("newEmail", newEmail); - updateObject.put("password", password); - return apiService.updateEmail(updateObject).compose(configureApiCallObserver()); - } - - @Override - public Observable updatePassword(String newPassword, String oldPassword, String oldPasswordConfirmation) { - Map updateObject = new HashMap<>(); - updateObject.put("newPassword", newPassword); - updateObject.put("password", oldPassword); - updateObject.put("confirmPassowrd", oldPasswordConfirmation); - return apiService.updatePassword(updateObject).compose(configureApiCallObserver()); - } - - @Override - public Observable allocatePoint(String stat) { - return apiService.allocatePoint(stat).compose(configureApiCallObserver()); - } - - @Override - public Observable bulkAllocatePoints(int strength, int intelligence, int constitution, int perception) { - Map> body = new HashMap<>(); - Map stats = new HashMap<>(); - stats.put("str", strength); - stats.put("int", intelligence); - stats.put("con", constitution); - stats.put("per", perception); - body.put("stats", stats); - return apiService.bulkAllocatePoints(body).compose(configureApiCallObserver()); - } - - @Override - public Observable retrieveMarketGear() { - return apiService.retrieveMarketGear().compose(configureApiCallObserver()); - } - - @Override - public Observable getWorldState() { - return apiService.getWorldState().compose(configureApiCallObserver()); - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt new file mode 100644 index 000000000..3b7b706f1 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt @@ -0,0 +1,788 @@ +package com.habitrpg.android.habitica.data.implementation + +import android.content.Context +import android.support.v7.app.AlertDialog +import android.util.Log +import com.amplitude.api.Amplitude +import com.google.gson.GsonBuilder +import com.google.gson.JsonSyntaxException +import com.google.gson.reflect.TypeToken +import com.habitrpg.android.habitica.BuildConfig +import com.habitrpg.android.habitica.HabiticaBaseApplication +import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.api.ApiService +import com.habitrpg.android.habitica.api.HostConfig +import com.habitrpg.android.habitica.api.Server +import com.habitrpg.android.habitica.data.ApiClient +import com.habitrpg.android.habitica.events.ShowConnectionProblemEvent +import com.habitrpg.android.habitica.helpers.PopupNotificationsManager +import com.habitrpg.android.habitica.models.* +import com.habitrpg.android.habitica.models.auth.UserAuth +import com.habitrpg.android.habitica.models.auth.UserAuthResponse +import com.habitrpg.android.habitica.models.auth.UserAuthSocial +import com.habitrpg.android.habitica.models.auth.UserAuthSocialTokens +import com.habitrpg.android.habitica.models.inventory.* +import com.habitrpg.android.habitica.models.members.Member +import com.habitrpg.android.habitica.models.responses.* +import com.habitrpg.android.habitica.models.shops.Shop +import com.habitrpg.android.habitica.models.shops.ShopItem +import com.habitrpg.android.habitica.models.social.Challenge +import com.habitrpg.android.habitica.models.social.ChatMessage +import com.habitrpg.android.habitica.models.social.Group +import com.habitrpg.android.habitica.models.tasks.Task +import com.habitrpg.android.habitica.models.tasks.TaskList +import com.habitrpg.android.habitica.models.user.Items +import com.habitrpg.android.habitica.models.user.Purchases +import com.habitrpg.android.habitica.models.user.Stats +import com.habitrpg.android.habitica.models.user.User +import com.habitrpg.android.habitica.proxy.CrashlyticsProxy +import com.habitrpg.android.habitica.utils.* +import io.reactivex.Flowable +import io.reactivex.FlowableTransformer +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.functions.BiFunction +import io.reactivex.functions.Consumer +import io.reactivex.schedulers.Schedulers +import io.realm.RealmList +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.logging.HttpLoggingInterceptor +import org.greenrobot.eventbus.EventBus +import retrofit2.HttpException +import retrofit2.Retrofit +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory +import retrofit2.converter.gson.GsonConverterFactory +import java.io.IOException +import java.net.SocketException +import java.net.SocketTimeoutException +import java.net.UnknownHostException +import java.util.* +import java.util.concurrent.TimeUnit +import javax.net.ssl.SSLException + + +class ApiClientImpl//private OnHabitsAPIResult mResultListener; +//private HostConfig mConfig; +(private val gsonConverter: GsonConverterFactory, private val hostConfig: HostConfig, private val crashlyticsProxy: CrashlyticsProxy, private val popupNotificationsManager: PopupNotificationsManager, private val context: Context) : Consumer, ApiClient { + private val retrofitAdapter: Retrofit + + // I think we don't need the ApiClientImpl anymore we could just use ApiService + private val apiService: ApiService + + private val apiCallTransformer = FlowableTransformer, Any> { observable -> + observable.map { habitResponse -> + if (habitResponse.notifications != null) { + popupNotificationsManager.showNotificationDialog(habitResponse.notifications) + } + habitResponse.data + } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnError(this) + } + private val displayedAlert: AlertDialog? = null + private var languageCode: String? = null + private var lastAPICallURL: String? = null + + init { + this.popupNotificationsManager.setApiClient(this) + + HabiticaBaseApplication.getComponent().inject(this) + crashlyticsProxy.setUserIdentifier(this.hostConfig.user) + crashlyticsProxy.setUserName(this.hostConfig.user) + Amplitude.getInstance().userId = this.hostConfig.user + + val logging = HttpLoggingInterceptor() + if (BuildConfig.DEBUG) { + logging.level = HttpLoggingInterceptor.Level.BODY + } + + val userAgent = System.getProperty("http.agent") + + val client = OkHttpClient.Builder() + .addInterceptor(logging) + .addNetworkInterceptor { chain -> + val original = chain.request() + var builder: Request.Builder = original.newBuilder() + if (this.hostConfig.user != null) { + builder = builder + .header("x-api-key", this.hostConfig.api) + .header("x-api-user", this.hostConfig.user) + } + builder = builder.header("x-client", "habitica-android") + if (userAgent != null) { + builder = builder.header("user-agent", userAgent) + } + if (!BuildConfig.STAGING_KEY.isEmpty()) { + builder = builder.header("Authorization", "Basic " + BuildConfig.STAGING_KEY) + } + val request = builder.method(original.method(), original.body()) + .build() + lastAPICallURL = original.url().toString() + chain.proceed(request) + } + .readTimeout(120, TimeUnit.SECONDS) + .build() + + val server = Server(this.hostConfig.address) + + retrofitAdapter = Retrofit.Builder() + .client(client) + .baseUrl(server.toString()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .addConverterFactory(gsonConverter) + .build() + + this.apiService = retrofitAdapter.create(ApiService::class.java) + } + + override fun registerUser(username: String, email: String, password: String, confirmPassword: String): Flowable { + val auth = UserAuth() + auth.username = username + auth.password = password + auth.confirmPassword = confirmPassword + auth.email = email + return this.apiService.registerUser(auth).compose(configureApiCallObserver()) + } + + override fun connectUser(username: String, password: String): Flowable { + val auth = UserAuth() + auth.username = username + auth.password = password + return this.apiService.connectLocal(auth).compose(configureApiCallObserver()) + } + + override fun connectSocial(network: String, userId: String, accessToken: String): Flowable { + val auth = UserAuthSocial() + auth.network = network + val authResponse = UserAuthSocialTokens() + authResponse.client_id = userId + authResponse.access_token = accessToken + auth.authResponse = authResponse + + return this.apiService.connectSocial(auth).compose(configureApiCallObserver()) + } + + override fun accept(throwable: Throwable) { + val throwableClass = throwable.javaClass + if (SocketException::class.java.isAssignableFrom(throwableClass) || SSLException::class.java.isAssignableFrom(throwableClass)) { + this.showConnectionProblemDialog(R.string.internal_error_api) + } else if (throwableClass == SocketTimeoutException::class.java || UnknownHostException::class.java == throwableClass) { + this.showConnectionProblemDialog(R.string.network_error_no_network_body) + } else if (throwableClass == retrofit2.adapter.rxjava2.HttpException::class.java) { + val error = throwable as HttpException + val res = getErrorResponse(error) + val status = error.code() + + if (error.response().raw().request().url().toString().endsWith("/user/push-devices")) { + //workaround for an error that sometimes displays that the user already has this push device + return + } + + if (status in 400..499) { + if (res.displayMessage.isNotEmpty()) { + showConnectionProblemDialog("", res.displayMessage) + } else if (status == 401) { + showConnectionProblemDialog(R.string.authentication_error_title, R.string.authentication_error_body) + } + } else if (status in 500..599) { + this.showConnectionProblemDialog(R.string.internal_error_api) + } else { + showConnectionProblemDialog(R.string.internal_error_api) + } + } else if (JsonSyntaxException::class.java.isAssignableFrom(throwableClass)) { + crashlyticsProxy.log("Json Error: " + lastAPICallURL + ", " + throwable.message) + } else { + crashlyticsProxy.logException(throwable) + } + } + + override fun getErrorResponse(throwable: HttpException): ErrorResponse { + val errorResponse = throwable.response().errorBody() ?: return ErrorResponse() + val errorConverter = gsonConverter + .responseBodyConverter(ErrorResponse::class.java, arrayOfNulls(0), retrofitAdapter) + return try { + errorConverter?.convert(errorResponse) as ErrorResponse + } catch (e: IOException) { + ErrorResponse() + } + + } + + override fun retrieveUser(withTasks: Boolean): Flowable { + + var userObservable = this.user + + if (withTasks) { + val tasksObservable = this.tasks + + userObservable = Flowable.zip(userObservable, tasksObservable, + BiFunction { habitRPGUser, tasks -> + habitRPGUser.tasks = tasks + habitRPGUser + }) + } + return userObservable + } + + override fun retrieveInboxMessages(): Flowable> { + return apiService.inboxMessages.compose(configureApiCallObserver()) + } + + override fun hasAuthenticationKeys(): Boolean { + return this.hostConfig.user != null + } + + private fun showConnectionProblemDialog(resourceMessageString: Int) { + showConnectionProblemDialog(R.string.network_error_title, resourceMessageString) + } + + private fun showConnectionProblemDialog(resourceTitleString: Int, resourceMessageString: Int) { + showConnectionProblemDialog(context.getString(resourceTitleString), context.getString(resourceMessageString)) + } + + private fun showConnectionProblemDialog(resourceTitleString: String, resourceMessageString: String) { + val event = ShowConnectionProblemEvent(resourceTitleString, resourceMessageString) + EventBus.getDefault().post(event) + if (BuildConfig.DEBUG) { + Log.d(TAG, "showConnectionProblemDialog: $resourceTitleString $resourceMessageString") + } + } + + /* + This function is used with Observer.compose to reuse transformers across the application. + See here for more info: http://blog.danlew.net/2015/03/02/dont-break-the-chain/ + */ + + override fun configureApiCallObserver(): FlowableTransformer, T> { + return apiCallTransformer as FlowableTransformer, T> + } + + override fun updateAuthenticationCredentials(userID: String?, apiToken: String?) { + this.hostConfig.user = userID + this.hostConfig.api = apiToken + crashlyticsProxy.setUserIdentifier(this.hostConfig.user) + crashlyticsProxy.setUserName(this.hostConfig.user) + Amplitude.getInstance().userId = this.hostConfig.user + } + + override fun setLanguageCode(languageCode: String) { + this.languageCode = languageCode + } + + override val status: Flowable + get() = apiService.status.compose(configureApiCallObserver()) + + override fun getContent(language: String): Flowable { + return apiService.getContent(language).compose(configureApiCallObserver()) + } + + override val user: Flowable + get() = apiService.user.compose(configureApiCallObserver()) + + override fun updateUser(updateDictionary: Map): Flowable { + return apiService.updateUser(updateDictionary).compose(configureApiCallObserver()) + } + + override fun registrationLanguage(registrationLanguage: String): Flowable { + return apiService.registrationLanguage(registrationLanguage).compose(configureApiCallObserver()) + } + + override fun retrieveInAppRewards(): Flowable> { + return apiService.retrieveInAppRewards().compose(configureApiCallObserver()) + } + + override fun retrieveOldGear(): Flowable> { + return apiService.retrieveOldGearRewards().compose(configureApiCallObserver()) + } + + override fun equipItem(type: String, itemKey: String): Flowable { + return apiService.equipItem(type, itemKey).compose(configureApiCallObserver()) + } + + override fun buyItem(itemKey: String): Flowable { + return apiService.buyItem(itemKey).compose(configureApiCallObserver()) + } + + override fun purchaseItem(type: String, itemKey: String): Flowable { + return apiService.purchaseItem(type, itemKey).compose(configureApiCallObserver()) + } + + override fun validateSubscription(request: SubscriptionValidationRequest): Flowable { + return apiService.validateSubscription(request).map { habitResponse -> + if (habitResponse.notifications != null) { + popupNotificationsManager.showNotificationDialog(habitResponse.notifications) + } + habitResponse.getData() + } + } + + override fun purchaseHourglassItem(type: String, itemKey: String): Flowable { + return apiService.purchaseHourglassItem(type, itemKey).compose(configureApiCallObserver()) + } + + override fun purchaseMysterySet(itemKey: String): Flowable { + return apiService.purchaseMysterySet(itemKey).compose(configureApiCallObserver()) + } + + override fun purchaseQuest(key: String): Flowable { + return apiService.purchaseQuest(key).compose(configureApiCallObserver()) + } + + override fun sellItem(itemType: String, itemKey: String): Flowable { + return apiService.sellItem(itemType, itemKey).compose(configureApiCallObserver()) + } + + override fun feedPet(petKey: String, foodKey: String): Flowable { + return apiService.feedPet(petKey, foodKey).compose(configureApiCallObserver()) + } + + override fun hatchPet(eggKey: String, hatchingPotionKey: String): Flowable { + return apiService.hatchPet(eggKey, hatchingPotionKey).compose(configureApiCallObserver()) + } + + override val tasks: Flowable + get() = apiService.tasks.compose(configureApiCallObserver()) + + override fun getTasks(type: String): Flowable { + return apiService.getTasks(type).compose(configureApiCallObserver()) + } + + + override fun getTasks(type: String, dueDate: String): Flowable { + return apiService.getTasks(type, dueDate).compose(configureApiCallObserver()) + } + + + override fun unlockPath(path: String): Flowable { + return apiService.unlockPath(path).compose(configureApiCallObserver()) + } + + override fun getTask(id: String): Flowable { + return apiService.getTask(id).compose(configureApiCallObserver()) + } + + override fun postTaskDirection(id: String, direction: String): Flowable { + return apiService.postTaskDirection(id, direction).compose(configureApiCallObserver()) + } + + override fun postTaskNewPosition(id: String, position: Int): Flowable> { + return apiService.postTaskNewPosition(id, position).compose(configureApiCallObserver()) + } + + override fun scoreChecklistItem(taskId: String, itemId: String): Flowable { + return apiService.scoreChecklistItem(taskId, itemId).compose(configureApiCallObserver()) + } + + override fun createTask(item: Task): Flowable { + return apiService.createTask(item).compose(configureApiCallObserver()) + } + + override fun createTasks(tasks: List): Flowable> { + return apiService.createTasks(tasks).compose(configureApiCallObserver()) + } + + override fun updateTask(id: String, item: Task): Flowable { + return apiService.updateTask(id, item).compose(configureApiCallObserver()) + } + + override fun deleteTask(id: String): Flowable { + return apiService.deleteTask(id).compose(configureApiCallObserver()) + } + + override fun createTag(tag: Tag): Flowable { + return apiService.createTag(tag).compose(configureApiCallObserver()) + } + + override fun updateTag(id: String, tag: Tag): Flowable { + return apiService.updateTag(id, tag).compose(configureApiCallObserver()) + } + + override fun deleteTag(id: String): Flowable { + return apiService.deleteTag(id).compose(configureApiCallObserver()) + } + + override fun sleep(): Flowable { + return apiService.sleep().compose(configureApiCallObserver()) + } + + override fun revive(): Flowable { + return apiService.revive().compose(configureApiCallObserver()) + } + + override fun useSkill(skillName: String, targetType: String, targetId: String): Flowable { + return apiService.useSkill(skillName, targetType, targetId).compose(configureApiCallObserver()) + } + + override fun useSkill(skillName: String, targetType: String): Flowable { + return apiService.useSkill(skillName, targetType).compose(configureApiCallObserver()) + } + + override fun changeClass(): Flowable { + return apiService.changeClass().compose(configureApiCallObserver()) + } + + override fun changeClass(className: String): Flowable { + return apiService.changeClass(className).compose(configureApiCallObserver()) + } + + override fun disableClasses(): Flowable { + return apiService.disableClasses().compose(configureApiCallObserver()) + } + + override fun markPrivateMessagesRead(): Flowable { + //This is necessary, because the API call returns weird data. + return apiService.markPrivateMessagesRead() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnError(this) + } + + override fun listGroups(type: String): Flowable> { + return apiService.listGroups(type).compose(configureApiCallObserver()) + } + + override fun getGroup(groupId: String): Flowable { + return apiService.getGroup(groupId).compose(configureApiCallObserver()) + } + + override fun updateGroup(id: String, item: Group): Flowable { + return apiService.updateGroup(id, item).compose(configureApiCallObserver()) + } + + override fun listGroupChat(groupId: String): Flowable> { + return apiService.listGroupChat(groupId).compose(configureApiCallObserver()) + } + + override fun joinGroup(groupId: String): Flowable { + return apiService.joinGroup(groupId).compose(configureApiCallObserver()) + } + + override fun leaveGroup(groupId: String): Flowable { + return apiService.leaveGroup(groupId).compose(configureApiCallObserver()) + } + + override fun postGroupChat(groupId: String, message: Map): Flowable { + return apiService.postGroupChat(groupId, message).compose(configureApiCallObserver()) + } + + override fun deleteMessage(groupId: String, messageId: String): Flowable { + return apiService.deleteMessage(groupId, messageId).compose(configureApiCallObserver()) + } + + override fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?): Flowable> { + return apiService.getGroupMembers(groupId, includeAllPublicFields).compose(configureApiCallObserver()) + } + + override fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?, lastId: String): Flowable> { + return apiService.getGroupMembers(groupId, includeAllPublicFields, lastId).compose(configureApiCallObserver()) + } + + override fun likeMessage(groupId: String, mid: String): Flowable { + return apiService.likeMessage(groupId, mid).compose(configureApiCallObserver()) + } + + override fun flagMessage(groupId: String, mid: String): Flowable { + return apiService.flagMessage(groupId, mid).compose(configureApiCallObserver()) + } + + override fun seenMessages(groupId: String): Flowable { + return apiService.seenMessages(groupId).compose(configureApiCallObserver()) + } + + override fun inviteToGroup(groupId: String, inviteData: Map): Flowable> { + return apiService.inviteToGroup(groupId, inviteData).compose(configureApiCallObserver()) + } + + override fun rejectGroupInvite(groupId: String): Flowable { + return apiService.rejectGroupInvite(groupId).compose(configureApiCallObserver()) + } + + override fun acceptQuest(groupId: String): Flowable { + return apiService.acceptQuest(groupId).compose(configureApiCallObserver()) + } + + override fun rejectQuest(groupId: String): Flowable { + return apiService.rejectQuest(groupId).compose(configureApiCallObserver()) + } + + override fun cancelQuest(groupId: String): Flowable { + return apiService.cancelQuest(groupId).compose(configureApiCallObserver()) + } + + override fun forceStartQuest(groupId: String, group: Group): Flowable { + return apiService.forceStartQuest(groupId, group).compose(configureApiCallObserver()) + } + + override fun inviteToQuest(groupId: String, questKey: String): Flowable { + return apiService.inviteToQuest(groupId, questKey).compose(configureApiCallObserver()) + } + + override fun abortQuest(groupId: String): Flowable { + return apiService.abortQuest(groupId).compose(configureApiCallObserver()) + } + + override fun leaveQuest(groupId: String): Flowable { + return apiService.leaveQuest(groupId).compose(configureApiCallObserver()) + } + + override fun validatePurchase(request: PurchaseValidationRequest): Flowable { + return apiService.validatePurchase(request).map { habitResponse -> + if (habitResponse.notifications != null) { + popupNotificationsManager.showNotificationDialog(habitResponse.notifications) + } + habitResponse.getData() + } + } + + override fun changeCustomDayStart(updateObject: Map): Flowable { + return apiService.changeCustomDayStart(updateObject).compose(configureApiCallObserver()) + } + + override fun getMember(memberId: String): Flowable { + return apiService.getMember(memberId).compose(configureApiCallObserver()) + } + + override fun getMemberAchievements(memberId: String): Flowable { + return apiService.getMemberAchievements(memberId).compose(configureApiCallObserver()) + } + + override fun postPrivateMessage(messageDetails: Map): Flowable { + return apiService.postPrivateMessage(messageDetails).compose(configureApiCallObserver()) + } + + override fun retrieveShopIventory(identifier: String): Flowable { + return apiService.retrieveShopInventory(identifier).compose(configureApiCallObserver()) + } + + override fun addPushDevice(pushDeviceData: Map): Flowable> { + return apiService.addPushDevice(pushDeviceData).compose(configureApiCallObserver()) + } + + override fun deletePushDevice(regId: String): Flowable> { + return apiService.deletePushDevice(regId).compose(configureApiCallObserver()) + } + + override val userChallenges: Flowable> + get() = apiService.userChallenges.compose(configureApiCallObserver()) + + override fun getChallengeTasks(challengeId: String): Flowable { + return apiService.getChallengeTasks(challengeId).compose(configureApiCallObserver()) + } + + override fun getChallenge(challengeId: String): Flowable { + return apiService.getChallenge(challengeId).compose(configureApiCallObserver()) + } + + override fun joinChallenge(challengeId: String): Flowable { + return apiService.joinChallenge(challengeId).compose(configureApiCallObserver()) + } + + override fun leaveChallenge(challengeId: String, body: LeaveChallengeBody): Flowable { + return apiService.leaveChallenge(challengeId, body).compose(configureApiCallObserver()) + } + + + override fun createChallenge(challenge: Challenge): Flowable { + return apiService.createChallenge(challenge).compose(configureApiCallObserver()) + } + + override fun createChallengeTasks(challengeId: String, tasks: List): Flowable> { + return apiService.createChallengeTasks(challengeId, tasks).compose(configureApiCallObserver()) + } + + override fun updateChallenge(challenge: Challenge): Flowable { + return apiService.updateChallenge(challenge.id, challenge).compose(configureApiCallObserver()) + } + + override fun deleteChallenge(challengeId: String): Flowable { + return apiService.deleteChallenge(challengeId).compose(configureApiCallObserver()) + } + + override fun debugAddTenGems(): Flowable { + return apiService.debugAddTenGems().compose(configureApiCallObserver()) + } + + override fun readNotification(notificationId: String): Flowable> { + return apiService.readNotification(notificationId).compose(configureApiCallObserver()) + } + + override val content: Flowable + get() = apiService.getContent(languageCode).compose(configureApiCallObserver()) + + override fun openMysteryItem(): Flowable { + return apiService.openMysteryItem().compose(configureApiCallObserver()) + } + + override fun runCron(): Flowable { + return apiService.runCron().compose(configureApiCallObserver()) + } + + override fun resetAccount(): Flowable { + return apiService.resetAccount().compose(configureApiCallObserver()) + } + + override fun deleteAccount(password: String): Flowable { + val updateObject = HashMap() + updateObject["password"] = password + return apiService.deleteAccount(updateObject).compose(configureApiCallObserver()) + } + + override fun togglePinnedItem(pinType: String, path: String): Flowable { + return apiService.togglePinnedItem(pinType, path).compose(configureApiCallObserver()) + } + + override fun sendPasswordResetEmail(email: String): Flowable { + val data = HashMap() + data["email"] = email + return apiService.sendPasswordResetEmail(data).compose(configureApiCallObserver()) + } + + override fun updateLoginName(newLoginName: String, password: String): Flowable { + val updateObject = HashMap() + updateObject["username"] = newLoginName + updateObject["password"] = password + return apiService.updateLoginName(updateObject).compose(configureApiCallObserver()) + } + + override fun updateEmail(newEmail: String, password: String): Flowable { + val updateObject = HashMap() + updateObject["newEmail"] = newEmail + updateObject["password"] = password + return apiService.updateEmail(updateObject).compose(configureApiCallObserver()) + } + + override fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable { + val updateObject = HashMap() + updateObject["newPassword"] = newPassword + updateObject["password"] = oldPassword + updateObject["confirmPassowrd"] = oldPasswordConfirmation + return apiService.updatePassword(updateObject).compose(configureApiCallObserver()) + } + + override fun allocatePoint(stat: String): Flowable { + return apiService.allocatePoint(stat).compose(configureApiCallObserver()) + } + + override fun bulkAllocatePoints(strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable { + val body = HashMap>() + val stats = HashMap() + stats["str"] = strength + stats["int"] = intelligence + stats["con"] = constitution + stats["per"] = perception + body["stats"] = stats + return apiService.bulkAllocatePoints(body).compose(configureApiCallObserver()) + } + + override fun retrieveMarketGear(): Flowable { + return apiService.retrieveMarketGear().compose(configureApiCallObserver()) + } + + override val worldState: Flowable + get() = apiService.worldState.compose(configureApiCallObserver()) + + companion object { + private const val TAG = "ApiClientImpl" + + fun createGsonFactory(): GsonConverterFactory { + val taskTagClassListType = object : TypeToken>() { + + }.type + val skillListType = object : TypeToken>() { + + }.type + val customizationListType = object : TypeToken>() { + + }.type + val tutorialStepListType = object : TypeToken>() { + + }.type + val faqArticleListType = object : TypeToken>() { + + }.type + val itemDataListType = object : TypeToken>() { + + }.type + val eggListType = object : TypeToken>() { + + }.type + val foodListType = object : TypeToken>() { + + }.type + val hatchingPotionListType = object : TypeToken>() { + + }.type + val questContentListType = object : TypeToken>() { + + }.type + val petMapType = object : TypeToken>() { + + }.type + val mountMapType = object : TypeToken>() { + + }.type + val petListType = object : TypeToken>() { + + }.type + val mountListType = object : TypeToken>() { + + }.type + val questCollectListType = object : TypeToken>() { + + }.type + val chatMessageListType = object : TypeToken>() { + + }.type + val challengeListType = object : TypeToken>() { + + }.type + val challengeRealmListType = object : TypeToken>() { + + }.type + val questDropItemListType = object : TypeToken>() { + + }.type + + //Exclusion strategy needed for DBFlow https://github.com/Raizlabs/DBFlow/issues/121 + val gson = GsonBuilder() + .registerTypeAdapter(taskTagClassListType, TaskTagDeserializer()) + .registerTypeAdapter(Boolean::class.java, BooleanAsIntAdapter()) + .registerTypeAdapter(Boolean::class.javaPrimitiveType, BooleanAsIntAdapter()) + .registerTypeAdapter(skillListType, SkillDeserializer()) + .registerTypeAdapter(TaskList::class.java, TaskListDeserializer()) + .registerTypeAdapter(Purchases::class.java, PurchasedDeserializer()) + .registerTypeAdapter(customizationListType, CustomizationDeserializer()) + .registerTypeAdapter(tutorialStepListType, TutorialStepListDeserializer()) + .registerTypeAdapter(faqArticleListType, FAQArticleListDeserilializer()) + .registerTypeAdapter(Group::class.java, GroupSerialization()) + .registerTypeAdapter(Date::class.java, DateDeserializer()) + .registerTypeAdapter(itemDataListType, EquipmentListDeserializer()) + .registerTypeAdapter(eggListType, EggListDeserializer()) + .registerTypeAdapter(foodListType, FoodListDeserializer()) + .registerTypeAdapter(hatchingPotionListType, HatchingPotionListDeserializer()) + .registerTypeAdapter(questContentListType, QuestListDeserializer()) + .registerTypeAdapter(petListType, PetListDeserializer()) + .registerTypeAdapter(mountListType, MountListDeserializer()) + .registerTypeAdapter(petMapType, PetMapDeserializer()) + .registerTypeAdapter(mountMapType, MountMapDeserializer()) + .registerTypeAdapter(ChatMessage::class.java, ChatMessageDeserializer()) + .registerTypeAdapter(Task::class.java, TaskSerializer()) + .registerTypeAdapter(ContentResult::class.java, ContentDeserializer()) + .registerTypeAdapter(FeedResponse::class.java, FeedResponseDeserializer()) + .registerTypeAdapter(Challenge::class.java, ChallengeDeserializer()) + .registerTypeAdapter(User::class.java, UserDeserializer()) + .registerTypeAdapter(questCollectListType, QuestCollectDeserializer()) + .registerTypeAdapter(chatMessageListType, ChatMessageListDeserializer()) + .registerTypeAdapter(challengeListType, ChallengeListDeserializer()) + .registerTypeAdapter(challengeRealmListType, ChallengeListDeserializer()) + .registerTypeAdapter(questDropItemListType, QuestDropItemsListSerialization()) + .registerTypeAdapter(Quest::class.java, QuestDeserializer()) + .registerTypeAdapter(Member::class.java, MemberSerialization()) + .registerTypeAdapter(WorldState::class.java, WorldStateSerialization()) + .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + .create() + return GsonConverterFactory.create(gson) + } + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/BaseRepositoryImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/BaseRepositoryImpl.java deleted file mode 100644 index cc131f29a..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/BaseRepositoryImpl.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.habitrpg.android.habitica.data.implementation; - -import com.habitrpg.android.habitica.data.ApiClient; -import com.habitrpg.android.habitica.data.BaseRepository; -import com.habitrpg.android.habitica.data.local.BaseLocalRepository; - -import java.util.List; - -import io.realm.RealmObject; - -public abstract class BaseRepositoryImpl implements BaseRepository { - - protected final T localRepository; - protected final ApiClient apiClient; - - public BaseRepositoryImpl(T localRepository, ApiClient apiClient) { - this.localRepository = localRepository; - this.apiClient = apiClient; - } - - public void close() { - this.localRepository.close(); - } - - @Override - public List getUnmanagedCopy(List list) { - return localRepository.getUnmanagedCopy(list); - } - - @Override - public boolean isClosed() { - return localRepository.isClosed(); - } - - @Override - public T getUnmanagedCopy(T object) { - return localRepository.getUnmanagedCopy(object); - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/BaseRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/BaseRepositoryImpl.kt new file mode 100644 index 000000000..c6f7819df --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/BaseRepositoryImpl.kt @@ -0,0 +1,25 @@ +package com.habitrpg.android.habitica.data.implementation + +import com.habitrpg.android.habitica.data.ApiClient +import com.habitrpg.android.habitica.data.BaseRepository +import com.habitrpg.android.habitica.data.local.BaseLocalRepository + +import io.realm.RealmObject + +abstract class BaseRepositoryImpl(protected val localRepository: T, protected val apiClient: ApiClient) : BaseRepository { + + override fun close() { + this.localRepository.close() + } + + override fun getUnmanagedCopy(list: List): List { + return localRepository.getUnmanagedCopy(list) + } + + override val isClosed: Boolean + get() = localRepository.isClosed + + override fun getUnmanagedCopy(obj: T): T { + return localRepository.getUnmanagedCopy(obj) + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.java deleted file mode 100644 index 04860d10b..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.habitrpg.android.habitica.data.implementation; - -import com.github.underscore.U; -import com.habitrpg.android.habitica.data.ApiClient; -import com.habitrpg.android.habitica.data.ChallengeRepository; -import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository; -import com.habitrpg.android.habitica.models.LeaveChallengeBody; -import com.habitrpg.android.habitica.models.social.Challenge; -import com.habitrpg.android.habitica.models.tasks.Task; -import com.habitrpg.android.habitica.models.tasks.TaskList; -import com.habitrpg.android.habitica.models.tasks.TasksOrder; -import com.habitrpg.android.habitica.models.user.User; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import io.realm.RealmResults; -import rx.Observable; -import rx.schedulers.Schedulers; - - -public class ChallengeRepositoryImpl extends BaseRepositoryImpl implements ChallengeRepository { - - public ChallengeRepositoryImpl(ChallengeLocalRepository localRepository, ApiClient apiClient) { - super(localRepository, apiClient); - } - - @Override - public Observable getChallenge(String challengeId) { - return apiClient.getChallenge(challengeId); - } - - @Override - public Observable getChallengeTasks(String challengeId) { - return apiClient.getChallengeTasks(challengeId); - } - - - private TasksOrder getTaskOrders(List taskList) { - Map> stringListMap = U.groupBy(taskList, t -> t.getType()); - - TasksOrder tasksOrder = new TasksOrder(); - - for (Map.Entry> entry : stringListMap.entrySet()) { - List taskIdList = U.map(entry.getValue(), t -> t.getId()); - - switch (entry.getKey()) { - case Task.TYPE_HABIT: - tasksOrder.setHabits(taskIdList); - break; - case Task.TYPE_DAILY: - tasksOrder.setDailys(taskIdList); - break; - case Task.TYPE_TODO: - tasksOrder.setTodos(taskIdList); - break; - case Task.TYPE_REWARD: - tasksOrder.setRewards(taskIdList); - break; - } - } - - return tasksOrder; - } - - private Observable> addChallengeTasks(String challengeId, List addedTaskList) { - return apiClient.createChallengeTasks(challengeId, addedTaskList); - } - - @Override - public Observable createChallenge(Challenge challenge, List taskList) { - challenge.tasksOrder = getTaskOrders(taskList); - - return Observable.create(subscriber -> { - apiClient.createChallenge(challenge).subscribe(challenge1 -> { - addChallengeTasks(challenge1.id, taskList).subscribe(task -> { - subscriber.onNext(challenge1); - subscriber.onCompleted(); - }, subscriber::onError); - - }, subscriber::onError); - }); - } - - @Override - public Observable updateChallenge(Challenge challenge, List fullTaskList, - List addedTaskList, List updatedTaskList, List removedTaskList) { - - ArrayList observablesToWait = new ArrayList<>(U.map(updatedTaskList, t -> apiClient.updateTask(t.getId(), t))); - observablesToWait.addAll(U.map(removedTaskList, apiClient::deleteTask)); - - if (addedTaskList.size() != 0) { - observablesToWait.add(addChallengeTasks(challenge.id, addedTaskList)); - } - - challenge.tasksOrder = getTaskOrders(fullTaskList); - - return Observable.from(observablesToWait) - .flatMap(task -> task.subscribeOn(Schedulers.computation())) - .toList() - .flatMap(tasks -> apiClient.updateChallenge(challenge)); - } - - @Override - public Observable deleteChallenge(String challengeId) { - return apiClient.deleteChallenge(challengeId); - } - - @Override - public Observable> getChallenges() { - return localRepository.getChallenges(); - } - - @Override - public Observable> getUserChallenges(String userId) { - return localRepository.getUserChallenges(userId); - } - - @Override - public Observable> retrieveChallenges(User user) { - return apiClient.getUserChallenges() - .doOnNext(localRepository::saveChallenges); - } - - @Override - public Observable leaveChallenge(Challenge challenge, LeaveChallengeBody leaveChallengeBody) { - if (challenge == null) { - return Observable.just(null); - } - return apiClient.leaveChallenge(challenge.id, leaveChallengeBody) - .doOnNext(aVoid -> localRepository.setParticipating(challenge, false)); - } - - @Override - public Observable joinChallenge(Challenge challenge) { - if (challenge == null) { - return Observable.just(null); - } - return apiClient.joinChallenge(challenge.id) - .doOnNext(aVoid -> localRepository.setParticipating(challenge, true)); - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt new file mode 100644 index 000000000..c891f1e7e --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt @@ -0,0 +1,111 @@ +package com.habitrpg.android.habitica.data.implementation + +import com.github.underscore.U +import com.habitrpg.android.habitica.data.ApiClient +import com.habitrpg.android.habitica.data.ChallengeRepository +import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository +import com.habitrpg.android.habitica.models.LeaveChallengeBody +import com.habitrpg.android.habitica.models.social.Challenge +import com.habitrpg.android.habitica.models.tasks.Task +import com.habitrpg.android.habitica.models.tasks.TaskList +import com.habitrpg.android.habitica.models.tasks.TasksOrder +import com.habitrpg.android.habitica.models.user.User +import io.reactivex.Flowable +import io.realm.RealmResults +import java.util.* + + +class ChallengeRepositoryImpl(localRepository: ChallengeLocalRepository, apiClient: ApiClient) : BaseRepositoryImpl(localRepository, apiClient), ChallengeRepository { + + override fun getChallenge(challengeId: String): Flowable { + return apiClient.getChallenge(challengeId) + } + + override fun getChallengeTasks(challengeId: String): Flowable { + return apiClient.getChallengeTasks(challengeId) + } + + + private fun getTaskOrders(taskList: List): TasksOrder { + val stringListMap = U.groupBy(taskList) { t -> t.type } + + val tasksOrder = TasksOrder() + + for ((key, value) in stringListMap) { + val taskIdList = U.map(value) { t -> t.id } + + when (key) { + Task.TYPE_HABIT -> tasksOrder.habits = taskIdList + Task.TYPE_DAILY -> tasksOrder.dailys = taskIdList + Task.TYPE_TODO -> tasksOrder.todos = taskIdList + Task.TYPE_REWARD -> tasksOrder.rewards = taskIdList + } + } + + return tasksOrder + } + + private fun addChallengeTasks(challenge: Challenge, addedTaskList: List): Flowable { + return apiClient.createChallengeTasks(challenge.id, addedTaskList).map { challenge } + } + + override fun createChallenge(challenge: Challenge, taskList: List): Flowable { + challenge.tasksOrder = getTaskOrders(taskList) + + return apiClient.createChallenge(challenge).flatMap { + addChallengeTasks(it, taskList) + } + } + + override fun updateChallenge(challenge: Challenge, fullTaskList: List, + addedTaskList: List, updatedTaskList: List, removedTaskList: List): Flowable { + + var flowable: Flowable<*> = Flowable.just("") + + updatedTaskList.forEach { task -> + flowable = flowable.flatMap { apiClient.updateTask(task.id ?: "", task) } + } + + removedTaskList.forEach { task -> + flowable = flowable.flatMap { apiClient.deleteTask(task) } + } + if (addedTaskList.isNotEmpty()) { + flowable = flowable.flatMap { addChallengeTasks(challenge, addedTaskList) } + } + + challenge.tasksOrder = getTaskOrders(fullTaskList) + + return flowable.flatMap { apiClient.updateChallenge(challenge) } + } + + override fun deleteChallenge(challengeId: String): Flowable { + return apiClient.deleteChallenge(challengeId) + } + + override fun getChallenges(): Flowable> { + return localRepository.challenges + } + + override fun getUserChallenges(userId: String): Flowable> { + return localRepository.getUserChallenges(userId) + } + + override fun retrieveChallenges(user: User): Flowable> { + return apiClient.userChallenges + .doOnNext { localRepository.saveChallenges(it) } + } + + override fun leaveChallenge(challenge: Challenge?, leaveChallengeBody: LeaveChallengeBody): Flowable { + return if (challenge == null) { + Flowable.empty() + } else apiClient.leaveChallenge(challenge.id, leaveChallengeBody) + .doOnNext { localRepository.setParticipating(challenge, false) } + } + + override fun joinChallenge(challenge: Challenge?): Flowable { + return if (challenge == null) { + Flowable.empty() + } else apiClient.joinChallenge(challenge.id) + .doOnNext { localRepository.setParticipating(challenge, true) } + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ContentRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ContentRepositoryImpl.kt index d8ad96d3a..b0047ad5e 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ContentRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ContentRepositoryImpl.kt @@ -5,38 +5,35 @@ import com.habitrpg.android.habitica.data.ContentRepository import com.habitrpg.android.habitica.data.local.ContentLocalRepository import com.habitrpg.android.habitica.models.ContentResult import com.habitrpg.android.habitica.models.WorldState - -import java.util.Date - -import rx.Observable -import rx.functions.Action1 +import io.reactivex.Flowable +import java.util.* abstract class ContentRepositoryImpl(localRepository: T, apiClient: ApiClient) : BaseRepositoryImpl(localRepository, apiClient), ContentRepository { private var lastContentSync = 0L private var lastWorldStateSync = 0L - override fun retrieveContent(): Observable { + override fun retrieveContent(): Flowable { return retrieveContent(false) } - override fun retrieveContent(forced: Boolean): Observable { + override fun retrieveContent(forced: Boolean): Flowable { val now = Date().time return if (forced || now - this.lastContentSync > 3600000) { lastContentSync = now - apiClient.getContent().doOnNext({ localRepository.saveContent(it) }) + apiClient.content.doOnNext({ localRepository.saveContent(it) }) } else { - Observable.just(null) + Flowable.empty() } } - override fun retrieveWorldState(): Observable { + override fun retrieveWorldState(): Flowable { val now = Date().time return if (now - this.lastWorldStateSync > 3600000) { lastWorldStateSync = now - apiClient.getWorldState().doOnNext({ localRepository.saveWorldState(it) }) + apiClient.worldState.doOnNext({ localRepository.saveWorldState(it) }) } else { - Observable.just(null) + Flowable.empty() } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/CustomizationRepositoryImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/CustomizationRepositoryImpl.java deleted file mode 100644 index 070e1e72f..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/CustomizationRepositoryImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.habitrpg.android.habitica.data.implementation; - -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.realm.RealmResults; -import rx.Observable; - -public class CustomizationRepositoryImpl extends ContentRepositoryImpl implements CustomizationRepository { - - public CustomizationRepositoryImpl(CustomizationLocalRepository localRepository, ApiClient apiClient) { - super(localRepository, apiClient); - } - - @Override - public Observable> getCustomizations(String type, String category, boolean onlyAvailable) { - return localRepository.getCustomizations(type, category, onlyAvailable); - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/CustomizationRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/CustomizationRepositoryImpl.kt new file mode 100644 index 000000000..50fb78540 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/CustomizationRepositoryImpl.kt @@ -0,0 +1,16 @@ +package com.habitrpg.android.habitica.data.implementation + +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.Flowable +import io.realm.RealmResults + +class CustomizationRepositoryImpl(localRepository: CustomizationLocalRepository, apiClient: ApiClient) : ContentRepositoryImpl(localRepository, apiClient), CustomizationRepository { + + override fun getCustomizations(type: String, category: String, onlyAvailable: Boolean): Flowable> { + return localRepository.getCustomizations(type, category, onlyAvailable) + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/FAQRepositoryImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/FAQRepositoryImpl.java deleted file mode 100644 index 2f0a0f6d7..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/FAQRepositoryImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.habitrpg.android.habitica.data.implementation; - -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.realm.RealmResults; -import rx.Observable; - - -public class FAQRepositoryImpl extends ContentRepositoryImpl implements FAQRepository { - public FAQRepositoryImpl(FAQLocalRepository localRepository, ApiClient apiClient) { - super(localRepository, apiClient); - } - - @Override - public Observable> getArticles() { - return localRepository.getArticles(); - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/FAQRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/FAQRepositoryImpl.kt new file mode 100644 index 000000000..70de3cbe6 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/FAQRepositoryImpl.kt @@ -0,0 +1,17 @@ +package com.habitrpg.android.habitica.data.implementation + +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.Flowable +import io.realm.RealmResults + + +class FAQRepositoryImpl(localRepository: FAQLocalRepository, apiClient: ApiClient) : ContentRepositoryImpl(localRepository, apiClient), FAQRepository { + + override fun getArticles(): Flowable> { + return localRepository.articles + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt index da7687265..22ba97ede 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt @@ -3,7 +3,6 @@ package com.habitrpg.android.habitica.data.implementation import com.habitrpg.android.habitica.data.ApiClient import com.habitrpg.android.habitica.data.InventoryRepository import com.habitrpg.android.habitica.data.local.InventoryLocalRepository -import com.habitrpg.android.habitica.helpers.RemoteConfigManager import com.habitrpg.android.habitica.models.inventory.* import com.habitrpg.android.habitica.models.responses.BuyResponse import com.habitrpg.android.habitica.models.responses.FeedResponse @@ -11,17 +10,16 @@ import com.habitrpg.android.habitica.models.shops.Shop import com.habitrpg.android.habitica.models.shops.ShopItem import com.habitrpg.android.habitica.models.user.Items import com.habitrpg.android.habitica.models.user.User +import io.reactivex.Flowable import io.realm.RealmResults -import rx.Observable -import java.util.* -class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClient: ApiClient, private val remoteConfigManager: RemoteConfigManager) : ContentRepositoryImpl(localRepository, apiClient), InventoryRepository { +class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClient: ApiClient) : ContentRepositoryImpl(localRepository, apiClient), InventoryRepository { - override fun getQuestContent(key: String): Observable { + override fun getQuestContent(key: String): Flowable { return localRepository.getQuestContent(key) } - override fun getItems(searchedKeys: List): Observable> { + override fun getItems(searchedKeys: List): Flowable> { return localRepository.getEquipment(searchedKeys) } @@ -29,75 +27,35 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie return localRepository.getArmoireRemainingCount() } - override fun getInAppRewards(): Observable> { + override fun getInAppRewards(): Flowable> { return localRepository.getInAppRewards() } - override fun retrieveInAppRewards(): Observable> { - return if (remoteConfigManager.newShopsEnabled()!!) { - apiClient.retrieveInAppRewards() - .doOnNext({ localRepository.saveInAppRewards(it) }) - } else { - apiClient.retrieveOldGear() - .map> { items -> - val itemKeys = ArrayList() - for (item in items) { - itemKeys.add(item.key) - } - itemKeys.add("potion") - itemKeys.add("armoire") - itemKeys - } - .flatMap>({ this.getItems(it) }) - .map> { items -> - val buyableItems = ArrayList() - if (items != null) { - for (item in items) { - val shopItem = ShopItem() - shopItem.key = item.key ?: "" - shopItem.text = item.text - shopItem.notes = item.notes - shopItem.value = item.value.toInt() - shopItem.currency = "gold" - if ("potion" == item.key) { - shopItem.purchaseType = "potion" - } else if ("armoire" == item.key) { - shopItem.purchaseType = "armoire" - } else { - shopItem.purchaseType = "gear" - } - - buyableItems.add(shopItem) - } - } - buyableItems - } - .doOnNext({ localRepository.saveInAppRewards(it) }) - .first() - } + override fun retrieveInAppRewards(): Flowable> { + return apiClient.retrieveInAppRewards().doOnNext { localRepository.saveInAppRewards(it) } } - override fun getOwnedEquipment(type: String): Observable> { + override fun getOwnedEquipment(type: String): Flowable> { return localRepository.getOwnedEquipment(type) } - override fun getOwnedEquipment(): Observable> { + override fun getOwnedEquipment(): Flowable> { return localRepository.getOwnedEquipment() } - override fun getOwnedItems(itemClass: Class, user: User?): Observable> { + override fun getOwnedItems(itemClass: Class, user: User?): Flowable> { return localRepository.getOwnedItems(itemClass, user) } - override fun getOwnedItems(user: User): Observable> { + override fun getOwnedItems(user: User): Flowable> { return localRepository.getOwnedItems(user) } - override fun getEquipment(key: String): Observable { + override fun getEquipment(key: String): Flowable { return localRepository.getEquipment(key) } - override fun openMysteryItem(user: User): Observable { + override fun openMysteryItem(user: User): Flowable { return apiClient.openMysteryItem().doOnNext { itemData -> itemData.owned = true localRepository.save(itemData) @@ -109,35 +67,35 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie localRepository.save(equipment) } - override fun getMounts(): Observable> { + override fun getMounts(): Flowable> { return localRepository.getMounts() } - override fun getMounts(type: String, group: String): Observable> { + override fun getMounts(type: String, group: String): Flowable> { return localRepository.getMounts(type, group) } - override fun getOwnedMounts(): Observable> { + override fun getOwnedMounts(): Flowable> { return localRepository.getOwnedMounts() } - override fun getOwnedMounts(animalType: String, animalGroup: String): Observable> { + override fun getOwnedMounts(animalType: String, animalGroup: String): Flowable> { return localRepository.getOwnedMounts(animalType, animalGroup) } - override fun getPets(): Observable> { + override fun getPets(): Flowable> { return localRepository.getPets() } - override fun getPets(type: String, group: String): Observable> { + override fun getPets(type: String, group: String): Flowable> { return localRepository.getPets(type, group) } - override fun getOwnedPets(): Observable> { + override fun getOwnedPets(): Flowable> { return localRepository.getOwnedPets() } - override fun getOwnedPets(type: String, group: String): Observable> { + override fun getOwnedPets(type: String, group: String): Flowable> { return localRepository.getOwnedPets(type, group) } @@ -149,12 +107,12 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie localRepository.changeOwnedCount(type, key, amountToAdd) } - override fun sellItem(user: User, type: String, key: String): Observable { + override fun sellItem(user: User, type: String, key: String): Flowable { return localRepository.getItem(type, key) .flatMap { item -> sellItem(user, item) } } - override fun sellItem(user: User?, item: Item): Observable { + override fun sellItem(user: User?, item: Item): Flowable { return apiClient.sellItem(item.type, item.key) .map { user1 -> localRepository.executeTransaction { realm -> @@ -177,11 +135,11 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie } } - override fun equipGear(user: User, key: String, asCostume: Boolean): Observable { + override fun equipGear(user: User, key: String, asCostume: Boolean): Flowable { return equip(user, if (asCostume) "costume" else "equipped", key) } - override fun equip(user: User?, type: String, key: String): Observable { + override fun equip(user: User?, type: String, key: String): Flowable { return apiClient.equipItem(type, key) .doOnNext { items -> if (user == null) { @@ -201,7 +159,7 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie } } - override fun feedPet(pet: Pet, food: Food): Observable { + override fun feedPet(pet: Pet, food: Food): Flowable { return apiClient.feedPet(pet.key, food.key) .doOnNext { feedResponse -> localRepository.changeOwnedCount(food, -1) @@ -209,7 +167,7 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie } } - override fun hatchPet(egg: Egg, hatchingPotion: HatchingPotion): Observable { + override fun hatchPet(egg: Egg, hatchingPotion: HatchingPotion): Flowable { return apiClient.hatchPet(egg.key, hatchingPotion.key) .doOnNext { localRepository.changeOwnedCount(egg, -1) @@ -218,12 +176,12 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie } } - override fun inviteToQuest(quest: QuestContent): Observable { + override fun inviteToQuest(quest: QuestContent): Flowable { return apiClient.inviteToQuest("party", quest.key) .doOnNext { localRepository.changeOwnedCount(quest, -1) } } - override fun buyItem(user: User, key: String, value: Double): Observable { + override fun buyItem(user: User, key: String, value: Double): Flowable { return apiClient.buyItem(key) .doOnNext { buyResponse -> val copiedUser = localRepository.getUnmanagedCopy(user) @@ -252,33 +210,33 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie } } - override fun retrieveShopInventory(identifier: String): Observable { + override fun retrieveShopInventory(identifier: String): Flowable { return apiClient.retrieveShopIventory(identifier) } - override fun retrieveMarketGear(): Observable { + override fun retrieveMarketGear(): Flowable { return apiClient.retrieveMarketGear() } - override fun purchaseMysterySet(categoryIdentifier: String): Observable { + override fun purchaseMysterySet(categoryIdentifier: String): Flowable { return apiClient.purchaseMysterySet(categoryIdentifier) } - override fun purchaseHourglassItem(purchaseType: String, key: String): Observable { + override fun purchaseHourglassItem(purchaseType: String, key: String): Flowable { return apiClient.purchaseHourglassItem(purchaseType, key) } - override fun purchaseQuest(key: String): Observable { + override fun purchaseQuest(key: String): Flowable { return apiClient.purchaseQuest(key) } - override fun purchaseItem(purchaseType: String, key: String): Observable { + override fun purchaseItem(purchaseType: String, key: String): Flowable { return apiClient.purchaseItem(purchaseType, key) } - override fun togglePinnedItem(item: ShopItem): Observable> { + override fun togglePinnedItem(item: ShopItem): Flowable> { return if (!item.isValid) { - Observable.just(null) + Flowable.empty() } else apiClient.togglePinnedItem(item.pinType ?: "", item.path ?: "") .flatMap { retrieveInAppRewards() } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.java deleted file mode 100644 index db9d6a115..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.habitrpg.android.habitica.data.implementation; - -import android.content.Context; - -import com.habitrpg.android.habitica.R; -import com.habitrpg.android.habitica.data.SetupCustomizationRepository; -import com.habitrpg.android.habitica.models.SetupCustomization; -import com.habitrpg.android.habitica.models.user.User; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.inject.Inject; - - -public class SetupCustomizationRepositoryImpl implements SetupCustomizationRepository { - - private final Context context; - - @Inject - public SetupCustomizationRepositoryImpl(Context context) { - this.context = context; - } - - @Override - public List getCustomizations(String category, User user) { - return getCustomizations(category, null, user); - } - - @Override - public List getCustomizations(String category, String subcategory, User user) { - switch (category) { - case "body": { - switch (subcategory) { - case "size": - return getSizes(); - case "shirt": - return getShirts(user.getPreferences().getSize()); - } - } - case "skin": - return getSkins(); - case "hair": { - switch (subcategory) { - case "bangs": - return getBangs(user.getPreferences().getHair().getColor()); - case "ponytail": - return getHairBases(user.getPreferences().getHair().getColor()); - case "color": - return getHairColors(); - } - } - case "extras": { - switch (subcategory) { - case "flower": - return getFlowers(); - case "glasses": - return getGlasses(); - case "wheelchair": - return getWheelchairs(); - } - } - } - return new ArrayList<>(); - } - - private List getWheelchairs() { - return Arrays.asList( - SetupCustomization.Companion.createWheelchair("none", 0), - SetupCustomization.Companion.createWheelchair("black", R.drawable.creator_chair_black), - SetupCustomization.Companion.createWheelchair("blue", R.drawable.creator_chair_blue), - SetupCustomization.Companion.createWheelchair("green", R.drawable.creator_chair_green), - SetupCustomization.Companion.createWheelchair("pink", R.drawable.creator_chair_pink), - SetupCustomization.Companion.createWheelchair("red", R.drawable.creator_chair_red), - SetupCustomization.Companion.createWheelchair("yellow", R.drawable.creator_chair_yellow) - ); - } - - private List getGlasses() { - return Arrays.asList( - SetupCustomization.Companion.createGlasses("", R.drawable.creator_blank_face), - SetupCustomization.Companion.createGlasses("eyewear_special_blackTopFrame", R.drawable.creator_eyewear_special_blacktopframe), - SetupCustomization.Companion.createGlasses("eyewear_special_blueTopFrame", R.drawable.creator_eyewear_special_bluetopframe), - SetupCustomization.Companion.createGlasses("eyewear_special_greenTopFrame", R.drawable.creator_eyewear_special_greentopframe), - SetupCustomization.Companion.createGlasses("eyewear_special_pinkTopFrame", R.drawable.creator_eyewear_special_pinktopframe), - SetupCustomization.Companion.createGlasses("eyewear_special_redTopFrame", R.drawable.creator_eyewear_special_redtopframe), - SetupCustomization.Companion.createGlasses("eyewear_special_yellowTopFrame", R.drawable.creator_eyewear_special_yellowtopframe), - SetupCustomization.Companion.createGlasses("eyewear_special_whiteTopFrame", R.drawable.creator_eyewear_special_whitetopframe) - ); - } - - private List getFlowers() { - return Arrays.asList( - SetupCustomization.Companion.createFlower("0", R.drawable.creator_blank_face), - SetupCustomization.Companion.createFlower("1", R.drawable.creator_hair_flower_1), - SetupCustomization.Companion.createFlower("2", R.drawable.creator_hair_flower_2), - SetupCustomization.Companion.createFlower("3", R.drawable.creator_hair_flower_3), - SetupCustomization.Companion.createFlower("4", R.drawable.creator_hair_flower_4), - SetupCustomization.Companion.createFlower("5", R.drawable.creator_hair_flower_5), - SetupCustomization.Companion.createFlower("6", R.drawable.creator_hair_flower_6) - ); - } - - private List getHairColors() { - return Arrays.asList( - SetupCustomization.Companion.createHairColor("white", R.color.hair_white), - SetupCustomization.Companion.createHairColor("brown", R.color.hair_brown), - SetupCustomization.Companion.createHairColor("blond", R.color.hair_blond), - SetupCustomization.Companion.createHairColor("red", R.color.hair_red), - SetupCustomization.Companion.createHairColor("black", R.color.hair_black) - ); - } - - private List getHairBases(String color) { - return Arrays.asList( - SetupCustomization.Companion.createHairPonytail("0", R.drawable.creator_blank_face), - SetupCustomization.Companion.createHairPonytail("1", getResId("creator_hair_base_1_"+color)), - SetupCustomization.Companion.createHairPonytail("3", getResId("creator_hair_base_3_"+color)) - ); - } - - private List getBangs(String color) { - return Arrays.asList( - SetupCustomization.Companion.createHairBangs("0", R.drawable.creator_blank_face), - SetupCustomization.Companion.createHairBangs("1", getResId("creator_hair_bangs_1_"+color)), - SetupCustomization.Companion.createHairBangs("2", getResId("creator_hair_bangs_2_"+color)), - SetupCustomization.Companion.createHairBangs("3", getResId("creator_hair_bangs_3_"+color)) - ); - } - - private List getSizes() { - return Arrays.asList( - SetupCustomization.Companion.createSize("slim", R.drawable.creator_slim_shirt_black, context.getString(R.string.avatar_size_slim)), - SetupCustomization.Companion.createSize("broad", R.drawable.creator_broad_shirt_black, context.getString(R.string.avatar_size_broad)) - ); - } - - private List getShirts(String size) { - if (size.equals("broad")) { - return Arrays.asList( - SetupCustomization.Companion.createShirt("black", R.drawable.creator_broad_shirt_black), - SetupCustomization.Companion.createShirt("blue", R.drawable.creator_broad_shirt_blue), - SetupCustomization.Companion.createShirt("green", R.drawable.creator_broad_shirt_green), - SetupCustomization.Companion.createShirt("pink", R.drawable.creator_broad_shirt_pink), - SetupCustomization.Companion.createShirt("white", R.drawable.creator_broad_shirt_white), - SetupCustomization.Companion.createShirt("yellow", R.drawable.creator_broad_shirt_yellow) - ); - } else { - return Arrays.asList( - SetupCustomization.Companion.createShirt("black", R.drawable.creator_slim_shirt_black), - SetupCustomization.Companion.createShirt("blue", R.drawable.creator_slim_shirt_blue), - SetupCustomization.Companion.createShirt("green", R.drawable.creator_slim_shirt_green), - SetupCustomization.Companion.createShirt("pink", R.drawable.creator_slim_shirt_pink), - SetupCustomization.Companion.createShirt("white", R.drawable.creator_slim_shirt_white), - SetupCustomization.Companion.createShirt("yellow", R.drawable.creator_slim_shirt_yellow) - ); - } - } - - private List getSkins() { - return Arrays.asList( - SetupCustomization.Companion.createSkin("ddc994", R.color.skin_ddc994), - SetupCustomization.Companion.createSkin("f5a76e", R.color.skin_f5a76e), - SetupCustomization.Companion.createSkin("ea8349", R.color.skin_ea8349), - SetupCustomization.Companion.createSkin("c06534", R.color.skin_c06534), - SetupCustomization.Companion.createSkin("98461a", R.color.skin_98461a), - SetupCustomization.Companion.createSkin("915533", R.color.skin_915533), - SetupCustomization.Companion.createSkin("c3e1dc", R.color.skin_c3e1dc), - SetupCustomization.Companion.createSkin("6bd049", R.color.skin_6bd049) - ); - } - - private int getResId(String resName) { - - try { - return context.getResources().getIdentifier(resName, "drawable", context.getPackageName()); - } catch (Exception e) { - e.printStackTrace(); - return -1; - } - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.kt new file mode 100644 index 000000000..6eb6fc9d2 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.kt @@ -0,0 +1,162 @@ +package com.habitrpg.android.habitica.data.implementation + +import android.content.Context + +import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.data.SetupCustomizationRepository +import com.habitrpg.android.habitica.models.SetupCustomization +import com.habitrpg.android.habitica.models.user.User + +import java.util.ArrayList +import java.util.Arrays + +import javax.inject.Inject + + +class SetupCustomizationRepositoryImpl @Inject +constructor(private val context: Context) : SetupCustomizationRepository { + + private val wheelchairs: List + get() = Arrays.asList( + SetupCustomization.createWheelchair("none", 0), + SetupCustomization.createWheelchair("black", R.drawable.creator_chair_black), + SetupCustomization.createWheelchair("blue", R.drawable.creator_chair_blue), + SetupCustomization.createWheelchair("green", R.drawable.creator_chair_green), + SetupCustomization.createWheelchair("pink", R.drawable.creator_chair_pink), + SetupCustomization.createWheelchair("red", R.drawable.creator_chair_red), + SetupCustomization.createWheelchair("yellow", R.drawable.creator_chair_yellow) + ) + + private val glasses: List + get() = Arrays.asList( + SetupCustomization.createGlasses("", R.drawable.creator_blank_face), + SetupCustomization.createGlasses("eyewear_special_blackTopFrame", R.drawable.creator_eyewear_special_blacktopframe), + SetupCustomization.createGlasses("eyewear_special_blueTopFrame", R.drawable.creator_eyewear_special_bluetopframe), + SetupCustomization.createGlasses("eyewear_special_greenTopFrame", R.drawable.creator_eyewear_special_greentopframe), + SetupCustomization.createGlasses("eyewear_special_pinkTopFrame", R.drawable.creator_eyewear_special_pinktopframe), + SetupCustomization.createGlasses("eyewear_special_redTopFrame", R.drawable.creator_eyewear_special_redtopframe), + SetupCustomization.createGlasses("eyewear_special_yellowTopFrame", R.drawable.creator_eyewear_special_yellowtopframe), + SetupCustomization.createGlasses("eyewear_special_whiteTopFrame", R.drawable.creator_eyewear_special_whitetopframe) + ) + + private val flowers: List + get() = Arrays.asList( + SetupCustomization.createFlower("0", R.drawable.creator_blank_face), + SetupCustomization.createFlower("1", R.drawable.creator_hair_flower_1), + SetupCustomization.createFlower("2", R.drawable.creator_hair_flower_2), + SetupCustomization.createFlower("3", R.drawable.creator_hair_flower_3), + SetupCustomization.createFlower("4", R.drawable.creator_hair_flower_4), + SetupCustomization.createFlower("5", R.drawable.creator_hair_flower_5), + SetupCustomization.createFlower("6", R.drawable.creator_hair_flower_6) + ) + + private val hairColors: List + get() = Arrays.asList( + SetupCustomization.createHairColor("white", R.color.hair_white), + SetupCustomization.createHairColor("brown", R.color.hair_brown), + SetupCustomization.createHairColor("blond", R.color.hair_blond), + SetupCustomization.createHairColor("red", R.color.hair_red), + SetupCustomization.createHairColor("black", R.color.hair_black) + ) + + private val sizes: List + get() = Arrays.asList( + SetupCustomization.createSize("slim", R.drawable.creator_slim_shirt_black, context.getString(R.string.avatar_size_slim)), + SetupCustomization.createSize("broad", R.drawable.creator_broad_shirt_black, context.getString(R.string.avatar_size_broad)) + ) + + private val skins: List + get() = Arrays.asList( + SetupCustomization.createSkin("ddc994", R.color.skin_ddc994), + SetupCustomization.createSkin("f5a76e", R.color.skin_f5a76e), + SetupCustomization.createSkin("ea8349", R.color.skin_ea8349), + SetupCustomization.createSkin("c06534", R.color.skin_c06534), + SetupCustomization.createSkin("98461a", R.color.skin_98461a), + SetupCustomization.createSkin("915533", R.color.skin_915533), + SetupCustomization.createSkin("c3e1dc", R.color.skin_c3e1dc), + SetupCustomization.createSkin("6bd049", R.color.skin_6bd049) + ) + + override fun getCustomizations(category: String, user: User): List { + return getCustomizations(category, null, user) + } + + override fun getCustomizations(category: String, subcategory: String?, user: User): List { + when (category) { + "body" -> { + return when (subcategory) { + "size" -> sizes + "shirt" -> getShirts(user.preferences.size ?: "slim") + else -> emptyList() + } + } + "skin" -> return skins + "hair" -> { + return when (subcategory) { + "bangs" -> getBangs(user.preferences.hair!!.color) + "ponytail" -> getHairBases(user.preferences.hair!!.color) + "color" -> hairColors + else -> emptyList() + } + } + "extras" -> { + return when (subcategory) { + "flower" -> flowers + "glasses" -> glasses + "wheelchair" -> wheelchairs + else -> emptyList() + } + } + } + return ArrayList() + } + + private fun getHairBases(color: String): List { + return Arrays.asList( + SetupCustomization.createHairPonytail("0", R.drawable.creator_blank_face), + SetupCustomization.createHairPonytail("1", getResId("creator_hair_base_1_$color")), + SetupCustomization.createHairPonytail("3", getResId("creator_hair_base_3_$color")) + ) + } + + private fun getBangs(color: String): List { + return Arrays.asList( + SetupCustomization.createHairBangs("0", R.drawable.creator_blank_face), + SetupCustomization.createHairBangs("1", getResId("creator_hair_bangs_1_$color")), + SetupCustomization.createHairBangs("2", getResId("creator_hair_bangs_2_$color")), + SetupCustomization.createHairBangs("3", getResId("creator_hair_bangs_3_$color")) + ) + } + + private fun getShirts(size: String): List { + return if (size == "broad") { + Arrays.asList( + SetupCustomization.createShirt("black", R.drawable.creator_broad_shirt_black), + SetupCustomization.createShirt("blue", R.drawable.creator_broad_shirt_blue), + SetupCustomization.createShirt("green", R.drawable.creator_broad_shirt_green), + SetupCustomization.createShirt("pink", R.drawable.creator_broad_shirt_pink), + SetupCustomization.createShirt("white", R.drawable.creator_broad_shirt_white), + SetupCustomization.createShirt("yellow", R.drawable.creator_broad_shirt_yellow) + ) + } else { + Arrays.asList( + SetupCustomization.createShirt("black", R.drawable.creator_slim_shirt_black), + SetupCustomization.createShirt("blue", R.drawable.creator_slim_shirt_blue), + SetupCustomization.createShirt("green", R.drawable.creator_slim_shirt_green), + SetupCustomization.createShirt("pink", R.drawable.creator_slim_shirt_pink), + SetupCustomization.createShirt("white", R.drawable.creator_slim_shirt_white), + SetupCustomization.createShirt("yellow", R.drawable.creator_slim_shirt_yellow) + ) + } + } + + private fun getResId(resName: String): Int { + return try { + context.resources.getIdentifier(resName, "drawable", context.packageName) + } catch (e: Exception) { + e.printStackTrace() + -1 + } + + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt index 68a368c9f..0e77abf91 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt @@ -12,43 +12,44 @@ import com.habitrpg.android.habitica.models.social.Challenge 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 io.realm.Realm +import io.reactivex.Flowable +import io.reactivex.Single +import io.reactivex.functions.BiFunction +import io.reactivex.functions.Consumer import io.realm.RealmResults -import rx.Observable -import rx.functions.Action1 import java.util.* class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: ApiClient, private val userId: String) : BaseRepositoryImpl(localRepository, apiClient), SocialRepository { - override fun retrieveGroupChat(groupId: String): Observable> { + override fun retrieveGroupChat(groupId: String): Single> { return apiClient.listGroupChat(groupId) - .flatMap { Observable.from(it) } + .flatMap { Flowable.fromIterable(it) } .map { chatMessage -> chatMessage.groupId = groupId chatMessage } .toList() - .doOnNext { chatMessages -> localRepository.saveChatMessages(groupId, chatMessages) } + .doOnSuccess { localRepository.saveChatMessages(groupId, it) } } - override fun getGroupChat(groupId: String): Observable> { + override fun getGroupChat(groupId: String): Flowable> { return localRepository.getGroupChat(groupId) } override fun markMessagesSeen(seenGroupId: String) { - apiClient.seenMessages(seenGroupId).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + apiClient.seenMessages(seenGroupId).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } - override fun flagMessage(chatMessage: ChatMessage): Observable { + override fun flagMessage(chatMessage: ChatMessage): Flowable { return if (chatMessage.id == "") { - Observable.just(null) + Flowable.empty() } else apiClient.flagMessage(chatMessage.groupId ?: "", chatMessage.id) } - override fun likeMessage(chatMessage: ChatMessage): Observable { + override fun likeMessage(chatMessage: ChatMessage): Flowable { if (chatMessage.id == "") { - return Observable.just(null) + return Flowable.empty() } val liked = chatMessage.userLikesMessage(userId) localRepository.likeMessage(chatMessage, userId, !liked) @@ -56,17 +57,15 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap .doOnError { localRepository.likeMessage(chatMessage, userId, liked) } } - override fun deleteMessage(chatMessage: ChatMessage): Observable { + override fun deleteMessage(chatMessage: ChatMessage): Flowable { return apiClient.deleteMessage(chatMessage.groupId ?: "", chatMessage.id) .doOnNext { localRepository.deleteMessage(chatMessage.id) } } - override fun postGroupChat(groupId: String, messageObject: HashMap): Observable { + override fun postGroupChat(groupId: String, messageObject: HashMap): Flowable { return apiClient.postGroupChat(groupId, messageObject) .map { postChatMessageResult -> - if (postChatMessageResult != null) { - postChatMessageResult.message.groupId = groupId - } + postChatMessageResult.message.groupId = groupId postChatMessageResult } .doOnNext { postChatMessageResult -> @@ -76,54 +75,53 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap } } - override fun postGroupChat(groupId: String, message: String): Observable { + override fun postGroupChat(groupId: String, message: String): Flowable { val messageObject = HashMap() messageObject["message"] = message return postGroupChat(groupId, messageObject) } - override fun retrieveGroup(id: String): Observable { + override fun retrieveGroup(id: String): Flowable { var observable = apiClient.getGroup(id) if ("party" != id && localRepository.doesGroupExist(id)) { - observable = observable.withLatestFrom(localRepository.getGroup(id) - .first()) { newGroup, oldGroup -> + observable = observable.withLatestFrom(localRepository.getGroup(id), BiFunction { newGroup, oldGroup -> newGroup.isMember = oldGroup.isMember newGroup - } + }) } - return Observable.zip(observable.doOnNext { localRepository.save(it) }, retrieveGroupChat(id) + return Flowable.zip(observable.doOnNext { localRepository.save(it) }, retrieveGroupChat(id) .map { it.forEach { it.groupId = id } return@map it } - .doOnNext { localRepository.save(it) } - ) { group, _ -> - return@zip group - } - + .doOnSuccess { localRepository.save(it) }.toFlowable(), + BiFunction, Group> { group, chat -> + group + } + ) } - override fun getGroup(id: String?): Observable { + override fun getGroup(id: String?): Flowable { if (id == null) { - return Observable.just(null) + return Flowable.empty() } return localRepository.getGroup(id) } - override fun leaveGroup(id: String?): Observable { + override fun leaveGroup(id: String?): Flowable { if (id == null) { - return Observable.just(null) + return Flowable.empty() } return apiClient.leaveGroup(id) - .flatMap { localRepository.getGroup(id).first() } + .flatMapMaybe { localRepository.getGroup(id).firstElement() } .doOnNext { group -> localRepository.executeTransaction { group.isMember = false } } } - override fun joinGroup(id: String?): Observable { + override fun joinGroup(id: String?): Flowable { if (id == null) { - return Observable.just(null) + return Flowable.empty() } return apiClient.joinGroup(id) .doOnNext { group -> @@ -132,9 +130,9 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap } } - override fun updateGroup(group: Group?, name: String?, description: String?, leader: String?, privacy: String?): Observable { + override fun updateGroup(group: Group?, name: String?, description: String?, leader: String?, privacy: String?): Flowable { if (group == null) { - return Observable.just(null) + return Flowable.empty() } val copiedGroup = localRepository.getUnmanagedCopy(group) copiedGroup.name = name @@ -145,7 +143,7 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap return apiClient.updateGroup(copiedGroup.id, copiedGroup) } - override fun retrieveGroups(type: String): Observable> { + override fun retrieveGroups(type: String): Flowable> { return apiClient.listGroups(type) .doOnNext { groups -> if ("guilds" == type) { @@ -155,39 +153,39 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap } } - override fun getGroups(type: String): Observable> = localRepository.getGroups(type) + override fun getGroups(type: String): Flowable> = localRepository.getGroups(type) - override fun getPublicGuilds(): Observable> = localRepository.getPublicGuilds() + override fun getPublicGuilds(): Flowable> = localRepository.getPublicGuilds() - override fun postPrivateMessage(messageObject: HashMap): Observable { + override fun postPrivateMessage(messageObject: HashMap): Flowable { return apiClient.postPrivateMessage(messageObject) } - override fun postPrivateMessage(recipientId: String, message: String): Observable { + override fun postPrivateMessage(recipientId: String, message: String): Flowable { val messageObject = HashMap() messageObject["message"] = message messageObject["toUserId"] = recipientId return postPrivateMessage(messageObject) } - override fun getGroupMembers(id: String): Observable> = localRepository.getGroupMembers(id) + override fun getGroupMembers(id: String): Flowable> = localRepository.getGroupMembers(id) - override fun retrieveGroupMembers(id: String, includeAllPublicFields: Boolean): Observable> { + override fun retrieveGroupMembers(id: String, includeAllPublicFields: Boolean): Flowable> { return apiClient.getGroupMembers(id, includeAllPublicFields) .doOnNext { members -> localRepository.saveGroupMembers(id, members) } } - override fun inviteToGroup(id: String, inviteData: Map): Observable> = apiClient.inviteToGroup(id, inviteData) + override fun inviteToGroup(id: String, inviteData: Map): Flowable> = apiClient.inviteToGroup(id, inviteData) - override fun getUserChallenges(): Observable> = apiClient.getUserChallenges() + override fun getUserChallenges(): Flowable> = apiClient.userChallenges - override fun getMember(userId: String?): Observable { + override fun getMember(userId: String?): Flowable { return if (userId == null) { - Observable.just(null) + Flowable.empty() } else apiClient.getMember(userId) } - override fun markPrivateMessagesRead(user: User?): Observable { + override fun markPrivateMessagesRead(user: User?): Flowable { return apiClient.markPrivateMessagesRead() .doOnNext { if (user?.isManaged == true) { @@ -196,50 +194,52 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap } } - override fun getUserGroups(): Observable> = localRepository.getUserGroups() + override fun getUserGroups(): Flowable> = localRepository.getUserGroups() - override fun acceptQuest(user: User, partyId: String): Observable { + override fun acceptQuest(user: User, partyId: String): Flowable { return apiClient.acceptQuest(partyId) .doOnNext { localRepository.updateRSVPNeeded(user, false) } } - override fun rejectQuest(user: User, partyId: String): Observable { + override fun rejectQuest(user: User, partyId: String): Flowable { return apiClient.rejectQuest(partyId) .doOnNext { localRepository.updateRSVPNeeded(user, false) } } - override fun leaveQuest(partyId: String?): Observable { - return apiClient.leaveQuest(partyId) + override fun leaveQuest(partyId: String?): Flowable { + return if (partyId == null) { + Flowable.empty() + } else apiClient.leaveQuest(partyId) } - override fun cancelQuest(partyId: String?): Observable { + override fun cancelQuest(partyId: String?): Flowable { if (partyId == null) { - return Observable.just(null) + return Flowable.empty() } return apiClient.cancelQuest(partyId) .doOnNext { localRepository.removeQuest(partyId) } } - override fun abortQuest(partyId: String?): Observable { + override fun abortQuest(partyId: String?): Flowable { if (partyId == null) { - return Observable.just(null) + return Flowable.empty() } return apiClient.abortQuest(partyId) .doOnNext { localRepository.removeQuest(partyId) } } - override fun rejectGroupInvite(groupId: String): Observable { + override fun rejectGroupInvite(groupId: String): Flowable { return apiClient.rejectQuest(groupId) } - override fun forceStartQuest(party: Group): Observable { + override fun forceStartQuest(party: Group): Flowable { return apiClient.forceStartQuest(party.id, localRepository.getUnmanagedCopy(party)) .doOnNext { localRepository.setQuestActivity(party, true) } } - override fun getMemberAchievements(userId: String?): Observable { + override fun getMemberAchievements(userId: String?): Flowable { return if (userId == null) { - Observable.just(null) + Flowable.empty() } else apiClient.getMemberAchievements(userId) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TagRepositoryImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TagRepositoryImpl.java deleted file mode 100644 index 14740428a..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TagRepositoryImpl.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.habitrpg.android.habitica.data.implementation; - -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 java.util.Collection; -import java.util.List; - -import io.realm.RealmResults; -import rx.Observable; - - -public class TagRepositoryImpl extends BaseRepositoryImpl implements TagRepository { - - public TagRepositoryImpl(TagLocalRepository localRepository, ApiClient apiClient) { - super(localRepository, apiClient); - } - - @Override - public Observable> getTags(String userId) { - return localRepository.getTags(userId); - } - - @Override - public Observable createTag(Tag tag) { - return apiClient.createTag(tag); - } - - @Override - public Observable updateTag(Tag tag) { - return apiClient.updateTag(tag.id, tag); - } - - @Override - public Observable deleteTag(String id) { - return apiClient.deleteTag(id); - } - - @Override - public Observable createTags(Collection tags) { - return Observable.defer(() -> Observable.from(tags)) - .filter(tag -> tag.getName() != null && !tag.getName().isEmpty()) - .flatMap(this::createTag); - } - - @Override - public Observable updateTags(Collection tags) { - return Observable.defer(() -> Observable.from(tags)) - .flatMap(this::updateTag); - } - - @Override - public Observable> deleteTags(Collection tagIds) { - return Observable.defer(() -> Observable.from(tagIds)) - .flatMap(this::deleteTag) - .toList(); - } - - @Override - public void removeOldTags(List onlineTags, String userID) { - localRepository.removeOldTags(onlineTags, userID); - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TagRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TagRepositoryImpl.kt new file mode 100644 index 000000000..79fdff2ef --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TagRepositoryImpl.kt @@ -0,0 +1,52 @@ +package com.habitrpg.android.habitica.data.implementation + +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.Flowable +import io.reactivex.Single +import io.realm.RealmResults + + +class TagRepositoryImpl(localRepository: TagLocalRepository, apiClient: ApiClient) : BaseRepositoryImpl(localRepository, apiClient), TagRepository { + + override fun getTags(userId: String): Flowable> { + return localRepository.getTags(userId) + } + + override fun createTag(tag: Tag): Flowable { + return apiClient.createTag(tag) + } + + override fun updateTag(tag: Tag): Flowable { + return apiClient.updateTag(tag.id, tag) + } + + override fun deleteTag(id: String): Flowable { + return apiClient.deleteTag(id) + } + + override fun createTags(tags: Collection): Single> { + return Flowable.defer { Flowable.fromIterable(tags) } + .filter { tag -> tag.name != null && !tag.getName().isEmpty() } + .flatMap { this.createTag(it) } + .toList() + } + + override fun updateTags(tags: Collection): Single> { + return Flowable.defer { Flowable.fromIterable(tags) } + .flatMap { this.updateTag(it) } + .toList() + } + + override fun deleteTags(tagIds: Collection): Single> { + return Flowable.defer { Flowable.fromIterable(tagIds) } + .flatMap { this.deleteTag(it) } + .toList() + } + + override fun removeOldTags(onlineTags: List, userID: String) { + localRepository.removeOldTags(onlineTags, userID) + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt index fe131d284..33feb6773 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt @@ -6,17 +6,14 @@ import com.habitrpg.android.habitica.data.local.TaskLocalRepository import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.responses.TaskDirection import com.habitrpg.android.habitica.models.responses.TaskScoringResult -import com.habitrpg.android.habitica.models.tasks.ChecklistItem -import com.habitrpg.android.habitica.models.tasks.RemindersItem -import com.habitrpg.android.habitica.models.tasks.Task -import com.habitrpg.android.habitica.models.tasks.TaskList -import com.habitrpg.android.habitica.models.tasks.TasksOrder +import com.habitrpg.android.habitica.models.tasks.* import com.habitrpg.android.habitica.models.user.User +import io.reactivex.Flowable +import io.reactivex.Maybe +import io.reactivex.functions.Consumer import io.realm.Realm import io.realm.RealmList import io.realm.RealmResults -import rx.Observable -import rx.functions.Action1 import java.text.SimpleDateFormat import java.util.* @@ -25,22 +22,22 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli private var lastTaskAction: Long = 0 - override fun getTasks(taskType: String, userID: String): Observable> = + override fun getTasks(taskType: String, userID: String): Flowable> = this.localRepository.getTasks(taskType, userID) - override fun getTasks(userId: String): Observable> = + override fun getTasks(userId: String): Flowable> = this.localRepository.getTasks(userId) override fun saveTasks(userId: String, order: TasksOrder, tasks: TaskList) { localRepository.saveTasks(userId, order, tasks) } - override fun retrieveTasks(userId: String, tasksOrder: TasksOrder): Observable { - return this.apiClient.getTasks() + override fun retrieveTasks(userId: String, tasksOrder: TasksOrder): Flowable { + return this.apiClient.tasks .doOnNext { res -> this.localRepository.saveTasks(userId, tasksOrder, res) } } - override fun retrieveCompletedTodos(userId: String): Observable { + override fun retrieveCompletedTodos(userId: String): Flowable { return this.apiClient.getTasks("completedTodos") .doOnNext { taskList -> val tasks = taskList.tasks @@ -50,20 +47,20 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli } } - override fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): Observable { + override fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): Flowable { 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) } } - override fun taskChecked(user: User?, task: Task, up: Boolean, force: Boolean): Observable { + override fun taskChecked(user: User?, task: Task, up: Boolean, force: Boolean): Flowable { val now = Date().time val id = task.id if (lastTaskAction > now - 500 && !force) { - return Observable.just(null) + return Flowable.empty() } if (id == null) { - return Observable.just(null) + return Flowable.empty() } lastTaskAction = now return this.apiClient.postTaskDirection(id, (if (up) TaskDirection.up else TaskDirection.down).toString()) @@ -106,14 +103,14 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli } } - override fun taskChecked(user: User?, taskId: String, up: Boolean, force: Boolean): Observable { - return localRepository.getTask(taskId).first() - .flatMap { task -> taskChecked(user, task, up, force) } + override fun taskChecked(user: User?, taskId: String, up: Boolean, force: Boolean): Maybe { + return localRepository.getTask(taskId).firstElement() + .flatMap { task -> taskChecked(user, task, up, force).singleElement() } } - override fun scoreChecklistItem(taskId: String, itemId: String): Observable { + override fun scoreChecklistItem(taskId: String, itemId: String): Flowable { return apiClient.scoreChecklistItem(taskId, itemId) - .flatMap { localRepository.getTask(taskId).first() } + .flatMapMaybe { localRepository.getTask(taskId).firstElement() } .doOnNext { task -> val updatedItem: ChecklistItem? = task.checklist?.lastOrNull { itemId == it.id } if (updatedItem != null) { @@ -122,14 +119,14 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli } } - override fun getTask(taskId: String): Observable = localRepository.getTask(taskId) + override fun getTask(taskId: String): Flowable = localRepository.getTask(taskId) - override fun getTaskCopy(taskId: String): Observable = localRepository.getTaskCopy(taskId) + override fun getTaskCopy(taskId: String): Flowable = localRepository.getTaskCopy(taskId) - override fun createTask(task: Task): Observable { + override fun createTask(task: Task): Flowable { val now = Date().time if (lastTaskAction > now - 500) { - return Observable.just(task) + return Flowable.empty() } lastTaskAction = now task.tags?.let { @@ -158,26 +155,26 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli task1.dateCreated = Date() task1 } - .doOnNext({ localRepository.saveTask(it) }) + .doOnNext { localRepository.saveTask(it) } } - override fun updateTask(task: Task): Observable { + override fun updateTask(task: Task): Maybe { val now = Date().time if (lastTaskAction > now - 500 || !task.isValid) { - return Observable.just(task) + return Maybe.just(task) } lastTaskAction = now - val id = task.id ?: return Observable.just(task) - return localRepository.getTaskCopy(id).first() - .flatMap { task1 -> apiClient.updateTask(id, task1) } + val id = task.id ?: return Maybe.just(task) + return localRepository.getTaskCopy(id).firstElement() + .flatMap { task1 -> apiClient.updateTask(id, task1).singleElement() } .map { task1 -> task1.position = task.position task1 } - .doOnNext({ localRepository.saveTask(it) }) + .doOnSuccess { localRepository.saveTask(it) } } - override fun deleteTask(taskId: String): Observable { + override fun deleteTask(taskId: String): Flowable { return apiClient.deleteTask(taskId) .doOnNext { localRepository.deleteTask(taskId) } } @@ -186,7 +183,7 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli localRepository.saveTask(task) } - override fun createTasks(newTasks: List): Observable> = apiClient.createTasks(newTasks) + override fun createTasks(newTasks: List): Flowable> = apiClient.createTasks(newTasks) override fun markTaskCompleted(taskId: String, isCompleted: Boolean) { localRepository.markTaskCompleted(taskId, isCompleted) @@ -204,38 +201,38 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli localRepository.swapTaskPosition(firstPosition, secondPosition) } - override fun updateTaskPosition(taskType: String, oldPosition: Int, newPosition: Int): Observable> { + override fun updateTaskPosition(taskType: String, oldPosition: Int, newPosition: Int): Maybe> { return localRepository.getTaskAtPosition(taskType, oldPosition) - .first() + .firstElement() .flatMap { task -> if (task.isValid) { - return@flatMap apiClient.postTaskNewPosition(task.id ?: "", newPosition) + return@flatMap apiClient.postTaskNewPosition(task.id ?: "", newPosition).firstElement() } - return@flatMap Observable.just>(ArrayList()) + return@flatMap Maybe.just>(ArrayList()) } - .doOnNext({ localRepository.updateTaskPositions(it) }) + .doOnSuccess { localRepository.updateTaskPositions(it) } } - override fun getUnmanagedTask(taskid: String): Observable = - getTask(taskid).map({ localRepository.getUnmanagedCopy(it) }) + override fun getUnmanagedTask(taskid: String): Flowable = + getTask(taskid).map { localRepository.getUnmanagedCopy(it) } override fun updateTaskInBackground(task: Task) { - updateTask(task).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + updateTask(task).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } override fun createTaskInBackground(task: Task) { - createTask(task).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + createTask(task).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } - override fun getTaskCopies(userId: String): Observable> = - getTasks(userId).map({ localRepository.getUnmanagedCopy(it) }) + override fun getTaskCopies(userId: String): Flowable> = + getTasks(userId).map { localRepository.getUnmanagedCopy(it) } - override fun getTaskCopies(tasks: List): Observable> = - Observable.just(localRepository.getUnmanagedCopy(tasks)) + override fun getTaskCopies(tasks: List): Flowable> = + Flowable.just(localRepository.getUnmanagedCopy(tasks)) - override fun updateDailiesIsDue(date: Date): Observable { + override fun updateDailiesIsDue(date: Date): Flowable { val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.US) return apiClient.getTasks("dailys", formatter.format(date)) - .flatMap({ localRepository.updateIsdue(it) }) + .flatMapMaybe { localRepository.updateIsdue(it) } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TutorialRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TutorialRepositoryImpl.kt index f7628eba1..aecaf4334 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TutorialRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TutorialRepositoryImpl.kt @@ -4,16 +4,15 @@ 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.Flowable import io.realm.RealmResults -import rx.Observable class TutorialRepositoryImpl(localRepository: TutorialLocalRepository, apiClient: ApiClient) : BaseRepositoryImpl(localRepository, apiClient), TutorialRepository { - override fun getTutorialStep(key: String): Observable = + override fun getTutorialStep(key: String): Flowable = localRepository.getTutorialStep(key) - override fun getTutorialSteps(keys: List): Observable> = + override fun getTutorialSteps(keys: List): Flowable> = localRepository.getTutorialSteps(keys) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt index ca13b55d2..7493a6314 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt @@ -14,9 +14,10 @@ import com.habitrpg.android.habitica.models.social.ChatMessage import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.android.habitica.models.user.Stats import com.habitrpg.android.habitica.models.user.User +import io.reactivex.Flowable +import io.reactivex.Maybe +import io.reactivex.functions.Consumer import io.realm.RealmResults -import rx.Observable -import rx.functions.Action1 import java.util.* import java.util.concurrent.TimeUnit @@ -24,28 +25,28 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli private var lastSync: Date? = null - override fun getUser(): Observable = getUser(userId) - override fun getInboxOverviewList(): Observable> = localRepository.getInboxOverviewList(userId) + override fun getUser(): Flowable = getUser(userId) + override fun getInboxOverviewList(): Flowable> = localRepository.getInboxOverviewList(userId) - override fun getUser(userID: String): Observable = localRepository.getUser(userID) + override fun getUser(userID: String): Flowable = localRepository.getUser(userID) - override fun updateUser(user: User?, updateData: Map): Observable { + override fun updateUser(user: User?, updateData: Map): Flowable { return if (user == null) { - Observable.just(User()) + Flowable.just(User()) } else apiClient.updateUser(updateData).map { newUser -> mergeUser(user, newUser) } } - override fun updateUser(user: User?, key: String, value: Any): Observable { + override fun updateUser(user: User?, key: String, value: Any): Flowable { val updateData = HashMap() updateData[key] = value return updateUser(user, updateData) } - override fun retrieveUser(withTasks: Boolean): Observable = + override fun retrieveUser(withTasks: Boolean): Flowable = retrieveUser(withTasks, false) - override fun retrieveUser(withTasks: Boolean, forced: Boolean): Observable { + override fun retrieveUser(withTasks: Boolean, forced: Boolean): Flowable { if (forced || this.lastSync == null || Date().time - (this.lastSync?.time ?: 0) > 180000) { lastSync = Date() return apiClient.retrieveUser(withTasks) @@ -59,10 +60,10 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli val calendar = GregorianCalendar() val timeZone = calendar.timeZone val offset = -TimeUnit.MINUTES.convert(timeZone.getOffset(calendar.timeInMillis).toLong(), TimeUnit.MILLISECONDS) - if (offset != user?.preferences?.timezoneOffset ?: 0) { + if (offset != user.preferences?.timezoneOffset ?: 0) { return@flatMap updateUser(user, "preferences.timezoneOffset", offset.toString()) } else { - return@flatMap Observable.just(user) + return@flatMap Flowable.just(user) } } } else { @@ -70,10 +71,10 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli } } - override fun getInboxMessages(replyToUserID: String?): Observable> = + override fun getInboxMessages(replyToUserID: String?): Flowable> = localRepository.getInboxMessages(userId, replyToUserID) - override fun retrieveInboxMessages(): Observable> { + override fun retrieveInboxMessages(): Flowable> { return apiClient.retrieveInboxMessages().doOnNext { messages -> messages.forEach { it.isInboxMessage = true @@ -82,7 +83,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli } } - override fun revive(user: User): Observable = + override fun revive(user: User): Flowable = apiClient.revive().map { newUser -> mergeUser(user, newUser) } override fun resetTutorial(user: User?) { @@ -95,21 +96,21 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli updateData } .flatMap { updateData -> updateUser(user, updateData) } - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } - override fun sleep(user: User): Observable { + override fun sleep(user: User): Flowable { localRepository.executeTransaction { user.preferences.isSleep = !user.preferences.sleep } return apiClient.sleep().map { user } } - override fun getSkills(user: User): Observable> = + override fun getSkills(user: User): Flowable> = localRepository.getSkills(user) - override fun getSpecialItems(user: User): Observable> = + override fun getSpecialItems(user: User): Flowable> = localRepository.getSpecialItems(user) - override fun useSkill(user: User?, key: String, target: String, taskId: String): Observable { + override fun useSkill(user: User?, key: String, target: String, taskId: String): Flowable { return apiClient.useSkill(key, target, taskId).doOnNext { skillResponse -> if (user != null) { mergeUser(user, skillResponse.user) @@ -117,7 +118,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli } } - override fun useSkill(user: User?, key: String, target: String): Observable { + override fun useSkill(user: User?, key: String, target: String): Flowable { return apiClient.useSkill(key, target) .map { response -> response.hpDiff = response.user.stats.getHp() - (user?.stats?.getHp() ?: 0.0) @@ -132,13 +133,13 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli } } - override fun changeClass(): Observable = apiClient.changeClass().flatMap { retrieveUser(false, true) } + override fun changeClass(): Flowable = apiClient.changeClass().flatMap { retrieveUser(false, true) } - override fun disableClasses(): Observable = apiClient.disableClasses().flatMap { retrieveUser(false, true) } + override fun disableClasses(): Flowable = apiClient.disableClasses().flatMap { retrieveUser(false, true) } - override fun changeClass(selectedClass: String): Observable = apiClient.changeClass(selectedClass) + override fun changeClass(selectedClass: String): Flowable = apiClient.changeClass(selectedClass) - override fun unlockPath(user: User, customization: Customization): Observable { + override fun unlockPath(user: User, customization: Customization): Flowable { return apiClient.unlockPath(customization.path) .doOnNext { unlockResponse -> val copiedUser = localRepository.getUnmanagedCopy(user) @@ -150,13 +151,13 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli } } - override fun unlockPath(user: User, set: CustomizationSet): Observable { + override fun unlockPath(user: User, set: CustomizationSet): Flowable { var path = "" for (customization in set.customizations) { path = path + "," + customization.path } if (path.isEmpty()) { - return Observable.just(null) + return Flowable.just(null) } path = path.substring(1) return apiClient.unlockPath(path) @@ -174,39 +175,39 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli runCron(ArrayList()) } - override fun readNotification(id: String): Observable> = apiClient.readNotification(id) + override fun readNotification(id: String): Flowable> = apiClient.readNotification(id) - override fun changeCustomDayStart(dayStartTime: Int): Observable { + override fun changeCustomDayStart(dayStartTime: Int): Flowable { val updateObject = HashMap() updateObject["dayStart"] = dayStartTime return apiClient.changeCustomDayStart(updateObject) } - override fun updateLanguage(user: User?, languageCode: String): Observable { + override fun updateLanguage(user: User?, languageCode: String): Flowable { return updateUser(user, "preferences.language", languageCode) .doOnNext { apiClient.setLanguageCode(languageCode) } } - override fun resetAccount(): Observable { + override fun resetAccount(): Flowable { return apiClient.resetAccount().flatMap { retrieveUser(true, true) } } - override fun deleteAccount(password: String): Observable = + override fun deleteAccount(password: String): Flowable = apiClient.deleteAccount(password) - override fun sendPasswordResetEmail(email: String): Observable = + override fun sendPasswordResetEmail(email: String): Flowable = apiClient.sendPasswordResetEmail(email) - override fun updateLoginName(newLoginName: String, password: String): Observable = + override fun updateLoginName(newLoginName: String, password: String): Flowable = apiClient.updateLoginName(newLoginName, password) - override fun updateEmail(newEmail: String, password: String): Observable = + override fun updateEmail(newEmail: String, password: String): Flowable = apiClient.updateEmail(newEmail, password) - override fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Observable = + override fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable = apiClient.updatePassword(newPassword, oldPassword, oldPasswordConfirmation) - override fun allocatePoint(user: User?, stat: String): Observable { + override fun allocatePoint(user: User?, stat: String): Flowable { if (user != null && user.isManaged) { localRepository.executeTransaction { when (stat) { @@ -233,7 +234,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli } } - override fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Observable = + override fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable = apiClient.bulkAllocatePoints(strength, intelligence, constitution, perception) .doOnNext { stats -> if (user != null && user.isManaged) { @@ -249,7 +250,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli } override fun runCron(tasks: MutableList) { - var observable: Observable = localRepository.getUser(userId).first() + var observable: Maybe = localRepository.getUser(userId).firstElement() .filter { it.needsCron } .map { user -> localRepository.executeTransaction { user.needsCron = false @@ -259,13 +260,13 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli } if (tasks.isNotEmpty()) { for (task in tasks) { - observable = observable.flatMap { taskRepository.taskChecked(null, task, true, true) } + observable = observable.flatMap { taskRepository.taskChecked(null, task, true, true).firstElement() } } - observable.toList() + observable } - observable.flatMap { apiClient.runCron() } - .flatMap { this.retrieveUser(true, true) } - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + observable.flatMap { apiClient.runCron().firstElement() } + .flatMap { this.retrieveUser(true, true).firstElement() } + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } private fun mergeUser(oldUser: User?, newUser: User): User? { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.java deleted file mode 100644 index 8c7c0ec6b..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.habitrpg.android.habitica.data.local; - - -import com.habitrpg.android.habitica.models.social.Challenge; -import com.habitrpg.android.habitica.models.tasks.Task; - -import java.util.List; - -import io.realm.RealmResults; -import rx.Observable; - -public interface ChallengeLocalRepository extends BaseLocalRepository { - Observable getChallenge(String id); - Observable> getTasks(Challenge challenge); - - Observable> getChallenges(); - - Observable> getUserChallenges(String userId); - - void setParticipating(Challenge challenge, boolean isParticipating); - - void saveChallenges(List challenges); -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.kt new file mode 100644 index 000000000..b467518fc --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.kt @@ -0,0 +1,21 @@ +package com.habitrpg.android.habitica.data.local + + +import com.habitrpg.android.habitica.models.social.Challenge +import com.habitrpg.android.habitica.models.tasks.Task + +import io.reactivex.Flowable +import io.realm.RealmResults + +interface ChallengeLocalRepository : BaseLocalRepository { + + val challenges: Flowable> + fun getChallenge(id: String): Flowable + fun getTasks(challenge: Challenge): Flowable> + + fun getUserChallenges(userId: String): Flowable> + + fun setParticipating(challenge: Challenge, isParticipating: Boolean) + + fun saveChallenges(challenges: List) +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/CustomizationLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/CustomizationLocalRepository.java deleted file mode 100644 index 1522d8ffe..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/CustomizationLocalRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.habitrpg.android.habitica.data.local; - -import com.habitrpg.android.habitica.models.inventory.Customization; - -import io.realm.RealmResults; -import rx.Observable; - -public interface CustomizationLocalRepository extends ContentLocalRepository { - Observable> getCustomizations(String type, String category, boolean onlyAvailable); -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/CustomizationLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/CustomizationLocalRepository.kt new file mode 100644 index 000000000..dd812c1bf --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/CustomizationLocalRepository.kt @@ -0,0 +1,10 @@ +package com.habitrpg.android.habitica.data.local + +import com.habitrpg.android.habitica.models.inventory.Customization + +import io.reactivex.Flowable +import io.realm.RealmResults + +interface CustomizationLocalRepository : ContentLocalRepository { + fun getCustomizations(type: String, category: String, onlyAvailable: Boolean): Flowable> +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/FAQLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/FAQLocalRepository.java deleted file mode 100644 index b9474c321..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/FAQLocalRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.habitrpg.android.habitica.data.local; - -import com.habitrpg.android.habitica.models.FAQArticle; - -import io.realm.RealmResults; -import rx.Observable; - -public interface FAQLocalRepository extends ContentLocalRepository { - - Observable> getArticles(); -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/FAQLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/FAQLocalRepository.kt new file mode 100644 index 000000000..d30055c23 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/FAQLocalRepository.kt @@ -0,0 +1,11 @@ +package com.habitrpg.android.habitica.data.local + +import com.habitrpg.android.habitica.models.FAQArticle + +import io.reactivex.Flowable +import io.realm.RealmResults + +interface FAQLocalRepository : ContentLocalRepository { + + val articles: Flowable> +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt index 277724fec..7c718704f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt @@ -1,51 +1,46 @@ package com.habitrpg.android.habitica.data.local -import com.habitrpg.android.habitica.models.inventory.Equipment -import com.habitrpg.android.habitica.models.inventory.Item -import com.habitrpg.android.habitica.models.inventory.Mount -import com.habitrpg.android.habitica.models.inventory.Pet -import com.habitrpg.android.habitica.models.inventory.QuestContent +import com.habitrpg.android.habitica.models.inventory.* import com.habitrpg.android.habitica.models.shops.ShopItem import com.habitrpg.android.habitica.models.user.User - +import io.reactivex.Flowable import io.realm.RealmResults -import rx.Observable interface InventoryLocalRepository : ContentLocalRepository { fun getArmoireRemainingCount(): Long - fun getOwnedEquipment(): Observable> + fun getOwnedEquipment(): Flowable> - fun getMounts(): Observable> + fun getMounts(): Flowable> - fun getOwnedMounts(): Observable> + fun getOwnedMounts(): Flowable> - fun getPets(): Observable> + fun getPets(): Flowable> - fun getOwnedPets(): Observable> + fun getOwnedPets(): Flowable> - fun getInAppRewards(): Observable> - fun getQuestContent(key: String): Observable + fun getInAppRewards(): Flowable> + fun getQuestContent(key: String): Flowable - fun getEquipment(searchedKeys: List): Observable> + fun getEquipment(searchedKeys: List): Flowable> - fun getOwnedEquipment(type: String): Observable> + fun getOwnedEquipment(type: String): Flowable> - fun getOwnedItems(itemClass: Class, user: User?): Observable> - fun getOwnedItems(user: User): Observable> + fun getOwnedItems(itemClass: Class, user: User?): Flowable> + fun getOwnedItems(user: User): Flowable> - fun getEquipment(key: String): Observable - fun getMounts(type: String, group: String): Observable> - fun getOwnedMounts(animalType: String, animalGroup: String): Observable> - fun getPets(type: String, group: String): Observable> - fun getOwnedPets(type: String, group: String): Observable> + fun getEquipment(key: String): Flowable + fun getMounts(type: String, group: String): Flowable> + fun getOwnedMounts(animalType: String, animalGroup: String): Flowable> + fun getPets(type: String, group: String): Flowable> + fun getOwnedPets(type: String, group: String): Flowable> fun updateOwnedEquipment(user: User) fun changeOwnedCount(type: String, key: String, amountToAdd: Int) fun changeOwnedCount(item: Item, amountToAdd: Int?) - fun getItem(type: String, key: String): Observable + fun getItem(type: String, key: String): Flowable fun decrementMysteryItemCount(user: User) fun saveInAppRewards(onlineItems: List) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/SocialLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/SocialLocalRepository.kt index b9116eac3..986a46965 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/SocialLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/SocialLocalRepository.kt @@ -4,23 +4,22 @@ import com.habitrpg.android.habitica.models.members.Member 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 io.reactivex.Flowable import io.realm.RealmResults -import rx.Observable interface SocialLocalRepository : BaseLocalRepository { - fun getPublicGuilds(): Observable> + fun getPublicGuilds(): Flowable> - fun getUserGroups(): Observable> - fun getGroups(type: String): Observable> + fun getUserGroups(): Flowable> + fun getGroups(type: String): Flowable> - fun getGroup(id: String): Observable + fun getGroup(id: String): Flowable - fun getGroupChat(groupId: String): Observable> + fun getGroupChat(groupId: String): Flowable> fun deleteMessage(id: String) - fun getGroupMembers(partyId: String): Observable> + fun getGroupMembers(partyId: String): Flowable> fun updateRSVPNeeded(user: User?, newValue: Boolean) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TagLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TagLocalRepository.java deleted file mode 100644 index dfbd20bff..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TagLocalRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.habitrpg.android.habitica.data.local; - -import com.habitrpg.android.habitica.models.Tag; - -import java.util.List; - -import io.realm.RealmResults; -import rx.Observable; - -public interface TagLocalRepository extends BaseLocalRepository { - Observable> getTags(String userId); - - void removeOldTags(List onlineTags, String userID); -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TagLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TagLocalRepository.kt new file mode 100644 index 000000000..535565a6f --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TagLocalRepository.kt @@ -0,0 +1,12 @@ +package com.habitrpg.android.habitica.data.local + +import com.habitrpg.android.habitica.models.Tag + +import io.reactivex.Flowable +import io.realm.RealmResults + +interface TagLocalRepository : BaseLocalRepository { + fun getTags(userId: String): Flowable> + + fun removeOldTags(onlineTags: List, userID: String) +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TaskLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TaskLocalRepository.kt index d2f25f107..cb2267a8b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TaskLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TaskLocalRepository.kt @@ -4,13 +4,14 @@ import com.habitrpg.android.habitica.models.tasks.RemindersItem import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.android.habitica.models.tasks.TaskList import com.habitrpg.android.habitica.models.tasks.TasksOrder +import io.reactivex.Flowable +import io.reactivex.Maybe import io.realm.RealmResults -import rx.Observable interface TaskLocalRepository : BaseLocalRepository { - fun getTasks(taskType: String, userID: String): Observable> - fun getTasks(userId: String): Observable> + fun getTasks(taskType: String, userID: String): Flowable> + fun getTasks(userId: String): Flowable> fun saveTasks(userId: String, tasksOrder: TasksOrder, tasks: TaskList) @@ -18,8 +19,8 @@ interface TaskLocalRepository : BaseLocalRepository { fun deleteTask(taskID: String) - fun getTask(taskId: String): Observable - fun getTaskCopy(taskId: String): Observable + fun getTask(taskId: String): Flowable + fun getTaskCopy(taskId: String): Flowable fun markTaskCompleted(taskId: String, isCompleted: Boolean) @@ -27,9 +28,9 @@ interface TaskLocalRepository : BaseLocalRepository { fun swapTaskPosition(firstPosition: Int, secondPosition: Int) - fun getTaskAtPosition(taskType: String, position: Int): Observable + fun getTaskAtPosition(taskType: String, position: Int): Flowable - fun updateIsdue(daily: TaskList): Observable + fun updateIsdue(daily: TaskList): Maybe fun updateTaskPositions(taskOrder: List) fun saveCompletedTodos(userId: String, tasks: MutableCollection) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TutorialLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TutorialLocalRepository.kt index 86e1a6aa1..15b690c02 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TutorialLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/TutorialLocalRepository.kt @@ -1,12 +1,11 @@ package com.habitrpg.android.habitica.data.local import com.habitrpg.android.habitica.models.TutorialStep - +import io.reactivex.Flowable import io.realm.RealmResults -import rx.Observable interface TutorialLocalRepository : BaseLocalRepository { - fun getTutorialStep(key: String): Observable - fun getTutorialSteps(keys: List): Observable> + fun getTutorialStep(key: String): Flowable + fun getTutorialSteps(keys: List): Flowable> } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/UserLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/UserLocalRepository.kt index 18422d5d6..d63dd24bc 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/UserLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/UserLocalRepository.kt @@ -4,25 +4,24 @@ import com.habitrpg.android.habitica.models.Skill import com.habitrpg.android.habitica.models.TutorialStep import com.habitrpg.android.habitica.models.social.ChatMessage import com.habitrpg.android.habitica.models.user.User - +import io.reactivex.Flowable import io.realm.RealmResults -import rx.Observable interface UserLocalRepository : BaseLocalRepository { - fun getTutorialSteps(): Observable> + fun getTutorialSteps(): Flowable> - fun getUser(userID: String): Observable + fun getUser(userID: String): Flowable fun saveUser(user: User) fun saveMessages(messages: List) - fun getSkills(user: User): Observable> + fun getSkills(user: User): Flowable> - fun getSpecialItems(user: User): Observable> + fun getSpecialItems(user: User): Flowable> - fun getInboxMessages(userId: String, replyToUserID: String?): Observable> + fun getInboxMessages(userId: String, replyToUserID: String?): Flowable> - fun getInboxOverviewList(userId: String): Observable> + fun getInboxOverviewList(userId: String): Flowable> } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmChallengeLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmChallengeLocalRepository.java deleted file mode 100644 index e842f3a24..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmChallengeLocalRepository.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.habitrpg.android.habitica.data.local.implementation; - -import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository; -import com.habitrpg.android.habitica.models.social.Challenge; -import com.habitrpg.android.habitica.models.tasks.Task; - -import java.util.ArrayList; -import java.util.List; - -import io.realm.OrderedRealmCollectionSnapshot; -import io.realm.Realm; -import io.realm.RealmResults; -import io.realm.Sort; -import rx.Observable; - -public class RealmChallengeLocalRepository extends RealmBaseLocalRepository implements ChallengeLocalRepository { - - public RealmChallengeLocalRepository(Realm realm) { - super(realm); - } - - @Override - public Observable getChallenge(String id) { - return getRealm().where(Challenge.class) - .equalTo("id", id) - .findFirstAsync() - .asObservable() - .filter(realmObject -> realmObject.isLoaded()) - .cast(Challenge.class); - } - - @Override - public Observable> getTasks(Challenge challenge) { - return null; - } - - @Override - public Observable> getChallenges() { - return getRealm().where(Challenge.class) - .isNotNull("name") - .findAllSortedAsync("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING) - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public Observable> getUserChallenges(String userId) { - return getRealm().where(Challenge.class) - .isNotNull("name") - .equalTo("isParticipating", true) - .findAllSortedAsync("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING) - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public void setParticipating(Challenge challenge, boolean isParticipating) { - getRealm().executeTransaction(realm1 -> challenge.isParticipating = isParticipating); - } - - @Override - public void saveChallenges(List onlineChallenges) { - OrderedRealmCollectionSnapshot localChallenges = getRealm().where(Challenge.class).findAll().createSnapshot(); - List challengesToDelete = new ArrayList<>(); - for (Challenge localTask : localChallenges) { - if (!onlineChallenges.contains(localTask)) { - challengesToDelete.add(localTask); - } - } - getRealm().executeTransaction(realm1 -> { - for (Challenge localTask : challengesToDelete) { - localTask.deleteFromRealm(); - } - }); - getRealm().executeTransaction(realm1 -> realm1.insertOrUpdate(onlineChallenges)); - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmChallengeLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmChallengeLocalRepository.kt new file mode 100644 index 000000000..69b9ae490 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmChallengeLocalRepository.kt @@ -0,0 +1,67 @@ +package com.habitrpg.android.habitica.data.local.implementation + +import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository +import com.habitrpg.android.habitica.models.social.Challenge +import com.habitrpg.android.habitica.models.tasks.Task + +import java.util.ArrayList + +import io.reactivex.Flowable +import io.realm.OrderedRealmCollectionSnapshot +import io.realm.Realm +import io.realm.RealmResults +import io.realm.Sort + +class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), ChallengeLocalRepository { + + override fun getChallenge(id: String): Flowable { + return realm.where(Challenge::class.java) + .equalTo("id", id) + .findAll() + .asFlowable() + .filter { realmObject -> realmObject.isLoaded } + .map { it.first() } + } + + override fun getTasks(challenge: Challenge): Flowable> { + return Flowable.empty() + } + + override val challenges: Flowable> + get() = realm.where(Challenge::class.java) + .isNotNull("name") + .sort("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING) + .findAll() + .asFlowable() + .filter { it.isLoaded } + + override fun getUserChallenges(userId: String): Flowable> { + return realm.where(Challenge::class.java) + .isNotNull("name") + .equalTo("isParticipating", true) + .sort("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING) + .findAllAsync() + .asFlowable() + .filter { it.isLoaded } + } + + override fun setParticipating(challenge: Challenge, isParticipating: Boolean) { + realm.executeTransaction { challenge.isParticipating = isParticipating } + } + + override fun saveChallenges(onlineChallenges: List) { + val localChallenges = realm.where(Challenge::class.java).findAll().createSnapshot() + val challengesToDelete = ArrayList() + for (localTask in localChallenges) { + if (!onlineChallenges.contains(localTask)) { + challengesToDelete.add(localTask) + } + } + realm.executeTransaction { + for (localTask in challengesToDelete) { + localTask.deleteFromRealm() + } + } + realm.executeTransaction { realm1 -> realm1.insertOrUpdate(onlineChallenges) } + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmContentLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmContentLocalRepository.kt index 15005e409..c40f50037 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmContentLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmContentLocalRepository.kt @@ -9,7 +9,7 @@ import com.habitrpg.android.habitica.models.social.Group import io.realm.Realm -internal open class RealmContentLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), ContentLocalRepository { +open class RealmContentLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), ContentLocalRepository { override fun saveContent(contentResult: ContentResult) { realm.executeTransactionAsync { realm1 -> diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmCustomizationLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmCustomizationLocalRepository.java deleted file mode 100644 index 86972d66b..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmCustomizationLocalRepository.java +++ /dev/null @@ -1,47 +0,0 @@ -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 java.util.Date; - -import io.realm.Realm; -import io.realm.RealmQuery; -import io.realm.RealmResults; -import rx.Observable; - - -public class RealmCustomizationLocalRepository extends RealmContentLocalRepository implements CustomizationLocalRepository { - - public RealmCustomizationLocalRepository(Realm realm) { - super(realm); - } - - @Override - public Observable> getCustomizations(String type, String category, boolean onlyAvailable) { - RealmQuery query = getRealm().where(Customization.class) - .equalTo("type", type) - .equalTo("category", category); - if (onlyAvailable) { - Date today = new Date(); - query = query - .beginGroup() - .beginGroup() - .lessThanOrEqualTo("availableFrom", today) - .greaterThanOrEqualTo("availableUntil", today) - .endGroup() - .or() - .beginGroup() - .isNull("availableFrom") - .isNull("availableUntil") - .endGroup() - .or() - .equalTo("purchased", true) - .endGroup(); - } - return query - .findAllSorted("customizationSet") - .asObservable() - .filter(RealmResults::isLoaded); - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmCustomizationLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmCustomizationLocalRepository.kt new file mode 100644 index 000000000..973144e34 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmCustomizationLocalRepository.kt @@ -0,0 +1,40 @@ +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 io.reactivex.Flowable +import io.realm.Realm +import io.realm.RealmResults +import java.util.* + + +class RealmCustomizationLocalRepository(realm: Realm) : RealmContentLocalRepository(realm), CustomizationLocalRepository { + + override fun getCustomizations(type: String, category: String, onlyAvailable: Boolean): Flowable> { + var query = realm.where(Customization::class.java) + .equalTo("type", type) + .equalTo("category", category) + if (onlyAvailable) { + val today = Date() + query = query + .beginGroup() + .beginGroup() + .lessThanOrEqualTo("availableFrom", today) + .greaterThanOrEqualTo("availableUntil", today) + .endGroup() + .or() + .beginGroup() + .isNull("availableFrom") + .isNull("availableUntil") + .endGroup() + .or() + .equalTo("purchased", true) + .endGroup() + } + return query + .sort("customizationSet") + .findAll() + .asFlowable() + .filter { it.isLoaded } + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmFAQLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmFAQLocalRepository.java deleted file mode 100644 index 4769bfc58..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmFAQLocalRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.habitrpg.android.habitica.data.local.implementation; - -import com.habitrpg.android.habitica.data.local.FAQLocalRepository; -import com.habitrpg.android.habitica.models.FAQArticle; - -import io.realm.Realm; -import io.realm.RealmResults; -import rx.Observable; - -public class RealmFAQLocalRepository extends RealmContentLocalRepository implements FAQLocalRepository { - - public RealmFAQLocalRepository(Realm realm) { - super(realm); - } - - @Override - public Observable> getArticles() { - return getRealm().where(FAQArticle.class) - .findAll() - .asObservable() - .filter(RealmResults::isLoaded); - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmFAQLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmFAQLocalRepository.kt new file mode 100644 index 000000000..4b09fe5a1 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmFAQLocalRepository.kt @@ -0,0 +1,16 @@ +package com.habitrpg.android.habitica.data.local.implementation + +import com.habitrpg.android.habitica.data.local.FAQLocalRepository +import com.habitrpg.android.habitica.models.FAQArticle +import io.reactivex.Flowable +import io.realm.Realm +import io.realm.RealmResults + +class RealmFAQLocalRepository(realm: Realm) : RealmContentLocalRepository(realm), FAQLocalRepository { + + override val articles: Flowable> + get() = realm.where(FAQArticle::class.java) + .findAll() + .asFlowable() + .filter{ it.isLoaded } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.java deleted file mode 100644 index ceb888ef5..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.java +++ /dev/null @@ -1,315 +0,0 @@ -package com.habitrpg.android.habitica.data.local.implementation; - -import android.content.Context; -import android.support.annotation.NonNull; - -import com.habitrpg.android.habitica.data.local.InventoryLocalRepository; -import com.habitrpg.android.habitica.helpers.RxErrorHandler; -import com.habitrpg.android.habitica.models.inventory.Egg; -import com.habitrpg.android.habitica.models.inventory.Equipment; -import com.habitrpg.android.habitica.models.inventory.Food; -import com.habitrpg.android.habitica.models.inventory.HatchingPotion; -import com.habitrpg.android.habitica.models.inventory.Item; -import com.habitrpg.android.habitica.models.inventory.Mount; -import com.habitrpg.android.habitica.models.inventory.Pet; -import com.habitrpg.android.habitica.models.inventory.QuestContent; -import com.habitrpg.android.habitica.models.inventory.SpecialItem; -import com.habitrpg.android.habitica.models.shops.ShopItem; -import com.habitrpg.android.habitica.models.user.User; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.realm.OrderedRealmCollectionSnapshot; -import io.realm.Realm; -import io.realm.RealmObject; -import io.realm.RealmQuery; -import io.realm.RealmResults; -import io.realm.Sort; -import kotlin.Unit; -import kotlin.jvm.functions.Function1; -import rx.Observable; -import rx.functions.Func4; - - -public class RealmInventoryLocalRepository extends RealmContentLocalRepository implements InventoryLocalRepository { - private final Context context; - - public RealmInventoryLocalRepository(Realm realm, Context context) { - super(realm); - this.context = context; - } - - @Override - public Observable getQuestContent(String key) { - return getRealm().where(QuestContent.class).equalTo("key", key).findFirstAsync() - .asObservable() - .filter(realmObject -> realmObject.isLoaded()) - .cast(QuestContent.class); - } - - @Override - public Observable> getEquipment(List searchedKeys) { - return getRealm().where(Equipment.class) - .in("key", searchedKeys.toArray(new String[0])) - .findAll() - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public long getArmoireRemainingCount() { - return getRealm().where(Equipment.class) - .equalTo("klass", "armoire") - .beginGroup() - .equalTo("owned", false) - .or() - .isNull("owned") - .endGroup() - .count(); - } - - @NonNull - @Override - public Observable> getOwnedEquipment(String type) { - return getRealm().where(Equipment.class) - .equalTo("type", type) - .equalTo("owned", true) - .findAll() - .asObservable() - .filter(RealmResults::isLoaded); - } - - @NonNull - @Override - public Observable> getOwnedEquipment() { - return getRealm().where(Equipment.class) - .equalTo("owned", true) - .findAll() - .asObservable() - .filter(RealmResults::isLoaded); - } - - @NotNull - @Override - public Observable> getOwnedItems(@NotNull Class itemClass, @Nullable User user) { - if (itemClass == null) { - return Observable.empty(); - } - - RealmQuery query = getRealm().where(itemClass); - if (SpecialItem.class.isAssignableFrom(itemClass)) { - if (user != null && user.getPurchased() != null && user.getPurchased().getPlan() != null) { - SpecialItem mysticItem; - if (query.count() == 0) { - mysticItem = SpecialItem.makeMysteryItem(context); - } else { - mysticItem = getUnmanagedCopy((SpecialItem) query.findFirst()); - } - mysticItem.setOwned(user.getPurchased().getPlan().mysteryItemCount); - this.save(mysticItem); - } - } else { - query = query.greaterThan("owned", 0); - } - return query.findAllAsync().asObservable().filter(RealmResults::isLoaded); - } - - @Override - public Observable> getOwnedItems(User user) { - return Observable.combineLatest( - getOwnedItems(Egg.class, user), - getOwnedItems(HatchingPotion.class, user), - getOwnedItems(Food.class, user), - getOwnedItems(QuestContent.class, user), - (Func4, RealmResults, RealmResults, RealmResults, Map>) (eggs, hatchingPotions, food, quests) -> { - Map items = new HashMap<>(); - for (Item item : eggs) { - items.put(item.getKey()+"-"+item.getType(), item); - } - for (Item item : hatchingPotions) { - items.put(item.getKey()+"-"+item.getType(), item); - } - for (Item item : food) { - items.put(item.getKey()+"-"+item.getType(), item); - } - for (Item item : quests) { - items.put(item.getKey()+"-"+item.getType(), item); - } - return items; - } - ); - } - - @Override - public Observable getEquipment(String key) { - return getRealm().where(Equipment.class) - .equalTo("key", key) - .findFirstAsync() - .asObservable() - .filter(realmObject -> realmObject.isLoaded()) - .cast(Equipment.class); - } - - @Override - public Observable> getMounts() { - return getRealm().where(Mount.class) - .findAllSorted("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING) - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public Observable> getMounts(String type, String group) { - return getRealm().where(Mount.class) - .equalTo("animalGroup", group) - .equalTo("animal", type) - .findAll() - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public Observable> getOwnedMounts() { - return getRealm().where(Mount.class) - .equalTo("owned", true) - .findAllSorted("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING) - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public Observable> getOwnedMounts(String animalType, String animalGroup) { - if (animalGroup == null) { - animalGroup = ""; - } - animalGroup = animalGroup.replace("pets", "mounts").replace("Pets", "Mounts"); - return getRealm().where(Mount.class) - .equalTo("animalGroup", animalGroup) - .equalTo("animal", animalType) - .equalTo("owned", true) - .findAllSorted("animal") - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public Observable> getPets() { - return getRealm().where(Pet.class) - .findAllSorted("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING) - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public Observable> getPets(String type, String group) { - return getRealm().where(Pet.class) - .equalTo("animalGroup", group) - .equalTo("animal", type) - .findAll() - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public Observable> getOwnedPets() { - return getRealm().where(Pet.class) - .greaterThan("trained", 0) - .findAllSorted("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING) - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public Observable> getOwnedPets(String type, String group) { - return getRealm().where(Pet.class) - .equalTo("animalGroup", group) - .equalTo("animal", type) - .greaterThan("trained", 0) - .findAllSorted("animal") - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public void updateOwnedEquipment(User user) { - - } - - @Override - public void changeOwnedCount(String type, String key, int amountToAdd) { - this.getItem(type, key).first().subscribe(item -> changeOwnedCount(item, amountToAdd), RxErrorHandler.handleEmptyError()); - } - - @Override - public void changeOwnedCount(Item item, Integer amountToAdd) { - getRealm().executeTransaction(realm1 -> item.setOwned(item.getOwned()+amountToAdd)); - } - - @Override - public Observable getItem(String type, String key) { - Class itemClass = null; - switch (type) { - case "eggs": - itemClass = Egg.class; - break; - case "hatchingPotions": - itemClass = HatchingPotion.class; - break; - case "food": - itemClass = Food.class; - break; - case "quests": - itemClass = QuestContent.class; - } - return getRealm().where(itemClass).equalTo("key", key).findFirstAsync().asObservable() - .filter(realmObject -> realmObject.isLoaded()) - .cast(Item.class); - } - - @Override - public void decrementMysteryItemCount(User user) { - SpecialItem item = getRealm().where(SpecialItem.class).equalTo("isMysteryItem", true).findFirst(); - getRealm().executeTransaction(realm1 -> { - if (item != null && item.isValid()) { - item.setOwned(item.getOwned() - 1); - } - if (user.isValid() && user.getPurchased() != null && user.getPurchased().getPlan() != null) { - user.getPurchased().getPlan().mysteryItemCount -= 1; - } - }); - } - - @Override - public Observable> getInAppRewards() { - return getRealm().where(ShopItem.class) - .findAllAsync() - .asObservable() - .filter(RealmResults::isLoaded); - } - - @Override - public void saveInAppRewards(@NotNull List onlineItems) { - OrderedRealmCollectionSnapshot localItems = getRealm().where(ShopItem.class).findAll().createSnapshot(); - getRealm().executeTransaction(realm1 -> { - for (ShopItem localItem : localItems) { - if (!onlineItems.contains(localItem)) { - localItem.deleteFromRealm(); - } - } - getRealm().insertOrUpdate(onlineItems); - }); - } - - @Override - public void changePetFeedStatus(@Nullable String key, int feedStatus) { - Pet pet = getRealm().where(Pet.class).equalTo("key", key).findFirst(); - if (pet != null) { - executeTransaction(realm -> { pet.setTrained(feedStatus); }); - } - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt new file mode 100644 index 000000000..e4558e2e2 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt @@ -0,0 +1,256 @@ +package com.habitrpg.android.habitica.data.local.implementation + +import android.content.Context +import com.habitrpg.android.habitica.data.local.InventoryLocalRepository +import com.habitrpg.android.habitica.extensions.notNull +import com.habitrpg.android.habitica.helpers.RxErrorHandler +import com.habitrpg.android.habitica.models.inventory.* +import com.habitrpg.android.habitica.models.shops.ShopItem +import com.habitrpg.android.habitica.models.user.User +import io.reactivex.Flowable +import io.reactivex.functions.Consumer +import io.reactivex.functions.Function4 +import io.realm.Realm +import io.realm.RealmObject +import io.realm.RealmResults +import io.realm.Sort + + +class RealmInventoryLocalRepository(realm: Realm, private val context: Context) : RealmContentLocalRepository(realm), InventoryLocalRepository { + + override fun getQuestContent(key: String): Flowable { + return realm.where(QuestContent::class.java).equalTo("key", key).findFirstAsync() + .asFlowable() + .filter { realmObject -> realmObject.isLoaded } + .cast(QuestContent::class.java) + } + + override fun getEquipment(searchedKeys: List): Flowable> { + return realm.where(Equipment::class.java) + .`in`("key", searchedKeys.toTypedArray()) + .findAll() + .asFlowable() + .filter { it.isLoaded } + } + + override fun getArmoireRemainingCount(): Long { + return realm.where(Equipment::class.java) + .equalTo("klass", "armoire") + .beginGroup() + .equalTo("owned", false) + .or() + .isNull("owned") + .endGroup() + .count() + } + + override fun getOwnedEquipment(type: String): Flowable> { + return realm.where(Equipment::class.java) + .equalTo("type", type) + .equalTo("owned", true) + .findAll() + .asFlowable() + .filter { it.isLoaded } + } + + override fun getOwnedEquipment(): Flowable> { + return realm.where(Equipment::class.java) + .equalTo("owned", true) + .findAll() + .asFlowable() + .filter { it.isLoaded } + } + + override fun getOwnedItems(itemClass: Class, user: User?): Flowable> { + var query = realm.where(itemClass) + if (SpecialItem::class.java.isAssignableFrom(itemClass)) { + if (user != null && user.purchased != null && user.purchased.plan != null) { + val mysticItem: SpecialItem = if (query.count() == 0L) { + SpecialItem.makeMysteryItem(context) + } else { + getUnmanagedCopy((query.findFirst() as SpecialItem?)!!) + } + mysticItem.owned = user.purchased.plan.mysteryItemCount + this.save(mysticItem) + } + } else { + query = query.greaterThan("owned", 0) + } + return query.findAllAsync().asFlowable() + .filter { it.isLoaded } + } + + override fun getOwnedItems(user: User): Flowable> { + return Flowable.combineLatest( + getOwnedItems(Egg::class.java, user), + getOwnedItems(HatchingPotion::class.java, user), + getOwnedItems(Food::class.java, user), + getOwnedItems(QuestContent::class.java, user), + Function4 { eggs, hatchingPotions, food, quests -> + val items = HashMap() + for (item in eggs) { + items[item.key + "-" + item.type] = item + } + for (item in hatchingPotions) { + items[item.key + "-" + item.type] = item + } + for (item in food) { + items[item.key + "-" + item.type] = item + } + for (item in quests) { + items[item.key + "-" + item.type] = item + } + items + } + ) + } + + override fun getEquipment(key: String): Flowable { + return realm.where(Equipment::class.java) + .equalTo("key", key) + .findFirstAsync() + .asFlowable() + .filter { realmObject -> realmObject.isLoaded } + .cast(Equipment::class.java) + } + + override fun getMounts(): Flowable> { + return realm.where(Mount::class.java) + .sort("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING) + .findAll() + .asFlowable() + .filter { it.isLoaded } + } + + override fun getMounts(type: String, group: String): Flowable> { + return realm.where(Mount::class.java) + .equalTo("animalGroup", group) + .equalTo("animal", type) + .findAll() + .asFlowable() + .filter { it.isLoaded } + } + + override fun getOwnedMounts(): Flowable> { + return realm.where(Mount::class.java) + .equalTo("owned", true) + .sort("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING) + .findAll() + .asFlowable() + .filter { it.isLoaded } + } + + override fun getOwnedMounts(animalType: String, animalGroup: String): Flowable> { + val thisAnimalGroup = animalGroup.replace("pets", "mounts").replace("Pets", "Mounts") + return realm.where(Mount::class.java) + .equalTo("animalGroup", thisAnimalGroup) + .equalTo("animal", animalType) + .equalTo("owned", true) + .sort("animal") + .findAll() + .asFlowable() + .filter { it.isLoaded } + } + + override fun getPets(): Flowable> { + return realm.where(Pet::class.java) + .sort("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING) + .findAll() + .asFlowable() + .filter { it.isLoaded } + } + + override fun getPets(type: String, group: String): Flowable> { + return realm.where(Pet::class.java) + .equalTo("animalGroup", group) + .equalTo("animal", type) + .findAll() + .asFlowable() + .filter { it.isLoaded } + } + + override fun getOwnedPets(): Flowable> { + return realm.where(Pet::class.java) + .greaterThan("trained", 0) + .sort("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING) + .findAll() + .asFlowable() + .filter { it.isLoaded } + } + + override fun getOwnedPets(type: String, group: String): Flowable> { + return realm.where(Pet::class.java) + .equalTo("animalGroup", group) + .equalTo("animal", type) + .greaterThan("trained", 0) + .sort("animal") + .findAll() + .asFlowable() + .filter { it.isLoaded } + } + + override fun updateOwnedEquipment(user: User) { + + } + + override fun changeOwnedCount(type: String, key: String, amountToAdd: Int) { + getItem(type, key).firstElement().subscribe( Consumer { changeOwnedCount(it, amountToAdd)}, RxErrorHandler.handleEmptyError()) + } + + override fun changeOwnedCount(item: Item, amountToAdd: Int?) { + amountToAdd.notNull { amount -> + realm.executeTransaction { item.owned = item.owned + amount } + } + } + + override fun getItem(type: String, key: String): Flowable { + val itemClass: Class = when (type) { + "eggs" -> Egg::class.java + "hatchingPotions" -> HatchingPotion::class.java + "food" -> Food::class.java + "quests" -> QuestContent::class.java + else -> Egg::class.java + } + return realm.where(itemClass).equalTo("key", key).findFirstAsync().asFlowable() + .filter { realmObject -> realmObject.isLoaded } + .cast(Item::class.java) + } + + override fun decrementMysteryItemCount(user: User) { + val item = realm.where(SpecialItem::class.java).equalTo("isMysteryItem", true).findFirst() + realm.executeTransaction { + if (item != null && item.isValid) { + item.setOwned(item.owned!! - 1) + } + if (user.isValid && user.purchased != null && user.purchased.plan != null) { + user.purchased.plan.mysteryItemCount -= 1 + } + } + } + + override fun getInAppRewards(): Flowable> { + return realm.where(ShopItem::class.java) + .findAllAsync() + .asFlowable() + .filter { it.isLoaded } + } + + override fun saveInAppRewards(onlineItems: List) { + val localItems = realm.where(ShopItem::class.java).findAll().createSnapshot() + realm.executeTransaction { + for (localItem in localItems) { + if (!onlineItems.contains(localItem)) { + localItem.deleteFromRealm() + } + } + realm.insertOrUpdate(onlineItems) + } + } + + override fun changePetFeedStatus(key: String?, feedStatus: Int) { + val pet = realm.where(Pet::class.java).equalTo("key", key).findFirst() + if (pet != null) { + executeTransaction { pet.trained = feedStatus } + } + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmSocialLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmSocialLocalRepository.kt index 8b98d9dfb..8e1811e7f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmSocialLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmSocialLocalRepository.kt @@ -1,71 +1,72 @@ package com.habitrpg.android.habitica.data.local.implementation import com.habitrpg.android.habitica.data.local.SocialLocalRepository -import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.members.Member import com.habitrpg.android.habitica.models.social.ChatMessage import com.habitrpg.android.habitica.models.social.ChatMessageLike import com.habitrpg.android.habitica.models.social.Group import com.habitrpg.android.habitica.models.user.User +import io.reactivex.Flowable import io.realm.Realm import io.realm.RealmResults import io.realm.Sort -import rx.Observable -import rx.functions.Action1 import java.util.* class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), SocialLocalRepository { - override fun getPublicGuilds(): Observable> = realm.where(Group::class.java) + override fun getPublicGuilds(): Flowable> = realm.where(Group::class.java) .equalTo("type", "guild") .equalTo("privacy", "public") - .findAllSorted("memberCount", Sort.DESCENDING) - .asObservable() - .filter({ it.isLoaded }) + .sort("memberCount", Sort.DESCENDING) + .findAll() + .asFlowable() + .filter { it.isLoaded } - override fun getUserGroups(): Observable> = realm.where(Group::class.java) + override fun getUserGroups(): Flowable> = realm.where(Group::class.java) .equalTo("type", "guild") .equalTo("isMember", true) - .findAllSorted("memberCount", Sort.DESCENDING) - .asObservable() - .filter({ it.isLoaded }) + .sort("memberCount", Sort.DESCENDING) + .findAll() + .asFlowable() + .filter { it.isLoaded } - override fun getGroups(type: String): Observable> { + override fun getGroups(type: String): Flowable> { return realm.where(Group::class.java) .equalTo("type", type) .findAllAsync() - .asObservable() - .filter({ it.isLoaded }) + .asFlowable() + .filter { it.isLoaded } } - override fun getGroup(id: String): Observable { + override fun getGroup(id: String): Flowable { return realm.where(Group::class.java) .equalTo("id", id) .findAll() - .asObservable() + .asFlowable() .filter { group -> group.isLoaded && group.isValid && !group.isEmpty() } .map { groups -> groups.first() } } - override fun getGroupChat(groupId: String): Observable> { + override fun getGroupChat(groupId: String): Flowable> { return realm.where(ChatMessage::class.java) .equalTo("groupId", groupId) - .findAllSorted("timestamp", Sort.DESCENDING) - .asObservable() - .filter({ it.isLoaded }) + .sort("timestamp", Sort.DESCENDING) + .findAll() + .asFlowable() + .filter { it.isLoaded } } override fun deleteMessage(id: String) { - getMessage(id).first().subscribe(Action1 { chatMessage -> realm.executeTransaction { chatMessage.deleteFromRealm() } }, RxErrorHandler.handleEmptyError()) + getMessage(id).firstElement().subscribe { chatMessage -> realm.executeTransaction { chatMessage.deleteFromRealm() } } } - override fun getGroupMembers(partyId: String): Observable> { + override fun getGroupMembers(partyId: String): Flowable> { return realm.where(Member::class.java) .equalTo("party.id", partyId) .findAllAsync() - .asObservable() - .filter({ it.isLoaded }) + .asFlowable() + .filter { it.isLoaded } } override fun updateRSVPNeeded(user: User?, newValue: Boolean) { @@ -136,10 +137,10 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm) } - private fun getMessage(id: String): Observable { + private fun getMessage(id: String): Flowable { return realm.where(ChatMessage::class.java).equalTo("id", id) .findAllAsync() - .asObservable() + .asFlowable() .filter { messages -> messages.isLoaded && messages.isValid && !messages.isEmpty() } .map { messages -> messages.first() } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTagLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTagLocalRepository.java deleted file mode 100644 index 7fc1d51cd..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTagLocalRepository.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.habitrpg.android.habitica.data.local.implementation; - -import com.habitrpg.android.habitica.data.local.TagLocalRepository; -import com.habitrpg.android.habitica.models.Tag; - -import java.util.List; - -import io.realm.OrderedRealmCollectionSnapshot; -import io.realm.Realm; -import io.realm.RealmResults; -import rx.Observable; - - -public class RealmTagLocalRepository extends RealmBaseLocalRepository implements TagLocalRepository { - public RealmTagLocalRepository(Realm realm) { - super(realm); - } - - @Override - public Observable> getTags(String userId) { - return getRealm().where(Tag.class).equalTo("userId", userId).findAll().asObservable(); - } - - @Override - public void removeOldTags(List onlineTags, String userID) { - OrderedRealmCollectionSnapshot localTags = getRealm().where(Tag.class).equalTo("userId", userID).findAll().createSnapshot(); - for (Tag localTag : localTags) { - if (!onlineTags.contains(localTag)) { - localTag.deleteFromRealm(); - } - } - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTagLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTagLocalRepository.kt new file mode 100644 index 000000000..9d0f60553 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTagLocalRepository.kt @@ -0,0 +1,24 @@ +package com.habitrpg.android.habitica.data.local.implementation + +import com.habitrpg.android.habitica.data.local.TagLocalRepository +import com.habitrpg.android.habitica.models.Tag +import io.reactivex.Flowable +import io.realm.Realm +import io.realm.RealmResults + + +class RealmTagLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), TagLocalRepository { + + override fun getTags(userId: String): Flowable> { + return realm.where(Tag::class.java).equalTo("userId", userId).findAll().asFlowable() + } + + override fun removeOldTags(onlineTags: List, userID: String) { + val localTags = realm.where(Tag::class.java).equalTo("userId", userID).findAll().createSnapshot() + for (localTag in localTags) { + if (!onlineTags.contains(localTag)) { + localTag.deleteFromRealm() + } + } + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt index 7585400a2..b93f6f84e 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt @@ -1,33 +1,31 @@ package com.habitrpg.android.habitica.data.local.implementation import com.habitrpg.android.habitica.data.local.TaskLocalRepository -import com.habitrpg.android.habitica.models.tasks.ChecklistItem -import com.habitrpg.android.habitica.models.tasks.RemindersItem -import com.habitrpg.android.habitica.models.tasks.Task -import com.habitrpg.android.habitica.models.tasks.TaskList -import com.habitrpg.android.habitica.models.tasks.TasksOrder +import com.habitrpg.android.habitica.models.tasks.* +import io.reactivex.Flowable +import io.reactivex.Maybe import io.realm.Realm import io.realm.RealmObject import io.realm.RealmResults -import rx.Observable -import kotlin.collections.ArrayList class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), TaskLocalRepository { - override fun getTasks(taskType: String, userID: String): Observable> { + override fun getTasks(taskType: String, userID: String): Flowable> { return realm.where(Task::class.java) .equalTo("type", taskType) .equalTo("userId", userID) - .findAllSorted("position") - .asObservable() + .sort("position") + .findAll() + .asFlowable() .filter({ it.isLoaded }) .retry(1) } - override fun getTasks(userId: String): Observable> { + override fun getTasks(userId: String): Flowable> { return realm.where(Task::class.java).equalTo("userId", userId) - .findAllSorted("position") - .asObservable() + .sort("position") + .findAll() + .asFlowable() .filter({ it.isLoaded }) } @@ -143,17 +141,17 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), } } - override fun getTask(taskId: String): Observable { - return realm.where(Task::class.java).equalTo("id", taskId).findFirstAsync().asObservable() + override fun getTask(taskId: String): Flowable { + return realm.where(Task::class.java).equalTo("id", taskId).findFirstAsync().asFlowable() .filter { realmObject -> realmObject.isLoaded } .cast(Task::class.java) } - override fun getTaskCopy(taskId: String): Observable { + override fun getTaskCopy(taskId: String): Flowable { return getTask(taskId) .map { task -> if (task.isManaged && task.isValid) { - return@map realm.copyFromRealm(task) + return@map realm.copyFromRealm(task) } else { return@map task } @@ -180,15 +178,15 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), } } - override fun getTaskAtPosition(taskType: String, position: Int): Observable { - return realm.where(Task::class.java).equalTo("type", taskType).equalTo("position", position).findFirstAsync().asObservable() + override fun getTaskAtPosition(taskType: String, position: Int): Flowable { + return realm.where(Task::class.java).equalTo("type", taskType).equalTo("position", position).findFirstAsync().asFlowable() .filter { realmObject -> realmObject.isLoaded } .cast(Task::class.java) } - override fun updateIsdue(daily: TaskList): Observable { - return Observable.just(realm.where(Task::class.java).equalTo("type", "daily").findAll()) - .first() + override fun updateIsdue(daily: TaskList): Maybe { + return Flowable.just(realm.where(Task::class.java).equalTo("type", "daily").findAll()) + .firstElement() .map { tasks -> realm.beginTransaction() tasks.filter { daily.tasks.containsKey(it.id) }.forEach { it.isDue = daily.tasks[it.id]?.isDue } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTutorialLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTutorialLocalRepository.kt index 039ced0fd..bd13a1542 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTutorialLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTutorialLocalRepository.kt @@ -2,17 +2,17 @@ package com.habitrpg.android.habitica.data.local.implementation import com.habitrpg.android.habitica.data.local.TutorialLocalRepository import com.habitrpg.android.habitica.models.TutorialStep +import io.reactivex.Flowable import io.realm.Realm import io.realm.RealmResults -import rx.Observable class RealmTutorialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), TutorialLocalRepository { - override fun getTutorialStep(key: String): Observable { + override fun getTutorialStep(key: String): Flowable { return realm.where(TutorialStep::class.java).equalTo("identifier", key) .findAllAsync() - .asObservable() + .asFlowable() .filter { realmObject -> realmObject.isLoaded && realmObject.isValid } .map { steps -> return@map if (steps.isEmpty()) { @@ -29,11 +29,11 @@ class RealmTutorialLocalRepository(realm: Realm) : RealmBaseLocalRepository(real .cast(TutorialStep::class.java) } - override fun getTutorialSteps(keys: List): Observable> { + override fun getTutorialSteps(keys: List): Flowable> { return realm.where(TutorialStep::class.java) .`in`("identifier", keys.toTypedArray()) .findAll() - .asObservable() - .filter({ it.isLoaded }) + .asFlowable() + .filter { it.isLoaded } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt index c5cf269aa..8d53dd795 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt @@ -7,21 +7,21 @@ import com.habitrpg.android.habitica.models.TutorialStep import com.habitrpg.android.habitica.models.social.Challenge import com.habitrpg.android.habitica.models.social.ChatMessage import com.habitrpg.android.habitica.models.user.User +import io.reactivex.Flowable import io.realm.Realm import io.realm.RealmResults import io.realm.Sort -import rx.Observable class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), UserLocalRepository { - override fun getTutorialSteps(): Observable> = realm.where(TutorialStep::class.java).findAll().asObservable() - .filter({ it.isLoaded }) + override fun getTutorialSteps(): Flowable> = realm.where(TutorialStep::class.java).findAll().asFlowable() + .filter { it.isLoaded } - override fun getUser(userID: String): Observable { + override fun getUser(userID: String): Flowable { return realm.where(User::class.java) .equalTo("id", userID) .findAll() - .asObservable() + .asFlowable() .filter { realmObject -> realmObject.isLoaded && realmObject.isValid && !realmObject.isEmpty() } .map { users -> users.first() } } @@ -72,17 +72,17 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), } } - override fun getSkills(user: User): Observable> { + override fun getSkills(user: User): Flowable> { val habitClass = if (user.preferences.disableClasses) "none" else user.stats.habitClass return realm.where(Skill::class.java) .equalTo("habitClass", habitClass) .lessThanOrEqualTo("lvl", user.stats.lvl) .findAll() - .asObservable() - .filter({ it.isLoaded }) + .asFlowable() + .filter { it.isLoaded } } - override fun getSpecialItems(user: User): Observable> { + override fun getSpecialItems(user: User): Flowable> { val specialItems = user.items.special val ownedItems = ArrayList() if (specialItems != null) { @@ -105,25 +105,27 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), return realm.where(Skill::class.java) .`in`("key", ownedItems.toTypedArray()) .findAll() - .asObservable() - .filter({ it.isLoaded }) + .asFlowable() + .filter { it.isLoaded } } - override fun getInboxMessages(userId: String, replyToUserID: String?): Observable> { + override fun getInboxMessages(userId: String, replyToUserID: String?): Flowable> { return realm.where(ChatMessage::class.java) .equalTo("isInboxMessage", true) .equalTo("uuid", replyToUserID) - .findAllSorted("timestamp", Sort.DESCENDING) - .asObservable() - .filter({ it.isLoaded }) + .sort("timestamp", Sort.DESCENDING) + .findAll() + .asFlowable() + .filter { it.isLoaded } } - override fun getInboxOverviewList(userId: String): Observable> { + override fun getInboxOverviewList(userId: String): Flowable> { return realm.where(ChatMessage::class.java) .equalTo("isInboxMessage", true) .distinct("uuid") .sort("timestamp", Sort.DESCENDING) - .asObservable() - .filter({ it.isLoaded }) + .findAll() + .asFlowable() + .filter { it.isLoaded } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/executors/PostExecutionThread.java b/Habitica/src/main/java/com/habitrpg/android/habitica/executors/PostExecutionThread.java index eaba4fb72..234fdb1c8 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/executors/PostExecutionThread.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/executors/PostExecutionThread.java @@ -1,6 +1,7 @@ package com.habitrpg.android.habitica.executors; -import rx.Scheduler; + +import io.reactivex.Scheduler; public interface PostExecutionThread { Scheduler getScheduler(); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/executors/UIThread.java b/Habitica/src/main/java/com/habitrpg/android/habitica/executors/UIThread.java index c763cb7ec..b3d7cf4ea 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/executors/UIThread.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/executors/UIThread.java @@ -3,8 +3,8 @@ package com.habitrpg.android.habitica.executors; import javax.inject.Inject; import javax.inject.Singleton; -import rx.Scheduler; -import rx.android.schedulers.AndroidSchedulers; +import io.reactivex.Scheduler; +import io.reactivex.android.schedulers.AndroidSchedulers; @Singleton public class UIThread implements PostExecutionThread { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/ViewHolder-Extensions.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/ViewHolder-Extensions.kt index 9e9bc762d..e5b015b31 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/ViewHolder-Extensions.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/ViewHolder-Extensions.kt @@ -1,6 +1,9 @@ package com.habitrpg.android.habitica.extensions +import android.content.Context +import android.support.annotation.ColorRes import android.support.annotation.IdRes +import android.support.v4.content.ContextCompat import android.view.View fun bindView(container: View, @IdRes res: Int) : Lazy { @@ -11,4 +14,9 @@ fun bindView(container: View, @IdRes res: Int) : Lazy { fun bindOptionalView(container: View?, @IdRes res: Int) : Lazy { @Suppress("UNCHECKED_CAST") return lazy(LazyThreadSafetyMode.NONE) { container?.findViewById(res) } +} + +fun bindColor(context: Context, @ColorRes res: Int) : Lazy { + @Suppress("UNCHECKED_CAST") + return lazy(LazyThreadSafetyMode.NONE) { ContextCompat.getColor(context, res) } } \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/QrCodeManager.java b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/QrCodeManager.java index bc32390ff..d4b26052e 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/QrCodeManager.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/QrCodeManager.java @@ -72,7 +72,7 @@ public class QrCodeManager { this.qrCodeWrapper = (FrameLayout) qrLayout.findViewById(R.id.qrCodeWrapper); if (userRepository != null) { - userRepository.getUser(userId).first().subscribe(avatarView::setAvatar, RxErrorHandler.handleEmptyError()); + userRepository.getUser(userId).firstElement().subscribe(avatarView::setAvatar, RxErrorHandler.handleEmptyError()); } this.displayQrCode(); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/RxErrorHandler.java b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/RxErrorHandler.java index 36cf5d179..3a2b3c7e1 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/RxErrorHandler.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/RxErrorHandler.java @@ -8,9 +8,8 @@ import com.habitrpg.android.habitica.proxy.CrashlyticsProxy; import java.io.EOFException; import java.io.IOException; +import io.reactivex.functions.Consumer; import retrofit2.HttpException; -import rx.functions.Action1; -import rx.plugins.RxJavaHooks; public class RxErrorHandler { @@ -21,14 +20,14 @@ public class RxErrorHandler { instance = new RxErrorHandler(); instance.crashlyticsProxy = crashlyticsProxy; - RxJavaHooks.setOnError(handleEmptyError()); + //RxJavaHooks.setOnError(handleEmptyError()); } - public static Action1 handleEmptyError() { + public static Consumer handleEmptyError() { //Can't be turned into a lambda, because it then doesn't work for some reason. - return new Action1() { + return new Consumer() { @Override - public void call(Throwable throwable) { + public void accept(Throwable throwable) { RxErrorHandler.reportError(throwable); } }; diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFileLoader.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFileLoader.kt index b3563da3e..aff466c48 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFileLoader.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFileLoader.kt @@ -4,15 +4,16 @@ import android.annotation.SuppressLint import android.content.Context import android.os.Environment import com.habitrpg.android.habitica.HabiticaApplication +import io.reactivex.Maybe +import io.reactivex.Observable +import io.reactivex.Single +import io.reactivex.schedulers.Schedulers import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response import okio.Okio -import rx.Observable -import rx.schedulers.Schedulers import java.io.File import java.io.IOException -import java.util.* // based on http://stackoverflow.com/questions/29838565/downloading-files-using-okhttp-okio-and-rxjava class SoundFileLoader(private val context: Context) { @@ -25,8 +26,8 @@ class SoundFileLoader(private val context: Context) { } @SuppressLint("SetWorldReadable", "ObsoleteSdkInt") - fun download(files: List): Observable> { - return Observable.from(files) + fun download(files: List): Single> { + return Observable.fromIterable(files) .flatMap({ audioFile -> val file = File(getFullAudioFilePath(audioFile)) if (file.exists() && file.length() > 5000) { @@ -46,7 +47,7 @@ class SoundFileLoader(private val context: Context) { throw IOException() } } catch (io: IOException) { - sub.onCompleted() + sub.onComplete() return@create } @@ -57,20 +58,19 @@ class SoundFileLoader(private val context: Context) { sink.flush() sink.close() } catch (io: IOException) { - sub.onCompleted() + sub.onComplete() return@create } file.setReadable(true, false) audioFile.file = file sub.onNext(audioFile) - sub.onCompleted() + sub.onComplete() } } fileObservable.subscribeOn(Schedulers.io()) }, 5) .toList() - .map({ ArrayList(it) }) } private fun getFullAudioFilePath(soundFile: SoundFile): String = diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.kt index b9e00229c..b067c2037 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.kt @@ -1,10 +1,11 @@ package com.habitrpg.android.habitica.helpers import com.habitrpg.android.habitica.HabiticaBaseApplication -import rx.Observable -import rx.functions.Action1 -import rx.schedulers.Schedulers -import java.util.* +import io.reactivex.Maybe +import io.reactivex.Observable +import io.reactivex.Single +import io.reactivex.functions.Consumer +import io.reactivex.schedulers.Schedulers import javax.inject.Inject class SoundManager { @@ -19,9 +20,9 @@ class SoundManager { HabiticaBaseApplication.getComponent().inject(this) } - fun preloadAllFiles(): Observable> { + fun preloadAllFiles(): Maybe> { if (soundTheme == SoundThemeOff) { - return Observable.empty() + return Maybe.empty() } val soundFiles = ArrayList() @@ -35,7 +36,7 @@ class SoundManager { soundFiles.add(SoundFile(soundTheme, SoundPlusHabit)) soundFiles.add(SoundFile(soundTheme, SoundReward)) soundFiles.add(SoundFile(soundTheme, SoundTodo)) - return soundFileLoader.download(soundFiles) + return soundFileLoader.download(soundFiles).toMaybe() } fun loadAndPlayAudio(type: String) { @@ -49,9 +50,9 @@ class SoundManager { val soundFiles = ArrayList() soundFiles.add(SoundFile(soundTheme, type)) - soundFileLoader.download(soundFiles).observeOn(Schedulers.newThread()).subscribe(Action1 { + soundFileLoader.download(soundFiles).observeOn(Schedulers.newThread()).subscribe(Consumer { val file = soundFiles[0] - loadedSoundFiles.put(type, file) + loadedSoundFiles[type] = file file.play() }, RxErrorHandler.handleEmptyError()) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/TaskAlarmManager.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/TaskAlarmManager.kt index 70a17626a..f33c0fa72 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/TaskAlarmManager.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/TaskAlarmManager.kt @@ -13,10 +13,10 @@ import com.habitrpg.android.habitica.models.tasks.RemindersItem import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.android.habitica.receivers.NotificationPublisher import com.habitrpg.android.habitica.receivers.TaskReceiver +import io.reactivex.Flowable +import io.reactivex.functions.Consumer import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe -import rx.Observable -import rx.functions.Action1 import java.util.* class TaskAlarmManager(private var context: Context, private var taskRepository: TaskRepository, private var userId: String) { @@ -60,15 +60,16 @@ class TaskAlarmManager(private var context: Context, private var taskRepository: fun addAlarmForTaskId(taskId: String) { taskRepository.getTaskCopy(taskId) .filter { task -> task.isValid && task.isManaged && Task.TYPE_DAILY == task.type } - .first() - .subscribe(Action1 { this.setAlarmsForTask(it) }, RxErrorHandler.handleEmptyError()) + .firstElement() + .subscribe(Consumer { this.setAlarmsForTask(it) }, RxErrorHandler.handleEmptyError()) } fun scheduleAllSavedAlarms() { taskRepository.getTaskCopies(userId) - .first() - .flatMap({ Observable.from(it) }) - .subscribe(Action1 { this.setAlarmsForTask(it) }, RxErrorHandler.handleEmptyError()) + .firstElement() + .toFlowable() + .flatMap { Flowable.fromIterable(it) } + .subscribe(Consumer { this.setAlarmsForTask(it) }, RxErrorHandler.handleEmptyError()) scheduleDailyReminder(context) val editor = PreferenceManager.getDefaultSharedPreferences(context).edit() diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/BuyRewardUseCase.java b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/BuyRewardUseCase.java index e8f0c2103..d93694f0c 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/BuyRewardUseCase.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/BuyRewardUseCase.java @@ -10,7 +10,7 @@ import com.habitrpg.android.habitica.models.user.User; import javax.inject.Inject; -import rx.Observable; +import io.reactivex.Flowable; public class BuyRewardUseCase extends UseCase { @@ -26,7 +26,7 @@ public class BuyRewardUseCase extends UseCase buildUseCaseObservable(BuyRewardUseCase.RequestValues requestValues) { + protected Flowable buildUseCaseObservable(BuyRewardUseCase.RequestValues requestValues) { return taskRepository .taskChecked(requestValues.user, requestValues.task, false, false) .doOnNext(res -> soundManager.loadAndPlayAudio(SoundManager.SoundReward)); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/CheckClassSelectionUseCase.java b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/CheckClassSelectionUseCase.java index a62a857df..2751a8d27 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/CheckClassSelectionUseCase.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/CheckClassSelectionUseCase.java @@ -12,7 +12,7 @@ import com.habitrpg.android.habitica.ui.activities.ClassSelectionActivity; import javax.inject.Inject; -import rx.Observable; +import io.reactivex.Flowable; import static com.habitrpg.android.habitica.ui.activities.MainActivity.SELECT_CLASS_RESULT; @@ -23,9 +23,8 @@ public class CheckClassSelectionUseCase extends UseCase buildUseCaseObservable(RequestValues requestValues) { - return Observable.defer(() -> { - + protected Flowable buildUseCaseObservable(RequestValues requestValues) { + return Flowable.defer(() -> { User user = requestValues.user; if(requestValues.selectClassEvent == null) { @@ -41,7 +40,7 @@ public class CheckClassSelectionUseCase extends UseCase { @@ -20,7 +20,7 @@ public class ChecklistCheckUseCase extends UseCase buildUseCaseObservable(ChecklistCheckUseCase.RequestValues requestValues) { + protected Flowable buildUseCaseObservable(ChecklistCheckUseCase.RequestValues requestValues) { return taskRepository.scoreChecklistItem(requestValues.taskId, requestValues.itemId); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/DailyCheckUseCase.java b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/DailyCheckUseCase.java index b47db89ed..61bfaf679 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/DailyCheckUseCase.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/DailyCheckUseCase.java @@ -10,7 +10,7 @@ import com.habitrpg.android.habitica.models.user.User; import javax.inject.Inject; -import rx.Observable; +import io.reactivex.Flowable; public class DailyCheckUseCase extends UseCase { @@ -26,7 +26,7 @@ public class DailyCheckUseCase extends UseCase buildUseCaseObservable(RequestValues requestValues) { + protected Flowable buildUseCaseObservable(RequestValues requestValues) { return taskRepository.taskChecked(requestValues.user, requestValues.task, requestValues.up, false).doOnNext(res -> soundManager.loadAndPlayAudio(SoundManager.SoundDaily)); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/DisplayItemDropUseCase.java b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/DisplayItemDropUseCase.java index d5c701386..a14f13b10 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/DisplayItemDropUseCase.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/DisplayItemDropUseCase.java @@ -12,7 +12,7 @@ import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar; import javax.inject.Inject; -import rx.Observable; +import io.reactivex.Flowable; public class DisplayItemDropUseCase extends UseCase { @@ -25,8 +25,8 @@ public class DisplayItemDropUseCase extends UseCase buildUseCaseObservable(RequestValues requestValues) { - return Observable.defer(() -> { + protected Flowable buildUseCaseObservable(RequestValues requestValues) { + return Flowable.defer(() -> { TaskScoringResult data = requestValues.data; if (data != null) { @@ -39,7 +39,7 @@ public class DisplayItemDropUseCase extends UseCase { @@ -26,7 +26,7 @@ public class HabitScoreUseCase extends UseCase buildUseCaseObservable(RequestValues requestValues) { + protected Flowable buildUseCaseObservable(RequestValues requestValues) { return taskRepository .taskChecked(requestValues.user, requestValues.habit, requestValues.up, false) .doOnNext(res -> soundManager.loadAndPlayAudio(requestValues.up ? SoundManager.SoundPlusHabit : SoundManager.SoundMinusHabit)); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/LevelUpUseCase.java b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/LevelUpUseCase.java index 09bf05bc5..a88ef53f6 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/LevelUpUseCase.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/LevelUpUseCase.java @@ -21,7 +21,7 @@ import org.greenrobot.eventbus.EventBus; import javax.inject.Inject; -import rx.Observable; +import io.reactivex.Flowable; public class LevelUpUseCase extends UseCase { @@ -37,8 +37,8 @@ public class LevelUpUseCase extends UseCase } @Override - protected Observable buildUseCaseObservable(RequestValues requestValues) { - return Observable.defer(() -> { + protected Flowable buildUseCaseObservable(RequestValues requestValues) { + return Flowable.defer(() -> { soundManager.loadAndPlayAudio(SoundManager.SoundLevelUp); SuppressedModals suppressedModals = requestValues.user.getPreferences().getSuppressModals(); @@ -47,7 +47,7 @@ public class LevelUpUseCase extends UseCase checkClassSelectionUseCase.observable(new CheckClassSelectionUseCase.RequestValues(requestValues.user, null, requestValues.activity)) .subscribe(aVoid -> {}, RxErrorHandler.handleEmptyError()); - return Observable.just(requestValues.user.getStats()); + return Flowable.just(requestValues.user.getStats()); } } @@ -80,7 +80,7 @@ public class LevelUpUseCase extends UseCase alert.show(); } - return Observable.just(requestValues.user.getStats()); + return Flowable.just(requestValues.user.getStats()); }); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/NotifyUserUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/NotifyUserUseCase.kt index 63759e7e1..cf10fa4ed 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/NotifyUserUseCase.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/NotifyUserUseCase.kt @@ -22,17 +22,17 @@ import com.habitrpg.android.habitica.models.user.User 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 rx.Observable +import io.reactivex.Flowable import javax.inject.Inject class NotifyUserUseCase @Inject constructor(threadExecutor: ThreadExecutor, postExecutionThread: PostExecutionThread, private val levelUpUseCase: LevelUpUseCase, private val userRepository: UserRepository) : UseCase(threadExecutor, postExecutionThread) { - override fun buildUseCaseObservable(requestValues: RequestValues): Observable { - return Observable.defer { + override fun buildUseCaseObservable(requestValues: RequestValues): Flowable { + return Flowable.defer { if (requestValues.user == null) { - return@defer Observable . just < Stats >(null) + return@defer Flowable.empty() } val stats = requestValues.user.stats @@ -47,7 +47,7 @@ constructor(threadExecutor: ThreadExecutor, postExecutionThread: PostExecutionTh if (view != null && type != null) { HabiticaSnackbar.showSnackbar(requestValues.snackbarTargetView, null, null, view, type) } - return@defer Observable.just(stats) + return@defer Flowable.just(stats) } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/TodoCheckUseCase.java b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/TodoCheckUseCase.java index 90b1b12c6..1cd56aee3 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/TodoCheckUseCase.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/TodoCheckUseCase.java @@ -10,7 +10,7 @@ import com.habitrpg.android.habitica.models.user.User; import javax.inject.Inject; -import rx.Observable; +import io.reactivex.Flowable; public class TodoCheckUseCase extends UseCase { @@ -26,7 +26,7 @@ public class TodoCheckUseCase extends UseCase buildUseCaseObservable(TodoCheckUseCase.RequestValues requestValues) { + protected Flowable buildUseCaseObservable(TodoCheckUseCase.RequestValues requestValues) { return taskRepository.taskChecked(requestValues.user, requestValues.task, requestValues.up, false).doOnNext(res -> soundManager.loadAndPlayAudio(SoundManager.SoundTodo)); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/UseCase.java b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/UseCase.java index e5c8edd03..900ec24ef 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/UseCase.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/UseCase.java @@ -3,7 +3,7 @@ package com.habitrpg.android.habitica.interactors; import com.habitrpg.android.habitica.executors.PostExecutionThread; import com.habitrpg.android.habitica.executors.ThreadExecutor; -import rx.Observable; +import io.reactivex.Flowable; public abstract class UseCase { @@ -17,12 +17,12 @@ public abstract class UseCase { } /** - * Builds an {@link rx.Observable} which will be used when executing the current {@link UseCase}. + * Builds an {@link rx.Flowable} which will be used when executing the current {@link UseCase}. */ - protected abstract Observable buildUseCaseObservable(Q requestValues); + protected abstract Flowable buildUseCaseObservable(Q requestValues); @SuppressWarnings("unchecked") - public Observable observable(Q requestValues) { + public Flowable observable(Q requestValues) { return this.buildUseCaseObservable(requestValues) .subscribeOn(postExecutionThread.getScheduler()) .observeOn(postExecutionThread.getScheduler()); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/ApiModule.java b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/ApiModule.java index 84bec4fc2..c4a02f188 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/ApiModule.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/ApiModule.java @@ -15,7 +15,7 @@ import javax.inject.Singleton; import dagger.Module; import dagger.Provides; import retrofit2.Retrofit; -import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; @Module @@ -29,7 +29,7 @@ public class ApiModule { @Provides public GsonConverterFactory providesGsonConverterFactory() { - return ApiClientImpl.createGsonFactory(); + return ApiClientImpl.Companion.createGsonFactory(); } @Provides @@ -48,7 +48,7 @@ public class ApiModule { public MaintenanceApiService providesMaintenanceApiService(GsonConverterFactory gsonConverter, HostConfig hostConfig) { Retrofit adapter = new Retrofit.Builder() .baseUrl("https://habitica-assets.s3.amazonaws.com/mobileApp/endpoint/") - .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(gsonConverter) .build(); return adapter.create(MaintenanceApiService.class); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java index 5af9879a4..9f23c2161 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java @@ -121,8 +121,8 @@ public class RepositoryModule { } @Provides - InventoryRepository providesInventoryRepository(InventoryLocalRepository localRepository, ApiClient apiClient, RemoteConfigManager remoteConfigManager) { - return new InventoryRepositoryImpl(localRepository, apiClient, remoteConfigManager); + InventoryRepository providesInventoryRepository(InventoryLocalRepository localRepository, ApiClient apiClient) { + return new InventoryRepositoryImpl(localRepository, apiClient); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/receivers/LocalNotificationActionReceiver.java b/Habitica/src/main/java/com/habitrpg/android/habitica/receivers/LocalNotificationActionReceiver.java index 3e7d9fb03..3953b8929 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/receivers/LocalNotificationActionReceiver.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/receivers/LocalNotificationActionReceiver.java @@ -40,7 +40,7 @@ public class LocalNotificationActionReceiver extends BroadcastReceiver { this.intent = intent; this.context = context; - this.userRepository.getUser().first().subscribe(this::onUserReceived, RxErrorHandler.handleEmptyError()); + this.userRepository.getUser().firstElement().subscribe(this::onUserReceived, RxErrorHandler.handleEmptyError()); } public void onUserReceived(User user) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.java index d767f7378..161fd99ba 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.java @@ -19,7 +19,7 @@ import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import butterknife.ButterKnife; -import rx.subscriptions.CompositeSubscription; +import io.reactivex.disposables.CompositeDisposable; public abstract class BaseActivity extends AppCompatActivity { @@ -31,7 +31,7 @@ public abstract class BaseActivity extends AppCompatActivity { return destroyed; } - protected CompositeSubscription compositeSubscription; + protected CompositeDisposable compositeSubscription; @Override protected void onCreate(Bundle savedInstanceState) { @@ -40,7 +40,7 @@ public abstract class BaseActivity extends AppCompatActivity { injectActivity(HabiticaBaseApplication.getComponent()); setContentView(getLayoutResId()); ButterKnife.bind(this); - compositeSubscription = new CompositeSubscription(); + compositeSubscription = new CompositeDisposable(); } @Override @@ -78,8 +78,8 @@ public abstract class BaseActivity extends AppCompatActivity { protected void onDestroy() { destroyed = true; - if (compositeSubscription != null && !compositeSubscription.isUnsubscribed()) { - compositeSubscription.unsubscribe(); + if (compositeSubscription != null && !compositeSubscription.isDisposed()) { + compositeSubscription.dispose(); } super.onDestroy(); } @@ -98,11 +98,7 @@ public abstract class BaseActivity extends AppCompatActivity { alwaysFinishActivitiesInt = Settings.System.getInt(getApplicationContext().getContentResolver(), Settings.System.ALWAYS_FINISH_ACTIVITIES, 0); } - if (alwaysFinishActivitiesInt == 1) { - return true; - } else { - return false; - } + return alwaysFinishActivitiesInt == 1; } void showDeveloperOptionsScreen() { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ChallengeDetailActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ChallengeDetailActivity.java index d167080b6..ae18d44e1 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ChallengeDetailActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ChallengeDetailActivity.java @@ -45,6 +45,7 @@ import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeTas import com.habitrpg.android.habitica.ui.helpers.MarkdownParser; import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper; import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar; +import com.habitrpg.android.habitica.utils.Action1; import net.pherth.android.emoji_library.EmojiParser; import net.pherth.android.emoji_library.EmojiTextView; @@ -62,7 +63,6 @@ import javax.inject.Named; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; -import rx.functions.Action1; public class ChallengeDetailActivity extends BaseActivity { @@ -148,14 +148,14 @@ public class ChallengeDetailActivity extends BaseActivity { List fullList = new ArrayList<>(); - userRepository.getUser(userId).first().subscribe(user -> { + userRepository.getUser(userId).firstElement().subscribe(user -> { ChallengeDetailActivity.this.user = user; createTaskRecyclerFragment(fullList); }, RxErrorHandler.handleEmptyError()); if (challengeId != null) { challengeRepository.getChallengeTasks(challengeId) - .first() + .firstElement() .subscribe(taskList -> { ArrayList resultList = new ArrayList<>(); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.java index 98eccfbf2..72b03d4ca 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.java @@ -22,9 +22,9 @@ import javax.inject.Inject; import butterknife.BindView; import butterknife.OnClick; -import rx.functions.Action1; +import io.reactivex.functions.Consumer; -public class ClassSelectionActivity extends BaseActivity implements Action1 { +public class ClassSelectionActivity extends BaseActivity implements Consumer { String currentClass; Boolean isInitialSelection; @@ -216,7 +216,7 @@ public class ClassSelectionActivity extends BaseActivity implements Action1 observable; + Flowable observable; if (editMode) { observable = updateChallenge(); @@ -503,7 +503,7 @@ public class CreateChallengeActivity extends BaseActivity { return c; } - private Observable createChallenge() { + private Flowable createChallenge() { Challenge c = getChallengeData(); List taskList = challengeTasks.getTaskList(); @@ -515,7 +515,7 @@ public class CreateChallengeActivity extends BaseActivity { return challengeRepository.createChallenge(c, taskList); } - private Observable updateChallenge() { + private Flowable updateChallenge() { Challenge c = getChallengeData(); List taskList = challengeTasks.getTaskList(); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FixCharacterValuesActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FixCharacterValuesActivity.kt index 32d746e46..32a83db3b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FixCharacterValuesActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FixCharacterValuesActivity.kt @@ -14,9 +14,9 @@ import com.habitrpg.android.habitica.models.user.User import com.habitrpg.android.habitica.modules.AppModule import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper import com.habitrpg.android.habitica.ui.views.settings.FixValuesEditText +import io.reactivex.functions.Action +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.activity_fixcharacter.* -import rx.functions.Action0 -import rx.functions.Action1 import javax.inject.Inject import javax.inject.Named @@ -40,7 +40,7 @@ class FixCharacterValuesActivity: BaseActivity() { setTitle(R.string.fix_character_values) setupToolbar(toolbar) - repository.getUser(userId).first().subscribe(Action1 { + repository.getUser(userId).firstElement().subscribe(Consumer { user = it }, RxErrorHandler.handleEmptyError()) } @@ -62,7 +62,7 @@ class FixCharacterValuesActivity: BaseActivity() { userInfo["stats.mp"] = manaEditText.getDoubleValue() userInfo["stats.lvl"] = levelEditText.getDoubleValue().toInt() userInfo["achievements.streak"] = streakEditText.getDoubleValue().toInt() - repository.updateUser(user, userInfo).subscribe(Action1 {}, RxErrorHandler.handleEmptyError(), Action0 { + repository.updateUser(user, userInfo).subscribe(Consumer {}, RxErrorHandler.handleEmptyError(), Action { progressDialog.dismiss() finish() }) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.java index a8f4de217..ff4cd1bb9 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.java @@ -58,8 +58,8 @@ import java.util.List; import javax.inject.Inject; import butterknife.BindView; +import io.reactivex.Flowable; import io.realm.RealmResults; -import rx.Observable; import static com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType; @@ -358,7 +358,7 @@ public class FullProfileActivity extends BaseActivity { addAttributeRow(getString(R.string.profile_level), byLevelStat, byLevelStat, byLevelStat, byLevelStat, true, false); } - private Observable> loadItemDataByOutfit(Outfit outfit) { + private Flowable> loadItemDataByOutfit(Outfit outfit) { ArrayList outfitList = new ArrayList<>(); outfitList.add(outfit.getArmor()); outfitList.add(outfit.getBack()); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/HabitButtonWidgetActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/HabitButtonWidgetActivity.java index a1e86556f..932080c68 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/HabitButtonWidgetActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/HabitButtonWidgetActivity.java @@ -73,7 +73,7 @@ public class HabitButtonWidgetActivity extends BaseActivity { compositeSubscription.add(adapter.getTaskSelectionEvents().subscribe(task -> taskSelected(task.getId()), RxErrorHandler.handleEmptyError())); recyclerView.setAdapter(adapter); - taskRepository.getTasks(Task.TYPE_HABIT, userId).first().subscribe(adapter::updateData, RxErrorHandler.handleEmptyError()); + taskRepository.getTasks(Task.TYPE_HABIT, userId).firstElement().subscribe(adapter::updateData, RxErrorHandler.handleEmptyError()); } public void taskSelected(String taskId) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.java index d65ecb5b6..9f721e69b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.java @@ -79,10 +79,10 @@ import javax.inject.Inject; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; -import rx.Observable; -import rx.exceptions.Exceptions; -import rx.functions.Action1; -import rx.schedulers.Schedulers; +import io.reactivex.Flowable; +import io.reactivex.exceptions.Exceptions; +import io.reactivex.functions.Consumer; +import io.reactivex.schedulers.Schedulers; import static com.habitrpg.android.habitica.R.id.password; @@ -90,7 +90,7 @@ import static com.habitrpg.android.habitica.R.id.password; * @author Mickael Goubin */ public class LoginActivity extends BaseActivity - implements Action1 { + implements Consumer { static final int REQUEST_CODE_PICK_ACCOUNT = 1000; private final static String TAG_ADDRESS = "address"; private final static String TAG_USERID = "user"; @@ -439,7 +439,7 @@ public class LoginActivity extends BaseActivity } @Override - public void call(UserAuthResponse userAuthResponse) { + public void accept(UserAuthResponse userAuthResponse) { try { saveTokens(userAuthResponse.getToken(), userAuthResponse.getId()); } catch (Exception e) { @@ -485,9 +485,9 @@ public class LoginActivity extends BaseActivity private void handleGoogleLoginResult() { String scopesString = Scopes.PROFILE + " " + Scopes.EMAIL; String scopes = "oauth2:" + scopesString; - Observable.defer(() -> { + Flowable.defer(() -> { try { - return Observable.just(GoogleAuthUtil.getToken(LoginActivity.this, googleEmail, scopes)); + return Flowable.just(GoogleAuthUtil.getToken(LoginActivity.this, googleEmail, scopes)); } catch (IOException | GoogleAuthException e) { throw Exceptions.propagate(e); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java index 63c1840e8..51465ac43 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java @@ -12,7 +12,6 @@ import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; -import android.inputmethodservice.Keyboard; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -123,8 +122,8 @@ import java.util.Map; import javax.inject.Inject; import butterknife.BindView; -import rx.Observable; -import rx.android.schedulers.AndroidSchedulers; +import io.reactivex.Completable; +import io.reactivex.android.schedulers.AndroidSchedulers; import static android.os.Build.VERSION.SDK_INT; import static com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType; @@ -1030,9 +1029,9 @@ public class MainActivity extends BaseActivity implements TutorialView.OnTutoria }) .setMessage(""); - Observable.just(null) + Completable.complete() .observeOn(AndroidSchedulers.mainThread()) - .subscribe(o -> { + .subscribe(() -> { final AlertDialog dialog = builder.create(); dialog.show(); }, RxErrorHandler.handleEmptyError()); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/SetupActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/SetupActivity.java index 7b4a1fbfa..df366e1f7 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/SetupActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/SetupActivity.java @@ -48,7 +48,7 @@ import javax.inject.Inject; import butterknife.BindView; import butterknife.OnClick; -import rx.Observable; +import io.reactivex.Flowable; public class SetupActivity extends BaseActivity implements ViewPager.OnPageChangeListener { @@ -87,7 +87,7 @@ public class SetupActivity extends BaseActivity implements ViewPager.OnPageChang if (user == null) { return userRepository.retrieveUser(true); } else { - return Observable.just(user); + return Flowable.just(user); } }) .subscribe(this::onUserReceived, RxErrorHandler.handleEmptyError())); @@ -212,8 +212,8 @@ public class SetupActivity extends BaseActivity implements ViewPager.OnPageChang public void onUserReceived(User user) { if (completedSetup) { - if (compositeSubscription != null && !compositeSubscription.isUnsubscribed()) { - compositeSubscription.unsubscribe(); + if (compositeSubscription != null && !compositeSubscription.isDisposed()) { + compositeSubscription.dispose(); } this.startMainActivity(); return; diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/SkillMemberActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/SkillMemberActivity.java index 94251c71c..9152a1c56 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/SkillMemberActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/SkillMemberActivity.java @@ -54,8 +54,8 @@ public class SkillMemberActivity extends BaseActivity { recyclerView.setAdapter(viewAdapter); userRepository.getUser() - .first() - .flatMap(user -> socialRepository.getGroupMembers(user.getParty().id)) + .firstElement() + .flatMap(user -> socialRepository.getGroupMembers(user.getParty().id).firstElement()) .subscribe(viewAdapter::updateData, RxErrorHandler.handleEmptyError()); } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java index 53e6f8f37..a905ec123 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java @@ -456,7 +456,7 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem enableRepeatables(); tagRepository.getTags(userId) - .first() + .firstElement() .subscribe(loadedTags -> { tags = loadedTags; createTagsCheckBoxes(); @@ -465,7 +465,7 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem if (taskId != null) { taskRepository.getTask(taskId) - .first() + .firstElement() .subscribe(task -> { this.task = task; if (task != null) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.kt index 67a23d795..87502144d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.kt @@ -13,14 +13,16 @@ import com.facebook.drawee.view.SimpleDraweeView import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.events.commands.OpenMenuItemCommand import com.habitrpg.android.habitica.extensions.bindView +import com.habitrpg.android.habitica.extensions.notNull import com.habitrpg.android.habitica.models.inventory.Customization import com.habitrpg.android.habitica.models.inventory.CustomizationSet import com.habitrpg.android.habitica.ui.fragments.NavigationDrawerFragment import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper +import io.reactivex.BackpressureStrategy +import io.reactivex.Flowable +import io.reactivex.subjects.PublishSubject import org.greenrobot.eventbus.EventBus -import rx.Observable -import rx.subjects.PublishSubject import java.util.* class CustomizationRecyclerViewAdapter : RecyclerView.Adapter() { @@ -120,16 +122,16 @@ class CustomizationRecyclerViewAdapter : RecyclerView.Adapter { - return selectCustomizationEvents.asObservable() + fun getSelectCustomizationEvents(): Flowable { + return selectCustomizationEvents.toFlowable(BackpressureStrategy.DROP) } - fun getUnlockCustomizationEvents(): Observable { - return unlockCustomizationEvents.asObservable() + fun getUnlockCustomizationEvents(): Flowable { + return unlockCustomizationEvents.toFlowable(BackpressureStrategy.DROP) } - fun getUnlockSetEvents(): Observable { - return unlockSetEvents.asObservable() + fun getUnlockSetEvents(): Flowable { + return unlockSetEvents.toFlowable(BackpressureStrategy.DROP) } internal inner class CustomizationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener { @@ -184,7 +186,10 @@ class CustomizationRecyclerViewAdapter : RecyclerView.Adapter { @@ -68,8 +69,8 @@ public class FAQOverviewRecyclerAdapter extends RecyclerView.Adapter getResetWalkthroughEvents() { - return resetWalkthroughEvents.asObservable(); + public Flowable getResetWalkthroughEvents() { + return resetWalkthroughEvents.toFlowable(BackpressureStrategy.DROP); } class FAQArticleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/NavigationDrawerAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/NavigationDrawerAdapter.kt index 89947b9cd..acecca657 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/NavigationDrawerAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/NavigationDrawerAdapter.kt @@ -1,22 +1,19 @@ package com.habitrpg.android.habitica.ui.adapter -import android.content.Context -import android.graphics.PorterDuff import android.support.v4.content.ContextCompat +import android.support.v4.graphics.drawable.DrawableCompat import android.support.v7.widget.RecyclerView import android.view.View import android.view.ViewGroup import android.widget.TextView import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.extensions.backgroundCompat import com.habitrpg.android.habitica.extensions.bindOptionalView import com.habitrpg.android.habitica.extensions.inflate import com.habitrpg.android.habitica.ui.menu.HabiticaDrawerItem -import rx.Observable -import rx.subjects.PublishSubject -import android.support.v4.graphics.drawable.DrawableCompat.setTint -import android.graphics.drawable.Drawable -import android.support.v4.graphics.drawable.DrawableCompat -import com.habitrpg.android.habitica.extensions.backgroundCompat +import io.reactivex.BackpressureStrategy +import io.reactivex.Flowable +import io.reactivex.subjects.PublishSubject class NavigationDrawerAdapter(tintColor: Int, backgroundTintColor: Int): RecyclerView.Adapter() { @@ -44,12 +41,12 @@ class NavigationDrawerAdapter(tintColor: Int, backgroundTintColor: Int): Recycle private val itemSelectedEvents = PublishSubject.create() - fun getItemSelectionEvents(): Observable = itemSelectedEvents.asObservable() + fun getItemSelectionEvents(): Flowable = itemSelectedEvents.toFlowable(BackpressureStrategy.DROP) fun getItemWithIdentifier(identifier: String): HabiticaDrawerItem? = items.find { it.identifier == identifier } - fun getItemPosition(identifier: String): Int = + private fun getItemPosition(identifier: String): Int = items.indexOfFirst { it.identifier == identifier } fun updateItem(item: HabiticaDrawerItem) { @@ -85,9 +82,9 @@ class NavigationDrawerAdapter(tintColor: Int, backgroundTintColor: Int): Recycle override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return if (viewType == 0) { - DrawerItemViewHolder(parent?.inflate(R.layout.drawer_main_item)) + DrawerItemViewHolder(parent.inflate(R.layout.drawer_main_item)) } else { - SectionHeaderViewHolder(parent?.inflate(R.layout.drawer_main_section_header)) + SectionHeaderViewHolder(parent.inflate(R.layout.drawer_main_section_header)) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/SkillTasksRecyclerViewAdapter.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/SkillTasksRecyclerViewAdapter.java index c2ae43c3b..e81a2cfb5 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/SkillTasksRecyclerViewAdapter.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/SkillTasksRecyclerViewAdapter.java @@ -14,10 +14,11 @@ import java.util.UUID; import butterknife.BindView; import butterknife.ButterKnife; +import io.reactivex.BackpressureStrategy; +import io.reactivex.Flowable; +import io.reactivex.subjects.PublishSubject; import io.realm.OrderedRealmCollection; import io.realm.RealmRecyclerViewAdapter; -import rx.Observable; -import rx.subjects.PublishSubject; public class SkillTasksRecyclerViewAdapter extends RealmRecyclerViewAdapter { @@ -53,11 +54,10 @@ public class SkillTasksRecyclerViewAdapter extends RealmRecyclerViewAdapter getTaskSelectionEvents() { - return taskSelectionEvents.asObservable(); + public Flowable getTaskSelectionEvents() { + return taskSelectionEvents.toFlowable(BackpressureStrategy.DROP); } - public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public Task task; diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/EquipmentRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/EquipmentRecyclerViewAdapter.kt index f92c89db5..6292393bc 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/EquipmentRecyclerViewAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/EquipmentRecyclerViewAdapter.kt @@ -1,26 +1,20 @@ package com.habitrpg.android.habitica.ui.adapter.inventory import android.content.Context -import android.net.Uri import android.support.v4.content.ContextCompat import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView - import com.facebook.drawee.view.SimpleDraweeView import com.habitrpg.android.habitica.R -import com.habitrpg.android.habitica.models.inventory.Equipment - -import butterknife.BindView -import butterknife.ButterKnife import com.habitrpg.android.habitica.extensions.bindView +import com.habitrpg.android.habitica.models.inventory.Equipment import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils +import io.reactivex.subjects.PublishSubject import io.realm.OrderedRealmCollection import io.realm.RealmRecyclerViewAdapter -import rx.Observable -import rx.subjects.PublishSubject class EquipmentRecyclerViewAdapter(data: OrderedRealmCollection?, autoUpdate: Boolean) : RealmRecyclerViewAdapter(data, autoUpdate) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ItemRecyclerAdapter.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ItemRecyclerAdapter.java index 7ad993589..23949d76e 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ItemRecyclerAdapter.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ItemRecyclerAdapter.java @@ -30,11 +30,12 @@ import org.greenrobot.eventbus.EventBus; import butterknife.BindView; import butterknife.ButterKnife; +import io.reactivex.BackpressureStrategy; +import io.reactivex.Flowable; +import io.reactivex.subjects.PublishSubject; import io.realm.OrderedRealmCollection; import io.realm.RealmRecyclerViewAdapter; import io.realm.RealmResults; -import rx.Observable; -import rx.subjects.PublishSubject; public class ItemRecyclerAdapter extends RealmRecyclerViewAdapter { @@ -53,8 +54,8 @@ public class ItemRecyclerAdapter extends RealmRecyclerViewAdapter getSellItemEvents() { - return sellItemEvents.asObservable(); + public Flowable getSellItemEvents() { + return sellItemEvents.toFlowable(BackpressureStrategy.DROP); } @Override @@ -77,8 +78,8 @@ public class ItemRecyclerAdapter extends RealmRecyclerViewAdapter getQuestInvitationEvents() { - return questInvitationEvents.asObservable(); + public Flowable getQuestInvitationEvents() { + return questInvitationEvents.toFlowable(BackpressureStrategy.DROP); } class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/MountDetailRecyclerAdapter.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/MountDetailRecyclerAdapter.java index 16d2e74a0..bdd91aff3 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/MountDetailRecyclerAdapter.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/MountDetailRecyclerAdapter.java @@ -19,10 +19,11 @@ import com.habitrpg.android.habitica.ui.menu.BottomSheetMenuItem; import butterknife.BindView; import butterknife.ButterKnife; +import io.reactivex.BackpressureStrategy; +import io.reactivex.Flowable; +import io.reactivex.subjects.PublishSubject; import io.realm.OrderedRealmCollection; import io.realm.RealmRecyclerViewAdapter; -import rx.Observable; -import rx.subjects.PublishSubject; public class MountDetailRecyclerAdapter extends RealmRecyclerViewAdapter { @@ -36,8 +37,8 @@ public class MountDetailRecyclerAdapter extends RealmRecyclerViewAdapter getEquipEvents() { - return equipEvents.asObservable(); + public Flowable getEquipEvents() { + return equipEvents.toFlowable(BackpressureStrategy.DROP); } @Override diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.java index 84e0bd916..6e2ac0fcb 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.java @@ -24,11 +24,12 @@ import org.greenrobot.eventbus.EventBus; import butterknife.BindView; import butterknife.ButterKnife; +import io.reactivex.BackpressureStrategy; +import io.reactivex.Flowable; +import io.reactivex.subjects.PublishSubject; import io.realm.OrderedRealmCollection; import io.realm.RealmRecyclerViewAdapter; import io.realm.RealmResults; -import rx.Observable; -import rx.subjects.PublishSubject; public class PetDetailRecyclerAdapter extends RealmRecyclerViewAdapter { @@ -41,8 +42,8 @@ public class PetDetailRecyclerAdapter extends RealmRecyclerViewAdapter getEquipEvents() { - return equipEvents.asObservable(); + public Flowable getEquipEvents() { + return equipEvents.toFlowable(BackpressureStrategy.DROP); } @Override diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ShopRecyclerAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ShopRecyclerAdapter.kt index 6e24d4b93..1c1171fd9 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ShopRecyclerAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ShopRecyclerAdapter.kt @@ -1,37 +1,26 @@ package com.habitrpg.android.habitica.ui.adapter.inventory import android.content.Context -import android.graphics.Bitmap -import android.graphics.Shader -import android.graphics.drawable.BitmapDrawable import android.support.v7.widget.RecyclerView import android.text.Html import android.text.method.LinkMovementMethod import android.view.View import android.view.ViewGroup import android.widget.Button -import android.widget.ImageView import android.widget.TextView -import com.facebook.drawee.view.SimpleDraweeView import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.events.commands.OpenGemPurchaseFragmentCommand -import com.habitrpg.android.habitica.extensions.backgroundCompat import com.habitrpg.android.habitica.extensions.bindView import com.habitrpg.android.habitica.extensions.inflate -import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.inventory.Item import com.habitrpg.android.habitica.models.shops.Shop import com.habitrpg.android.habitica.models.shops.ShopCategory import com.habitrpg.android.habitica.models.shops.ShopItem import com.habitrpg.android.habitica.models.user.User -import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils import com.habitrpg.android.habitica.ui.viewHolders.SectionViewHolder import com.habitrpg.android.habitica.ui.viewHolders.ShopItemViewHolder import com.habitrpg.android.habitica.ui.views.NPCBannerView import org.greenrobot.eventbus.EventBus -import rx.Observable -import rx.android.schedulers.AndroidSchedulers -import rx.functions.Action1 class ShopRecyclerAdapter : RecyclerView.Adapter() { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.java index e3a73d2ae..a8a2e1813 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.java @@ -28,12 +28,14 @@ import java.lang.reflect.Field; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; +import io.reactivex.BackpressureStrategy; +import io.reactivex.Flowable; +import io.reactivex.Maybe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; +import io.reactivex.subjects.PublishSubject; import io.realm.OrderedRealmCollection; import io.realm.RealmRecyclerViewAdapter; -import rx.Observable; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; -import rx.subjects.PublishSubject; public class ChatRecyclerViewAdapter extends RealmRecyclerViewAdapter { @@ -75,32 +77,32 @@ public class ChatRecyclerViewAdapter extends RealmRecyclerViewAdapter getLikeMessageEvents() { - return likeMessageEvents.asObservable(); + public Flowable getLikeMessageEvents() { + return likeMessageEvents.toFlowable(BackpressureStrategy.DROP); } - public Observable getUserLabelClickEvents() { - return userLabelClickEvents.asObservable(); + public Flowable getUserLabelClickEvents() { + return userLabelClickEvents.toFlowable(BackpressureStrategy.DROP); } - public Observable getPrivateMessageClickEvents() { - return privateMessageClickEvents.asObservable(); + public Flowable getPrivateMessageClickEvents() { + return privateMessageClickEvents.toFlowable(BackpressureStrategy.DROP); } - public Observable getDeleteMessageEvents() { - return deleteMessageEvents.asObservable(); + public Flowable getDeleteMessageEvents() { + return deleteMessageEvents.toFlowable(BackpressureStrategy.DROP); } - public Observable getFlagMessageEvents() { - return flatMessageEvents.asObservable(); + public Flowable getFlagMessageEvents() { + return flatMessageEvents.toFlowable(BackpressureStrategy.DROP); } - public Observable getCopyMessageAsTodoEvents() { - return copyMessageAsTodoEvents.asObservable(); + public Flowable getCopyMessageAsTodoEvents() { + return copyMessageAsTodoEvents.toFlowable(BackpressureStrategy.DROP); } - public Observable getCopyMessageEvents() { - return copyMessageEvents.asObservable(); + public Flowable getCopyMessageEvents() { + return copyMessageEvents.toFlowable(BackpressureStrategy.DROP); } @@ -177,7 +179,7 @@ public class ChatRecyclerViewAdapter extends RealmRecyclerViewAdapter { @@ -56,8 +57,8 @@ public class PartyMemberRecyclerViewAdapter extends RealmRecyclerViewAdapter getUserClickedEvents() { - return userClickedEvents.asObservable(); + public Flowable getUserClickedEvents() { + return userClickedEvents.toFlowable(BackpressureStrategy.DROP); } class MemberViewHolder extends RecyclerView.ViewHolder { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/challenges/ChallengeTasksRecyclerViewAdapter.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/challenges/ChallengeTasksRecyclerViewAdapter.java index f74ce5bcc..c2808bdc6 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/challenges/ChallengeTasksRecyclerViewAdapter.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/challenges/ChallengeTasksRecyclerViewAdapter.java @@ -21,8 +21,9 @@ import com.habitrpg.android.habitica.ui.viewHolders.tasks.TodoViewHolder; import java.util.List; -import rx.Observable; -import rx.subjects.PublishSubject; +import io.reactivex.BackpressureStrategy; +import io.reactivex.Flowable; +import io.reactivex.subjects.PublishSubject; public class ChallengeTasksRecyclerViewAdapter extends SortableTasksRecyclerViewAdapter { @@ -84,8 +85,8 @@ public class ChallengeTasksRecyclerViewAdapter return TYPE_HEADER; } - public Observable addItemObservable(){ - return addItemSubject; + public Flowable addItemObservable(){ + return addItemSubject.toFlowable(BackpressureStrategy.BUFFER); } public int addTaskUnder(Task taskToAdd, Task taskAbove) { @@ -165,7 +166,7 @@ public class ChallengeTasksRecyclerViewAdapter addBtn = (Button) itemView.findViewById(R.id.btn_add_task); addBtn.setClickable(true); addBtn.setOnClickListener(view -> callback.onNext(newTask)); - context = itemView.getContext(); + setContext(itemView.getContext()); } @Override @@ -184,7 +185,7 @@ public class ChallengeTasksRecyclerViewAdapter divider_name = (TextView) itemView.findViewById(R.id.divider_name); - context = itemView.getContext(); + setContext(itemView.getContext()); } @Override diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/BaseTasksRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/BaseTasksRecyclerViewAdapter.kt index 4483bbf8a..a5fd11377 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/BaseTasksRecyclerViewAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/BaseTasksRecyclerViewAdapter.kt @@ -5,7 +5,6 @@ import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup - import com.habitrpg.android.habitica.HabiticaBaseApplication import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.data.TaskRepository @@ -14,18 +13,13 @@ import com.habitrpg.android.habitica.helpers.TaskFilterHelper import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.android.habitica.proxy.CrashlyticsProxy import com.habitrpg.android.habitica.ui.viewHolders.tasks.BaseTaskViewHolder -import io.realm.RealmResults - -import java.util.ArrayList - +import io.reactivex.Flowable +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.functions.Consumer +import io.reactivex.schedulers.Schedulers +import java.util.* import javax.inject.Inject -import rx.Observable -import rx.android.schedulers.AndroidSchedulers -import rx.functions.Action1 -import rx.functions.Func1 -import rx.schedulers.Schedulers - abstract class BaseTasksRecyclerViewAdapter(var taskType: String, private val taskFilterHelper: TaskFilterHelper?, private val layoutResource: Int, newContext: Context, private val userID: String?) : RecyclerView.Adapter() { @Inject @@ -101,8 +95,8 @@ abstract class BaseTasksRecyclerViewAdapter(var taskTyp fun loadContent(forced: Boolean) { if (this.content == null || forced) { - taskRepository!!.getTasks(this.taskType, this.userID!!) - .flatMap({ Observable.from(it) }) + taskRepository.getTasks(this.taskType, this.userID!!) + .flatMap { Flowable.fromIterable(it) } .map { task -> task.parseMarkdown() task @@ -110,7 +104,7 @@ abstract class BaseTasksRecyclerViewAdapter(var taskTyp .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .toList() - .subscribe(Action1 { this.setTasks(it) }, RxErrorHandler.handleEmptyError()) + .subscribe(Consumer { this.setTasks(it) }, RxErrorHandler.handleEmptyError()) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RealmBaseTasksRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RealmBaseTasksRecyclerViewAdapter.kt index d61ccd1c1..b946bf169 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RealmBaseTasksRecyclerViewAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RealmBaseTasksRecyclerViewAdapter.kt @@ -147,7 +147,7 @@ abstract class RealmBaseTasksRecyclerViewAdapter(privat if (taskFilterHelper != null) { val query = taskFilterHelper.createQuery(unfilteredData) - updateData(query.findAllSorted("position")) + updateData(query.sort("position").findAll()) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseFragment.kt index 103744e41..9cf7d4432 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseFragment.kt @@ -15,11 +15,11 @@ import com.habitrpg.android.habitica.data.TutorialRepository import com.habitrpg.android.habitica.events.DisplayTutorialEvent import com.habitrpg.android.habitica.helpers.AmplitudeManager import com.habitrpg.android.habitica.helpers.RxErrorHandler +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.functions.Consumer import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBusException -import rx.android.schedulers.AndroidSchedulers -import rx.functions.Action1 -import rx.subscriptions.CompositeSubscription import java.util.* import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -35,7 +35,7 @@ abstract class BaseFragment : DialogFragment() { protected var tutorialCanBeDeferred = true var tutorialTexts: MutableList = ArrayList() - protected var compositeSubscription: CompositeSubscription = CompositeSubscription() + protected var compositeSubscription: CompositeDisposable = CompositeDisposable() open val displayedClassName: String? get() = this.javaClass.simpleName @@ -52,7 +52,7 @@ abstract class BaseFragment : DialogFragment() { } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - compositeSubscription = CompositeSubscription() + compositeSubscription = CompositeDisposable() // Receive Events try { @@ -83,10 +83,10 @@ abstract class BaseFragment : DialogFragment() { private fun showTutorialIfNeeded() { if (userVisibleHint && view != null) { if (this.tutorialStepIdentifier != null) { - tutorialRepository.getTutorialStep(this.tutorialStepIdentifier!!).first() + tutorialRepository.getTutorialStep(this.tutorialStepIdentifier ?: "").firstElement() .delay(1, TimeUnit.SECONDS) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(Action1 { step -> + .subscribe(Consumer { step -> if (step != null && step.isValid && step.isManaged && step.shouldDisplay()) { val event = DisplayTutorialEvent() event.step = step @@ -105,7 +105,7 @@ abstract class BaseFragment : DialogFragment() { if (displayedClassName != null) { val additionalData = HashMap() - additionalData.put("page", displayedClassName) + additionalData["page"] = displayedClassName AmplitudeManager.sendEvent("navigate", AmplitudeManager.EVENT_CATEGORY_NAVIGATION, AmplitudeManager.EVENT_HITTYPE_PAGEVIEW, additionalData) } } @@ -119,8 +119,8 @@ abstract class BaseFragment : DialogFragment() { unbinder!!.unbind() unbinder = null } - if (!compositeSubscription.isUnsubscribed) { - compositeSubscription.unsubscribe() + if (!compositeSubscription.isDisposed) { + compositeSubscription.dispose() } super.onDestroyView() diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt index a029777c7..c04a5f73a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt @@ -43,10 +43,9 @@ import com.habitrpg.android.habitica.ui.fragments.social.party.PartyFragment import com.habitrpg.android.habitica.ui.fragments.tasks.TasksFragment import com.habitrpg.android.habitica.ui.helpers.NavbarUtils import com.habitrpg.android.habitica.ui.menu.HabiticaDrawerItem +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.drawer_main.* -import kotlinx.android.synthetic.main.fragment_tavern_detail.* -import rx.functions.Action1 -import rx.subscriptions.CompositeSubscription import javax.inject.Inject /** @@ -71,7 +70,7 @@ class NavigationDrawerFragment : DialogFragment() { private lateinit var adapter: NavigationDrawerAdapter - private var subscriptions: CompositeSubscription? = null + private var subscriptions: CompositeDisposable? = null val isDrawerOpen: Boolean get() = drawerLayout?.isDrawerOpen(fragmentContainerView!!) ?: false @@ -144,7 +143,7 @@ class NavigationDrawerFragment : DialogFragment() { } else { NavigationDrawerAdapter(0, 0) } - subscriptions = CompositeSubscription() + subscriptions = CompositeDisposable() HabiticaBaseApplication.getComponent().inject(this) super.onCreate(savedInstanceState) @@ -172,19 +171,19 @@ class NavigationDrawerFragment : DialogFragment() { recyclerView.layoutManager = LinearLayoutManager(context) initializeMenuItems() - subscriptions?.add(adapter.getItemSelectionEvents().subscribe(Action1 { + subscriptions?.add(adapter.getItemSelectionEvents().subscribe(Consumer { setSelection(it, true) }, RxErrorHandler.handleEmptyError())) subscriptions?.add(socialRepository.getGroup(Group.TAVERN_ID) .doOnNext({ quest = it.quest }) .filter { it.hasActiveQuest } - .flatMap { inventoryRepository.getQuestContent(it.quest?.key).first() } - .subscribe(Action1 { + .flatMapMaybe { inventoryRepository.getQuestContent(it.quest?.key).firstElement() } + .subscribe(Consumer { questContent = it }, RxErrorHandler.handleEmptyError())) - subscriptions?.add(userRepository.getUser().subscribe(Action1 { + subscriptions?.add(userRepository.getUser().subscribe(Consumer { setUsername(it.profile.name) avatarView.setAvatar(it) questMenuView.configure(it) @@ -195,7 +194,7 @@ class NavigationDrawerFragment : DialogFragment() { } override fun onDestroy() { - subscriptions?.clear() + subscriptions?.dispose() socialRepository.close() inventoryRepository.close() userRepository.close() diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/StatsFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/StatsFragment.kt index 7528d524b..647ce1e41 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/StatsFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/StatsFragment.kt @@ -1,6 +1,7 @@ package com.habitrpg.android.habitica.ui.fragments import android.app.AlertDialog +import android.os.Build import android.os.Bundle import android.support.v4.content.ContextCompat import android.view.LayoutInflater @@ -18,10 +19,10 @@ import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.helpers.UserStatComputer import com.habitrpg.android.habitica.models.user.Stats import com.habitrpg.android.habitica.modules.AppModule -import com.habitrpg.android.habitica.ui.views.stats.BulkAllocateStatsDialog import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper +import com.habitrpg.android.habitica.ui.views.stats.BulkAllocateStatsDialog +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.fragment_stats.* -import rx.functions.Action1 import java.util.* import javax.inject.Inject import javax.inject.Named @@ -85,7 +86,7 @@ class StatsFragment: BaseMainFragment() { distributeClassHelpButton.setImageBitmap(HabiticaIconsHelper.imageOfInfoIcon()) distributeTaskHelpButton.setImageBitmap(HabiticaIconsHelper.imageOfInfoIcon()) - compositeSubscription.add(userRepository.getUser(userId).subscribe(Action1 { + compositeSubscription.add(userRepository.getUser(userId).subscribe(Consumer { user = it updateStats() updateAttributePoints() @@ -108,7 +109,7 @@ class StatsFragment: BaseMainFragment() { } automaticAllocationSwitch.setOnCheckedChangeListener{ _, isChecked -> - userRepository.updateUser(user, "preferences.automaticAllocation", isChecked).subscribe(Action1 {}, RxErrorHandler.handleEmptyError()) + userRepository.updateUser(user, "preferences.automaticAllocation", isChecked).subscribe(Consumer {}, RxErrorHandler.handleEmptyError()) } strengthStatsView.allocateAction = { allocatePoint(Stats.STRENGTH) } @@ -138,7 +139,7 @@ class StatsFragment: BaseMainFragment() { } private fun changeAutoAllocationMode(@Stats.AutoAllocationTypes allocationMode: String) { - userRepository.updateUser(user, "preferences.allocationMode", allocationMode).subscribe(Action1 {}, RxErrorHandler.handleEmptyError()) + userRepository.updateUser(user, "preferences.allocationMode", allocationMode).subscribe(Consumer {}, RxErrorHandler.handleEmptyError()) distributeEvenlyButton.isChecked = allocationMode == Stats.AUTO_ALLOCATE_FLAT distributeClassButton.isChecked = allocationMode == Stats.AUTO_ALLOCATE_CLASSBASED distributeTaskButton.isChecked = allocationMode == Stats.AUTO_ALLOCATE_TASKBASED @@ -151,7 +152,7 @@ class StatsFragment: BaseMainFragment() { } private fun allocatePoint(@Stats.StatsTypes stat: String) { - userRepository.allocatePoint(user, stat).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + userRepository.allocatePoint(user, stat).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } private fun updateAttributePoints() { @@ -181,7 +182,9 @@ class StatsFragment: BaseMainFragment() { val points = user?.stats?.points ?: 0 numberOfPointsTextView.text = getString(R.string.points_to_allocate, points) numberOfPointsTextView.setTextColor(ContextCompat.getColor(context, R.color.white)) - numberOfPointsTextView.background = ContextCompat.getDrawable(context, R.drawable.button_gray_100) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + numberOfPointsTextView.background = ContextCompat.getDrawable(context, R.drawable.button_gray_100) + } leftSparklesView.visibility = View.VISIBLE rightSparklesView.visibility = View.VISIBLE } else { @@ -242,9 +245,9 @@ class StatsFragment: BaseMainFragment() { outfitList.add(outfit.shield) outfitList.add(outfit.weapon) - inventoryRepository.getItems(outfitList).first() + inventoryRepository.getItems(outfitList).firstElement() .retry(1) - .subscribe(Action1 { + .subscribe(Consumer { val userStatComputer = UserStatComputer() val statsRows = userStatComputer.computeClassBonus(it, user) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt index 4e4a6149c..7244d0f1f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt @@ -17,11 +17,10 @@ import com.habitrpg.android.habitica.ui.adapter.CustomizationRecyclerViewAdapter import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment import com.habitrpg.android.habitica.ui.helpers.MarginDecoration import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator +import io.reactivex.Flowable +import io.reactivex.functions.Consumer import io.realm.RealmResults import kotlinx.android.synthetic.main.fragment_recyclerview.* -import rx.Observable -import rx.functions.Action1 -import java.util.* import javax.inject.Inject class AvatarCustomizationFragment : BaseMainFragment() { @@ -49,27 +48,27 @@ class AvatarCustomizationFragment : BaseMainFragment() { } userRepository.updateUser(user, updatePath, customization.identifier) } - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError())) + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) compositeSubscription.add(adapter.getUnlockCustomizationEvents() .flatMap { customization -> val user = this.user return@flatMap if (user != null) { userRepository.unlockPath(user, customization) } else { - Observable.just(null) + Flowable.empty() } } - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError())) + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) compositeSubscription.add(adapter.getUnlockSetEvents() .flatMap { set -> val user = this.user return@flatMap if (user != null) { userRepository.unlockPath(user, set) } else { - Observable.just(null) + Flowable.empty() } } - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError())) + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) return view @@ -118,10 +117,10 @@ class AvatarCustomizationFragment : BaseMainFragment() { if (user == null) { return } - compositeSubscription.add(customizationRepository.getCustomizations(type, category, true).subscribe(Action1> { adapter.setCustomizations(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(customizationRepository.getCustomizations(type, category, true).subscribe(Consumer> { adapter.setCustomizations(it) }, RxErrorHandler.handleEmptyError())) if (type == "hair" && (category == "beard" || category == "mustache")) { val otherCategory = if (category == "mustache") "beard" else "mustache" - compositeSubscription.add(customizationRepository.getCustomizations(type, otherCategory, true).subscribe(Action1> { adapter.additionalSetItems = it }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(customizationRepository.getCustomizations(type, otherCategory, true).subscribe(Consumer> { adapter.additionalSetItems = it }, RxErrorHandler.handleEmptyError())) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt index a2d4a6aa9..f174b94fd 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt @@ -10,8 +10,8 @@ import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.user.User import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.fragment_avatar_overview.* -import rx.functions.Action1 class AvatarOverviewFragment : BaseMainFragment(), AdapterView.OnItemSelectedListener { @@ -19,8 +19,8 @@ class AvatarOverviewFragment : BaseMainFragment(), AdapterView.OnItemSelectedLis super.onCreate(savedInstanceState) if (apiClient != null) { - apiClient.getContent() - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + apiClient.content + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } } @@ -105,7 +105,7 @@ class AvatarOverviewFragment : BaseMainFragment(), AdapterView.OnItemSelectedLis if (this.user != null && this.user!!.preferences.size != newSize) { userRepository.updateUser(user, "preferences.size", newSize) - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentDetailFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentDetailFragment.kt index 9e5df2fcc..ffbc578a6 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentDetailFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentDetailFragment.kt @@ -15,9 +15,9 @@ import com.habitrpg.android.habitica.models.user.Items import com.habitrpg.android.habitica.ui.adapter.inventory.EquipmentRecyclerViewAdapter import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator +import io.reactivex.functions.Consumer import io.realm.RealmResults import kotlinx.android.synthetic.main.fragment_recyclerview.* -import rx.functions.Action1 import javax.inject.Inject class EquipmentDetailFragment : BaseMainFragment() { @@ -39,8 +39,8 @@ class EquipmentDetailFragment : BaseMainFragment() { this.adapter.equippedGear = this.equippedGear this.adapter.isCostume = this.isCostume this.adapter.type = this.type - this.adapter.equipEvents.flatMap { key -> inventoryRepository.equipGear(user, key, isCostume!!) } - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + this.adapter.equipEvents.flatMapMaybe { key -> inventoryRepository.equipGear(user, key, isCostume ?: false).firstElement() } + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) return v } @@ -52,7 +52,7 @@ class EquipmentDetailFragment : BaseMainFragment() { recyclerView.addItemDecoration(DividerItemDecoration(getActivity()!!, DividerItemDecoration.VERTICAL)) recyclerView.itemAnimator = SafeDefaultItemAnimator() - type?.let { inventoryRepository.getOwnedEquipment(it).first().subscribe(Action1> { this.adapter.updateData(it) }, RxErrorHandler.handleEmptyError()) } + type?.let { inventoryRepository.getOwnedEquipment(it).firstElement().subscribe(Consumer> { this.adapter.updateData(it) }, RxErrorHandler.handleEmptyError()) } } override fun onDestroy() { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentOverviewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentOverviewFragment.kt index ce2840279..53c6c2038 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentOverviewFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentOverviewFragment.kt @@ -8,10 +8,9 @@ import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.data.InventoryRepository import com.habitrpg.android.habitica.helpers.RxErrorHandler -import com.habitrpg.android.habitica.ui.AvatarView import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.fragment_equipment_overview.* -import rx.functions.Action1 import javax.inject.Inject class EquipmentOverviewFragment : BaseMainFragment() { @@ -50,12 +49,12 @@ class EquipmentOverviewFragment : BaseMainFragment() { costumeSwitch.isChecked = user?.preferences?.costume ?: false - costumeSwitch.setOnCheckedChangeListener { _, isChecked -> userRepository.updateUser(user, "preferences.costume", isChecked).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) } + costumeSwitch.setOnCheckedChangeListener { _, isChecked -> userRepository.updateUser(user, "preferences.costume", isChecked).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } setImageNames() if (this.nameMapping.isEmpty()) { - compositeSubscription.add(inventoryRepository.ownedEquipment.subscribe(Action1 { + compositeSubscription.add(inventoryRepository.ownedEquipment.subscribe(Consumer { for (gear in it) { this.nameMapping[gear.key ?: ""] = gear.text } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.java index 1883d158a..3aa06873a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.java @@ -198,7 +198,7 @@ public class ItemRecyclerFragment extends BaseFragment { itemClass = SpecialItem.class; break; } - inventoryRepository.getOwnedItems(itemClass, user).first().subscribe(items -> { + inventoryRepository.getOwnedItems(itemClass, user).firstElement().subscribe(items -> { if (items.size() > 0) { adapter.updateData((OrderedRealmCollection) items); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt index ad7ee167d..130215dab 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt @@ -22,9 +22,10 @@ import com.habitrpg.android.habitica.models.user.User import com.habitrpg.android.habitica.ui.adapter.inventory.ShopRecyclerAdapter import com.habitrpg.android.habitica.ui.fragments.BaseFragment import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator +import io.reactivex.functions.BiFunction +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.fragment_recyclerview.* import org.greenrobot.eventbus.Subscribe -import rx.functions.Action1 import javax.inject.Inject class ShopFragment : BaseFragment() { @@ -109,9 +110,9 @@ class ShopFragment : BaseFragment() { compositeSubscription.add(socialRepository.getGroup(Group.TAVERN_ID) .filter { it.hasActiveQuest } - .filter { it.quest?.rageStrikes?.any { it.key == shopIdentifier } } + .filter { it.quest?.rageStrikes?.any { it.key == shopIdentifier } ?: false } .filter { it.quest?.rageStrikes?.filter { it.key == shopIdentifier }?.get(0)?.wasHit == true } - .subscribe(Action1 { + .subscribe(Consumer { adapter?.shopSpriteSuffix = "_"+it.quest?.key }, RxErrorHandler.handleEmptyError())) @@ -141,7 +142,7 @@ class ShopFragment : BaseFragment() { } shop1 } - .subscribe(Action1 { + .subscribe(Consumer { this.shop = it this.adapter?.setShop(it) }, RxErrorHandler.handleEmptyError()) @@ -150,26 +151,26 @@ class ShopFragment : BaseFragment() { user.notNull { compositeSubscription.add(this.inventoryRepository.getOwnedItems(it) - .subscribe(Action1 { adapter?.setOwnedItems(it) }, RxErrorHandler.handleEmptyError())) + .subscribe(Consumer { adapter?.setOwnedItems(it) }, RxErrorHandler.handleEmptyError())) } compositeSubscription.add(this.inventoryRepository.inAppRewards .map> { it.map { it.key } } - .subscribe(Action1 { adapter?.setPinnedItemKeys(it) }, RxErrorHandler.handleEmptyError())) + .subscribe(Consumer { adapter?.setPinnedItemKeys(it) }, RxErrorHandler.handleEmptyError())) } private fun loadMarketGear() { inventoryRepository.retrieveMarketGear() - .zipWith(inventoryRepository.ownedEquipment.first().map { it.map { it.key } }, { shop, equipment -> + .zipWith(inventoryRepository.ownedEquipment.map { it.map { it.key } }, BiFunction, Shop> { shop, equipment -> for (category in shop.categories) { - val items = category.items.filter({ + val items = category.items.filter { !equipment.contains(it.key) - }).sortedBy { it.locked } + }.sortedBy { it.locked } category.items.clear() category.items.addAll(items) } shop }) - .subscribe(Action1 { + .subscribe(Consumer { this.gearCategories = it.categories adapter?.gearCategories = it.categories }, RxErrorHandler.handleEmptyError()) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/MountDetailRecyclerFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/MountDetailRecyclerFragment.java index 3428ea740..aaa807186 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/MountDetailRecyclerFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/MountDetailRecyclerFragment.java @@ -108,7 +108,7 @@ public class MountDetailRecyclerFragment extends BaseMainFragment { private void loadItems() { if (animalType != null && animalGroup != null) { - inventoryRepository.getMounts(animalType, animalGroup).first().subscribe(adapter::updateData, RxErrorHandler.handleEmptyError()); + inventoryRepository.getMounts(animalType, animalGroup).firstElement().subscribe(adapter::updateData, RxErrorHandler.handleEmptyError()); } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/PetDetailRecyclerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/PetDetailRecyclerFragment.kt index 0ed6df24a..fafa63584 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/PetDetailRecyclerFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/PetDetailRecyclerFragment.kt @@ -2,11 +2,9 @@ package com.habitrpg.android.habitica.ui.fragments.inventory.stable import android.os.Bundle import android.support.v7.widget.GridLayoutManager -import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup - import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.data.InventoryRepository @@ -15,18 +13,15 @@ import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.inventory.Mount import com.habitrpg.android.habitica.models.inventory.Pet import com.habitrpg.android.habitica.models.user.Items -import com.habitrpg.android.habitica.models.user.User import com.habitrpg.android.habitica.ui.adapter.inventory.PetDetailRecyclerAdapter import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemRecyclerFragment import com.habitrpg.android.habitica.ui.helpers.MarginDecoration import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator +import io.reactivex.functions.Consumer import io.realm.RealmResults import kotlinx.android.synthetic.main.fragment_recyclerview.* - import org.greenrobot.eventbus.Subscribe -import rx.functions.Action1 - import javax.inject.Inject class PetDetailRecyclerFragment : BaseMainFragment() { @@ -74,7 +69,7 @@ class PetDetailRecyclerFragment : BaseMainFragment() { compositeSubscription.add(adapter.equipEvents .flatMap { key -> inventoryRepository.equip(user, "pet", key) } - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError())) + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) finalView.post { setGridSpanCount(finalView.width) } } @@ -100,8 +95,8 @@ class PetDetailRecyclerFragment : BaseMainFragment() { private fun loadItems() { if (animalType.isNotEmpty() && animalGroup.isNotEmpty()) { - inventoryRepository.getPets(animalType, animalGroup).first().subscribe(Action1> { adapter.updateData(it) }, RxErrorHandler.handleEmptyError()) - inventoryRepository.getOwnedMounts(animalType, animalGroup).subscribe(Action1> { adapter.setOwnedMounts(it) }, RxErrorHandler.handleEmptyError()) + inventoryRepository.getPets(animalType, animalGroup).firstElement().subscribe(Consumer> { adapter.updateData(it) }, RxErrorHandler.handleEmptyError()) + inventoryRepository.getOwnedMounts(animalType, animalGroup).subscribe(Consumer> { adapter.setOwnedMounts(it) }, RxErrorHandler.handleEmptyError()) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.java index 4889cb6e8..8ff534268 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.java @@ -30,7 +30,8 @@ import javax.inject.Inject; import butterknife.BindView; import butterknife.ButterKnife; -import rx.Observable; +import io.reactivex.Flowable; +import io.reactivex.Single; public class StableRecyclerFragment extends BaseFragment { private static final String ITEM_TYPE_KEY = "CLASS_TYPE_KEY"; @@ -132,18 +133,18 @@ public class StableRecyclerFragment extends BaseFragment { } private void loadItems() { - Observable observable; + Flowable observable; if ("pets".equals(itemType)) { - observable = inventoryRepository.getPets().first().flatMap(Observable::from); + observable = inventoryRepository.getPets().firstElement().toFlowable().flatMap(Flowable::fromIterable); } else { - observable = inventoryRepository.getMounts().first().flatMap(Observable::from); + observable = inventoryRepository.getMounts().firstElement().toFlowable().flatMap(Flowable::fromIterable); } observable.toList().flatMap(unsortedAnimals -> { List items = new ArrayList<>(); if (unsortedAnimals.size() == 0) { - return Observable.just(items); + return Single.just(items); } String lastSectionTitle = ""; @@ -181,7 +182,7 @@ public class StableRecyclerFragment extends BaseFragment { } } } - return Observable.just(items); + return Single.just(items); }).subscribe(items -> adapter.setItemList(items), RxErrorHandler.handleEmptyError()); } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/AuthenticationPreferenceFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/AuthenticationPreferenceFragment.kt index 5e1f28100..6cde9cc67 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/AuthenticationPreferenceFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/AuthenticationPreferenceFragment.kt @@ -22,8 +22,8 @@ import com.habitrpg.android.habitica.extensions.notNull import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.user.User import com.habitrpg.android.habitica.ui.views.subscriptions.SubscriptionDetailsView +import io.reactivex.functions.Consumer import org.greenrobot.eventbus.EventBus -import rx.functions.Action1 class AuthenticationPreferenceFragment: BasePreferencesFragment() { @@ -94,7 +94,7 @@ class AuthenticationPreferenceFragment: BasePreferencesFragment() { .setPositiveButton(R.string.change) { thisDialog, _ -> thisDialog.dismiss() userRepository.updateEmail(emailEditText?.text.toString(), passwordEditText?.text.toString()) - .subscribe(Action1 { + .subscribe(Consumer { configurePreference(findPreference("email"), emailEditText?.text.toString()) }, RxErrorHandler.handleEmptyError()) } @@ -118,7 +118,7 @@ class AuthenticationPreferenceFragment: BasePreferencesFragment() { .setPositiveButton(R.string.change) { thisDialog, _ -> thisDialog.dismiss() userRepository.updateLoginName(loginNameEditText?.text.toString(), passwordEditText?.text.toString()) - .subscribe(Action1 { + .subscribe(Consumer { configurePreference(findPreference("login_name"), loginNameEditText?.text.toString()) }, RxErrorHandler.handleEmptyError()) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/BasePreferencesFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/BasePreferencesFragment.kt index d15962202..8c0e2effd 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/BasePreferencesFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/BasePreferencesFragment.kt @@ -7,8 +7,8 @@ import com.habitrpg.android.habitica.data.UserRepository import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.user.User import com.habitrpg.android.habitica.modules.AppModule -import rx.functions.Action1 -import rx.subscriptions.CompositeSubscription +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.functions.Consumer import javax.inject.Inject import javax.inject.Named @@ -21,19 +21,19 @@ abstract class BasePreferencesFragment : PreferenceFragmentCompat() { internal open var user: User? = null - internal val compositeSubscription = CompositeSubscription() + internal val compositeSubscription = CompositeDisposable() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - userRepository.getUser(userId).first().subscribe(Action1 { + userRepository.getUser(userId).firstElement().subscribe(Consumer { this.user = it }, RxErrorHandler.handleEmptyError()) } override fun onDestroy() { userRepository.close() - compositeSubscription.unsubscribe() + compositeSubscription.dispose() super.onDestroy() } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.kt index 731c3e227..9bd13b18b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.kt @@ -26,7 +26,7 @@ import com.habitrpg.android.habitica.prefs.TimePreference import com.habitrpg.android.habitica.ui.activities.ClassSelectionActivity import com.habitrpg.android.habitica.ui.activities.FixCharacterValuesActivity import com.habitrpg.android.habitica.ui.activities.MainActivity -import rx.functions.Action1 +import io.reactivex.functions.Consumer import java.util.* import javax.inject.Inject @@ -49,7 +49,7 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare val userID = preferenceManager.sharedPreferences.getString(context?.getString(R.string.SP_userID), null) if (userID != null) { - compositeSubscription.add(userRepository.getUser(userID).subscribe(Action1 { this@PreferencesFragment.setUser(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(userRepository.getUser(userID).subscribe(Consumer { this@PreferencesFragment.setUser(it) }, RxErrorHandler.handleEmptyError())) } } @@ -166,7 +166,7 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare val pieces = timeval?.split(":".toRegex())?.dropLastWhile { it.isEmpty() }?.toTypedArray() if (pieces != null) { val hour = Integer.parseInt(pieces[0]) - userRepository.changeCustomDayStart(hour).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + userRepository.changeCustomDayStart(hour).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } } "language" -> { @@ -182,7 +182,7 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare activity?.resources?.updateConfiguration(configuration, activity?.resources?.displayMetrics) userRepository.updateLanguage(user, languageHelper.languageCode) .flatMap { inventoryRepository.retrieveContent(true) } - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { val intent = Intent(activity, MainActivity::class.java) @@ -197,12 +197,12 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare "audioTheme" -> { val newAudioTheme = sharedPreferences.getString(key, "off") userRepository.updateUser(user, "preferences.sound", newAudioTheme) - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) soundManager.soundTheme = newAudioTheme soundManager.preloadAllFiles() } "dailyDueDefaultView" -> userRepository.updateUser(user, "preferences.dailyDueDefaultView", sharedPreferences.getBoolean(key, false)) - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/ProfilePreferencesFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/ProfilePreferencesFragment.kt index c92362f6d..fbd5636c1 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/ProfilePreferencesFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/ProfilePreferencesFragment.kt @@ -8,8 +8,8 @@ import android.support.v7.preference.PreferenceCategory import com.habitrpg.android.habitica.HabiticaBaseApplication import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.user.User -import rx.Observable -import rx.functions.Action1 +import io.reactivex.Flowable +import io.reactivex.functions.Consumer class ProfilePreferencesFragment: BasePreferencesFragment(), SharedPreferences.OnSharedPreferenceChangeListener { @@ -55,13 +55,13 @@ class ProfilePreferencesFragment: BasePreferencesFragment(), SharedPreferences.O val profileCategory = findPreference("profile") as? PreferenceCategory configurePreference(profileCategory?.findPreference(key), sharedPreferences?.getString(key, "")) if (sharedPreferences != null) { - val observable: Observable? = when (key) { + val observable: Flowable? = when (key) { "display_name" -> userRepository.updateUser(user, "profile.name", sharedPreferences.getString(key, "")) "photo_url" -> userRepository.updateUser(user, "profile.photo", sharedPreferences.getString(key, "")) "about" -> userRepository.updateUser(user, "profile.blurb", sharedPreferences.getString(key, "")) else -> null } - observable?.subscribe(Action1 {}, RxErrorHandler.handleEmptyError()) + observable?.subscribe(Consumer {}, RxErrorHandler.handleEmptyError()) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillTasksRecyclerViewFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillTasksRecyclerViewFragment.java index fab7e0174..6607c5758 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillTasksRecyclerViewFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillTasksRecyclerViewFragment.java @@ -22,7 +22,7 @@ import javax.inject.Inject; import javax.inject.Named; import butterknife.BindView; -import rx.Observable; +import io.reactivex.Flowable; public class SkillTasksRecyclerViewFragment extends BaseFragment { @Inject @@ -57,7 +57,7 @@ public class SkillTasksRecyclerViewFragment extends BaseFragment { public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - taskRepository.getTasks(taskType, userId).first().subscribe(tasks -> adapter.updateData(tasks), RxErrorHandler.handleEmptyError()); + taskRepository.getTasks(taskType, userId).firstElement().subscribe(tasks -> adapter.updateData(tasks), RxErrorHandler.handleEmptyError()); recyclerView.setAdapter(adapter); layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); @@ -70,7 +70,7 @@ public class SkillTasksRecyclerViewFragment extends BaseFragment { recyclerView.setItemAnimator(new SafeDefaultItemAnimator()); } - public Observable getTaskSelectionEvents() { + public Flowable getTaskSelectionEvents() { return adapter.getTaskSelectionEvents(); } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillsFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillsFragment.kt index 942a98e35..3572bfd8a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillsFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillsFragment.kt @@ -26,10 +26,12 @@ import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.Companion.showSnackbar +import io.reactivex.Flowable +import io.reactivex.Maybe +import io.reactivex.Observable +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.fragment_skills.* import org.greenrobot.eventbus.Subscribe -import rx.Observable -import rx.functions.Action1 class SkillsFragment : BaseMainFragment() { @@ -73,9 +75,9 @@ class SkillsFragment : BaseMainFragment() { adapter?.mana = this.user?.stats?.getMp() user?.let { - Observable.concat(userRepository.getSkills(it).first().flatMap( { Observable.from(it) }), userRepository.getSpecialItems(it).first().flatMap( { Observable.from(it) })) + Observable.concat(userRepository.getSkills(it).firstElement().toObservable().flatMap { Observable.fromIterable(it) }, userRepository.getSpecialItems(it).firstElement().toObservable().flatMap { Observable.fromIterable(it) }) .toList() - .subscribe(Action1 { skills -> adapter?.setSkillList(skills) }, RxErrorHandler.handleEmptyError()) + .subscribe(Consumer { skills -> adapter?.setSkillList(skills) }, RxErrorHandler.handleEmptyError()) } } @@ -117,7 +119,7 @@ class SkillsFragment : BaseMainFragment() { ContextCompat.getColor(context!!, R.color.blue_10), "-" + usedSkill?.mana, HabiticaSnackbar.SnackbarDisplayType.BLUE) } - userRepository.retrieveUser(false).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + userRepository.retrieveUser(false).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } @@ -145,7 +147,7 @@ class SkillsFragment : BaseMainFragment() { return } displayProgressDialog() - val observable: Observable = if (taskId != null) { + val observable: Flowable = if (taskId != null) { userRepository.useSkill(user, skill.key, skill.target, taskId) } else { userRepository.useSkill(user, skill.key, skill.target) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt index 71a7894c8..03eac3c66 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt @@ -16,6 +16,7 @@ import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.data.SocialRepository import com.habitrpg.android.habitica.data.UserRepository +import com.habitrpg.android.habitica.extensions.notNull import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.social.ChatMessage import com.habitrpg.android.habitica.models.user.User @@ -25,13 +26,13 @@ import com.habitrpg.android.habitica.ui.adapter.social.ChatRecyclerViewAdapter import com.habitrpg.android.habitica.ui.fragments.BaseFragment import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar -import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.Companion.showSnackbar +import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType +import io.reactivex.functions.Action +import io.reactivex.functions.Consumer import io.realm.RealmResults import kotlinx.android.synthetic.main.fragment_chat.* import kotlinx.android.synthetic.main.tavern_chat_new_entry_item.* -import rx.functions.Action0 -import rx.functions.Action1 import javax.inject.Inject class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { @@ -73,7 +74,7 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { if (savedInstanceState.containsKey("userId")) { this.userId = savedInstanceState.getString("userId") if (this.userId != null) { - userRepository.getUser(userId!!).subscribe(Action1 { habitRPGUser -> this.user = habitRPGUser }, RxErrorHandler.handleEmptyError()) + userRepository.getUser(userId!!).subscribe(Consumer { habitRPGUser -> this.user = habitRPGUser }, RxErrorHandler.handleEmptyError()) } } @@ -103,19 +104,22 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { } chatAdapter = ChatRecyclerViewAdapter(null, true, user, true) - compositeSubscription.add(chatAdapter?.userLabelClickEvents?.subscribe(Action1 { userId -> FullProfileActivity.open(context, userId) }, RxErrorHandler.handleEmptyError())) - compositeSubscription.add(chatAdapter?.deleteMessageEvents?.subscribe(Action1 { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError())) - compositeSubscription.add(chatAdapter?.flagMessageEvents?.subscribe(Action1 { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError())) - compositeSubscription.add(chatAdapter?.copyMessageAsTodoEvents?.subscribe(Action1{ this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError())) - compositeSubscription.add(chatAdapter?.copyMessageEvents?.subscribe(Action1 { this.copyMessageToClipboard(it) }, RxErrorHandler.handleEmptyError())) - compositeSubscription.add(chatAdapter?.likeMessageEvents?.flatMap( { socialRepository.likeMessage(it) })?.subscribe(Action1 { }, RxErrorHandler.handleEmptyError())) + chatAdapter.notNull { + compositeSubscription.add(it.userLabelClickEvents.subscribe(Consumer { userId -> FullProfileActivity.open(context, userId) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(it.deleteMessageEvents.subscribe(Consumer { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(it.flagMessageEvents.subscribe(Consumer { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(it.copyMessageAsTodoEvents.subscribe(Consumer{ this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(it.copyMessageEvents.subscribe(Consumer { this.copyMessageToClipboard(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(it.likeMessageEvents.flatMap { socialRepository.likeMessage(it) }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) + } + chatBarView.sendAction = { sendChatMessage(it) } recyclerView.adapter = chatAdapter recyclerView.itemAnimator = SafeDefaultItemAnimator() - socialRepository.getGroupChat(groupId).first().subscribe(Action1> { this.setChatMessages(it) }, RxErrorHandler.handleEmptyError()) + socialRepository.getGroupChat(groupId).firstElement().subscribe(Consumer> { this.setChatMessages(it) }, RxErrorHandler.handleEmptyError()) if (user?.flags?.isCommunityGuidelinesAccepted == true) { communityGuidelinesView.visibility = View.GONE @@ -124,7 +128,7 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { val i = Intent(Intent.ACTION_VIEW) i.data = Uri.parse("https://habitica.com/static/community-guidelines") context?.startActivity(i) - userRepository.updateUser(user, "flags.communityGuidelinesAccepted", true).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + userRepository.updateUser(user, "flags.communityGuidelinesAccepted", true).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } } onRefresh() @@ -133,7 +137,7 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { override fun onRefresh() { refreshLayout.isRefreshing = true - socialRepository.retrieveGroupChat(groupId).subscribe(Action1 {}, RxErrorHandler.handleEmptyError(), Action0 { refreshLayout?.isRefreshing = false }) + socialRepository.retrieveGroupChat(groupId).doOnEvent { _, _ -> refreshLayout?.isRefreshing = false }.subscribe(Consumer {}, RxErrorHandler.handleEmptyError()) } fun setNavigatedToFragment(groupId: String) { @@ -167,7 +171,7 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { builder.setMessage(R.string.chat_flag_confirmation) .setPositiveButton(R.string.flag_confirm) { _, _ -> socialRepository.flagMessage(chatMessage) - .subscribe(Action1 { + .subscribe(Consumer { val activity = activity as MainActivity? showSnackbar(activity!!.getFloatingMenuWrapper(), "Flagged message by " + chatMessage.user, SnackbarDisplayType.NORMAL) }, RxErrorHandler.handleEmptyError()) @@ -184,7 +188,7 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { .setTitle(R.string.confirm_delete_tag_title) .setMessage(R.string.confirm_delete_tag_message) .setIcon(android.R.drawable.ic_dialog_alert) - .setPositiveButton(android.R.string.yes) { _, _ -> socialRepository.deleteMessage(chatMessage).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) } + .setPositiveButton(android.R.string.yes) { _, _ -> socialRepository.deleteMessage(chatMessage).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } .setNegativeButton(android.R.string.no, null).show() } } @@ -216,7 +220,7 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener { } private fun sendChatMessage(chatText: String) { - socialRepository.postGroupChat(groupId, chatText).subscribe(Action1 { + socialRepository.postGroupChat(groupId, chatText).subscribe(Consumer { recyclerView?.scrollToPosition(0) }, RxErrorHandler.handleEmptyError()) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt index 7aca0dd8a..f5f81f686 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt @@ -1,5 +1,10 @@ package com.habitrpg.android.habitica.ui.fragments.social +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.content.Intent +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -14,17 +19,12 @@ import com.habitrpg.android.habitica.models.invitations.PartyInvite import com.habitrpg.android.habitica.models.members.Member import com.habitrpg.android.habitica.models.social.Group import com.habitrpg.android.habitica.models.user.User -import com.habitrpg.android.habitica.ui.fragments.BaseFragment -import kotlinx.android.synthetic.main.fragment_group_info.* -import rx.functions.Action1 -import javax.inject.Inject -import android.content.ClipData -import android.content.ClipboardManager -import android.content.Context import com.habitrpg.android.habitica.ui.activities.MainActivity +import com.habitrpg.android.habitica.ui.fragments.BaseFragment import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar -import android.content.Intent -import android.net.Uri +import io.reactivex.functions.Consumer +import kotlinx.android.synthetic.main.fragment_group_info.* +import javax.inject.Inject class GroupInformationFragment : BaseFragment() { @@ -46,7 +46,7 @@ class GroupInformationFragment : BaseFragment() { if (user != null) { setUser(user) } else { - compositeSubscription.add(userRepository.getUser().subscribe(Action1 { + compositeSubscription.add(userRepository.getUser().subscribe(Consumer { user = it setUser(user) }, RxErrorHandler.handleEmptyError())) @@ -69,7 +69,7 @@ class GroupInformationFragment : BaseFragment() { .flatMap { userRepository.retrieveUser(false) } .flatMap { socialRepository.retrieveGroup("party") } .flatMap> { group1 -> socialRepository.retrieveGroupMembers(group1.id, true) } - .subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } }) @@ -77,7 +77,7 @@ class GroupInformationFragment : BaseFragment() { val userId = user?.invitations?.party?.id if (userId != null) { socialRepository.rejectGroupInvite(userId) - .subscribe(Action1 { setInvitation(null) }, RxErrorHandler.handleEmptyError()) + .subscribe(Consumer { setInvitation(null) }, RxErrorHandler.handleEmptyError()) } }) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildFragment.java index 888e9b21e..246d5f1ac 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildFragment.java @@ -23,8 +23,6 @@ import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment; import javax.inject.Inject; -import rx.functions.Action1; - public class GuildFragment extends BaseMainFragment { @Inject diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxFragment.kt index 957ca2451..77630e6ff 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxFragment.kt @@ -20,9 +20,9 @@ import com.habitrpg.android.habitica.modules.AppModule import com.habitrpg.android.habitica.prefs.scanner.IntentIntegrator import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment import com.habitrpg.android.habitica.ui.helpers.UiUtils +import io.reactivex.functions.Consumer import io.realm.RealmResults import kotlinx.android.synthetic.main.fragment_inbox.* -import rx.functions.Action1 import javax.inject.Inject import javax.inject.Named @@ -39,7 +39,7 @@ class InboxFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshListener, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) - this.socialRepository.markPrivateMessagesRead(user).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + this.socialRepository.markPrivateMessagesRead(user).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) return inflater.inflate(R.layout.fragment_inbox, container, false) } @@ -53,7 +53,7 @@ class InboxFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshListener, } private fun loadMessages() { - userRepository.getInboxOverviewList().subscribe(Action1> { + userRepository.getInboxOverviewList().subscribe(Consumer> { setInboxMessages(it) }, RxErrorHandler.handleEmptyError()) } @@ -115,7 +115,7 @@ class InboxFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshListener, override fun onRefresh() { inbox_refresh_layout.isRefreshing = true this.userRepository.retrieveInboxMessages() - .subscribe(Action1> { + .subscribe(Consumer> { inbox_refresh_layout.isRefreshing = false }, RxErrorHandler.handleEmptyError()) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt index f24d68dcf..d2f40c0de 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt @@ -25,10 +25,10 @@ import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator import com.habitrpg.android.habitica.ui.helpers.UiUtils import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.Companion.showSnackbar +import io.reactivex.functions.Action +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.fragment_inbox_message_list.* import kotlinx.android.synthetic.main.tavern_chat_new_entry_item.* -import rx.functions.Action0 -import rx.functions.Action1 import javax.inject.Inject class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshListener { @@ -60,11 +60,14 @@ class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefres chatAdapter?.setSendingUser(this.user) recyclerView.adapter = chatAdapter recyclerView.itemAnimator = SafeDefaultItemAnimator() - compositeSubscription.add(chatAdapter?.userLabelClickEvents?.subscribe(Action1 { FullProfileActivity.open(context, it) }, RxErrorHandler.handleEmptyError())) - compositeSubscription.add(chatAdapter?.deleteMessageEvents?.subscribe(Action1 { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError())) - compositeSubscription.add(chatAdapter?.flagMessageEvents?.subscribe(Action1 { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError())) - compositeSubscription.add(chatAdapter?.copyMessageAsTodoEvents?.subscribe(Action1 { this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError())) - compositeSubscription.add(chatAdapter?.copyMessageEvents?.subscribe(Action1 { this.copyMessageToClipboard(it) }, RxErrorHandler.handleEmptyError())) + chatAdapter.notNull { + compositeSubscription.add(it.userLabelClickEvents.subscribe(Consumer { FullProfileActivity.open(context, it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(it.deleteMessageEvents.subscribe(Consumer { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(it.flagMessageEvents.subscribe(Consumer { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(it.copyMessageAsTodoEvents.subscribe(Consumer { this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(it.copyMessageEvents.subscribe(Consumer { this.copyMessageToClipboard(it) }, RxErrorHandler.handleEmptyError())) + } + chatBarView.sendAction = { sendMessage(it) } @@ -84,8 +87,8 @@ class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefres private fun loadMessages() { if (user?.isManaged == true) { userRepository.getInboxMessages(replyToUserUUID) - .first() - .subscribe(Action1 { this.chatAdapter?.updateData(it) }, RxErrorHandler.handleEmptyError()) + .firstElement() + .subscribe(Consumer { this.chatAdapter?.updateData(it) }, RxErrorHandler.handleEmptyError()) } } @@ -107,9 +110,9 @@ class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefres private fun refreshUserInbox() { this.swipeRefreshLayout?.isRefreshing = true this.userRepository.retrieveUser(true) - .subscribe(Action1 { + .subscribe(Consumer { user = it - }, RxErrorHandler.handleEmptyError(), Action0 { + }, RxErrorHandler.handleEmptyError(), Action { swipeRefreshLayout?.isRefreshing = false }) } @@ -121,7 +124,7 @@ class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefres private fun sendMessage(chatText: String) { replyToUserUUID?.notNull { socialRepository.postPrivateMessage(it, chatText) - .subscribe(Action1 { this.refreshUserInbox() }, RxErrorHandler.handleEmptyError()) + .subscribe(Consumer { this.refreshUserInbox() }, RxErrorHandler.handleEmptyError()) UiUtils.dismissKeyboard(getActivity()) } } @@ -146,7 +149,7 @@ class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefres builder.setMessage(R.string.chat_flag_confirmation) .setPositiveButton(R.string.flag_confirm) { _, _ -> socialRepository.flagMessage(chatMessage) - .subscribe(Action1 { + .subscribe(Consumer { val activity = getActivity() as MainActivity? showSnackbar(activity!!.getFloatingMenuWrapper(), "Flagged message by " + chatMessage.user, HabiticaSnackbar.SnackbarDisplayType.NORMAL) }, RxErrorHandler.handleEmptyError()) @@ -162,7 +165,7 @@ class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefres .setTitle(R.string.confirm_delete_tag_title) .setMessage(R.string.confirm_delete_tag_message) .setIcon(android.R.drawable.ic_dialog_alert) - .setPositiveButton(android.R.string.yes) { _, _ -> socialRepository.deleteMessage(chatMessage).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) } + .setPositiveButton(android.R.string.yes) { _, _ -> socialRepository.deleteMessage(chatMessage).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } .setNegativeButton(android.R.string.no, null).show() } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/PublicGuildsFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/PublicGuildsFragment.java index 4b920f19f..ed347b46e 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/PublicGuildsFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/PublicGuildsFragment.java @@ -80,7 +80,7 @@ public class PublicGuildsFragment extends BaseMainFragment implements SearchView private void fetchGuilds() { if (this.socialRepository != null) { this.socialRepository.getPublicGuilds() - .first() + .firstElement() .subscribe(groups -> { if (PublicGuildsFragment.this.viewAdapter != null) { PublicGuildsFragment.this.viewAdapter.updateData(groups); @@ -96,7 +96,7 @@ public class PublicGuildsFragment extends BaseMainFragment implements SearchView MenuItem searchItem = menu.findItem(R.id.action_guild_search); SearchView guildSearchView = (SearchView) searchItem.getActionView(); - SearchView.SearchAutoComplete theTextArea = (SearchView.SearchAutoComplete) guildSearchView.findViewById(R.id.search_src_text); + SearchView.SearchAutoComplete theTextArea = guildSearchView.findViewById(R.id.search_src_text); theTextArea.setHintTextColor(ContextCompat.getColor(getContext(), R.color.white)); guildSearchView.setQueryHint(getString(R.string.guild_search_hint)); guildSearchView.setOnQueryTextListener(this); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/QuestDetailFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/QuestDetailFragment.java index ff0011d74..1908eb463 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/QuestDetailFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/QuestDetailFragment.java @@ -115,7 +115,7 @@ public class QuestDetailFragment extends BaseMainFragment { party = group; quest = group.getQuest(); setQuestParticipants(group.getQuest().getParticipants()); - socialRepository.getMember(quest.getLeader()).first().subscribe(member -> { + socialRepository.getMember(quest.getLeader()).firstElement().subscribe(member -> { if (getContext() != null && questLeaderView != null && member != null) { questLeaderView.setText(getContext().getString(R.string.quest_leader_header, member.getDisplayName())); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernDetailFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernDetailFragment.kt index 3992727a1..ebb20e461 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernDetailFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernDetailFragment.kt @@ -2,64 +2,42 @@ package com.habitrpg.android.habitica.ui.fragments.social import android.content.Context import android.content.Intent -import android.graphics.Bitmap import android.graphics.PorterDuff -import android.graphics.Shader -import android.graphics.drawable.BitmapDrawable import android.net.Uri -import android.os.Build import android.os.Bundle import android.support.v4.content.ContextCompat import android.support.v7.app.AlertDialog -import android.util.Log import android.view.Gravity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.FrameLayout -import android.widget.ImageView import android.widget.TextView - import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.AppComponent -import com.habitrpg.android.habitica.data.UserRepository -import com.habitrpg.android.habitica.helpers.RxErrorHandler -import com.habitrpg.android.habitica.models.user.User -import com.habitrpg.android.habitica.modules.AppModule -import com.habitrpg.android.habitica.ui.fragments.BaseFragment - -import javax.inject.Inject -import javax.inject.Named - -import com.facebook.common.executors.CallerThreadExecutor -import com.facebook.common.references.CloseableReference -import com.facebook.datasource.DataSource -import com.facebook.drawee.backends.pipeline.Fresco -import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber -import com.facebook.imagepipeline.image.CloseableImage -import com.facebook.imagepipeline.request.ImageRequestBuilder import com.habitrpg.android.habitica.data.InventoryRepository import com.habitrpg.android.habitica.data.SocialRepository +import com.habitrpg.android.habitica.data.UserRepository import com.habitrpg.android.habitica.events.commands.OpenMenuItemCommand import com.habitrpg.android.habitica.extensions.backgroundCompat -import com.habitrpg.android.habitica.extensions.layoutInflater import com.habitrpg.android.habitica.extensions.notNull import com.habitrpg.android.habitica.helpers.RemoteConfigManager -import com.habitrpg.android.habitica.models.inventory.Quest +import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.inventory.QuestContent import com.habitrpg.android.habitica.models.members.PlayerTier import com.habitrpg.android.habitica.models.social.Group +import com.habitrpg.android.habitica.models.user.User +import com.habitrpg.android.habitica.modules.AppModule +import com.habitrpg.android.habitica.ui.fragments.BaseFragment import com.habitrpg.android.habitica.ui.fragments.NavigationDrawerFragment -import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils import com.habitrpg.android.habitica.ui.views.HabiticaAlertDialog import com.habitrpg.android.habitica.ui.views.social.UsernameLabel -import kotlinx.android.synthetic.main.shop_header.* +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.fragment_tavern_detail.* +import kotlinx.android.synthetic.main.shop_header.* import org.greenrobot.eventbus.EventBus -import org.w3c.dom.Text -import rx.Observable -import rx.android.schedulers.AndroidSchedulers -import rx.functions.Action1 +import javax.inject.Inject +import javax.inject.Named class TavernDetailFragment : BaseFragment() { @@ -89,7 +67,7 @@ class TavernDetailFragment : BaseFragment() { shopSpriteSuffix = configManager.shopSpriteSuffix() - compositeSubscription.add(userRepository.getUser(userId).subscribe(Action1 { + compositeSubscription.add(userRepository.getUser(userId).subscribe(Consumer { this.user = it this.updatePausedState() }, RxErrorHandler.handleEmptyError())) @@ -107,8 +85,8 @@ class TavernDetailFragment : BaseFragment() { .doOnNext { if (!it.hasActiveQuest) worldBossSection.visibility = View.GONE } .filter { it.hasActiveQuest } .doOnNext { questProgressView.progress = it.quest} - .flatMap { inventoryRepository.getQuestContent(it.quest?.key).first() } - .subscribe(Action1 { + .flatMapMaybe { inventoryRepository.getQuestContent(it.quest?.key).firstElement() } + .subscribe(Consumer { questProgressView.quest = it worldBossSection.visibility = View.VISIBLE }, RxErrorHandler.handleEmptyError())) @@ -116,16 +94,16 @@ class TavernDetailFragment : BaseFragment() { compositeSubscription.add(socialRepository.getGroup(Group.TAVERN_ID) .filter { it.hasActiveQuest } .doOnNext { descriptionView.setText(R.string.tavern_description_world_boss) } - .filter { it.quest?.rageStrikes?.any { it.key == "tavern" } } + .filter { it.quest?.rageStrikes?.any { it.key == "tavern" } ?: false } .filter { it.quest?.rageStrikes?.filter { it.key == "tavern" }?.get(0)?.wasHit == true } - .subscribe(Action1 { + .subscribe(Consumer { val key = it.quest?.key if (key != null) { shopSpriteSuffix = key } }, RxErrorHandler.handleEmptyError())) - socialRepository.retrieveGroup(Group.TAVERN_ID).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + socialRepository.retrieveGroup(Group.TAVERN_ID).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) user.notNull { questProgressView.configure(it) } } @@ -139,7 +117,7 @@ class TavernDetailFragment : BaseFragment() { private fun bindButtons() { innButton.setOnClickListener { - user?.notNull { userRepository.sleep(it).subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) } + user?.notNull { userRepository.sleep(it).subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } } guidelinesButton.setOnClickListener { val i = Intent(Intent.ACTION_VIEW) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernFragment.kt index 79b8d504a..50b03f62d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernFragment.kt @@ -9,11 +9,9 @@ import android.view.ViewGroup import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.data.SocialRepository -import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.social.Group import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment import kotlinx.android.synthetic.main.fragment_viewpager.* -import rx.functions.Action1 import javax.inject.Inject class TavernFragment : BaseMainFragment() { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailDialogHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailDialogHolder.java index c8970e86d..f17b687e9 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailDialogHolder.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailDialogHolder.java @@ -21,6 +21,7 @@ import com.habitrpg.android.habitica.ui.activities.ChallengeDetailActivity; import com.habitrpg.android.habitica.ui.activities.FullProfileActivity; import com.habitrpg.android.habitica.ui.helpers.MarkdownParser; import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper; +import com.habitrpg.android.habitica.utils.Action1; import net.pherth.android.emoji_library.EmojiParser; import net.pherth.android.emoji_library.EmojiTextView; @@ -31,7 +32,6 @@ import java.util.Map; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; -import rx.functions.Action1; public class ChallengeDetailDialogHolder { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeFilterDialogHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeFilterDialogHolder.java index 875a297dc..2733f0794 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeFilterDialogHolder.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeFilterDialogHolder.java @@ -13,6 +13,7 @@ import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.models.social.Challenge; import com.habitrpg.android.habitica.models.social.Group; import com.habitrpg.android.habitica.ui.adapter.social.challenges.ChallengesFilterRecyclerViewAdapter; +import com.habitrpg.android.habitica.utils.Action1; import java.util.Collection; import java.util.HashMap; @@ -22,7 +23,6 @@ import java.util.Map; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; -import rx.functions.Action1; class ChallengeFilterDialogHolder { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.java index aa7f0cd76..72dbbf379 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.java @@ -32,8 +32,8 @@ import javax.inject.Named; import butterknife.BindView; import butterknife.ButterKnife; +import io.reactivex.Flowable; import io.realm.RealmResults; -import rx.Observable; public class ChallengeListFragment extends BaseMainFragment implements SwipeRefreshLayout.OnRefreshListener { @@ -109,7 +109,7 @@ public class ChallengeListFragment extends BaseMainFragment implements SwipeRefr } private void loadLocalChallenges() { - Observable> observable; + Flowable> observable; if (viewUserChallengesOnly && user != null) { observable = challengeRepository.getUserChallenges(user.getId()); @@ -117,7 +117,7 @@ public class ChallengeListFragment extends BaseMainFragment implements SwipeRefr observable = challengeRepository.getChallenges(); } - observable.first().subscribe(challenges -> { + observable.firstElement().subscribe(challenges -> { if (challenges.size() == 0) { fetchOnlineChallenges(); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengesOverviewFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengesOverviewFragment.java index 2f310ea78..54abf0720 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengesOverviewFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengesOverviewFragment.java @@ -108,7 +108,7 @@ public class ChallengesOverviewFragment extends BaseMainFragment { @Subscribe public void onEvent(ShowChallengeDetailDialogCommand cmd) { - challengeRepository.getChallenge(cmd.challengeId).first().subscribe(challenge -> ChallengeDetailDialogHolder.showDialog(getActivity(), challengeRepository, challenge, + challengeRepository.getChallenge(cmd.challengeId).firstElement().subscribe(challenge -> ChallengeDetailDialogHolder.showDialog(getActivity(), challengeRepository, challenge, challenge1 -> { // challenge left }), RxErrorHandler.handleEmptyError()); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.java index 62a0701b4..8b7b3b586 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.java @@ -152,7 +152,7 @@ public class PartyDetailFragment extends BaseFragment { questImageWrapper.setVisibility(View.VISIBLE); Handler mainHandler = new Handler(getContext().getMainLooper()); mainHandler.postDelayed(() -> inventoryRepository.getQuestContent(quest.getKey()) - .first() + .firstElement() .subscribe(PartyDetailFragment.this::updateQuestContent, RxErrorHandler.handleEmptyError()), 500); } else { newQuestButton.setVisibility(View.VISIBLE); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.java index dc427e692..3e9d5492f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.java @@ -37,8 +37,7 @@ import java.util.concurrent.TimeUnit; import javax.inject.Inject; -import rx.android.schedulers.AndroidSchedulers; - +import io.reactivex.android.schedulers.AndroidSchedulers; public class PartyFragment extends BaseMainFragment { @@ -71,7 +70,7 @@ public class PartyFragment extends BaseMainFragment { if (userHasParty()) { if (user != null) { getCompositeSubscription().add(socialRepository.getGroup(user.getParty().getId()) - .first() + .firstElement() //delay, so that realm can save party first .delay(500, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyMemberListFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyMemberListFragment.java index e269e2363..85ea0da6a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyMemberListFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyMemberListFragment.java @@ -85,7 +85,7 @@ public class PartyMemberListFragment extends BaseFragment { if (partyId == null) { return; } - socialRepository.getGroupMembers(partyId).first().subscribe(users -> { + socialRepository.getGroupMembers(partyId).firstElement().subscribe(users -> { if (adapter != null) { adapter.updateData(users); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt index 79e97bc02..e68887cbd 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt @@ -15,14 +15,14 @@ import com.habitrpg.android.habitica.models.shops.ShopItem import com.habitrpg.android.habitica.models.user.User import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.fragment_refresh_recyclerview.* -import rx.functions.Action1 import java.util.* class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - inventoryRepository.retrieveInAppRewards().subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + inventoryRepository.retrieveInAppRewards().subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) return super.onCreateView(inflater, container, savedInstanceState) } @@ -45,7 +45,7 @@ class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() { } recyclerView.itemAnimator = SafeDefaultItemAnimator() - inventoryRepository.inAppRewards.subscribe(Action1 { + inventoryRepository.inAppRewards.subscribe(Consumer { (recyclerAdapter as RewardsRecyclerViewAdapter?)?.updateItemRewards(it) }, RxErrorHandler.handleEmptyError()) } @@ -59,7 +59,7 @@ class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() { .flatMap> { inventoryRepository.retrieveInAppRewards() } .doOnTerminate { refreshLayout?.isRefreshing = false - }.subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } private fun setGridSpanCount(width: Int) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt index dbc3ee1c1..83289b5aa 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt @@ -24,17 +24,13 @@ import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.android.habitica.models.user.User import com.habitrpg.android.habitica.modules.AppModule import com.habitrpg.android.habitica.ui.activities.MainActivity -import com.habitrpg.android.habitica.ui.adapter.tasks.DailiesRecyclerViewHolder -import com.habitrpg.android.habitica.ui.adapter.tasks.HabitsRecyclerViewAdapter -import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter -import com.habitrpg.android.habitica.ui.adapter.tasks.TaskRecyclerViewAdapter -import com.habitrpg.android.habitica.ui.adapter.tasks.TodosRecyclerViewAdapter +import com.habitrpg.android.habitica.ui.adapter.tasks.* import com.habitrpg.android.habitica.ui.fragments.BaseFragment import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.fragment_refresh_recyclerview.* import org.greenrobot.eventbus.EventBus -import rx.android.schedulers.AndroidSchedulers -import rx.functions.Action1 import java.util.* import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -94,7 +90,7 @@ open class TaskRecyclerViewFragment : BaseFragment(), View.OnClickListener, Swip recyclerView.adapter = adapter if (this.classType != null) { - taskRepository.getTasks(this.classType ?: "", userID).first().subscribe(Action1 { this.recyclerAdapter?.updateUnfilteredData(it) + taskRepository.getTasks(this.classType ?: "", userID).firstElement().subscribe(Consumer { this.recyclerAdapter?.updateUnfilteredData(it) this.recyclerAdapter?.filter() }, RxErrorHandler.handleEmptyError()) } @@ -158,7 +154,7 @@ open class TaskRecyclerViewFragment : BaseFragment(), View.OnClickListener, Swip taskRepository.updateTaskPosition(classType ?: "", fromPosition, viewHolder.adapterPosition) .delay(1, TimeUnit.SECONDS) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(Action1 { recyclerAdapter?.ignoreUpdates = false + .subscribe(Consumer { recyclerAdapter?.ignoreUpdates = false recyclerAdapter?.notifyDataSetChanged()}, RxErrorHandler.handleEmptyError()) this.fromPosition = null } @@ -236,7 +232,7 @@ open class TaskRecyclerViewFragment : BaseFragment(), View.OnClickListener, Swip if (Task.TYPE_REWARD == className) { compositeSubscription.add(taskRepository.getTasks(this.className, userID) - .subscribe(Action1 { recyclerAdapter?.updateData(it) }, RxErrorHandler.handleEmptyError())) + .subscribe(Consumer { recyclerAdapter?.updateData(it) }, RxErrorHandler.handleEmptyError())) } } @@ -260,7 +256,7 @@ open class TaskRecyclerViewFragment : BaseFragment(), View.OnClickListener, Swip userRepository.retrieveUser(true, true) .doOnTerminate { refreshLayout?.isRefreshing = false - }.subscribe(Action1 { }, RxErrorHandler.handleEmptyError()) + }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()) } fun setActiveFilter(activeFilter: String) { @@ -270,7 +266,7 @@ open class TaskRecyclerViewFragment : BaseFragment(), View.OnClickListener, Swip recyclerAdapter?.filter() if (activeFilter == Task.FILTER_COMPLETED) { - compositeSubscription.add(taskRepository.retrieveCompletedTodos(userID).subscribe(Action1 {}, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(taskRepository.retrieveCompletedTodos(userID).subscribe(Consumer {}, RxErrorHandler.handleEmptyError())) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt index 17c30a001..4647a2e32 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt @@ -6,12 +6,7 @@ import android.os.Bundle import android.support.v4.app.Fragment import android.support.v4.app.FragmentPagerAdapter import android.support.v4.view.ViewPager -import android.view.LayoutInflater -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View -import android.view.ViewGroup +import android.view.* import com.github.clans.fab.FloatingActionButton import com.github.clans.fab.FloatingActionMenu import com.habitrpg.android.habitica.HabiticaBaseApplication @@ -26,8 +21,8 @@ import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.android.habitica.ui.activities.TaskFormActivity import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment import com.habitrpg.android.habitica.ui.views.tasks.TaskFilterDialog +import io.reactivex.functions.Consumer import org.greenrobot.eventbus.Subscribe -import rx.functions.Action1 import java.util.* import javax.inject.Inject @@ -235,7 +230,7 @@ class TasksFragment : BaseMainFragment() { if (bottomNavigation == null) { return } - tutorialRepository.getTutorialSteps(Arrays.asList("habits", "dailies", "todos", "rewards")).subscribe(Action1 { tutorialSteps -> + tutorialRepository.getTutorialSteps(Arrays.asList("habits", "dailies", "todos", "rewards")).subscribe(Consumer { tutorialSteps -> val activeTutorialFragments = ArrayList() for (step in tutorialSteps) { var id = -1 diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.java deleted file mode 100644 index 03ab53f57..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.java +++ /dev/null @@ -1,217 +0,0 @@ -package com.habitrpg.android.habitica.ui.viewHolders.tasks; - -import android.content.Context; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; -import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.habitrpg.android.habitica.R; -import com.habitrpg.android.habitica.events.TaskTappedEvent; -import com.habitrpg.android.habitica.helpers.RxErrorHandler; -import com.habitrpg.android.habitica.models.tasks.Task; -import com.habitrpg.android.habitica.ui.helpers.MarkdownParser; - -import net.pherth.android.emoji_library.EmojiTextView; - -import org.greenrobot.eventbus.EventBus; - -import butterknife.BindColor; -import butterknife.BindView; -import butterknife.ButterKnife; -import rx.Observable; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -public abstract class BaseTaskViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - - - public Task task; - protected Context context; - @BindView(R.id.checkedTextView) - EmojiTextView titleTextView; - - @BindView(R.id.notesTextView) - EmojiTextView notesTextView; - - @Nullable - @BindView(R.id.rightBorderView) - View rightBorderView; - - @BindColor(R.color.task_gray) - int taskGray; - - @Nullable - @BindView(R.id.specialTaskText) - TextView specialTaskTextView; - - @Nullable - @BindView(R.id.iconviewChallenge) - ImageView iconViewChallenge; - - @Nullable - @BindView(R.id.iconviewReminder) - ImageView iconViewReminder; - - @Nullable - @BindView(R.id.iconviewTag) - ImageView iconViewTag; - - @Nullable - @BindView(R.id.taskIconWrapper) - LinearLayout taskIconWrapper; - - @BindView(R.id.approvalRequiredTextField) - TextView approvalRequiredTextView; - - protected boolean openTaskDisabled, taskActionsDisabled; - - - public BaseTaskViewHolder(View itemView) { - this(itemView, true); - } - - public BaseTaskViewHolder(View itemView, boolean useButterKnife) { - super(itemView); - - itemView.setOnClickListener(this); - itemView.setClickable(true); - - if (useButterKnife) { - ButterKnife.bind(this, itemView); - } - - //Re enable when we find a way to only react when a link is tapped. - //this.notesTextView.setMovementMethod(LinkMovementMethod.getInstance()); - //this.titleTextView.setMovementMethod(LinkMovementMethod.getInstance()); - - context = itemView.getContext(); - } - - public void bindHolder(Task newTask, int position) { - this.task = newTask; - itemView.setBackgroundResource(R.color.white); - if (this.canContainMarkdown()) { - if (this.task.getParsedText() != null) { - this.titleTextView.setText(this.task.getParsedText()); - this.notesTextView.setText(this.task.getParsedNotes()); - } else { - this.titleTextView.setText(this.task.getText()); - this.notesTextView.setText(this.task.getNotes()); - Observable.just(this.task.getText()) - .map(MarkdownParser::parseMarkdown) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(parsedText -> { - this.task.setParsedText(parsedText); - this.titleTextView.setText(this.task.getParsedText()); - }, RxErrorHandler.handleEmptyError()); - Observable.just(this.task.getNotes()) - .map(MarkdownParser::parseMarkdown) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(parsedNotes -> { - this.task.setParsedNotes(parsedNotes); - this.notesTextView.setText(this.task.getParsedNotes()); - }, RxErrorHandler.handleEmptyError()); - } - } else { - this.titleTextView.setText(this.task.getText()); - this.notesTextView.setText(this.task.getNotes()); - } - if (this.task.getNotes() != null && this.task.getNotes().length() > 0) { - this.notesTextView.setVisibility(View.VISIBLE); - } else { - this.notesTextView.setVisibility(View.GONE); - } - - if (this.rightBorderView != null) { - this.rightBorderView.setBackgroundResource(this.task.getLightTaskColor()); - } - if (this.iconViewReminder != null) { - this.iconViewReminder.setVisibility(this.task.getReminders().size() > 0 ? View.VISIBLE : View.GONE); - } - if (this.iconViewTag != null) { - this.iconViewTag.setVisibility(this.task.getTags().size() > 0 ? View.VISIBLE : View.GONE); - } - - if (this.iconViewChallenge != null) { - this.iconViewChallenge.setVisibility(View.GONE); - } - - this.configureSpecialTaskTextView(task); - - if (this.taskIconWrapper != null) { - this.taskIconWrapper.setVisibility(getTaskIconWrapperIsVisible() ? View.VISIBLE : View.GONE); - } - - if (task.isPendingApproval()) { - approvalRequiredTextView.setVisibility(View.VISIBLE); - } else { - approvalRequiredTextView.setVisibility(View.GONE); - } - - } - - - - protected void configureSpecialTaskTextView(Task task) { - if (this.specialTaskTextView != null) { - this.specialTaskTextView.setVisibility(View.INVISIBLE); - } - } - - protected Boolean getTaskIconWrapperIsVisible() { - Boolean isVisible = false; - - if (this.iconViewReminder != null) { - if (this.iconViewReminder.getVisibility() == View.VISIBLE) { - isVisible = true; - } - } - if (this.iconViewTag != null) { - if (this.iconViewTag.getVisibility() == View.VISIBLE) { - isVisible = true; - } - } - if (this.iconViewChallenge != null) { - if (this.iconViewChallenge.getVisibility() == View.VISIBLE) { - isVisible = true; - } - } - if (this.iconViewReminder != null) { - if (this.iconViewReminder.getVisibility() == View.VISIBLE) { - isVisible = true; - } - } - if (this.specialTaskTextView != null) { - if (this.specialTaskTextView.getVisibility() == View.VISIBLE) { - isVisible = true; - } - } - return isVisible; - } - - @Override - public void onClick(View v) { - if (!v.equals(itemView) || this.openTaskDisabled) { - return; - } - - TaskTappedEvent event = new TaskTappedEvent(); - event.Task = task; - - EventBus.getDefault().post(event); - } - - public boolean canContainMarkdown() { - return true; - } - - public void setDisabled(boolean openTaskDisabled, boolean taskActionsDisabled) { - this.openTaskDisabled = openTaskDisabled; - this.taskActionsDisabled = taskActionsDisabled; - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.kt new file mode 100644 index 000000000..a58637124 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.kt @@ -0,0 +1,161 @@ +package com.habitrpg.android.habitica.ui.viewHolders.tasks + +import android.content.Context +import android.support.v7.widget.RecyclerView +import android.view.View +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.events.TaskTappedEvent +import com.habitrpg.android.habitica.extensions.bindColor +import com.habitrpg.android.habitica.extensions.bindOptionalView +import com.habitrpg.android.habitica.extensions.bindView +import com.habitrpg.android.habitica.extensions.notNull +import com.habitrpg.android.habitica.helpers.RxErrorHandler +import com.habitrpg.android.habitica.models.tasks.Task +import com.habitrpg.android.habitica.ui.helpers.MarkdownParser +import io.reactivex.Single +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.functions.Consumer +import io.reactivex.schedulers.Schedulers +import net.pherth.android.emoji_library.EmojiTextView +import org.greenrobot.eventbus.EventBus + +abstract class BaseTaskViewHolder @JvmOverloads constructor(itemView: View, useButterKnife: Boolean = true) : RecyclerView.ViewHolder(itemView), View.OnClickListener { + + + var task: Task? = null + protected var context: Context + private val titleTextView: EmojiTextView by bindView(itemView, R.id.checkedTextView) + private val notesTextView: EmojiTextView by bindView(itemView, R.id.notesTextView) + internal val rightBorderView: View? by bindOptionalView(itemView, R.id.rightBorderView) + protected val taskGray: Int by bindColor(itemView.context, R.color.task_gray) + protected val specialTaskTextView: TextView? by bindOptionalView(itemView, R.id.specialTaskText) + private val iconViewChallenge: ImageView by bindView(itemView, R.id.iconviewChallenge) + private val iconViewReminder: ImageView? by bindOptionalView(itemView, R.id.iconviewReminder) + private val iconViewTag: ImageView by bindView(itemView, R.id.iconviewTag) + private val taskIconWrapper: LinearLayout by bindView(itemView, R.id.taskIconWrapper) + private val approvalRequiredTextView: TextView by bindView(itemView, R.id.approvalRequiredTextField) + + private var openTaskDisabled: Boolean = false + private var taskActionsDisabled: Boolean = false + + protected open val taskIconWrapperIsVisible: Boolean + get() { + var isVisible = false + + if (iconViewReminder?.visibility == View.VISIBLE) { + isVisible = true + } + if (iconViewTag.visibility == View.VISIBLE) { + isVisible = true + } + if (iconViewChallenge.visibility == View.VISIBLE) { + isVisible = true + } + if (iconViewReminder?.visibility == View.VISIBLE) { + isVisible = true + } + if (specialTaskTextView?.visibility == View.VISIBLE) { + isVisible = true + } + return isVisible + } + + init { + + itemView.setOnClickListener(this) + itemView.isClickable = true + + //Re enable when we find a way to only react when a link is tapped. + //notesTextView.setMovementMethod(LinkMovementMethod.getInstance()); + //titleTextView.setMovementMethod(LinkMovementMethod.getInstance()); + + context = itemView.context + } + + open fun bindHolder(newTask: Task, position: Int) { + + task = newTask + itemView.setBackgroundResource(R.color.white) + if (canContainMarkdown()) { + if (newTask.parsedText != null) { + titleTextView.text = newTask.parsedText + notesTextView.text = newTask.parsedNotes + } else { + titleTextView.text = newTask.text + notesTextView.text = newTask.notes + Single.just(newTask.text) + .map { MarkdownParser.parseMarkdown(it) } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(Consumer{ parsedText -> + newTask.parsedText = parsedText + titleTextView.text = newTask.parsedText + }, RxErrorHandler.handleEmptyError()) + newTask.notes.notNull { + Single.just(it) + .map { MarkdownParser.parseMarkdown(it) } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(Consumer { parsedNotes -> + newTask.parsedNotes = parsedNotes + notesTextView.text = newTask.parsedNotes + }, RxErrorHandler.handleEmptyError()) + } + + } + } else { + titleTextView.text = newTask.text + notesTextView.text = newTask.notes + } + if (newTask.notes?.isNotEmpty() == true) { + notesTextView.visibility = View.VISIBLE + } else { + notesTextView.visibility = View.GONE + } + + rightBorderView?.setBackgroundResource(newTask.lightTaskColor) + iconViewReminder?.visibility = if (newTask.reminders?.size ?: 0 > 0) View.VISIBLE else View.GONE + iconViewTag.visibility = if (newTask.tags?.size ?: 0 > 0) View.VISIBLE else View.GONE + + iconViewChallenge.visibility = View.GONE + + configureSpecialTaskTextView(newTask) + + taskIconWrapper.visibility = if (taskIconWrapperIsVisible) View.VISIBLE else View.GONE + + if (newTask.isPendingApproval) { + approvalRequiredTextView.visibility = View.VISIBLE + } else { + approvalRequiredTextView.visibility = View.GONE + } + + } + + + protected open fun configureSpecialTaskTextView(task: Task) { + specialTaskTextView?.visibility = View.INVISIBLE + } + + override fun onClick(v: View) { + if (v != itemView || openTaskDisabled) { + return + } + + val event = TaskTappedEvent() + event.Task = task + + EventBus.getDefault().post(event) + } + + open fun canContainMarkdown(): Boolean { + return true + } + + open fun setDisabled(openTaskDisabled: Boolean, taskActionsDisabled: Boolean) { + this.openTaskDisabled = openTaskDisabled + this.taskActionsDisabled = taskActionsDisabled + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.java deleted file mode 100644 index 742afc933..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.habitrpg.android.habitica.ui.viewHolders.tasks; - -import android.content.Context; -import android.graphics.Rect; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.TouchDelegate; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.habitrpg.android.habitica.R; -import com.habitrpg.android.habitica.events.commands.ChecklistCheckedCommand; -import com.habitrpg.android.habitica.events.commands.TaskCheckedCommand; -import com.habitrpg.android.habitica.helpers.RxErrorHandler; -import com.habitrpg.android.habitica.models.tasks.ChecklistItem; -import com.habitrpg.android.habitica.models.tasks.Task; -import com.habitrpg.android.habitica.ui.helpers.MarkdownParser; - -import net.pherth.android.emoji_library.EmojiTextView; - -import org.greenrobot.eventbus.EventBus; - -import butterknife.BindView; -import butterknife.OnClick; -import rx.Observable; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -public abstract class ChecklistedViewHolder extends BaseTaskViewHolder implements CompoundButton.OnCheckedChangeListener { - - private static Integer expandedChecklistRow = null; - - @BindView(R.id.checkBoxHolder) - ViewGroup checkboxHolder; - @BindView(R.id.checkBox) - CheckBox checkbox; - @BindView(R.id.checklistView) - LinearLayout checklistView; - @BindView(R.id.checklistBottomSpace) - View checklistBottomSpace; - @BindView(R.id.checklistIndicatorWrapper) - ViewGroup checklistIndicatorWrapper; - @BindView(R.id.checkListCompletedTextView) - TextView checklistCompletedTextView; - @BindView(R.id.checkListAllTextView) - TextView checklistAllTextView; - - public ChecklistedViewHolder(View itemView) { - super(itemView); - checklistIndicatorWrapper.setClickable(true); - checkbox.setOnCheckedChangeListener(this); - expandCheckboxTouchArea(checkboxHolder, checkbox); - } - - @Override - public void bindHolder(Task newTask, int position) { - boolean completed = newTask.getCompleted(); - if (newTask.isPendingApproval()) { - completed = false; - } - this.checkbox.setChecked(completed); - if (this.shouldDisplayAsActive(newTask) && !newTask.isPendingApproval()) { - this.checkboxHolder.setBackgroundResource(newTask.getLightTaskColor()); - } else { - this.checkboxHolder.setBackgroundColor(this.taskGray); - } - this.checklistCompletedTextView.setText(String.valueOf(newTask.getCompletedChecklistCount())); - this.checklistAllTextView.setText(String.valueOf(newTask.getChecklist().size())); - - this.checklistView.removeAllViews(); - this.updateChecklistDisplay(); - - this.checklistIndicatorWrapper.setVisibility(newTask.getChecklist().size() == 0 ? View.GONE : View.VISIBLE); - if (this.rightBorderView != null) { - this.rightBorderView.setVisibility(newTask.getChecklist().size() == 0 ? View.VISIBLE : View.GONE); - if (newTask.getCompleted()) { - this.rightBorderView.setBackgroundResource(newTask.getLightTaskColor()); - } else { - this.rightBorderView.setBackgroundColor(this.taskGray); - } - } - super.bindHolder(newTask, position); - } - - abstract public Boolean shouldDisplayAsActive(Task newTask); - - public void updateChecklistDisplay() { - //This needs to be a LinearLayout, as ListViews can not be inside other ListViews. - if (this.checklistView != null) { - if (this.shouldDisplayExpandedChecklist()) { - LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - if (this.task.getChecklist().isValid()) { - for (ChecklistItem item : this.task.getChecklist()) { - LinearLayout itemView = (LinearLayout) layoutInflater.inflate(R.layout.checklist_item_row, this.checklistView, false); - CheckBox checkbox = itemView.findViewById(R.id.checkBox); - EmojiTextView textView = itemView.findViewById(R.id.checkedTextView); - // Populate the data into the template view using the data object - textView.setText(item.getText()); - - Observable.just(item.getText()) - .map(MarkdownParser::parseMarkdown) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(textView::setText, RxErrorHandler.handleEmptyError()); - checkbox.setChecked(item.getCompleted()); - checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> { - ChecklistCheckedCommand event = new ChecklistCheckedCommand(); - event.task = task; - event.item = item; - EventBus.getDefault().post(event); - }); - ViewGroup checkboxHolder = (ViewGroup) itemView.findViewById(R.id.checkBoxHolder); - expandCheckboxTouchArea(checkboxHolder, checkbox); - this.checklistView.addView(itemView); - } - } - this.checklistView.setVisibility(View.VISIBLE); - this.checklistBottomSpace.setVisibility(View.VISIBLE); - } else { - this.checklistView.removeAllViewsInLayout(); - this.checklistView.setVisibility(View.GONE); - this.checklistBottomSpace.setVisibility(View.GONE); - } - } - } - - @OnClick(R.id.checklistIndicatorWrapper) - public void onChecklistIndicatorClicked() { - expandedChecklistRow = this.shouldDisplayExpandedChecklist() ? null : getAdapterPosition(); - if (this.shouldDisplayExpandedChecklist()) { - RecyclerView recyclerView = (RecyclerView) this.checklistView.getParent().getParent(); - LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); - layoutManager.scrollToPositionWithOffset(this.getAdapterPosition(), 15); - } - updateChecklistDisplay(); - - } - - private boolean shouldDisplayExpandedChecklist() { - return expandedChecklistRow != null && getAdapterPosition() == expandedChecklistRow; - } - - public void expandCheckboxTouchArea(final View expandedView, final View checkboxView) { - expandedView.post(() -> { - Rect rect = new Rect(); - expandedView.getHitRect(rect); - expandedView.setTouchDelegate(new TouchDelegate(rect, checkboxView)); - }); - } - - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (buttonView.equals(checkbox)) { - if (!task.isValid()) { - return; - } - if (isChecked != task.getCompleted()) { - TaskCheckedCommand event = new TaskCheckedCommand(); - event.Task = task; - event.completed = !task.getCompleted(); - - // it needs to be changed after the event is send -> to the server - // maybe a refactor is needed here - EventBus.getDefault().post(event); - } - } - } - - @Override - public void setDisabled(boolean openTaskDisabled, boolean taskActionsDisabled) { - super.setDisabled(openTaskDisabled, taskActionsDisabled); - - this.checkbox.setEnabled(!taskActionsDisabled); - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt new file mode 100644 index 000000000..06c77853c --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt @@ -0,0 +1,170 @@ +package com.habitrpg.android.habitica.ui.viewHolders.tasks + +import android.content.Context +import android.graphics.Rect +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.TouchDelegate +import android.view.View +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.CompoundButton +import android.widget.LinearLayout +import android.widget.TextView + +import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.events.commands.ChecklistCheckedCommand +import com.habitrpg.android.habitica.events.commands.TaskCheckedCommand +import com.habitrpg.android.habitica.helpers.RxErrorHandler +import com.habitrpg.android.habitica.models.tasks.ChecklistItem +import com.habitrpg.android.habitica.models.tasks.Task +import com.habitrpg.android.habitica.ui.helpers.MarkdownParser + +import net.pherth.android.emoji_library.EmojiTextView + +import org.greenrobot.eventbus.EventBus + +import butterknife.BindView +import butterknife.OnClick +import com.habitrpg.android.habitica.extensions.bindView +import io.reactivex.Observable +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.functions.Consumer +import io.reactivex.schedulers.Schedulers + +abstract class ChecklistedViewHolder(itemView: View) : BaseTaskViewHolder(itemView), CompoundButton.OnCheckedChangeListener { + + private val checkboxHolder: ViewGroup by bindView(itemView, R.id.checkBoxHolder) + internal val checkbox: CheckBox by bindView(itemView, R.id.checkBox) + internal val checklistView: LinearLayout by bindView(itemView, R.id.checklistView) + internal val checklistBottomSpace: View by bindView(itemView, R.id.checklistBottomSpace) + internal val checklistIndicatorWrapper: ViewGroup by bindView(itemView, R.id.checklistIndicatorWrapper) + private val checklistCompletedTextView: TextView by bindView(itemView, R.id.checkListCompletedTextView) + private val checklistAllTextView: TextView by bindView(itemView, R.id.checkListAllTextView) + + init { + checklistIndicatorWrapper.isClickable = true + checkbox.setOnCheckedChangeListener(this) + expandCheckboxTouchArea(checkboxHolder, checkbox) + } + + override fun bindHolder(newTask: Task, position: Int) { + var completed = newTask.completed + if (newTask.isPendingApproval) { + completed = false + } + this.checkbox.isChecked = completed + if (this.shouldDisplayAsActive(newTask) && !newTask.isPendingApproval) { + this.checkboxHolder.setBackgroundResource(newTask.lightTaskColor) + } else { + this.checkboxHolder.setBackgroundColor(this.taskGray) + } + this.checklistCompletedTextView.text = newTask.completedChecklistCount.toString() + this.checklistAllTextView.text = newTask.checklist?.size.toString() + + this.checklistView.removeAllViews() + this.updateChecklistDisplay() + + this.checklistIndicatorWrapper.visibility = if (newTask.checklist?.size == 0) View.GONE else View.VISIBLE + this.rightBorderView?.visibility = if (newTask.checklist?.size == 0) View.VISIBLE else View.GONE + if (newTask.completed) { + this.rightBorderView?.setBackgroundResource(newTask.lightTaskColor) + } else { + this.rightBorderView?.setBackgroundColor(this.taskGray) + } + super.bindHolder(newTask, position) + } + + abstract fun shouldDisplayAsActive(newTask: Task): Boolean + + fun updateChecklistDisplay() { + //This needs to be a LinearLayout, as ListViews can not be inside other ListViews. + if (this.shouldDisplayExpandedChecklist()) { + val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater + if (this.task?.checklist?.isValid == true) { + for (item in this.task?.checklist ?: emptyList()) { + val itemView = layoutInflater.inflate(R.layout.checklist_item_row, this.checklistView, false) as LinearLayout + val checkbox = itemView.findViewById(R.id.checkBox) + val textView = itemView.findViewById(R.id.checkedTextView) + // Populate the data into the template view using the data object + textView.text = item.text + + Observable.just(item.text) + .map( { MarkdownParser.parseMarkdown(it) }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(Consumer { textView.setText(it) }, RxErrorHandler.handleEmptyError()) + checkbox.isChecked = item.completed + checkbox.setOnCheckedChangeListener { buttonView, isChecked -> + val event = ChecklistCheckedCommand() + event.task = task + event.item = item + EventBus.getDefault().post(event) + } + val checkboxHolder = itemView.findViewById(R.id.checkBoxHolder) as ViewGroup + expandCheckboxTouchArea(checkboxHolder, checkbox) + this.checklistView.addView(itemView) + } + } + this.checklistView.visibility = View.VISIBLE + this.checklistBottomSpace.visibility = View.VISIBLE + } else { + this.checklistView.removeAllViewsInLayout() + this.checklistView.visibility = View.GONE + this.checklistBottomSpace.visibility = View.GONE + } + } + + @OnClick(R.id.checklistIndicatorWrapper) + fun onChecklistIndicatorClicked() { + expandedChecklistRow = if (this.shouldDisplayExpandedChecklist()) null else adapterPosition + if (this.shouldDisplayExpandedChecklist()) { + val recyclerView = this.checklistView.parent.parent as RecyclerView + val layoutManager = recyclerView.layoutManager as LinearLayoutManager + layoutManager.scrollToPositionWithOffset(this.adapterPosition, 15) + } + updateChecklistDisplay() + + } + + private fun shouldDisplayExpandedChecklist(): Boolean { + return expandedChecklistRow != null && adapterPosition == expandedChecklistRow + } + + fun expandCheckboxTouchArea(expandedView: View?, checkboxView: View) { + expandedView?.post { + val rect = Rect() + expandedView.getHitRect(rect) + expandedView.touchDelegate = TouchDelegate(rect, checkboxView) + } + } + + override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) { + if (buttonView == checkbox) { + if (task?.isValid != true) { + return + } + if (isChecked != task?.completed) { + val event = TaskCheckedCommand() + event.Task = task + event.completed = task?.completed == false + + // it needs to be changed after the event is send -> to the server + // maybe a refactor is needed here + EventBus.getDefault().post(event) + } + } + } + + override fun setDisabled(openTaskDisabled: Boolean, taskActionsDisabled: Boolean) { + super.setDisabled(openTaskDisabled, taskActionsDisabled) + + this.checkbox.isEnabled = !taskActionsDisabled + } + + companion object { + + private var expandedChecklistRow: Int? = null + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.java deleted file mode 100644 index 1817c826c..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.habitrpg.android.habitica.ui.viewHolders.tasks; - -import android.view.View; -import android.widget.TextView; - -import com.habitrpg.android.habitica.R; -import com.habitrpg.android.habitica.models.tasks.Task; - -import butterknife.BindView; - -public class DailyViewHolder extends ChecklistedViewHolder { - - @BindView(R.id.streakTextView) - TextView streakTextView; - - public DailyViewHolder(View itemView) { - super(itemView); - } - - @Override - public void bindHolder(Task newTask, int position) { - this.task = newTask; - if (newTask.isChecklistDisplayActive()) { - this.checklistIndicatorWrapper.setBackgroundResource(newTask.getLightTaskColor()); - } else { - this.checklistIndicatorWrapper.setBackgroundColor(this.taskGray); - } - super.bindHolder(newTask, position); - } - - @Override - public Boolean shouldDisplayAsActive(Task newTask) { - return newTask.isDisplayedActive(); - } - - @Override - protected void configureSpecialTaskTextView(Task task) { - super.configureSpecialTaskTextView(task); - if (this.streakTextView != null) { - if (task.getStreak() != null && task.getStreak() > 0) { - this.streakTextView.setText(String.valueOf(task.getStreak())); - this.streakTextView.setVisibility(View.VISIBLE); - } else { - this.streakTextView.setVisibility(View.GONE); - } - } - } - - @Override - protected Boolean getTaskIconWrapperIsVisible() { - Boolean isVisible = super.getTaskIconWrapperIsVisible(); - if (this.streakTextView.getVisibility() == View.VISIBLE) { - isVisible = true; - } - return isVisible; - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt new file mode 100644 index 000000000..1fd4ed8f6 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt @@ -0,0 +1,45 @@ +package com.habitrpg.android.habitica.ui.viewHolders.tasks + +import android.view.View +import android.widget.TextView +import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.extensions.bindView +import com.habitrpg.android.habitica.models.tasks.Task + +class DailyViewHolder(itemView: View) : ChecklistedViewHolder(itemView) { + + private val streakTextView: TextView by bindView(itemView, R.id.streakTextView) + + override val taskIconWrapperIsVisible: Boolean + get() { + var isVisible: Boolean = super.taskIconWrapperIsVisible + if (this.streakTextView.visibility == View.VISIBLE) { + isVisible = true + } + return isVisible + } + + override fun bindHolder(newTask: Task, position: Int) { + this.task = newTask + if (newTask.isChecklistDisplayActive) { + this.checklistIndicatorWrapper.setBackgroundResource(newTask.lightTaskColor) + } else { + this.checklistIndicatorWrapper.setBackgroundColor(this.taskGray) + } + super.bindHolder(newTask, position) + } + + override fun shouldDisplayAsActive(newTask: Task): Boolean { + return newTask.isDisplayedActive + } + + override fun configureSpecialTaskTextView(task: Task) { + super.configureSpecialTaskTextView(task) + if (task.streak ?: 0 > 0) { + this.streakTextView.text = task.streak.toString() + this.streakTextView.visibility = View.VISIBLE + } else { + this.streakTextView.visibility = View.GONE + } + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.java deleted file mode 100644 index 1cd5b6d60..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.habitrpg.android.habitica.ui.viewHolders.tasks; - -import android.view.View; -import android.widget.Button; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.TextView; - -import com.habitrpg.android.habitica.R; -import com.habitrpg.android.habitica.events.HabitScoreEvent; -import com.habitrpg.android.habitica.models.tasks.Task; - -import org.greenrobot.eventbus.EventBus; - -import butterknife.BindView; -import butterknife.OnClick; - -public class HabitViewHolder extends BaseTaskViewHolder { - - @BindView(R.id.btnPlusWrapper) - FrameLayout btnPlusWrapper; - @BindView(R.id.btnPlusIconView) - ImageView btnPlusIconView; - @BindView(R.id.btnPlus) - Button btnPlus; - - @BindView(R.id.btnMinusWrapper) - FrameLayout btnMinusWrapper; - @BindView(R.id.btnMinusIconView) - ImageView btnMinusIconView; - @BindView(R.id.btnMinus) - Button btnMinus; - - @BindView(R.id.streakTextView) - TextView streakTextView; - - public HabitViewHolder(View itemView) { - super(itemView); - } - - @Override - public void bindHolder(Task newTask, int position) { - this.task = newTask; - if (newTask.getUp() != null && newTask.getUp()) { - this.btnPlusWrapper.setBackgroundResource(newTask.getLightTaskColor()); - if (newTask.getLightTaskColor() == R.color.yellow_100) { - this.btnPlusIconView.setImageResource(R.drawable.habit_plus_yellow); - } else { - this.btnPlusIconView.setImageResource(R.drawable.habit_plus); - } - this.btnPlus.setVisibility(View.VISIBLE); - this.btnPlus.setClickable(true); - } else { - this.btnPlusWrapper.setBackgroundResource(R.color.habit_inactive_gray); - this.btnPlusIconView.setImageResource(R.drawable.habit_plus_disabled); - this.btnPlus.setVisibility(View.GONE); - this.btnPlus.setClickable(false); - } - - if (newTask.getDown() != null && newTask.getDown()) { - this.btnMinusWrapper.setBackgroundResource(newTask.getLightTaskColor()); - if (newTask.getLightTaskColor() == R.color.yellow_100) { - this.btnMinusIconView.setImageResource(R.drawable.habit_minus_yellow); - } else { - this.btnMinusIconView.setImageResource(R.drawable.habit_minus); - } - this.btnMinus.setVisibility(View.VISIBLE); - this.btnMinus.setClickable(true); - } else { - this.btnMinusWrapper.setBackgroundResource(R.color.habit_inactive_gray); - this.btnMinusIconView.setImageResource(R.drawable.habit_minus_disabled); - this.btnMinus.setVisibility(View.GONE); - this.btnMinus.setClickable(false); - } - - String streakString = ""; - if (newTask.getCounterUp() != null && newTask.getCounterUp() > 0 && newTask.getCounterDown() != null && newTask.getCounterDown() > 0) { - streakString = streakString + "+" + String.valueOf(task.getCounterUp()) + " | -" + String.valueOf(task.getCounterDown()); - } else if (newTask.getCounterUp() != null && newTask.getCounterUp() > 0) { - streakString = streakString + "+" + String.valueOf(task.getCounterUp()); - } else if (newTask.getCounterDown() != null && newTask.getCounterDown() > 0) { - streakString = streakString + "-" + String.valueOf(task.getCounterDown()); - } - if (streakString.length() > 0) { - streakTextView.setText(streakString); - streakTextView.setVisibility(View.VISIBLE); - } else { - streakTextView.setVisibility(View.GONE); - } - super.bindHolder(newTask, position); - } - - @OnClick(R.id.btnPlus) - public void onPlusButtonClicked() { - HabitScoreEvent event = new HabitScoreEvent(); - event.Up = true; - event.habit = task; - EventBus.getDefault().post(event); - } - - @OnClick(R.id.btnMinus) - public void onMinusButtonClicked() { - HabitScoreEvent event = new HabitScoreEvent(); - event.Up = false; - event.habit = task; - EventBus.getDefault().post(event); - } - - @Override - public void setDisabled(boolean openTaskDisabled, boolean taskActionsDisabled) { - super.setDisabled(openTaskDisabled, taskActionsDisabled); - - this.btnPlus.setEnabled(!taskActionsDisabled); - this.btnMinus.setEnabled(!taskActionsDisabled); - } - - @Override - protected Boolean getTaskIconWrapperIsVisible() { - Boolean isVisible = super.getTaskIconWrapperIsVisible(); - if (this.streakTextView.getVisibility() == View.VISIBLE) { - isVisible = true; - } - return isVisible; - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt new file mode 100644 index 000000000..d5b5d7668 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt @@ -0,0 +1,107 @@ +package com.habitrpg.android.habitica.ui.viewHolders.tasks + +import android.view.View +import android.widget.Button +import android.widget.FrameLayout +import android.widget.ImageView +import android.widget.TextView +import butterknife.OnClick +import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.events.HabitScoreEvent +import com.habitrpg.android.habitica.extensions.bindView +import com.habitrpg.android.habitica.models.tasks.Task +import org.greenrobot.eventbus.EventBus + +class HabitViewHolder(itemView: View) : BaseTaskViewHolder(itemView) { + + private val btnPlusWrapper: FrameLayout by bindView(itemView, R.id.btnPlusWrapper) + private val btnPlusIconView: ImageView by bindView(itemView, R.id.btnPlusIconView) + private val btnPlus: Button by bindView(itemView, R.id.btnPlus) + private val btnMinusWrapper: FrameLayout by bindView(itemView, R.id.btnMinusWrapper) + private val btnMinusIconView: ImageView by bindView(itemView, R.id.btnMinusIconView) + private val btnMinus: Button by bindView(itemView, R.id.btnMinus) + private val streakTextView: TextView by bindView(itemView, R.id.streakTextView) + + override val taskIconWrapperIsVisible: Boolean + get() { + var isVisible: Boolean = super.taskIconWrapperIsVisible + if (this.streakTextView.visibility == View.VISIBLE) { + isVisible = true + } + return isVisible + } + + override fun bindHolder(newTask: Task, position: Int) { + this.task = newTask + if (newTask.up == true) { + this.btnPlusWrapper.setBackgroundResource(newTask.lightTaskColor) + if (newTask.lightTaskColor == R.color.yellow_100) { + this.btnPlusIconView.setImageResource(R.drawable.habit_plus_yellow) + } else { + this.btnPlusIconView.setImageResource(R.drawable.habit_plus) + } + this.btnPlus.visibility = View.VISIBLE + this.btnPlus.isClickable = true + } else { + this.btnPlusWrapper.setBackgroundResource(R.color.habit_inactive_gray) + this.btnPlusIconView.setImageResource(R.drawable.habit_plus_disabled) + this.btnPlus.visibility = View.GONE + this.btnPlus.isClickable = false + } + + if (newTask.down == true) { + this.btnMinusWrapper.setBackgroundResource(newTask.lightTaskColor) + if (newTask.lightTaskColor == R.color.yellow_100) { + this.btnMinusIconView.setImageResource(R.drawable.habit_minus_yellow) + } else { + this.btnMinusIconView.setImageResource(R.drawable.habit_minus) + } + this.btnMinus.visibility = View.VISIBLE + this.btnMinus.isClickable = true + } else { + this.btnMinusWrapper.setBackgroundResource(R.color.habit_inactive_gray) + this.btnMinusIconView.setImageResource(R.drawable.habit_minus_disabled) + this.btnMinus.visibility = View.GONE + this.btnMinus.isClickable = false + } + + var streakString = "" + if (newTask.counterUp != null && newTask.counterUp ?: 0 > 0 && newTask.counterDown != null && newTask.counterDown ?: 0 > 0) { + streakString = streakString + "+" + newTask.counterUp.toString() + " | -" + newTask.counterDown?.toString() + } else if (newTask.counterUp != null && newTask.counterUp ?: 0 > 0) { + streakString = streakString + "+" + newTask.counterUp.toString() + } else if (newTask.counterDown != null && newTask.counterDown ?: 0 > 0) { + streakString = streakString + "-" + newTask.counterDown.toString() + } + if (streakString.isNotEmpty()) { + streakTextView.text = streakString + streakTextView.visibility = View.VISIBLE + } else { + streakTextView.visibility = View.GONE + } + super.bindHolder(newTask, position) + } + + @OnClick(R.id.btnPlus) + fun onPlusButtonClicked() { + val event = HabitScoreEvent() + event.Up = true + event.habit = task + EventBus.getDefault().post(event) + } + + @OnClick(R.id.btnMinus) + fun onMinusButtonClicked() { + val event = HabitScoreEvent() + event.Up = false + event.habit = task + EventBus.getDefault().post(event) + } + + override fun setDisabled(openTaskDisabled: Boolean, taskActionsDisabled: Boolean) { + super.setDisabled(openTaskDisabled, taskActionsDisabled) + + this.btnPlus.isEnabled = !taskActionsDisabled + this.btnMinus.isEnabled = !taskActionsDisabled + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.java deleted file mode 100644 index 78120f940..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.habitrpg.android.habitica.ui.viewHolders.tasks; - -import android.support.v4.content.ContextCompat; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import com.habitrpg.android.habitica.R; -import com.habitrpg.android.habitica.events.TaskTappedEvent; -import com.habitrpg.android.habitica.events.commands.BuyRewardCommand; -import com.habitrpg.android.habitica.helpers.NumberAbbreviator; -import com.habitrpg.android.habitica.models.tasks.Task; -import com.habitrpg.android.habitica.ui.ItemDetailDialog; -import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper; - -import org.greenrobot.eventbus.EventBus; - -import butterknife.BindView; -import butterknife.OnClick; - -public class RewardViewHolder extends BaseTaskViewHolder { - - @BindView(R.id.buyButton) - View buyButton; - @BindView(R.id.priceLabel) - TextView priceLabel; - @BindView(R.id.gold_icon) - ImageView goldIconView; - - public RewardViewHolder(View itemView) { - super(itemView); - goldIconView.setImageBitmap(HabiticaIconsHelper.imageOfGold()); - } - - - private boolean isItem() { - return this.task.getSpecialTag() != null && this.task.getSpecialTag().equals("item"); - } - - @Override - public boolean canContainMarkdown() { - return !isItem(); - } - - @OnClick(R.id.buyButton) - void buyReward() { - BuyRewardCommand event = new BuyRewardCommand(); - event.Reward = task; - EventBus.getDefault().post(event); - } - - @Override - public void onClick(View v) { - if (!task.isValid()) { - return; - } - if (task.getSpecialTag() != null && task.getSpecialTag().equals("item")) { - ItemDetailDialog dialog = new ItemDetailDialog(context); - dialog.setTitle(task.getText()); - dialog.setDescription(task.getNotes()); - dialog.setImage("shop_" + this.task.getId()); - dialog.setCurrency("gold"); - dialog.setValue(task.getValue()); - dialog.setBuyListener((clickedDialog, which) -> this.buyReward()); - dialog.show(); - } else { - TaskTappedEvent event = new TaskTappedEvent(); - event.Task = task; - - EventBus.getDefault().post(event); - } - } - - @Override - public void setDisabled(boolean openTaskDisabled, boolean taskActionsDisabled) { - super.setDisabled(openTaskDisabled, taskActionsDisabled); - - this.buyButton.setEnabled(!taskActionsDisabled); - } - - public void bindHolder(Task reward, int position, boolean canBuy) { - this.task = reward; - super.bindHolder(reward, position); - this.priceLabel.setText(NumberAbbreviator.INSTANCE.abbreviate(itemView.getContext(), this.task.getValue())); - - if (canBuy) { - goldIconView.setAlpha(1.0f); - priceLabel.setTextColor(ContextCompat.getColor(context, R.color.yellow_50)); - } else { - goldIconView.setAlpha(0.4f); - priceLabel.setTextColor(ContextCompat.getColor(context, R.color.gray_500)); - } - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt new file mode 100644 index 000000000..57bb04eeb --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt @@ -0,0 +1,86 @@ +package com.habitrpg.android.habitica.ui.viewHolders.tasks + +import android.support.v4.content.ContextCompat +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import butterknife.OnClick +import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.events.TaskTappedEvent +import com.habitrpg.android.habitica.events.commands.BuyRewardCommand +import com.habitrpg.android.habitica.extensions.bindView +import com.habitrpg.android.habitica.helpers.NumberAbbreviator +import com.habitrpg.android.habitica.models.tasks.Task +import com.habitrpg.android.habitica.ui.ItemDetailDialog +import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper +import org.greenrobot.eventbus.EventBus + +class RewardViewHolder(itemView: View) : BaseTaskViewHolder(itemView) { + + internal val buyButton: View by bindView(itemView, R.id.buyButton) + internal val priceLabel: TextView by bindView(itemView, R.id.priceLabel) + private val goldIconView: ImageView by bindView(itemView, R.id.gold_icon) + + + private val isItem: Boolean + get() = this.task?.specialTag == "item" + + init { + goldIconView.setImageBitmap(HabiticaIconsHelper.imageOfGold()) + + buyButton.setOnClickListener { + buyReward() + } + } + + override fun canContainMarkdown(): Boolean { + return !isItem + } + + private fun buyReward() { + val event = BuyRewardCommand() + event.Reward = task + EventBus.getDefault().post(event) + } + + override fun onClick(v: View) { + if (task?.isValid != true) { + return + } + if (isItem) { + val dialog = ItemDetailDialog(context) + dialog.setTitle(task?.text) + dialog.setDescription(task?.notes) + dialog.setImage("shop_" + this.task?.id) + dialog.setCurrency("gold") + dialog.setValue(task!!.value) + dialog.setBuyListener { _, _ -> this.buyReward() } + dialog.show() + } else { + val event = TaskTappedEvent() + event.Task = task + + EventBus.getDefault().post(event) + } + } + + override fun setDisabled(openTaskDisabled: Boolean, taskActionsDisabled: Boolean) { + super.setDisabled(openTaskDisabled, taskActionsDisabled) + + this.buyButton.isEnabled = !taskActionsDisabled + } + + fun bindHolder(reward: Task, position: Int, canBuy: Boolean) { + this.task = reward + super.bindHolder(reward, position) + this.priceLabel.text = NumberAbbreviator.abbreviate(itemView.context, this.task!!.value) + + if (canBuy) { + goldIconView.alpha = 1.0f + priceLabel.setTextColor(ContextCompat.getColor(context, R.color.yellow_50)) + } else { + goldIconView.alpha = 0.4f + priceLabel.setTextColor(ContextCompat.getColor(context, R.color.gray_500)) + } + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.java deleted file mode 100644 index 17a5bd584..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.habitrpg.android.habitica.ui.viewHolders.tasks; - -import android.view.View; - -import com.habitrpg.android.habitica.models.tasks.Task; - -import java.text.DateFormat; - -public class TodoViewHolder extends ChecklistedViewHolder { - - private DateFormat dateFormatter; - - public TodoViewHolder(View itemView) { - super(itemView); - dateFormatter = android.text.format.DateFormat.getDateFormat(context); - } - - @Override - public void bindHolder(Task newTask, int position) { - this.task = newTask; - if (newTask.getCompleted()) { - this.checklistIndicatorWrapper.setBackgroundColor(this.taskGray); - } else { - this.checklistIndicatorWrapper.setBackgroundResource(newTask.getLightTaskColor()); - } - super.bindHolder(newTask, position); - } - - @Override - protected void configureSpecialTaskTextView(Task task) { - if (this.specialTaskTextView != null) { - if (task.getDueDate() != null) { - this.specialTaskTextView.setText(dateFormatter.format(task.getDueDate())); - this.specialTaskTextView.setVisibility(View.VISIBLE); - } else { - this.specialTaskTextView.setVisibility(View.INVISIBLE); - } - } - } - - @Override - public Boolean shouldDisplayAsActive(Task newTask) { - return !newTask.getCompleted(); - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt new file mode 100644 index 000000000..996bf5526 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt @@ -0,0 +1,35 @@ +package com.habitrpg.android.habitica.ui.viewHolders.tasks + +import android.view.View + +import com.habitrpg.android.habitica.models.tasks.Task + +import java.text.DateFormat + +class TodoViewHolder(itemView: View) : ChecklistedViewHolder(itemView) { + + private val dateFormatter: DateFormat = android.text.format.DateFormat.getDateFormat(context) + + override fun bindHolder(newTask: Task, position: Int) { + this.task = newTask + if (newTask.completed) { + checklistIndicatorWrapper.setBackgroundColor(taskGray) + } else { + checklistIndicatorWrapper.setBackgroundColor(newTask.lightTaskColor) + } + super.bindHolder(newTask, position) + } + + override fun configureSpecialTaskTextView(task: Task) { + if (task.dueDate != null) { + this.specialTaskTextView?.text = dateFormatter.format(task.dueDate) + this.specialTaskTextView?.visibility = View.VISIBLE + } else { + this.specialTaskTextView?.visibility = View.INVISIBLE + } + } + + override fun shouldDisplayAsActive(newTask: Task): Boolean { + return !newTask.completed + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/NPCBannerView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/NPCBannerView.kt index abf46f993..5f64fd2c9 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/NPCBannerView.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/NPCBannerView.kt @@ -14,9 +14,9 @@ import com.habitrpg.android.habitica.extensions.bindView import com.habitrpg.android.habitica.extensions.layoutInflater import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils -import rx.Observable -import rx.android.schedulers.AndroidSchedulers -import rx.functions.Action1 +import io.reactivex.Observable +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.functions.Consumer class NPCBannerView(context: Context?, attrs: AttributeSet?) : FrameLayout(context, attrs) { @@ -49,7 +49,7 @@ class NPCBannerView(context: Context?, attrs: AttributeSet?) : FrameLayout(conte backgroundView.scaleType = ImageView.ScaleType.FIT_START - DataBindingUtils.loadImage(identifier + "_background" + shopSpriteSuffix, { + DataBindingUtils.loadImage(identifier + "_background" + shopSpriteSuffix) { val aspectRatio = it.width / it.height.toFloat() val height = context.resources.getDimension(R.dimen.shop_height).toInt() val width = Math.round(height * aspectRatio) @@ -57,9 +57,9 @@ class NPCBannerView(context: Context?, attrs: AttributeSet?) : FrameLayout(conte drawable.tileModeX = Shader.TileMode.REPEAT Observable.just(drawable) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(Action1 { + .subscribe(Consumer { backgroundView.backgroundCompat = it }, RxErrorHandler.handleEmptyError()) - }) + } } } \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt index 538581766..9a88f7d19 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt @@ -33,10 +33,10 @@ import com.habitrpg.android.habitica.ui.views.insufficientCurrency.InsufficientG import com.habitrpg.android.habitica.ui.views.insufficientCurrency.InsufficientGoldDialog import com.habitrpg.android.habitica.ui.views.insufficientCurrency.InsufficientHourglassesDialog import com.habitrpg.android.habitica.ui.views.insufficientCurrency.InsufficientSubscriberGemsDialog +import io.reactivex.Flowable +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.functions.Consumer import org.greenrobot.eventbus.EventBus -import rx.Observable -import rx.functions.Action1 -import rx.subscriptions.CompositeSubscription import java.util.* import javax.inject.Inject @@ -88,11 +88,11 @@ class PurchaseDialog(context: Context, component: AppComponent, val item: ShopIt shopItem.isTypeItem -> contentView = PurchaseDialogItemContent(context) shopItem.isTypeQuest -> { contentView = PurchaseDialogQuestContent(context) - inventoryRepository.getQuestContent(shopItem.key).first().subscribe(Action1 { contentView.setQuestContent(it) }, RxErrorHandler.handleEmptyError()) + inventoryRepository.getQuestContent(shopItem.key).firstElement().subscribe(Consumer { contentView.setQuestContent(it) }, RxErrorHandler.handleEmptyError()) } shopItem.isTypeGear -> { contentView = PurchaseDialogGearContent(context) - inventoryRepository.getEquipment(shopItem.key).first().subscribe(Action1 { contentView.setEquipment(it) }, RxErrorHandler.handleEmptyError()) + inventoryRepository.getEquipment(shopItem.key).firstElement().subscribe(Consumer { contentView.setEquipment(it) }, RxErrorHandler.handleEmptyError()) checkGearClass() } "gems" == shopItem.purchaseType -> contentView = PurchaseDialogGemsContent(context) @@ -120,7 +120,7 @@ class PurchaseDialog(context: Context, component: AppComponent, val item: ShopIt } } - private val compositeSubscription: CompositeSubscription = CompositeSubscription() + private val compositeSubscription: CompositeDisposable = CompositeDisposable() var shopIdentifier: String? = null private var user: User? = null var isPinned: Boolean = false @@ -139,7 +139,7 @@ class PurchaseDialog(context: Context, component: AppComponent, val item: ShopIt shopItem = item - compositeSubscription.add(userRepository.getUser().subscribe(Action1 { this.setUser(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(userRepository.getUser().subscribe(Consumer { this.setUser(it) }, RxErrorHandler.handleEmptyError())) if (!this.configManager.newShopsEnabled()) { pinButton.visibility = View.GONE @@ -147,7 +147,7 @@ class PurchaseDialog(context: Context, component: AppComponent, val item: ShopIt closeButton.setOnClickListener { dismiss() } buyButton.setOnClickListener { onBuyButtonClicked() } - pinButton.setOnClickListener { inventoryRepository.togglePinnedItem(shopItem).subscribe(Action1 { isPinned = !this.isPinned }, RxErrorHandler.handleEmptyError()) } + pinButton.setOnClickListener { inventoryRepository.togglePinnedItem(shopItem).subscribe(Consumer { isPinned = !this.isPinned }, RxErrorHandler.handleEmptyError()) } } private fun setUser(user: User) { @@ -182,8 +182,8 @@ class PurchaseDialog(context: Context, component: AppComponent, val item: ShopIt override fun dismiss() { userRepository.close() inventoryRepository.close() - if (!compositeSubscription.isUnsubscribed) { - compositeSubscription.unsubscribe() + if (!compositeSubscription.isDisposed) { + compositeSubscription.dispose() } super.dismiss() } @@ -215,7 +215,7 @@ class PurchaseDialog(context: Context, component: AppComponent, val item: ShopIt } val gemsLeft = if (shopItem.limitedNumberLeft != null) shopItem.limitedNumberLeft else 0 if ((gemsLeft == 0 && shopItem.purchaseType == "gems") || shopItem.canAfford(user)) { - val observable: Observable + val observable: Flowable if (shopIdentifier != null && shopIdentifier == Shop.TIME_TRAVELERS_SHOP || "mystery_set" == shopItem.purchaseType) { observable = if (shopItem.purchaseType == "gear") { inventoryRepository.purchaseMysterySet(shopItem.categoryIdentifier) @@ -233,7 +233,7 @@ class PurchaseDialog(context: Context, component: AppComponent, val item: ShopIt else -> context.getString(R.string.armoireExp) } } - Observable.just(null) + Flowable.empty() } } else { observable = inventoryRepository.purchaseItem(shopItem.purchaseType, shopItem.key) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestProgressView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestProgressView.kt index a4d8f4f33..824289ea6 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestProgressView.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestProgressView.kt @@ -5,36 +5,33 @@ import android.content.SharedPreferences import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.RectF +import android.graphics.drawable.GradientDrawable import android.support.v4.content.ContextCompat import android.support.v7.app.AlertDialog import android.util.AttributeSet import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.FrameLayout import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import com.facebook.drawee.view.SimpleDraweeView import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.extensions.backgroundCompat import com.habitrpg.android.habitica.extensions.bindView +import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.inventory.Quest import com.habitrpg.android.habitica.models.inventory.QuestContent import com.habitrpg.android.habitica.models.inventory.QuestProgressCollect +import com.habitrpg.android.habitica.models.user.User import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils import com.habitrpg.android.habitica.ui.helpers.MarkdownParser import com.habitrpg.android.habitica.ui.views.* +import io.reactivex.Observable +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.functions.Consumer import io.realm.RealmList -import android.graphics.drawable.GradientDrawable -import android.net.Uri -import android.widget.FrameLayout -import com.facebook.drawee.backends.pipeline.Fresco -import com.facebook.drawee.interfaces.DraweeController -import com.habitrpg.android.habitica.extensions.backgroundCompat -import com.habitrpg.android.habitica.helpers.RxErrorHandler -import com.habitrpg.android.habitica.models.user.User -import rx.Observable -import rx.android.schedulers.AndroidSchedulers -import rx.functions.Action1 class QuestProgressView : LinearLayout { @@ -200,10 +197,10 @@ class QuestProgressView : LinearLayout { progress?.rageStrikes?.sortedByDescending { it.wasHit }?.forEach { strike -> val iconView = ImageView(context) if (strike.wasHit) { - DataBindingUtils.loadImage("rage_strike_${strike.key}", { + DataBindingUtils.loadImage("rage_strike_${strike.key}") { Observable.just(it) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(Action1 { + .subscribe(Consumer { val displayDensity = resources.displayMetrics.density val width = it.width * displayDensity val height = it.height * displayDensity @@ -213,7 +210,7 @@ class QuestProgressView : LinearLayout { showActiveStrikeAlert(strike.key) } }, RxErrorHandler.handleEmptyError()) - }) + } } else { iconView.setImageBitmap(HabiticaIconsHelper.imageOfRageStrikeInactive()) iconView.setOnClickListener { showPendingStrikeAlert() } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/BulkAllocateStatsDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/BulkAllocateStatsDialog.kt index e5403b906..4995de327 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/BulkAllocateStatsDialog.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/BulkAllocateStatsDialog.kt @@ -11,10 +11,9 @@ import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.data.UserRepository import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.user.User -import com.habitrpg.android.habitica.ui.views.stats.StatsSliderView +import io.reactivex.disposables.Disposable +import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.dialog_bulk_allocate.* -import rx.Subscription -import rx.functions.Action1 import javax.inject.Inject class BulkAllocateStatsDialog(context: Context, component: AppComponent) : AlertDialog(context) { @@ -22,7 +21,7 @@ class BulkAllocateStatsDialog(context: Context, component: AppComponent) : Alert @Inject lateinit var userRepository: UserRepository - var subscription: Subscription? = null + var subscription: Disposable? = null private var allocatedPoints: Int get() { @@ -87,7 +86,7 @@ class BulkAllocateStatsDialog(context: Context, component: AppComponent) : Alert override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - subscription = userRepository.getUser().subscribe(Action1 { + subscription = userRepository.getUser().subscribe(Consumer { user = it }, RxErrorHandler.handleEmptyError()) @@ -146,7 +145,7 @@ class BulkAllocateStatsDialog(context: Context, component: AppComponent) : Alert } override fun dismiss() { - subscription?.unsubscribe() + subscription?.dispose() super.dismiss() } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/TaskFilterDialog.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/TaskFilterDialog.java index 4f92f9143..ce7ed2d06 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/TaskFilterDialog.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/TaskFilterDialog.java @@ -43,6 +43,8 @@ import javax.inject.Inject; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; +import io.reactivex.Observable; +import io.reactivex.functions.Function; public class TaskFilterDialog extends AlertDialog implements RadioGroup.OnCheckedChangeListener { @@ -213,8 +215,8 @@ public class TaskFilterDialog extends AlertDialog implements RadioGroup.OnChecke if (this.getWindow() != null) { this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); } - repository.updateTags(editedTags.values()).subscribe(tag -> editedTags.remove(tag.getId()), RxErrorHandler.handleEmptyError()); - repository.createTags(createdTags.values()).subscribe(tag -> createdTags.remove(tag.getId()), RxErrorHandler.handleEmptyError()); + repository.updateTags(editedTags.values()).toObservable() .flatMap(tags -> Observable.fromIterable(tags)).subscribe(tag -> editedTags.remove(tag.id), RxErrorHandler.handleEmptyError()); + repository.createTags(createdTags.values()).toObservable() .flatMap(tags -> Observable.fromIterable(tags)).subscribe(tag -> createdTags.remove(tag.getId()), RxErrorHandler.handleEmptyError()); repository.deleteTags(deletedTags).subscribe(tags1 -> deletedTags.clear(), RxErrorHandler.handleEmptyError()); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/yesterdailies/YesterdailyDialog.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/yesterdailies/YesterdailyDialog.java index b238f45a0..2daf66b2d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/yesterdailies/YesterdailyDialog.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/yesterdailies/YesterdailyDialog.java @@ -27,8 +27,8 @@ import java.util.concurrent.TimeUnit; import butterknife.BindColor; import butterknife.BindView; import butterknife.ButterKnife; -import rx.Observable; -import rx.android.schedulers.AndroidSchedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; public class YesterdailyDialog extends AlertDialog { @@ -139,20 +139,19 @@ public class YesterdailyDialog extends AlertDialog { public static void showDialogIfNeeded(Activity activity, String userId, UserRepository userRepository, TaskRepository taskRepository) { if (userRepository != null && userId != null) { - Observable.just(null) + Observable.just("") .delay(500, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) .filter(aVoid -> !userRepository.isClosed()) - .flatMap(aVoid -> userRepository.getUser(userId)) - .first() - .filter(user -> user != null && user.getNeedsCron() != null && user.getNeedsCron()) - .flatMap(user -> { + .flatMapMaybe(aVoid -> userRepository.getUser(userId).firstElement()) + .filter(user -> user != null && user != null && user.getNeedsCron()) + .flatMapMaybe(user -> { final Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, -1); - return taskRepository.updateDailiesIsDue(cal.getTime()); + return taskRepository.updateDailiesIsDue(cal.getTime()).firstElement(); }) - .flatMap(user -> taskRepository.getTasks(Task.TYPE_DAILY, userId).first()) + .flatMapMaybe(user -> taskRepository.getTasks(Task.TYPE_DAILY, userId).firstElement()) .map(tasks -> tasks.where().equalTo("isDue", true).equalTo("completed", false).equalTo("yesterDaily", true).findAll()) - .flatMap(taskRepository::getTaskCopies) + .flatMapMaybe( tasks -> taskRepository.getTaskCopies(tasks).firstElement()) .retry(1) .subscribe(tasks -> { if (isDisplaying) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/Action.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/Action.kt new file mode 100644 index 000000000..9f236e157 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/Action.kt @@ -0,0 +1,10 @@ +package com.habitrpg.android.habitica.utils + +interface Action1 { + /** + * Consume the given value. + * @param t the value + * @throws Exception on error + */ + fun call(t: T) +} \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/HabitButtonWidgetProvider.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/HabitButtonWidgetProvider.java index 8d782d9ec..4d3fe0a87 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/HabitButtonWidgetProvider.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/HabitButtonWidgetProvider.java @@ -79,7 +79,7 @@ public class HabitButtonWidgetProvider extends BaseWidgetProvider { int[] ids = {appWidgetId}; if (taskId != null) { - userRepository.getUser(userId).first().flatMap(user -> taskRepository.taskChecked(user, taskId, TaskDirection.up.toString().equals(direction), false)) + userRepository.getUser(userId).firstElement().flatMap(user -> taskRepository.taskChecked(user, taskId, TaskDirection.up.toString().equals(direction), false)) .subscribe(taskDirectionData -> showToastForTaskDirection(context, taskDirectionData, userId), RxErrorHandler.handleEmptyError(), () -> this.onUpdate(context, mgr, ids)); } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/HabitButtonWidgetService.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/HabitButtonWidgetService.java index 70660fd2d..0a1caeb44 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/HabitButtonWidgetService.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/HabitButtonWidgetService.java @@ -58,7 +58,7 @@ public class HabitButtonWidgetService extends Service { makeTaskMapping(); for (String taskid : this.taskMapping.keySet()) { - taskRepository.getUnmanagedTask(taskid).first().subscribe(this::updateData, RxErrorHandler.handleEmptyError()); + taskRepository.getUnmanagedTask(taskid).firstElement().subscribe(this::updateData, RxErrorHandler.handleEmptyError()); } stopSelf(); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListFactory.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListFactory.java index 61c9365fd..83c6bf26b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListFactory.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListFactory.java @@ -26,8 +26,8 @@ import java.util.List; import javax.inject.Inject; import javax.inject.Named; -import rx.Observable; -import rx.android.schedulers.AndroidSchedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; public abstract class TaskListFactory implements RemoteViewsService.RemoteViewsFactory { private final int widgetId; @@ -62,14 +62,14 @@ public abstract class TaskListFactory implements RemoteViewsService.RemoteViewsF private void loadData() { Handler mainHandler = new Handler(context.getMainLooper()); mainHandler.post(() -> taskRepository.getTasks(taskType, userID) - .first() - .flatMap(Observable::from) + .firstElement() + .toObservable() + .flatMap(Observable::fromIterable) .filter(task -> (task.getType().equals(Task.TYPE_TODO) && !task.getCompleted()) || task.isDisplayedActive()) .toList() - .flatMap(tasks -> taskRepository.getTaskCopies(tasks)) + .flatMapMaybe(tasks -> taskRepository.getTaskCopies(tasks).firstElement()) .subscribeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread()) - .first() .subscribe(tasks -> { taskList = tasks; AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(widgetId, R.id.list_view); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListWidgetProvider.java b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListWidgetProvider.java index 934b5da49..cf69004fe 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListWidgetProvider.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/widget/TaskListWidgetProvider.java @@ -55,7 +55,7 @@ public abstract class TaskListWidgetProvider extends BaseWidgetProvider { String taskId = intent.getStringExtra(TASK_ID_ITEM); if (taskId != null) { - userRepository.getUser(userId).first().flatMap(user -> taskRepository.taskChecked(user, taskId, true, false)) + userRepository.getUser(userId).firstElement().flatMap(user -> taskRepository.taskChecked(user, taskId, true, false)) .subscribe(taskDirectionData -> { taskRepository.markTaskCompleted(taskId, true); showToastForTaskDirection(context, taskDirectionData, userId); diff --git a/build.gradle b/build.gradle index 9b8092514..73167e6a3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.2.50' + ext.kotlin_version = '1.2.51' ext.build_tools_version = '27.0.3' ext.sdk_version = 27 @@ -14,7 +14,7 @@ buildscript { classpath 'com.android.tools.build:gradle:3.1.3' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'com.google.gms:google-services:4.0.1' - classpath "io.realm:realm-gradle-plugin:3.7.2" + classpath "io.realm:realm-gradle-plugin:5.3.1" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2' classpath "gradle.plugin.io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.0.0.RC4-3" diff --git a/seeds-sdk/build.gradle b/seeds-sdk/build.gradle index 95c490691..af6913e11 100755 --- a/seeds-sdk/build.gradle +++ b/seeds-sdk/build.gradle @@ -61,7 +61,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'org.glassfish:javax.json:1.0.4' - implementation 'com.google.android.gms:play-services:11.4.2' + implementation 'com.google.android.gms:play-services:12.0.1' implementation 'com.google.code.gson:gson:2.8.2' implementation 'com.android.support:multidex:1.0.3' implementation 'com.loopj.android:android-async-http:1.4.9' @@ -71,7 +71,7 @@ dependencies { androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2' testImplementation 'junit:junit:4.12' testImplementation "org.robolectric:robolectric:3.3.2" - testImplementation "org.robolectric:shadows-multidex:3.3.2" + testImplementation "org.robolectric:shadows-multidex:3.8" } publish {