Removed all producteev source files

pull/14/head
Sam Bosley 11 years ago
parent 8d298dda58
commit 3622ae6bc1

@ -647,58 +647,6 @@
android:clearTaskOnLaunch="true">
</activity>
<service android:name="com.todoroo.astrid.reminders.ReminderSchedulingService"/>
<!-- producteev -->
<receiver android:name="com.todoroo.astrid.producteev.ProducteevFilterExposer">
<intent-filter>
<action android:name="com.todoroo.astrid.REQUEST_FILTERS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name="com.todoroo.astrid.producteev.ProducteevCustomFilterCriteriaExposer">
<intent-filter>
<action android:name="com.todoroo.astrid.REQUEST_CUSTOM_FILTER_CRITERIA" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity android:name="com.todoroo.astrid.producteev.ProducteevPreferences"
android:theme="@android:style/Theme"
android:label="@string/producteev_PPr_header">
<meta-data android:name="category"
android:resource="@string/SyP_label" />
<meta-data android:name="syncAction"
android:value="true" />
<intent-filter>
<action android:name="com.todoroo.astrid.SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.todoroo.astrid.producteev.ProducteevLoginActivity"
android:configChanges="orientation|keyboardHidden" />
<service android:name="com.todoroo.astrid.producteev.ProducteevBackgroundService">
<intent-filter>
<action android:name="com.todoroo.astrid.producteev.SYNC" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
<receiver android:name="com.todoroo.astrid.producteev.ProducteevStartupReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name="com.todoroo.astrid.producteev.ProducteevDetailExposer">
<intent-filter>
<action android:name="com.todoroo.astrid.REQUEST_DETAILS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name="com.todoroo.astrid.producteev.ProducteevSyncActionExposer">
<intent-filter>
<action android:name="com.todoroo.astrid.REQUEST_SYNC_ACTIONS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- rmilk -->
<receiver android:name="org.weloveastrid.rmilk.MilkFilterExposer">

@ -1,47 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev;
import com.todoroo.astrid.producteev.sync.ProducteevSyncProvider;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.sync.SyncBackgroundService;
import com.todoroo.astrid.sync.SyncProvider;
import com.todoroo.astrid.sync.SyncProviderUtilities;
/**
* SynchronizationService is the service that performs Astrid's background
* synchronization with online task managers. Starting this service
* schedules a repeating alarm which handles the synchronization
*
* @author Tim Su
*
*/
public class ProducteevBackgroundService extends SyncBackgroundService {
@Override
protected SyncProvider<?> getSyncProvider() {
return new ProducteevSyncProvider();
}
@Override
protected SyncProviderUtilities getSyncUtilities() {
return ProducteevUtilities.INSTANCE;
}
@Override
public void onCreate() {
super.onCreate();
StatisticsService.sessionStart(this);
}
@Override
public void onDestroy() {
StatisticsService.sessionStop(this);
super.onDestroy();
}
}

@ -1,285 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev;
import java.util.ArrayList;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.producteev.sync.ProducteevDashboard;
import com.todoroo.astrid.producteev.sync.ProducteevDataService;
import com.todoroo.astrid.producteev.sync.ProducteevSyncProvider;
import com.todoroo.astrid.producteev.sync.ProducteevTask;
import com.todoroo.astrid.producteev.sync.ProducteevUser;
import com.todoroo.astrid.service.MetadataService;
import com.todoroo.astrid.ui.PopupControlSet;
/**
* Control Set for managing task/dashboard assignments in Producteev
*
* @author Arne Jans <arne.jans@gmail.com>
*
*/
public class ProducteevControlSet extends PopupControlSet {
private Spinner responsibleSelector;
private Spinner dashboardSelector;
private ArrayList<ProducteevUser> users = null;
private ArrayList<ProducteevDashboard> dashboards = null;
@Autowired MetadataService metadataService;
@Autowired ExceptionService exceptionService;
private int lastDashboardSelection = 0;
public ProducteevControlSet(final Activity activity, int layout, int displayViewLayout, int title) {
super(activity, layout, displayViewLayout, title);
DependencyInjectionService.getInstance().inject(this);
}
/**
* Refresh the content of the responsibleSelector with the given userlist.
*
* @param newUsers the new userlist to show in the responsibleSelector
*/
private void refreshResponsibleSpinner(ArrayList<ProducteevUser> newUsers) {
Metadata metadata = ProducteevDataService.getInstance().getTaskMetadata(model.getId());
long responsibleId = -1;
if(metadata != null && metadata.containsNonNullValue(ProducteevTask.RESPONSIBLE_ID))
responsibleId = metadata.getValue(ProducteevTask.RESPONSIBLE_ID);
refreshResponsibleSpinner(newUsers, responsibleId);
}
/**
* Refresh the content of the responsibleSelector with the given userlist.
*
* @param newUsers the new userlist to show in the responsibleSelector
* @param responsibleId the id of the responsible user to set in the spinner
*/
private void refreshResponsibleSpinner(ArrayList<ProducteevUser> newUsers, long responsibleId) {
// Fill the responsible-spinner and set the current responsible
this.users = (newUsers == null ? new ArrayList<ProducteevUser>() : newUsers);
ArrayAdapter<ProducteevUser> usersAdapter = new ArrayAdapter<ProducteevUser>(activity,
android.R.layout.simple_spinner_item, this.users);
usersAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
responsibleSelector.setAdapter(usersAdapter);
int visibility = newUsers == null ? View.GONE : View.VISIBLE;
getView().findViewById(R.id.producteev_TEA_task_assign_label).setVisibility(visibility);
responsibleSelector.setVisibility(visibility);
int responsibleSpinnerIndex = 0;
for (int i = 0; i < this.users.size() ; i++) {
if (this.users.get(i).getId() == responsibleId ||
(responsibleId == -1 && this.users.get(i).getId() == Preferences.getLong(ProducteevUtilities.PREF_USER_ID, -1))) {
responsibleSpinnerIndex = i;
break;
}
}
responsibleSelector.setSelection(responsibleSpinnerIndex);
}
@Override
protected void readFromTaskOnInitialize() {
Metadata metadata = ProducteevDataService.getInstance().getTaskMetadata(model.getId());
if(metadata == null)
metadata = ProducteevTask.newMetadata();
// Fill the dashboard-spinner and set the current dashboard
long dashboardId = ProducteevUtilities.INSTANCE.getDefaultDashboard();
if(metadata.containsNonNullValue(ProducteevTask.DASHBOARD_ID))
dashboardId = metadata.getValue(ProducteevTask.DASHBOARD_ID);
StoreObject[] dashboardsData = ProducteevDataService.getInstance().getDashboards();
dashboards = new ArrayList<ProducteevDashboard>(dashboardsData.length);
ProducteevDashboard ownerDashboard = null;
int dashboardSpinnerIndex = -1;
int i = 0;
for (i=0;i<dashboardsData.length;i++) {
ProducteevDashboard dashboard = new ProducteevDashboard(dashboardsData[i]);
dashboards.add(dashboard);
if(dashboard.getId() == dashboardId) {
ownerDashboard = dashboard;
dashboardSpinnerIndex = i;
}
}
//dashboard to not sync as first spinner-entry
dashboards.add(0, new ProducteevDashboard(ProducteevUtilities.DASHBOARD_NO_SYNC, activity.getString(R.string.producteev_no_dashboard),null));
// dummy entry for adding a new dashboard
dashboards.add(new ProducteevDashboard(ProducteevUtilities.DASHBOARD_CREATE, activity.getString(R.string.producteev_create_dashboard),null));
ArrayAdapter<ProducteevDashboard> dashAdapter = new ArrayAdapter<ProducteevDashboard>(activity,
android.R.layout.simple_spinner_item, dashboards);
dashAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
dashboardSelector.setAdapter(dashAdapter);
dashboardSelector.setSelection(dashboardSpinnerIndex+1);
if (ownerDashboard == null || ownerDashboard.getId() == ProducteevUtilities.DASHBOARD_NO_SYNC
|| ownerDashboard.getId() == ProducteevUtilities.DASHBOARD_CREATE) {
responsibleSelector.setEnabled(false);
responsibleSelector.setAdapter(null);
getView().findViewById(R.id.producteev_TEA_task_assign_label).setVisibility(View.GONE);
return;
}
refreshResponsibleSpinner(ownerDashboard.getUsers());
}
@Override
protected void afterInflate() {
this.displayText.setText(activity.getString(R.string.producteev_TEA_control_set_display));
//view = LayoutInflater.from(activity).inflate(R.layout.producteev_control, parent, true);
this.responsibleSelector = (Spinner) getView().findViewById(R.id.producteev_TEA_task_assign);
TextView emptyView = new TextView(activity);
emptyView.setText(activity.getText(R.string.producteev_no_dashboard));
responsibleSelector.setEmptyView(emptyView);
this.dashboardSelector = (Spinner) getView().findViewById(R.id.producteev_TEA_dashboard_assign);
this.dashboardSelector.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> spinnerParent, View spinnerView,
int position, long id) {
final Spinner dashSelector = (Spinner) spinnerParent;
ProducteevDashboard dashboard = (ProducteevDashboard) dashSelector.getSelectedItem();
if (dashboard.getId() == ProducteevUtilities.DASHBOARD_CREATE) {
// let the user create a new dashboard
final EditText editor = new EditText(ProducteevControlSet.this.activity);
OnClickListener okListener = new OnClickListener() {
@Override
public void onClick(DialogInterface dlg, int which) {
Activity context = ProducteevControlSet.this.activity;
String newDashboardName = editor.getText().toString();
if (newDashboardName == null || newDashboardName.length() == 0) {
dlg.cancel();
} else {
// create the real dashboard, select it in the spinner and refresh responsiblespinner
ProgressDialog progressDialog = com.todoroo.andlib.utility.DialogUtilities.progressDialog(context,
context.getString(R.string.DLG_wait));
try {
progressDialog.show();
JSONObject newDashJSON = ProducteevSyncProvider.getInvoker().dashboardsCreate(
newDashboardName).getJSONObject("dashboard"); //$NON-NLS-1$
StoreObject local = ProducteevDataService.getInstance().updateDashboards(newDashJSON, true);
if (local != null) {
ProducteevDashboard newDashboard = new ProducteevDashboard(local);
ArrayAdapter<ProducteevDashboard> adapter = (ArrayAdapter<ProducteevDashboard>) dashSelector.getAdapter();
adapter.insert(newDashboard, adapter.getCount()-1);
dashSelector.setSelection(adapter.getCount()-2);
refreshResponsibleSpinner(newDashboard.getUsers());
DialogUtilities.dismissDialog(context, progressDialog);
}
} catch (Exception e) {
DialogUtilities.dismissDialog(context, progressDialog);
DialogUtilities.okDialog(context,
context.getString(R.string.DLG_error, e.getMessage()),
null);
exceptionService.reportError("pdv-create-dashboard", e); //$NON-NLS-1$
dashSelector.setSelection(0);
}
}
}
};
OnClickListener cancelListener = new OnClickListener() {
@Override
public void onClick(DialogInterface dlg, int which) {
dlg.cancel();
dashboardSelector.setSelection(lastDashboardSelection);
}
};
DialogUtilities.viewDialog(ProducteevControlSet.this.activity,
ProducteevControlSet.this.activity.getString(R.string.producteev_create_dashboard_name),
editor,
okListener,
cancelListener);
} else {
refreshResponsibleSpinner(dashboard.getUsers());
lastDashboardSelection = position;
}
}
@Override
public void onNothingSelected(AdapterView<?> spinnerParent) {
//
}
});
}
@Override
protected String writeToModelAfterInitialized(Task task) {
Metadata metadata = ProducteevDataService.getInstance().getTaskMetadata(task.getId());
try {
if (metadata == null) {
metadata = new Metadata();
metadata.setValue(Metadata.KEY, ProducteevTask.METADATA_KEY);
metadata.setValue(Metadata.TASK, task.getId());
metadata.setValue(ProducteevTask.ID, 0L);
}
ProducteevDashboard dashboard = (ProducteevDashboard) dashboardSelector.getSelectedItem();
metadata.setValue(ProducteevTask.DASHBOARD_ID, dashboard.getId());
ProducteevUser responsibleUser = (ProducteevUser) responsibleSelector.getSelectedItem();
if(responsibleUser == null)
metadata.setValue(ProducteevTask.RESPONSIBLE_ID, 0L);
else
metadata.setValue(ProducteevTask.RESPONSIBLE_ID, responsibleUser.getId());
// Erase PDTV-repeating-info if task itself is repeating with Astrid-repeat
if (task.containsNonNullValue(Task.RECURRENCE) && task.getValue(Task.RECURRENCE).length()>0) {
metadata.setValue(ProducteevTask.REPEATING_SETTING, ""); //$NON-NLS-1$
}
if(metadata.getSetValues().size() > 0) {
metadataService.save(metadata);
task.setValue(Task.MODIFICATION_DATE, DateUtilities.now());
}
} catch (Exception e) {
Log.e("error-saving-pdv", "Error Saving Metadata", e); //$NON-NLS-1$ //$NON-NLS-2$
}
return null;
}
@Override
protected void refreshDisplayView() {
// TODO Auto-generated method stub
}
}

@ -1,124 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev;
import java.util.Set;
import java.util.TreeSet;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
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;
import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Query;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.CustomFilterCriterion;
import com.todoroo.astrid.api.MultipleSelectCriterion;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.producteev.sync.ProducteevDashboard;
import com.todoroo.astrid.producteev.sync.ProducteevDataService;
import com.todoroo.astrid.producteev.sync.ProducteevTask;
import com.todoroo.astrid.producteev.sync.ProducteevUser;
public class ProducteevCustomFilterCriteriaExposer extends BroadcastReceiver {
private static final String IDENTIFIER_PRODUCTEEV_WORKSPACE = "producteev_workspace"; //$NON-NLS-1$
private static final String IDENTIFIER_PRODUCTEEV_ASSIGNEE = "producteev_assignee"; //$NON-NLS-1$
@SuppressWarnings("nls")
@Override
public void onReceive(Context context, Intent intent) {
// if we aren't logged in, don't expose features
if(!ProducteevUtilities.INSTANCE.isLoggedIn())
return;
Resources r = context.getResources();
StoreObject[] objects = ProducteevDataService.getInstance().getDashboards();
ProducteevDashboard[] dashboards = new ProducteevDashboard[objects.length];
for (int i = 0; i < objects.length; i++) {
dashboards[i] = new ProducteevDashboard(objects[i]);
}
CustomFilterCriterion[] ret = new CustomFilterCriterion[2];
int j = 0;
{
String[] workspaceNames = new String[objects.length];
String[] workspaceIds = new String[objects.length];
for (int i = 0; i < dashboards.length; i++) {
workspaceNames[i] = dashboards[i].getName();
workspaceIds[i] = String.valueOf(dashboards[i].getId());
}
ContentValues values = new ContentValues();
values.put(Metadata.KEY.name, ProducteevTask.METADATA_KEY);
values.put(ProducteevTask.DASHBOARD_ID.name, "?");
CustomFilterCriterion criterion = new MultipleSelectCriterion(
IDENTIFIER_PRODUCTEEV_WORKSPACE,
context.getString(R.string.CFC_producteev_in_workspace_text),
// Todo: abstract these metadata queries
Query.select(Metadata.TASK).from(Metadata.TABLE).join(Join.inner(
Task.TABLE, Metadata.TASK.eq(Task.ID))).where(Criterion.and(
TaskDao.TaskCriteria.activeAndVisible(),
MetadataDao.MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
ProducteevTask.DASHBOARD_ID.eq("?"))).toString(),
values,
workspaceNames,
workspaceIds,
((BitmapDrawable)r.getDrawable(R.drawable.silk_folder)).getBitmap(),
context.getString(R.string.CFC_producteev_in_workspace_name));
ret[j++] = criterion;
}
{
Set<ProducteevUser> users = new TreeSet<ProducteevUser>();
for (ProducteevDashboard dashboard : dashboards) {
users.addAll(dashboard.getUsers());
}
int numUsers = users.size();
String[] userNames = new String[numUsers];
String[] userIds = new String[numUsers];
int i = 0;
for (ProducteevUser user : users) {
userNames[i] = user.toString();
userIds[i] = String.valueOf(user.getId());
i++;
}
ContentValues values = new ContentValues(2);
values.put(Metadata.KEY.name, ProducteevTask.METADATA_KEY);
values.put(ProducteevTask.RESPONSIBLE_ID.name, "?");
CustomFilterCriterion criterion = new MultipleSelectCriterion(
IDENTIFIER_PRODUCTEEV_ASSIGNEE,
context.getString(R.string.CFC_producteev_assigned_to_text),
// Todo: abstract these metadata queries, and unify this code with the CustomFilterExposers.
Query.select(Metadata.TASK).from(Metadata.TABLE).join(Join.inner(
Task.TABLE, Metadata.TASK.eq(Task.ID))).where(Criterion.and(
TaskDao.TaskCriteria.activeAndVisible(),
MetadataDao.MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
ProducteevTask.RESPONSIBLE_ID.eq("?"))).toString(),
values,
userNames,
userIds,
((BitmapDrawable)r.getDrawable(R.drawable.silk_user_gray)).getBitmap(),
context.getString(R.string.CFC_producteev_assigned_to_name));
ret[j++] = criterion;
}
// transmit filter list
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_CUSTOM_FILTER_CRITERIA);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, ProducteevUtilities.IDENTIFIER);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, ret);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
}

@ -1,180 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.adapter.TaskAdapter;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.producteev.sync.ProducteevDashboard;
import com.todoroo.astrid.producteev.sync.ProducteevDataService;
import com.todoroo.astrid.producteev.sync.ProducteevTask;
/**
* Exposes Task Details for Producteev:
* - notes
*
* @author Tim Su <tim@todoroo.com>
*
*/
public class ProducteevDetailExposer extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ContextManager.setContext(context);
long taskId = intent.getLongExtra(AstridApiConstants.EXTRAS_TASK_ID, -1);
if(taskId == -1)
return;
String taskDetail;
try {
taskDetail = getTaskDetails(context, taskId);
} catch (Exception e) {
return;
}
if(taskDetail == null)
return;
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_DETAILS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, ProducteevUtilities.IDENTIFIER);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, taskDetail);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
@SuppressWarnings("nls")
public String getTaskDetails(Context context, long id) {
Metadata metadata = ProducteevDataService.getInstance().getTaskMetadata(id);
if(metadata == null)
return null;
StringBuilder builder = new StringBuilder();
if(!ProducteevUtilities.INSTANCE.isLoggedIn())
return null;
long dashboardId = -1;
if(metadata.containsNonNullValue(ProducteevTask.DASHBOARD_ID))
dashboardId = metadata.getValue(ProducteevTask.DASHBOARD_ID);
long responsibleId = -1;
if(metadata.containsNonNullValue(ProducteevTask.RESPONSIBLE_ID))
responsibleId = metadata.getValue(ProducteevTask.RESPONSIBLE_ID);
long creatorId = -1;
if(metadata.containsNonNullValue(ProducteevTask.CREATOR_ID))
creatorId = metadata.getValue(ProducteevTask.CREATOR_ID);
String repeatSetting = null;
if(metadata.containsNonNullValue(ProducteevTask.REPEATING_SETTING))
repeatSetting = metadata.getValue(ProducteevTask.REPEATING_SETTING);
// display dashboard if not "no sync" or "default"
StoreObject ownerDashboard = null;
for(StoreObject dashboard : ProducteevDataService.getInstance().getDashboards()) {
if(dashboard == null || !dashboard.containsNonNullValue(ProducteevDashboard.REMOTE_ID))
continue;
if(dashboard.getValue(ProducteevDashboard.REMOTE_ID) == dashboardId) {
ownerDashboard = dashboard;
break;
}
}
if(dashboardId != ProducteevUtilities.DASHBOARD_NO_SYNC && dashboardId
!= Preferences.getLong(ProducteevUtilities.PREF_DEFAULT_DASHBOARD, 0L) &&
ownerDashboard != null) {
String dashboardName = ownerDashboard.getValue(ProducteevDashboard.NAME);
builder.append("<img src='silk_folder'/> ").append(dashboardName).append(TaskAdapter.DETAIL_SEPARATOR); //$NON-NLS-1$
}
// display responsible user if not current one
if(responsibleId > 0 && ownerDashboard != null && responsibleId !=
Preferences.getLong(ProducteevUtilities.PREF_USER_ID, 0L)) {
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 = 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)).
append(TaskAdapter.DETAIL_SEPARATOR);
}
}
// display repeating task information
if (repeatSetting != null && repeatSetting.length() > 0) {
String interval = null;
String[] pdvRepeating = repeatSetting.split(",");
int pdvRepeatingValue = 0;
String pdvRepeatingDay = null;
try {
pdvRepeatingValue = Integer.parseInt(pdvRepeating[0]);
} catch (Exception e) {
pdvRepeatingDay = pdvRepeating[0];
pdvRepeatingValue = 1;
}
String pdvRepeatingInterval = pdvRepeating[1];
if (pdvRepeatingInterval.startsWith("day")) {
interval = context.getResources().getQuantityString(R.plurals.DUt_days, pdvRepeatingValue,
pdvRepeatingValue);
} else if (pdvRepeatingInterval.startsWith("weekday")) {
interval = context.getResources().getQuantityString(R.plurals.DUt_weekdays, pdvRepeatingValue,
pdvRepeatingValue);
} else if (pdvRepeatingInterval.startsWith("week")) {
interval = context.getResources().getQuantityString(R.plurals.DUt_weeks, pdvRepeatingValue,
pdvRepeatingValue);
} else if (pdvRepeatingInterval.startsWith("month")) {
interval = context.getResources().getQuantityString(R.plurals.DUt_months, pdvRepeatingValue,
pdvRepeatingValue);
} else if (pdvRepeatingInterval.startsWith("year")) {
interval = context.getResources().getQuantityString(R.plurals.DUt_years, pdvRepeatingValue,
pdvRepeatingValue);
}
interval = "<b>" + interval + "</b>"; //$NON-NLS-1$//$NON-NLS-2$
if (pdvRepeatingDay != null) {
DateFormatSymbols dfs = new DateFormatSymbols();
String[] weekdays = dfs.getShortWeekdays();
if (pdvRepeatingDay.equals("monday")) {
pdvRepeatingDay = weekdays[Calendar.MONDAY];
} else if (pdvRepeatingDay.equals("tuesday")) {
pdvRepeatingDay = weekdays[Calendar.TUESDAY];
} else if (pdvRepeatingDay.equals("wednesday")) {
pdvRepeatingDay = weekdays[Calendar.WEDNESDAY];
} else if (pdvRepeatingDay.equals("thursday")) {
pdvRepeatingDay = weekdays[Calendar.THURSDAY];
} else if (pdvRepeatingDay.equals("friday")) {
pdvRepeatingDay = weekdays[Calendar.FRIDAY];
} else if (pdvRepeatingDay.equals("saturday")) {
pdvRepeatingDay = weekdays[Calendar.SATURDAY];
} else if (pdvRepeatingDay.equals("sunday")) {
pdvRepeatingDay = weekdays[Calendar.SUNDAY];
}
interval = context.getResources().getString(R.string.repeat_detail_byday).replace("$I", //$NON-NLS-1$
interval).replace("$D", pdvRepeatingDay); //$NON-NLS-1$
}
String detail = context.getString(R.string.repeat_detail_duedate, interval);
builder.append("<img src='repeating_deadline'/> ").append(detail). //$NON-NLS-1$
append(TaskAdapter.DETAIL_SEPARATOR);
}
if(builder.length() == 0)
return null;
String result = builder.toString();
return result.substring(0, result.length() - TaskAdapter.DETAIL_SEPARATOR.length());
}
}

