diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 1868e48..e5f374d 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/build.gradle b/app/build.gradle index 178119f..8e3a0a1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,6 +10,11 @@ android { targetSdkVersion 28 versionCode 28 versionName "1.7" + javaCompileOptions { + annotationProcessorOptions { + arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] + } + } } buildTypes { release { @@ -40,7 +45,21 @@ dependencies { implementation 'net.danlew:android.joda:2.9.7' implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2' testImplementation 'junit:junit:4.12' + + // App Center def appCenterSdkVersion = '1.9.0' implementation "com.microsoft.appcenter:appcenter-analytics:${appCenterSdkVersion}" implementation "com.microsoft.appcenter:appcenter-crashes:${appCenterSdkVersion}" + + // Room components + def roomVersion = "2.1.0-alpha02" + implementation "androidx.room:room-runtime:$roomVersion" + annotationProcessor "androidx.room:room-compiler:$roomVersion" + testImplementation "androidx.room:room-testing:$roomVersion" + + // Lifecycle components + def archLifecycleVersion = '2.0.0' + implementation "android.arch.lifecycle:extensions:$archLifecycleVersion" + annotationProcessor "android.arch.lifecycle:compiler:$archLifecycleVersion" + } diff --git a/app/src/main/java/com/wismna/geoffroy/donext/dao/Task.java b/app/src/main/java/com/wismna/geoffroy/donext/dao/Task.java index 2cfbc42..664f34b 100644 --- a/app/src/main/java/com/wismna/geoffroy/donext/dao/Task.java +++ b/app/src/main/java/com/wismna/geoffroy/donext/dao/Task.java @@ -8,6 +8,8 @@ import org.joda.time.LocalDate; * Created by geoffroy on 15-11-25. * Data access object class that represents a Task */ + +@Deprecated public class Task { private long id; private String name; diff --git a/app/src/main/java/com/wismna/geoffroy/donext/dao/TaskList.java b/app/src/main/java/com/wismna/geoffroy/donext/dao/TaskList.java index a38ad2a..fb09136 100644 --- a/app/src/main/java/com/wismna/geoffroy/donext/dao/TaskList.java +++ b/app/src/main/java/com/wismna/geoffroy/donext/dao/TaskList.java @@ -6,6 +6,8 @@ import androidx.annotation.NonNull; * Created by geoffroy on 15-11-25. * Data access object class that represents a Task List */ + +@Deprecated public class TaskList { private long id; private String name; diff --git a/app/src/main/java/com/wismna/geoffroy/donext/data/AppDatabase.java b/app/src/main/java/com/wismna/geoffroy/donext/data/AppDatabase.java new file mode 100644 index 0000000..6d55e11 --- /dev/null +++ b/app/src/main/java/com/wismna/geoffroy/donext/data/AppDatabase.java @@ -0,0 +1,32 @@ +package com.wismna.geoffroy.donext.data; + +import android.content.Context; + +import androidx.room.Database; +import androidx.room.Room; +import androidx.room.RoomDatabase; +import androidx.room.TypeConverters; + +@Database(entities = {Task.class, TaskList.class}, views = {TodayTasksView.class}, version = 6) +@TypeConverters({Converters.class}) +public abstract class AppDatabase extends RoomDatabase { + public abstract TaskDao taskDao(); + public abstract TaskListDao taskListDao(); + + private static volatile AppDatabase INSTANCE; + + public static AppDatabase getDatabase(final Context context) { + if (INSTANCE == null) { + synchronized (AppDatabase.class) { + if (INSTANCE == null) { + INSTANCE = Room.databaseBuilder(context.getApplicationContext(), + AppDatabase.class, "donext.db") + .addMigrations(Migrations.MIGRATION_1_2, Migrations.MIGRATION_2_3, + Migrations.MIGRATION_3_4, Migrations.MIGRATION_4_6) + .build(); + } + } + } + return INSTANCE; + } +} diff --git a/app/src/main/java/com/wismna/geoffroy/donext/data/Converters.java b/app/src/main/java/com/wismna/geoffroy/donext/data/Converters.java new file mode 100644 index 0000000..f2d830a --- /dev/null +++ b/app/src/main/java/com/wismna/geoffroy/donext/data/Converters.java @@ -0,0 +1,17 @@ +package com.wismna.geoffroy.donext.data; + +import org.joda.time.LocalDate; + +import androidx.room.TypeConverter; + +public class Converters { + @TypeConverter + public static LocalDate fromDateString(String value) { + return LocalDate.parse(value); + } + + @TypeConverter + public static String toLocalDate(LocalDate value) { + return value.toString(); + } +} diff --git a/app/src/main/java/com/wismna/geoffroy/donext/data/Migrations.java b/app/src/main/java/com/wismna/geoffroy/donext/data/Migrations.java new file mode 100644 index 0000000..df23b99 --- /dev/null +++ b/app/src/main/java/com/wismna/geoffroy/donext/data/Migrations.java @@ -0,0 +1,33 @@ +package com.wismna.geoffroy.donext.data; + +import androidx.room.migration.Migration; +import androidx.sqlite.db.SupportSQLiteDatabase; + +public class Migrations { + + static final Migration MIGRATION_1_2 = new Migration(1, 2) { + @Override + public void migrate(SupportSQLiteDatabase database) { + database.execSQL("ALTER TABLE tasklist ADD COLUMN displayorder INTEGER"); + } + }; + static final Migration MIGRATION_2_3 = new Migration(2, 3) { + @Override + public void migrate(SupportSQLiteDatabase database) { + database.execSQL("ALTER TABLE tasklist ADD COLUMN visible INTEGER DEFAULT 1"); + database.execSQL("ALTER TABLE tasks ADD COLUMN duedate DATE"); + } + }; + static final Migration MIGRATION_3_4 = new Migration(3, 4) { + @Override + public void migrate(SupportSQLiteDatabase database) { + database.execSQL("ALTER TABLE tasks ADD COLUMN todaydate DATE"); + } + }; + static final Migration MIGRATION_4_6 = new Migration(4, 6) { + @Override + public void migrate(SupportSQLiteDatabase database) { + database.execSQL("ALTER TABLE tasks ADD COLUMN todayorder INTEGER"); + } + }; +} diff --git a/app/src/main/java/com/wismna/geoffroy/donext/data/Task.java b/app/src/main/java/com/wismna/geoffroy/donext/data/Task.java new file mode 100644 index 0000000..7d6e148 --- /dev/null +++ b/app/src/main/java/com/wismna/geoffroy/donext/data/Task.java @@ -0,0 +1,53 @@ +package com.wismna.geoffroy.donext.data; + +import org.joda.time.LocalDate; + +import androidx.annotation.NonNull; +import androidx.room.ColumnInfo; +import androidx.room.Entity; +import androidx.room.ForeignKey; +import androidx.room.Index; +import androidx.room.PrimaryKey; + +@Entity(tableName = "tasks", + indices = {@Index("list")}, + foreignKeys = @ForeignKey(entity = TaskList.class, + parentColumns = "_id", + childColumns = "list")) +public class Task { + @PrimaryKey(autoGenerate = true) + public long _id; + + @ColumnInfo(name = "name") + public String name; + + @ColumnInfo(name = "description") + public String description; + + @ColumnInfo(name = "cycle") + public int cycle = 0; + + @ColumnInfo(name = "priority") + public int priority = 1; + + @ColumnInfo(name = "done") + public boolean done = false; + + @ColumnInfo(name = "deleted") + public boolean deleted = false; + + @ColumnInfo(name = "displayorder") + public int order; + + @ColumnInfo(name = "todayorder") + public int todayOrder; + + @ColumnInfo(name = "list") + public long taskList; + + @ColumnInfo(name = "duedate") + public LocalDate dueDate; + + @ColumnInfo(name = "todaydate") + public LocalDate todayDate; +} diff --git a/app/src/main/java/com/wismna/geoffroy/donext/data/TaskDao.java b/app/src/main/java/com/wismna/geoffroy/donext/data/TaskDao.java new file mode 100644 index 0000000..f26e2c3 --- /dev/null +++ b/app/src/main/java/com/wismna/geoffroy/donext/data/TaskDao.java @@ -0,0 +1,55 @@ +package com.wismna.geoffroy.donext.data; + +import java.util.List; + +import androidx.lifecycle.LiveData; +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.Query; +import androidx.room.Update; + +@Dao +public interface TaskDao { + + @Insert() + void createTask (Task task); + + @Update() + void updateTask (Task task); + + @Query("SELECT " + + "tasks._id," + + "tasks.name," + + "tasks.todaydate," + + "tasklist.name AS tasklistname " + + " FROM tasks" + + " LEFT JOIN tasklist ON tasks.list = tasklist._id" + + " WHERE tasks.done = 0 AND tasks.deleted = 0") + LiveData> getAllTasks(); + + @Query("SELECT * FROM tasks WHERE list = :id AND done = 0 AND deleted = 0") + LiveData> getAllTasksFromList(long id); + + @Query("SELECT * FROM tasks WHERE list = :id AND done = 1 OR deleted = 1") + LiveData> getAllTasksFromHistoryList(long id); + + // TODO: replace query with view + //@Query("SELECT * FROM todaytasksview WHERE done = 0 AND deleted = 0") + @Query("SELECT * FROM tasks WHERE todaydate = date('now','localtime') AND done = 0 AND deleted = 0") + LiveData> getTodayTasks(); + + // TODO: replace this with item count from recycle view + @Query("SELECT MAX(displayorder) FROM tasks WHERE list = :id") + int getMaxOrder(long id); + + @Query("UPDATE tasks SET displayorder = displayorder - 1" + + " WHERE displayorder > (SELECT displayorder FROM tasks WHERE _id = :id)") + void updateRemainingRowsOrder(long id); + + @Query("UPDATE tasks SET todayorder = todayorder - 1" + + " WHERE todayorder > (SELECT todayorder FROM tasks WHERE _id = :id)") + void updateRemainingRowsTodayOrder(long id); + + @Query("UPDATE tasks SET deleted = 1 WHERE list = :id") + void deleteAllTasks(long id); +} diff --git a/app/src/main/java/com/wismna/geoffroy/donext/data/TaskList.java b/app/src/main/java/com/wismna/geoffroy/donext/data/TaskList.java new file mode 100644 index 0000000..f9f3eb9 --- /dev/null +++ b/app/src/main/java/com/wismna/geoffroy/donext/data/TaskList.java @@ -0,0 +1,25 @@ +package com.wismna.geoffroy.donext.data; + +import androidx.annotation.NonNull; +import androidx.room.ColumnInfo; +import androidx.room.Entity; +import androidx.room.PrimaryKey; + +@Entity(tableName = "tasklist") +public class TaskList { + + @PrimaryKey(autoGenerate = true) + public long _id; + + @ColumnInfo(name = "name") + public String name; + + @ColumnInfo(name = "visible") + public boolean visible = true; + + @ColumnInfo(name = "displayorder") + public int order; + + //@ColumnInfo(name = "taskcount") + public int taskCount; +} diff --git a/app/src/main/java/com/wismna/geoffroy/donext/data/TaskListDao.java b/app/src/main/java/com/wismna/geoffroy/donext/data/TaskListDao.java new file mode 100644 index 0000000..c974574 --- /dev/null +++ b/app/src/main/java/com/wismna/geoffroy/donext/data/TaskListDao.java @@ -0,0 +1,27 @@ +package com.wismna.geoffroy.donext.data; + +import java.util.List; + +import androidx.lifecycle.LiveData; +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.Query; +import androidx.room.Update; + +@Dao +public interface TaskListDao { + + @Insert() + void createTaskList(TaskList taskList); + + @Update() + void updateTaskList(TaskList taskList); + + @Query("SELECT *,(SELECT COUNT(*) FROM tasks WHERE tasks.list = tasklist._id) AS taskcount" + + " FROM tasklist WHERE visible = 1 ORDER BY displayorder ASC ") + LiveData> getVisibleTaskLists(); + + @Query("SELECT *, (SELECT COUNT(*) FROM tasks WHERE tasks.list = tasklist._id AND (tasks.deleted = 1 OR tasks.done = 1)) AS taskcount" + + " FROM tasklist WHERE visible = 0 OR taskcount > 0 ORDER BY displayorder ASC ") + LiveData> getInvisibleTaskLists(); +} diff --git a/app/src/main/java/com/wismna/geoffroy/donext/data/TodayTask.java b/app/src/main/java/com/wismna/geoffroy/donext/data/TodayTask.java new file mode 100644 index 0000000..83f9741 --- /dev/null +++ b/app/src/main/java/com/wismna/geoffroy/donext/data/TodayTask.java @@ -0,0 +1,20 @@ +package com.wismna.geoffroy.donext.data; + +import org.joda.time.LocalDate; + +import androidx.room.ColumnInfo; +import androidx.room.PrimaryKey; + +public class TodayTask { + @PrimaryKey() + public long _id; + + @ColumnInfo(name = "name") + public String name; + + @ColumnInfo(name = "todaydate") + public LocalDate todayDate; + + @ColumnInfo(name = "tasklistname") + public String taskListName; +} diff --git a/app/src/main/java/com/wismna/geoffroy/donext/data/TodayTasksView.java b/app/src/main/java/com/wismna/geoffroy/donext/data/TodayTasksView.java new file mode 100644 index 0000000..e054496 --- /dev/null +++ b/app/src/main/java/com/wismna/geoffroy/donext/data/TodayTasksView.java @@ -0,0 +1,20 @@ +package com.wismna.geoffroy.donext.data; + +import org.joda.time.LocalDate; + +import androidx.room.DatabaseView; + +@DatabaseView("SELECT * FROM tasks WHERE todaydate = date('now','localtime')") +public class TodayTasksView extends Task { + /*public long _id; + public String name; + public String description; + public int cycle; + public int priority; + public boolean done; + public boolean deleted; + public int order; + public int todayOrder; + public long taskList; + public LocalDate dueDate;*/ +} diff --git a/app/src/main/java/com/wismna/geoffroy/donext/database/TaskDataAccess.java b/app/src/main/java/com/wismna/geoffroy/donext/database/TaskDataAccess.java index 42619db..133cf1d 100644 --- a/app/src/main/java/com/wismna/geoffroy/donext/database/TaskDataAccess.java +++ b/app/src/main/java/com/wismna/geoffroy/donext/database/TaskDataAccess.java @@ -16,6 +16,7 @@ import java.util.List; * Created by geoffroy on 15-11-27. * Data access class that handles Tasks */ +@Deprecated public class TaskDataAccess implements AutoCloseable { public enum MODE { READ, diff --git a/app/src/main/java/com/wismna/geoffroy/donext/database/TaskListDataAccess.java b/app/src/main/java/com/wismna/geoffroy/donext/database/TaskListDataAccess.java index b7d1b5a..3d68d1c 100644 --- a/app/src/main/java/com/wismna/geoffroy/donext/database/TaskListDataAccess.java +++ b/app/src/main/java/com/wismna/geoffroy/donext/database/TaskListDataAccess.java @@ -14,6 +14,7 @@ import java.util.List; * Created by geoffroy on 15-11-25. * Data access class that handles Task Lists */ +@Deprecated public class TaskListDataAccess implements AutoCloseable { public enum MODE { READ, diff --git a/app/src/main/java/com/wismna/geoffroy/donext/repositories/TaskRepository.java b/app/src/main/java/com/wismna/geoffroy/donext/repositories/TaskRepository.java new file mode 100644 index 0000000..bccff95 --- /dev/null +++ b/app/src/main/java/com/wismna/geoffroy/donext/repositories/TaskRepository.java @@ -0,0 +1,68 @@ +package com.wismna.geoffroy.donext.repositories; + +import android.app.Application; +import android.os.AsyncTask; + +import com.wismna.geoffroy.donext.data.AppDatabase; +import com.wismna.geoffroy.donext.data.Task; +import com.wismna.geoffroy.donext.data.TaskDao; + +import java.util.List; + +import androidx.lifecycle.LiveData; + +public class TaskRepository { + private TaskDao mTaskDao; + + TaskRepository(Application application) { + AppDatabase db = AppDatabase.getDatabase(application); + mTaskDao = db.taskDao(); + } + + public void insert(Task task) { + new insertAsyncTask(mTaskDao).execute(task); + } + + public void update(Task task) { + new updateAsyncTask(mTaskDao).execute(task); + } + + public LiveData> getTasksInList(long taskId) { + return mTaskDao.getAllTasksFromList(taskId); + } + + public LiveData> getTodayTasks() { + return mTaskDao.getTodayTasks(); + } + + // Async tasks + private static class insertAsyncTask extends AsyncTask { + + private TaskDao mAsyncTaskDao; + + insertAsyncTask(TaskDao dao) { + mAsyncTaskDao = dao; + } + + @Override + protected Void doInBackground(final Task... params) { + mAsyncTaskDao.createTask(params[0]); + return null; + } + } + + private static class updateAsyncTask extends AsyncTask { + + private TaskDao mAsyncTaskDao; + + updateAsyncTask(TaskDao dao) { + mAsyncTaskDao = dao; + } + + @Override + protected Void doInBackground(final Task... params) { + mAsyncTaskDao.updateTask(params[0]); + return null; + } + } +}