/*
 * Derived from com.android.mms.ui.ConversationList
 * (tag android-4.4.4_r2.0.1)
 */

package ca.bmaupin.merge.sms.ui;

import ca.bmaupin.merge.sms.R;
import ca.bmaupin.merge.sms.data.Contact;
import ca.bmaupin.merge.sms.data.Conversation;
import android.app.ListActivity;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SqliteWrapper;
import android.os.Bundle;
import android.widget.TextView;

public class ConversationList extends ListActivity {
    private static final int THREAD_LIST_QUERY_TOKEN       = 1701;
	
    private ThreadListQueryHandler mQueryHandler;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.conversation_list_screen);
    }
    
    @Override
    protected void onStart() {
        super.onStart();

        startAsyncQuery();

        // we invalidate the contact cache here because we want to get updated presence
        // and any contact changes. We don't invalidate the cache by observing presence and contact
        // changes (since that's too untargeted), so as a tradeoff we do it here.
        // If we're in the middle of the app initialization where we're loading the conversation
        // threads, don't invalidate the cache because we're in the process of building it.
        // TODO: think of a better way to invalidate cache more surgically or based on actual
        // TODO: changes we care about
        if (!Conversation.loadingThreads()) {
            Contact.invalidateCache();
        }
    }
    
    private void startAsyncQuery() {
        try {
            ((TextView)(getListView().getEmptyView())).setText(R.string.loading_conversations);

            Conversation.startQueryForAll(mQueryHandler, THREAD_LIST_QUERY_TOKEN);
        } catch (SQLiteException e) {
            SqliteWrapper.checkSQLiteException(this, e);
        }
    }
    
    private final class ThreadListQueryHandler extends AsyncQueryHandler {
        public ThreadListQueryHandler(ContentResolver contentResolver) {
            super(contentResolver);
        }
    }
}

@@ -117,16 +117,91 @@
 ms.ui;%0A%0A
+import com.android.mms.MmsConfig;%0Aimport com.android.mms.util.DraftCache;%0A%0A
 import c
@@ -223,16 +223,16 @@
 .sms.R;%0A
-
 import c
@@ -423,24 +423,56 @@
 ntResolver;%0A
+import android.database.Cursor;%0A
 import andro
@@ -579,16 +579,74 @@
 Bundle;%0A
+import android.view.View;%0Aimport android.widget.ListView;%0A
 import a
@@ -842,16 +842,66 @@
 andler;%0A
+    private ConversationListAdapter mListAdapter;%0A
 %09%0A    @O
@@ -1069,16 +1069,1190 @@
 creen);%0A
+        %0A        ListView listView = getListView();%0A        %0A        // Tell the list view which view to display when the list is empty%0A        listView.setEmptyView(findViewById(R.id.empty));%0A%0A        initListAdapter();%0A    %7D%0A    %0A    @Override%0A    public void onPause() %7B%0A        super.onPause();%0A%0A        // Don't listen for changes while we're paused.%0A        mListAdapter.setOnContentChangedListener(null);%0A    %7D%0A    %0A    @Override%0A    protected void onResume() %7B%0A        super.onResume();%0A%0A        mListAdapter.setOnContentChangedListener(mContentChangedListener);%0A    %7D%0A    %0A    private final ConversationListAdapter.OnContentChangedListener mContentChangedListener =%0A            new ConversationListAdapter.OnContentChangedListener() %7B%0A            @Override%0A            public void onContentChanged(ConversationListAdapter adapter) %7B%0A                startAsyncQuery();%0A            %7D%0A        %7D;%0A%0A    private void initListAdapter() %7B%0A        mListAdapter = new ConversationListAdapter(this, null);%0A        mListAdapter.setOnContentChangedListener(mContentChangedListener);%0A        setListAdapter(mListAdapter);%0A        getListView().setRecyclerListener(mListAdapter);%0A
     %7D%0A  
@@ -3026,24 +3026,24 @@
 ateCache();%0A
-
         %7D%0A  
@@ -3043,32 +3043,375 @@
    %7D%0A    %7D%0A    %0A
+    @Override%0A    protected void onStop() %7B%0A        super.onStop();%0A%0A        // Close the cursor in the ListAdapter if the activity stopped.%0A        Cursor cursor = mListAdapter.getCursor();%0A        %0A        if (cursor != null && !cursor.isClosed()) %7B%0A            cursor.close();%0A        %7D%0A%0A        mListAdapter.changeCursor(null);%0A    %7D%0A    %0A
     private void

Add more basic elements to handle the activity lifecycle