add 'create conference' dialog

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/entities/Bookmark.java              |   5 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java |  23 
src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java       |   4 
src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java   |  13 
src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java   | 117 
src/main/res/layout/create_conference_dialog.xml                         |  42 
src/main/res/menu/start_conversation.xml                                 |  14 
src/main/res/values/strings.xml                                          |   5 
8 files changed, 203 insertions(+), 20 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/entities/Bookmark.java πŸ”—

@@ -50,9 +50,8 @@ public class Bookmark extends Element implements ListItem {
 
 	@Override
 	public String getDisplayName() {
-		if (this.mJoinedConversation != null
-				&& (this.mJoinedConversation.getMucOptions().getSubject() != null)) {
-			return this.mJoinedConversation.getMucOptions().getSubject();
+		if (this.mJoinedConversation != null) {
+			return this.mJoinedConversation.getName();
 		} else if (getBookmarkName() != null) {
 			return getBookmarkName();
 		} else {

src/main/java/eu/siacs/conversations/services/XmppConnectionService.java πŸ”—

@@ -26,6 +26,7 @@ import android.os.SystemClock;
 import android.preference.PreferenceManager;
 import android.provider.ContactsContract;
 import android.security.KeyChain;
+import android.util.Base64;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.LruCache;
@@ -2048,8 +2049,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 					}
 					return;
 				}
-				String localpart = new BigInteger(75, getRNG()).toString(32);
-				Jid jid = Jid.fromParts(localpart, server, null);
+				final Jid jid = Jid.fromParts(new BigInteger(64, getRNG()).toString(Character.MAX_RADIX), server, null);
 				final Conversation conversation = findOrCreateConversation(account, jid, true);
 				joinMuc(conversation, new OnConferenceJoined() {
 					@Override
@@ -2058,7 +2058,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 							@Override
 							public void onPushSucceeded() {
 								if (subject != null && !subject.trim().isEmpty()) {
-									pushSubjectToConference(conversation, subject);
+									pushSubjectToConference(conversation, subject.trim());
 								}
 								for (Jid invite : jids) {
 									invite(conversation, invite);
@@ -2066,6 +2066,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 								if (account.countPresences() > 1) {
 									directInvite(conversation, account.getJid().toBareJid());
 								}
+								saveConversationAsBookmark(conversation, subject);
 								if (callback != null) {
 									callback.success(conversation);
 								}
@@ -2073,6 +2074,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 
 							@Override
 							public void onPushFailed() {
+								archiveConversation(conversation);
 								if (callback != null) {
 									callback.error(R.string.conference_creation_failed, conversation);
 								}
@@ -3306,6 +3308,21 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 		return templates;
 	}
 
+	public void saveConversationAsBookmark(Conversation conversation, String name) {
+		Account account = conversation.getAccount();
+		Bookmark bookmark = new Bookmark(account, conversation.getJid().toBareJid());
+		if (!conversation.getJid().isBareJid()) {
+			bookmark.setNick(conversation.getJid().getResourcepart());
+		}
+		if (name != null && !name.trim().isEmpty()) {
+			bookmark.setBookmarkName(name.trim());
+		}
+		bookmark.setAutojoin(getPreferences().getBoolean("autojoin",true));
+		account.getBookmarks().add(bookmark);
+		pushBookmarks(account);
+		conversation.setBookmark(bookmark);
+	}
+
 	public interface OnMamPreferencesFetched {
 		void onPreferencesFetched(Element prefs);
 		void onPreferencesFetchFailed();

src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java πŸ”—

@@ -77,6 +77,8 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity {
 							String[] selection = getSelectedContactJids();
 							data.putExtra("contacts", selection);
 							data.putExtra("multiple", true);
+							data.putExtra(EXTRA_ACCOUNT,request.getStringExtra(EXTRA_ACCOUNT));
+							data.putExtra("subject", request.getStringExtra("subject"));
 							setResult(RESULT_OK, data);
 							finish();
 							return true;
@@ -121,6 +123,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity {
 				data.putExtra("conversation",
 						request.getStringExtra("conversation"));
 				data.putExtra("multiple", false);
+				data.putExtra("subject", request.getStringExtra("subject"));
 				setResult(RESULT_OK, data);
 				finish();
 			}
@@ -194,6 +197,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity {
 				data.putExtra("conversation",
 						request.getStringExtra("conversation"));
 				data.putExtra("multiple", false);
+				data.putExtra("subject", request.getStringExtra("subject"));
 				setResult(RESULT_OK, data);
 				finish();
 

src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java πŸ”—

@@ -26,7 +26,6 @@ import org.openintents.openpgp.util.OpenPgpUtils;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import eu.siacs.conversations.Config;
@@ -485,16 +484,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
 	}
 
 	protected void saveAsBookmark() {
-		Account account = mConversation.getAccount();
-		Bookmark bookmark = new Bookmark(account, mConversation.getJid().toBareJid());
-		if (!mConversation.getJid().isBareJid()) {
-			bookmark.setNick(mConversation.getJid().getResourcepart());
-		}
-		bookmark.setBookmarkName(mConversation.getMucOptions().getSubject());
-		bookmark.setAutojoin(getPreferences().getBoolean("autojoin",true));
-		account.getBookmarks().add(bookmark);
-		xmppConnectionService.pushBookmarks(account);
-		mConversation.setBookmark(bookmark);
+		xmppConnectionService.saveConversationAsBookmark(mConversation,
+				mConversation.getMucOptions().getSubject());
 	}
 
 	protected void deleteBookmark() {

src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java πŸ”—

@@ -10,6 +10,7 @@ import android.app.AlertDialog;
 import android.app.Fragment;
 import android.app.FragmentTransaction;
 import android.app.ListFragment;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
@@ -27,6 +28,7 @@ import android.support.v4.view.ViewPager;
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.util.Log;
+import android.util.Pair;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.KeyEvent;
@@ -54,6 +56,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.RunnableFuture;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import eu.siacs.conversations.Config;
@@ -94,6 +97,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
 	private EditText mSearchEditText;
 	private AtomicBoolean mRequestedContactsPermission = new AtomicBoolean(false);
 	private final int REQUEST_SYNC_CONTACTS = 0x3b28cf;
+	private final int REQUEST_CREATE_CONFERENCE = 0x3b39da;
 
 	private MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() {
 
@@ -201,6 +205,47 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
 		}
 	};
 	private String mInitialJid;
+	private Pair<Integer, Intent> mPostponedActivityResult;
+	private UiCallback<Conversation> mAdhocConferenceCallback = new UiCallback<Conversation>() {
+		@Override
+		public void success(final Conversation conversation) {
+			runOnUiThread(new Runnable() {
+				@Override
+				public void run() {
+					hideToast();
+					switchToConversation(conversation);
+				}
+			});
+		}
+
+		@Override
+		public void error(final int errorCode, Conversation object) {
+			runOnUiThread(new Runnable() {
+				@Override
+				public void run() {
+					replaceToast(getString(errorCode));
+				}
+			});
+		}
+
+		@Override
+		public void userInputRequried(PendingIntent pi, Conversation object) {
+
+		}
+	};
+	private Toast mToast;
+
+	protected void hideToast() {
+		if (mToast != null) {
+			mToast.cancel();
+		}
+	}
+
+	protected void replaceToast(String msg) {
+		hideToast();
+		mToast = Toast.makeText(this, msg ,Toast.LENGTH_LONG);
+		mToast.show();
+	}
 
 	@Override
 	public void onRosterUpdate() {
@@ -488,6 +533,36 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
 				});
 	}
 
+	private void showCreateConferenceDialog() {
+		final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+		builder.setTitle(R.string.create_conference);
+		final View dialogView = getLayoutInflater().inflate(R.layout.create_conference_dialog, null);
+		final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account);
+		final EditText subject = (EditText) dialogView.findViewById(R.id.subject);
+		populateAccountSpinner(this, mActivatedAccounts, spinner);
+		builder.setView(dialogView);
+		builder.setPositiveButton(R.string.choose_participants, new OnClickListener() {
+			@Override
+			public void onClick(DialogInterface dialog, int which) {
+				if (!xmppConnectionServiceBound) {
+					return;
+				}
+				final Account account = getSelectedAccount(spinner);
+				if (account == null) {
+					return;
+				}
+				Intent intent = new Intent(getApplicationContext(), ChooseContactActivity.class);
+				intent.putExtra("multiple", true);
+				intent.putExtra("show_enter_jid", true);
+				intent.putExtra("subject", subject.getText().toString());
+				intent.putExtra(EXTRA_ACCOUNT, account.getJid().toBareJid().toString());
+				startActivityForResult(intent, REQUEST_CREATE_CONFERENCE);
+			}
+		});
+		builder.setNegativeButton(R.string.cancel, null);
+		builder.create().show();
+	}
+
 	private Account getSelectedAccount(Spinner spinner) {
 		if (!spinner.isEnabled()) {
 			return null;
@@ -532,7 +607,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
 	public boolean onCreateOptionsMenu(Menu menu) {
 		getMenuInflater().inflate(R.menu.start_conversation, menu);
 		MenuItem menuCreateContact = menu.findItem(R.id.action_create_contact);
-		MenuItem menuCreateConference = menu.findItem(R.id.action_join_conference);
+		MenuItem menuCreateConference = menu.findItem(R.id.action_conference);
 		MenuItem menuHideOffline = menu.findItem(R.id.action_hide_offline);
 		menuHideOffline.setChecked(this.mHideOfflineContacts);
 		mMenuSearchView = menu.findItem(R.id.action_search);
@@ -564,6 +639,9 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
 			case R.id.action_join_conference:
 				showJoinConferenceDialog(null);
 				return true;
+			case R.id.action_create_conference:
+				showCreateConferenceDialog();
+				return true;
 			case R.id.action_scan_qr_code:
 				new IntentIntegrator(this).initiateScan();
 				return true;
@@ -616,6 +694,39 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
 					this.mPendingInvite = null;
 				}
 			}
+		} else if (resultCode == RESULT_OK) {
+			if (xmppConnectionServiceBound) {
+				this.mPostponedActivityResult = null;
+				if (requestCode == REQUEST_CREATE_CONFERENCE) {
+					Log.d(Config.LOGTAG,"account jid: "+ intent.getStringExtra(EXTRA_ACCOUNT));
+					Account account = extractAccount(intent);
+					final String subject = intent.getStringExtra("subject");
+					List<Jid> jids = new ArrayList<>();
+					if (intent.getBooleanExtra("multiple", false)) {
+						String[] toAdd = intent.getStringArrayExtra("contacts");
+						for (String item : toAdd) {
+							try {
+								jids.add(Jid.fromString(item));
+							} catch (InvalidJidException e) {
+								//ignored
+							}
+						}
+					} else {
+						try {
+							jids.add(Jid.fromString(intent.getStringExtra("contact")));
+						} catch (Exception e) {
+							//ignored
+						}
+					}
+					if (account != null && jids.size() > 1) {
+						xmppConnectionService.createAdhocConference(account, subject, jids, mAdhocConferenceCallback);
+						mToast = Toast.makeText(this, R.string.creating_conference,Toast.LENGTH_LONG);
+						mToast.show();
+					}
+				}
+			} else {
+				this.mPostponedActivityResult = new Pair<>(requestCode, intent);
+			}
 		}
 		super.onActivityResult(requestCode, requestCode, intent);
 	}
@@ -657,6 +768,10 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
 
 	@Override
 	protected void onBackendConnected() {
+		if (mPostponedActivityResult != null) {
+			onActivityResult(mPostponedActivityResult.first, RESULT_OK, mPostponedActivityResult.second);
+			this.mPostponedActivityResult = null;
+		}
 		this.mActivatedAccounts.clear();
 		for (Account account : xmppConnectionService.getAccounts()) {
 			if (account.getStatus() != Account.State.DISABLED) {

src/main/res/layout/create_conference_dialog.xml πŸ”—

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical"
+              android:paddingBottom="8dp"
+              android:paddingLeft="24dp"
+              android:paddingRight="24dp"
+              android:paddingTop="16dp">
+
+    <TextView
+        android:id="@+id/your_account"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/your_account"
+        android:textColor="@color/black87"
+        android:textSize="?attr/TextSizeBody" />
+
+    <Spinner
+        android:id="@+id/account"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:text="@string/conference_subject"
+        android:textColor="@color/black87"
+        android:textSize="?attr/TextSizeBody" />
+
+    <EditText
+        android:id="@+id/subject"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:hint="@string/edit_subject_hint"
+        android:inputType="textAutoComplete"
+        android:textColor="@color/black87"
+        android:textColorHint="@color/black54"
+        android:textSize="?attr/TextSizeBody"/>
+
+</LinearLayout>

src/main/res/menu/start_conversation.xml πŸ”—

@@ -13,10 +13,20 @@
         android:showAsAction="always"
         android:title="@string/create_contact" />
     <item
-        android:id="@+id/action_join_conference"
+        android:id="@+id/action_conference"
         android:icon="?attr/icon_add_group"
         android:showAsAction="always"
-        android:title="@string/join_conference" />
+        android:title="@string/join_or_create_conference">
+        <menu>
+            <item
+                android:id="@+id/action_join_conference"
+                android:title="@string/join_conference"/>
+            <item
+                android:id="@+id/action_create_conference"
+                android:title="@string/create_conference"/>
+
+        </menu>
+    </item>
     <item
         android:id="@+id/action_scan_qr_code"
         android:showAsAction="never"

src/main/res/values/strings.xml πŸ”—

@@ -644,4 +644,9 @@
 	<string name="device_does_not_support_battery_op">Your device does not support opting out of battery optimization</string>
 	<string name="show_password">Show password</string>
 	<string name="registration_please_wait">Registration failed: Try again later</string>
+	<string name="create_conference">Create conference</string>
+	<string name="join_or_create_conference">Join or create conference</string>
+	<string name="conference_subject">Subject</string>
+	<string name="choose_participants">Choose participants</string>
+	<string name="creating_conference">Creating conference…</string>
 </resources>