/* * Copyright (C) 2008 Torgny Bjers * * 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. */ package com.xorcode.andtweet; import android.content.ContentUris; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ContextMenu.ContextMenuInfo; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.LinearLayout; import android.widget.SimpleCursorAdapter; import android.widget.Toast; import com.xorcode.andtweet.data.AndTweetDatabase; import com.xorcode.andtweet.data.AndTweetPreferences; import com.xorcode.andtweet.data.PagedCursorAdapter; import com.xorcode.andtweet.data.SearchableCursorAdapter; import com.xorcode.andtweet.data.TweetBinder; import com.xorcode.andtweet.data.AndTweetDatabase.Users; /** * @author torgny.bjers * */ public class MessageListActivity extends TimelineActivity { private static final String TAG = MessageListActivity.class.getSimpleName(); // Context menu items public static final int CONTEXT_MENU_ITEM_REPLY = Menu.FIRST + 3; public static final int CONTEXT_MENU_ITEM_STAR = Menu.FIRST + 4; public static final int CONTEXT_MENU_ITEM_DIRECT_MESSAGE = Menu.FIRST + 5; public static final int CONTEXT_MENU_ITEM_UNFOLLOW = Menu.FIRST + 6; public static final int CONTEXT_MENU_ITEM_BLOCK = Menu.FIRST + 7; public static final int CONTEXT_MENU_ITEM_RETWEET = Menu.FIRST + 8; public static final int CONTEXT_MENU_ITEM_PROFILE = Menu.FIRST + 9; // TODO: get rid of this variable just like in TweetListActivity... private int mCurrentPage = 1; // Database cursors private Cursor mFriendsCursor; // Table columns to use for the direct messages data private static final String[] PROJECTION = new String[] { AndTweetDatabase.DirectMessages._ID, AndTweetDatabase.DirectMessages.AUTHOR_ID, AndTweetDatabase.DirectMessages.MESSAGE, AndTweetDatabase.DirectMessages.SENT_DATE }; // Table columns to use for the user data private static final String[] FRIENDS_PROJECTION = new String[] { Users._ID, Users.AUTHOR_ID }; /** * Called when the activity is first created. * * @see android.app.Activity#onCreate(android.os.Bundle) * * @param savedInstanceState */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Log.isLoggable(AndTweetService.APPTAG, Log.VERBOSE)) { Log.v(TAG, "onCreate"); } if (savedInstanceState != null) { if (savedInstanceState.containsKey(BUNDLE_KEY_IS_LOADING)) { mIsLoading = savedInstanceState.getBoolean(BUNDLE_KEY_IS_LOADING); } } final Intent intent = getIntent(); intent.setData(AndTweetDatabase.DirectMessages.CONTENT_URI); findViewById(R.id.tweetlist_info).setVisibility(View.GONE); findViewById(R.id.tweetlist_editor).setVisibility(View.GONE); // Create list footer for loading messages mListFooter = new LinearLayout(getApplicationContext()); mListFooter.setClickable(false); getListView().addFooterView(mListFooter); LayoutInflater inflater = LayoutInflater.from(getApplicationContext()); View tv = inflater.inflate(R.layout.item_loading, null); mListFooter.addView(tv, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); mListFooter.setVisibility(View.INVISIBLE); getListView().setOnScrollListener(this); initUI(); } @Override public boolean onSearchRequested() { Bundle appDataBundle = new Bundle(); appDataBundle.putParcelable("content_uri", AndTweetDatabase.DirectMessages.CONTENT_URI); startSearch(null, false, appDataBundle, false); return true; } @Override protected void onResume() { super.onResume(); findViewById(R.id.tweetlist_info).setVisibility(View.GONE); findViewById(R.id.tweetlist_editor).setVisibility(View.GONE); } @Override protected void onStart() { super.onStart(); mCursor = getContentResolver().query(getIntent().getData(), PROJECTION, null, null, AndTweetDatabase.DirectMessages.DEFAULT_SORT_ORDER + " LIMIT 0," + (mCurrentPage * PAGE_SIZE)); mFriendsCursor = getContentResolver().query(Users.CONTENT_URI, FRIENDS_PROJECTION, null, null, Users.DEFAULT_SORT_ORDER); createAdapters(); setProgressBarIndeterminateVisibility(mIsLoading); bindToService(); } @Override protected void onStop() { super.onStop(); mCursor.close(); mFriendsCursor.close(); disconnectService(); } @Override public void onDestroy() { super.onDestroy(); disconnectService(); } @Override protected void onSaveInstanceState(Bundle outState) { outState.putBoolean(BUNDLE_KEY_IS_LOADING, mIsLoading); super.onSaveInstanceState(outState); } @Override public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, view, menuInfo); // Add menu items //menu.add(0, CONTEXT_MENU_ITEM_REPLY, 0, R.string.menu_item_reply); //menu.add(0, CONTEXT_MENU_ITEM_RETWEET, 1, R.string.menu_item_retweet); //menu.add(0, CONTEXT_MENU_ITEM_STAR, 2, R.string.menu_item_star); //menu.add(0, CONTEXT_MENU_ITEM_DIRECT_MESSAGE, 3, R.string.menu_item_direct_message); //menu.add(0, CONTEXT_MENU_ITEM_PROFILE, 4, R.string.menu_item_view_profile); //menu.add(0, CONTEXT_MENU_ITEM_UNFOLLOW, 5, R.string.menu_item_unfollow); //menu.add(0, CONTEXT_MENU_ITEM_BLOCK, 6, R.string.menu_item_block); } @Override public boolean onContextItemSelected(MenuItem item) { super.onContextItemSelected(item); AdapterView.AdapterContextMenuInfo info; try { info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); } catch (ClassCastException e) { Log.e(TAG, "bad menuInfo", e); return false; } switch (item.getItemId()) { case CONTEXT_MENU_ITEM_REPLY: Uri uri = ContentUris.withAppendedId(AndTweetDatabase.DirectMessages.CONTENT_URI, info.id); Cursor c = getContentResolver().query(uri, new String[] { AndTweetDatabase.DirectMessages._ID, AndTweetDatabase.DirectMessages.AUTHOR_ID }, null, null, null); try { c.moveToFirst(); } catch (Exception e) { Log.e(TAG, "onContextItemSelected: " + e.toString()); } finally { if (c != null && !c.isClosed()) c.close(); } return true; case CONTEXT_MENU_ITEM_STAR: case CONTEXT_MENU_ITEM_RETWEET: case CONTEXT_MENU_ITEM_UNFOLLOW: case CONTEXT_MENU_ITEM_BLOCK: case CONTEXT_MENU_ITEM_DIRECT_MESSAGE: case CONTEXT_MENU_ITEM_PROFILE: Toast.makeText(this, R.string.unimplemented, Toast.LENGTH_SHORT).show(); return true; } return false; } /** * Initialize UI */ @Override protected void initUI() { super.initUI(); } private void createAdapters() { int listItemId = R.layout.messagelist_item; if (AndTweetPreferences.getDefaultSharedPreferences().getBoolean("appearance_use_avatars", false)) { listItemId = R.layout.messagelist_item_avatar; } PagedCursorAdapter directMessagesAdapter = new PagedCursorAdapter( MessageListActivity.this, listItemId, mCursor, new String[] { AndTweetDatabase.DirectMessages.AUTHOR_ID, AndTweetDatabase.DirectMessages.MESSAGE, AndTweetDatabase.DirectMessages.SENT_DATE }, new int[] { R.id.tweet_screen_name, R.id.tweet_message, R.id.tweet_sent }, AndTweetDatabase.DirectMessages.CONTENT_URI, PROJECTION, AndTweetDatabase.DirectMessages.DEFAULT_SORT_ORDER ); directMessagesAdapter.setViewBinder(new TweetBinder()); setListAdapter(directMessagesAdapter); SearchableCursorAdapter friendsAdapter = new SearchableCursorAdapter( this, android.R.layout.simple_dropdown_item_1line, mFriendsCursor, new String[] { Users.AUTHOR_ID }, new int[] { android.R.id.text1 }, Users.CONTENT_URI, FRIENDS_PROJECTION, Users.DEFAULT_SORT_ORDER ); friendsAdapter.setStringConversionColumn(mFriendsCursor.getColumnIndexOrThrow(Users.AUTHOR_ID)); } /** * Listener that checks for clicks on the main list view. * * @param adapterView * @param view * @param position * @param id */ @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { // TODO: This class is not fully implemented // Compare it to the TweetListActivity Toast.makeText(this, R.string.unimplemented, Toast.LENGTH_SHORT).show(); return; // if (id <= 0) { // return; // } // Uri uri = ContentUris.withAppendedId(AndTweetDatabase.DirectMessages.CONTENT_URI, id); // String action = getIntent().getAction(); // if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action)) { // setResult(RESULT_OK, new Intent().setData(uri)); // } else { // /** // * TODO: Such Activity is not implemented, resulting in the error: // * ERROR/AndroidRuntime(944): // * android.content.ActivityNotFoundException: No Activity found to handle Intent // * { action=android.intent.action.VIEW // * data=content://com.xorcode.andtweet/directmessages/944723647 // */ // startActivity(new Intent(Intent.ACTION_VIEW, uri)); // } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mTotalItemCount = totalItemCount; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (mIsLoading) { return; } switch (scrollState) { case SCROLL_STATE_IDLE: if (view.getLastVisiblePosition() >= mTotalItemCount - 1 && mTotalItemCount > 0) { if (getListView().getFooterViewsCount() == 1 && !mIsLoading) { mIsLoading = true; setProgressBarIndeterminateVisibility(true); mListFooter.setVisibility(View.VISIBLE); Thread thread = new Thread(mLoadListItems); thread.start(); } } break; case SCROLL_STATE_TOUCH_SCROLL: break; case SCROLL_STATE_FLING: break; } } /** * Message handler for messages from threads. */ protected Handler mHandler = new Handler() { /** * Message handler * * @param msg */ @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_DIRECT_MESSAGES_CHANGED: int numTweets = msg.arg1; if (numTweets > 0) { mNM.cancelAll(); } break; case MSG_DATA_LOADING: mIsLoading = msg.arg1 == 1 ? true : false; setProgressBarIndeterminateVisibility(mIsLoading); break; case MSG_AUTHENTICATION_ERROR: switch (msg.arg1) { case MSG_MANUAL_RELOAD: setProgressBarIndeterminateVisibility(false); break; case MSG_UPDATE_STATUS: break; } showDialog(DIALOG_AUTHENTICATION_FAILED); break; case MSG_SERVICE_UNAVAILABLE_ERROR: switch (msg.arg1) { case MSG_MANUAL_RELOAD: setProgressBarIndeterminateVisibility(false); break; case MSG_UPDATE_STATUS: break; } showDialog(DIALOG_SERVICE_UNAVAILABLE); break; case MSG_MANUAL_RELOAD: mIsLoading = false; Toast.makeText(MessageListActivity.this, R.string.timeline_reloaded, Toast.LENGTH_SHORT).show(); setProgressBarIndeterminateVisibility(false); break; case MSG_LOAD_ITEMS: switch (msg.arg1) { case STATUS_LOAD_ITEMS_SUCCESS: mIsLoading = false; mListFooter.setVisibility(View.INVISIBLE); ((SimpleCursorAdapter) getListAdapter()).changeCursor(mCursor); setProgressBarIndeterminateVisibility(false); break; case STATUS_LOAD_ITEMS_FAILURE: break; } break; case MSG_CONNECTION_TIMEOUT_EXCEPTION: switch (msg.arg1) { case MSG_MANUAL_RELOAD: setProgressBarIndeterminateVisibility(false); break; case MSG_UPDATE_STATUS: break; } showDialog(DIALOG_CONNECTION_TIMEOUT); break; default: super.handleMessage(msg); } } }; /** * Handles threaded sending of messages. */ protected Runnable mSendMessage = new Runnable() { public void run() { } }; /** * Load more items into the list. */ protected Runnable mLoadListItems = new Runnable() { public void run() { mCursor = ((PagedCursorAdapter) MessageListActivity.this.getListAdapter()).runQuery("LIMIT 0," + (++mCurrentPage * PAGE_SIZE)); mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_LOAD_ITEMS, STATUS_LOAD_ITEMS_SUCCESS, 0), 400); } }; }