Merge branch 'gtasks'

pull/14/head
Tim Su 15 years ago
commit d7f3108049

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.timsu.astrid"
android:versionName="3.4.0 (added EULA and option to turn off usage statistics)"
android:versionCode="162">
android:versionName="3.5.0-beta"
android:versionCode="163">
<!-- widgets, alarms, and services will break if Astrid is installed on SD card -->
<!-- android:installLocation="internalOnly"> -->
@ -53,7 +53,7 @@
android:minSdkVersion="3" />
<supports-screens />
<application android:icon="@drawable/icon"
<application android:icon="@drawable/icon" android:debuggable="true"
android:label="@string/app_name">
<!-- ====================================================== Activities = -->
@ -118,7 +118,19 @@
<!-- Activity for preferences -->
<activity android:name="com.todoroo.astrid.activity.EditPreferences" />
<!-- Activity that configures widget -->
<activity android:name="com.todoroo.astrid.widget.WidgetConfigActivity"
<activity android:name="com.todoroo.astrid.widget.TasksWidget$ConfigActivity"
android:theme="@style/Theme">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<activity android:name="com.todoroo.astrid.widget.PowerWidget42$ConfigActivity"
android:theme="@style/Theme">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<activity android:name="com.todoroo.astrid.widget.PowerWidget44$ConfigActivity"
android:theme="@style/Theme">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
@ -129,6 +141,7 @@
<receiver android:name="com.todoroo.astrid.reminders.Notifications" />
<!-- widgets -->
<receiver android:name="com.todoroo.astrid.widget.TasksWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
@ -136,6 +149,24 @@
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget_provider_info" />
</receiver>
<receiver android:name="com.todoroo.astrid.widget.PowerWidget44"
android:label="@string/PPW_widget_44_label"
android:icon="@drawable/icon_pp">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/power_widget_44_provider_info" />
</receiver>
<receiver android:name="com.todoroo.astrid.widget.PowerWidget42"
android:label="@string/PPW_widget_42_label"
android:icon="@drawable/icon_pp">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/power_widget_42_provider_info" />
</receiver>
<receiver android:name="com.todoroo.astrid.service.GlobalEventReceiver">
<intent-filter>
@ -146,8 +177,8 @@
<!-- ======================================================== Services = -->
<service android:name="com.todoroo.astrid.widget.TasksWidget$UpdateService" />
<service android:name="com.todoroo.astrid.widget.PowerWidget$UpdateService" />
<service android:name="com.todoroo.astrid.widget.PowerWidget42$UpdateService" />
<service android:name="com.todoroo.astrid.widget.PowerWidget44$UpdateService44" />
<service android:name="com.todoroo.astrid.widget.PowerWidget42$UpdateService42" />
<!-- ======================================================= Providers = -->
@ -214,7 +245,7 @@
</receiver>
<!-- gtasks -->
<!-- activity android:name="com.todoroo.astrid.gtasks.GtasksListActivity"
<activity android:name="com.todoroo.astrid.gtasks.GtasksListActivity"
android:windowSoftInputMode="stateHidden"
android:theme="@style/Theme">
<intent-filter>
@ -249,7 +280,7 @@
<action android:name="com.todoroo.astrid.REQUEST_SYNC_ACTIONS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver> -->
</receiver>
<!-- tags -->
<receiver android:name="com.todoroo.astrid.tags.TagsPlugin">

@ -3,11 +3,12 @@
*/
package com.todoroo.astrid.gtasks;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.AbstractModel;
@ -58,13 +59,9 @@ public class GtasksFilterExposer extends BroadcastReceiver {
GtasksMetadata.LIST_ID.eq(list.getValue(GtasksList.REMOTE_ID)))).orderBy(
Order.asc(Functions.cast(GtasksMetadata.ORDER, "INTEGER"))), //$NON-NLS-1$
values);
Intent intent = new Intent(ContextManager.getContext(), GtasksListActivity.class);
intent.putExtra(GtasksListActivity.TOKEN_LIST_ID, list.getValue(GtasksList.REMOTE_ID));
intent.putExtra(GtasksListActivity.TOKEN_FILTER, filter);
intent.setType(list.getValue(GtasksList.REMOTE_ID));
PendingIntent pendingIntent = PendingIntent.getActivity(ContextManager.getContext(),
0, intent, 0);
filter.intent = pendingIntent;
filter.customTaskList = new ComponentName(ContextManager.getContext(), GtasksListActivity.class);
filter.customExtras = new Bundle();
filter.customExtras.putString(GtasksListActivity.TOKEN_LIST_ID, list.getValue(GtasksList.REMOTE_ID));
return filter;
}

@ -235,12 +235,13 @@ public class GtasksSyncProvider extends SyncProvider<GtasksTaskContainer> {
gcm.authenticate(false);
} catch (GoogleLoginException e) {
Toast.makeText(activity, R.string.gtasks_login_error, Toast.LENGTH_LONG).show();
Log.e("gtasks", "login", e);
return;
} catch (IOException e) {
Toast.makeText(activity, R.string.SyP_ioerror, Toast.LENGTH_LONG).show();
Log.e("gtasks", "login", e);
}
String token = gcm.getToken();
System.err.println("got token " + token);
gtasksPreferenceService.setToken(token);
activity.startService(new Intent(SyncBackgroundService.SYNC_ACTION, null,
activity, GtasksBackgroundService.class));
@ -426,7 +427,8 @@ public class GtasksSyncProvider extends SyncProvider<GtasksTaskContainer> {
String remoteId = updateTaskHelper(local, null, createdTask);
gtasksTaskListUpdater.addRemoteTaskMapping(local.task.getId(), remoteId);
local.gtaskMetadata.setValue(GtasksMetadata.LIST_ID, remoteId);
local.gtaskMetadata.setValue(GtasksMetadata.ID, remoteId);
local.gtaskMetadata.setValue(GtasksMetadata.LIST_ID, list);
return local;
}

@ -1,73 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="1">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_above="@+id/footer"
android:orientation="vertical">
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:text="@string/PPW_color"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
<Spinner android:id="@+id/PPW_color"
android:drawSelectorOnTop="true" android:prompt="@string/PPW_color"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
<!--
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<CheckBox android:id="@+id/PPW_enable_calendar"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
<TextView android:text="@string/PPW_enable_calendar"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
-->
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<CheckBox android:id="@+id/PPW_disable_encouragements"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
<TextView android:text="@string/PPW_disable_encouragements"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_weight="1">
<TextView android:text="@string/PPW_filter"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
<!-- List -->
<ExpandableListView android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="100"
android:scrollbars="vertical"
android:cacheColorHint="#00000000"/>
</LinearLayout>
</LinearLayout>
<RelativeLayout android:id="@+id/footer"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:paddingTop="5dp" android:paddingBottom="3dp"
android:paddingLeft="3dp" android:paddingRight="3dp">
<Button android:id="@+id/ok"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@android:string/ok"/>
</RelativeLayout>
</RelativeLayout>

