diff --git a/AndroidManifest.xml b/AndroidManifest.xml index c8ada9219..370e5ba89 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="2.4.1"> diff --git a/res/layout/main.xml b/res/layout/main.xml index d0d3cd777..5d6ebafcc 100644 --- a/res/layout/main.xml +++ b/res/layout/main.xml @@ -29,6 +29,13 @@ android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> + + @@ -48,11 +56,19 @@ android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> - + + + + @@ -60,7 +76,14 @@ android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> - + + + More Synchronization Settings - Online Help + Help (opens in Browser) Take Astrid\'s Survey! Quick Tips @@ -263,6 +263,7 @@ Wish me luck!\n + Loading... Information Question View Task diff --git a/src/com/timsu/astrid/activities/SubActivity.java b/src/com/timsu/astrid/activities/SubActivity.java index d83f21bd3..4e3d7b590 100644 --- a/src/com/timsu/astrid/activities/SubActivity.java +++ b/src/com/timsu/astrid/activities/SubActivity.java @@ -29,7 +29,6 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; -import com.timsu.astrid.activities.TaskList.ActivityCode; import com.timsu.astrid.data.tag.TagController; import com.timsu.astrid.data.task.TaskController; @@ -40,10 +39,10 @@ import com.timsu.astrid.data.task.TaskController; */ abstract public class SubActivity { private TaskList parent; - ActivityCode code; + int code; private View view; - public SubActivity(TaskList parent, ActivityCode code, View view) { + public SubActivity(TaskList parent, int code, View view) { this.parent = parent; this.code = code; this.view = view; @@ -122,13 +121,13 @@ abstract public class SubActivity { return parent.gestureListener; } - public void switchToActivity(ActivityCode activity, Bundle state) { + public void switchToActivity(int activity, Bundle state) { parent.switchToActivity(activity, state); } // --- internal methods - protected ActivityCode getActivityCode() { + protected int getActivityCode() { return code; } diff --git a/src/com/timsu/astrid/activities/TagListSubActivity.java b/src/com/timsu/astrid/activities/TagListSubActivity.java index 96bf0e846..b6315a37a 100644 --- a/src/com/timsu/astrid/activities/TagListSubActivity.java +++ b/src/com/timsu/astrid/activities/TagListSubActivity.java @@ -21,8 +21,8 @@ package com.timsu.astrid.activities; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; -import java.util.Map; import android.app.AlertDialog; import android.content.Context; @@ -31,6 +31,7 @@ import android.content.Intent; import android.content.res.Resources; import android.database.Cursor; import android.os.Bundle; +import android.os.Handler; import android.view.ContextMenu; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -42,20 +43,20 @@ import android.view.ContextMenu.ContextMenuInfo; import android.view.View.OnCreateContextMenuListener; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.AdapterView.OnItemClickListener; import com.timsu.astrid.R; -import com.timsu.astrid.activities.TaskList.ActivityCode; import com.timsu.astrid.data.tag.TagIdentifier; import com.timsu.astrid.data.tag.TagModelForView; import com.timsu.astrid.data.task.TaskIdentifier; import com.timsu.astrid.data.task.TaskModelForList; -/** +/** * List all tags and allows a user to see all tasks for a given tag * * @author Tim Su (timsu@stanfordalumni.org) @@ -71,21 +72,32 @@ public class TagListSubActivity extends SubActivity { private static final int CONTEXT_SHOWHIDE_ID = Menu.FIRST + 12; private ListView listView; - private List tagArray; - private Map taskMap; - Map tagToTaskCount; + private LinkedList tagArray; + private HashMap taskMap; + HashMap tagToTaskCount; + private Handler handler; + private TextView loadingText; private static SortMode sortMode = SortMode.SIZE; private static boolean sortReverse = false; - - public TagListSubActivity(TaskList parent, ActivityCode code, View view) { + + public TagListSubActivity(TaskList parent, int code, View view) { super(parent, code, view); } @Override public void onDisplay(Bundle variables) { listView = (ListView)findViewById(R.id.taglist); - fillData(); + handler = new Handler(); + loadingText = (TextView)findViewById(R.id.loading); + + // time to go! + new Thread(new Runnable() { + @Override + public void run() { + fillData(); + } + }).start(); } // --- stuff for sorting @@ -148,24 +160,43 @@ public class TagListSubActivity extends SubActivity { /** Fill in the Tag List with our tags */ private void fillData() { - Resources r = getResources(); - tagArray = getTagController().getAllTags(getParent()); // perform sort sortTagArray(); + handler.post(new Runnable() { + @Override + public void run() { + // set up our adapter + final TagListAdapter tagAdapter = new TagListAdapter(getParent(), + android.R.layout.simple_list_item_1, tagArray, + tagToTaskCount); + + // set up ui components + setUpListUI(tagAdapter); + loadingText.setVisibility(View.GONE); + } + }); + } + + /** Set up list handlers and adapter. run on the UI thread */ + private void setUpListUI(ListAdapter adapter) { // set up the title + Resources r = getResources(); StringBuilder title = new StringBuilder(). append(r.getString(R.string.tagList_titlePrefix)). append(" ").append(r.getQuantityString(R.plurals.Ntags, tagArray.size(), tagArray.size())); - setTitle(title); + final CharSequence finalTitle = title; + handler.post(new Runnable() { + @Override + public void run() { + setTitle(finalTitle); + } + }); - // set up our adapter - TagListAdapter tagAdapter = new TagListAdapter(getParent(), - android.R.layout.simple_list_item_1, tagArray); - listView.setAdapter(tagAdapter); + listView.setAdapter(adapter); // list view listener listView.setOnItemClickListener(new OnItemClickListener() { @@ -176,7 +207,7 @@ public class TagListSubActivity extends SubActivity { Bundle bundle = new Bundle(); bundle.putLong(TaskListSubActivity.TAG_TOKEN, tag.getTagIdentifier().getId()); - switchToActivity(ActivityCode.TASK_LIST_W_TAG, bundle); + switchToActivity(TaskList.AC_TASK_LIST_W_TAG, bundle); } }); @@ -237,15 +268,15 @@ public class TagListSubActivity extends SubActivity { .setNegativeButton(android.R.string.cancel, null) .show(); } - + @Override /** Handle back button by moving to task list */ protected boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode == KeyEvent.KEYCODE_BACK) { - switchToActivity(ActivityCode.TASK_LIST, null); + switchToActivity(TaskList.AC_TASK_LIST, null); return true; } - + return false; } @@ -308,22 +339,25 @@ public class TagListSubActivity extends SubActivity { return true; } - + // --------------------------------------------------- tag list adapter - + private class TagListAdapter extends ArrayAdapter { private List objects; private int resource; private LayoutInflater inflater; + private HashMap tagCount; public TagListAdapter(Context context, int resource, - List objects) { + List objects, HashMap + tagToTaskCount) { super(context, resource, objects); inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); this.objects = objects; this.resource = resource; + this.tagCount = tagToTaskCount; } @Override @@ -344,12 +378,12 @@ public class TagListSubActivity extends SubActivity { final TextView name = ((TextView)view.findViewById(android.R.id.text1)); name.setText(new StringBuilder(tag.getName()). - append(" (").append(tagToTaskCount.get(tag)).append(")")); + append(" (").append(tagCount.get(tag)).append(")")); - if(tagToTaskCount.get(tag) == 0) + if(tagCount.get(tag) == 0) name.setTextColor(r.getColor(R.color.task_list_done)); else - name.setTextColor(r.getColor(android.R.color.white)); + name.setTextColor(r.getColor(android.R.color.white)); } } diff --git a/src/com/timsu/astrid/activities/TaskList.java b/src/com/timsu/astrid/activities/TaskList.java index 01af7f36c..0461b9c73 100644 --- a/src/com/timsu/astrid/activities/TaskList.java +++ b/src/com/timsu/astrid/activities/TaskList.java @@ -53,12 +53,10 @@ import com.timsu.astrid.utilities.StartupReceiver; */ public class TaskList extends Activity { - /** Enum for the different pages that we can display */ - public enum ActivityCode { - TASK_LIST, - TAG_LIST, - TASK_LIST_W_TAG - }; + // constants for the different pages that we can display + public static final int AC_TASK_LIST = 0; + public static final int AC_TAG_LIST = 1; + public static final int AC_TASK_LIST_W_TAG = 2; /** Bundle Key: activity code id of current activity */ private static final String LAST_ACTIVITY_TAG = "l"; @@ -142,7 +140,7 @@ public class TaskList extends Activity { // if we have no filter tag, we're not on the last task if(getCurrentSubActivity() == taskListWTag && ((TaskListSubActivity)taskListWTag).getFilterTag() == null) { - switchToActivity(ActivityCode.TASK_LIST, null); + switchToActivity(AC_TASK_LIST, null); } } @@ -150,11 +148,11 @@ public class TaskList extends Activity { private void setupUIComponents() { gestureDetector = new GestureDetector(new AstridGestureDetector()); viewFlipper = (ViewFlipper)findViewById(R.id.main); - taskList = new TaskListSubActivity(this, ActivityCode.TASK_LIST, + taskList = new TaskListSubActivity(this, AC_TASK_LIST, findViewById(R.id.tasklist_layout)); - tagList = new TagListSubActivity(this, ActivityCode.TAG_LIST, + tagList = new TagListSubActivity(this, AC_TAG_LIST, findViewById(R.id.taglist_layout)); - taskListWTag = new TaskListSubActivity(this, ActivityCode.TASK_LIST_W_TAG, + taskListWTag = new TaskListSubActivity(this, AC_TASK_LIST_W_TAG, findViewById(R.id.tasklistwtag_layout)); mInAnimationForward = AnimationUtils.loadAnimation(this, R.anim.slide_left_in); @@ -185,8 +183,8 @@ public class TaskList extends Activity { Math.abs(velocityX) > FLING_VEL_THRESHOLD) { switch(getCurrentSubActivity().getActivityCode()) { - case TASK_LIST: - switchToActivity(ActivityCode.TAG_LIST, null); + case AC_TASK_LIST: + switchToActivity(AC_TAG_LIST, null); return true; default: return false; @@ -198,11 +196,11 @@ public class TaskList extends Activity { Math.abs(velocityX) > FLING_VEL_THRESHOLD) { switch(getCurrentSubActivity().getActivityCode()) { - case TASK_LIST_W_TAG: - switchToActivity(ActivityCode.TAG_LIST, null); + case AC_TASK_LIST_W_TAG: + switchToActivity(AC_TAG_LIST, null); return true; - case TAG_LIST: - switchToActivity(ActivityCode.TASK_LIST, null); + case AC_TAG_LIST: + switchToActivity(AC_TASK_LIST, null); return true; default: return false; @@ -221,31 +219,31 @@ public class TaskList extends Activity { * ====================================================================== */ /** Switches to another activity, with appropriate animation */ - void switchToActivity(ActivityCode activity, Bundle variables) { + void switchToActivity(int activity, Bundle variables) { closeOptionsMenu(); // and flip to them switch(getCurrentSubActivity().getActivityCode()) { - case TASK_LIST: + case AC_TASK_LIST: viewFlipper.setInAnimation(mInAnimationForward); viewFlipper.setOutAnimation(mOutAnimationForward); switch(activity) { - case TAG_LIST: + case AC_TAG_LIST: viewFlipper.showNext(); break; - case TASK_LIST_W_TAG: - viewFlipper.setDisplayedChild(taskListWTag.code.ordinal()); + case AC_TASK_LIST_W_TAG: + viewFlipper.setDisplayedChild(taskListWTag.code); } break; - case TAG_LIST: + case AC_TAG_LIST: switch(activity) { - case TASK_LIST: + case AC_TASK_LIST: viewFlipper.setInAnimation(mInAnimationBackward); viewFlipper.setOutAnimation(mOutAnimationBackward); viewFlipper.showPrevious(); break; - case TASK_LIST_W_TAG: + case AC_TASK_LIST_W_TAG: viewFlipper.setInAnimation(mInAnimationForward); viewFlipper.setOutAnimation(mOutAnimationForward); viewFlipper.showNext(); @@ -253,28 +251,28 @@ public class TaskList extends Activity { } break; - case TASK_LIST_W_TAG: + case AC_TASK_LIST_W_TAG: viewFlipper.setInAnimation(mInAnimationBackward); viewFlipper.setOutAnimation(mOutAnimationBackward); switch(activity) { - case TAG_LIST: + case AC_TAG_LIST: viewFlipper.showPrevious(); break; - case TASK_LIST: - viewFlipper.setDisplayedChild(taskList.code.ordinal()); + case AC_TASK_LIST: + viewFlipper.setDisplayedChild(taskList.code); } break; } // initialize the components switch(activity) { - case TASK_LIST: + case AC_TASK_LIST: taskList.onDisplay(variables); break; - case TAG_LIST: + case AC_TAG_LIST: tagList.onDisplay(variables); break; - case TASK_LIST_W_TAG: + case AC_TASK_LIST_W_TAG: taskListWTag.onDisplay(variables); } @@ -293,7 +291,7 @@ public class TaskList extends Activity { @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - outState.putInt(LAST_ACTIVITY_TAG, getCurrentSubActivity().code.ordinal()); + outState.putInt(LAST_ACTIVITY_TAG, getCurrentSubActivity().code); outState.putBundle(LAST_BUNDLE_TAG, lastActivityBundle); } @@ -316,7 +314,7 @@ public class TaskList extends Activity { super.onActivityResult(requestCode, resultCode, data); if(resultCode == Constants.RESULT_GO_HOME) { - switchToActivity(ActivityCode.TASK_LIST, null); + switchToActivity(AC_TASK_LIST, null); } else getCurrentSubActivity().onActivityResult(requestCode, resultCode, data); } diff --git a/src/com/timsu/astrid/activities/TaskListAdapter.java b/src/com/timsu/astrid/activities/TaskListAdapter.java index 6410af8bb..5f674decd 100644 --- a/src/com/timsu/astrid/activities/TaskListAdapter.java +++ b/src/com/timsu/astrid/activities/TaskListAdapter.java @@ -339,7 +339,7 @@ public class TaskListAdapter extends ArrayAdapter { if(timeLeft < FULL_DATE_THRESHOLD) label.append(DateUtilities.getDurationString(r, - (int)Math.abs(timeLeft/1000), 1)); + (int)Math.abs(timeLeft), 1)); else label.append(DateUtilities.getFormattedDate(r, task.getDefiniteDueDate())); @@ -362,7 +362,7 @@ public class TaskListAdapter extends ArrayAdapter { if(timeLeft < FULL_DATE_THRESHOLD) label.append(DateUtilities.getDurationString(r, - (int)Math.abs(timeLeft/1000), 1)); + (int)Math.abs(timeLeft), 1)); else label.append(DateUtilities.getFormattedDate(r, task.getPreferredDueDate())); diff --git a/src/com/timsu/astrid/activities/TaskListSubActivity.java b/src/com/timsu/astrid/activities/TaskListSubActivity.java index 24948ed19..1fb8410f2 100644 --- a/src/com/timsu/astrid/activities/TaskListSubActivity.java +++ b/src/com/timsu/astrid/activities/TaskListSubActivity.java @@ -32,10 +32,12 @@ import java.util.Random; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; import android.util.Log; import android.view.ContextMenu; import android.view.KeyEvent; @@ -46,9 +48,9 @@ import android.view.ContextMenu.ContextMenuInfo; import android.view.View.OnCreateContextMenuListener; import android.widget.Button; import android.widget.ListView; +import android.widget.TextView; import com.timsu.astrid.R; -import com.timsu.astrid.activities.TaskList.ActivityCode; import com.timsu.astrid.activities.TaskListAdapter.TaskListAdapterHooks; import com.timsu.astrid.data.tag.TagController; import com.timsu.astrid.data.tag.TagIdentifier; @@ -109,13 +111,17 @@ public class TaskListSubActivity extends SubActivity { private static final int CONTEXT_SORT_REVERSE = Menu.FIRST + 26; private static final int CONTEXT_SORT_GROUP = Menu.FIRST; + // other constants private static final int SORTFLAG_FILTERDONE = (1 << 5); 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; // UI components private ListView listView; private Button addButton; private View layout; + private TextView loadingText; // other instance variables private Map tagMap; @@ -123,6 +129,7 @@ public class TaskListSubActivity extends SubActivity { private HashMap> taskTags; private Long selectedTaskId = null; private TaskModelForList selectedTask = null; + private Handler handler; // display filters private static boolean filterShowHidden = false; @@ -135,7 +142,7 @@ public class TaskListSubActivity extends SubActivity { * ======================================================= initialization * ====================================================================== */ - public TaskListSubActivity(TaskList parent, ActivityCode code, View view) { + public TaskListSubActivity(TaskList parent, int code, View view) { super(parent, code, view); } @@ -158,8 +165,15 @@ public class TaskListSubActivity extends SubActivity { } setupUIComponents(); - loadTaskListSort(); - fillData(); + + // time to go! + new Thread(new Runnable() { + @Override + public void run() { + loadTaskListSort(); + fillData(); + } + }).start(); if(variables != null && variables.containsKey(NOTIF_FLAGS_TOKEN)) { long repeatInterval = 0; @@ -177,7 +191,10 @@ public class TaskListSubActivity extends SubActivity { /** Initialize UI components */ public void setupUIComponents() { - listView = (ListView)findViewById(R.id.tasklist); + handler = new Handler(); + + listView = (ListView)findViewById(R.id.tasklist); + loadingText = (TextView)findViewById(R.id.loading); addButton = (Button)findViewById(R.id.addtask); addButton.setOnClickListener(new View.OnClickListener() { @@ -381,8 +398,6 @@ public class TaskListSubActivity extends SubActivity { /** Fill in the Task List with our tasks */ private void fillData() { - Resources r = getResources(); - // get a cursor to the task list Cursor tasksCursor; if(filterTag != null) { @@ -443,7 +458,6 @@ public class TaskListSubActivity extends SubActivity { int activeTasks = taskArray.size() - completedTasks; // sort task list - // do sort Collections.sort(taskArray, new Comparator() { @Override public int compare(TaskModelForList arg0, TaskModelForList arg1) { @@ -453,32 +467,53 @@ public class TaskListSubActivity extends SubActivity { if(sortReverse) Collections.reverse(taskArray); - // hide "add" button if we have a few tasks - if(taskArray.size() > 4) - addButton.setVisibility(View.GONE); - else - addButton.setVisibility(View.VISIBLE); + handler.post(new Runnable() { + @Override + public void run() { + // hide "add" button if we have too many tasks + int threshold = HIDE_ADD_BTN_PORTRAIT; + if(getParent().getWindowManager().getDefaultDisplay().getOrientation() == + ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) + threshold = HIDE_ADD_BTN_LANDSCPE; + + if(taskArray.size() > threshold) + addButton.setVisibility(View.GONE); + else + addButton.setVisibility(View.VISIBLE); + } + }); // set up the title - StringBuilder title = new StringBuilder(). - append(r.getString(R.string.taskList_titlePrefix)).append(" "); - if(filterTag != null) { - title.append(r.getString(R.string.taskList_titleTagPrefix, - filterTag.getName())).append(" "); - } + final int finalCompleted = completedTasks; + final int finalActive = activeTasks; + final int finalHidden = hiddenTasks; + handler.post(new Runnable() { + @Override + public void run() { + Resources r = getResources(); + StringBuilder title = new StringBuilder(). + append(r.getString(R.string.taskList_titlePrefix)).append(" "); + if(filterTag != null) { + title.append(r.getString(R.string.taskList_titleTagPrefix, + filterTag.getName())).append(" "); + } + + if(finalCompleted > 0) + title.append(r.getQuantityString(R.plurals.NactiveTasks, + finalActive, finalActive, taskArray.size())); + else + title.append(r.getQuantityString(R.plurals.Ntasks, + taskArray.size(), taskArray.size())); + if(finalHidden > 0) + title.append(" (+").append(finalHidden).append(" "). + append(r.getString(R.string.taskList_hiddenSuffix)).append(")"); + + setTitle(title); + setUpListUI(); + loadingText.setVisibility(View.GONE); + } + }); - if(completedTasks > 0) - title.append(r.getQuantityString(R.plurals.NactiveTasks, - activeTasks, activeTasks, taskArray.size())); - else - title.append(r.getQuantityString(R.plurals.Ntasks, - taskArray.size(), taskArray.size())); - if(hiddenTasks > 0) - title.append(" (+").append(hiddenTasks).append(" "). - append(r.getString(R.string.taskList_hiddenSuffix)).append(")"); - setTitle(title); - - setUpListUI(); } /** Set up the adapter for our task list */ @@ -628,18 +663,28 @@ public class TaskListSubActivity extends SubActivity { if(numServicesSynced == 0) DialogUtilities.okDialog(getParent(), getResources().getString( R.string.sync_no_synchronizers), null); - fillData(); + new Thread(new Runnable() { + @Override + public void run() { + fillData(); + } + }); } }); } else if(requestCode == ACTIVITY_TAGS) - switchToActivity(ActivityCode.TAG_LIST, null); + switchToActivity(TaskList.AC_TAG_LIST, null); } @Override public void onWindowFocusChanged(boolean hasFocus) { // refresh, since stuff might have changed... if(hasFocus) { - fillData(); + new Thread(new Runnable() { + @Override + public void run() { + fillData(); + } + }); } } @@ -692,7 +737,7 @@ public class TaskListSubActivity extends SubActivity { /** Show the tags view */ public void showTagsView() { - switchToActivity(ActivityCode.TAG_LIST, null); + switchToActivity(TaskList.AC_TAG_LIST, null); } /** Save the sorting mode to the preferences */ @@ -823,7 +868,7 @@ public class TaskListSubActivity extends SubActivity { fillData(); return true; case CONTEXT_FILTER_TAG: - switchToActivity(ActivityCode.TASK_LIST, null); + switchToActivity(TaskList.AC_TASK_LIST, null); return true; case CONTEXT_SORT_AUTO: if(sortMode == SortMode.AUTO)