diff --git a/app/src/main/java/app/fedilab/android/activities/LoginActivity.java b/app/src/main/java/app/fedilab/android/activities/LoginActivity.java index 038007008..19aff3d16 100644 --- a/app/src/main/java/app/fedilab/android/activities/LoginActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/LoginActivity.java @@ -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); 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 fbd6c1fb2..35f7a667c 100644 --- a/app/src/main/java/app/fedilab/android/activities/MastodonRegisterActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/MastodonRegisterActivity.java @@ -20,27 +20,43 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; +import android.widget.Toast; import androidx.appcompat.app.ActionBar; import androidx.appcompat.widget.Toolbar; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import com.jaredrummler.materialspinner.MaterialSpinner; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; import app.fedilab.android.R; +import app.fedilab.android.asynctasks.RetrieveInstanceRegAsyncTask; +import app.fedilab.android.client.APIResponse; +import app.fedilab.android.client.Entities.InstanceReg; +import app.fedilab.android.drawers.InstanceRegAdapter; import app.fedilab.android.helper.Helper; +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 { +public class MastodonRegisterActivity extends BaseActivity implements OnRetrieveInstanceInterface { + private Map categories; - private Map createMap() { - Map categories = new HashMap<>(); + private void createMap() { + categories = new HashMap<>(); categories.put("general", getString(R.string.category_general)); categories.put("regional", getString(R.string.category_regional)); categories.put("art", getString(R.string.category_art)); @@ -52,7 +68,6 @@ public class MastodonRegisterActivity extends BaseActivity { categories.put("adult", getString(R.string.category_adult)); categories.put("furry", getString(R.string.category_furry)); categories.put("food", getString(R.string.category_food)); - return categories; } @Override @@ -75,8 +90,8 @@ public class MastodonRegisterActivity extends BaseActivity { default: setTheme(R.style.AppThemeDark); } - - setContentView(R.layout.activity_login); + createMap(); + setContentView(R.layout.activity_register); ActionBar actionBar = getSupportActionBar(); if( actionBar != null ) { LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE); @@ -98,6 +113,35 @@ public class MastodonRegisterActivity extends BaseActivity { Helper.colorizeToolbar(toolbar, R.color.black, MastodonRegisterActivity.this); } } + + MaterialSpinner reg_category = findViewById(R.id.reg_category); + Helper.changeMaterialSpinnerColor(MastodonRegisterActivity.this, reg_category); + + String[] categoriesA = new String[categories.size()]; + String[] itemA = new String[categories.size()]; + Iterator it = categories.entrySet().iterator(); + int i = 0; + while (it.hasNext()) { + Map.Entry pair = (Map.Entry)it.next(); + itemA[i] = (String)pair.getKey(); + categoriesA[i] = (String)pair.getValue(); + i++; + it.remove(); + } + ArrayAdapter adcategories = new ArrayAdapter<>(MastodonRegisterActivity.this, + android.R.layout.simple_spinner_dropdown_item, categoriesA); + + reg_category.setAdapter(adcategories); + + //Manage privacies + reg_category.setOnItemSelectedListener(new MaterialSpinner.OnItemSelectedListener() { + @Override + public void onItemSelected(MaterialSpinner view, int position, long id, String item) { + + } + }); + + new RetrieveInstanceRegAsyncTask(MastodonRegisterActivity.this, "general", MastodonRegisterActivity.this).executeOnExecutor(THREAD_POOL_EXECUTOR); } @Override @@ -105,4 +149,20 @@ public class MastodonRegisterActivity extends BaseActivity { 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 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); + + + } } \ No newline at end of file diff --git a/app/src/main/java/app/fedilab/android/asynctasks/RetrieveInstanceRegAsyncTask.java b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveInstanceRegAsyncTask.java new file mode 100644 index 000000000..e1c001b3e --- /dev/null +++ b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveInstanceRegAsyncTask.java @@ -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 . */ +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 { + + private OnRetrieveInstanceInterface listener; + private APIResponse apiResponse; + private WeakReference 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); + } + +} 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 1eac6cf27..7fc2f6407 100644 --- a/app/src/main/java/app/fedilab/android/client/API.java +++ b/app/src/main/java/app/fedilab/android/client/API.java @@ -58,6 +58,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 +347,30 @@ public class API { } + /*** + * Get instance for registering an account *synchronously* + * @return APIResponse + */ + public APIResponse getInstanceReg(String category) { + try { + String response = new HttpsConnection(context, null).get(String.format("https://api.joinmastodon.org/servers?category=%s", category)); + List 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* @@ -4403,6 +4428,54 @@ public class API { return instance; } + + + /** + * Parse json response for several instance reg + * @param jsonArray JSONArray + * @return List + */ + public List parseInstanceReg(JSONArray jsonArray){ + + List 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 diff --git a/app/src/main/java/app/fedilab/android/client/APIResponse.java b/app/src/main/java/app/fedilab/android/client/APIResponse.java index 228382c48..f869dc467 100644 --- a/app/src/main/java/app/fedilab/android/client/APIResponse.java +++ b/app/src/main/java/app/fedilab/android/client/APIResponse.java @@ -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 storedStatuses; private boolean fetchmore = false; private List playlistForVideos; + private List instanceRegs = null; + public List getAccounts() { return accounts; @@ -238,4 +241,12 @@ public class APIResponse { public void setPlaylistForVideos(List playlistForVideos) { this.playlistForVideos = playlistForVideos; } + + public List getInstanceRegs() { + return instanceRegs; + } + + public void setInstanceRegs(List instanceRegs) { + this.instanceRegs = instanceRegs; + } } diff --git a/app/src/main/java/app/fedilab/android/drawers/InstanceRegAdapter.java b/app/src/main/java/app/fedilab/android/drawers/InstanceRegAdapter.java new file mode 100644 index 000000000..e07c0b3ea --- /dev/null +++ b/app/src/main/java/app/fedilab/android/drawers/InstanceRegAdapter.java @@ -0,0 +1,85 @@ +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 . */ + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import java.util.List; +import app.fedilab.android.R; +import app.fedilab.android.client.Entities.InstanceReg; + + +/** + * Created by Thomas on 14/06/2019. + * Adapter to display instances + */ + +public class InstanceRegAdapter extends RecyclerView.Adapter { + private Context context; + private List instanceRegs; + private LayoutInflater layoutInflater; + + public InstanceRegAdapter(Context context, List 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; + + } + + public long getItemId(int position) { + return position; + } + + @Override + public int getItemCount() { + return instanceRegs.size(); + } + + + class ViewHolder extends RecyclerView.ViewHolder{ + ImageView imageView; + + public ViewHolder(View itemView) { + super(itemView); + imageView = itemView.findViewById(R.id.media); + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 2860a5d3e..cbe675d89 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -104,6 +104,18 @@ android:layout_height="wrap_content" android:textSize="20sp" android:text="@string/connect_instance" /> + + + + - - + + \ No newline at end of file diff --git a/app/src/main/res/layout/drawer_instance_reg.xml b/app/src/main/res/layout/drawer_instance_reg.xml new file mode 100644 index 000000000..375251849 --- /dev/null +++ b/app/src/main/res/layout/drawer_instance_reg.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + +