Bug fixes:

- new RTM synchronization automatically starts the sync process
  - nags after postpone
  - if tag has special characters, no '@' in shortcut
  - delete old tasks
pull/14/head
Tim Su 17 years ago
parent c6ce2d9a23
commit 3c6a8c8716

@ -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="96"
android:versionName="2.5.3-1">
android:versionCode="97"
android:versionName="2.5.5">
<meta-data android:name="com.a0soft.gphone.aTrackDog.webURL"
android:value="http://www.weloveastrid.com" />

@ -52,6 +52,24 @@
<item>Time to shorten your todo list!</item>
</string-array>
<!-- Astrid's nagging when user clicks postpone -->
<string-array name="postpone_nags">
<item>Please tell me it isn\'t true that you're a procrastinator!</item>
<item>Doesn\'t being lazy get old sometimes?</item>
<item>Somewhere, someone is depending on you to finish this!</item>
<item>When you said postpone, you really meant \'I\'m doing this\', right?</item>
<item>This is the last time you postpone this, right?</item>
<item>Just finish this today, I won\'t tell anyone!</item>
<item>Why postpone when you can um... not postpone!</item>
<item>You\'ll finish this eventually, I presume?</item>
<item>I think you\'re really great! How about not putting this off?</item>
<item>Every time you do that, God kills a kitten, meow!</item>
<item>Postpone, postpone, postpone. When will you change!</item>
<item>I\'ve had enough with your excuses! Just do it already!</item>
<item>Didn\'t you make that excuse last time?</item>
<item>I can\'t help you organize your life if you do that...</item>
</string-array>
<!-- Icons for notification tray -->
<string-array name="notif_icon_entries">
<item>Pink</item>

@ -131,6 +131,7 @@
<string name="taskList_menu_help">Help (opens in Browser)</string>
<string name="taskList_menu_survey">Take Astrid\'s Survey!</string>
<string name="taskList_menu_tips">Quick Tips</string>
<string name="taskList_menu_cleanup">Clean Up Old Tasks</string>
<string name="taskList_context_edit">Edit Task</string>
<string name="taskList_context_delete">Delete Task</string>
@ -148,7 +149,10 @@
<string name="taskList_sort_duedate">Sort By Due Date</string>
<string name="taskList_sort_reverse">Sort Reverse</string>
<string name="taskList_postpone_count">Times You\'ve Postponed: %d</string>
<string name="taskList_postpone_firsttime">(Turn off Astrid\'s Hints on the Preferences screen)</string>
<string name="taskList_postpone_dialog">Postpone for how long?</string>
<string name="taskList_cleanup_dialog">"Delete completed tasks older than # days:"</string>
<!-- TaskEdit -->
<skip />
@ -359,6 +363,11 @@ Thanks for using Astrid!\n
<string name="prefs_fontSize_desc">Font on the main listing page (i.e. 22)</string>
<string name="prefs_category_other">Other</string>
<string name="p_postponecount">ppcount</string>
<string name="p_nagging">nagging</string>
<string name="prefs_nagging_title">Nag Messages</string>
<string name="prefs_nagging_desc">Astrid\'s little messages help you stay on track</string>
<string name="p_deadlineTime">deadline_time</string>
<string name="prefs_deadlineTime_title">Default Deadlines</string>

@ -89,6 +89,11 @@
<PreferenceCategory
android:title="@string/prefs_category_other">
<CheckBoxPreference
android:key="@string/p_nagging"
android:title="@string/prefs_nagging_title"
android:summary="@string/prefs_nagging_desc"
android:defaultValue="true" />
<EditTextPreference
android:key="@string/p_deadlineTime"
android:title="@string/prefs_deadlineTime_title"

@ -342,7 +342,12 @@ public class TagListSubActivity extends SubActivity {
String label = tag.getName();
if(tag.shouldHideFromMainList())
label = label.substring(1);
createShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "@" + label);
// add the @ sign if the task starts with a letter, for clarity
if(Character.isLetterOrDigit(label.charAt(0)))
label = "@" + label;
createShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
createShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON,
((BitmapDrawable)r.getDrawable(R.drawable.icon_tag)).getBitmap());
createShortcutIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");

