Repeats. woot

pull/14/head
Tim Su 14 years ago
parent eee441e9e3
commit 8e02edab68

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.timsu.astrid" package="com.timsu.astrid"
android:versionName="3.0.0-beta" android:versionCode="136"> android:versionName="3.0.0-beta" android:versionCode="137">
<!-- ================================================== Used Permissions = --> <!-- ================================================== Used Permissions = -->
@ -45,13 +45,14 @@
<!-- ========================================================== Metadata = --> <!-- ========================================================== Metadata = -->
<uses-sdk android:targetSdkVersion="4" /> <uses-sdk android:targetSdkVersion="4"
android:minSdkVersion="3" />
<supports-screens /> <supports-screens />
<application android:icon="@drawable/icon" <application android:icon="@drawable/icon"
android:label="@string/app_name" android:label="@string/app_name"
android:debuggable="true" android:debuggable="true">
android:installLocation="auto"> <!-- android:installLocation="auto"> -->
<!-- ====================================================== Activities = --> <!-- ====================================================== Activities = -->
@ -147,7 +148,7 @@
<!-- core --> <!-- core -->
<receiver android:name="com.todoroo.astrid.core.CorePlugin"> <receiver android:name="com.todoroo.astrid.core.CorePlugin">
<intent-filter> <intent-filter>
<action android:name="com.todoroo.astrid.REQUEST_PLUGINS" /> <action android:name="com.todoroo.astrid.REQUEST_ADDONS" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</receiver> </receiver>
@ -168,7 +169,7 @@
<!-- extended filters --> <!-- extended filters -->
<receiver android:name="com.todoroo.astrid.core.ExtendedPlugin"> <receiver android:name="com.todoroo.astrid.core.ExtendedPlugin">
<intent-filter> <intent-filter>
<action android:name="com.todoroo.astrid.REQUEST_PLUGINS" /> <action android:name="com.todoroo.astrid.REQUEST_ADDONS" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</receiver> </receiver>
@ -182,7 +183,7 @@
<!-- tags --> <!-- tags -->
<receiver android:name="com.todoroo.astrid.tags.TagsPlugin"> <receiver android:name="com.todoroo.astrid.tags.TagsPlugin">
<intent-filter> <intent-filter>
<action android:name="com.todoroo.astrid.REQUEST_PLUGINS" /> <action android:name="com.todoroo.astrid.REQUEST_ADDONS" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</receiver> </receiver>
@ -198,6 +199,14 @@
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<!-- repeats -->
<receiver android:name="com.todoroo.astrid.repeats.RepeatsPlugin">
<intent-filter>
<action android:name="com.todoroo.astrid.REQUEST_ADDONS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- notes --> <!-- notes -->
<receiver android:name="com.todoroo.astrid.notes.NoteDetailExposer"> <receiver android:name="com.todoroo.astrid.notes.NoteDetailExposer">

