Detailed changes
@@ -17,15 +17,18 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
+import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import java.util.HashSet;
+import java.util.UUID;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityWelcomeBinding;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.Compatibility;
import eu.siacs.conversations.utils.InstallReferrerUtils;
import eu.siacs.conversations.utils.SignupUtils;
@@ -35,11 +38,12 @@ import eu.siacs.conversations.xmpp.Jid;
import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
-public class WelcomeActivity extends XmppActivity implements XmppConnectionService.OnAccountCreated, KeyChainAliasCallback {
+public class WelcomeActivity extends XmppActivity implements XmppConnectionService.OnAccountCreated, XmppConnectionService.OnAccountUpdate, KeyChainAliasCallback {
private static final int REQUEST_IMPORT_BACKUP = 0x63fb;
private XmppUri inviteUri;
+ private Account onboardingAccount = null;
public static void launch(AppCompatActivity activity) {
Intent intent = new Intent(activity, WelcomeActivity.class);
@@ -82,8 +86,21 @@ public class WelcomeActivity extends XmppActivity implements XmppConnectionServi
}
@Override
- protected void refreshUiReal() {
+ protected synchronized void refreshUiReal() {
+ if (onboardingAccount == null) return;
+ if (onboardingAccount.getStatus() != Account.State.ONLINE) return;
+ Intent intent = new Intent(this, StartConversationActivity.class);
+ intent.putExtra("init", true);
+ intent.putExtra(EXTRA_ACCOUNT, onboardingAccount.getJid().asBareJid().toEscapedString());
+ onboardingAccount = null;
+ startActivity(intent);
+ finish();
+ }
+
+ @Override
+ public void onAccountUpdate() {
+ refreshUi();
}
@Override
@@ -124,9 +141,18 @@ public class WelcomeActivity extends XmppActivity implements XmppConnectionServi
setSupportActionBar(binding.toolbar);
configureActionBar(getSupportActionBar(), false);
binding.registerNewAccount.setOnClickListener(v -> {
- final Intent intent = new Intent(this, MagicCreateActivity.class);
- addInviteUri(intent);
- startActivity(intent);
+ if (hasInviteUri()) {
+ final Intent intent = new Intent(this, MagicCreateActivity.class);
+ addInviteUri(intent);
+ startActivity(intent);
+ } else {
+ binding.registerNewAccount.setText("Working...");
+ binding.registerNewAccount.setEnabled(false);
+ onboardingAccount = new Account(Jid.ofLocalAndDomain(UUID.randomUUID().toString(), Config.ONBOARDING_DOMAIN.toEscapedString()), CryptoHelper.createPassword(new SecureRandom()));
+ onboardingAccount.setOption(Account.OPTION_REGISTER, true);
+ onboardingAccount.setOption(Account.OPTION_FIXED_USERNAME, true);
+ xmppConnectionService.createAccount(onboardingAccount);
+ }
});
binding.useExisting.setOnClickListener(v -> {
final List<Account> accounts = xmppConnectionService.getAccounts();
@@ -235,6 +261,12 @@ public class WelcomeActivity extends XmppActivity implements XmppConnectionServi
}
}
+ protected boolean hasInviteUri() {
+ final Intent from = getIntent();
+ if (from != null && from.hasExtra(StartConversationActivity.EXTRA_INVITE_URI)) return true;
+ return this.inviteUri != null;
+ }
+
public void addInviteUri(Intent to) {
final Intent from = getIntent();
if (from != null && from.hasExtra(StartConversationActivity.EXTRA_INVITE_URI)) {
@@ -48,6 +48,7 @@ public final class Config {
public static final String DOMAIN_LOCK = null; //only allow account creation for this domain
public static final String MAGIC_CREATE_DOMAIN = "chatterboxtown.us";
public static final Jid QUICKSY_DOMAIN = Jid.of("cheogram.com");
+ public static final Jid ONBOARDING_DOMAIN = Jid.of("onboarding.cheogram.com");
public static final String CHANNEL_DISCOVERY = "https://search.jabber.network";
@@ -797,7 +797,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
}
}
} else if ((QuickConversationsService.isConversations() || !Config.QUICKSY_DOMAIN.equals(contactJid.getDomain())) && isWithStranger()) {
- return contactJid;
+ return contactJid.equals(Jid.of("cheogram.com")) ? "Cheogram" : contactJid;
} else {
return this.getContact().getDisplayName();
}
@@ -2400,7 +2400,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
}
public void updateWithResponse(final IqPacket iq) {
- if (getView().isAttachedToWindow()) {
+ if (getView() != null && getView().isAttachedToWindow()) {
getView().post(() -> updateWithResponseUiThread(iq));
} else {
pendingResponsePacket = iq;
@@ -2706,6 +2706,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
}
public View getView() {
+ if (mBinding == null) return null;
return mBinding.getRoot();
}
@@ -2874,8 +2875,9 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
actionsAdapter.notifyDataSetChanged();
if (pendingResponsePacket != null) {
- updateWithResponseUiThread(pendingResponsePacket);
+ final IqPacket pending = pendingResponsePacket;
pendingResponsePacket = null;
+ updateWithResponseUiThread(pending);
}
}
@@ -1805,6 +1805,10 @@ public class XmppConnectionService extends Service {
sendMessage(message, true, delay);
}
+ public boolean isOnboarding() {
+ return getAccounts().size() == 1 && getAccounts().get(0).getJid().getDomain().equals(Config.ONBOARDING_DOMAIN);
+ }
+
public void requestEasyOnboardingInvite(final Account account, final EasyOnboardingInvite.OnInviteRequested callback) {
final XmppConnection connection = account.getXmppConnection();
final Jid jid = connection == null ? null : connection.getJidForCommand(Namespace.EASY_ONBOARDING_INVITE);
@@ -1202,6 +1202,8 @@ public class ConversationFragment extends XmppFragment
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
+ if (activity.xmppConnectionService.isOnboarding()) return;
+
menuInflater.inflate(R.menu.fragment_conversation, menu);
final MenuItem menuMucDetails = menu.findItem(R.id.action_muc_details);
final MenuItem menuContactDetails = menu.findItem(R.id.action_contact_details);
@@ -2997,6 +2999,7 @@ public class ConversationFragment extends XmppFragment
}
if (node != null && commandJid != null) {
conversation.startCommand(commandFor(commandJid, node), activity.xmppConnectionService);
+ if (activity.xmppConnectionService.isOnboarding()) binding.tabLayout.setVisibility(View.GONE);
}
});
return;
@@ -740,10 +740,10 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
final Conversation conversation = ((ConversationFragment) mainFragment).getConversation();
if (conversation != null) {
actionBar.setTitle(conversation.getName());
- actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayHomeAsUpEnabled(!xmppConnectionService.isOnboarding());
ActionBarUtil.setActionBarOnClickListener(
binding.toolbar,
- (v) -> openConversationDetails(conversation)
+ (v) -> { if(!xmppConnectionService.isOnboarding()) openConversationDetails(conversation); }
);
return;
}
@@ -95,9 +95,13 @@ import eu.siacs.conversations.ui.widget.SwipeRefreshListFragment;
import eu.siacs.conversations.utils.AccountUtils;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.utils.XmppUri;
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
import eu.siacs.conversations.xmpp.XmppConnection;
+import eu.siacs.conversations.xmpp.forms.Data;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
public class StartConversationActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate, OnRosterUpdate, OnUpdateBlocklist, CreatePrivateGroupChatDialog.CreateConferenceDialogListener, JoinConferenceDialog.JoinConferenceDialogListener, SwipeRefreshLayout.OnRefreshListener, CreatePublicChannelDialog.CreatePublicChannelDialogListener {
@@ -918,8 +922,11 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
final String accountJid = intent.getStringExtra(EXTRA_ACCOUNT);
intent = null;
boolean hasPstnOrSms = false;
+ Account onboardingAccount = null;
outer:
for (Account account : xmppConnectionService.getAccounts()) {
+ if (onboardingAccount == null && account.getJid().getDomain().equals(Config.ONBOARDING_DOMAIN)) onboardingAccount = account;
+
if (accountJid != null) {
if(account.getJid().asBareJid().toEscapedString().equals(accountJid)) {
selectedAccount = account;
@@ -941,9 +948,88 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
}
if (!hasPstnOrSms) {
- startCommand(selectedAccount, Jid.of("cheogram.com/CHEOGRAM%jabber:iq:register"), "jabber:iq:register");
- finish();
- return;
+ if (onboardingAccount != null && !selectedAccount.getJid().equals(onboardingAccount.getJid())) {
+ final Account onboardAccount = onboardingAccount;
+ final Account newAccount = selectedAccount;
+ final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
+ packet.setTo(Jid.of("cheogram.com"));
+ final Element c = packet.addChild("command", Namespace.COMMANDS);
+ c.setAttribute("node", "change jabber id");
+ c.setAttribute("action", "execute");
+
+ xmppConnectionService.sendIqPacket(onboardingAccount, packet, (a, iq) -> {
+ Element command = iq.findChild("command", "http://jabber.org/protocol/commands");
+ if (command == null) {
+ Log.e(Config.LOGTAG, "Did not get expected data form from cheogram, got: " + iq);
+ return;
+ }
+
+ Element form = command.findChild("x", "jabber:x:data");
+ Data dataForm = form == null ? null : Data.parse(form);
+ if (dataForm == null || dataForm.getFieldByName("new-jid") == null) {
+ Log.e(Config.LOGTAG, "Did not get expected data form from cheogram, got: " + iq);
+ return;
+ }
+
+ dataForm.put("new-jid", newAccount.getJid().toEscapedString());
+ dataForm.submit();
+ command.setAttribute("action", "execute");
+ iq.setTo(iq.getFrom());
+ iq.setAttribute("type", "set");
+ iq.removeAttribute("from");
+ iq.removeAttribute("id");
+ xmppConnectionService.sendIqPacket(a, iq, (a2, iq2) -> {
+ Element command2 = iq2.findChild("command", "http://jabber.org/protocol/commands");
+ if (command2 != null && command2.getAttribute("status") != null && command2.getAttribute("status").equals("completed")) {
+ final IqPacket regPacket = new IqPacket(IqPacket.TYPE.SET);
+ regPacket.setTo(Jid.of("cheogram.com/CHEOGRAM%jabber:iq:register"));
+ final Element c2 = regPacket.addChild("command", Namespace.COMMANDS);
+ c2.setAttribute("node", "jabber:iq:register");
+ c2.setAttribute("action", "execute");
+ xmppConnectionService.sendIqPacket(newAccount, regPacket, (a3, iq3) -> {
+ Element command3 = iq3.findChild("command", "http://jabber.org/protocol/commands");
+ if (command3 == null) {
+ Log.e(Config.LOGTAG, "Did not get expected data form from cheogram, got: " + iq3);
+ return;
+ }
+
+ Element form3 = command3.findChild("x", "jabber:x:data");
+ Data dataForm3 = form3 == null ? null : Data.parse(form3);
+ if (dataForm3 == null || dataForm3.getFieldByName("confirm") == null) {
+ Log.e(Config.LOGTAG, "Did not get expected data form from cheogram, got: " + iq3);
+ return;
+ }
+
+ dataForm3.put("confirm", "true");
+ dataForm3.submit();
+ command3.setAttribute("action", "execute");
+ iq3.setTo(iq3.getFrom());
+ iq3.setAttribute("type", "set");
+ iq3.removeAttribute("from");
+ iq3.removeAttribute("id");
+ xmppConnectionService.sendIqPacket(newAccount, iq3, (a4, iq4) -> {
+ Element command4 = iq2.findChild("command", "http://jabber.org/protocol/commands");
+ if (command4 != null && command4.getAttribute("status") != null && command4.getAttribute("status").equals("completed")) {
+ xmppConnectionService.createContact(newAccount.getRoster().getContact(iq4.getFrom().asBareJid()), true);
+ Conversation withCheogram = xmppConnectionService.findOrCreateConversation(newAccount, iq4.getFrom().asBareJid(), true, true, true);
+ xmppConnectionService.markRead(withCheogram);
+ xmppConnectionService.clearConversationHistory(withCheogram);
+ xmppConnectionService.deleteAccount(onboardAccount);
+ } else {
+ Log.e(Config.LOGTAG, "Error confirming jid switch, got: " + iq4);
+ }
+ });
+ });
+ } else {
+ Log.e(Config.LOGTAG, "Error during jid switch, got: " + iq2);
+ }
+ });
+ });
+ } else {
+ startCommand(selectedAccount, Jid.of("cheogram.com/CHEOGRAM%jabber:iq:register"), "jabber:iq:register");
+ finish();
+ return;
+ }
}
}