begin converting repositories to kotlin

This commit is contained in:
Phillip Thelen 2017-10-31 19:51:23 +01:00
parent b938dd0ff0
commit fdbda662f9
29 changed files with 1046 additions and 1309 deletions

View file

@ -354,5 +354,5 @@ public interface ApiService {
Observable<HabitResponse<Stats>> allocatePoint(@Query("stat") String stat);
@POST("user/allocate-bulk")
Observable<HabitResponse<Stats>> bulkAllocatePoints(@Body Map<String, Integer> stats);
Observable<HabitResponse<Stats>> bulkAllocatePoints(@Body Map<String, Map<String, Integer>> stats);
}

View file

@ -1,63 +0,0 @@
package com.habitrpg.android.habitica.data;
import com.google.android.gms.tasks.Tasks;
import com.habitrpg.android.habitica.models.responses.TaskDirectionData;
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.TaskTag;
import com.habitrpg.android.habitica.models.tasks.TasksOrder;
import com.habitrpg.android.habitica.models.user.User;
import java.util.Date;
import java.util.List;
import io.realm.Realm;
import io.realm.RealmResults;
import rx.Observable;
public interface TaskRepository extends BaseRepository {
Observable<RealmResults<Task>> getTasks(String taskType, String userID);
Observable<RealmResults<Task>> getTasks(String userId);
void saveTasks(String userId, TasksOrder order, TaskList tasks);
Observable<TaskList> retrieveTasks(String userId, TasksOrder tasksOrder);
Observable<TaskList> retrieveTasks(String userId, TasksOrder tasksOrder, Date dueDate);
Observable<TaskScoringResult> taskChecked(User user, Task task, boolean up, boolean force);
Observable<TaskScoringResult> taskChecked(User user, String taskId, boolean up, boolean force);
Observable<Task> scoreChecklistItem(String taskId, String itemId);
Observable<Task> getTask(String taskId);
Observable<Task> getTaskCopy(String taskId);
Observable<Task> createTask(Task task);
Observable<Task> updateTask(Task task);
Observable<Void> deleteTask(String taskId);
void saveTask(Task task);
Observable<List<Task>> createTasks(List<Task> newTasks);
void markTaskCompleted(String taskId, boolean isCompleted);
void saveReminder(RemindersItem remindersItem);
void executeTransaction(Realm.Transaction transaction);
void swapTaskPosition(int firstPosition, int secondPosition);
Observable<List<String>> updateTaskPosition(int oldPosition, int newPosition);
Observable<Task> getUnmanagedTask(String taskid);
void updateTaskInBackground(Task task);
void createTaskInBackground(Task task);
Observable<List<Task>> getTaskCopies(String userId);
Observable<List<Task>> getTaskCopies(List<Task> tasks1);
Observable<TaskList> updateDailiesIsDue(Date date);
}

View file

@ -0,0 +1,62 @@
package com.habitrpg.android.habitica.data
import com.google.android.gms.tasks.Tasks
import com.habitrpg.android.habitica.models.responses.TaskDirectionData
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.TaskTag
import com.habitrpg.android.habitica.models.tasks.TasksOrder
import com.habitrpg.android.habitica.models.user.User
import java.util.Date
import io.realm.Realm
import io.realm.RealmResults
import rx.Observable
interface TaskRepository : BaseRepository {
fun getTasks(taskType: String, userID: String): Observable<RealmResults<Task>>
fun getTasks(userId: String): Observable<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 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 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 saveTask(task: Task)
fun createTasks(newTasks: List<Task>): Observable<List<Task>>
fun markTaskCompleted(taskId: String, isCompleted: Boolean)
fun saveReminder(remindersItem: RemindersItem)
fun executeTransaction(transaction: Realm.Transaction)
fun swapTaskPosition(firstPosition: Int, secondPosition: Int)
fun updateTaskPosition(oldPosition: Int, newPosition: Int): Observable<List<String>>
fun getUnmanagedTask(taskid: String): Observable<Task>
fun updateTaskInBackground(task: Task)
fun createTaskInBackground(task: Task)
fun getTaskCopies(userId: String): Observable<List<Task>>
fun getTaskCopies(tasks: List<Task>): Observable<List<Task>>
fun updateDailiesIsDue(date: Date): Observable<TaskList>
}

View file

@ -1,15 +0,0 @@
package com.habitrpg.android.habitica.data;
import com.habitrpg.android.habitica.models.TutorialStep;
import java.util.List;
import io.realm.RealmResults;
import rx.Observable;
public interface TutorialRepository extends BaseRepository {
Observable<TutorialStep> getTutorialStep(String key);
Observable<RealmResults<TutorialStep>> getTutorialSteps(List<String> keys);
}

View file

@ -0,0 +1,13 @@
package com.habitrpg.android.habitica.data
import com.habitrpg.android.habitica.models.TutorialStep
import io.realm.RealmResults
import rx.Observable
interface TutorialRepository : BaseRepository {
fun getTutorialStep(key: String): Observable<TutorialStep>
fun getTutorialSteps(keys: List<String>): Observable<RealmResults<TutorialStep>>
}

View file

@ -1,83 +0,0 @@
package com.habitrpg.android.habitica.data;
import android.support.annotation.Nullable;
import android.support.annotation.StringDef;
import com.habitrpg.android.habitica.models.Skill;
import com.habitrpg.android.habitica.models.inventory.Customization;
import com.habitrpg.android.habitica.models.inventory.CustomizationSet;
import com.habitrpg.android.habitica.models.responses.SkillResponse;
import com.habitrpg.android.habitica.models.responses.UnlockResponse;
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 org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Map;
import io.realm.RealmResults;
import rx.Observable;
public interface UserRepository extends BaseRepository {
Observable<User> getUser(String userID);
Observable<User> getUser();
Observable<User> updateUser(@Nullable User user, Map<String, Object> updateData);
Observable<User> updateUser(@Nullable User user, String key, Object value);
Observable<User> retrieveUser(Boolean withTasks);
Observable<User> retrieveUser(Boolean withTasks, Boolean forced);
Observable<RealmResults<ChatMessage>> getInboxMessages(String replyToUserID);
Observable<RealmResults<ChatMessage>> getInboxOverviewList();
Observable<User> revive(User user);
void resetTutorial(@Nullable User user);
Observable<User> sleep(User user);
Observable<RealmResults<Skill>> getSkills(User user);
Observable<RealmResults<Skill>> getSpecialItems(User user);
Observable<SkillResponse> useSkill(@Nullable User user, String key, String target, String taskId);
Observable<SkillResponse> useSkill(@Nullable User user, String key, String target);
Observable<User> changeClass();
Observable<User> disableClasses();
Observable<User> changeClass(String selectedClass);
Observable<UnlockResponse> unlockPath(User user, Customization customization);
Observable<UnlockResponse> unlockPath(User user, CustomizationSet set);
void runCron(List<Task> tasks);
void runCron();
Observable<List> readNotification(String id);
Observable<User> changeCustomDayStart(int dayStartTime);
Observable<User> updateLanguage(User user, String languageCode);
Observable<User> resetAccount();
Observable<Void> deleteAccount(String password);
Observable<Void> sendPasswordResetEmail(String email);
Observable<Void> updateLoginName(@NotNull String newLoginName, @NotNull String password);
Observable<Void> updateEmail(@NotNull String newEmail, @NotNull String password);
Observable<Void> updatePassword(@NotNull String newPassword, @NotNull String oldPassword, String oldPasswordConfirmation);
@NotNull
Observable<Stats> allocatePoint(@Nullable User user, @Stats.StatsTypes String s);
@NotNull
Observable<Stats> bulkAllocatePoints(int strength, int intelligence, int constitution, int perception);
}

View file

@ -0,0 +1,72 @@
package com.habitrpg.android.habitica.data
import com.habitrpg.android.habitica.models.Skill
import com.habitrpg.android.habitica.models.inventory.Customization
import com.habitrpg.android.habitica.models.inventory.CustomizationSet
import com.habitrpg.android.habitica.models.responses.SkillResponse
import com.habitrpg.android.habitica.models.responses.UnlockResponse
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.realm.RealmResults
import rx.Observable
interface UserRepository : BaseRepository {
val user: Observable<User>
val inboxOverviewList: Observable<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 retrieveUser(withTasks: Boolean): Observable<User>
fun retrieveUser(withTasks: Boolean = false, forced: Boolean = false): Observable<User>
fun getInboxMessages(replyToUserID: String): Observable<RealmResults<ChatMessage>>
fun revive(user: User): Observable<User>
fun resetTutorial(user: User?)
fun sleep(user: User): Observable<User>
fun getSkills(user: User): Observable<RealmResults<Skill>>
fun getSpecialItems(user: User): Observable<RealmResults<Skill>>
fun useSkill(user: User?, key: String, target: String, taskId: String): Observable<SkillResponse>
fun useSkill(user: User?, key: String, target: String): Observable<SkillResponse>
fun changeClass(): Observable<User>
fun disableClasses(): Observable<User>
fun changeClass(selectedClass: String): Observable<User>
fun unlockPath(user: User, customization: Customization): Observable<UnlockResponse>
fun unlockPath(user: User, set: CustomizationSet): Observable<UnlockResponse>
fun runCron(tasks: List<Task>)
fun runCron()
fun readNotification(id: String): Observable<List<*>>
fun changeCustomDayStart(dayStartTime: Int): Observable<User>
fun updateLanguage(user: User?, languageCode: String): Observable<User>
fun resetAccount(): Observable<User>
fun deleteAccount(password: String): Observable<Void>
fun sendPasswordResetEmail(email: String): Observable<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 allocatePoint(user: User?, @Stats.StatsTypes stat: String): Observable<Stats>
fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Observable<Stats>
}