@ -7,18 +7,18 @@ import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
/** /**
* Represents a plug-in for Astrid. Users can enable or disable plug-ins, * Represents an add-onn for Astrid. Users can enable or disable add-ons,
* which affect all other extension points that share the same identifier. * which affect all other extension points that share the same identifier.
* *
* @author Tim Su <tim@todoroo.com> * @author Tim Su <tim@todoroo.com>
* *
*/ */
public class Plugin implements Parcelable { public class Addon implements Parcelable {
/** /**
* Plug-in Identifier * Add-on Identifier
*/ */
public String plugin = null; public String addon = null;
/** /**
* Plug-in Title * Plug-in Title
@ -38,13 +38,13 @@ public class Plugin implements Parcelable {
/** /**
* Convenience constructor to generate a plug-in object * Convenience constructor to generate a plug-in object
* *
* @param plugin * @param addon
* @param title * @param title
* @param author * @param author
* @param description * @param description
*/ */
public Plugin(String plugin, String title, String author, String description) { public Addon(String addon, String title, String author, String description) {
this.plugin = plugin; this.addon = addon;
this.title = title; this.title = title;
this.author = author; this.author = author;
this.description = description; this.description = description;
@ -64,7 +64,7 @@ public class Plugin implements Parcelable {
* {@inheritDoc} * {@inheritDoc}
*/ */
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(plugin); dest.writeString(addon);
dest.writeString(title); dest.writeString(title);
dest.writeString(author); dest.writeString(author);
dest.writeString(description); dest.writeString(description);
@ -73,20 +73,20 @@ public class Plugin implements Parcelable {
/** /**
* Parcelable creator * Parcelable creator
*/ */
public static final Parcelable.Creator<Plugin> CREATOR = new Parcelable.Creator<Plugin>() { public static final Parcelable.Creator<Addon> CREATOR = new Parcelable.Creator<Addon>() {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public Plugin createFromParcel(Parcel source) { public Addon createFromParcel(Parcel source) {
return new Plugin(source.readString(), source.readString(), return new Addon(source.readString(), source.readString(),
source.readString(), source.readString()); source.readString(), source.readString());
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public Plugin[] newArray(int size) { public Addon[] newArray(int size) {
return new Plugin[size]; return new Addon[size];
}; };
}; };

@ -3,6 +3,8 @@
*/ */
package com.todoroo.astrid.api; package com.todoroo.astrid.api;
import android.widget.RemoteViews;
/** /**
* Constants for interfacing with Astrid. * Constants for interfacing with Astrid.
* *
@ -28,32 +30,35 @@ public class AstridApiConstants {
*/ */
public static final String PERMISSION_WRITE = PACKAGE + ".WRITE"; public static final String PERMISSION_WRITE = PACKAGE + ".WRITE";
// --- Broadcast Extras
/** /**
* Extras name for Task id * Extras name for task id
*/ */
public static final String EXTRAS_TASK_ID = "task"; public static final String EXTRAS_TASK_ID = "task";
/** /**
* Extras name for an array of response items * Extras name for a response item broadcast to astrid
*/ */
public static final String EXTRAS_ITEMS = "items"; public static final String EXTRAS_RESPONSE = "response";
/** /**
* Extras name for plug-in object * Extras name for plug-in identifier
*/ */
public static final String EXTRAS_PLUGIN = "plugin"; public static final String EXTRAS_ADDON = "addon";
// --- Plug-ins API // --- Add-ons API
/** /**
* Action name for broadcast intent requesting filters * Action name for broadcast intent requesting add-ons
*/ */
public static final String BROADCAST_REQUEST_PLUGINS = PACKAGE + ".REQUEST_PLUGINS"; public static final String BROADCAST_REQUEST_ADDONS = PACKAGE + ".REQUEST_ADDONS";
/** /**
* Action name for broadcast intent sending filters back to Astrid * Action name for broadcast intent sending add-ons back to Astrid
* @extra EXTRAS_RESPONSE an {@link Addon} object
*/ */
public static final String BROADCAST_SEND_PLUGINS = PACKAGE + ".SEND_PLUGINS"; public static final String BROADCAST_SEND_ADDONS = PACKAGE + ".SEND_ADDONS";
// --- Filters API // --- Filters API
@ -64,30 +69,39 @@ public class AstridApiConstants {
/** /**
* Action name for broadcast intent sending filters back to Astrid * Action name for broadcast intent sending filters back to Astrid
* @extra EXTRAS_ADDON your add-on identifier
* @extra EXTRAS_RESPONSE an array of {@link FilterListItem}s
*/ */
public static final String BROADCAST_SEND_FILTERS = PACKAGE + ".SEND_FILTERS"; public static final String BROADCAST_SEND_FILTERS = PACKAGE + ".SEND_FILTERS";
// --- Edit Operations API // --- Edit Controls API
/** /**
* Action name for broadcast intent requesting task edit operations * Action name for broadcast intent requesting task edit controls
* @extra EXTRAS_TASK_ID id of the task user is editing
*/ */
public static final String BROADCAST_REQUEST_EDIT_OPERATIONS = PACKAGE + ".REQUEST_EDIT_OPERATIONS"; public static final String BROADCAST_REQUEST_EDIT_CONTROLS = PACKAGE + ".REQUEST_EDIT_CONTROLS";
/** /**
* Action name for broadcast intent sending task edit operations back to Astrid * Action name for broadcast intent sending task edit controls back to Astrid
* @extra EXTRAS_ADDON your add-on identifier
* @extra EXTRAS_RESPONSE a {@link RemoteViews} with your edit controls
*/ */
public static final String BROADCAST_SEND_EDIT_OPERATIONS = PACKAGE + ".SEND_EDIT_OPERATIONS"; public static final String BROADCAST_SEND_EDIT_CONTROLS = PACKAGE + ".SEND_EDIT_CONTROLS";
// --- Task List Details API // --- Task List Details API
/** /**
* Action name for broadcast intent requesting task list details for a task * Action name for broadcast intent requesting task list details for a task
* @extra EXTRAS_TASK_ID id of the task
*/ */
public static final String BROADCAST_REQUEST_DETAILS = PACKAGE + ".REQUEST_DETAILS"; public static final String BROADCAST_REQUEST_DETAILS = PACKAGE + ".REQUEST_DETAILS";
/** /**
* Action name for broadcast intent sending details back to Astrid * Action name for broadcast intent sending details back to Astrid
* @extra EXTRAS_ADDON your add-on identifier
* @extra EXTRAS_TASK_ID id of the task
* @extra EXTRAS_RESPONSE a {@link TaskDetail} object
*/ */
public static final String BROADCAST_SEND_DETAILS = PACKAGE + ".SEND_DETAILS"; public static final String BROADCAST_SEND_DETAILS = PACKAGE + ".SEND_DETAILS";
@ -95,14 +109,19 @@ public class AstridApiConstants {
/** /**
* Action name for intents to be displayed on task context menu * Action name for intents to be displayed on task context menu
* @extra EXTRAS_TASK_ID id of the task
*/ */
public static final String ACTION_TASK_CONTEXT_MENU = PACKAGE + ".CONTEXT_MENU"; public static final String ACTION_TASK_CONTEXT_MENU = PACKAGE + ".CONTEXT_MENU";
/** /**
* Action name for intents to be displayed on Astrid's task list menu * Action name for intents to be displayed on Astrid's task list menu
* @extra EXTRAS_ADDON your add-on identifier
* @extra EXTRAS_RESPONSE an array of {@link Intent}s
*/ */
public static final String ACTION_TASK_LIST_MENU = PACKAGE + ".TASK_LIST_MENU"; public static final String ACTION_TASK_LIST_MENU = PACKAGE + ".TASK_LIST_MENU";
// --- Settings API
/** /**
* Action name for intents to be displayed in Astrid's settings * Action name for intents to be displayed in Astrid's settings
*/ */
@ -112,11 +131,13 @@ public class AstridApiConstants {
/** /**
* Action name for broadcast intent notifying that task was completed * Action name for broadcast intent notifying that task was completed
* @extra EXTRAS_TASK_ID id of the task
*/ */
public static final String BROADCAST_EVENT_TASK_COMPLETED = PACKAGE + ".TASK_COMPLETED"; public static final String BROADCAST_EVENT_TASK_COMPLETED = PACKAGE + ".TASK_COMPLETED";
/** /**
* Action name for broadcast intent notifying that task was created * Action name for broadcast intent notifying that task was created
* @extra EXTRAS_TASK_ID id of the task
*/ */
public static final String BROADCAST_EVENT_TASK_CREATED = PACKAGE + ".TASK_CREATED"; public static final String BROADCAST_EVENT_TASK_CREATED = PACKAGE + ".TASK_CREATED";

@ -34,7 +34,7 @@ public final class EditOperation implements Parcelable {
* Create an EditOperation object * Create an EditOperation object
* *
* @param plugin * @param plugin
* {@link Plugin} identifier that encompasses object * {@link Addon} identifier that encompasses object
* @param text * @param text
* label to display * label to display
* @param intent * @param intent

@ -64,7 +64,7 @@ public final class Filter extends FilterListItem {
* Utility constructor for creating a TaskList object * Utility constructor for creating a TaskList object
* *
* @param plugin * @param plugin
* {@link Plugin} identifier that encompasses object * {@link Addon} identifier that encompasses object
* @param listingTitle * @param listingTitle
* Title of this item as displayed on the lists page, e.g. Inbox * Title of this item as displayed on the lists page, e.g. Inbox
* @param title * @param title
@ -88,7 +88,7 @@ public final class Filter extends FilterListItem {
* Utility constructor * Utility constructor
* *
* @param plugin * @param plugin
* {@link Plugin} identifier that encompasses object * {@link Addon} identifier that encompasses object
*/ */
protected Filter(String plugin) { protected Filter(String plugin) {
this.plugin = plugin; this.plugin = plugin;

@ -29,7 +29,7 @@ public class FilterCategory extends FilterListItem {
* Constructor for creating a new FilterCategory * Constructor for creating a new FilterCategory
* *
* @param plugin * @param plugin
* {@link Plugin} identifier that encompasses object * {@link Addon} identifier that encompasses object
* @param listingTitle * @param listingTitle
* Title of this item as displayed on the lists page, e.g. Inbox * Title of this item as displayed on the lists page, e.g. Inbox
* @param children * @param children
@ -46,7 +46,7 @@ public class FilterCategory extends FilterListItem {
* Constructor for creating a new FilterCategory * Constructor for creating a new FilterCategory
* *
* @param plugin * @param plugin
* {@link Plugin} identifier that encompasses object * {@link Addon} identifier that encompasses object
*/ */
protected FilterCategory(String plugin) { protected FilterCategory(String plugin) {
this.plugin = plugin; this.plugin = plugin;

@ -23,7 +23,7 @@ public class FilterListHeader extends FilterListItem {
* Constructor for creating a new FilterListHeader * Constructor for creating a new FilterListHeader
* *
* @param plugin * @param plugin
* {@link Plugin} identifier that encompasses object * {@link Addon} identifier that encompasses object
* @param listingTitle * @param listingTitle
* @param listingIconResource * @param listingIconResource
* @param priority * @param priority
@ -37,7 +37,7 @@ public class FilterListHeader extends FilterListItem {
* Constructor for creating a new FilterListHeader * Constructor for creating a new FilterListHeader
* *
* @param plugin * @param plugin
* {@link Plugin} identifier that encompasses object * {@link Addon} identifier that encompasses object
*/ */
protected FilterListHeader(String plugin) { protected FilterListHeader(String plugin) {
this.plugin = plugin; this.plugin = plugin;

@ -33,7 +33,7 @@ public final class TaskDetail implements Parcelable {
* Creates a TaskDetail object * Creates a TaskDetail object
* *
* @param plugin * @param plugin
* {@link Plugin} identifier that encompasses object * {@link Addon} identifier that encompasses object
* @param text * @param text
* text to display * text to display
* @param color * @param color

@ -4,20 +4,22 @@
<booleanAttribute key="ch.zork.quicklaunch" value="true"/> <booleanAttribute key="ch.zork.quicklaunch" value="true"/>
<stringAttribute key="ch.zork.quicklaunch.icon" value="14.gif"/> <stringAttribute key="ch.zork.quicklaunch.icon" value="14.gif"/>
<intAttribute key="ch.zork.quicklaunch.index" value="0"/> <intAttribute key="ch.zork.quicklaunch.index" value="0"/>
<stringAttribute key="ch.zork.quicklaunch.mode" value="debug"/> <stringAttribute key="ch.zork.quicklaunch.mode" value="run"/>
<intAttribute key="com.android.ide.eclipse.adt.action" value="0"/> <intAttribute key="com.android.ide.eclipse.adt.action" value="0"/>
<stringAttribute key="com.android.ide.eclipse.adt.avd" value="android-22"/> <stringAttribute key="com.android.ide.eclipse.adt.avd" value="mytouch-4"/>
<stringAttribute key="com.android.ide.eclipse.adt.commandline" value="-scale 0.7"/> <stringAttribute key="com.android.ide.eclipse.adt.commandline" value="-scale 0.7"/>
<intAttribute key="com.android.ide.eclipse.adt.delay" value="0"/> <intAttribute key="com.android.ide.eclipse.adt.delay" value="0"/>
<booleanAttribute key="com.android.ide.eclipse.adt.nobootanim" value="true"/> <booleanAttribute key="com.android.ide.eclipse.adt.nobootanim" value="true"/>
<intAttribute key="com.android.ide.eclipse.adt.speed" value="0"/> <intAttribute key="com.android.ide.eclipse.adt.speed" value="0"/>
<booleanAttribute key="com.android.ide.eclipse.adt.target" value="true"/> <booleanAttribute key="com.android.ide.eclipse.adt.target" value="false"/>
<booleanAttribute key="com.android.ide.eclipse.adt.wipedata" value="false"/> <booleanAttribute key="com.android.ide.eclipse.adt.wipedata" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/astrid"/> <listEntry value="/astrid"/>
<listEntry value="/astrid/AndroidManifest.xml"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/> <listEntry value="4"/>
<listEntry value="1"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> <listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> <listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>

@ -10,5 +10,5 @@
# Indicates whether an apk should be generated for each density. # Indicates whether an apk should be generated for each density.
split.density=false split.density=false
# Project target. # Project target.
target=Google Inc.:Google APIs:8 target=android-4
apk-configurations= apk-configurations=

@ -54,7 +54,7 @@ public final class CoreFilterExposer extends BroadcastReceiver {
list[1] = all; list[1] = all;
list[2] = searchFilter; list[2] = searchFilter;
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS); Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ITEMS, list); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
} }

@ -5,7 +5,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Plugin; import com.todoroo.astrid.api.Addon;
public class CorePlugin extends BroadcastReceiver { public class CorePlugin extends BroadcastReceiver {
@ -13,11 +13,11 @@ public class CorePlugin extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
Plugin plugin = new Plugin(IDENTIFIER, "Core Filters", "Todoroo", Addon plugin = new Addon(IDENTIFIER, "Core Filters", "Todoroo",
"Provides 'Inbox' and 'All Tasks' Filters"); "Provides 'Inbox' and 'All Tasks' Filters");
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_PLUGINS); Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_ADDONS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_PLUGIN, plugin); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, plugin);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
} }

@ -82,7 +82,7 @@ public final class ExtendedFilterExposer extends BroadcastReceiver {
list[3] = hidden; list[3] = hidden;
list[4] = deleted; list[4] = deleted;
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS); Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ITEMS, list); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
} }

@ -5,7 +5,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Plugin; import com.todoroo.astrid.api.Addon;
public class ExtendedPlugin extends BroadcastReceiver { public class ExtendedPlugin extends BroadcastReceiver {
@ -13,11 +13,11 @@ public class ExtendedPlugin extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
Plugin plugin = new Plugin(IDENTIFIER, "Extended Filters", "Todoroo", Addon plugin = new Addon(IDENTIFIER, "Extended Filters", "Todoroo",
"Provides extended filters for viewing subsets of your tasks"); "Provides extended filters for viewing subsets of your tasks");
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_PLUGINS); Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_ADDONS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_PLUGIN, plugin); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, plugin);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
} }

@ -51,10 +51,8 @@ public class NoteDetailExposer extends BroadcastReceiver {
TaskDetail taskDetail = new TaskDetail(NotesPlugin.IDENTIFIER, notes); TaskDetail taskDetail = new TaskDetail(NotesPlugin.IDENTIFIER, notes);
// transmit // transmit
TaskDetail[] details = new TaskDetail[1];
details[0] = taskDetail;
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_DETAILS); Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_DETAILS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ITEMS, details); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, taskDetail);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
} }

@ -5,7 +5,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Plugin; import com.todoroo.astrid.api.Addon;
public class NotesPlugin extends BroadcastReceiver { public class NotesPlugin extends BroadcastReceiver {
@ -13,11 +13,11 @@ public class NotesPlugin extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
Plugin plugin = new Plugin(IDENTIFIER, "Notes", "Todoroo", Addon plugin = new Addon(IDENTIFIER, "Notes", "Todoroo",
"Lets you add and view notes for a task."); "Lets you add and view notes for a task.");
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_PLUGINS); Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_ADDONS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_PLUGIN, plugin); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, plugin);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
} }

@ -0,0 +1,214 @@
package com.todoroo.astrid.repeats;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout;
import android.widget.Spinner;
import com.google.ical.values.Frequency;
import com.google.ical.values.RRule;
import com.google.ical.values.Weekday;
import com.google.ical.values.WeekdayNum;
import com.timsu.astrid.R;
import com.timsu.astrid.widget.NumberPicker;
import com.timsu.astrid.widget.NumberPickerDialog;
import com.timsu.astrid.widget.NumberPickerDialog.OnNumberPickedListener;
import com.todoroo.astrid.activity.TaskEditActivity.TaskEditControlSet;
import com.todoroo.astrid.model.Task;
/**
* Control Set for managing repeats
*
* @author Tim Su <tim@todoroo.com>
*
*/
public class RepeatControlSet implements TaskEditControlSet {
private static final int INTERVAL_DAYS = 0;
private static final int INTERVAL_WEEKS = 1;
private static final int INTERVAL_MONTHS = 2;
private static final int INTERVAL_YEARS = 3;
private final Activity activity;
private final CheckBox enabled;
private final Button value;
private final Spinner interval;
private final Spinner type;
private final LinearLayout repeatContainer;
private final LinearLayout daysOfWeekContainer;
private final CompoundButton[] daysOfWeek = new CompoundButton[7];
public RepeatControlSet(final Activity activity, ViewGroup parent) {
this.activity = activity;
LayoutInflater.from(activity).inflate(R.layout.repeat_control, parent, true);
enabled = (CheckBox) activity.findViewById(R.id.repeatEnabled);
value = (Button) activity.findViewById(R.id.repeatValue);
interval = (Spinner) activity.findViewById(R.id.repeatInterval);
type = (Spinner) activity.findViewById(R.id.repeatType);
repeatContainer = (LinearLayout) activity.findViewById(R.id.repeatContainer);
daysOfWeekContainer = (LinearLayout) activity.findViewById(R.id.repeatDayOfWeekContainer);
setRepeatValue(1);
// set up days of week
DateFormatSymbols dfs = new DateFormatSymbols();
Calendar calendar = Calendar.getInstance();
int currentDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek());
LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1.0f/7);
for(int i = 0; i < 7; i++) {
CheckBox checkBox = new CheckBox(activity);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
checkBox.setText(dfs.getShortWeekdays()[dayOfWeek].substring(0, 1));
checkBox.setLayoutParams(lp);
checkBox.setTextSize(10);
checkBox.setTag(Weekday.values()[dayOfWeek - 1]);
if(dayOfWeek == currentDayOfWeek)
checkBox.setChecked(true);
daysOfWeek[i] = checkBox;
calendar.add(Calendar.DATE, 1);
daysOfWeekContainer.addView(checkBox);
}
// set up listeners
enabled.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
repeatContainer.setVisibility(isChecked ? View.VISIBLE : View.GONE);
}
});
value.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
repeatValueClick();
}
});
interval.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parentView, View view, int position, long id) {
daysOfWeekContainer.setVisibility(position == INTERVAL_WEEKS ? View.VISIBLE : View.GONE);
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
//
}
});
}
/** Set up the repeat value button */
private void setRepeatValue(int newValue) {
value.setText(activity.getString(R.string.repeat_every, newValue));
value.setTag(newValue);
}
protected void repeatValueClick() {
final int tagValue = (Integer)value.getTag();
final Runnable openDialogRunnable = new Runnable() {
public void run() {
int dialogValue = tagValue;
if(dialogValue == 0)
dialogValue = 1;
new NumberPickerDialog(activity, new OnNumberPickedListener() {
@Override
public void onNumberPicked(NumberPicker view,
int number) {
setRepeatValue(number);
}
}, activity.getResources().getString(R.string.repeat_picker_title),
dialogValue, 1, 1, 365).show();
}
};
openDialogRunnable.run();
}
@Override
public void readFromTask(Task task) {
String recurrence = task.getValue(Task.RECURRENCE);
if(recurrence.length() > 0) {
try {
RRule rrule = new RRule(recurrence);
setRepeatValue(rrule.getInterval());
switch(rrule.getFreq()) {
case DAILY:
interval.setSelection(INTERVAL_DAYS);
break;
case WEEKLY: {
interval.setSelection(INTERVAL_WEEKS);
for(WeekdayNum day : rrule.getByDay()) {
for(int i = 0; i < 7; i++)
if(daysOfWeek[i].getTag() == day.wday)
daysOfWeek[i].setChecked(true);
}
break;
}
case MONTHLY:
interval.setSelection(INTERVAL_MONTHS);
break;
case YEARLY:
interval.setSelection(INTERVAL_YEARS);
break;
}
} catch (ParseException e) {
recurrence = ""; //$NON-NLS-1$
}
}
enabled.setChecked(recurrence.length() > 0);
repeatContainer.setVisibility(enabled.isChecked() ? View.VISIBLE : View.GONE);
}
@Override
public void writeToModel(Task task) {
String result;
if(!enabled.isChecked())
result = ""; //$NON-NLS-1$
else {
RRule rrule = new RRule();
rrule.setInterval((Integer)value.getTag());
switch(interval.getSelectedItemPosition()) {
case INTERVAL_DAYS:
rrule.setFreq(Frequency.DAILY);
break;
case INTERVAL_WEEKS: {
rrule.setFreq(Frequency.WEEKLY);
ArrayList<WeekdayNum> days = new ArrayList<WeekdayNum>();
for(int i = 0; i < daysOfWeek.length; i++)
if(daysOfWeek[i].isChecked())
days.add(new WeekdayNum(0, (Weekday)daysOfWeek[i].getTag()));
rrule.setByDay(days);
break;
}
case INTERVAL_MONTHS:
rrule.setFreq(Frequency.MONTHLY);
break;
case INTERVAL_YEARS:
rrule.setFreq(Frequency.YEARLY);
}
result = rrule.toIcal();
}
task.setValue(Task.RECURRENCE, result);
}
}

