package com.closedcircles.client.activities; import android.app.Activity; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.graphics.Typeface; import android.os.Bundle; import android.os.ResultReceiver; import android.support.v4.view.ViewPager; import android.text.Editable; import android.util.Log; import android.view.ContextMenu; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ListView; import android.widget.Toast; import com.closedcircles.client.R; import com.closedcircles.client.WebConnectionManager; import com.closedcircles.client.model.*; import com.closedcircles.client.adapters.*; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class FragmentMessages extends android.support.v4.app.Fragment { ListView mViewMessages; EditText mEditText; int mSelectedPosition = 0; AdapterMessages mMessagesAdapter = null; int mSelected=-1; private Runnable mShowImeRunnable = null; private Runnable mScrollRunnable = null; private Runnable mPostReadRunnable = null; private ImageButton mbtnSend = null; HashMap<Long, Long> mItemsOnScreen = new HashMap<Long, Long>(); private class PostReadRunnable implements Runnable{ private long mThreadId = -1; private long mMsgId = -1; public PostReadRunnable(long thread_id, long msg_id){ mThreadId = thread_id; mMsgId = msg_id; } public void run() { WebConnectionManager.get().markRead(mThreadId, mMsgId); } } public static final FragmentMessages newInstance() { FragmentMessages f = new FragmentMessages(); return f; } public FragmentMessages() { super(); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.fragment_messages, container, false); mViewMessages = (ListView)view.findViewById(R.id.message_list); mEditText = (EditText)view.findViewById(R.id.edit_message); mbtnSend = (ImageButton)view.findViewById(R.id.send_message); Typeface authTypeface = Typeface.createFromAsset(getActivity().getAssets(), "Roboto-LightItalic.ttf"); Typeface msgTypeface = Typeface.createFromAsset(getActivity().getAssets(), "Messages.ttf"); mMessagesAdapter = new AdapterMessages(this, msgTypeface, authTypeface); mViewMessages.setAdapter(mMessagesAdapter); mViewMessages.setItemsCanFocus(true); updateList(false, false); mEditText.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent motionEvent) { setImeVisibility(true); return false; } }); mShowImeRunnable = new Runnable() { public void run() { InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); if (imm != null){ imm.showSoftInput(mEditText, 0); mEditText.postDelayed(mScrollRunnable, 1000); } } }; mScrollRunnable = new Runnable() { public void run() { mViewMessages.smoothScrollToPosition(mSelectedPosition); } }; mViewMessages.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { onMessageClicked(v, position); } }); mViewMessages.setOnScrollListener(new ListView.OnScrollListener() { int oldFirstVisibleItem = 0; int oldLastVisibleItem = 0; public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (firstVisibleItem > oldFirstVisibleItem) { for(int i = oldFirstVisibleItem; i < firstVisibleItem; i++) { onExit(i); } } if (firstVisibleItem < oldFirstVisibleItem) { for(int i = firstVisibleItem; i < oldFirstVisibleItem; i++) { onEnter(i); } } int lastVisibleItem = firstVisibleItem + visibleItemCount - 1; if (lastVisibleItem < oldLastVisibleItem) { for(int i = oldLastVisibleItem+1; i <= lastVisibleItem; i++) { onExit(i); } } if (lastVisibleItem > oldLastVisibleItem) { for(int i = oldLastVisibleItem+1; i <= lastVisibleItem; i++) { onEnter(i); } } oldFirstVisibleItem = firstVisibleItem; oldLastVisibleItem = lastVisibleItem; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) {} }); mbtnSend.setOnClickListener(new ImageButton.OnClickListener() { public void onClick(View v){ Editable text = mEditText.getText(); if ( text != null ) sendMessage(text.toString()); } }); registerForContextMenu(mViewMessages); return view; } public void onEnter(int position) { if ( !mItemsOnScreen.containsValue(Long.valueOf(position)) ) mItemsOnScreen.put(Long.valueOf(position), System.currentTimeMillis()); } public void onExit(int position) { if ( mItemsOnScreen.containsKey(Long.valueOf(position))){ if ( (System.currentTimeMillis()-mItemsOnScreen.get(Long.valueOf(position)))/1000 < WebConnectionManager.MESSAGE_MAKE_READ_TIME ){ mItemsOnScreen.remove( Long.valueOf(position)); } } } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if ( mViewMessages == null || mItemsOnScreen == null ) return; if (!isVisibleToUser) { int start = mViewMessages.getFirstVisiblePosition(); int end = mViewMessages.getLastVisiblePosition(); for ( int i=start;i<=end;++i ){ onExit(i); } //find largest visible position long largest = -1; for (long position : mItemsOnScreen.keySet()) { if ( position > largest ) largest = position; } if ( largest == -1 ) { mItemsOnScreen.clear(); return; } CirclesActivity activity = (CirclesActivity) getActivity(); Account account = WebConnectionManager.get().account(); Circle circle = account.getSelectedCircle(); if (circle == null) return; Circle.Thread thread = account.getSelectedThread(); if (thread != null && largest >= thread.getFirstUread() && largest < mMessagesAdapter.getCount() ) { //thread.setFirstUnread(position + 1); String str = "item was read" + largest; Log.w(getClass().getName(), str); WebConnectionManager.get().markRead(thread.getId(), mMessagesAdapter.getItem((int) largest).msg_id); } mItemsOnScreen.clear(); } else { int start = mViewMessages.getFirstVisiblePosition(); int end = mViewMessages.getLastVisiblePosition(); for ( int i=start;i<=end;++i ){ onEnter(i); } } } public int getSelectedPosition() { return mSelectedPosition; } public void onMessageClicked(View v, int position){ if (mMessagesAdapter != null) WebConnectionManager.get().account().setSelectedMsgId(mMessagesAdapter.getItem(position).msg_id); mViewMessages.setItemChecked(position, true); mSelectedPosition = position; } public void setImeVisibility(final boolean visible) { if ( mEditText == null ) return; if (visible) { mEditText.post(mShowImeRunnable); } else { mEditText.removeCallbacks(mShowImeRunnable); InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); if (imm != null) { imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0); } } } private void sendMessage(String msg){ if ( msg.isEmpty() ) return; if ( WebConnectionManager.get().checkConnection() == false ) { Toast.makeText(getActivity(), getResources().getText(R.string.no_connection), Toast.LENGTH_LONG).show(); return; } WebConnectionManager.get().sendMessage(msg); mEditText.setText(""); } private void editMessage(long msg_id, String msg){ if ( WebConnectionManager.get().checkConnection() == false ) { Toast.makeText(getActivity(), getResources().getText(R.string.no_connection), Toast.LENGTH_LONG).show(); return; } WebConnectionManager.get().editMessage(msg_id, msg); mEditText.setText(""); } public void clearList(){ mMessagesAdapter.clear(); } class MsgComparator implements Comparator<Circle.MsgThread> { @Override public int compare(Circle.MsgThread a, Circle.MsgThread b) { return (int)(a.msg_id-b.msg_id); }; }; public void updateList(boolean scroll_to_last, boolean scroll_to_last_read){ if( mMessagesAdapter == null ) return; mViewMessages.clearChoices(); // fill tread array to display in the list CirclesActivity activity = (CirclesActivity)getActivity(); Account account = WebConnectionManager.get().account(); Circle circle = account.getSelectedCircle(); if ( circle == null ) return; Circle.Thread thread = account.getSelectedThread(); ArrayList<Circle.MsgThread> messages = new ArrayList<Circle.MsgThread>(); int selected = -1; if ( thread == null ) { // add all circle messages /* for ( int i=0;i<circle.getNumMessages();++i ){ Message msg = circle.getMessage(i); if (msg.getId() == account.getSelectedMsgId()) selected = messages.size(); add_message(messages, msg); }*/ } else { // add all thread messages int size = thread.size(); for (int i = 0; i < size; ++i) { int position = thread.get(i); Message msg = circle.getMessage(position); if (msg.getId() == account.getSelectedMsgId()) selected = messages.size(); add_message(messages, msg); } } // sort messages Collections.sort(messages, new MsgComparator()); mMessagesAdapter.clear(); mMessagesAdapter.addAll(messages); if ( selected != -1 ) mViewMessages.setItemChecked(selected, true); // during adding new messages, try to scroll to the end, to see last added messages if ( scroll_to_last_read ) { if ( thread.hasUnread() ) mViewMessages.setSelection(thread.getFirstUread()); else mViewMessages.setSelection(mMessagesAdapter.getCount()-1); } else if ( scroll_to_last && messages.size()>0 && messages.get(messages.size()-1).msg_id == account.getNewMsgId() ){ mViewMessages.smoothScrollToPosition(mMessagesAdapter.getCount()-1); account.setNewMsgId(-1); } } private void add_message( ArrayList<Circle.MsgThread> messages, Message msg){ Circle.MsgThread m = new Circle.MsgThread(); m.msg = msg.getMessage(); m.authour = msg.getFullName(); String to_text = (msg.getFlags() & (long) (Message.OPENREPLAY)) != 0 ? ":reply @" : ":closed @"; if (msg.getParent() != -1) { to_text += msg.getParentName(); m.authour += to_text; } m.date = msg.getDate(); m.thread_id = msg.getThread(); m.msg_id = msg.getId(); m.isRead = msg.isRead(); messages.add(m); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo){ super.onCreateContextMenu(menu, v, menuInfo); MenuInflater inflater = getActivity().getMenuInflater(); inflater.inflate(R.menu.msg_context_menu, menu); } @Override public boolean onContextItemSelected(MenuItem item) { AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); // Handle presses on the action bar items switch (item.getItemId()) { case R.id.action_copy_text: copy_text(mMessagesAdapter.getItem(info.position).msg); return true; case R.id.action_delete: String str = new String(""); editMessage(mMessagesAdapter.getItem(info.position).msg_id, str); return true; case R.id.action_user_info: Intent i = new Intent(getActivity(), UserInfoActivity.class); i.putExtra(CirclesActivity.EXTRA_USER_NAME, mMessagesAdapter.getItem(info.position).authour); getActivity().startActivity(i); return true; default: return super.onOptionsItemSelected(item); } } public void copy_text(String text){ int sdk = android.os.Build.VERSION.SDK_INT; if(sdk < android.os.Build.VERSION_CODES.HONEYCOMB) { android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); clipboard.setText(text); } else { android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); android.content.ClipData clip = android.content.ClipData.newPlainText("text label",text); clipboard.setPrimaryClip(clip); } } }