View file

@ -991,12 +991,14 @@ public class ApiClientImpl implements Action1<Throwable>, ApiClient {
@Override
public Observable<Stats> bulkAllocatePoints(int strength, int intelligence, int constitution, int perception) {
Map<String, Map<String, Integer>> body = new HashMap<>();
Map<String, Integer> stats = new HashMap<>();
stats.put("str", strength);
stats.put("int", intelligence);
stats.put("con", constitution);
stats.put("per", perception);
return apiService.bulkAllocatePoints(stats).compose(configureApiCallObserver());
body.put("stats", stats);
return apiService.bulkAllocatePoints(body).compose(configureApiCallObserver());
}
@Override

View file

@ -1,267 +0,0 @@
package com.habitrpg.android.habitica.data.implementation;
import android.support.annotation.Nullable;
import com.habitrpg.android.habitica.data.ApiClient;
import com.habitrpg.android.habitica.data.TaskRepository;
import com.habitrpg.android.habitica.data.local.TaskLocalRepository;
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
import com.habitrpg.android.habitica.models.Tag;
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.user.Stats;
import com.habitrpg.android.habitica.models.user.User;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import io.realm.Realm;
import io.realm.RealmList;
import io.realm.RealmResults;
import rx.Observable;
public class TaskRepositoryImpl extends BaseRepositoryImpl<TaskLocalRepository> implements TaskRepository {
private long lastTaskAction = 0;
public TaskRepositoryImpl(TaskLocalRepository localRepository, ApiClient apiClient) {
super(localRepository, apiClient);
}
@Override
public Observable<RealmResults<Task>> getTasks(String taskType, String userID) {
return this.localRepository.getTasks(taskType, userID);
}
@Override
public Observable<RealmResults<Task>> getTasks(String userId) {
return this.localRepository.getTasks(userId);
}
@Override
public void saveTasks(String userId, TasksOrder order, TaskList tasks) {
localRepository.saveTasks(userId, order, tasks);
}
@Override
public Observable<TaskList> retrieveTasks(String userId, TasksOrder tasksOrder) {
return this.apiClient.getTasks()
.doOnNext(res -> this.localRepository.saveTasks(userId, tasksOrder, res));
}
@Override
public Observable<TaskList> retrieveTasks(String userId, TasksOrder tasksOrder, Date dueDate) {
DateFormat formatter = new 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
public Observable<TaskScoringResult> taskChecked(@Nullable User user, Task task, boolean up, boolean force) {
long now = new Date().getTime();
if (lastTaskAction > now-500 && !force) {
return Observable.just(null);
}
lastTaskAction = now;
return this.apiClient.postTaskDirection(task.getId(), (up ? TaskDirection.up : TaskDirection.down).toString())
.map(res -> {
// save local task changes
TaskScoringResult result = new TaskScoringResult();
if (user != null) {
Stats stats = user.getStats();
result.taskValueDelta = res.getDelta();
result.healthDelta = res.hp - stats.getHp();
result.experienceDelta = res.exp - stats.getExp();
result.manaDelta = res.mp - stats.getMp();
result.goldDelta = res.gp - stats.getGp();
result.hasLeveledUp = res.lvl > stats.getLvl();
if (res.get_tmp() != null) {
result.drop = res.get_tmp().getDrop();
}
this.localRepository.executeTransaction(realm -> {
if (task.getType() != null && !task.getType().equals("reward")) {
task.setValue(task.getValue() + res.getDelta());
if (Task.TYPE_DAILY.equals(task.getType()) || Task.TYPE_TODO.equals(task.getType())) {
task.setCompleted(up);
}
}
stats.setHp(res.hp);
stats.setExp(res.exp);
stats.setMp(res.mp);
stats.setGp(res.gp);
stats.setLvl(res.lvl);
user.setStats(stats);
});
}
return result;
});
}
@Override
public Observable<TaskScoringResult> taskChecked(User user, String taskId, boolean up, boolean force) {
return localRepository.getTask(taskId).first()
.flatMap(task -> taskChecked(user, task, up, force));
}
public Observable<Task> scoreChecklistItem(String taskId, String itemId) {
return apiClient.scoreChecklistItem(taskId, itemId)
.flatMap(task -> localRepository.getTask(taskId).first())
.doOnNext(task -> {
ChecklistItem updatedItem = null;
for (ChecklistItem item : task.getChecklist()) {
if (itemId.equals(item.getId())) {
updatedItem = item;
}
}
if (updatedItem != null) {
ChecklistItem finalUpdatedItem = updatedItem;
localRepository.executeTransaction(realm -> finalUpdatedItem.setCompleted(!finalUpdatedItem.getCompleted()));
}
});
}
@Override
public Observable<Task> getTask(String taskId) {
return localRepository.getTask(taskId);
}
@Override
public Observable<Task> getTaskCopy(String taskId) {
return localRepository.getTaskCopy(taskId);
}
@Override
public Observable<Task> createTask(Task task) {
long now = new Date().getTime();
if (lastTaskAction > now-500) {
return Observable.just(task);
}
lastTaskAction = now;
if (task.getTags() != null && task.getTags().size() > 0) {
RealmList<Tag> tags = new RealmList<>(localRepository.getUnmanagedCopy(task.getTags()).toArray(new Tag[0]));
task.setTags(tags);
}
if (task.getChecklist() != null && task.getChecklist().size() > 0) {
RealmList<ChecklistItem> checklist = new RealmList<>(localRepository.getUnmanagedCopy(task.getChecklist()).toArray(new ChecklistItem[0]));
task.setChecklist(checklist);
}
if (task.getReminders() != null && task.getReminders().size() > 0) {
RealmList<RemindersItem> reminders = new RealmList<>(localRepository.getUnmanagedCopy(task.getReminders()).toArray(new RemindersItem[0]));
task.setReminders(reminders);
}
return apiClient.createTask(task)
.map(task1 -> {
task1.setDateCreated(new Date());
return task1;
})
.doOnNext(localRepository::saveTask);
}
@Override
public Observable<Task> updateTask(Task task) {
long now = new Date().getTime();
if (lastTaskAction > now-500 || !task.isValid()) {
return Observable.just(task);
}
lastTaskAction = now;
return localRepository.getTaskCopy(task.getId()).first()
.flatMap(task1 -> apiClient.updateTask(task1.getId(), task1))
.map(task1 -> {
task1.setPosition(task.getPosition());
return task1;
})
.doOnNext(localRepository::saveTask);
}
@Override
public Observable<Void> deleteTask(String taskID) {
return apiClient.deleteTask(taskID)
.doOnNext(aVoid -> localRepository.deleteTask(taskID));
}
@Override
public void saveTask(Task task) {
localRepository.saveTask(task);
}
@Override
public Observable<List<Task>> createTasks(List<Task> newTasks) {
return apiClient.createTasks(newTasks);
}
@Override
public void markTaskCompleted(String taskId, boolean isCompleted) {
localRepository.markTaskCompleted(taskId, isCompleted);
}
@Override
public void saveReminder(RemindersItem remindersItem) {
localRepository.saveReminder(remindersItem);
}
@Override
public void executeTransaction(Realm.Transaction transaction) {
localRepository.executeTransaction(transaction);
}
@Override
public void swapTaskPosition(int firstPosition, int secondPosition) {
localRepository.swapTaskPosition(firstPosition, secondPosition);
}
public Observable<List<String>> updateTaskPosition(int oldPosition, int newPosition) {
return localRepository.getTaskAtPosition(oldPosition)
.first()
.flatMap(task -> {
if (task.isValid()) {
return apiClient.postTaskNewPosition(task.getId(), newPosition);
}
return Observable.just(null);
})
.doOnNext(localRepository::updateTaskPositions);
}
@Override
public Observable<Task> getUnmanagedTask(String taskid) {
return getTask(taskid)
.map(localRepository::getUnmanagedCopy);
}
@Override
public void updateTaskInBackground(Task task) {
updateTask(task).subscribe(task1 -> {}, RxErrorHandler.handleEmptyError());
}
@Override
public void createTaskInBackground(Task task) {
createTask(task).subscribe(task1 -> {}, RxErrorHandler.handleEmptyError());
}
@Override
public Observable<List<Task>> getTaskCopies(String userId) {
return getTasks(userId)
.map(localRepository::getUnmanagedCopy);
}
@Override
public Observable<List<Task>> getTaskCopies(List<Task> tasks) {
return Observable.just(localRepository.getUnmanagedCopy(tasks));
}
@Override
public Observable<TaskList> updateDailiesIsDue(Date date) {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.US);
return apiClient.getTasks("dailys", formatter.format(date))
.flatMap(localRepository::updateIsdue);
}
}

View file

@ -0,0 +1,212 @@
package com.habitrpg.android.habitica.data.implementation
import com.habitrpg.android.habitica.data.ApiClient
import com.habitrpg.android.habitica.data.TaskRepository
import com.habitrpg.android.habitica.data.local.TaskLocalRepository
import com.habitrpg.android.habitica.helpers.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.user.User
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.*
class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiClient) : BaseRepositoryImpl<TaskLocalRepository>(localRepository, apiClient), TaskRepository {
private var lastTaskAction: Long = 0
override fun getTasks(taskType: String, userID: String): Observable<RealmResults<Task>> =
this.localRepository.getTasks(taskType, userID)
override fun getTasks(userId: String): Observable<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.tasks
.doOnNext { res -> this.localRepository.saveTasks(userId, tasksOrder, res) }
}
override fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): Observable<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> {
val now = Date().time
if (lastTaskAction > now - 500 && !force) {
return Observable.just(null)
}
lastTaskAction = now
return this.apiClient.postTaskDirection(task.id, (if (up) TaskDirection.up else TaskDirection.down).toString())
.map { res ->
// save local task changes
val result = TaskScoringResult()
if (user != null) {
val stats = user.stats
result.taskValueDelta = res.delta
result.healthDelta = res.hp - stats.getHp()
result.experienceDelta = res.exp - stats.getExp()
result.manaDelta = res.mp - stats.getMp()
result.goldDelta = res.gp - stats.getGp()
result.hasLeveledUp = res.lvl > stats.getLvl()
if (res._tmp != null) {
result.drop = res._tmp.drop
}
this.localRepository.executeTransaction {
if (task.type != "reward") {
task.value = task.value + res.delta
if (Task.TYPE_DAILY == task.type || Task.TYPE_TODO == task.type) {
task.completed = up
}
}
stats.setHp(res.hp)
stats.setExp(res.exp)
stats.setMp(res.mp)
stats.setGp(res.gp)
stats.setLvl(res.lvl)
user.stats = stats
}
}
result
}
}
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 scoreChecklistItem(taskId: String, itemId: String): Observable<Task> {
return apiClient.scoreChecklistItem(taskId, itemId)
.flatMap { localRepository.getTask(taskId).first() }
.doOnNext { task ->
val updatedItem: ChecklistItem? = task.checklist.lastOrNull { itemId == it.id }
if (updatedItem != null) {
localRepository.executeTransaction { updatedItem.completed = !updatedItem.completed }
}
}
}
override fun getTask(taskId: String): Observable<Task> = localRepository.getTask(taskId)
override fun getTaskCopy(taskId: String): Observable<Task> = localRepository.getTaskCopy(taskId)
override fun createTask(task: Task): Observable<Task> {
val now = Date().time
if (lastTaskAction > now - 500) {
return Observable.just(task)
}
lastTaskAction = now
if (task.tags.size > 0) {
val tags = RealmList(*localRepository.getUnmanagedCopy(task.tags).toTypedArray())
task.tags = tags
}
if (task.checklist.size > 0) {
val checklist = RealmList(*localRepository.getUnmanagedCopy(task.checklist).toTypedArray())
task.checklist = checklist
}
if (task.reminders.size > 0) {
val reminders = RealmList(*localRepository.getUnmanagedCopy(task.reminders).toTypedArray())
task.reminders = reminders
}
return apiClient.createTask(task)
.map { task1 ->
task1.dateCreated = Date()
task1
}
.doOnNext({ localRepository.saveTask(it) })
}
override fun updateTask(task: Task): Observable<Task> {
val now = Date().time
if (lastTaskAction > now - 500 || !task.isValid) {
return Observable.just(task)
}
lastTaskAction = now
return localRepository.getTaskCopy(task.id ?: "").first()
.flatMap { task1 -> apiClient.updateTask(task1.id, task1) }
.map { task1 ->
task1.position = task.position
task1
}
.doOnNext({ localRepository.saveTask(it) })
}
override fun deleteTask(taskId: String): Observable<Void> {
return apiClient.deleteTask(taskId)
.doOnNext { localRepository.deleteTask(taskId) }
}
override fun saveTask(task: Task) {
localRepository.saveTask(task)
}
override fun createTasks(newTasks: List<Task>): Observable<List<Task>> = apiClient.createTasks(newTasks)
override fun markTaskCompleted(taskId: String, isCompleted: Boolean) {
localRepository.markTaskCompleted(taskId, isCompleted)
}
override fun saveReminder(remindersItem: RemindersItem) {
localRepository.saveReminder(remindersItem)
}
override fun executeTransaction(transaction: Realm.Transaction) {
localRepository.executeTransaction(transaction)
}
override fun swapTaskPosition(firstPosition: Int, secondPosition: Int) {
localRepository.swapTaskPosition(firstPosition, secondPosition)
}
override fun updateTaskPosition(oldPosition: Int, newPosition: Int): Observable<List<String>> {
return localRepository.getTaskAtPosition(oldPosition)
.first()
.flatMap { task ->
if (task.isValid) {
return@flatMap apiClient.postTaskNewPosition(task.id, newPosition)
}
return@flatMap Observable.just<List<String>>(null)
}
.doOnNext({ localRepository.updateTaskPositions(it) })
}
override fun getUnmanagedTask(taskid: String): Observable<Task> =
getTask(taskid).map({ localRepository.getUnmanagedCopy(it) })
override fun updateTaskInBackground(task: Task) {
updateTask(task).subscribe(Action1 { }, RxErrorHandler.handleEmptyError())
}
override fun createTaskInBackground(task: Task) {
createTask(task).subscribe(Action1 { }, RxErrorHandler.handleEmptyError())
}
override fun getTaskCopies(userId: String): Observable<List<Task>> =
getTasks(userId).map({ localRepository.getUnmanagedCopy(it) })
override fun getTaskCopies(tasks: List<Task>): Observable<List<Task>> =
Observable.just(localRepository.getUnmanagedCopy(tasks))
override fun updateDailiesIsDue(date: Date): Observable<TaskList> {
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.US)
return apiClient.getTasks("dailys", formatter.format(date))
.flatMap({ localRepository.updateIsdue(it) })
}
}

