Re-wrote producteev note handling to (1) not delete old notes that were not synced, and (2) detect notes deleted from producteev web

pull/14/head
Tim Su 14 years ago
parent 657487fbe5
commit f65222964e

@ -275,6 +275,9 @@ public class EditNoteActivity extends ListActivity {
}
public static NoteOrUpdate fromMetadata(Metadata m) {
if(!m.containsNonNullValue(NoteMetadata.THUMBNAIL))
m.setValue(NoteMetadata.THUMBNAIL, ""); //$NON-NLS-1$
return new NoteOrUpdate(m.getValue(NoteMetadata.THUMBNAIL),
m.getValue(NoteMetadata.TITLE),
m.getValue(NoteMetadata.BODY),
@ -323,7 +326,12 @@ public class EditNoteActivity extends ListActivity {
public synchronized void bindView(View view, NoteOrUpdate item) {
// picture
final AsyncImageView pictureView = (AsyncImageView)view.findViewById(R.id.picture); {
pictureView.setUrl(item.picture);
if(TextUtils.isEmpty(item.picture))
pictureView.setVisibility(View.GONE);
else {
pictureView.setVisibility(View.VISIBLE);
pictureView.setUrl(item.picture);
}
}
// name

@ -7,7 +7,6 @@ import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
@ -45,8 +44,8 @@ public class EditNoteExposer extends BroadcastReceiver {
int drawable;
if(!actFmPreferenceService.isLoggedIn()) {
Task task = PluginServices.getTaskService().fetchById(taskId, Task.NOTES);
if(task == null || TextUtils.isEmpty(task.getValue(Task.NOTES)))
Task task = PluginServices.getTaskService().fetchById(taskId, Task.ID, Task.NOTES);
if(task == null || !NotesPlugin.hasNotes(task))
return;
label = context.getString(R.string.ENE_label);
drawable = R.drawable.ic_qbar_comments;

@ -3,7 +3,6 @@
*/
package com.todoroo.astrid.notes;
import android.text.TextUtils;
import android.widget.RemoteViews;
import com.timsu.astrid.R;
@ -25,10 +24,9 @@ public class NotesDecorationExposer implements TaskDecorationExposer {
public TaskDecoration expose(Task task) {
if(Preferences.getBoolean(R.string.p_showNotes, false))
return null;
if(task == null || TextUtils.isEmpty(task.getValue(Task.NOTES)))
if(task == null || !NotesPlugin.hasNotes(task))
return null;
TaskDecoration decoration;
RemoteViews remoteViews = new RemoteViews(ContextManager.getContext().getPackageName(),
R.layout.note_decoration);

@ -98,13 +98,13 @@ public class ProducteevDetailExposer extends BroadcastReceiver {
// display responsible user if not current one
if(responsibleId > 0 && ownerDashboard != null && responsibleId !=
Preferences.getLong(ProducteevUtilities.PREF_USER_ID, 0L)) {
String user = getUserFromDashboard(ownerDashboard, responsibleId);
String user = ProducteevDashboard.getUserFromDashboard(ownerDashboard, responsibleId);
if(user != null)
builder.append("<img src='silk_user_gray'/> ").append(user).append(TaskAdapter.DETAIL_SEPARATOR); //$NON-NLS-1$
} else {
// display creator user if not responsible user
if(creatorId > 0 && ownerDashboard != null && creatorId != responsibleId) {
String user = getUserFromDashboard(ownerDashboard, creatorId);
String user = ProducteevDashboard.getUserFromDashboard(ownerDashboard, creatorId);
if(user != null)
builder.append("<img src='silk_user_orange'/> ").append( //$NON-NLS-1$
context.getString(R.string.producteev_PDE_task_from, user)).
@ -175,14 +175,4 @@ public class ProducteevDetailExposer extends BroadcastReceiver {
return result.substring(0, result.length() - TaskAdapter.DETAIL_SEPARATOR.length());
}
/** Try and find user in the dashboard. return null if un-findable */
private String getUserFromDashboard(StoreObject dashboard, long userId) {
String users = ";" + dashboard.getValue(ProducteevDashboard.USERS); //$NON-NLS-1$
int index = users.indexOf(";" + userId + ","); //$NON-NLS-1$ //$NON-NLS-2$
if(index > -1)
return users.substring(users.indexOf(',', index) + 1,
users.indexOf(';', index + 1));
return null;
}
}

@ -83,10 +83,11 @@ public final class ApiUtilities {
/**
* Create metadata from json object
* @param note JSON object with params id_note and message
* @param creatorName
* @return
*/
@SuppressWarnings("nls")
public static Metadata createNoteMetadata(JSONObject note) {
public static Metadata createNoteMetadata(JSONObject note, String creatorName) {
Metadata metadata = new Metadata();
metadata.setValue(Metadata.KEY, NoteMetadata.METADATA_KEY);
metadata.setValue(NoteMetadata.EXT_ID, note.optString("id_note"));
@ -96,8 +97,10 @@ public final class ApiUtilities {
long created = ApiUtilities.producteevToUnixTime(note.optString("time_create"), 0);
metadata.setValue(Metadata.CREATION_DATE, created);
// TODO if id_creator != yourself, update the title
metadata.setValue(NoteMetadata.TITLE, DateUtilities.getDateStringWithWeekday(ContextManager.getContext(),
if(creatorName != null)
metadata.setValue(NoteMetadata.TITLE, creatorName);
else
metadata.setValue(NoteMetadata.TITLE, DateUtilities.getDateStringWithWeekday(ContextManager.getContext(),
new Date(created)));
return metadata;
}

@ -102,4 +102,14 @@ public class ProducteevDashboard {
public ArrayList<ProducteevUser> getUsers() {
return users;
}
/** Try and find user in the dashboard. return null if un-findable */
public static String getUserFromDashboard(StoreObject dashboard, long userId) {
String users = ";" + dashboard.getValue(USERS); //$NON-NLS-1$
int index = users.indexOf(";" + userId + ","); //$NON-NLS-1$ //$NON-NLS-2$
if(index > -1)
return users.substring(users.indexOf(',', index) + 1,
users.indexOf(';', index + 1));
return null;
}
}

@ -154,8 +154,6 @@ public final class ProducteevDataService {
task.metadata.add(task.pdvTask);
metadataService.synchronizeMetadata(task.task.getId(), task.metadata,
Criterion.or(MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
Criterion.and(MetadataCriteria.withKey(NoteMetadata.METADATA_KEY),
NoteMetadata.EXT_PROVIDER.eq(NOTE_PROVIDER)),
MetadataCriteria.withKey(TagService.KEY)));
}

@ -27,6 +27,7 @@ import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService;
import com.todoroo.andlib.service.NotificationManager;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.Preferences;
@ -37,6 +38,7 @@ import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.notes.NoteMetadata;
import com.todoroo.astrid.producteev.ProducteevBackgroundService;
import com.todoroo.astrid.producteev.ProducteevFilterExposer;
import com.todoroo.astrid.producteev.ProducteevLoginActivity;
@ -184,8 +186,6 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
saveUserData(user);
String lastServerSync = Preferences.getStringValue(ProducteevUtilities.PREF_SERVER_LAST_SYNC);
String lastNotificationId = Preferences.getStringValue(ProducteevUtilities.PREF_SERVER_LAST_NOTIFICATION);
String lastActivityId = Preferences.getStringValue(ProducteevUtilities.PREF_SERVER_LAST_ACTIVITY);
// read dashboards
JSONArray dashboards = invoker.dashboardsShowList(lastServerSync);
@ -239,54 +239,7 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
ContextManager.getContext().sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
// notification/activities stuff
JSONArray notifications = invoker.activitiesShowNotifications(null, (lastNotificationId == null ? null : new Long(lastNotificationId)));
String[] notificationsList = parseActivities(notifications);
// update lastIds
if (notifications.length() > 0) {
lastNotificationId = ""+notifications.getJSONObject(0).getJSONObject("activity").getLong("id_activity");
}
// display notifications from producteev-log
Context context = ContextManager.getContext();
final NotificationManager nm = new NotificationManager.AndroidNotificationManager(context);
for (int i = 0; i< notificationsList.length; i++) {
long id_dashboard = notifications.getJSONObject(i).getJSONObject("activity").getLong("id_dashboard");
String dashboardName = null;
StoreObject[] dashboardsData = ProducteevDataService.getInstance().getDashboards();
ProducteevDashboard dashboard = null;
if (dashboardsData != null) {
for (int j=0; i<dashboardsData.length;i++) {
long id = dashboardsData[j].getValue(ProducteevDashboard.REMOTE_ID);
if (id == id_dashboard) {
dashboardName = dashboardsData[j].getValue(ProducteevDashboard.NAME);
dashboard = new ProducteevDashboard(id, dashboardName, null);
break;
}
}
}
// it seems dashboard is null if we get a notification about an unknown dashboard, just filter it.
if (dashboard != null) {
// initialize notification
int icon = R.drawable.ic_producteev_notification;
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, null, when);
CharSequence contentTitle = context.getString(R.string.producteev_notification_title)+": "+dashboard.getName();
Filter filter = ProducteevFilterExposer.filterFromList(context, dashboard, userId);
Intent notificationIntent = ShortcutActivity.createIntent(filter);
// filter the tags from the message
String message = notificationsList[i].replaceAll("<[^>]+>", "");
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, message, contentIntent);
nm.notify(Constants.NOTIFICATION_PRODUCTEEV_NOTIFICATIONS-i, notification);
}
}
// store lastIds in Preferences
Preferences.setString(ProducteevUtilities.PREF_SERVER_LAST_NOTIFICATION, lastNotificationId);
Preferences.setString(ProducteevUtilities.PREF_SERVER_LAST_ACTIVITY, lastActivityId);
processNotifications();
StatisticsService.reportEvent("pdv-sync-finished"); //$NON-NLS-1$
} catch (IllegalStateException e) {
@ -391,7 +344,7 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
return newRemoteTask;
}
/** Create a task container for the given RtmTaskSeries
/** Create a task container for the given ProducteevTask
* @throws JSONException */
private ProducteevTaskContainer parseRemoteTask(JSONObject remoteTask) throws JSONException {
Task task = new Task();
@ -424,17 +377,35 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
metadata.add(tagData);
}
ProducteevTaskContainer container = new ProducteevTaskContainer(task, metadata, remoteTask);
JSONArray notes = remoteTask.getJSONArray("notes");
for(int i = notes.length() - 1; i >= 0; i--) {
JSONObject note = notes.getJSONObject(i).getJSONObject("note");
metadata.add(ApiUtilities.createNoteMetadata(note));
}
if(note.getLong("deleted") != 0) {
PluginServices.getMetadataService().deleteWhere(Criterion.and(Metadata.KEY.eq(NoteMetadata.METADATA_KEY),
NoteMetadata.EXT_ID.eq(note.getString("id_note"))));
continue;
}
ProducteevTaskContainer container = new ProducteevTaskContainer(task, metadata, remoteTask);
long creator = note.getLong("id_creator");
metadata.add(ApiUtilities.createNoteMetadata(note, creatorName(container, creator)));
}
return container;
}
private String creatorName(ProducteevTaskContainer container, long creator) {
StoreObject[] dashboards = dataService.getDashboards();
for(int i = 0; i < dashboards.length; i++) {
Long dashboard = container.pdvTask.getValue(ProducteevTask.DASHBOARD_ID);
if(dashboard.equals(dashboards[i].getValue(ProducteevDashboard.REMOTE_ID))) {
return ProducteevDashboard.getUserFromDashboard(dashboards[i], creator);
}
}
return null;
}
@Override
protected ProducteevTaskContainer pull(ProducteevTaskContainer task) throws IOException {
if(!task.pdvTask.containsNonNullValue(ProducteevTask.ID))
@ -541,7 +512,7 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
if(!TextUtils.isEmpty(local.task.getValue(Task.NOTES))) {
String note = local.task.getValue(Task.NOTES);
JSONObject result = invoker.tasksNoteCreate(idTask, note);
local.metadata.add(ApiUtilities.createNoteMetadata(result.getJSONObject("note")));
local.metadata.add(ApiUtilities.createNoteMetadata(result.getJSONObject("note"), null));
local.task.setValue(Task.NOTES, "");
}
@ -745,6 +716,68 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
return label.getLong("id_label");
}
/**
* Show workspace notifications
*
* @throws ApiResponseParseException
* @throws ApiServiceException
* @throws IOException
* @throws JSONException
*/
private void processNotifications() throws ApiResponseParseException,
ApiServiceException, IOException, JSONException {
String lastNotificationId = Preferences.getStringValue(ProducteevUtilities.PREF_SERVER_LAST_NOTIFICATION);
String lastActivityId = Preferences.getStringValue(ProducteevUtilities.PREF_SERVER_LAST_ACTIVITY);
JSONArray notifications = invoker.activitiesShowNotifications(null, (lastNotificationId == null ? null : new Long(lastNotificationId)));
String[] notificationsList = parseActivities(notifications);
// update lastIds
if (notifications.length() > 0) {
lastNotificationId = ""+notifications.getJSONObject(0).getJSONObject("activity").getLong("id_activity");
}
// display notifications from producteev-log
Context context = ContextManager.getContext();
final NotificationManager nm = new NotificationManager.AndroidNotificationManager(context);
for (int i = 0; i< notificationsList.length; i++) {
long id_dashboard = notifications.getJSONObject(i).getJSONObject("activity").getLong("id_dashboard");
String dashboardName = null;
StoreObject[] dashboardsData = ProducteevDataService.getInstance().getDashboards();
ProducteevDashboard dashboard = null;
if (dashboardsData != null) {
for (int j=0; i<dashboardsData.length;i++) {
long id = dashboardsData[j].getValue(ProducteevDashboard.REMOTE_ID);
if (id == id_dashboard) {
dashboardName = dashboardsData[j].getValue(ProducteevDashboard.NAME);
dashboard = new ProducteevDashboard(id, dashboardName, null);
break;
}
}
}
// it seems dashboard is null if we get a notification about an unknown dashboard, just filter it.
if (dashboard != null) {
// initialize notification
int icon = R.drawable.ic_producteev_notification;
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, null, when);
CharSequence contentTitle = context.getString(R.string.producteev_notification_title)+": "+dashboard.getName();
Filter filter = ProducteevFilterExposer.filterFromList(context, dashboard, userId);
Intent notificationIntent = ShortcutActivity.createIntent(filter);
// filter the tags from the message
String message = notificationsList[i].replaceAll("<[^>]+>", "");
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, message, contentIntent);
nm.notify(Constants.NOTIFICATION_PRODUCTEEV_NOTIFICATIONS-i, notification);
}
}
// store lastIds in Preferences
Preferences.setString(ProducteevUtilities.PREF_SERVER_LAST_NOTIFICATION, lastNotificationId);
Preferences.setString(ProducteevUtilities.PREF_SERVER_LAST_ACTIVITY, lastActivityId);
}
// ----------------------------------------------------------------------
// ------------------------------------------------------- helper methods
// ----------------------------------------------------------------------

Loading…
Cancel
Save