gt:         if (taskAdapter != null)
context: /**
   * Copyright (c) 2012 Todoroo Inc
   *
   * See the file "LICENSE" for the full license governing this code.
   */
  package com.todoroo.astrid.activity;
  
  import java.util.List;
  import java.util.Timer;
  import java.util.TimerTask;
  import java.util.concurrent.atomic.AtomicReference;
  
  import android.app.Activity;
  import android.app.AlertDialog;
  import android.content.BroadcastReceiver;
  import android.content.Context;
  import android.content.DialogInterface;
  import android.content.Intent;
  import android.content.IntentFilter;
  import android.content.SharedPreferences;
  import android.content.SharedPreferences.Editor;
  import android.content.pm.PackageManager;
  import android.content.pm.ResolveInfo;
  import android.content.res.Resources;
  import android.database.Cursor;
  import android.database.sqlite.SQLiteException;
  import android.graphics.drawable.Drawable;
  import android.os.Bundle;
  import android.support.v4.app.Fragment;
  import android.text.TextUtils;
  import android.util.Log;
  import android.view.ContextMenu;
  import android.view.ContextMenu.ContextMenuInfo;
  import android.view.KeyEvent;
  import android.view.LayoutInflater;
  import android.view.MotionEvent;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.view.View.OnKeyListener;
  import android.view.View.OnTouchListener;
  import android.view.ViewGroup;
  import android.widget.AbsListView;
  import android.widget.AdapterView;
  import android.widget.AdapterView.AdapterContextMenuInfo;
  import android.widget.AdapterView.OnItemClickListener;
  import android.widget.LinearLayout;
  import android.widget.ListView;
  import android.widget.TextView;
  
  import com.actionbarsherlock.app.ActionBar;
  import com.actionbarsherlock.app.SherlockListFragment;
  import com.actionbarsherlock.view.Menu;
  import com.actionbarsherlock.view.MenuItem;
  import com.eztransition.tasquid.R;
  import com.todoroo.andlib.data.Property;
  import com.todoroo.andlib.data.TodorooCursor;
  import com.todoroo.andlib.service.Autowired;
  import com.todoroo.andlib.service.ContextManager;
  import com.todoroo.andlib.service.DependencyInjectionService;
  import com.todoroo.andlib.service.ExceptionService;
  import com.todoroo.andlib.sql.Criterion;
  import com.todoroo.andlib.sql.Field;
  import com.todoroo.andlib.sql.Join;
  import com.todoroo.andlib.utility.AndroidUtilities;
  import com.todoroo.andlib.utility.DateUtilities;
  import com.todoroo.andlib.utility.Preferences;
  import com.todoroo.astrid.actfm.ActFmLoginActivity;
  import com.todoroo.astrid.actfm.CommentsActivity;
  import com.todoroo.astrid.actfm.TagViewFragment;
  import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
  import com.todoroo.astrid.activity.SortSelectionActivity.OnSortSelectedListener;
  import com.todoroo.astrid.adapter.TaskAdapter;
  import com.todoroo.astrid.adapter.TaskAdapter.OnCompletedTaskListener;
  import com.todoroo.astrid.adapter.TaskAdapter.ViewHolder;
  import com.todoroo.astrid.api.AstridApiConstants;
  import com.todoroo.astrid.api.Filter;
  import com.todoroo.astrid.api.FilterWithCustomIntent;
  import com.todoroo.astrid.api.TaskContextActionExposer;
  import com.todoroo.astrid.api.TaskDecoration;
  import com.todoroo.astrid.core.CoreFilterExposer;
  import com.todoroo.astrid.core.CustomFilterActivity;
  import com.todoroo.astrid.core.SortHelper;
  import com.todoroo.astrid.dao.Database;
  import com.todoroo.astrid.dao.TaskListMetadataDao;
  import com.todoroo.astrid.data.Metadata;
  import com.todoroo.astrid.data.RemoteModel;
  import com.todoroo.astrid.data.TagData;
  import com.todoroo.astrid.data.Task;
  import com.todoroo.astrid.data.TaskAttachment;
  import com.todoroo.astrid.data.TaskListMetadata;
  import com.todoroo.astrid.data.User;
  import com.todoroo.astrid.helper.SyncActionHelper;
  import com.todoroo.astrid.helper.TaskListContextMenuExtensionLoader;
  import com.todoroo.astrid.helper.TaskListContextMenuExtensionLoader.ContextMenuItem;
  import com.todoroo.astrid.reminders.ReminderDebugContextActions;
  import com.todoroo.astrid.service.AddOnService;
  import com.todoroo.astrid.service.AstridDependencyInjector;
  import com.todoroo.astrid.service.MetadataService;
  import com.todoroo.astrid.service.StatisticsConstants;
  import com.todoroo.astrid.service.StatisticsService;
  import com.todoroo.astrid.service.TagDataService;
  import com.todoroo.astrid.service.TaskService;
  import com.todoroo.astrid.service.ThemeService;
  import com.todoroo.astrid.service.UpgradeService;
  import com.todoroo.astrid.subtasks.SubtasksHelper;
  import com.todoroo.astrid.subtasks.SubtasksListFragment;
  import com.todoroo.astrid.subtasks.SubtasksUpdater;
  import com.todoroo.astrid.sync.SyncProviderPreferences;
  import com.todoroo.astrid.tags.TaskToTagMetadata;
  import com.todoroo.astrid.timers.TimerPlugin;
  import com.todoroo.astrid.ui.FeedbackPromptDialogs;
  import com.todoroo.astrid.ui.QuickAddBar;
  import com.todoroo.astrid.utility.AstridPreferences;
  import com.todoroo.astrid.utility.Flags;
  import com.todoroo.astrid.welcome.HelpInfoPopover;
  import com.todoroo.astrid.welcome.tutorial.WelcomeWalkthrough;
  import com.todoroo.astrid.widget.TasksWidget;
  
  /**
   * Primary activity for the Bente application. Shows a list of upcoming tasks
   * and a user's coaches.
   *
   * @author Tim Su <tim@todoroo.com>
   *
   */
  public class TaskListFragment extends SherlockListFragment implements OnSortSelectedListener {
  
      public static final String TAG_TASKLIST_FRAGMENT = "tasklist_fragment"; //$NON-NLS-1$
  
      public static final String PREF_LAST_FEEDBACK_TIME = "pref_last_feedback_time"; //$NON-NLS-1$
      private static final long FEEDBACK_TIME_INTERVAL = DateUtilities.ONE_WEEK * 12;
  
      // --- activities
  
      public static final long AUTOSYNC_INTERVAL = 90000L;
      private static final long BACKGROUND_REFRESH_INTERVAL = 120000L;
      private static final long WAIT_BEFORE_AUTOSYNC = 2000L;
      public static final int ACTIVITY_EDIT_TASK = 0;
      public static final int ACTIVITY_SETTINGS = 1;
      public static final int ACTIVITY_SORT = 2;
      public static final int ACTIVITY_ADDONS = 3;
      public static final int ACTIVITY_MENU_EXTERNAL = 4;
      public static final int ACTIVITY_REQUEST_NEW_FILTER = 5;
  
      // --- menu codes
  
      protected static final int MENU_SETTINGS_ID = R.string.TLA_menu_settings;
      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;
      protected static final int MENU_ADDON_INTENT_ID = Menu.FIRST + 199;
  
      protected static final int CONTEXT_MENU_EDIT_TASK_ID = R.string.TAd_contextEditTask;
      protected static final int CONTEXT_MENU_COPY_TASK_ID = R.string.TAd_contextCopyTask;
      protected static final int CONTEXT_MENU_DELETE_TASK_ID = R.string.TAd_contextDeleteTask;
      protected static final int CONTEXT_MENU_UNDELETE_TASK_ID = R.string.TAd_contextUndeleteTask;
      protected static final int CONTEXT_MENU_PURGE_TASK_ID = R.string.TAd_contextPurgeTask;
      protected static final int CONTEXT_MENU_BROADCAST_INTENT_ID = Menu.FIRST + 25;
      protected static final int CONTEXT_MENU_PLUGIN_ID_FIRST = Menu.FIRST + 26;
  
      // --- constants
  
      /** token for passing a {@link Filter} object through extras */
      public static final String TOKEN_FILTER = "filter"; //$NON-NLS-1$
  
      private static final String TOKEN_EXTRAS = "extras"; //$NON-NLS-1$
  
      // --- instance variables
  
      @Autowired
      protected ExceptionService exceptionService;
  
      @Autowired
      protected TaskService taskService;
  
      @Autowired MetadataService metadataService;
  
      @Autowired Database database;
  
      @Autowired AddOnService addOnService;
  
      @Autowired UpgradeService upgradeService;
  
      @Autowired TagDataService tagDataService;
  
      @Autowired TaskListMetadataDao taskListMetadataDao;
  
      @Autowired ActFmPreferenceService actFmPreferenceService;
  
      private final TaskContextActionExposer[] contextItemExposers = new TaskContextActionExposer[] {
              new ReminderDebugContextActions.MakeNotification(),
              new ReminderDebugContextActions.WhenReminder(),
      };
  
      protected Resources resources;
      protected TaskAdapter taskAdapter = null;
      protected DetailReceiver detailReceiver = new DetailReceiver();
      protected RefreshReceiver refreshReceiver = new RefreshReceiver();
      protected final AtomicReference<String> sqlQueryTemplate = new AtomicReference<String>();
      protected SyncActionHelper syncActionHelper;
      protected Filter filter;
      protected int sortFlags;
      protected int sortSort;
      protected QuickAddBar quickAddBar;
  
      private Timer backgroundTimer;
      protected Bundle extras;
      protected boolean isInbox;
      protected boolean isTodayFilter;
      protected TaskListMetadata taskListMetadata;
  
      private final TaskListContextMenuExtensionLoader contextMenuExtensionLoader = new TaskListContextMenuExtensionLoader();
  
      // --- fragment handling variables
      protected OnTaskListItemClickedListener mListener;
      private boolean mDualFragments = false;
  
      /*
       * ======================================================================
       * ======================================================= initialization
       * ======================================================================
       */
  
      static {
          AstridDependencyInjector.initialize();
      }
  
      /**
       * Instantiates and returns an instance of TaskListFragment (or some subclass). Custom types of
       * TaskListFragment can be created, with the following precedence:
       *
       * --If the filter is of type {@link FilterWithCustomIntent}, the task list type it specifies will be used
       * --Otherwise, the specified customComponent will be used
       *
       * See also: instantiateWithFilterAndExtras(Filter, Bundle) which uses TaskListFragment as the default
       * custom component.
       * @param filter
       * @param extras
       * @param customComponent
       * @return
       */
      @SuppressWarnings("nls")
      public static TaskListFragment instantiateWithFilterAndExtras(Filter filter, Bundle extras, Class<?> customComponent) {
          Class<?> component = customComponent;
          if (filter instanceof FilterWithCustomIntent && component == null) {
              try {
                  component = Class.forName(((FilterWithCustomIntent) filter).customTaskList.getClassName());
              } catch (Exception e) {
                  // Invalid
              }
          }
          if (component == null)
              component = TaskListFragment.class;
  
          TaskListFragment newFragment;
          try {
              newFragment = (TaskListFragment) component.newInstance();
          } catch (java.lang.InstantiationException e) {
              Log.e("tla-instantiate", "tla-instantiate", e);
              newFragment = new TaskListFragment();
          } catch (IllegalAccessException e) {
              Log.e("tla-instantiate", "tla-instantiate", e);
              newFragment = new TaskListFragment();
          }
          Bundle args = new Bundle();
          args.putBundle(TOKEN_EXTRAS, extras);
          newFragment.setArguments(args);
          return newFragment;
      }
  
      /**
       * Convenience method for calling instantiateWithFilterAndExtras(Filter, Bundle, Class<?>) with
       * TaskListFragment as the default component
       * @param filter
       * @param extras
       * @return
       */
      public static TaskListFragment instantiateWithFilterAndExtras(Filter filter, Bundle extras) {
          return instantiateWithFilterAndExtras(filter, extras, null);
      }
  
      /**
       * Container Activity must implement this interface and we ensure that it
       * does during the onAttach() callback
       */
      public interface OnTaskListItemClickedListener {
          public void onTaskListItemClicked(long taskId);
          public void onTaskListItemClicked(long taskId, boolean editable);
      }
  
      @Override
      public void onAttach(Activity activity) {
          super.onAttach(activity);
          // Check that the container activity has implemented the callback
          // interface
          try {
              mListener = (OnTaskListItemClickedListener) activity;
          } catch (ClassCastException e) {
              throw new ClassCastException(activity.toString()
                      + " must implement OnTaskListItemClickedListener"); //$NON-NLS-1$
          }
      }
  
      /**
       * @return view to attach to the body of the task list. must contain two
       *         elements, a view with id android:id/empty and a list view with id
       *         android:id/list. It should NOT be attached to root
       */
      protected View getListBody(ViewGroup root) {
          return getActivity().getLayoutInflater().inflate(
                  R.layout.task_list_body_standard, root, false);
      }
  
      /** Called when loading up the activity */
      @Override
      public void onCreate(Bundle savedInstanceState) {
          DependencyInjectionService.getInstance().inject(this);
          super.onCreate(savedInstanceState);
          extras = getArguments() != null ? getArguments().getBundle(TOKEN_EXTRAS) : null;
          if (extras == null)
              extras = new Bundle(); // Just need an empty one to prevent potential null pointers
      }
  
      /*
       * (non-Javadoc)
       *
       * @see
       * android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater,
       * android.view.ViewGroup, android.os.Bundle)
       */
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
              Bundle savedInstanceState) {
          ViewGroup parent = (ViewGroup) getActivity().getLayoutInflater().inflate(
                  R.layout.task_list_activity, container, false);
          parent.addView(getListBody(parent), 0);
  
          return parent;
      }
  
      @Override
      public void onActivityCreated(Bundle savedInstanceState) {
          super.onActivityCreated(savedInstanceState);
          // We have a menu item to show in action bar.
          resources = getResources();
          setHasOptionsMenu(true);
          syncActionHelper = new SyncActionHelper(getActivity(), this);
          setUpUiComponents();
          initializeData();
          setupQuickAddBar();
  
          Fragment filterlistFrame = getFragmentManager().findFragmentByTag(
                  FilterListFragment.TAG_FILTERLIST_FRAGMENT);
          mDualFragments = (filterlistFrame != null)
                  && filterlistFrame.isInLayout();
  
          if (mDualFragments) {
              // In dual-pane mode, the list view highlights the selected item.
              getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
              getListView().setItemsCanFocus(false);
          }
  
          if (Preferences.getInt(AstridPreferences.P_UPGRADE_FROM, -1) > -1)
              upgradeService.showChangeLog(getActivity(),
                      Preferences.getInt(AstridPreferences.P_UPGRADE_FROM, -1));
  
          getListView().setOnItemClickListener(new OnItemClickListener() {
              @Override
              public void onItemClick(AdapterView<?> parent, View view,
                      int position, long id) {
                  if (taskAdapter != null) {
                      TodorooCursor<Task> cursor = (TodorooCursor<Task>)taskAdapter.getItem(position);
                      Task task = new Task(cursor);
                      if(task.isDeleted())
                          return;
  
                      onTaskListItemClicked(id, task.isEditable());
                  }
              }
          });
      }
  
      /**
       * @return the current tag you are viewing, or null if you're not viewing a tag
       */
      public TagData getActiveTagData() {
          return null;
      }
  
      public TaskListMetadata getTaskListMetadata() {
          return taskListMetadata;
      }
  
      protected void initializeData() {
          if (extras != null && extras.containsKey(TOKEN_FILTER)) {
              filter = extras.getParcelable(TOKEN_FILTER);
              extras.remove(TOKEN_FILTER); // Otherwise writing this filter to parcel gives infinite recursion
          } else {
              filter = CoreFilterExposer.buildInboxFilter(resources);
          }
          filter.setFilterQueryOverride(null);
          isInbox = CoreFilterExposer.isInbox(filter);
          isTodayFilter = false;
          if (!isInbox)
              isTodayFilter = CoreFilterExposer.isTodayFilter(filter);
  
          initializeTaskListMetadata();
  
          setUpTaskList();
          ((AstridActivity) getActivity()).setupActivityFragment(getActiveTagData());
  
          contextMenuExtensionLoader.loadInNewThread(getActivity());
      }
  
      protected void initializeTaskListMetadata() {
          TagData td = getActiveTagData();
          String tdId;
          if (td == null) {
              String filterId = null;
              String prefId = null;
              if (isInbox) {
                  filterId = TaskListMetadata.FILTER_ID_ALL;
                  prefId = SubtasksUpdater.ACTIVE_TASKS_ORDER;
              } else if (isTodayFilter) {
                  filterId = TaskListMetadata.FILTER_ID_TODAY;
                  prefId = SubtasksUpdater.TODAY_TASKS_ORDER;
              }
              if (!TextUtils.isEmpty(filterId)) {
                  taskListMetadata = taskListMetadataDao.fetchByTagId(filterId, TaskListMetadata.PROPERTIES);
                  if (taskListMetadata == null) {
                      String defaultOrder = Preferences.getStringValue(prefId);
                      if (TextUtils.isEmpty(defaultOrder))
                          defaultOrder = "[]"; //$NON-NLS-1$
                      defaultOrder = SubtasksHelper.convertTreeToRemoteIds(defaultOrder);
                      taskListMetadata = new TaskListMetadata();
                      taskListMetadata.setValue(TaskListMetadata.FILTER, filterId);
                      taskListMetadata.setValue(TaskListMetadata.TASK_IDS, defaultOrder);
                      taskListMetadataDao.createNew(taskListMetadata);
                  }
              }
          } else {
              tdId = td.getUuid();
              taskListMetadata = taskListMetadataDao.fetchByTagId(td.getUuid(), TaskListMetadata.PROPERTIES);
              if (taskListMetadata == null && !RemoteModel.isUuidEmpty(tdId)) {
                  taskListMetadata = new TaskListMetadata();
                  taskListMetadata.setValue(TaskListMetadata.TAG_UUID, tdId);
                  taskListMetadataDao.createNew(taskListMetadata);
              }
          }
          postLoadTaskListMetadata();
      }
  
      protected void postLoadTaskListMetadata() {
          // Hook
      }
  
      protected void addSyncRefreshMenuItem(Menu menu, int themeFlags) {
          addMenuItem(menu, R.string.TLA_menu_sync,
                  ThemeService.getDrawable(R.drawable.icn_menu_refresh, themeFlags), MENU_SYNC_ID, true);
      }
  
      protected void addMenuItem(Menu menu, int title, int imageRes, int id, boolean showAsAction) {
          AstridActivity activity = (AstridActivity) getActivity();
          if ((activity.getFragmentLayout() != AstridActivity.LAYOUT_SINGLE && showAsAction) || !(activity instanceof TaskListActivity)) {
              MenuItem item = menu.add(Menu.NONE, id, Menu.NONE, title);
              item.setIcon(imageRes);
              if (activity instanceof TaskListActivity)
                  item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
          } else {
              ((TaskListActivity) activity).getMainMenuPopover().addMenuItem(title, imageRes, id);
          }
      }
  
      protected void addMenuItem(Menu menu, CharSequence title, Drawable image, Intent customIntent, int id) {
          Activity activity = getActivity();
          if (activity instanceof TaskListActivity) {
              ((TaskListActivity) activity).getMainMenuPopover().addMenuItem(title, image, customIntent, id);
          } else {
              MenuItem item = menu.add(Menu.NONE, id, Menu.NONE, title);
              item.setIcon(image);
              item.setIntent(customIntent);
          }
      }
  
      /**
       * Create options menu (displayed when user presses menu key)
       *
       * @return true if menu should be displayed
       */
      @Override
      public void onCreateOptionsMenu(Menu menu, com.actionbarsherlock.view.MenuInflater inflater) {
          Activity activity = getActivity();
          if (activity == null)
              return;
          if (!isCurrentTaskListFragment())
              return;
  
          addMenuItems(menu, activity);
      }
  
      protected void addMenuItems(Menu menu, Activity activity) {
          boolean isTablet = AstridPreferences.useTabletLayout(activity);
          TaskListActivity tla = null;
          if (activity instanceof TaskListActivity) {
              tla = (TaskListActivity) activity;
              tla.getMainMenuPopover().clear();
          }
          // --- sync
          if (tla == null || tla.getTaskEditFragment() == null && Preferences.getBoolean(R.string.p_show_menu_sync, true))
              addSyncRefreshMenuItem(menu, isTablet ? ThemeService.FLAG_INVERT : 0);
  
          // --- sort
          if (allowResorting() && Preferences.getBoolean(R.string.p_show_menu_sort, true)) {
              addMenuItem(menu, R.string.TLA_menu_sort,
                      ThemeService.getDrawable(R.drawable.icn_menu_sort_by_size, isTablet ? ThemeService.FLAG_FORCE_DARK: 0), MENU_SORT_ID, false);
          }
  
          // --- new filter
          if (Preferences.getBoolean(R.string.p_use_filters, true))
              addMenuItem(menu, R.string.FLA_new_filter,
                      ThemeService.getDrawable(R.drawable.icn_menu_filters, isTablet ? ThemeService.FLAG_FORCE_DARK: 0), MENU_NEW_FILTER_ID, false);
  
          // ask about plug-ins
          Intent queryIntent = new Intent(
                  AstridApiConstants.ACTION_TASK_LIST_MENU);
  
          PackageManager pm = getActivity().getPackageManager();
          List<ResolveInfo> resolveInfoList = pm.queryIntentActivities(
                  queryIntent, 0);
          int length = resolveInfoList.size();
          for (int i = 0; i < length; i++) {
              ResolveInfo resolveInfo = resolveInfoList.get(i);
              Intent intent = new Intent(AstridApiConstants.ACTION_TASK_LIST_MENU);
              intent.setClassName(resolveInfo.activityInfo.packageName,
                      resolveInfo.activityInfo.name);
              addMenuItem(menu, resolveInfo.loadLabel(pm), resolveInfo.loadIcon(pm), intent, MENU_ADDON_INTENT_ID);
          }
      }
  
      protected boolean allowResorting() {
          return true;
      }
  
      protected void setUpUiComponents() {
          // set listener for quick-changing task priority
          getListView().setOnKeyListener(new OnKeyListener() {
              @Override
              public boolean onKey(View view, int keyCode, KeyEvent event) {
                  if (event.getAction() != KeyEvent.ACTION_UP || view == null)
                      return false;
  
                  boolean filterOn = getListView().isTextFilterEnabled();
                  View selected = getListView().getSelectedView();
  
                  // hot-key to set task priority - 1-4 or ALT + Q-R
                  if (!filterOn && event.getUnicodeChar() >= '1'
                          && event.getUnicodeChar() <= '4' && selected != null) {
                      int importance = event.getNumber() - '1';
                      Task task = ((ViewHolder) selected.getTag()).task;
                      task.setValue(Task.IMPORTANCE, importance);
                      taskService.save(task);
                      taskAdapter.setFieldContentsAndVisibility(selected);
                  }
                  // filter
                  else if (!filterOn && event.getUnicodeChar() != 0) {
                      getListView().setTextFilterEnabled(true);
                      getListView().setFilterText(
                              Character.toString((char) event.getUnicodeChar()));
                  }
                  // turn off filter if nothing is selected
                  else if (filterOn
                          && TextUtils.isEmpty(getListView().getTextFilter())) {
                      getListView().setTextFilterEnabled(false);
                  }
  
                  return false;
              }
          });
  
          SharedPreferences publicPrefs = AstridPreferences.getPublicPrefs(getActivity());
          sortFlags = publicPrefs.getInt(SortHelper.PREF_SORT_FLAGS, 0);
          sortSort = publicPrefs.getInt(SortHelper.PREF_SORT_SORT, 0);
          sortFlags = SortHelper.setManualSort(sortFlags, isDraggable());
  
          getView().findViewById(R.id.progressBar).setVisibility(View.GONE);
      }
  
      protected void setupQuickAddBar() {
          quickAddBar = (QuickAddBar) getView().findViewById(R.id.taskListFooter);
          quickAddBar.initialize((AstridActivity) getActivity(), this, mListener);
  
          getListView().setOnTouchListener(new OnTouchListener() {
              @Override
              public boolean onTouch(View v, MotionEvent event) {
                  quickAddBar.clearFocus();
                  return false;
              }
          });
  
          // set listener for astrid icon
          ((TextView) getView().findViewById(android.R.id.empty)).setOnClickListener(new OnClickListener() {
              @Override
              public void onClick(View v) {
                  quickAddBar.performButtonClick();
              }
          });
      }
  
      public void transitionForTaskEdit() {
          AndroidUtilities.callOverridePendingTransition(getActivity(),
                  R.anim.slide_left_in, R.anim.slide_left_out);
      }
  
      private void setUpBackgroundJobs() {
          backgroundTimer = new Timer();
  
          // start a thread to refresh periodically
          backgroundTimer.scheduleAtFixedRate(new TimerTask() {
              @Override
              public void run() {
                  // refresh if conditions match
                  Flags.checkAndClear(Flags.REFRESH);
                  getActivity().runOnUiThread(new Runnable() {
                      @Override
                      public void run() {
                          try {
                              refresh();
                          } catch (IllegalStateException e) {
                              // view may have been destroyed
                          }
                      }
                  });
              }
          }, BACKGROUND_REFRESH_INTERVAL, BACKGROUND_REFRESH_INTERVAL);
      }
  
      /*
       * ======================================================================
       * ============================================================ lifecycle
       * ======================================================================
       */
  
      @Override
      public void onStart() {
          super.onStart();
          quickAddBar.setupRecognizerApi();
      }
  
      @Override
      public void onStop() {
          super.onStop();
          quickAddBar.destroyRecognizerApi();
      }
  
      /**
       * Crazy hack so that tag view fragment won't automatically initiate an autosync after a tag
       * is deleted. TagViewFragment has to call onResume, but we don't want it to call
       * the normal tasklist onResume.
       */
      protected void parentOnResume() {
          super.onResume();
      }
  
      @Override
      public void onResume() {
          super.onResume();
  
          getActivity().registerReceiver(detailReceiver,
                  new IntentFilter(AstridApiConstants.BROADCAST_SEND_DETAILS));
          getActivity().registerReceiver(detailReceiver,
                  new IntentFilter(AstridApiConstants.BROADCAST_SEND_DECORATIONS));
          getActivity().registerReceiver(refreshReceiver,
                  new IntentFilter(AstridApiConstants.BROADCAST_EVENT_REFRESH));
          syncActionHelper.register();
  
          if (Flags.checkAndClear(Flags.REFRESH)) {
              refresh();
          }
  
          setUpBackgroundJobs();
  
          if (!Preferences.getBoolean(
                  WelcomeWalkthrough.KEY_SHOWED_WELCOME_LOGIN, false)) {
              Preferences.setBoolean(WelcomeWalkthrough.KEY_SHOWED_WELCOME_LOGIN,
                      true);
              Intent showWelcomeLogin = new Intent(getActivity(),
                      WelcomeWalkthrough.class);
              showWelcomeLogin.putExtra(ActFmLoginActivity.SHOW_TOAST, false);
              startActivity(showWelcomeLogin);
              return;
          }
  
          if (!Preferences.getBoolean(R.string.p_showed_add_task_help, false)) {
              showTaskCreateHelpPopover();
          } else if (!Preferences.getBoolean(R.string.p_showed_tap_task_help, false)) {
              showTaskEditHelpPopover();
          } else if (!Preferences.getBoolean(R.string.p_showed_lists_help, false)) {
              showListsHelp();
          }
          refreshFilterCount();
  
          initiateAutomaticSync();
  
          showFeedbackPrompt();
      }
  
      private void showFeedbackPrompt() {
          if (!(this instanceof TagViewFragment) &&
                  (DateUtilities.now() - Preferences.getLong(PREF_LAST_FEEDBACK_TIME, 0)) > FEEDBACK_TIME_INTERVAL &&
                  taskService.getUserActivationStatus()) {
              final LinearLayout root = (LinearLayout) getView().findViewById(R.id.taskListParent);
              if (root.findViewById(R.id.feedback_banner) == null) {
                  final View feedbackPrompt = getActivity().getLayoutInflater().inflate(R.layout.feedback_prompt, root, false);
  
                  feedbackPrompt.findViewById(R.id.positiveFeedback).setOnClickListener(new OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          try {
                              root.removeView(feedbackPrompt);
                              FeedbackPromptDialogs.showFeedbackDialog((AstridActivity) getActivity(), true);
                              Preferences.setLong(PREF_LAST_FEEDBACK_TIME, DateUtilities.now());
                          } catch (Exception e) {
                              e.printStackTrace();
                          }
                      }
                  });
  
                  feedbackPrompt.findViewById(R.id.negativeFeedback).setOnClickListener(new OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          try {
                              root.removeView(feedbackPrompt);
                              FeedbackPromptDialogs.showFeedbackDialog((AstridActivity) getActivity(), false);
                              Preferences.setLong(PREF_LAST_FEEDBACK_TIME, DateUtilities.now());
                          } catch (Exception e) {
                              e.printStackTrace();
                          }
                      }
                  });
  
                  root.addView(feedbackPrompt, 0);
              }
          }
      }
  
      protected boolean isCurrentTaskListFragment() {
          AstridActivity activity = (AstridActivity) getActivity();
          if (activity != null) {
              return activity.getTaskListFragment() == this;
          }
          return false;
      }
  
      public final void initiateAutomaticSync() {
          final AstridActivity activity = (AstridActivity) getActivity();
          if (activity == null)
              return;
          if (activity.fragmentLayout != AstridActivity.LAYOUT_SINGLE) {
              initiateAutomaticSyncImpl();
          } else {
              // In single fragment case, we're using swipe between lists,
              // so wait a couple seconds before initiating the autosync.
              new Thread() {
                  @Override
                  public void run() {
                      AndroidUtilities.sleepDeep(WAIT_BEFORE_AUTOSYNC);
                      activity.runOnUiThread(new Runnable() {
                          @Override
                          public void run() {
                              initiateAutomaticSyncImpl();
                          }
                      });
                  }
              }.start();
          }
      }
  
      /**
       * Implementation of initiation automatic sync. Subclasses should override this method;
       * the above method takes care of calling it in the correct way
       */
      protected void initiateAutomaticSyncImpl() {
          if (isCurrentTaskListFragment() && isInbox)
              syncActionHelper.initiateAutomaticSync();
      }
  
      // Subclasses should override this
      public void requestCommentCountUpdate() {
          TaskListActivity activity = (TaskListActivity) getActivity();
          if (activity != null)
              activity.setCommentsCount(0);
      }
  
      @Override
      public void onPause() {
          super.onPause();
  
          AndroidUtilities.tryUnregisterReceiver(getActivity(), detailReceiver);
          AndroidUtilities.tryUnregisterReceiver(getActivity(), refreshReceiver);
          syncActionHelper.unregister();
  
          backgroundTimer.cancel();
      }
  
      /**
       * Receiver which receives refresh intents
       *
       * @author Tim Su <tim@todoroo.com>
       *
       */
      protected class RefreshReceiver extends BroadcastReceiver {
          @Override
          public void onReceive(Context context, Intent intent) {
              if (intent == null
                      || !AstridApiConstants.BROADCAST_EVENT_REFRESH.equals(intent.getAction()))
                  return;
  
              final Activity activity = getActivity();
              if (activity != null) {
                  activity.runOnUiThread(new Runnable() {
                      @Override
                      public void run() {
                          refresh();
                          if (activity instanceof TaskListActivity)
                              ((TaskListActivity) activity).refreshMainMenu();
                      }
                  });
              }
          }
      }
  
      /**
       * Called by the RefreshReceiver when the task list receives a refresh
       * broadcast. Subclasses should override this.
       */
      protected void refresh() {
  