Better calendar integration: precreating events and then opening them up for edit, and also deleting them when you complete / delete your task.

pull/14/head
Tim Su 17 years ago
parent c4db48e97e
commit d1f6853643

@ -1,8 +1,8 @@
<?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:versionCode="84" android:versionCode="86"
android:versionName="2.3.3"> android:versionName="2.3.5">
<meta-data android:name="com.a0soft.gphone.aTrackDog.webURL" <meta-data android:name="com.a0soft.gphone.aTrackDog.webURL"
android:value="http://www.weloveastrid.com" /> android:value="http://www.weloveastrid.com" />
@ -11,6 +11,7 @@
<uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<application android:icon="@drawable/icon" android:label="@string/app_name"> <application android:icon="@drawable/icon" android:label="@string/app_name">

@ -42,8 +42,8 @@
<CheckBox android:id="@+id/cb1" <CheckBox android:id="@+id/cb1"
android:paddingBottom="5px" android:paddingBottom="5px"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_width="wrap_content" android:layout_width="48px"
android:layout_height="fill_parent" android:layout_height="52px"
android:scaleType="center" /> android:scaleType="center" />
<ImageView android:id="@+id/imageLeft" <ImageView android:id="@+id/imageLeft"

@ -159,6 +159,7 @@
<string name="definiteDueDate_label">Absolute Deadline</string> <string name="definiteDueDate_label">Absolute Deadline</string>
<string name="preferredDueDate_label">Goal Deadline</string> <string name="preferredDueDate_label">Goal Deadline</string>
<string name="addToCalendar_label">Add Task To Calendar</string> <string name="addToCalendar_label">Add Task To Calendar</string>
<string name="showCalendar_label">Open Calendar Event</string>
<string name="hiddenUntil_label">Hide Until This Date</string> <string name="hiddenUntil_label">Hide Until This Date</string>
<string name="repeat_label">Repeat Every</string> <string name="repeat_label">Repeat Every</string>
<string name="repeat_value_unset">No Repeat Set</string> <string name="repeat_value_unset">No Repeat Set</string>

@ -28,10 +28,13 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -207,6 +210,8 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
if(reminder != null) if(reminder != null)
notification.setTimeDuration(24*3600*reminder); notification.setTimeDuration(24*3600*reminder);
} }
if(model.getCalendarUri() != null)
addToCalendar.setText(r.getString(R.string.showCalendar_label));
// tags // tags
tags = tagController.getAllTags(this); tags = tagController.getAllTags(this);
@ -660,37 +665,69 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
@Override @Override
protected void onPause() { protected void onPause() {
// create calendar event
if(addToCalendar.isChecked() && model.getCalendarUri() == null) {
Uri uri = Uri.parse("content://calendar/events");
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put("title", name.getText().toString());
values.put("calendar_id", 1);
values.put("description", notes.getText().toString());
values.put("hasAlarm", 0);
values.put("transparency", 0);
values.put("visibility", 0);
Long deadlineDate = null;
if (model.getPreferredDueDate() != null)
deadlineDate = model.getPreferredDueDate().getTime();
else if (model.getDefiniteDueDate() != null)
deadlineDate = model.getDefiniteDueDate().getTime();
else
deadlineDate = System.currentTimeMillis() + 24*3600*1000L;
int estimatedTime = DEFAULT_CAL_TIME;
if(model.getEstimatedSeconds() != null &&
model.getEstimatedSeconds() > 0) {
estimatedTime = model.getEstimatedSeconds();
}
values.put("dtstart", deadlineDate - estimatedTime * 1000L);
values.put("dtend", deadlineDate);
Uri result = cr.insert(uri, values);
if(result != null)
model.setCalendarUri(result.toString());
else
Log.e("astrid", "Error creating calendar event!");
}
if(shouldSaveState) if(shouldSaveState)
save(); save();
// create calendar event if(addToCalendar.isChecked() && model.getCalendarUri() != null) {
if(addToCalendar.isChecked()) { Uri result = Uri.parse(model.getCalendarUri());
addToCalendar.setChecked(false); Intent intent = new Intent(Intent.ACTION_EDIT, result);
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setType("vnd.android.cursor.item/event");
intent.putExtra("title", name.getText());
// recalculate dates
Long deadlineDate = null; Long deadlineDate = null;
if(model.getPreferredDueDate() != null) if (model.getPreferredDueDate() != null)
deadlineDate = model.getPreferredDueDate().getTime(); deadlineDate = model.getPreferredDueDate().getTime();
else if(model.getDefiniteDueDate() != null) else if (model.getDefiniteDueDate() != null)
deadlineDate = model.getDefiniteDueDate().getTime(); deadlineDate = model.getDefiniteDueDate().getTime();
else
deadlineDate = System.currentTimeMillis() + 24*3600*1000L;
if(deadlineDate != null) { int estimatedTime = DEFAULT_CAL_TIME;
int estimatedTime = DEFAULT_CAL_TIME; if(model.getEstimatedSeconds() != null &&
if(model.getEstimatedSeconds() != null && model.getEstimatedSeconds() > 0) {
model.getEstimatedSeconds() > 0) estimatedTime = model.getEstimatedSeconds();
estimatedTime = model.getEstimatedSeconds();
intent.putExtra("beginTime", deadlineDate - estimatedTime * 1000L);
intent.putExtra("endTime", deadlineDate);
} else {
intent.putExtra("allDay", true);
} }
intent.putExtra("beginTime", deadlineDate - estimatedTime * 1000L);
intent.putExtra("endTime", deadlineDate);
startActivity(intent); startActivity(intent);
} }
super.onPause(); super.onPause();
} }