@ -1,197 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev;
import java.util.TreeSet;
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.ContextManager;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.AstridFilterExposer;
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.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.producteev.sync.ProducteevDashboard;
import com.todoroo.astrid.producteev.sync.ProducteevDataService;
import com.todoroo.astrid.producteev.sync.ProducteevTask;
import com.todoroo.astrid.producteev.sync.ProducteevUser;
/**
* Exposes filters based on Producteev Dashboards
*
* @author Arne Jans <arne.jans@gmail.com>
*
*/
public class ProducteevFilterExposer extends BroadcastReceiver implements AstridFilterExposer {
/**
* @param context
*/
public static Filter filterFromList(Context context, ProducteevDashboard dashboard, long currentUserId) {
String dashboardTitle = dashboard.getName();
String title = dashboard.getName();
ContentValues values = new ContentValues();
values.put(Metadata.KEY.name, ProducteevTask.METADATA_KEY);
values.put(ProducteevTask.DASHBOARD_ID.name, dashboard.getId());
values.put(ProducteevTask.ID.name, 0);
values.put(ProducteevTask.CREATOR_ID.name, currentUserId);
values.put(ProducteevTask.RESPONSIBLE_ID.name, currentUserId);
Filter filter;
if (currentUserId != -1)
filter = new Filter(dashboardTitle, title, new QueryTemplate().join(
ProducteevDataService.METADATA_JOIN).where(Criterion.and(
MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
TaskCriteria.isActive(),
TaskCriteria.isVisible(),
Criterion.or(ProducteevTask.CREATOR_ID.eq(currentUserId),
ProducteevTask.RESPONSIBLE_ID.eq(currentUserId)),
ProducteevTask.DASHBOARD_ID.eq(dashboard.getId()))),
values);
else
filter = new Filter(dashboardTitle, title, new QueryTemplate().join(
ProducteevDataService.METADATA_JOIN).where(Criterion.and(
MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
TaskCriteria.isActive(),
TaskCriteria.isVisible(),
ProducteevTask.DASHBOARD_ID.eq(dashboard.getId()))),
values);
return filter;
}
private Filter filterUserAssignedByMe(Context context, ProducteevUser user, long currentUserId) {
String title = context.getString(R.string.producteev_FEx_responsible_title, user.toString());
ContentValues values = new ContentValues();
values.put(Metadata.KEY.name, ProducteevTask.METADATA_KEY);
values.put(ProducteevTask.ID.name, 0);
values.put(ProducteevTask.CREATOR_ID.name, currentUserId);
values.put(ProducteevTask.RESPONSIBLE_ID.name, user.getId());
Filter filter = new Filter(user.toString(), title, new QueryTemplate().join(
ProducteevDataService.METADATA_JOIN).where(Criterion.and(
MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
TaskCriteria.isActive(),
TaskCriteria.isVisible(),
ProducteevTask.CREATOR_ID.eq(currentUserId),
ProducteevTask.RESPONSIBLE_ID.eq(user.getId()))),
values);
return filter;
}
private Filter filterUserAssignedByOthers(Context context, ProducteevUser user, long currentUserId) {
String title = context.getString(R.string.producteev_FEx_responsible_title, user.toString());
ContentValues values = new ContentValues();
values.put(Metadata.KEY.name, ProducteevTask.METADATA_KEY);
values.put(ProducteevTask.ID.name, 0);
values.put(ProducteevTask.CREATOR_ID.name, 0);
values.put(ProducteevTask.RESPONSIBLE_ID.name, currentUserId);
Filter filter = new Filter(user.toString(), title, new QueryTemplate().join(
ProducteevDataService.METADATA_JOIN).where(Criterion.and(
MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
TaskCriteria.isActive(),
TaskCriteria.isVisible(),
Criterion.not(ProducteevTask.CREATOR_ID.eq(currentUserId)),
ProducteevTask.RESPONSIBLE_ID.eq(user.getId()))),
values);
return filter;
}
@Override
public void onReceive(Context context, Intent intent) {
ContextManager.setContext(context);
FilterListItem[] list = prepareFilters(context);
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, ProducteevUtilities.IDENTIFIER);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
private FilterListItem[] prepareFilters(Context context) {
// if we aren't logged in, don't expose features
if(!ProducteevUtilities.INSTANCE.isLoggedIn())
return null;
StoreObject[] dashboards = ProducteevDataService.getInstance().getDashboards();
// If user does not have any dashboards, don't show this section at all
if(dashboards.length == 0)
return null;
FilterListHeader producteevHeader = new FilterListHeader(context.getString(R.string.producteev_FEx_header));
long currentUserId = Preferences.getLong(ProducteevUtilities.PREF_USER_ID, -1);
// load dashboards
Filter[] dashboardFilters = new Filter[dashboards.length];
for(int i = 0; i < dashboards.length; i++)
dashboardFilters[i] = filterFromList(context, new ProducteevDashboard(dashboards[i]), currentUserId);
FilterCategory producteevDashboards = new FilterCategory(context.getString(R.string.producteev_FEx_dashboard),
dashboardFilters);
// load responsible people, assigned by me
TreeSet<ProducteevUser> people = loadResponsiblePeople(dashboards);
Filter[] peopleByMeFilters = new Filter[people.size()];
int index = 0;
for (ProducteevUser person : people)
peopleByMeFilters[index++] = filterUserAssignedByMe(context, person, currentUserId);
FilterCategory producteevUsersByMeCategory = new FilterCategory(context.getString(R.string.producteev_FEx_responsible_byme),
peopleByMeFilters);
// load responsible people, assigned by others
Filter[] peopleByOthersFilters = new Filter[people.size()];
index = 0;
for (ProducteevUser person : people)
peopleByOthersFilters[index++] = filterUserAssignedByOthers(context, person, currentUserId);
FilterCategory producteevUsersByOthersCategory = new FilterCategory(context.getString(R.string.producteev_FEx_responsible_byothers),
peopleByOthersFilters);
// transmit filter list
FilterListItem[] list = new FilterListItem[4];
list[0] = producteevHeader;
list[1] = producteevDashboards;
list[2] = producteevUsersByMeCategory;
list[3] = producteevUsersByOthersCategory;
return list;
}
/**
* @param dashboards
* @return people in a map of name => pair(dashboard id, user id)
*/
private TreeSet<ProducteevUser> loadResponsiblePeople(StoreObject[] dashboards) {
TreeSet<ProducteevUser> users = new TreeSet<ProducteevUser>();
for(StoreObject dashboard : dashboards) {
ProducteevDashboard elDashboard = new ProducteevDashboard(dashboard);
users.addAll(elDashboard.getUsers());
}
return users;
}
@Override
public FilterListItem[] getFilters() {
if (ContextManager.getContext() == null)
return null;
return prepareFilters(ContextManager.getContext());
}
}

@ -1,240 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev;
import java.util.TimeZone;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.producteev.api.ApiAuthenticationException;
import com.todoroo.astrid.producteev.api.ProducteevInvoker;
import com.todoroo.astrid.producteev.sync.ProducteevSyncProvider;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
/**
* This activity allows users to sign in or log in to Producteev
*
* @author arne.jans
*
*/
public class ProducteevLoginActivity extends Activity {
// --- ui initialization
public ProducteevLoginActivity() {
super();
DependencyInjectionService.getInstance().inject(this);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ContextManager.setContext(this);
setContentView(R.layout.producteev_login_activity);
setTitle(R.string.producteev_PLA_title);
// terms clicking
findViewById(R.id.terms).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("https://www.producteev.com/#terms"))); //$NON-NLS-1$
}
});
final TextView errors = (TextView) findViewById(R.id.error);
final EditText emailEditText = (EditText) findViewById(R.id.email);
final EditText passwordEditText = (EditText) findViewById(R.id.password);
final View newUserLayout = findViewById(R.id.newUserLayout);
final Spinner timezoneList = (Spinner) findViewById(R.id.timezoneList);
String[] timezoneEntries = getResources().getStringArray(R.array.PLA_timezones_list);
String defaultTimeZone = TimeZone.getDefault().getID();
int selected = 0;
for(int i = 0; i < timezoneEntries.length; i++) {
if(timezoneEntries[i].equals(defaultTimeZone))
selected = i;
}
timezoneList.setSelection(selected);
Button signIn = (Button) findViewById(R.id.signIn);
signIn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
errors.setVisibility(View.GONE);
if(newUserLayout.getVisibility() == View.VISIBLE)
newUserLayout.setVisibility(View.GONE);
else {
Editable email = emailEditText.getText();
Editable password = passwordEditText.getText();
if(email.length() == 0 || password.length() == 0) {
errors.setVisibility(View.VISIBLE);
errors.setText(R.string.producteev_PLA_errorEmpty);
return;
}
performLogin(email.toString(), password.toString());
}
}
});
Button createNew = (Button) findViewById(R.id.createNew);
createNew.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
errors.setVisibility(View.GONE);
if(newUserLayout.getVisibility() != View.VISIBLE)
newUserLayout.setVisibility(View.VISIBLE);
else {
Editable email = emailEditText.getText();
Editable password = passwordEditText.getText();
Editable firstName = ((EditText)findViewById(R.id.firstName)).getText();
Editable lastName = ((EditText)findViewById(R.id.lastName)).getText();
String timezone = timezoneList.getSelectedItem().toString();
if(email.length() == 0 || password.length() == 0 ||
firstName.length() == 0 ||
lastName.length() == 0) {
errors.setVisibility(View.VISIBLE);
errors.setText(R.string.producteev_PLA_errorEmpty);
return;
}
performSignup(email.toString(), password.toString(),
firstName.toString(), lastName.toString(), timezone);
}
}
});
}
private void performLogin(final String email, final String password) {
final ProgressDialog dialog = DialogUtilities.progressDialog(this,
getString(R.string.DLG_wait));
final TextView errors = (TextView) findViewById(R.id.error);
dialog.show();
new Thread() {
@Override
public void run() {
ProducteevInvoker invoker = ProducteevSyncProvider.getInvoker();
final StringBuilder errorMessage = new StringBuilder();
try {
invoker.authenticate(email, password);
Preferences.setString(R.string.producteev_PPr_email, email);
Preferences.setString(R.string.producteev_PPr_password, password);
ProducteevUtilities.INSTANCE.setToken(invoker.getToken());
StatisticsService.reportEvent(StatisticsConstants.PRODUCTEEV_LOGIN);
synchronize();
} catch (ApiAuthenticationException e) {
errorMessage.append(getString(R.string.producteev_PLA_errorAuth));
} catch (Exception e) {
errorMessage.append(e.getMessage());
} finally {
runOnUiThread(new Runnable() {
public void run() {
DialogUtilities.dismissDialog(ProducteevLoginActivity.this, dialog);
if(errorMessage.length() > 0) {
errors.setVisibility(View.VISIBLE);
errors.setText(errorMessage);
}
}
});
}
}
}.start();
}
private void performSignup(final String email, final String password,
final String firstName, final String lastName, final String timezone) {
final ProgressDialog dialog = DialogUtilities.progressDialog(this,
getString(R.string.DLG_wait));
final TextView errors = (TextView) findViewById(R.id.error);
dialog.show();
new Thread() {
@Override
public void run() {
ProducteevInvoker invoker = ProducteevSyncProvider.getInvoker();
final StringBuilder errorMessage = new StringBuilder();
try {
invoker.usersSignUp(email, firstName, lastName, password, timezone, null);
invoker.authenticate(email, password);
Preferences.setString(R.string.producteev_PPr_email, email);
Preferences.setString(R.string.producteev_PPr_password, password);
ProducteevUtilities.INSTANCE.setToken(invoker.getToken());
StatisticsService.reportEvent(StatisticsConstants.PRODUCTEEV_SIGNUP);
synchronize();
} catch (Exception e) {
errorMessage.append(e.getMessage());
} finally {
runOnUiThread(new Runnable() {
public void run() {
DialogUtilities.dismissDialog(ProducteevLoginActivity.this, dialog);
if(errorMessage.length() > 0) {
errors.setVisibility(View.VISIBLE);
errors.setText(errorMessage);
}
}
});
}
}
}.start();
}
/**
* Perform synchronization
*/
protected void synchronize() {
startService(new Intent(null, null,
this, ProducteevBackgroundService.class));
finish();
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
}
@Override
protected void onPause() {
super.onPause();
StatisticsService.sessionPause();
}
@Override
protected void onStop() {
super.onStop();
StatisticsService.sessionStop(this);
}
}

@ -1,102 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import com.timsu.astrid.R;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.producteev.sync.ProducteevDashboard;
import com.todoroo.astrid.producteev.sync.ProducteevDataService;
import com.todoroo.astrid.producteev.sync.ProducteevSyncProvider;
import com.todoroo.astrid.sync.SyncProviderPreferences;
import com.todoroo.astrid.sync.SyncProviderUtilities;
/**
* Displays synchronization preferences and an action panel so users can
* initiate actions from the menu.
*
* @author timsu
*
*/
public class ProducteevPreferences extends SyncProviderPreferences {
@Override
public int getPreferenceResource() {
return R.xml.preferences_producteev;
}
@Override
public void startSync() {
new ProducteevSyncProvider().synchronize(this);
finish();
}
@Override
public void logOut() {
new ProducteevSyncProvider().signOut();
}
@Override
public SyncProviderUtilities getUtilities() {
return ProducteevUtilities.INSTANCE;
}
@Override
protected void onPause() {
super.onPause();
new ProducteevBackgroundService().scheduleService();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListPreference defaultDash = (ListPreference)findPreference(getString(R.string.producteev_PPr_defaultdash_key));
String[] entries, entryValues;
StoreObject[] dashboards = ProducteevDataService.getInstance().getDashboards();
if(ProducteevUtilities.INSTANCE.isLoggedIn() && dashboards.length > 0) {
entries = new String[dashboards.length + 1];
entryValues = new String[dashboards.length + 1];
for(int i = 0; i < dashboards.length; i++) {
entries[i + 1] = dashboards[i].getValue(ProducteevDashboard.NAME);
entryValues[i + 1] = Long.toString(dashboards[i].getValue(ProducteevDashboard.REMOTE_ID));
}
} else {
entries = new String[2];
entries[1] = getString(R.string.producteev_default_dashboard);
entryValues = new String[2];
entryValues[1] = Integer.toString(ProducteevUtilities.DASHBOARD_DEFAULT);
}
entries[0] = getString(R.string.producteev_no_dashboard);
entryValues[0] = Integer.toString(ProducteevUtilities.DASHBOARD_NO_SYNC);
defaultDash.setEntries(entries);
defaultDash.setEntryValues(entryValues);
}
@Override
public void updatePreferences(Preference preference, Object value) {
super.updatePreferences(preference, value);
final Resources r = getResources();
if (r.getString(R.string.producteev_PPr_defaultdash_key).equals(
preference.getKey())) {
int index = AndroidUtilities.indexOf(((ListPreference)preference).getEntryValues(), (String)value);
if(index == -1)
index = 1;
if(index == 0)
preference.setSummary(R.string.producteev_PPr_defaultdash_summary_none);
else
preference.setSummary(r.getString(
R.string.producteev_PPr_defaultdash_summary,
((ListPreference)preference).getEntries()[index]));
}
}
}

@ -1,28 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.astrid.service.AstridDependencyInjector;
public class ProducteevStartupReceiver extends BroadcastReceiver {
static {
AstridDependencyInjector.initialize();
}
@Override
/** Called when device is restarted */
public void onReceive(final Context context, Intent intent) {
ContextManager.setContext(context);
new ProducteevBackgroundService().scheduleService();
}
}

@ -1,43 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.SyncAction;
/**
* Exposes sync action
*
*/
public class ProducteevSyncActionExposer extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ContextManager.setContext(context);
// if we aren't logged in, don't expose sync action
if(!ProducteevUtilities.INSTANCE.isLoggedIn())
return;
Intent syncIntent = new Intent(null, null,
context, ProducteevBackgroundService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, syncIntent, PendingIntent.FLAG_UPDATE_CURRENT);
SyncAction syncAction = new SyncAction(context.getString(R.string.producteev_PPr_header),
pendingIntent);
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_SYNC_ACTIONS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, ProducteevUtilities.IDENTIFIER);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, syncAction);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
}

@ -1,84 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev;
import com.timsu.astrid.R;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.sync.SyncProviderUtilities;
/**
* Displays synchronization preferences and an action panel so users can
* initiate actions from the menu.
*
* @author timsu
*
*/
public class ProducteevUtilities extends SyncProviderUtilities {
/** add-on identifier */
public static final String IDENTIFIER = "pdv"; //$NON-NLS-1$
public static final ProducteevUtilities INSTANCE = new ProducteevUtilities();
/** setting for dashboard to getting created */
public static final int DASHBOARD_CREATE = -2;
/** setting for dashboard to not synchronize */
public static final int DASHBOARD_NO_SYNC = -1;
/** setting for dashboard to use default one */
public static final int DASHBOARD_DEFAULT = 0;
@Override
public String getIdentifier() {
return IDENTIFIER;
}
@Override
public int getSyncIntervalKey() {
return R.string.producteev_PPr_interval_key;
}
// --- producteev-specific preferences
public static final String PREF_SERVER_LAST_SYNC = IDENTIFIER + "_last_server"; //$NON-NLS-1$
public static final String PREF_SERVER_LAST_NOTIFICATION = IDENTIFIER + "_last_notification"; //$NON-NLS-1$
public static final String PREF_SERVER_LAST_ACTIVITY = IDENTIFIER + "_last_activity"; //$NON-NLS-1$
/** Producteev user's default dashboard. This is different from the
* preference key, which indicates where user wants to put new tasks */
public static final String PREF_DEFAULT_DASHBOARD = IDENTIFIER + "_defaultdash"; //$NON-NLS-1$
/** Producteev user's id */
public static final String PREF_USER_ID = IDENTIFIER + "_userid"; //$NON-NLS-1$
/**
* Gets default dashboard from setting
* @return DASHBOARD_NO_SYNC if should not sync, otherwise remote id
*/
public long getDefaultDashboard() {
int defaultDashboard = Preferences.getIntegerFromString(R.string.producteev_PPr_defaultdash_key,
DASHBOARD_DEFAULT);
if(defaultDashboard == DASHBOARD_NO_SYNC)
return DASHBOARD_NO_SYNC;
else if(defaultDashboard == DASHBOARD_DEFAULT)
return Preferences.getLong(PREF_DEFAULT_DASHBOARD, 0);
else
return (long) defaultDashboard;
}
private ProducteevUtilities() {
// prevent instantiation
}
@Override
public String getLoggedInUserName() {
return Preferences.getStringValue(R.string.producteev_PPr_email);
}
}

@ -1,23 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.api;
/**
* Exception that is thrown when an authentication exception occurs and users
* need to sign in
*
* @author timsu
*
*/
public class ApiAuthenticationException extends ApiServiceException {
private static final long serialVersionUID = 1696103465107607150L;
public ApiAuthenticationException(String detailMessage) {
super(detailMessage);
}
}

@ -1,24 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.api;
/**
* Exception that wraps an exception encountered during API invocation or
* processing.
*
* @author timsu
*
*/
public class ApiResponseParseException extends ApiServiceException {
private static final long serialVersionUID = 5421855785088364483L;
public ApiResponseParseException(Throwable throwable) {
super("Exception reading API response: " + throwable.getMessage()); //$NON-NLS-1$
initCause(throwable);
}
}

@ -1,40 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.api;
import java.io.IOException;
/**
* Exception that wraps an exception encountered during API invocation or
* processing.
*
* @author timsu
*
*/
public class ApiServiceException extends IOException {
private static final long serialVersionUID = 8805573304840404684L;
public ApiServiceException(String detailMessage) {
super(detailMessage);
}
public ApiServiceException(Throwable throwable) {
super(throwable.getMessage());
initCause(throwable);
}
public ApiServiceException() {
super();
}
@Override
public String toString() {
return getClass().getSimpleName() + ": " + getMessage(); //$NON-NLS-1$
}
}

@ -1,23 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.api;
/**
* Exception that wraps a 403 exception
*
* @author timsu
*
*/
public class ApiSignatureException extends ApiServiceException {
private static final long serialVersionUID = 4320984373933L;
public ApiSignatureException(String detailMessage) {
super(detailMessage);
}
}

