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}