View file

@ -1,28 +0,0 @@
package com.habitrpg.android.habitica.data.implementation;
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 java.util.List;
import io.realm.RealmResults;
import rx.Observable;
public class TutorialRepositoryImpl extends BaseRepositoryImpl<TutorialLocalRepository> implements TutorialRepository {
public TutorialRepositoryImpl(TutorialLocalRepository localRepository, ApiClient apiClient) {
super(localRepository, apiClient);
}
@Override
public Observable<TutorialStep> getTutorialStep(String key) {
return localRepository.getTutorialStep(key);
}
@Override
public Observable<RealmResults<TutorialStep>> getTutorialSteps(List<String> keys) {
return localRepository.getTutorialSteps(keys);
}
}

View file

@ -0,0 +1,19 @@
package com.habitrpg.android.habitica.data.implementation
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.realm.RealmResults
import rx.Observable
class TutorialRepositoryImpl(localRepository: TutorialLocalRepository, apiClient: ApiClient) : BaseRepositoryImpl<TutorialLocalRepository>(localRepository, apiClient), TutorialRepository {
override fun getTutorialStep(key: String): Observable<TutorialStep> =
localRepository.getTutorialStep(key)
override fun getTutorialSteps(keys: List<String>): Observable<RealmResults<TutorialStep>> =
localRepository.getTutorialSteps(keys)
}

View file

