From 7bb183fa2561578872500bd3a9b43b4b984b79f6 Mon Sep 17 00:00:00 2001 From: tom79 Date: Sat, 15 Jun 2019 11:43:32 +0200 Subject: [PATCH] Some improvements --- .../activities/MastodonRegisterActivity.java | 162 ++++++++++++++++-- .../CreateMastodonAccountAsyncTask.java | 59 +++++++ .../java/app/fedilab/android/client/API.java | 24 +++ .../client/Entities/AccountCreation.java | 41 +++++ app/src/main/res/layout/activity_register.xml | 28 ++- app/src/main/res/values/strings.xml | 16 ++ 6 files changed, 316 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/app/fedilab/android/asynctasks/CreateMastodonAccountAsyncTask.java create mode 100644 app/src/main/java/app/fedilab/android/client/Entities/AccountCreation.java diff --git a/app/src/main/java/app/fedilab/android/activities/MastodonRegisterActivity.java b/app/src/main/java/app/fedilab/android/activities/MastodonRegisterActivity.java index 3089cc734..161a1cf07 100644 --- a/app/src/main/java/app/fedilab/android/activities/MastodonRegisterActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/MastodonRegisterActivity.java @@ -17,7 +17,10 @@ package app.fedilab.android.activities; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.SuppressLint; +import android.content.Context; +import android.content.DialogInterface; import android.content.SharedPreferences; +import android.os.AsyncTask; import android.os.Bundle; import android.text.Html; import android.text.SpannableString; @@ -25,38 +28,44 @@ import android.text.Spanned; import android.text.method.LinkMovementMethod; import android.text.style.ForegroundColorSpan; import android.text.style.UnderlineSpan; -import android.transition.Slide; -import android.transition.Transition; -import android.transition.TransitionManager; -import android.util.Log; -import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.view.animation.TranslateAnimation; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.jaredrummler.materialspinner.MaterialSpinner; -import org.apache.poi.sl.usermodel.Line; - +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.net.HttpURLConnection; +import java.net.URL; import java.util.List; + import app.fedilab.android.R; +import app.fedilab.android.asynctasks.CreateMastodonAccountAsyncTask; +import app.fedilab.android.asynctasks.PostActionAsyncTask; import app.fedilab.android.asynctasks.RetrieveInstanceRegAsyncTask; +import app.fedilab.android.client.API; import app.fedilab.android.client.APIResponse; +import app.fedilab.android.client.Entities.AccountCreation; import app.fedilab.android.client.Entities.InstanceReg; import app.fedilab.android.drawers.InstanceRegAdapter; import app.fedilab.android.helper.Helper; +import app.fedilab.android.interfaces.OnPostStatusActionInterface; import app.fedilab.android.interfaces.OnRetrieveInstanceInterface; import es.dmoral.toasty.Toasty; @@ -67,9 +76,11 @@ import static android.os.AsyncTask.THREAD_POOL_EXECUTOR; * Register activity class */ -public class MastodonRegisterActivity extends BaseActivity implements OnRetrieveInstanceInterface { +public class MastodonRegisterActivity extends BaseActivity implements OnRetrieveInstanceInterface, OnPostStatusActionInterface { + private Button signup; + private String instance; @Override protected void onCreate(Bundle savedInstanceState) { @@ -161,6 +172,46 @@ public class MastodonRegisterActivity extends BaseActivity implements OnRetrieve }); new RetrieveInstanceRegAsyncTask(MastodonRegisterActivity.this, "general", MastodonRegisterActivity.this).executeOnExecutor(THREAD_POOL_EXECUTOR); + + signup = findViewById(R.id.signup); + EditText username = findViewById(R.id.username); + EditText email = findViewById(R.id.email); + EditText password = findViewById(R.id.password); + EditText password_confirm = findViewById(R.id.password_confirm); + CheckBox agreement = findViewById(R.id.agreement); + + signup.setOnClickListener(view->{ + if( username.getText().toString().trim().length() == 0 || email.getText().toString().trim().length() == 0 || + password.getText().toString().trim().length() == 0 || password_confirm.getText().toString().trim().length() == 0 || !agreement.isChecked()){ + Toasty.error(MastodonRegisterActivity.this, getString(R.string.all_field_filled)).show(); + return; + } + if(!password.getText().toString().trim().equals(password_confirm.toString().trim())){ + Toasty.error(MastodonRegisterActivity.this, getString(R.string.password_error)).show(); + return; + } + if(!android.util.Patterns.EMAIL_ADDRESS.matcher(email.getText().toString().trim()).matches()){ + Toasty.error(MastodonRegisterActivity.this, getString(R.string.email_error)).show(); + return; + } + if(password.getText().toString().trim().length() < 8 ){ + Toasty.error(MastodonRegisterActivity.this, getString(R.string.password_too_short)).show(); + return; + } + if(username.getText().toString().matches("[a-zA-Z0-9_]")){ + Toasty.error(MastodonRegisterActivity.this, getString(R.string.username_error)).show(); + return; + } + signup.setEnabled(false); + AccountCreation accountCreation = new AccountCreation(); + accountCreation.setEmail(email.getText().toString().trim()); + accountCreation.setPassword(password.getText().toString().trim()); + accountCreation.setPasswordConfirm(password_confirm.getText().toString().trim()); + accountCreation.setUsername(username.getText().toString().trim()); + new CreateMastodonAccountAsyncTask(MastodonRegisterActivity.this, accountCreation, MastodonRegisterActivity.this).executeOnExecutor(THREAD_POOL_EXECUTOR); + }); + + } @Override @@ -187,13 +238,13 @@ public class MastodonRegisterActivity extends BaseActivity implements OnRetrieve public void pickupInstance(String instance){ - + checkInstance(MastodonRegisterActivity.this, instance); LinearLayout form_container = findViewById(R.id.form_container); LinearLayout drawer_layout = findViewById(R.id.drawer_layout); TextView host_reg = findViewById(R.id.host_reg); host_reg.setText(instance); - + this.instance = instance; drawer_layout.animate() .translationY(0) @@ -231,6 +282,7 @@ public class MastodonRegisterActivity extends BaseActivity implements OnRetrieve @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); + findViewById(R.id.invitation).setVisibility(View.GONE); form_container.setVisibility(View.GONE); } }); @@ -238,6 +290,9 @@ public class MastodonRegisterActivity extends BaseActivity implements OnRetrieve TextView agreement_text = findViewById(R.id.agreement_text); + TextView username_indicator = findViewById(R.id.username_indicator); + username_indicator.setText(getString(R.string.username_indicator, instance)); + String tos = getString(R.string.tos); String serverrules = getString(R.string.server_rules); String content_agreement = getString(R.string.agreement_check, @@ -246,7 +301,88 @@ public class MastodonRegisterActivity extends BaseActivity implements OnRetrieve ); agreement_text.setMovementMethod(LinkMovementMethod.getInstance()); agreement_text.setText(Html.fromHtml(content_agreement)); + } + private void checkInstance(Context context, String instance){ + new checkRegistration(context, instance).executeOnExecutor(THREAD_POOL_EXECUTOR); + } + + @Override + public void onPostStatusAction(APIResponse apiResponse) { + if( apiResponse.getError() != null){ + if( apiResponse.getError().getError() != null){ + Toasty.error(MastodonRegisterActivity.this,apiResponse.getError().getError()).show(); + }else { + Toasty.error(MastodonRegisterActivity.this,getString(R.string.toast_error)).show(); + } + signup.setEnabled(true); + return; + } + SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); + int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); + int style; + if (theme == Helper.THEME_DARK) { + style = R.style.DialogDark; + } else if (theme == Helper.THEME_BLACK){ + style = R.style.DialogBlack; + }else { + style = R.style.Dialog; + } + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MastodonRegisterActivity.this, style); + AlertDialog alertDialog = dialogBuilder.create(); + alertDialog.setTitle(getString(R.string.account_created)); + alertDialog.setMessage(getString(R.string.account_created_message, this.instance)); + dialogBuilder.setCancelable(false); + dialogBuilder.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog,int which) { + dialog.dismiss(); + finish(); + } + }); + alertDialog.show(); + } + + + @SuppressLint("StaticFieldLeak") + private class checkRegistration extends AsyncTask { + + private String instance; + private WeakReference weakReference; + + checkRegistration(Context context, String instance){ + this.instance = instance; + this.weakReference = new WeakReference<>(context); + } + + @Override + protected String doInBackground(Void... params) { + String response = null; + try { + URL url = new URL("https://" + instance + "/auth/sign_up"); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { + java.util.Scanner s = new java.util.Scanner(connection.getInputStream()).useDelimiter("\\A"); + response = s.hasNext() ? s.next() : ""; + } + } catch (IOException e) { + e.printStackTrace(); + } + return response; + } + + @Override + protected void onPostExecute(String result) { + + + if( result != null && result.contains("invite_request_attributes")){ + TextView invitation = ((MastodonRegisterActivity)(weakReference.get())).findViewById(R.id.invitation); + if( invitation != null){ + invitation.setVisibility(View.VISIBLE); + } + } + + } } } \ No newline at end of file diff --git a/app/src/main/java/app/fedilab/android/asynctasks/CreateMastodonAccountAsyncTask.java b/app/src/main/java/app/fedilab/android/asynctasks/CreateMastodonAccountAsyncTask.java new file mode 100644 index 000000000..5b8b014c8 --- /dev/null +++ b/app/src/main/java/app/fedilab/android/asynctasks/CreateMastodonAccountAsyncTask.java @@ -0,0 +1,59 @@ +/* Copyright 2017 Thomas Schneider + * + * This file is a part of Fedilab + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Fedilab; if not, + * see . */ +package app.fedilab.android.asynctasks; + +import android.content.Context; +import android.os.AsyncTask; + +import java.lang.ref.WeakReference; +import app.fedilab.android.client.API; +import app.fedilab.android.client.APIResponse; +import app.fedilab.android.client.Entities.AccountCreation; +import app.fedilab.android.interfaces.OnPostStatusActionInterface; + + +/** + * Created by Thomas on 15/06/2019. + * Create a Mastodon account + */ + +public class CreateMastodonAccountAsyncTask extends AsyncTask { + + private OnPostStatusActionInterface listener; + private APIResponse apiResponse; + private app.fedilab.android.client.Entities.Status status; + private AccountCreation accountCreation; + private WeakReference contextReference; + + + public CreateMastodonAccountAsyncTask(Context context, AccountCreation accountCreation, OnPostStatusActionInterface onPostStatusActionInterface){ + this.contextReference = new WeakReference<>(context); + this.listener = onPostStatusActionInterface; + this.accountCreation = accountCreation; + } + + @Override + protected Void doInBackground(Void... params) { + apiResponse = new API(contextReference.get()).createAccount(accountCreation); + return null; + } + + @Override + protected void onPostExecute(Void result) { + listener.onPostStatusAction(apiResponse); + + } + +} diff --git a/app/src/main/java/app/fedilab/android/client/API.java b/app/src/main/java/app/fedilab/android/client/API.java index 65ec5474e..d0ccafa27 100644 --- a/app/src/main/java/app/fedilab/android/client/API.java +++ b/app/src/main/java/app/fedilab/android/client/API.java @@ -41,6 +41,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import app.fedilab.android.R; @@ -48,6 +49,7 @@ import app.fedilab.android.activities.MainActivity; import app.fedilab.android.asynctasks.RetrieveOpenCollectiveAsyncTask; import app.fedilab.android.asynctasks.UpdateAccountInfoAsyncTask; import app.fedilab.android.client.Entities.Account; +import app.fedilab.android.client.Entities.AccountCreation; import app.fedilab.android.client.Entities.Application; import app.fedilab.android.client.Entities.Attachment; import app.fedilab.android.client.Entities.Card; @@ -528,6 +530,28 @@ public class API { return newValues; } + public APIResponse createAccount(AccountCreation accountCreation){ + apiResponse = new APIResponse(); + HashMap params = new HashMap<>(); + params.put("username", accountCreation.getUsername()); + params.put("email", accountCreation.getEmail()); + params.put("password", accountCreation.getPassword()); + params.put("agreement", "true"); + params.put("locale", Locale.getDefault().getLanguage()); + try { + new HttpsConnection(context, this.instance).post(getAbsoluteUrl("/accounts"), 60, params, null); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (KeyManagementException e) { + e.printStackTrace(); + } catch (HttpsConnection.HttpsConnectionException e) { + setError(e.getStatusCode(), e); + e.printStackTrace(); + } + return apiResponse; + } /** * Returns an account diff --git a/app/src/main/java/app/fedilab/android/client/Entities/AccountCreation.java b/app/src/main/java/app/fedilab/android/client/Entities/AccountCreation.java new file mode 100644 index 000000000..70787fd33 --- /dev/null +++ b/app/src/main/java/app/fedilab/android/client/Entities/AccountCreation.java @@ -0,0 +1,41 @@ +package app.fedilab.android.client.Entities; + +public class AccountCreation { + + private String username; + private String email; + private String password; + private String passwordConfirm; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getPasswordConfirm() { + return passwordConfirm; + } + + public void setPasswordConfirm(String passwordConfirm) { + this.passwordConfirm = passwordConfirm; + } +} diff --git a/app/src/main/res/layout/activity_register.xml b/app/src/main/res/layout/activity_register.xml index de204ec5d..9fa5dedd4 100644 --- a/app/src/main/res/layout/activity_register.xml +++ b/app/src/main/res/layout/activity_register.xml @@ -73,7 +73,15 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" /> - + + + + server rules terms of service Sign up + This instance works with invitations. Your account will need to be manually approved by an administrator before being usable. + Please, fill all the fields! + Passwords don\'t match! + The email doesn\'t seem to be valid! + Your username will be unique on %1$s + You will be sent a confirmation e-mail + Use at least 8 characters + Password should contain at least 8 characters + Username should only contain letters, numbers and underscores + Account created! + + Your account has been created!\n\n + Think to validate your email within the 48 next hours.\n\n + You can now connect your account by writing %1$s in the first field and click on Connect.\n\n + Important: If your instance required validation, you will receive an email once it is validated! + %d vote %d votes