aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Schneppe <christian.schneppe@pix-art.de>2020-01-24 17:08:30 +0100
committerChristian Schneppe <christian.schneppe@pix-art.de>2020-01-24 17:08:30 +0100
commit6d74698aec0a2728ac1a88d27b3eb0aa7904e4c9 (patch)
tree25e7ba81c3fb8bcce0c46adbb44e7c553c8cecff
parentf4a207e859999b49603efcea548f4a09546bb569 (diff)
support registration via pars tokens
-rw-r--r--src/main/java/de/pixart/messenger/entities/Account.java4
-rw-r--r--src/main/java/de/pixart/messenger/ui/EditAccountActivity.java13
-rw-r--r--src/main/java/de/pixart/messenger/ui/MagicCreateActivity.java103
-rw-r--r--src/main/java/de/pixart/messenger/ui/UriHandlerActivity.java18
-rw-r--r--src/main/java/de/pixart/messenger/utils/Namespace.java2
-rw-r--r--src/main/java/de/pixart/messenger/utils/SignupUtils.java12
-rw-r--r--src/main/java/de/pixart/messenger/utils/XmppUri.java6
-rw-r--r--src/main/java/de/pixart/messenger/xmpp/XmppConnection.java26
-rw-r--r--src/main/res/layout/activity_magic_create.xml234
-rw-r--r--src/main/res/values/strings.xml2
10 files changed, 255 insertions, 165 deletions
diff --git a/src/main/java/de/pixart/messenger/entities/Account.java b/src/main/java/de/pixart/messenger/entities/Account.java
index fe31dbf07..edd0fdc8c 100644
--- a/src/main/java/de/pixart/messenger/entities/Account.java
+++ b/src/main/java/de/pixart/messenger/entities/Account.java
@@ -56,6 +56,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
public static final String RESOURCE = "resource";
public static final String PINNED_MECHANISM_KEY = "pinned_mechanism";
+ public static final String PRE_AUTH_REGISTRATION_TOKEN = "pre_auth_registration";
public static final int OPTION_USETLS = 0;
public static final int OPTION_DISABLED = 1;
@@ -655,6 +656,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
REGISTRATION_CONFLICT(true, false),
REGISTRATION_NOT_SUPPORTED(true, false),
REGISTRATION_PLEASE_WAIT(true, false),
+ REGISTRATION_INVALID_TOKEN(true, false),
REGISTRATION_PASSWORD_TOO_WEAK(true, false),
TLS_ERROR,
INCOMPATIBLE_SERVER,
@@ -719,6 +721,8 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
return R.string.account_status_regis_success;
case REGISTRATION_NOT_SUPPORTED:
return R.string.account_status_regis_not_sup;
+ case REGISTRATION_INVALID_TOKEN:
+ return R.string.account_status_regis_invalid_token;
case TLS_ERROR:
return R.string.account_status_tls_error;
case INCOMPATIBLE_SERVER:
diff --git a/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java b/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java
index fc669171f..4758f59bc 100644
--- a/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java
@@ -351,6 +351,16 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
if (mInitMode && mAccount != null && !mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY)) {
xmppConnectionService.deleteAccount(mAccount);
}
+
+ final boolean magicCreate = mAccount != null && mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) && !mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY);
+ final Jid jid = mAccount == null ? null : mAccount.getJid();
+
+ if (SignupUtils.isSupportTokenRegistry() && jid != null && magicCreate && !jid.getDomain().equals(Config.MAGIC_CREATE_DOMAIN)) {
+ final Intent intent = SignupUtils.getTokenRegistrationIntent(this, jid.getDomain(), mAccount.getKey(Account.PRE_AUTH_REGISTRATION_TOKEN));
+ startActivity(intent);
+ return;
+ }
+
if (xmppConnectionService.getAccounts().size() == 0 && Config.MAGIC_CREATE_DOMAIN != null) {
Intent intent = SignupUtils.getSignUpIntent(this);
startActivity(intent);
@@ -897,6 +907,9 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
return false;
}
switch (item.getItemId()) {
+ case android.R.id.home:
+ deleteAccountAndReturnIfNecessary();
+ break;
case R.id.action_import_backup:
if (hasStoragePermission(REQUEST_IMPORT_BACKUP)) {
startActivity(new Intent(this, ImportBackupActivity.class));
diff --git a/src/main/java/de/pixart/messenger/ui/MagicCreateActivity.java b/src/main/java/de/pixart/messenger/ui/MagicCreateActivity.java
index 372c2bc27..af7b965af 100644
--- a/src/main/java/de/pixart/messenger/ui/MagicCreateActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/MagicCreateActivity.java
@@ -1,6 +1,5 @@
package de.pixart.messenger.ui;
-import android.app.AlertDialog;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
@@ -9,12 +8,11 @@ import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.CheckBox;
import android.widget.CompoundButton;
-import android.widget.EditText;
-import android.widget.Spinner;
-import android.widget.TextView;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.widget.Toolbar;
+import androidx.databinding.DataBindingUtil;
import java.security.SecureRandom;
import java.util.Arrays;
@@ -23,18 +21,20 @@ import java.util.List;
import de.pixart.messenger.Config;
import de.pixart.messenger.R;
+import de.pixart.messenger.databinding.ActivityMagicCreateBinding;
import de.pixart.messenger.entities.Account;
import de.pixart.messenger.utils.CryptoHelper;
import rocks.xmpp.addr.Jid;
public class MagicCreateActivity extends XmppActivity implements TextWatcher, AdapterView.OnItemSelectedListener, CompoundButton.OnCheckedChangeListener {
- private TextView mFullJidDisplay;
- private EditText mUsername;
- private CheckBox mUseOwnProvider;
- private Spinner mServer;
private boolean useOwnProvider = false;
- String domain = null;
+ public static final String EXTRA_DOMAIN = "domain";
+ public static final String EXTRA_PRE_AUTH = "pre_auth";
+
+ private ActivityMagicCreateBinding binding;
+ private String domain;
+ private String preAuth;
@Override
protected void refreshUiReal() {
@@ -57,30 +57,31 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad
@Override
protected void onCreate(final Bundle savedInstanceState) {
+ final Intent data = getIntent();
+ this.domain = data == null ? null : data.getStringExtra(EXTRA_DOMAIN);
+ this.preAuth = data == null ? null : data.getStringExtra(EXTRA_PRE_AUTH);
if (getResources().getBoolean(R.bool.portrait_only)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_magic_create);
- setSupportActionBar(findViewById(R.id.toolbar));
- configureActionBar(getSupportActionBar());
- mFullJidDisplay = findViewById(R.id.full_jid);
+ this.binding = DataBindingUtil.setContentView(this, R.layout.activity_magic_create);
final List<String> domains = Arrays.asList(getResources().getStringArray(R.array.domains));
Collections.sort(domains, String::compareToIgnoreCase);
final ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_selectable_list_item, domains);
int defaultServer = adapter.getPosition("blabber.im");
- mUsername = findViewById(R.id.username);
- mUseOwnProvider = findViewById(R.id.use_own);
- mUseOwnProvider.setOnCheckedChangeListener(this);
- mServer = findViewById(R.id.server);
- mServer.setAdapter(adapter);
- mServer.setSelection(defaultServer);
- mServer.setOnItemSelectedListener(this);
+ binding.useOwn.setOnCheckedChangeListener(this);
+ binding.server.setAdapter(adapter);
+ binding.server.setSelection(defaultServer);
+ binding.server.setOnItemSelectedListener(this);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- Button next = findViewById(R.id.create_account);
- next.setOnClickListener(v -> {
+ setSupportActionBar((Toolbar) this.binding.toolbar);
+ configureActionBar(getSupportActionBar(), this.domain == null);
+ if (domain != null) {
+ binding.instructions.setText(getString(R.string.magic_create_text_on_x, domain));
+ }
+ binding.createAccount.setOnClickListener(v -> {
try {
- String username = mUsername.getText().toString();
+ final String username = binding.username.getText().toString();
if (domain == null && !useOwnProvider) {
domain = Config.MAGIC_CREATE_DOMAIN;
}
@@ -89,10 +90,10 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad
}
Jid jid = Jid.of(username.toLowerCase(), domain, null);
if (!jid.getEscapedLocal().equals(jid.getLocal()) || username.length() < 3) {
- mUsername.setError(getString(R.string.invalid_username));
- mUsername.requestFocus();
+ binding.username.setError(getString(R.string.invalid_username));
+ binding.username.requestFocus();
} else {
- mUsername.setError(null);
+ binding.username.setError(null);
Account account = xmppConnectionService.findAccountByJid(jid);
String password = CryptoHelper.createPassword(new SecureRandom());
if (account == null) {
@@ -100,6 +101,9 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad
account.setOption(Account.OPTION_REGISTER, true);
account.setOption(Account.OPTION_DISABLED, true);
account.setOption(Account.OPTION_MAGIC_CREATE, true);
+ if (this.preAuth != null) {
+ account.setKey(Account.PRE_AUTH_REGISTRATION_TOKEN, this.preAuth);
+ }
xmppConnectionService.createAccount(account);
}
Intent intent = new Intent(MagicCreateActivity.this, EditAccountActivity.class);
@@ -108,7 +112,6 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad
intent.putExtra("existing", false);
intent.putExtra("useownprovider", useOwnProvider);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
-
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.create_account));
builder.setCancelable(false);
@@ -131,13 +134,15 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad
}
});
builder.create().show();
+ StartConversationActivity.addInviteUri(intent, getIntent());
+ startActivity(intent);
}
} catch (IllegalArgumentException e) {
- mUsername.setError(getString(R.string.invalid_username));
- mUsername.requestFocus();
+ binding.username.setError(getString(R.string.invalid_username));
+ binding.username.requestFocus();
}
});
- mUsername.addTextChangedListener(this);
+ binding.username.addTextChangedListener(this);
}
@Override
@@ -157,43 +162,45 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
- generateJID(mUsername.getText().toString());
+ generateJID(binding.username.getText().toString());
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
- generateJID(mUsername.getText().toString());
+ generateJID(binding.username.getText().toString());
}
private void generateJID(String s) {
- domain = mServer.getSelectedItem().toString();
+ domain = binding.server.getSelectedItem().toString();
if (s.trim().length() > 0) {
try {
- mFullJidDisplay.setVisibility(View.VISIBLE);
- if (domain == null) {
- domain = Config.MAGIC_CREATE_DOMAIN;
+ binding.fullJid.setVisibility(View.VISIBLE);
+ final Jid jid;
+ if (this.domain == null) {
+ jid = Jid.ofLocalAndDomain(s, Config.MAGIC_CREATE_DOMAIN);
+ } else {
+ jid = Jid.ofLocalAndDomain(s, this.domain);
}
- Jid jid = Jid.of(s.toLowerCase(), domain, null);
- mFullJidDisplay.setText(getString(R.string.your_full_jid_will_be, jid.toEscapedString()));
+ binding.fullJid.setText(getString(R.string.your_full_jid_will_be, jid.toEscapedString()));
} catch (IllegalArgumentException e) {
- mFullJidDisplay.setVisibility(View.INVISIBLE);
+ binding.fullJid.setVisibility(View.INVISIBLE);
}
} else {
- mFullJidDisplay.setVisibility(View.INVISIBLE);
+ binding.fullJid.setVisibility(View.INVISIBLE);
}
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (mUseOwnProvider.isChecked()) {
- mServer.setEnabled(false);
- mFullJidDisplay.setVisibility(View.GONE);
+ if (binding.useOwn.isChecked()) {
+ binding.server.setEnabled(false);
+ binding.fullJid.setVisibility(View.GONE);
useOwnProvider = true;
} else {
- mServer.setEnabled(true);
- mFullJidDisplay.setVisibility(View.VISIBLE);
+ binding.server.setEnabled(true);
+ binding.fullJid.setVisibility(View.VISIBLE);
useOwnProvider = false;
}
}
-}
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/ui/UriHandlerActivity.java b/src/main/java/de/pixart/messenger/ui/UriHandlerActivity.java
index 9b53d5d24..bb34e7958 100644
--- a/src/main/java/de/pixart/messenger/ui/UriHandlerActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/UriHandlerActivity.java
@@ -7,14 +7,17 @@ import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import androidx.core.content.ContextCompat;
-import androidx.appcompat.app.AppCompatActivity;
+import android.util.Log;
import android.widget.Toast;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.content.ContextCompat;
+
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import de.pixart.messenger.Config;
import de.pixart.messenger.R;
import de.pixart.messenger.persistance.DatabaseBackend;
import de.pixart.messenger.utils.SignupUtils;
@@ -85,6 +88,17 @@ public class UriHandlerActivity extends AppCompatActivity {
final Intent intent;
final XmppUri xmppUri = new XmppUri(uri);
final List<Jid> accounts = DatabaseBackend.getInstance(this).getAccountJids(true);
+ if (SignupUtils.isSupportTokenRegistry() && xmppUri.isJidValid() && xmppUri.isAction(XmppUri.ACTION_REGISTER)) {
+ final String preauth = xmppUri.getParamater("preauth");
+ final Jid jid = xmppUri.getJid();
+ if (jid.isDomainJid()) {
+ intent = SignupUtils.getTokenRegistrationIntent(this, jid.getDomain(), preauth);
+ startActivity(intent);
+ return;
+ }
+ Log.d(Config.LOGTAG, "attempting to register on " + jid + " with preauth=" + preauth);
+ return;
+ }
if (accounts.size() == 0) {
if (xmppUri.isJidValid()) {
intent = SignupUtils.getSignUpIntent(this);
diff --git a/src/main/java/de/pixart/messenger/utils/Namespace.java b/src/main/java/de/pixart/messenger/utils/Namespace.java
index a6624309a..1fbe82a81 100644
--- a/src/main/java/de/pixart/messenger/utils/Namespace.java
+++ b/src/main/java/de/pixart/messenger/utils/Namespace.java
@@ -37,4 +37,6 @@ public final class Namespace {
public static final String BOOKMARKS2_COMPAT = BOOKMARKS2 + "#compat";
public static final String DISCO_ITEMS = "http://jabber.org/protocol/disco#items";
public static final String DISCO_INFO = "http://jabber.org/protocol/disco#info";
+ public static final String INVITE = "urn:xmpp:invite";
+ public static final String PARS = "urn:xmpp:pars:0";
}
diff --git a/src/main/java/de/pixart/messenger/utils/SignupUtils.java b/src/main/java/de/pixart/messenger/utils/SignupUtils.java
index 1fc368fa4..21c62cffa 100644
--- a/src/main/java/de/pixart/messenger/utils/SignupUtils.java
+++ b/src/main/java/de/pixart/messenger/utils/SignupUtils.java
@@ -8,12 +8,24 @@ import de.pixart.messenger.entities.Account;
import de.pixart.messenger.services.XmppConnectionService;
import de.pixart.messenger.ui.ConversationsActivity;
import de.pixart.messenger.ui.EditAccountActivity;
+import de.pixart.messenger.ui.MagicCreateActivity;
import de.pixart.messenger.ui.ManageAccountActivity;
import de.pixart.messenger.ui.StartConversationActivity;
import de.pixart.messenger.ui.WelcomeActivity;
public class SignupUtils {
+ public static boolean isSupportTokenRegistry() {
+ return true;
+ }
+
+ public static Intent getTokenRegistrationIntent(final Activity activity, String domain, String preauth) {
+ final Intent intent = new Intent(activity, MagicCreateActivity.class);
+ intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, domain);
+ intent.putExtra(MagicCreateActivity.EXTRA_PRE_AUTH, preauth);
+ return intent;
+ }
+
public static Intent getSignUpIntent(final Activity activity) {
final Intent intent = new Intent(activity, WelcomeActivity.class);
return intent;
diff --git a/src/main/java/de/pixart/messenger/utils/XmppUri.java b/src/main/java/de/pixart/messenger/utils/XmppUri.java
index fa83fb8f4..322b1f760 100644
--- a/src/main/java/de/pixart/messenger/utils/XmppUri.java
+++ b/src/main/java/de/pixart/messenger/utils/XmppUri.java
@@ -31,7 +31,9 @@ public class XmppUri {
public static final String OMEMO_URI_PARAM = "omemo-sid-";
private static final String OTR_URI_PARAM = "otr-fingerprint";
public static final String ACTION_JOIN = "join";
+
public static final String ACTION_MESSAGE = "message";
+ public static final String ACTION_REGISTER = "register";
public static Pattern XMPP_URI = Patterns.XMPP_PATTERN;
@@ -199,6 +201,10 @@ public class XmppUri {
return parameters.get("name");
}
+ public String getParamater(String key) {
+ return this.parameters.get(key);
+ }
+
public List<Fingerprint> getFingerprints() {
return this.fingerprints;
}
diff --git a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
index 617a2e3ad..b8cddc170 100644
--- a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
+++ b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
@@ -114,6 +114,7 @@ public class XmppConnection implements Runnable {
public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.getType() == IqPacket.TYPE.RESULT) {
account.setOption(Account.OPTION_REGISTER, false);
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": successfully registered new account on server");
throw new StateChangingError(Account.State.REGISTRATION_SUCCESSFUL);
} else {
final List<String> PASSWORD_TOO_WEAK_MSGS = Arrays.asList(
@@ -876,7 +877,7 @@ public class XmppConnection implements Runnable {
sendStartTLS();
} else if (this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) {
if (isSecure) {
- sendRegistryRequest();
+ register();
} else {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to find STARTTLS for registration process " + XmlHelper.printElementNames(this.streamFeatures));
throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
@@ -950,6 +951,25 @@ public class XmppConnection implements Runnable {
return mechanisms;
}
+ private void register() {
+ final String preAuth = account.getKey(Account.PRE_AUTH_REGISTRATION_TOKEN);
+ if (preAuth != null && features.invite()) {
+ final IqPacket preAuthRequest = new IqPacket(IqPacket.TYPE.SET);
+ preAuthRequest.addChild("preauth", Namespace.PARS).setAttribute("token", preAuth);
+ sendUnmodifiedIqPacket(preAuthRequest, (account, response) -> {
+ if (response.getType() == IqPacket.TYPE.RESULT) {
+ sendRegistryRequest();
+ } else {
+ final Element error = response.getError();
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": failed to pre auth. " + error);
+ throw new StateChangingError(Account.State.REGISTRATION_INVALID_TOKEN);
+ }
+ }, true);
+ } else {
+ sendRegistryRequest();
+ }
+ }
+
private void sendRegistryRequest() {
final IqPacket register = new IqPacket(IqPacket.TYPE.GET);
register.query(Namespace.REGISTER);
@@ -1899,6 +1919,10 @@ public class XmppConnection implements Runnable {
return hasDiscoFeature(Jid.of(account.getServer()), Namespace.REGISTER);
}
+ public boolean invite() {
+ return connection.streamFeatures != null && connection.streamFeatures.hasChild("register", Namespace.INVITE);
+ }
+
public boolean sm() {
return streamId != null
|| (connection.streamFeatures != null && connection.streamFeatures.hasChild("sm"));
diff --git a/src/main/res/layout/activity_magic_create.xml b/src/main/res/layout/activity_magic_create.xml
index e315a634b..11f2d8b00 100644
--- a/src/main/res/layout/activity_magic_create.xml
+++ b/src/main/res/layout/activity_magic_create.xml
@@ -1,128 +1,134 @@
<?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">
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
- <include layout="@layout/toolbar" />
-
- <ScrollView
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:fillViewport="true">
+ android:orientation="vertical">
+
+ <include
+ android:id="@+id/toolbar"
+ layout="@layout/toolbar" />
- <RelativeLayout
+ <ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="?attr/color_background_secondary">
-
- <LinearLayout
- android:id="@+id/linearLayout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentBottom="true"
- android:minHeight="256dp"
- android:orientation="vertical"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:paddingBottom="8dp">
- android:paddingLeft="16dp"
- android:paddingRight="16dp">
-
- <Space
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/magic_create_text"
- android:textAppearance="@style/TextAppearance.Conversations.Body1" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/pick_your_username"
- android:textAppearance="@style/TextAppearance.Conversations.Title" />
-
- <EditText
- android:id="@+id/username"
- style="@style/Widget.Conversations.EditText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="@string/username_hint"
- android:imeOptions="actionNext"
- android:inputType="text"
- android:textColor="?attr/text_Color_Main" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/choose_your_server"
- android:textAppearance="@style/TextAppearance.Conversations.Title" />
-
- <Spinner
- android:id="@+id/server"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:hint="@string/server_hint"
- android:prompt="@string/server_hint"
- android:spinnerMode="dialog" />
-
- <CheckBox
- android:id="@+id/use_own"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/use_own_provider" />
-
- <TextView
- android:id="@+id/full_jid"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/your_full_jid_will_be"
- android:textAppearance="@style/TextAppearance.Conversations.Caption"
- android:visibility="invisible" />
-
- <TextView
- android:id="@+id/server_info"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/welcome_server_info"
- android:textAppearance="@style/TextAppearance.Conversations.Caption" />
-
- <Button
- android:id="@+id/create_account"
- style="@style/Widget.Conversations.Button.Borderless"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="end"
- android:text="@string/next"
- android:textColor="?attr/colorAccent" />
-
- </LinearLayout>
+ android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_above="@+id/linearLayout"
- android:layout_alignParentStart="true"
- android:layout_alignParentLeft="true">
+ android:background="?attr/color_background_secondary">
- <ImageView
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:id="@+id/linearLayout"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_centerVertical="true"
- android:padding="8dp"
- android:src="@drawable/main_logo" />
+ android:layout_alignParentStart="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentBottom="true"
+ android:minHeight="256dp"
+ android:orientation="vertical"
+ android:paddingStart="16dp"
+ android:paddingLeft="16dp"
+ android:paddingEnd="16dp"
+ android:paddingRight="16dp"
+ android:paddingBottom="8dp">
+
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <TextView
+ android:id="@+id/instructions"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/magic_create_text"
+ android:textAppearance="@style/TextAppearance.Conversations.Body1" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/pick_your_username"
+ android:textAppearance="@style/TextAppearance.Conversations.Title" />
+
+ <EditText
+ android:id="@+id/username"
+ style="@style/Widget.Conversations.EditText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/username_hint"
+ android:imeOptions="actionNext"
+ android:inputType="text"
+ android:textColor="?attr/text_Color_Main" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/choose_your_server"
+ android:textAppearance="@style/TextAppearance.Conversations.Title" />
+
+ <Spinner
+ android:id="@+id/server"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:hint="@string/server_hint"
+ android:prompt="@string/server_hint"
+ android:spinnerMode="dialog" />
+
+ <CheckBox
+ android:id="@+id/use_own"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/use_own_provider" />
+
+ <TextView
+ android:id="@+id/full_jid"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/your_full_jid_will_be"
+ android:textAppearance="@style/TextAppearance.Conversations.Caption"
+ android:visibility="invisible" />
+
+ <TextView
+ android:id="@+id/server_info"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/welcome_server_info"
+ android:textAppearance="@style/TextAppearance.Conversations.Caption" />
+
+ <Button
+ android:id="@+id/create_account"
+ style="@style/Widget.Conversations.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end"
+ android:text="@string/next"
+ android:textColor="?attr/colorAccent" />
+
+ </LinearLayout>
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_above="@+id/linearLayout"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentLeft="true">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:padding="8dp"
+ android:src="@drawable/main_logo" />
+ </RelativeLayout>
</RelativeLayout>
- </RelativeLayout>
- </ScrollView>
-</LinearLayout> \ No newline at end of file
+ </ScrollView>
+ </LinearLayout>
+</layout> \ No newline at end of file
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 3c274366d..1c267eaf8 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -998,4 +998,6 @@
<string name="pref_theme_color_options">Theme color</string>
<string name="pref_enable_otr_summary">Enable OTR encryption for message encryption</string>
<string name="pref_enable_otr">Enable OTR encryption</string>
+ <string name="magic_create_text_on_x">You have been invited to %1$s. We will guide you through the process of creating an account.\\nWhen picking %1$s as a provider you will be able to communicate with users of other providers by giving them your full XMPP address.</string>
+ <string name="account_status_regis_invalid_token">Invalid registration token</string>
</resources>