diff --git a/src/cheogram/res/layout/command_page.xml b/src/cheogram/res/layout/command_page.xml
index c84fd6d4742414897a3f0d2eaa819a4f1f67da9f..667b901203caaaec46f7f03d12affd14d0a4a4b7 100644
--- a/src/cheogram/res/layout/command_page.xml
+++ b/src/cheogram/res/layout/command_page.xml
@@ -10,20 +10,20 @@
android:paddingTop="8dp"
android:layout_width="match_parent"
android:layout_height="fill_parent"
- android:layout_above="@+id/done"
+ android:layout_above="@+id/actions"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
-
+ android:horizontalSpacing="0dp"
+ android:verticalSpacing="0dp"
+ android:numColumns="2" />
+
diff --git a/src/cheogram/res/values/strings.xml b/src/cheogram/res/values/strings.xml
index 9b3ed33aed85bc6d5108850aff0327d45b367e15..bc35884e59447bf7e5e1e97047d38510e84e5033 100644
--- a/src/cheogram/res/values/strings.xml
+++ b/src/cheogram/res/values/strings.xml
@@ -13,4 +13,9 @@
If your contact is nearby, they can also scan the code below to accept your invitation.
Join %1$s and chat with me: %2$s
Share invite with…
+ Cancel
+ Next
+ Back
+ Finish
+ Close
diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java
index 7e42aca507be84850c53c92a7368662004174292..ec7e8c9b9190e7cab082d5c81cc6a42e9400b9fb 100644
--- a/src/main/java/eu/siacs/conversations/entities/Conversation.java
+++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java
@@ -2,21 +2,25 @@ package eu.siacs.conversations.entities;
import android.content.ContentValues;
import android.database.Cursor;
+import android.database.DataSetObserver;
import android.net.Uri;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
+import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
+import android.widget.TextView;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.viewpager.widget.PagerAdapter;
@@ -1225,6 +1229,11 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
mPager.setCurrentItem(getCount() - 1);
}
+ public void removeSession(CommandSession session) {
+ sessions.remove(session);
+ notifyDataSetChanged();
+ }
+
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
@@ -1235,14 +1244,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
CommandSession session = sessions.get(position-2);
CommandPageBinding binding = DataBindingUtil.inflate(LayoutInflater.from(container.getContext()), R.layout.command_page, container, false);
container.addView(binding.getRoot());
- binding.form.setAdapter(session);
- binding.done.setOnClickListener((button) -> {
- if (session.execute()) {
- sessions.remove(session);
- notifyDataSetChanged();
- }
- });
-
session.setBinding(binding);
return session;
}
@@ -1519,10 +1520,35 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
protected IqPacket response = null;
protected Element responseElement = null;
protected XmppConnectionService xmppConnectionService;
+ protected ArrayAdapter actionsAdapter;
CommandSession(String title, XmppConnectionService xmppConnectionService) {
mTitle = title;
this.xmppConnectionService = xmppConnectionService;
+ actionsAdapter = new ArrayAdapter(xmppConnectionService, R.layout.simple_list_item) {
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View v = super.getView(position, convertView, parent);
+ TextView tv = (TextView) v.findViewById(android.R.id.text1);
+ tv.setGravity(Gravity.CENTER);
+ int resId = xmppConnectionService.getResources().getIdentifier("action_" + tv.getText() , "string" , xmppConnectionService.getPackageName());
+ if (resId != 0) tv.setText(xmppConnectionService.getResources().getString(resId));
+ tv.setTextColor(ContextCompat.getColor(xmppConnectionService, R.color.white));
+ tv.setBackgroundColor(UIHelper.getColorForName(tv.getText().toString()));
+ return v;
+ }
+ };
+ actionsAdapter.registerDataSetObserver(new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ if (mBinding == null) return;
+
+ mBinding.actions.setNumColumns(actionsAdapter.getCount() > 1 ? 2 : 1);
+ }
+
+ @Override
+ public void onInvalidated() {}
+ });
}
public String getTitle() {
@@ -1532,10 +1558,19 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
public void updateWithResponse(IqPacket iq) {
this.responseElement = null;
this.response = iq;
+ this.actionsAdapter.clear();
Element command = iq.findChild("command", "http://jabber.org/protocol/commands");
if (iq.getType() == IqPacket.TYPE.RESULT && command != null) {
for (Element el : command.getChildren()) {
+ if (el.getName().equals("actions") && el.getNamespace().equals("http://jabber.org/protocol/commands")) {
+ for (Element action : el.getChildren()) {
+ if (!el.getNamespace().equals("http://jabber.org/protocol/commands")) continue;
+ if (action.getName().equals("execute")) continue;
+
+ actionsAdapter.add(action.getName());
+ }
+ }
if (el.getName().equals("x") && el.getNamespace().equals("jabber:x:data")) {
String title = el.findChildContent("title", "jabber:x:data");
if (title != null) {
@@ -1562,6 +1597,12 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
}
}
+ if (actionsAdapter.getCount() > 0) {
+ if (actionsAdapter.getPosition("cancel") < 0) actionsAdapter.insert("cancel", 0);
+ } else {
+ actionsAdapter.add("close");
+ }
+
notifyDataSetChanged();
}
@@ -1679,6 +1720,14 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
}
public boolean execute() {
+ return execute("execute");
+ }
+
+ public boolean execute(int actionPosition) {
+ return execute(actionsAdapter.getItem(actionPosition));
+ }
+
+ public boolean execute(String action) {
if (response == null || responseElement == null) return true;
Element command = response.findChild("command", "http://jabber.org/protocol/commands");
if (command == null) return true;
@@ -1695,7 +1744,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
final Element c = packet.addChild("command", Namespace.COMMANDS);
c.setAttribute("node", command.getAttribute("node"));
c.setAttribute("sessionid", command.getAttribute("sessionid"));
- c.setAttribute("action", "execute");
+ c.setAttribute("action", action);
c.addChild(responseElement);
xmppConnectionService.sendIqPacket(getAccount(), packet, (a, iq) -> {
@@ -1713,6 +1762,15 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
@Override
public boolean canScrollVertically() { return getItemCount() > 1; }
});
+ mBinding.form.setAdapter(this);
+ mBinding.actions.setAdapter(actionsAdapter);
+ mBinding.actions.setOnItemClickListener((parent, v, pos, id) -> {
+ if (execute(pos)) {
+ removeSession(CommandSession.this);
+ }
+ });
+
+ actionsAdapter.notifyDataSetChanged();
}
}
}