diff options
author | Christian Schneppe <christian.schneppe@pix-art.de> | 2020-01-24 17:08:30 +0100 |
---|---|---|
committer | Christian Schneppe <christian.schneppe@pix-art.de> | 2020-01-24 17:08:30 +0100 |
commit | 6d74698aec0a2728ac1a88d27b3eb0aa7904e4c9 (patch) | |
tree | 25e7ba81c3fb8bcce0c46adbb44e7c553c8cecff /src | |
parent | f4a207e859999b49603efcea548f4a09546bb569 (diff) |
support registration via pars tokens
Diffstat (limited to 'src')
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> |