1package de.gultsch.chat.ui;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import de.gultsch.chat.R;
7import de.gultsch.chat.crypto.PgpEngine;
8import de.gultsch.chat.crypto.PgpEngine.UserInputRequiredException;
9import de.gultsch.chat.entities.Account;
10import de.gultsch.chat.ui.EditAccount.EditAccountListener;
11import android.app.Activity;
12import android.app.AlertDialog;
13import android.content.Context;
14import android.content.DialogInterface;
15import android.content.DialogInterface.OnClickListener;
16import android.content.Intent;
17import android.content.IntentSender.SendIntentException;
18import android.os.Bundle;
19import android.util.Log;
20import android.view.ActionMode;
21import android.view.ActionMode.Callback;
22import android.view.LayoutInflater;
23import android.view.Menu;
24import android.view.MenuInflater;
25import android.view.MenuItem;
26import android.view.View;
27import android.view.ViewGroup;
28import android.widget.AdapterView;
29import android.widget.AdapterView.OnItemClickListener;
30import android.widget.AdapterView.OnItemLongClickListener;
31import android.widget.ArrayAdapter;
32import android.widget.ListView;
33import android.widget.TextView;
34
35public class ManageAccountActivity extends XmppActivity implements ActionMode.Callback {
36
37 public static final int REQUEST_ANNOUNCE_PGP = 0x73731;
38
39 protected boolean isActionMode = false;
40 protected ActionMode actionMode;
41 protected Account selectedAccountForActionMode = null;
42
43 protected List<Account> accountList = new ArrayList<Account>();
44 protected ListView accountListView;
45 protected ArrayAdapter<Account> accountListViewAdapter;
46 protected OnAccountListChangedListener accountChanged = new OnAccountListChangedListener() {
47
48 @Override
49 public void onAccountListChangedListener() {
50 Log.d("xmppService", "ui on account list changed listener");
51 accountList.clear();
52 accountList.addAll(xmppConnectionService.getAccounts());
53 runOnUiThread(new Runnable() {
54
55 @Override
56 public void run() {
57 if (accountList.size() == 1) {
58 startActivity(new Intent(getApplicationContext(),
59 NewConversationActivity.class));
60 }
61 accountListViewAdapter.notifyDataSetChanged();
62 }
63 });
64 }
65 };
66
67 @Override
68 protected void onCreate(Bundle savedInstanceState) {
69
70 super.onCreate(savedInstanceState);
71
72 setContentView(R.layout.manage_accounts);
73
74 accountListView = (ListView) findViewById(R.id.account_list);
75 accountListViewAdapter = new ArrayAdapter<Account>(
76 getApplicationContext(), R.layout.account_row, this.accountList) {
77 @Override
78 public View getView(int position, View view, ViewGroup parent) {
79 Account account = getItem(position);
80 if (view == null) {
81 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
82 view = (View) inflater.inflate(R.layout.account_row, null);
83 }
84 ((TextView) view.findViewById(R.id.account_jid))
85 .setText(account.getJid());
86 TextView statusView = (TextView) view
87 .findViewById(R.id.account_status);
88 switch (account.getStatus()) {
89 case Account.STATUS_DISABLED:
90 statusView.setText("temporarily disabled");
91 statusView.setTextColor(0xFF1da9da);
92 break;
93 case Account.STATUS_ONLINE:
94 statusView.setText("online");
95 statusView.setTextColor(0xFF83b600);
96 break;
97 case Account.STATUS_OFFLINE:
98 statusView.setText("offline");
99 statusView.setTextColor(0xFFe92727);
100 break;
101 case Account.STATUS_UNAUTHORIZED:
102 statusView.setText("unauthorized");
103 statusView.setTextColor(0xFFe92727);
104 break;
105 case Account.STATUS_SERVER_NOT_FOUND:
106 statusView.setText("server not found");
107 statusView.setTextColor(0xFFe92727);
108 break;
109 default:
110 break;
111 }
112
113 return view;
114 }
115 };
116 final Activity activity = this;
117 accountListView.setAdapter(this.accountListViewAdapter);
118 accountListView.setOnItemClickListener(new OnItemClickListener() {
119
120 @Override
121 public void onItemClick(AdapterView<?> arg0, View view,
122 int position, long arg3) {
123 if (!isActionMode) {
124 EditAccount dialog = new EditAccount();
125 dialog.setAccount(accountList.get(position));
126 dialog.setEditAccountListener(new EditAccountListener() {
127
128 @Override
129 public void onAccountEdited(Account account) {
130 xmppConnectionService.updateAccount(account);
131 }
132 });
133 dialog.show(getFragmentManager(), "edit_account");
134 } else {
135 selectedAccountForActionMode = accountList.get(position);
136 actionMode.invalidate();
137 }
138 }
139 });
140 accountListView.setOnItemLongClickListener(new OnItemLongClickListener() {
141
142 @Override
143 public boolean onItemLongClick(AdapterView<?> arg0, View view,
144 int position, long arg3) {
145 if (!isActionMode) {
146 accountListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
147 accountListView.setItemChecked(position,true);
148 selectedAccountForActionMode = accountList.get(position);
149 actionMode = activity.startActionMode((Callback) activity);
150 return true;
151 } else {
152 return false;
153 }
154 }
155 });
156 }
157
158 @Override
159 protected void onStop() {
160 if (xmppConnectionServiceBound) {
161 xmppConnectionService.removeOnAccountListChangedListener();
162 }
163 super.onStop();
164 }
165
166 @Override
167 void onBackendConnected() {
168 xmppConnectionService.setOnAccountListChangedListener(accountChanged);
169 this.accountList.clear();
170 this.accountList.addAll(xmppConnectionService.getAccounts());
171 accountListViewAdapter.notifyDataSetChanged();
172 if (this.accountList.size() == 0) {
173 getActionBar().setDisplayHomeAsUpEnabled(false);
174 addAccount();
175 }
176 }
177
178 @Override
179 public boolean onCreateOptionsMenu(Menu menu) {
180 getMenuInflater().inflate(R.menu.manageaccounts, menu);
181 return true;
182 }
183
184 @Override
185 public boolean onOptionsItemSelected(MenuItem item) {
186 switch (item.getItemId()) {
187 case R.id.action_settings:
188 startActivity(new Intent(this, SettingsActivity.class));
189 break;
190 case R.id.action_add_account:
191 addAccount();
192 break;
193 default:
194 break;
195 }
196 return super.onOptionsItemSelected(item);
197 }
198
199 protected void addAccount() {
200 final Activity activity = this;
201 EditAccount dialog = new EditAccount();
202 dialog.setEditAccountListener(new EditAccountListener() {
203
204 @Override
205 public void onAccountEdited(Account account) {
206 xmppConnectionService.createAccount(account);
207 activity.getActionBar().setDisplayHomeAsUpEnabled(true);
208 }
209 });
210 dialog.show(getFragmentManager(), "add_account");
211 }
212
213 @Override
214 public boolean onActionItemClicked(final ActionMode mode, MenuItem item) {
215 if (item.getItemId()==R.id.account_disable) {
216 selectedAccountForActionMode.setOption(Account.OPTION_DISABLED, true);
217 xmppConnectionService.updateAccount(selectedAccountForActionMode);
218 mode.finish();
219 } else if (item.getItemId()==R.id.account_enable) {
220 selectedAccountForActionMode.setOption(Account.OPTION_DISABLED, false);
221 xmppConnectionService.updateAccount(selectedAccountForActionMode);
222 mode.finish();
223 } else if (item.getItemId()==R.id.account_delete) {
224 AlertDialog.Builder builder = new AlertDialog.Builder(this);
225 builder.setTitle("Are you sure?");
226 builder.setIconAttribute(android.R.attr.alertDialogIcon);
227 builder.setMessage("If you delete your account your entire conversation history will be lost");
228 builder.setPositiveButton("Delete", new OnClickListener() {
229
230 @Override
231 public void onClick(DialogInterface dialog, int which) {
232 xmppConnectionService.deleteAccount(selectedAccountForActionMode);
233 selectedAccountForActionMode = null;
234 mode.finish();
235 }
236 });
237 builder.setNegativeButton("Cancel",null);
238 builder.create().show();
239 } else if (item.getItemId()==R.id.announce_pgp) {
240 mode.finish();
241 try {
242 xmppConnectionService.generatePgpAnnouncement(selectedAccountForActionMode);
243 } catch (PgpEngine.UserInputRequiredException e) {
244 try {
245 startIntentSenderForResult(e.getPendingIntent().getIntentSender(), REQUEST_ANNOUNCE_PGP, null, 0, 0, 0);
246 } catch (SendIntentException e1) {
247 Log.d("gultsch","sending intent failed");
248 }
249 }
250 }
251 return true;
252 }
253
254 @Override
255 public boolean onCreateActionMode(ActionMode mode, Menu menu) {
256 MenuInflater inflater = mode.getMenuInflater();
257 inflater.inflate(R.menu.manageaccounts_context, menu);
258 return true;
259 }
260
261 @Override
262 public void onDestroyActionMode(ActionMode mode) {
263 // TODO Auto-generated method stub
264
265 }
266
267 @Override
268 public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
269 if (selectedAccountForActionMode.isOptionSet(Account.OPTION_DISABLED)) {
270 menu.findItem(R.id.account_enable).setVisible(true);
271 menu.findItem(R.id.account_disable).setVisible(false);
272 } else {
273 menu.findItem(R.id.account_disable).setVisible(true);
274 menu.findItem(R.id.account_enable).setVisible(false);
275 }
276 return true;
277 }
278
279 @Override
280 public void onActionModeStarted(ActionMode mode) {
281 super.onActionModeStarted(mode);
282 this.isActionMode = true;
283 }
284
285 @Override
286 public void onActionModeFinished(ActionMode mode) {
287 super.onActionModeFinished(mode);
288 this.isActionMode = false;
289 accountListView.clearChoices();
290 accountListView.requestLayout();
291 accountListView.post(new Runnable() {
292 @Override
293 public void run() {
294 accountListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
295 }
296 });
297 }
298
299 @Override
300 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
301 super.onActivityResult(requestCode, resultCode, data);
302 if (resultCode == RESULT_OK) {
303 if (requestCode == REQUEST_ANNOUNCE_PGP) {
304 try {
305 xmppConnectionService.generatePgpAnnouncement(selectedAccountForActionMode);
306 } catch (UserInputRequiredException e) {
307 Log.d("gultsch","already came back. ignoring");
308 }
309 }
310 }
311 }
312}