mirror of https://github.com/tasks/tasks
Gtasks boilerplate. That's a lot of boilerplate, but it does get better with each iteration. In the future we should extract more of this type of functionality
parent
2c6400ed89
commit
35f5e65adc
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.gtasks;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.todoroo.andlib.service.Autowired;
|
||||
import com.todoroo.andlib.service.ContextManager;
|
||||
import com.todoroo.andlib.service.DependencyInjectionService;
|
||||
import com.todoroo.astrid.api.AstridApiConstants;
|
||||
import com.todoroo.astrid.data.Metadata;
|
||||
|
||||
/**
|
||||
* Exposes Task Details for Remember the Milk:
|
||||
* - RTM list
|
||||
* - RTM repeat information
|
||||
* - RTM notes
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class GtasksDetailExposer extends BroadcastReceiver {
|
||||
|
||||
public static final String DETAIL_SEPARATOR = " | "; //$NON-NLS-1$
|
||||
|
||||
@Autowired
|
||||
private GtasksMetadataService gtasksMetadataService;
|
||||
|
||||
@Autowired
|
||||
private GtasksListService gtasksListService;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
ContextManager.setContext(context);
|
||||
|
||||
// if we aren't logged in, don't expose features
|
||||
if(!GtasksUtilities.INSTANCE.isLoggedIn())
|
||||
return;
|
||||
|
||||
long taskId = intent.getLongExtra(AstridApiConstants.EXTRAS_TASK_ID, -1);
|
||||
if(taskId == -1)
|
||||
return;
|
||||
|
||||
boolean extended = intent.getBooleanExtra(AstridApiConstants.EXTRAS_EXTENDED, false);
|
||||
String taskDetail = getTaskDetails(taskId, extended);
|
||||
if(taskDetail == null)
|
||||
return;
|
||||
|
||||
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_DETAILS);
|
||||
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, GtasksUtilities.IDENTIFIER);
|
||||
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId);
|
||||
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_EXTENDED, extended);
|
||||
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, taskDetail);
|
||||
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
|
||||
}
|
||||
|
||||
public String getTaskDetails(long id, boolean extended) {
|
||||
if(extended)
|
||||
return null;
|
||||
|
||||
DependencyInjectionService.getInstance().inject(this);
|
||||
|
||||
Metadata metadata = gtasksMetadataService.getTaskMetadata(id);
|
||||
if(metadata == null)
|
||||
return null;
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
long listId = metadata.getValue(GtasksMetadata.LIST_ID);
|
||||
String listName = gtasksListService.getListName(listId);
|
||||
// RTM list is out of date. don't display RTM stuff
|
||||
if(listName == GtasksListService.LIST_NOT_FOUND)
|
||||
return null;
|
||||
|
||||
builder.append("<img src='silk_folder'/> ").append(listName); //$NON-NLS-1$
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.gtasks;
|
||||
|
||||
import org.weloveastrid.rmilk.MilkUtilities;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.timsu.astrid.R;
|
||||
import com.todoroo.andlib.service.Autowired;
|
||||
import com.todoroo.andlib.service.ContextManager;
|
||||
import com.todoroo.andlib.service.DependencyInjectionService;
|
||||
import com.todoroo.andlib.sql.Criterion;
|
||||
import com.todoroo.andlib.sql.Join;
|
||||
import com.todoroo.andlib.sql.QueryTemplate;
|
||||
import com.todoroo.astrid.api.AstridApiConstants;
|
||||
import com.todoroo.astrid.api.Filter;
|
||||
import com.todoroo.astrid.api.FilterCategory;
|
||||
import com.todoroo.astrid.api.FilterListHeader;
|
||||
import com.todoroo.astrid.api.FilterListItem;
|
||||
import com.todoroo.astrid.data.Metadata;
|
||||
import com.todoroo.astrid.data.StoreObject;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import com.todoroo.astrid.data.MetadataApiDao.MetadataCriteria;
|
||||
import com.todoroo.astrid.data.TaskApiDao.TaskCriteria;
|
||||
|
||||
/**
|
||||
* Exposes filters based on RTM lists
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class GtasksFilterExposer extends BroadcastReceiver {
|
||||
|
||||
@Autowired
|
||||
private GtasksListService gtasksListService;
|
||||
private StoreObject[] lists;
|
||||
|
||||
private Filter filterFromList(StoreObject list) {
|
||||
String listName = list.getValue(GtasksList.NAME);
|
||||
ContentValues values = new ContentValues();
|
||||
values.putAll(GtasksMetadata.createEmptyMetadata().getMergedValues());
|
||||
values.remove(Metadata.TASK.name);
|
||||
values.put(GtasksMetadata.LIST_ID.name, list.getValue(GtasksList.REMOTE_ID));
|
||||
Filter filter = new Filter(listName, listName, new QueryTemplate().join(
|
||||
Join.left(Metadata.TABLE, Task.ID.eq(Metadata.TASK))).where(Criterion.and(
|
||||
MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY),
|
||||
TaskCriteria.activeAndVisible(),
|
||||
GtasksMetadata.LIST_ID.eq(list.getValue(GtasksList.REMOTE_ID)))),
|
||||
values);
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
ContextManager.setContext(context);
|
||||
DependencyInjectionService.getInstance().inject(this);
|
||||
|
||||
// if we aren't logged in, don't expose features
|
||||
if(!GtasksUtilities.INSTANCE.isLoggedIn())
|
||||
return;
|
||||
|
||||
lists = gtasksListService.getLists();
|
||||
|
||||
// If user does not have any lists, don't show this section at all
|
||||
if(noListsToShow())
|
||||
return;
|
||||
|
||||
Filter[] listFilters = new Filter[lists.length];
|
||||
for(int i = 0; i < lists.length; i++)
|
||||
listFilters[i] = filterFromList(lists[i]);
|
||||
|
||||
FilterListHeader header = new FilterListHeader(context.getString(R.string.gtasks_FEx_header));
|
||||
FilterCategory listsCategory = new FilterCategory(context.getString(R.string.gtasks_FEx_list),
|
||||
listFilters);
|
||||
|
||||
// transmit filter list
|
||||
FilterListItem[] list = new FilterListItem[2];
|
||||
list[0] = header;
|
||||
list[1] = listsCategory;
|
||||
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
|
||||
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, MilkUtilities.IDENTIFIER);
|
||||
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
|
||||
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
|
||||
}
|
||||
|
||||
private boolean noListsToShow() {
|
||||
return lists.length == 0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.todoroo.astrid.gtasks;
|
||||
|
||||
import com.todoroo.andlib.data.Property.IntegerProperty;
|
||||
import com.todoroo.andlib.data.Property.LongProperty;
|
||||
import com.todoroo.andlib.data.Property.StringProperty;
|
||||
import com.todoroo.astrid.data.StoreObject;
|
||||
|
||||
/**
|
||||
* {@link StoreObject} entries for a GTasks List
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class GtasksList {
|
||||
|
||||
/** type*/
|
||||
public static final String TYPE = "gtasks-list"; //$NON-NLS-1$
|
||||
|
||||
/** list id in g-tasks */
|
||||
public static final LongProperty REMOTE_ID = new LongProperty(StoreObject.TABLE,
|
||||
StoreObject.ITEM.name);
|
||||
|
||||
/** list name */
|
||||
public static final StringProperty NAME = new StringProperty(StoreObject.TABLE,
|
||||
StoreObject.VALUE1.name);
|
||||
|
||||
/** list order */
|
||||
public static final IntegerProperty ORDER = new IntegerProperty(StoreObject.TABLE,
|
||||
StoreObject.VALUE2.name);
|
||||
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
package com.todoroo.astrid.gtasks;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import com.todoroo.andlib.data.TodorooCursor;
|
||||
import com.todoroo.andlib.service.Autowired;
|
||||
import com.todoroo.andlib.service.DependencyInjectionService;
|
||||
import com.todoroo.andlib.sql.Query;
|
||||
import com.todoroo.astrid.dao.StoreObjectDao;
|
||||
import com.todoroo.astrid.dao.StoreObjectDao.StoreObjectCriteria;
|
||||
import com.todoroo.astrid.data.StoreObject;
|
||||
|
||||
public class GtasksListService {
|
||||
|
||||
public static final String LIST_NOT_FOUND = null;
|
||||
|
||||
@Autowired
|
||||
private StoreObjectDao storeObjectDao;
|
||||
|
||||
private StoreObject[] lists = null;
|
||||
|
||||
public GtasksListService() {
|
||||
DependencyInjectionService.getInstance().inject(this);
|
||||
}
|
||||
|
||||
private void readLists() {
|
||||
if(lists != null)
|
||||
return;
|
||||
|
||||
TodorooCursor<StoreObject> cursor = storeObjectDao.query(Query.select(StoreObject.PROPERTIES).
|
||||
where(StoreObjectCriteria.byType(GtasksList.TYPE)));
|
||||
try {
|
||||
lists = new StoreObject[cursor.getCount()];
|
||||
for(int i = 0; i < lists.length; i++) {
|
||||
cursor.moveToNext();
|
||||
StoreObject dashboard = new StoreObject(cursor);
|
||||
lists[i] = dashboard;
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
public StoreObject[] getLists() {
|
||||
readLists();
|
||||
return lists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list name
|
||||
* @param listId
|
||||
* @return NOT_FOUND if no list by this id exists, otherwise list name
|
||||
*/
|
||||
public String getListName(long listId) {
|
||||
readLists();
|
||||
for(StoreObject list : lists)
|
||||
if(list.getValue(GtasksList.REMOTE_ID).equals(listId))
|
||||
return list.getValue(GtasksList.NAME);
|
||||
return LIST_NOT_FOUND;
|
||||
}
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
public void updateLists(JSONArray newLists) throws JSONException {
|
||||
for(int i = 0; i < newLists.length(); i++) {
|
||||
JSONObject remote = newLists.getJSONObject(i);
|
||||
|
||||
long id = remote.optLong("id");
|
||||
StoreObject local = null;
|
||||
for(StoreObject list : lists) {
|
||||
if(list.getValue(GtasksList.REMOTE_ID).equals(id)) {
|
||||
local = list;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(local == null)
|
||||
local = new StoreObject();
|
||||
|
||||
local.setValue(StoreObject.TYPE, GtasksList.TYPE);
|
||||
local.setValue(GtasksList.REMOTE_ID, id);
|
||||
local.setValue(GtasksList.NAME, remote.getString("title"));
|
||||
local.setValue(GtasksList.ORDER, i);
|
||||
storeObjectDao.persist(local);
|
||||
}
|
||||
|
||||
clearListCache();
|
||||
}
|
||||
|
||||
private void clearListCache() {
|
||||
lists = null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.todoroo.astrid.gtasks;
|
||||
|
||||
import com.todoroo.andlib.data.Property.IntegerProperty;
|
||||
import com.todoroo.andlib.data.Property.LongProperty;
|
||||
import com.todoroo.astrid.data.Metadata;
|
||||
import com.todoroo.astrid.utility.Preferences;
|
||||
|
||||
/**
|
||||
* Metadata entries for a GTasks Task
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public class GtasksMetadata {
|
||||
|
||||
private static final int ORDERING_UNSET = -1;
|
||||
|
||||
/** metadata key */
|
||||
public static final String METADATA_KEY = "gtasks"; //$NON-NLS-1$
|
||||
|
||||
/** task id in google */
|
||||
public static final LongProperty ID = new LongProperty(Metadata.TABLE,
|
||||
Metadata.VALUE1.name);
|
||||
|
||||
public static final LongProperty LIST_ID = new LongProperty(Metadata.TABLE,
|
||||
Metadata.VALUE2.name);
|
||||
|
||||
public static final LongProperty OWNER_ID = new LongProperty(Metadata.TABLE,
|
||||
Metadata.VALUE3.name);
|
||||
|
||||
public static final IntegerProperty INDENTATION = new IntegerProperty(Metadata.TABLE,
|
||||
Metadata.VALUE4.name);
|
||||
|
||||
public static final IntegerProperty ORDERING = new IntegerProperty(Metadata.TABLE,
|
||||
Metadata.VALUE5.name);
|
||||
|
||||
public static Metadata createEmptyMetadata() {
|
||||
Metadata metadata = new Metadata();
|
||||
metadata.setValue(Metadata.KEY, GtasksMetadata.METADATA_KEY);
|
||||
metadata.setValue(ID, 0L);
|
||||
metadata.setValue(LIST_ID, Preferences.getLong(GtasksUtilities.PREF_DEFAULT_LIST, 0));
|
||||
metadata.setValue(OWNER_ID, 0L);
|
||||
metadata.setValue(INDENTATION, 0);
|
||||
metadata.setValue(ORDERING, ORDERING_UNSET);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
/**
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.gtasks;
|
||||
|
||||
import com.todoroo.andlib.data.Property;
|
||||
import com.todoroo.andlib.data.TodorooCursor;
|
||||
import com.todoroo.andlib.service.Autowired;
|
||||
import com.todoroo.andlib.service.DependencyInjectionService;
|
||||
import com.todoroo.andlib.sql.Criterion;
|
||||
import com.todoroo.andlib.sql.Join;
|
||||
import com.todoroo.andlib.sql.Query;
|
||||
import com.todoroo.astrid.core.PluginServices;
|
||||
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
|
||||
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
|
||||
import com.todoroo.astrid.data.Metadata;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import com.todoroo.astrid.service.MetadataService;
|
||||
import com.todoroo.astrid.service.TaskService;
|
||||
|
||||
/**
|
||||
* Service for working with GTasks metadata
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
public final class GtasksMetadataService {
|
||||
|
||||
// --- constants
|
||||
|
||||
/** Utility for joining tasks with metadata */
|
||||
public static final Join METADATA_JOIN = Join.left(Metadata.TABLE, Task.ID.eq(Metadata.TASK));
|
||||
|
||||
// --- instance variables
|
||||
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
|
||||
@Autowired
|
||||
private MetadataService metadataService;
|
||||
|
||||
public GtasksMetadataService() {
|
||||
DependencyInjectionService.getInstance().inject(this);
|
||||
}
|
||||
|
||||
// --- task and metadata methods
|
||||
|
||||
/**
|
||||
* Clears metadata information. Used when user logs out of service
|
||||
*/
|
||||
public void clearMetadata() {
|
||||
metadataService.deleteWhere(Metadata.KEY.eq(GtasksMetadata.METADATA_KEY));
|
||||
PluginServices.getTaskService().clearDetails(Task.ID.in(Query.select(Metadata.TASK).from(Metadata.TABLE).
|
||||
where(MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets tasks that were created since last sync
|
||||
* @param properties
|
||||
* @return
|
||||
*/
|
||||
public TodorooCursor<Task> getLocallyCreated(Property<?>[] properties) {
|
||||
return
|
||||
taskService.query(Query.select(properties).join(GtasksMetadataService.METADATA_JOIN).where(Criterion.and(
|
||||
Criterion.not(Task.ID.in(Query.select(Metadata.TASK).from(Metadata.TABLE).
|
||||
where(Criterion.and(MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY), GtasksMetadata.ID.gt(0))))),
|
||||
TaskCriteria.isActive())).groupBy(Task.ID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets tasks that were modified since last sync
|
||||
* @param properties
|
||||
* @return null if never sync'd
|
||||
*/
|
||||
public TodorooCursor<Task> getLocallyUpdated(Property<?>[] properties) {
|
||||
long lastSyncDate = GtasksUtilities.INSTANCE.getLastSyncDate();
|
||||
if(lastSyncDate == 0)
|
||||
return taskService.query(Query.select(Task.ID).where(Criterion.none));
|
||||
return
|
||||
taskService.query(Query.select(properties).join(GtasksMetadataService.METADATA_JOIN).
|
||||
where(Criterion.and(MetadataCriteria.withKey(GtasksMetadata.METADATA_KEY),
|
||||
Task.MODIFICATION_DATE.gt(lastSyncDate))).groupBy(Task.ID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads metadata out of a task
|
||||
* @return null if no metadata found
|
||||
*/
|
||||
public Metadata getTaskMetadata(long taskId) {
|
||||
TodorooCursor<Metadata> cursor = metadataService.query(Query.select(
|
||||
Metadata.PROPERTIES).where(
|
||||
MetadataCriteria.byTaskAndwithKey(taskId, GtasksMetadata.METADATA_KEY)));
|
||||
try {
|
||||
if(cursor.getCount() == 0)
|
||||
return null;
|
||||
cursor.moveToFirst();
|
||||
return new Metadata(cursor);
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.todoroo.astrid.gtasks;
|
||||
|
||||
import com.timsu.astrid.R;
|
||||
import com.todoroo.astrid.sync.SyncProviderUtilities;
|
||||
|
||||
/**
|
||||
* Methods for working with GTasks preferences
|
||||
*
|
||||
* @author timsu
|
||||
*
|
||||
*/
|
||||
public class GtasksUtilities extends SyncProviderUtilities {
|
||||
|
||||
/** add-on identifier */
|
||||
public static final String IDENTIFIER = "gtasks"; //$NON-NLS-1$
|
||||
|
||||
public static final GtasksUtilities INSTANCE = new GtasksUtilities();
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return IDENTIFIER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSyncIntervalKey() {
|
||||
return R.string.gtasks_GPr_interval_key;
|
||||
}
|
||||
|
||||
/** GTasks user's default list id */
|
||||
public static final String PREF_DEFAULT_LIST = IDENTIFIER + "_defaultlist"; //$NON-NLS-1$
|
||||
|
||||
private GtasksUtilities() {
|
||||
// prevent instantiation
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- ============================================= Plugin Boilerplate == -->
|
||||
|
||||
<!-- filters header: GTasks -->
|
||||
<string name="gtasks_FEx_header">Google Tasks</string>
|
||||
|
||||
<!-- filter category for GTasks lists -->
|
||||
<string name="gtasks_FEx_list">By List</string>
|
||||
|
||||
<!-- ============================================== GtasksPreferences == -->
|
||||
|
||||
<!-- GTasks Preferences Title -->
|
||||
<string name="gtasks_MPr_header">Google Tasks</string>
|
||||
|
||||
<!-- ================================================ Synchronization == -->
|
||||
|
||||
<!-- title for notification tray when synchronizing -->
|
||||
<string name="gtasks_notification_title">Astrid: Google Tasks</string>
|
||||
|
||||
</resources>
|
||||
|
||||
Loading…
Reference in New Issue