@ -4,8 +4,8 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/list_selector_background"
android:paddingTop="4dip"
android:paddingBottom="4dip"
android:paddingTop="2dip"
android:paddingBottom="2dip"
android:paddingLeft="4dip"
android:paddingRight="4dip"
android:orientation="vertical">
@ -27,7 +27,6 @@
android:layout_width="0dip"
android:layout_height="fill_parent"/>
<!-- grabber -->
<ImageView android:id="@+id/grabber"
android:layout_width="wrap_content"
@ -37,7 +36,7 @@
<LinearLayout android:id="@+id/taskText"
android:layout_width="fill_parent"
android:layout_height="42dip"
android:layout_height="fill_parent"
android:layout_weight="100"
android:gravity="center_vertical"
android:background="@android:drawable/list_selector_background"

@ -1,11 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- See the file "LICENSE" for the full license governing this code. -->
<!-- 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:background="@drawable/background_gradient">
<!-- header -->
<LinearLayout android:id="@+id/colors"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:text="@string/PPW_color"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Spinner
android:id="@+id/PPW_color"
android:drawSelectorOnTop="true"
android:prompt="@string/PPW_color"
android:entries="@array/PPW_colors"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<CheckBox
android:id="@+id/PPW_disable_encouragements"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/PPW_disable_encouragements" />
<!-- List -->
<ExpandableListView android:id="@android:id/list"
android:layout_width="fill_parent"

@ -18,8 +18,41 @@
<string name="PPW_past_due">Past Due:</string>
<string-array name="PPW_encouragements">
<item>Ready to work?</item>
<!-- general encouragements -->
<item>Hi there!</item>
<item>Have time to finish something?</item>
<item>Gosh, you are looking suave today!</item>
<item>Do something great today!</item>
<item>Make me proud today!</item>
<item>How are you doing today?</item>
</string-array>
<string-array name="PPW_encouragements_tod">
<!-- encouragements based on time of day -->
<item>Good morning!</item>
<item>Good afternoon!</item>
<item>Good evening!</item>
<item>Late night?</item>
<item>It\s early, get something done!</item>
<item>Afternoon tea, perhaps?</item>
<item>Enjoy the evening!</item>
<item>Sleep is good for you, you know!</item>
</string-array>
<string-array name="PPW_encouragements_completed">
<!-- encouragements based on tasks completed (%d => completed) -->
<item>You\'ve already completed %d tasks!</item>
<item>Score in life: %d tasks completed</item>
<item>Smile! You\'ve already finished %d tasks!</item>
</string-array>
<string name="PPW_encouragements_completed"></string>
<string-array name="PPW_colors">
<item>Black</item>
<item>White</item>
<item>Blue</item>
<item>Red</item>
</string-array>
</resources>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:configure="com.todoroo.astrid.widget.ConfigurePowerWidget42Activity"
android:configure="com.todoroo.astrid.widget.PowerWidget42$ConfigActivity"
android:minWidth="294dip"
android:minHeight="146dip"
android:updatePeriodMillis="86400000"

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:configure="com.todoroo.astrid.widget.ConfigurePowerWidgetActivity"
android:configure="com.todoroo.astrid.widget.PowerWidget44$ConfigActivity"
android:minWidth="294dip"
android:minHeight="294dip"
android:updatePeriodMillis="86400000"

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:configure="com.todoroo.astrid.widget.WidgetConfigActivity"
android:configure="com.todoroo.astrid.widget.TasksWidget$ConfigActivity"
android:minWidth="142dip"
android:minHeight="142dip"
android:updatePeriodMillis="86400000"

@ -7,8 +7,10 @@ import java.util.concurrent.atomic.AtomicReference;
import android.app.ListActivity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnTouchListener;
import android.widget.TextView;
import com.commonsware.cwac.tlv.TouchListView;
@ -79,6 +81,14 @@ public class DraggableTaskListActivity extends TaskListActivity {
registerForContextMenu(getListView());
loadTaskListContent(false);
getTouchListView().setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
taskAdapter.clearSelection();
return false;
}
});
}
public Property<?>[] getProperties() {

@ -5,8 +5,8 @@ package com.todoroo.astrid.activity;
import android.app.AlertDialog;
import android.app.ExpandableListActivity;
import android.app.PendingIntent.CanceledException;
import android.app.SearchManager;
import android.app.PendingIntent.CanceledException;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
@ -18,22 +18,21 @@ import android.net.Uri;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.TextView.OnEditorActionListener;
import com.todoroo.astrid.service.StatisticsService;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
@ -50,7 +49,7 @@ import com.todoroo.astrid.api.IntentFilter;
import com.todoroo.astrid.core.SearchFilter;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.utility.Constants;
import com.todoroo.astrid.service.StatisticsService;
/**
* Activity that displays a user's task lists and allows users
@ -204,17 +203,14 @@ public class FilterListActivity extends ExpandableListActivity {
protected boolean onItemClicked(FilterListItem item) {
if(item instanceof Filter) {
Filter filter = (Filter)item;
Intent intent = new Intent(FilterListActivity.this, TaskListActivity.class);
intent.putExtra(TaskListActivity.TOKEN_FILTER, filter);
if(filter instanceof FilterWithCustomIntent) {
try {
((FilterWithCustomIntent)filter).intent.send();
} catch (CanceledException e) {
// we won't do anything in this case
}
} else {
Intent intent = new Intent(FilterListActivity.this, TaskListActivity.class);
intent.putExtra(TaskListActivity.TOKEN_FILTER, filter);
startActivity(intent);
FilterWithCustomIntent customFilter = ((FilterWithCustomIntent)filter);
intent.setComponent(customFilter.customTaskList);
intent.getExtras().putAll(customFilter.customExtras);
}
startActivity(intent);
AndroidUtilities.callApiMethod(5, this, "overridePendingTransition", //$NON-NLS-1$
new Class<?>[] { Integer.TYPE, Integer.TYPE },
R.anim.slide_left_in, R.anim.slide_left_out);

@ -22,6 +22,7 @@ package com.todoroo.astrid.activity;
import java.util.Map.Entry;
import android.app.Activity;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Intent;
import android.os.Bundle;
@ -31,6 +32,7 @@ import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterWithCustomIntent;
import com.todoroo.astrid.data.Task;
/**
@ -60,6 +62,8 @@ public class ShortcutActivity extends Activity {
/** token for passing a {@link Filter}'s values for new tasks through extras as exploded ContentValues */
public static final String TOKEN_FILTER_VALUES_ITEM = "v4ntp_"; //$NON-NLS-1$
/** token for passing a ComponentNameto launch */
public static final String TOKEN_CUSTOM_CLASS = "class"; //$NON-NLS-1$
// --- implementation
@ -80,6 +84,13 @@ public class ShortcutActivity extends Activity {
private void launchTaskList(Intent intent) {
Bundle extras = intent.getExtras();
Intent taskListIntent = new Intent(this, TaskListActivity.class);
if(extras != null && extras.containsKey(TOKEN_CUSTOM_CLASS)) {
taskListIntent.setComponent(ComponentName.unflattenFromString(extras.getString(TOKEN_CUSTOM_CLASS)));
taskListIntent.putExtras(intent.getExtras());
}
if(extras != null && extras.containsKey(TOKEN_FILTER_SQL)) {
// launched from desktop shortcut, must create a fake filter
String title = extras.getString(TOKEN_FILTER_TITLE);
@ -111,19 +122,18 @@ public class ShortcutActivity extends Activity {
}
Filter filter = new Filter("", title, sql, values); //$NON-NLS-1$
Intent taskListIntent = new Intent(this, TaskListActivity.class);
taskListIntent.putExtra(TaskListActivity.TOKEN_FILTER, filter);
startActivity(taskListIntent);
} else if(extras != null && extras.containsKey(TOKEN_SINGLE_TASK)) {
Filter filter = new Filter("", getString(R.string.TLA_custom), //$NON-NLS-1$
new QueryTemplate().where(Task.ID.eq(extras.getLong(TOKEN_SINGLE_TASK, -1))), null);
Intent taskListIntent = new Intent(this, TaskListActivity.class);
taskListIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
taskListIntent.putExtra(TaskListActivity.TOKEN_FILTER, filter);
startActivity(taskListIntent);
}
startActivity(taskListIntent);
finish();
}
@ -131,6 +141,13 @@ public class ShortcutActivity extends Activity {
Intent shortcutIntent = new Intent(ContextManager.getContext(),
ShortcutActivity.class);
if(filter instanceof FilterWithCustomIntent) {
FilterWithCustomIntent customFilter = ((FilterWithCustomIntent)filter);
shortcutIntent.putExtra(TOKEN_CUSTOM_CLASS, customFilter.customTaskList.flattenToString());
for(String key : customFilter.customExtras.keySet())
putExtra(shortcutIntent, key, customFilter.customExtras.get(key));
}
shortcutIntent.setAction(Intent.ACTION_VIEW);
shortcutIntent.putExtra(ShortcutActivity.TOKEN_FILTER_TITLE,
filter.title);
@ -141,20 +158,24 @@ public class ShortcutActivity extends Activity {
String key = TOKEN_FILTER_VALUES_ITEM + item.getKey();
Object value = item.getValue();
// assume one of the big 4...
if (value instanceof String)
shortcutIntent.putExtra(key, (String) value);
else if (value instanceof Integer)
shortcutIntent.putExtra(key, (Integer) value);
else if (value instanceof Double)
shortcutIntent.putExtra(key, (Double) value);
else if (value instanceof Long)
shortcutIntent.putExtra(key, (Long) value);
else
throw new IllegalStateException(
"Unsupported bundle type " + value.getClass()); //$NON-NLS-1$
putExtra(shortcutIntent, key, value);
}
}
return shortcutIntent;
}
private static void putExtra(Intent intent, String key, Object value) {
// assume one of the big 4...
if (value instanceof String)
intent.putExtra(key, (String) value);
else if (value instanceof Integer)
intent.putExtra(key, (Integer) value);
else if (value instanceof Double)
intent.putExtra(key, (Double) value);
else if (value instanceof Long)
intent.putExtra(key, (Long) value);
else
throw new IllegalStateException(
"Unsupported bundle type " + value.getClass()); //$NON-NLS-1$
}
}

