Start refactoring Tasks to realm

This commit is contained in:
Phillip Thelen 2017-04-20 21:10:05 +02:00 committed by
parent f5ad6488bc
commit d80359dbdb
51 changed files with 619 additions and 1223 deletions

View file

@ -3,6 +3,7 @@ apply plugin: 'com.android.databinding'
apply plugin: 'io.fabric'
apply plugin: 'com.neenbedankt.android-apt'
apply plugin: 'com.noveogroup.android.check'
apply plugin: 'realm-android'
buildscript {
repositories {
@ -149,6 +150,8 @@ dependencies {
compile 'com.roughike:bottom-bar:2.2.0'
compile 'io.realm:android-adapters:2.0.0'
compile(project(':seeds-sdk')) {
exclude group: 'com.google.android.gms'
exclude group: 'com.android.support', module: 'multidex'

View file

@ -41,6 +41,8 @@ import java.lang.reflect.Field;
import javax.inject.Inject;
import dagger.Lazy;
import io.realm.Realm;
import io.realm.RealmConfiguration;
//contains all HabiticaApplicationLogic except dagger componentInitialisation
public abstract class HabiticaBaseApplication extends MultiDexApplication {
@ -129,6 +131,7 @@ public abstract class HabiticaBaseApplication extends MultiDexApplication {
// You should not init your app in this process.
return;
}
setupRealm();
setupDagger();
crashlyticsProxy.init(this);
setupLeakCanary();
@ -149,6 +152,16 @@ public abstract class HabiticaBaseApplication extends MultiDexApplication {
checkIfNewVersion();
}
protected void setupRealm() {
Realm.init(this);
RealmConfiguration.Builder builder = new RealmConfiguration.Builder()
.schemaVersion(1);
if (BuildConfig.DEBUG) {
builder = builder.deleteRealmIfMigrationNeeded();
}
Realm.setDefaultConfiguration(builder.build());
}
private void checkIfNewVersion() {
PackageInfo info = null;
try {

View file

@ -21,7 +21,6 @@ public class HabitRPGUserCallback implements Action1<HabitRPGUser> {
@Override
public void call(HabitRPGUser user) {
// Negue: once everything is refactored to DbFlowTaskLocalRepository, this will be removed
user.async().save();
if (callBack != null) {
callBack.onUserReceived(user);

View file

@ -27,15 +27,7 @@ public class TaskScoringCallback implements Action1<TaskDirectionData> {
@Override
public void call(TaskDirectionData taskDirectionData) {
taskRepository.getTask(taskId).subscribe(task -> {
if (task != null && task.type != null && !task.type.equals("reward")) {
task.value = task.value + taskDirectionData.getDelta();
taskRepository.saveTask(task);
}
mCallback.onTaskDataReceived(taskDirectionData, task);
});
taskRepository.getTask(taskId).first().subscribe(task -> mCallback.onTaskDataReceived(taskDirectionData, task));
if (taskDirectionData.get_tmp() != null) {
if (taskDirectionData.get_tmp().getDrop() != null) {
String type = taskDirectionData.get_tmp().getDrop().getType();

View file

@ -14,8 +14,6 @@ public class TaskUpdateCallback implements Action1<Task> {
@Override
public void call(Task task) {
task.save();
EventBus.getDefault().post(new TaskUpdatedEvent(task));
}
}

View file

@ -5,11 +5,12 @@ 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<List<Tag>> getTags(String userId);
Observable<RealmResults<Tag>> getTags(String userId);
Observable<Tag> createTag(Tag tag);
Observable<Tag> updateTag(Tag tag);

View file

@ -10,18 +10,22 @@ import com.habitrpg.android.habitica.models.tasks.TasksOrder;
import java.util.List;
import io.realm.Realm;
import io.realm.RealmResults;
import rx.Observable;
public interface TaskRepository extends BaseRepository {
Observable<List<Task>> getTasks(String taskType, String userID);
Observable<List<Task>> getTasks(String userId);
Observable<RealmResults<Task>> getTasks(String taskType, String userID);
Observable<RealmResults<Task>> getTasks(String userId);
Observable<TaskList> refreshTasks(TasksOrder tasksOrder);
Observable<TaskDirectionData> taskChecked(Task task, boolean up);
Observable<TaskDirectionData> taskChecked(String taskId, boolean up);
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);
@ -34,7 +38,9 @@ public interface TaskRepository extends BaseRepository {
void removeOldTaskTags(List<TaskTag> onlineTaskTags);
void removeOldReminders(List<RemindersItem> onlineReminders);
Observable<TaskDirectionData> postTaskDirection(String taskId, String direction);
void markTaskCompleted(String taskId, boolean isCompleted);
void saveReminder(RemindersItem remindersItem);
void executeTransaction(Realm.Transaction transaction);
}

View file

@ -103,6 +103,8 @@ import java.util.Map;
import javax.net.ssl.SSLException;
import io.realm.Realm;
import io.realm.RealmList;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.ResponseBody;
@ -204,7 +206,7 @@ public class ApiClientImpl implements Action1<Throwable>, ApiClient {
}
public static GsonConverterFactory createGsonFactory() {
Type taskTagClassListType = new TypeToken<List<TaskTag>>() {
Type taskTagClassListType = new TypeToken<RealmList<TaskTag>>() {
}.getType();
Type skillListType = new TypeToken<List<Skill>>() {
}.getType();
@ -354,29 +356,13 @@ public class ApiClientImpl implements Action1<Throwable>, ApiClient {
userObservable = Observable.zip(userObservable, tasksObservable,
(habitRPGUser, tasks) -> {
List<Task> sortedTasks = new ArrayList<>();
sortedTasks.addAll(sortTasks(tasks.tasks, habitRPGUser.getTasksOrder().getHabits()));
sortedTasks.addAll(sortTasks(tasks.tasks, habitRPGUser.getTasksOrder().getDailys()));
sortedTasks.addAll(sortTasks(tasks.tasks, habitRPGUser.getTasksOrder().getTodos()));
sortedTasks.addAll(sortTasks(tasks.tasks, habitRPGUser.getTasksOrder().getRewards()));
habitRPGUser.setHabits(sortTasks(tasks.tasks, habitRPGUser.getTasksOrder().getHabits()));
habitRPGUser.setDailys(sortTasks(tasks.tasks, habitRPGUser.getTasksOrder().getDailys()));
habitRPGUser.setTodos(sortTasks(tasks.tasks, habitRPGUser.getTasksOrder().getTodos()));
habitRPGUser.setRewards(sortTasks(tasks.tasks, habitRPGUser.getTasksOrder().getRewards()));
for (Task task : tasks.tasks.values()) {
switch (task.getType()) {
case Task.TYPE_HABIT:
habitRPGUser.getHabits().add(task);
break;
case Task.TYPE_DAILY:
habitRPGUser.getDailys().add(task);
break;
case Task.TYPE_TODO:
habitRPGUser.getTodos().add(task);
break;
case Task.TYPE_REWARD:
habitRPGUser.getRewards().add(task);
break;
default:
break;
}
}
Realm.getDefaultInstance().executeTransactionAsync(realm -> realm.copyToRealmOrUpdate(sortedTasks));
return habitRPGUser;
});

View file

@ -8,6 +8,7 @@ import com.habitrpg.android.habitica.models.Tag;
import java.util.Collection;
import java.util.List;
import io.realm.RealmResults;
import rx.Observable;
@ -18,7 +19,7 @@ public class TagRepositoryImpl extends BaseRepositoryImpl<TagLocalRepository> im
}
@Override
public Observable<List<Tag>> getTags(String userId) {
public Observable<RealmResults<Tag>> getTags(String userId) {
return localRepository.getTags(userId);
}

View file

@ -19,6 +19,8 @@ import org.greenrobot.eventbus.EventBus;
import java.util.Date;
import java.util.List;
import io.realm.Realm;
import io.realm.RealmResults;
import rx.Observable;
@ -31,12 +33,12 @@ public class TaskRepositoryImpl extends BaseRepositoryImpl<TaskLocalRepository>
}
@Override
public Observable<List<Task>> getTasks(String taskType, String userID) {
public Observable<RealmResults<Task>> getTasks(String taskType, String userID) {
return this.localRepository.getTasks(taskType, userID);
}
@Override
public Observable<List<Task>> getTasks(String userId) {
public Observable<RealmResults<Task>> getTasks(String userId) {
return this.localRepository.getTasks(userId);
}
@ -57,15 +59,26 @@ public class TaskRepositoryImpl extends BaseRepositoryImpl<TaskLocalRepository>
.doOnNext(res -> {
// save local task changes
if (task.type != null && !task.type.equals("reward")) {
task.value = task.value + res.getDelta();
this.localRepository.saveTask(task);
this.localRepository.executeTransaction(realm -> {
task.value = task.value + res.getDelta();
if (Task.TYPE_DAILY.equals(task.type) || Task.TYPE_TODO.equals(task.type)) {
task.completed = up;
}
});
}
});
}
@Override
public Observable<TaskDirectionData> taskChecked(String taskId, boolean up) {
return localRepository.getTask(taskId)
.flatMap(task -> taskChecked(task, up));
}
public Observable<Task> scoreChecklistItem(String taskId, String itemId){
return apiClient.scoreChecklistItem(taskId, itemId).doOnNext(this.localRepository::saveTask);
return apiClient.scoreChecklistItem(taskId, itemId)
.doOnNext(this.localRepository::saveTask);
}
@Override
@ -73,6 +86,11 @@ public class TaskRepositoryImpl extends BaseRepositoryImpl<TaskLocalRepository>
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();
@ -81,10 +99,7 @@ public class TaskRepositoryImpl extends BaseRepositoryImpl<TaskLocalRepository>
}
lastTaskAction = now;
return apiClient.createItem(task)
.doOnNext(task1 -> {
localRepository.saveTask(task1);
EventBus.getDefault().post(new TaskCreatedEvent(task1));
});
.doOnNext(localRepository::saveTask);
}
@Override
@ -95,10 +110,7 @@ public class TaskRepositoryImpl extends BaseRepositoryImpl<TaskLocalRepository>
}
lastTaskAction = now;
return apiClient.updateTask(task.getId(), task)
.doOnNext(task1 -> {
localRepository.saveTask(task1);
EventBus.getDefault().post(new TaskUpdatedEvent(task1));
});
.doOnNext(localRepository::saveTask);
}
@Override
@ -137,13 +149,18 @@ public class TaskRepositoryImpl extends BaseRepositoryImpl<TaskLocalRepository>
localRepository.removeOldReminders(onlineReminders);
}
@Override
public Observable<TaskDirectionData> postTaskDirection(String taskId, String direction) {
return apiClient.postTaskDirection(taskId, direction);
}
@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);
}
}

View file

@ -1,6 +1,10 @@
package com.habitrpg.android.habitica.data.local;
import io.realm.Realm;
public interface BaseLocalRepository {
void close();
void executeTransaction(Realm.Transaction transaction);
}

View file

@ -4,10 +4,11 @@ import com.habitrpg.android.habitica.models.Tag;
import java.util.List;
import io.realm.RealmResults;
import rx.Observable;
public interface TagLocalRepository extends BaseLocalRepository {
Observable<List<Tag>> getTags(String userId);
Observable<RealmResults<Tag>> getTags(String userId);
void removeOldTags(List<Tag> onlineTags);
}

View file

@ -9,12 +9,13 @@ 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<List<Task>> getTasks(String taskType, String userID);
Observable<List<Task>> getTasks(String userId);
Observable<RealmResults<Task>> getTasks(String taskType, String userID);
Observable<RealmResults<Task>> getTasks(String userId);
void saveTasks(TasksOrder tasksOrder, TaskList tasks);
@ -28,6 +29,9 @@ public interface TaskLocalRepository extends BaseLocalRepository {
void deleteTask(String taskID);
Observable<Task> getTask(String taskId);
Observable<Task> getTaskCopy(String taskId);
void markTaskCompleted(String taskId, boolean isCompleted);
void saveReminder(RemindersItem remindersItem);
}

View file

@ -10,6 +10,7 @@ import com.raizlabs.android.dbflow.sql.language.Where;
import java.util.Date;
import java.util.List;
import io.realm.Realm;
import rx.Observable;
public class DbFlowCustomizationLocalRepository implements CustomizationLocalRepository {
@ -18,6 +19,11 @@ public class DbFlowCustomizationLocalRepository implements CustomizationLocalRep
}
@Override
public void executeTransaction(Realm.Transaction transaction) {
}
@Override
public Observable<List<Customization>> getCustomizations(String type, String category) {
return Observable.defer(() -> {

View file

@ -6,6 +6,7 @@ import com.raizlabs.android.dbflow.sql.language.Select;
import java.util.List;
import io.realm.Realm;
import rx.Observable;
public class DbFlowFAQLocalRepository implements FAQLocalRepository {
@ -14,6 +15,11 @@ public class DbFlowFAQLocalRepository implements FAQLocalRepository {
}
@Override
public void executeTransaction(Realm.Transaction transaction) {
}
@Override
public Observable<List<FAQArticle>> getArticles() {
return Observable.defer(() -> Observable.just(new Select().from(FAQArticle.class).queryList()));

View file

@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import io.realm.Realm;
import rx.Observable;
public class DbFlowInventoryLocalRepository implements InventoryLocalRepository {
@ -34,6 +35,11 @@ public class DbFlowInventoryLocalRepository implements InventoryLocalRepository
}
@Override
public void executeTransaction(Realm.Transaction transaction) {
}
@Override
public Observable<QuestContent> getQuestContent(String key) {
return Observable.defer(() -> Observable.just(new Select().from(QuestContent.class).querySingle()))

View file

@ -7,6 +7,7 @@ import com.raizlabs.android.dbflow.sql.language.Select;
import java.util.List;
import io.realm.Realm;
import rx.Observable;
@ -16,6 +17,11 @@ public class DbFlowSocialLocalRepository implements SocialLocalRepository {
}
@Override
public void executeTransaction(Realm.Transaction transaction) {
}
@Override
public Observable<Challenge> getChallenge(String challengeId) {
return Observable.defer(() -> Observable.just(new Select().from(Challenge.class).where(Condition.column("id").eq(challengeId)).querySingle()));
@ -31,7 +37,7 @@ public class DbFlowSocialLocalRepository implements SocialLocalRepository {
return Observable.defer(() -> Observable.just(new Select()
.from(Challenge.class)
.where(Condition.column("name").isNotNull())
.and(Condition.column("user_id").is(userId))
.and(Condition.column("userId").is(userId))
.queryList()));
}
}

View file

@ -1,79 +0,0 @@
package com.habitrpg.android.habitica.data.local.implementation;
import android.database.sqlite.SQLiteDoneException;
import com.habitrpg.android.habitica.data.local.TagLocalRepository;
import com.habitrpg.android.habitica.models.Tag;
import com.raizlabs.android.dbflow.runtime.transaction.BaseTransaction;
import com.raizlabs.android.dbflow.runtime.transaction.TransactionListener;
import com.raizlabs.android.dbflow.sql.builder.Condition;
import com.raizlabs.android.dbflow.sql.language.From;
import com.raizlabs.android.dbflow.sql.language.OrderBy;
import com.raizlabs.android.dbflow.sql.language.Select;
import java.util.ArrayList;
import java.util.List;
import rx.Observable;
public class DbFlowTagLocalRepository implements TagLocalRepository {
@Override
public void close() {
}
@Override
public Observable<List<Tag>> getTags(String userId) {
return Observable.defer(() -> Observable.just(new Select().from(Tag.class)
.where(Condition.column("user_id").eq(userId))
.orderBy(OrderBy.columns("position", "dateCreated").descending())
.queryList()));
}
@Override
public void removeOldTags(List<Tag> onlineTags) {
final ArrayList<String> onlineTaskTagItemIdList = new ArrayList<>();
for (Tag item : onlineTags) {
onlineTaskTagItemIdList.add(item.getId());
}
From<Tag> query = new Select().from(Tag.class);
try {
if (query.count() != onlineTags.size()) {
// Load Database Checklist items
query.async().queryList(new TransactionListener<List<Tag>>() {
@Override
public void onResultReceived(List<Tag> items) {
ArrayList<Tag> tagsToDelete = new ArrayList<>();
for (Tag tag : items) {
if (!onlineTaskTagItemIdList.contains(tag.getId())) {
tagsToDelete.add(tag);
}
}
for (Tag tag : tagsToDelete) {
tag.async().delete();
}
}
@Override
public boolean onReady(BaseTransaction<List<Tag>> baseTransaction) {
return false;
}
@Override
public boolean hasResult(BaseTransaction<List<Tag>> transaction, List<Tag> result) {
return result != null && result.size() > 0;
}
});
}
} catch (SQLiteDoneException ignored) {
//Ignored
}
}
}

View file

@ -1,313 +0,0 @@
package com.habitrpg.android.habitica.data.local.implementation;
import android.database.sqlite.SQLiteDoneException;
import com.habitrpg.android.habitica.data.local.TaskLocalRepository;
import com.habitrpg.android.habitica.events.TaskRemovedEvent;
import com.habitrpg.android.habitica.models.tasks.ChecklistItem;
import com.habitrpg.android.habitica.models.tasks.Days;
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.raizlabs.android.dbflow.runtime.transaction.BaseTransaction;
import com.raizlabs.android.dbflow.runtime.transaction.TransactionListener;
import com.raizlabs.android.dbflow.sql.builder.Condition;
import com.raizlabs.android.dbflow.sql.language.Delete;
import com.raizlabs.android.dbflow.sql.language.From;
import com.raizlabs.android.dbflow.sql.language.OrderBy;
import com.raizlabs.android.dbflow.sql.language.Select;
import com.raizlabs.android.dbflow.sql.language.Where;
import org.greenrobot.eventbus.EventBus;
import java.util.ArrayList;
import java.util.List;
import rx.Observable;
public class DbFlowTaskLocalRepository implements TaskLocalRepository {
@Override
public Observable<List<Task>> getTasks(String taskType, String userID) {
return Observable.defer(() -> Observable.just(new Select().from(Task.class)
.where(Condition.column("type").eq(taskType))
.and(Condition.CombinedCondition
.begin(Condition.column("completed").eq(false))
.or(Condition.column("type").eq("daily"))
)
.and(Condition.column("user_id").eq(userID))
.orderBy(OrderBy.columns("position", "dateCreated").descending())
.queryList()));
}
@Override
public Observable<List<Task>> getTasks(String userId) {
return Observable.defer(() -> Observable.just(new Select().from(Task.class)
.where(Condition.column("user_id").eq(userId))
.and(Condition.CombinedCondition
.begin(Condition.column("completed").eq(false))
.or(Condition.column("type").eq("daily"))
)
.orderBy(OrderBy.columns("position", "dateCreated").descending())
.queryList())); }
public Observable<Task> getTask(String taskID) {
return Observable.defer(() -> Observable.just(new Select().from(Task.class)
.where(Condition.column("id").eq(taskID))
.querySingle()));
}
@Override
public void markTaskCompleted(String taskId, boolean isCompleted) {
getTask(taskId).subscribe(task -> {
task.completed = isCompleted;
saveTask(task);
}, throwable -> {});
}
@Override
public void saveTasks(TasksOrder tasksOrder, TaskList tasks) {
sortTasks(tasks, tasksOrder.getHabits());
sortTasks(tasks, tasksOrder.getDailys());
sortTasks(tasks, tasksOrder.getTodos());
sortTasks(tasks, tasksOrder.getRewards());
// Negue: once everything is refactored to DbFlowTaskLocalRepository, this will be used to save the tasks
// not in HabitRPGUserCallback
/*
for (Task t : tasks){
t.async().save();
}
*/
}
@Override
public void saveTask(Task task) {
task.async().save();
}
@Override
public void removeOldTasks(String userID, List<Task> onlineTaskList) {
final ArrayList<String> onlineTaskIdList = new ArrayList<>();
for (Task oTask : onlineTaskList) {
onlineTaskIdList.add(oTask.getId());
}
Where<Task> query = new Select().from(Task.class).where(Condition.column("user_id").eq(userID));
try {
if (query.count() != onlineTaskList.size()) {
// Load Database Tasks
query.async().queryList(new TransactionListener<List<Task>>() {
@Override
public void onResultReceived(List<Task> tasks) {
ArrayList<Task> tasksToDelete = new ArrayList<>();
for (Task dbTask : tasks) {
if (!onlineTaskIdList.contains(dbTask.getId())) {
tasksToDelete.add(dbTask);
}
}
for (Task delTask : tasksToDelete) {
// TaskTag
new Delete().from(TaskTag.class).where(Condition.column("task_id").eq(delTask.getId())).async().execute();
// ChecklistItem
new Delete().from(ChecklistItem.class).where(Condition.column("task_id").eq(delTask.getId())).async().execute();
// Days
new Delete().from(Days.class).where(Condition.column("task_id").eq(delTask.getId())).async().execute();
// TASK
delTask.async().delete();
EventBus.getDefault().post(new TaskRemovedEvent(delTask.getId()));
}
}
@Override
public boolean onReady(BaseTransaction<List<Task>> baseTransaction) {
return false;
}
@Override
public boolean hasResult(BaseTransaction<List<Task>> baseTransaction, List<Task> tasks) {
return tasks != null && tasks.size() > 0;
}
});
}
} catch (SQLiteDoneException ignored) {
//Ignored
}
}
@Override
public void removeOldChecklists(List<ChecklistItem> onlineChecklistItems) {
final ArrayList<String> onlineChecklistItemIdList = new ArrayList<>();
for (ChecklistItem item : onlineChecklistItems) {
onlineChecklistItemIdList.add(item.getId());
}
From<ChecklistItem> query = new Select().from(ChecklistItem.class);
try {
if (query.count() != onlineChecklistItems.size()) {
// Load Database Checklist items
query.async().queryList(new TransactionListener<List<ChecklistItem>>() {
@Override
public void onResultReceived(List<ChecklistItem> items) {
ArrayList<ChecklistItem> checkListItemsToDelete = new ArrayList<>();
for (ChecklistItem chItem : items) {
if (!onlineChecklistItemIdList.contains(chItem.getId())) {
checkListItemsToDelete.add(chItem);
}
}
for (ChecklistItem chItem : checkListItemsToDelete) {
chItem.async().delete();
}
}
@Override
public boolean onReady(BaseTransaction<List<ChecklistItem>> baseTransaction) {
return false;
}
@Override
public boolean hasResult(BaseTransaction<List<ChecklistItem>> baseTransaction, List<ChecklistItem> items) {
return items != null && items.size() > 0;
}
});
}
} catch (SQLiteDoneException ignored) {
//Ignored
}
}
@Override
public void removeOldTaskTags(List<TaskTag> onlineTaskTags) {
final ArrayList<String> onlineTaskTagItemIdList = new ArrayList<>();
for (TaskTag item : onlineTaskTags) {
onlineTaskTagItemIdList.add(item.getId());
}
From<TaskTag> query = new Select().from(TaskTag.class);
try {
if (query.count() != onlineTaskTags.size()) {
// Load Database Checklist items
query.async().queryList(new TransactionListener<List<TaskTag>>() {
@Override
public void onResultReceived(List<TaskTag> items) {
ArrayList<TaskTag> checkListItemsToDelete = new ArrayList<>();
for (TaskTag ttag : items) {
if (!onlineTaskTagItemIdList.contains(ttag.getId())) {
checkListItemsToDelete.add(ttag);
}
}
for (TaskTag ttag : checkListItemsToDelete) {
ttag.async().delete();
}
}
@Override
public boolean onReady(BaseTransaction<List<TaskTag>> baseTransaction) {
return false;
}
@Override
public boolean hasResult(BaseTransaction<List<TaskTag>> baseTransaction, List<TaskTag> items) {
return items != null && items.size() > 0;
}
});
}
} catch (SQLiteDoneException ignored) {
//Ignored
}
}
@Override
public void removeOldReminders(List<RemindersItem> onlineReminders) {
final ArrayList<String> onlineReminderIds = new ArrayList<>();
for (RemindersItem item : onlineReminders) {
onlineReminderIds.add(item.getId());
}
From<RemindersItem> query = new Select().from(RemindersItem.class);
try {
if (query.count() != onlineReminders.size()) {
// Load Database Checklist items
query.async().queryList(new TransactionListener<List<RemindersItem>>() {
@Override
public void onResultReceived(List<RemindersItem> items) {
ArrayList<RemindersItem> remindersToDelete = new ArrayList<>();
for (RemindersItem reminder : items) {
if (!onlineReminderIds.contains(reminder.getId())) {
remindersToDelete.add(reminder);
}
}
for (RemindersItem reminder : remindersToDelete) {
reminder.async().delete();
}
}
@Override
public boolean onReady(BaseTransaction<List<RemindersItem>> baseTransaction) {
return false;
}
@Override
public boolean hasResult(BaseTransaction<List<RemindersItem>> baseTransaction, List<RemindersItem> items) {
return items != null && items.size() > 0;
}
});
}
} catch (SQLiteDoneException ignored) {
//Ignored
}
}
@Override
public void deleteTask(String taskID) {
getTask(taskID).subscribe(Task::delete, throwable -> {});
}
private List<Task> sortTasks(TaskList taskList, List<String> taskOrder) {
List<Task> taskResult = new ArrayList<>();
int position = 0;
for (String taskId : taskOrder) {
Task task = taskList.tasks.get(taskId);
if (task != null) {
task.position = position;
taskResult.add(task);
position++;
taskList.tasks.remove(taskId);
}
}
return taskResult;
}
@Override
public void close() {
}
}

View file

@ -7,6 +7,7 @@ import com.raizlabs.android.dbflow.sql.language.Select;
import java.util.List;
import io.realm.Realm;
import rx.Observable;
public class DbFlowTutorialLocalRepository implements TutorialLocalRepository {
@ -15,6 +16,11 @@ public class DbFlowTutorialLocalRepository implements TutorialLocalRepository {
}
@Override
public void executeTransaction(Realm.Transaction transaction) {
}
@Override
public Observable<TutorialStep> getTutorialStep(String key) {
return Observable.defer(() -> Observable.just(new Select().from(TutorialStep.class).where(Condition.column("key").eq(key)).querySingle()));

View file

@ -11,6 +11,7 @@ import com.raizlabs.android.dbflow.sql.language.Select;
import java.util.ArrayList;
import java.util.List;
import io.realm.Realm;
import rx.Observable;
public class DbFlowUserLocalRepository implements UserLocalRepository {
@ -19,6 +20,11 @@ public class DbFlowUserLocalRepository implements UserLocalRepository {
}
@Override
public void executeTransaction(Realm.Transaction transaction) {
}
@Override
public Observable<HabitRPGUser> getUser(String userID) {
return Observable.defer(() -> Observable.just(new Select()

View file

@ -0,0 +1,24 @@
package com.habitrpg.android.habitica.data.local.implementation;
import com.habitrpg.android.habitica.data.local.BaseLocalRepository;
import io.realm.Realm;
abstract class RealmBaseLocalRepository implements BaseLocalRepository {
Realm realm;
RealmBaseLocalRepository(Realm realm) {
this.realm = realm;
}
@Override
public void close() {
realm.close();
}
@Override
public void executeTransaction(Realm.Transaction transaction) {
realm.executeTransaction(transaction);
}
}

View file

@ -0,0 +1,27 @@
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.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 realm.where(Tag.class).equalTo("userId", userId).findAll().asObservable();
}
@Override
public void removeOldTags(List<Tag> onlineTags) {
}
}

View file

@ -0,0 +1,92 @@
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.TaskTag;
import com.habitrpg.android.habitica.models.tasks.TasksOrder;
import java.util.List;
import io.realm.Realm;
import io.realm.RealmResults;
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").asObservable()
.filter(RealmResults::isLoaded);
}
@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(TasksOrder tasksOrder, TaskList tasks) {
realm.executeTransaction(realm1 -> realm1.copyToRealm(tasks.tasks.values()));
}
@Override
public void saveTask(Task task) {
realm.executeTransaction(realm1 -> realm1.copyToRealm(task));
}
@Override
public void removeOldTasks(String userID, List<Task> onlineTaskList) {
}
@Override
public void removeOldChecklists(List<ChecklistItem> onlineChecklistItems) {
}
@Override
public void removeOldTaskTags(List<TaskTag> onlineTaskTags) {
}
@Override
public void removeOldReminders(List<RemindersItem> onlineReminders) {
}
@Override
public void deleteTask(String taskID) {
Task task = realm.where(Task.class).equalTo("id", taskID).findFirst();
realm.executeTransaction(realm1 -> task.deleteFromRealm());
}
@Override
public Observable<Task> getTask(String taskId) {
return realm.where(Task.class).equalTo("id", taskId).findFirst().asObservable();
}
@Override
public Observable<Task> getTaskCopy(String taskId) {
return getTask(taskId)
.map(realm::copyFromRealm);
}
@Override
public void markTaskCompleted(String taskId, boolean isCompleted) {
Task task = realm.where(Task.class).equalTo("id", taskId).findFirst();
realm.executeTransaction(realm1 -> task.completed = true);
}
@Override
public void saveReminder(RemindersItem remindersItem) {
realm.executeTransaction(realm1 -> realm1.copyToRealm(remindersItem));
}
}

View file

@ -212,7 +212,7 @@ public class TaskAlarmManager {
setAlarm(context, cal.getTimeInMillis(), sender);
remindersItem.save();
taskRepository.saveReminder(remindersItem);
}
private void removeAlarmForRemindersItem(RemindersItem remindersItem) {

View file

@ -1,57 +1,28 @@
package com.habitrpg.android.habitica.models;
import com.habitrpg.android.habitica.HabitDatabase;
import com.habitrpg.android.habitica.models.tasks.TaskTag;
import com.raizlabs.android.dbflow.annotation.Column;
import com.raizlabs.android.dbflow.annotation.ModelContainer;
import com.raizlabs.android.dbflow.annotation.NotNull;
import com.raizlabs.android.dbflow.annotation.OneToMany;
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
import com.raizlabs.android.dbflow.annotation.Table;
import com.raizlabs.android.dbflow.sql.builder.Condition;
import com.raizlabs.android.dbflow.sql.language.Select;
import com.raizlabs.android.dbflow.structure.BaseModel;
import java.util.List;
import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
/**
* Description of a Tag in HabitRPG
* Created by MagicMicky on 16/03/14.
*/
@ModelContainer
@Table(databaseName = HabitDatabase.NAME)
public class Tag extends BaseModel {
public class Tag extends RealmObject {
@Column
@PrimaryKey
@NotNull
public String id;
@Column
@NotNull
public String user_id;
public List<TaskTag> tasks;
@Column
public String userId;
public RealmList<TaskTag> tasks;
String name;
public Tag() {
this(null, null);
}
public Tag(String id, String name) {
this.setId(id);
this.setName(name);
}
@OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "tasks")
public List<TaskTag> getTasks() {
if (tasks == null) {
tasks = new Select()
.from(TaskTag.class)
.where(Condition.column("tag_id").eq(this.id)).and(Condition.column("task_id").isNotNull())
.queryList();
}
return tasks;
}
@ -71,15 +42,6 @@ public class Tag extends BaseModel {
this.id = id;
}
@Override
public void delete() {
if (getTasks() != null) {
for (TaskTag tt : getTasks()) {
tt.delete();
}
}
super.delete();
}
@Override
public boolean equals(Object o) {
@ -89,12 +51,4 @@ public class Tag extends BaseModel {
}
return super.equals(o);
}
@Override
public void save() {
if (user_id == null) {
return;
}
super.save();
}
}

View file

@ -1,37 +1,18 @@
package com.habitrpg.android.habitica.models.tasks;
import com.habitrpg.android.habitica.HabitDatabase;
import com.habitrpg.android.habitica.database.ExcludeCheckListItem;
import com.raizlabs.android.dbflow.annotation.Column;
import com.raizlabs.android.dbflow.annotation.ForeignKey;
import com.raizlabs.android.dbflow.annotation.ForeignKeyReference;
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
import com.raizlabs.android.dbflow.annotation.Table;
import com.raizlabs.android.dbflow.structure.BaseModel;
import com.raizlabs.android.dbflow.structure.container.ForeignKeyContainer;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
/**
* Created by viirus on 06/07/15.
*/
@Table(databaseName = HabitDatabase.NAME)
public class ChecklistItem extends BaseModel {
public class ChecklistItem extends RealmObject {
@Column
@ForeignKey(
references = {@ForeignKeyReference(columnName = "task_id",
columnType = String.class,
foreignColumnName = "id")},
saveForeignKeyModel = false)
@ExcludeCheckListItem
ForeignKeyContainer<Task> task;
@Column
Task task;
@PrimaryKey
private String id;
@Column
private String text;
@Column
private boolean completed;
@Column
private int position;
public ChecklistItem() {
@ -91,24 +72,10 @@ public class ChecklistItem extends BaseModel {
}
public Task getTask() {
if (task != null) {
return task.toModel();
} else {
return null;
}
return task;
}
public void setTask(Task task) {
this.task = new ForeignKeyContainer<>(Task.class);
this.task.setModel(task);
this.task.put("id", task.id);
}
@Override
public void save() {
if (this.getId() == null || this.getId().isEmpty()) {
return;
}
super.save();
this.task = task;
}
}

View file

@ -1,26 +1,18 @@
package com.habitrpg.android.habitica.models.tasks;
import com.habitrpg.android.habitica.HabitDatabase;
import com.raizlabs.android.dbflow.annotation.Column;
import com.raizlabs.android.dbflow.annotation.ModelContainer;
import com.raizlabs.android.dbflow.annotation.NotNull;
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
import com.raizlabs.android.dbflow.annotation.Table;
import com.raizlabs.android.dbflow.structure.BaseModel;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
/**
* Created by viirus on 06/07/15.
*/
@ModelContainer
@Table(databaseName = HabitDatabase.NAME)
public class Days extends BaseModel {
public class Days extends RealmObject {
@Column
@PrimaryKey
@NotNull
String task_id;
@Column
private boolean m, t, w, th, f, s, su;
public Days() {

View file

@ -1,44 +1,19 @@
package com.habitrpg.android.habitica.models.tasks;
import com.habitrpg.android.habitica.HabitDatabase;
import com.habitrpg.android.habitica.database.ExcludeCheckListItem;
import com.habitrpg.android.habitica.events.ReminderDeleteEvent;
import com.raizlabs.android.dbflow.annotation.Column;
import com.raizlabs.android.dbflow.annotation.ForeignKey;
import com.raizlabs.android.dbflow.annotation.ForeignKeyReference;
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
import com.raizlabs.android.dbflow.annotation.Table;
import com.raizlabs.android.dbflow.sql.builder.Condition;
import com.raizlabs.android.dbflow.sql.language.Select;
import com.raizlabs.android.dbflow.structure.BaseModel;
import com.raizlabs.android.dbflow.structure.container.ForeignKeyContainer;
import org.greenrobot.eventbus.EventBus;
import java.util.Date;
import java.util.List;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
/**
* Created by keithholliday on 5/31/16.
*/
@Table(databaseName = HabitDatabase.NAME)
public class RemindersItem extends BaseModel {
@Column
@ForeignKey(
references = {@ForeignKeyReference(columnName = "task_id",
columnType = String.class,
foreignColumnName = "id")},
saveForeignKeyModel = false)
@ExcludeCheckListItem
ForeignKeyContainer<Task> task;
@Column
public class RemindersItem extends RealmObject {
Task task;
@PrimaryKey
private String id;
@Column
private Date startDate;
@Column
private Date time;
@Column
private Integer alarmId;
//Use to store task type before a task is created
@ -77,29 +52,11 @@ public class RemindersItem extends BaseModel {
}
public Task getTask() {
if (task != null) {
//This will get all the task info
Task taskModel = task.toModel();
if (taskModel.getId() == null) {
return taskModel;
}
List<Task> task = new Select()
.from(Task.class)
.where(Condition.column("id").eq(taskModel.getId()))
.queryList();
return task.get(0);
} else {
return null;
}
return task;
}
public void setTask(Task task) {
this.task = new ForeignKeyContainer<>(Task.class);
this.task.setModel(task);
this.task.put("id", task.getId());
this.task = task;
}
public String getType() {
@ -109,20 +66,4 @@ public class RemindersItem extends BaseModel {
public void setType(String type) {
this.type = type;
}
@Override
public void save() {
if (this.getId() == null) {
return;
}
super.save();
}
@Override
public void delete() {
ReminderDeleteEvent event = new ReminderDeleteEvent();
event.reminder = this;
EventBus.getDefault().post(event);
super.delete();
}
}

View file

@ -3,21 +3,9 @@ package com.habitrpg.android.habitica.models.tasks;
import android.support.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
import com.habitrpg.android.habitica.HabitDatabase;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.events.TaskDeleteEvent;
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser;
import com.raizlabs.android.dbflow.annotation.Column;
import com.raizlabs.android.dbflow.annotation.ForeignKey;
import com.raizlabs.android.dbflow.annotation.ForeignKeyReference;
import com.raizlabs.android.dbflow.annotation.ModelContainer;
import com.raizlabs.android.dbflow.annotation.NotNull;
import com.raizlabs.android.dbflow.annotation.OneToMany;
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
import com.raizlabs.android.dbflow.annotation.Table;
import com.raizlabs.android.dbflow.sql.builder.Condition;
import com.raizlabs.android.dbflow.sql.language.Select;
import com.raizlabs.android.dbflow.structure.BaseModel;
import org.greenrobot.eventbus.EventBus;
@ -28,12 +16,12 @@ import java.util.GregorianCalendar;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Created by viirus on 10/08/15.
*/
@ModelContainer
@Table(databaseName = HabitDatabase.NAME)
public class Task extends BaseModel {
import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.Ignore;
import io.realm.annotations.PrimaryKey;
public class Task extends RealmObject {
public static final String TYPE_HABIT = "habit";
public static final String TYPE_TODO = "todo";
public static final String TYPE_DAILY = "daily";
@ -51,58 +39,36 @@ public class Task extends BaseModel {
public static final String ATTRIBUTE_CONSTITUTION = "con";
public static final String ATTRIBUTE_INTELLIGENCE = "int";
public static final String ATTRIBUTE_PERCEPTION = "per";
@Column
@SerializedName("userId")
public String user_id;
@Column
public String userId;
public Float priority;
@Column
public String text, notes, attribute, type;
@Column
public double value;
public List<TaskTag> tags;
@Column
public RealmList<TaskTag> tags;
public Date dateCreated;
@Column
public int position;
@Column
@ForeignKey(references = {@ForeignKeyReference(columnName = "group_id",
columnType = String.class,
foreignColumnName = "task_id")})
public TaskGroupPlan group;
//Habits
@Column
public Boolean up, down;
//todos/dailies
@Column
public boolean completed;
public List<ChecklistItem> checklist;
public List<RemindersItem> reminders;
public RealmList<ChecklistItem> checklist;
public RealmList<RemindersItem> reminders;
//dailies
@Column
public String frequency;
@Column
public Integer everyX, streak;
@Column
public
Date startDate;
@Column
@ForeignKey(references = {@ForeignKeyReference(columnName = "days_id",
columnType = String.class,
foreignColumnName = "task_id")})
public Date startDate;
public Days repeat;
//todos
@Column
@SerializedName("date")
public Date duedate;
//TODO: private String lastCompleted;
// used for buyable items
public String specialTag;
@Ignore
public CharSequence parsedText;
@Ignore
public CharSequence parsedNotes;
@Column
@PrimaryKey
@NotNull
@SerializedName("_id")
String id;
@ -198,25 +164,15 @@ public class Task extends BaseModel {
this.type = type;
}
@OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "tags")
public List<TaskTag> getTags() {
if (tags == null) {
tags = new Select()
.from(TaskTag.class)
.where(Condition.column("task_id").eq(this.id))
.queryList();
}
return tags;
}
public void setTags(List<TaskTag> tags) {
for (TaskTag tag : tags) {
tag.setTask(this);
}
public void setTags(RealmList<TaskTag> tags) {
this.tags = tags;
}
public boolean containsAnyTagId(ArrayList<String> tagIdList) {
public boolean containsAnyTagId(List<String> tagIdList) {
getTags();
for (TaskTag t : tags) {
@ -231,7 +187,7 @@ public class Task extends BaseModel {
public boolean containsAllTagIds(List<String> tagIdList) {
getTags();
ArrayList<String> allTagIds = new ArrayList<String>();
List<String> allTagIds = new ArrayList<String>();
for (TaskTag t : tags) {
allTagIds.add(t.getTag().getId());
@ -287,41 +243,19 @@ public class Task extends BaseModel {
}
@OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "checklist")
public List<ChecklistItem> getChecklist() {
if (this.checklist == null) {
this.checklist = new Select()
.from(ChecklistItem.class)
.where(Condition.column("task_id").eq(this.id))
.orderBy(true, "position")
.queryList();
}
return this.checklist;
}
public void setChecklist(List<ChecklistItem> checklist) {
for (ChecklistItem checklistItem : checklist) {
checklistItem.setTask(this);
}
public void setChecklist(RealmList<ChecklistItem> checklist) {
this.checklist = checklist;
}
@OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "reminders")
public List<RemindersItem> getReminders() {
if (this.reminders == null) {
this.reminders = new Select()
.from(RemindersItem.class)
.where(Condition.column("task_id").eq(this.id))
.orderBy(true, "time")
.queryList();
}
return this.reminders;
}
public void setReminders(List<RemindersItem> reminders) {
for (RemindersItem remindersItem : reminders) {
remindersItem.setTask(this);
}
public void setReminders(RealmList<RemindersItem> reminders) {
this.reminders = reminders;
}
@ -434,79 +368,6 @@ public class Task extends BaseModel {
this.attribute = attribute;
}
@Override
public void save() {
if (this.getId() == null || this.getId().length() == 0) {
return;
}
List<TaskTag> tmpTags = tags;
List<ChecklistItem> tmpChecklist = checklist;
List<RemindersItem> tmpReminders = reminders;
// remove them, so that the database don't add empty entries
tags = null;
checklist = null;
reminders = null;
if (repeat != null) {
repeat.task_id = this.id;
}
if (group != null) {
group.task_id = this.id;
}
super.save();
tags = tmpTags;
checklist = tmpChecklist;
reminders = tmpReminders;
if (this.tags != null) {
for (TaskTag tag : this.tags) {
tag.setTask(this);
tag.async().save();
}
}
int position = 0;
if (this.checklist != null) {
for (ChecklistItem item : this.checklist) {
if (item.getTask() == null) {
item.setTask(this);
}
item.setPosition(position);
item.async().save();
position++;
}
}
int index = 0;
if (this.reminders != null) {
for (RemindersItem item : this.reminders) {
if (item.getTask() == null) {
item.setTask(this);
}
if (item.getId() == null) {
item.setId(this.id + "task-reminder" + index);
}
item.async().save();
index++;
}
}
}
@Override
public void update() {
if (this.getId() == null || this.getId().length() == 0) {
return;
}
super.update();
}
public int getLightTaskColor() {
if (this.value < -20)
return R.color.worst_100;
@ -647,14 +508,6 @@ public class Task extends BaseModel {
return newTime.getTime();
}
@Override
public void delete() {
TaskDeleteEvent event = new TaskDeleteEvent();
event.task = this;
EventBus.getDefault().post(event);
super.delete();
}
public boolean isGroupTask() {
if (group != null) {
if (group.approvalRequired) {

View file

@ -1,23 +1,13 @@
package com.habitrpg.android.habitica.models.tasks;
import com.habitrpg.android.habitica.HabitDatabase;
import com.raizlabs.android.dbflow.annotation.Column;
import com.raizlabs.android.dbflow.annotation.ModelContainer;
import com.raizlabs.android.dbflow.annotation.NotNull;
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
import com.raizlabs.android.dbflow.annotation.Table;
import com.raizlabs.android.dbflow.structure.BaseModel;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
@ModelContainer
@Table(databaseName = HabitDatabase.NAME)
public class TaskGroupPlan extends BaseModel {
public class TaskGroupPlan extends RealmObject {
@Column
@PrimaryKey
@NotNull
String task_id;
@Column
public boolean approvalRequested, approvalApproved, approvalRequired;
}

View file

@ -1,36 +1,19 @@
package com.habitrpg.android.habitica.models.tasks;
import com.habitrpg.android.habitica.HabitDatabase;
import com.habitrpg.android.habitica.models.Tag;
import com.raizlabs.android.dbflow.annotation.Column;
import com.raizlabs.android.dbflow.annotation.ForeignKey;
import com.raizlabs.android.dbflow.annotation.ForeignKeyReference;
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
import com.raizlabs.android.dbflow.annotation.Table;
import com.raizlabs.android.dbflow.structure.BaseModel;
import com.raizlabs.android.dbflow.structure.container.ForeignKeyContainer;
import com.habitrpg.android.habitica.models.Tag;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
/**
* Created by viirus on 08/08/15.
*/
@Table(databaseName = HabitDatabase.NAME)
public class TaskTag extends BaseModel {
public class TaskTag extends RealmObject {
@Column
@ForeignKey(references = {@ForeignKeyReference(columnName = "tag_id",
columnType = String.class,
foreignColumnName = "id")},
saveForeignKeyModel = false)
public ForeignKeyContainer<Tag> tag;
@Column
@ForeignKey(references = {@ForeignKeyReference(columnName = "task_id",
columnType = String.class,
foreignColumnName = "id")},
saveForeignKeyModel = false)
public ForeignKeyContainer<Task> task;
@Column
public Tag tag;
public Task task;
@PrimaryKey
String id;
private String tagId = "";
@ -45,26 +28,21 @@ public class TaskTag extends BaseModel {
}
public Tag getTag() {
return tag.toModel();
return tag;
}
public void setTag(Tag tag) {
this.tag = new ForeignKeyContainer<>(Tag.class);
this.tag.setModel(tag);
this.tag.put("id", tag.id);
this.tag = tag;
tagId = tag.id;
updatePrimaryKey();
}
public Task getTask() {
return task.toModel();
return task;
}
public void setTask(Task task) {
this.task = new ForeignKeyContainer<>(Task.class);
this.task.setModel(task);
this.task.put("id", task.id);
this.task = task;
taskId = task.id;
updatePrimaryKey();

View file

@ -31,13 +31,8 @@ import java.util.Map;
@Table(databaseName = HabitDatabase.NAME)
public class HabitRPGUser extends BaseModel {
List<Task> dailys;
List<Task> todos;
List<Task> rewards;
List<Task> habits;
List<Challenge> challengeList;
List<Tag> tags;
@Column
@PrimaryKey
@SerializedName("_id")
@ -239,85 +234,6 @@ public class HabitRPGUser extends BaseModel {
this.purchased = purchased;
}
@OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "habits")
public List<Task> getHabits() {
if (habits == null) {
habits = new Select()
.from(Task.class)
.where(Condition.column("type").eq("habit"))
.and(Condition.column("user_id").eq(this.id))
.queryList();
}
return habits;
}
public void setHabits(List<Task> habits) {
this.habits = habits;
}
@OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "dailys")
public List<Task> getDailys() {
if (dailys == null) {
dailys = new Select()
.from(Task.class)
.where(Condition.column("type").eq("daily"))
.and(Condition.column("user_id").eq(this.id))
.queryList();
}
return dailys;
}
public void setDailys(List<Task> dailys) {
this.dailys = dailys;
}
@OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "todos")
public List<Task> getTodos() {
if (todos == null) {
todos = new Select()
.from(Task.class)
.where(Condition.column("type").eq("todo"))
.and(Condition.column("user_id").eq(this.id))
.queryList();
}
return todos;
}
public void setTodos(List<Task> todos) {
this.todos = todos;
}
@OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "rewards")
public List<Task> getRewards() {
if (rewards == null) {
rewards = new Select()
.from(Task.class)
.where(Condition.column("type").eq("reward"))
.and(Condition.column("user_id").eq(this.id))
.queryList();
}
return rewards;
}
public void setRewards(List<Task> rewards) {
this.rewards = rewards;
}
@OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "tags")
public List<Tag> getTags() {
if (tags == null) {
tags = new Select()
.from(Tag.class)
.where(Condition.column("user_id").eq(this.id))
.queryList();
}
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
public Flags getFlags() {
return flags;
}
@ -353,7 +269,7 @@ public class HabitRPGUser extends BaseModel {
@Override
public void save() {
// We need to set the user_id to all other objects
// We need to set the userId to all other objects
if (id == null) {
return;
}
@ -376,31 +292,6 @@ public class HabitRPGUser extends BaseModel {
invitations.user_id = id;
}
ArrayList<Task> allTasks = new ArrayList<Task>();
if (dailys != null) {
allTasks.addAll(dailys);
}
if (todos != null) {
allTasks.addAll(todos);
}
if (habits != null) {
allTasks.addAll(habits);
}
if (rewards != null) {
allTasks.addAll(rewards);
}
for (Task t : allTasks) {
t.user_id = id;
}
if (tags != null) {
for (Tag t : tags) {
t.user_id = id;
}
}
List<Challenge> challenges = getChallengeList();
List<Challenge> newChallenges = new ArrayList<>();
if (getChallenges() != null) {

View file

@ -34,15 +34,17 @@ import com.habitrpg.android.habitica.data.local.implementation.DbFlowCustomizati
import com.habitrpg.android.habitica.data.local.implementation.DbFlowFAQLocalRepository;
import com.habitrpg.android.habitica.data.local.implementation.DbFlowInventoryLocalRepository;
import com.habitrpg.android.habitica.data.local.implementation.DbFlowSocialLocalRepository;
import com.habitrpg.android.habitica.data.local.implementation.DbFlowTagLocalRepository;
import com.habitrpg.android.habitica.data.local.implementation.DbFlowTaskLocalRepository;
import com.habitrpg.android.habitica.data.local.implementation.DbFlowTutorialLocalRepository;
import com.habitrpg.android.habitica.data.local.implementation.DbFlowUserLocalRepository;
import com.habitrpg.android.habitica.data.local.implementation.RealmTagLocalRepository;
import com.habitrpg.android.habitica.data.local.implementation.RealmTaskLocalRepository;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import io.realm.Realm;
import io.realm.RealmConfiguration;
@Module
public class RepositoryModule {
@ -50,12 +52,16 @@ public class RepositoryModule {
@Provides
SetupCustomizationRepository providesSetupCustomizationRepository(Context context) {
return new SetupCustomizationRepositoryImpl(context);
}
@Provides
TaskLocalRepository providesTaskLocalRepository() {
return new DbFlowTaskLocalRepository();
Realm providesRealm(Context context) {
return Realm.getDefaultInstance();
}
@Provides
TaskLocalRepository providesTaskLocalRepository(Realm realm) {
return new RealmTaskLocalRepository(realm);
}
@Provides
@ -65,8 +71,8 @@ public class RepositoryModule {
}
@Provides
TagLocalRepository providesTagLocalRepository() {
return new DbFlowTagLocalRepository();
TagLocalRepository providesTagLocalRepository(Realm realm) {
return new RealmTagLocalRepository(realm);
}
@Provides

View file

@ -96,10 +96,7 @@ import com.habitrpg.android.habitica.models.inventory.Pet;
import com.habitrpg.android.habitica.models.responses.MaintenanceResponse;
import com.habitrpg.android.habitica.models.responses.TaskDirectionData;
import com.habitrpg.android.habitica.models.shops.Shop;
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.TaskTag;
import com.habitrpg.android.habitica.models.user.HabitRPGUser;
import com.habitrpg.android.habitica.models.user.Preferences;
import com.habitrpg.android.habitica.models.user.SpecialItems;
@ -129,7 +126,6 @@ import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
@ -229,8 +225,11 @@ public class MainActivity extends BaseActivity implements Action1<Throwable>, Ha
// endregion
@Nullable
private Drawer drawer;
@Nullable
private AccountHeader accountHeader;
@Nullable
private BaseMainFragment activeFragment;
private AvatarWithBarsViewModel avatarInHeader;
private AlertDialog faintDialog;
@ -266,12 +265,6 @@ public class MainActivity extends BaseActivity implements Action1<Throwable>, Ha
return;
}
userRepository.getUser(hostConfig.getUser())
.subscribe(newUser -> {
MainActivity.this.user = newUser;
MainActivity.this.setUserData(true);
}, throwable -> {});
setupToolbar(toolbar);
avatarInHeader = new AvatarWithBarsViewModel(this, avatar_with_bars);
@ -292,6 +285,12 @@ public class MainActivity extends BaseActivity implements Action1<Throwable>, Ha
avatar_with_bars.setPadding((int)px, getStatusBarHeight(), (int)px, 0);
}
userRepository.getUser(hostConfig.getUser())
.subscribe(newUser -> {
MainActivity.this.user = newUser;
MainActivity.this.setUserData(true);
}, throwable -> {});
EventBus.getDefault().register(this);
}
@ -455,13 +454,8 @@ public class MainActivity extends BaseActivity implements Action1<Throwable>, Ha
// multiple crashes because user is null
if (user != null) {
ArrayList<Task> allTasks = new ArrayList<>();
allTasks.addAll(user.getDailys());
allTasks.addAll(user.getTodos());
allTasks.addAll(user.getHabits());
allTasks.addAll(user.getRewards());
taskRepository.removeOldTasks(user.getId(), allTasks);
/*taskRepository.removeOldTasks(user.getId(), allTasks);
ArrayList<ChecklistItem> allChecklistItems = new ArrayList<>();
for (Task t : allTasks) {
@ -487,7 +481,7 @@ public class MainActivity extends BaseActivity implements Action1<Throwable>, Ha
}
taskRepository.removeOldReminders(allReminders);
tagRepository.removeOldTags(user.getTags());
tagRepository.removeOldTags(user.getTags());*/
inventoryRepository.updateOwnedEquipment(user);
}
@ -521,17 +515,20 @@ public class MainActivity extends BaseActivity implements Action1<Throwable>, Ha
}
private void updateUserAvatars() {
avatarInHeader.updateData(user);
if (avatarInHeader != null) {
avatarInHeader.updateData(user);
}
}
private void updateHeader() {
updateUserAvatars();
setTranslatedFragmentTitle(activeFragment);
android.support.v7.app.ActionBarDrawerToggle actionBarDrawerToggle = drawer.getActionBarDrawerToggle();
if (actionBarDrawerToggle != null) {
actionBarDrawerToggle.setDrawerIndicatorEnabled(true);
if (drawer != null) {
android.support.v7.app.ActionBarDrawerToggle actionBarDrawerToggle = drawer.getActionBarDrawerToggle();
if (actionBarDrawerToggle != null) {
actionBarDrawerToggle.setDrawerIndicatorEnabled(true);
}
}
}
@ -1148,16 +1145,6 @@ public class MainActivity extends BaseActivity implements Action1<Throwable>, Ha
});
}
@Subscribe
public void onEvent(final TaskSaveEvent event) {
Task task = event.task;
if (event.created) {
this.taskRepository.createTask(task).subscribe(task1 -> {}, throwable -> {});
} else {
this.taskRepository.updateTask(task).subscribe(task1 -> {}, throwable -> {});
}
}
private void checkMaintenance() {
this.maintenanceService.getMaintenanceStatus()
.compose(apiClient.configureApiCallObserver())

View file

@ -78,6 +78,10 @@ import javax.inject.Inject;
import butterknife.BindView;
import butterknife.OnClick;
import io.realm.Realm;
import io.realm.RealmList;
import io.realm.RealmObject;
import rx.Observable;
public class TaskFormActivity extends BaseActivity implements AdapterView.OnItemSelectedListener {
public static final String TASK_ID_KEY = "taskId";
@ -246,7 +250,7 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem
.setTitle(getString(R.string.taskform_delete_title))
.setMessage(getString(R.string.taskform_delete_message)).setPositiveButton(getString(R.string.yes), (dialog, which) -> {
if (task != null) {
task.delete();
taskRepository.deleteTask(task.getId());
}
finish();
@ -322,7 +326,9 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem
}
if (taskId != null) {
taskRepository.getTask(taskId).subscribe(task -> {
taskRepository.getTask(taskId)
.first()
.subscribe(task -> {
this.task = task;
if (task != null) {
populate(task);
@ -732,113 +738,128 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem
}
private boolean saveTask(Task task) {
task.text = MarkdownParser.parseCompiled(taskText.getText());
if (checklistAdapter != null) {
if (checklistAdapter.getCheckListItems() != null) {
task.setChecklist(checklistAdapter.getCheckListItems());
}
}
if (remindersAdapter != null) {
if (remindersAdapter.getRemindersItems() != null) {
task.setReminders(remindersAdapter.getRemindersItems());
}
}
if (task.text.isEmpty()) {
String text = MarkdownParser.parseCompiled(taskText.getText());
if (text == null || text.isEmpty()) {
return false;
}
task.notes = MarkdownParser.parseCompiled(taskNotes.getText());
taskRepository.executeTransaction(realm -> {
task.text = text;
if (this.taskDifficultySpinner.getSelectedItemPosition() == 0) {
task.setPriority((float) 0.1);
} else if (this.taskDifficultySpinner.getSelectedItemPosition() == 1) {
task.setPriority((float) 1.0);
} else if (this.taskDifficultySpinner.getSelectedItemPosition() == 2) {
task.setPriority((float) 1.5);
} else if (this.taskDifficultySpinner.getSelectedItemPosition() == 3) {
task.setPriority((float) 2.0);
}
if (TextUtils.isEmpty(allocationMode) || !allocationMode.equals("taskbased")) {
task.setAttribute(Task.ATTRIBUTE_STRENGTH);
} else {
switch (this.taskAttributeSpinner.getSelectedItemPosition()) {
case 0:
task.setAttribute(Task.ATTRIBUTE_STRENGTH);
break;
case 1:
task.setAttribute(Task.ATTRIBUTE_INTELLIGENCE);
break;
case 2:
task.setAttribute(Task.ATTRIBUTE_CONSTITUTION);
break;
case 3:
task.setAttribute(Task.ATTRIBUTE_PERCEPTION);
break;
if (checklistAdapter != null) {
if (checklistAdapter.getCheckListItems() != null) {
for (ChecklistItem item : task.getChecklist()) {
item.setText(checklistAdapter.checklistTexts.get(item.getId()));
}
}
}
}
switch (task.type) {
case "habit": {
task.setUp(positiveCheckBox.isChecked());
task.setDown(negativeCheckBox.isChecked());
if (remindersAdapter != null) {
if (remindersAdapter.getRemindersItems() != null) {
task.getReminders().addAll(remindersAdapter.getRemindersItems());
}
}
break;
case "daily": {
task.setStartDate(new Date(startDateListener.getCalendar().getTimeInMillis()));
if (this.dailyFrequencySpinner.getSelectedItemPosition() == 0) {
task.setFrequency("weekly");
Days repeat = task.getRepeat();
if (repeat == null) {
repeat = new Days();
task.setRepeat(repeat);
RealmList<TaskTag> taskTags = new RealmList<>();
for (Tag tag : selectedTags) {
TaskTag tt = new TaskTag();
tt.setTag(tag);
tt.setTask(task);
taskTags.add(tt);
}
task.setTags(taskTags);
task.notes = MarkdownParser.parseCompiled(taskNotes.getText());
if (taskDifficultySpinner.getSelectedItemPosition() == 0) {
task.setPriority((float) 0.1);
} else if (taskDifficultySpinner.getSelectedItemPosition() == 1) {
task.setPriority((float) 1.0);
} else if (taskDifficultySpinner.getSelectedItemPosition() == 2) {
task.setPriority((float) 1.5);
} else if (taskDifficultySpinner.getSelectedItemPosition() == 3) {
task.setPriority((float) 2.0);
}
if (TextUtils.isEmpty(allocationMode) || !allocationMode.equals("taskbased")) {
task.setAttribute(Task.ATTRIBUTE_STRENGTH);
} else {
switch (taskAttributeSpinner.getSelectedItemPosition()) {
case 0:
task.setAttribute(Task.ATTRIBUTE_STRENGTH);
break;
case 1:
task.setAttribute(Task.ATTRIBUTE_INTELLIGENCE);
break;
case 2:
task.setAttribute(Task.ATTRIBUTE_CONSTITUTION);
break;
case 3:
task.setAttribute(Task.ATTRIBUTE_PERCEPTION);
break;
}
}
switch (task.type) {
case "habit": {
task.setUp(positiveCheckBox.isChecked());
task.setDown(negativeCheckBox.isChecked());
}
break;
case "daily": {
task.setStartDate(new Date(startDateListener.getCalendar().getTimeInMillis()));
if (dailyFrequencySpinner.getSelectedItemPosition() == 0) {
task.setFrequency("weekly");
Days repeat = task.getRepeat();
if (repeat == null) {
repeat = new Days();
task.setRepeat(repeat);
}
int offset = firstDayOfTheWeekHelper.getDailyTaskFormOffset();
repeat.setM(weekdayCheckboxes.get(offset).isChecked());
repeat.setT(weekdayCheckboxes.get((offset + 1) % 7).isChecked());
repeat.setW(weekdayCheckboxes.get((offset + 2) % 7).isChecked());
repeat.setTh(weekdayCheckboxes.get((offset + 3) % 7).isChecked());
repeat.setF(weekdayCheckboxes.get((offset + 4) % 7).isChecked());
repeat.setS(weekdayCheckboxes.get((offset + 5) % 7).isChecked());
repeat.setSu(weekdayCheckboxes.get((offset + 6) % 7).isChecked());
} else {
task.setFrequency("daily");
task.setEveryX(frequencyPicker.getValue());
}
}
break;
case "todo": {
if (dueDateCheckBox.isChecked()) {
task.setDueDate(new Date(dueDateListener.getCalendar().getTimeInMillis()));
} else {
task.setDueDate(null);
}
}
break;
case "reward": {
String value = taskValue.getText().toString();
if (!value.isEmpty()) {
NumberFormat localFormat = DecimalFormat.getInstance(Locale.getDefault());
try {
task.setValue(localFormat.parse(value).doubleValue());
} catch (ParseException e) {
}
} else {
task.setValue(0.0d);
}
int offset = firstDayOfTheWeekHelper.getDailyTaskFormOffset();
repeat.setM(this.weekdayCheckboxes.get(offset).isChecked());
repeat.setT(this.weekdayCheckboxes.get((offset + 1) % 7).isChecked());
repeat.setW(this.weekdayCheckboxes.get((offset + 2) % 7).isChecked());
repeat.setTh(this.weekdayCheckboxes.get((offset + 3) % 7).isChecked());
repeat.setF(this.weekdayCheckboxes.get((offset + 4) % 7).isChecked());
repeat.setS(this.weekdayCheckboxes.get((offset + 5) % 7).isChecked());
repeat.setSu(this.weekdayCheckboxes.get((offset + 6) % 7).isChecked());
} else {
task.setFrequency("daily");
task.setEveryX(this.frequencyPicker.getValue());
}
break;
}
break;
case "todo": {
if (dueDateCheckBox.isChecked()) {
task.setDueDate(new Date(dueDateListener.getCalendar().getTimeInMillis()));
} else {
task.setDueDate(null);
}
}
break;
case "reward": {
String value = taskValue.getText().toString();
if (!value.isEmpty()) {
NumberFormat localFormat = DecimalFormat.getInstance(Locale.getDefault());
try {
task.setValue(localFormat.parse(value).doubleValue());
} catch (ParseException e) {
}
} else {
task.setValue(0.0d);
}
}
break;
}
});
return true;
}
@ -858,24 +879,14 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem
}
if (this.saveTask(this.task)) {
List<TaskTag> taskTags = new ArrayList<>();
for (Tag tag : selectedTags) {
TaskTag tt = new TaskTag();
tt.setTag(tag);
tt.setTask(task);
taskTags.add(tt);
}
//save
this.task.setTags(taskTags);
this.task.save();
//send back to other elements.
TaskSaveEvent event = new TaskSaveEvent();
Observable<Task> observable;
if (TaskFormActivity.this.task.getId() == null) {
event.created = true;
observable = taskRepository.createTask(task);
} else {
observable = taskRepository.updateTask(task);
}
event.task = TaskFormActivity.this.task;
EventBus.getDefault().post(event);
observable.subscribe(task1 -> {}, throwable -> {});
}
}

View file

@ -17,7 +17,9 @@ import com.habitrpg.android.habitica.ui.helpers.ItemTouchHelperViewHolder;
import net.pherth.android.emoji_library.EmojiEditText;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
@ -29,21 +31,23 @@ public class CheckListAdapter extends RecyclerView.Adapter<CheckListAdapter.Item
implements ItemTouchHelperAdapter {
private final List<ChecklistItem> items = new ArrayList<>();
public final Map<String, String> checklistTexts = new HashMap<>();
public CheckListAdapter(List<ChecklistItem> checklistItems) {
items.addAll(checklistItems);
for (ChecklistItem item : checklistItems) {
checklistTexts.put(item.getId(), item.getText());
}
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.checklist_item, parent, false);
ItemViewHolder itemViewHolder = new ItemViewHolder(view);
return itemViewHolder;
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
holder.textWatcher.position = position;
holder.checkListTextView.setText(items.get(position).getText());
}
@ -116,7 +120,7 @@ public class CheckListAdapter extends RecyclerView.Adapter<CheckListAdapter.Item
private class ChecklistTextWatcher implements TextWatcher {
public int position;
public String id;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@ -125,7 +129,7 @@ public class CheckListAdapter extends RecyclerView.Adapter<CheckListAdapter.Item
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
items.get(position).setText(checkListTextView.getText().toString());
checklistTexts.put(id, checkListTextView.getText().toString());
}
@Override

View file

@ -7,16 +7,17 @@ import android.view.ViewGroup;
import com.habitrpg.android.habitica.HabiticaBaseApplication;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.helpers.TaskFilterHelper;
import com.habitrpg.android.habitica.models.tasks.Task;
import com.habitrpg.android.habitica.ui.viewHolders.tasks.DailyViewHolder;
public class DailiesRecyclerViewHolder extends SortableTasksRecyclerViewAdapter<DailyViewHolder> {
import io.realm.OrderedRealmCollection;
public class DailiesRecyclerViewHolder extends RealmBaseTasksRecyclerViewAdapter<DailyViewHolder> {
public int dailyResetOffset;
public DailiesRecyclerViewHolder(String taskType, TaskFilterHelper taskFilterHelper, int layoutResource,
Context newContext, String userID, int dailyResetOffset,
@Nullable SortTasksCallback sortTasksCallback) {
super(taskType, taskFilterHelper, layoutResource, newContext, userID, sortTasksCallback);
public DailiesRecyclerViewHolder(@Nullable OrderedRealmCollection<Task> data, boolean autoUpdate, int layoutResource, int dailyResetOffset) {
super(data, autoUpdate, layoutResource);
this.dailyResetOffset = dailyResetOffset;
}
@ -24,10 +25,4 @@ public class DailiesRecyclerViewHolder extends SortableTasksRecyclerViewAdapter<
public DailyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new DailyViewHolder(getContentView(parent), dailyResetOffset);
}
@Override
protected void injectThis(AppComponent component) {
HabiticaBaseApplication.getComponent().inject(this);
}
}

View file

@ -7,22 +7,20 @@ import android.view.ViewGroup;
import com.habitrpg.android.habitica.HabiticaBaseApplication;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.helpers.TaskFilterHelper;
import com.habitrpg.android.habitica.models.tasks.Task;
import com.habitrpg.android.habitica.ui.viewHolders.tasks.HabitViewHolder;
public class HabitsRecyclerViewAdapter extends SortableTasksRecyclerViewAdapter<HabitViewHolder> {
import io.realm.OrderedRealmCollection;
public class HabitsRecyclerViewAdapter extends RealmBaseTasksRecyclerViewAdapter<HabitViewHolder> {
public HabitsRecyclerViewAdapter(String taskType, TaskFilterHelper taskFilterHelper, int layoutResource, Context newContext, String userID, @Nullable SortTasksCallback sortCallback) {
super(taskType, taskFilterHelper, layoutResource, newContext, userID, sortCallback);
public HabitsRecyclerViewAdapter(@Nullable OrderedRealmCollection<Task> data, boolean autoUpdate, int layoutResource) {
super(data, autoUpdate, layoutResource);
}
@Override
public HabitViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new HabitViewHolder(getContentView(parent));
}
@Override
protected void injectThis(AppComponent component) {
HabiticaBaseApplication.getComponent().inject(this);
}
}

View file

@ -0,0 +1,43 @@
package com.habitrpg.android.habitica.ui.adapter.tasks;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.habitrpg.android.habitica.models.tasks.Task;
import com.habitrpg.android.habitica.ui.viewHolders.tasks.BaseTaskViewHolder;
import io.realm.OrderedRealmCollection;
import io.realm.RealmRecyclerViewAdapter;
public abstract class RealmBaseTasksRecyclerViewAdapter<VH extends BaseTaskViewHolder> extends RealmRecyclerViewAdapter<Task, VH> {
private final int layoutResource;
public RealmBaseTasksRecyclerViewAdapter(@Nullable OrderedRealmCollection<Task> data, boolean autoUpdate, int layoutResource) {
super(data, autoUpdate);
this.layoutResource = layoutResource;
}
@Override
public VH onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(VH holder, int position) {
Task item = getItem(position);
if (item != null) {
holder.bindHolder(item, position);
}
}
View getContentView(ViewGroup parent) {
return getContentView(parent, layoutResource);
}
protected View getContentView(ViewGroup parent, int layoutResource) {
return LayoutInflater.from(parent.getContext()).inflate(layoutResource, parent, false);
}
}

View file

@ -71,7 +71,6 @@ public class RemindersAdapter extends RecyclerView.Adapter<RemindersAdapter.Item
@Override
public void onItemDismiss(int position) {
if (position >= 0 && position < reminders.size()) {
reminders.get(position).async().delete();
reminders.remove(position);
notifyItemRemoved(position);
}

View file

@ -18,20 +18,22 @@ import com.habitrpg.android.habitica.ui.viewHolders.tasks.RewardViewHolder;
import java.util.ArrayList;
import java.util.List;
import io.realm.OrderedRealmCollection;
import rx.Observable;
public class RewardsRecyclerViewAdapter extends BaseTasksRecyclerViewAdapter<RewardViewHolder> {
public class RewardsRecyclerViewAdapter extends RealmBaseTasksRecyclerViewAdapter<RewardViewHolder> {
private final InventoryRepository inventoryRepository;
private final Context context;
private InventoryRepository inventoryRepository;
@Nullable
private final HabitRPGUser user;
private HabitRPGUser user;
public RewardsRecyclerViewAdapter(String taskType, TaskFilterHelper taskFilterHelper, int layoutResource, Context newContext, @Nullable HabitRPGUser user, InventoryRepository inventoryRepository) {
super(taskType, taskFilterHelper, layoutResource, newContext, user != null ? user.getId() : null);
this.user = user;
this.inventoryRepository = inventoryRepository;
public RewardsRecyclerViewAdapter(@Nullable OrderedRealmCollection<Task> data, boolean autoUpdate, int layoutResource, Context context) {
super(data, autoUpdate, layoutResource);
this.context = context;
}
@Override
public RewardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new RewardViewHolder(getContentView(parent));
@ -79,21 +81,9 @@ public class RewardsRecyclerViewAdapter extends BaseTasksRecyclerViewAdapter<Rew
}, throwable -> {}));
})
.subscribe(items -> {
this.filteredContent.addAll(items);
notifyDataSetChanged();
}, throwable -> {
});
}
}
@Override
protected void injectThis(AppComponent component) {
HabiticaBaseApplication.getComponent().inject(this);
}
@Override
public void setTasks(List<Task> tasks) {
super.setTasks(tasks);
this.loadEquipmentRewards();
}
}

View file

@ -7,13 +7,16 @@ import android.view.ViewGroup;
import com.habitrpg.android.habitica.HabiticaBaseApplication;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.helpers.TaskFilterHelper;
import com.habitrpg.android.habitica.models.tasks.Task;
import com.habitrpg.android.habitica.ui.viewHolders.tasks.TodoViewHolder;
public class TodosRecyclerViewAdapter extends SortableTasksRecyclerViewAdapter<TodoViewHolder> {
import io.realm.OrderedRealmCollection;
public TodosRecyclerViewAdapter(String taskType, TaskFilterHelper taskFilterHelper, int layoutResource,
Context newContext, String userID, @Nullable SortTasksCallback sortCallback) {
super(taskType, taskFilterHelper, layoutResource, newContext, userID, sortCallback);
public class TodosRecyclerViewAdapter extends RealmBaseTasksRecyclerViewAdapter<TodoViewHolder> {
public TodosRecyclerViewAdapter(@Nullable OrderedRealmCollection<Task> data, boolean autoUpdate, int layoutResource) {
super(data, autoUpdate, layoutResource);
}
@Override
@ -21,8 +24,4 @@ public class TodosRecyclerViewAdapter extends SortableTasksRecyclerViewAdapter<T
return new TodoViewHolder(getContentView(parent));
}
@Override
protected void injectThis(AppComponent component) {
HabiticaBaseApplication.getComponent().inject(this);
}
}

View file

@ -19,6 +19,7 @@ import com.habitrpg.android.habitica.callbacks.HabitRPGUserCallback;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.data.ApiClient;
import com.habitrpg.android.habitica.data.InventoryRepository;
import com.habitrpg.android.habitica.data.TaskRepository;
import com.habitrpg.android.habitica.data.UserRepository;
import com.habitrpg.android.habitica.events.TaskCreatedEvent;
import com.habitrpg.android.habitica.events.TaskRemovedEvent;
@ -34,6 +35,7 @@ import com.habitrpg.android.habitica.ui.activities.MainActivity;
import com.habitrpg.android.habitica.ui.adapter.tasks.BaseTasksRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.DailiesRecyclerViewHolder;
import com.habitrpg.android.habitica.ui.adapter.tasks.HabitsRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.RealmBaseTasksRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.SortableTasksRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.TodosRecyclerViewAdapter;
@ -54,6 +56,7 @@ import javax.inject.Named;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.realm.RealmList;
/**
* TaskRecyclerViewFragment
@ -63,7 +66,7 @@ import butterknife.ButterKnife;
*/
public class TaskRecyclerViewFragment extends BaseFragment implements View.OnClickListener, SwipeRefreshLayout.OnRefreshListener {
private static final String CLASS_TYPE_KEY = "CLASS_TYPE_KEY";
public BaseTasksRecyclerViewAdapter recyclerAdapter;
public RealmBaseTasksRecyclerViewAdapter recyclerAdapter;
@Inject
@Named(AppModule.NAMED_USER_ID)
String userID;
@ -75,6 +78,8 @@ public class TaskRecyclerViewFragment extends BaseFragment implements View.OnCli
UserRepository userRepository;
@Inject
InventoryRepository inventoryRepository;
@Inject
TaskRepository taskRepository;
LinearLayoutManager layoutManager = null;
@ -147,33 +152,35 @@ public class TaskRecyclerViewFragment extends BaseFragment implements View.OnCli
// TODO needs a bit of cleanup
public void setInnerAdapter() {
int layoutOfType;
if (this.classType != null) {
switch (this.classType) {
case Task.TYPE_HABIT:
layoutOfType = R.layout.habit_item_card;
this.recyclerAdapter = new HabitsRecyclerViewAdapter(Task.TYPE_HABIT, taskFilterHelper, layoutOfType, getContext(), userID, sortCallback);
allowReordering();
break;
case Task.TYPE_DAILY:
layoutOfType = R.layout.daily_item_card;
int dailyResetOffset = 0;
if (user != null) {
dailyResetOffset = user.getPreferences().getDayStart();
}
this.recyclerAdapter = new DailiesRecyclerViewHolder(Task.TYPE_DAILY, taskFilterHelper, layoutOfType, getContext(), userID, dailyResetOffset, sortCallback);
allowReordering();
break;
case Task.TYPE_TODO:
layoutOfType = R.layout.todo_item_card;
this.recyclerAdapter = new TodosRecyclerViewAdapter(Task.TYPE_TODO, taskFilterHelper, layoutOfType, getContext(), userID, sortCallback);
allowReordering();
return;
case Task.TYPE_REWARD:
layoutOfType = R.layout.reward_item_card;
this.recyclerAdapter = new RewardsRecyclerViewAdapter(Task.TYPE_REWARD, taskFilterHelper, layoutOfType, getContext(), user, inventoryRepository);
break;
}
taskRepository.getTasks(this.classType, userID).first().subscribe(tasks -> {
int layoutOfType;
switch (this.classType) {
case Task.TYPE_HABIT:
layoutOfType = R.layout.habit_item_card;
this.recyclerAdapter = new HabitsRecyclerViewAdapter(tasks, true, layoutOfType);
allowReordering();
break;
case Task.TYPE_DAILY:
layoutOfType = R.layout.daily_item_card;
int dailyResetOffset = 0;
if (user != null) {
dailyResetOffset = user.getPreferences().getDayStart();
}
this.recyclerAdapter = new DailiesRecyclerViewHolder(tasks, true, layoutOfType, dailyResetOffset);
allowReordering();
break;
case Task.TYPE_TODO:
layoutOfType = R.layout.todo_item_card;
this.recyclerAdapter = new TodosRecyclerViewAdapter(tasks, true, layoutOfType);
allowReordering();
return;
case Task.TYPE_REWARD:
layoutOfType = R.layout.reward_item_card;
this.recyclerAdapter = new RewardsRecyclerViewAdapter(tasks, true, layoutOfType, getContext());
break;
}
});
}
}
@ -336,31 +343,6 @@ public class TaskRecyclerViewFragment extends BaseFragment implements View.OnCli
return this.classType != null ? this.classType : "";
}
@Subscribe
public void onEvent(FilterTasksByTagsCommand cmd) {
recyclerAdapter.filter();
}
@Subscribe
public void onEvent(TaskCheckedCommand event) {
recyclerAdapter.checkTask(event.Task, event.completed);
}
@Subscribe
public void onEvent(TaskUpdatedEvent event) {
recyclerAdapter.updateTask(event.task);
}
@Subscribe
public void onEvent(TaskCreatedEvent event) {
recyclerAdapter.addTask(event.task);
}
@Subscribe
public void onEvent(TaskRemovedEvent event) {
recyclerAdapter.removeTask(event.deletedTaskId);
}
@Override
public void onRefresh() {
swipeRefreshLayout.setRefreshing(true);
@ -376,6 +358,6 @@ public class TaskRecyclerViewFragment extends BaseFragment implements View.OnCli
if (classType != null) {
taskFilterHelper.setActiveFilter(classType, activeFilter);
}
recyclerAdapter.filter();
//recyclerAdapter.filter();
}
}

View file

@ -37,6 +37,7 @@ import com.habitrpg.android.habitica.ui.activities.MainActivity;
import com.habitrpg.android.habitica.ui.activities.TaskFormActivity;
import com.habitrpg.android.habitica.ui.adapter.tasks.BaseTasksRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.DailiesRecyclerViewHolder;
import com.habitrpg.android.habitica.ui.adapter.tasks.RealmBaseTasksRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.SortableTasksRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
import com.habitrpg.android.habitica.ui.views.tasks.TaskFilterDialog;
@ -164,7 +165,7 @@ public class TasksFragment extends BaseMainFragment {
private void showFilterDialog() {
TaskFilterDialog dialog = new TaskFilterDialog(getContext(), HabiticaBaseApplication.getComponent());
if (user != null) {
dialog.setTags(user.getTags());
//dialog.setTags();
}
dialog.setActiveTags(taskFilterHelper.getTags());
if (getActiveFragment() != null) {
@ -176,10 +177,10 @@ public class TasksFragment extends BaseMainFragment {
dialog.setListener((activeTaskFilter, activeTags) -> {
int activePos = viewPager.getCurrentItem();
if (activePos >= 1 && viewFragmentsDictionary.get(activePos-1).recyclerAdapter != null) {
viewFragmentsDictionary.get(activePos-1).recyclerAdapter.filter();
//viewFragmentsDictionary.get(activePos-1).recyclerAdapter.filter();
}
if (activePos < viewPager.getAdapter().getCount()-1 && viewFragmentsDictionary.get(activePos+1).recyclerAdapter != null) {
viewFragmentsDictionary.get(activePos+1).recyclerAdapter.filter();
//viewFragmentsDictionary.get(activePos+1).recyclerAdapter.filter();
}
if (getActiveFragment() != null) {
getActiveFragment().setActiveFilter(activeTaskFilter);
@ -351,12 +352,12 @@ public class TasksFragment extends BaseMainFragment {
for (int index = 0; index < viewFragmentsDictionary.size(); index++) {
TaskRecyclerViewFragment fragment = viewFragmentsDictionary.get(index);
if (fragment != null) {
BaseTasksRecyclerViewAdapter adapter = fragment.recyclerAdapter;
RealmBaseTasksRecyclerViewAdapter adapter = fragment.recyclerAdapter;
if (adapter.getClass().equals(DailiesRecyclerViewHolder.class)) {
final DailiesRecyclerViewHolder dailyAdapter = (DailiesRecyclerViewHolder) fragment.recyclerAdapter;
dailyAdapter.dailyResetOffset = this.user.getPreferences().getDayStart();
}
AsyncTask.execute(() -> adapter.loadContent(true));
//AsyncTask.execute(() -> adapter.loadContent(true));
}
}
}

View file

@ -95,16 +95,20 @@ public abstract class BaseTaskViewHolder extends RecyclerView.ViewHolder impleme
} else {
this.titleTextView.setText(this.task.getText());
this.notesTextView.setText(this.task.getNotes());
Observable.just(this.task)
.map(task1 -> {
task.parsedText = MarkdownParser.parseMarkdown(task.getText());
task.parsedNotes = MarkdownParser.parseMarkdown(task.getNotes());
return task;
})
Observable.just(this.task.getText())
.map(MarkdownParser::parseMarkdown)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(task2 -> {
.subscribe(parsedText -> {
this.task.parsedText = parsedText;
this.titleTextView.setText(this.task.parsedText);
}, Throwable::printStackTrace);
Observable.just(this.task.getNotes())
.map(MarkdownParser::parseMarkdown)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(parsedNotes -> {
this.task.parsedNotes = parsedNotes;
this.notesTextView.setText(this.task.parsedNotes);
}, Throwable::printStackTrace);
}

View file

@ -148,8 +148,6 @@ public abstract class ChecklistedViewHolder extends BaseTaskViewHolder implement
// it needs to be changed after the event is send -> to the server
// maybe a refactor is needed here
EventBus.getDefault().post(event);
task.completed = event.completed;
task.save();
}
} else {
View v = (View) buttonView.getParent();

View file

@ -12,15 +12,14 @@ import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import io.realm.RealmList;
public class TaskTagDeserializer implements JsonDeserializer<List<TaskTag>> {
@Override
public List<TaskTag> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
List<TaskTag> taskTags = new ArrayList<>();
List<Tag> allTags;
List<TaskTag> taskTags = new RealmList<>();
List<Tag> allTags = new ArrayList<>();
try {
allTags = new Select()
.from(Tag.class)
.queryList();
} catch (RuntimeException e) {
//Tests don't have a database
allTags = new ArrayList<>();

View file

@ -11,6 +11,7 @@ import android.widget.RemoteViews;
import com.habitrpg.android.habitica.HabiticaBaseApplication;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.data.TaskRepository;
import com.habitrpg.android.habitica.models.responses.TaskDirection;
import com.habitrpg.android.habitica.modules.AppModule;
import javax.inject.Inject;
@ -74,7 +75,7 @@ public class HabitButtonWidgetProvider extends BaseWidgetProvider {
int[] ids = {appWidgetId};
if (taskId != null) {
taskRepository.postTaskDirection(taskId, direction)
taskRepository.taskChecked(taskId, TaskDirection.up.toString().equals(direction))
.subscribe(taskDirectionData -> {
taskRepository.getTask(taskId).subscribe(task -> {
task.value = task.value + taskDirectionData.getDelta();

View file

@ -50,13 +50,12 @@ public abstract class TaskListWidgetProvider extends BaseWidgetProvider {
public void onReceive(Context context, Intent intent) {
setUp(context);
if (intent.getAction().equals(DAILY_ACTION)) {
AppWidgetManager mgr = AppWidgetManager.getInstance(context);
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
String taskId = intent.getStringExtra(TASK_ID_ITEM);
if (taskId != null) {
taskRepository.postTaskDirection(taskId, TaskDirection.up.toString())
taskRepository.taskChecked(taskId, true)
.subscribe(taskDirectionData -> {
taskRepository.markTaskCompleted(taskId, true);
showToastForTaskDirection(context, taskDirectionData, userId);

View file

@ -9,6 +9,8 @@ buildscript {
classpath 'com.android.databinding:dataBinder:1.0-rc4'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
classpath 'com.google.gms:google-services:3.0.0'
classpath "io.realm:realm-gradle-plugin:3.1.3"
}
}