@@ -1406,6 +1406,10 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
pagerAdapter.startCommand(command, xmppConnectionService);
}
+ public void startMucConfig(XmppConnectionService xmppConnectionService) {
+ pagerAdapter.startMucConfig(xmppConnectionService);
+ }
+
public boolean switchToSession(final String node) {
return pagerAdapter.switchToSession(node);
}
@@ -1574,6 +1578,37 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
if (mPager != null) mPager.setCurrentItem(getCount() - 1);
}
+ public void startMucConfig(XmppConnectionService xmppConnectionService) {
+ MucConfigSession session = new MucConfigSession(xmppConnectionService);
+ final IqPacket packet = new IqPacket(IqPacket.TYPE.GET);
+ packet.setTo(Conversation.this.getJid().asBareJid());
+ packet.addChild("query", "http://jabber.org/protocol/muc#owner");
+
+ final TimerTask task = new TimerTask() {
+ @Override
+ public void run() {
+ if (getAccount().getStatus() != Account.State.ONLINE) {
+ final TimerTask self = this;
+ new Timer().schedule(new TimerTask() {
+ @Override
+ public void run() {
+ self.run();
+ }
+ }, 1000);
+ } else {
+ xmppConnectionService.sendIqPacket(getAccount(), packet, (a, iq) -> {
+ session.updateWithResponse(iq);
+ }, 120L);
+ }
+ }
+ };
+ task.run();
+
+ sessions.add(session);
+ notifyDataSetChanged();
+ if (mPager != null) mPager.setCurrentItem(getCount() - 1);
+ }
+
public void removeSession(ConversationPage session) {
sessions.remove(session);
notifyDataSetChanged();
@@ -3434,6 +3469,99 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
return null;
}
}
+
+ class MucConfigSession extends CommandSession {
+ MucConfigSession(XmppConnectionService xmppConnectionService) {
+ super("Configure Channel", null, xmppConnectionService);
+ }
+
+ @Override
+ protected void updateWithResponseUiThread(final IqPacket iq) {
+ Timer oldTimer = this.loadingTimer;
+ this.loadingTimer = new Timer();
+ oldTimer.cancel();
+ this.executing = false;
+ this.loading = false;
+ this.loadingHasBeenLong = false;
+ this.responseElement = null;
+ this.fillableFieldCount = 0;
+ this.reported = null;
+ this.response = iq;
+ this.items.clear();
+ this.actionsAdapter.clear();
+ layoutManager.setSpanCount(1);
+
+ final Element query = iq.findChild("query", "http://jabber.org/protocol/muc#owner");
+ if (iq.getType() == IqPacket.TYPE.RESULT && query != null) {
+ final Data form = Data.parse(query.findChild("x", "jabber:x:data"));
+ final String title = form.getTitle();
+ if (title != null) {
+ mTitle = title;
+ ConversationPagerAdapter.this.notifyDataSetChanged();
+ }
+
+ this.responseElement = form;
+ setupReported(form.findChild("reported", "jabber:x:data"));
+ if (mBinding != null) mBinding.form.setLayoutManager(setupLayoutManager());
+
+ if (actionsAdapter.countExceptCancel() < 1) {
+ actionsAdapter.add(Pair.create("save", "Save"));
+ }
+
+ if (actionsAdapter.getPosition("cancel") < 0) {
+ actionsAdapter.insert(Pair.create("cancel", "cancel"), 0);
+ }
+ } else if (iq.getType() == IqPacket.TYPE.RESULT) {
+ expectingRemoval = true;
+ removeSession(this);
+ return;
+ } else {
+ actionsAdapter.add(Pair.create("close", "close"));
+ }
+
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public synchronized boolean execute(String action) {
+ if ("cancel".equals(action)) {
+ final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
+ packet.setTo(response.getFrom());
+ final Element form = packet
+ .addChild("query", "http://jabber.org/protocol/muc#owner")
+ .addChild("x", "jabber:x:data");
+ form.setAttribute("type", "cancel");
+ xmppConnectionService.sendIqPacket(getAccount(), packet, null);
+ return true;
+ }
+
+ if (!"save".equals(action)) return true;
+
+ final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
+ packet.setTo(response.getFrom());
+
+ String formType = responseElement == null ? null : responseElement.getAttribute("type");
+ if (responseElement != null &&
+ responseElement.getName().equals("x") &&
+ responseElement.getNamespace().equals("jabber:x:data") &&
+ formType != null && formType.equals("form")) {
+
+ responseElement.setAttribute("type", "submit");
+ packet
+ .addChild("query", "http://jabber.org/protocol/muc#owner")
+ .addChild(responseElement);
+ }
+
+ executing = true;
+ xmppConnectionService.sendIqPacket(getAccount(), packet, (a, iq) -> {
+ updateWithResponse(iq);
+ }, 120L);
+
+ loading();
+
+ return false;
+ }
+ }
}
public static class Thread {
@@ -3151,8 +3151,7 @@ public class ConversationFragment extends XmppFragment
binding.commandsView.setOnItemClickListener((parent, view, position, id) -> {
if (activity == null) return;
- final Element command = commandAdapter.getItem(position);
- activity.startCommand(ConversationFragment.this.conversation.getAccount(), command.getAttributeAsJid("jid"), command.getAttribute("node"));
+ commandAdapter.getItem(position).start(activity, ConversationFragment.this.conversation);
});
refreshCommands(false);
}
@@ -3169,6 +3168,11 @@ public class ConversationFragment extends XmppFragment
protected void refreshCommands(boolean delayShow) {
if (commandAdapter == null) return;
+ final CommandAdapter.MucConfig mucConfig =
+ conversation.getMucOptions().getSelf().getAffiliation().ranks(MucOptions.Affiliation.OWNER) ?
+ new CommandAdapter.MucConfig() :
+ null;
+
Jid commandJid = conversation.getContact().resourceWhichSupport(Namespace.COMMANDS);
if (commandJid == null && conversation.getMode() == Conversation.MODE_MULTI && conversation.getMucOptions().hasFeature(Namespace.COMMANDS)) {
commandJid = conversation.getJid().asBareJid();
@@ -3177,7 +3181,14 @@ public class ConversationFragment extends XmppFragment
commandJid = conversation.getJid();
}
if (commandJid == null) {
- conversation.hideViewPager();
+ binding.commandsViewProgressbar.setVisibility(View.GONE);
+ if (mucConfig == null) {
+ conversation.hideViewPager();
+ } else {
+ commandAdapter.clear();
+ commandAdapter.add(mucConfig);
+ conversation.showViewPager();
+ }
} else {
if (!delayShow) conversation.showViewPager();
binding.commandsViewProgressbar.setVisibility(View.VISIBLE);
@@ -3185,15 +3196,17 @@ public class ConversationFragment extends XmppFragment
if (activity == null) return;
activity.runOnUiThread(() -> {
+ binding.commandsViewProgressbar.setVisibility(View.GONE);
+ commandAdapter.clear();
if (iq.getType() == IqPacket.TYPE.RESULT) {
- binding.commandsViewProgressbar.setVisibility(View.GONE);
- commandAdapter.clear();
for (Element child : iq.query().getChildren()) {
if (!"item".equals(child.getName()) || !Namespace.DISCO_ITEMS.equals(child.getNamespace())) continue;
- commandAdapter.add(child);
+ commandAdapter.add(new CommandAdapter.Command0050(child));
}
}
+ if (mucConfig != null) commandAdapter.add(mucConfig);
+
if (commandAdapter.getCount() < 1) {
conversation.hideViewPager();
} else if (delayShow) {
@@ -3353,7 +3366,10 @@ public class ConversationFragment extends XmppFragment
private Element commandFor(final Jid jid, final String node) {
if (commandAdapter != null) {
for (int i = 0; i < commandAdapter.getCount(); i++) {
- Element command = commandAdapter.getItem(i);
+ final CommandAdapter.Command c = commandAdapter.getItem(i);
+ if (!(c instanceof CommandAdapter.Command0050)) continue;
+
+ final Element command = ((CommandAdapter.Command0050) c).el;
final String commandNode = command.getAttribute("node");
if (commandNode == null || !commandNode.equals(node)) continue;
@@ -9,11 +9,13 @@ import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import eu.siacs.conversations.R;
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.databinding.CommandRowBinding;
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.ui.ConversationsActivity;
+import eu.siacs.conversations.ui.XmppActivity;
+import eu.siacs.conversations.xml.Element;
-public class CommandAdapter extends ArrayAdapter<Element> {
+public class CommandAdapter extends ArrayAdapter<CommandAdapter.Command> {
public CommandAdapter(XmppActivity activity) {
super(activity, 0);
}
@@ -21,7 +23,37 @@ public class CommandAdapter extends ArrayAdapter<Element> {
@Override
public View getView(int position, View view, @NonNull ViewGroup parent) {
CommandRowBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.command_row, parent, false);
- binding.command.setText(getItem(position).getAttribute("name"));
+ binding.command.setText(getItem(position).getName());
return binding.getRoot();
}
+
+ public interface Command {
+ public String getName();
+ public void start(final ConversationsActivity activity, final Conversation conversation);
+ }
+
+ public static class Command0050 implements Command {
+ public final Element el;
+ public Command0050(Element el) { this.el = el; }
+
+ public String getName() {
+ return el.getAttribute("name");
+ }
+
+ public void start(final ConversationsActivity activity, final Conversation conversation) {
+ activity.startCommand(conversation.getAccount(), el.getAttributeAsJid("jid"), el.getAttribute("node"));
+ }
+ }
+
+ public static class MucConfig implements Command {
+ public MucConfig() { }
+
+ public String getName() {
+ return "⚙️ Configure Channel";
+ }
+
+ public void start(final ConversationsActivity activity, final Conversation conversation) {
+ conversation.startMucConfig(activity.xmppConnectionService);
+ }
+ }
}