@ -1,362 +0,0 @@
package com.habitrpg.android.habitica.data.implementation;
import android.support.annotation.Nullable;
import com.habitrpg.android.habitica.data.ApiClient;
import com.habitrpg.android.habitica.data.TaskRepository;
import com.habitrpg.android.habitica.data.UserRepository;
import com.habitrpg.android.habitica.data.local.UserLocalRepository;
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
import com.habitrpg.android.habitica.models.Skill;
import com.habitrpg.android.habitica.models.TutorialStep;
import com.habitrpg.android.habitica.models.inventory.Customization;
import com.habitrpg.android.habitica.models.inventory.CustomizationSet;
import com.habitrpg.android.habitica.models.responses.SkillResponse;
import com.habitrpg.android.habitica.models.responses.TaskScoringResult;
import com.habitrpg.android.habitica.models.responses.UnlockResponse;
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 org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import io.realm.RealmResults;
import rx.Observable;
public class UserRepositoryImpl extends BaseRepositoryImpl<UserLocalRepository> implements UserRepository {
private Date lastSync;
private String userId;
private TaskRepository taskRepository;
public UserRepositoryImpl(UserLocalRepository localRepository, ApiClient apiClient, String userId, TaskRepository taskRepository) {
super(localRepository, apiClient);
this.taskRepository = taskRepository;
this.userId = userId;
}
@Override
public Observable<User> getUser(String userID) {
return localRepository.getUser(userID);
}
@Override
public Observable<User> getUser() {
return getUser(userId);
}
@Override
public Observable<User> updateUser(@Nullable User user, Map<String, Object> updateData) {
if (user == null) {
return Observable.just(null);
}
return apiClient.updateUser(updateData)
.map(newUser -> mergeUser(user, newUser));
}
@Override
public Observable<User> updateUser(@Nullable User user, String key, Object value) {
Map<String, Object> updateData = new HashMap<>();
updateData.put(key, value);
return updateUser(user, updateData);
}
@Override
public Observable<User> retrieveUser(Boolean withTasks) {
return retrieveUser(withTasks, false);
}
@Override
public Observable<User> retrieveUser(Boolean withTasks, Boolean forced) {
if (forced || this.lastSync == null || (new Date().getTime() - this.lastSync.getTime()) > 180000) {
lastSync = new Date();
return apiClient.retrieveUser(withTasks)
.doOnNext(localRepository::saveUser)
.doOnNext(user -> {
if (withTasks) {
taskRepository.saveTasks(user.getId(), user.getTasksOrder(), user.tasks);
}
})
.flatMap(user -> {
Calendar calendar = new GregorianCalendar();
TimeZone timeZone = calendar.getTimeZone();
long offset = -TimeUnit.MINUTES.convert(timeZone.getOffset(calendar.getTimeInMillis()), TimeUnit.MILLISECONDS);
if (user != null && user.getPreferences() != null && offset != user.getPreferences().getTimezoneOffset()) {
return updateUser(user, "preferences.timezoneOffset", String.valueOf(offset));
} else {
return Observable.just(user);
}
});
} else {
return getUser();
}
}
@Override
public Observable<RealmResults<ChatMessage>> getInboxMessages(String replyToUserID) {
return localRepository.getInboxMessages(userId, replyToUserID);
}
@Override
public Observable<RealmResults<ChatMessage>> getInboxOverviewList() {
return localRepository.getInboxOverviewList(userId);
}
@Override
public Observable<User> revive(User user) {
return apiClient.revive().map(newUser -> mergeUser(user, newUser));
}
@Override
public void resetTutorial(User user) {
localRepository.getTutorialSteps()
.map(tutorialSteps -> {
Map<String, Object> updateData = new HashMap<>();
for (TutorialStep step : tutorialSteps) {
updateData.put("flags.tutorial." + step.getTutorialGroup() + "." + step.getIdentifier(), false);
}
return updateData;
})
.flatMap(updateData -> updateUser(user, updateData))
.subscribe(tutorialSteps -> {}, RxErrorHandler.handleEmptyError());
}
@Override
public Observable<User> sleep(User user) {
localRepository.executeTransaction(realm -> user.getPreferences().setSleep(!user.getPreferences().getSleep()));
return apiClient.sleep()
.map(isSleeping -> user);
}
@Override
public Observable<RealmResults<Skill>> getSkills(User user) {
return localRepository.getSkills(user);
}
@Override
public Observable<RealmResults<Skill>> getSpecialItems(User user) {
return localRepository.getSpecialItems(user);
}
@Override
public Observable<SkillResponse> useSkill(User user, String key, String target, String taskId) {
return apiClient.useSkill(key, target, taskId).doOnNext(skillResponse -> {
if (user != null) {
mergeUser(user, skillResponse.user);
}
});
}
@Override
public Observable<SkillResponse> useSkill(User user, String key, String target) {
return apiClient.useSkill(key, target)
.map(response -> {
response.hpDiff = response.user.getStats().getHp() - user.getStats().getHp();
response.expDiff = response.user.getStats().getExp() - user.getStats().getExp();
response.goldDiff = response.user.getStats().getGp() - user.getStats().getGp();
return response;
})
.doOnNext(skillResponse -> {
if (user != null) {
mergeUser(user, skillResponse.user);
}
});
}
@Override
public Observable<User> changeClass() {
return apiClient.changeClass();
}
@Override
public Observable<User> disableClasses() {
return apiClient.disableClasses();
}
@Override
public Observable<User> changeClass(String selectedClass) {
return apiClient.changeClass(selectedClass);
}
@Override
public Observable<UnlockResponse> unlockPath(User user, Customization customization) {
return apiClient.unlockPath(customization.getPath())
.doOnNext(unlockResponse -> {
User copiedUser = localRepository.getUnmanagedCopy(user);
copiedUser.setPreferences(unlockResponse.preferences);
copiedUser.setPurchased(unlockResponse.purchased);
copiedUser.setItems(unlockResponse.items);
copiedUser.setBalance(copiedUser.getBalance()-customization.getPrice()/4.0);
localRepository.saveUser(copiedUser);
});
}
@Override
public Observable<UnlockResponse> unlockPath(User user, CustomizationSet set) {
String path = "";
for (Customization customization : set.customizations) {
path = path + "," + customization.getPath();
}
if (path.length() == 0) {
return Observable.just(null);
}
path = path.substring(1);
return apiClient.unlockPath(path)
.doOnNext(unlockResponse -> {
User copiedUser = localRepository.getUnmanagedCopy(user);
copiedUser.setPreferences(unlockResponse.preferences);
copiedUser.setPurchased(unlockResponse.purchased);
copiedUser.setItems(unlockResponse.items);
copiedUser.setBalance(copiedUser.getBalance()-set.price/4.0);
localRepository.saveUser(copiedUser);
});
}
@Override
public void runCron() {
runCron(new ArrayList<>());
}
@Override
public Observable<List> readNotification(String id) {
return apiClient.readNotification(id);
}
@Override
public Observable<User> changeCustomDayStart(int dayStartTime) {
Map<String, Object> updateObject = new HashMap<>();
updateObject.put("dayStart", dayStartTime);
return apiClient.changeCustomDayStart(updateObject);
}
@Override
public Observable<User> updateLanguage(User user, String languageCode) {
return updateUser(user, "preferences.language", languageCode)
.doOnNext(user1 -> apiClient.setLanguageCode(languageCode));
}
@Override
public Observable<User> resetAccount() {
return apiClient.resetAccount()
.flatMap(aVoid -> retrieveUser(true, true));
}
@Override
public Observable<Void> deleteAccount(String password) {
return apiClient.deleteAccount(password);
}
@Override
public Observable<Void> sendPasswordResetEmail(String email) {
return apiClient.sendPasswordResetEmail(email);
}
@Override
public Observable<Void> updateLoginName(@NotNull String newLoginName, @NotNull String password) {
return apiClient.updateLoginName(newLoginName, password);
}
@Override
public Observable<Void> updateEmail(@NotNull String newEmail, @NotNull String password) {
return apiClient.updateEmail(newEmail, password);
}
@Override
public Observable<Void> updatePassword(@NotNull String newPassword, @NotNull String oldPassword, String oldPasswordConfirmation) {
return apiClient.updatePassword(newPassword, oldPassword, oldPasswordConfirmation);
}
@NotNull
@Override
public Observable<Stats> allocatePoint(@Nullable User user, String stat) {
if (user != null && user.isManaged()) {
localRepository.executeTransaction(realm -> {
if (Stats.STRENGTH.equals(stat)) {
user.getStats().str += 1;
} else if (Stats.INTELLIGENCE.equals(stat)) {
user.getStats()._int += 1;
} else if (Stats.CONSTITUTION.equals(stat)) {
user.getStats().con += 1;
} else if (Stats.PERCEPTION.equals(stat)) {
user.getStats().per += 1;
}
user.getStats().points -= 1;
});
}
return apiClient.allocatePoint(stat)
.doOnNext(stats -> {
if (user != null && user.isManaged()) {
localRepository.executeTransaction(realm -> {
user.getStats().str = stats.str;
user.getStats().con = stats.con;
user.getStats().per = stats.per;
user.getStats()._int = stats._int;
user.getStats().points = stats.points;
user.getStats().mp = stats.mp;
});
}
});
}
@NotNull
@Override
public Observable<Stats> bulkAllocatePoints(int strength, int intelligence, int constitution, int perception) {
return apiClient.bulkAllocatePoints(strength, intelligence, constitution, perception);
}
@Override
public void runCron(List<Task> tasks) {
Observable<List<TaskScoringResult>> observable;
if (tasks.size() > 0) {
observable = Observable.from(tasks)
.flatMap(task -> taskRepository.taskChecked(null, task, true, true))
.toList();
} else {
observable = Observable.just(null);
}
localRepository.getUser(userId).first().subscribe(user -> localRepository.executeTransaction(realm -> user.setNeedsCron(false)), RxErrorHandler.handleEmptyError());
observable.flatMap(taskScoringResults -> apiClient.runCron())
.flatMap(aVoid -> this.retrieveUser(true, true))
.subscribe(user -> {}, RxErrorHandler.handleEmptyError());
}
private User mergeUser(User oldUser, User newUser) {
if (oldUser == null || !oldUser.isValid()) {
return oldUser;
}
User copiedUser;
if (oldUser.isManaged()) {
copiedUser = localRepository.getUnmanagedCopy(oldUser);
} else {
copiedUser = oldUser;
}
if (newUser.getItems() != null) {
copiedUser.setItems(newUser.getItems());
}
if (newUser.getPreferences() != null) {
copiedUser.setPreferences(newUser.getPreferences());
}
if (newUser.getFlags() != null) {
copiedUser.setFlags(newUser.getFlags());
}
if (newUser.getStats() != null) {
copiedUser.getStats().merge(newUser.getStats());
}
localRepository.saveUser(copiedUser);
return oldUser;
}
}

View file