@ -45,7 +45,7 @@ import com.timsu.astrid.utilities.Preferences;
public abstract class AbstractTaskModel extends AbstractModel { public abstract class AbstractTaskModel extends AbstractModel {
/** Version number of this model */ /** Version number of this model */
static final int VERSION = 3; static final int VERSION = 4;
public static final int COMPLETE_PERCENTAGE = 100; public static final int COMPLETE_PERCENTAGE = 100;
@ -67,6 +67,7 @@ public abstract class AbstractTaskModel extends AbstractModel {
static final String REPEAT = "repeat"; static final String REPEAT = "repeat";
static final String CREATION_DATE = "creationDate"; static final String CREATION_DATE = "creationDate";
static final String COMPLETION_DATE = "completionDate"; static final String COMPLETION_DATE = "completionDate";
static final String CALENDAR_URI = "calendarUri";
// reserved fields --- // reserved fields ---
static final String BLOCKING_ON = "blockingOn"; static final String BLOCKING_ON = "blockingOn";
@ -99,6 +100,7 @@ public abstract class AbstractTaskModel extends AbstractModel {
defaultValues.put(LAST_NOTIFIED, (Long)null); defaultValues.put(LAST_NOTIFIED, (Long)null);
defaultValues.put(REPEAT, 0); defaultValues.put(REPEAT, 0);
defaultValues.put(COMPLETION_DATE, (Long)null); defaultValues.put(COMPLETION_DATE, (Long)null);
defaultValues.put(CALENDAR_URI, (String)null);
} }
// --- database helper // --- database helper
@ -133,7 +135,8 @@ public abstract class AbstractTaskModel extends AbstractModel {
append(LAST_NOTIFIED).append(" integer,"). append(LAST_NOTIFIED).append(" integer,").
append(REPEAT).append(" integer,"). append(REPEAT).append(" integer,").
append(CREATION_DATE).append(" integer,"). append(CREATION_DATE).append(" integer,").
append(COMPLETION_DATE).append(" integer"). append(COMPLETION_DATE).append(" integer,").
append(CALENDAR_URI).append(" text").
append(");").toString(); append(");").toString();
db.execSQL(sql); db.execSQL(sql);
} }
@ -176,6 +179,16 @@ public abstract class AbstractTaskModel extends AbstractModel {
Log.e("astrid", "Error updating table!", e); Log.e("astrid", "Error updating table!", e);
} }
case 3:
sql = new StringBuilder().append("ALTER TABLE ").
append(tableName).append(" ADD COLUMN ").
append(CALENDAR_URI).append(" text").toString();
try {
db.execSQL(sql);
} catch (Exception e) {
Log.e("astrid", "Error updating table!", e);
}
break; break;
default: default:
// we don't know how to handle it... do the unfortunate thing // we don't know how to handle it... do the unfortunate thing
@ -410,6 +423,14 @@ public abstract class AbstractTaskModel extends AbstractModel {
return new RepeatInfo(interval, value); return new RepeatInfo(interval, value);
} }
protected String getCalendarUri() {
String uri = retrieveString(CALENDAR_URI);
if(uri != null && uri.length() == 0)
return null;
else
return uri;
}
// --- setters // --- setters
protected void setName(String name) { protected void setName(String name) {
@ -493,6 +514,10 @@ public abstract class AbstractTaskModel extends AbstractModel {
putIfChangedFromDatabase(REPEAT, repeat); putIfChangedFromDatabase(REPEAT, repeat);
} }
protected void setCalendarUri(String uri) {
putIfChangedFromDatabase(CALENDAR_URI, uri);
}
// --- utility methods // --- utility methods
protected void putDate(String fieldName, Date date) { protected void putDate(String fieldName, Date date) {

@ -25,12 +25,15 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import android.app.Activity; import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.database.SQLException; import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.util.Log;
import com.timsu.astrid.data.AbstractController; import com.timsu.astrid.data.AbstractController;
import com.timsu.astrid.data.sync.SyncDataController; import com.timsu.astrid.data.sync.SyncDataController;
@ -201,7 +204,7 @@ public class TaskController extends AbstractController {
if(taskId == null) if(taskId == null)
throw new UnsupportedOperationException("Cannot delete uncreated task!"); throw new UnsupportedOperationException("Cannot delete uncreated task!");
long id = taskId.getId(); long id = taskId.getId();
Notifications.deleteAlarm(context, null, id); cleanupTask(taskId);
return database.delete(TASK_TABLE_NAME, KEY_ROWID + "=" + id, null) > 0; return database.delete(TASK_TABLE_NAME, KEY_ROWID + "=" + id, null) > 0;
} }
@ -283,7 +286,32 @@ public class TaskController extends AbstractController {
repeatModel.repeatTaskBy(context, this, repeatInfo); repeatModel.repeatTaskBy(context, this, repeatInfo);
cursor.close(); cursor.close();
Notifications.deleteAlarm(context, null, task.getTaskIdentifier().getId()); cleanupTask(task.getTaskIdentifier());
}
/** Clean up state from a task. Called when deleting or completing it */
private void cleanupTask(TaskIdentifier taskId) {
// delete notifications & alarms
Notifications.deleteAlarm(context, null, taskId.getId());
// delete calendar event
try {
Cursor cursor = fetchTaskCursor(taskId, new String[] {
AbstractTaskModel.CALENDAR_URI });
cursor.moveToFirst();
String uri = cursor.getString(0);
cursor.close();
if(uri != null && uri.length() > 0) {
ContentResolver cr = context.getContentResolver();
cr.delete(Uri.parse(uri), null, null);
ContentValues values = new ContentValues();
values.put(AbstractTaskModel.CALENDAR_URI, (String)null);
database.update(TASK_TABLE_NAME, values, KEY_ROWID + "=" +
taskId.getId(), null);
}
} catch (Exception e) {
Log.e("astrid", "Error deleting calendar event", e);
}
} }
/** Set last notification date */ /** Set last notification date */

@ -46,6 +46,7 @@ public class TaskModelForEdit extends AbstractTaskModel implements Notifiable {
PROGRESS_PERCENTAGE, PROGRESS_PERCENTAGE,
NOTES, NOTES,
REPEAT, REPEAT,
CALENDAR_URI,
}; };
// --- constructors // --- constructors
@ -136,6 +137,11 @@ public class TaskModelForEdit extends AbstractTaskModel implements Notifiable {
return super.getRepeat(); return super.getRepeat();
} }
@Override
public String getCalendarUri() {
return super.getCalendarUri();
}
@Override @Override
public void setDefiniteDueDate(Date definiteDueDate) { public void setDefiniteDueDate(Date definiteDueDate) {
super.setDefiniteDueDate(definiteDueDate); super.setDefiniteDueDate(definiteDueDate);
@ -190,4 +196,9 @@ public class TaskModelForEdit extends AbstractTaskModel implements Notifiable {
public void setRepeat(RepeatInfo taskRepeat) { public void setRepeat(RepeatInfo taskRepeat) {
super.setRepeat(taskRepeat); super.setRepeat(taskRepeat);
} }
@Override
public void setCalendarUri(String uri) {
super.setCalendarUri(uri);
}
} }

Loading…
Cancel
Save