/** * Copyright (c) 2012 Todoroo Inc * * See the file "LICENSE" for the full license governing this code. */ package com.todoroo.astrid.locale; import android.app.Activity; import android.app.AlertDialog; import android.app.ListActivity; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ListView; import android.widget.Spinner; import com.timsu.astrid.R; import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.astrid.activity.AddOnActivity; import com.todoroo.astrid.adapter.FilterAdapter; import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.FilterCategory; import com.todoroo.astrid.api.FilterListItem; import com.todoroo.astrid.core.PluginServices; import com.todoroo.astrid.service.StatisticsConstants; import com.todoroo.astrid.service.StatisticsService; import com.twofortyfouram.SharedResources; /** * Activity to edit alerts from Locale * * @author Tim Su <tim@todoroo.com> * */ public final class LocaleEditAlerts extends ListActivity { // --- locale constants /** key name for filter title in bundle */ @SuppressWarnings("nls") public static final String KEY_FILTER_TITLE = "title"; /** key name for filter SQL in bundle */ @SuppressWarnings("nls") public static final String KEY_SQL = "sql"; /** key name for filter content-values in bundle */ @SuppressWarnings("nls") public static final String KEY_VALUES = "val"; /** key name for interval (integer, # of seconds) */ @SuppressWarnings("nls") public static final String KEY_INTERVAL = "interval"; // --- activity constants /** * Indices for interval setting */ public static final int INTERVAL_ONE_HOUR = 0; public static final int INTERVAL_SIX_HOURS = 1; public static final int INTERVAL_TWELVE_HOURS = 2; public static final int INTERVAL_ONE_DAY = 3; public static final int INTERVAL_THREE_DAYS = 4; public static final int INTERVAL_ONE_WEEK = 5; /** * Intervals in seconds */ public static final int[] INTERVALS = new int[] { 3600, 6 * 3600, 12 * 3600, 24 * 3600, 3 * 24 * 3600, 7 * 24 * 3600 }; /** * Menu ID of the save item. */ private static final int MENU_SAVE = 1; /** * Menu ID of the don't save item. */ private static final int MENU_DONT_SAVE = 2; // --- implementation FilterAdapter adapter = null; Spinner interval = null; /** * Flag boolean that can only be set to true via the "Don't Save" menu item in {@link #onMenuItemSelected(int, MenuItem)}. If * true, then this {@code Activity} should return {@link Activity#RESULT_CANCELED} in {@link #finish()}. * <p> * There is no need to save/restore this field's state when the {@code Activity} is paused. */ private boolean isCancelled = false; private boolean isRemoved = false; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { setTheme(R.style.Theme); super.onCreate(savedInstanceState); setContentView(R.layout.locale_edit_alerts); ContextManager.setContext(this); /* * Locale guarantees that the breadcrumb string will be present, but checking for null anyway makes your Activity more * robust and re-usable */ final String breadcrumbString = getIntent().getStringExtra(com.twofortyfouram.Intent.EXTRA_STRING_BREADCRUMB); if (breadcrumbString != null) setTitle(String.format("%s%s%s", breadcrumbString, com.twofortyfouram.Intent.BREADCRUMB_SEPARATOR, //$NON-NLS-1$ getString(R.string.locale_edit_alerts_title))); /* * Load the Locale background frame from Locale */ // ((LinearLayout) findViewById(R.id.frame)).setBackgroundDrawable( // SharedResources.getDrawableResource(getPackageManager(), // SharedResources.DRAWABLE_LOCALE_BORDER)); // set up UI components interval = (Spinner) findViewById(R.id.intervalSpinner); interval.setSelection(INTERVAL_ONE_DAY); String selectionToMatch = null; try { /* * if savedInstanceState == null, then we are entering the Activity directly from Locale and we need to check whether the * Intent has forwarded a Bundle extra (e.g. whether we editing an old setting or creating a new one) */ if (savedInstanceState == null) { final Bundle forwardedBundle = getIntent().getBundleExtra(com.twofortyfouram.Intent.EXTRA_BUNDLE); /* * the forwardedBundle would be null if this was a new setting */ if (forwardedBundle != null) { final int intervalValue = forwardedBundle.getInt(KEY_INTERVAL, INTERVALS[interval.getSelectedItemPosition()]); for(int i = 0; i < INTERVALS.length; i++) { if(intervalValue == INTERVALS[i]) { interval.setSelection(i); break; } } selectionToMatch = forwardedBundle.getString(KEY_SQL); } } } catch (Exception e) { selectionToMatch = null; Log.e("astrid-locale", "Error loading bundle", e); //$NON-NLS-1$ //$NON-NLS-2$ } // if we match a selection, make it selected final String finalSelection = selectionToMatch; adapter = new FilterAdapter(this, getListView(), R.layout.filter_adapter_row, true) { @Override public void onReceiveFilter(FilterListItem item) { if(adapter.getSelection() != null || finalSelection == null) return; if(item instanceof Filter) { if(finalSelection.equals(((Filter)item).getSqlQuery())) adapter.setSelection(item); } else if(item instanceof FilterCategory) { Filter[] filters = ((FilterCategory)item).children; if(filters == null) return; for(Filter filter : filters) if(finalSelection.equals(filter.getSqlQuery())) { adapter.setSelection(filter); break; } } } }; adapter.filterStyle = R.style.TextAppearance_LEA_Filter; adapter.headerStyle = R.style.TextAppearance_LEA_Header; setListAdapter(adapter); // check for plugin if(!PluginServices.getAddOnService().hasLocalePlugin()) { isRemoved = true; new AlertDialog.Builder(this) .setTitle(R.string.DLG_information_title) .setMessage(R.string.locale_plugin_required) .setCancelable(false) .setPositiveButton(android.R.string.ok, AddOnActivity.createAddOnClicker(LocaleEditAlerts.this, true)) .show(); StatisticsService.reportEvent(StatisticsConstants.LOCALE_EDIT_ALERTS_NO_PLUGIN); } else { StatisticsService.reportEvent(StatisticsConstants.LOCALE_EDIT_ALERTS); } } @Override public void onListItemClick(ListView parent, View v, int position, long id) { Filter item = adapter.getItem(position); adapter.setSelection(item); } /** * Called when the {@code Activity} is being terminated. This method determines the state of the {@code Activity} and what * sort of result should be returned to <i>Locale</i>. */ @Override public void finish() { if(isRemoved) setResult(com.twofortyfouram.Intent.RESULT_REMOVE); else if (isCancelled) setResult(RESULT_CANCELED); else { final FilterListItem selected = adapter.getSelection(); final int intervalIndex = interval.getSelectedItemPosition(); if (selected == null) { /* * If nothing is selected, return as if user had canceled */ setResult(RESULT_CANCELED); } else { /* * This is the return Intent, into which we'll put all the required extras */ final Intent returnIntent = new Intent(); /* * This extra is the data to ourselves: either for the Activity or the BroadcastReceiver. Note that anything * placed in this bundle must be available to Locale's class loader. So storing String, int, and other basic * objects will work just fine. You cannot store an object that only exists in your project, as Locale will be * unable to serialize it. */ final Bundle storeAndForwardExtras = new Bundle(); Filter filterItem = (Filter) selected; storeAndForwardExtras.putString(KEY_FILTER_TITLE, filterItem.title); storeAndForwardExtras.putString(KEY_SQL, filterItem.getSqlQuery()); if(filterItem.valuesForNewTasks != null) storeAndForwardExtras.putString(KEY_VALUES, AndroidUtilities.contentValuesToSerializedString(filterItem.valuesForNewTasks)); storeAndForwardExtras.putInt(KEY_INTERVAL, INTERVALS[intervalIndex]); returnIntent.putExtra(com.twofortyfouram.Intent.EXTRA_BUNDLE, storeAndForwardExtras); /* * This is the blurb concisely describing what your setting's state is. This is simply used for display in the UI. */ if (filterItem.title != null && filterItem.title.length() > com.twofortyfouram.Intent.MAXIMUM_BLURB_LENGTH) returnIntent.putExtra(com.twofortyfouram.Intent.EXTRA_STRING_BLURB, filterItem.title.substring(0, com.twofortyfouram.Intent.MAXIMUM_BLURB_LENGTH)); else returnIntent.putExtra(com.twofortyfouram.Intent.EXTRA_STRING_BLURB, filterItem.title); setResult(RESULT_OK, returnIntent); } } super.finish(); } // --- boring stuff @Override protected void onResume() { super.onResume(); StatisticsService.sessionStart(this); adapter.registerRecevier(); } @Override protected void onPause() { super.onPause(); StatisticsService.sessionPause(); adapter.unregisterRecevier(); } @Override protected void onStart() { super.onStart(); } @Override protected void onStop() { super.onStop(); StatisticsService.sessionStop(this); } /** * {@inheritDoc} */ @Override public boolean onCreateOptionsMenu(final Menu menu) { super.onCreateOptionsMenu(menu); final PackageManager manager = getPackageManager(); /* * We are dynamically loading resources from Locale's APK. This will only work if Locale is actually installed */ menu.add(0, MENU_DONT_SAVE, 0, SharedResources.getTextResource(manager, SharedResources.STRING_MENU_DONTSAVE)) .setIcon(SharedResources.getDrawableResource(manager, SharedResources.DRAWABLE_MENU_DONTSAVE)).getItemId(); menu.add(0, MENU_SAVE, 0, SharedResources.getTextResource(manager, SharedResources.STRING_MENU_SAVE)) .setIcon(SharedResources.getDrawableResource(manager, SharedResources.DRAWABLE_MENU_SAVE)).getItemId(); return true; } /** * {@inheritDoc} */ @Override public boolean onMenuItemSelected(final int featureId, final MenuItem item) { switch (item.getItemId()) { case MENU_SAVE: { finish(); return true; } case MENU_DONT_SAVE: { isCancelled = true; finish(); return true; } } return super.onOptionsItemSelected(item); } }