diff --git a/api/src/com/todoroo/andlib/data/Property.java b/api/src/com/todoroo/andlib/data/Property.java index 43709cfd8..e3c892d5f 100644 --- a/api/src/com/todoroo/andlib/data/Property.java +++ b/api/src/com/todoroo/andlib/data/Property.java @@ -45,7 +45,7 @@ public abstract class Property extends Field implements Cloneable { * expression which is derived from default table name */ protected Property(Table table, String columnName) { - this(table, columnName, (table == null) ? (columnName) : (table.name + "." + columnName)); + this(table, columnName, (table == null) ? (columnName) : (table.name() + "." + columnName)); } /** @@ -53,7 +53,7 @@ public abstract class Property extends Field implements Cloneable { * expression which is derived from default table name */ protected Property(Table table, String columnName, boolean nullable) { - this(table, columnName, (table == null) ? (columnName) : (table.name + "." + columnName)); + this(table, columnName, (table == null) ? (columnName) : (table.name() + "." + columnName)); this.nullable = nullable; } diff --git a/api/src/com/todoroo/andlib/data/Table.java b/api/src/com/todoroo/andlib/data/Table.java index 5527e2d8c..29da2cf77 100644 --- a/api/src/com/todoroo/andlib/data/Table.java +++ b/api/src/com/todoroo/andlib/data/Table.java @@ -77,4 +77,10 @@ public final class Table extends SqlTable { return expression + " AS " + alias; //$NON-NLS-1$ return expression; } + + public String name() { + if(hasAlias()) + return alias; + return name; + } } \ No newline at end of file diff --git a/astrid/plugin-src/com/todoroo/astrid/core/LinkActionExposer.java b/astrid/plugin-src/com/todoroo/astrid/core/LinkActionExposer.java index 5ea7f4dc8..0e69643b8 100644 --- a/astrid/plugin-src/com/todoroo/astrid/core/LinkActionExposer.java +++ b/astrid/plugin-src/com/todoroo/astrid/core/LinkActionExposer.java @@ -28,7 +28,6 @@ import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.api.TaskAction; import com.todoroo.astrid.api.TaskDecoration; import com.todoroo.astrid.data.Task; -import com.todoroo.astrid.files.FileMetadata; import com.todoroo.astrid.files.FilesAction; import com.todoroo.astrid.notes.NotesAction; @@ -42,12 +41,8 @@ public class LinkActionExposer { private PackageManager pm; - public List getActionsForTask(Context context, long taskId) { + public List getActionsForTask(Context context, Task task, boolean hasAttachments) { List result = new ArrayList(); - if(taskId == -1) - return result; - - Task task = PluginServices.getTaskService().fetchById(taskId, Task.ID, Task.TITLE, Task.NOTES); if (task == null) return result; String notes = task.getValue(Task.NOTES); @@ -55,7 +50,6 @@ public class LinkActionExposer { Linkify.addLinks(titleSpan, Linkify.ALL); URLSpan[] urlSpans = titleSpan.getSpans(0, titleSpan.length(), URLSpan.class); - boolean hasAttachments = FileMetadata.taskHasAttachments(taskId); if(urlSpans.length == 0 && TextUtils.isEmpty(notes) && !hasAttachments) return result; @@ -67,7 +61,7 @@ public class LinkActionExposer { int start = titleSpan.getSpanStart(urlSpan); int end = titleSpan.getSpanEnd(urlSpan); String text = titleSpan.subSequence(start, end).toString(); - TaskAction taskAction = createLinkAction(context, taskId, url, text); + TaskAction taskAction = createLinkAction(context, task.getId(), url, text); if (taskAction != null) result.add(taskAction); } diff --git a/astrid/plugin-src/com/todoroo/astrid/tags/TagFilterExposer.java b/astrid/plugin-src/com/todoroo/astrid/tags/TagFilterExposer.java index 54113cb64..5b5c192f3 100644 --- a/astrid/plugin-src/com/todoroo/astrid/tags/TagFilterExposer.java +++ b/astrid/plugin-src/com/todoroo/astrid/tags/TagFilterExposer.java @@ -38,7 +38,6 @@ import com.todoroo.astrid.api.FilterCategory; import com.todoroo.astrid.api.FilterListItem; import com.todoroo.astrid.api.FilterWithCustomIntent; import com.todoroo.astrid.api.FilterWithUpdate; -import com.todoroo.astrid.core.PluginServices; import com.todoroo.astrid.core.SortHelper; import com.todoroo.astrid.dao.TaskDao.TaskCriteria; import com.todoroo.astrid.data.Metadata; @@ -84,10 +83,8 @@ public class TagFilterExposer extends BroadcastReceiver implements AstridFilterE filter.color = Color.GRAY; } - TagData tagData = PluginServices.getTagDataService().getTag(tag.tag, TagData.ID, - TagData.USER_ID, TagData.MEMBER_COUNT); int deleteIntentLabel; - if (tagData != null && tagData.getValue(TagData.MEMBER_COUNT) > 0 && tagData.getValue(TagData.USER_ID) != 0) + if (tag.memberCount > 0 && tag.userId != 0) deleteIntentLabel = R.string.tag_cm_leave; else deleteIntentLabel = R.string.tag_cm_delete; @@ -109,8 +106,6 @@ public class TagFilterExposer extends BroadcastReceiver implements AstridFilterE filter.customTaskList = new ComponentName(ContextManager.getContext(), fragmentClass); if(tag.image != null) filter.imageUrl = tag.image; - if(tag.updateText != null) - filter.updateText = tag.updateText; Bundle extras = new Bundle(); extras.putString(TagViewFragment.EXTRA_TAG_NAME, tag.tag); extras.putLong(TagViewFragment.EXTRA_TAG_REMOTE_ID, tag.remoteId); @@ -121,9 +116,7 @@ public class TagFilterExposer extends BroadcastReceiver implements AstridFilterE /** Create a filter from tag data object */ public static Filter filterFromTagData(Context context, TagData tagData) { - Tag tag = new Tag(tagData.getValue(TagData.NAME), - tagData.getValue(TagData.TASK_COUNT), - tagData.getValue(TagData.REMOTE_ID)); + Tag tag = new Tag(tagData); return filterFromTag(context, tag, TaskCriteria.activeAndVisible()); } diff --git a/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java b/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java index 78290471e..94f06c4aa 100644 --- a/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java +++ b/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java @@ -33,7 +33,6 @@ import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.sql.QueryTemplate; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.actfm.TagViewFragment; -import com.todoroo.astrid.actfm.sync.ActFmPreferenceService; import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.core.PluginServices; import com.todoroo.astrid.dao.MetadataDao; @@ -43,7 +42,6 @@ import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.TaskApiDao; -import com.todoroo.astrid.data.Update; import com.todoroo.astrid.service.MetadataService; import com.todoroo.astrid.service.TagDataService; import com.todoroo.astrid.service.TaskService; @@ -119,7 +117,8 @@ public final class TagService { public int count; public long remoteId; public String image; - public String updateText; + public long userId; + public long memberCount; public Tag(String tag, int count, long remoteId) { this.tag = tag; @@ -132,6 +131,8 @@ public final class TagService { count = tagData.getValue(TagData.TASK_COUNT); remoteId = tagData.getValue(TagData.REMOTE_ID); image = tagData.getValue(TagData.PICTURE); + userId = tagData.getValue(TagData.USER_ID); + memberCount = tagData.getValue(TagData.MEMBER_COUNT); } @Override @@ -337,10 +338,6 @@ public final class TagService { if(TextUtils.isEmpty(tag.tag)) continue; tags.put(tagName, tag); - - Update update = tagDataService.getLatestUpdate(tagData); - if(update != null) - tag.updateText = ActFmPreferenceService.updateToString(update); } } finally { cursor.close(); diff --git a/astrid/src/com/todoroo/astrid/activity/TaskListFragment.java b/astrid/src/com/todoroo/astrid/activity/TaskListFragment.java index 8898e3b8f..78eb1fe97 100644 --- a/astrid/src/com/todoroo/astrid/activity/TaskListFragment.java +++ b/astrid/src/com/todoroo/astrid/activity/TaskListFragment.java @@ -59,6 +59,9 @@ import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.ExceptionService; +import com.todoroo.andlib.sql.Criterion; +import com.todoroo.andlib.sql.Field; +import com.todoroo.andlib.sql.Join; import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.actfm.ActFmLoginActivity; @@ -79,6 +82,7 @@ import com.todoroo.astrid.core.CustomFilterActivity; import com.todoroo.astrid.core.SortHelper; import com.todoroo.astrid.dao.Database; import com.todoroo.astrid.dao.TaskDao.TaskCriteria; +import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; import com.todoroo.astrid.helper.SyncActionHelper; @@ -97,6 +101,7 @@ import com.todoroo.astrid.service.ThemeService; import com.todoroo.astrid.service.UpgradeService; import com.todoroo.astrid.subtasks.SubtasksListFragment; import com.todoroo.astrid.sync.SyncProviderPreferences; +import com.todoroo.astrid.taskrabbit.TaskRabbitMetadata; import com.todoroo.astrid.ui.QuickAddBar; import com.todoroo.astrid.utility.AstridPreferences; import com.todoroo.astrid.utility.Constants; @@ -877,6 +882,8 @@ public class TaskListFragment extends ListFragment implements OnScrollListener, }); } + public static final String TR_METADATA_JOIN = "for_taskrab"; //$NON-NLS-1$ + /** * Fill in the Task List with current items * @@ -887,8 +894,15 @@ public class TaskListFragment extends ListFragment implements OnScrollListener, if (filter == null) return; + // TODO: For now, we'll modify the query to join and include the task rabbit data here. + // Eventually, we might consider restructuring things so that this query is constructed elsewhere. + String joinedTaskRabbitQuery = Join.left(Metadata.TABLE.as(TR_METADATA_JOIN), + Criterion.and(Field.field(TR_METADATA_JOIN + "." + Metadata.KEY.name).eq(TaskRabbitMetadata.METADATA_KEY), //$NON-NLS-1$ + Task.ID.eq(Field.field(TR_METADATA_JOIN) + "." + Metadata.TASK.name))) //$NON-NLS-1$ + + filter.getSqlQuery(); + sqlQueryTemplate.set(SortHelper.adjustQueryForFlagsAndSort( - filter.getSqlQuery(), sortFlags, sortSort)); + joinedTaskRabbitQuery, sortFlags, sortSort)); // perform query TodorooCursor currentCursor; diff --git a/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java b/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java index c98f9c8bb..ae3c2c7ad 100644 --- a/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java +++ b/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java @@ -57,10 +57,15 @@ import android.widget.TextView; import com.timsu.astrid.R; import com.todoroo.andlib.data.Property; +import com.todoroo.andlib.data.Property.LongProperty; import com.todoroo.andlib.data.TodorooCursor; 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.Field; +import com.todoroo.andlib.sql.Join; +import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.Pair; @@ -71,7 +76,9 @@ import com.todoroo.astrid.api.TaskAction; import com.todoroo.astrid.api.TaskDecoration; import com.todoroo.astrid.api.TaskDecorationExposer; import com.todoroo.astrid.core.LinkActionExposer; +import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.files.FileMetadata; import com.todoroo.astrid.files.FilesAction; import com.todoroo.astrid.files.FilesControlSet; import com.todoroo.astrid.helper.AsyncImageView; @@ -82,8 +89,6 @@ import com.todoroo.astrid.service.StatisticsConstants; import com.todoroo.astrid.service.StatisticsService; import com.todoroo.astrid.service.TaskService; import com.todoroo.astrid.service.ThemeService; -import com.todoroo.astrid.taskrabbit.TaskRabbitDataService; -import com.todoroo.astrid.taskrabbit.TaskRabbitTaskContainer; import com.todoroo.astrid.timers.TimerDecorationExposer; import com.todoroo.astrid.ui.CheckableImageView; import com.todoroo.astrid.utility.Constants; @@ -104,6 +109,9 @@ public class TaskAdapter extends CursorAdapter implements Filterable { public static final String BROADCAST_EXTRA_TASK = "model"; //$NON-NLS-1$ + private static final LongProperty TASK_RABBIT_ID = new LongProperty(Metadata.TABLE.as(TaskListFragment.TR_METADATA_JOIN), + Metadata.ID.name); + // --- other constants /** Properties that need to be read from the action item */ @@ -123,7 +131,8 @@ public class TaskAdapter extends CursorAdapter implements Filterable { Task.RECURRENCE, Task.NOTES, Task.USER_ID, - Task.USER + Task.USER, + TASK_RABBIT_ID // Task rabbit metadata id (non-zero means it exists) }; public static int[] IMPORTANCE_RESOURCES = new int[] { @@ -323,6 +332,8 @@ public class TaskAdapter extends CursorAdapter implements Filterable { TodorooCursor cursor = (TodorooCursor)c; ViewHolder viewHolder = ((ViewHolder)view.getTag()); + viewHolder.isTaskRabbit = (cursor.get(TASK_RABBIT_ID) > 0); + Task task = viewHolder.task; task.clear(); task.readFromCursor(cursor); @@ -359,6 +370,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { public LinearLayout taskRow; public View taskActionContainer; public ImageView taskActionIcon; + public boolean isTaskRabbit; public View[] decorations; } @@ -427,9 +439,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { // image view final AsyncImageView pictureView = viewHolder.picture; { if (pictureView != null) { - TaskRabbitTaskContainer container = TaskRabbitDataService.getInstance().getContainerForTask(task); - - if(task.getValue(Task.USER_ID) == Task.USER_ID_SELF && !container.isTaskRabbit()) { + if(task.getValue(Task.USER_ID) == Task.USER_ID_SELF && !viewHolder.isTaskRabbit) { pictureView.setVisibility(View.GONE); if (viewHolder.pictureBorder != null) viewHolder.pictureBorder.setVisibility(View.GONE); @@ -438,7 +448,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { if (viewHolder.pictureBorder != null) viewHolder.pictureBorder.setVisibility(View.VISIBLE); pictureView.setUrl(null); - if (container.isTaskRabbit()) { + if (viewHolder.isTaskRabbit) { pictureView.setDefaultImageResource(R.drawable.task_rabbit_image); } else if(task.getValue(Task.USER_ID) == Task.USER_ID_UNASSIGNED) pictureView.setDefaultImageResource(R.drawable.icn_anyone_transparent); @@ -773,39 +783,57 @@ public class TaskAdapter extends CursorAdapter implements Filterable { private final Map taskActionLoader = Collections.synchronizedMap(new HashMap()); + + + @SuppressWarnings("nls") public class ActionsLoaderThread extends Thread { + public static final String FILE_COLUMN = "fileId"; + private static final String METADATA_JOIN = "for_actions"; + + private final LongProperty fileIdProperty = new LongProperty(Metadata.TABLE.as(METADATA_JOIN), Metadata.ID.name); + @Override public void run() { AndroidUtilities.sleepDeep(500L); - final TodorooCursor fetchCursor = taskService.fetchFiltered( - query.get(), null, Task.ID, Task.TITLE, Task.DETAILS, Task.DETAILS_DATE, - Task.MODIFICATION_DATE, Task.COMPLETION_DATE); + String groupedQuery; + if (query.get().contains("ORDER BY")) //$NON-NLS-1$ + groupedQuery = query.get().replace("ORDER BY", "GROUP BY " + Task.ID + " ORDER BY"); //$NON-NLS-1$ + else + groupedQuery = query.get() + " GROUP BY " + Task.ID; + + Query q = Query.select(Task.ID, Task.TITLE, Task.NOTES, Task.COMPLETION_DATE, + fileIdProperty.as(FILE_COLUMN)) + .join(Join.left(Metadata.TABLE.as(METADATA_JOIN), + Criterion.and(Field.field(METADATA_JOIN + "." + Metadata.KEY.name).eq(FileMetadata.METADATA_KEY), + Task.ID.eq(Field.field(METADATA_JOIN + "." + Metadata.TASK.name))))).withQueryTemplate(groupedQuery); + final TodorooCursor fetchCursor = taskService.query(q); + + try { + Task task = new Task(); + LinkActionExposer linkActionExposer = new LinkActionExposer(); + for(fetchCursor.moveToFirst(); !fetchCursor.isAfterLast(); fetchCursor.moveToNext()) { + task.clear(); + task.readFromCursor(fetchCursor); + if(task.isCompleted()) + continue; + + boolean hasAttachments = (fetchCursor.get(fileIdProperty) > 0); + List actions = linkActionExposer. + getActionsForTask(ContextManager.getContext(), task, hasAttachments); + if (actions.size() > 0) + taskActionLoader.put(task.getId(), actions.get(0)); + } + } finally { + fetchCursor.close(); + } final Activity activity = fragment.getActivity(); if (activity != null) { activity.runOnUiThread(new Runnable() { @Override public void run() { - try { - Task task = new Task(); - LinkActionExposer linkActionExposer = new LinkActionExposer(); - - for(fetchCursor.moveToFirst(); !fetchCursor.isAfterLast(); fetchCursor.moveToNext()) { - task.clear(); - task.readFromCursor(fetchCursor); - if(task.isCompleted()) - continue; - - List actions = linkActionExposer. - getActionsForTask(ContextManager.getContext(), task.getId()); - if (actions.size() > 0) - taskActionLoader.put(task.getId(), actions.get(0)); - } - if(taskActionLoader.size() > 0) { - notifyDataSetChanged(); - } - } finally { - fetchCursor.close(); + if(taskActionLoader.size() > 0) { + notifyDataSetChanged(); } } }); diff --git a/astrid/src/com/todoroo/astrid/service/TaskService.java b/astrid/src/com/todoroo/astrid/service/TaskService.java index b5bd5faff..134aa7367 100644 --- a/astrid/src/com/todoroo/astrid/service/TaskService.java +++ b/astrid/src/com/todoroo/astrid/service/TaskService.java @@ -189,7 +189,7 @@ public class TaskService { return newTask; } - public Task cloneReusableTask(Task task, String listName, long remoteId) { + public Task cloneReusableTask(Task task, String listName, long tagRemoteId) { Task newTask = fetchById(task.getId(), Task.PROPERTIES); if (newTask == null) return new Task(); @@ -205,8 +205,8 @@ public class TaskService { tag.setValue(Metadata.TASK, newTask.getId()); tag.setValue(Metadata.KEY, TagService.KEY); tag.setValue(TagService.TAG, listName); - if (remoteId > 0) - tag.setValue(TagService.REMOTE_ID, remoteId); + if (tagRemoteId > 0) + tag.setValue(TagService.REMOTE_ID, tagRemoteId); metadataDao.createNew(tag); } return newTask;