- notification icon themes
   - add to calendar (no event title yet)
   - delete is sped up
   - fixed bug with repeat double-happening
   - fixed bug with task completion % not displaying
   - fixed bug with date being prematurely marked as overdue
pull/14/head
Tim Su 17 years ago
parent 3b7601ef01
commit 20c1d95b5c

@ -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:versionCode="80"
android:versionName="2.2.9">
android:versionCode="83"
android:versionName="2.3.2">
<meta-data android:name="com.a0soft.gphone.aTrackDog.webURL"
android:value="http://www.weloveastrid.com" />

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

@ -207,6 +207,11 @@
android:layout_height="wrap_content"/>
</LinearLayout>
<CheckBox android:id="@+id/add_to_calendar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/addToCalendar_label"/>
<TextView android:id="@+id/hiddenUntil_label"
android:layout_width="wrap_content"
@ -268,8 +273,7 @@
android:layout_height="1dip"
android:padding="5dip"
android:background="@android:drawable/divider_horizontal_dark"
/>
/>
<TextView android:id="@+id/elapsedDuration_label"
android:layout_width="wrap_content"

@ -43,13 +43,13 @@
android:paddingBottom="5px"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_height="fill_parent"
android:scaleType="center" />
<ImageView android:id="@+id/imageLeft"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_height="fill_parent"
android:scaleType="center"/>
</LinearLayout>

@ -52,4 +52,16 @@
<item>Time to shorten your todo list!</item>
</string-array>
<string-array name="notif_icon_entries">
<item>Pink</item>
<item>Boring</item>
<item>Astrid</item>
</string-array>
<string-array name="notif_icon_values">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
</resources>

@ -116,8 +116,9 @@
<string name="taskList_menu_more">More</string>
<string name="taskList_menu_sync">Synchronization</string>
<string name="taskList_menu_settings">Settings</string>
<string name="taskList_menu_help">Help</string>
<string name="taskList_menu_help">Online Help</string>
<string name="taskList_menu_survey">Take Astrid\'s Survey!</string>
<string name="taskList_menu_tips">Quick Tips</string>
<string name="taskList_context_edit">Edit Task</string>
<string name="taskList_context_delete">Delete Task</string>
@ -157,6 +158,7 @@
<string name="elapsedDuration_label">Time Already Spent on Task</string>
<string name="definiteDueDate_label">Absolute Deadline</string>
<string name="preferredDueDate_label">Goal Deadline</string>
<string name="addToCalendar_label">Add Task To Calendar</string>
<string name="hiddenUntil_label">Hide Until This Date</string>
<string name="repeat_label">Repeat Every</string>
<string name="repeat_value_unset">No Repeat Set</string>
@ -271,6 +273,17 @@ Wish me luck!\n
<string name="delete_this_tag_title">Remove this tag from all tasks?</string>
<string name="stop_timer_title">Stop the timer?</string>
<string name="quick_tips">
Some things you may not know about Astrid:\n
\n
- To create a task, just start typing!\n
- While editing a task, hit \'back\' to save it\n
- Select a task &amp; press 1-4 to quickly change it\'s priority\n
- If a task has a deadline, long-press to postpone it\n
\n
Thanks for using Astrid!\n
</string>
<!-- Notification -->
@ -309,7 +322,11 @@ Wish me luck!\n
<string name="p_notification_ringtone">notification_ringtone</string>
<string name="prefs_notification_title">Notification Ringtone</string>
<string name="prefs_notification_desc">Choose how Astrid alerts you!</string>
<string name="prefs_notification_desc">Choose a ringtone for Astrid\'s alerts</string>
<string name="p_notif_icon">notif_theme</string>
<string name="prefs_notificon_title">Notification Icons</string>
<string name="prefs_notificon_desc">Choose Astrid\'s notification bar icon</string>
<string name="prefs_category_appearance">Appearance</string>

@ -27,6 +27,13 @@
android:ringtoneType="notification"
android:showDefault="true"
android:showSilent="true" />
<ListPreference
android:key="@string/p_notif_icon"
android:entries="@array/notif_icon_entries"
android:entryValues="@array/notif_icon_values"
android:title="@string/prefs_notificon_title"
android:summary="@string/prefs_notificon_desc" />
</PreferenceCategory>
<PreferenceCategory