@ -0,0 +1,273 @@
package com.habitrpg.android.habitica.data.implementation
import com.habitrpg.android.habitica.data.ApiClient
import com.habitrpg.android.habitica.data.TaskRepository
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.data.local.UserLocalRepository
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.Skill
import com.habitrpg.android.habitica.models.inventory.Customization
import com.habitrpg.android.habitica.models.inventory.CustomizationSet
import com.habitrpg.android.habitica.models.responses.SkillResponse
import com.habitrpg.android.habitica.models.responses.TaskScoringResult
import com.habitrpg.android.habitica.models.responses.UnlockResponse
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.realm.RealmResults
import rx.Observable
import rx.functions.Action1
import java.util.*
import java.util.concurrent.TimeUnit
class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiClient, private val userId: String, private val taskRepository: TaskRepository) : BaseRepositoryImpl<UserLocalRepository>(localRepository, apiClient), UserRepository {
private var lastSync: Date? = null
override val user: Observable<User>
get() = getUser(userId) //To change initializer of created properties use File | Settings | File Templates.
override val inboxOverviewList: Observable<RealmResults<ChatMessage>>
get() = localRepository.getInboxOverviewList(userId) //To change initializer of created properties use File | Settings | File Templates.
override fun getUser(userID: String): Observable<User> = localRepository.getUser(userID)
override fun updateUser(user: User?, updateData: Map<String, Any>): Observable<User> {
return if (user == null) {
Observable.just(null)
} else apiClient.updateUser(updateData).map { newUser -> mergeUser(user, newUser) }
}
override fun updateUser(user: User?, key: String, value: Any): Observable<User> {
val updateData = HashMap<String, Any>()
updateData.put(key, value)
return updateUser(user, updateData)
}
override fun retrieveUser(withTasks: Boolean): Observable<User> =
retrieveUser(withTasks, false)
override fun retrieveUser(withTasks: Boolean, forced: Boolean): Observable<User> {
if (forced || this.lastSync == null || Date().time - (this.lastSync?.time ?: 0) > 180000) {
lastSync = Date()
return apiClient.retrieveUser(withTasks)
.doOnNext({ localRepository.saveUser(it) })
.doOnNext { user ->
if (withTasks) {
taskRepository.saveTasks(user.id, user.tasksOrder, user.tasks)
}
}
.flatMap { user ->
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) {
return@flatMap updateUser(user, "preferences.timezoneOffset", offset.toString())
} else {
return@flatMap Observable.just(user)
}
}
} else {
return user
}
}
override fun getInboxMessages(replyToUserID: String): Observable<RealmResults<ChatMessage>> =
localRepository.getInboxMessages(userId, replyToUserID)
override fun revive(user: User): Observable<User> =
apiClient.revive().map { newUser -> mergeUser(user, newUser) }
override fun resetTutorial(user: User?) {
localRepository.tutorialSteps
.map<Map<String, Any>> { tutorialSteps ->
val updateData = HashMap<String, Any>()
for (step in tutorialSteps) {
updateData.put("flags.tutorial." + step.tutorialGroup + "." + step.identifier, false)
}
updateData
}
.flatMap { updateData -> updateUser(user, updateData) }
.subscribe(Action1 { }, RxErrorHandler.handleEmptyError())
}
override fun sleep(user: User): Observable<User> {
localRepository.executeTransaction { user.preferences.sleep = !user.preferences.sleep }
return apiClient.sleep().map { user }
}
override fun getSkills(user: User): Observable<RealmResults<Skill>> =
localRepository.getSkills(user)
override fun getSpecialItems(user: User): Observable<RealmResults<Skill>> =
localRepository.getSpecialItems(user)
override fun useSkill(user: User?, key: String, target: String, taskId: String): Observable<SkillResponse> {
return apiClient.useSkill(key, target, taskId).doOnNext { skillResponse ->
if (user != null) {
mergeUser(user, skillResponse.user)
}
}
}
override fun useSkill(user: User?, key: String, target: String): Observable<SkillResponse> {
return apiClient.useSkill(key, target)
.map { response ->
response.hpDiff = response.user.stats.getHp() - (user?.stats?.getHp() ?: 0.0)
response.expDiff = response.user.stats.getExp() - (user?.stats?.getExp() ?: 0.0)
response.goldDiff = response.user.stats.getGp() - (user?.stats?.getGp() ?: 0.0)
response
}
.doOnNext { skillResponse ->
if (user != null) {
mergeUser(user, skillResponse.user)
}
}
}
override fun changeClass(): Observable<User> = apiClient.changeClass()
override fun disableClasses(): Observable<User> = apiClient.disableClasses()
override fun changeClass(selectedClass: String): Observable<User> = apiClient.changeClass(selectedClass)
override fun unlockPath(user: User, customization: Customization): Observable<UnlockResponse> {
return apiClient.unlockPath(customization.path)
.doOnNext { unlockResponse ->
val copiedUser = localRepository.getUnmanagedCopy(user)
copiedUser.preferences = unlockResponse.preferences
copiedUser.purchased = unlockResponse.purchased
copiedUser.items = unlockResponse.items
copiedUser.balance = copiedUser.balance - customization.price / 4.0
localRepository.saveUser(copiedUser)
}
}
override fun unlockPath(user: User, set: CustomizationSet): Observable<UnlockResponse> {
var path = ""
for (customization in set.customizations) {
path = path + "," + customization.path
}
if (path.isEmpty()) {
return Observable.just(null)
}
path = path.substring(1)
return apiClient.unlockPath(path)
.doOnNext { unlockResponse ->
val copiedUser = localRepository.getUnmanagedCopy(user)
copiedUser.preferences = unlockResponse.preferences
copiedUser.purchased = unlockResponse.purchased
copiedUser.items = unlockResponse.items
copiedUser.balance = copiedUser.balance - set.price / 4.0
localRepository.saveUser(copiedUser)
}
}
override fun runCron() {
runCron(ArrayList())
}
override fun readNotification(id: String): Observable<List<*>> = apiClient.readNotification(id)
override fun changeCustomDayStart(dayStartTime: Int): Observable<User> {
val updateObject = HashMap<String, Any>()
updateObject.put("dayStart", dayStartTime)
return apiClient.changeCustomDayStart(updateObject)
}
override fun updateLanguage(user: User?, languageCode: String): Observable<User> {
return updateUser(user, "preferences.language", languageCode)
.doOnNext { apiClient.setLanguageCode(languageCode) }
}
override fun resetAccount(): Observable<User> {
return apiClient.resetAccount()
.flatMap { retrieveUser(true, true) }
}
override fun deleteAccount(password: String): Observable<Void> =
apiClient.deleteAccount(password)
override fun sendPasswordResetEmail(email: String): Observable<Void> =
apiClient.sendPasswordResetEmail(email)
override fun updateLoginName(newLoginName: String, password: String): Observable<Void> =
apiClient.updateLoginName(newLoginName, password)
override fun updateEmail(newEmail: String, password: String): Observable<Void> =
apiClient.updateEmail(newEmail, password)
override fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Observable<Void> =
apiClient.updatePassword(newPassword, oldPassword, oldPasswordConfirmation)
override fun allocatePoint(user: User?, stat: String): Observable<Stats> {
if (user != null && user.isManaged) {
localRepository.executeTransaction {
when (stat) {
Stats.STRENGTH -> user.stats.str += 1
Stats.INTELLIGENCE -> user.stats._int += 1
Stats.CONSTITUTION -> user.stats.con += 1
Stats.PERCEPTION -> user.stats.per += 1
}
user.stats.points -= 1
}
}
return apiClient.allocatePoint(stat)
.doOnNext { stats ->
if (user != null && user.isManaged) {
localRepository.executeTransaction {
user.stats.str = stats.str
user.stats.con = stats.con
user.stats.per = stats.per
user.stats._int = stats._int
user.stats.points = stats.points
user.stats.mp = stats.mp
}
}
}
}
override fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Observable<Stats> =
apiClient.bulkAllocatePoints(strength, intelligence, constitution, perception)
override fun runCron(tasks: List<Task>) {
val observable: Observable<List<TaskScoringResult>> = if (tasks.isNotEmpty()) {
Observable.from(tasks)
.flatMap { task -> taskRepository.taskChecked(null, task, true, true) }
.toList()
} else {
Observable.just(null)
}
localRepository.getUser(userId).first().subscribe(Action1 { user -> localRepository.executeTransaction { user.needsCron = false } }, RxErrorHandler.handleEmptyError())
observable.flatMap { apiClient.runCron() }
.flatMap { this.retrieveUser(true, true) }
.subscribe(Action1 { }, RxErrorHandler.handleEmptyError())
}
private fun mergeUser(oldUser: User?, newUser: User): User? {
if (oldUser == null || !oldUser.isValid) {
return oldUser
}
val copiedUser: User = if (oldUser.isManaged) {
localRepository.getUnmanagedCopy(oldUser)
} else {
oldUser
}
if (newUser.items != null) {
copiedUser.items = newUser.items
}
if (newUser.preferences != null) {
copiedUser.preferences = newUser.preferences
}
if (newUser.flags != null) {
copiedUser.flags = newUser.flags
}
if (newUser.stats != null) {
copiedUser.stats.merge(newUser.stats)
}
localRepository.saveUser(copiedUser)
return oldUser
}
}