@ -71,7 +71,7 @@ public class TaskList extends Activity {
private static final int FLING_DIST_THRESHOLD = 160;
/** Maximum distance in the other axis for a fling */
private static final int MAX_FLING_OTHER_AXIS = 100;
private static final int MAX_FLING_OTHER_AXIS = 130;
/** Minimum velocity a fling must have to trigger motion */
private static final int FLING_VEL_THRESHOLD = 300;
@ -94,6 +94,7 @@ public class TaskList extends Activity {
TagController tagController;
// static variables
public static boolean synchronizeNow = false;
/** If set, the application will close when this activity gets focus */
static boolean shouldCloseInstance = false;
@ -128,8 +129,11 @@ public class TaskList extends Activity {
}
// auto sync if requested
Integer autoSyncHours = Preferences.autoSyncFrequency(this);
if(autoSyncHours != null) {
Float autoSyncHours = Preferences.autoSyncFrequency(this);
if(synchronizeNow) {
synchronizeNow = false;
Synchronizer.synchronize(this, true, null);
} else if(autoSyncHours != null) {
final Date lastSync = Preferences.getSyncLastSync(this);
if(lastSync == null || lastSync.getTime() +

@ -65,8 +65,10 @@ import com.timsu.astrid.utilities.Constants;
import com.timsu.astrid.utilities.DialogUtilities;
import com.timsu.astrid.utilities.Notifications;
import com.timsu.astrid.utilities.Preferences;
import com.timsu.astrid.widget.NumberPicker;
import com.timsu.astrid.widget.NumberPickerDialog;
import com.timsu.astrid.widget.NNumberPickerDialog.OnNNumberPickedListener;
import com.timsu.astrid.widget.NumberPickerDialog.OnNumberPickedListener;
/**
* Primary view for the Astrid Application. Lists all of the tasks in the
@ -100,7 +102,7 @@ public class TaskListSubActivity extends SubActivity {
private static final int OPTIONS_SYNC_ID = Menu.FIRST + 10;
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_CLEANUP_ID = Menu.FIRST + 13;
private static final int OPTIONS_QUICK_TIPS = Menu.FIRST + 14;
private static final int CONTEXT_FILTER_HIDDEN = Menu.FIRST + 20;
@ -117,6 +119,7 @@ public class TaskListSubActivity extends SubActivity {
private static final int SORTFLAG_FILTERHIDDEN = (1 << 6);
private static final int HIDE_ADD_BTN_PORTRAIT = 4;
private static final int HIDE_ADD_BTN_LANDSCPE = 2;
private static final float POSTPONE_STAT_PCT = 0.3f;
// UI components
private ListView listView;
@ -170,6 +173,8 @@ public class TaskListSubActivity extends SubActivity {
}
setupUIComponents();
// declare the reload runnable, which is called when the task list
// wants to reload itself
reLoadRunnable = new Runnable() {
@Override
public void run() {
@ -184,8 +189,11 @@ public class TaskListSubActivity extends SubActivity {
}
};
if(getLastNonConfigurationInstance() != null) {
context = (TaskListContext)getLastNonConfigurationInstance();
// if we have a non-configuration instance (i.e. the screen was just
// rotated), use that instead of loading the whole task list again.
// this makes screen rotation an inexpensive operation
if (getLastNonConfigurationInstance() != null) {
context = (TaskListContext) getLastNonConfigurationInstance();
listView.setAdapter(context.listAdapter);
onTaskListLoaded();
return;
@ -205,7 +213,8 @@ public class TaskListSubActivity extends SubActivity {
Toast.makeText(getParent(), R.string.missing_tag, Toast.LENGTH_SHORT).show();
}
// time to go!
// time to go! creates a thread that loads the task list, then
// displays the reminder box if it is requested
context.loadingThread = new Thread(new Runnable() {
@Override
public void run() {
@ -316,6 +325,9 @@ public class TaskListSubActivity extends SubActivity {
R.string.taskList_menu_settings);
item.setAlphabeticShortcut('p');
item = menu.add(Menu.NONE, OPTIONS_CLEANUP_ID, Menu.NONE,
R.string.taskList_menu_cleanup);
item = menu.add(Menu.NONE, OPTIONS_QUICK_TIPS, Menu.NONE,
R.string.taskList_menu_tips);
@ -323,12 +335,16 @@ public class TaskListSubActivity extends SubActivity {
R.string.taskList_menu_help);
item.setAlphabeticShortcut('h');
item = menu.add(Menu.NONE, OPTIONS_SURVEY_ID, Menu.NONE,
R.string.taskList_menu_survey);
return true;
}
/**
* Enum that determines how the task list is sorted. Contains a comparison
* method that determines sorting order.
*
* @author timsu
*
*/
private enum SortMode {
ALPHA {
@Override
@ -379,8 +395,12 @@ public class TaskListSubActivity extends SubActivity {
// clear notifications
Notifications.clearAllNotifications(getParent(), task.getTaskIdentifier());
String[] responses = r.getStringArray(R.array.reminder_responses);
String response = responses[new Random().nextInt(responses.length)];
String response;
if(Preferences.shouldShowNags(getParent())) {
String[] responses = r.getStringArray(R.array.reminder_responses);
response = responses[new Random().nextInt(responses.length)];
} else
response = "";
new AlertDialog.Builder(getParent())
.setTitle(R.string.taskView_notifyTitle)
.setMessage(task.getName() + "\n\n" + response)
@ -409,6 +429,13 @@ public class TaskListSubActivity extends SubActivity {
.show();
}
/** Helper method to "snooze" an alert (i.e. set a new one for some time
* from now.
*
* @param task
* @param repeatInterval
* @param flags
*/
private void snoozeAlert(final TaskModelForList task,
final long repeatInterval, final int flags) {
DialogUtilities.hourMinutePicker(getParent(),
@ -914,10 +941,75 @@ public class TaskListSubActivity extends SubActivity {
return input;
}
/** Show a dialog box and delete old tasks as requested */
private void cleanOldTasks() {
final Resources r = getResources();
new NumberPickerDialog(getParent(), new OnNumberPickedListener() {
@Override
public void onNumberPicked(NumberPicker view, int number) {
Date date = new Date(System.currentTimeMillis() - 24L*3600*1000*number);
int deleted = getTaskController().deleteCompletedTasksOlderThan(date);
DialogUtilities.okDialog(getParent(), r.getQuantityString(R.plurals.Ntasks,
deleted, deleted) + " " + r.getString(R.string.taskList_deleted),
null);
if(TaskListSubActivity.filterShowDone)
reloadList();
}
}, r.getString(R.string.taskList_cleanup_dialog),
30, 5, 0, 999).show();
}
/** Show a dialog box to postpone your tasks */
private void postponeTask(final TaskModelForList task) {
final Resources r = getResources();
DialogUtilities.dayHourPicker(getParent(), r.getString(R.string.taskList_postpone_dialog),
new OnNNumberPickedListener() {
public void onNumbersPicked(int[] values) {
long postponeMillis = (values[0] * 24 + values[1]) * 3600L * 1000;
task.setPreferredDueDate(computePostponeDate(task
.getPreferredDueDate(), postponeMillis,
true));
task.setDefiniteDueDate(computePostponeDate(
task.getDefiniteDueDate(), postponeMillis, true));
task.setHiddenUntil(computePostponeDate(task.
getHiddenUntil(), postponeMillis, false));
getTaskController().saveTask(task);
getTaskController().updateAlarmForTask(
task.getTaskIdentifier());
context.listAdapter.refreshItem(listView,
context.taskArray.indexOf(task));
// show nag
int postponeCount = Preferences.getPostponeCount(getParent());
if(Preferences.shouldShowNags(getParent())) {
Random random = new Random();
final String nagText;
if(postponeCount == 0)
nagText = r.getString(R.string.taskList_postpone_firsttime);
else if(random.nextFloat() < POSTPONE_STAT_PCT)
nagText = r.getString(R.string.taskList_postpone_count,
postponeCount);
else {
String[] nags = r.getStringArray(R.array.postpone_nags);
nagText = nags[random.nextInt(nags.length)];
}
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getParent(), nagText, Toast.LENGTH_LONG).show();
}
});
}
Preferences.setPostponeCount(getParent(), postponeCount + 1);
}
});
}
@Override
public boolean onMenuItemSelected(int featureId, final MenuItem item) {
final TaskModelForList task;
Resources r = getResources();
switch(item.getItemId()) {
// --- options menu items
@ -950,14 +1042,8 @@ public class TaskListSubActivity extends SubActivity {
Uri.parse(Constants.HELP_URL));
launchActivity(browserIntent, 0);
return true;
case OPTIONS_SURVEY_ID:
browserIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse(Constants.SURVEY_URL));
launchActivity(browserIntent, 0);
return true;
case OPTIONS_QUICK_TIPS:
DialogUtilities.okDialog(getParent(),
r.getString(R.string.quick_tips), null);
case OPTIONS_CLEANUP_ID:
cleanOldTasks();
return true;
// --- list context menu items
@ -974,25 +1060,8 @@ public class TaskListSubActivity extends SubActivity {
toggleTimer(task);
return true;
case TaskListAdapter.CONTEXT_POSTPONE_ID:
task = context.tasksById.get((long)item.getGroupId());
DialogUtilities.dayHourPicker(getParent(),
r.getString(R.string.taskList_postpone_dialog),
new OnNNumberPickedListener() {
public void onNumbersPicked(int[] values) {
long postponeMillis = (values[0] * 24 + values[1]) *
3600L * 1000;
task.setPreferredDueDate(computePostponeDate(
task.getPreferredDueDate(), postponeMillis, true));
task.setDefiniteDueDate(computePostponeDate(
task.getDefiniteDueDate(), postponeMillis, true));
task.setHiddenUntil(computePostponeDate(
task.getHiddenUntil(), postponeMillis, false));
getTaskController().saveTask(task);
getTaskController().updateAlarmForTask(task.getTaskIdentifier());
context.listAdapter.refreshItem(listView, context.taskArray.indexOf(task));
}
});
task = context.tasksById.get((long) item.getGroupId());
postponeTask(task);
return true;
// --- display context menu items
@ -1044,7 +1113,7 @@ public class TaskListSubActivity extends SubActivity {
}
/* ======================================================================
*===================================================== getters / setters
* ===================================================== getters / setters
* ====================================================================== */
public TagModelForView getFilterTag() {

@ -118,6 +118,13 @@ public class TaskController extends AbstractController {
null, null, null, null, null, null);
}
/** Delete all completed tasks with date < older than date */
public int deleteCompletedTasksOlderThan(Date olderThanDate) {
return database.delete(TASK_TABLE_NAME, String.format("`%s` >= '%d' AND `%s` <= '%d'",
AbstractTaskModel.PROGRESS_PERCENTAGE, AbstractTaskModel.COMPLETE_PERCENTAGE,
AbstractTaskModel.COMPLETION_DATE, olderThanDate.getTime()), null);
}
/** Create a list of tasks from the db cursor given */
public ArrayList<TaskModelForList> createTaskListFromCursor(Cursor cursor) {
ArrayList<TaskModelForList> list = new ArrayList<TaskModelForList>();

@ -49,6 +49,7 @@ import com.mdt.rtm.data.RtmTasks;
import com.mdt.rtm.data.RtmAuth.Perms;
import com.mdt.rtm.data.RtmTask.Priority;
import com.timsu.astrid.R;
import com.timsu.astrid.activities.TaskList;
import com.timsu.astrid.data.enums.Importance;
import com.timsu.astrid.data.sync.SyncMapping;
import com.timsu.astrid.data.task.TaskModelForSync;
@ -145,6 +146,7 @@ public class RTMSyncService extends SynchronizationService {
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
TaskList.synchronizeNow = true;
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse(url));
activity.startActivity(intent);

@ -46,6 +46,9 @@ public class Preferences {
if(!prefs.contains(r.getString(R.string.p_deadlineTime))) {
editor.putString(r.getString(R.string.p_deadlineTime), "1");
}
if(!prefs.contains(r.getString(R.string.p_postponecount))) {
editor.putString(r.getString(R.string.p_postponecount), "0");
}
if(!prefs.contains(r.getString(R.string.p_notif_defaultRemind))) {
editor.putString(r.getString(R.string.p_notif_defaultRemind), "0");
}
@ -93,6 +96,8 @@ public class Preferences {
}
}
// --- sysetm preferences
/** CurrentVersion: the currently installed version of Astrid */
public static int getCurrentVersion(Context context) {
return getPrefs(context).getInt(P_CURRENT_VERSION, 0);
@ -116,6 +121,8 @@ public class Preferences {
editor.commit();
}
// --- notification settings
/** returns hour at which quiet hours start, or null if not set */
public static Integer getQuietHourStart(Context context) {
return getIntegerValue(context, R.string.p_notif_quietStart);
@ -154,6 +161,33 @@ public class Preferences {
R.string.p_notif_annoy), DEFAULT_PERSISTENCE_MODE);
}
/** Return # of days to remind by default */
public static Integer getDefaultReminder(Context context) {
return getIntegerValue(context, R.string.p_notif_defaultRemind);
}
// --- postpone count & settings
/** whether nags for postponing and other things should be shown */
public static boolean shouldShowNags(Context context) {
return getPrefs(context).getBoolean(context.getResources().
getString(R.string.p_nagging), true);
}
/** gets # of times user has postponed a task */
public static Integer getPostponeCount(Context context) {
return getIntegerValue(context, R.string.p_postponecount);
}
/** sets # of times user has postponed a task */
public static void setPostponeCount(Context context, int value) {
Editor editor = getPrefs(context).edit();
editor.putInt(context.getResources().getString(R.string.p_postponecount), value);
editor.commit();
}
// --- appearance settings
/** returns the font size user wants on the front page */
public static Integer getTaskListFontSize(Context context) {
return getIntegerValue(context, R.string.p_fontSize);
@ -171,11 +205,6 @@ public class Preferences {
R.string.p_colorize), DEFAULT_COLORIZE);
}
/** Return # of days to remind by default */
public static Integer getDefaultReminder(Context context) {
return getIntegerValue(context, R.string.p_notif_defaultRemind);
}
/** TaskListSort: the sorting method for the task list */
public static int getTaskListSort(Context context) {
return getPrefs(context).getInt(P_TASK_LIST_SORT, 0);
@ -244,8 +273,8 @@ public class Preferences {
}
/** returns the font size user wants on the front page */
public static Integer autoSyncFrequency(Context context) {
return getIntegerValue(context, R.string.p_sync_every);
public static Float autoSyncFrequency(Context context) {
return getFloatValue(context, R.string.p_sync_every);
}
/** Last Auto-Sync Date, or null */
@ -270,16 +299,25 @@ public class Preferences {
// --- helper methods
/** Clear the given preference */
private static void clearPref(Context context, String key) {
Editor editor = getPrefs(context).edit();
editor.remove(key);
editor.commit();
}
/** Get preferences object from the context */
private static SharedPreferences getPrefs(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context);
}
/** Gets an integer value from a string resource id. Returns null
* if the value is not set or not an integer.
*
* @param context
* @param keyResource resource from string.xml
* @return integer value, or null on error
*/
private static Integer getIntegerValue(Context context, int keyResource) {
Resources r = context.getResources();
String value = getPrefs(context).getString(r.getString(keyResource), "");
@ -291,6 +329,24 @@ public class Preferences {
}
}
/** Gets an float value from a string resource id. Returns null
* if the value is not set or not an flat.
*
* @param context
* @param keyResource resource from string.xml
* @return
*/
private static Float getFloatValue(Context context, int keyResource) {
Resources r = context.getResources();
String value = getPrefs(context).getString(r.getString(keyResource), "");
try {
return Float.parseFloat(value);
} catch (Exception e) {
return null;
}
}
public static TaskFieldsVisibility getTaskFieldsVisibility(Context context) {
return TaskFieldsVisibility.getFromPreferences(context, getPrefs(context));
}

Loading…
Cancel
Save