Enable message read/unread toggling
* Automatically marked read when entering MessageView * Marked unread via menu selected during MessageView * Provider updated (directly - see note) * Enable context menu in MessageList and enable "open" & toggle unread NOTE: Does not use the correct service notifications yet; Just updates the providers. NOTE: The UI for the context menu is incomplete, it says "mark as read" but it actually toggles the state. The true UI is to flip the text to match the current state e.g. "mark as read" or "mark as unread". That will be much simpler to implement when we switch to a custom list item view class, where we can cache the read/unread state (and other tidbits).
This commit is contained in:
parent
48c8cc34b7
commit
bb0f962dbb
24
res/menu/message_list_context.xml
Normal file
24
res/menu/message_list_context.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2009 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@+id/open" android:title="@string/open_action" />
|
||||||
|
<item android:id="@+id/delete" android:title="@string/delete_action" />
|
||||||
|
<item android:id="@+id/forward" android:title="@string/forward_action" />
|
||||||
|
<item android:id="@+id/reply_all" android:title="@string/reply_all_action" />
|
||||||
|
<item android:id="@+id/reply" android:title="@string/reply_action" />
|
||||||
|
<item android:id="@+id/mark_as_read" android:title="@string/mark_as_read_action" />
|
||||||
|
</menu>
|
@ -25,20 +25,25 @@ import com.android.email.provider.EmailContent;
|
|||||||
import com.android.email.provider.EmailContent.MessageColumns;
|
import com.android.email.provider.EmailContent.MessageColumns;
|
||||||
|
|
||||||
import android.app.ListActivity;
|
import android.app.ListActivity;
|
||||||
|
import android.content.ContentUris;
|
||||||
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.view.ContextMenu;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
|
import android.view.ContextMenu.ContextMenuInfo;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.CursorAdapter;
|
import android.widget.CursorAdapter;
|
||||||
@ -136,18 +141,7 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
// TODO these can be lighter-weight lookups
|
onOpenMessage(id);
|
||||||
EmailContent.Message message = EmailContent.Message.restoreMessageWithId(this, id);
|
|
||||||
EmailContent.Mailbox mailbox =
|
|
||||||
EmailContent.Mailbox.restoreMailboxWithId(this, message.mMailboxKey);
|
|
||||||
|
|
||||||
if (mailbox.mType == EmailContent.Mailbox.TYPE_DRAFTS) {
|
|
||||||
// TODO need id-based API for MessageCompose
|
|
||||||
// MessageCompose.actionEditDraft(this, id);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
MessageView.actionView(this, id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@ -182,6 +176,49 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
||||||
|
super.onCreateContextMenu(menu, v, menuInfo);
|
||||||
|
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||||
|
|
||||||
|
// TODO: There is no context menu for the outbox
|
||||||
|
// TODO: There is probably a special context menu for the trash
|
||||||
|
|
||||||
|
getMenuInflater().inflate(R.menu.message_list_context, menu);
|
||||||
|
|
||||||
|
// TODO: flip the "mark as read" string if the message is already read
|
||||||
|
// In order to do this, I really should cache the read state in the item view,
|
||||||
|
// instead of re-reading data from the cursor.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onContextItemSelected(MenuItem item) {
|
||||||
|
AdapterView.AdapterContextMenuInfo info =
|
||||||
|
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
|
||||||
|
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.open:
|
||||||
|
onOpenMessage(info.id);
|
||||||
|
break;
|
||||||
|
case R.id.delete:
|
||||||
|
//onDelete(holder);
|
||||||
|
break;
|
||||||
|
case R.id.reply:
|
||||||
|
//onReply(holder);
|
||||||
|
break;
|
||||||
|
case R.id.reply_all:
|
||||||
|
//onReplyAll(holder);
|
||||||
|
break;
|
||||||
|
case R.id.forward:
|
||||||
|
//onForward(holder);
|
||||||
|
break;
|
||||||
|
case R.id.mark_as_read:
|
||||||
|
onToggleRead(info.id, info.targetView);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return super.onContextItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
private void onRefresh() {
|
private void onRefresh() {
|
||||||
// TODO: This needs to loop through all open mailboxes (there might be more than one)
|
// TODO: This needs to loop through all open mailboxes (there might be more than one)
|
||||||
EmailContent.Mailbox mailbox =
|
EmailContent.Mailbox mailbox =
|
||||||
@ -212,6 +249,38 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
AccountSettings.actionSettings(this, mailbox.mAccountKey);
|
AccountSettings.actionSettings(this, mailbox.mAccountKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onOpenMessage(long messageId) {
|
||||||
|
// TODO Necessary info about the mailbox should have been cached in the listview item
|
||||||
|
// Instead, we're going to pull it from the DB here (expensively and in the wrong thread)
|
||||||
|
EmailContent.Message message = EmailContent.Message.restoreMessageWithId(this, messageId);
|
||||||
|
EmailContent.Mailbox mailbox =
|
||||||
|
EmailContent.Mailbox.restoreMailboxWithId(this, message.mMailboxKey);
|
||||||
|
|
||||||
|
if (mailbox.mType == EmailContent.Mailbox.TYPE_DRAFTS) {
|
||||||
|
// TODO need id-based API for MessageCompose
|
||||||
|
// MessageCompose.actionEditDraft(this, messageId);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MessageView.actionView(this, messageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onToggleRead(long messageId, View itemView) {
|
||||||
|
// TODO the read-unread state of the given message should be cached in the listview item.
|
||||||
|
// Instead, we're going to pull it from the DB here (expensively and in the wrong thread)
|
||||||
|
EmailContent.Message message = EmailContent.Message.restoreMessageWithId(this, messageId);
|
||||||
|
boolean isRead = ! message.mFlagRead;
|
||||||
|
|
||||||
|
// TODO this should be a call to the controller, since it may possibly kick off
|
||||||
|
// more than just a DB update. Also, the DB update shouldn't be in the UI thread
|
||||||
|
// as it is here.
|
||||||
|
ContentValues cv = new ContentValues();
|
||||||
|
cv.put(EmailContent.MessageColumns.FLAG_READ, isRead ? 1 : 0);
|
||||||
|
Uri uri = ContentUris.withAppendedId(
|
||||||
|
EmailContent.Message.SYNCED_CONTENT_URI, messageId);
|
||||||
|
getContentResolver().update(uri, cv, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Async task for loading a single folder out of the UI thread
|
* Async task for loading a single folder out of the UI thread
|
||||||
*
|
*
|
||||||
|
@ -569,6 +569,9 @@ public class MessageView extends Activity
|
|||||||
mFavoriteIcon.setImageDrawable(newFavorite ? mFavoriteIconOn : mFavoriteIconOff);
|
mFavoriteIcon.setImageDrawable(newFavorite ? mFavoriteIconOn : mFavoriteIconOff);
|
||||||
|
|
||||||
// Update provider
|
// Update provider
|
||||||
|
// TODO this should be a call to the controller, since it may possibly kick off
|
||||||
|
// more than just a DB update. Also, the DB update shouldn't be in the UI thread
|
||||||
|
// as it is here.
|
||||||
mMessage.mFlagFavorite = newFavorite;
|
mMessage.mFlagFavorite = newFavorite;
|
||||||
ContentValues cv = new ContentValues();
|
ContentValues cv = new ContentValues();
|
||||||
cv.put(EmailContent.MessageColumns.FLAG_FAVORITE, newFavorite ? 1 : 0);
|
cv.put(EmailContent.MessageColumns.FLAG_FAVORITE, newFavorite ? 1 : 0);
|
||||||
@ -619,13 +622,17 @@ public class MessageView extends Activity
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onMarkAsUnread() {
|
private void onMarkAsRead(boolean isRead) {
|
||||||
if (mOldMessage != null) {
|
if (mMessage != null && mMessage.mFlagRead != isRead) {
|
||||||
MessagingController.getInstance(getApplication()).markMessageRead(
|
// TODO this should be a call to the controller, since it may possibly kick off
|
||||||
mAccount,
|
// more than just a DB update. Also, the DB update shouldn't be in the UI thread
|
||||||
mFolder,
|
// as it is here.
|
||||||
mOldMessage.getUid(),
|
mMessage.mFlagFavorite = isRead;
|
||||||
false);
|
ContentValues cv = new ContentValues();
|
||||||
|
cv.put(EmailContent.MessageColumns.FLAG_READ, isRead ? 1 : 0);
|
||||||
|
Uri uri = ContentUris.withAppendedId(
|
||||||
|
EmailContent.Message.SYNCED_CONTENT_URI, mMessageId);
|
||||||
|
getContentResolver().update(uri, cv, null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -763,7 +770,8 @@ public class MessageView extends Activity
|
|||||||
onForward();
|
onForward();
|
||||||
break;
|
break;
|
||||||
case R.id.mark_as_unread:
|
case R.id.mark_as_unread:
|
||||||
onMarkAsUnread();
|
onMarkAsRead(false);
|
||||||
|
finish();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -1050,6 +1058,9 @@ public class MessageView extends Activity
|
|||||||
// toast? why would this fail?
|
// toast? why would this fail?
|
||||||
reloadBodyFromCursor(null); // hack to force text for display
|
reloadBodyFromCursor(null); // hack to force text for display
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At this point it's fair to mark the message as "read"
|
||||||
|
onMarkAsRead(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user