@ -0,0 +1,26 @@
package com.todoroo.astrid.repeats;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.timsu.astrid.R;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Addon;
public class RepeatsPlugin extends BroadcastReceiver {
static final String IDENTIFIER = "repeats"; //$NON-NLS-1$
@Override
public void onReceive(Context context, Intent intent) {
Addon plugin = new Addon(IDENTIFIER, context.getString(R.string.repeat_plugin),
context.getString(R.string.AOA_internal_author),
context.getString(R.string.repeat_plugin_desc));
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_ADDONS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, plugin);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
}

@ -39,10 +39,8 @@ public class TagDetailExposer extends BroadcastReceiver {
context.getString(R.string.tag_TLA_detail, tagList)); context.getString(R.string.tag_TLA_detail, tagList));
// transmit // transmit
TaskDetail[] details = new TaskDetail[1];
details[0] = taskDetail;
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_DETAILS); Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_DETAILS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ITEMS, details); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, taskDetail);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
} }

@ -97,7 +97,7 @@ public class TagFilterExposer extends BroadcastReceiver {
list[2] = tagsCategoryBySize; list[2] = tagsCategoryBySize;
list[3] = tagsCategoryByAlpha; list[3] = tagsCategoryByAlpha;
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS); Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ITEMS, list); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
} }

