Update to RxJava 2, RxAndroid 2 and Realm 5

This commit is contained in:
Phillip Thelen 2018-07-06 00:10:17 +02:00
parent d4ca24e65b
commit e66c95bda0
177 changed files with 3580 additions and 4228 deletions

View file

@ -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'

View file

@ -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) {

View file

@ -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<HabitResponse<Status>> getStatus();
Flowable<HabitResponse<Status>> getStatus();
@GET("content")
Observable<HabitResponse<ContentResult>> getContent(@Query("language") String language);
Flowable<HabitResponse<ContentResult>> getContent(@Query("language") String language);
/* user API */
@GET("user/")
Observable<HabitResponse<User>> getUser();
Flowable<HabitResponse<User>> getUser();
@PUT("user/")
Observable<HabitResponse<User>> updateUser(@Body Map<String, Object> updateDictionary);
Flowable<HabitResponse<User>> updateUser(@Body Map<String, Object> updateDictionary);
@PUT("user/")
Observable<HabitResponse<User>> registrationLanguage(@Header("Accept-Language") String registrationLanguage);
Flowable<HabitResponse<User>> registrationLanguage(@Header("Accept-Language") String registrationLanguage);
@GET("inbox/messages")
Observable<HabitResponse<List<ChatMessage>>> getInboxMessages();
Flowable<HabitResponse<List<ChatMessage>>> getInboxMessages();
@GET("user/in-app-rewards")
Observable<HabitResponse<List<ShopItem>>> retrieveInAppRewards();
Flowable<HabitResponse<List<ShopItem>>> retrieveInAppRewards();
@GET("user/inventory/buy")
Observable<HabitResponse<List<ShopItem>>> retrieveOldGearRewards();
Flowable<HabitResponse<List<ShopItem>>> retrieveOldGearRewards();
@POST("user/equip/{type}/{key}")
Observable<HabitResponse<Items>> equipItem(@Path("type") String type, @Path("key") String itemKey);
Flowable<HabitResponse<Items>> equipItem(@Path("type") String type, @Path("key") String itemKey);
@POST("user/buy/{key}")
Observable<HabitResponse<BuyResponse>> buyItem(@Path("key") String itemKey);
Flowable<HabitResponse<BuyResponse>> buyItem(@Path("key") String itemKey);
@POST("user/purchase/{type}/{key}")
Observable<HabitResponse<Void>> purchaseItem(@Path("type") String type, @Path("key") String itemKey);
Flowable<HabitResponse<Void>> purchaseItem(@Path("type") String type, @Path("key") String itemKey);
@POST("user/purchase-hourglass/{type}/{key}")
Observable<HabitResponse<Void>> purchaseHourglassItem(@Path("type") String type, @Path("key") String itemKey);
Flowable<HabitResponse<Void>> purchaseHourglassItem(@Path("type") String type, @Path("key") String itemKey);
@POST("user/buy-mystery-set/{key}")
Observable<HabitResponse<Void>> purchaseMysterySet(@Path("key") String itemKey);
Flowable<HabitResponse<Void>> purchaseMysterySet(@Path("key") String itemKey);
@POST("user/buy-quest/{key}")
Observable<HabitResponse<Void>> purchaseQuest(@Path("key") String key);
Flowable<HabitResponse<Void>> purchaseQuest(@Path("key") String key);
@POST("user/sell/{type}/{key}")
Observable<HabitResponse<User>> sellItem(@Path("type") String itemType, @Path("key") String itemKey);
Flowable<HabitResponse<User>> sellItem(@Path("type") String itemType, @Path("key") String itemKey);
@POST("user/feed/{pet}/{food}")
Observable<HabitResponse<FeedResponse>> feedPet(@Path("pet") String petKey, @Path("food") String foodKey);
Flowable<HabitResponse<FeedResponse>> feedPet(@Path("pet") String petKey, @Path("food") String foodKey);
@POST("user/hatch/{egg}/{hatchingPotion}")
Observable<HabitResponse<Items>> hatchPet(@Path("egg") String eggKey, @Path("hatchingPotion") String hatchingPotionKey);
Flowable<HabitResponse<Items>> hatchPet(@Path("egg") String eggKey, @Path("hatchingPotion") String hatchingPotionKey);
@GET("tasks/user")
Observable<HabitResponse<TaskList>> getTasks();
Flowable<HabitResponse<TaskList>> getTasks();
@GET("tasks/user")
Observable<HabitResponse<TaskList>> getTasks(@Query("type") String type);
Flowable<HabitResponse<TaskList>> getTasks(@Query("type") String type);
@GET("tasks/user")
Observable<HabitResponse<TaskList>> getTasks(@Query("type") String type, @Query("dueDate") String dueDate);
Flowable<HabitResponse<TaskList>> getTasks(@Query("type") String type, @Query("dueDate") String dueDate);
@POST("user/unlock")
Observable<HabitResponse<UnlockResponse>> unlockPath(@Query("path") String path);
Flowable<HabitResponse<UnlockResponse>> unlockPath(@Query("path") String path);
@GET("tasks/{id}")
Observable<HabitResponse<Task>> getTask(@Path("id") String id);
Flowable<HabitResponse<Task>> getTask(@Path("id") String id);
@POST("tasks/{id}/score/{direction}")
Observable<HabitResponse<TaskDirectionData>> postTaskDirection(@Path("id") String id, @Path("direction") String direction);
Flowable<HabitResponse<TaskDirectionData>> postTaskDirection(@Path("id") String id, @Path("direction") String direction);
@POST("tasks/{id}/move/to/{position}")
Observable<HabitResponse<List<String>>> postTaskNewPosition(@Path("id") String id, @Path("position") int position);
Flowable<HabitResponse<List<String>>> postTaskNewPosition(@Path("id") String id, @Path("position") int position);
@POST("tasks/{taskId}/checklist/{itemId}/score")
Observable<HabitResponse<Task>> scoreChecklistItem(@Path("taskId") String taskId, @Path("itemId") String itemId);
Flowable<HabitResponse<Task>> scoreChecklistItem(@Path("taskId") String taskId, @Path("itemId") String itemId);
@POST("tasks/user")
Observable<HabitResponse<Task>> createTask(@Body Task item);
Flowable<HabitResponse<Task>> createTask(@Body Task item);
@POST("tasks/user")
Observable<HabitResponse<List<Task>>> createTasks(@Body List<Task> tasks);
Flowable<HabitResponse<List<Task>>> createTasks(@Body List<Task> tasks);
@PUT("tasks/{id}")
Observable<HabitResponse<Task>> updateTask(@Path("id") String id, @Body Task item);
Flowable<HabitResponse<Task>> updateTask(@Path("id") String id, @Body Task item);
@DELETE("tasks/{id}")
Observable<HabitResponse<Void>> deleteTask(@Path("id") String id);
Flowable<HabitResponse<Void>> deleteTask(@Path("id") String id);
@POST("tags")
Observable<HabitResponse<Tag>> createTag(@Body Tag tag);
Flowable<HabitResponse<Tag>> createTag(@Body Tag tag);
@PUT("tags/{id}")
Observable<HabitResponse<Tag>> updateTag(@Path("id") String id, @Body Tag tag);
Flowable<HabitResponse<Tag>> updateTag(@Path("id") String id, @Body Tag tag);
@DELETE("tags/{id}")
Observable<HabitResponse<Void>> deleteTag(@Path("id") String id);
Flowable<HabitResponse<Void>> deleteTag(@Path("id") String id);
@POST("user/auth/local/register")
Observable<HabitResponse<UserAuthResponse>> registerUser(@Body UserAuth auth);
Flowable<HabitResponse<UserAuthResponse>> registerUser(@Body UserAuth auth);
@POST("user/auth/local/login")
Observable<HabitResponse<UserAuthResponse>> connectLocal(@Body UserAuth auth);
Flowable<HabitResponse<UserAuthResponse>> connectLocal(@Body UserAuth auth);
@POST("user/auth/social")
Observable<HabitResponse<UserAuthResponse>> connectSocial(@Body UserAuthSocial auth);
Flowable<HabitResponse<UserAuthResponse>> connectSocial(@Body UserAuthSocial auth);
@POST("user/sleep")
Observable<HabitResponse<Boolean>> sleep();
Flowable<HabitResponse<Boolean>> sleep();
@POST("user/revive")
Observable<HabitResponse<User>> revive();
Flowable<HabitResponse<User>> revive();
@POST("user/class/cast/{skill}")
Observable<HabitResponse<SkillResponse>> useSkill(@Path("skill") String skillName, @Query("targetType") String targetType, @Query("targetId") String targetId);
Flowable<HabitResponse<SkillResponse>> useSkill(@Path("skill") String skillName, @Query("targetType") String targetType, @Query("targetId") String targetId);
@POST("user/class/cast/{skill}")
Observable<HabitResponse<SkillResponse>> useSkill(@Path("skill") String skillName, @Query("targetType") String targetType);
Flowable<HabitResponse<SkillResponse>> useSkill(@Path("skill") String skillName, @Query("targetType") String targetType);
@POST("user/change-class")
Observable<HabitResponse<User>> changeClass();
Flowable<HabitResponse<User>> changeClass();
@POST("user/change-class")
Observable<HabitResponse<User>> changeClass(@Query("class") String className);
Flowable<HabitResponse<User>> changeClass(@Query("class") String className);
@POST("user/disable-classes")
Observable<HabitResponse<User>> disableClasses();
Flowable<HabitResponse<User>> disableClasses();
@POST("user/mark-pms-read")
Observable<Void> markPrivateMessagesRead();
Flowable<Void> markPrivateMessagesRead();
/* Group API */
@GET("groups")
Observable<HabitResponse<List<Group>>> listGroups(@Query("type") String type);
Flowable<HabitResponse<List<Group>>> listGroups(@Query("type") String type);
@GET("groups/{gid}")
Observable<HabitResponse<Group>> getGroup(@Path("gid") String groupId);
Flowable<HabitResponse<Group>> getGroup(@Path("gid") String groupId);
@PUT("groups/{id}")
Observable<HabitResponse<Void>> updateGroup(@Path("id") String id, @Body Group item);
Flowable<HabitResponse<Void>> updateGroup(@Path("id") String id, @Body Group item);
@GET("groups/{gid}/chat")
Observable<HabitResponse<List<ChatMessage>>> listGroupChat(@Path("gid") String groupId);
Flowable<HabitResponse<List<ChatMessage>>> listGroupChat(@Path("gid") String groupId);
@POST("groups/{gid}/join")
Observable<HabitResponse<Group>> joinGroup(@Path("gid") String groupId);
Flowable<HabitResponse<Group>> joinGroup(@Path("gid") String groupId);
@POST("groups/{gid}/leave")
Observable<HabitResponse<Void>> leaveGroup(@Path("gid") String groupId);
Flowable<HabitResponse<Void>> leaveGroup(@Path("gid") String groupId);
@POST("groups/{gid}/chat")
Observable<HabitResponse<PostChatMessageResult>> postGroupChat(@Path("gid") String groupId, @Body Map<String, String> message);
Flowable<HabitResponse<PostChatMessageResult>> postGroupChat(@Path("gid") String groupId, @Body Map<String, String> message);
@DELETE("groups/{gid}/chat/{messageId}")
Observable<HabitResponse<Void>> deleteMessage(@Path("gid") String groupId, @Path("messageId") String messageId);
Flowable<HabitResponse<Void>> deleteMessage(@Path("gid") String groupId, @Path("messageId") String messageId);
@GET("groups/{gid}/members")
Observable<HabitResponse<List<Member>>> getGroupMembers(@Path("gid") String groupId, @Query("includeAllPublicFields") Boolean includeAllPublicFields);
Flowable<HabitResponse<List<Member>>> getGroupMembers(@Path("gid") String groupId, @Query("includeAllPublicFields") Boolean includeAllPublicFields);
@GET("groups/{gid}/members")
Observable<HabitResponse<List<Member>>> getGroupMembers(@Path("gid") String groupId, @Query("includeAllPublicFields") Boolean includeAllPublicFields, @Query("lastId") String lastId);
Flowable<HabitResponse<List<Member>>> 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<HabitResponse<ChatMessage>> likeMessage(@Path("gid") String groupId, @Path("mid") String mid);
Flowable<HabitResponse<ChatMessage>> likeMessage(@Path("gid") String groupId, @Path("mid") String mid);
@POST("groups/{gid}/chat/{mid}/flag")
Observable<HabitResponse<Void>> flagMessage(@Path("gid") String groupId, @Path("mid") String mid);
Flowable<HabitResponse<Void>> flagMessage(@Path("gid") String groupId, @Path("mid") String mid);
@POST("groups/{gid}/chat/seen")
Observable<HabitResponse<Void>> seenMessages(@Path("gid") String groupId);
Flowable<HabitResponse<Void>> seenMessages(@Path("gid") String groupId);
@POST("groups/{gid}/invite")
Observable<HabitResponse<List<String>>> inviteToGroup(@Path("gid") String groupId, @Body Map<String, Object> inviteData);
Flowable<HabitResponse<List<String>>> inviteToGroup(@Path("gid") String groupId, @Body Map<String, Object> inviteData);
@POST("groups/{gid}/reject-invite")
Observable<HabitResponse<Void>> rejectGroupInvite(@Path("gid") String groupId);
Flowable<HabitResponse<Void>> rejectGroupInvite(@Path("gid") String groupId);
@POST("groups/{gid}/quests/accept")
Observable<HabitResponse<Void>> acceptQuest(@Path("gid") String groupId);
Flowable<HabitResponse<Void>> acceptQuest(@Path("gid") String groupId);
@POST("groups/{gid}/quests/reject")
Observable<HabitResponse<Void>> rejectQuest(@Path("gid") String groupId);
Flowable<HabitResponse<Void>> rejectQuest(@Path("gid") String groupId);
@POST("groups/{gid}/quests/cancel")
Observable<HabitResponse<Void>> cancelQuest(@Path("gid") String groupId);
Flowable<HabitResponse<Void>> cancelQuest(@Path("gid") String groupId);
@POST("groups/{gid}/quests/force-start")
Observable<HabitResponse<Quest>> forceStartQuest(@Path("gid") String groupId, @Body Group group);
Flowable<HabitResponse<Quest>> forceStartQuest(@Path("gid") String groupId, @Body Group group);
@POST("groups/{gid}/quests/invite/{questKey}")
Observable<HabitResponse<Quest>> inviteToQuest(@Path("gid") String groupId, @Path("questKey") String questKey);
Flowable<HabitResponse<Quest>> inviteToQuest(@Path("gid") String groupId, @Path("questKey") String questKey);
@POST("groups/{gid}/quests/abort")
Observable<HabitResponse<Quest>> abortQuest(@Path("gid") String groupId);
Flowable<HabitResponse<Quest>> abortQuest(@Path("gid") String groupId);
@POST("groups/{gid}/quests/leave")
Observable<HabitResponse<Void>> leaveQuest(@Path("gid") String groupId);
Flowable<HabitResponse<Void>> leaveQuest(@Path("gid") String groupId);
@POST("/iap/android/verify")
Observable<HabitResponse<PurchaseValidationResult>> validatePurchase(@Body PurchaseValidationRequest request);
Flowable<HabitResponse<PurchaseValidationResult>> validatePurchase(@Body PurchaseValidationRequest request);
@POST("/iap/android/subscribe")
Observable<HabitResponse<Void>> validateSubscription(@Body SubscriptionValidationRequest request);
Flowable<HabitResponse<Void>> validateSubscription(@Body SubscriptionValidationRequest request);
@POST("user/custom-day-start")
Observable<HabitResponse<User>> changeCustomDayStart(@Body Map<String, Object> updateObject);
Flowable<HabitResponse<User>> changeCustomDayStart(@Body Map<String, Object> updateObject);
//Members URL
@GET("members/{mid}")
Observable<HabitResponse<Member>> getMember(@Path("mid") String memberId);
Flowable<HabitResponse<Member>> getMember(@Path("mid") String memberId);
@GET("members/{mid}/achievements")
Observable<HabitResponse<AchievementResult>> getMemberAchievements(@Path("mid") String memberId);
Flowable<HabitResponse<AchievementResult>> getMemberAchievements(@Path("mid") String memberId);
@POST("members/send-private-message")
Observable<HabitResponse<PostChatMessageResult>> postPrivateMessage(@Body Map<String, String> messageDetails);
Flowable<HabitResponse<PostChatMessageResult>> postPrivateMessage(@Body Map<String, String> messageDetails);
@GET("shops/{identifier}")
Observable<HabitResponse<Shop>> retrieveShopInventory(@Path("identifier") String identifier);
Flowable<HabitResponse<Shop>> retrieveShopInventory(@Path("identifier") String identifier);
@GET("shops/market-gear")
Observable<HabitResponse<Shop>> retrieveMarketGear();
Flowable<HabitResponse<Shop>> retrieveMarketGear();
//Push notifications
@POST("user/push-devices")
Observable<HabitResponse<List<Void>>> addPushDevice(@Body Map<String, String> pushDeviceData);
Flowable<HabitResponse<List<Void>>> addPushDevice(@Body Map<String, String> pushDeviceData);
@DELETE("user/push-devices/{regId}")
Observable<HabitResponse<List<Void>>> deletePushDevice(@Path("regId") String regId);
Flowable<HabitResponse<List<Void>>> deletePushDevice(@Path("regId") String regId);
/* challenges api */
@GET("challenges/user")
Observable<HabitResponse<List<Challenge>>> getUserChallenges();
Flowable<HabitResponse<List<Challenge>>> getUserChallenges();
@GET("tasks/challenge/{challengeId}")
Observable<HabitResponse<TaskList>> getChallengeTasks(@Path("challengeId") String challengeId);
Flowable<HabitResponse<TaskList>> getChallengeTasks(@Path("challengeId") String challengeId);
@GET("challenges/{challengeId}")
Observable<HabitResponse<Challenge>> getChallenge(@Path("challengeId") String challengeId);
Flowable<HabitResponse<Challenge>> getChallenge(@Path("challengeId") String challengeId);
@POST("challenges/{challengeId}/join")
Observable<HabitResponse<Challenge>> joinChallenge(@Path("challengeId") String challengeId);
Flowable<HabitResponse<Challenge>> joinChallenge(@Path("challengeId") String challengeId);
@POST("challenges/{challengeId}/leave")
Observable<HabitResponse<Void>> leaveChallenge(@Path("challengeId") String challengeId, @Body LeaveChallengeBody body);
Flowable<HabitResponse<Void>> leaveChallenge(@Path("challengeId") String challengeId, @Body LeaveChallengeBody body);
@POST("challenges")
Observable<HabitResponse<Challenge>> createChallenge(@Body Challenge challenge);
Flowable<HabitResponse<Challenge>> createChallenge(@Body Challenge challenge);
@POST("tasks/challenge/{challengeId}")
Observable<HabitResponse<List<Task>>> createChallengeTasks(@Path("challengeId") String challengeId, @Body List<Task> tasks);
Flowable<HabitResponse<List<Task>>> createChallengeTasks(@Path("challengeId") String challengeId, @Body List<Task> tasks);
@PUT("challenges/{challengeId}")
Observable<HabitResponse<Challenge>> updateChallenge(@Path("challengeId") String challengeId, @Body Challenge challenge);
Flowable<HabitResponse<Challenge>> updateChallenge(@Path("challengeId") String challengeId, @Body Challenge challenge);
@DELETE("challenges/{challengeId}")
Observable<HabitResponse<Void>> deleteChallenge(@Path("challengeId") String challengeId);
Flowable<HabitResponse<Void>> deleteChallenge(@Path("challengeId") String challengeId);
//DEBUG: These calls only work on a local development server
@POST("debug/add-ten-gems")
Observable<HabitResponse<Void>> debugAddTenGems();
Flowable<HabitResponse<Void>> debugAddTenGems();
// Notifications
@POST("notifications/{notificationId}/read")
Observable<HabitResponse<List>> readNotification(@Path("notificationId") String notificationId);
Flowable<HabitResponse<List>> readNotification(@Path("notificationId") String notificationId);
@POST("user/open-mystery-item")
Observable<HabitResponse<Equipment>> openMysteryItem();
Flowable<HabitResponse<Equipment>> openMysteryItem();
@POST("cron")
Observable<HabitResponse<Void>> runCron();
Flowable<HabitResponse<Void>> runCron();
@POST("user/reset")
Observable<HabitResponse<Void>> resetAccount();
Flowable<HabitResponse<Void>> resetAccount();
@HTTP(method = "DELETE", path = "user", hasBody = true)
Observable<HabitResponse<Void>> deleteAccount(@Body Map<String, String> body);
Flowable<HabitResponse<Void>> deleteAccount(@Body Map<String, String> body);
@GET("user/toggle-pinned-item/{pinType}/{path}")
Observable<HabitResponse<Void>> togglePinnedItem(@Path("pinType") String pinType,@Path("path") String path);
Flowable<HabitResponse<Void>> togglePinnedItem(@Path("pinType") String pinType,@Path("path") String path);
@POST("user/reset-password")
Observable<HabitResponse<Void>> sendPasswordResetEmail(@Body Map<String, String> data);
Flowable<HabitResponse<Void>> sendPasswordResetEmail(@Body Map<String, String> data);
@PUT("user/auth/update-username")
Observable<HabitResponse<Void>> updateLoginName(@Body Map<String, String> data);
Flowable<HabitResponse<Void>> updateLoginName(@Body Map<String, String> data);
@PUT("user/auth/update-email")
Observable<HabitResponse<Void>> updateEmail(@Body Map<String, String> data);
Flowable<HabitResponse<Void>> updateEmail(@Body Map<String, String> data);
@PUT("user/auth/update-password")
Observable<HabitResponse<Void>> updatePassword(@Body Map<String, String> data);
Flowable<HabitResponse<Void>> updatePassword(@Body Map<String, String> data);
@POST("user/allocate")
Observable<HabitResponse<Stats>> allocatePoint(@Query("stat") String stat);
Flowable<HabitResponse<Stats>> allocatePoint(@Query("stat") String stat);
@POST("user/allocate-bulk")
Observable<HabitResponse<Stats>> bulkAllocatePoints(@Body Map<String, Map<String, Integer>> stats);
Flowable<HabitResponse<Stats>> bulkAllocatePoints(@Body Map<String, Map<String, Integer>> stats);
@GET("world-state")
Observable<HabitResponse<WorldState>> getWorldState();
Flowable<HabitResponse<WorldState>> getWorldState();
}

