allow to temporarily disable accounts

Daniel Gultsch created

Change summary

gen/de/gultsch/chat/R.java                              |  23 +
res/drawable-hdpi/ic_action_add_person.png              |   0 
res/drawable-hdpi/ic_action_delete.png                  |   0 
res/drawable-mdpi/ic_action_add_person.png              |   0 
res/drawable-mdpi/ic_action_delete.png                  |   0 
res/drawable-xhdpi/ic_action_add_person.png             |   0 
res/drawable-xhdpi/ic_action_delete.png                 |   0 
res/drawable-xxhdpi/ic_action_add_person.png            |   0 
res/layout/account_row.xml                              |   3 
res/menu/manageaccounts.xml                             |   3 
res/menu/manageaccounts_context.xml                     |  17 +
res/values/arrays.xml                                   |   4 
src/de/gultsch/chat/entities/Account.java               |  23 +
src/de/gultsch/chat/services/XmppConnectionService.java |  13 
src/de/gultsch/chat/ui/EditAccount.java                 |   4 
src/de/gultsch/chat/ui/ManageAccountActivity.java       | 124 +++++++++-
src/de/gultsch/chat/ui/NewConversationActivity.java     |   2 
17 files changed, 183 insertions(+), 33 deletions(-)

Detailed changes

gen/de/gultsch/chat/R.java 🔗