@ -5,7 +5,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Plugin; import com.todoroo.astrid.api.Addon;
public class TagsPlugin extends BroadcastReceiver { public class TagsPlugin extends BroadcastReceiver {
@ -13,11 +13,11 @@ public class TagsPlugin extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
Plugin plugin = new Plugin(IDENTIFIER, "Tags", "Todoroo", Addon plugin = new Addon(IDENTIFIER, "Tags", "Todoroo",
"Provides tagging support for tasks."); "Provides tagging support for tasks.");
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_PLUGINS); Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_ADDONS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_PLUGIN, plugin); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ADDON, plugin);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
} }

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- See the file "LICENSE" for the full license governing this code. -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<View
android:layout_width="fill_parent"
android:layout_height="1dip"
android:padding="5dip"
android:background="@android:drawable/divider_horizontal_dark" />
<CheckBox android:id="@+id/repeatEnabled"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/repeat_enabled"/>
<LinearLayout android:id="@+id/repeatContainer"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button android:id="@+id/repeatValue"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Spinner android:id="@+id/repeatInterval"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:prompt="@string/repeat_interval_prompt"
android:entries="@array/repeat_interval"/>
</LinearLayout>
<Spinner android:id="@+id/repeatType"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:entries="@array/repeat_type"/>
<LinearLayout android:id="@+id/repeatDayOfWeekContainer"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</merge>

@ -196,43 +196,16 @@
android:paddingBottom="5dip" android:paddingBottom="5dip"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<View
android:layout_width="fill_parent"
android:layout_height="1dip"
android:padding="5dip"
android:background="@android:drawable/divider_horizontal_dark" />
<!-- repeat --> <!-- add-ons -->
<TextView <LinearLayout android:id="@+id/tab_extra_addons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/repeat_label"
android:visibility="gone"
style="@style/TextAppearance.GEN_EditLabel" />
<LinearLayout
android:orientation="horizontal"
android:paddingRight="10dip"
android:visibility="gone"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
<Button android:orientation="vertical" />
android:id="@+id/repeat_value"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Spinner
android:id="@+id/repeat_interval"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- separator -->
<View <View
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="1dip" android:layout_height="1dip"
android:visibility="gone"
android:padding="5dip" android:padding="5dip"
android:background="@android:drawable/divider_horizontal_dark" /> android:background="@android:drawable/divider_horizontal_dark" />
@ -332,6 +305,12 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<!-- add-ons -->
<LinearLayout android:id="@+id/tab_addons_addons"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
<!-- separator --> <!-- separator -->
<View <View
android:layout_width="fill_parent" android:layout_width="fill_parent"

@ -18,7 +18,7 @@
<!-- permission description for READ_TASKS --> <!-- permission description for READ_TASKS -->
<string name="write_permission_desc">create new tasks, edit existing tasks</string> <string name="write_permission_desc">create new tasks, edit existing tasks</string>
<!-- ======================== Generic Plurals ========================== --> <!-- ==================================================== Generic Units == -->
<plurals name="DUt_years"> <plurals name="DUt_years">
<!-- plurals: years --> <!-- plurals: years -->
@ -397,4 +397,10 @@ If you don\'t want to see the new task right after you complete the old one, you
<!-- Default Hide Until Description (%s => setting) --> <!-- Default Hide Until Description (%s => setting) -->
<string name="EPr_default_hideUntil_desc">Currently Set To: %s</string> <string name="EPr_default_hideUntil_desc">Currently Set To: %s</string>
<!-- ==================================================== AddOnActivity == -->
<!-- Add Ons: author for internal authors -->
<string name="AOA_internal_author">Astrid Team</string>
</resources> </resources>

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- See the file "LICENSE" for the full license governing this code. -->
<resources>
<!-- Resources for built-in repeat plug-in -->
<!-- repeating plugin name -->
<string name="repeat_plugin">Repeating Tasks</string>
<!-- repeating plugin description -->
<string name="repeat_plugin_desc">Allows tasks to repeat</string>
<!-- checkbox for turning on/off repeats -->
<string name="repeat_enabled">Repeats</string>
<!-- button for "every x" part of repeat (%d -> repeat value) -->
<string name="repeat_every">Every %d</string>
<!-- hint when opening repeat interval -->
<string name="repeat_interval_prompt">Repeat Interval</string>
<string-array name="repeat_interval">
<!-- repeat interval (days,weeks,months,hours) -->
<item>Day(s)</item>
<item>Week(s)</item>
<item>Month(s)</item>
<item>Year(s)</item>
</string-array>
<string-array name="repeat_type">
<!-- repeat type (date to repeat from) -->
<item>from due date</item>
<item>from completion date</item>
</string-array>
</resources>