View file

@ -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<HabitResponse<MaintenanceResponse>> getMaintenanceStatus();
Flowable<HabitResponse<MaintenanceResponse>> getMaintenanceStatus();
@GET("deprecation-android.json")
Observable<HabitResponse<MaintenanceResponse>> getDepricationStatus();
Flowable<HabitResponse<MaintenanceResponse>> getDepricationStatus();
}

View file

@ -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<Status> getStatus();
Observable<ContentResult> getContent();
Observable<ContentResult> getContent(String language);
/* user API */
Observable<User> getUser();
Observable<User> updateUser(Map<String, Object> updateDictionary);
Observable<User> registrationLanguage(String registrationLanguage);
Observable<List<ShopItem>> retrieveInAppRewards();
Observable<List<ShopItem>> retrieveOldGear();
Observable<Items> equipItem(String type, String itemKey);
Observable<BuyResponse> buyItem(String itemKey);
Observable<Void> purchaseItem(String type, String itemKey);
Observable<Void> purchaseHourglassItem(String type, String itemKey);
Observable<Void> purchaseMysterySet(String itemKey);
Observable<Void> purchaseQuest(String key);
Observable<Void> validateSubscription(SubscriptionValidationRequest request);
Observable<User> sellItem(String itemType, String itemKey);
Observable<FeedResponse> feedPet(String petKey, String foodKey);
Observable<Items> hatchPet(String eggKey, String hatchingPotionKey);
Observable<TaskList> getTasks();
Observable<TaskList> getTasks(String type);
Observable<TaskList> getTasks(String type, String dueDate);
Observable<UnlockResponse> unlockPath(String path);
Observable<Task> getTask(String id);
Observable<TaskDirectionData> postTaskDirection(String id, String direction);
Observable<List<String>> postTaskNewPosition(String id, int position);
Observable<Task> scoreChecklistItem(String taskId, String itemId);
Observable<Task> createTask(Task item);
Observable<List<Task>> createTasks(List<Task> tasks);
Observable<Task> updateTask(String id, Task item);
Observable<Void> deleteTask(String id);
Observable<Tag> createTag(Tag tag);
Observable<Tag> updateTag(String id, Tag tag);
Observable<Void> deleteTag(String id);
Observable<UserAuthResponse> registerUser(String username, String email, String password, String confirmPassword);
Observable<UserAuthResponse> connectUser(String username, String password);
Observable<UserAuthResponse> connectSocial(String network, String userId, String accessToken);
Observable<Boolean> sleep();
Observable<User> revive();
Observable<SkillResponse> useSkill(String skillName, String targetType, String targetId);
Observable<SkillResponse> useSkill(String skillName, String targetType);
Observable<User> changeClass();
Observable<User> changeClass(String className);
Observable<User> disableClasses();
Observable<Void> markPrivateMessagesRead();
/* Group API */
Observable<List<Group>> listGroups(String type);
Observable<Group> getGroup(String groupId);
Observable<Void> updateGroup(String id, Group item);
Observable<List<ChatMessage>> listGroupChat(String groupId);
Observable<Group> joinGroup(String groupId);
Observable<Void> leaveGroup(String groupId);
Observable<PostChatMessageResult> postGroupChat(String groupId, Map<String, String> message);
Observable<Void> deleteMessage(String groupId, String messageId);
Observable<List<Member>> getGroupMembers(String groupId, Boolean includeAllPublicFields);
Observable<List<Member>> getGroupMembers(String groupId, Boolean includeAllPublicFields, String lastId);
// Like returns the full chat list
Observable<ChatMessage> likeMessage(String groupId, String mid);
Observable<Void> flagMessage(String groupId, String mid);
Observable<Void> seenMessages(String groupId);
Observable<List<String>> inviteToGroup(String groupId, Map<String, Object> inviteData);
Observable<Void> rejectGroupInvite(String groupId);
Observable<Void> acceptQuest(String groupId);
Observable<Void> rejectQuest(String groupId);
Observable<Void> cancelQuest(String groupId);
Observable<Quest> forceStartQuest(String groupId, Group group);
Observable<Quest> inviteToQuest(String groupId,String questKey);
Observable<Quest> abortQuest(String groupId);
Observable<Void> leaveQuest(String groupId);
Observable<PurchaseValidationResult> validatePurchase(PurchaseValidationRequest request);
Observable<User> changeCustomDayStart(Map<String, Object> updateObject);
//Members URL
Observable<Member> getMember(String memberId);
Observable<AchievementResult> getMemberAchievements(String memberId);
Observable<PostChatMessageResult> postPrivateMessage(Map<String, String> messageDetails);
Observable<Shop> retrieveShopIventory(String identifier);
//Push notifications
Observable<List<Void>> addPushDevice(Map<String, String> pushDeviceData);
Observable<List<Void>> deletePushDevice(String regId);
/* challenges api */
Observable<List<Challenge>> getUserChallenges();
Observable<TaskList> getChallengeTasks(String challengeId);
Observable<Challenge> getChallenge(String challengeId);
Observable<Challenge> joinChallenge(String challengeId);
Observable<Void> leaveChallenge(String challengeId, LeaveChallengeBody body);
Observable<Challenge> createChallenge(Challenge challenge);
Observable<List<Task>> createChallengeTasks(String challengeId, List<Task> tasks);
Observable<Challenge> updateChallenge(Challenge challenge);
Observable<Void> deleteChallenge(String challengeId);
//DEBUG: These calls only work on a local development server
Observable<Void> debugAddTenGems();
// Notifications
Observable<List> readNotification(String notificationId);
ErrorResponse getErrorResponse(HttpException throwable);
void updateAuthenticationCredentials(@Nullable String userID, @Nullable String apiToken);
boolean hasAuthenticationKeys();
Observable<User> retrieveUser(boolean withTasks);
Observable<List<ChatMessage>> retrieveInboxMessages();
<T> Observable.Transformer<HabitResponse<T>, T> configureApiCallObserver();
Observable<Equipment> openMysteryItem();
Observable<Void> runCron();
Observable<Void> resetAccount();
Observable<Void> deleteAccount(String password);
Observable<Void> togglePinnedItem(String pinType, String path);
Observable<Void> sendPasswordResetEmail(String email);
Observable<Void> updateLoginName(String newLoginName, String password);
Observable<Void> updateEmail(String newEmail, String password);
Observable<Void> updatePassword(String newPassword, String oldPassword, String oldPasswordConfirmation);
Observable<Stats> allocatePoint(String stat);
Observable<Stats> bulkAllocatePoints(int strength, int intelligence, int constitution, int perception);
Observable<Shop> retrieveMarketGear();
Observable<WorldState> getWorldState();
}

View file

@ -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<Status>
val content: Flowable<ContentResult>
/* user API */
val user: Flowable<User>
val tasks: Flowable<TaskList>
/* challenges api */
val userChallenges: Flowable<List<Challenge>>
val worldState: Flowable<WorldState>
fun setLanguageCode(languageCode: String)
fun getContent(language: String): Flowable<ContentResult>
fun updateUser(updateDictionary: Map<String, Any>): Flowable<User>
fun registrationLanguage(registrationLanguage: String): Flowable<User>
fun retrieveInAppRewards(): Flowable<List<ShopItem>>
fun retrieveOldGear(): Flowable<List<ShopItem>>
fun equipItem(type: String, itemKey: String): Flowable<Items>
fun buyItem(itemKey: String): Flowable<BuyResponse>
fun purchaseItem(type: String, itemKey: String): Flowable<Void>
fun purchaseHourglassItem(type: String, itemKey: String): Flowable<Void>
fun purchaseMysterySet(itemKey: String): Flowable<Void>
fun purchaseQuest(key: String): Flowable<Void>
fun validateSubscription(request: SubscriptionValidationRequest): Flowable<Void>
fun sellItem(itemType: String, itemKey: String): Flowable<User>
fun feedPet(petKey: String, foodKey: String): Flowable<FeedResponse>
fun hatchPet(eggKey: String, hatchingPotionKey: String): Flowable<Items>
fun getTasks(type: String): Flowable<TaskList>
fun getTasks(type: String, dueDate: String): Flowable<TaskList>
fun unlockPath(path: String): Flowable<UnlockResponse>
fun getTask(id: String): Flowable<Task>
fun postTaskDirection(id: String, direction: String): Flowable<TaskDirectionData>
fun postTaskNewPosition(id: String, position: Int): Flowable<List<String>>
fun scoreChecklistItem(taskId: String, itemId: String): Flowable<Task>
fun createTask(item: Task): Flowable<Task>
fun createTasks(tasks: List<Task>): Flowable<List<Task>>
fun updateTask(id: String, item: Task): Flowable<Task>
fun deleteTask(id: String): Flowable<Void>
fun createTag(tag: Tag): Flowable<Tag>
fun updateTag(id: String, tag: Tag): Flowable<Tag>
fun deleteTag(id: String): Flowable<Void>
fun registerUser(username: String, email: String, password: String, confirmPassword: String): Flowable<UserAuthResponse>
fun connectUser(username: String, password: String): Flowable<UserAuthResponse>
fun connectSocial(network: String, userId: String, accessToken: String): Flowable<UserAuthResponse>
fun sleep(): Flowable<Boolean>
fun revive(): Flowable<User>
fun useSkill(skillName: String, targetType: String, targetId: String): Flowable<SkillResponse>
fun useSkill(skillName: String, targetType: String): Flowable<SkillResponse>
fun changeClass(): Flowable<User>
fun changeClass(className: String): Flowable<User>
fun disableClasses(): Flowable<User>
fun markPrivateMessagesRead(): Flowable<Void>
/* Group API */
fun listGroups(type: String): Flowable<List<Group>>
fun getGroup(groupId: String): Flowable<Group>
fun updateGroup(id: String, item: Group): Flowable<Void>
fun listGroupChat(groupId: String): Flowable<List<ChatMessage>>
fun joinGroup(groupId: String): Flowable<Group>
fun leaveGroup(groupId: String): Flowable<Void>
fun postGroupChat(groupId: String, message: Map<String, String>): Flowable<PostChatMessageResult>
fun deleteMessage(groupId: String, messageId: String): Flowable<Void>
fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?): Flowable<List<Member>>
fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?, lastId: String): Flowable<List<Member>>
// Like returns the full chat list
fun likeMessage(groupId: String, mid: String): Flowable<ChatMessage>
fun flagMessage(groupId: String, mid: String): Flowable<Void>
fun seenMessages(groupId: String): Flowable<Void>
fun inviteToGroup(groupId: String, inviteData: Map<String, Any>): Flowable<List<String>>
fun rejectGroupInvite(groupId: String): Flowable<Void>
fun acceptQuest(groupId: String): Flowable<Void>
fun rejectQuest(groupId: String): Flowable<Void>
fun cancelQuest(groupId: String): Flowable<Void>
fun forceStartQuest(groupId: String, group: Group): Flowable<Quest>
fun inviteToQuest(groupId: String, questKey: String): Flowable<Quest>
fun abortQuest(groupId: String): Flowable<Quest>
fun leaveQuest(groupId: String): Flowable<Void>
fun validatePurchase(request: PurchaseValidationRequest): Flowable<PurchaseValidationResult>
fun changeCustomDayStart(updateObject: Map<String, Any>): Flowable<User>
//Members URL
fun getMember(memberId: String): Flowable<Member>
fun getMemberAchievements(memberId: String): Flowable<AchievementResult>
fun postPrivateMessage(messageDetails: Map<String, String>): Flowable<PostChatMessageResult>
fun retrieveShopIventory(identifier: String): Flowable<Shop>
//Push notifications
fun addPushDevice(pushDeviceData: Map<String, String>): Flowable<List<Void>>
fun deletePushDevice(regId: String): Flowable<List<Void>>
fun getChallengeTasks(challengeId: String): Flowable<TaskList>
fun getChallenge(challengeId: String): Flowable<Challenge>
fun joinChallenge(challengeId: String): Flowable<Challenge>
fun leaveChallenge(challengeId: String, body: LeaveChallengeBody): Flowable<Void>
fun createChallenge(challenge: Challenge): Flowable<Challenge>
fun createChallengeTasks(challengeId: String, tasks: List<Task>): Flowable<List<Task>>
fun updateChallenge(challenge: Challenge): Flowable<Challenge>
fun deleteChallenge(challengeId: String): Flowable<Void>
//DEBUG: These calls only work on a local development server
fun debugAddTenGems(): Flowable<Void>
// Notifications
fun readNotification(notificationId: String): Flowable<List<*>>
fun getErrorResponse(throwable: HttpException): ErrorResponse
fun updateAuthenticationCredentials(userID: String?, apiToken: String?)
fun hasAuthenticationKeys(): Boolean
fun retrieveUser(withTasks: Boolean): Flowable<User>
fun retrieveInboxMessages(): Flowable<List<ChatMessage>>
fun <T> configureApiCallObserver(): FlowableTransformer<HabitResponse<T>, T>
fun openMysteryItem(): Flowable<Equipment>
fun runCron(): Flowable<Void>
fun resetAccount(): Flowable<Void>
fun deleteAccount(password: String): Flowable<Void>
fun togglePinnedItem(pinType: String, path: String): Flowable<Void>
fun sendPasswordResetEmail(email: String): Flowable<Void>
fun updateLoginName(newLoginName: String, password: String): Flowable<Void>
fun updateEmail(newEmail: String, password: String): Flowable<Void>
fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable<Void>
fun allocatePoint(stat: String): Flowable<Stats>
fun bulkAllocatePoints(strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable<Stats>
fun retrieveMarketGear(): Flowable<Shop>
}

