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

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

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

@ -344,7 +344,16 @@
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT"/>
</intent-filter> </intent-filter>
</receiver> </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"/> android:windowSoftInputMode="stateHidden|adjustResize"/>
<!-- alarms --> <!-- alarms -->

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

@ -19,6 +19,7 @@ import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Join; import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.sql.Query;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; 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 * Save / Merge JSON user
* @param userObject * @param userObject

@ -42,6 +42,7 @@ import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Join; import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Order; import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.sql.Query;
@ -837,7 +838,26 @@ public final class ActFmSyncService {
if(serverTime == 0) { if(serverTime == 0) {
Long[] remoteIdArray = remoteIds.toArray(new Long[remoteIds.size()]); 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); return result.optInt("time", 0);
@ -1212,6 +1232,7 @@ public final class ActFmSyncService {
} catch (SQLiteConstraintException e) { } catch (SQLiteConstraintException e) {
taskDao.handleSQLiteConstraintException(remote); taskDao.handleSQLiteConstraintException(remote);
} }
ids.add(remote.getId()); ids.add(remote.getId());
metadataService.synchronizeMetadata(remote.getId(), metadata, MetadataCriteria.withKey(TagService.KEY)); metadataService.synchronizeMetadata(remote.getId(), metadata, MetadataCriteria.withKey(TagService.KEY));
synchronizeAttachments(item, remote); synchronizeAttachments(item, remote);
@ -1444,10 +1465,23 @@ public final class ActFmSyncService {
* @throws JSONException * @throws JSONException
*/ */
public static void tagFromJson(JSONObject json, TagData model) 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.clearValue(TagData.REMOTE_ID);
model.setValue(TagData.REMOTE_ID, json.getLong("id")); model.setValue(TagData.REMOTE_ID, json.getLong("id"));
model.setValue(TagData.NAME, json.getString("name")); 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")) if(json.has("picture"))
model.setValue(TagData.PICTURE, json.optString("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.Autowired;
import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Join; import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.Preferences; 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_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$ private static final String LAST_USERS_FETCH_TIME = "actfm_lastUsers"; //$NON-NLS-1$
// --- synchronize active tasks // --- synchronize active tasks
@ -146,9 +149,9 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
new Thread(new Runnable() { new Thread(new Runnable() {
public void run() { public void run() {
callback.started(); callback.started();
callback.incrementMax(140); callback.incrementMax(160);
final AtomicInteger finisher = new AtomicInteger(4); final AtomicInteger finisher = new AtomicInteger(5);
actFmPreferenceService.recordSyncStart(); actFmPreferenceService.recordSyncStart();
updateUserStatus(); updateUserStatus();
@ -159,6 +162,8 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
startUpdatesFetcher(manual, callback, finisher); startUpdatesFetcher(manual, callback, finisher);
startFeaturedListFetcher(callback, finisher);
actFmSyncService.waitUntilEmpty(); actFmSyncService.waitUntilEmpty();
startTaskFetcher(manual, callback, finisher); 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 */ /** @return runnable to fetch changes to tags */
@ -346,10 +376,12 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
private void pushQueuedTags(final SyncResultCallback callback, private void pushQueuedTags(final SyncResultCallback callback,
final AtomicInteger finisher, int lastTagSyncTime) { final AtomicInteger finisher, int lastTagSyncTime) {
TodorooCursor<TagData> tagDataCursor = tagDataService.query(Query.select(TagData.PROPERTIES) 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), TagData.REMOTE_ID.eq(0),
Criterion.and(TagData.REMOTE_ID.gt(0), Criterion.and(TagData.REMOTE_ID.gt(0),
TagData.MODIFICATION_DATE.gt(lastTagSyncTime))))); TagData.MODIFICATION_DATE.gt(lastTagSyncTime))))));
try { try {
pushQueued(callback, finisher, tagDataCursor, true, tagPusher); pushQueued(callback, finisher, tagDataCursor, true, tagPusher);
} finally { } finally {

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

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

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

@ -330,7 +330,7 @@ public final class TagService {
tagData.readFromCursor(cursor); tagData.readFromCursor(cursor);
String tagName = tagData.getValue(TagData.NAME).trim(); String tagName = tagData.getValue(TagData.NAME).trim();
Tag tag = new Tag(tagData); 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); tags.remove(tagName);
continue; continue;
} }
@ -356,6 +356,37 @@ public final class TagService {
return tagList; 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 * Save the given array of tags into the database
* @param taskId * @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:layout_alignParentTop="true"
android:scrollbars="vertical" android:scrollbars="vertical"
android:divider="@android:color/transparent" android:divider="@android:color/transparent"
android:dividerHeight="1px"
android:background="@android:color/transparent"
android:cacheColorHint="#00000000"/> android:cacheColorHint="#00000000"/>
</LinearLayout> </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:layout_alignParentTop="true"
android:scrollbars="vertical" android:scrollbars="vertical"
android:divider="@android:color/transparent" android:divider="@android:color/transparent"
android:dividerHeight="1px"
android:background="@android:color/transparent"
android:cacheColorHint="#00000000"/> android:cacheColorHint="#00000000"/>
</LinearLayout> </LinearLayout>

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

@ -54,6 +54,13 @@
</RelativeLayout> </RelativeLayout>
</LinearLayout> </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 <Button
android:id="@+id/comments" android:id="@+id/comments"
android:layout_width="51dip" 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>

@ -51,6 +51,9 @@
<!-- show friends view preference --> <!-- show friends view preference -->
<string name="p_show_friends_view">show_friends_view</string> <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 --> <!-- enable third party addons preference -->
<string name="p_third_party_addons">third_party_addons</string> <string name="p_third_party_addons">third_party_addons</string>
@ -61,6 +64,9 @@
<!-- force tablets to use phone layout --> <!-- force tablets to use phone layout -->
<string name="p_force_phone_layout">force_phone_layout</string> <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"> <string-array name="TEA_reminder_random_hours">
<!-- values (in hours) associated with items above. --> <!-- values (in hours) associated with items above. -->
<item>1</item> <item>1</item>

@ -271,6 +271,20 @@
<!-- share login: OAUTH Login Prompt --> <!-- share login: OAUTH Login Prompt -->
<string name="actfm_OLA_prompt">Please log in:</string> <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 == --> <!-- ================================================ Synchronization == -->
<!-- Indicates the logged in user name. %s -> user's name --> <!-- Indicates the logged in user name. %s -> user's name -->

@ -128,6 +128,9 @@
<!-- Menu: Friends --> <!-- Menu: Friends -->
<string name="TLA_menu_friends">People</string> <string name="TLA_menu_friends">People</string>
<!-- Menu: Featured Lists -->
<string name="TLA_menu_featured_lists">Featured Lists</string>
<!-- Menu: Suggestions --> <!-- Menu: Suggestions -->
<string name="TLA_menu_suggestions">Suggestions</string> <string name="TLA_menu_suggestions">Suggestions</string>
@ -659,6 +662,8 @@
<string name = "EPr_cal_start_at_due_time">Start calendar events at due time</string> <string name = "EPr_cal_start_at_due_time">Start calendar events at due time</string>
<string name="EPr_force_phone_layout">Use phone layout</string> <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 name="EPr_swipe_lists_restart_alert">You will need to restart Astrid for this change to take effect</string>

@ -34,5 +34,9 @@
android:title="@string/EPr_force_phone_layout" android:title="@string/EPr_force_phone_layout"
android:key="@string/p_force_phone_layout" android:key="@string/p_force_phone_layout"
android:defaultValue="false"/> android:defaultValue="false"/>
<CheckBoxPreference
android:title="@string/EPr_show_featured_lists"
android:key="@string/p_show_featured_lists_labs"
android:defaultValue="false"/>
</PreferenceScreen> </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 POWER_PACK_PREFERENCE = 5;
private static final int REQUEST_CODE_SYNC = 0; 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; private static final int REQUEST_CODE_FILES_DIR = 2;
public static final int RESULT_CODE_THEME_CHANGED = 1; 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>(); private static final HashMap<Class<?>, Integer> PREFERENCE_REQUEST_CODES = new HashMap<Class<?>, Integer>();
static { static {
PREFERENCE_REQUEST_CODES.put(SyncProviderPreferences.class, REQUEST_CODE_SYNC); 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) { private void addPluginPreferences(PreferenceScreen screen) {
@ -494,9 +494,13 @@ public class EditPreferences extends TodorooPreferenceActivity {
setResult(SyncProviderPreferences.RESULT_CODE_SYNCHRONIZE); setResult(SyncProviderPreferences.RESULT_CODE_SYNCHRONIZE);
finish(); finish();
return; 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); setResult(RESULT_CODE_PERFORMANCE_PREF_CHANGED);
return; 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) { } else if (requestCode == REQUEST_CODE_FILES_DIR && resultCode == RESULT_OK) {
if (data != null) { if (data != null) {
String dir = data.getStringExtra(FileExplore.RESULT_DIR_SELECTED); 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.AstridApiConstants;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem; import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.core.CoreFilterExposer;
import com.todoroo.astrid.core.CustomFilterExposer; import com.todoroo.astrid.core.CustomFilterExposer;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.people.PeopleListFragment; import com.todoroo.astrid.helper.AsyncImageView;
import com.todoroo.astrid.people.PeopleViewActivity; import com.todoroo.astrid.people.PeopleFilterMode;
import com.todoroo.astrid.service.StatisticsConstants; import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService; import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.ThemeService; import com.todoroo.astrid.service.ThemeService;
import com.todoroo.astrid.service.abtesting.ABTestEventReportingService; import com.todoroo.astrid.service.abtesting.ABTestEventReportingService;
import com.todoroo.astrid.tags.TagService; import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.tags.reusable.FeaturedListFilterMode;
import com.todoroo.astrid.ui.DateChangedAlerts; import com.todoroo.astrid.ui.DateChangedAlerts;
import com.todoroo.astrid.ui.FragmentPopover; import com.todoroo.astrid.ui.FragmentPopover;
import com.todoroo.astrid.ui.MainMenuPopover; 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$ 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; @Autowired private ABTestEventReportingService abTestEventReportingService;
@ -83,7 +86,10 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
private ImageView listsNavDisclosure; private ImageView listsNavDisclosure;
private TextView lists; private TextView lists;
private ImageView mainMenu; private ImageView mainMenu;
private AsyncImageView personImage;
private Button commentsButton; private Button commentsButton;
private int filterMode;
private FilterModeSpec filterModeSpec;
private TaskListFragmentPager tlfPager; private TaskListFragmentPager tlfPager;
private TaskListFragmentPagerAdapter tlfPagerAdapter; private TaskListFragmentPagerAdapter tlfPagerAdapter;
@ -155,6 +161,8 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
listsNavDisclosure = (ImageView) actionBar.getCustomView().findViewById(R.id.list_disclosure_arrow); listsNavDisclosure = (ImageView) actionBar.getCustomView().findViewById(R.id.list_disclosure_arrow);
lists = (TextView) actionBar.getCustomView().findViewById(R.id.list_title); lists = (TextView) actionBar.getCustomView().findViewById(R.id.list_title);
mainMenu = (ImageView) actionBar.getCustomView().findViewById(R.id.main_menu); 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); commentsButton = (Button) actionBar.getCustomView().findViewById(R.id.comments);
initializeFragments(actionBar); initializeFragments(actionBar);
@ -226,7 +234,7 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
} }
protected Filter getDefaultFilter() { protected Filter getDefaultFilter() {
return CoreFilterExposer.buildInboxFilter(getResources()); return filterModeSpec.getDefaultFilter(this);
} }
private boolean swipeIsEnabled() { private boolean swipeIsEnabled() {
@ -259,6 +267,8 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
protected void initializeFragments(ActionBar actionBar) { protected void initializeFragments(ActionBar actionBar) {
View filterFragment = findViewById(R.id.filterlist_fragment_container); View filterFragment = findViewById(R.id.filterlist_fragment_container);
View editFragment = findViewById(R.id.taskedit_fragment_container); View editFragment = findViewById(R.id.taskedit_fragment_container);
filterMode = getIntent().getIntExtra(FILTER_MODE, FILTER_MODE_NORMAL);
updateFilterModeSpec(filterMode);
if (filterFragment != null) { if (filterFragment != null) {
actionBar.setDisplayHomeAsUpEnabled(false); 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, setupFragment(FilterListFragment.TAG_FILTERLIST_FRAGMENT,
R.id.filterlist_fragment_container, filterFragmentClass, false, false); R.id.filterlist_fragment_container, filterModeSpec.getFilterListClass(), false, false);
} else { } else {
fragmentLayout = LAYOUT_SINGLE; fragmentLayout = LAYOUT_SINGLE;
actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true);
listsNav.setOnClickListener(popupMenuClickListener); listsNav.setOnClickListener(popupMenuClickListener);
createListsPopover(); createListsPopover();
setupPopoverWithFilterList((FilterListFragment) setupFragment(FilterListFragment.TAG_FILTERLIST_FRAGMENT, 0, 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) if (isTablet)
setupMainMenuForPeopleViewState(getIntent().getBooleanExtra(PEOPLE_VIEW, false)); mainMenuPopover.refreshFixedItems();
} }
private void setupPopoverWithFragment(FragmentPopover popover, Fragment frag, LayoutParams params) { private void setupPopoverWithFragment(FragmentPopover popover, Fragment frag, LayoutParams params) {
@ -366,7 +372,9 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
if (tef != null) if (tef != null)
onBackPressed(); onBackPressed();
return super.onFilterItemClicked(item); boolean result = super.onFilterItemClicked(item);
filterModeSpec.onFilterItemClickedCallback(item);
return result;
} }
private void setListsDropdownSelected(boolean selected) { private void setListsDropdownSelected(boolean selected) {
@ -637,7 +645,7 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
@Override @Override
public boolean shouldAddMenuItem(int itemId) { public boolean shouldAddMenuItem(int itemId) {
return true; return AndroidUtilities.indexOf(filterModeSpec.getForbiddenMenuItems(), itemId) < 0;
} }
@Override @Override
@ -645,21 +653,19 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
TaskListFragment tlf = getTaskListFragment(); TaskListFragment tlf = getTaskListFragment();
switch (item) { switch (item) {
case MainMenuPopover.MAIN_MENU_ITEM_LISTS: case MainMenuPopover.MAIN_MENU_ITEM_LISTS:
if (fragmentLayout == LAYOUT_SINGLE) if (filterMode == FILTER_MODE_NORMAL)
listsNav.performClick(); listsNav.performClick();
else else
togglePeopleView(); setFilterMode(FILTER_MODE_NORMAL);
return; return;
case MainMenuPopover.MAIN_MENU_ITEM_SEARCH: case MainMenuPopover.MAIN_MENU_ITEM_SEARCH:
onSearchRequested(); onSearchRequested();
return; return;
case MainMenuPopover.MAIN_MENU_ITEM_FEATURED_LISTS:
setFilterMode(FILTER_MODE_FEATURED);
return;
case MainMenuPopover.MAIN_MENU_ITEM_FRIENDS: case MainMenuPopover.MAIN_MENU_ITEM_FRIENDS:
if (fragmentLayout != LAYOUT_SINGLE) { setFilterMode(FILTER_MODE_PEOPLE);
togglePeopleView();
} else {
Intent peopleIntent = new Intent(this, PeopleViewActivity.class);
startActivity(peopleIntent);
}
return; return;
case MainMenuPopover.MAIN_MENU_ITEM_SUGGESTIONS: case MainMenuPopover.MAIN_MENU_ITEM_SUGGESTIONS:
// Doesn't exist yet // Doesn't exist yet
@ -672,29 +678,55 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
tlf.handleOptionsMenuItemSelected(item, customIntent); tlf.handleOptionsMenuItemSelected(item, customIntent);
} }
private void togglePeopleView() { private void setFilterMode(int mode) {
FilterListFragment flf = getFilterListFragment(); filterMode = mode;
boolean peopleMode = !(flf instanceof PeopleListFragment); updateFilterModeSpec(mode);
if (peopleMode)
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, setupFragment(FilterListFragment.TAG_FILTERLIST_FRAGMENT, R.id.filterlist_fragment_container,
PeopleListFragment.class, false, true); filterModeSpec.getFilterListClass(), false, true);
else }
setupFragment(FilterListFragment.TAG_FILTERLIST_FRAGMENT,
R.id.filterlist_fragment_container, FilterListFragment.class, false, true);
setupMainMenuForPeopleViewState(peopleMode); onFilterItemClicked(getDefaultFilter());
getIntent().putExtra(PEOPLE_VIEW, peopleMode); if (fragmentLayout == LAYOUT_SINGLE)
listsNav.performClick();
getIntent().putExtra(FILTER_MODE, mode);
} }
private void setupMainMenuForPeopleViewState(boolean inPeopleMode) { public void refreshMainMenu() {
mainMenuPopover.setFixedItemVisibility(0, inPeopleMode ? View.VISIBLE : View.GONE, true); mainMenuPopover.refreshFixedItems();
mainMenuPopover.setFixedItemVisibility(1, inPeopleMode ? View.GONE : View.VISIBLE, true);
TypedValue tv = new TypedValue(); 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); 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() { public MainMenuPopover getMainMenuPopover() {
return mainMenuPopover; 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; 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_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_SYNC_ID = R.string.TLA_menu_sync;
protected static final int MENU_SUPPORT_ID = R.string.TLA_menu_support; 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; 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())) || !AstridApiConstants.BROADCAST_EVENT_REFRESH.equals(intent.getAction()))
return; return;
Activity activity = getActivity(); final Activity activity = getActivity();
if (activity != null) { if (activity != null) {
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
refresh(); refresh();
if (activity instanceof TaskListActivity)
((TaskListActivity) activity).refreshMainMenu();
} }
}); });
} }

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

@ -189,6 +189,29 @@ public class TaskService {
return newTask; 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 * Delete the given task. Instead of deleting from the database, we set
* the deleted flag. * the deleted flag.

@ -152,6 +152,8 @@ public class ThemeService {
return R.drawable.icn_menu_refresh_dark; return R.drawable.icn_menu_refresh_dark;
case R.drawable.icn_menu_filters: case R.drawable.icn_menu_filters:
return R.drawable.icn_menu_filters_dark; 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: case R.drawable.icn_menu_sort_by_size:
return R.drawable.icn_menu_sort_by_size_dark; return R.drawable.icn_menu_sort_by_size_dark;
case R.drawable.icn_menu_search: 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_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_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_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_SUGGESTIONS = R.string.TLA_menu_suggestions;
public static final int MAIN_MENU_ITEM_SETTINGS = R.string.TLA_menu_settings; 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 LinearLayout bottomFixed;
private final int rowLayout; private final int rowLayout;
private boolean suppressNextKeyEvent = false; private boolean suppressNextKeyEvent = false;
private final boolean isTablet;
public void setMenuListener(MainMenuListener listener) { public void setMenuListener(MainMenuListener listener) {
this.mListener = listener; this.mListener = listener;
@ -75,9 +77,11 @@ public class MainMenuPopover extends FragmentPopover implements InterceptTouchLi
topFixed = (LinearLayout) getContentView().findViewById(R.id.topFixedItems); topFixed = (LinearLayout) getContentView().findViewById(R.id.topFixedItems);
bottomFixed = (LinearLayout) getContentView().findViewById(R.id.bottomFixedItems); bottomFixed = (LinearLayout) getContentView().findViewById(R.id.bottomFixedItems);
this.isTablet = isTablet;
mListener = listener; mListener = listener;
addFixedItems(isTablet); addFixedItems();
} }
public boolean didInterceptTouch(KeyEvent event) { public boolean didInterceptTouch(KeyEvent event) {
@ -101,7 +105,7 @@ public class MainMenuPopover extends FragmentPopover implements InterceptTouchLi
super.setBackgroundDrawable(null); super.setBackgroundDrawable(null);
} }
private void addFixedItems(boolean isTablet) { private void addFixedItems() {
int themeFlags = isTablet ? ThemeService.FLAG_FORCE_DARK : 0; int themeFlags = isTablet ? ThemeService.FLAG_FORCE_DARK : 0;
addMenuItem(R.string.TLA_menu_lists, addMenuItem(R.string.TLA_menu_lists,
ThemeService.getDrawable(R.drawable.icn_menu_lists, themeFlags), 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), ThemeService.getDrawable(R.drawable.icn_menu_friends, themeFlags),
MAIN_MENU_ITEM_FRIENDS, null, topFixed); 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, addMenuItem(R.string.TLA_menu_search,
ThemeService.getDrawable(R.drawable.icn_menu_search, themeFlags), ThemeService.getDrawable(R.drawable.icn_menu_search, themeFlags),
MAIN_MENU_ITEM_SEARCH, null, topFixed); 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 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) { public void setFixedItemVisibility(int index, int visibility, boolean top) {
LinearLayout container = top ? topFixed : bottomFixed; LinearLayout container = top ? topFixed : bottomFixed;
if (index < 0 || index >= container.getChildCount()) if (index < 0 || index >= container.getChildCount())

@ -13,12 +13,14 @@ import android.content.res.Resources;
import com.timsu.astrid.R; import com.timsu.astrid.R;
import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.Preferences; import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.activity.BeastModePreferences; import com.todoroo.astrid.activity.BeastModePreferences;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.core.PluginServices; import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.User; import com.todoroo.astrid.data.User;
import com.todoroo.astrid.service.ThemeService; import com.todoroo.astrid.service.ThemeService;
@ -81,6 +83,14 @@ public class AstridPreferences {
Preferences.setString(R.string.p_theme, ThemeService.THEME_WHITE); Preferences.setString(R.string.p_theme, ThemeService.THEME_WHITE);
} }
setShowFriendsView();
setShowFeaturedLists();
editor.commit();
}
private static void setShowFriendsView() {
// Show friends view if necessary // Show friends view if necessary
boolean showFriends = false; boolean showFriends = false;
TodorooCursor<User> users = PluginServices.getUserDao().query(Query.select(User.ID).limit(1)); TodorooCursor<User> users = PluginServices.getUserDao().query(Query.select(User.ID).limit(1));
@ -90,8 +100,19 @@ public class AstridPreferences {
users.close(); users.close();
} }
Preferences.setBoolean(R.string.p_show_friends_view, showFriends); 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 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 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 # 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 ) 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 for LANG in "${UNUSED[@]}"; do

Loading…
Cancel
Save