@ -1,112 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.api;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.json.JSONObject;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.notes.NoteMetadata;
import com.todoroo.astrid.producteev.sync.ProducteevDataService;
/**
* Utilities for working with API responses and JSON objects
*
* @author timsu
*
*/
public final class ApiUtilities {
private static final SimpleDateFormat timeParser = new SimpleDateFormat(
"EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); //$NON-NLS-1$
private static final SimpleDateFormat timeWriter = new SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss Z", Locale.US); //$NON-NLS-1$
private static final SimpleDateFormat dateWriter = new SimpleDateFormat(
"yyyy/MM/dd", Locale.US); //$NON-NLS-1$
/**
* Utility method to convert PDV time to unix time
*
* @param date
* @param defaultValue
* @return
*/
public static long producteevToUnixTime(String value, long defaultValue) {
synchronized(timeParser) {
try {
return DateUtilities.dateToUnixtime(timeParser.parse(value));
} catch (ParseException e) {
return defaultValue;
}
}
}
/**
* Utility method to convert unix time to PDV time
* @param time
* @return
*/
public static String unixTimeToProducteev(long time) {
synchronized(timeWriter) {
return timeWriter.format(DateUtilities.unixtimeToDate(time));
}
}
/**
* Utility method to convert unix date to PDV date
* @param time
* @return
*/
public static String unixDateToProducteev(long date) {
synchronized(dateWriter) {
return dateWriter.format(DateUtilities.unixtimeToDate(date));
}
}
/**
* Un-escape a Producteev string
* @param string
* @return
*/
public static String decode(String string) {
return StringEscapeUtils.unescapeHtml(string);
}
/**
* 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, String creatorName) {
Metadata metadata = new Metadata();
metadata.setValue(Metadata.KEY, NoteMetadata.METADATA_KEY);
metadata.setValue(NoteMetadata.EXT_ID, note.optString("id_note"));
metadata.setValue(NoteMetadata.EXT_PROVIDER, ProducteevDataService.NOTE_PROVIDER);
metadata.setValue(NoteMetadata.BODY, ApiUtilities.decode(note.optString("message")));
long created = ApiUtilities.producteevToUnixTime(note.optString("time_create"), 0);
metadata.setValue(Metadata.CREATION_DATE, created);
if(creatorName != null)
metadata.setValue(NoteMetadata.TITLE, creatorName);
else
metadata.setValue(NoteMetadata.TITLE, DateUtilities.getDateStringWithWeekday(ContextManager.getContext(),
new Date(created)));
return metadata;
}
}

@ -1,682 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.api;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import org.apache.commons.codec.digest.DigestUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.text.TextUtils;
import com.todoroo.andlib.utility.Pair;
@SuppressWarnings("nls")
public class ProducteevInvoker {
private final String URL = "https://api.producteev.com/";
private final String apiKey;
private final String apiSecret;
/** saved credentials in case we need to re-log in */
private String retryEmail;
private String retryPassword;
private String token = null;
/**
* Create new producteev service
* @param apiKey
* @param apiSecret
*/
public ProducteevInvoker(String apiKey, String apiSecret) {
this.apiKey = apiKey;
this.apiSecret = apiSecret;
}
// --- authentication and time
/**
* Authenticate the given user
*/
public void authenticate(String email, String password) throws IOException, ApiServiceException {
retryEmail = email;
retryPassword = password;
JSONObject response = invokeGet("users/login.json",
"email", email, "password", password);
try {
token = response.getJSONObject("login").getString("token");
} catch (JSONException e) {
throw new ApiServiceException(e);
}
}
public boolean hasToken() {
return token != null;
}
public void setCredentials(String token, String email, String password) {
this.token = token;
retryEmail = email;
retryPassword = password;
}
public String getToken() {
return token;
}
/**
* Gets Server time
*/
public String time() throws IOException, ApiServiceException {
JSONObject response = invokeGet("time.json");
try {
return response.getJSONObject("time").getString("value");
} catch (JSONException e) {
throw new ApiServiceException(e);
}
}
// --- users
/**
* Sign up as the given user
*/
public JSONObject usersSignUp(String email, String firstName, String lastName, String
password, String timezone, Long fbUid) throws IOException, ApiServiceException {
return invokeGet("users/signup.json",
"email", email,
"firstname", firstName,
"lastname", lastName,
"password", password,
"timezone", timezone,
"fbuid", fbUid);
}
// --- dashboards
/**
* show list
*
* @param idResponsible (optional) if null return every task for current user
* @param since (optional) if not null, the function only returns tasks modified or created since this date
*
* @return array tasks/view
*/
public JSONArray dashboardsShowList(String since) throws ApiServiceException, IOException {
return getResponse(callAuthenticated("dashboards/show_list.json",
"token", token,
"since", since), "dashboards");
}
/**
* create a dasbhoard
*
* @param name
* @return the new created dashboard as JSONObject
*/
public JSONObject dashboardsCreate(String name) throws ApiServiceException, IOException {
return callAuthenticated("dashboards/create.json",
"token", token,
"title", name);
}
/**
* return the list of users who can access a specific dashboard
*
* @param idDashboard
* @param dashboard array-information about the dashboard, if this ...
*/
public JSONArray dashboardsAccess(long idDashboard, String dashboard) throws ApiServiceException, IOException {
return getResponse(callAuthenticated("dashboards/access.json",
"token", token,
"id_dashboard", idDashboard,
"dashboard", dashboard),"dashboard");
}
// --- tasks
/**
* create a task
*
* @param title
* @param idResponsible (optional)
* @param idDashboard (optional);
* @param deadline (optional)
* @param reminder (optional) 0 = "None", 1 = "5 minutes before", 2 = "15 minutes before", 3 = "30 minutes before", 4 = "1 hour before", 5 = "2 hours before", 6 = "1 day before", 7 = "2 days before", 8 = "on date of event"
* @param status (optional) (1 = UNDONE, 2 = DONE)
* @param star (optional) (0 to 5 stars)
*
* @return task
*/
public JSONObject tasksCreate(String title, Long idResponsible, Long idDashboard,
String deadline, Integer reminder, Integer status, Integer star) throws ApiServiceException, IOException {
return callAuthenticated("tasks/create.json",
"token", token,
"title", title,
"id_responsible", idResponsible,
"id_dashboard", idDashboard,
"deadline", deadline,
"reminder", reminder,
"status", status,
"star", star);
}
/**
* show list
*
* @param idResponsible (optional) if null return every task for current user
* @param since (optional) if not null, the function only returns tasks modified or created since this date
*
* @return array tasks/view
*/
public JSONArray tasksShowList(Long idDashboard, String since) throws ApiServiceException, IOException {
return getResponse(callAuthenticated("tasks/show_list.json",
"token", token,
"id_dashboard", idDashboard,
"since", since), "tasks");
}
/**
* get a task
*
* @param idTask
*
* @return array tasks/view
*/
public JSONObject tasksView(Long idTask) throws ApiServiceException, IOException {
return callAuthenticated("tasks/view.json",
"token", token,
"id_task", idTask);
}
/**
* change title of a task
*
* @param idTask
* @param title
*
* @return array tasks/view
*/
public JSONObject tasksSetTitle(long idTask, String title) throws ApiServiceException, IOException {
return callAuthenticated("tasks/set_title.json",
"token", token,
"id_task", idTask,
"title", title);
}
/**
* set status of a task
*
* @param idTask
* @param status (1 = UNDONE, 2 = DONE)
*
* @return array tasks/view
*/
public JSONObject tasksSetStatus(long idTask, int status) throws ApiServiceException, IOException {
return callAuthenticated("tasks/set_status.json",
"token", token,
"id_task", idTask,
"status", status);
}
/**
* set star status of a task
*
* @param idTask
* @param star (0 to 5 stars)
*
* @return array tasks/view
*/
public JSONObject tasksSetStar(long idTask, int star) throws ApiServiceException, IOException {
return callAuthenticated("tasks/set_star.json",
"token", token,
"id_task", idTask,
"star", star);
}
/**
* set a deadline
*
* @param idTask
* @param deadline
* @param allDay (optional), 1: all day task (time specified in deadline will be ignored), 0: deadline with time
*
* @return array tasks/view
*/
public JSONObject tasksSetDeadline(long idTask, String deadline, Integer allDay) throws ApiServiceException, IOException {
return callAuthenticated("tasks/set_deadline.json",
"token", token,
"id_task", idTask,
"deadline", deadline,
"all_day", allDay);
}
/**
* unset a deadline
*
* @param idTask
*
* @return array tasks/view
*/
public JSONObject tasksUnsetDeadline(long idTask) throws ApiServiceException, IOException {
return callAuthenticated("tasks/unset_deadline.json",
"token", token,
"id_task", idTask);
}
/**
* set repeating
*
* @param idTask
* @param repeatInterval
* @param repeatValue
*
* @return array tasks/view
* @throws IOException
* @throws ApiServiceException
*/
public JSONObject tasksSetRepeating(long idTask, String repeatInterval, Integer repeatValue) throws ApiServiceException, IOException {
return callAuthenticated("tasks/set_repeating.json",
"token", token,
"id_task", idTask,
"repeat_interval", repeatInterval,
"repeat_value", (repeatValue == null ? 1 : repeatValue));
}
/**
* unset repeating
*
* @param idTask
*
* @return array tasks/view
* @throws IOException
* @throws ApiServiceException
*/
public JSONObject tasksUnsetRepeating(long idTask) throws ApiServiceException, IOException {
return callAuthenticated("tasks/unset_repeating.json",
"token", token,
"id_task", idTask);
}
/**
* set a workspace
*
* @param idTask
* @param id_dashboard
*
* @return array tasks/view
*/
public JSONObject tasksSetWorkspace(long idTask, long idDashboard) throws ApiServiceException, IOException {
return callAuthenticated("tasks/set_workspace.json",
"token", token,
"id_task", idTask,
"id_dashboard", idDashboard);
}
/**
* delete a task
*
* @param idTask
*
* @return array with the result = (Array("stats" => Array("result" => "TRUE|FALSE"))
*/
public JSONObject tasksDelete(long idTask) throws ApiServiceException, IOException {
return callAuthenticated("tasks/delete.json",
"token", token,
"id_task", idTask);
}
/**
* get labels assigned to a task
*
* @param idTask
*
* @return array: list of labels/view
*/
public JSONArray tasksLabels(long idTask) throws ApiServiceException, IOException {
return getResponse(callAuthenticated("tasks/labels.json",
"token", token,
"id_task", idTask), "labels");
}
/**
* change labels for a task
*
* @param idTask
* @param idLabels
*
* @return array: tasks/view
*/
public JSONObject tasksChangeLabel(long idTask, long... idLabels) throws ApiServiceException, IOException {
Object[] parameters = new Object[2 * (idLabels.length + 2)];
parameters[0] = "token"; parameters[1] = token;
parameters[2] = "id_task"; parameters[3] = idTask;
for(int i = 0; i < idLabels.length; i++) {
parameters[i * 2 + 4] = "id_label[]";
parameters[i * 2 + 5] = idLabels[i];
}
return callAuthenticated("tasks/change_labels.json", parameters);
}
/**
* set a labels to a task
*
* @param idTask
* @param idLabels
*
* @return array: tasks/view
*/
@Deprecated
public JSONObject tasksSetLabel(long idTask, long idLabel) throws ApiServiceException, IOException {
return callAuthenticated("tasks/set_label.json",
"token", token,
"id_task", idTask,
"id_label", idLabel);
}
/**
* set a labels to a task
*
* @param idTask
* @param idLabel
*
* @return array: tasks/view
*/
@Deprecated
public JSONObject tasksUnsetLabel(long idTask, long idLabel) throws ApiServiceException, IOException {
return callAuthenticated("tasks/unset_label.json",
"token", token,
"id_task", idTask,
"id_label", idLabel);
}
/**
* change responsible of a task
*
* @param idTask
* @param idResponsible
*
* @return array: tasks/view
*/
public JSONObject tasksSetResponsible(long idTask, long idResponsible) throws ApiServiceException, IOException {
return callAuthenticated("tasks/set_responsible.json",
"token", token,
"id_task", idTask,
"id_responsible", idResponsible);
}
/**
* change responsible of a task
*
* @param idTask
* @param idResponsible
*
* @return array: tasks/view
*/
public JSONObject tasksUnsetResponsible(long idTask) throws ApiServiceException, IOException {
return callAuthenticated("tasks/unset_responsible.json",
"token", token,
"id_task", idTask);
}
/**
* create a note attached to a task
*
* @param idTask
* @param message
*
* @return array tasks::note_view
*/
public JSONObject tasksNoteCreate(long idTask, String message) throws ApiServiceException, IOException {
return callAuthenticated("tasks/note_create.json",
"token", token,
"id_task", idTask,
"message", message);
}
// --- labels
/**
* get every label for a given dashboard
*
* @param idTask
* @param idLabel
*
* @return array: labels/view
*/
public JSONArray labelsShowList(long idDashboard, String since) throws ApiServiceException, IOException {
return getResponse(callAuthenticated("labels/show_list.json",
"token", token,
"id_dashboard", idDashboard,
"since", since), "labels");
}
/**
* create a label
*
* @param idDashboard
* @param title
*
* @return array: labels/view
*/
public JSONObject labelsCreate(long idDashboard, String title) throws ApiServiceException, IOException {
return callAuthenticated("labels/create.json",
"token", token,
"id_dashboard", idDashboard,
"title", title);
}
public JSONObject labelsDelete(long idLabel) throws ApiServiceException, IOException {
return callAuthenticated("labels/delete.json",
"token", token,
"id_label", idLabel);
}
// --- notifications/activities
/**
* get every activities
*
* @param dashboardId (optional) if not null, this function only returns notifications for this specific dashboard
* @param lastId (optional) this function returns only activities later than this id
*/
public JSONArray activitiesShowActivities(Long dashboardId, Long lastId) throws ApiResponseParseException, ApiServiceException, IOException {
return getResponse(callAuthenticated("activities/show_activities.json",
"token", token,
"id_dashboard", dashboardId,
"last_id", lastId), "activities");
}
/**
* get every notification for the current user
* @param dashboardId
* @param lastId
* @return
* @throws ApiResponseParseException
* @throws ApiServiceException
* @throws IOException
*/
public JSONArray activitiesShowNotifications(Long dashboardId, Long lastId) throws ApiResponseParseException, ApiServiceException, IOException {
return getResponse(callAuthenticated("activities/show_notifications.json",
"token", token,
"id_dashboard", dashboardId,
"last_id", lastId), "activities");
}
// --- users
/**
* get a user
*
* @param idColleague
*
* @return array information about the user
*/
public JSONObject usersView(Long idColleague) throws ApiServiceException, IOException {
return callAuthenticated("users/view.json",
"token", token,
"id_colleague", idColleague);
}
public JSONObject usersColleagues() throws ApiServiceException, IOException {
return callAuthenticated("users/colleagues.json",
"token", token);
}
// --- invocation
private final ProducteevRestClient restClient = new ProducteevRestClient();
/**
* Invokes authenticated method using HTTP GET. Will retry after re-authenticating if service exception encountered
*
* @param method
* API method to invoke
* @param getParameters
* Name/Value pairs. Values will be URL encoded.
* @return response object
*/
private JSONObject callAuthenticated(String method, Object... getParameters)
throws IOException, ApiServiceException {
try {
String request = createFetchUrl(method, getParameters);
String response = null;
try {
response = restClient.get(request);
} catch (ApiSignatureException e) {
// clear cookies, get new token, retry
String oldToken = token;
restClient.reset();
authenticate(retryEmail, retryPassword);
for(int i = 0; i < getParameters.length; i++)
if(oldToken.equals(getParameters[i])) {
getParameters[i] = getToken();
}
request = createFetchUrl(method, getParameters);
try {
response = restClient.get(request);
} catch (ApiSignatureException newException) {
//
}
if(response == null)
throw e;
}
if(response.startsWith("DEBUG MESSAGE")) {
System.err.println(response);
return new JSONObject();
}
try {
if(TextUtils.isEmpty(response))
return new JSONObject();
return new JSONObject(response);
} catch (JSONException e) {
System.err.println(response);
throw new ApiResponseParseException(e);
}
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
/**
* Invokes API method using HTTP GET
*
* @param method
* API method to invoke
* @param getParameters
* Name/Value pairs. Values will be URL encoded.
* @return response object
*/
JSONObject invokeGet(String method, Object... getParameters) throws IOException, ApiServiceException {
try {
String request = createFetchUrl(method, getParameters);
String response = restClient.get(request);
if(response.startsWith("DEBUG MESSAGE")) {
System.err.println(response);
return new JSONObject();
}
return new JSONObject(response);
} catch (JSONException e) {
throw new ApiResponseParseException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
/**
* Creates a URL for invoking an HTTP GET/POST on the given method
* @param method
* @param getParameters
* @return
* @throws UnsupportedEncodingException
* @throws NoSuchAlgorithmException
*/
String createFetchUrl(String method, Object... getParameters) throws UnsupportedEncodingException, NoSuchAlgorithmException {
ArrayList<Pair<String, Object>> params = new ArrayList<Pair<String, Object>>();
for(int i = 0; i < getParameters.length; i += 2)
params.add(new Pair<String, Object>(getParameters[i].toString(), getParameters[i+1]));
params.add(new Pair<String, Object>("api_key", apiKey));
Collections.sort(params, new Comparator<Pair<String, Object>>() {
@Override
public int compare(Pair<String, Object> object1,
Pair<String, Object> object2) {
return object1.getLeft().compareTo(object2.getLeft());
}
});
StringBuilder requestBuilder = new StringBuilder(URL).append(method).append('?');
StringBuilder sigBuilder = new StringBuilder();
for(Pair<String, Object> entry : params) {
if(entry.getRight() == null)
continue;
String key = entry.getLeft();
String value = entry.getRight().toString();
String encoded = URLEncoder.encode(value, "UTF-8");
requestBuilder.append(key).append('=').append(encoded).append('&');
if(!key.endsWith("[]"))
sigBuilder.append(key).append(value);
}
sigBuilder.append(apiSecret);
String signature = DigestUtils.md5Hex(sigBuilder.toString());
requestBuilder.append("api_sig").append('=').append(signature);
return requestBuilder.toString();
}
/**
* Helper method to get a field out or throw an api exception
* @param response
* @param field
* @return
* @throws ApiResponseParseException
*/
private JSONArray getResponse(JSONObject response, String field) throws ApiResponseParseException {
try {
if(!response.has(field))
return new JSONArray();
return response.getJSONArray(field);
} catch (JSONException e) {
throw new ApiResponseParseException(e);
}
}
}

@ -1,188 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.api;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONObject;
import com.todoroo.andlib.service.RestClient;
import com.todoroo.astrid.utility.Constants;
/**
* RestClient allows Android to consume web requests.
* <p>
* Portions by Praeda:
* http://senior.ceng.metu.edu.tr/2009/praeda/2009/01/11/a-simple
* -restful-client-at-android/
*
* @author Tim Su <tim@todoroo.com>
*
*/
public class ProducteevRestClient implements RestClient {
private static final int HTTP_OK = 200;
private static final int TIMEOUT_MILLIS = 30000;
private static HttpClient httpClient = null;
private static String convertStreamToString(InputStream is) {
/*
* To convert the InputStream to String we use the
* BufferedReader.readLine() method. We iterate until the BufferedReader
* return null which means there's no more data to read. Each line will
* appended to a StringBuilder and returned as String.
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(is), 16384);
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n"); //$NON-NLS-1$
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
private synchronized static void initializeHttpClient() {
if (httpClient == null) {
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_MILLIS);
HttpConnectionParams.setSoTimeout(params, TIMEOUT_MILLIS);
httpClient = new DefaultHttpClient(params);
}
}
private String processHttpResponse(HttpResponse response) throws IOException, ApiServiceException {
HttpEntity entity = response.getEntity();
String body = null;
if (entity != null) {
InputStream contentStream = entity.getContent();
try {
body = convertStreamToString(contentStream);
} finally {
contentStream.close();
}
}
if(Constants.DEBUG)
System.err.println(body);
int statusCode = response.getStatusLine().getStatusCode();
if(statusCode != HTTP_OK || (body != null && body.startsWith("{\"error\":"))) { //$NON-NLS-1$
ApiServiceException error;
try {
JSONObject errorObject = new JSONObject(body).getJSONObject("error"); //$NON-NLS-1$
String errorMessage = errorObject.getString("message"); //$NON-NLS-1$
if(statusCode == 403)
error = new ApiSignatureException(errorMessage);
else if(statusCode == 401)
error = new ApiAuthenticationException(errorMessage);
else
error = new ApiServiceException(errorMessage);
} catch (Exception e) {
if(statusCode == 401)
error = new ApiAuthenticationException(response.getStatusLine().getReasonPhrase());
else
error = new ApiServiceException(response.getStatusLine() +
"\n" + body); //$NON-NLS-1$
}
throw error;
}
return body;
}
/**
* Issue an HTTP GET for the given URL, return the response
*
* @param url url with url-encoded params
* @return response, or null if there was no response
* @throws IOException
*/
public synchronized String get(String url) throws IOException {
initializeHttpClient();
if(Constants.DEBUG)
System.err.println("GET: " + url); //$NON-NLS-1$ // (debug)
try {
HttpGet httpGet = new HttpGet(url);
HttpResponse response = httpClient.execute(httpGet);
return processHttpResponse(response);
} catch (IOException e) {
throw e;
} catch (Exception e) {
IOException ioException = new IOException(e.getMessage());
ioException.initCause(e);
throw ioException;
}
}
/**
* Issue an HTTP POST for the given URL, return the response
*
* @param url
* @param data
* url-encoded data
* @param headers
* @throws IOException
*/
public synchronized String post(String url, HttpEntity data, Header... headers) throws IOException {
initializeHttpClient();
if(Constants.DEBUG)
System.err.println("POST: " + url); //$NON-NLS-1$ // (debug)
try {
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(data);
HttpResponse response = httpClient.execute(httpPost);
return processHttpResponse(response);
} catch (IOException e) {
throw e;
} catch (Exception e) {
IOException ioException = new IOException(e.getMessage());
ioException.initCause(e);
throw ioException;
}
}
/**
* Destroy and re-create http client
*/
public void reset() {
httpClient = null;
}
}

@ -1,123 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.sync;
import java.util.ArrayList;
import java.util.StringTokenizer;
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 Producteev Dashboard
*
* @author Tim Su <tim@todoroo.com>
*
*/
public class ProducteevDashboard {
/** type*/
public static final String TYPE = "pdv-dash"; //$NON-NLS-1$
/** dashboard id in producteev */
public static final LongProperty REMOTE_ID = new LongProperty(StoreObject.TABLE,
StoreObject.ITEM.name);
/** dashboard name */
public static final StringProperty NAME = new StringProperty(StoreObject.TABLE,
StoreObject.VALUE1.name);
/** users (list in the format "id_user,name;id_user,name;") */
public static final StringProperty USERS = new StringProperty(StoreObject.TABLE,
StoreObject.VALUE2.name);
// data class-part
private final long id;
private final String name;
private ArrayList<ProducteevUser> users = null;
public ProducteevDashboard (StoreObject dashboardData) {
this(dashboardData.getValue(REMOTE_ID),dashboardData.getValue(NAME),(dashboardData.containsValue(USERS)?dashboardData.getValue(USERS):null));
}
/**
* Constructor for a dashboard.
*
* @param id id of the remote dashboard
* @param name name of the remote dashboard
* @param usercsv csv-userstring as returned by a StoreObject-dashboard with property ProducteevDashboard.USERS
*/
@SuppressWarnings("nls")
public ProducteevDashboard(long id, String name, String usercsv) {
this.id = id;
this.name = name;
if (usercsv == null)
return;
StringTokenizer tokenizer = new StringTokenizer(usercsv, ";");
int usercount = tokenizer.countTokens();
while (tokenizer.hasMoreTokens()) {
String userdata = tokenizer.nextToken();
int delim_index = userdata.indexOf(",");
String userid = userdata.substring(0, delim_index);
String username = userdata.substring(delim_index+1);
int name_gap = username.indexOf(" ");
String firstname = (name_gap == -1 ? username : username.substring(0,name_gap));
String lastname = (name_gap == -1 ? null : username.substring(name_gap+1));
if (users == null) {
users = new ArrayList<ProducteevUser>(usercount);
}
users.add(new ProducteevUser(Long.parseLong(userid),null,firstname,lastname));
}
}
/**
* @return the id
*/
public long getId() {
return id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* return the name of this dashboard
*/
@Override
public String toString() {
return name;
}
/**
* @return the users
*/
public ArrayList<ProducteevUser> getUsers() {
if (users == null) {
return new ArrayList<ProducteevUser>(); // Don't return null
}
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;
}
}

@ -1,310 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.sync;
import java.util.ArrayList;
import java.util.Random;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import com.todoroo.andlib.data.Property;
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.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.StoreObjectDao;
import com.todoroo.astrid.dao.StoreObjectDao.StoreObjectCriteria;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
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.ProducteevUtilities;
import com.todoroo.astrid.producteev.api.ApiUtilities;
import com.todoroo.astrid.service.MetadataService;
import com.todoroo.astrid.tags.TaskToTagMetadata;
public final class ProducteevDataService {
// --- constants
/** Utility for joining tasks with metadata */
public static final Join METADATA_JOIN = Join.left(Metadata.TABLE, Task.ID.eq(Metadata.TASK));
/** NoteMetadata provider string */
public static final String NOTE_PROVIDER = "producteev"; //$NON-NLS-1$
// --- singleton
private static ProducteevDataService instance = null;
public static synchronized ProducteevDataService getInstance() {
if(instance == null)
instance = new ProducteevDataService(ContextManager.getContext());
return instance;
}
// --- instance variables
protected final Context context;
@Autowired
private TaskDao taskDao;
@Autowired
private MetadataService metadataService;
@Autowired
private StoreObjectDao storeObjectDao;
private final ProducteevUtilities preferences = ProducteevUtilities.INSTANCE;
static final Random random = new Random();
private ProducteevDataService(Context context) {
this.context = context;
DependencyInjectionService.getInstance().inject(this);
}
// --- task and metadata methods
/**
* Clears metadata information. Used when user logs out of service
*/
public void clearMetadata() {
PluginServices.getTaskService().clearDetails(Task.ID.in(Query.select(Metadata.TASK).from(Metadata.TABLE).
where(MetadataCriteria.withKey(ProducteevTask.METADATA_KEY))));
metadataService.deleteWhere(Metadata.KEY.eq(ProducteevTask.METADATA_KEY));
storeObjectDao.deleteWhere(StoreObject.TYPE.eq(ProducteevDashboard.TYPE));
}
/**
* Gets tasks that were created since last sync
* @param properties
* @return
*/
public TodorooCursor<Task> getLocallyCreated(Property<?>[] properties) {
return
taskDao.query(Query.select(properties).join(ProducteevDataService.METADATA_JOIN).where(
Criterion.and(
Criterion.not(Task.ID.in(Query.select(Metadata.TASK).from(Metadata.TABLE).
where(Criterion.and(MetadataCriteria.withKey(ProducteevTask.METADATA_KEY), ProducteevTask.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 = preferences.getLastSyncDate();
if(lastSyncDate == 0)
return taskDao.query(Query.select(Task.ID).where(Criterion.none));
return
taskDao.query(Query.select(properties).join(ProducteevDataService.METADATA_JOIN).where(
Criterion.and(
MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
ProducteevTask.ID.gt(0),
Task.MODIFICATION_DATE.gt(lastSyncDate))).
groupBy(Task.ID));
}
/**
* Searches for a local task with same remote id, updates this task's id
* @param remoteTask
* @return true if found local match
*/
public boolean findLocalMatch(ProducteevTaskContainer remoteTask) {
if(remoteTask.task.getId() != Task.NO_ID)
return true;
TodorooCursor<Task> cursor = taskDao.query(Query.select(Task.ID).
join(ProducteevDataService.METADATA_JOIN).where(Criterion.and(MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
ProducteevTask.ID.eq(remoteTask.pdvTask.getValue(ProducteevTask.ID)))));
try {
if(cursor.getCount() == 0)
return false;
cursor.moveToFirst();
remoteTask.task.setId(cursor.get(Task.ID));
return true;
} finally {
cursor.close();
}
}
/**
* Saves a task and its metadata
* @param task
*/
public void saveTaskAndMetadata(ProducteevTaskContainer task) {
taskDao.save(task.task);
task.metadata.add(task.pdvTask);
// note we don't include note metadata, since we only receive deltas
metadataService.synchronizeMetadata(task.task.getId(), task.metadata,
Criterion.or(MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
MetadataCriteria.withKey(TaskToTagMetadata.KEY)), true);
}
/**
* Reads a task and its metadata
* @param task
* @return
*/
public ProducteevTaskContainer readTaskAndMetadata(TodorooCursor<Task> taskCursor) {
Task task = new Task(taskCursor);
// read tags, notes, etc
ArrayList<Metadata> metadata = new ArrayList<Metadata>();
TodorooCursor<Metadata> metadataCursor = metadataService.query(Query.select(Metadata.PROPERTIES).
where(Criterion.and(MetadataCriteria.byTask(task.getId()),
Criterion.or(MetadataCriteria.withKey(TaskToTagMetadata.KEY),
MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
MetadataCriteria.withKey(NoteMetadata.METADATA_KEY)))));
try {
for(metadataCursor.moveToFirst(); !metadataCursor.isAfterLast(); metadataCursor.moveToNext()) {
metadata.add(new Metadata(metadataCursor));
}
} finally {
metadataCursor.close();
}
return new ProducteevTaskContainer(task, metadata);
}
/**
* 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, ProducteevTask.METADATA_KEY)));
try {
if(cursor.getCount() == 0)
return null;
cursor.moveToFirst();
return new Metadata(cursor);
} finally {
cursor.close();
}
}
/**
* Reads task notes out of a task
*/
public TodorooCursor<Metadata> getTaskNotesCursor(long taskId) {
TodorooCursor<Metadata> cursor = metadataService.query(Query.select(Metadata.PROPERTIES).
where(MetadataCriteria.byTaskAndwithKey(taskId, NoteMetadata.METADATA_KEY)));
return cursor;
}
private void readDashboards() {
if (dashboards == null) {
dashboards = readStoreObjects(ProducteevDashboard.TYPE);
}
}
/**
* Reads store objects.
*/
public StoreObject[] readStoreObjects(String type) {
StoreObject[] ret;
TodorooCursor<StoreObject> cursor = storeObjectDao.query(Query.select(StoreObject.PROPERTIES).
where(StoreObjectCriteria.byType(type)));
try {
ret = new StoreObject[cursor.getCount()];
for(int i = 0; i < ret.length; i++) {
cursor.moveToNext();
StoreObject dashboard = new StoreObject(cursor);
ret[i] = dashboard;
}
} finally {
cursor.close();
}
return ret;
}
// --- dashboard methods
private StoreObject[] dashboards = null;
/**
* @return a list of dashboards
*/
public StoreObject[] getDashboards() {
readDashboards();
return dashboards;
}
/**
* Reads dashboards
* @throws JSONException
*/
@SuppressWarnings("nls")
public void updateDashboards(JSONArray changedDashboards) throws JSONException {
readDashboards();
for(int i = 0; i < changedDashboards.length(); i++) {
JSONObject remote = changedDashboards.getJSONObject(i).getJSONObject("dashboard");
updateDashboards(remote, false);
}
// clear dashboard cache
dashboards = null;
}
@SuppressWarnings("nls")
public StoreObject updateDashboards(JSONObject remote, boolean reinitCache) throws JSONException {
if (reinitCache)
readDashboards();
long id = remote.getLong("id_dashboard");
StoreObject local = null;
for(StoreObject dashboard : dashboards) {
if(dashboard.getValue(ProducteevDashboard.REMOTE_ID).equals(id)) {
local = dashboard;
break;
}
}
if(remote.getInt("deleted") != 0) {
if(local != null)
storeObjectDao.delete(local.getId());
}
if(local == null)
local = new StoreObject();
local.setValue(StoreObject.TYPE, ProducteevDashboard.TYPE);
local.setValue(ProducteevDashboard.REMOTE_ID, id);
local.setValue(ProducteevDashboard.NAME, ApiUtilities.decode(remote.getString("title")));
StringBuilder users = new StringBuilder();
JSONArray accessList = remote.getJSONArray("accesslist");
for(int j = 0; j < accessList.length(); j++) {
JSONObject user = accessList.getJSONObject(j).getJSONObject("user");
users.append(user.getLong("id_user")).append(',');
String name = ApiUtilities.decode(user.optString("firstname", "") + ' ' +
user.optString("lastname", ""));
users.append(name.trim()).append(';');
}
local.setValue(ProducteevDashboard.USERS, users.toString());
storeObjectDao.persist(local);
if (reinitCache)
dashboards = null;
return local;
}
}

@ -1,811 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.sync;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.Property;
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.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;
import com.todoroo.astrid.activity.ShortcutActivity;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.dao.TaskDao;
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;
import com.todoroo.astrid.producteev.ProducteevPreferences;
import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.producteev.api.ApiResponseParseException;
import com.todoroo.astrid.producteev.api.ApiServiceException;
import com.todoroo.astrid.producteev.api.ApiUtilities;
import com.todoroo.astrid.producteev.api.ProducteevInvoker;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.sync.SyncContainer;
import com.todoroo.astrid.sync.SyncProvider;
import com.todoroo.astrid.sync.SyncProviderUtilities;
import com.todoroo.astrid.tags.TaskToTagMetadata;
import com.todoroo.astrid.utility.Constants;
@SuppressWarnings("nls")
public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer> {
private static final long TASK_ID_UNSYNCED = 1L;
private ProducteevDataService dataService = null;
private ProducteevInvoker invoker = null;
private final ProducteevUtilities preferences = ProducteevUtilities.INSTANCE;
/** producteev user id. set during sync */
private long userId;
/** map of producteev dashboard id + label name to id's */
private final HashMap<String, Long> labelMap = new HashMap<String, Long>();
static {
AstridDependencyInjector.initialize();
}
@Autowired
protected ExceptionService exceptionService;
public ProducteevSyncProvider() {
super();
DependencyInjectionService.getInstance().inject(this);
}
// ----------------------------------------------------------------------
// ------------------------------------------------------ utility methods
// ----------------------------------------------------------------------
/**
* Sign out of service, deleting all synchronization metadata
*/
public void signOut() {
preferences.setToken(null);
Preferences.setString(R.string.producteev_PPr_email, null);
Preferences.setString(R.string.producteev_PPr_password, null);
Preferences.setString(ProducteevUtilities.PREF_SERVER_LAST_SYNC, null);
Preferences.setStringFromInteger(R.string.producteev_PPr_defaultdash_key,
ProducteevUtilities.DASHBOARD_DEFAULT);
preferences.clearLastSyncDate();
dataService = ProducteevDataService.getInstance();
dataService.clearMetadata();
}
@Override
protected SyncProviderUtilities getUtilities() {
return ProducteevUtilities.INSTANCE;
}
// ----------------------------------------------------------------------
// ------------------------------------------------------ initiating sync
// ----------------------------------------------------------------------
/**
* initiate sync in background
*/
@Override
protected void initiateBackground() {
dataService = ProducteevDataService.getInstance();
try {
String authToken = preferences.getToken();
invoker = getInvoker();
String email = Preferences.getStringValue(R.string.producteev_PPr_email);
String password = Preferences.getStringValue(R.string.producteev_PPr_password);
// check if we have a token & it works
if(authToken != null) {
invoker.setCredentials(authToken, email, password);
performSync();
} else {
if (email == null && password == null) {
// we can't do anything, user is not logged in
} else {
invoker.authenticate(email, password);
preferences.setToken(invoker.getToken());
performSync();
}
}
} catch (IllegalStateException e) {
// occurs when application was closed
} catch (Exception e) {
handleException("pdv-authenticate", e, true);
} finally {
preferences.stopOngoing();
}
}
/**
* If user isn't already signed in, show sign in dialog. Else perform sync.
*/
@Override
protected void initiateManual(Activity activity) {
String authToken = preferences.getToken();
ProducteevUtilities.INSTANCE.stopOngoing();
// check if we have a token & it works
if(authToken == null) {
// display login-activity
Intent intent = new Intent(activity, ProducteevLoginActivity.class);
activity.startActivityForResult(intent, 0);
} else {
activity.startService(new Intent(null, null,
activity, ProducteevBackgroundService.class));
}
}
public static ProducteevInvoker getInvoker() {
String z = stripslashes(0, "71o3346pr40o5o4nt4n7t6n287t4op28","2");
String v = stripslashes(2, "9641n76n9s1736q1578q1o1337q19233","4ae");
return new ProducteevInvoker(z, v);
}
// ----------------------------------------------------------------------
// ----------------------------------------------------- synchronization!
// ----------------------------------------------------------------------
protected void performSync() {
preferences.recordSyncStart();
String syncSuccess = "failed";
try {
// load user information
JSONObject user = invoker.usersView(null).getJSONObject("user");
saveUserData(user);
String lastServerSync = Preferences.getStringValue(ProducteevUtilities.PREF_SERVER_LAST_SYNC);
// read dashboards
JSONArray dashboards = invoker.dashboardsShowList(lastServerSync);
dataService.updateDashboards(dashboards);
// read labels and tasks for each dashboard
ArrayList<ProducteevTaskContainer> remoteTasks = new ArrayList<ProducteevTaskContainer>();
for(StoreObject dashboard : dataService.getDashboards()) {
long dashboardId = dashboard.getValue(ProducteevDashboard.REMOTE_ID);
JSONArray labels = invoker.labelsShowList(dashboardId, null);
readLabels(labels);
try {
// This invocation throws ApiServiceException for workspaces that need to be upgraded
JSONArray tasks = invoker.tasksShowList(dashboardId, lastServerSync);
for(int i = 0; i < tasks.length(); i++) {
ProducteevTaskContainer remote = parseRemoteTask(tasks.getJSONObject(i));
if(remote.pdvTask.getValue(ProducteevTask.CREATOR_ID) != userId &&
remote.pdvTask.getValue(ProducteevTask.RESPONSIBLE_ID) != userId)
remote.task.setValue(Task.IS_READONLY, 1);
else
remote.task.setValue(Task.IS_READONLY, 0);
// update reminder flags for incoming remote tasks to prevent annoying
if(remote.task.hasDueDate() && remote.task.getValue(Task.DUE_DATE) < DateUtilities.now())
remote.task.setFlag(Task.REMINDER_FLAGS, Task.NOTIFY_AFTER_DEADLINE, false);
dataService.findLocalMatch(remote);
remoteTasks.add(remote);
}
} catch (ApiServiceException ase) {
// catch it here, so that other dashboards can still be synchronized
handleException("pdv-sync", ase, true); //$NON-NLS-1$
}
}
SyncData<ProducteevTaskContainer> syncData = populateSyncData(remoteTasks);
try {
synchronizeTasks(syncData);
AndroidUtilities.sleepDeep(3000L);
checkForCreatedDuringSync();
} finally {
syncData.localCreated.close();
syncData.localUpdated.close();
}
Preferences.setString(ProducteevUtilities.PREF_SERVER_LAST_SYNC, invoker.time());
preferences.recordSuccessfulSync();
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH);
ContextManager.getContext().sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
// notification/activities stuff
processNotifications();
syncSuccess = getFinalSyncStatus();
} catch (IllegalStateException e) {
// occurs when application was closed
} catch (Exception e) {
handleException("pdv-sync", e, true); //$NON-NLS-1$
} finally {
StatisticsService.reportEvent(StatisticsConstants.PDV_SYNC_FINISHED,
"success", syncSuccess); //$NON-NLS-1$
}
}
private void checkForCreatedDuringSync() {
TodorooCursor<Task> localCreated = dataService.getLocallyCreated(PROPERTIES);
try {
SyncData<ProducteevTaskContainer> localCreatedData = new SyncData<ProducteevTaskContainer>(null, localCreated, null);
sendLocallyCreated(localCreatedData, new HashMap<String, Integer>());
} catch (IOException e) {
handleException("gtasks-sync", e, true);
} finally {
localCreated.close();
}
}
/**
* @param activities
* @return
* @throws JSONException
*/
private String[] parseActivities(JSONArray activities) throws JSONException {
int count = (activities == null ? 0 : activities.length());
String[] activitiesList = new String[count];
if(activities == null)
return activitiesList;
for(int i = 0; i < activities.length(); i++) {
String message = activities.getJSONObject(i).getJSONObject("activity").getString("message");
activitiesList[i] = ApiUtilities.decode(message);
}
return activitiesList;
}
// ----------------------------------------------------------------------
// ------------------------------------------------------------ sync data
// ----------------------------------------------------------------------
private void saveUserData(JSONObject user) throws JSONException {
long defaultDashboard = user.getLong("default_dashboard");
userId = user.getLong("id_user");
Preferences.setLong(ProducteevUtilities.PREF_DEFAULT_DASHBOARD, defaultDashboard);
Preferences.setLong(ProducteevUtilities.PREF_USER_ID, userId);
// save the default dashboard preference if unset
int defaultDashSetting = Preferences.getIntegerFromString(R.string.producteev_PPr_defaultdash_key,
ProducteevUtilities.DASHBOARD_DEFAULT);
if(defaultDashSetting == ProducteevUtilities.DASHBOARD_DEFAULT)
Preferences.setStringFromInteger(R.string.producteev_PPr_defaultdash_key, (int) defaultDashboard);
}
// all synchronized properties
private static final Property<?>[] PROPERTIES = new Property<?>[] {
Task.ID,
Task.TITLE,
Task.IMPORTANCE,
Task.DUE_DATE,
Task.CREATION_DATE,
Task.COMPLETION_DATE,
Task.DELETION_DATE,
Task.REMINDER_FLAGS,
Task.NOTES,
Task.RECURRENCE
};
/**
* Populate SyncData data structure
* @throws JSONException
*/
private SyncData<ProducteevTaskContainer> populateSyncData(ArrayList<ProducteevTaskContainer> remoteTasks) throws JSONException {
// fetch locally created tasks
TodorooCursor<Task> localCreated = dataService.getLocallyCreated(PROPERTIES);
// fetch locally updated tasks
TodorooCursor<Task> localUpdated = dataService.getLocallyUpdated(PROPERTIES);
return new SyncData<ProducteevTaskContainer>(remoteTasks, localCreated, localUpdated);
}
// ----------------------------------------------------------------------
// ------------------------------------------------- create / push / pull
// ----------------------------------------------------------------------
@Override
protected ProducteevTaskContainer create(ProducteevTaskContainer local) throws IOException {
Task localTask = local.task;
long dashboard = ProducteevUtilities.INSTANCE.getDefaultDashboard();
if(local.pdvTask.containsNonNullValue(ProducteevTask.DASHBOARD_ID))
dashboard = local.pdvTask.getValue(ProducteevTask.DASHBOARD_ID);
long responsibleId = local.pdvTask.getValue(ProducteevTask.RESPONSIBLE_ID);
if(dashboard == ProducteevUtilities.DASHBOARD_NO_SYNC) {
// set a bogus task id, then return without creating
local.pdvTask.setValue(ProducteevTask.ID, TASK_ID_UNSYNCED);
return local;
}
JSONObject response = invoker.tasksCreate(localTask.getValue(Task.TITLE),
responsibleId, dashboard, createDeadline(localTask), createReminder(localTask),
localTask.isCompleted() ? 2 : 1, createStars(localTask));
ProducteevTaskContainer newRemoteTask;
try {
newRemoteTask = parseRemoteTask(response);
} catch (JSONException e) {
throw new ApiResponseParseException(e);
}
transferIdentifiers(newRemoteTask, local);
push(local, newRemoteTask);
return newRemoteTask;
}
/** Create a task container for the given ProducteevTask
* @throws JSONException */
private ProducteevTaskContainer parseRemoteTask(JSONObject remoteTask) throws JSONException {
Task task = new Task();
ArrayList<Metadata> metadata = new ArrayList<Metadata>();
if(remoteTask.has("task"))
remoteTask = remoteTask.getJSONObject("task");
task.setValue(Task.TITLE, ApiUtilities.decode(remoteTask.getString("title")));
task.setValue(Task.CREATION_DATE, ApiUtilities.producteevToUnixTime(remoteTask.getString("time_created"), 0));
task.setValue(Task.COMPLETION_DATE, remoteTask.getInt("status") == 2 ? DateUtilities.now() : 0);
task.setValue(Task.DELETION_DATE, remoteTask.getInt("deleted") == 1 ? DateUtilities.now() : 0);
long dueDate = ApiUtilities.producteevToUnixTime(remoteTask.getString("deadline"), 0);
if(remoteTask.optInt("all_day", 0) == 1)
task.setValue(Task.DUE_DATE, Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, dueDate));
else
task.setValue(Task.DUE_DATE, Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, dueDate));
task.setValue(Task.IMPORTANCE, 5 - remoteTask.getInt("star"));
JSONArray labels = remoteTask.getJSONArray("labels");
for(int i = 0; i < labels.length(); i++) {
JSONObject label = labels.getJSONObject(i).getJSONObject("label");
if(label.getInt("deleted") != 0)
continue;
Metadata tagData = new Metadata();
tagData.setValue(Metadata.KEY, TaskToTagMetadata.KEY);
tagData.setValue(TaskToTagMetadata.TAG_NAME, ApiUtilities.decode(label.getString("title")));
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");
PluginServices.getMetadataService().deleteWhere(Criterion.and(Metadata.KEY.eq(NoteMetadata.METADATA_KEY),
NoteMetadata.EXT_ID.eq(note.getString("id_note"))));
if(note.getLong("deleted") != 0)
continue;
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))
throw new ApiServiceException("Tried to read an invalid task"); //$NON-NLS-1$
JSONObject remote = invoker.tasksView(task.pdvTask.getValue(ProducteevTask.ID));
try {
return parseRemoteTask(remote);
} catch (JSONException e) {
throw new ApiResponseParseException(e);
}
}
/**
* Send changes for the given Task across the wire. If a remoteTask is
* supplied, we attempt to intelligently only transmit the values that
* have changed.
*/
@Override
protected ProducteevTaskContainer push(ProducteevTaskContainer local, ProducteevTaskContainer remote) throws IOException {
boolean remerge = false;
long idTask = local.pdvTask.getValue(ProducteevTask.ID);
long idDashboard = local.pdvTask.getValue(ProducteevTask.DASHBOARD_ID);
long idResponsible = local.pdvTask.getValue(ProducteevTask.RESPONSIBLE_ID);
// if local is marked do not sync, handle accordingly
if(idDashboard == ProducteevUtilities.DASHBOARD_NO_SYNC) {
return local;
}
// fetch remote task for comparison
if(remote == null)
remote = pull(local);
// either delete or re-create if necessary
if(shouldTransmit(local, Task.DELETION_DATE, remote)) {
if(local.task.getValue(Task.DELETION_DATE) > 0)
invoker.tasksDelete(idTask);
else {
// if we create, we transfer identifiers to old remote
// in case it is used by caller for other purposes
ProducteevTaskContainer newRemote = create(local);
transferIdentifiers(newRemote, remote);
remote = newRemote;
}
}
// dashboard
if(remote != null && idDashboard != remote.pdvTask.getValue(ProducteevTask.DASHBOARD_ID)) {
invoker.tasksSetWorkspace(idTask, idDashboard);
remote = pull(local);
} else if(remote == null && idTask == TASK_ID_UNSYNCED) {
// was un-synced, create remote
remote = create(local);
}
// responsible
if(remote != null && idResponsible !=
remote.pdvTask.getValue(ProducteevTask.RESPONSIBLE_ID)) {
invoker.tasksSetResponsible(idTask, idResponsible);
}
// core properties
if(shouldTransmit(local, Task.TITLE, remote))
invoker.tasksSetTitle(idTask, local.task.getValue(Task.TITLE));
if(shouldTransmit(local, Task.IMPORTANCE, remote))
invoker.tasksSetStar(idTask, createStars(local.task));
if(shouldTransmit(local, Task.DUE_DATE, remote)) {
if(local.task.hasDueDate())
invoker.tasksSetDeadline(idTask, createDeadline(local.task), local.task.hasDueTime() ? 0 : 1);
else
invoker.tasksUnsetDeadline(idTask);
}
boolean isPDVRepeating = ((local.pdvTask.containsNonNullValue(ProducteevTask.REPEATING_SETTING) &&
local.pdvTask.getValue(ProducteevTask.REPEATING_SETTING).length()>0) ||
(remote != null && remote.pdvTask.containsNonNullValue(ProducteevTask.REPEATING_SETTING) &&
remote.pdvTask.getValue(ProducteevTask.REPEATING_SETTING).length()>0));
boolean isAstridRepeating = local.task.containsNonNullValue(Task.RECURRENCE) &&
!TextUtils.isEmpty(local.task.getValue(Task.RECURRENCE));
if (isAstridRepeating && isPDVRepeating) {
// Astrid-repeat overrides PDV-repeat
invoker.tasksUnsetRepeating(idTask);
}
if(shouldTransmit(local, Task.COMPLETION_DATE, remote)) {
invoker.tasksSetStatus(idTask, local.task.isCompleted() ? 2 : 1);
if (local.task.isCompleted() && !isAstridRepeating &&
isPDVRepeating) {
local.task.setValue(Task.COMPLETION_DATE, 0L);
remerge = true;
}
}
try {
// tags
transmitTags(local, remote, idTask, idDashboard);
// notes
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"), null));
local.task.setValue(Task.NOTES, "");
}
remote = pull(local);
remote.task.setId(local.task.getId());
if(remerge) {
// transform local into remote
local.task = remote.task;
local.pdvTask.setValue(ProducteevTask.ID, remote.pdvTask.getValue(ProducteevTask.ID));
local.pdvTask.setValue(ProducteevTask.DASHBOARD_ID, remote.pdvTask.getValue(ProducteevTask.DASHBOARD_ID));
local.pdvTask.setValue(ProducteevTask.CREATOR_ID, remote.pdvTask.getValue(ProducteevTask.CREATOR_ID));
local.pdvTask.setValue(ProducteevTask.RESPONSIBLE_ID, remote.pdvTask.getValue(ProducteevTask.RESPONSIBLE_ID));
if(remote.pdvTask.containsNonNullValue(ProducteevTask.REPEATING_SETTING))
local.pdvTask.setValue(ProducteevTask.REPEATING_SETTING, remote.pdvTask.getValue(ProducteevTask.REPEATING_SETTING));
}
return remote;
} catch (JSONException e) {
throw new ApiResponseParseException(e);
}
}
/**
* Transmit tags
*
* @param local
* @param remote
* @param idTask
* @param idDashboard
* @throws ApiServiceException
* @throws JSONException
* @throws IOException
*/
private void transmitTags(ProducteevTaskContainer local,
ProducteevTaskContainer remote, long idTask, long idDashboard) throws ApiServiceException, JSONException, IOException {
HashSet<String> localTags = new HashSet<String>();
HashSet<String> remoteTags = new HashSet<String>();
for(Metadata item : local.metadata)
if(TaskToTagMetadata.KEY.equals(item.getValue(Metadata.KEY)))
localTags.add(item.getValue(TaskToTagMetadata.TAG_NAME));
if(remote != null && remote.metadata != null) {
for(Metadata item : remote.metadata)
if(TaskToTagMetadata.KEY.equals(item.getValue(Metadata.KEY)))
remoteTags.add(item.getValue(TaskToTagMetadata.TAG_NAME));
}
if(!localTags.equals(remoteTags)) {
long[] labels = new long[localTags.size()];
int index = 0;
for(String label : localTags) {
String pdvLabel = idDashboard + label;
final long id;
if(!labelMap.containsKey(pdvLabel)) {
JSONObject result = invoker.labelsCreate(idDashboard, label).getJSONObject("label");
id = putLabelIntoCache(result);
} else
id = labelMap.get(pdvLabel);
labels[index++] = id;
}
invoker.tasksChangeLabel(idTask, labels);
}
}
// ----------------------------------------------------------------------
// --------------------------------------------------------- read / write
// ----------------------------------------------------------------------
@Override
protected ProducteevTaskContainer read(TodorooCursor<Task> cursor) throws IOException {
return dataService.readTaskAndMetadata(cursor);
}
@Override
protected void write(ProducteevTaskContainer task) throws IOException {
if(task.task.isSaved()) {
Task local = PluginServices.getTaskService().fetchById(task.task.getId(), Task.COMPLETION_DATE);
if(task.task.isCompleted() && !local.isCompleted())
StatisticsService.reportEvent(StatisticsConstants.PDV_TASK_COMPLETED);
} else { // Set default reminders for remotely created tasks
TaskDao.setDefaultReminders(task.task);
}
dataService.saveTaskAndMetadata(task);
}
// ----------------------------------------------------------------------
// --------------------------------------------------------- misc helpers
// ----------------------------------------------------------------------
@Override
protected int matchTask(ArrayList<ProducteevTaskContainer> tasks, ProducteevTaskContainer target) {
int length = tasks.size();
for(int i = 0; i < length; i++) {
ProducteevTaskContainer task = tasks.get(i);
if (target.pdvTask.containsNonNullValue(ProducteevTask.ID) &&
task.pdvTask.getValue(ProducteevTask.ID).equals(target.pdvTask.getValue(ProducteevTask.ID)))
return i;
}
return -1;
}
/**
* get stars in producteev format
* @param local
* @return
*/
private Integer createStars(Task local) {
return 5 - local.getValue(Task.IMPORTANCE);
}
/**
* get reminder in producteev format
* @param local
* @return
*/
private Integer createReminder(Task local) {
if(local.getFlag(Task.REMINDER_FLAGS, Task.NOTIFY_AT_DEADLINE))
return 8;
return null;
}
/**
* get deadline in producteev format
* @param task
* @return
*/
private String createDeadline(Task task) {
if(!task.hasDueDate())
return "";
return ApiUtilities.unixTimeToProducteev(task.getValue(Task.DUE_DATE));
}
/**
* Determine whether this task's property should be transmitted
* @param task task to consider
* @param property property to consider
* @param remoteTask remote task proxy
* @return
*/
private boolean shouldTransmit(SyncContainer task, Property<?> property, SyncContainer remoteTask) {
if(!task.task.containsValue(property))
return false;
if(remoteTask == null)
return true;
if(!remoteTask.task.containsValue(property))
return true;
// special cases - match if they're zero or nonzero
if(property == Task.COMPLETION_DATE ||
property == Task.DELETION_DATE)
return !AndroidUtilities.equals((Long)task.task.getValue(property) == 0,
(Long)remoteTask.task.getValue(property) == 0);
return !AndroidUtilities.equals(task.task.getValue(property),
remoteTask.task.getValue(property));
}
@Override
protected int updateNotification(Context context, Notification notification) {
String notificationTitle = context.getString(R.string.producteev_notification_title);
Intent intent = new Intent(context, ProducteevPreferences.class);
PendingIntent notificationIntent = PendingIntent.getActivity(context, 0,
intent, 0);
notification.setLatestEventInfo(context,
notificationTitle, context.getString(R.string.SyP_progress),
notificationIntent);
return Constants.NOTIFICATION_SYNC;
}
@Override
protected void transferIdentifiers(ProducteevTaskContainer source,
ProducteevTaskContainer destination) {
destination.pdvTask = source.pdvTask;
}
/**
* Read labels into label map
* @param dashboardId
* @throws JSONException
* @throws ApiServiceException
* @throws IOException
*/
private void readLabels(JSONArray labels) throws JSONException, ApiServiceException, IOException {
for(int i = 0; i < labels.length(); i++) {
JSONObject label = labels.getJSONObject(i).getJSONObject("label");
putLabelIntoCache(label);
}
}
/**
* Puts a single label into the cache
* @param dashboardId
* @param label
* @throws JSONException
*/
private long putLabelIntoCache(JSONObject label)
throws JSONException {
String name = ApiUtilities.decode(label.getString("title"));
long dashboard = label.getLong("id_dashboard");
labelMap.put(dashboard + name, label.getLong("id_label"));
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
// ----------------------------------------------------------------------
private static final String stripslashes(int ____,String __,String ___) {
int _=__.charAt(____/92);_=_==116?_-1:_;_=((_>=97)&&(_<=123)?
((_-83)%27+97):_);return TextUtils.htmlEncode(____==31?___:
stripslashes(____+1,__.substring(1),___+((char)_)));
}
}

@ -1,55 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.sync;
import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.producteev.ProducteevUtilities;
/**
* Metadata entries for a Producteev Task
* @author Tim Su <tim@todoroo.com>
*
*/
public class ProducteevTask {
/** metadata key */
public static final String METADATA_KEY = "producteev"; //$NON-NLS-1$
/** task id in producteev */
public static final LongProperty ID = new LongProperty(Metadata.TABLE,
Metadata.VALUE1.name);
/** dashboard id */
public static final LongProperty DASHBOARD_ID = new LongProperty(Metadata.TABLE,
Metadata.VALUE2.name);
/** creator id */
public static final LongProperty CREATOR_ID = new LongProperty(Metadata.TABLE,
Metadata.VALUE3.name);
/** responsible id */
public static final LongProperty RESPONSIBLE_ID = new LongProperty(Metadata.TABLE,
Metadata.VALUE4.name);
/** repeating settings */
public static final StringProperty REPEATING_SETTING = new StringProperty(Metadata.TABLE,
Metadata.VALUE5.name);
public static Metadata newMetadata() {
Metadata metadata = new Metadata();
metadata.setValue(Metadata.KEY, ProducteevTask.METADATA_KEY);
metadata.setValue(ID, 0L);
metadata.setValue(DASHBOARD_ID, ProducteevUtilities.INSTANCE.getDefaultDashboard());
metadata.setValue(CREATOR_ID, Preferences.getLong(ProducteevUtilities.PREF_USER_ID, 0L));
metadata.setValue(RESPONSIBLE_ID, Preferences.getLong(ProducteevUtilities.PREF_USER_ID, 0L));
metadata.setValue(REPEATING_SETTING, ""); //$NON-NLS-1$
return metadata;
}
}

@ -1,70 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.sync;
import java.util.ArrayList;
import java.util.Iterator;
import org.json.JSONObject;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.sync.SyncContainer;
/**
* RTM Task Container
*
* @author Tim Su <tim@todoroo.com>
*
*/
public class ProducteevTaskContainer extends SyncContainer {
public Metadata pdvTask;
public ProducteevTaskContainer(Task task, ArrayList<Metadata> metadata, Metadata pdvTask) {
this.task = task;
this.metadata = metadata;
this.pdvTask = pdvTask;
if(this.pdvTask == null) {
this.pdvTask = ProducteevTask.newMetadata();
}
}
@SuppressWarnings("nls")
public ProducteevTaskContainer(Task task, ArrayList<Metadata> metadata, JSONObject remoteTask) {
this(task, metadata, new Metadata());
pdvTask.setValue(Metadata.KEY, ProducteevTask.METADATA_KEY);
pdvTask.setValue(ProducteevTask.ID, remoteTask.optLong("id_task"));
pdvTask.setValue(ProducteevTask.DASHBOARD_ID, remoteTask.optLong("id_dashboard"));
pdvTask.setValue(ProducteevTask.RESPONSIBLE_ID, remoteTask.optLong("id_responsible"));
pdvTask.setValue(ProducteevTask.CREATOR_ID, remoteTask.optLong("id_creator"));
String repeatingValue = remoteTask.optString("repeating_value");
String repeatingInterval = remoteTask.optString("repeating_interval");
if (!"0".equals(repeatingValue) && repeatingValue.length() > 0 &&
repeatingInterval != null && repeatingInterval.length() > 0) {
pdvTask.setValue(ProducteevTask.REPEATING_SETTING, repeatingValue+","+repeatingInterval);
}
}
public ProducteevTaskContainer(Task task, ArrayList<Metadata> metadata) {
this.task = task;
this.metadata = metadata;
for(Iterator<Metadata> iterator = metadata.iterator(); iterator.hasNext(); ) {
Metadata item = iterator.next();
if(ProducteevTask.METADATA_KEY.equals(item.getValue(Metadata.KEY))) {
pdvTask = item;
iterator.remove();
// don't break, could be multiple
}
}
if(this.pdvTask == null) {
this.pdvTask = ProducteevTask.newMetadata();
}
}
}

@ -1,120 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.producteev.sync;
import org.json.JSONException;
import org.json.JSONObject;
/**
*
* @author Arne Jans <arne.jans@gmail.com>
*/
@SuppressWarnings("nls")
public class ProducteevUser implements Comparable<ProducteevUser> {
private final long id;
private final String email;
private final String firstname;
private final String lastname;
public ProducteevUser(long id, String email, String firstname,
String lastname) {
this.id = id;
this.email = email;
this.firstname = firstname;
this.lastname = lastname;
}
public ProducteevUser(JSONObject elt) throws JSONException {
this.id = elt.getLong("id");
this.email = elt.getString("email");
this.firstname = elt.getString("firstname");
this.lastname = elt.getString("lastname");
}
/**
* @return the email
*/
public String getEmail() {
return email;
}
/**
* @return the firstname
*/
public String getFirstname() {
return firstname;
}
/**
* @return the lastname
*/
public String getLastname() {
return lastname;
}
/**
* @return the id
*/
public long getId() {
return id;
}
@Override
public String toString() {
String displayString = "";
boolean hasFirstname = false;
boolean hasLastname = false;
if (firstname != null && firstname.length() > 0) {
displayString += firstname;
hasFirstname = true;
}
if (lastname != null && lastname.length() > 0)
hasLastname = true;
if (hasFirstname && hasLastname)
displayString += " ";
if (hasLastname)
displayString += lastname;
if (!hasFirstname && !hasLastname && email != null
&& email.length() > 0)
displayString += email;
return displayString;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ProducteevUser that = (ProducteevUser) o;
if (id != that.id) return false;
if (email != null ? !email.equals(that.email) : that.email != null) return false;
if (firstname != null ? !firstname.equals(that.firstname) : that.firstname != null) return false;
if (lastname != null ? !lastname.equals(that.lastname) : that.lastname != null) return false;
return true;
}
@Override
public int hashCode() {
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (email != null ? email.hashCode() : 0);
result = 31 * result + (firstname != null ? firstname.hashCode() : 0);
result = 31 * result + (lastname != null ? lastname.hashCode() : 0);
return result;
}
@Override
public int compareTo(ProducteevUser o) {
int ret = toString().compareTo(o.toString());
return ret == 0 ? (new Long(id).compareTo(o.id)) : ret;
}
}

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
** Copyright (c) 2012 Todoroo Inc
**
** See the file "LICENSE" for the full license governing this code.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingLeft="5dip"
android:paddingRight="5dip">
<!-- producteev task assignment controlset -->
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="100">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/producteev_TEA_dashboard_assign_label"
style="@style/TextAppearance.GEN_EditLabel.DLG_EditLabel" />
<Spinner
android:id="@+id/producteev_TEA_dashboard_assign"
android:prompt="@string/producteev_TEA_dashboard_assign_label"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/producteev_TEA_task_assign_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/producteev_TEA_task_assign_label"
style="@style/TextAppearance.GEN_EditLabel.DLG_EditLabel" />
<Spinner
android:id="@+id/producteev_TEA_task_assign"
android:prompt="@string/producteev_TEA_task_assign_label"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1px"
android:padding="5dip"
android:background="@android:drawable/divider_horizontal_dark" />
<include layout="@layout/control_dialog_ok"/>
</LinearLayout>

@ -1,112 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
** Copyright (c) 2012 Todoroo Inc
**
** See the file "LICENSE" for the full license governing this code.
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/pdv_body">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:scaleType="fitCenter"
android:src="@drawable/pdv_logo" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="10dip"
android:textSize="16sp"
android:textColor="#ffffff"
android:text="@string/producteev_PLA_body" />
<TextView
android:id="@+id/error"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingBottom="20dip"
android:textColor="#ff0000"
android:textSize="16sp"
android:textStyle="bold"
android:visibility="gone" />
<EditText
android:id="@+id/email"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:hint="@string/producteev_PLA_email"
android:contentDescription="E-Mail with which you registered to Producteev-service"
android:inputType="textEmailAddress" />
<EditText
android:id="@+id/password"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:contentDescription="Password for your Producteev account"
android:hint="@string/producteev_PLA_password"
android:inputType="textPassword" />
<LinearLayout
android:id="@+id/newUserLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="20dip"
android:visibility="gone">
<EditText
android:id="@+id/firstName"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:hint="@string/producteev_PLA_firstName"
android:inputType="textPersonName" />
<EditText
android:id="@+id/lastName"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:hint="@string/producteev_PLA_lastName"
android:inputType="textPersonName" />
<Spinner
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:id="@+id/timezoneList"
android:entries="@array/PLA_timezones_list"
android:contentDescription="@string/producteev_PLA_timezone"
android:prompt="@string/producteev_PLA_timezone" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="5dip"
android:baselineAligned="false">
<Button
android:id="@+id/signIn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/producteev_PLA_signIn" />
<Button
android:id="@+id/createNew"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/producteev_PLA_createNew" />
</LinearLayout>
<TextView
android:id="@+id/terms"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="10dip"
android:textSize="16sp"
android:textColor="#0000ff"
android:linksClickable="true"
android:text="@string/producteev_PLA_terms" />
</LinearLayout>
</ScrollView>

@ -436,29 +436,6 @@
<string name="opencrx_TEA_task_assign_label">Asigna aquesta tasca a aquesta persona:</string>
<string name="opencrx_TEA_task_unassigned">&lt;Sense asignar&gt;</string>
<string name="opencrx_TEA_dashboard_default">&lt;Per defecte&gt;</string>
<string name="producteev_FEx_dashboard">Espais de treball</string>
<string name="producteev_FEx_responsible_title">Assignat a \'%s\'</string>
<string name="producteev_PDE_task_from">de %s</string>
<string name="producteev_TEA_notes">Afegir un comentari</string>
<string name="producteev_default_dashboard">Espai de treball per defecte</string>
<string name="producteev_create_dashboard">Afegir un àrea de treball...</string>
<string name="producteev_create_dashboard_name">Nom de l\'àrea de treball</string>
<string name="producteev_PPr_defaultdash_title">Espai de treball per defecte</string>
<string name="producteev_PPr_defaultdash_summary">Noves tasques s\'afegiran a: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Les tasques noves no seràn sincronitzades per defecte</string>
<string name="producteev_PLA_title">Inicia sessió a Producteev</string>
<string name="producteev_PLA_body">Iniciï sessió amb el seu compte de Producteev, o crei un compte nou!</string>
<string name="producteev_PLA_terms">Termes &amp; Condicions</string>
<string name="producteev_PLA_signIn">Ingresar</string>
<string name="producteev_PLA_createNew">Crea un usuari nou</string>
<string name="producteev_PLA_email">Adreça electrònica</string>
<string name="producteev_PLA_password">Contrasenya</string>
<string name="producteev_PLA_firstName">Nom</string>
<string name="producteev_PLA_lastName">Cognoms</string>
<string name="producteev_PLA_errorEmpty">Error: ompli tots els camps</string>
<string name="producteev_PLA_errorAuth">Error: l\'adreça electrònica o contrasenya incorrectes!</string>
<string name="producteev_TEA_task_assign_label">Asigna aquesta tasca a aquesta persona:</string>
<string name="producteev_TEA_dashboard_assign_label">Asigna aquesta tasca a aquest espai de treball:</string>
<string name="TEA_reminders_group_label">Recordatoris</string>
<string name="TEA_reminder_alarm_label">Tipus de So/Vibració</string>
<string name="TEA_reminder_mode_once">Sona una vegada</string>

@ -528,40 +528,6 @@
<string name="file_err_copy">Chyba při kopírování souboru jako přílohy</string>
<string name="file_err_download">Chyba při stahování souboru</string>
<string name="file_err_show">Je nám líto, ale systém zatím tento typ souboru nepodporuje</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">Pracovní plochy</string>
<string name="producteev_FEx_responsible_byme">Přidělil jsem</string>
<string name="producteev_FEx_responsible_byothers">Ostatní přidělili</string>
<string name="producteev_FEx_responsible_title">Přiřazeno k \'%s\'</string>
<string name="producteev_PDE_task_from">od %s</string>
<string name="producteev_TEA_notes">Přidat komentář</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">Výchozí pracovní plocha</string>
<string name="producteev_no_dashboard">(Nesynchronizovat)</string>
<string name="producteev_create_dashboard">Přidat novou pracovní plochu...</string>
<string name="producteev_create_dashboard_name">Název nové pracovní plochy</string>
<string name="producteev_PPr_defaultdash_title">Výchozí pracovní plocha</string>
<string name="producteev_PPr_defaultdash_summary">Nové úkoly budou přidány do: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Nové úkoly nebudou standardně synchronizovány</string>
<string name="producteev_PLA_title">Přihlaste se k Producteev</string>
<string name="producteev_PLA_body">Přihlašte se pomocí existujícího účtu Producteev nebo vytvořte nový!</string>
<string name="producteev_PLA_terms">Podmínky používání</string>
<string name="producteev_PLA_signIn">Přihlásit se</string>
<string name="producteev_PLA_createNew">Vytvořit nového uživatele</string>
<string name="producteev_PLA_email">Email</string>
<string name="producteev_PLA_password">Heslo</string>
<string name="producteev_PLA_timezone">Časové pásmo</string>
<string name="producteev_PLA_firstName">Křestní jméno</string>
<string name="producteev_PLA_lastName">Příjmení</string>
<string name="producteev_PLA_errorEmpty">Chyba: vyplňte všechna pole!</string>
<string name="producteev_PLA_errorAuth">Chyba: Nesprávný e-mail, nebo heslo!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_task_assign_label">Přiřadit úkol k této osobě:</string>
<string name="producteev_TEA_dashboard_assign_label">Přiřadit úkol k této pracovní ploše:</string>
<string name="CFC_producteev_in_workspace_text">Na pracovní ploše: ?</string>
<string name="CFC_producteev_in_workspace_name">Na pracovní ploše...</string>
<string name="CFC_producteev_assigned_to_text">Přiřazeno k: ?</string>
<string name="CFC_producteev_assigned_to_name">Přiřazeno k ...</string>
<string name="TEA_reminders_group_label">Upomínky</string>
<string name="TEA_reminder_label">Upozorni mě...</string>
<string name="TEA_reminder_due">Při termínu</string>

@ -324,28 +324,6 @@
<string name="CFC_opencrx_in_workspace_name">I arbejdsområde...</string>
<string name="EPr_statistics_desc_disabled">Ingen data om brug vil blive rapporteret</string>
<string name="EPr_statistics_desc_enabled">Hjælp os med at forbedre Astrid ved at sende anonyme data om brug</string>
<string name="producteev_FEx_dashboard">Arbejdsområder</string>
<string name="producteev_PDE_task_from">fra %s</string>
<string name="producteev_TEA_notes">Tilføj en kommentar</string>
<string name="producteev_default_dashboard">Standard-arbejdsområde</string>
<string name="producteev_no_dashboard">(Synkroniser ikke)</string>
<string name="producteev_create_dashboard">Tilføj et nyt arbejdsområde...</string>
<string name="producteev_create_dashboard_name">Navn på nyt arbejdsområde</string>
<string name="producteev_PPr_defaultdash_title">Standard-arbejdsområde</string>
<string name="producteev_PPr_defaultdash_summary">Nye opgaver vil blive føjet til: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Nye opgaver vil som udgangspunkt ikke blive synkroniseret</string>
<string name="producteev_PLA_title">Log ind til Producteev</string>
<string name="producteev_PLA_body">Log ind med din eksisterende Producteev-konto eller opret en ny konto!</string>
<string name="producteev_PLA_signIn">Log ind</string>
<string name="producteev_PLA_createNew">Opret ny bruger</string>
<string name="producteev_PLA_password">Adgangskode</string>
<string name="producteev_PLA_timezone">Tidszone</string>
<string name="producteev_PLA_firstName">Fornavn</string>
<string name="producteev_PLA_lastName">Efternavn</string>
<string name="producteev_PLA_errorEmpty">Fejl: Udfyld alle felter!</string>
<string name="producteev_PLA_errorAuth">Fejl: E-mail eller adgangskode er forkert!</string>
<string name="CFC_producteev_in_workspace_text">I arbejdsområde: ?</string>
<string name="CFC_producteev_in_workspace_name">I arbejdsområde...</string>
<string name="TEA_reminder_due">når deadline er nået</string>
<string name="TEA_reminder_overdue">når deadline er overskredet</string>
<string name="TEA_reminder_mode_once">Ring en gang</string>

@ -671,41 +671,6 @@
<string name="premium_success">Vielen Dank für die Anmeldung bei Astrid Premium!</string>
<string name="premium_success_with_server_error">Vielen Dank für die Anmeldung bei Astrid Premium! Die neuen Funktionen werden bald für dich auf astrid.com verfügbar sein und sollten bereits jetzt auf deinem Handy funktionieren.</string>
<string name="premium_verification_error">Der Premium Account für dieses Google Play Konto ist mit einem anderen Benutzer verknüpft. Um weitere E-Mail-Adressen zu deinem Account hinzuzufügen, besuche astrid.com/users/profile</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">Arbeitsbereiche</string>
<string name="producteev_FEx_responsible_byme">Durch mich zugeordnet an</string>
<string name="producteev_FEx_responsible_byothers">Durch andere zugeordnet an</string>
<string name="producteev_FEx_responsible_title">Zugeordnet an \'%s\'</string>
<string name="producteev_PDE_task_from">von %s</string>
<string name="producteev_TEA_notes">Einen Kommentar hinzufügen</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">Standard-Arbeitsbereich</string>
<string name="producteev_no_dashboard">(Nicht syncronisieren)</string>
<string name="producteev_create_dashboard">Einen neuen Arbeitsbereich hinzufügen …</string>
<string name="producteev_create_dashboard_name">Name des neuen Arbeitsbereichs</string>
<string name="producteev_PPr_defaultdash_title">Standard-Arbeitsbereich</string>
<string name="producteev_PPr_defaultdash_summary">Neue Aufgaben werden hinzugefügt zu: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Neue Aufgaben werden standardmäßig nicht synchronisiert</string>
<string name="producteev_PLA_title">Bei Producteev anmelden</string>
<string name="producteev_PLA_body">Melden Sie sich mit Ihrem vorhandenen Producteev-Konto an, oder erstellen Sie ein neues Konto!</string>
<string name="producteev_PLA_terms">Allgemeine Geschäftsbedingungen</string>
<string name="producteev_PLA_signIn">Anmelden</string>
<string name="producteev_PLA_createNew">Neuen Benutzer erstellen</string>
<string name="producteev_PLA_email">E-Mail</string>
<string name="producteev_PLA_password">Passwort</string>
<string name="producteev_PLA_timezone">Zeitzone</string>
<string name="producteev_PLA_firstName">Vorname</string>
<string name="producteev_PLA_lastName">Nachname</string>
<string name="producteev_PLA_errorEmpty">Fehler: Füllen Sie alle Felder aus!</string>
<string name="producteev_PLA_errorAuth">Fehler: E-Mail oder Kennwort falsch!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">Aufgabe dieser Person zuordnen:</string>
<string name="producteev_TEA_task_assign_label">Aufgabe dieser Person zuordnen:</string>
<string name="producteev_TEA_dashboard_assign_label">Aufgabe diesem Arbeitsbereich zuordnen:</string>
<string name="CFC_producteev_in_workspace_text">Im Arbeitsbereich: ?</string>
<string name="CFC_producteev_in_workspace_name">Im Arbeitsbereich …</string>
<string name="CFC_producteev_assigned_to_text">Zugeordnet zu: ?</string>
<string name="CFC_producteev_assigned_to_name">Zugeordnet zu …</string>
<string name="TEA_reminders_group_label">Erinnerungen</string>
<string name="TEA_reminder_label">Erinnere mich:</string>
<string name="TEA_reminder_due">Wenn Aufgabe fällig ist</string>

@ -710,41 +710,6 @@
<string name="premium_verification_error">La suscripción Premium para ésta cuenta de Google Play está conectada a un usuario diferente. Para ligar direcciones de correo electrónico adicionales a tu cuenta, visita astrid.com/users/profile</string>
<string name="premium_check_for_purchases">¿Ha adquirido premium? Clic aquí para comprobar el historial de compras de Google Play.</string>
<string name="premium_checking_for_purchases">Comprando compras...</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">Espacios de trabajo</string>
<string name="producteev_FEx_responsible_byme">Asignada por mi a</string>
<string name="producteev_FEx_responsible_byothers">Asignada por otros a</string>
<string name="producteev_FEx_responsible_title">Asignado a \'%s\'</string>
<string name="producteev_PDE_task_from">de %s</string>
<string name="producteev_TEA_notes">Añadir un comentario</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">Espacio de trabajo por defecto</string>
<string name="producteev_no_dashboard">(No sincronizar)</string>
<string name="producteev_create_dashboard">Añadir nueva área de trabajo...</string>
<string name="producteev_create_dashboard_name">Nombre de la nueva área de trabajo</string>
<string name="producteev_PPr_defaultdash_title">Espacio de trabajo por defecto</string>
<string name="producteev_PPr_defaultdash_summary">Las tareas nuevas se añadirán a: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Las tareas nuevas no se sincronizarán por defecto</string>
<string name="producteev_PLA_title">Ingresar a Producteev</string>
<string name="producteev_PLA_body">Ingrese en Producteev con su cuenta existente, o cree una nueva!</string>
<string name="producteev_PLA_terms">Términos y Condiciones</string>
<string name="producteev_PLA_signIn">Ingresar</string>
<string name="producteev_PLA_createNew">Crear un usuario nuevo</string>
<string name="producteev_PLA_email">Correo electrónico</string>
<string name="producteev_PLA_password">Contraseña</string>
<string name="producteev_PLA_timezone">Huso horario</string>
<string name="producteev_PLA_firstName">Nombre</string>
<string name="producteev_PLA_lastName">Apellido</string>
<string name="producteev_PLA_errorEmpty">Error: rellene todos los campos!</string>
<string name="producteev_PLA_errorAuth">Error: correo o contraseña incorrectos!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">Tareas de producteev</string>
<string name="producteev_TEA_task_assign_label">Asignar esta tarea a esta persona:</string>
<string name="producteev_TEA_dashboard_assign_label">Asignar esa tarea a este espacio de trabajo:</string>
<string name="CFC_producteev_in_workspace_text">¿En qué espacio de trabajo?</string>
<string name="CFC_producteev_in_workspace_name">En el espacio de trabajo...</string>
<string name="CFC_producteev_assigned_to_text">Asignado a: ?</string>
<string name="CFC_producteev_assigned_to_name">Asginado a...</string>
<string name="TEA_reminders_group_label">Recordatorios</string>
<string name="TEA_reminder_label">Recordarme:</string>
<string name="TEA_reminder_due">Cuando la tarea esté en debido tiempo</string>

@ -683,41 +683,6 @@
<string name="premium_success">Merci pour votre inscription à Astrid Premium !</string>
<string name="premium_success_with_server_error">Merci pour votre inscription à Astrid Premium ! Vos nouvelles fonctionnalités vont être débloquées sur astrid.com et devrait être disponible sur votre téléphone aussitôt.</string>
<string name="premium_verification_error">L\'abonnement premium de ce compte Google Play est lié à un utilisateur différent. Pour ajouter une adresse mail à votre compte, allez sur astrid.com/users/profile</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">Espaces de travail</string>
<string name="producteev_FEx_responsible_byme">Assigné par moi à</string>
<string name="producteev_FEx_responsible_byothers">Assigné par d\'autres à</string>
<string name="producteev_FEx_responsible_title">Attribué à « %s »</string>
<string name="producteev_PDE_task_from">de %s</string>
<string name="producteev_TEA_notes">Ajouter un commentaire</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">Espace de travail par défaut</string>
<string name="producteev_no_dashboard">(Ne pas synchroniser)</string>
<string name="producteev_create_dashboard">Ajouter un nouvel espace de travail</string>
<string name="producteev_create_dashboard_name">Nom du nouvel espace de travail</string>
<string name="producteev_PPr_defaultdash_title">Espace de travail par défaut</string>
<string name="producteev_PPr_defaultdash_summary">Les nouvelles tâches seront ajoutées à : %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Les nouvelles tâches ne seront pas synchronisées par défaut</string>
<string name="producteev_PLA_title">Se Connecter à Producteev</string>
<string name="producteev_PLA_body">Connectez-vous avec votre compte Producteev existant, ou créez un nouveau compte !</string>
<string name="producteev_PLA_terms">Termes Et Conditions</string>
<string name="producteev_PLA_signIn">S\'identifier</string>
<string name="producteev_PLA_createNew">Créer un nouvel utilisateur</string>
<string name="producteev_PLA_email">E-mail</string>
<string name="producteev_PLA_password">Mot de passe</string>
<string name="producteev_PLA_timezone">Fuseau horaire</string>
<string name="producteev_PLA_firstName">Prénom</string>
<string name="producteev_PLA_lastName">Nom</string>
<string name="producteev_PLA_errorEmpty">Erreur : remplissez tous les champs !</string>
<string name="producteev_PLA_errorAuth">Erreur: E-mail ou mot de passe incorrect!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">Tâche attribuée Producteev</string>
<string name="producteev_TEA_task_assign_label">Attribuer cette tâche à cette personne :</string>
<string name="producteev_TEA_dashboard_assign_label">Attribuer cette tâche à cet espace de travail :</string>
<string name="CFC_producteev_in_workspace_text">Dans l\'espace de travail : ?</string>
<string name="CFC_producteev_in_workspace_name">Dans l\'espace de travail...</string>
<string name="CFC_producteev_assigned_to_text">Attribué à : ?</string>
<string name="CFC_producteev_assigned_to_name">Attribué à...</string>
<string name="TEA_reminders_group_label">Rappels</string>
<string name="TEA_reminder_label">Rappel moi :</string>
<string name="TEA_reminder_due">... lorsque la tâche est échue</string>

@ -474,34 +474,6 @@
<string name="EPr_statistics_title">Statistiche Anomime Utilizzo</string>
<string name="EPr_statistics_desc_disabled">Nessun dato verrà inviato</string>
<string name="EPr_statistics_desc_enabled">Aiutaci a migliorare Astrid inviando informazioni anonime sull\'utilizzo</string>
<string name="producteev_FEx_dashboard">Aree di lavoro</string>
<string name="producteev_FEx_responsible_byme">Assegnato a</string>
<string name="producteev_FEx_responsible_title">Assegnato a \'%s\'</string>
<string name="producteev_PDE_task_from">da %s</string>
<string name="producteev_TEA_notes">Aggiungi un Commento</string>
<string name="producteev_default_dashboard">Spazio di lavoro predefinito</string>
<string name="producteev_no_dashboard">Non Sincronizzare</string>
<string name="producteev_create_dashboard">Aggiungi un nuovo Spazio di Lavoro...</string>
<string name="producteev_create_dashboard_name">Nome per il nuovo Spazio di Lavoro</string>
<string name="producteev_PPr_defaultdash_title">Spazio di lavoro predefinito</string>
<string name="producteev_PPr_defaultdash_summary">Le nuove attività verranno aggiunte a: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Le nuove attività non verranno sincronizzate in modo predefinito</string>
<string name="producteev_PLA_title">Accedi a Producteev</string>
<string name="producteev_PLA_body">Entra con il tuo account Producteev, o registra un nuovo account!</string>
<string name="producteev_PLA_terms">Termini &amp; Condizioni</string>
<string name="producteev_PLA_signIn">Accedi</string>
<string name="producteev_PLA_createNew">Crea Nuovo Utente</string>
<string name="producteev_PLA_timezone">Fuso orario</string>
<string name="producteev_PLA_firstName">Nome</string>
<string name="producteev_PLA_lastName">Cognome</string>
<string name="producteev_PLA_errorEmpty">Errore: riempi tutti i campi!</string>
<string name="producteev_PLA_errorAuth">Errore: e-mail o password sbagliate!</string>
<string name="producteev_TEA_task_assign_label">Assegna questa attività alla persona seguente:</string>
<string name="producteev_TEA_dashboard_assign_label">Assegna questa attività a questo spazio di lavoro:</string>
<string name="CFC_producteev_in_workspace_text">Nello spazio di lavoro: ?</string>
<string name="CFC_producteev_in_workspace_name">Nello spazio di lavoro...</string>
<string name="CFC_producteev_assigned_to_text">Assegnato a: ?</string>
<string name="CFC_producteev_assigned_to_name">Assegnato a...</string>
<string name="TEA_reminder_label">Ricordami...</string>
<string name="TEA_reminder_due">... quando l\'attività deve terminare</string>
<string name="TEA_reminder_overdue">... quando l\'attività è in ritardo</string>

@ -625,41 +625,6 @@
<string name="premium_description_2">סינכרון קבצים עם אתר astrid.com</string>
<string name="premium_login_prompt">יש צורך בחשבון באתר astrid.com כדי להרשם לגירסת הפרימיום. אנא התחבר או הרשם.</string>
<string name="premium_success_with_server_error">תודה על ההרשמה לאסטריד פרימיום! התכונות החדשות תיפתחנה לשימוש באתר astrid.com בקרוב, ותהיינה זמינות בטלפון שלך מיידית.</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">משטחי עבודה</string>
<string name="producteev_FEx_responsible_byme">הטלתי על</string>
<string name="producteev_FEx_responsible_byothers">הוטלו עלי</string>
<string name="producteev_FEx_responsible_title">הוטל על \'%s\'</string>
<string name="producteev_PDE_task_from">מ- %s</string>
<string name="producteev_TEA_notes">הוסף הערה</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">משטח עבודה ברירת מחדל</string>
<string name="producteev_no_dashboard">(אל תסנכרן)</string>
<string name="producteev_create_dashboard">הוסף משטח עבודה חדש...</string>
<string name="producteev_create_dashboard_name">שם של משטח עבודה חדש...</string>
<string name="producteev_PPr_defaultdash_title">ברירת מחדל של משטח עבודה</string>
<string name="producteev_PPr_defaultdash_summary">משימות חדשות תתווספנה ל־%s</string>
<string name="producteev_PPr_defaultdash_summary_none">משימות חדשות לא תסתנכרנה באופן אוטומטי</string>
<string name="producteev_PLA_title">Producteev התחבר ל</string>
<string name="producteev_PLA_body">התחבר באמצעות חשבון ה־Producteev שלך או צור חשבון חדש!</string>
<string name="producteev_PLA_terms">תנאים והתניות</string>
<string name="producteev_PLA_signIn">התחבר</string>
<string name="producteev_PLA_createNew">צור משתמש חדש</string>
<string name="producteev_PLA_email">דוא״ל</string>
<string name="producteev_PLA_password">סיסמא</string>
<string name="producteev_PLA_timezone">איזור זמן</string>
<string name="producteev_PLA_firstName">שם פרטי</string>
<string name="producteev_PLA_lastName">שם משפחה</string>
<string name="producteev_PLA_errorEmpty">שגיאה: אנא מלא את כל השדות!</string>
<string name="producteev_PLA_errorAuth">שגיאה: כתובת דוא״ל או סיסמא אינם נכונים!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">הטלת משימה של Producteev</string>
<string name="producteev_TEA_task_assign_label">הטל משימה זו על אדם זה:</string>
<string name="producteev_TEA_dashboard_assign_label">הצב משימה זו במשטח עבודה:</string>
<string name="CFC_producteev_in_workspace_text">במשטח עבודה: ?</string>
<string name="CFC_producteev_in_workspace_name">במשטח עבודה...</string>
<string name="CFC_producteev_assigned_to_text">הוטל על: ?</string>
<string name="CFC_producteev_assigned_to_name">הוטל על...</string>
<string name="TEA_reminders_group_label">תזכורות</string>
<string name="TEA_reminder_label">הזכר לי:</string>
<string name="TEA_reminder_due">כאשר הגיע מועד הסף</string>

@ -352,14 +352,6 @@
<string name="EPr_statistics_title">匿名の使用統計データ</string>
<string name="EPr_statistics_desc_disabled">使用統計情報は送信されません</string>
<string name="EPr_statistics_desc_enabled">送られた使用統計情報は Astrid の改善に使用されます</string>
<string name="producteev_PLA_title">Producteev にログイン</string>
<string name="producteev_PLA_body">既存の Producteev アカウントにサインインするか、アカウントを作成してください</string>
<string name="producteev_PLA_signIn">サインイン</string>
<string name="producteev_PLA_email">メールアドレス</string>
<string name="producteev_PLA_password">パスワード</string>
<string name="producteev_PLA_timezone">タイムゾーン</string>
<string name="producteev_PLA_errorEmpty">エラー: すべての入力欄を入力してください</string>
<string name="producteev_PLA_errorAuth">エラー: メールアドレスかパスワードが正しくありません</string>
<string name="TEA_reminder_label">通知するのは...</string>
<string name="TEA_reminder_due">期限になったとき</string>
<string name="TEA_reminder_overdue">期限を過ぎたとき</string>

@ -710,41 +710,6 @@
<string name="premium_verification_error">이 구글 플레이 계정으로 구매한 프리미엄 이용권은 다른 사용자에게 연결되어 있습니다. 당신의 계정에 추가적인 이메일을 연결하려면 astrid.com/users/profile 을 방문하세요.</string>
<string name="premium_check_for_purchases">프리미엄을 이미 구매하셨나요? 구글 플레이에서 구매 내역을 확인하려면 여기를 클릭하세요</string>
<string name="premium_checking_for_purchases">구매 확인 중...</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">작업공간</string>
<string name="producteev_FEx_responsible_byme">내가 할당한 사람:</string>
<string name="producteev_FEx_responsible_byothers">다른 사람이 할당한 사람:</string>
<string name="producteev_FEx_responsible_title">할당됨: \'%s\'</string>
<string name="producteev_PDE_task_from">from %s</string>
<string name="producteev_TEA_notes">댓글 달기</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">기본 작업공간</string>
<string name="producteev_no_dashboard">(싱크 중지)</string>
<string name="producteev_create_dashboard">새로운 작업공간 추가...</string>
<string name="producteev_create_dashboard_name">새로운 작업공간 이름</string>
<string name="producteev_PPr_defaultdash_title">기본 작업공간</string>
<string name="producteev_PPr_defaultdash_summary">새 일정 추가장소: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">새 일정은 기본적으로 동기화되지 않습니다</string>
<string name="producteev_PLA_title">Producteev 로그인 하기</string>
<string name="producteev_PLA_body">Producteev 계정으로 로그인 하시거나 새로운 계정을 만드세요!</string>
<string name="producteev_PLA_terms">계약 조건</string>
<string name="producteev_PLA_signIn">로그인</string>
<string name="producteev_PLA_createNew">새 사용자 생성</string>
<string name="producteev_PLA_email">이메일</string>
<string name="producteev_PLA_password">비밀번호</string>
<string name="producteev_PLA_timezone">표준시간대</string>
<string name="producteev_PLA_firstName">이름</string>
<string name="producteev_PLA_lastName"></string>
<string name="producteev_PLA_errorEmpty">에러: 모든 항목을 입력하세요!</string>
<string name="producteev_PLA_errorAuth">에러: 이메일이나 비밀번호가 맞지 않습니다!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">Producteev 일정</string>
<string name="producteev_TEA_task_assign_label">이 일정을 다음 사람에 할당:</string>
<string name="producteev_TEA_dashboard_assign_label">이 일정을 다음 작업공간에 할당:</string>
<string name="CFC_producteev_in_workspace_text">작업공간에: ?</string>
<string name="CFC_producteev_in_workspace_name">작업공간...</string>
<string name="CFC_producteev_assigned_to_text">할당된 사람: ?</string>
<string name="CFC_producteev_assigned_to_name">할당된 사람...</string>
<string name="TEA_reminders_group_label">알림</string>
<string name="TEA_reminder_label">알려주세요:</string>
<string name="TEA_reminder_due">완료일이 되었을 때</string>

@ -289,35 +289,6 @@
<string name="CFC_opencrx_assigned_to_name">Tildelt...</string>
<string name="EPr_statistics_desc_disabled">Ingen bruksdata vil bli rapportert</string>
<string name="EPr_statistics_desc_enabled">Hjelp oss å forbedre Astrid ved å sende anonym bruksdata</string>
<string name="producteev_FEx_dashboard">Arbeidsområder</string>
<string name="producteev_FEx_responsible_title">Tildelt til \'%s\'</string>
<string name="producteev_PDE_task_from">fra %s</string>
<string name="producteev_TEA_notes">Legg til kommentar</string>
<string name="producteev_default_dashboard">Standart arbeidsområde</string>
<string name="producteev_no_dashboard">(Ikke synkroniser)</string>
<string name="producteev_create_dashboard">Legg til nytt arbeidsområde</string>
<string name="producteev_create_dashboard_name">Navn for nytt arbeidsområde</string>
<string name="producteev_PPr_defaultdash_title">Standart arbeidsområde</string>
<string name="producteev_PPr_defaultdash_summary">Nye oppgaver legges til: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Nye oppgaver synkroniseres ikke automatisk</string>
<string name="producteev_PLA_title">Logg inn på Producteev</string>
<string name="producteev_PLA_body">Logg inn med din Producteev-konto eller opprett en ny konto!</string>
<string name="producteev_PLA_terms">Brukervilkår</string>
<string name="producteev_PLA_signIn">Logg inn</string>
<string name="producteev_PLA_createNew">Lag ny bruker</string>
<string name="producteev_PLA_email">E-post</string>
<string name="producteev_PLA_password">Passord</string>
<string name="producteev_PLA_timezone">Tidssone</string>
<string name="producteev_PLA_firstName">Fornavn</string>
<string name="producteev_PLA_lastName">Etternavn</string>
<string name="producteev_PLA_errorEmpty">Feil: Alle felt må fylles ut!</string>
<string name="producteev_PLA_errorAuth">Feil: feil e-post eller passord!</string>
<string name="producteev_TEA_task_assign_label">Tildel følgende person denne oppgaven:</string>
<string name="producteev_TEA_dashboard_assign_label">Legg oppgaven til dette arbeidsområdet:</string>
<string name="CFC_producteev_in_workspace_text">I arbeidsområde:?</string>
<string name="CFC_producteev_in_workspace_name">I arbeidsområde...</string>
<string name="CFC_producteev_assigned_to_text">Tildelt: ?</string>
<string name="CFC_producteev_assigned_to_name">Tildelt...</string>
<string name="TEA_reminder_label">Minn meg på...</string>
<string name="TEA_reminder_due">...når oppgaven forfaller</string>
<string name="TEA_reminder_overdue">... når oppgaven har forfalt</string>

@ -620,41 +620,6 @@
<string name="file_err_copy">Fout bij kopiëren toe te voegen bestand</string>
<string name="file_err_download">Fout bij downloaden bestand</string>
<string name="file_err_show">Sorry, het systeem ondersteunt dit bestandstype niet</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">Werkbladen</string>
<string name="producteev_FEx_responsible_byme">Ook aan mij toegewezen</string>
<string name="producteev_FEx_responsible_byothers">Ook aan anderen toegewezen</string>
<string name="producteev_FEx_responsible_title">Toegewezen Aan \'%s\'</string>
<string name="producteev_PDE_task_from">van %s</string>
<string name="producteev_TEA_notes">Commentaar toevoegen</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">Standaard Workspace</string>
<string name="producteev_no_dashboard">(Niet synchroniseren)</string>
<string name="producteev_create_dashboard">Nieuwe Workspace toevoegen...</string>
<string name="producteev_create_dashboard_name">Naam voor nieuwe Workspace</string>
<string name="producteev_PPr_defaultdash_title">Standaard Workspace</string>
<string name="producteev_PPr_defaultdash_summary">Nieuwe taken worden toegevoegd aan: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Nieuwe taken worden standaard niet gesynchroniseerd</string>
<string name="producteev_PLA_title">Aanmelden bij Producteev</string>
<string name="producteev_PLA_body">Meld je aan bij Producteev met je bestaande gegevens of maak een nieuw account aan.</string>
<string name="producteev_PLA_terms">Algemene Voorwaarden</string>
<string name="producteev_PLA_signIn">Aanmelden</string>
<string name="producteev_PLA_createNew">Maak gebruikersaccount</string>
<string name="producteev_PLA_email">E-mail</string>
<string name="producteev_PLA_password">Wachtwoord</string>
<string name="producteev_PLA_timezone">Tijdzone</string>
<string name="producteev_PLA_firstName">Voornaam</string>
<string name="producteev_PLA_lastName">Achternaam</string>
<string name="producteev_PLA_errorEmpty">Fout: vul alle velden in!</string>
<string name="producteev_PLA_errorAuth">Fout: e-mail of wachtwoord verkeerd ingevuld!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">Producteev Toewijzing</string>
<string name="producteev_TEA_task_assign_label">Taak aan deze persoon toewijzen:</string>
<string name="producteev_TEA_dashboard_assign_label">Taak aan deze Workspace toewijzen:</string>
<string name="CFC_producteev_in_workspace_text">In Workspace: ?</string>
<string name="CFC_producteev_in_workspace_name">In Workspace...</string>
<string name="CFC_producteev_assigned_to_text">Toegewezen aan: ?</string>
<string name="CFC_producteev_assigned_to_name">Toegewezen aan...</string>
<string name="TEA_reminders_group_label">Herinneringen</string>
<string name="TEA_reminder_label">Herinneren:</string>
<string name="TEA_reminder_due">op einddatum taak</string>

@ -620,37 +620,6 @@
<string name="premium_description_2">Synchronizuj pliki z astrid.com</string>
<string name="premium_description_3">Dodaj załączniki przez email</string>
<string name="premium_description_4">Zapisz notatki głosowe jako pliki audio</string>
<string name="producteev_FEx_dashboard">Obszary robocze</string>
<string name="producteev_FEx_responsible_byme">Przydzielone przeze mnie</string>
<string name="producteev_FEx_responsible_byothers">Przydzielone przez innych też</string>
<string name="producteev_FEx_responsible_title">Przypisany do \'%s\'</string>
<string name="producteev_PDE_task_from">od %s</string>
<string name="producteev_TEA_notes">Dodaj komentarz</string>
<string name="producteev_default_dashboard">Domyślny obszar roboczy</string>
<string name="producteev_no_dashboard">(Nie synchronizuj)</string>
<string name="producteev_create_dashboard">Dodaj nowy obszar roboczy...</string>
<string name="producteev_create_dashboard_name">Nazwa nowego obszaru roboczego</string>
<string name="producteev_PPr_defaultdash_title">Domyślny obszar roboczy</string>
<string name="producteev_PPr_defaultdash_summary">Nowe zadania będą dodawane do %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Nowe zadania nie będą domyślnie synchronizowane</string>
<string name="producteev_PLA_title">Zaloguj do Producteev</string>
<string name="producteev_PLA_body">Zaloguj się używając aktualnego konta Producteev lub utwórz nowe!</string>
<string name="producteev_PLA_terms">Zasady &amp; Warunki</string>
<string name="producteev_PLA_signIn">Zaloguj się</string>
<string name="producteev_PLA_createNew">Utwórz nowego użytkownika</string>
<string name="producteev_PLA_email">Adres e-mail</string>
<string name="producteev_PLA_password">Hasło</string>
<string name="producteev_PLA_timezone">Strefa czasowa</string>
<string name="producteev_PLA_firstName">Imię</string>
<string name="producteev_PLA_lastName">Nazwisko</string>
<string name="producteev_PLA_errorEmpty">Błąd: wypełnij wszystkie pola!</string>
<string name="producteev_PLA_errorAuth">Błąd: e-mail lub hasło niepoprawne!</string>
<string name="producteev_TEA_task_assign_label">Przypisz to zadanie do tej osoby:</string>
<string name="producteev_TEA_dashboard_assign_label">Przypisz to zadanie do tego obszaru roboczego:</string>
<string name="CFC_producteev_in_workspace_text">W grupie roboczej: ?</string>
<string name="CFC_producteev_in_workspace_name">W grupie roboczej...</string>
<string name="CFC_producteev_assigned_to_text">Przypisany do: ?</string>
<string name="CFC_producteev_assigned_to_name">Przypisany do...</string>
<string name="TEA_reminders_group_label">Przypomnienia</string>
<string name="TEA_reminder_label">Przypomnij mi:</string>
<string name="TEA_reminder_due">Jeśli zadanie jest wynikiem</string>

@ -690,41 +690,6 @@
<string name="premium_success">Obrigado por se inscrever no Astrid Premium!</string>
<string name="premium_success_with_server_error">Obrigado por assinar o Astrid Premium! Os novos recursos serão desbloqueados para você em astrid.com em breve e devem estar disponíveis em seu telefone imediatamente.</string>
<string name="premium_verification_error">A assinatura premium para esta conta Google Play está conectada com um usuário diferente. Para conectar e-mails adicionais em sua conta, visite http://astrid.com/users/profile</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">Espaços de trabalho</string>
<string name="producteev_FEx_responsible_byme">Atribuído por mim com</string>
<string name="producteev_FEx_responsible_byothers">Atribuído por outras pessoas para</string>
<string name="producteev_FEx_responsible_title">Atribuído a \'%s\'</string>
<string name="producteev_PDE_task_from">de %s</string>
<string name="producteev_TEA_notes">Inserir comentário</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">Área de trabalho padrão</string>
<string name="producteev_no_dashboard">(Não Sincronizar)</string>
<string name="producteev_create_dashboard">Inserir novo espaço de trabalho</string>
<string name="producteev_create_dashboard_name">Nome para novo espaço de trabalho</string>
<string name="producteev_PPr_defaultdash_title">Área de trabalho padrão</string>
<string name="producteev_PPr_defaultdash_summary">Novas tarefas serão inseridas em: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Novas tarefas não serão sincronizadas por padrão</string>
<string name="producteev_PLA_title">Logar-se ao Producteev</string>
<string name="producteev_PLA_body">Entrar com uma conta Producteev existente, ou criar uma nova conta!</string>
<string name="producteev_PLA_terms">Termos &amp; Condições</string>
<string name="producteev_PLA_signIn">Entrar</string>
<string name="producteev_PLA_createNew">Criar Novo Usuário</string>
<string name="producteev_PLA_email">E-mail</string>
<string name="producteev_PLA_password">Senha</string>
<string name="producteev_PLA_timezone">Fuso horário</string>
<string name="producteev_PLA_firstName">Primeiro Nome</string>
<string name="producteev_PLA_lastName">Sobrenome</string>
<string name="producteev_PLA_errorEmpty">Erro: preencha todos os campos!</string>
<string name="producteev_PLA_errorAuth">Erro: E-mail ou senha incorreta!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">Atribuição Producteev</string>
<string name="producteev_TEA_task_assign_label">Atribuir essa tarefa a esta pessoa:</string>
<string name="producteev_TEA_dashboard_assign_label">Atribuir essa tarefa a esta área de trabalho:</string>
<string name="CFC_producteev_in_workspace_text">Na área de trabalho: ?</string>
<string name="CFC_producteev_in_workspace_name">Na área de trabalho...</string>
<string name="CFC_producteev_assigned_to_text">Atribuído a:?</string>
<string name="CFC_producteev_assigned_to_name">Atribuído a ...</string>
<string name="TEA_reminders_group_label">Lembretes</string>
<string name="TEA_reminder_label">Lembre me:</string>
<string name="TEA_reminder_due">no dia que a tarefa vencer</string>

@ -705,41 +705,6 @@
<string name="premium_success">Спасибо за то, что подписались на Astrid Premium!</string>
<string name="premium_success_with_server_error">Спасибо за то, что оформили премиум подписку на Astrid! Новые возможности на astrid.com разблокируются в ближайшее время, на Вашем телефоне они должны быть доступны уже сейчас.</string>
<string name="premium_verification_error">Премиум подписка для этой учетной записи Google Play оформлена на другого пользователя. Привязать дополнительный email к своей учетной записи можно здесь: astrid.com/users/profile</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">Рабочие области</string>
<string name="producteev_FEx_responsible_byme">Назначено мною</string>
<string name="producteev_FEx_responsible_byothers">Назначено другими</string>
<string name="producteev_FEx_responsible_title">Ответственный \'%s\'</string>
<string name="producteev_PDE_task_from">от %s</string>
<string name="producteev_TEA_notes">Добавить комментарий</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">Рабочая среда по умолчанию</string>
<string name="producteev_no_dashboard">(Не синхронизировано)</string>
<string name="producteev_create_dashboard">Добавить новую рабочую среду</string>
<string name="producteev_create_dashboard_name">Имя новой рабочей среды</string>
<string name="producteev_PPr_defaultdash_title">Рабочая среда по умолчанию</string>
<string name="producteev_PPr_defaultdash_summary">Добавлять новые задачи в %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Новые задачи не будут синхонизированы по умолчанию</string>
<string name="producteev_PLA_title">Войти в Producteev</string>
<string name="producteev_PLA_body">Войдите в Producteev, используя существующую учётную запись, или создайте новую учётную запись!</string>
<string name="producteev_PLA_terms">Условия использования</string>
<string name="producteev_PLA_signIn">Войти</string>
<string name="producteev_PLA_createNew">Создать нового пользователя</string>
<string name="producteev_PLA_email">Электронная почта</string>
<string name="producteev_PLA_password">Пароль</string>
<string name="producteev_PLA_timezone">Часовой пояс</string>
<string name="producteev_PLA_firstName">Имя</string>
<string name="producteev_PLA_lastName">Фамилия</string>
<string name="producteev_PLA_errorEmpty">Ошибка: заполните все поля!</string>
<string name="producteev_PLA_errorAuth">Ошибка: неправильная почта или пароль!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">Назначение Producteev</string>
<string name="producteev_TEA_task_assign_label">Назначить эту задачу этому человеку:</string>
<string name="producteev_TEA_dashboard_assign_label">Назначить эту задачу для этой рабочей области:</string>
<string name="CFC_producteev_in_workspace_text">в среде: ?</string>
<string name="CFC_producteev_in_workspace_name">в среде...</string>
<string name="CFC_producteev_assigned_to_text">Присвоено: ?</string>
<string name="CFC_producteev_assigned_to_name">Присвоено ...</string>
<string name="TEA_reminders_group_label">Напоминания</string>
<string name="TEA_reminder_label">Напомнить мне:</string>
<string name="TEA_reminder_due">… при наступлении срока задания</string>

@ -553,41 +553,6 @@
<string name="EPr_statistics_title">Anonym användningsstatistik</string>
<string name="EPr_statistics_desc_disabled">Inga användningsdata rapporteras</string>
<string name="EPr_statistics_desc_enabled">Hjälp oss att förbättra Astrid genom att skicka anonym användningsstatistik</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">Arbetsytor</string>
<string name="producteev_FEx_responsible_byme">Tilldelad</string>
<string name="producteev_FEx_responsible_byothers">Tilldelad av andra till</string>
<string name="producteev_FEx_responsible_title">Tilldelad \'%s\'</string>
<string name="producteev_PDE_task_from">från %s</string>
<string name="producteev_TEA_notes">Lägg till en kommentar</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">Standardarbetsytan</string>
<string name="producteev_no_dashboard">(synkronisera inte)</string>
<string name="producteev_create_dashboard">Lägg till ny arbetsyta</string>
<string name="producteev_create_dashboard_name">Namn till ny arbetsyta</string>
<string name="producteev_PPr_defaultdash_title">Standardarbetsytan</string>
<string name="producteev_PPr_defaultdash_summary">Nya uppgifter läggs till: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Nya uppgifter synkroniseras inte automatiskt</string>
<string name="producteev_PLA_title">Logga in till Producteev</string>
<string name="producteev_PLA_body">Logga in med ditt nuvarande Producteev-konto, eller skapa ett nytt konto!</string>
<string name="producteev_PLA_terms">Användarvillkor</string>
<string name="producteev_PLA_signIn">Logga in</string>
<string name="producteev_PLA_createNew">Skapa ny användare</string>
<string name="producteev_PLA_email">E-post</string>
<string name="producteev_PLA_password">Lösenord</string>
<string name="producteev_PLA_timezone">Tidszon</string>
<string name="producteev_PLA_firstName">Förnamn</string>
<string name="producteev_PLA_lastName">Efternamn</string>
<string name="producteev_PLA_errorEmpty">Fel: fyll i alla fält!</string>
<string name="producteev_PLA_errorAuth">Fel: fel e-post eller lösenord!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">Uppgift i Producteev</string>
<string name="producteev_TEA_task_assign_label">Tilldela denna uppgift följande person:</string>
<string name="producteev_TEA_dashboard_assign_label">Tilldela denna uppgift följande arbetsyta:</string>
<string name="CFC_producteev_in_workspace_text">I arbetsyta: ?</string>
<string name="CFC_producteev_in_workspace_name">I arbetsyta...</string>
<string name="CFC_producteev_assigned_to_text">Tilldelad: ?</string>
<string name="CFC_producteev_assigned_to_name">Tilldelad...</string>
<string name="TEA_reminders_group_label">Påminnelser</string>
<string name="TEA_reminder_due">...när uppgiften förfaller</string>
<string name="TEA_reminder_overdue">...när uppgiften har förfallit</string>

@ -233,34 +233,6 @@
<string name="CFC_opencrx_assigned_to_text">มอบหมายให้: ?</string>
<string name="CFC_opencrx_assigned_to_name">มอบหมายให้...</string>
<string name="EPr_statistics_desc_disabled">ไม่มีข้อมูลการใช้งานที่จะรายงาน</string>
<string name="producteev_FEx_dashboard">พื้นที่ทำงาน</string>
<string name="producteev_FEx_responsible_byme">มอบหมายให้กับ</string>
<string name="producteev_FEx_responsible_title">มอบหมายให้กับ \'%s\'</string>
<string name="producteev_PDE_task_from">จาก %s</string>
<string name="producteev_TEA_notes">เพิ่มความคิดเห็น</string>
<string name="producteev_default_dashboard">พื้นที่ทำงานตั้งต้น</string>
<string name="producteev_create_dashboard">เพิ่มพื้นที่ทำงานใหม่</string>
<string name="producteev_create_dashboard_name">ชื่อของพื้นที่ทำงานใหม่</string>
<string name="producteev_PPr_defaultdash_title">พื้นที่ทำงานตั้งต้น</string>
<string name="producteev_PPr_defaultdash_summary">แผนงานใหม่จะถูกเพิ่มไปยัง: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">แผนงานใหม่จะไม่ถูกเชื่อมโยงข้อมูลตามค่าตั้งต้น</string>
<string name="producteev_PLA_title">เข้าใช้งาน Producteev</string>
<string name="producteev_PLA_body">เข้าสู่ระบบโดยบัญชี Producteev ที่มีอยู่, หรือสร้างบัญชีใหม่</string>
<string name="producteev_PLA_signIn">เข้าสู่ระบบ</string>
<string name="producteev_PLA_createNew">สร้างผู้ใช้งานใหม่</string>
<string name="producteev_PLA_email">อี-เมล์</string>
<string name="producteev_PLA_password">รหัสผ่าน</string>
<string name="producteev_PLA_timezone">เขตเวลา</string>
<string name="producteev_PLA_firstName">ชื่อจริง</string>
<string name="producteev_PLA_lastName">นามสกุล</string>
<string name="producteev_PLA_errorEmpty">ข้อผิดพลาด: เติมให้ครบทุกช่อง</string>
<string name="producteev_PLA_errorAuth">ข้อผิดพลาด: อีเมล์หรือรหัสผ่าน ไม่ถูกต้อง</string>
<string name="producteev_TEA_task_assign_label">มอบหมายแผนงานนี้ให้กับบุคคลนี้:</string>
<string name="producteev_TEA_dashboard_assign_label">มอบหมายแผนงานนี้ให้กับพื้นที่ทำงานนี้:</string>
<string name="CFC_producteev_in_workspace_text">ในพื้นที่ทำงาน: ?</string>
<string name="CFC_producteev_in_workspace_name">ในพื้นที่ทำงาน...</string>
<string name="CFC_producteev_assigned_to_text">มอบหมายให้: ?</string>
<string name="CFC_producteev_assigned_to_name">มอบหมายให้...</string>
<string-array name="TEA_reminder_random">
<item>an hour</item>
<item>a day</item>

@ -683,41 +683,6 @@
<string name="premium_success">Astrid Premium üyesi olduğunuz için teşekkür ederiz!</string>
<string name="premium_success_with_server_error">Astrid Premium üyesi olduğunuz için teşekkür ederiz! Yeni özelliker sizin için yakında astrid.com\'da açılacak ve hemen telefonunuzda kullanabileceksiniz.</string>
<string name="premium_verification_error">Premium üyelik, bu Google Play hesabı için başka bir kullanıcıya bağlı görünüyor. Hesabınıza ek e-postalar için ziyaret edin: astrid.com/users/profile</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">Çalışma Alanları</string>
<string name="producteev_FEx_responsible_byme">Tarafımdan şu kişiye atandı:</string>
<string name="producteev_FEx_responsible_byothers">Diğerleri tarafından şu kişiye atandı:</string>
<string name="producteev_FEx_responsible_title">Atandı: \'%s\'</string>
<string name="producteev_PDE_task_from">%s\'den</string>
<string name="producteev_TEA_notes">ıklama Ekle</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">Varsayılan Çalışma Alanı</string>
<string name="producteev_no_dashboard">(Eşleştirme Yapma)</string>
<string name="producteev_create_dashboard">Yeni Çalışma Alanı ekle</string>
<string name="producteev_create_dashboard_name">Çalışma Alanı adı</string>
<string name="producteev_PPr_defaultdash_title">Varsayılan Çalışma Alanı</string>
<string name="producteev_PPr_defaultdash_summary">Yeni görevler şuraya kaydedilecek: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">Yeni görevler öntanımlı olarak eşleştirilmeyecek</string>
<string name="producteev_PLA_title">Producteev\'e giriş yap</string>
<string name="producteev_PLA_body">Mevcut Producteev hesabı ile giriş yap</string>
<string name="producteev_PLA_terms">Şartlar &amp; Koşullar</string>
<string name="producteev_PLA_signIn">Giriş Yap</string>
<string name="producteev_PLA_createNew">Yeni Kullanıcı Oluştur</string>
<string name="producteev_PLA_email">E-Posta</string>
<string name="producteev_PLA_password">Parola</string>
<string name="producteev_PLA_timezone">Zaman dilimi</string>
<string name="producteev_PLA_firstName">Ad</string>
<string name="producteev_PLA_lastName">Soyad</string>
<string name="producteev_PLA_errorEmpty">Hata: bütün alanları doldurun!</string>
<string name="producteev_PLA_errorAuth">Hata: e-posta ya da şifre hatalı!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">Producteev Görevleri</string>
<string name="producteev_TEA_task_assign_label">Bu görevi şu kişiye ata:</string>
<string name="producteev_TEA_dashboard_assign_label">Bu görevi şu çalışma alanına ata:</string>
<string name="CFC_producteev_in_workspace_text">Çalışma alanında: ?</string>
<string name="CFC_producteev_in_workspace_name">Çalışma alanında...</string>
<string name="CFC_producteev_assigned_to_text">Atandı: ?</string>
<string name="CFC_producteev_assigned_to_name">Atandı...</string>
<string name="TEA_reminders_group_label">Hatırlatmalar</string>
<string name="TEA_reminder_label">Bana Hatırlat:</string>
<string name="TEA_reminder_due">Görev son tarihinde</string>

@ -669,41 +669,6 @@
<string name="premium_login_prompt">为了成功购买高级版本您需要一个Astrid.com的账户。 请在我们的网站上登录或者注册。</string>
<string name="premium_success">谢谢购买清单小助理高级版本(Astrid Premium)</string>
<string name="premium_verification_error">此Google Play 帐户的高级版本正与另一个用户连接。访问astrid.com/users/profile并连接您帐户的另一个电子邮箱。</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">任务区</string>
<string name="producteev_FEx_responsible_byme">指派给</string>
<string name="producteev_FEx_responsible_byothers">由他人分配给</string>
<string name="producteev_FEx_responsible_title">指派给 \'%s\'</string>
<string name="producteev_PDE_task_from">来自 %s</string>
<string name="producteev_TEA_notes">新增注释</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">预设任务区</string>
<string name="producteev_no_dashboard">(不要同步)</string>
<string name="producteev_create_dashboard">新增任务区</string>
<string name="producteev_create_dashboard_name">命名新任务区</string>
<string name="producteev_PPr_defaultdash_title">预设任务区</string>
<string name="producteev_PPr_defaultdash_summary">新任务将加入: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">新任务预设将不会执行同步</string>
<string name="producteev_PLA_title">登录到 Producteev</string>
<string name="producteev_PLA_body">使用 Producteev 帐号登陆或建立新帐号!</string>
<string name="producteev_PLA_terms">条款及条件</string>
<string name="producteev_PLA_signIn">登陆</string>
<string name="producteev_PLA_createNew">新建使用者</string>
<string name="producteev_PLA_email">电子邮件</string>
<string name="producteev_PLA_password">密码</string>
<string name="producteev_PLA_timezone">时区</string>
<string name="producteev_PLA_firstName">名字</string>
<string name="producteev_PLA_lastName">姓氏</string>
<string name="producteev_PLA_errorEmpty">错误: 所有字段需要填写!</string>
<string name="producteev_PLA_errorAuth">错误: 电子邮件或密码不正确!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">Producteev 任务分配系统</string>
<string name="producteev_TEA_task_assign_label">指派任务给此人:</string>
<string name="producteev_TEA_dashboard_assign_label">指派任务给此任务区:</string>
<string name="CFC_producteev_in_workspace_text">在任务区: ?</string>
<string name="CFC_producteev_in_workspace_name">在任务区...</string>
<string name="CFC_producteev_assigned_to_text">指派给:?</string>
<string name="CFC_producteev_assigned_to_name">指派给...</string>
<string name="TEA_reminders_group_label">提醒</string>
<string name="TEA_reminder_label">提醒我:</string>
<string name="TEA_reminder_due">当任务到期时</string>

@ -672,41 +672,6 @@
<string name="premium_success">謝謝購買Astrid Premium</string>
<string name="premium_success_with_server_error">謝謝購買Astrid Premium新的特點將會很快在astrid.com發布並且在您的手機裡立刻得到更新。</string>
<string name="premium_verification_error">此Google Play 帳戶的高級版本正與另一個用戶連接。訪問astrid.com/users/profile並連接您帳戶的另一個電子郵箱。</string>
<string name="producteev_FEx_header">Producteev</string>
<string name="producteev_FEx_dashboard">工作區</string>
<string name="producteev_FEx_responsible_byme">指派給</string>
<string name="producteev_FEx_responsible_byothers">由他人分配給</string>
<string name="producteev_FEx_responsible_title">指派給 \'%s\'</string>
<string name="producteev_PDE_task_from">來自 %s</string>
<string name="producteev_TEA_notes">新增註解</string>
<string name="producteev_PPr_header">Producteev</string>
<string name="producteev_default_dashboard">預設工作區</string>
<string name="producteev_no_dashboard">不要同步</string>
<string name="producteev_create_dashboard">新增工作區</string>
<string name="producteev_create_dashboard_name">命名新工作區</string>
<string name="producteev_PPr_defaultdash_title">預設工作區</string>
<string name="producteev_PPr_defaultdash_summary">新工作將加入: %s</string>
<string name="producteev_PPr_defaultdash_summary_none">新工作預設將不會執行同步</string>
<string name="producteev_PLA_title">登入Producteev</string>
<string name="producteev_PLA_body">使用Producteev帳號登入或建立新帳號!</string>
<string name="producteev_PLA_terms">條款及條件</string>
<string name="producteev_PLA_signIn">登入</string>
<string name="producteev_PLA_createNew">新建使用者</string>
<string name="producteev_PLA_email">電子郵件</string>
<string name="producteev_PLA_password">密碼</string>
<string name="producteev_PLA_timezone">時區</string>
<string name="producteev_PLA_firstName">名字</string>
<string name="producteev_PLA_lastName">姓氏</string>
<string name="producteev_PLA_errorEmpty">錯誤: 所有欄位需要填寫!</string>
<string name="producteev_PLA_errorAuth">錯誤: 電子郵件或密碼不正確!</string>
<string name="producteev_notification_title">Producteev</string>
<string name="producteev_TEA_control_set_display">Producteev 任務工作分配系統</string>
<string name="producteev_TEA_task_assign_label">指派工作給此人:</string>
<string name="producteev_TEA_dashboard_assign_label">指派工作給此工作區:</string>
<string name="CFC_producteev_in_workspace_text">在工作區: ?</string>
<string name="CFC_producteev_in_workspace_name">在工作區...</string>
<string name="CFC_producteev_assigned_to_text">指派改: ?</string>
<string name="CFC_producteev_assigned_to_name">指派給...</string>
<string name="TEA_reminders_group_label">提醒</string>
<string name="TEA_reminder_label">提醒我:</string>
<string name="TEA_reminder_due">當任務工作到期時</string>

@ -409,13 +409,6 @@
<!-- Preference Key (do not translate) -->
<string name="rmilk_MPr_interval_key">sync_freq</string>
<!-- ======================================================= PRODUCTEEV == -->
<string name="producteev_PPr_interval_key">producteev_sync_freq</string>
<string name="producteev_PPr_email">producteev_email</string>
<string name="producteev_PPr_password">producteev_password</string>
<string name="producteev_PPr_defaultdash_key">producteev_defaultdash</string>
<!-- =========================================================== GTASKS == -->
<string name="gtasks_GPr_interval_key">gtasks_sync_freq</string>

@ -1,137 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
** Copyright (c) 2012 Todoroo Inc
**
** 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: Producteev -->
<string name="producteev_FEx_header">Producteev</string>
<!-- filter category for Producteev dashboards -->
<string name="producteev_FEx_dashboard">Workspaces</string>
<!-- filter category for Producteev responsible person -->
<string name="producteev_FEx_responsible_byme">Assigned by me to</string>
<!-- filter category for Producteev responsible person -->
<string name="producteev_FEx_responsible_byothers">Assigned by others to</string>
<!-- Producteev responsible filter title (%s => responsiblename) -->
<string name="producteev_FEx_responsible_title">Assigned To \'%s\'</string>
<!-- detail for showing tasks created by someone else (%s => person name) -->
<string name="producteev_PDE_task_from">from %s</string>
<!-- replacement string for task edit "Notes" when using Producteev -->
<string name="producteev_TEA_notes">Add a Comment</string>
<!-- ==================================================== Preferences == -->
<!-- Preferences Title: Producteev -->
<string name="producteev_PPr_header">Producteev</string>
<!-- dashboard title for producteev default dashboard -->
<string name="producteev_default_dashboard">Default Workspace</string>
<!-- dashboard title for tasks that are not synchronized -->
<string name="producteev_no_dashboard">(Do Not Synchronize)</string>
<!-- dashboard spinner entry on TEA for adding a new dashboard -->
<string name="producteev_create_dashboard">Add new Workspace...</string>
<!-- dashboard spinner entry on TEA for adding a new dashboard -->
<string name="producteev_create_dashboard_name">Name for new Workspace</string>
<!-- preference title for default dashboard -->
<string name="producteev_PPr_defaultdash_title">Default Workspace</string>
<!-- preference description for default dashboard (%s -> setting) -->
<string name="producteev_PPr_defaultdash_summary">New tasks will be added to: %s</string>
<!-- preference description for default dashboard (when set to 'not synchronized') -->
<string name="producteev_PPr_defaultdash_summary_none">New tasks will not be synchronized by default</string>
<!-- ================================================= Login Activity == -->
<!-- Activity Title: Producteev Login -->
<string name="producteev_PLA_title">Log In to Producteev</string>
<!-- Instructions: Producteev login -->
<string name="producteev_PLA_body">Sign in with your existing
Producteev account, or create a new account!</string>
<!-- Producteev Terms Link -->
<string name="producteev_PLA_terms">Terms &amp; Conditions</string>
<!-- Sign In Button -->
<string name="producteev_PLA_signIn">Sign In</string>
<!-- Create New User Button -->
<string name="producteev_PLA_createNew">Create New User</string>
<!-- E-mail Address Label -->
<string name="producteev_PLA_email">E-mail</string>
<!-- Password Label -->
<string name="producteev_PLA_password">Password</string>
<!-- Timezone Spinner -->
<string name="producteev_PLA_timezone">Timezone</string>
<!-- Confirm Password Label -->
<!-- First Name Label -->
<string name="producteev_PLA_firstName">First Name</string>
<!-- Last Name Label -->
<string name="producteev_PLA_lastName">Last Name</string>
<!-- Error Message when fields aren't filled out -->
<string name="producteev_PLA_errorEmpty">Error: fill out all fields!</string>
<!-- Error Message when passwords don't match -->
<!-- Error Message when we receive a HTTP 401 Unauthorized -->
<string name="producteev_PLA_errorAuth">Error: e-mail or password incorrect!</string>
<!-- ================================================ Synchronization == -->
<!-- title for notification tray after synchronizing -->
<string name="producteev_notification_title">Producteev</string>
<!-- text for notification tray when synchronizing -->
<!-- Error msg when io exception -->
<!-- Prod Login email not specified-->
<!-- Prod Login password not specified-->
<!-- ================================================ labels for layout-elements == -->
<!-- Label for Producteev control set row -->
<string name="producteev_TEA_control_set_display">Producteev Assignment</string>
<!-- label for task-assignment spinner on taskeditactivity -->
<string name="producteev_TEA_task_assign_label">Assign this task to this person:</string>
<!-- Spinner-item for unassigned tasks on taskeditactivity -->
<!-- label for dashboard-assignment spinner on taskeditactivity -->
<string name="producteev_TEA_dashboard_assign_label">Assign this task to this workspace:</string>
<!-- Spinner-item for default dashboard on taskeditactivity -->
<string name="CFC_producteev_in_workspace_text">In workspace: ?</string>
<string name="CFC_producteev_in_workspace_name">In workspace...</string>
<string name="CFC_producteev_assigned_to_text">Assigned to: ?</string>
<string name="CFC_producteev_assigned_to_name">Assigned to...</string>
</resources>

@ -1,321 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
** Copyright (c) 2012 Todoroo Inc
**
** See the file "LICENSE" for the full license governing this code.
-->
<resources>
<!-- list of allowed timezones for user-signup in producteev -->
<string-array name="PLA_timezones_list">
<item>Africa/Abidjan</item>
<item>Africa/Accra</item>
<item>Africa/Addis_Ababa</item>
<item>Africa/Algiers</item>
<item>Africa/Asmara</item>
<item>Africa/Bamako</item>
<item>Africa/Bangui</item>
<item>Africa/Banjul</item>
<item>Africa/Bissau</item>
<item>Africa/Blantyre</item>
<item>Africa/Brazzaville</item>
<item>Africa/Bujumbura</item>
<item>Africa/Cairo</item>
<item>Africa/Casablanca</item>
<item>Africa/Ceuta</item>
<item>Africa/Conakry</item>
<item>Africa/Dakar</item>
<item>Africa/Dar_es_Salaam</item>
<item>Africa/Djibouti</item>
<item>Africa/Douala</item>
<item>Africa/El_Aaiun</item>
<item>Africa/Freetown</item>
<item>Africa/Gaborone</item>
<item>Africa/Harare</item>
<item>Africa/Johannesburg</item>
<item>Africa/Kampala</item>
<item>Africa/Khartoum</item>
<item>Africa/Kigali</item>
<item>Africa/Kinshasa</item>
<item>Africa/Lagos</item>
<item>Africa/Libreville</item>
<item>Africa/Lome</item>
<item>Africa/Luanda</item>
<item>Africa/Lubumbashi</item>
<item>Africa/Lusaka</item>
<item>Africa/Malabo</item>
<item>Africa/Maputo</item>
<item>Africa/Maseru</item>
<item>Africa/Mbabane</item>
<item>Africa/Mogadishu</item>
<item>Africa/Monrovia</item>
<item>Africa/Nairobi</item>
<item>Africa/Ndjamena</item>
<item>Africa/Niamey</item>
<item>Africa/Nouakchott</item>
<item>Africa/Ouagadougou</item>
<item>Africa/Porto-Novo</item>
<item>Africa/Sao_Tome</item>
<item>Africa/Tripoli</item>
<item>Africa/Tunis</item>
<item>Africa/Windhoek</item>
<item>America/Anchorage</item>
<item>America/Anguilla</item>
<item>America/Antigua</item>
<item>America/Araguaina</item>
<item>America/Argentina/Buenos_Aires</item>
<item>America/Aruba</item>
<item>America/Asuncion</item>
<item>America/Bahia</item>
<item>America/Barbados</item>
<item>America/Belem</item>
<item>America/Belize</item>
<item>America/Boa_Vista</item>
<item>America/Bogota</item>
<item>America/Campo_Grande</item>
<item>America/Caracas</item>
<item>America/Cayenne</item>
<item>America/Cayman</item>
<item>America/Chicago</item>
<item>America/Costa_Rica</item>
<item>America/Cuiaba</item>
<item>America/Curacao</item>
<item>America/Danmarkshavn</item>
<item>America/Dawson_Creek</item>
<item>America/Denver</item>
<item>America/Dominica</item>
<item>America/Edmonton</item>
<item>America/El_Salvador</item>
<item>America/Fortaleza</item>
<item>America/Godthab</item>
<item>America/Grand_Turk</item>
<item>America/Grenada</item>
<item>America/Guadeloupe</item>
<item>America/Guatemala</item>
<item>America/Guayaquil</item>
<item>America/Guyana</item>
<item>America/Halifax</item>
<item>America/Havana</item>
<item>America/Hermosillo</item>
<item>America/Iqaluit</item>
<item>America/Jamaica</item>
<item>America/La_Paz</item>
<item>America/Lima</item>
<item>America/Los_Angeles</item>
<item>America/Maceio</item>
<item>America/Managua</item>
<item>America/Manaus</item>
<item>America/Martinique</item>
<item>America/Mazatlan</item>
<item>America/Mexico_City</item>
<item>America/Miquelon</item>
<item>America/Montevideo</item>
<item>America/Montreal</item>
<item>America/Montserrat</item>
<item>America/Nassau</item>
<item>America/New_York</item>
<item>America/Noronha</item>
<item>America/Panama</item>
<item>America/Paramaribo</item>
<item>America/Phoenix</item>
<item>America/Port_of_Spain</item>
<item>America/Port-au-Prince</item>
<item>America/Porto_Velho</item>
<item>America/Puerto_Rico</item>
<item>America/Recife</item>
<item>America/Regina</item>
<item>America/Rio_Branco</item>
<item>America/Santiago</item>
<item>America/Santo_Domingo</item>
<item>America/Sao_Paulo</item>
<item>America/Scoresbysund</item>
<item>America/St_Johns</item>
<item>America/St_Kitts</item>
<item>America/St_Lucia</item>
<item>America/St_Thomas</item>
<item>America/St_Vincent</item>
<item>America/Tegucigalpa</item>
<item>America/Thule</item>
<item>America/Tijuana</item>
<item>America/Toronto</item>
<item>America/Tortola</item>
<item>America/Vancouver</item>
<item>America/Whitehorse</item>
<item>America/Winnipeg</item>
<item>America/Yellowknife</item>
<item>Antarctica/Casey</item>
<item>Antarctica/Davis</item>
<item>Antarctica/DumontDUrville</item>
<item>Antarctica/Mawson</item>
<item>Antarctica/Palmer</item>
<item>Antarctica/Rothera</item>
<item>Antarctica/Syowa</item>
<item>Antarctica/Vostok</item>
<item>Asia/Aden</item>
<item>Asia/Almaty</item>
<item>Asia/Amman</item>
<item>Asia/Aqtau</item>
<item>Asia/Aqtobe</item>
<item>Asia/Ashgabat</item>
<item>Asia/Baghdad</item>
<item>Asia/Bahrain</item>
<item>Asia/Baku</item>
<item>Asia/Bangkok</item>
<item>Asia/Beirut</item>
<item>Asia/Bishkek</item>
<item>Asia/Brunei</item>
<item>Asia/Calcutta</item>
<item>Asia/Choibalsan</item>
<item>Asia/Colombo</item>
<item>Asia/Damascus</item>
<item>Asia/Dhaka</item>
<item>Asia/Dili</item>
<item>Asia/Dubai</item>
<item>Asia/Dushanbe</item>
<item>Asia/Gaza</item>
<item>Asia/Hong_Kong</item>
<item>Asia/Hovd</item>
<item>Asia/Irkutsk</item>
<item>Asia/Jakarta</item>
<item>Asia/Jayapura</item>
<item>Asia/Jerusalem</item>
<item>Asia/Kabul</item>
<item>Asia/Kamchatka</item>
<item>Asia/Karachi</item>
<item>Asia/Katmandu</item>
<item>Asia/Krasnoyarsk</item>
<item>Asia/Kuala_Lumpur</item>
<item>Asia/Kuwait</item>
<item>Asia/Macau</item>
<item>Asia/Magadan</item>
<item>Asia/Makassar</item>
<item>Asia/Manila</item>
<item>Asia/Muscat</item>
<item>Asia/Nicosia</item>
<item>Asia/Omsk</item>
<item>Asia/Phnom_Penh</item>
<item>Asia/Pyongyang</item>
<item>Asia/Qatar</item>
<item>Asia/Rangoon</item>
<item>Asia/Riyadh</item>
<item>Asia/Saigon</item>
<item>Asia/Seoul</item>
<item>Asia/Shanghai</item>
<item>Asia/Singapore</item>
<item>Asia/Taipei</item>
<item>Asia/Tashkent</item>
<item>Asia/Tbilisi</item>
<item>Asia/Tehran</item>
<item>Asia/Thimphu</item>
<item>Asia/Tokyo</item>
<item>Asia/Ulaanbaatar</item>
<item>Asia/Vientiane</item>
<item>Asia/Vladivostok</item>
<item>Asia/Yakutsk</item>
<item>Asia/Yekaterinburg</item>
<item>Asia/Yerevan</item>
<item>Atlantic/Azores</item>
<item>Atlantic/Bermuda</item>
<item>Atlantic/Canary</item>
<item>Atlantic/Cape_Verde</item>
<item>Atlantic/Faroe</item>
<item>Atlantic/Reykjavik</item>
<item>Atlantic/South_Georgia</item>
<item>Atlantic/St_Helena</item>
<item>Atlantic/Stanley</item>
<item>Australia/Adelaide</item>
<item>Australia/Brisbane</item>
<item>Australia/Darwin</item>
<item>Australia/Hobart</item>
<item>Australia/Perth</item>
<item>Australia/Sydney</item>
<item>Etc/GMT</item>
<item>Europe/Amsterdam</item>
<item>Europe/Andorra</item>
<item>Europe/Athens</item>
<item>Europe/Belgrade</item>
<item>Europe/Berlin</item>
<item>Europe/Brussels</item>
<item>Europe/Bucharest</item>
<item>Europe/Budapest</item>
<item>Europe/Chisinau</item>
<item>Europe/Copenhagen</item>
<item>Europe/Dublin</item>
<item>Europe/Gibraltar</item>
<item>Europe/Helsinki</item>
<item>Europe/Istanbul</item>
<item>Europe/Kaliningrad</item>
<item>Europe/Kiev</item>
<item>Europe/Lisbon</item>
<item>Europe/London</item>
<item>Europe/Luxembourg</item>
<item>Europe/Madrid</item>
<item>Europe/Malta</item>
<item>Europe/Minsk</item>
<item>Europe/Monaco</item>
<item>Europe/Moscow</item>
<item>Europe/Oslo</item>
<item>Europe/Paris</item>
<item>Europe/Prague</item>
<item>Europe/Riga</item>
<item>Europe/Rome</item>
<item>Europe/Samara</item>
<item>Europe/Sofia</item>
<item>Europe/Stockholm</item>
<item>Europe/Tallinn</item>
<item>Europe/Tirane</item>
<item>Europe/Vaduz</item>
<item>Europe/Vienna</item>
<item>Europe/Vilnius</item>
<item>Europe/Warsaw</item>
<item>Europe/Zurich</item>
<item>Indian/Antananarivo</item>
<item>Indian/Chagos</item>
<item>Indian/Christmas</item>
<item>Indian/Cocos</item>
<item>Indian/Comoro</item>
<item>Indian/Kerguelen</item>
<item>Indian/Mahe</item>
<item>Indian/Maldives</item>
<item>Indian/Mauritius</item>
<item>Indian/Mayotte</item>
<item>Indian/Reunion</item>
<item>Pacific/Apia</item>
<item>Pacific/Auckland</item>
<item>Pacific/Easter</item>
<item>Pacific/Efate</item>
<item>Pacific/Enderbury</item>
<item>Pacific/Fakaofo</item>
<item>Pacific/Fiji</item>
<item>Pacific/Funafuti</item>
<item>Pacific/Galapagos</item>
<item>Pacific/Gambier</item>
<item>Pacific/Guadalcanal</item>
<item>Pacific/Guam</item>
<item>Pacific/Honolulu</item>
<item>Pacific/Johnston</item>
<item>Pacific/Kiritimati</item>
<item>Pacific/Kosrae</item>
<item>Pacific/Kwajalein</item>
<item>Pacific/Majuro</item>
<item>Pacific/Marquesas</item>
<item>Pacific/Midway</item>
<item>Pacific/Nauru</item>
<item>Pacific/Niue</item>
<item>Pacific/Norfolk</item>
<item>Pacific/Noumea</item>
<item>Pacific/Pago_Pago</item>
<item>Pacific/Palau</item>
<item>Pacific/Pitcairn</item>
<item>Pacific/Ponape</item>
<item>Pacific/Port_Moresby</item>
<item>Pacific/Rarotonga</item>
<item>Pacific/Saipan</item>
<item>Pacific/Tahiti</item>
<item>Pacific/Tarawa</item>
<item>Pacific/Tongatapu</item>
<item>Pacific/Truk</item>
<item>Pacific/Wake</item>
<item>Pacific/Wallis</item>
<item>US/Eastern</item>
</string-array>
</resources>

@ -1,47 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
** Copyright (c) 2012 Todoroo Inc
**
** See the file "LICENSE" for the full license governing this code.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="@string/sync_SPr_group_status"
android:title="@string/sync_SPr_group_status">
<com.todoroo.astrid.ui.MultilinePreference
android:layout="@layout/status_preference"
android:key="@string/sync_SPr_status_key"
android:textSize="24sp"
android:gravity="center"/>
<com.todoroo.astrid.ui.MultilinePreference
android:key="@string/sync_SPr_key_last_error"
android:textSize="24sp"
android:gravity="center"/>
</PreferenceCategory>
<PreferenceCategory
android:key="@string/sync_SPr_key_options"
android:title="@string/sync_SPr_group_options">
<com.todoroo.astrid.ui.MultilineListPreference
android:key="@string/producteev_PPr_interval_key"
android:entries="@array/sync_SPr_interval_entries"
android:entryValues="@array/sync_SPr_interval_values"
android:title="@string/sync_SPr_interval_title" />
<com.todoroo.astrid.ui.MultilineListPreference
android:key="@string/producteev_PPr_defaultdash_key"
android:title="@string/producteev_PPr_defaultdash_title" />
<com.todoroo.astrid.ui.MultilinePreference
android:key="@string/sync_SPr_forget_key"
android:title="@string/sync_SPr_forget"
android:summary="@string/sync_SPr_forget_description" />
</PreferenceCategory>
</PreferenceScreen>

@ -55,8 +55,6 @@ import com.todoroo.astrid.files.FileExplore;
import com.todoroo.astrid.gcal.CalendarStartupReceiver;
import com.todoroo.astrid.gtasks.GtasksPreferences;
import com.todoroo.astrid.helper.MetadataHelper;
import com.todoroo.astrid.producteev.ProducteevPreferences;
import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.service.AddOnService;
import com.todoroo.astrid.service.MarketStrategy.AmazonMarketStrategy;
import com.todoroo.astrid.service.StartupService;
@ -362,10 +360,6 @@ public class EditPreferences extends TodorooPreferenceActivity {
&& AmazonMarketStrategy.isKindleFire())
continue;
if (ProducteevPreferences.class.getName().equals(resolveInfo.activityInfo.name)
&& !Preferences.getBoolean(R.string.p_third_party_addons, false) && !ProducteevUtilities.INSTANCE.isLoggedIn())
continue;
Preference preference = new Preference(this);
preference.setTitle(resolveInfo.activityInfo.loadLabel(pm));
Bundle metadata = resolveInfo.activityInfo.metaData;

@ -83,8 +83,6 @@ import com.todoroo.astrid.helper.TaskEditControlSet;
import com.todoroo.astrid.notes.EditNoteActivity;
import com.todoroo.astrid.opencrx.OpencrxControlSet;
import com.todoroo.astrid.opencrx.OpencrxCoreUtils;
import com.todoroo.astrid.producteev.ProducteevControlSet;
import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.reminders.Notifications;
import com.todoroo.astrid.repeats.RepeatControlSet;
import com.todoroo.astrid.service.AddOnService;
@ -589,20 +587,6 @@ ViewPager.OnPageChangeListener, EditNoteActivity.UpdatesChangedListener {
controls.add(filesControlSet);
controlSetMap.put(getString(R.string.TEA_ctrl_files_pref), filesControlSet);
try {
if (ProducteevUtilities.INSTANCE.isLoggedIn()) {
ProducteevControlSet producteevControl = new ProducteevControlSet(
getActivity(), R.layout.control_set_producteev,
R.layout.control_set_default_display,
R.string.producteev_TEA_control_set_display);
controls.add(producteevControl);
basicControls.addView(producteevControl.getDisplayView());
notesEditText.setHint(R.string.producteev_TEA_notes);
}
} catch (Exception e) {
Log.e("astrid-error", "loading-control-set", e); //$NON-NLS-1$ //$NON-NLS-2$
}
try {
if (OpencrxCoreUtils.INSTANCE.isLoggedIn()) {
OpencrxControlSet ocrxControl = new OpencrxControlSet(

@ -39,8 +39,6 @@ import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.SyncAction;
import com.todoroo.astrid.gtasks.GtasksPreferences;
import com.todoroo.astrid.producteev.ProducteevPreferences;
import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.service.MarketStrategy.AmazonMarketStrategy;
import com.todoroo.astrid.service.SyncV2Service;
import com.todoroo.astrid.sync.SyncResultCallback;
@ -212,11 +210,6 @@ public class SyncActionHelper {
&& AmazonMarketStrategy.isKindleFire())
continue;
if (ProducteevPreferences.class.getName().equals(
resolveInfo.activityInfo.name)
&& !ProducteevUtilities.INSTANCE.isLoggedIn() && !Preferences.getBoolean(R.string.p_third_party_addons, false))
continue;
if (resolveInfo.activityInfo.metaData != null) {
Bundle metadata = resolveInfo.activityInfo.metaData;
if (!metadata.getBoolean("syncAction")) //$NON-NLS-1$

@ -111,7 +111,7 @@ public class AddOnService {
* Get one AddOn-descriptor by packageName and title.
*
* @param packageName could be Constants.PACKAGE or one of AddOnService-constants
* @param title the descriptive title, as in "Producteev" or "Astrid Power Pack"
* @param title the descriptive title, as in "Astrid Power Pack"
* @return the addon-descriptor, if it is available (registered here in getAddOns), otherwise null
*/
public AddOn getAddOn(String packageName, String title) {

@ -132,7 +132,6 @@ public class AstridDependencyInjector extends AbstractDependencyInjector {
// these make reference to fields defined above
injectables.put("errorReporters", new ErrorReporter[] {
new AndroidLogReporter(),
new FlurryReporter()
});
}

@ -1,54 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.service;
import java.io.PrintWriter;
import java.io.StringWriter;
import android.database.sqlite.SQLiteException;
import com.todoroo.andlib.service.ExceptionService.ErrorReporter;
import com.todoroo.astrid.producteev.api.ProducteevRestClient;
public class FlurryReporter implements ErrorReporter {
@SuppressWarnings("nls")
public void handleError(String name, Throwable error) {
if(error == null)
return;
String message = error.toString();
StringWriter writer = new StringWriter();
PrintWriter writerPrinter = new PrintWriter(writer);
error.printStackTrace(writerPrinter);
writerPrinter.flush();
writerPrinter.close();
String trace = writer.toString();
// shorten the string
trace = trace.substring(message.length());
trace = trace.replaceAll(ProducteevRestClient.class.getName(), "!pdvRest");
trace = trace.replaceAll("com.todoroo.bente", "!ctb");
trace = trace.replaceAll("com.todoroo.astrid", "!cta");
trace = trace.replaceAll("com.todoroo.android", "!ctc");
trace = trace.replaceAll("com.mdt.rtm", "!rtm");
trace = trace.replaceAll("android.database.sqlite", "!sqlite");
trace = trace.replaceAll("android", "!A");
trace = trace.replaceAll("database", "!db");
trace = trace.replaceAll("org.apache.harmony.xml.parsers", "!xmlp");
trace = trace.replaceAll(IllegalStateException.class.getName(), "IlStEx");
trace = trace.replaceAll(ClassCastException.class.getName(), "ClCaEx");
trace = trace.replaceAll(NullPointerException.class.getName(), "NPEx");
trace = trace.replaceAll(SQLiteException.class.getName(), "SqLiEx");
trace = trace.replaceAll(".java:", ":");
StatisticsService.reportError(name, message, trace);
}
}

@ -64,7 +64,6 @@ import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
import com.todoroo.astrid.opencrx.OpencrxCoreUtils;
import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.reminders.ReengagementService;
import com.todoroo.astrid.reminders.ReminderStartupReceiver;
import com.todoroo.astrid.service.abtesting.ABChooser;
@ -244,7 +243,6 @@ public class StartupService {
taskService.cleanup();
// if sync ongoing flag was set, clear it
ProducteevUtilities.INSTANCE.stopOngoing();
MilkUtilities.INSTANCE.stopOngoing();
gtasksPreferenceService.stopOngoing();
actFmPreferenceService.stopOngoing();

@ -58,8 +58,6 @@ public class StatisticsConstants {
public static final String ACTFM_TASK_SHARED = "actfm-task-shared";
public static final String TASK_ASSIGNED_EMAIL = "task-assigned-email";
public static final String TASK_ASSIGNED_PICKER = "task-assigned-picker";
public static final String PRODUCTEEV_LOGIN = "producteev-login";
public static final String PRODUCTEEV_SIGNUP = "producteev-signup";
public static final String TASK_SNOOZE = "task-snooze";
public static final String TASK_COMPLETED_API2 = "task-completed-api2";
public static final String TIMER_START = "timer-start";

@ -48,7 +48,6 @@ import com.todoroo.astrid.data.UserActivity;
import com.todoroo.astrid.gcal.GCalHelper;
import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.opencrx.OpencrxCoreUtils;
import com.todoroo.astrid.producteev.sync.ProducteevTask;
import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.tags.TaskToTagMetadata;
import com.todoroo.astrid.utility.TitleParser;
@ -201,8 +200,6 @@ public class TaskService {
if(GtasksMetadata.METADATA_KEY.equals(metadata.getValue(Metadata.KEY)))
metadata.setValue(GtasksMetadata.ID, ""); //$NON-NLS-1$
if(ProducteevTask.METADATA_KEY.equals(metadata.getValue(Metadata.KEY)))
metadata.setValue(ProducteevTask.ID, 0L);
if(MilkTaskFields.METADATA_KEY.equals(metadata.getValue(Metadata.KEY))) {
metadata.setValue(MilkTaskFields.TASK_ID, 0L);
metadata.setValue(MilkTaskFields.TASK_SERIES_ID, 0L);

@ -48,7 +48,6 @@ import com.todoroo.astrid.dao.StoreObjectDao;
import com.todoroo.astrid.dao.StoreObjectDao.StoreObjectCriteria;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.utility.Constants;
/**
@ -304,10 +303,7 @@ public class UpdateMessageService {
private boolean pluginConditionMatches(String plugin) {
// handle internal plugin specially
if(PLUGIN_PDV.equals(plugin)) {
return ProducteevUtilities.INSTANCE.isLoggedIn();
}
else if(PLUGIN_GTASKS.equals(plugin)) {
if(PLUGIN_GTASKS.equals(plugin)) {
return gtasksPreferenceService.isLoggedIn();
}
else if(PLUGIN_RMILK.equals(plugin)) {

@ -5,8 +5,6 @@
*/
package com.todoroo.astrid.service;
import java.util.Date;
import org.weloveastrid.rmilk.data.MilkNoteHelper;
import android.app.Activity;
@ -23,11 +21,9 @@ import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.Property.StringProperty;
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.Query;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
@ -42,7 +38,6 @@ import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.helper.DueDateTimeMigrator;
import com.todoroo.astrid.notes.NoteMetadata;
import com.todoroo.astrid.producteev.sync.ProducteevDataService;
import com.todoroo.astrid.service.abtesting.ABChooser;
import com.todoroo.astrid.subtasks.SubtasksMetadataMigration;
import com.todoroo.astrid.tags.TagCaseMigrator;
@ -740,12 +735,7 @@ public final class UpgradeService {
t.close();
TodorooCursor<Metadata> m = metadataService.query(Query.select(Metadata.PROPERTIES).
where(Criterion.or(Metadata.KEY.eq("producteev-note"),
Metadata.KEY.eq("rmilk-note"))));
StringProperty PDV_NOTE_ID = Metadata.VALUE1;
StringProperty PDV_NOTE_MESSAGE = Metadata.VALUE2;
LongProperty PDV_NOTE_CREATED = new LongProperty(Metadata.TABLE, Metadata.VALUE3.name);
where(Metadata.KEY.eq("rmilk-note")));
StringProperty RTM_NOTE_ID = Metadata.VALUE1;
StringProperty RTM_NOTE_TITLE = Metadata.VALUE2;
@ -764,25 +754,18 @@ public final class UpgradeService {
title = metadata.getValue(RTM_NOTE_TITLE);
created = metadata.getValue(RTM_NOTE_CREATED);
provider = MilkNoteHelper.PROVIDER;
} else {
id = metadata.getValue(PDV_NOTE_ID);
body = metadata.getValue(PDV_NOTE_MESSAGE);
created = metadata.getValue(PDV_NOTE_CREATED);
title = DateUtilities.getDateStringWithWeekday(ContextManager.getContext(),
new Date(created));
provider = ProducteevDataService.NOTE_PROVIDER;
metadata.setValue(Metadata.KEY, NoteMetadata.METADATA_KEY);
metadata.setValue(Metadata.CREATION_DATE, created);
metadata.setValue(NoteMetadata.BODY, body);
metadata.setValue(NoteMetadata.TITLE, title);
metadata.setValue(NoteMetadata.THUMBNAIL, null);
metadata.setValue(NoteMetadata.EXT_PROVIDER, provider);
metadata.setValue(NoteMetadata.EXT_ID, id);
metadata.clearValue(Metadata.ID);
metadataService.save(metadata);
}
metadata.setValue(Metadata.KEY, NoteMetadata.METADATA_KEY);
metadata.setValue(Metadata.CREATION_DATE, created);
metadata.setValue(NoteMetadata.BODY, body);
metadata.setValue(NoteMetadata.TITLE, title);
metadata.setValue(NoteMetadata.THUMBNAIL, null);
metadata.setValue(NoteMetadata.EXT_PROVIDER, provider);
metadata.setValue(NoteMetadata.EXT_ID, id);
metadata.clearValue(Metadata.ID);
metadataService.save(metadata);
}
m.close();
}

@ -18,8 +18,6 @@ import android.widget.ToggleButton;
import com.timsu.astrid.R;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.helper.TaskEditControlSet;
import com.todoroo.astrid.opencrx.OpencrxCoreUtils;
import com.todoroo.astrid.producteev.ProducteevUtilities;
/**
* Control Set for setting task importance
@ -61,10 +59,7 @@ public class ImportanceControlSet extends TaskEditControlSet {
}
private int getTextSize() {
if (ProducteevUtilities.INSTANCE.isLoggedIn())
return 14;
else
return 24;
return 24;
}
public Integer getImportance() {
@ -89,8 +84,6 @@ public class ImportanceControlSet extends TaskEditControlSet {
int min = Task.IMPORTANCE_MOST;
int max = Task.IMPORTANCE_LEAST;
if(ProducteevUtilities.INSTANCE.isLoggedIn() || OpencrxCoreUtils.INSTANCE.isLoggedIn())
max = 5;
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
@ -102,25 +95,16 @@ public class ImportanceControlSet extends TaskEditControlSet {
final ToggleButton button = new ToggleButton(activity);
LinearLayout.LayoutParams params;
int dimension;
if (ProducteevUtilities.INSTANCE.isLoggedIn()) {
dimension = 38;
} else {
dimension = 38;
}
int dimension = 38;
params = new LinearLayout.LayoutParams((int) (metrics.density * dimension), (int) (metrics.density * dimension));
usedWidth += dimension;
button.setLayoutParams(params);
StringBuilder label = new StringBuilder();
if(ProducteevUtilities.INSTANCE.isLoggedIn() || OpencrxCoreUtils.INSTANCE.isLoggedIn())
label.append(5 - i).append("\n\u2605"); //$NON-NLS-1$
else {
if (i == max)
label.append('\u25CB');
for(int j = Task.IMPORTANCE_LEAST - 1; j >= i; j--)
label.append('!');
}
if (i == max)
label.append('\u25CB');
for(int j = Task.IMPORTANCE_LEAST - 1; j >= i; j--)
label.append('!');
button.setTextColor(colors[i]);
button.setTextOff(label);

@ -49,11 +49,11 @@ import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.helper.AmazonRequestsHelper;
import com.todoroo.astrid.helper.AsyncImageView;
import com.todoroo.astrid.producteev.api.StringEscapeUtils;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.taskrabbit.TaskRabbitControlSet;
import com.todoroo.astrid.utility.Constants;
import com.todoroo.astrid.utility.StringEscapeUtils;
@SuppressWarnings("nls")
public class WebServicesView extends LinearLayout {

@ -75,9 +75,6 @@ public final class Constants {
/** Notification Manager id for locale */
public static final int NOTIFICATION_LOCALE = -3;
/** Notification Manager id for producteev notifications*/
public static final int NOTIFICATION_PRODUCTEEV_NOTIFICATIONS = -4;
/** Notification Manager id for astrid.com */
public static final int NOTIFICATION_ACTFM = -5;

@ -15,7 +15,7 @@
* limitations under the License.
*/
package com.todoroo.astrid.producteev.api;
package com.todoroo.astrid.utility;
import java.io.IOException;
import java.io.StringWriter;

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.todoroo.astrid.producteev.api;
package com.todoroo.astrid.utility;
import java.io.IOException;
import java.io.StringWriter;

@ -10,7 +10,6 @@ import java.util.Arrays;
import java.util.List;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.test.DatabaseTestCase;
public class QuickAddMarkupTest extends DatabaseTestCase {
@ -18,7 +17,6 @@ public class QuickAddMarkupTest extends DatabaseTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
ProducteevUtilities.INSTANCE.setToken(null);
}
public void testTags() {

@ -66,7 +66,6 @@ public class AstridTranslationTests extends TranslationTests {
contains(r, R.string.CFC_title_contains_text, failures, "?");
contains(r, R.string.CFC_importance_text, failures, "?");
contains(r, R.string.CFC_dueBefore_text, failures, "?");
contains(r, R.string.CFC_producteev_assigned_to_text, failures, "?");
}
});

Loading…
Cancel
Save