View file

@ -1,15 +0,0 @@
package com.habitrpg.android.habitica.data;
import java.util.List;
import io.realm.RealmObject;
public interface BaseRepository {
void close();
<T extends RealmObject> T getUnmanagedCopy(T object);
<T extends RealmObject> List<T> getUnmanagedCopy(List<T> list);
boolean isClosed();
}

View file

@ -0,0 +1,13 @@
package com.habitrpg.android.habitica.data
import io.realm.RealmObject
interface BaseRepository {
val isClosed: Boolean
fun close()
fun <T : RealmObject> getUnmanagedCopy(obj: T): T
fun <T : RealmObject> getUnmanagedCopy(list: List<T>): List<T>
}

View file

@ -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<Challenge> getChallenge(String challengeId);
Observable<TaskList> getChallengeTasks(String challengeId);
Flowable<Challenge> getChallenge(String challengeId);
Flowable<TaskList> getChallengeTasks(String challengeId);
Observable<Challenge> createChallenge(Challenge challenge, List<Task> taskList);
Flowable<Challenge> createChallenge(Challenge challenge, List<Task> 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<Challenge> updateChallenge(Challenge challenge, List<Task> fullTaskList,
Flowable<Challenge> updateChallenge(Challenge challenge, List<Task> fullTaskList,
List<Task> addedTaskList, List<Task> updatedTaskList, List<String> removedTaskList);
Observable<Void> deleteChallenge(String challengeId);
Flowable<Void> deleteChallenge(String challengeId);
Observable<RealmResults<Challenge>> getChallenges();
Observable<RealmResults<Challenge>> getUserChallenges(String userId);
Flowable<RealmResults<Challenge>> getChallenges();
Flowable<RealmResults<Challenge>> getUserChallenges(String userId);
Observable<List<Challenge>> retrieveChallenges(User user);
Flowable<List<Challenge>> retrieveChallenges(User user);
Observable<Void> leaveChallenge(Challenge challenge, LeaveChallengeBody leaveChallengeBody);
Flowable<Void> leaveChallenge(Challenge challenge, LeaveChallengeBody leaveChallengeBody);
Observable<Challenge> joinChallenge(Challenge challenge);
Flowable<Challenge> joinChallenge(Challenge challenge);
}

View file

@ -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<ContentResult> retrieveContent();
Observable<ContentResult> retrieveContent(boolean forced);
Flowable<ContentResult> retrieveContent();
Flowable<ContentResult> retrieveContent(boolean forced);
Observable<WorldState> retrieveWorldState();
Flowable<WorldState> retrieveWorldState();
}

View file

@ -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<RealmResults<Customization>> getCustomizations(String type, String category, boolean onlyAvailable);
Flowable<RealmResults<Customization>> getCustomizations(String type, String category, boolean onlyAvailable);
}

View file

@ -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<RealmResults<FAQArticle>> getArticles();
Flowable<RealmResults<FAQArticle>> getArticles();
}

View file

@ -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<QuestContent> getQuestContent(String key);
Flowable<QuestContent> getQuestContent(String key);
Observable<RealmResults<Equipment>> getItems(List<String> searchedKeys);
Flowable<RealmResults<Equipment>> getItems(List<String> searchedKeys);
long getArmoireRemainingCount();
Observable<RealmResults<ShopItem>> getInAppRewards();
Observable<List<ShopItem>> retrieveInAppRewards();
Flowable<RealmResults<ShopItem>> getInAppRewards();
Flowable<List<ShopItem>> retrieveInAppRewards();
Observable<RealmResults<Equipment>> getOwnedEquipment(@NotNull String type);
Observable<RealmResults<Equipment>> getOwnedEquipment();
Flowable<RealmResults<Equipment>> getOwnedEquipment(@NotNull String type);
Flowable<RealmResults<Equipment>> getOwnedEquipment();
Observable<? extends RealmResults<? extends Item>> getOwnedItems(Class<? extends Item> itemClass, User user);
Observable<? extends Map<String, Item>> getOwnedItems(@NotNull User user);
Flowable<? extends RealmResults<? extends Item>> getOwnedItems(Class<? extends Item> itemClass, User user);
Flowable<? extends Map<String, Item>> getOwnedItems(@NotNull User user);
Observable<Equipment> getEquipment(String key);
Flowable<Equipment> getEquipment(String key);
Observable<Equipment> openMysteryItem(User user);
Flowable<Equipment> openMysteryItem(User user);
void saveEquipment(Equipment equipment);
Observable<RealmResults<Mount>> getMounts();
Observable<RealmResults<Mount>> getMounts(@NotNull String type, @NotNull String group);
Flowable<RealmResults<Mount>> getMounts();
Flowable<RealmResults<Mount>> getMounts(@NotNull String type, @NotNull String group);
Observable<RealmResults<Mount>> getOwnedMounts();
Observable<RealmResults<Mount>> getOwnedMounts(@NotNull String animalType, @NotNull String animalGroup);
Flowable<RealmResults<Mount>> getOwnedMounts();
Flowable<RealmResults<Mount>> getOwnedMounts(@NotNull String animalType, @NotNull String animalGroup);
Observable<RealmResults<Pet>> getPets();
Observable<RealmResults<Pet>> getPets(@NotNull String type, @NotNull String group);
Flowable<RealmResults<Pet>> getPets();
Flowable<RealmResults<Pet>> getPets(@NotNull String type, @NotNull String group);
Observable<RealmResults<Pet>> getOwnedPets();
Observable<RealmResults<Pet>> getOwnedPets(@NotNull String type, @NotNull String group);
Flowable<RealmResults<Pet>> getOwnedPets();
Flowable<RealmResults<Pet>> getOwnedPets(@NotNull String type, @NotNull String group);
void updateOwnedEquipment(User user);
void changeOwnedCount(String type, String key, int amountToAdd);
Observable<User> sellItem(User user, String type, String key);
Observable<User> sellItem(User user, Item item);
Flowable<User> sellItem(User user, String type, String key);
Flowable<User> sellItem(User user, Item item);
Observable<Items> equipGear(User user, String equipment, boolean asCostume);
Observable<Items> equip(User user, String type, String key);
Flowable<Items> equipGear(User user, String equipment, boolean asCostume);
Flowable<Items> equip(User user, String type, String key);
Observable<FeedResponse> feedPet(Pet pet, Food food);
Flowable<FeedResponse> feedPet(Pet pet, Food food);
Observable<Items> hatchPet(Egg egg, HatchingPotion hatchingPotion);
Flowable<Items> hatchPet(Egg egg, HatchingPotion hatchingPotion);
Observable<Quest> inviteToQuest(QuestContent quest);
Flowable<Quest> inviteToQuest(QuestContent quest);
Observable<BuyResponse> buyItem(User user, String id, double value);
Flowable<BuyResponse> buyItem(User user, String id, double value);
Observable<Shop> retrieveShopInventory(String identifier);
Observable<Shop> retrieveMarketGear();
Flowable<Shop> retrieveShopInventory(String identifier);
Flowable<Shop> retrieveMarketGear();
Observable<Void> purchaseMysterySet(String categoryIdentifier);
Flowable<Void> purchaseMysterySet(String categoryIdentifier);
Observable<Void> purchaseHourglassItem(String purchaseType, String key);
Flowable<Void> purchaseHourglassItem(String purchaseType, String key);
Observable<Void> purchaseQuest(String key);
Flowable<Void> purchaseQuest(String key);
Observable<Void> purchaseItem(String purchaseType, String key);
Flowable<Void> purchaseItem(String purchaseType, String key);
Observable<List<ShopItem>> togglePinnedItem(ShopItem item);
Flowable<List<ShopItem>> togglePinnedItem(ShopItem item);
}

View file

@ -8,6 +8,6 @@ import java.util.List;
public interface SetupCustomizationRepository {
public List<SetupCustomization> getCustomizations(String type, User user);
public List<SetupCustomization> getCustomizations(String type, String subtype, User user);
List<SetupCustomization> getCustomizations(String type, User user);
List<SetupCustomization> getCustomizations(String type, String subtype, User user);
}

View file

@ -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<RealmResults<Group>>
fun getPublicGuilds(): Flowable<RealmResults<Group>>
fun getUserChallenges(): Observable<List<Challenge>>
fun getUserChallenges(): Flowable<List<Challenge>>
fun getUserGroups(): Observable<RealmResults<Group>>
fun retrieveGroupChat(groupId: String): Observable<List<ChatMessage>>
fun getGroupChat(groupId: String): Observable<RealmResults<ChatMessage>>
fun getUserGroups(): Flowable<RealmResults<Group>>
fun retrieveGroupChat(groupId: String): Single<List<ChatMessage>>
fun getGroupChat(groupId: String): Flowable<RealmResults<ChatMessage>>
fun markMessagesSeen(seenGroupId: String)
fun flagMessage(chatMessage: ChatMessage): Observable<Void>
fun flagMessage(chatMessage: ChatMessage): Flowable<Void>
fun likeMessage(chatMessage: ChatMessage): Observable<ChatMessage>
fun likeMessage(chatMessage: ChatMessage): Flowable<ChatMessage>
fun deleteMessage(chatMessage: ChatMessage): Observable<Void>
fun deleteMessage(chatMessage: ChatMessage): Flowable<Void>
fun postGroupChat(groupId: String, messageObject: HashMap<String, String>): Observable<PostChatMessageResult>
fun postGroupChat(groupId: String, message: String): Observable<PostChatMessageResult>
fun postGroupChat(groupId: String, messageObject: HashMap<String, String>): Flowable<PostChatMessageResult>
fun postGroupChat(groupId: String, message: String): Flowable<PostChatMessageResult>
fun retrieveGroup(id: String): Observable<Group>
fun getGroup(id: String?): Observable<Group>
fun retrieveGroup(id: String): Flowable<Group>
fun getGroup(id: String?): Flowable<Group>
fun leaveGroup(id: String?): Observable<Group>
fun leaveGroup(id: String?): Flowable<Group>
fun joinGroup(id: String?): Observable<Group>
fun joinGroup(id: String?): Flowable<Group>
fun updateGroup(group: Group?, name: String?, description: String?, leader: String?, privacy: String?): Observable<Void>
fun updateGroup(group: Group?, name: String?, description: String?, leader: String?, privacy: String?): Flowable<Void>
fun retrieveGroups(type: String): Observable<List<Group>>
fun getGroups(type: String): Observable<RealmResults<Group>>
fun retrieveGroups(type: String): Flowable<List<Group>>
fun getGroups(type: String): Flowable<RealmResults<Group>>
fun postPrivateMessage(messageObject: HashMap<String, String>): Observable<PostChatMessageResult>
fun postPrivateMessage(recipientId: String, message: String): Observable<PostChatMessageResult>
fun postPrivateMessage(messageObject: HashMap<String, String>): Flowable<PostChatMessageResult>
fun postPrivateMessage(recipientId: String, message: String): Flowable<PostChatMessageResult>
fun getGroupMembers(id: String): Observable<RealmResults<Member>>
fun retrieveGroupMembers(id: String, includeAllPublicFields: Boolean): Observable<List<Member>>
fun getGroupMembers(id: String): Flowable<RealmResults<Member>>
fun retrieveGroupMembers(id: String, includeAllPublicFields: Boolean): Flowable<List<Member>>
fun inviteToGroup(id: String, inviteData: Map<String, Any>): Observable<List<String>>
fun inviteToGroup(id: String, inviteData: Map<String, Any>): Flowable<List<String>>
fun getMember(userId: String?): Observable<Member>
fun getMember(userId: String?): Flowable<Member>
fun markPrivateMessagesRead(user: User?): Observable<Void>
fun markPrivateMessagesRead(user: User?): Flowable<Void>
fun acceptQuest(user: User, partyId: String): Observable<Void>
fun rejectQuest(user: User, partyId: String): Observable<Void>
fun acceptQuest(user: User, partyId: String): Flowable<Void>
fun rejectQuest(user: User, partyId: String): Flowable<Void>
fun leaveQuest(partyId: String?): Observable<Void>
fun leaveQuest(partyId: String?): Flowable<Void>
fun cancelQuest(partyId: String?): Observable<Void>
fun cancelQuest(partyId: String?): Flowable<Void>
fun abortQuest(partyId: String?): Observable<Quest>
fun abortQuest(partyId: String?): Flowable<Quest>
fun rejectGroupInvite(groupId: String): Observable<Void>
fun rejectGroupInvite(groupId: String): Flowable<Void>
fun forceStartQuest(party: Group): Observable<Quest>
fun forceStartQuest(party: Group): Flowable<Quest>
fun getMemberAchievements(userId: String?): Observable<AchievementResult>
fun getMemberAchievements(userId: String?): Flowable<AchievementResult>
}

View file

@ -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<RealmResults<Tag>> getTags(String userId);
Observable<Tag> createTag(Tag tag);
Observable<Tag> updateTag(Tag tag);
Observable<Void> deleteTag(String id);
Observable<Tag> createTags(Collection<Tag> tags);
Observable<Tag> updateTags(Collection<Tag> tags);
Observable<List<Void>> deleteTags(Collection<String> tagIds);
void removeOldTags(List<Tag> onlineTags, String userID);
}

View file

@ -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<RealmResults<Tag>>
fun createTag(tag: Tag): Flowable<Tag>
fun updateTag(tag: Tag): Flowable<Tag>
fun deleteTag(id: String): Flowable<Void>
fun createTags(tags: Collection<Tag>): Single<List<Tag>>
fun updateTags(tags: Collection<Tag>): Single<List<Tag>>
fun deleteTags(tagIds: Collection<String>): Single<List<Void>>
fun removeOldTags(onlineTags: List<Tag>, userID: String)
}

View file

@ -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<RealmResults<Task>>
fun getTasks(userId: String): Observable<RealmResults<Task>>
fun getTasks(taskType: String, userID: String): Flowable<RealmResults<Task>>
fun getTasks(userId: String): Flowable<RealmResults<Task>>
fun saveTasks(userId: String, order: TasksOrder, tasks: TaskList)
fun retrieveTasks(userId: String, tasksOrder: TasksOrder): Observable<TaskList>
fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): Observable<TaskList>
fun retrieveTasks(userId: String, tasksOrder: TasksOrder): Flowable<TaskList>
fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): Flowable<TaskList>
fun taskChecked(user: User?, task: Task, up: Boolean, force: Boolean): Observable<TaskScoringResult?>
fun taskChecked(user: User?, taskId: String, up: Boolean, force: Boolean): Observable<TaskScoringResult?>
fun scoreChecklistItem(taskId: String, itemId: String): Observable<Task>
fun taskChecked(user: User?, task: Task, up: Boolean, force: Boolean): Flowable<TaskScoringResult?>
fun taskChecked(user: User?, taskId: String, up: Boolean, force: Boolean): Maybe<TaskScoringResult?>
fun scoreChecklistItem(taskId: String, itemId: String): Flowable<Task>
fun getTask(taskId: String): Observable<Task>
fun getTaskCopy(taskId: String): Observable<Task>
fun createTask(task: Task): Observable<Task>
fun updateTask(task: Task): Observable<Task>
fun deleteTask(taskId: String): Observable<Void>
fun getTask(taskId: String): Flowable<Task>
fun getTaskCopy(taskId: String): Flowable<Task>
fun createTask(task: Task): Flowable<Task>
fun updateTask(task: Task): Maybe<Task>?
fun deleteTask(taskId: String): Flowable<Void>
fun saveTask(task: Task)
fun createTasks(newTasks: List<Task>): Observable<List<Task>>
fun createTasks(newTasks: List<Task>): Flowable<List<Task>>
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<List<String>>
fun updateTaskPosition(taskType: String, oldPosition: Int, newPosition: Int): Maybe<List<String>>
fun getUnmanagedTask(taskid: String): Observable<Task>
fun getUnmanagedTask(taskid: String): Flowable<Task>
fun updateTaskInBackground(task: Task)
fun createTaskInBackground(task: Task)
fun getTaskCopies(userId: String): Observable<List<Task>>
fun getTaskCopies(userId: String): Flowable<List<Task>>
fun getTaskCopies(tasks: List<Task>): Observable<List<Task>>
fun getTaskCopies(tasks: List<Task>): Flowable<List<Task>>
fun updateDailiesIsDue(date: Date): Observable<TaskList>
fun retrieveCompletedTodos(userId: String): Observable<TaskList>
fun updateDailiesIsDue(date: Date): Flowable<TaskList>
fun retrieveCompletedTodos(userId: String): Flowable<TaskList>
}

View file

@ -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<TutorialStep>
fun getTutorialSteps(keys: List<String>): Observable<RealmResults<TutorialStep>>
fun getTutorialStep(key: String): Flowable<TutorialStep>
fun getTutorialSteps(keys: List<String>): Flowable<RealmResults<TutorialStep>>
}

