diff --git a/astrid/AndroidManifest.xml b/astrid/AndroidManifest.xml index f153b4607..386dcf36e 100644 --- a/astrid/AndroidManifest.xml +++ b/astrid/AndroidManifest.xml @@ -1,192 +1,203 @@ + package="com.timsu.astrid" + android:versionName="2.14.4" android:versionCode="135"> - + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + diff --git a/astrid/common-src/com/todoroo/andlib/sql/Query.java b/astrid/common-src/com/todoroo/andlib/sql/Query.java index 91bb608f4..9d4398911 100644 --- a/astrid/common-src/com/todoroo/andlib/sql/Query.java +++ b/astrid/common-src/com/todoroo/andlib/sql/Query.java @@ -20,6 +20,7 @@ import com.todoroo.andlib.data.Property; public final class Query { private SqlTable table; + private String queryTemplate = null; private final ArrayList criterions = new ArrayList(); private final ArrayList fields = new ArrayList(); private final ArrayList joins = new ArrayList(); @@ -80,10 +81,19 @@ public final class Query { StringBuilder sql = new StringBuilder(); visitSelectClause(sql); visitFromClause(sql); - visitJoinClause(sql); - visitWhereClause(sql); - visitGroupByClause(sql); - visitOrderByClause(sql); + + if(queryTemplate == null) { + visitJoinClause(sql); + visitWhereClause(sql); + visitGroupByClause(sql); + visitOrderByClause(sql); + } else { + if(joins.size() > 0 || groupBies.size() > 0 || orders.size() > 0 || + havings.size() > 0) + throw new IllegalStateException("Can't have extras AND query template"); //$NON-NLS-1$ + sql.append(queryTemplate); + } + return sql.toString(); } @@ -169,4 +179,14 @@ public final class Query { public Property[] getFields() { return fields.toArray(new Property[fields.size()]); } + + /** + * Add the SQL query template (comes after the "from") + * @param sqlQuery + * @return + */ + public Query withQueryTemplate(String template) { + queryTemplate = template; + return this; + } } diff --git a/astrid/plugin-src/com/todoroo/astrid/alarms/Alarm.java b/astrid/plugin-src/com/todoroo/astrid/alarms/Alarm.java index e9a39ab33..77f732acc 100644 --- a/astrid/plugin-src/com/todoroo/astrid/alarms/Alarm.java +++ b/astrid/plugin-src/com/todoroo/astrid/alarms/Alarm.java @@ -38,8 +38,8 @@ public class Alarm extends AbstractModel { public static final LongProperty TASK = new LongProperty( TABLE, "task"); - /** Alarm Time (seconds since epoch) */ - public static final IntegerProperty TIME = new IntegerProperty( + /** Alarm Time */ + public static final LongProperty TIME = new LongProperty( TABLE, "time"); /** Alarm Type (see constants) */ diff --git a/astrid/plugin-src/com/todoroo/astrid/filters/CoreFilterExposer.java b/astrid/plugin-src/com/todoroo/astrid/filters/CoreFilterExposer.java index 17504eba0..24c009b32 100644 --- a/astrid/plugin-src/com/todoroo/astrid/filters/CoreFilterExposer.java +++ b/astrid/plugin-src/com/todoroo/astrid/filters/CoreFilterExposer.java @@ -7,6 +7,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.graphics.drawable.BitmapDrawable; import com.timsu.astrid.R; import com.todoroo.andlib.sql.Criterion; @@ -29,25 +30,18 @@ import com.todoroo.astrid.model.Task; */ public final class CoreFilterExposer extends BroadcastReceiver { - @SuppressWarnings("nls") @Override public void onReceive(Context context, Intent intent) { Resources r = context.getResources(); // build filters - Filter inbox = new Filter(CorePlugin.pluginIdentifier, r.getString(R.string.BFE_Inbox), - r.getString(R.string.BFE_Inbox), - new QueryTemplate().where(Criterion.and(TaskCriteria.isActive(), - TaskCriteria.isVisible(DateUtilities.now()))).orderBy( - Order.asc(Functions.caseStatement(Task.DUE_DATE.eq(0), - String.format("(%d + 1000 * %s)", DateUtilities.now(), Task.IMPORTANCE), - String.format("(%s + 1000 * %s)", Task.DUE_DATE, Task.IMPORTANCE)))), - null); + Filter inbox = buildInboxFilter(r); Filter all = new Filter(CorePlugin.pluginIdentifier, r.getString(R.string.BFE_All), r.getString(R.string.BFE_All), new QueryTemplate().orderBy(Order.desc(Task.MODIFICATION_DATE)), null); + all.listingIcon = ((BitmapDrawable)r.getDrawable(R.drawable.filter_all)).getBitmap(); // transmit filter list FilterListItem[] list = new FilterListItem[2]; @@ -58,4 +52,22 @@ public final class CoreFilterExposer extends BroadcastReceiver { context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); } + /** + * Build inbox filter + * @return + */ + @SuppressWarnings("nls") + public static Filter buildInboxFilter(Resources r) { + Filter inbox = new Filter(CorePlugin.pluginIdentifier, r.getString(R.string.BFE_Inbox), + r.getString(R.string.BFE_Inbox), + new QueryTemplate().where(Criterion.and(TaskCriteria.isActive(), + TaskCriteria.isVisible(DateUtilities.now()))).orderBy( + Order.asc(Functions.caseStatement(Task.DUE_DATE.eq(0), + String.format("(%d + 1000 * %s)", DateUtilities.now(), Task.IMPORTANCE), + String.format("(%s + 1000 * %s)", Task.DUE_DATE, Task.IMPORTANCE)))), + null); + inbox.listingIcon = ((BitmapDrawable)r.getDrawable(R.drawable.filter_inbox)).getBitmap(); + return inbox; + } + } diff --git a/astrid/plugin-src/com/todoroo/astrid/filters/CorePlugin.java b/astrid/plugin-src/com/todoroo/astrid/filters/CorePlugin.java index e009f863b..f11031b08 100644 --- a/astrid/plugin-src/com/todoroo/astrid/filters/CorePlugin.java +++ b/astrid/plugin-src/com/todoroo/astrid/filters/CorePlugin.java @@ -7,7 +7,6 @@ import android.content.Intent; import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.Plugin; -@SuppressWarnings("nls") public class CorePlugin extends BroadcastReceiver { static final String pluginIdentifier = "core"; diff --git a/astrid/plugin-src/com/todoroo/astrid/filters/ExtendedFilterExposer.java b/astrid/plugin-src/com/todoroo/astrid/filters/ExtendedFilterExposer.java index 024e605f1..f496fc9b1 100644 --- a/astrid/plugin-src/com/todoroo/astrid/filters/ExtendedFilterExposer.java +++ b/astrid/plugin-src/com/todoroo/astrid/filters/ExtendedFilterExposer.java @@ -7,7 +7,6 @@ import android.content.BroadcastReceiver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; -import android.content.res.Resources; import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Order; @@ -16,6 +15,7 @@ import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.activity.FilterListActivity; import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.Filter; +import com.todoroo.astrid.api.FilterListHeader; import com.todoroo.astrid.api.FilterListItem; import com.todoroo.astrid.dao.TaskDao.TaskCriteria; import com.todoroo.astrid.model.Task; @@ -28,31 +28,43 @@ import com.todoroo.astrid.model.Task; */ public final class ExtendedFilterExposer extends BroadcastReceiver { - @SuppressWarnings("nls") @Override public void onReceive(Context context, Intent intent) { - Resources r = context.getResources(); - // build filters + FilterListHeader header = new FilterListHeader(ExtendedPlugin.pluginIdentifier, + "Extended"); + + Filter alphabetical = new Filter(ExtendedPlugin.pluginIdentifier, + "Inbox (sorted by name)", + "Inbox (sorted by name)", + new QueryTemplate().where(Criterion.and(TaskCriteria.isActive(), + TaskCriteria.isVisible(DateUtilities.now()))). + orderBy(Order.asc(Task.TITLE)), + null); + ContentValues hiddenValues = new ContentValues(); - hiddenValues.put(Task.HIDE_UNTIL, DateUtilities.now() + DateUtilities.ONE_DAY); - Filter hidden = new Filter(ExtendedPlugin.pluginIdentifier, "Hidden Tasks", + hiddenValues.put(Task.HIDE_UNTIL.name, DateUtilities.now() + DateUtilities.ONE_DAY); + Filter hidden = new Filter(ExtendedPlugin.pluginIdentifier, + "Hidden Tasks", "Hidden Tasks", new QueryTemplate().where(Criterion.and(TaskCriteria.isActive(), Criterion.not(TaskCriteria.isVisible(DateUtilities.now())))). orderBy(Order.asc(Task.HIDE_UNTIL)), hiddenValues); - Filter alphabetical = new Filter(ExtendedPlugin.pluginIdentifier, - "Inbox (sorted by name)", - "Inbox (sorted by name)", - new QueryTemplate().orderBy(Order.asc(Task.TITLE)), + Filter deleted = new Filter(ExtendedPlugin.pluginIdentifier, + "Deleted Tasks", + "Deleted Tasks", + new QueryTemplate().where(TaskCriteria.isDeleted()). + orderBy(Order.desc(Task.DELETION_DATE)), null); // transmit filter list - FilterListItem[] list = new FilterListItem[2]; - list[0] = inbox; - list[1] = all; + FilterListItem[] list = new FilterListItem[4]; + list[0] = header; + list[1] = alphabetical; + list[2] = hidden; + list[3] = deleted; Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ITEMS, list); context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); diff --git a/astrid/plugin-src/com/todoroo/astrid/filters/ExtendedPlugin.java b/astrid/plugin-src/com/todoroo/astrid/filters/ExtendedPlugin.java index f6b5e6a82..36703531b 100644 --- a/astrid/plugin-src/com/todoroo/astrid/filters/ExtendedPlugin.java +++ b/astrid/plugin-src/com/todoroo/astrid/filters/ExtendedPlugin.java @@ -7,7 +7,6 @@ import android.content.Intent; import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.Plugin; -@SuppressWarnings("nls") public class ExtendedPlugin extends BroadcastReceiver { static final String pluginIdentifier = "extended"; diff --git a/astrid/plugin-src/com/todoroo/astrid/tags/DetailExposer.java b/astrid/plugin-src/com/todoroo/astrid/tags/DetailExposer.java new file mode 100644 index 000000000..88b374435 --- /dev/null +++ b/astrid/plugin-src/com/todoroo/astrid/tags/DetailExposer.java @@ -0,0 +1,50 @@ +/** + * See the file "LICENSE" for the full license governing this code. + */ +package com.todoroo.astrid.tags; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.timsu.astrid.R; +import com.todoroo.astrid.api.AstridApiConstants; +import com.todoroo.astrid.api.TaskDetail; + +/** + * Exposes {@link TaskDetail} for tags, i.e. "Tags: frogs, animals" + * + * @author Tim Su + * + */ +public class DetailExposer extends BroadcastReceiver { + + private static TagService tagService = null; + + @Override + public void onReceive(Context context, Intent intent) { + // get tags associated with this task + long taskId = intent.getLongExtra(AstridApiConstants.EXTRAS_TASK_ID, -1); + if(taskId == -1) + return; + + if(tagService == null) + tagService = new TagService(context); + String tagList = tagService.getTagsAsString(taskId); + + if(tagList.length() == 0) + return; + + TaskDetail taskDetail = new TaskDetail(TagsPlugin.IDENTIFIER, + context.getString(R.string.tag_TLA_detail, tagList)); + + // transmit + TaskDetail[] details = new TaskDetail[1]; + details[0] = taskDetail; + Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_DETAILS); + broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ITEMS, details); + broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId); + context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); + } + +} diff --git a/astrid/plugin-src/com/todoroo/astrid/tags/FilterExposer.java b/astrid/plugin-src/com/todoroo/astrid/tags/FilterExposer.java index 204c33bda..3ef39c1e1 100644 --- a/astrid/plugin-src/com/todoroo/astrid/tags/FilterExposer.java +++ b/astrid/plugin-src/com/todoroo/astrid/tags/FilterExposer.java @@ -4,16 +4,18 @@ package com.todoroo.astrid.tags; import android.content.BroadcastReceiver; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; -import com.todoroo.astrid.R; +import com.timsu.astrid.R; +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.tags.DataService.Tag; +import com.todoroo.astrid.tags.TagService.Tag; /** * Exposes filters based on tags @@ -23,15 +25,21 @@ import com.todoroo.astrid.tags.DataService.Tag; */ public class FilterExposer extends BroadcastReceiver { + private TagService tagService; @SuppressWarnings("nls") - private Filter filterFromTag(Context context, Tag tag, DataService tagService) { + private Filter filterFromTag(Context context, Tag tag) { String listTitle = context.getString(R.string.tag_FEx_tag_w_size). replace("$T", tag.tag).replace("$C", Integer.toString(tag.count)); String title = context.getString(R.string.tag_FEx_name, tag.tag); - Filter filter = new Filter(listTitle, title, - tagService.getQuery(tag.tag), - tagService.getNewTaskSql(tag.tag)); + QueryTemplate tagTemplate = tag.queryTemplate(); + ContentValues contentValues = new ContentValues(); + contentValues.put(TagService.KEY, tag.tag); + + Filter filter = new Filter(TagsPlugin.IDENTIFIER, + listTitle, title, + tagTemplate, + contentValues); // filters[0].contextMenuLabels = new String[] { // "Rename Tag", @@ -47,26 +55,28 @@ public class FilterExposer extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - DataService tagService = new DataService(context); - Tag[] tagsByAlpha = tagService.getGroupedTags(DataService.GROUPED_TAGS_BY_ALPHA); + tagService = new TagService(context); + Tag[] tagsByAlpha = tagService.getGroupedTags(TagService.GROUPED_TAGS_BY_ALPHA); // If user does not have any tags, don't show this section at all if(tagsByAlpha.length == 0) return; - Tag[] tagsBySize = tagService.getGroupedTags(DataService.GROUPED_TAGS_BY_SIZE); + Tag[] tagsBySize = tagService.getGroupedTags(TagService.GROUPED_TAGS_BY_SIZE); Filter[] filtersByAlpha = new Filter[tagsByAlpha.length]; for(int i = 0; i < tagsByAlpha.length; i++) - filtersByAlpha[i] = filterFromTag(context, tagsByAlpha[i], tagService); + filtersByAlpha[i] = filterFromTag(context, tagsByAlpha[i]); Filter[] filtersBySize = new Filter[tagsBySize.length]; for(int i = 0; i < tagsBySize.length; i++) - filtersBySize[i] = filterFromTag(context, tagsBySize[i], tagService); + filtersBySize[i] = filterFromTag(context, tagsBySize[i]); - FilterListHeader tagsHeader = new FilterListHeader(context.getString(R.string.tag_FEx_header)); - FilterCategory tagsCategoryBySize = new FilterCategory( + FilterListHeader tagsHeader = new FilterListHeader(TagsPlugin.IDENTIFIER, + context.getString(R.string.tag_FEx_header)); + FilterCategory tagsCategoryBySize = new FilterCategory(TagsPlugin.IDENTIFIER, context.getString(R.string.tag_FEx_by_size), filtersBySize); - FilterCategory tagsCategoryByAlpha = new FilterCategory(context.getString(R.string.tag_FEx_alpha), filtersByAlpha); + FilterCategory tagsCategoryByAlpha = new FilterCategory(TagsPlugin.IDENTIFIER, + context.getString(R.string.tag_FEx_alpha), filtersByAlpha); // transmit filter list FilterListItem[] list = new FilterListItem[3]; diff --git a/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java b/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java index bb8c113fa..2b3066835 100644 --- a/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java +++ b/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import android.content.Context; -import com.todoroo.andlib.data.Property; import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.Property.CountProperty; import com.todoroo.andlib.service.Autowired; @@ -13,6 +12,7 @@ import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Join; import com.todoroo.andlib.sql.Order; import com.todoroo.andlib.sql.Query; +import com.todoroo.andlib.sql.QueryTemplate; import com.todoroo.astrid.dao.MetadataDao; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; import com.todoroo.astrid.model.Metadata; @@ -57,7 +57,7 @@ public class TagService { * @author Tim Su * */ - public class Tag { + public final class Tag { public String tag; int count; @@ -65,6 +65,18 @@ public class TagService { public String toString() { return tag; } + + /** + * Return SQL selector query for getting tasks with a given tag + * + * @param tag + * @return + */ + public QueryTemplate queryTemplate() { + return new QueryTemplate().join(Join.inner(Metadata.TABLE, + Task.ID.eq(Metadata.TASK))).where(Criterion.and( + MetadataCriteria.withKey(KEY), Metadata.VALUE.eq(tag))); + } } /** @@ -123,18 +135,6 @@ public class TagService { return tagBuilder.toString(); } - /** - * Return SQL selector query for getting tasks with a given tag - * - * @param tag - * @return - */ - public Query tasksWithTag(String tag, Property... properties) { - return Query.select(properties).join(Join.inner(Metadata.TABLE, - Task.ID.eq(Metadata.TASK))).where(Criterion.and( - MetadataCriteria.withKey(KEY), Metadata.VALUE.eq(tag))); - } - /** * Save the given array of tags into the database * @param taskId diff --git a/astrid/plugin-src/com/todoroo/astrid/tags/TagsPlugin.java b/astrid/plugin-src/com/todoroo/astrid/tags/TagsPlugin.java new file mode 100644 index 000000000..b29a045c1 --- /dev/null +++ b/astrid/plugin-src/com/todoroo/astrid/tags/TagsPlugin.java @@ -0,0 +1,24 @@ +package com.todoroo.astrid.tags; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.todoroo.astrid.api.AstridApiConstants; +import com.todoroo.astrid.api.Plugin; + +public class TagsPlugin extends BroadcastReceiver { + + static final String IDENTIFIER = "tags"; + + @Override + public void onReceive(Context context, Intent intent) { + Plugin plugin = new Plugin(IDENTIFIER, "Tags", "Todoroo", + "Provides tagging support for tasks."); + + Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_PLUGINS); + broadcastIntent.putExtra(AstridApiConstants.EXTRAS_PLUGIN, plugin); + context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); + } + +} diff --git a/astrid/res/drawable/filter_all.png b/astrid/res/drawable/filter_all.png new file mode 100644 index 000000000..3d09261a2 Binary files /dev/null and b/astrid/res/drawable/filter_all.png differ diff --git a/astrid/res/drawable/filter_alpha.png b/astrid/res/drawable/filter_alpha.png new file mode 100644 index 000000000..b7960db9d Binary files /dev/null and b/astrid/res/drawable/filter_alpha.png differ diff --git a/astrid/res/drawable/filter_deleted.png b/astrid/res/drawable/filter_deleted.png new file mode 100644 index 000000000..1514d51a3 Binary files /dev/null and b/astrid/res/drawable/filter_deleted.png differ diff --git a/astrid/res/drawable/filter_hidden.png b/astrid/res/drawable/filter_hidden.png new file mode 100644 index 000000000..5bf8313c6 Binary files /dev/null and b/astrid/res/drawable/filter_hidden.png differ diff --git a/astrid/res/drawable/filter_inbox.png b/astrid/res/drawable/filter_inbox.png new file mode 100644 index 000000000..fed62219f Binary files /dev/null and b/astrid/res/drawable/filter_inbox.png differ diff --git a/astrid/res/drawable/filter_recent.png b/astrid/res/drawable/filter_recent.png new file mode 100644 index 000000000..6a9bf0370 Binary files /dev/null and b/astrid/res/drawable/filter_recent.png differ diff --git a/astrid/res/drawable/filter_tags1.png b/astrid/res/drawable/filter_tags1.png new file mode 100644 index 000000000..454a59f30 Binary files /dev/null and b/astrid/res/drawable/filter_tags1.png differ diff --git a/astrid/res/drawable/filter_tags2.png b/astrid/res/drawable/filter_tags2.png new file mode 100644 index 000000000..ebaf0e874 Binary files /dev/null and b/astrid/res/drawable/filter_tags2.png differ diff --git a/astrid/res/drawable/filter_untagged.png b/astrid/res/drawable/filter_untagged.png new file mode 100644 index 000000000..9fbae6725 Binary files /dev/null and b/astrid/res/drawable/filter_untagged.png differ diff --git a/astrid/res/values/styles-3.0.xml b/astrid/res/values/styles-3.0.xml index f450eecf0..815405ffd 100644 --- a/astrid/res/values/styles-3.0.xml +++ b/astrid/res/values/styles-3.0.xml @@ -55,7 +55,7 @@