@ -183,14 +183,14 @@ public class FilterListActivity extends ExpandableListActivity {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
try { try {
Parcelable[] filters = intent.getExtras(). Parcelable[] filters = intent.getExtras().
getParcelableArray(AstridApiConstants.EXTRAS_ITEMS); getParcelableArray(AstridApiConstants.EXTRAS_RESPONSE);
for (Parcelable item : filters) { for (Parcelable item : filters) {
adapter.add((FilterListItem)item); adapter.add((FilterListItem)item);
} }
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
} catch (Exception e) { } catch (Exception e) {
exceptionService.reportError("receive-filter-" + //$NON-NLS-1$ exceptionService.reportError("receive-filter-" + //$NON-NLS-1$
intent.getStringExtra(AstridApiConstants.EXTRAS_PLUGIN), e); intent.getStringExtra(AstridApiConstants.EXTRAS_ADDON), e);
} }
} }
} }

@ -27,13 +27,16 @@ import java.util.List;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.DatePickerDialog; import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.TabActivity; import android.app.TabActivity;
import android.app.TimePickerDialog; import android.app.TimePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.TimePickerDialog.OnTimeSetListener; import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.BroadcastReceiver;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
@ -44,6 +47,7 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView; import android.widget.AutoCompleteTextView;
import android.widget.Button; import android.widget.Button;
@ -53,35 +57,32 @@ import android.widget.DatePicker;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RemoteViews;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TabHost; import android.widget.TabHost;
import android.widget.TextView; import android.widget.TextView;
import android.widget.TimePicker; import android.widget.TimePicker;
import android.widget.Toast; import android.widget.Toast;
import android.widget.ToggleButton; import android.widget.ToggleButton;
import android.widget.AdapterView.OnItemSelectedListener;
import com.flurry.android.FlurryAgent; import com.flurry.android.FlurryAgent;
import com.timsu.astrid.R; import com.timsu.astrid.R;
import com.timsu.astrid.data.enums.RepeatInterval;
import com.timsu.astrid.data.task.TaskModelForEdit; import com.timsu.astrid.data.task.TaskModelForEdit;
import com.timsu.astrid.data.task.AbstractTaskModel.RepeatInfo;
import com.timsu.astrid.utilities.AstridUtilities; import com.timsu.astrid.utilities.AstridUtilities;
import com.timsu.astrid.widget.NumberPicker;
import com.timsu.astrid.widget.NumberPickerDialog;
import com.timsu.astrid.widget.TimeDurationControlSet; import com.timsu.astrid.widget.TimeDurationControlSet;
import com.timsu.astrid.widget.NumberPickerDialog.OnNumberPickedListener;
import com.timsu.astrid.widget.TimeDurationControlSet.TimeDurationType; import com.timsu.astrid.widget.TimeDurationControlSet.TimeDurationType;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.Property.IntegerProperty; import com.todoroo.andlib.data.Property.IntegerProperty;
import com.todoroo.andlib.data.Property.StringProperty; import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService; import com.todoroo.andlib.service.ExceptionService;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.dao.Database; import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.model.Metadata; import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task; import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.repeats.RepeatControlSet;
import com.todoroo.astrid.service.StartupService; import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.service.TaskService; import com.todoroo.astrid.service.TaskService;
import com.todoroo.astrid.tags.TagService; import com.todoroo.astrid.tags.TagService;
@ -155,6 +156,9 @@ public final class TaskEditActivity extends TabActivity {
/** whether task should be saved when this activity exits */ /** whether task should be saved when this activity exits */
private boolean shouldSaveState = true; private boolean shouldSaveState = true;
/** edit control receiver */
private final ControlReceiver controlReceiver = new ControlReceiver();
/* ====================================================================== /* ======================================================================
* ======================================================= initialization * ======================================================= initialization
* ====================================================================== */ * ====================================================================== */
@ -214,7 +218,6 @@ public final class TaskEditActivity extends TabActivity {
controls.add( new RandomReminderControlSet(R.id.reminder_random, controls.add( new RandomReminderControlSet(R.id.reminder_random,
R.id.reminder_random_interval)); R.id.reminder_random_interval));
controls.add(new TagsControlSet(R.id.tags_container)); controls.add(new TagsControlSet(R.id.tags_container));
controls.add(new RepeatControlSet(R.id.repeat_value, R.id.repeat_interval));
controls.add(new CalendarControlSet(R.id.add_to_calendar, R.id.view_calendar_event)); controls.add(new CalendarControlSet(R.id.add_to_calendar, R.id.view_calendar_event));
controls.add(new TimeDurationTaskEditControlSet(Task.ESTIMATED_SECONDS, controls.add(new TimeDurationTaskEditControlSet(Task.ESTIMATED_SECONDS,
@ -224,9 +227,18 @@ public final class TaskEditActivity extends TabActivity {
0, R.string.hour_minutes_dialog, 0, R.string.hour_minutes_dialog,
TimeDurationType.HOURS_MINUTES)); TimeDurationType.HOURS_MINUTES));
// internal add-ins
LinearLayout extrasAddons = (LinearLayout) findViewById(R.id.tab_extra_addons);
controls.add(new RepeatControlSet(this, extrasAddons));
// read data // read data
populateFields(); populateFields();
// request add-on controls
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_REQUEST_EDIT_CONTROLS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, model.getId());
sendOrderedBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
// set up listeners // set up listeners
setUpListeners(); setUpListeners();
} }
@ -324,7 +336,7 @@ public final class TaskEditActivity extends TabActivity {
setTitle(r.getString(R.string.TEA_view_title, model.getValue(Task.TITLE))); setTitle(r.getString(R.string.TEA_view_title, model.getValue(Task.TITLE)));
for(TaskEditControlSet controlSet : controls) for(TaskEditControlSet controlSet : controls)
controlSet.readFromModel(); controlSet.readFromTask(model);
} }
/** Save task model from values in UI components */ /** Save task model from values in UI components */
@ -338,12 +350,45 @@ public final class TaskEditActivity extends TabActivity {
} }
for(TaskEditControlSet controlSet : controls) for(TaskEditControlSet controlSet : controls)
controlSet.writeToModel(); controlSet.writeToModel(model);
taskService.save(model, false); taskService.save(model, false);
showSaveToast(); showSaveToast();
} }
/* ======================================================================
* ================================================ edit control handling
* ====================================================================== */
/**
* Receiver which receives intents to add items to the filter list
*
* @author Tim Su <tim@todoroo.com>
*
*/
protected class ControlReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
Bundle extras = intent.getExtras();
RemoteViews view = extras.getParcelable(AstridApiConstants.EXTRAS_RESPONSE);
// add a separator
View separator = new View(TaskEditActivity.this);
separator.setPadding(5, 5, 5, 5);
separator.setBackgroundResource(android.R.drawable.divider_horizontal_dark);
LinearLayout dest = (LinearLayout)findViewById(R.id.tab_addons_addons);
dest.addView(separator);
view.apply(TaskEditActivity.this, dest);
} catch (Exception e) {
exceptionService.reportError("receive-detail-" + //$NON-NLS-1$
intent.getStringExtra(AstridApiConstants.EXTRAS_ADDON), e);
}
}
}
/* ====================================================================== /* ======================================================================
* ======================================================= event handlers * ======================================================= event handlers
* ====================================================================== */ * ====================================================================== */
@ -475,13 +520,15 @@ public final class TaskEditActivity extends TabActivity {
protected void onPause() { protected void onPause() {
if(shouldSaveState) if(shouldSaveState)
save(); save();
super.onPause(); super.onPause();
unregisterReceiver(controlReceiver);
} }
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
registerReceiver(controlReceiver,
new IntentFilter(AstridApiConstants.BROADCAST_SEND_EDIT_CONTROLS));
} }
@Override @Override
@ -517,12 +564,12 @@ public final class TaskEditActivity extends TabActivity {
/** /**
* Read data from model to update the control set * Read data from model to update the control set
*/ */
public void readFromModel(); public void readFromTask(Task task);
/** /**
* Write data from control set to model * Write data from control set to model
*/ */
public void writeToModel(); public void writeToModel(Task task);
} }
// --- EditTextControlSet // --- EditTextControlSet
@ -542,13 +589,13 @@ public final class TaskEditActivity extends TabActivity {
} }
@Override @Override
public void readFromModel() { public void readFromTask(Task task) {
editText.setText(model.getValue(property)); editText.setText(task.getValue(property));
} }
@Override @Override
public void writeToModel() { public void writeToModel(Task task) {
model.setValue(property, editText.getText().toString()); task.setValue(property, editText.getText().toString());
} }
} }
@ -571,13 +618,13 @@ public final class TaskEditActivity extends TabActivity {
} }
@Override @Override
public void readFromModel() { public void readFromTask(Task task) {
controlSet.setTimeDuration(model.getValue(property)); controlSet.setTimeDuration(task.getValue(property));
} }
@Override @Override
public void writeToModel() { public void writeToModel(Task task) {
model.setValue(property, controlSet.getTimeDurationInSeconds()); task.setValue(property, controlSet.getTimeDurationInSeconds());
} }
} }
@ -643,13 +690,13 @@ public final class TaskEditActivity extends TabActivity {
} }
@Override @Override
public void readFromModel() { public void readFromTask(Task task) {
setImportance(model.getValue(Task.IMPORTANCE)); setImportance(task.getValue(Task.IMPORTANCE));
} }
@Override @Override
public void writeToModel() { public void writeToModel(Task task) {
model.setValue(Task.IMPORTANCE, getImportance()); task.setValue(Task.IMPORTANCE, getImportance());
} }
} }
@ -812,15 +859,15 @@ public final class TaskEditActivity extends TabActivity {
// --- setting up values // --- setting up values
@Override @Override
public void readFromModel() { public void readFromTask(Task task) {
long dueDate = model.getValue(Task.DUE_DATE); long dueDate = task.getValue(Task.DUE_DATE);
createUrgencyList(dueDate); createUrgencyList(dueDate);
} }
@Override @Override
public void writeToModel() { public void writeToModel(Task task) {
UrgencyValue item = urgencyAdapter.getItem(urgency.getSelectedItemPosition()); UrgencyValue item = urgencyAdapter.getItem(urgency.getSelectedItemPosition());
model.setValue(Task.DUE_DATE, item.dueDate); task.setValue(Task.DUE_DATE, item.dueDate);
} }
} }
@ -938,9 +985,9 @@ public final class TaskEditActivity extends TabActivity {
// --- setting up values // --- setting up values
@Override @Override
public void readFromModel() { public void readFromTask(Task task) {
long date = model.getValue(Task.HIDE_UNTIL); long date = task.getValue(Task.HIDE_UNTIL);
long dueDate = model.getValue(Task.DUE_DATE); long dueDate = task.getValue(Task.DUE_DATE);
int selection = 0; int selection = 0;
if(date == 0) { if(date == 0) {
@ -968,10 +1015,10 @@ public final class TaskEditActivity extends TabActivity {
} }
@Override @Override
public void writeToModel() { public void writeToModel(Task task) {
HideUntilValue item = adapter.getItem(hideUntil.getSelectedItemPosition()); HideUntilValue item = adapter.getItem(hideUntil.getSelectedItemPosition());
long value = model.createHideUntil(item.setting, item.date); long value = task.createHideUntil(item.setting, item.date);
model.setValue(Task.HIDE_UNTIL, value); task.setValue(Task.HIDE_UNTIL, value);
} }
} }
@ -1021,13 +1068,13 @@ public final class TaskEditActivity extends TabActivity {
} }
@Override @Override
public void readFromModel() { public void readFromTask(Task task) {
setValue(model.getValue(Task.REMINDER_FLAGS)); setValue(task.getValue(Task.REMINDER_FLAGS));
} }
@Override @Override
public void writeToModel() { public void writeToModel(Task task) {
model.setValue(Task.REMINDER_FLAGS, getValue()); task.setValue(Task.REMINDER_FLAGS, getValue());
} }
} }
@ -1076,8 +1123,8 @@ public final class TaskEditActivity extends TabActivity {
} }
@Override @Override
public void readFromModel() { public void readFromTask(Task task) {
long time = model.getValue(Task.REMINDER_PERIOD); long time = task.getValue(Task.REMINDER_PERIOD);
boolean shouldDisable = time <= 0; boolean shouldDisable = time <= 0;
if(time <= 0) { if(time <= 0) {
@ -1093,12 +1140,12 @@ public final class TaskEditActivity extends TabActivity {
} }
@Override @Override
public void writeToModel() { public void writeToModel(Task task) {
if(settingCheckbox.isChecked()) { if(settingCheckbox.isChecked()) {
int hourValue = hours[periodSpinner.getSelectedItemPosition()]; int hourValue = hours[periodSpinner.getSelectedItemPosition()];
model.setValue(Task.REMINDER_PERIOD, hourValue * DateUtilities.ONE_HOUR); task.setValue(Task.REMINDER_PERIOD, hourValue * DateUtilities.ONE_HOUR);
} else } else
model.setValue(Task.REMINDER_PERIOD, 0L); task.setValue(Task.REMINDER_PERIOD, 0L);
} }
} }
@ -1121,10 +1168,10 @@ public final class TaskEditActivity extends TabActivity {
@SuppressWarnings("nls") @SuppressWarnings("nls")
@Override @Override
public void readFromModel() { public void readFromTask(Task task) {
// tags (only configure if not already set) // tags (only configure if not already set)
if(tagsContainer.getChildCount() == 0) { if(tagsContainer.getChildCount() == 0) {
TodorooCursor<Metadata> cursor = tagService.getTags(model.getId()); TodorooCursor<Metadata> cursor = tagService.getTags(task.getId());
try { try {
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext())
addTag(cursor.get(Metadata.VALUE)); addTag(cursor.get(Metadata.VALUE));
@ -1136,7 +1183,7 @@ public final class TaskEditActivity extends TabActivity {
} }
@Override @Override
public void writeToModel() { public void writeToModel(Task task) {
ArrayList<String> tags = new ArrayList<String>(); ArrayList<String> tags = new ArrayList<String>();
for(int i = 0; i < tagsContainer.getChildCount(); i++) { for(int i = 0; i < tagsContainer.getChildCount(); i++) {
@ -1146,7 +1193,7 @@ public final class TaskEditActivity extends TabActivity {
tags.add(tagName.getText().toString()); tags.add(tagName.getText().toString());
} }
tagService.synchronizeTags(model.getId(), tags); tagService.synchronizeTags(task.getId(), tags);
} }
/** Adds a tag to the tag field */ /** Adds a tag to the tag field */
@ -1180,6 +1227,7 @@ public final class TaskEditActivity extends TabActivity {
// //
} }
public void beforeTextChanged(CharSequence s, int start, int count, public void beforeTextChanged(CharSequence s, int start, int count,
int after) { int after) {
// //
@ -1198,85 +1246,6 @@ public final class TaskEditActivity extends TabActivity {
} }
} }
public class RepeatControlSet implements TaskEditControlSet {
private final Button repeatValue;
private final Spinner repeatInterval;
public RepeatControlSet(int repeatValue, int repeatInterval) {
this.repeatValue = (Button) findViewById(repeatValue);
this.repeatInterval = (Spinner) findViewById(repeatInterval);
ArrayAdapter<String> repeatAdapter = new ArrayAdapter<String>(
TaskEditActivity.this, android.R.layout.simple_spinner_item,
RepeatInterval.getLabels(getResources()));
repeatAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
this.repeatInterval.setAdapter(repeatAdapter);
this.repeatValue.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
repeatValueClick();
}
});
}
/** Set up the repeat value button */
void setRepeatValue(int value) {
if(value == 0)
repeatValue.setText(R.string.repeat_value_unset);
else
repeatValue.setText(Integer.toString(value));
repeatValue.setTag(value);
}
private RepeatInfo getRepeatValue() {
if(repeatValue.getTag() == null || repeatValue.getTag().equals(0))
return null;
return new RepeatInfo(RepeatInterval.values()
[repeatInterval.getSelectedItemPosition()],
(Integer)repeatValue.getTag());
}
protected void repeatValueClick() {
final int tagValue = (Integer)repeatValue.getTag();
final Runnable openDialogRunnable = new Runnable() {
public void run() {
int dialogValue = tagValue;
if(dialogValue == 0)
dialogValue = 1;
new NumberPickerDialog(TaskEditActivity.this, new OnNumberPickedListener() {
public void onNumberPicked(NumberPicker view, int number) {
setRepeatValue(number);
}
}, getResources().getString(R.string.repeat_picker_title),
dialogValue, 1, 0, 31).show();
}
};
openDialogRunnable.run();
}
@Override
public void readFromModel() {
// repeats
RepeatInfo repeatInfo = RepeatInfo.fromSingleField(model.getValue(Task.REPEAT));
if(repeatInfo != null) {
setRepeatValue(repeatInfo.getValue());
repeatInterval.setSelection(repeatInfo.getInterval().ordinal());
} else
setRepeatValue(0);
}
@Override
public void writeToModel() {
RepeatInfo repeatInfo = getRepeatValue();
model.setValue(Task.REPEAT, RepeatInfo.toSingleField(repeatInfo));
}
}
/** /**
* Calendar Control Set * Calendar Control Set
* @author Tim Su <tim@todoroo.com> * @author Tim Su <tim@todoroo.com>
@ -1373,11 +1342,11 @@ public final class TaskEditActivity extends TabActivity {
} }
@Override @Override
public void readFromModel() { public void readFromTask(Task task) {
} }
@Override @Override
public void writeToModel() { public void writeToModel(Task task) {
} }
} }

@ -18,28 +18,27 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.database.Cursor; import android.database.Cursor;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcelable;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.Window;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.View.OnKeyListener; import android.view.View.OnKeyListener;
import android.view.Window;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.AbsListView; import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ListView; import android.widget.ListView;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.TextView.OnEditorActionListener; import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import com.flurry.android.FlurryAgent; import com.flurry.android.FlurryAgent;
import com.timsu.astrid.R; import com.timsu.astrid.R;
@ -417,12 +416,11 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
try { try {
Bundle extras = intent.getExtras(); Bundle extras = intent.getExtras();
long taskId = extras.getLong(AstridApiConstants.EXTRAS_TASK_ID); long taskId = extras.getLong(AstridApiConstants.EXTRAS_TASK_ID);
Parcelable[] details = extras.getParcelableArray(AstridApiConstants.EXTRAS_ITEMS); TaskDetail detail = extras.getParcelable(AstridApiConstants.EXTRAS_RESPONSE);
for(Parcelable detail : details) taskAdapter.addDetails(getListView(), taskId, detail);
taskAdapter.addDetails(getListView(), taskId, (TaskDetail)detail);
} catch (Exception e) { } catch (Exception e) {
exceptionService.reportError("receive-detail-" + //$NON-NLS-1$ exceptionService.reportError("receive-detail-" + //$NON-NLS-1$
intent.getStringExtra(AstridApiConstants.EXTRAS_PLUGIN), e); intent.getStringExtra(AstridApiConstants.EXTRAS_ADDON), e);
} }
} }
} }

@ -20,7 +20,7 @@ public class SearchFilter extends FilterListItem {
* Constructor for creating a new SearchFilter * Constructor for creating a new SearchFilter
* *
* @param plugin * @param plugin
* {@link Plugin} identifier that encompasses object * {@link Addon} identifier that encompasses object
* @param listingTitle * @param listingTitle
* Title of this item as displayed on the lists page, e.g. Inbox * Title of this item as displayed on the lists page, e.g. Inbox
*/ */
@ -33,7 +33,7 @@ public class SearchFilter extends FilterListItem {
* Constructor for creating a new SearchFilter * Constructor for creating a new SearchFilter
* *
* @param plugin * @param plugin
* {@link Plugin} identifier that encompasses object * {@link Addon} identifier that encompasses object
*/ */
protected SearchFilter(String plugin) { protected SearchFilter(String plugin) {
this.plugin = plugin; this.plugin = plugin;

@ -25,7 +25,7 @@ public final class Database extends AbstractDatabase {
* Database version number. This variable must be updated when database * Database version number. This variable must be updated when database
* tables are updated, as it determines whether a database needs updating. * tables are updated, as it determines whether a database needs updating.
*/ */
public static final int VERSION = 1; public static final int VERSION = 2;
/** /**
* Database name (must be unique) * Database name (must be unique)
@ -73,6 +73,17 @@ public final class Database extends AbstractDatabase {
@Override @Override
protected boolean onUpgrade(int oldVersion, int newVersion) { protected boolean onUpgrade(int oldVersion, int newVersion) {
switch(oldVersion) {
case 1: {
SqlConstructorVisitor visitor = new SqlConstructorVisitor();
String sql = "ALTER TABLE " + Task.TABLE.name + " ADD " +
Task.RECURRENCE.accept(visitor, null);
database.execSQL(sql);
return true;
}
}
return false; return false;
} }

@ -5,15 +5,25 @@
*/ */
package com.todoroo.astrid.dao; package com.todoroo.astrid.dao;
import java.text.ParseException;
import java.util.Date;
import java.util.TimeZone;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.google.ical.iter.RecurrenceIterator;
import com.google.ical.iter.RecurrenceIteratorFactory;
import com.google.ical.values.DateTimeValueImpl;
import com.google.ical.values.DateValue;
import com.google.ical.values.DateValueImpl;
import com.timsu.astrid.R; import com.timsu.astrid.R;
import com.todoroo.andlib.data.GenericDao; import com.todoroo.andlib.data.GenericDao;
import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService;
import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
@ -36,6 +46,9 @@ public class TaskDao extends GenericDao<Task> {
@Autowired @Autowired
Database database; Database database;
@Autowired
ExceptionService exceptionService;
ReminderService reminderService; ReminderService reminderService;
public TaskDao() { public TaskDao() {
@ -273,6 +286,57 @@ public class TaskDao extends GenericDao<Task> {
* @param duringSync * @param duringSync
*/ */
private void afterComplete(Task task, ContentValues values, boolean duringSync) { private void afterComplete(Task task, ContentValues values, boolean duringSync) {
task = fetch(task.getId(), Task.ID, Task.RECURRENCE, Task.DUE_DATE);
if(task == null)
return;
String recurrence = task.getValue(Task.RECURRENCE);
if(recurrence.length() > 0) {
Date date = new Date();
DateValue today = new DateValueImpl(date.getYear() + 1900, date.getMonth() + 1, date.getDate());
DateValue dateValue;
if(task.hasDueDate() && task.hasDueTime()) {
date = new Date(task.getValue(Task.DUE_DATE));
dateValue = new DateTimeValueImpl(date.getYear() + 1900,
date.getMonth() + 1, date.getDate(),
date.getHours(), date.getMinutes(), date.getSeconds());
} else if(task.hasDueDate()) {
date = new Date(task.getValue(Task.DUE_DATE));
dateValue = new DateValueImpl(date.getYear() + 1900, date.getMonth() + 1, date.getDate());
} else {
dateValue = today;
}
try {
RecurrenceIterator iterator = RecurrenceIteratorFactory.createRecurrenceIterator(recurrence,
dateValue, TimeZone.getDefault());
if(dateValue.compareTo(today) < 0)
dateValue = today;
iterator.advanceTo(dateValue);
iterator.next();
if(iterator.hasNext()) {
long dueDate;
DateValue newDate = iterator.next();
if(newDate instanceof DateTimeValueImpl) {
DateTimeValueImpl newDateTime = (DateTimeValueImpl)newDate;
dueDate = task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME,
new Date(newDateTime.year() - 1900, newDateTime.month() - 1,
newDateTime.day(), newDateTime.hour(),
newDateTime.minute(), newDateTime.second()).getTime());
} else {
dueDate = task.createDueDate(Task.URGENCY_SPECIFIC_DAY,
new Date(newDate.year() - 1900, newDate.month() - 1,
newDate.day()).getTime());
}
task.setValue(Task.DUE_DATE, dueDate);
task.setValue(Task.COMPLETION_DATE, 0L);
persist(task);
}
} catch (ParseException e) {
exceptionService.reportError("recurrence-rule: " + recurrence, e); //$NON-NLS-1$
}
}
/*Cursor cursor = fetchTaskCursor(task.getTaskIdentifier(), /*Cursor cursor = fetchTaskCursor(task.getTaskIdentifier(),
TaskModelForHandlers.FIELD_LIST); TaskModelForHandlers.FIELD_LIST);
TaskModelForHandlers model = new TaskModelForHandlers(cursor, values); TaskModelForHandlers model = new TaskModelForHandlers(cursor, values);

@ -12,7 +12,6 @@ import android.content.ContentValues;
import android.content.res.Resources; import android.content.res.Resources;
import com.timsu.astrid.R; import com.timsu.astrid.R;
import com.timsu.astrid.data.task.AbstractTaskModel.RepeatInfo;
import com.todoroo.andlib.data.AbstractModel; import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.Property; import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.Property.IntegerProperty; import com.todoroo.andlib.data.Property.IntegerProperty;
@ -103,8 +102,8 @@ public final class Task extends AbstractModel {
public static final LongProperty REMINDER_LAST = new LongProperty( public static final LongProperty REMINDER_LAST = new LongProperty(
TABLE, "lastNotified"); TABLE, "lastNotified");
public static final IntegerProperty REPEAT = new IntegerProperty( public static final StringProperty RECURRENCE = new StringProperty(
TABLE, "repeat"); TABLE, "recurrence");
public static final IntegerProperty FLAGS = new IntegerProperty( public static final IntegerProperty FLAGS = new IntegerProperty(
TABLE, "flags"); TABLE, "flags");
@ -164,7 +163,7 @@ public final class Task extends AbstractModel {
defaultValues.put(IMPORTANCE.name, IMPORTANCE_NONE); defaultValues.put(IMPORTANCE.name, IMPORTANCE_NONE);
defaultValues.put(CALENDAR_URI.name, ""); defaultValues.put(CALENDAR_URI.name, "");
defaultValues.put(REPEAT.name, 0); defaultValues.put(RECURRENCE.name, "");
defaultValues.put(REMINDER_PERIOD.name, 0); defaultValues.put(REMINDER_PERIOD.name, 0);
defaultValues.put(REMINDER_FLAGS.name, 0); defaultValues.put(REMINDER_FLAGS.name, 0);
defaultValues.put(ESTIMATED_SECONDS.name, 0); defaultValues.put(ESTIMATED_SECONDS.name, 0);
@ -244,13 +243,6 @@ public final class Task extends AbstractModel {
return (getValue(property) & flag) > 0; return (getValue(property) & flag) > 0;
} }
/**
* @return repeat data structure. Requires REPEAT
*/
public RepeatInfo getRepeatInfo() {
return RepeatInfo.fromSingleField(getValue(Task.REPEAT));
}
// --- due and hide until date management // --- due and hide until date management
/** urgency array index -> significance */ /** urgency array index -> significance */

@ -12,8 +12,8 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log; import android.util.Log;
import com.timsu.astrid.R; import com.timsu.astrid.R;
@ -141,7 +141,7 @@ public class Astrid2To3UpgradeHelper {
propertyMap.put(AbstractTaskModel.NOTIFICATIONS, Task.REMINDER_PERIOD); propertyMap.put(AbstractTaskModel.NOTIFICATIONS, Task.REMINDER_PERIOD);
propertyMap.put(AbstractTaskModel.NOTIFICATION_FLAGS, Task.REMINDER_FLAGS); propertyMap.put(AbstractTaskModel.NOTIFICATION_FLAGS, Task.REMINDER_FLAGS);
propertyMap.put(AbstractTaskModel.LAST_NOTIFIED, Task.REMINDER_LAST); propertyMap.put(AbstractTaskModel.LAST_NOTIFIED, Task.REMINDER_LAST);
propertyMap.put(AbstractTaskModel.REPEAT, Task.REPEAT); // propertyMap.put(AbstractTaskModel.REPEAT, Task.REPEAT); // TODO
propertyMap.put(AbstractTaskModel.CREATION_DATE, Task.CREATION_DATE); propertyMap.put(AbstractTaskModel.CREATION_DATE, Task.CREATION_DATE);
propertyMap.put(AbstractTaskModel.COMPLETION_DATE, Task.COMPLETION_DATE); propertyMap.put(AbstractTaskModel.COMPLETION_DATE, Task.COMPLETION_DATE);
propertyMap.put(AbstractTaskModel.CALENDAR_URI, Task.CALENDAR_URI); propertyMap.put(AbstractTaskModel.CALENDAR_URI, Task.CALENDAR_URI);

@ -84,6 +84,15 @@ public class AstridDependencyInjector implements AbstractDependencyInjector {
injectables.put("minutesAbbrevResource", R.plurals.DUt_minutesShort); injectables.put("minutesAbbrevResource", R.plurals.DUt_minutesShort);
injectables.put("secondsAbbrevResource", R.plurals.DUt_secondsShort); injectables.put("secondsAbbrevResource", R.plurals.DUt_secondsShort);
// com.todoroo.android.utility
injectables.put("nNumberPickerLayout", R.layout.n_number_picker_dialog);
injectables.put("numberPickerLayout", R.layout.number_picker);
injectables.put("numberPickerIncrementId", R.id.increment);
injectables.put("numberPickerDecrementId", R.id.decrement);
injectables.put("numberPickerId", R.id.numberPicker);
injectables.put("numberPickerInputId", R.id.timepicker_input);
injectables.put("numberPickerDialogLayout", R.layout.number_picker_dialog);
// com.todoroo.astrid.dao // com.todoroo.astrid.dao
injectables.put("database", Database.class); injectables.put("database", Database.class);
injectables.put("taskDao", TaskDao.class); injectables.put("taskDao", TaskDao.class);

@ -24,6 +24,10 @@ public final class UpgradeService {
if(from < 136) if(from < 136)
new Astrid2To3UpgradeHelper().upgrade2To3(); new Astrid2To3UpgradeHelper().upgrade2To3();
else if(from < 137) {
// TODO upgrade recurrence
}
// display changelog // display changelog
showChangeLog(from); showChangeLog(from);

Loading…
Cancel
Save