From 52da0fe7c9c68d4545f068fb84efbf0854c37392 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 28 Jan 2014 19:21:54 +0100 Subject: account management --- src/de/gultsch/chat/entities/Account.java | 74 +++++++- src/de/gultsch/chat/entities/Message.java | 2 +- .../gultsch/chat/persistance/DatabaseBackend.java | 33 +++- .../chat/services/XmppConnectionService.java | 16 ++ src/de/gultsch/chat/ui/ConversationFragment.java | 22 +-- src/de/gultsch/chat/ui/EditAccount.java | 196 +++++++++++++++++++++ src/de/gultsch/chat/ui/ManageAccountActivity.java | 139 ++++++++++++++- .../gultsch/chat/ui/NewConversationActivity.java | 16 +- src/de/gultsch/chat/utils/Validator.java | 14 ++ 9 files changed, 485 insertions(+), 27 deletions(-) create mode 100644 src/de/gultsch/chat/ui/EditAccount.java create mode 100644 src/de/gultsch/chat/utils/Validator.java (limited to 'src') diff --git a/src/de/gultsch/chat/entities/Account.java b/src/de/gultsch/chat/entities/Account.java index 5b83ca79..5f95af63 100644 --- a/src/de/gultsch/chat/entities/Account.java +++ b/src/de/gultsch/chat/entities/Account.java @@ -1,18 +1,86 @@ package de.gultsch.chat.entities; import android.content.ContentValues; +import android.database.Cursor; +import android.util.Log; public class Account extends AbstractEntity{ private static final long serialVersionUID = 6174825093869578035L; + public static final String TABLENAME = "accounts"; + + public static final String USERNAME = "username"; + public static final String SERVER = "server"; + public static final String PASSWORD = "password"; + + protected String username; + protected String server; + protected String password; + + protected boolean online = false; + public Account() { - this.uuid = ""; + this.uuid = "0"; + } + + public Account(String username, String server, String password) { + this(java.util.UUID.randomUUID().toString(),username,server,password); + } + public Account(String uuid, String username, String server,String password) { + this.uuid = uuid; + this.username = username; + this.server = server; + this.password = password; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getServer() { + return server; } + + public void setServer(String server) { + this.server = server; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public boolean isOnline() { + return online; + } + + public String getJid() { + return username+"@"+server; + } + @Override public ContentValues getContentValues() { - // TODO Auto-generated method stub - return null; + ContentValues values = new ContentValues(); + values.put(UUID,uuid); + values.put(USERNAME, username); + values.put(SERVER, server); + values.put(PASSWORD, password); + return values; + } + + public static Account fromCursor(Cursor cursor) { + return new Account(cursor.getString(cursor.getColumnIndex(UUID)), + cursor.getString(cursor.getColumnIndex(USERNAME)), + cursor.getString(cursor.getColumnIndex(SERVER)), + cursor.getString(cursor.getColumnIndex(PASSWORD))); } } diff --git a/src/de/gultsch/chat/entities/Message.java b/src/de/gultsch/chat/entities/Message.java index b52e44b4..130435b9 100644 --- a/src/de/gultsch/chat/entities/Message.java +++ b/src/de/gultsch/chat/entities/Message.java @@ -54,7 +54,7 @@ public class Message extends AbstractEntity { @Override public ContentValues getContentValues() { ContentValues values = new ContentValues(); - values.put(UUID, this.uuid); + values.put(UUID, uuid); values.put(CONVERSATION, conversationUuid); values.put(COUNTERPART, counterpart); values.put(BODY, body); diff --git a/src/de/gultsch/chat/persistance/DatabaseBackend.java b/src/de/gultsch/chat/persistance/DatabaseBackend.java index 0689851f..677ab748 100644 --- a/src/de/gultsch/chat/persistance/DatabaseBackend.java +++ b/src/de/gultsch/chat/persistance/DatabaseBackend.java @@ -11,6 +11,7 @@ import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; public class DatabaseBackend extends SQLiteOpenHelper { @@ -36,6 +37,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { + Message.COUNTERPART + " TEXT, " + Message.BODY + " TEXT, " + Message.ENCRYPTION + " NUMBER, " + Message.STATUS + " NUMBER)"); + db.execSQL("create table "+Account.TABLENAME+"("+Account.UUID+" TEXT,"+Account.USERNAME+" TEXT,"+Account.SERVER+" TEXT,"+Account.PASSWORD+" TEXT)"); } @Override @@ -60,6 +62,11 @@ public class DatabaseBackend extends SQLiteOpenHelper { SQLiteDatabase db = this.getWritableDatabase(); db.insert(Message.TABLENAME, null, message.getContentValues()); } + + public void createAccount(Account account) { + SQLiteDatabase db = this.getWritableDatabase(); + db.insert(Account.TABLENAME,null, account.getContentValues()); + } public int getConversationCount() { SQLiteDatabase db = this.getReadableDatabase(); @@ -107,9 +114,33 @@ public class DatabaseBackend extends SQLiteOpenHelper { } public void updateConversation(Conversation conversation) { - SQLiteDatabase db = this.getReadableDatabase(); + SQLiteDatabase db = this.getWritableDatabase(); String[] args = {conversation.getUuid()}; db.update(Conversation.TABLENAME, conversation.getContentValues(),Conversation.UUID+"=?",args); } + + public List getAccounts() { + List list = new ArrayList(); + SQLiteDatabase db = this.getReadableDatabase(); + Cursor cursor = db.query(Account.TABLENAME, null, null, null, null, null, null); + Log.d("gultsch","found "+cursor.getCount()+" accounts"); + while (cursor.moveToNext()) { + list.add(Account.fromCursor(cursor)); + } + return list; + } + + public void updateAccount(Account account) { + SQLiteDatabase db = this.getWritableDatabase(); + String[] args = {account.getUuid()}; + db.update(Account.TABLENAME, account.getContentValues(),Account.UUID+"=?",args); + } + + public void deleteAccount(Account account) { + SQLiteDatabase db = this.getWritableDatabase(); + String[] args = {account.getUuid()}; + Log.d("gultsch","backend trying to delete account with uuid:"+account.getUuid()); + db.delete(Account.TABLENAME,Account.UUID+"=?",args); + } } diff --git a/src/de/gultsch/chat/services/XmppConnectionService.java b/src/de/gultsch/chat/services/XmppConnectionService.java index 20af9742..b8a54523 100644 --- a/src/de/gultsch/chat/services/XmppConnectionService.java +++ b/src/de/gultsch/chat/services/XmppConnectionService.java @@ -48,6 +48,10 @@ public class XmppConnectionService extends Service { return databaseBackend.getConversations(status); } + public List getAccounts() { + return databaseBackend.getAccounts(); + } + public List getMessages(Conversation conversation) { return databaseBackend.getMessages(conversation, 100); } @@ -72,4 +76,16 @@ public class XmppConnectionService extends Service { public int getConversationCount() { return this.databaseBackend.getConversationCount(); } + + public void createAccount(Account account) { + databaseBackend.createAccount(account); + } + + public void updateAccount(Account account) { + databaseBackend.updateAccount(account); + } + + public void deleteAccount(Account account) { + databaseBackend.deleteAccount(account); + } } diff --git a/src/de/gultsch/chat/ui/ConversationFragment.java b/src/de/gultsch/chat/ui/ConversationFragment.java index 5ba58bbf..1ae04ce9 100644 --- a/src/de/gultsch/chat/ui/ConversationFragment.java +++ b/src/de/gultsch/chat/ui/ConversationFragment.java @@ -154,17 +154,15 @@ public class ConversationFragment extends Fragment { this.conversation = activity.getConversationList().get(activity.getSelectedConversation()); this.messageList.clear(); this.messageList.addAll(this.conversation.getMessages()); + // rendering complete. now go tell activity to close pane + if (!activity.shouldPaneBeOpen()) { + activity.getSlidingPaneLayout().closePane(); + } + + int size = this.messageList.size(); + if (size >= 1) + messagesView.setSelection(size - 1); } - - - // rendering complete. now go tell activity to close pane - if (!activity.shouldPaneBeOpen()) { - activity.getSlidingPaneLayout().closePane(); - } - - int size = this.messageList.size(); - if (size >= 1) - messagesView.setSelection(size - 1); } public void onBackendConnected() { @@ -172,5 +170,9 @@ public class ConversationFragment extends Fragment { this.conversation = activity.getConversationList().get(activity.getSelectedConversation()); this.messageList.clear(); this.messageList.addAll(this.conversation.getMessages()); + // rendering complete. now go tell activity to close pane + if (!activity.shouldPaneBeOpen()) { + activity.getSlidingPaneLayout().closePane(); + } } } diff --git a/src/de/gultsch/chat/ui/EditAccount.java b/src/de/gultsch/chat/ui/EditAccount.java new file mode 100644 index 00000000..7cb48472 --- /dev/null +++ b/src/de/gultsch/chat/ui/EditAccount.java @@ -0,0 +1,196 @@ +package de.gultsch.chat.ui; + +import de.gultsch.chat.R; +import de.gultsch.chat.entities.Account; +import de.gultsch.chat.utils.Validator; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.EditText; +import android.widget.RelativeLayout; +import android.widget.TextView; + +public class EditAccount extends DialogFragment { + + protected Account account; + + public void setAccount(Account account) { + this.account = account; + } + + public interface EditAccountListener { + public void onAccountEdited(Account account); + + public void onAccountDelete(Account account); + } + + protected EditAccountListener listener = null; + + public void setEditAccountListener(EditAccountListener listener) { + this.listener = listener; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + LayoutInflater inflater = getActivity().getLayoutInflater(); + View view = inflater.inflate(R.layout.edit_account_dialog, null); + final EditText jidText = (EditText) view.findViewById(R.id.account_jid); + final EditText usernameText = (EditText) view + .findViewById(R.id.account_username); + final EditText serverText = (EditText) view + .findViewById(R.id.account_server); + final TextView usernameDesc = (TextView) view + .findViewById(R.id.textView2); + final TextView confirmPwDesc = (TextView) view.findViewById(R.id.account_confirm_password_desc); + CheckBox showAdvanced = (CheckBox) view + .findViewById(R.id.account_show_advanced); + final RelativeLayout advancedOptions = (RelativeLayout) view + .findViewById(R.id.advanced_options); + showAdvanced.setOnCheckedChangeListener(new OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + if (isChecked) { + advancedOptions.setVisibility(View.VISIBLE); + usernameDesc.setText("Username"); + usernameText.setVisibility(View.VISIBLE); + jidText.setVisibility(View.GONE); + } else { + advancedOptions.setVisibility(View.GONE); + usernameDesc.setText("Jabber ID"); + usernameText.setVisibility(View.GONE); + jidText.setVisibility(View.VISIBLE); + } + } + }); + + final EditText password = (EditText) view + .findViewById(R.id.account_password); + final EditText passwordConfirm = (EditText) view + .findViewById(R.id.account_password_confirm2); + final CheckBox registerAccount = (CheckBox) view + .findViewById(R.id.edit_account_register_new); + + final String okButtonDesc; + + if (account != null) { + builder.setTitle("Edit account"); + registerAccount.setVisibility(View.GONE); + jidText.setText(account.getJid()); + password.setText(account.getPassword()); + usernameText.setText(account.getUsername()); + serverText.setText(account.getServer()); + okButtonDesc = "Edit"; + builder.setNegativeButton("Delete Account", new OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle("Are you sure?"); + builder.setIconAttribute(android.R.attr.alertDialogIcon); + builder.setMessage("If you delete your account your entire conversation history will be lost"); + builder.setPositiveButton("Delete", new OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + if (listener!=null) { + listener.onAccountDelete(account); + } + } + }); + builder.setNegativeButton("Cancel",null); + builder.create().show(); + } + }); + } else { + builder.setTitle("Add account"); + okButtonDesc = "Add"; + } + + registerAccount + .setOnCheckedChangeListener(new OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + AlertDialog d = (AlertDialog) getDialog(); + Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE); + if (isChecked) { + positiveButton.setText("Register"); + passwordConfirm.setVisibility(View.VISIBLE); + confirmPwDesc.setVisibility(View.VISIBLE); + } else { + passwordConfirm.setVisibility(View.GONE); + positiveButton.setText("Add"); + confirmPwDesc.setVisibility(View.GONE); + } + } + }); + + builder.setView(view); + builder.setNeutralButton("Cancel", null); + builder.setPositiveButton(okButtonDesc, null); + return builder.create(); + } + + @Override + public void onStart() { + super.onStart(); + final AlertDialog d = (AlertDialog) getDialog(); + Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE); + positiveButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + boolean showAdvanced = ((CheckBox) d.findViewById(R.id.account_show_advanced)).isChecked(); + EditText jidEdit = (EditText) d.findViewById(R.id.account_jid); + String jid = jidEdit.getText().toString(); + EditText usernameEdit = (EditText) d.findViewById(R.id.account_username); + String username = usernameEdit.getText().toString(); + EditText serverEdit = (EditText) d.findViewById(R.id.account_server); + String server = serverEdit.getText().toString(); + EditText passwordEdit = (EditText) d.findViewById(R.id.account_password); + String password = passwordEdit.getText().toString(); + if (!showAdvanced) { + if (Validator.isValidJid(jid)) { + String[] parts = jid.split("@"); + username = parts[0]; + server = parts[1]; + } else { + jidEdit.setError("Invalid Jabber ID"); + return; + } + } else { + if (username.length()==0) { + usernameEdit.setError("username is too short"); + return; + } else if (server.length()==0) { + serverEdit.setError("server is too short"); + return; + } + } + if (account!=null) { + account.setPassword(password); + account.setUsername(username); + account.setServer(server); + } else { + account = new Account(username, server, password); + } + if (listener!=null) { + listener.onAccountEdited(account); + d.dismiss(); + } + } + }); + } +} diff --git a/src/de/gultsch/chat/ui/ManageAccountActivity.java b/src/de/gultsch/chat/ui/ManageAccountActivity.java index 741f60c3..8ba092db 100644 --- a/src/de/gultsch/chat/ui/ManageAccountActivity.java +++ b/src/de/gultsch/chat/ui/ManageAccountActivity.java @@ -1,7 +1,142 @@ package de.gultsch.chat.ui; -import android.app.Activity; +import java.util.ArrayList; +import java.util.List; -public class ManageAccountActivity extends Activity { +import de.gultsch.chat.R; +import de.gultsch.chat.entities.Account; +import de.gultsch.chat.ui.EditAccount.EditAccountListener; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; +public class ManageAccountActivity extends XmppActivity { + + + protected List accountList = new ArrayList(); + protected ListView accountListView; + protected ArrayAdapter accountListViewAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + setContentView(R.layout.manage_accounts); + + accountListView = (ListView) findViewById(R.id.account_list); + accountListViewAdapter = new ArrayAdapter(getApplicationContext(), R.layout.account_row, this.accountList) { + @Override + public View getView(int position, View view, ViewGroup parent) { + if (view == null) { + LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); + view = (View) inflater.inflate(R.layout.account_row, null); + } + ((TextView) view.findViewById(R.id.account_jid)).setText(getItem(position).getJid()); + + return view; + } + }; + 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); + } + + @Override + public void onAccountDelete(Account account) { + + Log.d("gultsch","deleting account:"+account.getJid()); + + xmppConnectionService.deleteAccount(account); + + //dont bother finding the right account in the frontend list. just reload + accountList.clear(); + accountList.addAll(xmppConnectionService.getAccounts()); + + accountListViewAdapter.notifyDataSetChanged(); + + } + }); + dialog.show(getFragmentManager(),"edit_account"); + } + }); + } + + @Override + public void onStart() { + super.onStart(); + if (xmppConnectionServiceBound) { + Log.d("gultsch","already bound"); + this.accountList.clear(); + this.accountList.addAll(xmppConnectionService + .getAccounts()); + accountListViewAdapter.notifyDataSetChanged(); + } + } + + @Override + void onBackendConnected() { + Log.d("gultsch","called on backend connected"); + this.accountList.clear(); + this.accountList.addAll(xmppConnectionService.getAccounts()); + accountListViewAdapter.notifyDataSetChanged(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.manageaccounts, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_settings: + startActivity(new Intent(this, SettingsActivity.class)); + break; + case R.id.action_add_account: + EditAccount dialog = new EditAccount(); + dialog.setEditAccountListener(new EditAccountListener() { + + @Override + public void onAccountEdited(Account account) { + xmppConnectionService.createAccount(account); + accountList.add(account); + accountListViewAdapter.notifyDataSetChanged(); + } + + @Override + public void onAccountDelete(Account account) { + //this will never be called + } + }); + dialog.show(getFragmentManager(),"add_account"); + break; + default: + break; + } + return super.onOptionsItemSelected(item); + } } diff --git a/src/de/gultsch/chat/ui/NewConversationActivity.java b/src/de/gultsch/chat/ui/NewConversationActivity.java index d3a3aa00..e30fcbb8 100644 --- a/src/de/gultsch/chat/ui/NewConversationActivity.java +++ b/src/de/gultsch/chat/ui/NewConversationActivity.java @@ -2,14 +2,13 @@ package de.gultsch.chat.ui; import java.util.LinkedHashMap; import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import de.gultsch.chat.R; import de.gultsch.chat.entities.Account; import de.gultsch.chat.entities.Contact; import de.gultsch.chat.entities.Conversation; import de.gultsch.chat.persistance.DatabaseBackend; +import de.gultsch.chat.utils.Validator; import android.os.Bundle; import android.provider.ContactsContract; import android.text.Editable; @@ -36,9 +35,6 @@ public class NewConversationActivity extends XmppActivity { final protected LinkedHashMap availableJabberContacts = new LinkedHashMap(); protected View newContactView; protected Contact newContact; - - public static final Pattern VALID_JID = - Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE); static final String[] PROJECTION = new String[] { ContactsContract.Data.CONTACT_ID, @@ -181,8 +177,7 @@ public class NewConversationActivity extends XmppActivity { } LinearLayout createNewContact = (LinearLayout) findViewById(R.id.create_new_contact); - Matcher matcher = VALID_JID.matcher(search); - if (matcher.find()) { + if (Validator.isValidJid(search)) { createNewContact.removeAllViews(); String name = search.split("@")[0]; newContact = new Contact(name,search,DEFAULT_PROFILE_PHOTO); @@ -217,9 +212,10 @@ public class NewConversationActivity extends XmppActivity { @Override void onBackendConnected() { - - getActionBar().setDisplayHomeAsUpEnabled(false); - getActionBar().setHomeButtonEnabled(false); + if (xmppConnectionService.getConversationCount()==0) { + getActionBar().setDisplayHomeAsUpEnabled(false); + getActionBar().setHomeButtonEnabled(false); + } } @Override diff --git a/src/de/gultsch/chat/utils/Validator.java b/src/de/gultsch/chat/utils/Validator.java new file mode 100644 index 00000000..a29ffa0a --- /dev/null +++ b/src/de/gultsch/chat/utils/Validator.java @@ -0,0 +1,14 @@ +package de.gultsch.chat.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Validator { + public static final Pattern VALID_JID = + Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE); + + public static boolean isValidJid(String jid) { + Matcher matcher = VALID_JID.matcher(jid); + return matcher.find(); + } +} -- cgit v1.2.3