View file

@ -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<User>
fun getInboxOverviewList(): Observable<RealmResults<ChatMessage>>
fun getUser(): Flowable<User>
fun getInboxOverviewList(): Flowable<RealmResults<ChatMessage>>
fun getUser(userID: String): Observable<User>
fun updateUser(user: User?, updateData: Map<String, Any>): Observable<User>
fun updateUser(user: User?, key: String, value: Any): Observable<User>
fun getUser(userID: String): Flowable<User>
fun updateUser(user: User?, updateData: Map<String, Any>): Flowable<User>
fun updateUser(user: User?, key: String, value: Any): Flowable<User>
fun retrieveUser(withTasks: Boolean): Observable<User>
fun retrieveUser(withTasks: Boolean = false, forced: Boolean = false): Observable<User>
fun retrieveUser(withTasks: Boolean): Flowable<User>
fun retrieveUser(withTasks: Boolean = false, forced: Boolean = false): Flowable<User>
fun getInboxMessages(replyToUserID: String?): Observable<RealmResults<ChatMessage>>
fun retrieveInboxMessages(): Observable<List<ChatMessage>>
fun getInboxMessages(replyToUserID: String?): Flowable<RealmResults<ChatMessage>>
fun retrieveInboxMessages(): Flowable<List<ChatMessage>>
fun revive(user: User): Observable<User>
fun revive(user: User): Flowable<User>
fun resetTutorial(user: User?)
fun sleep(user: User): Observable<User>
fun sleep(user: User): Flowable<User>
fun getSkills(user: User): Observable<RealmResults<Skill>>
fun getSkills(user: User): Flowable<RealmResults<Skill>>
fun getSpecialItems(user: User): Observable<RealmResults<Skill>>
fun getSpecialItems(user: User): Flowable<RealmResults<Skill>>
fun useSkill(user: User?, key: String, target: String, taskId: String): Observable<SkillResponse>
fun useSkill(user: User?, key: String, target: String, taskId: String): Flowable<SkillResponse>
fun useSkill(user: User?, key: String, target: String): Observable<SkillResponse>
fun useSkill(user: User?, key: String, target: String): Flowable<SkillResponse>
fun changeClass(): Observable<User>
fun changeClass(): Flowable<User>
fun disableClasses(): Observable<User>
fun disableClasses(): Flowable<User>
fun changeClass(selectedClass: String): Observable<User>
fun changeClass(selectedClass: String): Flowable<User>
fun unlockPath(user: User, customization: Customization): Observable<UnlockResponse>
fun unlockPath(user: User, set: CustomizationSet): Observable<UnlockResponse>
fun unlockPath(user: User, customization: Customization): Flowable<UnlockResponse>
fun unlockPath(user: User, set: CustomizationSet): Flowable<UnlockResponse>
fun runCron(tasks: MutableList<Task>)
fun runCron()
fun readNotification(id: String): Observable<List<*>>
fun readNotification(id: String): Flowable<List<*>>
fun changeCustomDayStart(dayStartTime: Int): Observable<User>
fun changeCustomDayStart(dayStartTime: Int): Flowable<User>
fun updateLanguage(user: User?, languageCode: String): Observable<User>
fun updateLanguage(user: User?, languageCode: String): Flowable<User>
fun resetAccount(): Observable<User>
fun deleteAccount(password: String): Observable<Void>
fun resetAccount(): Flowable<User>
fun deleteAccount(password: String): Flowable<Void>
fun sendPasswordResetEmail(email: String): Observable<Void>
fun sendPasswordResetEmail(email: String): Flowable<Void>
fun updateLoginName(newLoginName: String, password: String): Observable<Void>
fun updateEmail(newEmail: String, password: String): Observable<Void>
fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Observable<Void>
fun updateLoginName(newLoginName: String, password: String): Flowable<Void>
fun updateEmail(newEmail: String, password: String): Flowable<Void>
fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable<Void>
fun allocatePoint(user: User?, @Stats.StatsTypes stat: String): Observable<Stats>
fun allocatePoint(user: User?, @Stats.StatsTypes stat: String): Flowable<Stats>
fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Observable<Stats>
fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable<Stats>
}

View file