@ -913,4 +913,8 @@ public class TaskAdapter extends CursorAdapter implements Filterable {
}
}
public void clearSelection() {
expanded = -1;
}
}

@ -1,8 +1,8 @@
package com.todoroo.astrid.api;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@ -10,7 +10,8 @@ import com.todoroo.andlib.sql.QueryTemplate;
public class FilterWithCustomIntent extends Filter {
public PendingIntent intent = null;
public ComponentName customTaskList = null;
public Bundle customExtras = null;
protected FilterWithCustomIntent() {
super();
@ -43,13 +44,15 @@ public class FilterWithCustomIntent extends Filter {
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeParcelable(intent, 0);
dest.writeParcelable(customTaskList, 0);
dest.writeParcelable(customExtras, 0);
}
@Override
public void readFromParcel(Parcel source) {
super.readFromParcel(source);
intent = source.readParcelable(Intent.class.getClassLoader());
customTaskList = source.readParcelable(ComponentName.class.getClassLoader());
customExtras = source.readParcelable(Bundle.class.getClassLoader());
}
/**

@ -0,0 +1,7 @@
package com.todoroo.astrid.dao;
public interface DatabaseUpdateListener {
public void onDatabaseUpdated();
}

@ -17,15 +17,16 @@ import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.provider.Astrid2TaskProvider;
import com.todoroo.astrid.provider.Astrid3ContentProvider;
import com.todoroo.astrid.reminders.Notifications;
import com.todoroo.astrid.reminders.ReminderService;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.widget.PowerWidget;
import com.todoroo.astrid.widget.PowerWidget42;
import com.todoroo.astrid.widget.PowerWidget44;
import com.todoroo.astrid.widget.TasksWidget;
/**
@ -244,14 +245,26 @@ public class TaskDao extends DatabaseDao<Task> {
afterTasklistChange();
}
private final DatabaseUpdateListener[] taskChangeListeners = new DatabaseUpdateListener[] {
new DatabaseUpdateListener() {
@Override
public void onDatabaseUpdated() {
Astrid2TaskProvider.notifyDatabaseModification();
Astrid3ContentProvider.notifyDatabaseModification();
TasksWidget.updateWidgets(ContextManager.getContext());
}
},
new PowerWidget44(),
new PowerWidget42()
};
/**
* Called when task list has changed
*/
private void afterTasklistChange() {
Astrid2TaskProvider.notifyDatabaseModification();
TasksWidget.updateWidgets(ContextManager.getContext());
PowerWidget.updateWidgets(ContextManager.getContext());
PowerWidget42.updateWidgets(ContextManager.getContext());
for(DatabaseUpdateListener listener : taskChangeListeners) {
listener.onDatabaseUpdated();
}
}
/**

@ -4,6 +4,7 @@
package com.todoroo.astrid.provider;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
@ -17,6 +18,7 @@ import com.todoroo.andlib.data.AbstractDatabase;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.DatabaseDao;
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.astrid.api.AstridApiConstants;
@ -371,4 +373,11 @@ public class Astrid3ContentProvider extends ContentProvider {
return cursor;
}
// --- change listeners
public static void notifyDatabaseModification() {
ContentResolver cr = ContextManager.getContext().getContentResolver();
cr.notifyChange(Task.CONTENT_URI, null);
}
}

@ -18,6 +18,7 @@ import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.GtasksTaskListUpdater;
import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.utility.Constants;
import com.todoroo.astrid.widget.EncouragementService;
/**
* Astrid application dependency injector loads classes in Astrid with the
@ -77,6 +78,9 @@ public class AstridDependencyInjector extends AbstractDependencyInjector {
// com.todoroo.astrid.tags
injectables.put("tagService", TagService.class);
// com.todoroo.astrid.widget
injectables.put("encouragementService", EncouragementService.class);
// these make reference to fields defined above
injectables.put("errorReporters", new ErrorReporter[] {
new AndroidLogReporter(),

@ -18,6 +18,7 @@ import com.todoroo.astrid.dao.Database;
public final class UpgradeService {
public static final int V3_4_0 = 162;
public static final int V3_3_0 = 155;
public static final int V3_2_0 = 147;
public static final int V3_1_0 = 146;
@ -105,10 +106,15 @@ public final class UpgradeService {
"If you liked the old version, you can also go back by " +
"<a href='http://bit.ly/oldastrid'>clicking here</a>",
});
newVersionString(changeLog, "3.5.0 beta", new String[] {
"Google Tasks (experimental!)",
"Power Pack 4x2 and 4x4 Widgets (beta!)",
});
if(from >= V3_3_0)
newVersionString(changeLog, "3.3.6 (9/27/10)", new String[] {
"Restored alarm functionality",
"Producteev: sync can now remove due dates in Producteev",
newVersionString(changeLog, "3.4.0 (10/08/10)", new String[] {
"End User License Agreement",
"Option to disable usage statistics",
"Bug fixes with Producteev",
});
if(from >= V3_0_0 && from < V3_3_0)
newVersionString(changeLog, "3.3.0 (9/17/10)", new String[] {

@ -1,200 +0,0 @@
package com.todoroo.astrid.widget;
import android.app.ExpandableListActivity;
import android.appwidget.AppWidgetManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.Spinner;
import com.todoroo.astrid.service.StatisticsService;
import com.timsu.astrid.R;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.adapter.FilterAdapter;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterCategory;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.utility.Constants;
import com.todoroo.andlib.utility.Preferences;
/**
* Configure options for the Power Pack widget. Select a color, filter to use, enable/disable encouragements.
*
* @author jwong
*
*/
public class ConfigurePowerWidget42Activity extends ExpandableListActivity {
int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
FilterAdapter adapter = null;
String[] colors = new String[]{
"Black",
"Blue",
"Red",
"White"
};
public ConfigurePowerWidget42Activity() {
super();
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Set the result to CANCELED. This will cause the widget host to cancel
// out of the widget placement if they press the back button.
setResult(RESULT_CANCELED);
// Set the view layout resource to use.
setContentView(R.layout.power_widget_configure);
setTitle(R.string.PPW_configure_title);
// Find the widget id from the intent.
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
// If they gave us an intent without the widget id, just bail.
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
}
ArrayAdapter<String> colorAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, colors);
colorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Spinner colorSpinner = (Spinner) findViewById(R.id.PPW_color);
colorSpinner.setAdapter(colorAdapter);
// set up ui
adapter = new FilterAdapter(this, getExpandableListView(),
R.layout.filter_adapter_row, true);
setListAdapter(adapter);
Button button = (Button)findViewById(R.id.ok);
button.setOnClickListener(mOnClickListener);
StatisticsService.reportEvent("power-widget-config"); //$NON-NLS-1$
}
View.OnClickListener mOnClickListener = new View.OnClickListener() {
public void onClick(View v) {
final Context context = ConfigurePowerWidget42Activity.this;
Spinner colorSpinner = (Spinner) findViewById(R.id.PPW_color);
int colorPos = colorSpinner.getSelectedItemPosition();
String color = colors[colorPos];
// removed calendar option
// CheckBox chk_enableCalendar = (CheckBox) findViewById(R.id.PPW_enable_calendar);
// boolean enableCalendar = chk_enableCalendar.isChecked();
boolean enableCalendar = false;
CheckBox chk_disableEncouragements = (CheckBox) findViewById(R.id.PPW_disable_encouragements);
boolean disableEncouragements = chk_disableEncouragements.isChecked();
// Save configuration options
saveConfiguration(adapter.getSelection(), color, enableCalendar, !disableEncouragements);
// Push widget update to surface with newly set prefix
PowerWidget42.updateAppWidget(context, mAppWidgetId);
// Make sure we pass back the original appWidgetId
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
}
};
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
FilterListItem item = (FilterListItem) adapter.getChild(groupPosition,
childPosition);
if(item instanceof Filter) {
adapter.setSelection(item);
}
return true;
}
@Override
public void onGroupExpand(int groupPosition) {
FilterListItem item = (FilterListItem) adapter.getGroup(groupPosition);
if(item instanceof Filter)
adapter.setSelection(item);
else if(item instanceof FilterCategory)
adapter.saveExpansionSetting((FilterCategory) item, true);
}
@Override
public void onGroupCollapse(int groupPosition) {
FilterListItem item = (FilterListItem) adapter.getGroup(groupPosition);
if(item instanceof Filter)
adapter.setSelection(item);
else if(item instanceof FilterCategory)
adapter.saveExpansionSetting((FilterCategory) item, false);
}
@Override
protected void onResume() {
super.onResume();
adapter.registerRecevier();
}
@Override
protected void onPause() {
super.onPause();
adapter.unregisterRecevier();
}
@Override
protected void onStart() {
super.onStart();
StatisticsService.sessionStart(this);
}
@Override
protected void onStop() {
super.onStop();
StatisticsService.sessionStop(this);
}
private void saveConfiguration(FilterListItem filterListItem, String color, boolean enableCalendar, boolean enableEncouragements){
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
String sql = null, contentValuesString = null, title = null;
if(filterListItem != null && filterListItem instanceof Filter) {
sql = ((Filter)filterListItem).sqlQuery;
ContentValues values = ((Filter)filterListItem).valuesForNewTasks;
if(values != null)
contentValuesString = AndroidUtilities.contentValuesToSerializedString(values);
title = ((Filter)filterListItem).title;
}
Preferences.setString(PowerWidget.PREF_TITLE + mAppWidgetId, title);
Preferences.setString(PowerWidget.PREF_SQL + mAppWidgetId, sql);
Preferences.setString(PowerWidget.PREF_VALUES + mAppWidgetId, contentValuesString);
Preferences.setString(PowerWidget.PREF_COLOR + mAppWidgetId, color);
Preferences.setBoolean(PowerWidget.PREF_ENABLE_CALENDAR + mAppWidgetId, enableCalendar);
Preferences.setBoolean(PowerWidget.PREF_ENCOURAGEMENTS + mAppWidgetId, enableEncouragements);
}
}

