diff --git a/src/cheogram/res/layout/command_text_field.xml b/src/cheogram/res/layout/command_text_field.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8d0d362bc9618e8bb851f43384cda2feecab14c3
--- /dev/null
+++ b/src/cheogram/res/layout/command_text_field.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java
index 1ca3c5b3ec70185a527522866fefb5382941bd86..67f3ccf70ebdcc640e853c77023fc44230b88762 100644
--- a/src/main/java/eu/siacs/conversations/entities/Conversation.java
+++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java
@@ -3,7 +3,9 @@ package eu.siacs.conversations.entities;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
+import android.text.Editable;
import android.text.TextUtils;
+import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -42,6 +44,7 @@ import eu.siacs.conversations.crypto.PgpDecryptionService;
import eu.siacs.conversations.databinding.CommandPageBinding;
import eu.siacs.conversations.databinding.CommandNoteBinding;
import eu.siacs.conversations.databinding.CommandResultFieldBinding;
+import eu.siacs.conversations.databinding.CommandTextFieldBinding;
import eu.siacs.conversations.databinding.CommandWebviewBinding;
import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.services.AvatarService;
@@ -1201,7 +1204,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
}
public void startCommand(Element command, XmppConnectionService xmppConnectionService) {
- CommandSession session = new CommandSession(command.getAttribute("name"));
+ CommandSession session = new CommandSession(command.getAttribute("name"), xmppConnectionService);
final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
packet.setTo(command.getAttributeAsJid("jid"));
@@ -1231,8 +1234,10 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
container.addView(binding.getRoot());
binding.form.setAdapter(session);
binding.done.setOnClickListener((button) -> {
- sessions.remove(session);
- notifyDataSetChanged();
+ if (session.execute()) {
+ sessions.remove(session);
+ notifyDataSetChanged();
+ }
});
session.setBinding(binding);
@@ -1368,6 +1373,49 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
}
}
+ class TextFieldViewHolder extends ViewHolder implements TextWatcher {
+ public TextFieldViewHolder(CommandTextFieldBinding binding) {
+ super(binding);
+ binding.textinput.addTextChangedListener(this);
+ }
+ protected Element mValue = null;
+
+ @Override
+ public void bind(Element field) {
+ String label = field.getAttribute("label");
+ if (label == null) label = field.getAttribute("var");
+ if (label == null) label = "";
+ binding.textinputLayout.setHint(label);
+
+ String desc = field.findChildContent("desc", "jabber:x:data");
+ if (desc == null) {
+ binding.desc.setVisibility(View.GONE);
+ } else {
+ binding.desc.setVisibility(View.VISIBLE);
+ binding.desc.setText(desc);
+ }
+
+ mValue = field.findChild("value", "jabber:x:data");
+ if (mValue == null) {
+ mValue = field.addChild("value", "jabber:x:data");
+ }
+ binding.textinput.setText(mValue.getContent());
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (mValue == null) return;
+
+ mValue.setContent(s.toString());
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int count, int after) { }
+ }
+
class WebViewHolder extends ViewHolder {
public WebViewHolder(CommandWebviewBinding binding) { super(binding); }
@@ -1390,14 +1438,17 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
final int TYPE_NOTE = 2;
final int TYPE_WEB = 3;
final int TYPE_RESULT_FIELD = 4;
+ final int TYPE_TEXT_FIELD = 5;
protected String mTitle;
protected CommandPageBinding mBinding = null;
protected IqPacket response = null;
protected Element responseElement = null;
+ protected XmppConnectionService xmppConnectionService;
- CommandSession(String title) {
+ CommandSession(String title, XmppConnectionService xmppConnectionService) {
mTitle = title;
+ this.xmppConnectionService = xmppConnectionService;
}
public String getTitle() {
@@ -1496,7 +1547,12 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
if (item.getName().equals("note")) return TYPE_NOTE;
if (item.getNamespace().equals("jabber:x:oob")) return TYPE_WEB;
if (item.getName().equals("instructions") && item.getNamespace().equals("jabber:x:data")) return TYPE_NOTE;
- if (item.getName().equals("field") && item.getNamespace().equals("jabber:x:data")) return TYPE_RESULT_FIELD;
+ if (item.getName().equals("field") && item.getNamespace().equals("jabber:x:data")) {
+ String formType = responseElement.getAttribute("type");
+ String fieldType = item.getAttribute("type");
+ if (formType.equals("result") || fieldType.equals("fixed")) return TYPE_RESULT_FIELD;
+ if (formType.equals("form")) return TYPE_TEXT_FIELD;
+ }
return -1;
} else {
return TYPE_ERROR;
@@ -1522,6 +1578,10 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
CommandResultFieldBinding binding = DataBindingUtil.inflate(LayoutInflater.from(container.getContext()), R.layout.command_result_field, container, false);
return new ResultFieldViewHolder(binding);
}
+ case TYPE_TEXT_FIELD: {
+ CommandTextFieldBinding binding = DataBindingUtil.inflate(LayoutInflater.from(container.getContext()), R.layout.command_text_field, container, false);
+ return new TextFieldViewHolder(binding);
+ }
default:
throw new IllegalArgumentException("Unknown viewType: " + viewType);
}
@@ -1536,6 +1596,35 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
return mBinding.getRoot();
}
+ public boolean execute() {
+ if (response == null || responseElement == null) return true;
+ Element command = response.findChild("command", "http://jabber.org/protocol/commands");
+ if (command == null) return true;
+ String status = command.getAttribute("status");
+ if (status == null || !status.equals("executing")) return true;
+ if (!responseElement.getName().equals("x") || !responseElement.getNamespace().equals("jabber:x:data")) return true;
+ String formType = responseElement.getAttribute("type");
+ if (formType == null || !formType.equals("form")) return true;
+
+ responseElement.setAttribute("type", "submit");
+
+ final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
+ packet.setTo(response.getFrom());
+ 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.addChild(responseElement);
+
+ xmppConnectionService.sendIqPacket(getAccount(), packet, (a, iq) -> {
+ getView().post(() -> {
+ updateWithResponse(iq);
+ });
+ });
+
+ return false;
+ }
+
public void setBinding(CommandPageBinding b) {
mBinding = b;
mBinding.form.setLayoutManager(new LinearLayoutManager(mPager.getContext()) {