diff --git a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevBackgroundService.java b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevBackgroundService.java
index 761ab8301..97c65620a 100644
--- a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevBackgroundService.java
+++ b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevBackgroundService.java
@@ -1,128 +1,128 @@
-package com.todoroo.astrid.producteev;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.IBinder;
-import android.util.Log;
-
-import com.timsu.astrid.R;
-import com.todoroo.andlib.service.ContextManager;
-import com.todoroo.andlib.utility.DateUtilities;
-import com.todoroo.astrid.producteev.sync.ProducteevSyncProvider;
-import com.todoroo.astrid.utility.Preferences;
-
-/**
- * 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 Service {
-
- /** Minimum time before an auto-sync */
- private static final long AUTO_SYNC_MIN_OFFSET = 5*60*1000L;
-
- /** alarm identifier */
- public static final String SYNC_ACTION = "sync"; //$NON-NLS-1$
-
- // --- BroadcastReceiver abstract methods
-
- /** Receive the alarm - start the synchronize service! */
- @Override
- public void onStart(Intent intent, int startId) {
- if(SYNC_ACTION.equals(intent.getAction()))
- startSynchronization(this);
- }
-
- /** Start the actual synchronization */
- private void startSynchronization(Context context) {
- if(context == null || context.getResources() == null)
- return;
-
- ContextManager.setContext(context);
-
- if(ProducteevUtilities.INSTANCE.isOngoing())
- return;
-
- new ProducteevSyncProvider().synchronize(context);
- }
-
- // --- alarm management
-
- /**
- * Schedules repeating alarm for auto-synchronization
- */
- public static void scheduleService() {
- int syncFrequencySeconds = Preferences.getIntegerFromString(
- R.string.producteev_PPr_interval_key, -1);
- Context context = ContextManager.getContext();
- if(syncFrequencySeconds <= 0) {
- unscheduleService(context);
- return;
- }
-
- // figure out synchronization frequency
- long interval = 1000L * syncFrequencySeconds;
- long offset = computeNextSyncOffset(interval);
-
- // give a little padding
- offset = Math.max(offset, AUTO_SYNC_MIN_OFFSET);
-
- AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- PendingIntent pendingIntent = PendingIntent.getService(context, 0,
- createAlarmIntent(context), PendingIntent.FLAG_UPDATE_CURRENT);
-
- Log.i("Astrid", "Autosync set for " + offset / 1000 //$NON-NLS-1$ //$NON-NLS-2$
- + " seconds repeating every " + syncFrequencySeconds); //$NON-NLS-1$
-
- // cancel all existing
- am.cancel(pendingIntent);
-
- // schedule new
- am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + offset,
- interval, pendingIntent);
- }
-
-
- /**
- * Removes repeating alarm for auto-synchronization
- */
- private static void unscheduleService(Context context) {
- AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
- PendingIntent pendingIntent = PendingIntent.getService(context, 0,
- createAlarmIntent(context), PendingIntent.FLAG_UPDATE_CURRENT);
- am.cancel(pendingIntent);
- }
-
- /** Create the alarm intent */
- private static Intent createAlarmIntent(Context context) {
- Intent intent = new Intent(context, ProducteevBackgroundService.class);
- intent.setAction(SYNC_ACTION);
- return intent;
- }
-
- // --- utility methods
-
-
- private static long computeNextSyncOffset(long interval) {
- // figure out last synchronize time
- long lastSyncDate = ProducteevUtilities.INSTANCE.getLastSyncDate();
-
- // if user never synchronized, give them a full offset period before bg sync
- if(lastSyncDate != 0)
- return Math.max(0, lastSyncDate + interval - DateUtilities.now());
- else
- return interval;
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
-}
+package com.todoroo.astrid.producteev;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.util.Log;
+
+import com.timsu.astrid.R;
+import com.todoroo.andlib.service.ContextManager;
+import com.todoroo.andlib.utility.DateUtilities;
+import com.todoroo.astrid.producteev.sync.ProducteevSyncProvider;
+import com.todoroo.astrid.utility.Preferences;
+
+/**
+ * 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 Service {
+
+ /** Minimum time before an auto-sync */
+ private static final long AUTO_SYNC_MIN_OFFSET = 5*60*1000L;
+
+ /** alarm identifier */
+ public static final String SYNC_ACTION = "sync"; //$NON-NLS-1$
+
+ // --- BroadcastReceiver abstract methods
+
+ /** Receive the alarm - start the synchronize service! */
+ @Override
+ public void onStart(Intent intent, int startId) {
+ if(SYNC_ACTION.equals(intent.getAction()))
+ startSynchronization(this);
+ }
+
+ /** Start the actual synchronization */
+ private void startSynchronization(Context context) {
+ if(context == null || context.getResources() == null)
+ return;
+
+ ContextManager.setContext(context);
+
+ if(ProducteevUtilities.INSTANCE.isOngoing())
+ return;
+
+ new ProducteevSyncProvider().synchronize(context);
+ }
+
+ // --- alarm management
+
+ /**
+ * Schedules repeating alarm for auto-synchronization
+ */
+ public static void scheduleService() {
+ int syncFrequencySeconds = Preferences.getIntegerFromString(
+ R.string.producteev_PPr_interval_key, -1);
+ Context context = ContextManager.getContext();
+ if(syncFrequencySeconds <= 0) {
+ unscheduleService(context);
+ return;
+ }
+
+ // figure out synchronization frequency
+ long interval = 1000L * syncFrequencySeconds;
+ long offset = computeNextSyncOffset(interval);
+
+ // give a little padding
+ offset = Math.max(offset, AUTO_SYNC_MIN_OFFSET);
+
+ AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ PendingIntent pendingIntent = PendingIntent.getService(context, 0,
+ createAlarmIntent(context), PendingIntent.FLAG_UPDATE_CURRENT);
+
+ Log.i("Astrid", "Autosync set for " + offset / 1000 //$NON-NLS-1$ //$NON-NLS-2$
+ + " seconds repeating every " + syncFrequencySeconds); //$NON-NLS-1$
+
+ // cancel all existing
+ am.cancel(pendingIntent);
+
+ // schedule new
+ am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + offset,
+ interval, pendingIntent);
+ }
+
+
+ /**
+ * Removes repeating alarm for auto-synchronization
+ */
+ private static void unscheduleService(Context context) {
+ AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
+ PendingIntent pendingIntent = PendingIntent.getService(context, 0,
+ createAlarmIntent(context), PendingIntent.FLAG_UPDATE_CURRENT);
+ am.cancel(pendingIntent);
+ }
+
+ /** Create the alarm intent */
+ private static Intent createAlarmIntent(Context context) {
+ Intent intent = new Intent(context, ProducteevBackgroundService.class);
+ intent.setAction(SYNC_ACTION);
+ return intent;
+ }
+
+ // --- utility methods
+
+
+ private static long computeNextSyncOffset(long interval) {
+ // figure out last synchronize time
+ long lastSyncDate = ProducteevUtilities.INSTANCE.getLastSyncDate();
+
+ // if user never synchronized, give them a full offset period before bg sync
+ if(lastSyncDate != 0)
+ return Math.max(0, lastSyncDate + interval - DateUtilities.now());
+ else
+ return interval;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+}
diff --git a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevLoginActivity.java b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevLoginActivity.java
new file mode 100644
index 000000000..145d0c97c
--- /dev/null
+++ b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevLoginActivity.java
@@ -0,0 +1,145 @@
+/*
+ * ASTRID: Android's Simple Task Recording Dashboard
+ *
+ * Copyright (c) 2009 Tim Su
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package com.todoroo.astrid.producteev;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.timsu.astrid.R;
+import com.todoroo.andlib.service.Autowired;
+import com.todoroo.andlib.service.DependencyInjectionService;
+import com.todoroo.andlib.utility.DialogUtilities;
+
+/**
+ * This activity displays a WebView
that allows users to log in to
+ * the synchronization provider requested. A callback method determines whether
+ * their login was successful and therefore whether to dismiss the dialog.
+ *
+ * @author arne.jans
+ *
+ */
+public class ProducteevLoginActivity extends Activity {
+
+ @Autowired
+ DialogUtilities dialogUtilities;
+
+ // --- callback
+
+ /** Callback interface */
+ public interface SyncLoginCallback {
+ /**
+ * Verifies whether the user's login attempt was successful. Will be
+ * called off of the UI thread, use the handler to post messages.
+ *
+ * @return error string, or null if sync was successful
+ */
+ public String verifyLogin(Handler handler, String email, String password);
+ }
+
+ protected static SyncLoginCallback callback = null;
+
+ /** Sets callback method */
+ public static void setCallback(SyncLoginCallback newCallback) {
+ callback = newCallback;
+ }
+
+ // --- ui initialization
+
+ public ProducteevLoginActivity() {
+ super();
+ DependencyInjectionService.getInstance().inject(this);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.producteev_login_activity);
+
+ final EditText emailEditText = (EditText) findViewById(R.id.Poducteev_EMail_EditText);
+ final EditText passwordEditText = (EditText) findViewById(R.id.Producteev_Password_EditText);
+ Button cancel = (Button) findViewById(R.id.cancel);
+ Button login = (Button) findViewById(R.id.done);
+
+ login.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ final Handler handler = new Handler();
+
+ if (callback == null) {
+ finish();
+ return;
+ }
+
+ final String email = emailEditText.getText().toString();
+ final String password = passwordEditText.getText().toString();
+ if (email == null || email.length() == 0) {
+ // no email given
+ Toast.makeText(ProducteevLoginActivity.this,
+ R.string.producteev_MLA_email_empty,
+ Toast.LENGTH_LONG).show();
+ setResult(RESULT_CANCELED);
+ finish();
+ return;
+
+ }
+ if (password == null || password.length() == 0) {
+ // no password given
+ Toast.makeText(ProducteevLoginActivity.this,
+ R.string.producteev_MLA_password_empty,
+ Toast.LENGTH_LONG).show();
+ setResult(RESULT_CANCELED);
+ finish();
+ return;
+
+ }
+ new Thread(new Runnable() {
+ public void run() {
+ final String result = callback.verifyLogin(handler,
+ email, password);
+ if (result == null) {
+ finish();
+ } else {
+ // display the error
+ handler.post(new Runnable() {
+ public void run() {
+ dialogUtilities.okDialog(
+ ProducteevLoginActivity.this,
+ result, null);
+ }
+ });
+ }
+ }
+ }).start();
+ }
+ });
+
+ cancel.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/astrid/res/layout/producteev_login_activity.xml b/astrid/res/layout/producteev_login_activity.xml
new file mode 100644
index 000000000..153a5626f
--- /dev/null
+++ b/astrid/res/layout/producteev_login_activity.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+