diff --git a/astrid/AndroidManifest.xml b/astrid/AndroidManifest.xml index 393440d45..e0c32e88a 100644 --- a/astrid/AndroidManifest.xml +++ b/astrid/AndroidManifest.xml @@ -211,6 +211,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -308,12 +365,6 @@ - - - - - - @@ -436,49 +487,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksDecorationExposer.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksDecorationExposer.java index b81756dbd..7d27dab19 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksDecorationExposer.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksDecorationExposer.java @@ -9,11 +9,11 @@ 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.astrid.api.Filter; import com.todoroo.astrid.api.TaskDecoration; import com.todoroo.astrid.api.TaskDecorationExposer; import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.utility.Flags; /** * Exposes {@link TaskDecoration} for GTasks indentation @@ -31,11 +31,11 @@ public class GtasksDecorationExposer implements TaskDecorationExposer { } @Override - public TaskDecoration expose(Filter activeFilter, Task task) { + public TaskDecoration expose(Task task) { if(!gtasksPreferenceService.isLoggedIn()) return null; - if(!activeFilter.sqlQuery.contains(GtasksMetadata.METADATA_KEY)) + if(Flags.checkAndClear(Flags.GTASKS)) return null; return createDecoration(task); diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksIndentAction.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksIndentAction.java index 9be89e951..e42f68b8c 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksIndentAction.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksIndentAction.java @@ -12,7 +12,13 @@ import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.core.PluginServices; import com.todoroo.astrid.data.Metadata; +import com.todoroo.astrid.utility.Flags; +/** + * Context Menu actions for changing indent level of a task + * @author Tim Su + * + */ abstract public class GtasksIndentAction extends BroadcastReceiver { @Autowired private GtasksMetadataService gtasksMetadataService; @@ -37,6 +43,7 @@ abstract public class GtasksIndentAction extends BroadcastReceiver { metadata.setValue(GtasksMetadata.INDENTATION, newIndent); PluginServices.getMetadataService().save(metadata); + Flags.set(Flags.REFRESH); Toast.makeText(context, context.getString(R.string.gtasks_indent_toast, newIndent), Toast.LENGTH_SHORT).show(); } diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksOrderAction.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksOrderAction.java new file mode 100644 index 000000000..739ef6b7d --- /dev/null +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksOrderAction.java @@ -0,0 +1,61 @@ +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.core.PluginServices; +import com.todoroo.astrid.data.Metadata; +import com.todoroo.astrid.utility.Flags; + +/** + * Context Menu actions for changing the order of a task + * @author Tim Su + * + */ +abstract public class GtasksOrderAction extends BroadcastReceiver { + + @Autowired private GtasksMetadataService gtasksMetadataService; + + abstract int getDelta(); + + @Override + public void onReceive(Context context, Intent intent) { + ContextManager.setContext(context); + DependencyInjectionService.getInstance().inject(this); + + long taskId = intent.getLongExtra(AstridApiConstants.EXTRAS_TASK_ID, -1); + if(taskId == -1) + return; + + Metadata metadata = gtasksMetadataService.getTaskMetadata(taskId); + if(metadata == null) { + metadata = GtasksMetadata.createEmptyMetadata(taskId); + } + + // TODO + + PluginServices.getMetadataService().save(metadata); + + Flags.set(Flags.REFRESH); + } + + public static class GtasksMoveUpAction extends GtasksOrderAction { + @Override + public int getDelta() { + return -1; + } + } + + public static class GtasksMoveDownAction extends GtasksOrderAction { + @Override + public int getDelta() { + return 1; + } + } + +} diff --git a/astrid/plugin-src/com/todoroo/astrid/timers/TimerDecorationExposer.java b/astrid/plugin-src/com/todoroo/astrid/timers/TimerDecorationExposer.java index 105b6119b..a66b6507c 100644 --- a/astrid/plugin-src/com/todoroo/astrid/timers/TimerDecorationExposer.java +++ b/astrid/plugin-src/com/todoroo/astrid/timers/TimerDecorationExposer.java @@ -3,11 +3,6 @@ */ package com.todoroo.astrid.timers; -import java.util.HashMap; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; import android.graphics.Color; import android.os.SystemClock; import android.text.format.DateUtils; @@ -15,10 +10,10 @@ import android.view.View; import android.widget.RemoteViews; import com.timsu.astrid.R; +import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.utility.DateUtilities; -import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.TaskDecoration; -import com.todoroo.astrid.core.PluginServices; +import com.todoroo.astrid.api.TaskDecorationExposer; import com.todoroo.astrid.data.Task; /** @@ -27,51 +22,21 @@ import com.todoroo.astrid.data.Task; * @author Tim Su * */ -public class TimerDecorationExposer extends BroadcastReceiver { +public class TimerDecorationExposer implements TaskDecorationExposer { private static final int TIMING_BG_COLOR = Color.argb(200, 220, 50, 0); - private static HashMap decorations = - new HashMap(); - - private static HashMap tasksNeedingUpdate = - new HashMap(); - - public static void updateTimer(long taskId) { - decorations.remove(taskId); - tasksNeedingUpdate.put(taskId, true); - } - @Override - public void onReceive(Context context, Intent intent) { - long taskId = intent.getLongExtra(AstridApiConstants.EXTRAS_TASK_ID, -1); - if(taskId == -1) - return; - - Task task; - try { - if(tasksNeedingUpdate.containsKey(taskId)) - task = PluginServices.getTaskService().fetchById(taskId, Task.ID, Task.ELAPSED_SECONDS, Task.TIMER_START); - else - task = intent.getParcelableExtra("model"); //$NON-NLS-1$ - } catch (IllegalStateException e) { - return; - } - - if(task == null || task.getId() != taskId || (task.getValue(Task.ELAPSED_SECONDS) == 0 && + public TaskDecoration expose(Task task) { + if(task == null || (task.getValue(Task.ELAPSED_SECONDS) == 0 && task.getValue(Task.TIMER_START) == 0)) - return; + return null; TaskDecoration decoration; - if(!decorations.containsKey(taskId)) { - RemoteViews remoteViews = new RemoteViews(context.getPackageName(), - R.layout.timer_decoration); - decoration = new TaskDecoration(remoteViews, - TaskDecoration.POSITION_LEFT, 0); - decorations.put(taskId, decoration); - } else { - decoration = decorations.get(taskId); - } + RemoteViews remoteViews = new RemoteViews(ContextManager.getContext().getPackageName(), + R.layout.timer_decoration); + decoration = new TaskDecoration(remoteViews, + TaskDecoration.POSITION_LEFT, 0); long elapsed = task.getValue(Task.ELAPSED_SECONDS) * 1000L; if(task.getValue(Task.TIMER_START) != 0) { @@ -91,13 +56,7 @@ public class TimerDecorationExposer extends BroadcastReceiver { decoration.decoration.setViewVisibility(R.id.label, View.VISIBLE); } - - // transmit - Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_DECORATIONS); - broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, TimerPlugin.IDENTIFIER); - broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, decoration); - broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId); - context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); + return decoration; } private String buildFormat(long elapsed) { diff --git a/astrid/plugin-src/com/todoroo/astrid/timers/TimerPlugin.java b/astrid/plugin-src/com/todoroo/astrid/timers/TimerPlugin.java index 69d632dff..9c14628c7 100644 --- a/astrid/plugin-src/com/todoroo/astrid/timers/TimerPlugin.java +++ b/astrid/plugin-src/com/todoroo/astrid/timers/TimerPlugin.java @@ -36,7 +36,7 @@ public class TimerPlugin extends BroadcastReceiver { } /** - * stops timer and sets elapsed time. you still need to save the task. + * toggles timer and updates elapsed time. * @param task * @param start if true, start timer. else, stop it */ @@ -53,12 +53,10 @@ public class TimerPlugin extends BroadcastReceiver { } } PluginServices.getTaskService().save(task); - TimerDecorationExposer.updateTimer(task.getId()); // transmit new intents Intent intent = new Intent(AstridApiConstants.BROADCAST_REQUEST_ACTIONS); intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, task.getId()); - new TimerDecorationExposer().onReceive(context, intent); new TimerActionExposer().onReceive(context, intent); // update notification diff --git a/astrid/res/values/strings-gtasks.xml b/astrid/res/values/strings-gtasks.xml index 3280cecf1..febd2d61a 100644 --- a/astrid/res/values/strings-gtasks.xml +++ b/astrid/res/values/strings-gtasks.xml @@ -13,11 +13,17 @@ New Indentation: %d + + ▲ Move Up + - Move Right + ▶ Move Right - Move Left + ◀ Move Left + + + ▼ Move Down diff --git a/astrid/src/com/todoroo/astrid/activity/TaskListActivity.java b/astrid/src/com/todoroo/astrid/activity/TaskListActivity.java index 69f2ee890..91c2f5f79 100644 --- a/astrid/src/com/todoroo/astrid/activity/TaskListActivity.java +++ b/astrid/src/com/todoroo/astrid/activity/TaskListActivity.java @@ -75,6 +75,7 @@ import com.todoroo.astrid.dao.Database; import com.todoroo.astrid.dao.TaskDao.TaskCriteria; import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.gtasks.GtasksMetadata; import com.todoroo.astrid.helper.TaskListContextMenuExtensionLoader; import com.todoroo.astrid.helper.TaskListContextMenuExtensionLoader.ContextMenuItem; import com.todoroo.astrid.reminders.Notifications; @@ -617,6 +618,10 @@ public class TaskListActivity extends ListActivity implements OnScrollListener, TodorooCursor currentCursor = taskService.fetchFiltered( sqlQueryTemplate.get(), null, TaskAdapter.PROPERTIES); startManagingCursor(currentCursor); + if(sqlQueryTemplate.get().contains(GtasksMetadata.METADATA_KEY)) + Flags.set(Flags.GTASKS); + else + Flags.checkAndClear(Flags.GTASKS); // set up list adapters taskAdapter = new TaskAdapter(this, R.layout.task_adapter_row, diff --git a/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java b/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java index 395ec404d..79dd75ee1 100644 --- a/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java +++ b/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java @@ -35,7 +35,6 @@ import android.widget.CheckBox; import android.widget.CursorAdapter; import android.widget.Filterable; import android.widget.LinearLayout; -import android.widget.ListView; import android.widget.TextView; import com.timsu.astrid.R; @@ -51,9 +50,13 @@ import com.todoroo.astrid.activity.TaskListActivity; import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.TaskAction; import com.todoroo.astrid.api.TaskDecoration; +import com.todoroo.astrid.api.TaskDecorationExposer; import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.gtasks.GtasksDecorationExposer; +import com.todoroo.astrid.helper.TaskAdapterAddOnManager; import com.todoroo.astrid.service.AddOnService; import com.todoroo.astrid.service.TaskService; +import com.todoroo.astrid.timers.TimerDecorationExposer; import com.todoroo.astrid.utility.Constants; import com.todoroo.astrid.utility.Preferences; @@ -118,10 +121,9 @@ public class TaskAdapter extends CursorAdapter implements Filterable { // --- task detail and decoration soft caches - public final ExtendedDetailManager extendedDetailManager = new ExtendedDetailManager(); - public final DecorationManager decorationManager = - new DecorationManager(); - public final TaskActionManager taskActionManager = new TaskActionManager(); + public final ExtendedDetailManager extendedDetailManager; + public final DecorationManager decorationManager; + public final TaskActionManager taskActionManager; /** * Constructor @@ -159,6 +161,10 @@ public class TaskAdapter extends CursorAdapter implements Filterable { detailLoader = new DetailLoaderThread(); detailLoader.start(); + + extendedDetailManager = new ExtendedDetailManager(); + decorationManager = new DecorationManager(); + taskActionManager = new TaskActionManager(); } /* ====================================================================== @@ -399,8 +405,6 @@ public class TaskAdapter extends CursorAdapter implements Filterable { // it's best to do this, though, in order to append details to each other private final Map taskDetailLoader = Collections.synchronizedMap(new HashMap(0)); - private final Task taskDetailContainer = new Task(); - public class DetailLoaderThread extends Thread { @Override public void run() { @@ -412,7 +416,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { activity.startManagingCursor(fetchCursor); Random random = new Random(); try { - Task task = taskDetailContainer; + Task task = new Task(); for(fetchCursor.moveToFirst(); !fetchCursor.isAfterLast(); fetchCursor.moveToNext()) { task.clear(); task.readFromCursor(fetchCursor); @@ -425,15 +429,21 @@ public class TaskAdapter extends CursorAdapter implements Filterable { taskDetailLoader.put(task.getId(), new StringBuilder(task.getValue(Task.DETAILS))); requestNewDetails(task); + System.err.println("Refreshing details: " + task.getId()); } continue; + } else { + System.err.println("Forced loading of details: " + task.getId() + + "\n details: " + new Date(task.getValue(Task.DETAILS_DATE)) + + "\n modified: " + new Date(task.getValue(Task.MODIFICATION_DATE))); } addTaskToLoadingArray(task); - requestNewDetails(task); task.setValue(Task.DETAILS, DETAIL_SEPARATOR); task.setValue(Task.DETAILS_DATE, DateUtilities.now()); taskService.save(task); + + requestNewDetails(task); } } catch (Exception e) { // suppress silently @@ -472,18 +482,15 @@ public class TaskAdapter extends CursorAdapter implements Filterable { synchronized(details) { if(details.toString().contains(detail)) return; - if(details.length() > 0 && !details.toString().endsWith(DETAIL_SEPARATOR)) + if(details.length() > 0) details.append(DETAIL_SEPARATOR); - else if(details.equals(DETAIL_SEPARATOR)) - details.setLength(0); details.append(detail); - taskDetailContainer.setId(id); - String detailsAsString = details.toString(); - if(detailsAsString.startsWith(DETAIL_SEPARATOR)) - detailsAsString = detailsAsString.substring(DETAIL_SEPARATOR.length()); - taskDetailContainer.setValue(Task.DETAILS, details.toString()); - taskDetailContainer.setValue(Task.DETAILS_DATE, DateUtilities.now()); - taskService.save(taskDetailContainer); + Task task = new Task(); + task.setId(id); + System.err.println("task " + id + " - '" + details.toString() + "' (" + detail + ")"); + task.setValue(Task.DETAILS, details.toString()); + task.setValue(Task.DETAILS_DATE, DateUtilities.now()); + taskService.save(task); } activity.runOnUiThread(new Runnable() { @@ -544,14 +551,15 @@ public class TaskAdapter extends CursorAdapter implements Filterable { * @author Tim Su * */ - public class ExtendedDetailManager extends AddOnManager { + public class ExtendedDetailManager extends TaskAdapterAddOnManager { private final Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_REQUEST_DETAILS); public ExtendedDetailManager() { - // + super(activity); } @Override + protected Intent createBroadcastIntent(Task task) { broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, task.getId()); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_EXTENDED, true); @@ -567,6 +575,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { @SuppressWarnings("nls") @Override + protected void draw(ViewHolder viewHolder, long taskId, Collection details) { if(details == null || viewHolder.task.getId() != taskId) return; @@ -594,7 +603,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { } @Override - void reset(ViewHolder viewHolder, long taskId) { + protected void reset(ViewHolder viewHolder, long taskId) { TextView view = viewHolder.extendedDetails; view.setVisibility(View.GONE); } @@ -606,27 +615,45 @@ public class TaskAdapter extends CursorAdapter implements Filterable { * @author Tim Su * */ - public class DecorationManager extends AddOnManager { - private final Intent intent = new Intent(AstridApiConstants.BROADCAST_REQUEST_DECORATIONS); + public class DecorationManager extends TaskAdapterAddOnManager { - @Override - Intent createBroadcastIntent(Task task) { - // performance hack, get rid of me when task list performance is improved - if(isFling || task.getValue(Task.TIMER_START) == 0 && - task.getValue(Task.ELAPSED_SECONDS) == 0) - return null; - intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, task.getId()); - intent.putExtra(BROADCAST_EXTRA_TASK, task); - return intent; + public DecorationManager() { + super(activity); } + private final TaskDecorationExposer[] exposers = new TaskDecorationExposer[] { + new TimerDecorationExposer(), + new GtasksDecorationExposer() + }; + + /** + * Request add-ons for the given task + * @return true if cache miss, false if cache hit + */ @Override - public void addNew(long taskId, String addOn, TaskDecoration item) { - super.addNew(taskId, addOn, item); + public boolean request(ViewHolder viewHolder) { + long taskId = viewHolder.task.getId(); + + Collection list = initialize(taskId); + if(list != null) { + draw(viewHolder, taskId, list); + return false; + } + + // request details + draw(viewHolder, taskId, get(taskId)); + + for(TaskDecorationExposer exposer : exposers) { + TaskDecoration deco = exposer.expose(viewHolder.task); + if(deco != null) + addNew(viewHolder.task.getId(), exposer.getClass().getName(), deco); + } + + return true; } @Override - void draw(ViewHolder viewHolder, long taskId, Collection decorations) { + protected void draw(ViewHolder viewHolder, long taskId, Collection decorations) { if(decorations == null || viewHolder.task.getId() != taskId) return; @@ -660,7 +687,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { } @Override - void reset(ViewHolder viewHolder, long taskId) { + protected void reset(ViewHolder viewHolder, long taskId) { if(viewHolder.decorations != null) { for(View view : viewHolder.decorations) viewHolder.taskRow.removeView(view); @@ -670,6 +697,11 @@ public class TaskAdapter extends CursorAdapter implements Filterable { else viewHolder.view.setBackgroundResource(android.R.drawable.list_selector_background); } + + @Override + protected Intent createBroadcastIntent(Task task) { + return null; + } } /** @@ -678,7 +710,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { * @author Tim Su * */ - public class TaskActionManager extends AddOnManager { + public class TaskActionManager extends TaskAdapterAddOnManager { private final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, @@ -686,14 +718,18 @@ public class TaskAdapter extends CursorAdapter implements Filterable { private final Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_REQUEST_ACTIONS); + public TaskActionManager() { + super(activity); + } + @Override - Intent createBroadcastIntent(Task task) { + protected Intent createBroadcastIntent(Task task) { broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, task.getId()); return broadcastIntent; } @Override - void draw(final ViewHolder viewHolder, final long taskId, Collection actions) { + protected void draw(final ViewHolder viewHolder, final long taskId, Collection actions) { if(actions == null || viewHolder.task.getId() != taskId) return; @@ -735,7 +771,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { } @Override - void reset(ViewHolder viewHolder, long taskId) { + protected void reset(ViewHolder viewHolder, long taskId) { if(expanded != taskId) { viewHolder.actions.setVisibility(View.GONE); return; @@ -873,122 +909,4 @@ public class TaskAdapter extends CursorAdapter implements Filterable { } } - /* ====================================================================== - * ========================================================= addon helper - * ====================================================================== */ - - abstract public class AddOnManager { - - private final Map> cache = - Collections.synchronizedMap(new HashMap>(0)); - - // --- interface - - /** - * Request add-ons for the given task - * @return true if cache miss, false if cache hit - */ - public boolean request(ViewHolder viewHolder) { - long taskId = viewHolder.task.getId(); - - Collection list = initialize(taskId); - if(list != null) { - draw(viewHolder, taskId, list); - return false; - } - - // request details - draw(viewHolder, taskId, get(taskId)); - Intent broadcastIntent = createBroadcastIntent(viewHolder.task); - if(broadcastIntent != null) - activity.sendOrderedBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); - return true; - } - - /** creates a broadcast intent for requesting */ - abstract Intent createBroadcastIntent(Task task); - - /** updates the given view */ - abstract void draw(ViewHolder viewHolder, long taskId, Collection list); - - /** resets the view as if there was nothing */ - abstract void reset(ViewHolder viewHolder, long taskId); - - /** on receive an intent */ - public void addNew(long taskId, String addOn, TYPE item) { - if(item == null) - return; - - Collection cacheList = addIfNotExists(taskId, addOn, item); - if(cacheList != null) { - ListView listView = activity.getListView(); - // update view if it is visible - int length = listView.getChildCount(); - for(int i = 0; i < length; i++) { - ViewHolder viewHolder = (ViewHolder) listView.getChildAt(i).getTag(); - if(viewHolder == null || viewHolder.task.getId() != taskId) - continue; - draw(viewHolder, taskId, cacheList); - break; - } - } - } - - /** - * Clears the cache - */ - public void clearCache() { - cache.clear(); - } - - /** - * Clears single item from cache - */ - public void clearCache(long taskId) { - cache.remove(taskId); - } - - // --- internal goodies - - /** - * Retrieves a list. If it doesn't exist, list is created, but - * the method will return null - * @param taskId - * @return list if there was already one - */ - protected synchronized Collection initialize(long taskId) { - if(cache.containsKey(taskId) && cache.get(taskId) != null) - return get(taskId); - cache.put(taskId, new HashMap(0)); - return null; - } - - /** - * Adds an item to the cache if it doesn't exist - * @param taskId - * @param item - * @return iterator if item was added, null if it already existed - */ - protected synchronized Collection addIfNotExists(long taskId, String addOn, - TYPE item) { - HashMap list = cache.get(taskId); - if(list == null) - return null; - if(list.containsKey(addOn) && list.get(addOn).equals(item)) - return null; - list.put(addOn, item); - return get(taskId); - } - - /** - * Gets an item at the given index - * @param taskId - * @return - */ - protected Collection get(long taskId) { - return cache.get(taskId).values(); - } - - } - } diff --git a/astrid/src/com/todoroo/astrid/api/TaskDecorationExposer.java b/astrid/src/com/todoroo/astrid/api/TaskDecorationExposer.java index ccde31380..59b071552 100644 --- a/astrid/src/com/todoroo/astrid/api/TaskDecorationExposer.java +++ b/astrid/src/com/todoroo/astrid/api/TaskDecorationExposer.java @@ -12,10 +12,10 @@ public interface TaskDecorationExposer { /** * Expose task decorations for the given task - * * @param task + * * @return null if no decorations, or decoration */ - public TaskDecoration expose(Filter activeFilter, Task task); + public TaskDecoration expose(Task task); } diff --git a/astrid/src/com/todoroo/astrid/dao/TaskDao.java b/astrid/src/com/todoroo/astrid/dao/TaskDao.java index 57f9a66a4..7f2b7a287 100644 --- a/astrid/src/com/todoroo/astrid/dao/TaskDao.java +++ b/astrid/src/com/todoroo/astrid/dao/TaskDao.java @@ -211,10 +211,11 @@ public class TaskDao extends DatabaseDao { @Override public boolean saveExisting(Task item) { - if(!item.getSetValues().containsKey(Task.DETAILS.name)) + if(!item.getSetValues().containsKey(Task.DETAILS_DATE.name)) { item.setValue(Task.DETAILS, null); - if(!item.getSetValues().containsKey(Task.DETAILS_DATE.name)) item.setValue(Task.MODIFICATION_DATE, DateUtilities.now()); + } + System.err.println(">> SAVE EXISTING: " + item.getSetValues()); return super.saveExisting(item); } diff --git a/astrid/src/com/todoroo/astrid/helper/TaskAdapterAddOnManager.java b/astrid/src/com/todoroo/astrid/helper/TaskAdapterAddOnManager.java new file mode 100644 index 000000000..178aee80a --- /dev/null +++ b/astrid/src/com/todoroo/astrid/helper/TaskAdapterAddOnManager.java @@ -0,0 +1,140 @@ +/** + * + */ +package com.todoroo.astrid.helper; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import android.app.ListActivity; +import android.content.Intent; +import android.widget.ListView; + +import com.todoroo.astrid.adapter.TaskAdapter.ViewHolder; +import com.todoroo.astrid.api.AstridApiConstants; +import com.todoroo.astrid.data.Task; + +abstract public class TaskAdapterAddOnManager { + + private final ListActivity activity; + + /** + * @param taskAdapter + */ + protected TaskAdapterAddOnManager(ListActivity activity) { + this.activity = activity; + } + + private final Map> cache = + Collections.synchronizedMap(new HashMap>(0)); + + // --- interface + + /** + * Request add-ons for the given task + * @return true if cache miss, false if cache hit + */ + public boolean request(ViewHolder viewHolder) { + long taskId = viewHolder.task.getId(); + + Collection list = initialize(taskId); + if(list != null) { + draw(viewHolder, taskId, list); + return false; + } + + // request details + draw(viewHolder, taskId, get(taskId)); + Intent broadcastIntent = createBroadcastIntent(viewHolder.task); + if(broadcastIntent != null) + activity.sendOrderedBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); + return true; + } + + /** creates a broadcast intent for requesting */ + abstract protected Intent createBroadcastIntent(Task task); + + /** updates the given view */ + abstract protected void draw(ViewHolder viewHolder, long taskId, Collection list); + + /** resets the view as if there was nothing */ + abstract protected void reset(ViewHolder viewHolder, long taskId); + + /** on receive an intent */ + public void addNew(long taskId, String addOn, TYPE item) { + if(item == null) + return; + + Collection cacheList = addIfNotExists(taskId, addOn, item); + if(cacheList != null) { + ListView listView = activity.getListView(); + // update view if it is visible + int length = listView.getChildCount(); + for(int i = 0; i < length; i++) { + ViewHolder viewHolder = (ViewHolder) listView.getChildAt(i).getTag(); + if(viewHolder == null || viewHolder.task.getId() != taskId) + continue; + draw(viewHolder, taskId, cacheList); + break; + } + } + } + + /** + * Clears the cache + */ + public void clearCache() { + cache.clear(); + } + + /** + * Clears single item from cache + */ + public void clearCache(long taskId) { + cache.remove(taskId); + } + + // --- internal goodies + + /** + * Retrieves a list. If it doesn't exist, list is created, but + * the method will return null + * @param taskId + * @return list if there was already one + */ + protected synchronized Collection initialize(long taskId) { + if(cache.containsKey(taskId) && cache.get(taskId) != null) + return get(taskId); + cache.put(taskId, new HashMap(0)); + return null; + } + + /** + * Adds an item to the cache if it doesn't exist + * @param taskId + * @param item + * @return iterator if item was added, null if it already existed + */ + protected synchronized Collection addIfNotExists(long taskId, String addOn, + TYPE item) { + HashMap list = cache.get(taskId); + if(list == null) + return null; + if(list.containsKey(addOn) && list.get(addOn).equals(item)) + return null; + list.put(addOn, item); + return get(taskId); + } + + /** + * Gets an item at the given index + * @param taskId + * @return + */ + protected Collection get(long taskId) { + return cache.get(taskId).values(); + } + +} \ No newline at end of file diff --git a/astrid/src/com/todoroo/astrid/utility/Flags.java b/astrid/src/com/todoroo/astrid/utility/Flags.java index 3908433c2..2ac8a0da8 100644 --- a/astrid/src/com/todoroo/astrid/utility/Flags.java +++ b/astrid/src/com/todoroo/astrid/utility/Flags.java @@ -7,7 +7,12 @@ public class Flags { /** * Whether to refresh the task list */ - public static final int REFRESH = 1; + public static final int REFRESH = 1 << 0; + + /** + * Whether active filter is GTasks + */ + public static final int GTASKS = 1 << 1; public static boolean checkAndClear(int flag) { boolean set = (state & flag) > 0; @@ -15,6 +20,10 @@ public class Flags { return set; } + public static boolean check(int flag) { + return (state & flag) > 0; + } + public static void set(int flag) { state |= flag; } diff --git a/tests/src/com/todoroo/astrid/gtasks/GtasksDecorationExposerTest.java b/tests/src/com/todoroo/astrid/gtasks/GtasksDecorationExposerTest.java index a839b45e8..9d92186e2 100644 --- a/tests/src/com/todoroo/astrid/gtasks/GtasksDecorationExposerTest.java +++ b/tests/src/com/todoroo/astrid/gtasks/GtasksDecorationExposerTest.java @@ -66,7 +66,7 @@ public class GtasksDecorationExposerTest extends DatabaseTestCase { inflated.measure(100, 100); int width = inflated.getMeasuredWidth(); - result = new GtasksDecorationExposer().expose(gtasksFilter(), otherTask); + result = new GtasksDecorationExposer().expose(otherTask); View otherInflated = result.decoration.apply(getContext(), null); otherInflated.measure(100, 100); int otherWidth = otherInflated.getMeasuredWidth(); @@ -120,7 +120,7 @@ public class GtasksDecorationExposerTest extends DatabaseTestCase { } private void whenRequestingDecoration(Filter filter, Task task) { - result = new GtasksDecorationExposer().expose(filter, task); + result = new GtasksDecorationExposer().expose(task); } private void givenLoggedInStatus(boolean status) {