@@ -11,6 +11,7 @@ public final class R {
     public static final class array {
         public static final int conversation_encryption_type_entries=0x7f050000;
         public static final int conversation_encryption_type_values=0x7f050001;
+        public static final int manage_account_options=0x7f050002;
     }
     public static final class attr {
     }
@@ -28,17 +29,20 @@ public final class R {
         public static final int es_slidingpane_shadow=0x7f020000;
         public static final int ic_action_add=0x7f020001;
         public static final int ic_action_add_person=0x7f020002;
-        public static final int ic_action_send=0x7f020003;
-        public static final int ic_action_send_now=0x7f020004;
-        public static final int ic_action_unsecure=0x7f020005;
-        public static final int ic_launcher=0x7f020006;
-        public static final int ic_profile=0x7f020007;
-        public static final int message_border=0x7f020008;
-        public static final int notification=0x7f020009;
-        public static final int section_header=0x7f02000a;
+        public static final int ic_action_delete=0x7f020003;
+        public static final int ic_action_send=0x7f020004;
+        public static final int ic_action_send_now=0x7f020005;
+        public static final int ic_action_unsecure=0x7f020006;
+        public static final int ic_launcher=0x7f020007;
+        public static final int ic_profile=0x7f020008;
+        public static final int message_border=0x7f020009;
+        public static final int notification=0x7f02000a;
+        public static final int section_header=0x7f02000b;
     }
     public static final class id {
         public static final int account_confirm_password_desc=0x7f0a0011;
+        public static final int account_disable=0x7f0a002c;
+        public static final int account_enable=0x7f0a002d;
         public static final int account_jid=0x7f0a0000;
         public static final int account_list=0x7f0a0021;
         public static final int account_password=0x7f0a000f;
@@ -98,7 +102,8 @@ public final class R {
     public static final class menu {
         public static final int conversations=0x7f090000;
         public static final int manageaccounts=0x7f090001;
-        public static final int newconversation=0x7f090002;
+        public static final int manageaccounts_context=0x7f090002;
+        public static final int newconversation=0x7f090003;
     }
     public static final class string {
         public static final int action_accounts=0x7f070003;

res/layout/account_row.xml 🔗

@@ -2,7 +2,8 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="8dp">
+    android:padding="8dp"
+    android:background="?android:attr/activatedBackgroundIndicator">
 
  
 

res/menu/manageaccounts.xml 🔗

@@ -2,7 +2,8 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android" >
     <item android:id="@+id/action_add_account"
         android:showAsAction="always"
-        android:title="@string/action_add_account"/>
+        android:title="@string/action_add_account"
+        android:icon="@drawable/ic_action_add_person"/>
  <item
         android:id="@+id/action_settings"
         android:orderInCategory="100"

res/menu/manageaccounts_context.xml 🔗

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item android:icon="@drawable/ic_action_delete"
+        android:title="Delete"
+        android:showAsAction="always"
+        />
+    <item
+        android:id="@+id/account_disable"
+        android:title="Temporarily disable"
+        android:showAsAction="always"/>
+    <item
+        android:id="@+id/account_enable"
+        android:title="Enable"
+        android:showAsAction="always"
+        android:visible="false"/>
+
+</menu>

res/values/arrays.xml 🔗

@@ -10,4 +10,8 @@
         <item>pgp</item>
         <item>otr</item>
     </array>
+    <array name="manage_account_options">
+        <item>Delete</item>
+        <item>Disable</item>
+    </array>
 </resources>

src/de/gultsch/chat/entities/Account.java 🔗

@@ -17,7 +17,9 @@ public class Account  extends AbstractEntity{
 	public static final String ROSTERVERSION = "rosterversion";
 	
 	public static final int OPTION_USETLS = 0;
+	public static final int OPTION_DISABLED = 1;
 	
+	public static final int STATUS_DISABLED = -1;
 	public static final int STATUS_OFFLINE = 0;
 	public static final int STATUS_ONLINE = 1;
 	public static final int STATUS_UNAUTHORIZED = 2;
@@ -55,6 +57,20 @@ public class Account  extends AbstractEntity{
 		return ((options & (1 << option)) != 0);
 	}
 	
+	public void setOption(int option, boolean value) {
+		if (value) {
+			Log.d("xmppService","options: "+options);
+			this.options = (this.options | 1 << option);
+			Log.d("xmppService","setting option "+option+" to 1");
+			Log.d("xmppService","options: "+options);
+		} else {
+			Log.d("xmppService","options: "+options);
+			Log.d("xmppService","setting option "+option+" to 0");
+			this.options = (this.options ^ 1 << option);
+			Log.d("xmppService","options: "+options);
+		}
+	}
+	
 	public String getUsername() {
 		return username;
 	}
@@ -84,7 +100,11 @@ public class Account  extends AbstractEntity{
 	}
 	
 	public int getStatus() {
-		return this.status;
+		if (isOptionSet(OPTION_DISABLED)) {
+			return STATUS_DISABLED;
+		} else {
+			return this.status;
+		}
 	}
 	
 	public void setResource(String resource) {
@@ -102,6 +122,7 @@ public class Account  extends AbstractEntity{
 		values.put(USERNAME, username);
 		values.put(SERVER, server);
 		values.put(PASSWORD, password);
+		values.put(OPTIONS,options);
 		return values;
 	}
 	

src/de/gultsch/chat/services/XmppConnectionService.java 🔗

@@ -95,8 +95,11 @@ public class XmppConnectionService extends Service {
 	public int onStartCommand(Intent intent, int flags, int startId) {
 		for (Account account : accounts) {
 			if (!connections.containsKey(account)) {
-				
-				this.connections.put(account, this.createConnection(account));
+				if (!account.isOptionSet(Account.OPTION_DISABLED)) {
+					this.connections.put(account, this.createConnection(account));
+				} else {
+					Log.d(LOGTAG,account.getJid()+": not starting because it's disabled");
+				}
 			}
 		}
 		return START_STICKY;
@@ -253,7 +256,11 @@ public class XmppConnectionService extends Service {
 			connection.disconnect();
 			this.connections.remove(account);
 		}
-		this.connections.put(account, this.createConnection(account));
+		if (!account.isOptionSet(Account.OPTION_DISABLED)) {
+			this.connections.put(account, this.createConnection(account));
+		} else {
+			Log.d(LOGTAG,account.getJid()+": not starting because it's disabled");
+		}
 		if (accountChangedListener!=null) accountChangedListener.onAccountListChangedListener();
 	}
 

src/de/gultsch/chat/ui/EditAccount.java 🔗

@@ -92,7 +92,7 @@ public class EditAccount extends DialogFragment {
 			usernameText.setText(account.getUsername());
 			serverText.setText(account.getServer());
 			okButtonDesc = "Edit";
-			builder.setNegativeButton("Delete Account", new OnClickListener() {
+			/*builder.setNegativeButton("Delete Account", new OnClickListener() {
 				
 				@Override
 				public void onClick(DialogInterface dialog, int which) {
@@ -112,7 +112,7 @@ public class EditAccount extends DialogFragment {
 					builder.setNegativeButton("Cancel",null);
 					builder.create().show();
 				}
-			});
+			});*/
 		} else {
 			builder.setTitle("Add account");
 			okButtonDesc = "Add";

src/de/gultsch/chat/ui/ManageAccountActivity.java 🔗

@@ -7,23 +7,32 @@ import de.gultsch.chat.R;
 import de.gultsch.chat.entities.Account;
 import de.gultsch.chat.ui.EditAccount.EditAccountListener;
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
+import android.view.ActionMode;
+import android.view.ActionMode.Callback;
 import android.view.LayoutInflater;
 import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
 import android.widget.ArrayAdapter;
 import android.widget.ListView;
 import android.widget.TextView;
 
-public class ManageAccountActivity extends XmppActivity {
+public class ManageAccountActivity extends XmppActivity implements ActionMode.Callback {
 
+	protected boolean isActionMode = false;
+	protected ActionMode actionMode;
+	protected Account selectedAccountForActionMode = null;
+	
 	protected List<Account> accountList = new ArrayList<Account>();
 	protected ListView accountListView;
 	protected ArrayAdapter<Account> accountListViewAdapter;
@@ -70,6 +79,10 @@ public class ManageAccountActivity extends XmppActivity {
 				TextView statusView = (TextView) view
 						.findViewById(R.id.account_status);
 				switch (account.getStatus()) {
+				case Account.STATUS_DISABLED:
+					statusView.setText("temporarily disabled");
+					statusView.setTextColor(0xFF1da9da);
+					break;
 				case Account.STATUS_ONLINE:
 					statusView.setText("online");
 					statusView.setTextColor(0xFF83b600);
@@ -93,27 +106,49 @@ public class ManageAccountActivity extends XmppActivity {
 				return view;
 			}
 		};
+		final Activity activity = this;
 		accountListView.setAdapter(this.accountListViewAdapter);
 		accountListView.setOnItemClickListener(new OnItemClickListener() {
 
 			@Override
 			public void onItemClick(AdapterView<?> arg0, View view,
 					int position, long arg3) {
-				EditAccount dialog = new EditAccount();
-				dialog.setAccount(accountList.get(position));
-				dialog.setEditAccountListener(new EditAccountListener() {
-
-					@Override
-					public void onAccountEdited(Account account) {
-						xmppConnectionService.updateAccount(account);
-					}
+				if (!isActionMode) {
+					EditAccount dialog = new EditAccount();
+					dialog.setAccount(accountList.get(position));
+					dialog.setEditAccountListener(new EditAccountListener() {
+	
+						@Override
+						public void onAccountEdited(Account account) {
+							xmppConnectionService.updateAccount(account);
+						}
+	
+						@Override
+						public void onAccountDelete(Account account) {
+							xmppConnectionService.deleteAccount(account);
+						}
+					});
+					dialog.show(getFragmentManager(), "edit_account");
+				} else {
+					selectedAccountForActionMode = accountList.get(position);
+					actionMode.invalidate();
+				}
+			}
+		});
+		accountListView.setOnItemLongClickListener(new OnItemLongClickListener() {
 
-					@Override
-					public void onAccountDelete(Account account) {
-						xmppConnectionService.deleteAccount(account);
-					}
-				});
-				dialog.show(getFragmentManager(), "edit_account");
+			@Override
+			public boolean onItemLongClick(AdapterView<?> arg0, View view,
+					int position, long arg3) {
+				if (!isActionMode) {
+					accountListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+					accountListView.setItemChecked(position,true);
+					selectedAccountForActionMode = accountList.get(position);
+					actionMode = activity.startActionMode((Callback) activity);
+					return true;
+				} else {
+					return false;
+				}
 			}
 		});
 	}
@@ -180,4 +215,63 @@ public class ManageAccountActivity extends XmppActivity {
 		});
 		dialog.show(getFragmentManager(), "add_account");
 	}
+
+	@Override
+	public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+		if (item.getItemId()==R.id.account_disable) {
+			selectedAccountForActionMode.setOption(Account.OPTION_DISABLED, true);
+			xmppConnectionService.updateAccount(selectedAccountForActionMode);
+			mode.finish();
+		} else if (item.getItemId()==R.id.account_enable) {
+			selectedAccountForActionMode.setOption(Account.OPTION_DISABLED, false);
+			xmppConnectionService.updateAccount(selectedAccountForActionMode);
+			mode.finish();
+		}
+		return true;
+	}
+
+	@Override
+	public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+		MenuInflater inflater = mode.getMenuInflater();
+        inflater.inflate(R.menu.manageaccounts_context, menu);
+		return true;
+	}
+
+	@Override
+	public void onDestroyActionMode(ActionMode mode) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+		if (selectedAccountForActionMode.isOptionSet(Account.OPTION_DISABLED)) {
+        	menu.findItem(R.id.account_enable).setVisible(true);
+        	menu.findItem(R.id.account_disable).setVisible(false);
+        } else {
+        	menu.findItem(R.id.account_disable).setVisible(true);
+        	menu.findItem(R.id.account_enable).setVisible(false);
+        }
+		return true;
+	}
+	
+	@Override
+	public void onActionModeStarted(ActionMode mode) {
+		super.onActionModeStarted(mode);
+		this.isActionMode = true;
+	}
+	
+	@Override
+	public void onActionModeFinished(ActionMode mode) {
+		super.onActionModeFinished(mode);
+		this.isActionMode = false;
+		accountListView.clearChoices();
+		accountListView.requestLayout();
+		accountListView.post(new Runnable() {
+            @Override
+            public void run() {
+                accountListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
+            }
+        });
+	}
 }

src/de/gultsch/chat/ui/NewConversationActivity.java 🔗

@@ -185,7 +185,7 @@ public class NewConversationActivity extends XmppActivity {
 	
 					AlertDialog.Builder builder = new AlertDialog.Builder(activity);
 					builder.setTitle("Choose account");
-					builder.setSingleChoiceItems(accountList,0,new OnClickListener() {
+					builder.setItems(accountList,new OnClickListener() {
 						
 						@Override
 						public void onClick(DialogInterface dialog, int which) {