View file

@ -1,40 +0,0 @@
package com.habitrpg.android.habitica.data.local;
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.TaskTag;
import com.habitrpg.android.habitica.models.tasks.TasksOrder;
import java.util.List;
import io.realm.RealmResults;
import rx.Observable;
public interface TaskLocalRepository extends BaseLocalRepository {
Observable<RealmResults<Task>> getTasks(String taskType, String userID);
Observable<RealmResults<Task>> getTasks(String userId);
void saveTasks(String userId, TasksOrder tasksOrder, TaskList tasks);
void saveTask(Task task);
void deleteTask(String taskID);
Observable<Task> getTask(String taskId);
Observable<Task> getTaskCopy(String taskId);
void markTaskCompleted(String taskId, boolean isCompleted);
void saveReminder(RemindersItem remindersItem);
void swapTaskPosition(int firstPosition, int secondPosition);
Observable<Task> getTaskAtPosition(int currentPosition);
Observable<TaskList> updateIsdue(TaskList daily);
void updateTaskPositions(List<String> taskOrder);
}

View file

@ -0,0 +1,38 @@
package com.habitrpg.android.habitica.data.local
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.TaskTag
import com.habitrpg.android.habitica.models.tasks.TasksOrder
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 saveTasks(userId: String, tasksOrder: TasksOrder, tasks: TaskList)
fun saveTask(task: Task)
fun deleteTask(taskID: String)
fun getTask(taskId: String): Observable<Task>
fun getTaskCopy(taskId: String): Observable<Task>
fun markTaskCompleted(taskId: String, isCompleted: Boolean)
fun saveReminder(remindersItem: RemindersItem)
fun swapTaskPosition(firstPosition: Int, secondPosition: Int)
fun getTaskAtPosition(currentPosition: Int): Observable<Task>
fun updateIsdue(daily: TaskList): Observable<TaskList>
fun updateTaskPositions(taskOrder: List<String>)
}

View file

@ -1,14 +0,0 @@
package com.habitrpg.android.habitica.data.local;
import com.habitrpg.android.habitica.models.TutorialStep;
import java.util.List;
import io.realm.RealmResults;
import rx.Observable;
public interface TutorialLocalRepository extends BaseLocalRepository {
Observable<TutorialStep> getTutorialStep(String key);
Observable<RealmResults<TutorialStep>> getTutorialSteps(List<String> keys);
}

View file

@ -0,0 +1,12 @@
package com.habitrpg.android.habitica.data.local
import com.habitrpg.android.habitica.models.TutorialStep
import io.realm.RealmResults
import rx.Observable
interface TutorialLocalRepository : BaseLocalRepository {
fun getTutorialStep(key: String): Observable<TutorialStep>
fun getTutorialSteps(keys: List<String>): Observable<RealmResults<TutorialStep>>
}

View file

@ -1,28 +0,0 @@
package com.habitrpg.android.habitica.data.local;
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 java.util.List;
import io.realm.RealmResults;
import rx.Observable;
public interface UserLocalRepository extends BaseLocalRepository {
Observable<User> getUser(String userID);
void saveUser(User user);
Observable<RealmResults<TutorialStep>> getTutorialSteps();
Observable<RealmResults<Skill>> getSkills(User user);
Observable<RealmResults<Skill>> getSpecialItems(User user);
Observable<RealmResults<ChatMessage>> getInboxMessages(String userId, String replyToUserID);
Observable<RealmResults<ChatMessage>> getInboxOverviewList(String userId);
}

View file

@ -0,0 +1,26 @@
package com.habitrpg.android.habitica.data.local
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.realm.RealmResults
import rx.Observable
interface UserLocalRepository : BaseLocalRepository {
val tutorialSteps: Observable<RealmResults<TutorialStep>>
fun getUser(userID: String): Observable<User>
fun saveUser(user: User)
fun getSkills(user: User): Observable<RealmResults<Skill>>
fun getSpecialItems(user: User): Observable<RealmResults<Skill>>
fun getInboxMessages(userId: String, replyToUserID: String): Observable<RealmResults<ChatMessage>>
fun getInboxOverviewList(userId: String): Observable<RealmResults<ChatMessage>>
}

View file

@ -8,7 +8,7 @@ import java.util.List;
import io.realm.Realm;
import io.realm.RealmObject;
abstract class RealmBaseLocalRepository implements BaseLocalRepository {
public abstract class RealmBaseLocalRepository implements BaseLocalRepository {
Realm realm;

View file

@ -1,235 +0,0 @@
package com.habitrpg.android.habitica.data.local.implementation;
import android.support.annotation.Nullable;
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 java.util.ArrayList;
import java.util.List;
import java.util.Map;
import io.realm.OrderedRealmCollectionSnapshot;
import io.realm.Realm;
import io.realm.RealmResults;
import io.realm.Sort;
import rx.Observable;
public class RealmTaskLocalRepository extends RealmBaseLocalRepository implements TaskLocalRepository {
public RealmTaskLocalRepository(Realm realm) {
super(realm);
}
@Override
public Observable<RealmResults<Task>> getTasks(String taskType, String userID) {
return realm.where(Task.class)
.equalTo("type", taskType)
.equalTo("userId", userID)
.findAllSorted("position")
.sort("dateCreated", Sort.DESCENDING)
.asObservable()
.filter(RealmResults::isLoaded)
.retry(1);
}
@Override
public Observable<RealmResults<Task>> getTasks(String userId) {
return realm.where(Task.class).equalTo("userId", userId).findAll().asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public void saveTasks(@Nullable String userId, TasksOrder tasksOrder, TaskList tasks) {
List<Task> sortedTasks = new ArrayList<>();
if (tasks != null) {
if (tasksOrder != null) {
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.getHabits()));
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.getDailys()));
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.getTodos()));
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.getRewards()));
} else {
sortedTasks.addAll(tasks.tasks.values());
}
}
if (userId != null) {
removeOldTasks(userId, sortedTasks);
List<ChecklistItem> allChecklistItems = new ArrayList<>();
for (Task t : sortedTasks) {
if (t.getChecklist() != null) {
allChecklistItems.addAll(t.getChecklist());
}
}
removeOldChecklists(allChecklistItems);
List<RemindersItem> allReminders = new ArrayList<>();
for (Task t : sortedTasks) {
if (t.getReminders() != null) {
allReminders.addAll(t.getReminders());
}
}
removeOldReminders(allReminders);
}
realm.executeTransactionAsync(realm1 -> realm1.insertOrUpdate(sortedTasks));
}
private List<Task> sortTasks(Map<String, Task> taskMap, List<String> taskOrder) {
List<Task> taskList = new ArrayList<>();
int position = 0;
for (String taskId : taskOrder) {
Task task = taskMap.get(taskId);
if (task != null) {
task.setPosition(position);
taskList.add(task);
position++;
taskMap.remove(taskId);
}
}
return taskList;
}
@Override
public void saveTask(Task task) {
realm.executeTransaction(realm1 -> realm1.insertOrUpdate(task));
}
private void removeOldTasks(String userID, List<Task> onlineTaskList) {
OrderedRealmCollectionSnapshot<Task> localTasks = realm.where(Task.class).equalTo("userId", userID).findAll().createSnapshot();
List<Task> tasksToDelete = new ArrayList<>();
for (Task localTask : localTasks) {
if (!onlineTaskList.contains(localTask)) {
tasksToDelete.add(localTask);
}
}
realm.executeTransaction(realm1 -> {
for (Task localTask : tasksToDelete) {
if (localTask.getChecklist() != null) {
localTask.getChecklist().deleteAllFromRealm();
}
if (localTask.getReminders() != null) {
localTask.getReminders().deleteAllFromRealm();
}
localTask.deleteFromRealm();
}
});
}
private void removeOldChecklists(List<ChecklistItem> onlineItems) {
OrderedRealmCollectionSnapshot<ChecklistItem> localItems = realm.where(ChecklistItem.class).findAll().createSnapshot();
List<ChecklistItem> itemsToDelete = new ArrayList<>();
for (ChecklistItem localItem : localItems) {
if (!onlineItems.contains(localItem)) {
itemsToDelete.add(localItem);
}
}
realm.executeTransaction(realm1 -> {
for (ChecklistItem item : itemsToDelete) {
item.deleteFromRealm();
}
});
}
private void removeOldReminders(List<RemindersItem> onlineReminders) {
OrderedRealmCollectionSnapshot<RemindersItem> localReminders = realm.where(RemindersItem.class).findAll().createSnapshot();
List<RemindersItem> itemsToDelete = new ArrayList<>();
for (RemindersItem localItem : localReminders) {
if (!onlineReminders.contains(localItem)) {
itemsToDelete.add(localItem);
}
}
realm.executeTransaction(realm1 -> {
for (RemindersItem item : itemsToDelete) {
item.deleteFromRealm();
}
});
}
@Override
public void deleteTask(String taskID) {
Task task = realm.where(Task.class).equalTo("id", taskID).findFirstAsync();
realm.executeTransaction(realm1 -> task.deleteFromRealm());
}
@Override
public Observable<Task> getTask(String taskId) {
return realm.where(Task.class).equalTo("id", taskId).findFirstAsync().asObservable()
.filter(realmObject -> realmObject.isLoaded())
.cast(Task.class);
}
@Override
public Observable<Task> getTaskCopy(String taskId) {
return getTask(taskId)
.map(task -> {
if (task.isManaged() && task.isValid()) {
return realm.copyFromRealm(task);
} else {
return task;
}
});
}
@Override
public void markTaskCompleted(String taskId, boolean isCompleted) {
Task task = realm.where(Task.class).equalTo("id", taskId).findFirstAsync();
realm.executeTransaction(realm1 -> task.setCompleted(true));
}
@Override
public void saveReminder(RemindersItem remindersItem) {
realm.executeTransaction(realm1 -> realm1.insertOrUpdate(remindersItem));
}
@Override
public void swapTaskPosition(int firstPosition, int secondPosition) {
Task firstTask = realm.where(Task.class).equalTo("position", firstPosition).findFirst();
Task secondTask = realm.where(Task.class).equalTo("position", secondPosition).findFirst();
if (firstTask != null && secondTask != null && firstTask.isValid() && secondTask.isValid()) {
realm.executeTransaction(realm1 -> {
firstTask.setPosition(secondPosition);
secondTask.setPosition(firstPosition);
});
}
}
@Override
public Observable<Task> getTaskAtPosition(int currentPosition) {
return realm.where(Task.class).equalTo("position", currentPosition).findFirstAsync().asObservable()
.filter(realmObject -> realmObject.isLoaded())
.cast(Task.class);
}
@Override
public Observable<TaskList> updateIsdue(TaskList dailies) {
return Observable.just(realm.where(Task.class).equalTo("type", "daily").findAll())
.first()
.map(tasks -> {
realm.beginTransaction();
for (Task task : tasks) {
if (dailies.tasks.containsKey(task.getId())) {
task.setDue(dailies.tasks.get(task.getId()).isDue());
}
}
realm.commitTransaction();
return dailies;
});
}
@Override
public void updateTaskPositions(List<String> taskOrder) {
if (taskOrder.size() > 0) {
RealmResults<Task> tasks = realm.where(Task.class).in("id", taskOrder.toArray(new String[0])).findAll();
realm.executeTransaction(realm1 -> {
for (Task task : tasks) {
if (taskOrder.contains(task.getId())) {
task.setPosition(taskOrder.indexOf(task.getId()));
}
}
});
}
}
}

