Merge pull request #4438 from k9mail/bye_CursorAdapter
Switch MessageListAdapter away from CursorAdapter
This commit is contained in:
commit
4fa2fd7094
5 changed files with 231 additions and 235 deletions
|
@ -2,7 +2,6 @@ package com.fsck.k9.fragment
|
|||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.database.Cursor
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.Drawable
|
||||
|
@ -15,7 +14,7 @@ import android.text.style.StyleSpan
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.CursorAdapter
|
||||
import android.widget.BaseAdapter
|
||||
import android.widget.TextView
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.core.view.isVisible
|
||||
|
@ -26,20 +25,18 @@ import com.fsck.k9.mail.Address
|
|||
import com.fsck.k9.ui.ContactBadge
|
||||
import com.fsck.k9.ui.R
|
||||
import com.fsck.k9.ui.messagelist.MessageListAppearance
|
||||
import com.fsck.k9.ui.messagelist.MessageListExtractor
|
||||
import com.fsck.k9.ui.messagelist.MessageListItem
|
||||
import kotlin.math.max
|
||||
|
||||
class MessageListAdapter internal constructor(
|
||||
context: Context,
|
||||
private val context: Context,
|
||||
theme: Resources.Theme,
|
||||
private val res: Resources,
|
||||
private val layoutInflater: LayoutInflater,
|
||||
private val contactsPictureLoader: ContactPictureLoader,
|
||||
private val messageListExtractor: MessageListExtractor,
|
||||
private val listItemListener: MessageListItemActionListener,
|
||||
private val appearance: MessageListAppearance
|
||||
) : CursorAdapter(context, null, 0) {
|
||||
) : BaseAdapter() {
|
||||
|
||||
private val forwardedIcon: Drawable
|
||||
private val answeredIcon: Drawable
|
||||
|
@ -77,9 +74,13 @@ class MessageListAdapter internal constructor(
|
|||
array.recycle()
|
||||
}
|
||||
|
||||
var activeMessage: MessageReference? = null
|
||||
var messages: List<MessageListItem> = emptyList()
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
var uniqueIdColumn: Int = 0
|
||||
var activeMessage: MessageReference? = null
|
||||
|
||||
var selected: Set<Long> = emptySet()
|
||||
|
||||
|
@ -100,7 +101,23 @@ class MessageListAdapter internal constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun newView(context: Context, cursor: Cursor, parent: ViewGroup): View {
|
||||
override fun hasStableIds(): Boolean = true
|
||||
|
||||
override fun getCount(): Int = messages.size
|
||||
|
||||
override fun getItemId(position: Int): Long = messages[position].uniqueId
|
||||
|
||||
override fun getItem(position: Int): MessageListItem = messages[position]
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
|
||||
val message = getItem(position)
|
||||
val view: View = convertView ?: newView(parent)
|
||||
bindView(view, context, message)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
private fun newView(parent: ViewGroup?): View {
|
||||
val view = layoutInflater.inflate(R.layout.message_list_item, parent, false)
|
||||
|
||||
val holder = MessageViewHolder(view, listItemListener)
|
||||
|
@ -125,14 +142,13 @@ class MessageListAdapter internal constructor(
|
|||
return view
|
||||
}
|
||||
|
||||
override fun bindView(view: View, context: Context, cursor: Cursor) {
|
||||
val item = messageListExtractor.extractMessageListItem(cursor, uniqueIdColumn)
|
||||
val isSelected = selected.contains(item.uniqueId)
|
||||
val isActive = isActiveMessage(item)
|
||||
private fun bindView(view: View, context: Context, message: MessageListItem) {
|
||||
val isSelected = selected.contains(message.uniqueId)
|
||||
val isActive = isActiveMessage(message)
|
||||
|
||||
val holder = view.tag as MessageViewHolder
|
||||
|
||||
with(item) {
|
||||
with(message) {
|
||||
val maybeBoldTypeface = if (isRead) Typeface.NORMAL else Typeface.BOLD
|
||||
val displayDate = DateUtils.getRelativeTimeSpanString(context, messageDate)
|
||||
val displayThreadCount = if (appearance.showingThreadedList) threadCount else 0
|
||||
|
|
|
@ -92,20 +92,13 @@ import com.fsck.k9.search.SqlQueryBuilder;
|
|||
import com.fsck.k9.ui.R;
|
||||
import com.fsck.k9.ui.messagelist.MessageListAppearance;
|
||||
import com.fsck.k9.ui.messagelist.MessageListExtractor;
|
||||
import com.fsck.k9.ui.messagelist.MessageListItem;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.fsck.k9.Account.Expunge.EXPUNGE_MANUALLY;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.ACCOUNT_UUID_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.FLAGGED_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.FOLDER_SERVER_ID_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.ID_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.PROJECTION;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.READ_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.SUBJECT_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.THREADED_PROJECTION;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.THREAD_COUNT_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.THREAD_ROOT_COLUMN;
|
||||
import static com.fsck.k9.fragment.MLFProjectionInfo.UID_COLUMN;
|
||||
|
||||
|
||||
public class MessageListFragment extends Fragment implements OnItemClickListener,
|
||||
|
@ -174,7 +167,6 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
|
||||
private Cursor[] cursors;
|
||||
private boolean[] cursorValid;
|
||||
private int uniqueIdColumn;
|
||||
|
||||
/**
|
||||
* Stores the server ID of the folder that we want to open as soon as possible after load.
|
||||
|
@ -358,24 +350,22 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
return;
|
||||
}
|
||||
|
||||
Cursor cursor = (Cursor) parent.getItemAtPosition(position);
|
||||
if (cursor == null) {
|
||||
return;
|
||||
}
|
||||
int adapterPosition = listViewToAdapterPosition(position);
|
||||
MessageListItem messageListItem = adapter.getItem(adapterPosition);
|
||||
|
||||
if (selectedCount > 0) {
|
||||
toggleMessageSelect(position);
|
||||
} else {
|
||||
if (showingThreadedList && cursor.getInt(THREAD_COUNT_COLUMN) > 1) {
|
||||
Account account = getAccountFromCursor(cursor);
|
||||
String folderServerId = cursor.getString(FOLDER_SERVER_ID_COLUMN);
|
||||
if (showingThreadedList && messageListItem.getThreadCount() > 1) {
|
||||
Account account = messageListItem.getAccount();
|
||||
String folderServerId = messageListItem.getFolderServerId();
|
||||
|
||||
// If threading is enabled and this item represents a thread, display the thread contents.
|
||||
long rootId = cursor.getLong(THREAD_ROOT_COLUMN);
|
||||
long rootId = messageListItem.getThreadRoot();
|
||||
fragmentListener.showThread(account, folderServerId, rootId);
|
||||
} else {
|
||||
// This item represents a message; just display the message.
|
||||
openMessageAtPosition(listViewToAdapterPosition(position));
|
||||
openMessageAtPosition(adapterPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -585,7 +575,6 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
getResources(),
|
||||
layoutInflater,
|
||||
ContactPicture.getContactPictureLoader(),
|
||||
messageListExtractor,
|
||||
this,
|
||||
getMessageListAppearance()
|
||||
);
|
||||
|
@ -1094,8 +1083,8 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
onResendMessage(getMessageAtPosition(adapterPosition));
|
||||
selectedCount = 0;
|
||||
} else if (id == R.id.same_sender) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(adapterPosition);
|
||||
String senderAddress = MlfUtils.getSenderAddressFromCursor(cursor);
|
||||
MessageListItem messageListItem = adapter.getItem(adapterPosition);
|
||||
String senderAddress = messageListItem.getSenderAddress();
|
||||
if (senderAddress != null) {
|
||||
fragmentListener.showMoreFromSameSender(senderAddress);
|
||||
}
|
||||
|
@ -1131,21 +1120,18 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
|
||||
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
|
||||
Cursor cursor = (Cursor) listView.getItemAtPosition(info.position);
|
||||
|
||||
if (cursor == null) {
|
||||
return;
|
||||
}
|
||||
int adapterPosition = listViewToAdapterPosition(info.position);
|
||||
MessageListItem messageListItem = adapter.getItem(adapterPosition);
|
||||
|
||||
getActivity().getMenuInflater().inflate(R.menu.message_list_item_context, menu);
|
||||
menu.findItem(R.id.debug_delete_locally).setVisible(K9.DEVELOPER_MODE);
|
||||
|
||||
contextMenuUniqueId = cursor.getLong(uniqueIdColumn);
|
||||
Account account = getAccountFromCursor(cursor);
|
||||
contextMenuUniqueId = messageListItem.getUniqueId();
|
||||
Account account = messageListItem.getAccount();
|
||||
|
||||
String subject = cursor.getString(SUBJECT_COLUMN);
|
||||
boolean read = (cursor.getInt(READ_COLUMN) == 1);
|
||||
boolean flagged = (cursor.getInt(FLAGGED_COLUMN) == 1);
|
||||
String subject = messageListItem.getSubject();
|
||||
boolean read = messageListItem.isRead();
|
||||
boolean flagged = messageListItem.isStarred();
|
||||
|
||||
menu.setHeaderTitle(subject);
|
||||
|
||||
|
@ -1416,12 +1402,12 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
|
||||
selectedCount = 0;
|
||||
for (int i = 0, end = adapter.getCount(); i < end; i++) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(i);
|
||||
long uniqueId = cursor.getLong(uniqueIdColumn);
|
||||
MessageListItem messageListItem = adapter.getItem(i);
|
||||
long uniqueId = messageListItem.getUniqueId();
|
||||
this.selected.add(uniqueId);
|
||||
|
||||
if (showingThreadedList) {
|
||||
int threadCount = cursor.getInt(THREAD_COUNT_COLUMN);
|
||||
int threadCount = messageListItem.getThreadCount();
|
||||
selectedCount += (threadCount > 1) ? threadCount : 1;
|
||||
} else {
|
||||
selectedCount++;
|
||||
|
@ -1457,15 +1443,15 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
|
||||
@Override
|
||||
public void toggleMessageFlagWithAdapterPosition(int adapterPosition) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(adapterPosition);
|
||||
boolean flagged = (cursor.getInt(FLAGGED_COLUMN) == 1);
|
||||
MessageListItem messageListItem = adapter.getItem(adapterPosition);
|
||||
boolean flagged = messageListItem.isStarred();
|
||||
|
||||
setFlag(adapterPosition,Flag.FLAGGED, !flagged);
|
||||
}
|
||||
|
||||
private void toggleMessageSelectWithAdapterPosition(int adapterPosition) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(adapterPosition);
|
||||
long uniqueId = cursor.getLong(uniqueIdColumn);
|
||||
MessageListItem messageListItem = adapter.getItem(adapterPosition);
|
||||
long uniqueId = messageListItem.getUniqueId();
|
||||
|
||||
boolean selected = this.selected.contains(uniqueId);
|
||||
if (!selected) {
|
||||
|
@ -1476,7 +1462,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
|
||||
int selectedCountDelta = 1;
|
||||
if (showingThreadedList) {
|
||||
int threadCount = cursor.getInt(THREAD_COUNT_COLUMN);
|
||||
int threadCount = messageListItem.getThreadCount();
|
||||
if (threadCount > 1) {
|
||||
selectedCountDelta = threadCount;
|
||||
}
|
||||
|
@ -1519,12 +1505,12 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
boolean isBatchRead = false;
|
||||
|
||||
for (int i = 0, end = adapter.getCount(); i < end; i++) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(i);
|
||||
long uniqueId = cursor.getLong(uniqueIdColumn);
|
||||
MessageListItem messageListItem = adapter.getItem(i);
|
||||
long uniqueId = messageListItem.getUniqueId();
|
||||
|
||||
if (selected.contains(uniqueId)) {
|
||||
boolean read = (cursor.getInt(READ_COLUMN) == 1);
|
||||
boolean flagged = (cursor.getInt(FLAGGED_COLUMN) == 1);
|
||||
boolean read = messageListItem.isRead();
|
||||
boolean flagged = messageListItem.isStarred();
|
||||
|
||||
if (!flagged) {
|
||||
isBatchFlag = true;
|
||||
|
@ -1548,15 +1534,15 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
return;
|
||||
}
|
||||
|
||||
Cursor cursor = (Cursor) adapter.getItem(adapterPosition);
|
||||
Account account = preferences.getAccount(cursor.getString(ACCOUNT_UUID_COLUMN));
|
||||
MessageListItem messageListItem = adapter.getItem(adapterPosition);
|
||||
Account account = messageListItem.getAccount();
|
||||
|
||||
if (showingThreadedList && cursor.getInt(THREAD_COUNT_COLUMN) > 1) {
|
||||
long threadRootId = cursor.getLong(THREAD_ROOT_COLUMN);
|
||||
if (showingThreadedList && messageListItem.getThreadCount() > 1) {
|
||||
long threadRootId = messageListItem.getThreadRoot();
|
||||
messagingController.setFlagForThreads(account,
|
||||
Collections.singletonList(threadRootId), flag, newState);
|
||||
} else {
|
||||
long id = cursor.getLong(ID_COLUMN);
|
||||
long id = messageListItem.getDatabaseId();
|
||||
messagingController.setFlag(account, Collections.singletonList(id), flag,
|
||||
newState);
|
||||
}
|
||||
|
@ -1574,22 +1560,21 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
Set<Account> accounts = new HashSet<>();
|
||||
|
||||
for (int position = 0, end = adapter.getCount(); position < end; position++) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(position);
|
||||
long uniqueId = cursor.getLong(uniqueIdColumn);
|
||||
MessageListItem messageListItem = adapter.getItem(position);
|
||||
long uniqueId = messageListItem.getUniqueId();
|
||||
|
||||
if (selected.contains(uniqueId)) {
|
||||
String uuid = cursor.getString(ACCOUNT_UUID_COLUMN);
|
||||
Account account = preferences.getAccount(uuid);
|
||||
Account account = messageListItem.getAccount();
|
||||
accounts.add(account);
|
||||
|
||||
if (showingThreadedList && cursor.getInt(THREAD_COUNT_COLUMN) > 1) {
|
||||
if (showingThreadedList && messageListItem.getThreadCount() > 1) {
|
||||
List<Long> threadRootIdList = threadMap.get(account);
|
||||
if (threadRootIdList == null) {
|
||||
threadRootIdList = new ArrayList<>();
|
||||
threadMap.put(account, threadRootIdList);
|
||||
}
|
||||
|
||||
threadRootIdList.add(cursor.getLong(THREAD_ROOT_COLUMN));
|
||||
threadRootIdList.add(messageListItem.getThreadRoot());
|
||||
} else {
|
||||
List<Long> messageIdList = messageMap.get(account);
|
||||
if (messageIdList == null) {
|
||||
|
@ -1597,7 +1582,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
messageMap.put(account, messageIdList);
|
||||
}
|
||||
|
||||
messageIdList.add(cursor.getLong(ID_COLUMN));
|
||||
messageIdList.add(messageListItem.getDatabaseId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1947,11 +1932,11 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
Set<String> accountUuids = new HashSet<>(maxAccounts);
|
||||
|
||||
for (int position = 0, end = adapter.getCount(); position < end; position++) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(position);
|
||||
long uniqueId = cursor.getLong(uniqueIdColumn);
|
||||
MessageListItem messageListItem = adapter.getItem(position);
|
||||
long uniqueId = messageListItem.getUniqueId();
|
||||
|
||||
if (selected.contains(uniqueId)) {
|
||||
String accountUuid = cursor.getString(ACCOUNT_UUID_COLUMN);
|
||||
String accountUuid = messageListItem.getAccount().getUuid();
|
||||
accountUuids.add(accountUuid);
|
||||
|
||||
if (accountUuids.size() == MessageListFragment.this.accountUuids.length) {
|
||||
|
@ -2226,11 +2211,11 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
}
|
||||
|
||||
private MessageReference getReferenceForPosition(int position) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(position);
|
||||
MessageListItem messageListItem = adapter.getItem(position);
|
||||
|
||||
String accountUuid = cursor.getString(ACCOUNT_UUID_COLUMN);
|
||||
String folderServerId = cursor.getString(FOLDER_SERVER_ID_COLUMN);
|
||||
String messageUid = cursor.getString(UID_COLUMN);
|
||||
String accountUuid = messageListItem.getAccount().getUuid();
|
||||
String folderServerId = messageListItem.getFolderServerId();
|
||||
String messageUid = messageListItem.getMessageUid();
|
||||
return new MessageReference(accountUuid, folderServerId, messageUid, null);
|
||||
}
|
||||
|
||||
|
@ -2253,11 +2238,11 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
|
||||
private int getPosition(MessageReference messageReference) {
|
||||
for (int i = 0, len = adapter.getCount(); i < len; i++) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(i);
|
||||
MessageListItem messageListItem = adapter.getItem(i);
|
||||
|
||||
String accountUuid = cursor.getString(ACCOUNT_UUID_COLUMN);
|
||||
String folderServerId = cursor.getString(FOLDER_SERVER_ID_COLUMN);
|
||||
String uid = cursor.getString(UID_COLUMN);
|
||||
String accountUuid = messageListItem.getAccount().getUuid();
|
||||
String folderServerId = messageListItem.getFolderServerId();
|
||||
String uid = messageListItem.getMessageUid();
|
||||
|
||||
if (accountUuid.equals(messageReference.getAccountUuid()) &&
|
||||
folderServerId.equals(messageReference.getFolderServerId()) &&
|
||||
|
@ -2305,8 +2290,8 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
|
||||
private int getPositionForUniqueId(long uniqueId) {
|
||||
for (int position = 0, end = adapter.getCount(); position < end; position++) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(position);
|
||||
if (cursor.getLong(uniqueIdColumn) == uniqueId) {
|
||||
MessageListItem messageListItem = adapter.getItem(position);
|
||||
if (messageListItem.getUniqueId() == uniqueId) {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|
@ -2319,11 +2304,11 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
return null;
|
||||
}
|
||||
|
||||
Cursor cursor = (Cursor) adapter.getItem(adapterPosition);
|
||||
MessageListItem messageListItem = adapter.getItem(adapterPosition);
|
||||
|
||||
String accountUuid = cursor.getString(ACCOUNT_UUID_COLUMN);
|
||||
String folderServerId = cursor.getString(FOLDER_SERVER_ID_COLUMN);
|
||||
String messageUid = cursor.getString(UID_COLUMN);
|
||||
String accountUuid = messageListItem.getAccount().getUuid();
|
||||
String folderServerId = messageListItem.getFolderServerId();
|
||||
String messageUid = messageListItem.getMessageUid();
|
||||
|
||||
return new MessageReference(accountUuid, folderServerId, messageUid, null);
|
||||
}
|
||||
|
@ -2331,8 +2316,8 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
private List<MessageReference> getCheckedMessages() {
|
||||
List<MessageReference> messages = new ArrayList<>(selected.size());
|
||||
for (int position = 0, end = adapter.getCount(); position < end; position++) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(position);
|
||||
long uniqueId = cursor.getLong(uniqueIdColumn);
|
||||
MessageListItem messageListItem = adapter.getItem(position);
|
||||
long uniqueId = messageListItem.getUniqueId();
|
||||
|
||||
if (selected.contains(uniqueId)) {
|
||||
MessageReference message = getMessageAtPosition(position);
|
||||
|
@ -2357,21 +2342,26 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
}
|
||||
|
||||
public void onToggleFlagged() {
|
||||
onToggleFlag(Flag.FLAGGED, FLAGGED_COLUMN);
|
||||
onToggleFlag(Flag.FLAGGED);
|
||||
}
|
||||
|
||||
public void onToggleRead() {
|
||||
onToggleFlag(Flag.SEEN, READ_COLUMN);
|
||||
onToggleFlag(Flag.SEEN);
|
||||
}
|
||||
|
||||
private void onToggleFlag(Flag flag, int flagColumn) {
|
||||
private void onToggleFlag(Flag flag) {
|
||||
int adapterPosition = getAdapterPositionForSelectedMessage();
|
||||
if (adapterPosition == ListView.INVALID_POSITION) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cursor cursor = (Cursor) adapter.getItem(adapterPosition);
|
||||
boolean flagState = (cursor.getInt(flagColumn) == 1);
|
||||
MessageListItem messageListItem = adapter.getItem(adapterPosition);
|
||||
boolean flagState = false;
|
||||
if (flag == Flag.SEEN) {
|
||||
flagState = messageListItem.isRead();
|
||||
} else if (flag == Flag.FLAGGED) {
|
||||
flagState = messageListItem.isStarred();
|
||||
}
|
||||
setFlag(adapterPosition, flag, !flagState);
|
||||
}
|
||||
|
||||
|
@ -2577,6 +2567,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
cursorValid[loaderId] = true;
|
||||
|
||||
Cursor cursor;
|
||||
int uniqueIdColumn;
|
||||
if (cursors.length > 1) {
|
||||
cursor = new MergeCursorWithUniqueId(cursors, getComparator());
|
||||
uniqueIdColumn = cursor.getColumnIndex("_id");
|
||||
|
@ -2584,11 +2575,13 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
cursor = data;
|
||||
uniqueIdColumn = ID_COLUMN;
|
||||
}
|
||||
adapter.setUniqueIdColumn(uniqueIdColumn);
|
||||
|
||||
List<MessageListItem> messageListItems = messageListExtractor.extractMessageList(cursor, uniqueIdColumn);
|
||||
|
||||
if (isThreadDisplay) {
|
||||
if (cursor.moveToFirst()) {
|
||||
title = cursor.getString(SUBJECT_COLUMN);
|
||||
if (!messageListItems.isEmpty()) {
|
||||
MessageListItem messageListItem = messageListItems.get(0);
|
||||
title = messageListItem.getSubject();
|
||||
if (!TextUtils.isEmpty(title)) {
|
||||
title = Utility.stripSubject(title);
|
||||
}
|
||||
|
@ -2601,12 +2594,12 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
}
|
||||
}
|
||||
|
||||
cleanupSelected(cursor);
|
||||
cleanupSelected(messageListItems);
|
||||
adapter.setSelected(selected);
|
||||
|
||||
updateContextMenu(cursor);
|
||||
updateContextMenu(messageListItems);
|
||||
|
||||
adapter.swapCursor(cursor);
|
||||
adapter.setMessages(messageListItems);
|
||||
|
||||
resetActionMode();
|
||||
computeBatchDirection();
|
||||
|
@ -2648,14 +2641,13 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
/**
|
||||
* Close the context menu when the message it was opened for is no longer in the message list.
|
||||
*/
|
||||
private void updateContextMenu(Cursor cursor) {
|
||||
private void updateContextMenu(List<MessageListItem> messageListItems) {
|
||||
if (contextMenuUniqueId == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
|
||||
long uniqueId = cursor.getLong(uniqueIdColumn);
|
||||
if (uniqueId == contextMenuUniqueId) {
|
||||
for (MessageListItem messageListItem : messageListItems) {
|
||||
if (messageListItem.getUniqueId() == contextMenuUniqueId) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2667,14 +2659,14 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
}
|
||||
}
|
||||
|
||||
private void cleanupSelected(Cursor cursor) {
|
||||
private void cleanupSelected(List<MessageListItem> messageListItems) {
|
||||
if (selected.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<Long> selected = new HashSet<>();
|
||||
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
|
||||
long uniqueId = cursor.getLong(uniqueIdColumn);
|
||||
for (MessageListItem messageListItem : messageListItems) {
|
||||
long uniqueId = messageListItem.getUniqueId();
|
||||
if (this.selected.contains(uniqueId)) {
|
||||
selected.add(uniqueId);
|
||||
}
|
||||
|
@ -2727,11 +2719,11 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
|
||||
selectedCount = 0;
|
||||
for (int i = 0, end = adapter.getCount(); i < end; i++) {
|
||||
Cursor cursor = (Cursor) adapter.getItem(i);
|
||||
long uniqueId = cursor.getLong(uniqueIdColumn);
|
||||
MessageListItem messageListItem = adapter.getItem(i);
|
||||
long uniqueId = messageListItem.getUniqueId();
|
||||
|
||||
if (selected.contains(uniqueId)) {
|
||||
int threadCount = cursor.getInt(THREAD_COUNT_COLUMN);
|
||||
int threadCount = messageListItem.getThreadCount();
|
||||
selectedCount += (threadCount > 1) ? threadCount : 1;
|
||||
}
|
||||
}
|
||||
|
@ -2740,12 +2732,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
|
|||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
selected.clear();
|
||||
adapter.swapCursor(null);
|
||||
}
|
||||
|
||||
private Account getAccountFromCursor(Cursor cursor) {
|
||||
String accountUuid = cursor.getString(ACCOUNT_UUID_COLUMN);
|
||||
return preferences.getAccount(accountUuid);
|
||||
adapter.setMessages(Collections.<MessageListItem>emptyList());
|
||||
}
|
||||
|
||||
void remoteSearchFinished() {
|
||||
|
|
|
@ -11,7 +11,11 @@ class MessageListExtractor(
|
|||
private val preferences: Preferences,
|
||||
private val messageHelper: MessageHelper
|
||||
) {
|
||||
fun extractMessageListItem(cursor: Cursor, uniqueIdColumn: Int): MessageListItem {
|
||||
fun extractMessageList(cursor: Cursor, uniqueIdColumn: Int): List<MessageListItem> {
|
||||
return cursor.map { extractMessageListItem(it, uniqueIdColumn) }
|
||||
}
|
||||
|
||||
private fun extractMessageListItem(cursor: Cursor, uniqueIdColumn: Int): MessageListItem {
|
||||
val position = cursor.position
|
||||
val accountUuid = cursor.getString(MLFProjectionInfo.ACCOUNT_UUID_COLUMN)
|
||||
val account = preferences.getAccount(accountUuid)
|
||||
|
@ -41,6 +45,9 @@ class MessageListExtractor(
|
|||
val uniqueId = cursor.getLong(uniqueIdColumn)
|
||||
val folderServerId = cursor.getString(MLFProjectionInfo.FOLDER_SERVER_ID_COLUMN)
|
||||
val messageUid = cursor.getString(MLFProjectionInfo.UID_COLUMN)
|
||||
val databaseId = cursor.getLong(MLFProjectionInfo.ID_COLUMN)
|
||||
val senderAddress = fromAddresses.getOrNull(0)?.address
|
||||
val threadRoot = cursor.getLong(MLFProjectionInfo.THREAD_ROOT_COLUMN)
|
||||
|
||||
return MessageListItem(
|
||||
position,
|
||||
|
@ -62,7 +69,10 @@ class MessageListExtractor(
|
|||
hasAttachments,
|
||||
uniqueId,
|
||||
folderServerId,
|
||||
messageUid
|
||||
messageUid,
|
||||
databaseId,
|
||||
senderAddress,
|
||||
threadRoot
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -93,4 +103,11 @@ class MessageListExtractor(
|
|||
private fun Cursor.getIntIfColumnPresent(columnIndex: Int): Int? {
|
||||
return if (columnCount >= columnIndex + 1) getInt(columnIndex) else null
|
||||
}
|
||||
|
||||
private inline fun <T> Cursor.map(block: (Cursor) -> T): List<T> {
|
||||
return List(count) { index ->
|
||||
moveToPosition(index)
|
||||
block(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,5 +23,8 @@ data class MessageListItem(
|
|||
val hasAttachments: Boolean,
|
||||
val uniqueId: Long,
|
||||
val folderServerId: String,
|
||||
val messageUid: String
|
||||
val messageUid: String,
|
||||
val databaseId: Long,
|
||||
val senderAddress: String?,
|
||||
val threadRoot: Long
|
||||
)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package com.fsck.k9.fragment
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.database.MatrixCursor
|
||||
import android.text.Spannable
|
||||
import android.text.style.AbsoluteSizeSpan
|
||||
import android.view.ContextThemeWrapper
|
||||
|
@ -17,49 +15,31 @@ import com.fsck.k9.Account
|
|||
import com.fsck.k9.FontSizes
|
||||
import com.fsck.k9.FontSizes.FONT_DEFAULT
|
||||
import com.fsck.k9.FontSizes.LARGE
|
||||
import com.fsck.k9.Preferences
|
||||
import com.fsck.k9.RobolectricTest
|
||||
import com.fsck.k9.contacts.ContactPictureLoader
|
||||
import com.fsck.k9.helper.MessageHelper
|
||||
import com.fsck.k9.mail.Address
|
||||
import com.fsck.k9.provider.EmailProvider.MessageColumns
|
||||
import com.fsck.k9.provider.EmailProvider.SpecialColumns
|
||||
import com.fsck.k9.provider.EmailProvider.ThreadColumns
|
||||
import com.fsck.k9.textString
|
||||
import com.fsck.k9.ui.ContactBadge
|
||||
import com.fsck.k9.ui.R
|
||||
import com.fsck.k9.ui.messagelist.MessageListAppearance
|
||||
import com.fsck.k9.ui.messagelist.MessageListExtractor
|
||||
import com.nhaarman.mockito_kotlin.anyArray
|
||||
import com.nhaarman.mockito_kotlin.doReturn
|
||||
import com.nhaarman.mockito_kotlin.eq
|
||||
import com.fsck.k9.ui.messagelist.MessageListItem
|
||||
import com.nhaarman.mockito_kotlin.mock
|
||||
import com.nhaarman.mockito_kotlin.whenever
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.mockito.AdditionalMatchers.aryEq
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
|
||||
private const val SOME_ACCOUNT_UUID = "6b84207b-25de-4dab-97c3-953bbf03fec6"
|
||||
private const val DISPLAY_NAME = "Display Name"
|
||||
private const val FIRST_LINE_DEFAULT_FONT_SIZE = 18f
|
||||
private const val SECOND_LINE_DEFAULT_FONT_SIZE = 14f
|
||||
private const val DATE_DEFAULT_FONT_SIZE = 14f
|
||||
|
||||
class MessageListAdapterTest : RobolectricTest() {
|
||||
val context: Context = ContextThemeWrapper(RuntimeEnvironment.application, R.style.Theme_K9_Light)
|
||||
val testAccount = Account(SOME_ACCOUNT_UUID)
|
||||
|
||||
val messageHelper: MessageHelper = mock {
|
||||
on { getDisplayName(eq(testAccount), anyArray(), anyArray()) } doReturn DISPLAY_NAME
|
||||
}
|
||||
val preferences: Preferences = mock {
|
||||
on { getAccount(SOME_ACCOUNT_UUID) } doReturn testAccount
|
||||
}
|
||||
val contactsPictureLoader: ContactPictureLoader = mock()
|
||||
val listItemListener: MessageListItemActionListener = mock()
|
||||
|
||||
|
@ -100,21 +80,21 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun withStarsAndFlaggedMessage_shouldCheckStarCheckBox() {
|
||||
fun withStarsAndStarredMessage_shouldCheckStarCheckBox() {
|
||||
val adapter = createAdapter(stars = true)
|
||||
val cursor = createCursor(flagged = 1)
|
||||
val messageListItem = createMessageListItem(isStarred = true)
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertTrue(view.starView.isChecked)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun withStarsAndUnflaggedMessage_shouldNotCheckStarCheckBox() {
|
||||
fun withStarsAndUnstarredMessage_shouldNotCheckStarCheckBox() {
|
||||
val adapter = createAdapter(stars = true)
|
||||
val cursor = createCursor(flagged = 0)
|
||||
val messageListItem = createMessageListItem(isStarred = false)
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertFalse(view.starView.isChecked)
|
||||
}
|
||||
|
@ -140,9 +120,9 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
@Test
|
||||
fun withThreadCountOne_shouldHideThreadCountView() {
|
||||
val adapter = createAdapter()
|
||||
val cursor = createCursor(threadCount = 1)
|
||||
val messageListItem = createMessageListItem(threadCount = 1)
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertTrue(view.threadCountView.isGone)
|
||||
}
|
||||
|
@ -150,9 +130,9 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
@Test
|
||||
fun withThreadCountGreaterOne_shouldShowThreadCountViewWithExpectedValue() {
|
||||
val adapter = createAdapter()
|
||||
val cursor = createCursor(threadCount = 13)
|
||||
val messageListItem = createMessageListItem(threadCount = 13)
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertTrue(view.threadCountView.isVisible)
|
||||
assertEquals("13", view.threadCountView.textString)
|
||||
|
@ -161,9 +141,9 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
@Test
|
||||
fun withoutSenderAboveSubject_shouldShowSubjectInFirstLine() {
|
||||
val adapter = createAdapter(senderAboveSubject = false)
|
||||
val cursor = createCursor(subject = "Subject")
|
||||
val messageListItem = createMessageListItem(subject = "Subject")
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertEquals("Subject", view.firstLineView.textString)
|
||||
}
|
||||
|
@ -171,37 +151,39 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
@Test
|
||||
fun withSenderAboveSubject_shouldShowDisplayNameInFirstLine() {
|
||||
val adapter = createAdapter(senderAboveSubject = true)
|
||||
val messageListItem = createMessageListItem(displayName = "Display Name")
|
||||
|
||||
val view = adapter.createAndBindView()
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertEquals(DISPLAY_NAME, view.firstLineView.textString)
|
||||
assertEquals("Display Name", view.firstLineView.textString)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun withoutSenderAboveSubjectAndZeroPreviewLines_shouldShowDisplayNameInSecondLine() {
|
||||
val adapter = createAdapter(senderAboveSubject = false, previewLines = 0)
|
||||
val messageListItem = createMessageListItem(displayName = "Display Name")
|
||||
|
||||
val view = adapter.createAndBindView()
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertEquals(DISPLAY_NAME, view.secondLineView.textString)
|
||||
assertEquals("Display Name", view.secondLineView.textString)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun withoutSenderAboveSubjectAndPreviewLines_shouldShowDisplayNameAndPreviewInSecondLine() {
|
||||
val adapter = createAdapter(senderAboveSubject = false, previewLines = 1)
|
||||
val cursor = createCursor(preview = "Preview")
|
||||
val messageListItem = createMessageListItem(displayName = "Display Name", previewText = "Preview")
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertEquals(secondLine(DISPLAY_NAME, "Preview"), view.secondLineView.textString)
|
||||
assertEquals(secondLine("Display Name", "Preview"), view.secondLineView.textString)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun withSenderAboveSubjectAndZeroPreviewLines_shouldShowSubjectInSecondLine() {
|
||||
val adapter = createAdapter(senderAboveSubject = true, previewLines = 0)
|
||||
val cursor = createCursor(subject = "Subject")
|
||||
val messageListItem = createMessageListItem(subject = "Subject")
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertEquals("Subject", view.secondLineView.textString)
|
||||
}
|
||||
|
@ -209,9 +191,9 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
@Test
|
||||
fun withSenderAboveSubjectAndPreviewLines_shouldShowSubjectAndPreviewInSecondLine() {
|
||||
val adapter = createAdapter(senderAboveSubject = true, previewLines = 1)
|
||||
val cursor = createCursor(subject = "Subject", preview = "Preview")
|
||||
val messageListItem = createMessageListItem(subject = "Subject", previewText = "Preview")
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertEquals(secondLine("Subject", "Preview"), view.secondLineView.textString)
|
||||
}
|
||||
|
@ -220,10 +202,9 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
@Ignore("Currently failing. See issue #4152.")
|
||||
fun withSenderAboveSubjectAndMessageToMe_shouldDisplayIndicatorInFirstLine() {
|
||||
val adapter = createAdapter(senderAboveSubject = true)
|
||||
val cursor = createCursor(to = "to@domain.example")
|
||||
configureMessageHelperMockToMe("to@domain.example")
|
||||
val messageListItem = createMessageListItem(toMe = true)
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertTrue(view.firstLineView.containsToMeIndicator())
|
||||
}
|
||||
|
@ -232,10 +213,9 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
@Ignore("Currently failing. See issue #4152.")
|
||||
fun withSenderAboveSubjectAndMessageCcMe_shouldDisplayIndicatorInFirstLine() {
|
||||
val adapter = createAdapter(senderAboveSubject = true)
|
||||
val cursor = createCursor(cc = "cc@domain.example")
|
||||
configureMessageHelperMockToMe("cc@domain.example")
|
||||
val messageListItem = createMessageListItem(ccMe = true)
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertTrue(view.firstLineView.containsCcMeIndicator())
|
||||
}
|
||||
|
@ -243,10 +223,9 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
@Test
|
||||
fun withoutSenderAboveSubjectAndMessageToMe_shouldDisplayIndicatorInSecondLine() {
|
||||
val adapter = createAdapter(senderAboveSubject = false)
|
||||
val cursor = createCursor(to = "to@domain.example")
|
||||
configureMessageHelperMockToMe("to@domain.example")
|
||||
val messageListItem = createMessageListItem(toMe = true)
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertTrue(view.secondLineView.containsToMeIndicator())
|
||||
}
|
||||
|
@ -254,30 +233,29 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
@Test
|
||||
fun withoutSenderAboveSubjectAndMessageCcMe_shouldDisplayIndicatorInSecondLine() {
|
||||
val adapter = createAdapter(senderAboveSubject = false)
|
||||
val cursor = createCursor(cc = "cc@domain.example")
|
||||
configureMessageHelperMockToMe("cc@domain.example")
|
||||
val messageListItem = createMessageListItem(ccMe = true)
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertTrue(view.secondLineView.containsCcMeIndicator())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun withAttachmentCountZero_shouldHideAttachmentCountView() {
|
||||
fun withoutAttachments_shouldHideAttachmentCountView() {
|
||||
val adapter = createAdapter()
|
||||
val cursor = createCursor(attachmentCount = 0)
|
||||
val messageListItem = createMessageListItem(hasAttachments = false)
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertTrue(view.attachmentCountView.isGone)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun withNonZeroAttachmentCount_shouldShowAttachmentCountView() {
|
||||
fun withAttachments_shouldShowAttachmentCountView() {
|
||||
val adapter = createAdapter()
|
||||
val cursor = createCursor(attachmentCount = 3)
|
||||
val messageListItem = createMessageListItem(hasAttachments = true)
|
||||
|
||||
val view = adapter.createAndBindView(cursor)
|
||||
val view = adapter.createAndBindView(messageListItem)
|
||||
|
||||
assertTrue(view.attachmentCountView.isVisible)
|
||||
}
|
||||
|
@ -420,11 +398,6 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
assertEquals(22f, view.secondLineView.textSize)
|
||||
}
|
||||
|
||||
fun configureMessageHelperMockToMe(address: String) {
|
||||
val addresses = Address.parse(address)
|
||||
whenever(messageHelper.toMe(eq(testAccount), aryEq(addresses))).thenReturn(true)
|
||||
}
|
||||
|
||||
fun createFontSizes(
|
||||
subject: Int = FONT_DEFAULT,
|
||||
sender: Int = FONT_DEFAULT,
|
||||
|
@ -466,66 +439,66 @@ class MessageListAdapterTest : RobolectricTest() {
|
|||
res = context.resources,
|
||||
layoutInflater = LayoutInflater.from(context),
|
||||
contactsPictureLoader = contactsPictureLoader,
|
||||
messageListExtractor = MessageListExtractor(preferences, messageHelper),
|
||||
listItemListener = listItemListener,
|
||||
appearance = appearance
|
||||
)
|
||||
}
|
||||
|
||||
fun createCursor(
|
||||
id: Long = 0L,
|
||||
uid: String = "irrelevant",
|
||||
internalDate: Long = 0L,
|
||||
fun createMessageListItem(
|
||||
position: Int = 0,
|
||||
account: Account = Account(SOME_ACCOUNT_UUID),
|
||||
subject: String = "irrelevant",
|
||||
date: Long = 0L,
|
||||
sender: String = "irrelevant@domain.example",
|
||||
to: String = "irrelevant@domain.example",
|
||||
cc: String = "irrelevant@domain.example",
|
||||
read: Int = 0,
|
||||
flagged: Int = 0,
|
||||
answered: Int = 0,
|
||||
forwarded: Int = 0,
|
||||
attachmentCount: Int = 0,
|
||||
folderId: String = "irrelevant",
|
||||
previewType: String = "text",
|
||||
preview: String = "irrelevant",
|
||||
threadRoot: Long = 0L,
|
||||
accountUuid: String = SOME_ACCOUNT_UUID,
|
||||
threadCount: Int = 0,
|
||||
messageDate: Long = 0L,
|
||||
displayName: CharSequence = "irrelevant",
|
||||
counterPartyAddress: Address? = Address.parse("irrelevant@domain.example").first(),
|
||||
fromMe: Boolean = false,
|
||||
toMe: Boolean = false,
|
||||
ccMe: Boolean = false,
|
||||
previewText: String = "irrelevant",
|
||||
isMessageEncrypted: Boolean = false,
|
||||
isRead: Boolean = false,
|
||||
isStarred: Boolean = false,
|
||||
isAnswered: Boolean = false,
|
||||
isForwarded: Boolean = false,
|
||||
hasAttachments: Boolean = false,
|
||||
uniqueId: Long = 0L,
|
||||
folderServerId: String = "irrelevant",
|
||||
threadCount: Int = 0
|
||||
): Cursor {
|
||||
val mapping = mapOf(
|
||||
MessageColumns.ID to id,
|
||||
MessageColumns.UID to uid,
|
||||
MessageColumns.INTERNAL_DATE to internalDate,
|
||||
MessageColumns.SUBJECT to subject,
|
||||
MessageColumns.DATE to date,
|
||||
MessageColumns.SENDER_LIST to Address.pack(Address.parse(sender)),
|
||||
MessageColumns.TO_LIST to Address.pack(Address.parse(to)),
|
||||
MessageColumns.CC_LIST to Address.pack(Address.parse(cc)),
|
||||
MessageColumns.READ to read,
|
||||
MessageColumns.FLAGGED to flagged,
|
||||
MessageColumns.ANSWERED to answered,
|
||||
MessageColumns.FORWARDED to forwarded,
|
||||
MessageColumns.ATTACHMENT_COUNT to attachmentCount,
|
||||
MessageColumns.FOLDER_ID to folderId,
|
||||
MessageColumns.PREVIEW_TYPE to previewType,
|
||||
MessageColumns.PREVIEW to preview,
|
||||
ThreadColumns.ROOT to threadRoot,
|
||||
SpecialColumns.ACCOUNT_UUID to accountUuid,
|
||||
SpecialColumns.FOLDER_SERVER_ID to folderServerId,
|
||||
SpecialColumns.THREAD_COUNT to threadCount
|
||||
messageUid: String = "irrelevant",
|
||||
databaseId: Long = 0L,
|
||||
senderAddress: String? = null,
|
||||
threadRoot: Long = 0L
|
||||
): MessageListItem {
|
||||
return MessageListItem(
|
||||
position,
|
||||
account,
|
||||
subject,
|
||||
threadCount,
|
||||
messageDate,
|
||||
displayName,
|
||||
counterPartyAddress,
|
||||
fromMe,
|
||||
toMe,
|
||||
ccMe,
|
||||
previewText,
|
||||
isMessageEncrypted,
|
||||
isRead,
|
||||
isStarred,
|
||||
isAnswered,
|
||||
isForwarded,
|
||||
hasAttachments,
|
||||
uniqueId,
|
||||
folderServerId,
|
||||
messageUid,
|
||||
databaseId,
|
||||
senderAddress,
|
||||
threadRoot
|
||||
)
|
||||
return MatrixCursor(mapping.keys.toTypedArray())
|
||||
.apply { addRow(mapping.values.toTypedArray()) }
|
||||
.also { it.moveToFirst() }
|
||||
}
|
||||
|
||||
fun MessageListAdapter.createAndBindView(cursor: Cursor = createCursor()): View {
|
||||
val view = newView(context, cursor, LinearLayout(context))
|
||||
bindView(view, context, cursor)
|
||||
|
||||
return view
|
||||
fun MessageListAdapter.createAndBindView(item: MessageListItem = createMessageListItem()): View {
|
||||
messages = listOf(item)
|
||||
return getView(0, null, LinearLayout(context))
|
||||
}
|
||||
|
||||
fun secondLine(senderOrSubject: String, preview: String) = "$senderOrSubject $preview"
|
||||
|
|
Loading…
Reference in a new issue