@ -29,6 +29,7 @@ import java.util.Set;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.os.Bundle;
@ -88,20 +89,21 @@ import com.timsu.astrid.widget.TimeDurationControlSet.TimeDurationType;
public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
// bundle arguments
public static final String TAG_NAME_TOKEN = "t";
public static final String START_CHAR_TOKEN = "s";
public static final String TAG_NAME_TOKEN = "t";
public static final String START_CHAR_TOKEN = "s";
// menu items
private static final int SAVE_ID = Menu.FIRST;
private static final int DISCARD_ID = Menu.FIRST + 1;
private static final int DELETE_ID = Menu.FIRST + 2;
private static final int SAVE_ID = Menu.FIRST;
private static final int DISCARD_ID = Menu.FIRST + 1;
private static final int DELETE_ID = Menu.FIRST + 2;
// other constants
private static final int MAX_TAGS = 5;
private static final int MAX_ALERTS = 5;
private static final String TAB_BASIC = "basic";
private static final String TAB_DATES = "dates";
private static final String TAB_ALERTS = "alerts";
private static final int MAX_TAGS = 5;
private static final int MAX_ALERTS = 5;
private static final String TAB_BASIC = "basic";
private static final String TAB_DATES = "dates";
private static final String TAB_ALERTS = "alerts";
private static final int DEFAULT_CAL_TIME = 3600;
// UI components
private EditText name;
@ -118,6 +120,7 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
private LinearLayout alertsContainer;
private Button repeatValue;
private Spinner repeatInterval;
private CheckBox addToCalendar;
// other instance variables
private boolean shouldSaveState = true;
@ -255,11 +258,6 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
if(name.getText().length() == 0)
return;
// if we've removed a deadline, delete alarms
if((definiteDueDate.getDate() == null && model.getDefiniteDueDate() != null) ||
(preferredDueDate.getDate() == null && model.getPreferredDueDate() != null))
Notifications.deleteAlarm(this, model.getTaskIdentifier().getId());
model.setName(name.getText().toString());
model.setEstimatedSeconds(estimatedDuration.getTimeDurationInSeconds());
model.setElapsedSeconds(elapsedDuration.getTimeDurationInSeconds());
@ -370,6 +368,7 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
alertsContainer = (LinearLayout)findViewById(R.id.alert_container);
repeatInterval = (Spinner)findViewById(R.id.repeat_interval);
repeatValue = (Button)findViewById(R.id.repeat_value);
addToCalendar = (CheckBox)findViewById(R.id.add_to_calendar);
// individual ui component initialization
ArrayAdapter<String> repeatAdapter = new ArrayAdapter<String>(
@ -663,6 +662,35 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
protected void onPause() {
if(shouldSaveState)
save();
// create calendar event
if(addToCalendar.isChecked()) {
addToCalendar.setChecked(false);
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setType("vnd.android.cursor.item/event");
intent.putExtra("title", name.getText());
Long deadlineDate = null;
if(model.getPreferredDueDate() != null)
deadlineDate = model.getPreferredDueDate().getTime();
else if(model.getDefaultValues() != null)
deadlineDate = model.getDefiniteDueDate().getTime();
if(deadlineDate != null) {
int estimatedTime = DEFAULT_CAL_TIME;
if(model.getEstimatedSeconds() != null &&
model.getEstimatedSeconds() > 0)
estimatedTime = model.getEstimatedSeconds();
intent.putExtra("beginTime", deadlineDate - estimatedTime * 1000L);
intent.putExtra("endTime", deadlineDate);
} else {
intent.putExtra("allDay", true);
}
startActivity(intent);
}
super.onPause();
}

@ -70,10 +70,10 @@ public class TaskList extends Activity {
public static final String VARIABLES_TAG = "v";
/** Minimum distance a fling must cover to trigger motion */
private static final int FLING_DIST_THRESHOLD = 100;
private static final int FLING_DIST_THRESHOLD = 70;
/** Minimum velocity a fling must have to trigger motion */
private static final int FLING_VEL_THRESHOLD = 300;
private static final int FLING_VEL_THRESHOLD = 250;
// view components
private ViewFlipper viewFlipper;

@ -43,11 +43,9 @@ import android.view.View.OnKeyListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.CompoundButton.OnCheckedChangeListener;
import com.timsu.astrid.R;
import com.timsu.astrid.data.alerts.AlertController;
@ -93,9 +91,6 @@ public class TaskListAdapter extends ArrayAdapter<TaskModelForList> {
private static final Format alarmFormat = new SimpleDateFormat(
"MM/dd hh:mm");
/** Threshold under which to display a task as red, in millis */
private static final long TASK_OVERDUE_THRESHOLD = 30 * 60 * 1000L;
private final Activity activity;
private List<TaskModelForList> objects;
private int resource;
@ -323,7 +318,7 @@ public class TaskListAdapter extends ArrayAdapter<TaskModelForList> {
if(task.getDefiniteDueDate() != null) {
long timeLeft = task.getDefiniteDueDate().getTime() -
System.currentTimeMillis();
if(timeLeft > TASK_OVERDUE_THRESHOLD) {
if(timeLeft > 0) {
label.append(r.getString(R.string.taskList_dueIn)).append(" ");
} else {
taskOverdue = true;
@ -339,7 +334,7 @@ public class TaskListAdapter extends ArrayAdapter<TaskModelForList> {
long timeLeft = task.getPreferredDueDate().getTime() -
System.currentTimeMillis();
label.append(r.getString(R.string.taskList_goalPrefix)).append(" ");
if(timeLeft > TASK_OVERDUE_THRESHOLD) {
if(timeLeft > 0) {
label.append(r.getString(R.string.taskList_dueIn)).append(" ");
} else {
label.append(r.getString(R.string.taskList_overdueBy)).append(" ");
@ -533,15 +528,14 @@ public class TaskListAdapter extends ArrayAdapter<TaskModelForList> {
final CheckBox progress = ((CheckBox)view.findViewById(R.id.cb1));
// clicking the check box
progress.setOnCheckedChangeListener(new OnCheckedChangeListener() {
progress.setOnClickListener(new View.OnClickListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
View parent = (View)buttonView.getParent().getParent();
public void onClick(View v) {
View parent = (View)v.getParent().getParent();
TaskModelForList task = (TaskModelForList)parent.getTag();
int newProgressPercentage;
if(isChecked)
if(progress.isChecked())
newProgressPercentage =
TaskModelForList.getCompletedPercentage();
else
@ -552,6 +546,7 @@ public class TaskListAdapter extends ArrayAdapter<TaskModelForList> {
setupView(parent, task);
}
}
});
// clicking the text field
@ -691,7 +686,7 @@ public class TaskListAdapter extends ArrayAdapter<TaskModelForList> {
float completedPercentage = 0;
if(task.getEstimatedSeconds() > 0) {
completedPercentage = task.getElapsedSeconds() /
completedPercentage = 1.0f * task.getElapsedSeconds() /
task.getEstimatedSeconds();
}

@ -98,6 +98,7 @@ public class TaskListSubActivity extends SubActivity {
private static final int OPTIONS_SETTINGS_ID = Menu.FIRST + 11;
private static final int OPTIONS_HELP_ID = Menu.FIRST + 12;
private static final int OPTIONS_SURVEY_ID = Menu.FIRST + 13;
private static final int OPTIONS_QUICK_TIPS = Menu.FIRST + 14;
private static final int CONTEXT_FILTER_HIDDEN = Menu.FIRST + 20;
private static final int CONTEXT_FILTER_DONE = Menu.FIRST + 21;
@ -246,13 +247,15 @@ public class TaskListSubActivity extends SubActivity {
R.string.taskList_menu_settings);
item.setAlphabeticShortcut('p');
item = menu.add(Menu.NONE, OPTIONS_QUICK_TIPS, Menu.NONE,
R.string.taskList_menu_tips);
item = menu.add(Menu.NONE, OPTIONS_HELP_ID, Menu.NONE,
R.string.taskList_menu_help);
item.setAlphabeticShortcut('h');
item = menu.add(Menu.NONE, OPTIONS_SURVEY_ID, Menu.NONE,
R.string.taskList_menu_survey);
item.setAlphabeticShortcut('h');
return true;
}
@ -764,6 +767,10 @@ public class TaskListSubActivity extends SubActivity {
Uri.parse(Constants.SURVEY_URL));
launchActivity(browserIntent, 0);
return true;
case OPTIONS_QUICK_TIPS:
DialogUtilities.okDialog(getParent(),
r.getString(R.string.quick_tips), null);
return true;
// --- list context menu items
case TaskListAdapter.CONTEXT_EDIT_ID:

@ -201,7 +201,7 @@ public class TaskController extends AbstractController {
if(taskId == null)
throw new UnsupportedOperationException("Cannot delete uncreated task!");
long id = taskId.getId();
Notifications.deleteAlarm(context, id);
Notifications.deleteAlarm(context, null, id);
return database.delete(TASK_TABLE_NAME, KEY_ROWID + "=" + id, null) > 0;
}

@ -86,7 +86,7 @@ public class Notifications extends BroadcastReceiver {
", repeat " + repeatInterval);
if(!showNotification(context, id, flags, repeatInterval, reminder)) {
deleteAlarm(context, id);
deleteAlarm(context, intent, id);
NotificationManager nm = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
nm.cancel((int)id);
@ -138,7 +138,7 @@ public class Notifications extends BroadcastReceiver {
// return if we don't need to go any further
if(shouldDeleteAlarm(task)) {
deleteAlarm(context, task.getTaskIdentifier().getId());
deleteAlarm(context, null, task.getTaskIdentifier().getId());
return;
}
@ -149,8 +149,8 @@ public class Notifications extends BroadcastReceiver {
long when;
// get or make up a last notification time
if(task.getLastNotificationDate() == null) {
when = System.currentTimeMillis() +
(long)(interval * (0.3f + 0.7f * random.nextFloat()));
when = System.currentTimeMillis() -
(long)(interval * (0.7f * random.nextFloat()));
taskController.setLastNotificationTime(task.getTaskIdentifier(),
new Date(when));
} else {
@ -167,6 +167,12 @@ public class Notifications extends BroadcastReceiver {
int estimatedDuration = DEADLINE_NOTIFY_SECS;
if(task.getEstimatedSeconds() != null && task.getEstimatedSeconds() > DEADLINE_NOTIFY_SECS)
estimatedDuration = (int)(task.getEstimatedSeconds() * 1.5f);
clearAlarm(context, task.getTaskIdentifier().getId(), FLAG_DEFINITE_DEADLINE);
clearAlarm(context, task.getTaskIdentifier().getId(), FLAG_PREFERRED_DEADLINE);
clearAlarm(context, task.getTaskIdentifier().getId(), FLAG_DEFINITE_DEADLINE | FLAG_OVERDUE);
clearAlarm(context, task.getTaskIdentifier().getId(), FLAG_PREFERRED_DEADLINE | FLAG_OVERDUE);
if((task.getNotificationFlags() & TaskModelForList.NOTIFY_BEFORE_DEADLINE) > 0) {
scheduleDeadline(context, task.getDefiniteDueDate(), -estimatedDuration,
0, FLAG_DEFINITE_DEADLINE, task);
@ -215,6 +221,7 @@ public class Notifications extends BroadcastReceiver {
*/
private static void scheduleDeadline(Context context, Date deadline, int
offsetSeconds, int intervalSeconds, int flags, Notifiable task) {
long id = task.getTaskIdentifier().getId();
if(deadline == null)
return;
long when = deadline.getTime() + offsetSeconds * 1000;
@ -222,10 +229,10 @@ public class Notifications extends BroadcastReceiver {
return;
if (intervalSeconds == 0)
scheduleAlarm(context, task.getTaskIdentifier().getId(), when,
scheduleAlarm(context, id, when,
flags);
else
scheduleRepeatingAlarm(context, task.getTaskIdentifier().getId(),
scheduleRepeatingAlarm(context, id,
when, flags, intervalSeconds * 1000);
}
@ -255,13 +262,12 @@ public class Notifications extends BroadcastReceiver {
}
/** Delete the given alarm */
public static void deleteAlarm(Context context, long id) {
public static void deleteAlarm(Context context, Intent trigger, long id) {
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
// clear all possible alarms
for(int flag = 0; flag < (6 << FIXED_ID_SHIFT); flag++) {
if(trigger != null) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
createAlarmIntent(context, id, flag), 0);
trigger, 0);
am.cancel(pendingIntent);
}
@ -269,6 +275,14 @@ public class Notifications extends BroadcastReceiver {
clearAllNotifications(context, new TaskIdentifier(id));
}
/** Clear the alarm given by the id and flags */
public static void clearAlarm(Context context, long id, int flags) {
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
createAlarmIntent(context, id, flags), 0);
am.cancel(pendingIntent);
}
/** Schedules a single alarm for a single task */
public static void scheduleAlarm(Context context, long id, long when,
int flags) {
@ -386,9 +400,20 @@ public class Notifications extends BroadcastReceiver {
// create notification object
String appName = r.getString(R.string.app_name);
int icon;
switch(Preferences.getNotificationIconTheme(context)) {
case PINK:
icon = R.drawable.notif_pink_alarm;
break;
case BORING:
icon = R.drawable.notif_boring_alarm;
break;
default:
icon = R.drawable.notif_astrid;
}
Notification notification = new Notification(
R.drawable.notification_tag_pink, reminder,
System.currentTimeMillis());
icon, reminder, System.currentTimeMillis());
notification.setLatestEventInfo(context,
appName,
reminder + " " + taskName,
@ -452,10 +477,21 @@ public class Notifications extends BroadcastReceiver {
(int)taskId.getId(), notifyIntent, 0);
// create notification object
int icon;
switch(Preferences.getNotificationIconTheme(context)) {
case PINK:
icon = R.drawable.notif_pink_working;
break;
case BORING:
icon = R.drawable.notif_boring_working;
break;
default:
icon = R.drawable.notif_astrid;
}
String appName = r.getString(R.string.app_name);
Notification notification = new Notification(
R.drawable.notification_clock, text,
System.currentTimeMillis());
icon, text, System.currentTimeMillis());
notification.setLatestEventInfo(context,
appName,
text,

@ -21,6 +21,13 @@ public class Preferences {
private static final String P_SYNC_RTM_LAST_SYNC = "rtmlastsync";
private static final String P_SYNC_LAST_SYNC = "lastsync";
// pref values
public enum NotificationIconTheme {
PINK,
BORING,
ASTRID
}
// default values
private static final boolean DEFAULT_PERSISTENCE_MODE = true;
private static final boolean DEFAULT_COLORIZE = false;
@ -42,7 +49,7 @@ public class Preferences {
editor.putString(r.getString(R.string.p_deadlineTime), "7");
}
if(!prefs.contains(r.getString(R.string.p_notif_defaultRemind))) {
editor.putString(r.getString(R.string.p_notif_defaultRemind), "7");
editor.putString(r.getString(R.string.p_notif_defaultRemind), "0");
}
if(!prefs.contains(r.getString(R.string.p_colorize))) {
editor.putBoolean(r.getString(R.string.p_colorize), DEFAULT_COLORIZE);
@ -121,7 +128,15 @@ public class Preferences {
return getIntegerValue(context, R.string.p_notif_quietEnd);
}
/** Get notification ringtone, or null if not set */
/** returns hour at which quiet hours start, or null if not set */
public static NotificationIconTheme getNotificationIconTheme(Context context) {
Integer index = getIntegerValue(context, R.string.p_notif_icon);
if(index == null)
index = 0;
return NotificationIconTheme.values()[index];
}
/** Get notification ring tone, or null if not set */
public static Uri getNotificationRingtone(Context context) {
Resources r = context.getResources();
String value = getPrefs(context).getString(r.getString(

Loading…
Cancel
Save