View file

@ -0,0 +1,176 @@
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 java.util.ArrayList
import io.realm.Realm
import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.Sort
import rx.Observable
class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), TaskLocalRepository {
override fun getTasks(taskType: String, userID: String): Observable<RealmResults<Task>> {
return realm.where(Task::class.java)
.equalTo("type", taskType)
.equalTo("userId", userID)
.findAllSorted("position")
.sort("dateCreated", Sort.DESCENDING)
.asObservable()
.filter({ it.isLoaded })
.retry(1)
}
override fun getTasks(userId: String): Observable<RealmResults<Task>> {
return realm.where(Task::class.java).equalTo("userId", userId).findAll().asObservable()
.filter({ it.isLoaded })
}
override fun saveTasks(userId: String, tasksOrder: TasksOrder, tasks: TaskList) {
val sortedTasks = ArrayList<Task>()
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.habits))
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.dailys))
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.todos))
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.rewards))
removeOldTasks(userId, sortedTasks)
val allChecklistItems = ArrayList<ChecklistItem>()
for (t in sortedTasks) {
allChecklistItems.addAll(t.checklist)
}
removeOldChecklists(allChecklistItems)
val allReminders = ArrayList<RemindersItem>()
for (t in sortedTasks) {
allReminders.addAll(t.reminders)
}
removeOldReminders(allReminders)
realm.executeTransactionAsync { realm1 -> realm1.insertOrUpdate(sortedTasks) }
}
private fun sortTasks(taskMap: MutableMap<String, Task>, taskOrder: List<String>): List<Task> {
val taskList = ArrayList<Task>()
var position = 0
for (taskId in taskOrder) {
val task = taskMap[taskId]
if (task != null) {
task.position = position
taskList.add(task)
position++
taskMap.remove(taskId)
}
}
return taskList
}
override fun saveTask(task: Task) {
realm.executeTransaction { realm1 -> realm1.insertOrUpdate(task) }
}
private fun removeOldTasks(userID: String, onlineTaskList: List<Task>) {
val localTasks = realm.where(Task::class.java).equalTo("userId", userID).findAll().createSnapshot()
val tasksToDelete = localTasks.filterNot { onlineTaskList.contains(it) }
realm.executeTransaction {
for (localTask in tasksToDelete) {
localTask.checklist.deleteAllFromRealm()
localTask.reminders.deleteAllFromRealm()
localTask.deleteFromRealm()
}
}
}
private fun removeOldChecklists(onlineItems: List<ChecklistItem>) {
val localItems = realm.where(ChecklistItem::class.java).findAll().createSnapshot()
val itemsToDelete = localItems.filterNot { onlineItems.contains(it) }
realm.executeTransaction {
for (item in itemsToDelete) {
item.deleteFromRealm()
}
}
}
private fun removeOldReminders(onlineReminders: List<RemindersItem>) {
val localReminders = realm.where(RemindersItem::class.java).findAll().createSnapshot()
val itemsToDelete = localReminders.filterNot { onlineReminders.contains(it) }
realm.executeTransaction {
for (item in itemsToDelete) {
item.deleteFromRealm()
}
}
}
override fun deleteTask(taskID: String) {
val task = realm.where(Task::class.java).equalTo("id", taskID).findFirstAsync()
realm.executeTransaction { task.deleteFromRealm() }
}
override fun getTask(taskId: String): Observable<Task> {
return realm.where(Task::class.java).equalTo("id", taskId).findFirstAsync().asObservable<RealmObject>()
.filter { realmObject -> realmObject.isLoaded }
.cast(Task::class.java)
}
override fun getTaskCopy(taskId: String): Observable<Task> {
return getTask(taskId)
.map { task ->
if (task.isManaged && task.isValid) {
return@map realm.copyFromRealm<Task>(task)
} else {
return@map task
}
}
}
override fun markTaskCompleted(taskId: String, isCompleted: Boolean) {
val task = realm.where(Task::class.java).equalTo("id", taskId).findFirstAsync()
realm.executeTransaction { task.completed = true }
}
override fun saveReminder(remindersItem: RemindersItem) {
realm.executeTransaction { it.insertOrUpdate(remindersItem) }
}
override fun swapTaskPosition(firstPosition: Int, secondPosition: Int) {
val firstTask = realm.where(Task::class.java).equalTo("position", firstPosition).findFirst()
val secondTask = realm.where(Task::class.java).equalTo("position", secondPosition).findFirst()
if (firstTask != null && secondTask != null && firstTask.isValid && secondTask.isValid) {
realm.executeTransaction {
firstTask.position = secondPosition
secondTask.position = firstPosition
}
}
}
override fun getTaskAtPosition(currentPosition: Int): Observable<Task> {
return realm.where(Task::class.java).equalTo("position", currentPosition).findFirstAsync().asObservable<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()
.map { tasks ->
realm.beginTransaction()
tasks.filter { daily.tasks.containsKey(it.id) }.forEach { it.isDue = daily.tasks[it.id]?.isDue }
realm.commitTransaction()
daily
}
}
override fun updateTaskPositions(taskOrder: List<String>) {
if (taskOrder.isNotEmpty()) {
val tasks = realm.where(Task::class.java).`in`("id", taskOrder.toTypedArray()).findAll()
realm.executeTransaction {
tasks.filter { taskOrder.contains(it.id) }.forEach { it.position = taskOrder.indexOf(it.id) }
}
}
}
}

View file

@ -1,37 +0,0 @@
package com.habitrpg.android.habitica.data.local.implementation;
import com.habitrpg.android.habitica.data.local.TutorialLocalRepository;
import com.habitrpg.android.habitica.models.TutorialStep;
import java.util.List;
import io.realm.Realm;
import io.realm.RealmResults;
import rx.Observable;
public class RealmTutorialLocalRepository extends RealmBaseLocalRepository implements TutorialLocalRepository {
public RealmTutorialLocalRepository(Realm realm) {
super(realm);
}
@Override
public Observable<TutorialStep> getTutorialStep(String key) {
return realm.where(TutorialStep.class).equalTo("identifier", key)
.findAllAsync()
.asObservable()
.filter(realmObject -> realmObject.isLoaded() && realmObject.isValid() && !realmObject.isEmpty())
.map(steps -> steps.first())
.cast(TutorialStep.class);
}
@Override
public Observable<RealmResults<TutorialStep>> getTutorialSteps(List<String> keys) {
return realm.where(TutorialStep.class)
.in("identifier", (String[]) keys.toArray())
.findAll()
.asObservable()
.filter(RealmResults::isLoaded);
}
}

View file