@ -1,200 +0,0 @@
package com.todoroo.astrid.widget;
import android.app.ExpandableListActivity;
import android.appwidget.AppWidgetManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.Spinner;
import com.todoroo.astrid.service.StatisticsService;
import com.timsu.astrid.R;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.adapter.FilterAdapter;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterCategory;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.utility.Constants;
import com.todoroo.andlib.utility.Preferences;
/**
* Configure options for the Power Pack widget. Select a color, filter to use, enable/disable encouragements.
*
* @author jwong
*
*/
public class ConfigurePowerWidgetActivity extends ExpandableListActivity {
int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
FilterAdapter adapter = null;
String[] colors = new String[]{
"Black",
"Blue",
"Red",
"White"
};
public ConfigurePowerWidgetActivity() {
super();
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Set the result to CANCELED. This will cause the widget host to cancel
// out of the widget placement if they press the back button.
setResult(RESULT_CANCELED);
// Set the view layout resource to use.
setContentView(R.layout.power_widget_configure);
setTitle(R.string.PPW_configure_title);
// Find the widget id from the intent.
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
// If they gave us an intent without the widget id, just bail.
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
}
ArrayAdapter<String> colorAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, colors);
colorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Spinner colorSpinner = (Spinner) findViewById(R.id.PPW_color);
colorSpinner.setAdapter(colorAdapter);
// set up ui
adapter = new FilterAdapter(this, getExpandableListView(),
R.layout.filter_adapter_row, true);
setListAdapter(adapter);
Button button = (Button)findViewById(R.id.ok);
button.setOnClickListener(mOnClickListener);
StatisticsService.reportEvent("power-widget-config"); //$NON-NLS-1$
}
View.OnClickListener mOnClickListener = new View.OnClickListener() {
public void onClick(View v) {
final Context context = ConfigurePowerWidgetActivity.this;
Spinner colorSpinner = (Spinner) findViewById(R.id.PPW_color);
int colorPos = colorSpinner.getSelectedItemPosition();
String color = colors[colorPos];
// removed calendar option
// CheckBox chk_enableCalendar = (CheckBox) findViewById(R.id.PPW_enable_calendar);
// boolean enableCalendar = chk_enableCalendar.isChecked();
boolean enableCalendar = false;
CheckBox chk_disableEncouragements = (CheckBox) findViewById(R.id.PPW_disable_encouragements);
boolean disableEncouragements = chk_disableEncouragements.isChecked();
// Save configuration options
saveConfiguration(adapter.getSelection(), color, enableCalendar, !disableEncouragements);
// Push widget update to surface with newly set prefix
PowerWidget.updateAppWidget(context, mAppWidgetId);
// Make sure we pass back the original appWidgetId
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
}
};
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
FilterListItem item = (FilterListItem) adapter.getChild(groupPosition,
childPosition);
if(item instanceof Filter) {
adapter.setSelection(item);
}
return true;
}
@Override
public void onGroupExpand(int groupPosition) {
FilterListItem item = (FilterListItem) adapter.getGroup(groupPosition);
if(item instanceof Filter)
adapter.setSelection(item);
else if(item instanceof FilterCategory)
adapter.saveExpansionSetting((FilterCategory) item, true);
}
@Override
public void onGroupCollapse(int groupPosition) {
FilterListItem item = (FilterListItem) adapter.getGroup(groupPosition);
if(item instanceof Filter)
adapter.setSelection(item);
else if(item instanceof FilterCategory)
adapter.saveExpansionSetting((FilterCategory) item, false);
}
@Override
protected void onResume() {
super.onResume();
adapter.registerRecevier();
}
@Override
protected void onPause() {
super.onPause();
adapter.unregisterRecevier();
}
@Override
protected void onStart() {
super.onStart();
StatisticsService.sessionStart(this);
}
@Override
protected void onStop() {
super.onStop();
StatisticsService.sessionStop(this);
}
private void saveConfiguration(FilterListItem filterListItem, String color, boolean enableCalendar, boolean enableEncouragements){
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
String sql = null, contentValuesString = null, title = null;
if(filterListItem != null && filterListItem instanceof Filter) {
sql = ((Filter)filterListItem).sqlQuery;
ContentValues values = ((Filter)filterListItem).valuesForNewTasks;
if(values != null)
contentValuesString = AndroidUtilities.contentValuesToSerializedString(values);
title = ((Filter)filterListItem).title;
}
Preferences.setString(PowerWidget.PREF_TITLE + mAppWidgetId, title);
Preferences.setString(PowerWidget.PREF_SQL + mAppWidgetId, sql);
Preferences.setString(PowerWidget.PREF_VALUES + mAppWidgetId, contentValuesString);
Preferences.setString(PowerWidget.PREF_COLOR + mAppWidgetId, color);
Preferences.setBoolean(PowerWidget.PREF_ENABLE_CALENDAR + mAppWidgetId, enableCalendar);
Preferences.setBoolean(PowerWidget.PREF_ENCOURAGEMENTS + mAppWidgetId, enableEncouragements);
}
}

