mirror of https://github.com/tasks/tasks
Convert Astrid2TaskProvider to Kotlin
parent
94787c7d1d
commit
e94d230d1b
@ -1,246 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.provider;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.todoroo.astrid.dao.TaskDao;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import dagger.hilt.EntryPoint;
|
||||
import dagger.hilt.InstallIn;
|
||||
import dagger.hilt.android.EntryPointAccessors;
|
||||
import dagger.hilt.android.components.ApplicationComponent;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import org.tasks.BuildConfig;
|
||||
import org.tasks.R;
|
||||
import org.tasks.analytics.Firebase;
|
||||
import org.tasks.data.TagDao;
|
||||
import org.tasks.data.TagData;
|
||||
import org.tasks.data.TagDataDao;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* This is the legacy Astrid task provider. While it will continue to be supported, note that it
|
||||
* does not expose all of the information in Astrid, nor does it support many editing operations.
|
||||
*
|
||||
* <p>See the individual methods for a description of what is returned.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*/
|
||||
public class Astrid2TaskProvider extends ContentProvider {
|
||||
|
||||
@EntryPoint
|
||||
@InstallIn(ApplicationComponent.class)
|
||||
public interface Astrid2TaskProviderEntryPoint {
|
||||
TagDataDao getTagDataDao();
|
||||
TaskDao getTaskDao();
|
||||
TagDao getTagDao();
|
||||
Firebase getFirebase();
|
||||
}
|
||||
|
||||
private static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".tasksprovider";
|
||||
|
||||
private static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
|
||||
|
||||
private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
|
||||
private static final String NAME = "name";
|
||||
private static final String IMPORTANCE_COLOR = "importance_color";
|
||||
private static final String IDENTIFIER = "identifier";
|
||||
private static final String PREFERRED_DUE_DATE = "preferredDueDate";
|
||||
private static final String DEFINITE_DUE_DATE = "definiteDueDate";
|
||||
private static final String IMPORTANCE = "importance";
|
||||
private static final String ID = "id";
|
||||
|
||||
private static final String TAGS_ID = "tags_id";
|
||||
|
||||
private static final String[] TASK_FIELD_LIST =
|
||||
new String[] {
|
||||
NAME,
|
||||
IMPORTANCE_COLOR,
|
||||
PREFERRED_DUE_DATE,
|
||||
DEFINITE_DUE_DATE,
|
||||
IMPORTANCE,
|
||||
IDENTIFIER,
|
||||
TAGS_ID
|
||||
};
|
||||
|
||||
private static final String[] TAGS_FIELD_LIST = new String[] {ID, NAME};
|
||||
|
||||
private static final int URI_TASKS = 0;
|
||||
private static final int URI_TAGS = 1;
|
||||
|
||||
private static final String TAG_SEPARATOR = "|";
|
||||
|
||||
static {
|
||||
URI_MATCHER.addURI(AUTHORITY, "tasks", URI_TASKS);
|
||||
URI_MATCHER.addURI(AUTHORITY, "tags", URI_TAGS);
|
||||
}
|
||||
|
||||
public static void notifyDatabaseModification(Context context) {
|
||||
try {
|
||||
context.getContentResolver().notifyChange(CONTENT_URI, null);
|
||||
} catch (Exception e) {
|
||||
Timber.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(@NonNull Uri uri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(@NonNull Uri uri, ContentValues values) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private Astrid2TaskProviderEntryPoint hilt() {
|
||||
return EntryPointAccessors.fromApplication(
|
||||
getContext().getApplicationContext(), Astrid2TaskProviderEntryPoint.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: tag id is no longer a real column, so we pass in a UID generated from the tag string.
|
||||
*
|
||||
* @return two-column cursor: tag id (string) and tag name
|
||||
*/
|
||||
private Cursor getTags() {
|
||||
List<TagData> tags = hilt().getTagDataDao().tagDataOrderedByName();
|
||||
|
||||
MatrixCursor ret = new MatrixCursor(TAGS_FIELD_LIST);
|
||||
|
||||
for (TagData tag : tags) {
|
||||
Object[] values = new Object[2];
|
||||
values[0] = tagNameToLong(tag.getName());
|
||||
values[1] = tag.getName();
|
||||
|
||||
ret.addRow(values);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private long tagNameToLong(String tag) {
|
||||
MessageDigest m;
|
||||
try {
|
||||
m = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Timber.e(e);
|
||||
return -1;
|
||||
}
|
||||
|
||||
m.update(tag.getBytes(), 0, tag.length());
|
||||
return new BigInteger(1, m.digest()).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cursor with the following columns
|
||||
*
|
||||
* <ol>
|
||||
* <li>task title, string
|
||||
* <li>task importance color, int android RGB color
|
||||
* <li>task due date (was: preferred due date), long millis since epoch
|
||||
* <li>task due date (was: absolute due date), long millis since epoch
|
||||
* <li>task importance, integer from 0 to 3 (0 => most important)
|
||||
* <li>task id, long
|
||||
* <li>task tags, string tags separated by |
|
||||
* </ol>
|
||||
*
|
||||
* @return cursor as described above
|
||||
*/
|
||||
private Cursor getTasks() {
|
||||
Astrid2TaskProviderEntryPoint hilt = hilt();
|
||||
hilt.getFirebase().logEvent(R.string.event_query_legacy_content_provider);
|
||||
List<Task> tasks = hilt.getTaskDao().getAstrid2TaskProviderTasks();
|
||||
MatrixCursor ret = new MatrixCursor(TASK_FIELD_LIST);
|
||||
for (Task task : tasks) {
|
||||
String taskTags = getTagsAsString(task.getId(), TAG_SEPARATOR);
|
||||
|
||||
Object[] values = new Object[7];
|
||||
values[0] = task.getTitle();
|
||||
values[1] = getPriorityColor(getContext(), task.getPriority());
|
||||
values[2] = task.getDueDate();
|
||||
values[3] = task.getDueDate();
|
||||
values[4] = task.getPriority();
|
||||
values[5] = task.getId();
|
||||
values[6] = taskTags;
|
||||
|
||||
ret.addRow(values);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static int getPriorityColor(Context context, int priority) {
|
||||
return context.getColor(getPriorityResId(priority));
|
||||
}
|
||||
|
||||
@ColorRes private static int getPriorityResId(int priority) {
|
||||
if (priority <= 0) {
|
||||
return R.color.red_500;
|
||||
} else if (priority == 1) {
|
||||
return R.color.amber_500;
|
||||
} else if (priority == 2) {
|
||||
return R.color.blue_500;
|
||||
} else {
|
||||
return R.color.grey_500;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(
|
||||
@NonNull Uri uri,
|
||||
String[] projection,
|
||||
String selection,
|
||||
String[] selectionArgs,
|
||||
String sortOrder) {
|
||||
switch (URI_MATCHER.match(uri)) {
|
||||
case URI_TASKS:
|
||||
return getTasks();
|
||||
case URI_TAGS:
|
||||
return getTags();
|
||||
default:
|
||||
throw new IllegalStateException("Unrecognized URI:" + uri);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(
|
||||
@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
throw new UnsupportedOperationException("not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return tags as a list of strings separated by given separator
|
||||
*
|
||||
* @return empty string if no tags, otherwise string
|
||||
*/
|
||||
private String getTagsAsString(long taskId, String separator) {
|
||||
return Joiner.on(separator).join(hilt().getTagDao().getTagNames(taskId));
|
||||
}
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.provider
|
||||
|
||||
import android.content.ContentProvider
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.UriMatcher
|
||||
import android.database.Cursor
|
||||
import android.database.MatrixCursor
|
||||
import android.net.Uri
|
||||
import androidx.annotation.ColorRes
|
||||
import com.todoroo.astrid.dao.TaskDao
|
||||
import dagger.hilt.EntryPoint
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.EntryPointAccessors
|
||||
import dagger.hilt.android.components.ApplicationComponent
|
||||
import org.tasks.BuildConfig
|
||||
import org.tasks.R
|
||||
import org.tasks.analytics.Firebase
|
||||
import org.tasks.data.TagDao
|
||||
import org.tasks.data.TagDataDao
|
||||
import timber.log.Timber
|
||||
import java.math.BigInteger
|
||||
import java.security.MessageDigest
|
||||
import java.security.NoSuchAlgorithmException
|
||||
|
||||
/**
|
||||
* This is the legacy Astrid task provider. While it will continue to be supported, note that it
|
||||
* does not expose all of the information in Astrid, nor does it support many editing operations.
|
||||
*
|
||||
*
|
||||
* See the individual methods for a description of what is returned.
|
||||
*
|
||||
* @author Tim Su <tim></tim>@todoroo.com>
|
||||
*/
|
||||
class Astrid2TaskProvider : ContentProvider() {
|
||||
@EntryPoint
|
||||
@InstallIn(ApplicationComponent::class)
|
||||
interface Astrid2TaskProviderEntryPoint {
|
||||
val tagDataDao: TagDataDao
|
||||
val taskDao: TaskDao
|
||||
val tagDao: TagDao
|
||||
val firebase: Firebase
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val AUTHORITY = BuildConfig.APPLICATION_ID + ".tasksprovider"
|
||||
private val CONTENT_URI = Uri.parse("content://$AUTHORITY")
|
||||
private val URI_MATCHER = UriMatcher(UriMatcher.NO_MATCH)
|
||||
private const val NAME = "name"
|
||||
private const val IMPORTANCE_COLOR = "importance_color"
|
||||
private const val IDENTIFIER = "identifier"
|
||||
private const val PREFERRED_DUE_DATE = "preferredDueDate"
|
||||
private const val DEFINITE_DUE_DATE = "definiteDueDate"
|
||||
private const val IMPORTANCE = "importance"
|
||||
private const val ID = "id"
|
||||
private const val TAGS_ID = "tags_id"
|
||||
private val TASK_FIELD_LIST = arrayOf(
|
||||
NAME,
|
||||
IMPORTANCE_COLOR,
|
||||
PREFERRED_DUE_DATE,
|
||||
DEFINITE_DUE_DATE,
|
||||
IMPORTANCE,
|
||||
IDENTIFIER,
|
||||
TAGS_ID
|
||||
)
|
||||
private val TAGS_FIELD_LIST = arrayOf(ID, NAME)
|
||||
private const val URI_TASKS = 0
|
||||
private const val URI_TAGS = 1
|
||||
private const val TAG_SEPARATOR = "|"
|
||||
@JvmStatic
|
||||
fun notifyDatabaseModification(context: Context) {
|
||||
try {
|
||||
context.contentResolver.notifyChange(CONTENT_URI, null)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPriorityColor(context: Context?, priority: Int): Int {
|
||||
return context!!.getColor(getPriorityResId(priority))
|
||||
}
|
||||
|
||||
@ColorRes
|
||||
private fun getPriorityResId(priority: Int): Int {
|
||||
return when {
|
||||
priority <= 0 -> R.color.red_500
|
||||
priority == 1 -> R.color.amber_500
|
||||
priority == 2 -> R.color.blue_500
|
||||
else -> R.color.grey_500
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
URI_MATCHER.addURI(AUTHORITY, "tasks", URI_TASKS)
|
||||
URI_MATCHER.addURI(AUTHORITY, "tags", URI_TAGS)
|
||||
}
|
||||
}
|
||||
|
||||
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?) = 0
|
||||
|
||||
override fun getType(uri: Uri): String? = null
|
||||
|
||||
override fun insert(uri: Uri, values: ContentValues?): Uri? = null
|
||||
|
||||
override fun onCreate() = true
|
||||
|
||||
private fun hilt(): Astrid2TaskProviderEntryPoint {
|
||||
return EntryPointAccessors.fromApplication(
|
||||
context!!.applicationContext, Astrid2TaskProviderEntryPoint::class.java)
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: tag id is no longer a real column, so we pass in a UID generated from the tag string.
|
||||
*
|
||||
* @return two-column cursor: tag id (string) and tag name
|
||||
*/
|
||||
private val tags: Cursor
|
||||
get() {
|
||||
val tags = hilt().tagDataDao.tagDataOrderedByName()
|
||||
val ret = MatrixCursor(TAGS_FIELD_LIST)
|
||||
for (tag in tags) {
|
||||
val values = arrayOfNulls<Any>(2)
|
||||
values[0] = tagNameToLong(tag.name)
|
||||
values[1] = tag.name
|
||||
ret.addRow(values)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
private fun tagNameToLong(tag: String?): Long {
|
||||
val m: MessageDigest
|
||||
m = try {
|
||||
MessageDigest.getInstance("MD5")
|
||||
} catch (e: NoSuchAlgorithmException) {
|
||||
Timber.e(e)
|
||||
return -1
|
||||
}
|
||||
m.update(tag!!.toByteArray(), 0, tag.length)
|
||||
return BigInteger(1, m.digest()).toLong()
|
||||
}
|
||||
|
||||
/**
|
||||
* Cursor with the following columns
|
||||
*
|
||||
*
|
||||
* 1. task title, string
|
||||
* 1. task importance color, int android RGB color
|
||||
* 1. task due date (was: preferred due date), long millis since epoch
|
||||
* 1. task due date (was: absolute due date), long millis since epoch
|
||||
* 1. task importance, integer from 0 to 3 (0 => most important)
|
||||
* 1. task id, long
|
||||
* 1. task tags, string tags separated by |
|
||||
*
|
||||
*
|
||||
* @return cursor as described above
|
||||
*/
|
||||
private val tasks: Cursor
|
||||
get() {
|
||||
val hilt = hilt()
|
||||
hilt.firebase.logEvent(R.string.event_query_legacy_content_provider)
|
||||
val tasks = hilt.taskDao.getAstrid2TaskProviderTasks()
|
||||
val ret = MatrixCursor(TASK_FIELD_LIST)
|
||||
for (task in tasks) {
|
||||
val taskTags = getTagsAsString(task.id, TAG_SEPARATOR)
|
||||
val values = arrayOfNulls<Any>(7)
|
||||
values[0] = task.title
|
||||
values[1] = getPriorityColor(context, task.priority)
|
||||
values[2] = task.dueDate
|
||||
values[3] = task.dueDate
|
||||
values[4] = task.priority
|
||||
values[5] = task.id
|
||||
values[6] = taskTags
|
||||
ret.addRow(values)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
override fun query(
|
||||
uri: Uri,
|
||||
projection: Array<String>?,
|
||||
selection: String?,
|
||||
selectionArgs: Array<String>?,
|
||||
sortOrder: String?): Cursor? {
|
||||
return when (URI_MATCHER.match(uri)) {
|
||||
URI_TASKS -> tasks
|
||||
URI_TAGS -> tags
|
||||
else -> throw IllegalStateException("Unrecognized URI:$uri")
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(
|
||||
uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int {
|
||||
throw UnsupportedOperationException("not supported")
|
||||
}
|
||||
|
||||
/**
|
||||
* Return tags as a list of strings separated by given separator
|
||||
*
|
||||
* @return empty string if no tags, otherwise string
|
||||
*/
|
||||
private fun getTagsAsString(taskId: Long, separator: String) =
|
||||
hilt().tagDao.getTagNames(taskId).joinToString(separator)
|
||||
}
|
Loading…
Reference in New Issue