Permalink
Browse files

Allow custom snooze times for calendar reminders.

It's possible to
- snooze all reminders with a custom timeout at once using a new button
- snooze single reminders by long-pressing them and selecting the
  appropriate menu item

Change-Id: I6c43625d06f0a3b108c67baf9830bbebea9e0dc8
  • Loading branch information...
1 parent e4d2a63 commit e4e4f39f6732326047b8b2c2aec93c9189a9b594 @maniac103 maniac103 committed with djMesias Dec 21, 2011
View
6 res/layout/alert_activity.xml
@@ -36,6 +36,12 @@
android:layout_weight="1"
android:text="@string/snooze_all_label" />
+ <Button android:id="@+id/snooze_all_by"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/snooze_all_by_label" />
+
<Button android:id="@+id/dismiss_all"
android:layout_width="0dip"
android:layout_height="wrap_content"
View
4 res/values-de/strings.xml
@@ -108,7 +108,11 @@
<string name="discard_label" msgid="4510607554910139220">"Rückgängig"</string>
<string name="import_label" msgid="6993796574741477222">"Import"</string>
<string name="snooze_all_label" msgid="4994488813124409077">"Später erinnern"</string>
+ <string name="snooze_all_by_label">"Später erinnern in\u2026"</string>
<string name="dismiss_all_label" msgid="1834400025868091301">"Alle schließen"</string>
+ <string name="menu_item_info">Anzeigen</string>
+ <string name="menu_item_snooze">Später erinnern in\u2026</string>
+ <string name="title_snooze_for">Erinnern in\u2026</string>
<string name="does_not_repeat" msgid="1877681921029738999">"Einmaliger Termin"</string>
<string name="daily" msgid="560350706808680448">"Täglich"</string>
<string name="every_weekday" msgid="5896574838353902978">"Jeden Werktag (Mo. - Fr.)"</string>
View
6 res/values-es/strings.xml
@@ -107,8 +107,12 @@
<string name="save_label" msgid="2133599104834432589">"OK"</string>
<string name="discard_label" msgid="4510607554910139220">"Revertir"</string>
<string name="import_label" msgid="6993796574741477222">"Importar"</string>
- <string name="snooze_all_label" msgid="4994488813124409077">"Posponer recordatorios"</string>
+ <string name="snooze_all_label" msgid="4994488813124409077">"Posponer todo"</string>
+ <string name="snooze_all_by_label">"Posponer todo a\u2026"</string>
<string name="dismiss_all_label" msgid="1834400025868091301">"Descartar todo"</string>
+ <string name="menu_item_info">Mostrar información</string>
+ <string name="menu_item_snooze">Posponer\u2026</string>
+ <string name="title_snooze_for">Posponer a\u2026</string>
<string name="does_not_repeat" msgid="1877681921029738999">"Evento único"</string>
<string name="daily" msgid="560350706808680448">"Cada día"</string>
<string name="every_weekday" msgid="5896574838353902978">"Cada día laborable (lunes-viernes)"</string>
View
9 res/values/strings.xml
@@ -291,9 +291,18 @@
<!-- The button label for making the reminder alarms go away temporarily.
The reminder alarms will fire off again in 5 minutes. -->
<string name="snooze_all_label">"Snooze all"</string>
+ <!-- The button label for making the reminder alarms go away temporarily
+ with a custom timeout. -->
+ <string name="snooze_all_by_label">"Snooze all by\u2026"</string>
<!-- The button label for dismissing all the current reminder alarms. This
causes them to disappear from the notification screen. -->
<string name="dismiss_all_label">"Dismiss all"</string>
+ <!-- Context menu item for opening item info -->
+ <string name="menu_item_info">Show information</string>
+ <!-- Context menu item for snoozing the item -->
+ <string name="menu_item_snooze">Snooze\u2026</string>
+ <!-- Snooze dialog title -->
+ <string name="title_snooze_for">Snooze for\u2026</string>
<!-- Repetition dialog options: -->
<skip />
View
214 src/com/android/calendar/AlertActivity.java
@@ -21,33 +21,40 @@
import android.app.Activity;
import android.app.AlarmManager;
+import android.app.AlertDialog;
import android.app.NotificationManager;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Calendar.CalendarAlerts;
import android.provider.Calendar.CalendarAlertsColumns;
import android.provider.Calendar.Events;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
-import android.widget.AdapterView.OnItemClickListener;
/**
* The alert panel that pops up when there is a calendar event alarm.
* This activity is started by an intent that specifies an event id.
*/
-public class AlertActivity extends Activity {
+public class AlertActivity extends Activity implements View.OnCreateContextMenuListener {
// The default snooze delay: 5 minutes
public static final long SNOOZE_DELAY = 5 * 60 * 1000L;
@@ -90,12 +97,16 @@
// as it is used consistently everywhere.
public static final int NOTIFICATION_ID = 0;
+ private static final int MENU_INFO_ID = Menu.FIRST;
+ private static final int MENU_SNOOZE_ID = Menu.FIRST + 1;
+
private ContentResolver mResolver;
private AlertAdapter mAdapter;
private QueryHandler mQueryHandler;
private Cursor mCursor;
private ListView mListView;
private Button mSnoozeAllButton;
+ private Button mSnoozeAllByButton;
private Button mDismissAllButton;
@@ -129,6 +140,7 @@ protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
// The results are in, enable the buttons
mSnoozeAllButton.setEnabled(true);
+ mSnoozeAllByButton.setEnabled(true);
mDismissAllButton.setEnabled(true);
} else {
cursor.close();
@@ -171,31 +183,6 @@ private static ContentValues makeContentValues(long eventId, long begin, long en
return values;
}
- private OnItemClickListener mViewListener = new OnItemClickListener() {
-
- public void onItemClick(AdapterView<?> parent, View view, int position,
- long i) {
- AlertActivity alertActivity = AlertActivity.this;
- Cursor cursor = alertActivity.getItemForView(view);
-
- long id = cursor.getInt(AlertActivity.INDEX_EVENT_ID);
- long startMillis = cursor.getLong(AlertActivity.INDEX_BEGIN);
- long endMillis = cursor.getLong(AlertActivity.INDEX_END);
-
- Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, id);
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- intent.setClass(alertActivity, EventInfoActivity.class);
- intent.putExtra(EVENT_BEGIN_TIME, startMillis);
- intent.putExtra(EVENT_END_TIME, endMillis);
-
- // Mark this alarm as DISMISSED
- dismissAlarm(cursor.getLong(INDEX_ROW_ID));
-
- startActivity(intent);
- alertActivity.finish();
- }
- };
-
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -216,15 +203,23 @@ protected void onCreate(Bundle icicle) {
mListView = (ListView) findViewById(R.id.alert_container);
mListView.setItemsCanFocus(true);
mListView.setAdapter(mAdapter);
- mListView.setOnItemClickListener(mViewListener);
+ mListView.setOnCreateContextMenuListener(this);
+ mListView.setOnItemClickListener(new OnItemClickListener() {
+ public void onItemClick(AdapterView<?> parent, View view, int position, long i) {
+ showItemInfo(getItemForView(view));
+ }
+ });
mSnoozeAllButton = (Button) findViewById(R.id.snooze_all);
mSnoozeAllButton.setOnClickListener(mSnoozeAllListener);
+ mSnoozeAllByButton = (Button) findViewById(R.id.snooze_all_by);
+ mSnoozeAllByButton.setOnClickListener(mSnoozeAllByListener);
mDismissAllButton = (Button) findViewById(R.id.dismiss_all);
mDismissAllButton.setOnClickListener(mDismissAllListener);
// Disable the buttons, since they need mCursor, which is created asynchronously
mSnoozeAllButton.setEnabled(false);
+ mSnoozeAllByButton.setEnabled(false);
mDismissAllButton.setEnabled(false);
}
@@ -238,7 +233,7 @@ protected void onResume() {
mQueryHandler.startQuery(0, null, uri, PROJECTION, SELECTION,
SELECTIONARG, CalendarAlerts.DEFAULT_SORT_ORDER);
} else {
- mCursor.requery();
+ updateCursor();
}
}
@@ -260,6 +255,33 @@ protected void onDestroy() {
}
}
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ Cursor cursor = getItemFromMenuInfo(menuInfo);
+ if (cursor != null) {
+ menu.setHeaderTitle(cursor.getString(INDEX_TITLE));
+ menu.add(Menu.NONE, MENU_INFO_ID, Menu.NONE, R.string.menu_item_info);
+ menu.add(Menu.NONE, MENU_SNOOZE_ID, Menu.NONE, R.string.menu_item_snooze);
+ }
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ Cursor cursor = getItemFromMenuInfo(item.getMenuInfo());
+
+ switch (item.getItemId()) {
+ case MENU_INFO_ID:
+ showItemInfo(cursor);
+ break;
+ case MENU_SNOOZE_ID:
+ handleItemSnooze(cursor);
+ break;
+ default:
+ return super.onContextItemSelected(item);
+ }
+ return true;
+ }
+
private OnClickListener mSnoozeAllListener = new OnClickListener() {
public void onClick(View v) {
long alarmTime = System.currentTimeMillis() + SNOOZE_DELAY;
@@ -268,32 +290,33 @@ public void onClick(View v) {
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.cancel(NOTIFICATION_ID);
- long scheduleAlarmTime = 0;
- mCursor.moveToPosition(-1);
- while (mCursor.moveToNext()) {
- long eventId = mCursor.getLong(INDEX_EVENT_ID);
- long begin = mCursor.getLong(INDEX_BEGIN);
- long end = mCursor.getLong(INDEX_END);
-
- // Set the "minutes" to zero to indicate this is a snoozed
- // alarm. There is code in AlertService.java that checks
- // this field.
- ContentValues values =
- makeContentValues(eventId, begin, end, alarmTime, 0 /* minutes */);
-
- // Create a new alarm entry in the CalendarAlerts table
- if (mCursor.isLast()) {
- scheduleAlarmTime = alarmTime;
- }
- mQueryHandler.startInsert(0, scheduleAlarmTime, CalendarAlerts.CONTENT_URI, values);
- }
-
+ snoozeEvents(0, alarmTime);
dismissFiredAlarms();
finish();
}
};
+ private OnClickListener mSnoozeAllByListener = new OnClickListener() {
+ public void onClick(View v) {
+ getSnoozeTimeDialog(new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ long alarmTime = getSnoozeAlarmTime(which);
+
+ NotificationManager nm =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ nm.cancel(NOTIFICATION_ID);
+
+ snoozeEvents(0, alarmTime);
+ dismissFiredAlarms();
+
+ dialog.dismiss();
+ finish();
+ }
+ }).show();
+ }
+ };
+
private OnClickListener mDismissAllListener = new OnClickListener() {
public void onClick(View v) {
NotificationManager nm =
@@ -306,6 +329,87 @@ public void onClick(View v) {
}
};
+ private void updateCursor() {
+ mCursor.requery();
+ if (isEmpty()) {
+ finish();
+ }
+ }
+
+ private long getSnoozeAlarmTime(int listPosition) {
+ final String value = getResources().getStringArray(R.array.reminder_minutes_values)[listPosition];
+ final long delay = Long.parseLong(value) * 60 * 1000;
+ return System.currentTimeMillis() + delay;
+ }
+
+ private AlertDialog.Builder getSnoozeTimeDialog(DialogInterface.OnClickListener listener) {
+ return new AlertDialog.Builder(this)
+ .setTitle(R.string.title_snooze_for)
+ .setSingleChoiceItems(R.array.reminder_minutes_labels, -1, listener)
+ .setNegativeButton(android.R.string.cancel, null);
+ }
+
+ private void snoozeEvents(long event, long alarmTime) {
+ long scheduleAlarmTime = 0;
+ mCursor.moveToPosition(-1);
+ while (mCursor.moveToNext()) {
+ long eventId = mCursor.getLong(INDEX_EVENT_ID);
+ long begin = mCursor.getLong(INDEX_BEGIN);
+ long end = mCursor.getLong(INDEX_END);
+
+ if (event != 0 && event != eventId) {
+ continue;
+ }
+
+ // Set the "minutes" to zero to indicate this is a snoozed
+ // alarm. There is code in AlertService.java that checks
+ // this field.
+ ContentValues values =
+ makeContentValues(eventId, begin, end, alarmTime, 0 /* minutes */);
+
+ // Create a new alarm entry in the CalendarAlerts table
+ if (eventId != 0 || mCursor.isLast()) {
+ scheduleAlarmTime = alarmTime;
+ }
+ mQueryHandler.startInsert(0, scheduleAlarmTime, CalendarAlerts.CONTENT_URI, values);
+ }
+ }
+
+ private void handleItemSnooze(Cursor cursor) {
+ final long id = cursor.getInt(AlertActivity.INDEX_ROW_ID);
+ final long eventId = cursor.getInt(AlertActivity.INDEX_EVENT_ID);
+
+ getSnoozeTimeDialog(new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ long alarmTime = getSnoozeAlarmTime(which);
+
+ snoozeEvents(eventId, alarmTime);
+ dismissAlarm(id);
+ dialog.dismiss();
+ AlertService.updateAlertNotification(AlertActivity.this);
+ updateCursor();
+ }
+ }).show();
+ }
+
+ private void showItemInfo(Cursor cursor) {
+ long id = cursor.getInt(AlertActivity.INDEX_EVENT_ID);
+ long startMillis = cursor.getLong(AlertActivity.INDEX_BEGIN);
+ long endMillis = cursor.getLong(AlertActivity.INDEX_END);
+
+ Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, id);
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ intent.setClass(this, EventInfoActivity.class);
+ intent.putExtra(EVENT_BEGIN_TIME, startMillis);
+ intent.putExtra(EVENT_END_TIME, endMillis);
+
+ // Mark this alarm as DISMISSED
+ dismissAlarm(cursor.getLong(INDEX_ROW_ID));
+ AlertService.updateAlertNotification(this);
+
+ startActivity(intent);
+ }
+
public boolean isEmpty() {
return (mCursor.getCount() == 0);
}
@@ -317,4 +421,16 @@ public Cursor getItemForView(View view) {
}
return (Cursor) mListView.getAdapter().getItem(index);
}
+
+ private Cursor getItemFromMenuInfo(ContextMenuInfo menuInfo) {
+ AdapterContextMenuInfo info;
+
+ try {
+ info = (AdapterContextMenuInfo) menuInfo;
+ } catch (ClassCastException e) {
+ return null;
+ }
+
+ return (Cursor) mListView.getAdapter().getItem(info.position);
+ }
}

0 comments on commit e4e4f39

Please sign in to comment.