@ -0,0 +1,84 @@
package com.todoroo.astrid.widget;
import java.util.Date;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.service.TaskService;
public class EncouragementService {
@Autowired private TaskService taskService;
private final EncouragementProvider[] providers = new EncouragementProvider[] {
new ResourceEncouragementProvider(),
new TimeOfDayEncouragementProvider(),
new CompletionCountEncouragementProvider()
};
public EncouragementService() {
DependencyInjectionService.getInstance().inject(this);
}
public String getEncouragement() {
int index = (int)Math.floor(Math.random() * providers.length);
return providers[index].getEncouragement();
}
public interface EncouragementProvider {
public String getEncouragement();
}
public static class ResourceEncouragementProvider implements EncouragementProvider {
@Override
public String getEncouragement() {
String[] encouragements = ContextManager.getResources().getStringArray(R.array.PPW_encouragements);
int encouragementIdx = (int)Math.floor(Math.random() * encouragements.length);
return encouragements[encouragementIdx];
}
}
public static class TimeOfDayEncouragementProvider implements EncouragementProvider {
private static int GOOD_MORNING = 0;
private static int GOOD_AFTERNOON = 1;
private static int GOOD_EVENING = 2;
private static int LATE_NIGHT = 3;
@Override
public String getEncouragement() {
String[] encouragements = ContextManager.getResources().
getStringArray(R.array.PPW_encouragements_tod);
int index = (int)Math.floor(Math.random() * (encouragements.length / 4));
int hour = new Date().getHours();
if(hour >= 6 && hour < 12)
return encouragements[4*index + GOOD_MORNING];
else if(hour >= 12 && hour < 18)
return encouragements[4*index + GOOD_AFTERNOON];
else if(hour >= 18 && hour < 23)
return encouragements[4*index + GOOD_EVENING];
return encouragements[4*index + LATE_NIGHT];
}
}
public class CompletionCountEncouragementProvider implements EncouragementProvider {
@Override
public String getEncouragement() {
Filter filter = new Filter(null, null, new QueryTemplate().where(TaskCriteria.completed()), null);
int completed = taskService.countTasks(filter);
String[] encouragements = ContextManager.getResources().
getStringArray(R.array.PPW_encouragements_completed);
int index = (int)Math.floor(Math.random() * (encouragements.length));
return String.format(encouragements[index], completed);
}
}
}

