diff --git a/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java b/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java index 941f8602d..63355d58c 100644 --- a/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java +++ b/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java @@ -148,11 +148,8 @@ public class MainActivity extends AppCompatActivity if(notificationsFragment.getUserVisibleHint() && isActivityVisible()){ notificationsFragment.updateData(notification); }else{ - updateNotifCounter(); notificationsFragment.refresh(notification); } - }else { - updateNotifCounter(); } }else if(eventStreaming == StreamingService.EventStreaming.UPDATE){ Status status = b.getParcelable("data"); @@ -160,11 +157,8 @@ public class MainActivity extends AppCompatActivity if(homeFragment.getUserVisibleHint() && isActivityVisible()){ homeFragment.updateData(status); }else{ - updateHomeCounter(); homeFragment.refresh(status); } - }else{ - updateHomeCounter(); } }else if(eventStreaming == StreamingService.EventStreaming.DELETE){ String id = b.getString("id"); @@ -176,6 +170,8 @@ public class MainActivity extends AppCompatActivity } } } + updateNotifCounter(); + updateHomeCounter(); } }; LocalBroadcastManager.getInstance(this).registerReceiver(receive_data, new IntentFilter(Helper.RECEIVE_DATA)); @@ -868,6 +864,8 @@ public class MainActivity extends AppCompatActivity public void onResume(){ super.onResume(); MainActivity.activityResumed(); + updateNotifCounter(); + updateHomeCounter(); //Proceeds to update of the authenticated account if(Helper.isLoggedIn(getApplicationContext())) new UpdateAccountInfoByIDAsyncTask(getApplicationContext(), MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/AboutActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/AboutActivity.java index 56802633c..ff352f391 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/AboutActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/AboutActivity.java @@ -23,23 +23,28 @@ import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; -import android.text.SpannableString; -import android.text.Spanned; -import android.text.TextPaint; -import android.text.method.LinkMovementMethod; -import android.text.style.ClickableSpan; +import android.util.Log; import android.view.MenuItem; +import android.view.MotionEvent; import android.view.View; import android.widget.Button; import android.widget.TextView; +import java.util.ArrayList; import java.util.List; import fr.gouv.etalab.mastodon.asynctasks.RetrieveDeveloperAccountsAsyncTask; -import fr.gouv.etalab.mastodon.client.APIResponse; +import fr.gouv.etalab.mastodon.asynctasks.RetrieveRelationshipAsyncTask; +import fr.gouv.etalab.mastodon.asynctasks.RetrieveRemoteAccountsAsyncTask; import fr.gouv.etalab.mastodon.client.Entities.Account; +import fr.gouv.etalab.mastodon.client.Entities.Error; +import fr.gouv.etalab.mastodon.client.Entities.Relationship; +import fr.gouv.etalab.mastodon.drawers.AccountSearchDevAdapter; +import fr.gouv.etalab.mastodon.helper.ExpandableHeightListView; import fr.gouv.etalab.mastodon.helper.Helper; -import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearcAccountshInterface; +import fr.gouv.etalab.mastodon.interfaces.OnRetrieveRelationshipInterface; +import fr.gouv.etalab.mastodon.interfaces.OnRetrieveRemoteAccountInterface; +import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchDevelopersAccountshInterface; import mastodon.etalab.gouv.fr.mastodon.R; @@ -48,9 +53,12 @@ import mastodon.etalab.gouv.fr.mastodon.R; * About activity */ -public class AboutActivity extends AppCompatActivity implements OnRetrieveSearcAccountshInterface { +public class AboutActivity extends AppCompatActivity implements OnRetrieveRemoteAccountInterface, OnRetrieveSearchDevelopersAccountshInterface, OnRetrieveRelationshipInterface { - private Button about_developer; + private List developers = new ArrayList<>(); + private List contributors = new ArrayList<>(); + private AccountSearchDevAdapter accountSearchWebAdapterDeveloper; + private AccountSearchDevAdapter accountSearchWebAdapterContributors; @SuppressWarnings("deprecation") @Override @@ -73,7 +81,8 @@ public class AboutActivity extends AppCompatActivity implements OnRetrieveSearcA about_version.setText(getResources().getString(R.string.about_vesrion, version)); } catch (PackageManager.NameNotFoundException ignored) {} - about_developer = (Button) findViewById(R.id.about_developer); + ExpandableHeightListView lv_developers = (ExpandableHeightListView) findViewById(R.id.lv_developers); + ExpandableHeightListView lv_contributors = (ExpandableHeightListView) findViewById(R.id.lv_contributors); Button about_code = (Button) findViewById(R.id.about_code); Button about_license = (Button) findViewById(R.id.about_license); Button about_thekinrar = (Button) findViewById(R.id.about_thekinrar); @@ -93,17 +102,7 @@ public class AboutActivity extends AppCompatActivity implements OnRetrieveSearcA startActivity(browserIntent); } }); - if(Helper.isLoggedIn(getApplicationContext())) { - about_developer.setEnabled(false); - new RetrieveDeveloperAccountsAsyncTask(getApplicationContext(),AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - about_developer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://mastodon.etalab.gouv.fr/@tschneider")); - startActivity(browserIntent); - } - }); + about_license.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -120,32 +119,21 @@ public class AboutActivity extends AppCompatActivity implements OnRetrieveSearcA } }); - TextView about_thanks = (TextView) findViewById(R.id.about_thanks_dev); - String currentText = about_thanks.getText().toString(); - SpannableString spanned_thanks = new SpannableString(currentText); - int startPosition = spanned_thanks.toString().indexOf("@PhotonQyv"); - int endPosition = startPosition + "@PhotonQyv".length(); - spanned_thanks.setSpan(new ClickableSpan() { - @Override - public void onClick(View textView) { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://mastodon.xyz/@PhotonQyv")); - startActivity(browserIntent); - } - @Override - public void updateDrawState(TextPaint ds) { - super.updateDrawState(ds); - } - }, startPosition, endPosition, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); - about_thanks.setText(spanned_thanks, TextView.BufferType.SPANNABLE); - about_thanks.setMovementMethod(LinkMovementMethod.getInstance()); if( theme == Helper.THEME_LIGHT) { - about_developer.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white)); about_code.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white)); about_thekinrar.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white)); about_translation.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white)); about_license.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white)); } + + lv_contributors.setExpanded(true); + lv_developers.setExpanded(true); + accountSearchWebAdapterContributors = new AccountSearchDevAdapter(AboutActivity.this, contributors); + lv_contributors.setAdapter(accountSearchWebAdapterContributors); + accountSearchWebAdapterDeveloper = new AccountSearchDevAdapter(AboutActivity.this, developers); + lv_developers.setAdapter(accountSearchWebAdapterDeveloper); + new RetrieveDeveloperAccountsAsyncTask(getApplicationContext(), AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -160,22 +148,99 @@ public class AboutActivity extends AppCompatActivity implements OnRetrieveSearcA } } + @Override - public void onRetrieveSearchAccounts(APIResponse apiResponse) { - about_developer.setEnabled(true); - final List accounts = apiResponse.getAccounts(); - if( accounts != null && accounts.size() > 0 && accounts.get(0) != null) { - about_developer.setOnClickListener(null); - about_developer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(AboutActivity.this, ShowAccountActivity.class); - Bundle b = new Bundle(); - b.putString("accountId", accounts.get(0).getId()); - intent.putExtras(b); - startActivity(intent); - } - }); + public void onRetrieveRemoteAccount(boolean error, String name, String username, String instance_name, boolean locked, String avatar, String bio, int statusCount, int followingCount, int followersCount) { + if( error){ + return; + } + Account account = new Account(); + account.setInstance(instance_name); + account.setAcct(username + "@" + instance_name); + account.setAvatar(avatar); + account.setDisplay_name(username); + account.setStatuses_count(statusCount); + account.setFollowers_count(followersCount); + account.setFollowing_count(followingCount); + account.setUsername(name); + account.setLocked(locked); + account.setNote(bio); + account.setFollowing(false); + account.setRemote(true); + + if( username.equals("@tschneider")) { + developers.add(account); + accountSearchWebAdapterDeveloper.notifyDataSetChanged(); + }else { + contributors.add(account); + accountSearchWebAdapterContributors.notifyDataSetChanged(); + } + + } + + @Override + public void onRetrieveSearchDevelopersAccounts(ArrayList accounts) { + if( accounts == null || accounts.size() == 0) { + new RetrieveRemoteAccountsAsyncTask("tschneider", "mastodon.etalab.gouv.fr", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new RetrieveRemoteAccountsAsyncTask("PhotonQyv", "mastodon.xyz", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new RetrieveRemoteAccountsAsyncTask("angrytux", "social.tchncs.de", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + return; + } + boolean tschneider = false; + boolean PhotonQyv = false; + boolean angrytux = false; + for(Account account: accounts){ + if( account.getUsername().equals("tschneider")){ + account.setFollowing(false); + account.setRemote(false); + developers.add(account); + accountSearchWebAdapterDeveloper.notifyDataSetChanged(); + tschneider = true; + new RetrieveRelationshipAsyncTask(getApplicationContext(), account.getId(),AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + if( account.getUsername().equals("PhotonQyv")){ + account.setFollowing(false); + account.setRemote(false); + contributors.add(account); + accountSearchWebAdapterContributors.notifyDataSetChanged(); + PhotonQyv = true; + new RetrieveRelationshipAsyncTask(getApplicationContext(), account.getId(),AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + if( account.getUsername().equals("angrytux")){ + account.setFollowing(false); + account.setRemote(false); + contributors.add(account); + accountSearchWebAdapterContributors.notifyDataSetChanged(); + angrytux = true; + new RetrieveRelationshipAsyncTask(getApplicationContext(), account.getId(),AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } + if( !tschneider) + new RetrieveRemoteAccountsAsyncTask("tschneider", "mastodon.etalab.gouv.fr", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + if( !PhotonQyv) + new RetrieveRemoteAccountsAsyncTask("PhotonQyv", "mastodon.xyz", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + if( !angrytux) + new RetrieveRemoteAccountsAsyncTask("angrytux", "social.tchncs.de", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + @Override + public void onRetrieveRelationship(Relationship relationship, Error error) { + SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); + String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, ""); + if( error != null){ + return; + } + for( int i = 0 ; i < developers.size() ; i++){ + if( developers.get(i).getId().equals(relationship.getId()) && relationship.isFollowing() || userId.trim().equals(relationship.getId())){ + developers.get(i).setFollowing(true); + accountSearchWebAdapterDeveloper.notifyDataSetChanged(); + } + } + for( int i = 0 ; i < contributors.size() ; i++){ + if( contributors.get(i).getId().equals(relationship.getId()) && relationship.isFollowing() || userId.trim().equals(relationship.getId())){ + contributors.get(i).setFollowing(true); + accountSearchWebAdapterContributors.notifyDataSetChanged(); + } } } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/RemoteFollowActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/RemoteFollowActivity.java index 55262e673..3047deb47 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/RemoteFollowActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/RemoteFollowActivity.java @@ -261,7 +261,7 @@ public class RemoteFollowActivity extends AppCompatActivity implements OnRetriev @Override - public void onRetrieveRemoteAccount(boolean error, String name, String username, boolean locked, String avatar, String bio, int statusCount, int followingCount, int followersCount) { + public void onRetrieveRemoteAccount(boolean error, String name, String username, String instance_name, boolean locked, String avatar, String bio, int statusCount, int followingCount, int followersCount) { loader.setVisibility(View.GONE); rf_search.setEnabled(true); if( error){ diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveDeveloperAccountsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveDeveloperAccountsAsyncTask.java index caa29d57a..63afa5432 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveDeveloperAccountsAsyncTask.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveDeveloperAccountsAsyncTask.java @@ -16,9 +16,13 @@ package fr.gouv.etalab.mastodon.asynctasks; import android.content.Context; import android.os.AsyncTask; + +import java.util.ArrayList; + import fr.gouv.etalab.mastodon.client.API; import fr.gouv.etalab.mastodon.client.APIResponse; -import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearcAccountshInterface; +import fr.gouv.etalab.mastodon.client.Entities.Account; +import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchDevelopersAccountshInterface; /** @@ -29,23 +33,32 @@ import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearcAccountshInterface; public class RetrieveDeveloperAccountsAsyncTask extends AsyncTask { private Context context; - private APIResponse apiResponse; - private OnRetrieveSearcAccountshInterface listener; + private OnRetrieveSearchDevelopersAccountshInterface listener; + private ArrayList accounts; - public RetrieveDeveloperAccountsAsyncTask(Context context, OnRetrieveSearcAccountshInterface onRetrieveSearcAccountshInterface){ + public RetrieveDeveloperAccountsAsyncTask(Context context, OnRetrieveSearchDevelopersAccountshInterface onRetrieveSearchDevelopersAccountshInterface){ this.context = context; - this.listener = onRetrieveSearcAccountshInterface; + this.listener = onRetrieveSearchDevelopersAccountshInterface; } @Override protected Void doInBackground(Void... params) { API api = new API(context); - apiResponse = api.searchDeveloper(); + accounts = new ArrayList<>(); + APIResponse apiResponse = api.searchAccounts("@tschneider@mastodon.etalab.gouv.fr", 1); + if( apiResponse.getAccounts() != null && apiResponse.getAccounts().size() > 0) + accounts.add(apiResponse.getAccounts().get(0)); + apiResponse = api.searchAccounts("@PhotonQyv@mastodon.xyz",1); + if( apiResponse.getAccounts() != null && apiResponse.getAccounts().size() > 0) + accounts.add(apiResponse.getAccounts().get(0)); + apiResponse = api.searchAccounts("@angrytux@social.tchncs.de",1); + if( apiResponse.getAccounts() != null && apiResponse.getAccounts().size() > 0) + accounts.add(apiResponse.getAccounts().get(0)); return null; } @Override protected void onPostExecute(Void result) { - listener.onRetrieveSearchAccounts(apiResponse); + listener.onRetrieveSearchDevelopersAccounts(accounts); } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRemoteAccountsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRemoteAccountsAsyncTask.java index 94141cbd1..2e3bfec6f 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRemoteAccountsAsyncTask.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRemoteAccountsAsyncTask.java @@ -15,10 +15,11 @@ package fr.gouv.etalab.mastodon.asynctasks; import android.os.AsyncTask; + import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.select.Elements; -import java.io.IOException; + import fr.gouv.etalab.mastodon.interfaces.OnRetrieveRemoteAccountInterface; @@ -56,23 +57,24 @@ public class RetrieveRemoteAccountsAsyncTask extends AsyncTask Elements nameElement = document.getElementsByClass("name"); name = nameElement.get(0).getElementsByClass("p-name").get(0).html(); username = nameElement.get(0).getElementsByTag("span").get(1).html(); - islocked = nameElement.get(0).getElementsByClass("fa-lock") != null; + islocked = (nameElement.get(0).getElementsByClass("fa-lock") != null && nameElement.get(0).getElementsByClass("fa-lock").size() > 0); Elements bioElement = document.getElementsByClass("bio"); bio = bioElement.get(0).html(); Elements countElement = document.getElementsByClass("counter-number"); - statusCount = Integer.parseInt(countElement.get(0).html()); - followingCount = Integer.parseInt(countElement.get(1).html()); - followersCount = Integer.parseInt(countElement.get(2).html()); - } catch (IOException | IndexOutOfBoundsException e) { + statusCount = Integer.parseInt(countElement.get(0).html().replace(",","")); + followingCount = Integer.parseInt(countElement.get(1).html().replace(",","")); + followersCount = Integer.parseInt(countElement.get(2).html().replace(",","")); + } catch (Exception e) { error = true; + e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void result) { - listener.onRetrieveRemoteAccount(error, name, username, islocked, avatar, bio, statusCount, followingCount, followersCount); + listener.onRetrieveRemoteAccount(error, name, username, instance, islocked, avatar, bio, statusCount, followingCount, followersCount); } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java index 312c42e4b..b16de7a9a 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java @@ -1118,37 +1118,6 @@ public class API { return results; } - /** - * Retrieves Developer account when searching (ie: via @...) *synchronously* - * - * @return APIResponse - */ - public APIResponse searchDeveloper() { - RequestParams params = new RequestParams(); - params.add("q", "tschneider"); - get("/accounts/search", params, new JsonHttpResponseHandler() { - @Override - public void onSuccess(int statusCode, Header[] headers, JSONObject response) { - accounts = new ArrayList<>(); - account = parseAccountResponse(context, response); - accounts.add(account); - apiResponse.setSince_id(findSinceId(headers)); - apiResponse.setMax_id(findMaxId(headers)); - } - @Override - public void onSuccess(int statusCode, Header[] headers, JSONArray response) { - accounts = parseDeveloperResponse(response); - apiResponse.setSince_id(findSinceId(headers)); - apiResponse.setMax_id(findMaxId(headers)); - } - @Override - public void onFailure(int statusCode, Header[] headers, Throwable error, JSONObject response){ - setError(statusCode, error); - } - }); - apiResponse.setAccounts(accounts); - return apiResponse; - } /** * Retrieves Accounts when searching (ie: via @...) *synchronously* * diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Account.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Account.java index de8cdadb6..85bf71f83 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Account.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Account.java @@ -43,6 +43,8 @@ public class Account implements Parcelable { private String header_static; private String token; private String instance; + private boolean isFollowing; + private boolean isRemote; protected Account(Parcel in) { id = in.readString(); @@ -237,4 +239,20 @@ public class Account implements Parcelable { dest.writeString(token); dest.writeString(instance); } + + public boolean isFollowing() { + return isFollowing; + } + + public void setFollowing(boolean following) { + isFollowing = following; + } + + public boolean isRemote() { + return isRemote; + } + + public void setRemote(boolean remote) { + isRemote = remote; + } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/AccountSearchDevAdapter.java b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/AccountSearchDevAdapter.java new file mode 100644 index 000000000..c05e52c87 --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/AccountSearchDevAdapter.java @@ -0,0 +1,206 @@ +package fr.gouv.etalab.mastodon.drawers; +/* Copyright 2017 Thomas Schneider + * + * This file is a part of Mastalab + * + * 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. + * + * Mastalab 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 Mastalab; if not, + * see . */ + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.drawable.Drawable; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.support.design.widget.FloatingActionButton; +import android.support.v4.content.ContextCompat; +import android.text.Html; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache; +import com.nostra13.universalimageloader.core.DisplayImageOptions; +import com.nostra13.universalimageloader.core.ImageLoader; +import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; +import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer; + +import java.io.File; +import java.util.List; + +import fr.gouv.etalab.mastodon.activities.ShowAccountActivity; +import fr.gouv.etalab.mastodon.asynctasks.PostActionAsyncTask; +import fr.gouv.etalab.mastodon.client.API; +import fr.gouv.etalab.mastodon.client.Entities.Account; +import fr.gouv.etalab.mastodon.client.Entities.Error; +import fr.gouv.etalab.mastodon.client.PatchBaseImageDownloader; +import fr.gouv.etalab.mastodon.helper.Helper; +import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface; +import mastodon.etalab.gouv.fr.mastodon.R; + +import static fr.gouv.etalab.mastodon.helper.Helper.changeDrawableColor; + + +/** + * Created by Thomas on 03/09/2017. + * Adapter for accounts from web + */ +public class AccountSearchDevAdapter extends BaseAdapter implements OnPostActionInterface { + + private List accounts; + private LayoutInflater layoutInflater; + private Context context; + private ViewHolder holder; + + public AccountSearchDevAdapter(Context context, List accounts){ + this.context = context; + this.accounts = accounts; + layoutInflater = LayoutInflater.from(context); + } + + + + @Override + public int getCount() { + return accounts.size(); + } + + @Override + public Object getItem(int position) { + return accounts.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + + ImageLoader imageLoader = ImageLoader.getInstance(); + File cacheDir = new File(context.getCacheDir(), context.getString(R.string.app_name)); + ImageLoaderConfiguration configImg = new ImageLoaderConfiguration.Builder(context) + .imageDownloader(new PatchBaseImageDownloader(context)) + .threadPoolSize(5) + .threadPriority(Thread.MIN_PRIORITY + 3) + .denyCacheImageMultipleSizesInMemory() + .diskCache(new UnlimitedDiskCache(cacheDir)) + .build(); + if( !imageLoader.isInited()) + imageLoader.init(configImg); + DisplayImageOptions options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false) + .cacheOnDisk(true).resetViewBeforeLoading(true).build(); + final Account account = accounts.get(position); + + if (convertView == null) { + convertView = layoutInflater.inflate(R.layout.drawer_account_search_dev, parent, false); + holder = new ViewHolder(); + holder.account_pp = (ImageView) convertView.findViewById(R.id.account_pp); + holder.account_dn = (TextView) convertView.findViewById(R.id.account_dn); + holder.account_un = (TextView) convertView.findViewById(R.id.account_un); + holder.account_follow = (FloatingActionButton) convertView.findViewById(R.id.account_follow); + holder.acccount_container = (LinearLayout) convertView.findViewById(R.id.acccount_container); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + //Redraws icon for locked accounts + final float scale = context.getResources().getDisplayMetrics().density; + if( account != null && account.isLocked()){ + Drawable img = ContextCompat.getDrawable(context, R.drawable.ic_action_lock_closed); + img.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (20 * scale + 0.5f)); + holder.account_dn.setCompoundDrawables( null, null, img, null); + }else{ + holder.account_dn.setCompoundDrawables( null, null, null, null); + } + + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + holder.account_dn.setText(Html.fromHtml(Helper.shortnameToUnicode(account.getDisplay_name(), true), Html.FROM_HTML_MODE_LEGACY)); + holder.account_un.setText(Html.fromHtml(Helper.shortnameToUnicode(account.getUsername(), true), Html.FROM_HTML_MODE_LEGACY)); + }else { + //noinspection deprecation + holder.account_dn.setText(Html.fromHtml(Helper.shortnameToUnicode(account.getDisplay_name(), true))); + holder.account_un.setText(Html.fromHtml(Helper.shortnameToUnicode(account.getUsername(), true))); + } + changeDrawableColor(context, R.drawable.ic_action_lock_closed,R.color.mastodonC4); + //Profile picture + imageLoader.displayImage(account.getAvatar(), holder.account_pp, options); + + if( account.isFollowing()){ + holder.account_follow.setVisibility(View.GONE); + }else{ + holder.account_follow.setVisibility(View.VISIBLE); + } + + if( account.isRemote()) { + holder.account_follow.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + holder.account_follow.setEnabled(false); + new PostActionAsyncTask(context, API.StatusAction.REMOTE_FOLLOW, account.getAcct(), AccountSearchDevAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + }); + }else { + holder.account_follow.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + holder.account_follow.setEnabled(false); + new PostActionAsyncTask(context, API.StatusAction.FOLLOW, account.getId(), AccountSearchDevAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + }); + holder.acccount_container.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(context, ShowAccountActivity.class); + Bundle b = new Bundle(); + b.putString("accountId", account.getId()); + intent.putExtras(b); + context.startActivity(intent); + } + }); + } + + return convertView; + } + + @Override + public void onPostAction(int statusCode, API.StatusAction statusAction, String userId, Error error) { + if( error != null){ + final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + boolean show_error_messages = sharedpreferences.getBoolean(Helper.SET_SHOW_ERROR_MESSAGES, true); + if( show_error_messages) + Toast.makeText(context, error.getError(),Toast.LENGTH_LONG).show(); + holder.account_follow.setEnabled(true); + return; + } + holder.account_follow.setVisibility(View.GONE); + Toast.makeText(context, R.string.toast_follow, Toast.LENGTH_LONG).show(); + } + + + private class ViewHolder { + LinearLayout acccount_container; + ImageView account_pp; + TextView account_dn; + TextView account_un; + FloatingActionButton account_follow; + } + +} \ No newline at end of file diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/ExpandableHeightListView.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/ExpandableHeightListView.java new file mode 100644 index 000000000..bf207a0f8 --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/ExpandableHeightListView.java @@ -0,0 +1,64 @@ +package fr.gouv.etalab.mastodon.helper; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; + +/** + * Created by Thomas on 03/09/2017. + * Expanded listview + */ + +public class ExpandableHeightListView extends ListView + { + + boolean expanded = false; + + public ExpandableHeightListView(Context context) + { + super(context); + } + + public ExpandableHeightListView(Context context, AttributeSet attrs) + { + super(context, attrs); + } + + public ExpandableHeightListView(Context context, AttributeSet attrs,int defStyle) + { + super(context, attrs, defStyle); + } + + public boolean isExpanded() + { + return expanded; + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) + { + // HACK! TAKE THAT ANDROID! + if (isExpanded()) + { + // Calculate entire height by providing a very large height hint. + // But do not use the highest 2 bits of this integer; those are + // reserved for the MeasureSpec mode. + int expandSpec = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST); + super.onMeasure(widthMeasureSpec, expandSpec); + + ViewGroup.LayoutParams params = getLayoutParams(); + params.height = getMeasuredHeight(); + } + else + { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + + public void setExpanded(boolean expanded) + { + this.expanded = expanded; + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java index c5ff7961c..ad3a4b7c4 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java @@ -18,6 +18,7 @@ package fr.gouv.etalab.mastodon.helper; import android.app.Activity; +import android.preference.PreferenceManager; import android.support.annotation.RequiresApi; import android.support.v7.app.AlertDialog; import android.app.DownloadManager; @@ -81,6 +82,7 @@ import android.widget.TextView; import android.widget.Toast; import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import com.loopj.android.http.BuildConfig; import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache; import com.nostra13.universalimageloader.core.DisplayImageOptions; @@ -102,11 +104,13 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.lang.reflect.Type; import java.net.InetAddress; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; @@ -203,8 +207,10 @@ public class Helper { public static final String SET_PREVIEW_REPLIES_PP = "set_preview_replies_pp"; public static final String SET_TRANSLATOR = "set_translator"; public static final String SET_LED_COLOUR = "set_led_colour"; - public static final String SET_UNREAD_NOTIFICATIONS = "set_unread_notifications"; - public static final String SET_UNREAD_TOOTS = "set_unread_toots"; + private static final String SET_UNREAD_NOTIFICATIONS = "set_unread_notifications"; + private static final String SET_UNREAD_TOOTS = "set_unread_toots"; + private static final String SET_DEVELOPERS = "set_developers"; + private static final String SET_DEVELOPERS_CACHE_DATE = "set_developers_cache_date"; public static final int ATTACHMENT_ALWAYS = 1; public static final int ATTACHMENT_WIFI = 2; @@ -1672,4 +1678,31 @@ public class Helper { editor.apply(); } } + + + public static String[] developers = { + "https://mastodon.etalab.gouv.fr/@tschneider", + "https://mastodon.xyz/@PhotonQyv", + "https://social.tchncs.de/@angrytux" + }; + + public static void cacheDevelopers(Context context, ArrayList accounts){ + SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedpreferences.edit(); + Gson gson = new Gson(); + String serializedAccounts = gson.toJson(accounts); + editor.putString(Helper.SET_DEVELOPERS, serializedAccounts); + editor.putString(Helper.SET_DEVELOPERS_CACHE_DATE, dateToString(context, new Date())); + editor.apply(); + } + + + public static ArrayList getDevelopers(Context context){ + SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + Gson gson = new Gson(); + String json = sharedpreferences.getString(Helper.SET_DEVELOPERS, null); + Type type = new TypeToken>() {}.getType(); + return gson.fromJson(json, type); + } + } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveRemoteAccountInterface.java b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveRemoteAccountInterface.java index 4d984933e..4388e231d 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveRemoteAccountInterface.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveRemoteAccountInterface.java @@ -20,5 +20,5 @@ package fr.gouv.etalab.mastodon.interfaces; * Interface for retrieving a remote account */ public interface OnRetrieveRemoteAccountInterface { - void onRetrieveRemoteAccount(boolean error, String name, String username, boolean locked, String avatar, String bio, int statusCount, int followingCount, int followersCount); + void onRetrieveRemoteAccount(boolean error, String name, String username, String instance, boolean locked, String avatar, String bio, int statusCount, int followingCount, int followersCount); } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveSearchDevelopersAccountshInterface.java b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveSearchDevelopersAccountshInterface.java new file mode 100644 index 000000000..12b1db865 --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveSearchDevelopersAccountshInterface.java @@ -0,0 +1,28 @@ +/* Copyright 2017 Thomas Schneider + * + * This file is a part of Mastalab + * + * 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. + * + * Mastalab 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 Mastalab; if not, + * see . */ +package fr.gouv.etalab.mastodon.interfaces; + +import java.util.ArrayList; + +import fr.gouv.etalab.mastodon.client.Entities.Account; + + +/** + * Created by Thomas on 03/09/2017. + * Interface for search dev accounts + */ +public interface OnRetrieveSearchDevelopersAccountshInterface { + void onRetrieveSearchDevelopersAccounts(ArrayList accounts); +} diff --git a/app/src/main/res/layout-sw600dp/activity_about.xml b/app/src/main/res/layout-sw600dp/activity_about.xml index 1ebba5a63..0974666b6 100644 --- a/app/src/main/res/layout-sw600dp/activity_about.xml +++ b/app/src/main/res/layout-sw600dp/activity_about.xml @@ -40,40 +40,42 @@ android:layout_height="wrap_content" /> - + - -