@ -0,0 +1,30 @@
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.realm.Realm
import io.realm.RealmResults
import rx.Observable
import rx.functions.Func1
class RealmTutorialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), TutorialLocalRepository {
override fun getTutorialStep(key: String): Observable<TutorialStep> {
return realm.where(TutorialStep::class.java).equalTo("identifier", key)
.findAllAsync()
.asObservable()
.filter { realmObject -> realmObject.isLoaded && realmObject.isValid && !realmObject.isEmpty() }
.map { steps -> steps.first() }
.cast(TutorialStep::class.java)
}
override fun getTutorialSteps(keys: List<String>): Observable<RealmResults<TutorialStep>> {
return realm.where(TutorialStep::class.java)
.`in`("identifier", keys.toTypedArray())
.findAll()
.asObservable()
.filter({ it.isLoaded })
}
}

View file

@ -1,127 +0,0 @@
package com.habitrpg.android.habitica.data.local.implementation;
import com.habitrpg.android.habitica.data.local.UserLocalRepository;
import com.habitrpg.android.habitica.models.Skill;
import com.habitrpg.android.habitica.models.Tag;
import com.habitrpg.android.habitica.models.TutorialStep;
import com.habitrpg.android.habitica.models.social.ChatMessage;
import com.habitrpg.android.habitica.models.user.SpecialItems;
import com.habitrpg.android.habitica.models.user.User;
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 RealmUserLocalRepository extends RealmBaseLocalRepository implements UserLocalRepository {
public RealmUserLocalRepository(Realm realm) {
super(realm);
}
@Override
public Observable<User> getUser(String userID) {
return realm.where(User.class)
.equalTo("id", userID)
.findAll()
.asObservable()
.filter(realmObject -> realmObject.isLoaded() && realmObject.isValid() && !realmObject.isEmpty())
.map(users -> users.first());
}
@Override
public void saveUser(User user) {
realm.executeTransaction(realm1 -> realm1.insertOrUpdate(user));
if (user.getTags() != null) {
removeOldTags(user.getId(), user.getTags());
}
}
private void removeOldTags(String userId, List<Tag> onlineTags) {
OrderedRealmCollectionSnapshot<Tag> tags = realm.where(Tag.class).equalTo("userId", userId).findAll().createSnapshot();
List<Tag> tagsToDelete = new ArrayList<>();
for (Tag tag : tags) {
if (!onlineTags.contains(tag)) {
tagsToDelete.add(tag);
}
}
realm.executeTransaction(realm1 -> {
for (Tag tag : tagsToDelete) {
tag.deleteFromRealm();
}
});
}
@Override
public Observable<RealmResults<TutorialStep>> getTutorialSteps() {
return realm.where(TutorialStep.class).findAll().asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public Observable<RealmResults<Skill>> getSkills(User user) {
return realm.where(Skill.class)
.equalTo("habitClass", user.getStats().getHabitClass())
.lessThanOrEqualTo("lvl", user.getStats().lvl)
.findAll()
.asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public Observable<RealmResults<Skill>> getSpecialItems(User user) {
SpecialItems specialItems = user.getItems().getSpecial();
List<String> ownedItems = new ArrayList<>();
if (specialItems != null) {
if (specialItems.getSnowball() > 0) {
ownedItems.add("snowball");
}
if (specialItems.getShinySeed() > 0) {
ownedItems.add("shinySeed");
}
if (specialItems.getSeafoam() > 0) {
ownedItems.add("seafoam");
}
if (specialItems.getSpookySparkles() > 0) {
ownedItems.add("spookySparkles");
}
}
if (ownedItems.size() == 0) {
ownedItems.add("");
}
return realm.where(Skill.class)
.in("key", ownedItems.toArray(new String[0]))
.findAll()
.asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public Observable<RealmResults<ChatMessage>> getInboxMessages(String userId, String replyToUserID) {
return realm.where(ChatMessage.class)
.equalTo("isInboxMessage", true)
.equalTo("uuid", replyToUserID)
.findAllSorted("timestamp", Sort.DESCENDING)
.asObservable()
.filter(RealmResults::isLoaded);
}
@Override
public Observable<RealmResults<ChatMessage>> getInboxOverviewList(String userId) {
return realm.where(ChatMessage.class)
.equalTo("isInboxMessage", true)
.distinct("uuid")
.sort("timestamp", Sort.DESCENDING)
.asObservable()
.filter(RealmResults::isLoaded);
}
}

View file

@ -0,0 +1,99 @@
package com.habitrpg.android.habitica.data.local.implementation
import com.habitrpg.android.habitica.data.local.UserLocalRepository
import com.habitrpg.android.habitica.models.Skill
import com.habitrpg.android.habitica.models.Tag
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.realm.Realm
import io.realm.RealmResults
import io.realm.Sort
import rx.Observable
class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), UserLocalRepository {
override val tutorialSteps: Observable<RealmResults<TutorialStep>>
get() = realm.where(TutorialStep::class.java).findAll().asObservable()
.filter({ it.isLoaded })
override fun getUser(userID: String): Observable<User> {
return realm.where(User::class.java)
.equalTo("id", userID)
.findAll()
.asObservable()
.filter { realmObject -> realmObject.isLoaded && realmObject.isValid && !realmObject.isEmpty() }
.map { users -> users.first() }
}
override fun saveUser(user: User) {
realm.executeTransaction { realm1 -> realm1.insertOrUpdate(user) }
if (user.tags != null) {
removeOldTags(user.id, user.tags)
}
}
private fun removeOldTags(userId: String, onlineTags: List<Tag>) {
val tags = realm.where(Tag::class.java).equalTo("userId", userId).findAll().createSnapshot()
val tagsToDelete = tags.filterNot { onlineTags.contains(it) }
realm.executeTransaction {
for (tag in tagsToDelete) {
tag.deleteFromRealm()
}
}
}
override fun getSkills(user: User): Observable<RealmResults<Skill>> {
return realm.where(Skill::class.java)
.equalTo("habitClass", user.stats.getHabitClass())
.lessThanOrEqualTo("lvl", user.stats.lvl)
.findAll()
.asObservable()
.filter({ it.isLoaded })
}
override fun getSpecialItems(user: User): Observable<RealmResults<Skill>> {
val specialItems = user.items.special
val ownedItems = ArrayList<String>()
if (specialItems != null) {
if (specialItems.snowball > 0) {
ownedItems.add("snowball")
}
if (specialItems.shinySeed > 0) {
ownedItems.add("shinySeed")
}
if (specialItems.seafoam > 0) {
ownedItems.add("seafoam")
}
if (specialItems.spookySparkles > 0) {
ownedItems.add("spookySparkles")
}
}
if (ownedItems.size == 0) {
ownedItems.add("")
}
return realm.where(Skill::class.java)
.`in`("key", ownedItems.toTypedArray())
.findAll()
.asObservable()
.filter({ it.isLoaded })
}
override fun getInboxMessages(userId: String, replyToUserID: String): Observable<RealmResults<ChatMessage>> {
return realm.where(ChatMessage::class.java)
.equalTo("isInboxMessage", true)
.equalTo("uuid", replyToUserID)
.findAllSorted("timestamp", Sort.DESCENDING)
.asObservable()
.filter({ it.isLoaded })
}
override fun getInboxOverviewList(userId: String): Observable<RealmResults<ChatMessage>> {
return realm.where(ChatMessage::class.java)
.equalTo("isInboxMessage", true)
.distinct("uuid")
.sort("timestamp", Sort.DESCENDING)
.asObservable()
.filter({ it.isLoaded })
}
}

View file

@ -54,13 +54,15 @@ class ProfilePreferencesFragment: BasePreferencesFragment(), SharedPreferences.O
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
val profileCategory = findPreference("profile") as? PreferenceCategory
configurePreference(profileCategory?.findPreference(key), sharedPreferences?.getString(key, ""))
val observable: Observable<User>? = when (key) {
"display_name" -> userRepository.updateUser(user, "profile.name", sharedPreferences?.getString(key, ""))
"photo_url" -> userRepository.updateUser(user, "profile.photo", sharedPreferences?.getString(key, ""))
"about" -> userRepository.updateUser(user, "profile.blurb", sharedPreferences?.getString(key, ""))
else -> null
if (sharedPreferences != null) {
val observable: Observable<User>? = when (key) {
"display_name" -> userRepository.updateUser(user, "profile.name", sharedPreferences.getString(key, ""))
"photo_url" -> userRepository.updateUser(user, "profile.photo", sharedPreferences.getString(key, ""))
"about" -> userRepository.updateUser(user, "profile.blurb", sharedPreferences.getString(key, ""))
else -> null
}
observable?.subscribe(Action1 {}, RxErrorHandler.handleEmptyError())
}
observable?.subscribe(Action1 {}, RxErrorHandler.handleEmptyError())
}
}

View file

@ -74,7 +74,7 @@ class BulkAllocateStatsDialog(context: Context, component: AppComponent) : Alert
private fun saveChanges() {
val progressDialog = ProgressDialog.show(context, context.getString(R.string.allocating_points), null, true)
userRepository.bulkAllocatePoints(strengthSliderView.currentValue, intelligenceSliderView.currentValue, constitutionSliderView.currentValue, perceptionSliderView.currentValue)
userRepository.bulkAllocatePoints(user, strengthSliderView.currentValue, intelligenceSliderView.currentValue, constitutionSliderView.currentValue, perceptionSliderView.currentValue)
.subscribe({
progressDialog.dismiss()
this.dismiss()