ConversationActivity.java

  1package de.gultsch.chat.ui;
  2
  3import java.util.ArrayList;
  4import java.util.Collections;
  5import java.util.Comparator;
  6import java.util.List;
  7
  8import de.gultsch.chat.R;
  9import de.gultsch.chat.R.id;
 10import de.gultsch.chat.entities.Contact;
 11import de.gultsch.chat.entities.Conversation;
 12import de.gultsch.chat.entities.Message;
 13import de.gultsch.chat.utils.UIHelper;
 14import android.net.Uri;
 15import android.os.Bundle;
 16import android.app.FragmentTransaction;
 17import android.app.NotificationManager;
 18import android.content.Context;
 19import android.content.Intent;
 20import android.graphics.Typeface;
 21import android.support.v4.widget.SlidingPaneLayout;
 22import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener;
 23import android.util.Log;
 24import android.view.KeyEvent;
 25import android.view.LayoutInflater;
 26import android.view.Menu;
 27import android.view.MenuItem;
 28import android.view.View;
 29import android.view.ViewGroup;
 30import android.view.inputmethod.InputMethodManager;
 31import android.widget.AdapterView;
 32import android.widget.AdapterView.OnItemClickListener;
 33import android.widget.ArrayAdapter;
 34import android.widget.ListView;
 35import android.widget.PopupMenu;
 36import android.widget.PopupMenu.OnMenuItemClickListener;
 37import android.widget.TextView;
 38import android.widget.ImageView;
 39
 40public class ConversationActivity extends XmppActivity {
 41
 42	public static final String VIEW_CONVERSATION = "viewConversation";
 43	public static final String CONVERSATION = "conversationUuid";
 44	
 45	public static final int INSERT_CONTACT = 0x9889;
 46
 47	protected SlidingPaneLayout spl;
 48
 49	private List<Conversation> conversationList = new ArrayList<Conversation>();
 50	private Conversation selectedConversation = null;
 51	private ListView listView;
 52	
 53	private boolean paneShouldBeOpen = true;
 54	private ArrayAdapter<Conversation> listAdapter;
 55	
 56	private OnConversationListChangedListener onConvChanged = new OnConversationListChangedListener() {
 57		
 58		@Override
 59		public void onConversationListChanged() {
 60			final Conversation currentConv = getSelectedConversation();
 61			conversationList.clear();
 62			conversationList.addAll(xmppConnectionService
 63					.getConversations());
 64			runOnUiThread(new Runnable() {
 65				
 66				@Override
 67				public void run() {	
 68					updateConversationList();
 69					/*for(int i = 0; i < conversationList.size(); ++i) {
 70						if (currentConv == conversationList.get(i)) {
 71							selectedConversation = conversationList.get(i);
 72							break;
 73						}
 74					}*/
 75					if(paneShouldBeOpen) {
 76						selectedConversation = conversationList.get(0);
 77						if (conversationList.size() >= 1) {
 78							swapConversationFragment();
 79						} else {
 80							startActivity(new Intent(getApplicationContext(), NewConversationActivity.class));
 81							finish();
 82						}
 83					}
 84					ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager().findFragmentByTag("conversation");
 85					if (selectedFragment!=null) {
 86						selectedFragment.updateMessages();
 87					}
 88				}
 89			});
 90		}
 91	};
 92	private boolean contactInserted = false;
 93	
 94	
 95	public List<Conversation> getConversationList() {
 96		return this.conversationList;
 97	}
 98
 99	public Conversation getSelectedConversation() {
100		return this.selectedConversation;
101	}
102	
103	public ListView getConversationListView() {
104		return this.listView;
105	}
106	
107	public SlidingPaneLayout getSlidingPaneLayout() {
108		return this.spl;
109	}
110	
111	public boolean shouldPaneBeOpen() {
112		return paneShouldBeOpen;
113	}
114	
115	public void updateConversationList() {
116		if (conversationList.size() >= 1) {
117			Collections.sort(this.conversationList, new Comparator<Conversation>() {
118				@Override
119				public int compare(Conversation lhs, Conversation rhs) {
120					return (int) (rhs.getLatestMessage().getTimeSent() - lhs.getLatestMessage().getTimeSent());
121				}
122			});
123		}
124		this.listView.invalidateViews();
125	}
126	
127	@Override
128	protected void onCreate(Bundle savedInstanceState) {
129
130		super.onCreate(savedInstanceState);
131
132		setContentView(R.layout.fragment_conversations_overview);
133
134		listView = (ListView) findViewById(R.id.list);
135
136		this.listAdapter = new ArrayAdapter<Conversation>(this,
137				R.layout.conversation_list_row, conversationList) {
138			@Override
139			public View getView(int position, View view, ViewGroup parent) {
140				if (view == null) {
141					LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
142					view = (View) inflater.inflate(
143							R.layout.conversation_list_row, null);
144				}
145				Conversation conv = getItem(position);
146				TextView convName = (TextView) view.findViewById(R.id.conversation_name);
147				convName.setText(conv.getName());
148				TextView convLastMsg = (TextView) view.findViewById(R.id.conversation_lastmsg);
149				convLastMsg.setText(conv.getLatestMessage().getBody());
150				
151				if(!conv.isRead()) {
152					convName.setTypeface(null,Typeface.BOLD);
153					convLastMsg.setTypeface(null,Typeface.BOLD);
154				} else {
155					convName.setTypeface(null,Typeface.NORMAL);
156					convLastMsg.setTypeface(null,Typeface.NORMAL);
157				}
158				
159				((TextView) view.findViewById(R.id.conversation_lastupdate))
160				.setText(UIHelper.readableTimeDifference(getItem(position).getLatestMessage().getTimeSent()));
161				
162				Uri profilePhoto = getItem(position).getProfilePhotoUri();
163				ImageView imageView = (ImageView) view.findViewById(R.id.conversation_image);
164				if (profilePhoto!=null) {
165					imageView.setImageURI(profilePhoto);
166				} else {
167					imageView.setImageBitmap(UIHelper.getUnknownContactPicture(getItem(position).getName(),200));
168				}
169				
170				
171				((ImageView) view.findViewById(R.id.conversation_image))
172						.setImageURI(getItem(position).getProfilePhotoUri());
173				return view;
174			}
175
176		};
177		
178		listView.setAdapter(this.listAdapter);
179
180		listView.setOnItemClickListener(new OnItemClickListener() {
181
182			@Override
183			public void onItemClick(AdapterView<?> arg0, View clickedView,
184					int position, long arg3) {
185				paneShouldBeOpen = false;
186				if (selectedConversation != conversationList.get(position)) {
187					selectedConversation = conversationList.get(position);
188					swapConversationFragment(); //.onBackendConnected(conversationList.get(position));
189				} else {
190					spl.closePane();
191				}
192			}
193		});
194		spl = (SlidingPaneLayout) findViewById(id.slidingpanelayout);
195		spl.setParallaxDistance(150);
196		spl.setShadowResource(R.drawable.es_slidingpane_shadow);
197		spl.setSliderFadeColor(0);
198		spl.setPanelSlideListener(new PanelSlideListener() {
199
200			@Override
201			public void onPanelOpened(View arg0) {
202				paneShouldBeOpen = true;
203				getActionBar().setDisplayHomeAsUpEnabled(false);
204				getActionBar().setTitle(R.string.app_name);
205				invalidateOptionsMenu();
206
207				InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
208
209				View focus = getCurrentFocus();
210
211				if (focus != null) {
212
213					inputManager.hideSoftInputFromWindow(
214							focus.getWindowToken(),
215							InputMethodManager.HIDE_NOT_ALWAYS);
216				}
217			}
218
219			@Override
220			public void onPanelClosed(View arg0) {
221				paneShouldBeOpen = false;
222				if (conversationList.size() > 0) {
223					getActionBar().setDisplayHomeAsUpEnabled(true);
224					getActionBar().setTitle(getSelectedConversation().getName());
225					invalidateOptionsMenu();
226					if (!getSelectedConversation().isRead()) {
227						getSelectedConversation().markRead();
228						updateConversationList();
229					}
230				}
231			}
232
233			@Override
234			public void onPanelSlide(View arg0, float arg1) {
235				// TODO Auto-generated method stub
236
237			}
238		});
239	}
240
241	@Override
242	public boolean onCreateOptionsMenu(Menu menu) {
243		getMenuInflater().inflate(R.menu.conversations, menu);
244		MenuItem menuSecure = (MenuItem) menu.findItem(R.id.action_security);
245		
246		if (spl.isOpen()) {
247			((MenuItem) menu.findItem(R.id.action_archive)).setVisible(false);
248			((MenuItem) menu.findItem(R.id.action_details)).setVisible(false);
249			menuSecure.setVisible(false);
250		} else {
251			((MenuItem) menu.findItem(R.id.action_add)).setVisible(false);
252			if (this.getSelectedConversation()!=null) {
253				if (this.getSelectedConversation().getMode() == Conversation.MODE_MULTI) {
254					((MenuItem) menu.findItem(R.id.action_security)).setVisible(false);
255					menuSecure.setVisible(false);
256					((MenuItem) menu.findItem(R.id.action_archive)).setTitle("Leave conference");
257				} else {
258					if (this.getSelectedConversation().getLatestMessage().getEncryption() != Message.ENCRYPTION_NONE) {
259						menuSecure.setIcon(R.drawable.ic_action_secure);
260					}
261				}
262			}
263		}
264		return true;
265	}
266
267	@Override
268	public boolean onOptionsItemSelected(MenuItem item) {
269		switch (item.getItemId()) {
270		case android.R.id.home:
271			spl.openPane();
272			break;
273		case R.id.action_settings:
274			startActivity(new Intent(this, SettingsActivity.class));
275			break;
276		case R.id.action_accounts:
277			startActivity(new Intent(this, ManageAccountActivity.class));
278			break;
279		case R.id.action_add:
280			startActivity(new Intent(this, NewConversationActivity.class));
281			break;
282		case R.id.action_archive:
283			Conversation conv = getSelectedConversation();
284			conv.setStatus(Conversation.STATUS_ARCHIVED);
285			paneShouldBeOpen = true;
286			spl.openPane();
287			xmppConnectionService.archiveConversation(conv);
288			selectedConversation = conversationList.get(0);
289			break;
290		case R.id.action_details:
291			DialogContactDetails details = new DialogContactDetails();
292			Contact contact = this.getSelectedConversation().getContact();
293			if (contact != null) {
294				contact.setAccount(this.selectedConversation.getAccount());
295				details.setContact(contact);
296				details.show(getFragmentManager(), "details");
297			} else {
298				Log.d("xmppService","contact was null - means not in roster");
299			}
300			break;
301		case R.id.action_security:
302			final Conversation selConv = getSelectedConversation();
303			View menuItemView = findViewById(R.id.action_security);
304			PopupMenu popup = new PopupMenu(this, menuItemView);
305			final ConversationFragment fragment = (ConversationFragment) getFragmentManager().findFragmentByTag("conversation");
306		    if (fragment!=null) {
307				popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
308					
309					@Override
310					public boolean onMenuItemClick(MenuItem item) {
311						switch (item.getItemId()) {
312						case R.id.encryption_choice_none:
313							selConv.nextMessageEncryption = Message.ENCRYPTION_NONE;
314							item.setChecked(true);
315							break;
316						case R.id.encryption_choice_otr:
317							selConv.nextMessageEncryption = Message.ENCRYPTION_OTR;
318							item.setChecked(true);
319							break;
320						case R.id.encryption_choice_pgp:
321							selConv.nextMessageEncryption = Message.ENCRYPTION_PGP;
322							item.setChecked(true);
323							break;
324						default:
325							selConv.nextMessageEncryption = Message.ENCRYPTION_NONE;
326							break;
327						}
328						fragment.updateChatMsgHint();
329						return true;
330					}
331				});
332			    popup.inflate(R.menu.encryption_choices);
333			    switch (selConv.nextMessageEncryption) {
334				case Message.ENCRYPTION_NONE:
335					popup.getMenu().findItem(R.id.encryption_choice_none).setChecked(true);
336					break;
337				case Message.ENCRYPTION_OTR:
338					popup.getMenu().findItem(R.id.encryption_choice_otr).setChecked(true);
339					break;
340				case Message.ENCRYPTION_PGP:
341					popup.getMenu().findItem(R.id.encryption_choice_pgp).setChecked(true);
342					break;
343				default:
344					popup.getMenu().findItem(R.id.encryption_choice_none).setChecked(true);
345					break;
346				}
347			    popup.show();
348		    }
349
350			break;
351		default:
352			break;
353		}
354		return super.onOptionsItemSelected(item);
355	}
356
357	protected ConversationFragment swapConversationFragment() {
358		ConversationFragment selectedFragment = new ConversationFragment();
359		
360		FragmentTransaction transaction = getFragmentManager()
361				.beginTransaction();
362		transaction.replace(R.id.selected_conversation, selectedFragment,"conversation");
363		transaction.commit();
364		return selectedFragment;
365	}
366
367	@Override
368	public boolean onKeyDown(int keyCode, KeyEvent event) {
369		if (keyCode == KeyEvent.KEYCODE_BACK) {
370			if (!spl.isOpen()) {
371				spl.openPane();
372				return false;
373			}
374		}
375		return super.onKeyDown(keyCode, event);
376	}
377	
378	public void onStart() {
379		super.onStart();
380		NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
381		nm.cancelAll();
382		if (conversationList.size()>=1) {
383			onConvChanged.onConversationListChanged();
384		}
385	}
386	
387	@Override
388	protected void onStop() {
389		Log.d("gultsch","called on stop in conversation activity");
390		if (xmppConnectionServiceBound) {
391        	xmppConnectionService.removeOnConversationListChangedListener();
392		}
393		super.onStop();
394	}
395
396	@Override
397	void onBackendConnected() {
398		
399		xmppConnectionService.setOnConversationListChangedListener(this.onConvChanged);
400		
401		if (conversationList.size()==0) {
402			conversationList.clear();
403			conversationList.addAll(xmppConnectionService
404					.getConversations());
405			
406			this.updateConversationList();
407		}
408
409		if ((getIntent().getAction().equals(Intent.ACTION_VIEW) && (!handledViewIntent))) {
410			if (getIntent().getType().equals(
411					ConversationActivity.VIEW_CONVERSATION)) {
412				handledViewIntent = true;
413
414				String convToView = (String) getIntent().getExtras().get(CONVERSATION);
415
416				for(int i = 0; i < conversationList.size(); ++i) {
417					if (conversationList.get(i).getUuid().equals(convToView)) {
418						selectedConversation = conversationList.get(i);
419					}
420				}
421				paneShouldBeOpen = false;
422				swapConversationFragment();
423			}
424		} else {
425			if (xmppConnectionService.getAccounts().size() == 0) {
426				startActivity(new Intent(this, ManageAccountActivity.class));
427				finish();
428			} else if (conversationList.size() <= 0) {
429				//add no history
430				startActivity(new Intent(this, NewConversationActivity.class));
431				finish();
432			} else {
433				spl.openPane();
434				//find currently loaded fragment
435				ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager().findFragmentByTag("conversation");
436				if (selectedFragment!=null) {
437					Log.d("gultsch","ConversationActivity. found old fragment.");
438					selectedFragment.onBackendConnected();
439				} else {
440					Log.d("gultsch","conversationactivity. no old fragment found. creating new one");
441					selectedConversation = conversationList.get(0);
442					Log.d("gultsch","selected conversation is #"+selectedConversation);
443					swapConversationFragment();
444				}
445			}
446		}
447	}
448	
449	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
450		if (requestCode==INSERT_CONTACT) {
451			Log.d("xmppService","contact inserted");
452			this.contactInserted  = true;
453		}
454	}
455}