Merge branch 'improve_login' into develop
This commit is contained in:
commit
8f80a6188b
|
@ -128,6 +128,11 @@
|
|||
<data android:pathPattern=".*\\.fedilab" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="app.fedilab.android.activities.MastodonRegisterActivity"
|
||||
android:windowSoftInputMode="stateAlwaysHidden"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/app_name"
|
||||
/>
|
||||
<activity android:name="app.fedilab.android.activities.LoginActivity"
|
||||
android:windowSoftInputMode="stateAlwaysHidden"
|
||||
android:configChanges="orientation|screenSize"
|
||||
|
|
|
@ -35,8 +35,10 @@ import androidx.appcompat.app.AlertDialog;
|
|||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.text.Editable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.UnderlineSpan;
|
||||
import android.text.util.Linkify;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -62,6 +64,7 @@ import com.jaredrummler.materialspinner.MaterialSpinner;
|
|||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
|
@ -213,6 +216,25 @@ public class LoginActivity extends BaseActivity {
|
|||
changeDrawableColor(getApplicationContext(), R.drawable.mastodon_icon, R.color.mastodonC3);
|
||||
}
|
||||
|
||||
TextView create_an_account_message = findViewById(R.id.create_an_account);
|
||||
SpannableString content_create = new SpannableString(getString(R.string.join_mastodon));
|
||||
content_create.setSpan(new UnderlineSpan(), 0, content_create.length(), 0);
|
||||
if( theme == Helper.THEME_DARK)
|
||||
content_create.setSpan(new ForegroundColorSpan(ContextCompat.getColor(LoginActivity.this, R.color.dark_link_toot)), 0, content_create.length(),
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
else if( theme == Helper.THEME_BLACK)
|
||||
content_create.setSpan(new ForegroundColorSpan(ContextCompat.getColor(LoginActivity.this, R.color.black_link_toot)), 0, content_create.length(),
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
else if( theme == Helper.THEME_LIGHT)
|
||||
content_create.setSpan(new ForegroundColorSpan(ContextCompat.getColor(LoginActivity.this, R.color.mastodonC4)), 0, content_create.length(),
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
create_an_account_message.setText(content_create);
|
||||
create_an_account_message.setOnClickListener(v -> {
|
||||
Intent mainActivity = new Intent(LoginActivity.this, MastodonRegisterActivity.class);
|
||||
startActivity(mainActivity);
|
||||
});
|
||||
|
||||
|
||||
login_instance = findViewById(R.id.login_instance);
|
||||
login_uid = findViewById(R.id.login_uid);
|
||||
login_passwd = findViewById(R.id.login_passwd);
|
||||
|
|
|
@ -0,0 +1,410 @@
|
|||
/* 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 <http://www.gnu.org/licenses>. */
|
||||
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.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.UnderlineSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
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.json.JSONObject;
|
||||
|
||||
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;
|
||||
|
||||
import static android.os.AsyncTask.THREAD_POOL_EXECUTOR;
|
||||
|
||||
/**
|
||||
* Created by Thomas on 13/06/2019.
|
||||
* Register activity class
|
||||
*/
|
||||
|
||||
public class MastodonRegisterActivity extends BaseActivity implements OnRetrieveInstanceInterface, OnPostStatusActionInterface {
|
||||
|
||||
|
||||
private Button signup;
|
||||
private String instance;
|
||||
private TextView error_message;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
|
||||
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
|
||||
switch (theme){
|
||||
case Helper.THEME_LIGHT:
|
||||
setTheme(R.style.AppTheme);
|
||||
break;
|
||||
case Helper.THEME_DARK:
|
||||
setTheme(R.style.AppThemeDark);
|
||||
break;
|
||||
case Helper.THEME_BLACK:
|
||||
setTheme(R.style.AppThemeBlack);
|
||||
break;
|
||||
default:
|
||||
setTheme(R.style.AppThemeDark);
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_register);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if( actionBar != null ) {
|
||||
LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
|
||||
assert inflater != null;
|
||||
@SuppressLint("InflateParams") View view = inflater.inflate(R.layout.simple_bar, null);
|
||||
actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
|
||||
ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close);
|
||||
TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title);
|
||||
toolbar_close.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
toolbar_title.setText(R.string.sign_up);
|
||||
if (theme == Helper.THEME_LIGHT){
|
||||
Toolbar toolbar = actionBar.getCustomView().findViewById(R.id.toolbar);
|
||||
Helper.colorizeToolbar(toolbar, R.color.black, MastodonRegisterActivity.this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
MaterialSpinner reg_category = findViewById(R.id.reg_category);
|
||||
Helper.changeMaterialSpinnerColor(MastodonRegisterActivity.this, reg_category);
|
||||
String[] categoriesA = {
|
||||
getString(R.string.category_general),
|
||||
getString(R.string.category_regional),
|
||||
getString(R.string.category_art),
|
||||
getString(R.string.category_journalism),
|
||||
getString(R.string.category_activism),
|
||||
"LGBTQ+",
|
||||
getString(R.string.category_games),
|
||||
getString(R.string.category_tech),
|
||||
getString(R.string.category_adult),
|
||||
getString(R.string.category_furry),
|
||||
getString(R.string.category_food)
|
||||
|
||||
};
|
||||
String[] itemA = {
|
||||
"general",
|
||||
"regional",
|
||||
"art",
|
||||
"journalism",
|
||||
"activism",
|
||||
"lgbt",
|
||||
"games",
|
||||
"tech",
|
||||
"adult",
|
||||
"furry",
|
||||
"food",
|
||||
};
|
||||
ArrayAdapter<String> adcategories = new ArrayAdapter<>(MastodonRegisterActivity.this,
|
||||
android.R.layout.simple_spinner_dropdown_item, categoriesA);
|
||||
|
||||
reg_category.setAdapter(adcategories);
|
||||
|
||||
reg_category.setSelectedIndex(0);
|
||||
//Manage privacies
|
||||
reg_category.setOnItemSelectedListener(new MaterialSpinner.OnItemSelectedListener<String>() {
|
||||
@Override
|
||||
public void onItemSelected(MaterialSpinner view, int position, long id, String item) {
|
||||
new RetrieveInstanceRegAsyncTask(MastodonRegisterActivity.this, itemA[position], MastodonRegisterActivity.this).executeOnExecutor(THREAD_POOL_EXECUTOR);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
error_message = findViewById(R.id.error_message);
|
||||
|
||||
signup.setOnClickListener(view->{
|
||||
error_message.setVisibility(View.GONE);
|
||||
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.getText().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, instance, MastodonRegisterActivity.this).executeOnExecutor(THREAD_POOL_EXECUTOR);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume(){
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRetrieveInstance(APIResponse apiResponse) {
|
||||
if( apiResponse.getError() != null ){
|
||||
Toasty.error(MastodonRegisterActivity.this, getString(R.string.toast_error_instance_reg), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
List<InstanceReg> instanceRegs = apiResponse.getInstanceRegs();
|
||||
RecyclerView lv_instances = findViewById(R.id.reg_category_view);
|
||||
InstanceRegAdapter instanceRegAdapter = new InstanceRegAdapter(MastodonRegisterActivity.this, instanceRegs);
|
||||
LinearLayoutManager mLayoutManager = new LinearLayoutManager(MastodonRegisterActivity.this);
|
||||
lv_instances.setLayoutManager(mLayoutManager);
|
||||
lv_instances.setNestedScrollingEnabled(false);
|
||||
lv_instances.setAdapter(instanceRegAdapter);
|
||||
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
.alpha(0.0f)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
drawer_layout.setVisibility(View.GONE);
|
||||
form_container.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
TextView change_instance = findViewById(R.id.change_instance);
|
||||
final SpannableString change = new SpannableString(String.format("(%s)", getString(R.string.change)));
|
||||
change.setSpan(new UnderlineSpan(), 0, change.length(), 0);
|
||||
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
|
||||
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
|
||||
if( theme == Helper.THEME_DARK)
|
||||
change.setSpan(new ForegroundColorSpan(ContextCompat.getColor(MastodonRegisterActivity.this, R.color.dark_link_toot)), 0, change.length(),
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
else if( theme == Helper.THEME_BLACK)
|
||||
change.setSpan(new ForegroundColorSpan(ContextCompat.getColor(MastodonRegisterActivity.this, R.color.black_link_toot)), 0, change.length(),
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
else if( theme == Helper.THEME_LIGHT)
|
||||
change.setSpan(new ForegroundColorSpan(ContextCompat.getColor(MastodonRegisterActivity.this, R.color.mastodonC4)), 0, change.length(),
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
change_instance.setText(change);
|
||||
change_instance.setOnClickListener(view -> {
|
||||
drawer_layout.setVisibility(View.VISIBLE);
|
||||
drawer_layout.animate()
|
||||
.translationY(0)
|
||||
.alpha(1.f)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
findViewById(R.id.invitation).setVisibility(View.GONE);
|
||||
form_container.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
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,
|
||||
"<a href='https://" + instance + "/about/more' >"+serverrules +"</a>",
|
||||
"<a href='https://" + instance + "/terms' >"+tos +"</a>"
|
||||
);
|
||||
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){
|
||||
String errorMessage;
|
||||
if( apiResponse.getError().getError() != null){
|
||||
try{
|
||||
String[] resp = apiResponse.getError().getError().split(":");
|
||||
if( resp.length == 2)
|
||||
errorMessage = apiResponse.getError().getError().split(":")[1];
|
||||
else if( resp.length == 3)
|
||||
errorMessage = apiResponse.getError().getError().split(":")[2];
|
||||
else
|
||||
errorMessage = getString(R.string.toast_error);
|
||||
}catch (Exception e){
|
||||
errorMessage = getString(R.string.toast_error);
|
||||
}
|
||||
}else {
|
||||
errorMessage = getString(R.string.toast_error);
|
||||
}
|
||||
error_message.setText(errorMessage);
|
||||
error_message.setVisibility(View.VISIBLE);
|
||||
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);
|
||||
dialogBuilder.setCancelable(false);
|
||||
dialogBuilder.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,int which) {
|
||||
dialog.dismiss();
|
||||
Intent mainActivity = new Intent(MastodonRegisterActivity.this, MainActivity.class);
|
||||
mainActivity.putExtra(Helper.INTENT_ACTION, Helper.ADD_USER_INTENT);
|
||||
startActivity(mainActivity);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
AlertDialog alertDialog = dialogBuilder.create();
|
||||
alertDialog.setTitle(getString(R.string.account_created));
|
||||
alertDialog.setMessage(getString(R.string.account_created_message, this.instance));
|
||||
alertDialog.show();
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private class checkRegistration extends AsyncTask<Void, Void, String> {
|
||||
|
||||
private String instance;
|
||||
private WeakReference<Context> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -51,7 +51,6 @@ import android.text.Html;
|
|||
import android.text.InputFilter;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.util.Patterns;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* 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 <http://www.gnu.org/licenses>. */
|
||||
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<Void, Void, Void> {
|
||||
|
||||
private OnPostStatusActionInterface listener;
|
||||
private APIResponse apiResponse;
|
||||
private app.fedilab.android.client.Entities.Status status;
|
||||
private AccountCreation accountCreation;
|
||||
private WeakReference<Context> contextReference;
|
||||
private String instance;
|
||||
|
||||
public CreateMastodonAccountAsyncTask(Context context, AccountCreation accountCreation, String instance, OnPostStatusActionInterface onPostStatusActionInterface){
|
||||
this.contextReference = new WeakReference<>(context);
|
||||
this.listener = onPostStatusActionInterface;
|
||||
this.accountCreation = accountCreation;
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
apiResponse = new API(contextReference.get(), instance, null).createAccount(accountCreation);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
listener.onPostStatusAction(apiResponse);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* Copyright 2019 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 <http://www.gnu.org/licenses>. */
|
||||
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.interfaces.OnRetrieveInstanceInterface;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Thomas on 14/06/2019.
|
||||
* Retrieves instances for registration
|
||||
*/
|
||||
|
||||
public class RetrieveInstanceRegAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private OnRetrieveInstanceInterface listener;
|
||||
private APIResponse apiResponse;
|
||||
private WeakReference<Context> contextReference;
|
||||
private String category;
|
||||
|
||||
public RetrieveInstanceRegAsyncTask(Context context, String category, OnRetrieveInstanceInterface onRetrieveInstanceInterface){
|
||||
this.contextReference = new WeakReference<>(context);
|
||||
this.listener = onRetrieveInstanceInterface;
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
apiResponse = new API(this.contextReference.get()).getInstanceReg(category);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
listener.onRetrieveInstance(apiResponse);
|
||||
}
|
||||
|
||||
}
|
|
@ -16,7 +16,6 @@ package app.fedilab.android.asynctasks;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
|
@ -41,13 +42,16 @@ 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;
|
||||
import app.fedilab.android.activities.LoginActivity;
|
||||
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;
|
||||
|
@ -58,6 +62,7 @@ import app.fedilab.android.client.Entities.Filters;
|
|||
import app.fedilab.android.client.Entities.HowToVideo;
|
||||
import app.fedilab.android.client.Entities.Instance;
|
||||
import app.fedilab.android.client.Entities.InstanceNodeInfo;
|
||||
import app.fedilab.android.client.Entities.InstanceReg;
|
||||
import app.fedilab.android.client.Entities.InstanceSocial;
|
||||
import app.fedilab.android.client.Entities.Mention;
|
||||
import app.fedilab.android.client.Entities.NodeInfo;
|
||||
|
@ -346,6 +351,31 @@ public class API {
|
|||
}
|
||||
|
||||
|
||||
/***
|
||||
* Get instance for registering an account *synchronously*
|
||||
* @return APIResponse
|
||||
*/
|
||||
public APIResponse getInstanceReg(String category) {
|
||||
apiResponse = new APIResponse();
|
||||
try {
|
||||
String response = new HttpsConnection(context, null).get(String.format("https://api.joinmastodon.org/servers?category=%s", category));
|
||||
List<InstanceReg> instanceRegs = parseInstanceReg(new JSONArray(response));
|
||||
apiResponse.setInstanceRegs(instanceRegs);
|
||||
} catch (HttpsConnection.HttpsConnectionException e) {
|
||||
setError(e.getStatusCode(), e);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (KeyManagementException e) {
|
||||
e.printStackTrace();
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return apiResponse;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***
|
||||
* Update credential of the authenticated user *synchronously*
|
||||
|
@ -502,6 +532,73 @@ public class API {
|
|||
return newValues;
|
||||
}
|
||||
|
||||
public APIResponse createAccount(AccountCreation accountCreation){
|
||||
apiResponse = new APIResponse();
|
||||
|
||||
try {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
params.put(Helper.CLIENT_NAME, Helper.CLIENT_NAME_VALUE);
|
||||
params.put(Helper.REDIRECT_URIS, Helper.REDIRECT_CONTENT);
|
||||
params.put(Helper.SCOPES, Helper.OAUTH_SCOPES);
|
||||
params.put(Helper.WEBSITE, Helper.WEBSITE_VALUE);
|
||||
String response = new HttpsConnection(context, this.instance).post(getAbsoluteUrl("/apps"), 30, params, null);
|
||||
JSONObject resobj = new JSONObject(response);
|
||||
String client_id = resobj.getString("client_id");
|
||||
String client_secret = resobj.getString("client_secret");
|
||||
|
||||
params = new HashMap<>();
|
||||
params.put("grant_type", "client_credentials");
|
||||
params.put("client_id", client_id);
|
||||
params.put("client_secret", client_secret);
|
||||
params.put("scope", "read write");
|
||||
response = new HttpsConnection(context, this.instance).post("https://" + this.instance + "/oauth/token", 30, params, null);
|
||||
JSONObject res = new JSONObject(response);
|
||||
String app_token = res.getString("access_token");
|
||||
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());
|
||||
response = new HttpsConnection(context, this.instance).post(getAbsoluteUrl("/accounts"), 60, params, app_token);
|
||||
|
||||
res = new JSONObject(response);
|
||||
String access_token = res.getString("access_token");
|
||||
|
||||
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
account.setToken(access_token);
|
||||
account.setClient_id(client_id);
|
||||
account.setClient_secret(client_secret);
|
||||
account.setRefresh_token(null);
|
||||
account.setInstance(instance);
|
||||
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||
boolean userExists = new AccountDAO(context, db).userExist(account);
|
||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||
editor.putString(Helper.PREF_KEY_ID, account.getId());
|
||||
editor.putBoolean(Helper.PREF_IS_MODERATOR, account.isModerator());
|
||||
editor.putBoolean(Helper.PREF_IS_ADMINISTRATOR, account.isAdmin());
|
||||
editor.putString(Helper.PREF_INSTANCE, instance);
|
||||
editor.apply();
|
||||
if( userExists)
|
||||
new AccountDAO(context, db).updateAccountCredential(account);
|
||||
else {
|
||||
if( account.getUsername() != null && account.getCreated_at() != null)
|
||||
new AccountDAO(context, db).insertAccount(account);
|
||||
}
|
||||
} 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();
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return apiResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an account
|
||||
|
@ -4403,6 +4500,54 @@ public class API {
|
|||
return instance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Parse json response for several instance reg
|
||||
* @param jsonArray JSONArray
|
||||
* @return List<Status>
|
||||
*/
|
||||
public List<InstanceReg> parseInstanceReg(JSONArray jsonArray){
|
||||
|
||||
List<InstanceReg> instanceRegs = new ArrayList<>();
|
||||
try {
|
||||
int i = 0;
|
||||
while (i < jsonArray.length() ){
|
||||
JSONObject resobj = jsonArray.getJSONObject(i);
|
||||
InstanceReg instanceReg = parseInstanceReg(resobj);
|
||||
i++;
|
||||
instanceRegs.add(instanceReg);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return instanceRegs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse json response an unique instance for registering
|
||||
* @param resobj JSONObject
|
||||
* @return InstanceReg
|
||||
*/
|
||||
private InstanceReg parseInstanceReg(JSONObject resobj){
|
||||
InstanceReg instanceReg = new InstanceReg();
|
||||
try {
|
||||
instanceReg.setDomain(resobj.getString("domain"));
|
||||
instanceReg.setVersion(resobj.getString("version"));
|
||||
instanceReg.setDescription(resobj.getString("description"));
|
||||
instanceReg.setLanguage(resobj.getString("language"));
|
||||
instanceReg.setCategory(resobj.getString("category"));
|
||||
instanceReg.setProxied_thumbnail(resobj.getString("proxied_thumbnail"));
|
||||
instanceReg.setTotal_users(resobj.getInt("total_users"));
|
||||
instanceReg.setLast_week_users(resobj.getInt("last_week_users"));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return instanceReg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Parse Pleroma emojis
|
||||
* @param jsonObject JSONObject
|
||||
|
|
|
@ -25,6 +25,7 @@ import app.fedilab.android.client.Entities.Error;
|
|||
import app.fedilab.android.client.Entities.Filters;
|
||||
import app.fedilab.android.client.Entities.HowToVideo;
|
||||
import app.fedilab.android.client.Entities.Instance;
|
||||
import app.fedilab.android.client.Entities.InstanceReg;
|
||||
import app.fedilab.android.client.Entities.Notification;
|
||||
import app.fedilab.android.client.Entities.Peertube;
|
||||
import app.fedilab.android.client.Entities.PeertubeNotification;
|
||||
|
@ -62,6 +63,8 @@ public class APIResponse {
|
|||
private List<StoredStatus> storedStatuses;
|
||||
private boolean fetchmore = false;
|
||||
private List<String> playlistForVideos;
|
||||
private List<InstanceReg> instanceRegs = null;
|
||||
|
||||
|
||||
public List<Account> getAccounts() {
|
||||
return accounts;
|
||||
|
@ -238,4 +241,12 @@ public class APIResponse {
|
|||
public void setPlaylistForVideos(List<String> playlistForVideos) {
|
||||
this.playlistForVideos = playlistForVideos;
|
||||
}
|
||||
|
||||
public List<InstanceReg> getInstanceRegs() {
|
||||
return instanceRegs;
|
||||
}
|
||||
|
||||
public void setInstanceRegs(List<InstanceReg> instanceRegs) {
|
||||
this.instanceRegs = instanceRegs;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package app.fedilab.android.client.Entities;
|
||||
/* Copyright 2019 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 <http://www.gnu.org/licenses>. */
|
||||
|
||||
public class InstanceReg {
|
||||
|
||||
private String domain;
|
||||
private String version;
|
||||
private String description;
|
||||
private String language;
|
||||
private String category;
|
||||
private String proxied_thumbnail;
|
||||
private int total_users;
|
||||
private int last_week_users;
|
||||
private boolean selected = false;
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public void setDomain(String domain) {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public String getProxied_thumbnail() {
|
||||
return proxied_thumbnail;
|
||||
}
|
||||
|
||||
public void setProxied_thumbnail(String proxied_thumbnail) {
|
||||
this.proxied_thumbnail = proxied_thumbnail;
|
||||
}
|
||||
|
||||
public int getTotal_users() {
|
||||
return total_users;
|
||||
}
|
||||
|
||||
public void setTotal_users(int total_users) {
|
||||
this.total_users = total_users;
|
||||
}
|
||||
|
||||
public int getLast_week_users() {
|
||||
return last_week_users;
|
||||
}
|
||||
|
||||
public void setLast_week_users(int last_week_users) {
|
||||
this.last_week_users = last_week_users;
|
||||
}
|
||||
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
public void setSelected(boolean selected) {
|
||||
this.selected = selected;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package app.fedilab.android.drawers;
|
||||
/* Copyright 2019 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 <http://www.gnu.org/licenses>. */
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.FitCenter;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
||||
import java.util.List;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.activities.MastodonRegisterActivity;
|
||||
import app.fedilab.android.client.Entities.InstanceReg;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Thomas on 14/06/2019.
|
||||
* Adapter to display instances
|
||||
*/
|
||||
|
||||
public class InstanceRegAdapter extends RecyclerView.Adapter {
|
||||
private Context context;
|
||||
private List<InstanceReg> instanceRegs;
|
||||
private LayoutInflater layoutInflater;
|
||||
|
||||
public InstanceRegAdapter(Context context, List<InstanceReg> instanceRegs) {
|
||||
this.context = context;
|
||||
this.instanceRegs = instanceRegs;
|
||||
this.layoutInflater = LayoutInflater.from(this.context);
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return instanceRegs.size();
|
||||
}
|
||||
|
||||
public InstanceReg getItem(int position) {
|
||||
return instanceRegs.get(position);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(layoutInflater.inflate(R.layout.drawer_instance_reg, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
|
||||
InstanceReg instanceReg = instanceRegs.get(position);
|
||||
|
||||
final InstanceRegAdapter.ViewHolder holder = (InstanceRegAdapter.ViewHolder) viewHolder;
|
||||
|
||||
holder.instance_choose.setOnClickListener(v -> {
|
||||
((MastodonRegisterActivity)context).pickupInstance(instanceReg.getDomain());
|
||||
});
|
||||
|
||||
holder.instance_count_user.setText(context.getString(R.string.users,Helper.withSuffix(instanceReg.getTotal_users())));
|
||||
holder.instance_description.setText(instanceReg.getDescription());
|
||||
holder.instance_host.setText(instanceReg.getDomain());
|
||||
holder.instance_version.setText(String.format("%s - %s", instanceReg.getCategory(),instanceReg.getVersion()));
|
||||
Glide.with(context)
|
||||
.load(instanceReg.getProxied_thumbnail())
|
||||
.apply(new RequestOptions().transforms(new FitCenter(), new RoundedCorners(10)))
|
||||
.into(holder.instance_pp);
|
||||
}
|
||||
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return instanceRegs.size();
|
||||
}
|
||||
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder{
|
||||
ImageView instance_pp;
|
||||
TextView instance_host, instance_version, instance_description, instance_count_user;
|
||||
ImageButton instance_choose;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
instance_pp = itemView.findViewById(R.id.instance_pp);
|
||||
instance_host = itemView.findViewById(R.id.instance_host);
|
||||
instance_version = itemView.findViewById(R.id.instance_version);
|
||||
instance_description = itemView.findViewById(R.id.instance_description);
|
||||
instance_count_user = itemView.findViewById(R.id.instance_count_user);
|
||||
instance_choose = itemView.findViewById(R.id.instance_choose);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -104,6 +104,18 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:text="@string/connect_instance" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/create_an_account"
|
||||
android:gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/join_mastodon"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:visibility="gone"
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2019 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 <http://www.gnu.org/licenses>.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/parent"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:animateLayoutChanges="true"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<!-- category -->
|
||||
<TextView
|
||||
android:gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pickup_instance_category"/>
|
||||
<com.jaredrummler.materialspinner.MaterialSpinner
|
||||
android:textSize="16sp"
|
||||
android:id="@+id/reg_category"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/reg_category_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:visibility="gone"
|
||||
android:id="@+id/form_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:id="@+id/host_reg"
|
||||
android:textSize="18sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:layout_marginStart="10dp"
|
||||
android:id="@+id/change_instance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:visibility="gone"
|
||||
android:id="@+id/invitation"
|
||||
android:textColor="@color/red_1"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:text="@string/validation_needed"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:layout_margin="10dp"
|
||||
android:padding="5dp"
|
||||
android:id="@+id/error_message"
|
||||
android:textColor="@color/red_1"
|
||||
android:background="@drawable/red_border"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:layout_marginTop="20dp"
|
||||
android:labelFor="@+id/username"
|
||||
android:text="@string/username"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="wrap_content" />
|
||||
<EditText
|
||||
android:id="@+id/username"
|
||||
android:inputType="text"
|
||||
android:singleLine="true"
|
||||
android:maxLength="30"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/username_indicator"
|
||||
android:layout_width="match_parent"
|
||||
android:textSize="12sp"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:labelFor="@+id/email"
|
||||
android:text="@string/email"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="wrap_content" />
|
||||
<EditText
|
||||
android:id="@+id/email"
|
||||
android:inputType="textEmailAddress"
|
||||
android:singleLine="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/email_indicator"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/email_indicator"
|
||||
android:textSize="12sp"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:labelFor="@+id/password"
|
||||
android:text="@string/password"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="wrap_content" />
|
||||
<EditText
|
||||
android:id="@+id/password"
|
||||
android:inputType="textPassword"
|
||||
android:singleLine="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/password_indicator"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/password_indicator"
|
||||
android:textSize="12sp"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:labelFor="@+id/password_confirm"
|
||||
android:text="@string/password_confirm"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="wrap_content" />
|
||||
<EditText
|
||||
android:id="@+id/password_confirm"
|
||||
android:inputType="textPassword"
|
||||
android:singleLine="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<CheckBox
|
||||
android:id="@+id/agreement"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:id="@+id/agreement_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/signup"
|
||||
android:text="@string/sign_up"
|
||||
style="@style/Base.Widget.AppCompat.Button.Colored"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,89 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2019 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 <http://www.gnu.org/licenses>.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/main_container"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/border_bottom"
|
||||
android:divider="@null"
|
||||
android:layout_margin="10dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:baselineAligned="false">
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<ImageView
|
||||
android:id="@+id/instance_pp"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="@string/instance_logo" />
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/instance_host"
|
||||
android:textSize="16sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:id="@+id/instance_version"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/instance_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="60dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical">
|
||||
<ImageButton
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:id="@+id/instance_choose"
|
||||
style="@style/Widget.AppCompat.Button.Colored"
|
||||
android:layout_width="35dp"
|
||||
android:layout_height="35dp"
|
||||
android:layout_margin="5dp"
|
||||
android:background="@color/mastodonC4"
|
||||
android:contentDescription="@string/validate"
|
||||
android:src="@drawable/ic_check"
|
||||
android:tooltipText="@string/validate" />
|
||||
<TextView
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:id="@+id/instance_count_user"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -991,6 +991,42 @@
|
|||
<string name="mention_status">Mention the status</string>
|
||||
<string name="action_news">News</string>
|
||||
<string name="set_display_news_from_fedilab">Display news from Fedilab\'s account</string>
|
||||
<string name="category_general">General</string>
|
||||
<string name="category_regional">Regional</string>
|
||||
<string name="category_art">Art</string>
|
||||
<string name="category_journalism">Journalism</string>
|
||||
<string name="category_activism">Activism</string>
|
||||
<string name="category_games">Gaming</string>
|
||||
<string name="category_tech">Technology</string>
|
||||
<string name="category_adult">Adult content</string>
|
||||
<string name="category_furry">Furry</string>
|
||||
<string name="category_food">Food</string>
|
||||
<string name="instance_logo">Logo of the instance</string>
|
||||
<string name="toast_error_instance_reg">Something went wrong when checking available instances!</string>
|
||||
<string name="join_mastodon">Join Mastodon</string>
|
||||
<string name="pickup_instance_category">Choose an instance by picking up a category, then click on a check button.</string>
|
||||
<string name="users">%1$s users</string>
|
||||
<string name="password_confirm">Confirm password</string>
|
||||
<string name="agreement_check">I agree to %1$s and %2$s</string>
|
||||
<string name="server_rules">server rules</string>
|
||||
<string name="tos">terms of service</string>
|
||||
<string name="sign_up">Sign up</string>
|
||||
<string name="validation_needed">This instance works with invitations. Your account will need to be manually approved by an administrator before being usable.</string>
|
||||
<string name="all_field_filled">Please, fill all the fields!</string>
|
||||
<string name="password_error">Passwords don\'t match!</string>
|
||||
<string name="email_error">The email doesn\'t seem to be valid!</string>
|
||||
<string name="username_indicator">Your username will be unique on %1$s</string>
|
||||
<string name="email_indicator">You will be sent a confirmation e-mail</string>
|
||||
<string name="password_indicator">Use at least 8 characters</string>
|
||||
<string name="password_too_short">Password should contain at least 8 characters</string>
|
||||
<string name="username_error">Username should only contain letters, numbers and underscores</string>
|
||||
<string name="account_created">Account created!</string>
|
||||
<string name="account_created_message">
|
||||
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 <b>%1$s</b> in the first field and click on <b>Connect</b>.\n\n
|
||||
<b>Important</b>: If your instance required validation, you will receive an email once it is validated!
|
||||
</string>
|
||||
<plurals name="number_of_vote">
|
||||
<item quantity="one">%d vote</item>
|
||||
<item quantity="other">%d votes</item>
|
||||
|
|
Loading…
Reference in New Issue