@ -31,26 +31,31 @@ import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.core.CoreFilterExposer;
import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.dao.DatabaseUpdateListener;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.TaskService;
/**
* Power Pack widget. Supports 4x4 size. Configured via
* ConfigurePowerWidgetActivity when widget is added to homescreen.
* Power Pack widget
*
* @author jwong (jwong@dayspring-tech.com)
*
*/
@SuppressWarnings("nls")
public class PowerWidget extends AppWidgetProvider {
abstract public class PowerWidget extends AppWidgetProvider implements DatabaseUpdateListener {
static final String LOG_TAG = "PowerWidget";
static Class<?> updateService;
// --- abstract hooks
/** service for updating the widget */
abstract public Class<? extends UpdateService> getUpdateService();
// --- implementation
static {
AstridDependencyInjector.initialize();
updateService = PowerWidget.UpdateService.class;
}
@ -61,12 +66,6 @@ public class PowerWidget extends AppWidgetProvider {
static final String ACTION_SCROLL_DOWN = "com.todoroo.astrid.widget.ACTION_SCROLL_DOWN";
// Prefix for Shared Preferences
static final String PREF_COLOR = "powerwidget-color-";
static final String PREF_ENABLE_CALENDAR = "powerwidget-enableCalendar-";
static final String PREF_ENCOURAGEMENTS = "powerwidget-enableEncouragements-";
static final String PREF_TITLE = "powerwidget-title-";
static final String PREF_SQL = "powerwidget-sql-";
static final String PREF_VALUES = "powerwidget-values-";
static final String PREF_ENCOURAGEMENT_LAST_ROTATION_TIME = "powerwidget-encouragementRotationTime-";
static final String PREF_ENCOURAGEMENT_CURRENT = "powerwidget-encouragementCurrent-";
static final String PREF_LAST_COMPLETED_ID = "powerwidget-lastCompletedId-";
@ -100,9 +99,6 @@ public class PowerWidget extends AppWidgetProvider {
R.id.checkbox3, R.id.checkbox4, R.id.checkbox5, R.id.checkbox6,
R.id.checkbox7, R.id.checkbox8, R.id.checkbox9, R.id.checkbox10 };
// # of rows defined in the xml file
static int ROW_LIMIT = 10;
public static int[] IMPORTANCE_DRAWABLES = new int[] {
R.drawable.importance_1, R.drawable.importance_2, R.drawable.importance_3,
R.drawable.importance_4, R.drawable.importance_5, R.drawable.importance_6
@ -119,7 +115,7 @@ public class PowerWidget extends AppWidgetProvider {
super.onUpdate(context, appWidgetManager, appWidgetIds);
// Start in service to prevent Application Not Responding timeout
Intent updateIntent = new Intent(context, updateService);
Intent updateIntent = new Intent(context, getUpdateService());
updateIntent.putExtra(APP_WIDGET_IDS, appWidgetIds);
context.startService(updateIntent);
} catch (SecurityException e) {
@ -158,7 +154,7 @@ public class PowerWidget extends AppWidgetProvider {
if (intent != null && (ACTION_SCROLL_UP.equals(intent.getAction()) ||
ACTION_SCROLL_DOWN.equals(intent.getAction()) ||
ACTION_MARK_COMPLETE.equals(intent.getAction()))) {
Intent updateIntent = new Intent(context, updateService);
Intent updateIntent = new Intent(context, getUpdateService());
updateIntent.setAction(intent.getAction());
updateIntent.putExtras(intent.getExtras());
context.startService(updateIntent);
@ -168,34 +164,36 @@ public class PowerWidget extends AppWidgetProvider {
}
/**
* Update all widgets
* @param id
*/
public static void updateWidgets(Context context) {
context.startService(new Intent(ContextManager.getContext(),
updateService));
@Override
public void onDatabaseUpdated() {
Context context = ContextManager.getContext();
context.startService(new Intent(context, getUpdateService()));
}
/**
* Update widget with the given id
* @param id
*/
public static void updateAppWidget(Context context, int appWidgetId){
Intent updateIntent = new Intent(context, updateService);
public void updateAppWidget(Context context, int appWidgetId){
Intent updateIntent = new Intent(context, getUpdateService());
updateIntent.putExtra(APP_WIDGET_IDS, new int[]{ appWidgetId });
context.startService(updateIntent);
}
public static class UpdateService extends Service {
static Class<?> widgetClass;
static int widgetLayout;
abstract public static class UpdateService extends Service {
static {
widgetClass = PowerWidget.class;
widgetLayout = R.layout.widget_power_44;
}
// --- abstract hooks
/** widget class */
abstract public Class<? extends PowerWidget> getWidgetClass();
/** widget layout resource id */
abstract public int getWidgetLayout();
/** # rows defined in the xml file */
abstract public int getRowLimit();
// --- implementation
private static final int SCROLL_OFFSET_UNSET = -1;
@ -208,6 +206,9 @@ public class PowerWidget extends AppWidgetProvider {
@Autowired
private TaskService taskService;
@Autowired
private EncouragementService encouragementService;
public UpdateService() {
DependencyInjectionService.getInstance().inject(this);
}
@ -232,7 +233,7 @@ public class PowerWidget extends AppWidgetProvider {
manager.updateAppWidget(appWidgetId, views);
} else {
if (appWidgetIds == null){
appWidgetIds = manager.getAppWidgetIds(new ComponentName(this, widgetClass));
appWidgetIds = manager.getAppWidgetIds(new ComponentName(this, getWidgetClass()));
}
for (int id : appWidgetIds) {
RemoteViews views = buildUpdate(this, id, scrollOffset);
@ -250,9 +251,9 @@ public class PowerWidget extends AppWidgetProvider {
DependencyInjectionService.getInstance().inject(this);
RemoteViews views = new RemoteViews(context.getPackageName(),
widgetLayout);
getWidgetLayout());
String color = Preferences.getStringValue(PowerWidget.PREF_COLOR + appWidgetId);
String color = Preferences.getStringValue(WidgetConfigActivity.PREF_COLOR + appWidgetId);
int widgetBackground = R.id.widget_bg_black;
int textColor = Color.WHITE, overdueColor = context.getResources().getColor(R.color.task_list_overdue);
@ -280,14 +281,13 @@ public class PowerWidget extends AppWidgetProvider {
views.setViewVisibility(widgetBackground, View.VISIBLE);
// set encouragement
boolean showEncouragements = Preferences.getBoolean(PowerWidget.PREF_ENCOURAGEMENTS + appWidgetId, true);
boolean showEncouragements = Preferences.getBoolean(WidgetConfigActivity.PREF_ENCOURAGEMENTS + appWidgetId, true);
long lastRotation = Preferences.getLong(PowerWidget.PREF_ENCOURAGEMENT_LAST_ROTATION_TIME + appWidgetId, 0);
if (showEncouragements){
// is it time to update the encouragement?
if (System.currentTimeMillis() - lastRotation > ENCOURAGEMENT_CYCLE_TIME){
String[] encouragements = context.getResources().getStringArray(R.array.PPW_encouragements);
int encouragementIdx = (int)Math.floor(Math.random() * encouragements.length);
Preferences.setString(PowerWidget.PREF_ENCOURAGEMENT_CURRENT + appWidgetId, encouragements[encouragementIdx]);
String encouragement = encouragementService.getEncouragement();
Preferences.setString(PowerWidget.PREF_ENCOURAGEMENT_CURRENT + appWidgetId, encouragement);
Preferences.setLong(PowerWidget.PREF_ENCOURAGEMENT_LAST_ROTATION_TIME + appWidgetId, System.currentTimeMillis());
}
views.setTextViewText(R.id.encouragement_text, Preferences.getStringValue(PowerWidget.PREF_ENCOURAGEMENT_CURRENT + appWidgetId));
@ -344,7 +344,7 @@ public class PowerWidget extends AppWidgetProvider {
scrollOffset = Math.max(0, scrollOffset);
query = query.replaceAll("[lL][iI][mM][iI][tT] +[^ ]+", "") + " LIMIT " +
scrollOffset + "," + (ROW_LIMIT + 1);
scrollOffset + "," + (getRowLimit() + 1);
// load last completed task
Task lastCompleted = null;
@ -364,7 +364,7 @@ public class PowerWidget extends AppWidgetProvider {
Task task = new Task();
int position;
for (position = 0; position < cursor.getCount() && position < ROW_LIMIT; position++) {
for (position = 0; position < cursor.getCount() && position < getRowLimit(); position++) {
if(lastCompleted != null && lastCompletedPosition == position + scrollOffset) {
task = lastCompleted;
} else {
@ -386,7 +386,7 @@ public class PowerWidget extends AppWidgetProvider {
IMPORTANCE_DRAWABLES[task.getValue(Task.IMPORTANCE)]);
// check box
Intent markCompleteIntent = new Intent(context, widgetClass);
Intent markCompleteIntent = new Intent(context, getWidgetClass());
markCompleteIntent.setAction(ACTION_MARK_COMPLETE);
markCompleteIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
markCompleteIntent.putExtra(COMPLETED_TASK_ID, taskId);
@ -441,7 +441,7 @@ public class PowerWidget extends AppWidgetProvider {
views.setViewVisibility(TASK_DUE[position], View.VISIBLE);
}
for(; position < ROW_LIMIT; position++) {
for(; position < getRowLimit(); position++) {
views.setViewVisibility(TASK_IMPORTANCE[position], View.INVISIBLE);
views.setViewVisibility(TASK_CHECKBOX[position], View.INVISIBLE);
views.setViewVisibility(TASK_TITLE[position], View.INVISIBLE);
@ -449,7 +449,7 @@ public class PowerWidget extends AppWidgetProvider {
}
// create intent to scroll up
Intent scrollUpIntent = new Intent(context, widgetClass);
Intent scrollUpIntent = new Intent(context, getWidgetClass());
scrollUpIntent.setAction(ACTION_SCROLL_UP);
scrollUpIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
scrollUpIntent.setType(AppWidgetManager.EXTRA_APPWIDGET_ID + appWidgetId);
@ -467,7 +467,7 @@ public class PowerWidget extends AppWidgetProvider {
views.setOnClickPendingIntent(R.id.scroll_up_alt, pScrollUpIntent);
// create intent to scroll down
Intent scrollDownIntent = new Intent(context, widgetClass);
Intent scrollDownIntent = new Intent(context, getWidgetClass());
scrollDownIntent.setAction(ACTION_SCROLL_DOWN);
scrollDownIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
scrollDownIntent.setType(AppWidgetManager.EXTRA_APPWIDGET_ID + appWidgetId);
@ -497,13 +497,13 @@ public class PowerWidget extends AppWidgetProvider {
private Filter getFilter(int widgetId) {
// base our filter off the inbox filter, replace stuff if we have it
Filter filter = CoreFilterExposer.buildInboxFilter(getResources());
String sql = Preferences.getStringValue(PREF_SQL + widgetId);
String sql = Preferences.getStringValue(WidgetConfigActivity.PREF_SQL + widgetId);
if(sql != null)
filter.sqlQuery = sql;
String title = Preferences.getStringValue(PREF_TITLE + widgetId);
String title = Preferences.getStringValue(WidgetConfigActivity.PREF_TITLE + widgetId);
if(title != null)
filter.title = title;
String contentValues = Preferences.getStringValue(PREF_VALUES + widgetId);
String contentValues = Preferences.getStringValue(WidgetConfigActivity.PREF_VALUES + widgetId);
if(contentValues != null)
filter.valuesForNewTasks = AndroidUtilities.contentValuesFromSerializedString(contentValues);

@ -2,41 +2,40 @@ package com.todoroo.astrid.widget;
import com.timsu.astrid.R;
/**
* Power Pack widget. Supports 4x2 size. Configured via
* ConfigurePowerWidget42Activity when widget is added to homescreen.
*
* This class extends PowerWidget but sets references to itself for use in Intents.
*
* @author jwong (jwong@dayspring-tech.com)
*
*/
@SuppressWarnings("nls")
public class PowerWidget42 extends PowerWidget {
static final String LOG_TAG = "PowerWidget42";
@Override
public Class<? extends UpdateService> getUpdateService() {
return UpdateService42.class;
}
static {
// set reference to my UpdateService for calls to launch the service
updateService = PowerWidget42.UpdateService.class;
public static class UpdateService42 extends PowerWidget.UpdateService {
ROW_LIMIT = 5;
}
@Override
public Class<? extends PowerWidget> getWidgetClass() {
return PowerWidget42.class;
}
@Override
public int getWidgetLayout() {
return R.layout.widget_power_42;
}
/**
* Extend PowerWidget's UpdateService so that the widget provider class
* can be specified. We can't just used PowerWidget's UpdateService
* since it's a static class and uses PowerWidget's variables, not this
* class' variables.
*
* @author jwong (jwong@dayspring-tech.com)
*
*/
public static class UpdateService extends PowerWidget.UpdateService {
static {
widgetClass = PowerWidget42.class;
widgetLayout = R.layout.widget_power_42;
@Override
public int getRowLimit() {
return 5;
}
}
public static class ConfigActivity extends WidgetConfigActivity {
@Override
public boolean showColorSelectionSetting() {
return true;
}
@Override
public void updateWidget() {
new PowerWidget42().updateAppWidget(this, mAppWidgetId);
}
}
}

@ -0,0 +1,46 @@
package com.todoroo.astrid.widget;
import com.timsu.astrid.R;
public class PowerWidget44 extends PowerWidget {
@Override
public Class<? extends UpdateService> getUpdateService() {
return UpdateService44.class;
}
public static class UpdateService44 extends PowerWidget.UpdateService {
@Override
public Class<? extends PowerWidget> getWidgetClass() {
return PowerWidget44.class;
}
@Override
public int getWidgetLayout() {
return R.layout.widget_power_44;
}
@Override
public int getRowLimit() {
return 10;
}
}
public static class ConfigActivity extends WidgetConfigActivity {
@Override
public boolean showColorSelectionSetting() {
return true;
}
@Override
public boolean showEncouragementSetting() {
return true;
}
@Override
public void updateWidget() {
new PowerWidget44().updateAppWidget(this, mAppWidgetId);
}
}
}

@ -20,6 +20,7 @@ import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.activity.SortSelectionActivity;
import com.todoroo.astrid.activity.TaskEditActivity;
import com.todoroo.astrid.activity.TaskListActivity;
@ -29,7 +30,6 @@ import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.TaskService;
import com.todoroo.andlib.utility.Preferences;
public class TasksWidget extends AppWidgetProvider {
@ -37,10 +37,6 @@ public class TasksWidget extends AppWidgetProvider {
AstridDependencyInjector.initialize();
}
static final String PREF_TITLE = "taskswidget-title-"; //$NON-NLS-1$
static final String PREF_SQL = "taskswidget-sql-"; //$NON-NLS-1$
static final String PREF_VALUES = "taskswidget-values-"; //$NON-NLS-1$
public final static int[] TEXT_IDS = { R.id.task_1, R.id.task_2,
R.id.task_3, R.id.task_4, R.id.task_5 };
public final static int[] SEPARATOR_IDS = { R.id.separator_1,
@ -81,6 +77,13 @@ public class TasksWidget extends AppWidgetProvider {
context.startService(intent);
}
public static class ConfigActivity extends WidgetConfigActivity {
@Override
public void updateWidget() {
TasksWidget.updateWidget(this, mAppWidgetId);
}
}
public static class UpdateService extends Service {
public static String EXTRA_WIDGET_ID = "widget_id"; //$NON-NLS-1$
@ -208,13 +211,13 @@ public class TasksWidget extends AppWidgetProvider {
private Filter getFilter(int widgetId) {
// base our filter off the inbox filter, replace stuff if we have it
Filter filter = CoreFilterExposer.buildInboxFilter(getResources());
String sql = Preferences.getStringValue(PREF_SQL + widgetId);
String sql = Preferences.getStringValue(WidgetConfigActivity.PREF_SQL + widgetId);
if(sql != null)
filter.sqlQuery = sql;
String title = Preferences.getStringValue(PREF_TITLE + widgetId);
String title = Preferences.getStringValue(WidgetConfigActivity.PREF_TITLE + widgetId);
if(title != null)
filter.title = title;
String contentValues = Preferences.getStringValue(PREF_VALUES + widgetId);
String contentValues = Preferences.getStringValue(WidgetConfigActivity.PREF_VALUES + widgetId);
if(contentValues != null)
filter.valuesForNewTasks = AndroidUtilities.contentValuesFromSerializedString(contentValues);

@ -5,26 +5,61 @@ import android.appwidget.AppWidgetManager;
import android.content.ContentValues;
import android.content.Intent;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.Spinner;
import com.todoroo.astrid.service.StatisticsService;
import com.timsu.astrid.R;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.adapter.FilterAdapter;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterCategory;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.utility.Constants;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.service.StatisticsService;
@SuppressWarnings("nls")
abstract public class WidgetConfigActivity extends ExpandableListActivity {
static final String PREF_COLOR = "widget-color-";
static final String PREF_ENABLE_CALENDAR = "widget-enableCalendar-";
static final String PREF_ENCOURAGEMENTS = "widget-enableEncouragements-";
static final String PREF_TITLE = "widget-title-";
static final String PREF_SQL = "widget-sql-";
static final String PREF_VALUES = "widget-values-";
public class WidgetConfigActivity extends ExpandableListActivity {
int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
FilterAdapter adapter = null;
@SuppressWarnings("nls")
public String[] COLORS = new String[] {
"Black",
"White",
"Blue",
"Red"
};
public WidgetConfigActivity() {
super();
}
abstract public void updateWidget();
/** whether to show 'hide encouragements' */
public boolean showEncouragementSetting() {
return false;
}
/** whether to show color selection */
public boolean showColorSelectionSetting() {
return false;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@ -36,7 +71,7 @@ public class WidgetConfigActivity extends ExpandableListActivity {
// Set the view layout resource to use.
setContentView(R.layout.widget_config_activity);
setTitle(R.string.WCA_title);
setTitle(R.string.PPW_configure_title);
// Find the widget id from the intent.
Intent intent = getIntent();
@ -51,6 +86,12 @@ public class WidgetConfigActivity extends ExpandableListActivity {
finish();
}
if(!showColorSelectionSetting())
findViewById(R.id.colors).setVisibility(View.GONE);
if(!showEncouragementSetting())
findViewById(R.id.PPW_disable_encouragements).setVisibility(View.GONE);
// set up ui
adapter = new FilterAdapter(this, getExpandableListView(),
R.layout.filter_adapter_row, true);
@ -64,11 +105,21 @@ public class WidgetConfigActivity extends ExpandableListActivity {
View.OnClickListener mOnClickListener = new View.OnClickListener() {
public void onClick(View v) {
Spinner colorSpinner = (Spinner) findViewById(R.id.PPW_color);
int colorPos = colorSpinner.getSelectedItemPosition();
String color = COLORS[colorPos];
boolean enableCalendar = false;
CheckBox chk_disableEncouragements = (CheckBox) findViewById(R.id.PPW_disable_encouragements);
boolean disableEncouragements = chk_disableEncouragements.isChecked();
if(!showEncouragementSetting())
disableEncouragements = true;
// Save configuration options
saveConfiguration(adapter.getSelection());
saveConfiguration(adapter.getSelection(), color, enableCalendar, disableEncouragements);
// Push widget update to surface with newly set prefix
TasksWidget.updateWidget(WidgetConfigActivity.this, mAppWidgetId);
updateWidget();
// Make sure we pass back the original appWidgetId
Intent resultValue = new Intent();
@ -131,7 +182,10 @@ public class WidgetConfigActivity extends ExpandableListActivity {
StatisticsService.sessionStop(this);
}
private void saveConfiguration(FilterListItem filterListItem) {
private void saveConfiguration(FilterListItem filterListItem, String color, boolean enableCalendar, boolean disableEncouragements){
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
String sql = null, contentValuesString = null, title = null;
if(filterListItem != null && filterListItem instanceof Filter) {
@ -142,10 +196,13 @@ public class WidgetConfigActivity extends ExpandableListActivity {
title = ((Filter)filterListItem).title;
}
Preferences.setString(TasksWidget.PREF_TITLE + mAppWidgetId, title);
Preferences.setString(TasksWidget.PREF_SQL + mAppWidgetId, sql);
Preferences.setString(TasksWidget.PREF_VALUES + mAppWidgetId, contentValuesString);
Preferences.setString(WidgetConfigActivity.PREF_TITLE + mAppWidgetId, title);
Preferences.setString(WidgetConfigActivity.PREF_SQL + mAppWidgetId, sql);
Preferences.setString(WidgetConfigActivity.PREF_VALUES + mAppWidgetId, contentValuesString);
StatisticsService.reportEvent("widget-config"); //$NON-NLS-1$
Preferences.setString(WidgetConfigActivity.PREF_COLOR + mAppWidgetId, color);
Preferences.setBoolean(WidgetConfigActivity.PREF_ENABLE_CALENDAR + mAppWidgetId, enableCalendar);
Preferences.setBoolean(WidgetConfigActivity.PREF_ENCOURAGEMENTS + mAppWidgetId, !disableEncouragements);
}
}

Loading…
Cancel
Save