@ -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<Throwable>, 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<HabitResponse<Any>, 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<UserAuthResponse> {
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<UserAuthResponse> {
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<UserAuthResponse> {
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<User> {
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<List<ChatMessage>> {
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 <T> configureApiCallObserver(): FlowableTransformer<HabitResponse<T>, T> {
return apiCallTransformer as FlowableTransformer<HabitResponse<T>, 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<Status>
get() = apiService.status.compose(configureApiCallObserver())
override fun getContent(language: String): Flowable<ContentResult> {
return apiService.getContent(language).compose(configureApiCallObserver())
}
override val user: Flowable<User>
get() = apiService.user.compose(configureApiCallObserver())
override fun updateUser(updateDictionary: Map<String, Any>): Flowable<User> {
return apiService.updateUser(updateDictionary).compose(configureApiCallObserver())
}
override fun registrationLanguage(registrationLanguage: String): Flowable<User> {
return apiService.registrationLanguage(registrationLanguage).compose(configureApiCallObserver())
}
override fun retrieveInAppRewards(): Flowable<List<ShopItem>> {
return apiService.retrieveInAppRewards().compose(configureApiCallObserver())
}
override fun retrieveOldGear(): Flowable<List<ShopItem>> {
return apiService.retrieveOldGearRewards().compose(configureApiCallObserver())
}
override fun equipItem(type: String, itemKey: String): Flowable<Items> {
return apiService.equipItem(type, itemKey).compose(configureApiCallObserver())
}
override fun buyItem(itemKey: String): Flowable<BuyResponse> {
return apiService.buyItem(itemKey).compose(configureApiCallObserver())
}
override fun purchaseItem(type: String, itemKey: String): Flowable<Void> {
return apiService.purchaseItem(type, itemKey).compose(configureApiCallObserver())
}
override fun validateSubscription(request: SubscriptionValidationRequest): Flowable<Void> {
return apiService.validateSubscription(request).map { habitResponse ->
if (habitResponse.notifications != null) {
popupNotificationsManager.showNotificationDialog(habitResponse.notifications)
}
habitResponse.getData()
}
}
override fun purchaseHourglassItem(type: String, itemKey: String): Flowable<Void> {
return apiService.purchaseHourglassItem(type, itemKey).compose(configureApiCallObserver())
}
override fun purchaseMysterySet(itemKey: String): Flowable<Void> {
return apiService.purchaseMysterySet(itemKey).compose(configureApiCallObserver())
}
override fun purchaseQuest(key: String): Flowable<Void> {
return apiService.purchaseQuest(key).compose(configureApiCallObserver())
}
override fun sellItem(itemType: String, itemKey: String): Flowable<User> {
return apiService.sellItem(itemType, itemKey).compose(configureApiCallObserver())
}
override fun feedPet(petKey: String, foodKey: String): Flowable<FeedResponse> {
return apiService.feedPet(petKey, foodKey).compose(configureApiCallObserver())
}
override fun hatchPet(eggKey: String, hatchingPotionKey: String): Flowable<Items> {
return apiService.hatchPet(eggKey, hatchingPotionKey).compose(configureApiCallObserver())
}
override val tasks: Flowable<TaskList>
get() = apiService.tasks.compose(configureApiCallObserver())
override fun getTasks(type: String): Flowable<TaskList> {
return apiService.getTasks(type).compose(configureApiCallObserver())
}
override fun getTasks(type: String, dueDate: String): Flowable<TaskList> {
return apiService.getTasks(type, dueDate).compose(configureApiCallObserver())
}
override fun unlockPath(path: String): Flowable<UnlockResponse> {
return apiService.unlockPath(path).compose(configureApiCallObserver())
}
override fun getTask(id: String): Flowable<Task> {
return apiService.getTask(id).compose(configureApiCallObserver())
}
override fun postTaskDirection(id: String, direction: String): Flowable<TaskDirectionData> {
return apiService.postTaskDirection(id, direction).compose(configureApiCallObserver())
}
override fun postTaskNewPosition(id: String, position: Int): Flowable<List<String>> {
return apiService.postTaskNewPosition(id, position).compose(configureApiCallObserver())
}
override fun scoreChecklistItem(taskId: String, itemId: String): Flowable<Task> {
return apiService.scoreChecklistItem(taskId, itemId).compose(configureApiCallObserver())
}
override fun createTask(item: Task): Flowable<Task> {
return apiService.createTask(item).compose(configureApiCallObserver())
}
override fun createTasks(tasks: List<Task>): Flowable<List<Task>> {
return apiService.createTasks(tasks).compose(configureApiCallObserver())
}
override fun updateTask(id: String, item: Task): Flowable<Task> {
return apiService.updateTask(id, item).compose(configureApiCallObserver())
}
override fun deleteTask(id: String): Flowable<Void> {
return apiService.deleteTask(id).compose(configureApiCallObserver())
}
override fun createTag(tag: Tag): Flowable<Tag> {
return apiService.createTag(tag).compose(configureApiCallObserver())
}
override fun updateTag(id: String, tag: Tag): Flowable<Tag> {
return apiService.updateTag(id, tag).compose(configureApiCallObserver())
}
override fun deleteTag(id: String): Flowable<Void> {
return apiService.deleteTag(id).compose(configureApiCallObserver())
}
override fun sleep(): Flowable<Boolean> {
return apiService.sleep().compose(configureApiCallObserver())
}
override fun revive(): Flowable<User> {
return apiService.revive().compose(configureApiCallObserver())
}
override fun useSkill(skillName: String, targetType: String, targetId: String): Flowable<SkillResponse> {
return apiService.useSkill(skillName, targetType, targetId).compose(configureApiCallObserver())
}
override fun useSkill(skillName: String, targetType: String): Flowable<SkillResponse> {
return apiService.useSkill(skillName, targetType).compose(configureApiCallObserver())
}
override fun changeClass(): Flowable<User> {
return apiService.changeClass().compose(configureApiCallObserver())
}
override fun changeClass(className: String): Flowable<User> {
return apiService.changeClass(className).compose(configureApiCallObserver())
}
override fun disableClasses(): Flowable<User> {
return apiService.disableClasses().compose(configureApiCallObserver())
}
override fun markPrivateMessagesRead(): Flowable<Void> {
//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<List<Group>> {
return apiService.listGroups(type).compose(configureApiCallObserver())
}
override fun getGroup(groupId: String): Flowable<Group> {
return apiService.getGroup(groupId).compose(configureApiCallObserver())
}
override fun updateGroup(id: String, item: Group): Flowable<Void> {
return apiService.updateGroup(id, item).compose(configureApiCallObserver())
}
override fun listGroupChat(groupId: String): Flowable<List<ChatMessage>> {
return apiService.listGroupChat(groupId).compose(configureApiCallObserver())
}
override fun joinGroup(groupId: String): Flowable<Group> {
return apiService.joinGroup(groupId).compose(configureApiCallObserver())
}
override fun leaveGroup(groupId: String): Flowable<Void> {
return apiService.leaveGroup(groupId).compose(configureApiCallObserver())
}
override fun postGroupChat(groupId: String, message: Map<String, String>): Flowable<PostChatMessageResult> {
return apiService.postGroupChat(groupId, message).compose(configureApiCallObserver())
}
override fun deleteMessage(groupId: String, messageId: String): Flowable<Void> {
return apiService.deleteMessage(groupId, messageId).compose(configureApiCallObserver())
}
override fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?): Flowable<List<Member>> {
return apiService.getGroupMembers(groupId, includeAllPublicFields).compose(configureApiCallObserver())
}
override fun getGroupMembers(groupId: String, includeAllPublicFields: Boolean?, lastId: String): Flowable<List<Member>> {
return apiService.getGroupMembers(groupId, includeAllPublicFields, lastId).compose(configureApiCallObserver())
}
override fun likeMessage(groupId: String, mid: String): Flowable<ChatMessage> {
return apiService.likeMessage(groupId, mid).compose(configureApiCallObserver())
}
override fun flagMessage(groupId: String, mid: String): Flowable<Void> {
return apiService.flagMessage(groupId, mid).compose(configureApiCallObserver())
}
override fun seenMessages(groupId: String): Flowable<Void> {
return apiService.seenMessages(groupId).compose(configureApiCallObserver())
}
override fun inviteToGroup(groupId: String, inviteData: Map<String, Any>): Flowable<List<String>> {
return apiService.inviteToGroup(groupId, inviteData).compose(configureApiCallObserver())
}
override fun rejectGroupInvite(groupId: String): Flowable<Void> {
return apiService.rejectGroupInvite(groupId).compose(configureApiCallObserver())
}
override fun acceptQuest(groupId: String): Flowable<Void> {
return apiService.acceptQuest(groupId).compose(configureApiCallObserver())
}
override fun rejectQuest(groupId: String): Flowable<Void> {
return apiService.rejectQuest(groupId).compose(configureApiCallObserver())
}
override fun cancelQuest(groupId: String): Flowable<Void> {
return apiService.cancelQuest(groupId).compose(configureApiCallObserver())
}
override fun forceStartQuest(groupId: String, group: Group): Flowable<Quest> {
return apiService.forceStartQuest(groupId, group).compose(configureApiCallObserver())
}
override fun inviteToQuest(groupId: String, questKey: String): Flowable<Quest> {
return apiService.inviteToQuest(groupId, questKey).compose(configureApiCallObserver())
}
override fun abortQuest(groupId: String): Flowable<Quest> {
return apiService.abortQuest(groupId).compose(configureApiCallObserver())
}
override fun leaveQuest(groupId: String): Flowable<Void> {
return apiService.leaveQuest(groupId).compose(configureApiCallObserver())
}
override fun validatePurchase(request: PurchaseValidationRequest): Flowable<PurchaseValidationResult> {
return apiService.validatePurchase(request).map { habitResponse ->
if (habitResponse.notifications != null) {
popupNotificationsManager.showNotificationDialog(habitResponse.notifications)
}
habitResponse.getData()
}
}
override fun changeCustomDayStart(updateObject: Map<String, Any>): Flowable<User> {
return apiService.changeCustomDayStart(updateObject).compose(configureApiCallObserver())
}
override fun getMember(memberId: String): Flowable<Member> {
return apiService.getMember(memberId).compose(configureApiCallObserver())
}
override fun getMemberAchievements(memberId: String): Flowable<AchievementResult> {
return apiService.getMemberAchievements(memberId).compose(configureApiCallObserver())
}
override fun postPrivateMessage(messageDetails: Map<String, String>): Flowable<PostChatMessageResult> {
return apiService.postPrivateMessage(messageDetails).compose(configureApiCallObserver())
}
override fun retrieveShopIventory(identifier: String): Flowable<Shop> {
return apiService.retrieveShopInventory(identifier).compose(configureApiCallObserver())
}
override fun addPushDevice(pushDeviceData: Map<String, String>): Flowable<List<Void>> {
return apiService.addPushDevice(pushDeviceData).compose(configureApiCallObserver())
}
override fun deletePushDevice(regId: String): Flowable<List<Void>> {
return apiService.deletePushDevice(regId).compose(configureApiCallObserver())
}
override val userChallenges: Flowable<List<Challenge>>
get() = apiService.userChallenges.compose(configureApiCallObserver())
override fun getChallengeTasks(challengeId: String): Flowable<TaskList> {
return apiService.getChallengeTasks(challengeId).compose(configureApiCallObserver())
}
override fun getChallenge(challengeId: String): Flowable<Challenge> {
return apiService.getChallenge(challengeId).compose(configureApiCallObserver())
}
override fun joinChallenge(challengeId: String): Flowable<Challenge> {
return apiService.joinChallenge(challengeId).compose(configureApiCallObserver())
}
override fun leaveChallenge(challengeId: String, body: LeaveChallengeBody): Flowable<Void> {
return apiService.leaveChallenge(challengeId, body).compose(configureApiCallObserver())
}
override fun createChallenge(challenge: Challenge): Flowable<Challenge> {
return apiService.createChallenge(challenge).compose(configureApiCallObserver())
}
override fun createChallengeTasks(challengeId: String, tasks: List<Task>): Flowable<List<Task>> {
return apiService.createChallengeTasks(challengeId, tasks).compose(configureApiCallObserver())
}
override fun updateChallenge(challenge: Challenge): Flowable<Challenge> {
return apiService.updateChallenge(challenge.id, challenge).compose(configureApiCallObserver())
}
override fun deleteChallenge(challengeId: String): Flowable<Void> {
return apiService.deleteChallenge(challengeId).compose(configureApiCallObserver())
}
override fun debugAddTenGems(): Flowable<Void> {
return apiService.debugAddTenGems().compose(configureApiCallObserver())
}
override fun readNotification(notificationId: String): Flowable<List<*>> {
return apiService.readNotification(notificationId).compose(configureApiCallObserver())
}
override val content: Flowable<ContentResult>
get() = apiService.getContent(languageCode).compose(configureApiCallObserver())
override fun openMysteryItem(): Flowable<Equipment> {
return apiService.openMysteryItem().compose(configureApiCallObserver())
}
override fun runCron(): Flowable<Void> {
return apiService.runCron().compose(configureApiCallObserver())
}
override fun resetAccount(): Flowable<Void> {
return apiService.resetAccount().compose(configureApiCallObserver())
}
override fun deleteAccount(password: String): Flowable<Void> {
val updateObject = HashMap<String, String>()
updateObject["password"] = password
return apiService.deleteAccount(updateObject).compose(configureApiCallObserver())
}
override fun togglePinnedItem(pinType: String, path: String): Flowable<Void> {
return apiService.togglePinnedItem(pinType, path).compose(configureApiCallObserver())
}
override fun sendPasswordResetEmail(email: String): Flowable<Void> {
val data = HashMap<String, String>()
data["email"] = email
return apiService.sendPasswordResetEmail(data).compose(configureApiCallObserver())
}
override fun updateLoginName(newLoginName: String, password: String): Flowable<Void> {
val updateObject = HashMap<String, String>()
updateObject["username"] = newLoginName
updateObject["password"] = password
return apiService.updateLoginName(updateObject).compose(configureApiCallObserver())
}
override fun updateEmail(newEmail: String, password: String): Flowable<Void> {
val updateObject = HashMap<String, String>()
updateObject["newEmail"] = newEmail
updateObject["password"] = password
return apiService.updateEmail(updateObject).compose(configureApiCallObserver())
}
override fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable<Void> {
val updateObject = HashMap<String, String>()
updateObject["newPassword"] = newPassword
updateObject["password"] = oldPassword
updateObject["confirmPassowrd"] = oldPasswordConfirmation
return apiService.updatePassword(updateObject).compose(configureApiCallObserver())
}
override fun allocatePoint(stat: String): Flowable<Stats> {
return apiService.allocatePoint(stat).compose(configureApiCallObserver())
}
override fun bulkAllocatePoints(strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable<Stats> {
val body = HashMap<String, Map<String, Int>>()
val stats = HashMap<String, Int>()
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<Shop> {
return apiService.retrieveMarketGear().compose(configureApiCallObserver())
}
override val worldState: Flowable<WorldState>
get() = apiService.worldState.compose(configureApiCallObserver())
companion object {
private const val TAG = "ApiClientImpl"
fun createGsonFactory(): GsonConverterFactory {
val taskTagClassListType = object : TypeToken<RealmList<Tag>>() {
}.type
val skillListType = object : TypeToken<List<Skill>>() {
}.type
val customizationListType = object : TypeToken<RealmList<Customization>>() {
}.type
val tutorialStepListType = object : TypeToken<RealmList<TutorialStep>>() {
}.type
val faqArticleListType = object : TypeToken<RealmList<FAQArticle>>() {
}.type
val itemDataListType = object : TypeToken<RealmList<Equipment>>() {
}.type
val eggListType = object : TypeToken<RealmList<Egg>>() {
}.type
val foodListType = object : TypeToken<RealmList<Food>>() {
}.type
val hatchingPotionListType = object : TypeToken<RealmList<HatchingPotion>>() {
}.type
val questContentListType = object : TypeToken<RealmList<QuestContent>>() {
}.type
val petMapType = object : TypeToken<Map<String, Pet>>() {
}.type
val mountMapType = object : TypeToken<Map<String, Mount>>() {
}.type
val petListType = object : TypeToken<RealmList<Pet>>() {
}.type
val mountListType = object : TypeToken<RealmList<Mount>>() {
}.type
val questCollectListType = object : TypeToken<RealmList<QuestCollect>>() {
}.type
val chatMessageListType = object : TypeToken<RealmList<ChatMessage>>() {
}.type
val challengeListType = object : TypeToken<List<Challenge>>() {
}.type
val challengeRealmListType = object : TypeToken<RealmList<Challenge>>() {
}.type
val questDropItemListType = object : TypeToken<RealmList<QuestDropItem>>() {
}.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)
}
}
}

View file

@ -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<T extends BaseLocalRepository> 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 <T extends RealmObject> List<T> getUnmanagedCopy(List<T> list) {
return localRepository.getUnmanagedCopy(list);
}
@Override
public boolean isClosed() {
return localRepository.isClosed();
}
@Override
public <T extends RealmObject> T getUnmanagedCopy(T object) {
return localRepository.getUnmanagedCopy(object);
}
}

View file

@ -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<T : BaseLocalRepository>(protected val localRepository: T, protected val apiClient: ApiClient) : BaseRepository {
override fun close() {
this.localRepository.close()
}
override fun <T : RealmObject> getUnmanagedCopy(list: List<T>): List<T> {
return localRepository.getUnmanagedCopy(list)
}
override val isClosed: Boolean
get() = localRepository.isClosed
override fun <T : RealmObject> getUnmanagedCopy(obj: T): T {
return localRepository.getUnmanagedCopy(obj)
}
}

View file

@ -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<ChallengeLocalRepository> implements ChallengeRepository {
public ChallengeRepositoryImpl(ChallengeLocalRepository localRepository, ApiClient apiClient) {
super(localRepository, apiClient);
}
@Override
public Observable<Challenge> getChallenge(String challengeId) {
return apiClient.getChallenge(challengeId);
}
@Override
public Observable<TaskList> getChallengeTasks(String challengeId) {
return apiClient.getChallengeTasks(challengeId);
}
private TasksOrder getTaskOrders(List<Task> taskList) {
Map<String, List<Task>> stringListMap = U.groupBy(taskList, t -> t.getType());
TasksOrder tasksOrder = new TasksOrder();
for (Map.Entry<String, List<Task>> entry : stringListMap.entrySet()) {
List<String> 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<List<Task>> addChallengeTasks(String challengeId, List<Task> addedTaskList) {
return apiClient.createChallengeTasks(challengeId, addedTaskList);
}
@Override
public Observable<Challenge> createChallenge(Challenge challenge, List<Task> 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<Challenge> updateChallenge(Challenge challenge, List<Task> fullTaskList,
List<Task> addedTaskList, List<Task> updatedTaskList, List<String> removedTaskList) {
ArrayList<Observable> 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<Void> deleteChallenge(String challengeId) {
return apiClient.deleteChallenge(challengeId);
}
@Override
public Observable<RealmResults<Challenge>> getChallenges() {
return localRepository.getChallenges();
}
@Override
public Observable<RealmResults<Challenge>> getUserChallenges(String userId) {
return localRepository.getUserChallenges(userId);
}
@Override
public Observable<List<Challenge>> retrieveChallenges(User user) {
return apiClient.getUserChallenges()
.doOnNext(localRepository::saveChallenges);
}
@Override
public Observable<Void> 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<Challenge> joinChallenge(Challenge challenge) {
if (challenge == null) {
return Observable.just(null);
}
return apiClient.joinChallenge(challenge.id)
.doOnNext(aVoid -> localRepository.setParticipating(challenge, true));
}
}

View file

@ -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<ChallengeLocalRepository>(localRepository, apiClient), ChallengeRepository {
override fun getChallenge(challengeId: String): Flowable<Challenge> {
return apiClient.getChallenge(challengeId)
}
override fun getChallengeTasks(challengeId: String): Flowable<TaskList> {
return apiClient.getChallengeTasks(challengeId)
}
private fun getTaskOrders(taskList: List<Task>): TasksOrder {
val stringListMap = U.groupBy(taskList) { t -> t.type }
val tasksOrder = TasksOrder()
for ((key, value) in stringListMap) {
val taskIdList = U.map<String, Task>(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<Task>): Flowable<Challenge> {
return apiClient.createChallengeTasks(challenge.id, addedTaskList).map { challenge }
}
override fun createChallenge(challenge: Challenge, taskList: List<Task>): Flowable<Challenge> {
challenge.tasksOrder = getTaskOrders(taskList)
return apiClient.createChallenge(challenge).flatMap {
addChallengeTasks(it, taskList)
}
}
override fun updateChallenge(challenge: Challenge, fullTaskList: List<Task>,
addedTaskList: List<Task>, updatedTaskList: List<Task>, removedTaskList: List<String>): Flowable<Challenge> {
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<Void> {
return apiClient.deleteChallenge(challengeId)
}
override fun getChallenges(): Flowable<RealmResults<Challenge>> {
return localRepository.challenges
}
override fun getUserChallenges(userId: String): Flowable<RealmResults<Challenge>> {
return localRepository.getUserChallenges(userId)
}
override fun retrieveChallenges(user: User): Flowable<List<Challenge>> {
return apiClient.userChallenges
.doOnNext { localRepository.saveChallenges(it) }
}
override fun leaveChallenge(challenge: Challenge?, leaveChallengeBody: LeaveChallengeBody): Flowable<Void> {
return if (challenge == null) {
Flowable.empty()
} else apiClient.leaveChallenge(challenge.id, leaveChallengeBody)
.doOnNext { localRepository.setParticipating(challenge, false) }
}
override fun joinChallenge(challenge: Challenge?): Flowable<Challenge> {
return if (challenge == null) {
Flowable.empty()
} else apiClient.joinChallenge(challenge.id)
.doOnNext { localRepository.setParticipating(challenge, true) }
}
}

View file

@ -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<T : ContentLocalRepository>(localRepository: T, apiClient: ApiClient) : BaseRepositoryImpl<T>(localRepository, apiClient), ContentRepository {
private var lastContentSync = 0L
private var lastWorldStateSync = 0L
override fun retrieveContent(): Observable<ContentResult> {
override fun retrieveContent(): Flowable<ContentResult> {
return retrieveContent(false)
}
override fun retrieveContent(forced: Boolean): Observable<ContentResult> {
override fun retrieveContent(forced: Boolean): Flowable<ContentResult> {
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<WorldState> {
override fun retrieveWorldState(): Flowable<WorldState> {
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()
}
}
}

View file

@ -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<CustomizationLocalRepository> implements CustomizationRepository {
public CustomizationRepositoryImpl(CustomizationLocalRepository localRepository, ApiClient apiClient) {
super(localRepository, apiClient);
}
@Override
public Observable<RealmResults<Customization>> getCustomizations(String type, String category, boolean onlyAvailable) {
return localRepository.getCustomizations(type, category, onlyAvailable);
}
}

View file

@ -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<CustomizationLocalRepository>(localRepository, apiClient), CustomizationRepository {
override fun getCustomizations(type: String, category: String, onlyAvailable: Boolean): Flowable<RealmResults<Customization>> {
return localRepository.getCustomizations(type, category, onlyAvailable)
}
}

View file

@ -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<FAQLocalRepository> implements FAQRepository {
public FAQRepositoryImpl(FAQLocalRepository localRepository, ApiClient apiClient) {
super(localRepository, apiClient);
}
@Override
public Observable<RealmResults<FAQArticle>> getArticles() {
return localRepository.getArticles();
}
}

View file

@ -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<FAQLocalRepository>(localRepository, apiClient), FAQRepository {
override fun getArticles(): Flowable<RealmResults<FAQArticle>> {
return localRepository.articles
}
}

View file

@ -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<InventoryLocalRepository>(localRepository, apiClient), InventoryRepository {
class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClient: ApiClient) : ContentRepositoryImpl<InventoryLocalRepository>(localRepository, apiClient), InventoryRepository {
override fun getQuestContent(key: String): Observable<QuestContent> {
override fun getQuestContent(key: String): Flowable<QuestContent> {
return localRepository.getQuestContent(key)
}
override fun getItems(searchedKeys: List<String>): Observable<RealmResults<Equipment>> {
override fun getItems(searchedKeys: List<String>): Flowable<RealmResults<Equipment>> {
return localRepository.getEquipment(searchedKeys)
}
@ -29,75 +27,35 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie
return localRepository.getArmoireRemainingCount()
}
override fun getInAppRewards(): Observable<RealmResults<ShopItem>> {
override fun getInAppRewards(): Flowable<RealmResults<ShopItem>> {
return localRepository.getInAppRewards()
}
override fun retrieveInAppRewards(): Observable<List<ShopItem>> {
return if (remoteConfigManager.newShopsEnabled()!!) {
apiClient.retrieveInAppRewards()
.doOnNext({ localRepository.saveInAppRewards(it) })
} else {
apiClient.retrieveOldGear()
.map<List<String>> { items ->
val itemKeys = ArrayList<String>()
for (item in items) {
itemKeys.add(item.key)
}
itemKeys.add("potion")
itemKeys.add("armoire")
itemKeys
}
.flatMap<RealmResults<Equipment>>({ this.getItems(it) })
.map<List<ShopItem>> { items ->
val buyableItems = ArrayList<ShopItem>()
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<List<ShopItem>> {
return apiClient.retrieveInAppRewards().doOnNext { localRepository.saveInAppRewards(it) }
}
override fun getOwnedEquipment(type: String): Observable<RealmResults<Equipment>> {
override fun getOwnedEquipment(type: String): Flowable<RealmResults<Equipment>> {
return localRepository.getOwnedEquipment(type)
}
override fun getOwnedEquipment(): Observable<RealmResults<Equipment>> {
override fun getOwnedEquipment(): Flowable<RealmResults<Equipment>> {
return localRepository.getOwnedEquipment()
}
override fun getOwnedItems(itemClass: Class<out Item>, user: User?): Observable<out RealmResults<out Item>> {
override fun getOwnedItems(itemClass: Class<out Item>, user: User?): Flowable<out RealmResults<out Item>> {
return localRepository.getOwnedItems(itemClass, user)
}
override fun getOwnedItems(user: User): Observable<out Map<String, Item>> {
override fun getOwnedItems(user: User): Flowable<out Map<String, Item>> {
return localRepository.getOwnedItems(user)
}
override fun getEquipment(key: String): Observable<Equipment> {
override fun getEquipment(key: String): Flowable<Equipment> {
return localRepository.getEquipment(key)
}
override fun openMysteryItem(user: User): Observable<Equipment> {
override fun openMysteryItem(user: User): Flowable<Equipment> {
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<RealmResults<Mount>> {
override fun getMounts(): Flowable<RealmResults<Mount>> {
return localRepository.getMounts()
}
override fun getMounts(type: String, group: String): Observable<RealmResults<Mount>> {
override fun getMounts(type: String, group: String): Flowable<RealmResults<Mount>> {
return localRepository.getMounts(type, group)
}
override fun getOwnedMounts(): Observable<RealmResults<Mount>> {
override fun getOwnedMounts(): Flowable<RealmResults<Mount>> {
return localRepository.getOwnedMounts()
}
override fun getOwnedMounts(animalType: String, animalGroup: String): Observable<RealmResults<Mount>> {
override fun getOwnedMounts(animalType: String, animalGroup: String): Flowable<RealmResults<Mount>> {
return localRepository.getOwnedMounts(animalType, animalGroup)
}
override fun getPets(): Observable<RealmResults<Pet>> {
override fun getPets(): Flowable<RealmResults<Pet>> {
return localRepository.getPets()
}
override fun getPets(type: String, group: String): Observable<RealmResults<Pet>> {
override fun getPets(type: String, group: String): Flowable<RealmResults<Pet>> {
return localRepository.getPets(type, group)
}
override fun getOwnedPets(): Observable<RealmResults<Pet>> {
override fun getOwnedPets(): Flowable<RealmResults<Pet>> {
return localRepository.getOwnedPets()
}
override fun getOwnedPets(type: String, group: String): Observable<RealmResults<Pet>> {
override fun getOwnedPets(type: String, group: String): Flowable<RealmResults<Pet>> {
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<User> {
override fun sellItem(user: User, type: String, key: String): Flowable<User> {
return localRepository.getItem(type, key)
.flatMap { item -> sellItem(user, item) }
}
override fun sellItem(user: User?, item: Item): Observable<User> {
override fun sellItem(user: User?, item: Item): Flowable<User> {
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<Items> {
override fun equipGear(user: User, key: String, asCostume: Boolean): Flowable<Items> {
return equip(user, if (asCostume) "costume" else "equipped", key)
}
override fun equip(user: User?, type: String, key: String): Observable<Items> {
override fun equip(user: User?, type: String, key: String): Flowable<Items> {
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<FeedResponse> {
override fun feedPet(pet: Pet, food: Food): Flowable<FeedResponse> {
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<Items> {
override fun hatchPet(egg: Egg, hatchingPotion: HatchingPotion): Flowable<Items> {
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<Quest> {
override fun inviteToQuest(quest: QuestContent): Flowable<Quest> {
return apiClient.inviteToQuest("party", quest.key)
.doOnNext { localRepository.changeOwnedCount(quest, -1) }
}
override fun buyItem(user: User, key: String, value: Double): Observable<BuyResponse> {
override fun buyItem(user: User, key: String, value: Double): Flowable<BuyResponse> {
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<Shop> {
override fun retrieveShopInventory(identifier: String): Flowable<Shop> {
return apiClient.retrieveShopIventory(identifier)
}
override fun retrieveMarketGear(): Observable<Shop> {
override fun retrieveMarketGear(): Flowable<Shop> {
return apiClient.retrieveMarketGear()
}
override fun purchaseMysterySet(categoryIdentifier: String): Observable<Void> {
override fun purchaseMysterySet(categoryIdentifier: String): Flowable<Void> {
return apiClient.purchaseMysterySet(categoryIdentifier)
}
override fun purchaseHourglassItem(purchaseType: String, key: String): Observable<Void> {
override fun purchaseHourglassItem(purchaseType: String, key: String): Flowable<Void> {
return apiClient.purchaseHourglassItem(purchaseType, key)
}
override fun purchaseQuest(key: String): Observable<Void> {
override fun purchaseQuest(key: String): Flowable<Void> {
return apiClient.purchaseQuest(key)
}
override fun purchaseItem(purchaseType: String, key: String): Observable<Void> {
override fun purchaseItem(purchaseType: String, key: String): Flowable<Void> {
return apiClient.purchaseItem(purchaseType, key)
}
override fun togglePinnedItem(item: ShopItem): Observable<List<ShopItem>> {
override fun togglePinnedItem(item: ShopItem): Flowable<List<ShopItem>> {
return if (!item.isValid) {
Observable.just(null)
Flowable.empty()
} else apiClient.togglePinnedItem(item.pinType ?: "", item.path ?: "")
.flatMap { retrieveInAppRewards() }
}

View file

@ -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<SetupCustomization> getCustomizations(String category, User user) {
return getCustomizations(category, null, user);
}
@Override
public List<SetupCustomization> 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<SetupCustomization> 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<SetupCustomization> 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<SetupCustomization> 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<SetupCustomization> 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<SetupCustomization> 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<SetupCustomization> 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<SetupCustomization> 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<SetupCustomization> 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<SetupCustomization> 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;
}
}
}

View file

@ -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<SetupCustomization>
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<SetupCustomization>
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<SetupCustomization>
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<SetupCustomization>
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<SetupCustomization>
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<SetupCustomization>
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<SetupCustomization> {
return getCustomizations(category, null, user)
}
override fun getCustomizations(category: String, subcategory: String?, user: User): List<SetupCustomization> {
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<SetupCustomization> {
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<SetupCustomization> {
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<SetupCustomization> {
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
}
}
}

View file

@ -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<SocialLocalRepository>(localRepository, apiClient), SocialRepository {
override fun retrieveGroupChat(groupId: String): Observable<List<ChatMessage>> {
override fun retrieveGroupChat(groupId: String): Single<List<ChatMessage>> {
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<RealmResults<ChatMessage>> {
override fun getGroupChat(groupId: String): Flowable<RealmResults<ChatMessage>> {
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<Void> {
override fun flagMessage(chatMessage: ChatMessage): Flowable<Void> {
return if (chatMessage.id == "") {
Observable.just(null)
Flowable.empty()
} else apiClient.flagMessage(chatMessage.groupId ?: "", chatMessage.id)
}
override fun likeMessage(chatMessage: ChatMessage): Observable<ChatMessage> {
override fun likeMessage(chatMessage: ChatMessage): Flowable<ChatMessage> {
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<Void> {
override fun deleteMessage(chatMessage: ChatMessage): Flowable<Void> {
return apiClient.deleteMessage(chatMessage.groupId ?: "", chatMessage.id)
.doOnNext { localRepository.deleteMessage(chatMessage.id) }
}
override fun postGroupChat(groupId: String, messageObject: HashMap<String, String>): Observable<PostChatMessageResult> {
override fun postGroupChat(groupId: String, messageObject: HashMap<String, String>): Flowable<PostChatMessageResult> {
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<PostChatMessageResult> {
override fun postGroupChat(groupId: String, message: String): Flowable<PostChatMessageResult> {
val messageObject = HashMap<String, String>()
messageObject["message"] = message
return postGroupChat(groupId, messageObject)
}
override fun retrieveGroup(id: String): Observable<Group> {
override fun retrieveGroup(id: String): Flowable<Group> {
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<Group, Group, Group> { 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, List<ChatMessage>, Group> { group, chat ->
group
}
)
}
override fun getGroup(id: String?): Observable<Group> {
override fun getGroup(id: String?): Flowable<Group> {
if (id == null) {
return Observable.just(null)
return Flowable.empty()
}
return localRepository.getGroup(id)
}
override fun leaveGroup(id: String?): Observable<Group> {
override fun leaveGroup(id: String?): Flowable<Group> {
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<Group> {
override fun joinGroup(id: String?): Flowable<Group> {
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<Void> {
override fun updateGroup(group: Group?, name: String?, description: String?, leader: String?, privacy: String?): Flowable<Void> {
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<List<Group>> {
override fun retrieveGroups(type: String): Flowable<List<Group>> {
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<RealmResults<Group>> = localRepository.getGroups(type)
override fun getGroups(type: String): Flowable<RealmResults<Group>> = localRepository.getGroups(type)
override fun getPublicGuilds(): Observable<RealmResults<Group>> = localRepository.getPublicGuilds()
override fun getPublicGuilds(): Flowable<RealmResults<Group>> = localRepository.getPublicGuilds()
override fun postPrivateMessage(messageObject: HashMap<String, String>): Observable<PostChatMessageResult> {
override fun postPrivateMessage(messageObject: HashMap<String, String>): Flowable<PostChatMessageResult> {
return apiClient.postPrivateMessage(messageObject)
}
override fun postPrivateMessage(recipientId: String, message: String): Observable<PostChatMessageResult> {
override fun postPrivateMessage(recipientId: String, message: String): Flowable<PostChatMessageResult> {
val messageObject = HashMap<String, String>()
messageObject["message"] = message
messageObject["toUserId"] = recipientId
return postPrivateMessage(messageObject)
}
override fun getGroupMembers(id: String): Observable<RealmResults<Member>> = localRepository.getGroupMembers(id)
override fun getGroupMembers(id: String): Flowable<RealmResults<Member>> = localRepository.getGroupMembers(id)
override fun retrieveGroupMembers(id: String, includeAllPublicFields: Boolean): Observable<List<Member>> {
override fun retrieveGroupMembers(id: String, includeAllPublicFields: Boolean): Flowable<List<Member>> {
return apiClient.getGroupMembers(id, includeAllPublicFields)
.doOnNext { members -> localRepository.saveGroupMembers(id, members) }
}
override fun inviteToGroup(id: String, inviteData: Map<String, Any>): Observable<List<String>> = apiClient.inviteToGroup(id, inviteData)
override fun inviteToGroup(id: String, inviteData: Map<String, Any>): Flowable<List<String>> = apiClient.inviteToGroup(id, inviteData)
override fun getUserChallenges(): Observable<List<Challenge>> = apiClient.getUserChallenges()
override fun getUserChallenges(): Flowable<List<Challenge>> = apiClient.userChallenges
override fun getMember(userId: String?): Observable<Member> {
override fun getMember(userId: String?): Flowable<Member> {
return if (userId == null) {
Observable.just(null)
Flowable.empty()
} else apiClient.getMember(userId)
}
override fun markPrivateMessagesRead(user: User?): Observable<Void> {
override fun markPrivateMessagesRead(user: User?): Flowable<Void> {
return apiClient.markPrivateMessagesRead()
.doOnNext {
if (user?.isManaged == true) {
@ -196,50 +194,52 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
}
}
override fun getUserGroups(): Observable<RealmResults<Group>> = localRepository.getUserGroups()
override fun getUserGroups(): Flowable<RealmResults<Group>> = localRepository.getUserGroups()
override fun acceptQuest(user: User, partyId: String): Observable<Void> {
override fun acceptQuest(user: User, partyId: String): Flowable<Void> {
return apiClient.acceptQuest(partyId)
.doOnNext { localRepository.updateRSVPNeeded(user, false) }
}
override fun rejectQuest(user: User, partyId: String): Observable<Void> {
override fun rejectQuest(user: User, partyId: String): Flowable<Void> {
return apiClient.rejectQuest(partyId)
.doOnNext { localRepository.updateRSVPNeeded(user, false) }
}
override fun leaveQuest(partyId: String?): Observable<Void> {
return apiClient.leaveQuest(partyId)
override fun leaveQuest(partyId: String?): Flowable<Void> {
return if (partyId == null) {
Flowable.empty()
} else apiClient.leaveQuest(partyId)
}
override fun cancelQuest(partyId: String?): Observable<Void> {
override fun cancelQuest(partyId: String?): Flowable<Void> {
if (partyId == null) {
return Observable.just(null)
return Flowable.empty()
}
return apiClient.cancelQuest(partyId)
.doOnNext { localRepository.removeQuest(partyId) }
}
override fun abortQuest(partyId: String?): Observable<Quest> {
override fun abortQuest(partyId: String?): Flowable<Quest> {
if (partyId == null) {
return Observable.just(null)
return Flowable.empty()
}
return apiClient.abortQuest(partyId)
.doOnNext { localRepository.removeQuest(partyId) }
}
override fun rejectGroupInvite(groupId: String): Observable<Void> {
override fun rejectGroupInvite(groupId: String): Flowable<Void> {
return apiClient.rejectQuest(groupId)
}
override fun forceStartQuest(party: Group): Observable<Quest> {
override fun forceStartQuest(party: Group): Flowable<Quest> {
return apiClient.forceStartQuest(party.id, localRepository.getUnmanagedCopy(party))
.doOnNext { localRepository.setQuestActivity(party, true) }
}
override fun getMemberAchievements(userId: String?): Observable<AchievementResult> {
override fun getMemberAchievements(userId: String?): Flowable<AchievementResult> {
return if (userId == null) {
Observable.just(null)
Flowable.empty()
} else apiClient.getMemberAchievements(userId)
}
}

View file

@ -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<TagLocalRepository> implements TagRepository {
public TagRepositoryImpl(TagLocalRepository localRepository, ApiClient apiClient) {
super(localRepository, apiClient);
}
@Override
public Observable<RealmResults<Tag>> getTags(String userId) {
return localRepository.getTags(userId);
}
@Override
public Observable<Tag> createTag(Tag tag) {
return apiClient.createTag(tag);
}
@Override
public Observable<Tag> updateTag(Tag tag) {
return apiClient.updateTag(tag.id, tag);
}
@Override
public Observable<Void> deleteTag(String id) {
return apiClient.deleteTag(id);
}
@Override
public Observable<Tag> createTags(Collection<Tag> tags) {
return Observable.defer(() -> Observable.from(tags))
.filter(tag -> tag.getName() != null && !tag.getName().isEmpty())
.flatMap(this::createTag);
}
@Override
public Observable<Tag> updateTags(Collection<Tag> tags) {
return Observable.defer(() -> Observable.from(tags))
.flatMap(this::updateTag);
}
@Override
public Observable<List<Void>> deleteTags(Collection<String> tagIds) {
return Observable.defer(() -> Observable.from(tagIds))
.flatMap(this::deleteTag)
.toList();
}
@Override
public void removeOldTags(List<Tag> onlineTags, String userID) {
localRepository.removeOldTags(onlineTags, userID);
}
}

View file

@ -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<TagLocalRepository>(localRepository, apiClient), TagRepository {
override fun getTags(userId: String): Flowable<RealmResults<Tag>> {
return localRepository.getTags(userId)
}
override fun createTag(tag: Tag): Flowable<Tag> {
return apiClient.createTag(tag)
}
override fun updateTag(tag: Tag): Flowable<Tag> {
return apiClient.updateTag(tag.id, tag)
}
override fun deleteTag(id: String): Flowable<Void> {
return apiClient.deleteTag(id)
}
override fun createTags(tags: Collection<Tag>): Single<List<Tag>> {
return Flowable.defer { Flowable.fromIterable(tags) }
.filter { tag -> tag.name != null && !tag.getName().isEmpty() }
.flatMap { this.createTag(it) }
.toList()
}
override fun updateTags(tags: Collection<Tag>): Single<List<Tag>> {
return Flowable.defer { Flowable.fromIterable(tags) }
.flatMap { this.updateTag(it) }
.toList()
}
override fun deleteTags(tagIds: Collection<String>): Single<List<Void>> {
return Flowable.defer { Flowable.fromIterable(tagIds) }
.flatMap { this.deleteTag(it) }
.toList()
}
override fun removeOldTags(onlineTags: List<Tag>, userID: String) {
localRepository.removeOldTags(onlineTags, userID)
}
}

View file

@ -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<RealmResults<Task>> =
override fun getTasks(taskType: String, userID: String): Flowable<RealmResults<Task>> =
this.localRepository.getTasks(taskType, userID)
override fun getTasks(userId: String): Observable<RealmResults<Task>> =
override fun getTasks(userId: String): Flowable<RealmResults<Task>> =
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<TaskList> {
return this.apiClient.getTasks()
override fun retrieveTasks(userId: String, tasksOrder: TasksOrder): Flowable<TaskList> {
return this.apiClient.tasks
.doOnNext { res -> this.localRepository.saveTasks(userId, tasksOrder, res) }
}
override fun retrieveCompletedTodos(userId: String): Observable<TaskList> {
override fun retrieveCompletedTodos(userId: String): Flowable<TaskList> {
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<TaskList> {
override fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): Flowable<TaskList> {
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.US)
return this.apiClient.getTasks("dailys", formatter.format(dueDate))
.doOnNext { res -> this.localRepository.saveTasks(userId, tasksOrder, res) }
}
override fun taskChecked(user: User?, task: Task, up: Boolean, force: Boolean): Observable<TaskScoringResult?> {
override fun taskChecked(user: User?, task: Task, up: Boolean, force: Boolean): Flowable<TaskScoringResult?> {
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<TaskScoringResult?> {
return localRepository.getTask(taskId).first()
.flatMap { task -> taskChecked(user, task, up, force) }
override fun taskChecked(user: User?, taskId: String, up: Boolean, force: Boolean): Maybe<TaskScoringResult?> {
return localRepository.getTask(taskId).firstElement()
.flatMap { task -> taskChecked(user, task, up, force).singleElement() }
}
override fun scoreChecklistItem(taskId: String, itemId: String): Observable<Task> {
override fun scoreChecklistItem(taskId: String, itemId: String): Flowable<Task> {
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<Task> = localRepository.getTask(taskId)
override fun getTask(taskId: String): Flowable<Task> = localRepository.getTask(taskId)
override fun getTaskCopy(taskId: String): Observable<Task> = localRepository.getTaskCopy(taskId)
override fun getTaskCopy(taskId: String): Flowable<Task> = localRepository.getTaskCopy(taskId)
override fun createTask(task: Task): Observable<Task> {
override fun createTask(task: Task): Flowable<Task> {
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<Task> {
override fun updateTask(task: Task): Maybe<Task> {
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<Void> {
override fun deleteTask(taskId: String): Flowable<Void> {
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<Task>): Observable<List<Task>> = apiClient.createTasks(newTasks)
override fun createTasks(newTasks: List<Task>): Flowable<List<Task>> = 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<List<String>> {
override fun updateTaskPosition(taskType: String, oldPosition: Int, newPosition: Int): Maybe<List<String>> {
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<List<String>>(ArrayList())
return@flatMap Maybe.just<List<String>>(ArrayList())
}
.doOnNext({ localRepository.updateTaskPositions(it) })
.doOnSuccess { localRepository.updateTaskPositions(it) }
}
override fun getUnmanagedTask(taskid: String): Observable<Task> =
getTask(taskid).map({ localRepository.getUnmanagedCopy(it) })
override fun getUnmanagedTask(taskid: String): Flowable<Task> =
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<List<Task>> =
getTasks(userId).map({ localRepository.getUnmanagedCopy(it) })
override fun getTaskCopies(userId: String): Flowable<List<Task>> =
getTasks(userId).map { localRepository.getUnmanagedCopy(it) }
override fun getTaskCopies(tasks: List<Task>): Observable<List<Task>> =
Observable.just(localRepository.getUnmanagedCopy(tasks))
override fun getTaskCopies(tasks: List<Task>): Flowable<List<Task>> =
Flowable.just(localRepository.getUnmanagedCopy(tasks))
override fun updateDailiesIsDue(date: Date): Observable<TaskList> {
override fun updateDailiesIsDue(date: Date): Flowable<TaskList> {
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) }
}
}

View file

@ -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<TutorialLocalRepository>(localRepository, apiClient), TutorialRepository {
override fun getTutorialStep(key: String): Observable<TutorialStep> =
override fun getTutorialStep(key: String): Flowable<TutorialStep> =
localRepository.getTutorialStep(key)
override fun getTutorialSteps(keys: List<String>): Observable<RealmResults<TutorialStep>> =
override fun getTutorialSteps(keys: List<String>): Flowable<RealmResults<TutorialStep>> =
localRepository.getTutorialSteps(keys)
}

View file

@ -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<User> = getUser(userId)
override fun getInboxOverviewList(): Observable<RealmResults<ChatMessage>> = localRepository.getInboxOverviewList(userId)
override fun getUser(): Flowable<User> = getUser(userId)
override fun getInboxOverviewList(): Flowable<RealmResults<ChatMessage>> = localRepository.getInboxOverviewList(userId)
override fun getUser(userID: String): Observable<User> = localRepository.getUser(userID)
override fun getUser(userID: String): Flowable<User> = localRepository.getUser(userID)
override fun updateUser(user: User?, updateData: Map<String, Any>): Observable<User> {
override fun updateUser(user: User?, updateData: Map<String, Any>): Flowable<User> {
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<User> {
override fun updateUser(user: User?, key: String, value: Any): Flowable<User> {
val updateData = HashMap<String, Any>()
updateData[key] = value
return updateUser(user, updateData)
}
override fun retrieveUser(withTasks: Boolean): Observable<User> =
override fun retrieveUser(withTasks: Boolean): Flowable<User> =
retrieveUser(withTasks, false)
override fun retrieveUser(withTasks: Boolean, forced: Boolean): Observable<User> {
override fun retrieveUser(withTasks: Boolean, forced: Boolean): Flowable<User> {
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<RealmResults<ChatMessage>> =
override fun getInboxMessages(replyToUserID: String?): Flowable<RealmResults<ChatMessage>> =
localRepository.getInboxMessages(userId, replyToUserID)
override fun retrieveInboxMessages(): Observable<List<ChatMessage>> {
override fun retrieveInboxMessages(): Flowable<List<ChatMessage>> {
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<User> =
override fun revive(user: User): Flowable<User> =
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<User> {
override fun sleep(user: User): Flowable<User> {
localRepository.executeTransaction { user.preferences.isSleep = !user.preferences.sleep }
return apiClient.sleep().map { user }
}
override fun getSkills(user: User): Observable<RealmResults<Skill>> =
override fun getSkills(user: User): Flowable<RealmResults<Skill>> =
localRepository.getSkills(user)
override fun getSpecialItems(user: User): Observable<RealmResults<Skill>> =
override fun getSpecialItems(user: User): Flowable<RealmResults<Skill>> =
localRepository.getSpecialItems(user)
override fun useSkill(user: User?, key: String, target: String, taskId: String): Observable<SkillResponse> {
override fun useSkill(user: User?, key: String, target: String, taskId: String): Flowable<SkillResponse> {
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<SkillResponse> {
override fun useSkill(user: User?, key: String, target: String): Flowable<SkillResponse> {
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<User> = apiClient.changeClass().flatMap { retrieveUser(false, true) }
override fun changeClass(): Flowable<User> = apiClient.changeClass().flatMap { retrieveUser(false, true) }
override fun disableClasses(): Observable<User> = apiClient.disableClasses().flatMap { retrieveUser(false, true) }
override fun disableClasses(): Flowable<User> = apiClient.disableClasses().flatMap { retrieveUser(false, true) }
override fun changeClass(selectedClass: String): Observable<User> = apiClient.changeClass(selectedClass)
override fun changeClass(selectedClass: String): Flowable<User> = apiClient.changeClass(selectedClass)
override fun unlockPath(user: User, customization: Customization): Observable<UnlockResponse> {
override fun unlockPath(user: User, customization: Customization): Flowable<UnlockResponse> {
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<UnlockResponse> {
override fun unlockPath(user: User, set: CustomizationSet): Flowable<UnlockResponse> {
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<List<*>> = apiClient.readNotification(id)
override fun readNotification(id: String): Flowable<List<*>> = apiClient.readNotification(id)
override fun changeCustomDayStart(dayStartTime: Int): Observable<User> {
override fun changeCustomDayStart(dayStartTime: Int): Flowable<User> {
val updateObject = HashMap<String, Any>()
updateObject["dayStart"] = dayStartTime
return apiClient.changeCustomDayStart(updateObject)
}
override fun updateLanguage(user: User?, languageCode: String): Observable<User> {
override fun updateLanguage(user: User?, languageCode: String): Flowable<User> {
return updateUser(user, "preferences.language", languageCode)
.doOnNext { apiClient.setLanguageCode(languageCode) }
}
override fun resetAccount(): Observable<User> {
override fun resetAccount(): Flowable<User> {
return apiClient.resetAccount().flatMap { retrieveUser(true, true) }
}
override fun deleteAccount(password: String): Observable<Void> =
override fun deleteAccount(password: String): Flowable<Void> =
apiClient.deleteAccount(password)
override fun sendPasswordResetEmail(email: String): Observable<Void> =
override fun sendPasswordResetEmail(email: String): Flowable<Void> =
apiClient.sendPasswordResetEmail(email)
override fun updateLoginName(newLoginName: String, password: String): Observable<Void> =
override fun updateLoginName(newLoginName: String, password: String): Flowable<Void> =
apiClient.updateLoginName(newLoginName, password)
override fun updateEmail(newEmail: String, password: String): Observable<Void> =
override fun updateEmail(newEmail: String, password: String): Flowable<Void> =
apiClient.updateEmail(newEmail, password)
override fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Observable<Void> =
override fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable<Void> =
apiClient.updatePassword(newPassword, oldPassword, oldPasswordConfirmation)
override fun allocatePoint(user: User?, stat: String): Observable<Stats> {
override fun allocatePoint(user: User?, stat: String): Flowable<Stats> {
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<Stats> =
override fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable<Stats> =
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<Task>) {
var observable: Observable<Any> = localRepository.getUser(userId).first()
var observable: Maybe<Any> = 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? {

View file

@ -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<Challenge> getChallenge(String id);
Observable<List<Task>> getTasks(Challenge challenge);
Observable<RealmResults<Challenge>> getChallenges();
Observable<RealmResults<Challenge>> getUserChallenges(String userId);
void setParticipating(Challenge challenge, boolean isParticipating);
void saveChallenges(List<Challenge> challenges);
}

View file

@ -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<RealmResults<Challenge>>
fun getChallenge(id: String): Flowable<Challenge>
fun getTasks(challenge: Challenge): Flowable<List<Task>>
fun getUserChallenges(userId: String): Flowable<RealmResults<Challenge>>
fun setParticipating(challenge: Challenge, isParticipating: Boolean)
fun saveChallenges(challenges: List<Challenge>)
}

View file

@ -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<RealmResults<Customization>> getCustomizations(String type, String category, boolean onlyAvailable);
}

View file

@ -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<RealmResults<Customization>>
}

View file

@ -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<RealmResults<FAQArticle>> getArticles();
}

View file

@ -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<RealmResults<FAQArticle>>
}

View file

@ -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<RealmResults<Equipment>>
fun getOwnedEquipment(): Flowable<RealmResults<Equipment>>
fun getMounts(): Observable<RealmResults<Mount>>
fun getMounts(): Flowable<RealmResults<Mount>>
fun getOwnedMounts(): Observable<RealmResults<Mount>>
fun getOwnedMounts(): Flowable<RealmResults<Mount>>
fun getPets(): Observable<RealmResults<Pet>>
fun getPets(): Flowable<RealmResults<Pet>>
fun getOwnedPets(): Observable<RealmResults<Pet>>
fun getOwnedPets(): Flowable<RealmResults<Pet>>
fun getInAppRewards(): Observable<RealmResults<ShopItem>>
fun getQuestContent(key: String): Observable<QuestContent>
fun getInAppRewards(): Flowable<RealmResults<ShopItem>>
fun getQuestContent(key: String): Flowable<QuestContent>
fun getEquipment(searchedKeys: List<String>): Observable<RealmResults<Equipment>>
fun getEquipment(searchedKeys: List<String>): Flowable<RealmResults<Equipment>>
fun getOwnedEquipment(type: String): Observable<RealmResults<Equipment>>
fun getOwnedEquipment(type: String): Flowable<RealmResults<Equipment>>
fun getOwnedItems(itemClass: Class<out Item>, user: User?): Observable<out RealmResults<out Item>>
fun getOwnedItems(user: User): Observable<out Map<String, Item>>
fun getOwnedItems(itemClass: Class<out Item>, user: User?): Flowable<out RealmResults<out Item>>
fun getOwnedItems(user: User): Flowable<out Map<String, Item>>
fun getEquipment(key: String): Observable<Equipment>
fun getMounts(type: String, group: String): Observable<RealmResults<Mount>>
fun getOwnedMounts(animalType: String, animalGroup: String): Observable<RealmResults<Mount>>
fun getPets(type: String, group: String): Observable<RealmResults<Pet>>
fun getOwnedPets(type: String, group: String): Observable<RealmResults<Pet>>
fun getEquipment(key: String): Flowable<Equipment>
fun getMounts(type: String, group: String): Flowable<RealmResults<Mount>>
fun getOwnedMounts(animalType: String, animalGroup: String): Flowable<RealmResults<Mount>>
fun getPets(type: String, group: String): Flowable<RealmResults<Pet>>
fun getOwnedPets(type: String, group: String): Flowable<RealmResults<Pet>>
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<Item>
fun getItem(type: String, key: String): Flowable<Item>
fun decrementMysteryItemCount(user: User)
fun saveInAppRewards(onlineItems: List<ShopItem>)

View file

@ -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<RealmResults<Group>>
fun getPublicGuilds(): Flowable<RealmResults<Group>>
fun getUserGroups(): Observable<RealmResults<Group>>
fun getGroups(type: String): Observable<RealmResults<Group>>
fun getUserGroups(): Flowable<RealmResults<Group>>
fun getGroups(type: String): Flowable<RealmResults<Group>>
fun getGroup(id: String): Observable<Group>
fun getGroup(id: String): Flowable<Group>
fun getGroupChat(groupId: String): Observable<RealmResults<ChatMessage>>
fun getGroupChat(groupId: String): Flowable<RealmResults<ChatMessage>>
fun deleteMessage(id: String)
fun getGroupMembers(partyId: String): Observable<RealmResults<Member>>
fun getGroupMembers(partyId: String): Flowable<RealmResults<Member>>
fun updateRSVPNeeded(user: User?, newValue: Boolean)

View file

@ -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<RealmResults<Tag>> getTags(String userId);
void removeOldTags(List<Tag> onlineTags, String userID);
}

View file

@ -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<RealmResults<Tag>>
fun removeOldTags(onlineTags: List<Tag>, userID: String)
}

View file

@ -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<RealmResults<Task>>
fun getTasks(userId: String): Observable<RealmResults<Task>>
fun getTasks(taskType: String, userID: String): Flowable<RealmResults<Task>>
fun getTasks(userId: String): Flowable<RealmResults<Task>>
fun saveTasks(userId: String, tasksOrder: TasksOrder, tasks: TaskList)
@ -18,8 +19,8 @@ interface TaskLocalRepository : BaseLocalRepository {
fun deleteTask(taskID: String)
fun getTask(taskId: String): Observable<Task>
fun getTaskCopy(taskId: String): Observable<Task>
fun getTask(taskId: String): Flowable<Task>
fun getTaskCopy(taskId: String): Flowable<Task>
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<Task>
fun getTaskAtPosition(taskType: String, position: Int): Flowable<Task>
fun updateIsdue(daily: TaskList): Observable<TaskList>
fun updateIsdue(daily: TaskList): Maybe<TaskList>
fun updateTaskPositions(taskOrder: List<String>)
fun saveCompletedTodos(userId: String, tasks: MutableCollection<Task>)

View file

@ -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<TutorialStep>
fun getTutorialSteps(keys: List<String>): Observable<RealmResults<TutorialStep>>
fun getTutorialStep(key: String): Flowable<TutorialStep>
fun getTutorialSteps(keys: List<String>): Flowable<RealmResults<TutorialStep>>
}

View file

@ -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<RealmResults<TutorialStep>>
fun getTutorialSteps(): Flowable<RealmResults<TutorialStep>>
fun getUser(userID: String): Observable<User>
fun getUser(userID: String): Flowable<User>
fun saveUser(user: User)
fun saveMessages(messages: List<ChatMessage>)
fun getSkills(user: User): Observable<RealmResults<Skill>>
fun getSkills(user: User): Flowable<RealmResults<Skill>>
fun getSpecialItems(user: User): Observable<RealmResults<Skill>>
fun getSpecialItems(user: User): Flowable<RealmResults<Skill>>
fun getInboxMessages(userId: String, replyToUserID: String?): Observable<RealmResults<ChatMessage>>
fun getInboxMessages(userId: String, replyToUserID: String?): Flowable<RealmResults<ChatMessage>>
fun getInboxOverviewList(userId: String): Observable<RealmResults<ChatMessage>>
fun getInboxOverviewList(userId: String): Flowable<RealmResults<ChatMessage>>
}

View file

@ -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<Challenge> getChallenge(String id) {
return getRealm().where(Challenge.class)
.equalTo("id", id)
.findFirstAsync()
.asObservable()
.filter(realmObject -> realmObject.isLoaded())
.cast(Challenge.class);
}
@Override
public Observable<List<Task>> getTasks(Challenge challenge) {
return null;
}
@Override
public Observable<RealmResults<Challenge>> getChallenges() {
return getRealm().where(Challenge.class)
.isNotNull("name")
.findAllSortedAsync("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING)
.asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public Observable<RealmResults<Challenge>> 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<Challenge> onlineChallenges) {
OrderedRealmCollectionSnapshot<Challenge> localChallenges = getRealm().where(Challenge.class).findAll().createSnapshot();
List<Challenge> 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));
}
}

View file

@ -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<Challenge> {
return realm.where(Challenge::class.java)
.equalTo("id", id)
.findAll()
.asFlowable()
.filter { realmObject -> realmObject.isLoaded }
.map { it.first() }
}
override fun getTasks(challenge: Challenge): Flowable<List<Task>> {
return Flowable.empty()
}
override val challenges: Flowable<RealmResults<Challenge>>
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<RealmResults<Challenge>> {
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<Challenge>) {
val localChallenges = realm.where(Challenge::class.java).findAll().createSnapshot()
val challengesToDelete = ArrayList<Challenge>()
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) }
}
}

View file

@ -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 ->

View file

@ -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<RealmResults<Customization>> getCustomizations(String type, String category, boolean onlyAvailable) {
RealmQuery<Customization> 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);
}
}

View file

@ -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<RealmResults<Customization>> {
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 }
}
}

View file

@ -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<RealmResults<FAQArticle>> getArticles() {
return getRealm().where(FAQArticle.class)
.findAll()
.asObservable()
.filter(RealmResults::isLoaded);
}
}

View file

@ -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<RealmResults<FAQArticle>>
get() = realm.where(FAQArticle::class.java)
.findAll()
.asFlowable()
.filter{ it.isLoaded }
}

View file

@ -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<QuestContent> getQuestContent(String key) {
return getRealm().where(QuestContent.class).equalTo("key", key).findFirstAsync()
.asObservable()
.filter(realmObject -> realmObject.isLoaded())
.cast(QuestContent.class);
}
@Override
public Observable<RealmResults<Equipment>> getEquipment(List<String> 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<RealmResults<Equipment>> getOwnedEquipment(String type) {
return getRealm().where(Equipment.class)
.equalTo("type", type)
.equalTo("owned", true)
.findAll()
.asObservable()
.filter(RealmResults::isLoaded);
}
@NonNull
@Override
public Observable<RealmResults<Equipment>> getOwnedEquipment() {
return getRealm().where(Equipment.class)
.equalTo("owned", true)
.findAll()
.asObservable()
.filter(RealmResults::isLoaded);
}
@NotNull
@Override
public Observable<? extends RealmResults<? extends Item>> getOwnedItems(@NotNull Class<? extends Item> itemClass, @Nullable User user) {
if (itemClass == null) {
return Observable.empty();
}
RealmQuery<? extends Item> 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<? extends Map<String, Item>> getOwnedItems(User user) {
return Observable.combineLatest(
getOwnedItems(Egg.class, user),
getOwnedItems(HatchingPotion.class, user),
getOwnedItems(Food.class, user),
getOwnedItems(QuestContent.class, user),
(Func4<RealmResults<? extends Item>, RealmResults<? extends Item>, RealmResults<? extends Item>, RealmResults<? extends Item>, Map<String, Item>>) (eggs, hatchingPotions, food, quests) -> {
Map<String, Item> 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<Equipment> getEquipment(String key) {
return getRealm().where(Equipment.class)
.equalTo("key", key)
.findFirstAsync()
.asObservable()
.filter(realmObject -> realmObject.isLoaded())
.cast(Equipment.class);
}
@Override
public Observable<RealmResults<Mount>> getMounts() {
return getRealm().where(Mount.class)
.findAllSorted("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING)
.asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public Observable<RealmResults<Mount>> getMounts(String type, String group) {
return getRealm().where(Mount.class)
.equalTo("animalGroup", group)
.equalTo("animal", type)
.findAll()
.asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public Observable<RealmResults<Mount>> getOwnedMounts() {
return getRealm().where(Mount.class)
.equalTo("owned", true)
.findAllSorted("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING)
.asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public Observable<RealmResults<Mount>> 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<RealmResults<Pet>> getPets() {
return getRealm().where(Pet.class)
.findAllSorted("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING)
.asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public Observable<RealmResults<Pet>> getPets(String type, String group) {
return getRealm().where(Pet.class)
.equalTo("animalGroup", group)
.equalTo("animal", type)
.findAll()
.asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public Observable<RealmResults<Pet>> getOwnedPets() {
return getRealm().where(Pet.class)
.greaterThan("trained", 0)
.findAllSorted("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING)
.asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public Observable<RealmResults<Pet>> 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<Item> getItem(String type, String key) {
Class<? extends RealmObject> 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<RealmResults<ShopItem>> getInAppRewards() {
return getRealm().where(ShopItem.class)
.findAllAsync()
.asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public void saveInAppRewards(@NotNull List<? extends ShopItem> onlineItems) {
OrderedRealmCollectionSnapshot<ShopItem> 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); });
}
}
}

View file

@ -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<QuestContent> {
return realm.where(QuestContent::class.java).equalTo("key", key).findFirstAsync()
.asFlowable<RealmObject>()
.filter { realmObject -> realmObject.isLoaded }
.cast(QuestContent::class.java)
}
override fun getEquipment(searchedKeys: List<String>): Flowable<RealmResults<Equipment>> {
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<RealmResults<Equipment>> {
return realm.where(Equipment::class.java)
.equalTo("type", type)
.equalTo("owned", true)
.findAll()
.asFlowable()
.filter { it.isLoaded }
}
override fun getOwnedEquipment(): Flowable<RealmResults<Equipment>> {
return realm.where(Equipment::class.java)
.equalTo("owned", true)
.findAll()
.asFlowable()
.filter { it.isLoaded }
}
override fun getOwnedItems(itemClass: Class<out Item>, user: User?): Flowable<out RealmResults<out Item>> {
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<out Map<String, Item>> {
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<String, Item>()
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<Equipment> {
return realm.where(Equipment::class.java)
.equalTo("key", key)
.findFirstAsync()
.asFlowable<RealmObject>()
.filter { realmObject -> realmObject.isLoaded }
.cast(Equipment::class.java)
}
override fun getMounts(): Flowable<RealmResults<Mount>> {
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<RealmResults<Mount>> {
return realm.where(Mount::class.java)
.equalTo("animalGroup", group)
.equalTo("animal", type)
.findAll()
.asFlowable()
.filter { it.isLoaded }
}
override fun getOwnedMounts(): Flowable<RealmResults<Mount>> {
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<RealmResults<Mount>> {
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<RealmResults<Pet>> {
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<RealmResults<Pet>> {
return realm.where(Pet::class.java)
.equalTo("animalGroup", group)
.equalTo("animal", type)
.findAll()
.asFlowable()
.filter { it.isLoaded }
}
override fun getOwnedPets(): Flowable<RealmResults<Pet>> {
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<RealmResults<Pet>> {
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<Item> {
val itemClass: Class<out RealmObject> = 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<RealmObject>()
.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<RealmResults<ShopItem>> {
return realm.where(ShopItem::class.java)
.findAllAsync()
.asFlowable()
.filter { it.isLoaded }
}
override fun saveInAppRewards(onlineItems: List<ShopItem>) {
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 }
}
}
}

View file

@ -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<RealmResults<Group>> = realm.where(Group::class.java)
override fun getPublicGuilds(): Flowable<RealmResults<Group>> = 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<RealmResults<Group>> = realm.where(Group::class.java)
override fun getUserGroups(): Flowable<RealmResults<Group>> = 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<RealmResults<Group>> {
override fun getGroups(type: String): Flowable<RealmResults<Group>> {
return realm.where(Group::class.java)
.equalTo("type", type)
.findAllAsync()
.asObservable()
.filter({ it.isLoaded })
.asFlowable()
.filter { it.isLoaded }
}
override fun getGroup(id: String): Observable<Group> {
override fun getGroup(id: String): Flowable<Group> {
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<RealmResults<ChatMessage>> {
override fun getGroupChat(groupId: String): Flowable<RealmResults<ChatMessage>> {
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<RealmResults<Member>> {
override fun getGroupMembers(partyId: String): Flowable<RealmResults<Member>> {
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<ChatMessage> {
private fun getMessage(id: String): Flowable<ChatMessage> {
return realm.where(ChatMessage::class.java).equalTo("id", id)
.findAllAsync()
.asObservable()
.asFlowable()
.filter { messages -> messages.isLoaded && messages.isValid && !messages.isEmpty() }
.map { messages -> messages.first() }
}

View file

@ -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<RealmResults<Tag>> getTags(String userId) {
return getRealm().where(Tag.class).equalTo("userId", userId).findAll().asObservable();
}
@Override
public void removeOldTags(List<Tag> onlineTags, String userID) {
OrderedRealmCollectionSnapshot<Tag> localTags = getRealm().where(Tag.class).equalTo("userId", userID).findAll().createSnapshot();
for (Tag localTag : localTags) {
if (!onlineTags.contains(localTag)) {
localTag.deleteFromRealm();
}
}
}
}

View file

@ -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<RealmResults<Tag>> {
return realm.where(Tag::class.java).equalTo("userId", userId).findAll().asFlowable()
}
override fun removeOldTags(onlineTags: List<Tag>, userID: String) {
val localTags = realm.where(Tag::class.java).equalTo("userId", userID).findAll().createSnapshot()
for (localTag in localTags) {
if (!onlineTags.contains(localTag)) {
localTag.deleteFromRealm()
}
}
}
}

View file

@ -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<RealmResults<Task>> {
override fun getTasks(taskType: String, userID: String): Flowable<RealmResults<Task>> {
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<RealmResults<Task>> {
override fun getTasks(userId: String): Flowable<RealmResults<Task>> {
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<Task> {
return realm.where(Task::class.java).equalTo("id", taskId).findFirstAsync().asObservable<RealmObject>()
override fun getTask(taskId: String): Flowable<Task> {
return realm.where(Task::class.java).equalTo("id", taskId).findFirstAsync().asFlowable<RealmObject>()
.filter { realmObject -> realmObject.isLoaded }
.cast(Task::class.java)
}
override fun getTaskCopy(taskId: String): Observable<Task> {
override fun getTaskCopy(taskId: String): Flowable<Task> {
return getTask(taskId)
.map { task ->
if (task.isManaged && task.isValid) {
return@map realm.copyFromRealm<Task>(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<Task> {
return realm.where(Task::class.java).equalTo("type", taskType).equalTo("position", position).findFirstAsync().asObservable<RealmObject>()
override fun getTaskAtPosition(taskType: String, position: Int): Flowable<Task> {
return realm.where(Task::class.java).equalTo("type", taskType).equalTo("position", position).findFirstAsync().asFlowable<RealmObject>()
.filter { realmObject -> realmObject.isLoaded }
.cast(Task::class.java)
}
override fun updateIsdue(daily: TaskList): Observable<TaskList> {
return Observable.just(realm.where(Task::class.java).equalTo("type", "daily").findAll())
.first()
override fun updateIsdue(daily: TaskList): Maybe<TaskList> {
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 }

View file

@ -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<TutorialStep> {
override fun getTutorialStep(key: String): Flowable<TutorialStep> {
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<String>): Observable<RealmResults<TutorialStep>> {
override fun getTutorialSteps(keys: List<String>): Flowable<RealmResults<TutorialStep>> {
return realm.where(TutorialStep::class.java)
.`in`("identifier", keys.toTypedArray())
.findAll()
.asObservable()
.filter({ it.isLoaded })
.asFlowable()
.filter { it.isLoaded }
}
}

View file

@ -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<RealmResults<TutorialStep>> = realm.where(TutorialStep::class.java).findAll().asObservable()
.filter({ it.isLoaded })
override fun getTutorialSteps(): Flowable<RealmResults<TutorialStep>> = realm.where(TutorialStep::class.java).findAll().asFlowable()
.filter { it.isLoaded }
override fun getUser(userID: String): Observable<User> {
override fun getUser(userID: String): Flowable<User> {
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<RealmResults<Skill>> {
override fun getSkills(user: User): Flowable<RealmResults<Skill>> {
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<RealmResults<Skill>> {
override fun getSpecialItems(user: User): Flowable<RealmResults<Skill>> {
val specialItems = user.items.special
val ownedItems = ArrayList<String>()
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<RealmResults<ChatMessage>> {
override fun getInboxMessages(userId: String, replyToUserID: String?): Flowable<RealmResults<ChatMessage>> {
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<RealmResults<ChatMessage>> {
override fun getInboxOverviewList(userId: String): Flowable<RealmResults<ChatMessage>> {
return realm.where(ChatMessage::class.java)
.equalTo("isInboxMessage", true)
.distinct("uuid")
.sort("timestamp", Sort.DESCENDING)
.asObservable()
.filter({ it.isLoaded })
.findAll()
.asFlowable()
.filter { it.isLoaded }
}
}

View file

@ -1,6 +1,7 @@
package com.habitrpg.android.habitica.executors;
import rx.Scheduler;
import io.reactivex.Scheduler;
public interface PostExecutionThread {
Scheduler getScheduler();

View file

@ -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 {

View file

@ -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 <T : View> bindView(container: View, @IdRes res: Int) : Lazy<T> {
@ -11,4 +14,9 @@ fun <T : View> bindView(container: View, @IdRes res: Int) : Lazy<T> {
fun <T : View> bindOptionalView(container: View?, @IdRes res: Int) : Lazy<T?> {
@Suppress("UNCHECKED_CAST")
return lazy(LazyThreadSafetyMode.NONE) { container?.findViewById<T>(res) }
}
fun bindColor(context: Context, @ColorRes res: Int) : Lazy<Int> {
@Suppress("UNCHECKED_CAST")
return lazy(LazyThreadSafetyMode.NONE) { ContextCompat.getColor(context, res) }
}

View file

@ -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();

View file

@ -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<Throwable> handleEmptyError() {
public static Consumer<Throwable> handleEmptyError() {
//Can't be turned into a lambda, because it then doesn't work for some reason.
return new Action1<Throwable>() {
return new Consumer<Throwable>() {
@Override
public void call(Throwable throwable) {
public void accept(Throwable throwable) {
RxErrorHandler.reportError(throwable);
}
};

View file

@ -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<SoundFile>): Observable<List<SoundFile>> {
return Observable.from(files)
fun download(files: List<SoundFile>): Single<List<SoundFile>> {
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 =

View file

@ -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<List<SoundFile>> {
fun preloadAllFiles(): Maybe<List<SoundFile>> {
if (soundTheme == SoundThemeOff) {
return Observable.empty()
return Maybe.empty()
}
val soundFiles = ArrayList<SoundFile>()
@ -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<SoundFile>()
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())
}

View file

@ -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<Task>({ Observable.from(it) })
.subscribe(Action1 { this.setAlarmsForTask(it) }, RxErrorHandler.handleEmptyError())
.firstElement()
.toFlowable()
.flatMap<Task> { Flowable.fromIterable(it) }
.subscribe(Consumer { this.setAlarmsForTask(it) }, RxErrorHandler.handleEmptyError())
scheduleDailyReminder(context)
val editor = PreferenceManager.getDefaultSharedPreferences(context).edit()

View file

@ -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<BuyRewardUseCase.RequestValues, TaskScoringResult> {
@ -26,7 +26,7 @@ public class BuyRewardUseCase extends UseCase<BuyRewardUseCase.RequestValues, Ta
}
@Override
protected Observable<TaskScoringResult> buildUseCaseObservable(BuyRewardUseCase.RequestValues requestValues) {
protected Flowable<TaskScoringResult> buildUseCaseObservable(BuyRewardUseCase.RequestValues requestValues) {
return taskRepository
.taskChecked(requestValues.user, requestValues.task, false, false)
.doOnNext(res -> soundManager.loadAndPlayAudio(SoundManager.SoundReward));

View file

@ -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<CheckClassSelectionUseCa
}
@Override
protected Observable<Void> buildUseCaseObservable(RequestValues requestValues) {
return Observable.defer(() -> {
protected Flowable<Void> buildUseCaseObservable(RequestValues requestValues) {
return Flowable.defer(() -> {
User user = requestValues.user;
if(requestValues.selectClassEvent == null) {
@ -41,7 +40,7 @@ public class CheckClassSelectionUseCase extends UseCase<CheckClassSelectionUseCa
displayClassSelectionActivity(user, requestValues.selectClassEvent, requestValues.activity);
}
return Observable.just(null);
return Flowable.empty();
});
}

View file

@ -7,7 +7,7 @@ import com.habitrpg.android.habitica.models.tasks.Task;
import javax.inject.Inject;
import rx.Observable;
import io.reactivex.Flowable;
public class ChecklistCheckUseCase extends UseCase<ChecklistCheckUseCase.RequestValues, Task> {
@ -20,7 +20,7 @@ public class ChecklistCheckUseCase extends UseCase<ChecklistCheckUseCase.Request
}
@Override
protected Observable<Task> buildUseCaseObservable(ChecklistCheckUseCase.RequestValues requestValues) {
protected Flowable<Task> buildUseCaseObservable(ChecklistCheckUseCase.RequestValues requestValues) {
return taskRepository.scoreChecklistItem(requestValues.taskId, requestValues.itemId);
}

View file

@ -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<DailyCheckUseCase.RequestValues, TaskScoringResult> {
@ -26,7 +26,7 @@ public class DailyCheckUseCase extends UseCase<DailyCheckUseCase.RequestValues,
}
@Override
protected Observable<TaskScoringResult> buildUseCaseObservable(RequestValues requestValues) {
protected Flowable<TaskScoringResult> buildUseCaseObservable(RequestValues requestValues) {
return taskRepository.taskChecked(requestValues.user, requestValues.task, requestValues.up, false).doOnNext(res -> soundManager.loadAndPlayAudio(SoundManager.SoundDaily));
}

View file

@ -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<DisplayItemDropUseCase.RequestValues, Void> {
@ -25,8 +25,8 @@ public class DisplayItemDropUseCase extends UseCase<DisplayItemDropUseCase.Reque
}
@Override
protected Observable<Void> buildUseCaseObservable(RequestValues requestValues) {
return Observable.defer(() -> {
protected Flowable<Void> buildUseCaseObservable(RequestValues requestValues) {
return Flowable.defer(() -> {
TaskScoringResult data = requestValues.data;
if (data != null) {
@ -39,7 +39,7 @@ public class DisplayItemDropUseCase extends UseCase<DisplayItemDropUseCase.Reque
}
}
return Observable.just(null);
return Flowable.empty();
});
}

View file

@ -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 HabitScoreUseCase extends UseCase<HabitScoreUseCase.RequestValues, TaskScoringResult> {
@ -26,7 +26,7 @@ public class HabitScoreUseCase extends UseCase<HabitScoreUseCase.RequestValues,
}
@Override
protected Observable<TaskScoringResult> buildUseCaseObservable(RequestValues requestValues) {
protected Flowable<TaskScoringResult> buildUseCaseObservable(RequestValues requestValues) {
return taskRepository
.taskChecked(requestValues.user, requestValues.habit, requestValues.up, false)
.doOnNext(res -> soundManager.loadAndPlayAudio(requestValues.up ? SoundManager.SoundPlusHabit : SoundManager.SoundMinusHabit));

View file

@ -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<LevelUpUseCase.RequestValues, Stats> {
@ -37,8 +37,8 @@ public class LevelUpUseCase extends UseCase<LevelUpUseCase.RequestValues, Stats>
}
@Override
protected Observable<Stats> buildUseCaseObservable(RequestValues requestValues) {
return Observable.defer(() -> {
protected Flowable<Stats> 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<LevelUpUseCase.RequestValues, Stats>
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<LevelUpUseCase.RequestValues, Stats>
alert.show();
}
return Observable.just(requestValues.user.getStats());
return Flowable.just(requestValues.user.getStats());
});
}

View file

@ -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<NotifyUserUseCase.RequestValues, Stats>(threadExecutor, postExecutionThread) {
override fun buildUseCaseObservable(requestValues: RequestValues): Observable<Stats> {
return Observable.defer {
override fun buildUseCaseObservable(requestValues: RequestValues): Flowable<Stats> {
return Flowable.defer {
if (requestValues.user == null) {
return@defer Observable . just < Stats >(null)
return@defer Flowable.empty<Stats>()
}
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>(stats)
return@defer Flowable.just(stats)
}
}
}

View file

@ -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<TodoCheckUseCase.RequestValues, TaskScoringResult> {
@ -26,7 +26,7 @@ public class TodoCheckUseCase extends UseCase<TodoCheckUseCase.RequestValues, T
}
@Override
protected Observable<TaskScoringResult> buildUseCaseObservable(TodoCheckUseCase.RequestValues requestValues) {
protected Flowable<TaskScoringResult> buildUseCaseObservable(TodoCheckUseCase.RequestValues requestValues) {
return taskRepository.taskChecked(requestValues.user, requestValues.task, requestValues.up, false).doOnNext(res -> soundManager.loadAndPlayAudio(SoundManager.SoundTodo));
}

View file

@ -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<Q extends UseCase.RequestValues, T> {
@ -17,12 +17,12 @@ public abstract class UseCase<Q extends UseCase.RequestValues, T> {
}
/**
* 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<T> buildUseCaseObservable(Q requestValues);
protected abstract Flowable<T> buildUseCaseObservable(Q requestValues);
@SuppressWarnings("unchecked")
public Observable<T> observable(Q requestValues) {
public Flowable<T> observable(Q requestValues) {
return this.buildUseCaseObservable(requestValues)
.subscribeOn(postExecutionThread.getScheduler())
.observeOn(postExecutionThread.getScheduler());

View file

@ -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);

View file

@ -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);
}

View file

@ -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) {

View file

@ -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() {

View file

@ -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<Task> 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<Task> resultList = new ArrayList<>();

View file

@ -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<User> {
public class ClassSelectionActivity extends BaseActivity implements Consumer<User> {
String currentClass;
Boolean isInitialSelection;
@ -216,7 +216,7 @@ public class ClassSelectionActivity extends BaseActivity implements Action1<User
}
@Override
public void call(User user) {
public void accept(User user) {
if (shouldFinish) {
if (progressDialog != null) {
progressDialog.dismiss();

View file

@ -58,7 +58,7 @@ import javax.inject.Named;
import butterknife.BindView;
import butterknife.OnClick;
import rx.Observable;
import io.reactivex.Flowable;
public class CreateChallengeActivity extends BaseActivity {
public static final String CHALLENGE_ID_KEY = "challengeId";
@ -159,7 +159,7 @@ public class CreateChallengeActivity extends BaseActivity {
savingInProgress = true;
ProgressDialog dialog = ProgressDialog.show(this, "", "Saving challenge data. Please wait...", true, false);
Observable<Challenge> observable;
Flowable<Challenge> observable;
if (editMode) {
observable = updateChallenge();
@ -503,7 +503,7 @@ public class CreateChallengeActivity extends BaseActivity {
return c;
}
private Observable<Challenge> createChallenge() {
private Flowable<Challenge> createChallenge() {
Challenge c = getChallengeData();
List<Task> taskList = challengeTasks.getTaskList();
@ -515,7 +515,7 @@ public class CreateChallengeActivity extends BaseActivity {
return challengeRepository.createChallenge(c, taskList);
}
private Observable<Challenge> updateChallenge() {
private Flowable<Challenge> updateChallenge() {
Challenge c = getChallengeData();
List<Task> taskList = challengeTasks.getTaskList();

View file

@ -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()
})

View file

@ -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<RealmResults<Equipment>> loadItemDataByOutfit(Outfit outfit) {
private Flowable<RealmResults<Equipment>> loadItemDataByOutfit(Outfit outfit) {
ArrayList<String> outfitList = new ArrayList<>();
outfitList.add(outfit.getArmor());
outfitList.add(outfit.getBack());

View file

@ -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) {

View file

@ -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<UserAuthResponse> {
implements Consumer<UserAuthResponse> {
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);
}

View file

@ -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());

View file

@ -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;

View file

@ -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());
}
}

Some files were not shown because too many files have changed in this diff Show more