Merge remote-tracking branch 'upstream/master' into 120712_sb_in_app_billing

pull/14/head
Sam Bosley 12 years ago
commit c26dc76e91

@ -128,6 +128,9 @@ public final class TagData extends RemoteModel {
/** whether tag is emergent */
public static final int FLAG_EMERGENT = 1 << 2;
/** whether tag represents a featured list */
public static final int FLAG_FEATURED = 1 << 3;
// --- defaults
/** Default values container */

@ -344,7 +344,16 @@
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<activity android:name="com.todoroo.astrid.people.PeopleViewActivity"
<!-- Featured lists -->
<receiver android:name="com.todoroo.astrid.tags.reusable.FeaturedListFilterExposer">
<intent-filter>
<action android:name="com.timsu.astrid.REQUEST_FEATURED_LISTS"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<activity android:name="com.todoroo.astrid.tags.reusable.FeaturedListActivity"
android:windowSoftInputMode="stateHidden|adjustResize"/>
<!-- alarms -->

@ -103,8 +103,6 @@ public class TagViewFragment extends TaskListFragment {
private boolean justDeleted = false;
//private ImageAdapter galleryAdapter;
// --- UI initialization
@Override
@ -149,7 +147,7 @@ public class TagViewFragment extends TaskListFragment {
*/
@Override
protected View getListBody(ViewGroup root) {
ViewGroup parent = (ViewGroup) getActivity().getLayoutInflater().inflate(R.layout.task_list_body_tag, root, false);
ViewGroup parent = (ViewGroup) getActivity().getLayoutInflater().inflate(getTaskListBodyLayout(), root, false);
taskListView = super.getListBody(parent);
parent.addView(taskListView);
@ -157,6 +155,10 @@ public class TagViewFragment extends TaskListFragment {
return parent;
}
protected int getTaskListBodyLayout() {
return R.layout.task_list_body_tag;
}
private void showListSettingsPopover() {
if (!AstridPreferences.canShowPopover())
return;
@ -302,7 +304,7 @@ public class TagViewFragment extends TaskListFragment {
Preferences.setLong(LAST_FETCH_KEY + tagData.getId(), DateUtilities.now());
}
private void setUpMembersGallery() {
protected void setUpMembersGallery() {
LinearLayout membersView = (LinearLayout)getView().findViewById(R.id.shared_with);
membersView.setOnClickListener(settingsListener);
try {
@ -537,7 +539,7 @@ public class TagViewFragment extends TaskListFragment {
@Override
protected boolean hasDraggableOption() {
return true;
return tagData != null && !tagData.getFlag(TagData.FLAGS, TagData.FLAG_FEATURED);
}
@Override

@ -19,6 +19,7 @@ import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Query;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
@ -204,6 +205,27 @@ public final class ActFmDataService {
}
}
@SuppressWarnings("nls")
public void saveFeaturedList(JSONObject featObject) throws JSONException {
TodorooCursor<TagData> cursor = tagDataService.query(Query.select(TagData.PROPERTIES).where(
Criterion.and(Functions.bitwiseAnd(TagData.FLAGS, TagData.FLAG_FEATURED).gt(0), TagData.REMOTE_ID.eq(featObject.get("id")))));
try {
cursor.moveToNext();
TagData tagData = new TagData();
if (!cursor.isAfterLast()) {
tagData.readFromCursor(cursor);
if(!tagData.getValue(TagData.NAME).equals(featObject.getString("name")))
TagService.getInstance().rename(tagData.getValue(TagData.NAME), featObject.getString("name"));
cursor.moveToNext();
}
ActFmSyncService.JsonHelper.featuredListFromJson(featObject, tagData);
tagDataService.save(tagData);
} finally {
cursor.close();
}
}
/**
* Save / Merge JSON user
* @param userObject

@ -42,6 +42,7 @@ import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.Query;
@ -837,7 +838,26 @@ public final class ActFmSyncService {
if(serverTime == 0) {
Long[] remoteIdArray = remoteIds.toArray(new Long[remoteIds.size()]);
tagDataService.deleteWhere(Criterion.not(TagData.REMOTE_ID.in(remoteIdArray)));
tagDataService.deleteWhere(Criterion.and(
Criterion.not(Functions.bitwiseAnd(TagData.FLAGS, TagData.FLAG_FEATURED).gt(0)),
Criterion.not(TagData.REMOTE_ID.in(remoteIdArray))));
}
return result.optInt("time", 0);
}
public int fetchFeaturedLists(int serverTime) throws JSONException, IOException {
if (!checkForToken())
return 0;
JSONObject result = actFmInvoker.invoke("featured_lists",
"token", token, "modified_after", serverTime);
JSONArray featuredLists = result.getJSONArray("list");
if (featuredLists.length() > 0)
Preferences.setBoolean(R.string.p_show_featured_lists, true);
for (int i = 0; i < featuredLists.length(); i++) {
JSONObject featObject = featuredLists.getJSONObject(i);
actFmDataService.saveFeaturedList(featObject);
}
return result.optInt("time", 0);
@ -1212,6 +1232,7 @@ public final class ActFmSyncService {
} catch (SQLiteConstraintException e) {
taskDao.handleSQLiteConstraintException(remote);
}
ids.add(remote.getId());
metadataService.synchronizeMetadata(remote.getId(), metadata, MetadataCriteria.withKey(TagService.KEY));
synchronizeAttachments(item, remote);
@ -1444,10 +1465,23 @@ public final class ActFmSyncService {
* @throws JSONException
*/
public static void tagFromJson(JSONObject json, TagData model) throws JSONException {
parseTagDataFromJson(json, model, false);
}
public static void featuredListFromJson(JSONObject json, TagData model) throws JSONException {
parseTagDataFromJson(json, model, true);
}
private static void parseTagDataFromJson(JSONObject json, TagData model, boolean featuredList) throws JSONException {
model.clearValue(TagData.REMOTE_ID);
model.setValue(TagData.REMOTE_ID, json.getLong("id"));
model.setValue(TagData.NAME, json.getString("name"));
readUser(json.getJSONObject("user"), model, TagData.USER_ID, TagData.USER);
if (!featuredList)
readUser(json.getJSONObject("user"), model, TagData.USER_ID, TagData.USER);
if (featuredList)
model.setFlag(TagData.FLAGS, TagData.FLAG_FEATURED, true);
if(json.has("picture"))
model.setValue(TagData.PICTURE, json.optString("picture", ""));

@ -21,6 +21,7 @@ import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.Preferences;
@ -135,6 +136,8 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
private static final String LAST_TAG_FETCH_TIME = "actfm_lastTag"; //$NON-NLS-1$
private static final String LAST_FEATURED_TAG_FETCH_TIME = "actfm_last_featuredTag"; //$NON-NLS-1$
private static final String LAST_USERS_FETCH_TIME = "actfm_lastUsers"; //$NON-NLS-1$
// --- synchronize active tasks
@ -146,9 +149,9 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
new Thread(new Runnable() {
public void run() {
callback.started();
callback.incrementMax(140);
callback.incrementMax(160);
final AtomicInteger finisher = new AtomicInteger(4);
final AtomicInteger finisher = new AtomicInteger(5);
actFmPreferenceService.recordSyncStart();
updateUserStatus();
@ -159,6 +162,8 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
startUpdatesFetcher(manual, callback, finisher);
startFeaturedListFetcher(callback, finisher);
actFmSyncService.waitUntilEmpty();
startTaskFetcher(manual, callback, finisher);
@ -259,7 +264,32 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
}
}
});
}
/** fetch changes to tags */
private void startFeaturedListFetcher(final SyncResultCallback callback,
final AtomicInteger finisher) {
new Thread(new Runnable() {
@Override
public void run() {
int time = Preferences.getInt(LAST_FEATURED_TAG_FETCH_TIME, 0);
try {
if (Preferences.getBoolean(R.string.p_show_featured_lists_labs, false)) {
time = actFmSyncService.fetchFeaturedLists(time);
Preferences.setInt(LAST_FEATURED_TAG_FETCH_TIME, time);
}
} catch (JSONException e) {
handler.handleException("actfm-sync", e, e.toString()); //$NON-NLS-1$
} catch (IOException e) {
handler.handleException("actfm-sync", e, e.toString()); //$NON-NLS-1$
} finally {
callback.incrementProgress(20);
if(finisher.decrementAndGet() == 0) {
finishSync(callback);
}
}
}
}).start();
}
/** @return runnable to fetch changes to tags */
@ -346,10 +376,12 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
private void pushQueuedTags(final SyncResultCallback callback,
final AtomicInteger finisher, int lastTagSyncTime) {
TodorooCursor<TagData> tagDataCursor = tagDataService.query(Query.select(TagData.PROPERTIES)
.where(Criterion.or(
.where(Criterion.and(
Functions.bitwiseAnd(TagData.FLAGS, TagData.FLAG_FEATURED).eq(0),
Criterion.or(
TagData.REMOTE_ID.eq(0),
Criterion.and(TagData.REMOTE_ID.gt(0),
TagData.MODIFICATION_DATE.gt(lastTagSyncTime)))));
TagData.MODIFICATION_DATE.gt(lastTagSyncTime))))));
try {
pushQueued(callback, finisher, tagDataCursor, true, tagPusher);
} finally {

@ -58,7 +58,7 @@ public class PhoneStateChangedReceiver extends BroadcastReceiver {
AndroidUtilities.sleepDeep(WAIT_BEFORE_READ_LOG);
Cursor calls = context.getContentResolver().query(
Calls.CONTENT_URI,
null,
new String[] { Calls.NUMBER, Calls.DATE, Calls.CACHED_NAME },
Calls.TYPE + " = ? AND " + Calls.NEW + " = ?",
new String[] { Integer.toString(Calls.MISSED_TYPE), "1" },
Calls.DATE + " DESC"
@ -89,9 +89,7 @@ public class PhoneStateChangedReceiver extends BroadcastReceiver {
int nameIndex = calls.getColumnIndex(Calls.CACHED_NAME);
String name = calls.getString(nameIndex);
int timeIndex = calls.getColumnIndex(Calls.DATE);
long time = calls.getLong(timeIndex);
String timeString = DateUtilities.getTimeString(context, new Date(time));
String timeString = DateUtilities.getTimeString(context, new Date(date));
long contactId = getContactIdFromNumber(context, number);

@ -24,22 +24,32 @@ public class LabsPreferences extends TodorooPreferenceActivity {
return R.xml.preferences_labs;
}
public static final int PERFORMANCE_SETTING_CHANGED = 3;
public static final int RESULT_TLA_NEEDS_REFRESH = 3;
public static final int RESULT_NEEDS_SYNC = 4;
private class SetResultOnPreferenceChangeListener implements OnPreferenceChangeListener {
private final int resultCode;
public SetResultOnPreferenceChangeListener(int resultCode) {
this.resultCode = resultCode;
}
private final OnPreferenceChangeListener settingChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference p, Object newValue) {
setResult(PERFORMANCE_SETTING_CHANGED);
setResult(resultCode);
updatePreferences(p, newValue);
return true;
}
};
}
@Override
public void onCreate(android.os.Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EditPreferences.removeForbiddenPreferences(getPreferenceScreen(), getResources());
if (!AndroidUtilities.isTabletSized(this)) {
PreferenceScreen screen = getPreferenceScreen();
screen.removePreference(screen.findPreference(getString(R.string.p_force_phone_layout)));
}
}
@Override
@ -48,7 +58,7 @@ public class LabsPreferences extends TodorooPreferenceActivity {
String key = preference.getKey();
if (r.getString(R.string.p_swipe_lists_performance_key).equals(key)) {
preference.setOnPreferenceChangeListener(settingChangedListener);
preference.setOnPreferenceChangeListener(new SetResultOnPreferenceChangeListener(RESULT_TLA_NEEDS_REFRESH));
int index = 0;
if(value instanceof String && !TextUtils.isEmpty((String)value))
@ -76,12 +86,9 @@ public class LabsPreferences extends TodorooPreferenceActivity {
screen.removePreference(preference);
}
} else if (r.getString(R.string.p_force_phone_layout).equals(key)) {
if (!AndroidUtilities.isTabletSized(this)) {
PreferenceScreen screen = getPreferenceScreen();
screen.removePreference(preference);
} else {
preference.setOnPreferenceChangeListener(settingChangedListener);
}
preference.setOnPreferenceChangeListener(new SetResultOnPreferenceChangeListener(RESULT_TLA_NEEDS_REFRESH));
} else if (r.getString(R.string.p_show_featured_lists_labs).equals(key)) {
preference.setOnPreferenceChangeListener(new SetResultOnPreferenceChangeListener(RESULT_NEEDS_SYNC));
}
}

@ -0,0 +1,59 @@
package com.todoroo.astrid.people;
import android.content.Context;
import com.timsu.astrid.R;
import com.todoroo.astrid.activity.FilterListFragment;
import com.todoroo.astrid.activity.FilterModeSpec;
import com.todoroo.astrid.activity.TaskListFragment;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.api.FilterWithUpdate;
import com.todoroo.astrid.helper.AsyncImageView;
import com.todoroo.astrid.ui.MainMenuPopover;
public class PeopleFilterMode implements FilterModeSpec {
private AsyncImageView imageView;
@Override
public Filter getDefaultFilter(Context context) {
Filter defaultFilter = PeopleFilterExposer.mySharedTasks(context);
return defaultFilter;
}
@Override
public Class<? extends FilterListFragment> getFilterListClass() {
return PeopleListFragment.class;
}
@Override
public void onFilterItemClickedCallback(FilterListItem item) {
if (imageView == null)
return;
if (item instanceof FilterWithUpdate)
imageView.setUrl(((FilterWithUpdate) item).imageUrl);
else
imageView.setUrl(null);
}
public void setImageView(AsyncImageView imageView) {
this.imageView = imageView;
}
@Override
public int[] getForbiddenMenuItems() {
return FORBIDDEN_MENU_ITEMS;
}
@Override
public int getMainMenuIconAttr() {
return R.attr.asPeopleMenu;
}
private static final int[] FORBIDDEN_MENU_ITEMS = {
TaskListFragment.MENU_NEW_FILTER_ID,
TaskListFragment.MENU_ADDONS_ID,
MainMenuPopover.MAIN_MENU_ITEM_FRIENDS
};
}

@ -22,8 +22,8 @@ public class PeopleListFragment extends FilterListFragment {
@Override
protected int getLayout(Activity activity) {
if (AstridPreferences.useTabletLayout(activity))
return R.layout.people_list_fragment_3pane;
return R.layout.filter_list_fragment_alternative_3pane;
else
return R.layout.people_list_fragment;
return R.layout.filter_list_fragment_alternative;
}
}

@ -1,85 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.people;
import android.content.Intent;
import android.os.Bundle;
import com.timsu.astrid.R;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.activity.FilterListFragment;
import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.activity.TaskListFragment;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.api.FilterWithUpdate;
import com.todoroo.astrid.helper.AsyncImageView;
import com.todoroo.astrid.ui.MainMenuPopover;
public class PeopleViewActivity extends TaskListActivity {
private AsyncImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
imageView = (AsyncImageView) findViewById(R.id.person_image);
imageView.setDefaultImageResource(R.drawable.icn_default_person_image);
}
@Override
protected int getContentView() {
return R.layout.people_view_wrapper_activity;
}
@Override
protected Filter getDefaultFilter() {
Filter defaultFilter = PeopleFilterExposer.mySharedTasks(this);
return defaultFilter;
}
@Override
protected Class<? extends FilterListFragment> getFilterListClass() {
return PeopleListFragment.class;
}
@Override
protected int getHeaderView() {
return R.layout.header_people_view;
}
@Override
public boolean onFilterItemClicked(FilterListItem item) {
boolean result = super.onFilterItemClicked(item);
if (result && item instanceof FilterWithUpdate)
imageView.setUrl(((FilterWithUpdate) item).imageUrl);
else
imageView.setUrl(null);
return result;
}
private static final int[] FORBIDDEN_MENU_ITEMS = {
TaskListFragment.MENU_NEW_FILTER_ID,
TaskListFragment.MENU_ADDONS_ID,
MainMenuPopover.MAIN_MENU_ITEM_FRIENDS
};
@Override
public boolean shouldAddMenuItem(int itemId) {
return AndroidUtilities.indexOf(FORBIDDEN_MENU_ITEMS, itemId) < 0;
}
@Override
public void mainMenuItemSelected(int item, Intent customIntent) {
if (item == MainMenuPopover.MAIN_MENU_ITEM_LISTS) {
finish();
return;
}
super.mainMenuItemSelected(item, customIntent);
}
}

@ -6,6 +6,7 @@
package com.todoroo.astrid.tags;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.BroadcastReceiver;
@ -60,9 +61,11 @@ public class TagFilterExposer extends BroadcastReceiver implements AstridFilterE
private static final String TAG = "tag"; //$NON-NLS-1$
@Autowired TagDataService tagDataService;
@Autowired protected TagDataService tagDataService;
@Autowired GtasksPreferenceService gtasksPreferenceService;
protected boolean addUntaggedFilter = true;
/** Create filter from new tag object */
@SuppressWarnings("nls")
public static FilterWithCustomIntent filterFromTag(Context context, Tag tag, Criterion criterion) {
@ -141,7 +144,7 @@ public class TagFilterExposer extends BroadcastReceiver implements AstridFilterE
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
private FilterListItem[] prepareFilters(Context context) {
protected FilterListItem[] prepareFilters(Context context) {
DependencyInjectionService.getInstance().inject(this);
ContextManager.setContext(context);
@ -155,13 +158,18 @@ public class TagFilterExposer extends BroadcastReceiver implements AstridFilterE
}
private void addTags(ArrayList<FilterListItem> list) {
ArrayList<Tag> tagList = TagService.getInstance().getTagList();
List<Tag> tagList = getTagList();
list.add(filterFromTags(tagList.toArray(new Tag[tagList.size()]),
R.string.tag_FEx_header));
}
protected List<Tag> getTagList() {
return TagService.getInstance().getTagList();
}
private FilterCategory filterFromTags(Tag[] tags, int name) {
Filter[] filters = new Filter[tags.length + 1];
int length = addUntaggedFilter ? tags.length + 1 : tags.length;
Filter[] filters = new Filter[length];
Context context = ContextManager.getContext();
Resources r = context.getResources();
@ -170,22 +178,30 @@ public class TagFilterExposer extends BroadcastReceiver implements AstridFilterE
int themeFlags = isTablet ? ThemeService.FLAG_FORCE_LIGHT : 0;
// --- untagged
int untaggedLabel = gtasksPreferenceService.isLoggedIn() ?
R.string.tag_FEx_untagged_w_astrid : R.string.tag_FEx_untagged;
Filter untagged = new Filter(r.getString(untaggedLabel),
r.getString(R.string.tag_FEx_untagged),
TagService.untaggedTemplate(),
null);
untagged.listingIcon = ((BitmapDrawable)r.getDrawable(
ThemeService.getDrawable(R.drawable.gl_lists, themeFlags))).getBitmap();
filters[0] = untagged;
for(int i = 0; i < tags.length; i++)
filters[i+1] = filterFromTag(context, tags[i], TaskCriteria.activeAndVisible());
if (addUntaggedFilter) {
int untaggedLabel = gtasksPreferenceService.isLoggedIn() ?
R.string.tag_FEx_untagged_w_astrid : R.string.tag_FEx_untagged;
Filter untagged = new Filter(r.getString(untaggedLabel),
r.getString(R.string.tag_FEx_untagged),
TagService.untaggedTemplate(),
null);
untagged.listingIcon = ((BitmapDrawable)r.getDrawable(
ThemeService.getDrawable(R.drawable.gl_lists, themeFlags))).getBitmap();
filters[0] = untagged;
}
for(int i = 0; i < tags.length; i++) {
int index = addUntaggedFilter ? i + 1 : i;
filters[index] = constructFilter(context, tags[i]);
}
FilterCategory filter = new FilterCategory(context.getString(name), filters);
return filter;
}
protected Filter constructFilter(Context context, Tag tag) {
return filterFromTag(context, tag, TaskCriteria.activeAndVisible());
}
// --- tag manipulation activities
public abstract static class TagActivity extends Activity {

@ -330,7 +330,7 @@ public final class TagService {
tagData.readFromCursor(cursor);
String tagName = tagData.getValue(TagData.NAME).trim();
Tag tag = new Tag(tagData);
if(tagData.getValue(TagData.DELETION_DATE) > 0 || tagData.getFlag(TagData.FLAGS, TagData.FLAG_EMERGENT)) {
if(tagData.getValue(TagData.DELETION_DATE) > 0 || tagData.getFlag(TagData.FLAGS, TagData.FLAG_EMERGENT) || tagData.getFlag(TagData.FLAGS, TagData.FLAG_FEATURED)) {
tags.remove(tagName);
continue;
}
@ -356,6 +356,37 @@ public final class TagService {
return tagList;
}
public ArrayList<Tag> getFeaturedLists() {
HashMap<String, Tag> tags = new HashMap<String, Tag>();
TodorooCursor<TagData> cursor = tagDataService.query(Query.select(TagData.PROPERTIES)
.where(Functions.bitwiseAnd(TagData.FLAGS, TagData.FLAG_FEATURED).gt(0)));
try {
TagData tagData = new TagData();
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
tagData.readFromCursor(cursor);
if (tagData.getValue(TagData.DELETION_DATE) > 0)
continue;
String tagName = tagData.getValue(TagData.NAME).trim();
Tag tag = new Tag(tagData);
if(TextUtils.isEmpty(tag.tag))
continue;
tags.put(tagName, tag);
}
} finally {
cursor.close();
}
ArrayList<Tag> tagList = new ArrayList<Tag>(tags.values());
Collections.sort(tagList,
new Comparator<Tag>() {
@Override
public int compare(Tag object1, Tag object2) {
return object1.tag.compareToIgnoreCase(object2.tag);
}
});
return tagList;
}
/**
* Save the given array of tags into the database
* @param taskId

@ -0,0 +1,37 @@
package com.todoroo.astrid.tags.reusable;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.widget.ListView;
import com.todoroo.astrid.adapter.FilterAdapter;
import com.todoroo.astrid.utility.Constants;
public class FeaturedListFilterAdapter extends FilterAdapter {
public static final String BROADCAST_REQUEST_FEATURED_LISTS = Constants.PACKAGE + ".REQUEST_FEATURED_LISTS"; //$NON-NLS-1$
public static final String BROADCAST_SEND_FEATURED_LISTS = Constants.PACKAGE + ".SEND_FEATURED_LISTS"; //$NON-NLS-1$
public FeaturedListFilterAdapter(Activity activity, ListView listView,
int rowLayout, boolean skipIntentFilters) {
super(activity, listView, rowLayout, skipIntentFilters);
}
@Override
public void getLists() {
Intent broadcastIntent = new Intent(BROADCAST_REQUEST_FEATURED_LISTS);
activity.sendBroadcast(broadcastIntent);
}
@Override
public void registerRecevier() {
IntentFilter peopleFilter = new IntentFilter(BROADCAST_SEND_FEATURED_LISTS);
activity.registerReceiver(filterReceiver, peopleFilter);
getLists();
}
@Override
public void unregisterRecevier() {
activity.unregisterReceiver(filterReceiver);
}
}

@ -0,0 +1,102 @@
package com.todoroo.astrid.tags.reusable;
import java.util.List;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.astrid.actfm.TagViewFragment;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.api.FilterWithCustomIntent;
import com.todoroo.astrid.api.FilterWithUpdate;
import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.TaskApiDao.TaskCriteria;
import com.todoroo.astrid.tags.TagFilterExposer;
import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.tags.TagService.Tag;
public class FeaturedListFilterExposer extends TagFilterExposer {
@Override
public void onReceive(Context context, Intent intent) {
addUntaggedFilter = false;
FilterListItem[] listAsArray = prepareFilters(context);
Intent broadcastIntent = new Intent(FeaturedListFilterAdapter.BROADCAST_SEND_FEATURED_LISTS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, listAsArray);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
private static FilterWithCustomIntent filterFromFeaturedList(Tag tag, Criterion criterion) {
String title = tag.tag;
QueryTemplate tagTemplate = tag.queryTemplate(criterion);
ContentValues contentValues = new ContentValues();
contentValues.put(Metadata.KEY.name, TagService.KEY);
contentValues.put(TagService.TAG.name, tag.tag);
FilterWithUpdate filter = new FilterWithUpdate(tag.tag,
title, tagTemplate,
contentValues);
Class<?> fragmentClass = FeaturedTaskListFragment.class;
filter.customTaskList = new ComponentName(ContextManager.getContext(), fragmentClass);
if(tag.image != null)
filter.imageUrl = tag.image;
Bundle extras = new Bundle();
extras.putString(TagViewFragment.EXTRA_TAG_NAME, tag.tag);
extras.putLong(TagViewFragment.EXTRA_TAG_REMOTE_ID, tag.remoteId);
filter.customExtras = extras;
return filter;
}
public static Filter getDefaultFilter() {
TodorooCursor<TagData> firstFilter = PluginServices.getTagDataService()
.query(Query.select(TagData.PROPERTIES)
.where(Criterion.and(
Functions.bitwiseAnd(TagData.FLAGS, TagData.FLAG_FEATURED).gt(0),
TagData.DELETION_DATE.eq(0),
TagData.NAME.isNotNull(),
TagData.NAME.neq(""))) //$NON-NLS-1$
.orderBy(Order.asc(TagData.NAME))
.limit(1));
try {
if (firstFilter.getCount() > 0) {
firstFilter.moveToFirst();
TagData tagData = new TagData(firstFilter);
Tag tag = new Tag(tagData);
return filterFromFeaturedList(tag, TaskCriteria.activeAndVisible());
} else {
return null;
}
} finally {
firstFilter.close();
}
}
@Override
protected Filter constructFilter(Context context, Tag tag) {
return filterFromFeaturedList(tag, TaskCriteria.activeAndVisible());
}
@Override
protected List<Tag> getTagList() {
return TagService.getInstance().getFeaturedLists();
}
}

@ -0,0 +1,53 @@
package com.todoroo.astrid.tags.reusable;
import android.content.Context;
import com.timsu.astrid.R;
import com.todoroo.astrid.activity.FilterListFragment;
import com.todoroo.astrid.activity.FilterModeSpec;
import com.todoroo.astrid.activity.TaskListFragment;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.core.CoreFilterExposer;
import com.todoroo.astrid.ui.MainMenuPopover;
public class FeaturedListFilterMode implements FilterModeSpec {
@Override
public int[] getForbiddenMenuItems() {
return FORBIDDEN_MENU_ITEMS;
}
private static final int[] FORBIDDEN_MENU_ITEMS = {
TaskListFragment.MENU_NEW_FILTER_ID,
TaskListFragment.MENU_ADDONS_ID,
MainMenuPopover.MAIN_MENU_ITEM_FEATURED_LISTS
};
@Override
public Class<? extends FilterListFragment> getFilterListClass() {
return FeaturedListFragment.class;
}
@Override
public Filter getDefaultFilter(Context context) {
Filter defaultFilter = FeaturedListFilterExposer.getDefaultFilter();
if (defaultFilter == null)
return CoreFilterExposer.buildInboxFilter(context.getResources());
else
return defaultFilter;
}
@Override
public int getMainMenuIconAttr() {
return R.attr.asMainMenu;
}
@Override
public void onFilterItemClickedCallback(FilterListItem item) {
//
}
}

@ -0,0 +1,25 @@
package com.todoroo.astrid.tags.reusable;
import android.app.Activity;
import com.timsu.astrid.R;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.activity.FilterListFragment;
import com.todoroo.astrid.adapter.FilterAdapter;
public class FeaturedListFragment extends FilterListFragment {
@Override
protected FilterAdapter instantiateAdapter() {
return new FeaturedListFilterAdapter(getActivity(), null, R.layout.filter_adapter_row, false);
}
@Override
protected int getLayout(Activity activity) {
if (AndroidUtilities.isTabletSized(activity))
return R.layout.filter_list_fragment_alternative_3pane;
else
return R.layout.filter_list_fragment_alternative;
}
}

@ -0,0 +1,113 @@
package com.todoroo.astrid.tags.reusable;
import android.app.Activity;
import android.app.ProgressDialog;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.astrid.actfm.TagViewFragment;
import com.todoroo.astrid.adapter.TaskAdapter;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.TagDataService;
import com.todoroo.astrid.utility.Flags;
public class FeaturedTaskListFragment extends TagViewFragment {
@Autowired private TagDataService tagDataService;
@Override
protected TaskAdapter createTaskAdapter(TodorooCursor<Task> cursor) {
return new ReusableTaskAdapter(this, R.layout.reusable_task_adapter_row,
cursor, sqlQueryTemplate, false, null);
}
@Override
protected void setupQuickAddBar() {
super.setupQuickAddBar();
quickAddBar.setVisibility(View.GONE);
((TextView) getView().findViewById(android.R.id.empty)).setOnClickListener(null);
}
@Override
public void onTaskListItemClicked(long taskId) {
// Do nothing
}
@Override
protected int getTaskListBodyLayout() {
return R.layout.task_list_body_featured_list;
}
@Override
protected void setUpMembersGallery() {
// Repurposed this method to set up listener for clone list button
View clone = getView().findViewById(R.id.clone_list);
clone.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Clone list
if (taskAdapter == null || taskAdapter.getCount() == 0) {
Toast.makeText(getActivity(), R.string.actfm_feat_list_clone_empty, Toast.LENGTH_LONG).show();
return;
}
final String localName = tagData.getValue(TagData.NAME) + " " + getString(R.string.actfm_feat_list_suffix); //$NON-NLS-1$
long remoteId = 0;
TodorooCursor<TagData> existing = tagDataService.query(Query.select(TagData.REMOTE_ID)
.where(TagData.NAME.eqCaseInsensitive(localName)));
try {
if (existing.getCount() > 0) {
existing.moveToFirst();
TagData match = new TagData(existing);
remoteId = match.getValue(TagData.REMOTE_ID);
}
} finally {
existing.close();
}
final ProgressDialog pd = DialogUtilities.progressDialog(getActivity(), getString(R.string.actfm_feat_list_cloning));
final long finalRemoteId = remoteId;
new Thread(new Runnable() {
@Override
public void run() {
TodorooCursor<Task> tasks = taskService.fetchFiltered(taskAdapter.getQuery(), null, Task.PROPERTIES);
try {
Task t = new Task();
for (tasks.moveToFirst(); !tasks.isAfterLast(); tasks.moveToNext()) {
t.readFromCursor(tasks);
taskService.cloneReusableTask(t,
localName, finalRemoteId);
}
Activity activity = getActivity();
if (activity != null) {
DialogUtilities.dismissDialog(activity, pd);
DialogUtilities.okDialog(activity, getString(R.string.actfm_feat_list_clone_success), null);
}
Flags.set(Flags.REFRESH);
} finally {
tasks.close();
}
}
}).start();
}
});
}
@Override
protected void refresh() {
loadTaskListContent(true);
((TextView)taskListView.findViewById(android.R.id.empty)).setText(R.string.TLA_no_items);
setUpMembersGallery();
}
}

@ -0,0 +1,84 @@
package com.todoroo.astrid.tags.reusable;
import java.util.concurrent.atomic.AtomicReference;
import android.content.Context;
import android.database.Cursor;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.activity.TaskListFragment;
import com.todoroo.astrid.adapter.TaskAdapter;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.utility.Flags;
public class ReusableTaskAdapter extends TaskAdapter {
public ReusableTaskAdapter(TaskListFragment fragment, int resource,
Cursor c, AtomicReference<String> query, boolean autoRequery,
OnCompletedTaskListener onCompletedTaskListener) {
super(fragment, resource, c, query, autoRequery, onCompletedTaskListener);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
ViewGroup view = (ViewGroup)inflater.inflate(resource, parent, false);
ReusableTaskViewHolder viewHolder = new ReusableTaskViewHolder();
viewHolder.task = new Task();
viewHolder.clone = (ImageView) view.findViewById(R.id.clone_task);
viewHolder.title = (TextView) view.findViewById(R.id.title);
boolean showFullTaskTitle = Preferences.getBoolean(R.string.p_fullTaskTitle, false);
if (showFullTaskTitle) {
viewHolder.title.setMaxLines(Integer.MAX_VALUE);
}
view.setTag(viewHolder);
for(int i = 0; i < view.getChildCount(); i++)
view.getChildAt(i).setTag(viewHolder);
viewHolder.clone.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ReusableTaskViewHolder holder = (ReusableTaskViewHolder) v.getTag();
taskService.cloneReusableTask(holder.task, null, 0);
Toast.makeText(fragment.getActivity(), R.string.actfm_feat_list_task_clone_success, Toast.LENGTH_LONG).show();
Flags.set(Flags.REFRESH);
}
});
return view;
}
@Override
public void bindView(View view, Context context, Cursor c) {
TodorooCursor<Task> cursor = (TodorooCursor<Task>)c;
ReusableTaskViewHolder viewHolder = (ReusableTaskViewHolder) view.getTag();
Task task = viewHolder.task;
task.clear();
task.readFromCursor(cursor);
viewHolder.title.setText(task.getValue(Task.TITLE));
if (Preferences.getBoolean(R.string.p_allowCompressedTaskRows, false)) {
view.setMinimumHeight(0);
} else {
view.setMinimumHeight(minRowHeight);
}
}
public static class ReusableTaskViewHolder {
public Task task;
public ImageView clone;
public TextView title;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true"
android:drawable="@drawable/icn_clone_down" />
<item android:drawable="@drawable/icn_clone_up" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

@ -18,6 +18,8 @@
android:layout_alignParentTop="true"
android:scrollbars="vertical"
android:divider="@android:color/transparent"
android:dividerHeight="1px"
android:background="@android:color/transparent"
android:cacheColorHint="#00000000"/>
</LinearLayout>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:name="com.todoroo.astrid.tags.reusable.FeaturedListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="filterlist_fragment">
</fragment>
</FrameLayout>

@ -18,6 +18,8 @@
android:layout_alignParentTop="true"
android:scrollbars="vertical"
android:divider="@android:color/transparent"
android:dividerHeight="1px"
android:background="@android:color/transparent"
android:cacheColorHint="#00000000"/>
</LinearLayout>

@ -7,7 +7,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="?attr/asListPopoverBg"
android:background="@color/tablet_list_bg"
android:orientation="vertical">
@ -18,6 +18,8 @@
android:layout_alignParentTop="true"
android:scrollbars="vertical"
android:divider="@android:color/transparent"
android:dividerHeight="1px"
android:background="@android:color/transparent"
android:cacheColorHint="#00000000"/>
</LinearLayout>

@ -54,6 +54,13 @@
</RelativeLayout>
</LinearLayout>
<com.todoroo.astrid.helper.AsyncImageView
android:id="@+id/person_image"
android:layout_width="51dip"
android:layout_height="fill_parent"
android:scaleType="centerCrop"
android:visibility="gone"/>
<Button
android:id="@+id/comments"
android:layout_width="51dip"

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- See the file "LICENSE" for the full license governing this code. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:astrid="http://schemas.android.com/apk/res/com.timsu.astrid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/list_selector_background"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:id="@+id/clone_task"
android:layout_width="45dip"
android:layout_height="45dip"
android:layout_centerVertical="true"
android:src="@drawable/btn_clone"
android:scaleType="fitCenter"
android:padding="6dip"/>
<!-- task name -->
<TextView
android:id="@+id/title"
style="@style/TextAppearance.TAd_ItemTitle"
android:layout_marginLeft="3dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="100"
android:gravity="center_vertical"
android:maxLines="2" />
</LinearLayout>

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="100">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="43dip"
android:layout_weight="1"
android:gravity="center"
android:background="?attr/asMembersHeaderBackground">
<TextView
android:id="@+id/clone_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
style="@style/TextAppearance"
android:textStyle="bold"
android:textColor="#333333"
android:text="@string/actfm_feat_list_clone"/>
<ImageView
android:id="@+id/members_edit"
android:layout_width="43dip"
android:layout_height="43dip"
android:padding="5dip"
android:layout_weight="1"
android:src="@drawable/list_settings"
android:scaleType="fitCenter"
android:visibility="gone"/>
</LinearLayout>
<TextView
android:id="@+id/filter_assigned"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:paddingTop="3dip"
android:paddingBottom="3dip"
style="@style/TextAppearance"
android:background="@android:color/darker_gray"
android:visibility="gone"/>
</LinearLayout>
<!-- List body goes here -->
</LinearLayout>

@ -52,6 +52,9 @@
<!-- show friends view preference -->
<string name="p_show_friends_view">show_friends_view</string>
<!-- show featured lists preference -->
<string name="p_show_featured_lists">show_featured_lists</string>
<!-- enable third party addons preference -->
<string name="p_third_party_addons">third_party_addons</string>
@ -61,6 +64,9 @@
<!-- force tablets to use phone layout -->
<string name="p_force_phone_layout">force_phone_layout</string>
<!-- show featured lists -->
<string name="p_show_featured_lists_labs">show_featured_lists_labs</string>
<string-array name="TEA_reminder_random_hours">
<!-- values (in hours) associated with items above. -->
<item>1</item>

@ -271,6 +271,20 @@
<!-- share login: OAUTH Login Prompt -->
<string name="actfm_OLA_prompt">Please log in:</string>
<!-- ================================================ Featured Lists -->
<string name="actfm_feat_list_clone">Copy this list</string>
<string name="actfm_feat_list_suffix">(Copy)</string>
<string name="actfm_feat_list_cloning">Copying...</string>
<string name="actfm_feat_list_clone_success">Success!</string>
<string name="actfm_feat_list_task_clone_success">Task copied</string>
<string name="actfm_feat_list_clone_empty">No tasks to copy</string>
<!-- ================================================ Synchronization == -->
<!-- Indicates the logged in user name. %s -> user's name -->

@ -128,6 +128,9 @@
<!-- Menu: Friends -->
<string name="TLA_menu_friends">People</string>
<!-- Menu: Featured Lists -->
<string name="TLA_menu_featured_lists">Featured Lists</string>
<!-- Menu: Suggestions -->
<string name="TLA_menu_suggestions">Suggestions</string>
@ -660,6 +663,8 @@
<string name="EPr_force_phone_layout">Use phone layout</string>
<string name="EPr_show_featured_lists">Show featured lists</string>
<string name="EPr_swipe_lists_restart_alert">You will need to restart Astrid for this change to take effect</string>
<string-array name="EPr_swipe_lists_performance_mode">

@ -34,5 +34,9 @@
android:title="@string/EPr_force_phone_layout"
android:key="@string/p_force_phone_layout"
android:defaultValue="false"/>
<CheckBoxPreference
android:title="@string/EPr_show_featured_lists"
android:key="@string/p_show_featured_lists_labs"
android:defaultValue="false"/>
</PreferenceScreen>

@ -0,0 +1,42 @@
package com.todoroo.astrid.activity;
import android.content.Context;
import com.timsu.astrid.R;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.core.CoreFilterExposer;
import com.todoroo.astrid.ui.MainMenuPopover;
public class DefaultFilterMode implements FilterModeSpec {
@Override
public int[] getForbiddenMenuItems() {
if (Preferences.getBoolean(R.string.p_show_featured_lists_labs, false))
return new int[0];
else
return new int[] { MainMenuPopover.MAIN_MENU_ITEM_FEATURED_LISTS };
}
@Override
public Class<? extends FilterListFragment> getFilterListClass() {
return FilterListFragment.class;
}
@Override
public Filter getDefaultFilter(Context context) {
return CoreFilterExposer.buildInboxFilter(context.getResources());
}
@Override
public int getMainMenuIconAttr() {
return R.attr.asMainMenu;
}
@Override
public void onFilterItemClickedCallback(FilterListItem item) {
//
}
}

@ -85,7 +85,7 @@ public class EditPreferences extends TodorooPreferenceActivity {
private static final int POWER_PACK_PREFERENCE = 5;
private static final int REQUEST_CODE_SYNC = 0;
private static final int REQUEST_CODE_PERFORMANCE = 1;
private static final int REQUEST_CODE_LABS = 1;
private static final int REQUEST_CODE_FILES_DIR = 2;
public static final int RESULT_CODE_THEME_CHANGED = 1;
@ -253,7 +253,7 @@ public class EditPreferences extends TodorooPreferenceActivity {
private static final HashMap<Class<?>, Integer> PREFERENCE_REQUEST_CODES = new HashMap<Class<?>, Integer>();
static {
PREFERENCE_REQUEST_CODES.put(SyncProviderPreferences.class, REQUEST_CODE_SYNC);
PREFERENCE_REQUEST_CODES.put(LabsPreferences.class, REQUEST_CODE_PERFORMANCE);
PREFERENCE_REQUEST_CODES.put(LabsPreferences.class, REQUEST_CODE_LABS);
}
private void addPluginPreferences(PreferenceScreen screen) {
@ -494,9 +494,13 @@ public class EditPreferences extends TodorooPreferenceActivity {
setResult(SyncProviderPreferences.RESULT_CODE_SYNCHRONIZE);
finish();
return;
} else if (requestCode == REQUEST_CODE_PERFORMANCE && resultCode == LabsPreferences.PERFORMANCE_SETTING_CHANGED) {
} else if (requestCode == REQUEST_CODE_LABS && resultCode == LabsPreferences.RESULT_TLA_NEEDS_REFRESH) {
setResult(RESULT_CODE_PERFORMANCE_PREF_CHANGED);
return;
} else if (requestCode == REQUEST_CODE_LABS && resultCode == LabsPreferences.RESULT_NEEDS_SYNC) {
if (Preferences.getBoolean(R.string.p_show_featured_lists_labs, false))
setResult(SyncProviderPreferences.RESULT_CODE_SYNCHRONIZE);
return;
} else if (requestCode == REQUEST_CODE_FILES_DIR && resultCode == RESULT_OK) {
if (data != null) {
String dir = data.getStringExtra(FileExplore.RESULT_DIR_SELECTED);

@ -0,0 +1,17 @@
package com.todoroo.astrid.activity;
import android.content.Context;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
public interface FilterModeSpec {
public int[] getForbiddenMenuItems();
public Class<? extends FilterListFragment> getFilterListClass();
public Filter getDefaultFilter(Context context);
public int getMainMenuIconAttr();
public void onFilterItemClickedCallback(FilterListItem item);
}

@ -45,16 +45,16 @@ import com.todoroo.astrid.adapter.TaskListFragmentPagerAdapter;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.core.CoreFilterExposer;
import com.todoroo.astrid.core.CustomFilterExposer;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.people.PeopleListFragment;
import com.todoroo.astrid.people.PeopleViewActivity;
import com.todoroo.astrid.helper.AsyncImageView;
import com.todoroo.astrid.people.PeopleFilterMode;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.ThemeService;
import com.todoroo.astrid.service.abtesting.ABTestEventReportingService;
import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.tags.reusable.FeaturedListFilterMode;
import com.todoroo.astrid.ui.DateChangedAlerts;
import com.todoroo.astrid.ui.FragmentPopover;
import com.todoroo.astrid.ui.MainMenuPopover;
@ -75,7 +75,10 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
public static final String OPEN_TASK = "openTask"; //$NON-NLS-1$
private static final String PEOPLE_VIEW = "peopleView"; //$NON-NLS-1$
private static final String FILTER_MODE = "filterMode"; //$NON-NLS-1$
private static final int FILTER_MODE_NORMAL = 0;
private static final int FILTER_MODE_PEOPLE = 1;
private static final int FILTER_MODE_FEATURED = 2;
@Autowired private ABTestEventReportingService abTestEventReportingService;
@ -83,7 +86,10 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
private ImageView listsNavDisclosure;
private TextView lists;
private ImageView mainMenu;
private AsyncImageView personImage;
private Button commentsButton;
private int filterMode;
private FilterModeSpec filterModeSpec;
private TaskListFragmentPager tlfPager;
private TaskListFragmentPagerAdapter tlfPagerAdapter;
@ -155,6 +161,8 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
listsNavDisclosure = (ImageView) actionBar.getCustomView().findViewById(R.id.list_disclosure_arrow);
lists = (TextView) actionBar.getCustomView().findViewById(R.id.list_title);
mainMenu = (ImageView) actionBar.getCustomView().findViewById(R.id.main_menu);
personImage = (AsyncImageView) actionBar.getCustomView().findViewById(R.id.person_image);
personImage.setDefaultImageResource(R.drawable.icn_default_person_image);
commentsButton = (Button) actionBar.getCustomView().findViewById(R.id.comments);
initializeFragments(actionBar);
@ -226,7 +234,7 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
}
protected Filter getDefaultFilter() {
return CoreFilterExposer.buildInboxFilter(getResources());
return filterModeSpec.getDefaultFilter(this);
}
private boolean swipeIsEnabled() {
@ -259,6 +267,8 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
protected void initializeFragments(ActionBar actionBar) {
View filterFragment = findViewById(R.id.filterlist_fragment_container);
View editFragment = findViewById(R.id.taskedit_fragment_container);
filterMode = getIntent().getIntExtra(FILTER_MODE, FILTER_MODE_NORMAL);
updateFilterModeSpec(filterMode);
if (filterFragment != null) {
actionBar.setDisplayHomeAsUpEnabled(false);
@ -275,19 +285,15 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
}
}
boolean peopleView = getIntent().getBooleanExtra(PEOPLE_VIEW, false);
Class<? extends FilterListFragment> filterFragmentClass =
peopleView ? PeopleListFragment.class : FilterListFragment.class;
setupFragment(FilterListFragment.TAG_FILTERLIST_FRAGMENT,
R.id.filterlist_fragment_container, filterFragmentClass, false, false);
R.id.filterlist_fragment_container, filterModeSpec.getFilterListClass(), false, false);
} else {
fragmentLayout = LAYOUT_SINGLE;
actionBar.setDisplayHomeAsUpEnabled(true);
listsNav.setOnClickListener(popupMenuClickListener);
createListsPopover();
setupPopoverWithFilterList((FilterListFragment) setupFragment(FilterListFragment.TAG_FILTERLIST_FRAGMENT, 0,
getFilterListClass(), true, false));
filterModeSpec.getFilterListClass(), true, false));
}
}
@ -328,7 +334,7 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
});
if (isTablet)
setupMainMenuForPeopleViewState(getIntent().getBooleanExtra(PEOPLE_VIEW, false));
mainMenuPopover.refreshFixedItems();
}
private void setupPopoverWithFragment(FragmentPopover popover, Fragment frag, LayoutParams params) {
@ -366,7 +372,9 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
if (tef != null)
onBackPressed();
return super.onFilterItemClicked(item);
boolean result = super.onFilterItemClicked(item);
filterModeSpec.onFilterItemClickedCallback(item);
return result;
}
private void setListsDropdownSelected(boolean selected) {
@ -637,7 +645,7 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
@Override
public boolean shouldAddMenuItem(int itemId) {
return true;
return AndroidUtilities.indexOf(filterModeSpec.getForbiddenMenuItems(), itemId) < 0;
}
@Override
@ -645,21 +653,19 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
TaskListFragment tlf = getTaskListFragment();
switch (item) {
case MainMenuPopover.MAIN_MENU_ITEM_LISTS:
if (fragmentLayout == LAYOUT_SINGLE)
if (filterMode == FILTER_MODE_NORMAL)
listsNav.performClick();
else
togglePeopleView();
setFilterMode(FILTER_MODE_NORMAL);
return;
case MainMenuPopover.MAIN_MENU_ITEM_SEARCH:
onSearchRequested();
return;
case MainMenuPopover.MAIN_MENU_ITEM_FEATURED_LISTS:
setFilterMode(FILTER_MODE_FEATURED);
return;
case MainMenuPopover.MAIN_MENU_ITEM_FRIENDS:
if (fragmentLayout != LAYOUT_SINGLE) {
togglePeopleView();
} else {
Intent peopleIntent = new Intent(this, PeopleViewActivity.class);
startActivity(peopleIntent);
}
setFilterMode(FILTER_MODE_PEOPLE);
return;
case MainMenuPopover.MAIN_MENU_ITEM_SUGGESTIONS:
// Doesn't exist yet
@ -672,29 +678,55 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
tlf.handleOptionsMenuItemSelected(item, customIntent);
}
private void togglePeopleView() {
FilterListFragment flf = getFilterListFragment();
boolean peopleMode = !(flf instanceof PeopleListFragment);
if (peopleMode)
private void setFilterMode(int mode) {
filterMode = mode;
updateFilterModeSpec(mode);
refreshMainMenu();
if (fragmentLayout == LAYOUT_SINGLE) {
createListsPopover();
setupPopoverWithFilterList((FilterListFragment) setupFragment(FilterListFragment.TAG_FILTERLIST_FRAGMENT, 0,
filterModeSpec.getFilterListClass(), true, true));
if (mode == FILTER_MODE_PEOPLE) {
personImage.setVisibility(View.VISIBLE);
commentsButton.setVisibility(View.GONE);
((PeopleFilterMode) filterModeSpec).setImageView(personImage);
} else {
personImage.setVisibility(View.GONE);
commentsButton.setVisibility(View.VISIBLE);
}
} else {
setupFragment(FilterListFragment.TAG_FILTERLIST_FRAGMENT, R.id.filterlist_fragment_container,
PeopleListFragment.class, false, true);
else
setupFragment(FilterListFragment.TAG_FILTERLIST_FRAGMENT,
R.id.filterlist_fragment_container, FilterListFragment.class, false, true);
filterModeSpec.getFilterListClass(), false, true);
}
setupMainMenuForPeopleViewState(peopleMode);
getIntent().putExtra(PEOPLE_VIEW, peopleMode);
onFilterItemClicked(getDefaultFilter());
if (fragmentLayout == LAYOUT_SINGLE)
listsNav.performClick();
getIntent().putExtra(FILTER_MODE, mode);
}
private void setupMainMenuForPeopleViewState(boolean inPeopleMode) {
mainMenuPopover.setFixedItemVisibility(0, inPeopleMode ? View.VISIBLE : View.GONE, true);
mainMenuPopover.setFixedItemVisibility(1, inPeopleMode ? View.GONE : View.VISIBLE, true);
public void refreshMainMenu() {
mainMenuPopover.refreshFixedItems();
TypedValue tv = new TypedValue();
getTheme().resolveAttribute(inPeopleMode ? R.attr.asPeopleMenu : R.attr.asMainMenu, tv, false);
getTheme().resolveAttribute(filterModeSpec.getMainMenuIconAttr(), tv, false);
mainMenu.setImageResource(tv.data);
}
private void updateFilterModeSpec(int mode) {
switch(mode) {
case FILTER_MODE_PEOPLE:
filterModeSpec = new PeopleFilterMode();
break;
case FILTER_MODE_FEATURED:
filterModeSpec = new FeaturedListFilterMode();
break;
case FILTER_MODE_NORMAL:
default:
filterModeSpec = new DefaultFilterMode();
}
}
public MainMenuPopover getMainMenuPopover() {
return mainMenuPopover;
}

@ -132,7 +132,7 @@ public class TaskListFragment extends ListFragment implements OnScrollListener,
public static final int MENU_ADDONS_ID = R.string.TLA_menu_addons;
protected static final int MENU_SETTINGS_ID = R.string.TLA_menu_settings;
protected static final int MENU_SORT_ID = R.string.TLA_menu_sort;
public static final int MENU_SORT_ID = R.string.TLA_menu_sort;
protected static final int MENU_SYNC_ID = R.string.TLA_menu_sync;
protected static final int MENU_SUPPORT_ID = R.string.TLA_menu_support;
public static final int MENU_NEW_FILTER_ID = R.string.FLA_new_filter;
@ -710,12 +710,14 @@ public class TaskListFragment extends ListFragment implements OnScrollListener,
|| !AstridApiConstants.BROADCAST_EVENT_REFRESH.equals(intent.getAction()))
return;
Activity activity = getActivity();
final Activity activity = getActivity();
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
refresh();
if (activity instanceof TaskListActivity)
((TaskListActivity) activity).refreshMainMenu();
}
});
}

@ -157,7 +157,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable {
// --- instance variables
@Autowired
private TaskService taskService;
protected TaskService taskService;
public static int APPLY_LISTENERS_PARENT = 0;
public static int APPLY_LISTENERS_ROW_BODY= 1;
@ -168,8 +168,8 @@ public class TaskAdapter extends CursorAdapter implements Filterable {
protected final HashMap<Long, Boolean> completedItems = new HashMap<Long, Boolean>(0);
protected OnCompletedTaskListener onCompletedTaskListener = null;
public boolean isFling = false;
private final int resource;
private final LayoutInflater inflater;
protected final int resource;
protected final LayoutInflater inflater;
private DetailLoaderThread detailLoader;
private ActionsLoaderThread actionsLoader;
private int fontSize;
@ -179,7 +179,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable {
private final AtomicReference<String> query;
private final int minRowHeight;
protected final int minRowHeight;
// measure utilities
protected final Paint paint;
@ -263,6 +263,10 @@ public class TaskAdapter extends CursorAdapter implements Filterable {
return newCursor;
}
public String getQuery() {
return query.get();
}
/* ======================================================================
* =========================================================== view setup
* ====================================================================== */
@ -1013,7 +1017,6 @@ public class TaskAdapter extends CursorAdapter implements Filterable {
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
fontSize = Preferences.getIntegerFromString(R.string.p_fontSize, 18);
}
protected final View.OnClickListener completeBoxListener = new View.OnClickListener() {

@ -189,6 +189,29 @@ public class TaskService {
return newTask;
}
public Task cloneReusableTask(Task task, String listName, long remoteId) {
Task newTask = fetchById(task.getId(), Task.PROPERTIES);
if (newTask == null)
return new Task();
newTask.clearValue(Task.ID);
newTask.clearValue(Task.REMOTE_ID);
newTask.clearValue(Task.USER);
newTask.clearValue(Task.USER_ID);
taskDao.save(newTask);
if (listName != null) {
Metadata tag = new Metadata();
tag.setValue(Metadata.TASK, newTask.getId());
tag.setValue(Metadata.KEY, TagService.KEY);
tag.setValue(TagService.TAG, listName);
if (remoteId > 0)
tag.setValue(TagService.REMOTE_ID, remoteId);
metadataDao.createNew(tag);
}
return newTask;
}
/**
* Delete the given task. Instead of deleting from the database, we set
* the deleted flag.

@ -152,6 +152,8 @@ public class ThemeService {
return R.drawable.icn_menu_refresh_dark;
case R.drawable.icn_menu_filters:
return R.drawable.icn_menu_filters_dark;
case R.drawable.icn_featured_lists:
return R.drawable.icn_featured_lists_dark;
case R.drawable.icn_menu_sort_by_size:
return R.drawable.icn_menu_sort_by_size_dark;
case R.drawable.icn_menu_search:

@ -29,6 +29,7 @@ public class MainMenuPopover extends FragmentPopover implements InterceptTouchLi
public static final int MAIN_MENU_ITEM_LISTS = R.string.TLA_menu_lists;
public static final int MAIN_MENU_ITEM_FRIENDS = R.string.TLA_menu_friends;
public static final int MAIN_MENU_ITEM_FEATURED_LISTS = R.string.TLA_menu_featured_lists;
public static final int MAIN_MENU_ITEM_SEARCH = R.string.TLA_menu_search;
public static final int MAIN_MENU_ITEM_SUGGESTIONS = R.string.TLA_menu_suggestions;
public static final int MAIN_MENU_ITEM_SETTINGS = R.string.TLA_menu_settings;
@ -45,6 +46,7 @@ public class MainMenuPopover extends FragmentPopover implements InterceptTouchLi
private final LinearLayout bottomFixed;
private final int rowLayout;
private boolean suppressNextKeyEvent = false;
private final boolean isTablet;
public void setMenuListener(MainMenuListener listener) {
this.mListener = listener;
@ -75,9 +77,11 @@ public class MainMenuPopover extends FragmentPopover implements InterceptTouchLi
topFixed = (LinearLayout) getContentView().findViewById(R.id.topFixedItems);
bottomFixed = (LinearLayout) getContentView().findViewById(R.id.bottomFixedItems);
this.isTablet = isTablet;
mListener = listener;
addFixedItems(isTablet);
addFixedItems();
}
public boolean didInterceptTouch(KeyEvent event) {
@ -101,7 +105,7 @@ public class MainMenuPopover extends FragmentPopover implements InterceptTouchLi
super.setBackgroundDrawable(null);
}
private void addFixedItems(boolean isTablet) {
private void addFixedItems() {
int themeFlags = isTablet ? ThemeService.FLAG_FORCE_DARK : 0;
addMenuItem(R.string.TLA_menu_lists,
ThemeService.getDrawable(R.drawable.icn_menu_lists, themeFlags),
@ -112,6 +116,11 @@ public class MainMenuPopover extends FragmentPopover implements InterceptTouchLi
ThemeService.getDrawable(R.drawable.icn_menu_friends, themeFlags),
MAIN_MENU_ITEM_FRIENDS, null, topFixed);
if (Preferences.getBoolean(R.string.p_show_featured_lists, false))
addMenuItem(R.string.TLA_menu_featured_lists,
ThemeService.getDrawable(R.drawable.icn_featured_lists, themeFlags),
MAIN_MENU_ITEM_FEATURED_LISTS, null, topFixed);
addMenuItem(R.string.TLA_menu_search,
ThemeService.getDrawable(R.drawable.icn_menu_search, themeFlags),
MAIN_MENU_ITEM_SEARCH, null, topFixed);
@ -120,6 +129,12 @@ public class MainMenuPopover extends FragmentPopover implements InterceptTouchLi
MAIN_MENU_ITEM_SETTINGS, null, bottomFixed); // Settings item
}
public void refreshFixedItems() {
topFixed.removeAllViews();
bottomFixed.removeAllViews();
addFixedItems();
}
public void setFixedItemVisibility(int index, int visibility, boolean top) {
LinearLayout container = top ? topFixed : bottomFixed;
if (index < 0 || index >= container.getChildCount())

@ -13,12 +13,14 @@ import android.content.res.Resources;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.activity.BeastModePreferences;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.User;
import com.todoroo.astrid.service.ThemeService;
@ -81,6 +83,14 @@ public class AstridPreferences {
Preferences.setString(R.string.p_theme, ThemeService.THEME_WHITE);
}
setShowFriendsView();
setShowFeaturedLists();
editor.commit();
}
private static void setShowFriendsView() {
// Show friends view if necessary
boolean showFriends = false;
TodorooCursor<User> users = PluginServices.getUserDao().query(Query.select(User.ID).limit(1));
@ -90,8 +100,19 @@ public class AstridPreferences {
users.close();
}
Preferences.setBoolean(R.string.p_show_friends_view, showFriends);
}
editor.commit();
private static void setShowFeaturedLists() {
// Show featured lists if necessary
boolean showFeaturedLists = false;
TodorooCursor<TagData> featLists = PluginServices.getTagDataService().query(Query.select(TagData.ID)
.where(Functions.bitwiseAnd(TagData.FLAGS, TagData.FLAG_FEATURED).gt(0)).limit(1));
try {
showFeaturedLists = featLists.getCount() > 0;
} finally {
featLists.close();
}
Preferences.setBoolean(R.string.p_show_featured_lists, showFeaturedLists);
}
/* ======================================================================

@ -13,6 +13,9 @@ ${catxml} astrid/res/values/strings*.xml > astrid/res/values/strings.xml
a2po $* --android astrid/res --gettext astrid/locales --groups strings --ignore-fuzzy --template android.pot
a2po $* --android api/res --gettext api/locales --groups strings --ignore-fuzzy --template api.pot
mv astrid/res/values-he astrid/res/values-iw 2> /dev/null
mv api/res/values-he api/res/values-iw 2> /dev/null
# remove unused lp translations
UNUSED=( ar bg el en-rGB eo et eu fi fo gl hi hr hu id ka lt ml oc ro sk sl ta uk vi )
for LANG in "${UNUSED[@]}"; do

Loading…
Cancel
Save