From ebdf48df70e49b6e3f35ad4280f46aab1b793108 Mon Sep 17 00:00:00 2001 From: stom79 Date: Wed, 26 Dec 2018 15:43:36 +0100 Subject: [PATCH] Follow PixelFed instances --- .../mastodon/activities/BaseMainActivity.java | 53 ++++++- .../mastodon/activities/MediaActivity.java | 2 +- .../asynctasks/RetrieveFeedsAsyncTask.java | 6 +- .../fr/gouv/etalab/mastodon/client/API.java | 40 ++++- .../mastodon/drawers/StatusListAdapter.java | 145 ++++++++++++++---- .../fragments/DisplayStatusFragment.java | 34 ++-- .../etalab/mastodon/helper/CrossActions.java | 12 +- .../gouv/etalab/mastodon/helper/Helper.java | 12 +- app/src/main/res/drawable-hdpi/pixelfed.png | Bin 0 -> 2045 bytes app/src/main/res/drawable-ldpi/pixelfed.png | Bin 0 -> 704 bytes app/src/main/res/drawable-mdpi/pixelfed.png | Bin 0 -> 1127 bytes app/src/main/res/drawable-xhdpi/pixelfed.png | Bin 0 -> 3137 bytes app/src/main/res/drawable-xxhdpi/pixelfed.png | Bin 0 -> 5886 bytes .../main/res/drawable-xxxhdpi/pixelfed.png | Bin 0 -> 8674 bytes app/src/main/res/layout/drawer_art.xml | 33 +++- app/src/main/res/layout/search_instance.xml | 27 +++- app/src/main/res/menu/remote_instances.xml | 10 ++ app/src/main/res/values/strings.xml | 3 + 18 files changed, 301 insertions(+), 76 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/pixelfed.png create mode 100644 app/src/main/res/drawable-ldpi/pixelfed.png create mode 100644 app/src/main/res/drawable-mdpi/pixelfed.png create mode 100644 app/src/main/res/drawable-xhdpi/pixelfed.png create mode 100644 app/src/main/res/drawable-xxhdpi/pixelfed.png create mode 100644 app/src/main/res/drawable-xxxhdpi/pixelfed.png diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java index c067df164..b854beaeb 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java @@ -70,10 +70,10 @@ import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; -import android.widget.CheckBox; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.RadioGroup; import android.widget.RelativeLayout; import android.widget.SeekBar; import android.widget.TextView; @@ -407,6 +407,7 @@ public abstract class BaseMainActivity extends BaseActivity if(remoteInstances != null) { SubMenu submMastodon = popup.getMenu().findItem(R.id.action_show_mastodon).getSubMenu(); SubMenu submPeertube = popup.getMenu().findItem(R.id.action_show_peertube).getSubMenu(); + SubMenu submPixelfed = popup.getMenu().findItem(R.id.action_show_pixelfed).getSubMenu(); SubMenu submChannel = popup.getMenu().findItem(R.id.action_show_channel).getSubMenu(); int i = 0, j = 0 , k = 0; for (RemoteInstance remoteInstance : remoteInstances) { @@ -473,6 +474,37 @@ public abstract class BaseMainActivity extends BaseActivity }); k++; } + if (remoteInstance.getType() == null || remoteInstance.getType().equals("PIXELFED")) { + MenuItem itemPlaceHolder = submPixelfed.findItem(R.id.pixelfed_instance); + if( itemPlaceHolder != null) + itemPlaceHolder.setVisible(false); + MenuItem item = submPixelfed.add(0, j, Menu.NONE, remoteInstance.getHost()); + item.setIcon(R.drawable.pixelfed); + item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + DisplayStatusFragment statusFragment; + Bundle bundle = new Bundle(); + statusFragment = new DisplayStatusFragment(); + bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.PIXELFED); + bundle.putString("remote_instance", remoteInstance.getHost()); + statusFragment.setArguments(bundle); + String fragmentTag = "REMOTE_INSTANCE"; + instance_id = remoteInstance.getDbID(); + FragmentManager fragmentManager = getSupportFragmentManager(); + fragmentManager.beginTransaction() + .replace(R.id.main_app_container, statusFragment, fragmentTag).commit(); + main_app_container.setVisibility(View.VISIBLE); + viewPager.setVisibility(View.GONE); + tabLayout.setVisibility(View.GONE); + toolbarTitle.setVisibility(View.VISIBLE); + delete_instance.setVisibility(View.VISIBLE); + toolbarTitle.setText(remoteInstance.getHost()); + return false; + } + }); + j++; + } if (remoteInstance.getType() == null || remoteInstance.getType().equals("PEERTUBE")) { MenuItem itemPlaceHolder = submPeertube.findItem(R.id.peertube_instances); if( itemPlaceHolder != null) @@ -516,7 +548,9 @@ public abstract class BaseMainActivity extends BaseActivity dialogBuilder.setView(dialogView); AutoCompleteTextView instance_list = dialogView.findViewById(R.id.search_instance); - CheckBox peertube_instance = dialogView.findViewById(R.id.peertube_instance); + //Manage download of attachments + RadioGroup radioGroup = dialogView.findViewById(R.id.set_attachment_group); + instance_list.setFilters(new InputFilter[]{new InputFilter.LengthFilter(60)}); dialogBuilder.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() { @Override @@ -527,18 +561,23 @@ public abstract class BaseMainActivity extends BaseActivity @Override public void run() { try { - if( !peertube_instance.isChecked()) + if(radioGroup.getCheckedRadioButtonId() == R.id.mastodon_instance) new HttpsConnection(BaseMainActivity.this).get("https://" + instanceName + "/api/v1/timelines/public?local=true", 10, null, null); - else + else if( radioGroup.getCheckedRadioButtonId() == R.id.peertube_instance) new HttpsConnection(BaseMainActivity.this).get("https://" + instanceName + "/api/v1/videos/", 10, null, null); + else if( radioGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance) { + new HttpsConnection(BaseMainActivity.this).get("https://" + instanceName + "/api/v1/timelines/public", 10, null, null); + } runOnUiThread(new Runnable() { public void run() { JSONObject resobj; dialog.dismiss(); - if( peertube_instance.isChecked()) - new InstancesDAO(BaseMainActivity.this, db).insertInstance(instanceName, "PEERTUBE"); - else + if(radioGroup.getCheckedRadioButtonId() == R.id.mastodon_instance) new InstancesDAO(BaseMainActivity.this, db).insertInstance(instanceName, "MASTODON"); + else if( radioGroup.getCheckedRadioButtonId() == R.id.peertube_instance) + new InstancesDAO(BaseMainActivity.this, db).insertInstance(instanceName, "PEERTUBE"); + else if( radioGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance) + new InstancesDAO(BaseMainActivity.this, db).insertInstance(instanceName, "PIXELFED"); DisplayStatusFragment statusFragment; Bundle bundle = new Bundle(); statusFragment = new DisplayStatusFragment(); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/MediaActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/MediaActivity.java index b14fefa4c..bbef6be7e 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/MediaActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/MediaActivity.java @@ -368,7 +368,7 @@ public class MediaActivity extends BaseActivity implements OnDownloadInterface { attachment.setType(type); } final String finalUrl = url; - switch (type){ + switch (type.toLowerCase()){ case "image": pbar_inf.setScaleY(1f); imageView.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java index c7ba3c25e..5c7991ca8 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java @@ -75,7 +75,8 @@ public class RetrieveFeedsAsyncTask extends AsyncTask { CACHE_STATUS, REMOTE_INSTANCE, ART, - NOTIFICATION + NOTIFICATION, + PIXELFED } @@ -159,6 +160,9 @@ public class RetrieveFeedsAsyncTask extends AsyncTask { case CONVERSATION: apiResponse = api.getConversationTimeline(max_id); break; + case PIXELFED: + apiResponse = api.getPixelfedTimeline(instanceName, max_id); + break; case REMOTE_INSTANCE: if( this.name != null && this.remoteInstance != null){ //For Peertube channels apiResponse = api.getPeertubeChannelVideos(this.remoteInstance, this.name); 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 bc47ba348..b44c97c3f 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 @@ -803,6 +803,38 @@ public class API { } + + /** + * Retrieves public pixelfed timeline for the account *synchronously* + * @param max_id String id max + * @return APIResponse + */ + public APIResponse getPixelfedTimeline(String remoteInstance, String max_id) { + + HashMap params = new HashMap<>(); + if (max_id != null) + params.put("page", max_id); + statuses = new ArrayList<>(); + try { + HttpsConnection httpsConnection = new HttpsConnection(context); + String response = httpsConnection.get(getAbsoluteUrlRemote(remoteInstance, "/timelines/public/"), 60, params, prefKeyOauthTokenT); + apiResponse.setSince_id(httpsConnection.getSince_id()); + apiResponse.setMax_id(httpsConnection.getMax_id()); + statuses = parseStatuses(context, new JSONArray(response)); + } 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(); + } + apiResponse.setStatuses(statuses); + return apiResponse; + } /** * Retrieves Peertube videos from an instance *synchronously* * @return APIResponse @@ -2957,9 +2989,6 @@ public class API { }catch (Exception e){status.setVisibility("public");} status.setLanguage(resobj.get("language").toString()); status.setUrl(resobj.get("url").toString()); - //TODO: replace by the value - status.setApplication(new Application()); - //Retrieves attachments JSONArray arrayAttachement = resobj.getJSONArray("media_attachments"); ArrayList attachments = new ArrayList<>(); @@ -3043,7 +3072,6 @@ public class API { } status.setApplication(application); - status.setAccount(parseAccountResponse(context, resobj.getJSONObject("account"))); status.setContent(resobj.get("content").toString()); status.setFavourites_count(Integer.valueOf(resobj.get("favourites_count").toString())); @@ -3593,7 +3621,9 @@ public class API { private String getAbsoluteUrl(String action) { return Helper.instanceWithProtocol(this.instance) + "/api/v1" + action; } - + private String getAbsoluteUrlRemote(String remote, String action) { + return "https://" + remote + "/api/v1" + action; + } private String getAbsoluteUrlRemoteInstance(String instanceName) { return "https://" + instanceName + "/api/v1/timelines/public?local=true"; diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java index b6561dbf6..ff2ab3574 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java @@ -32,6 +32,7 @@ import android.os.Bundle; import android.os.CountDownTimer; import android.os.Handler; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import android.support.v7.widget.PopupMenu; @@ -63,12 +64,16 @@ import android.widget.TimePicker; import android.widget.Toast; import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; import com.bumptech.glide.load.resource.bitmap.CenterCrop; import com.bumptech.glide.load.resource.bitmap.FitCenter; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; +import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.target.Target; import com.bumptech.glide.request.transition.Transition; import com.github.stom79.mytransl.MyTransL; import com.github.stom79.mytransl.client.HttpsConnectionException; @@ -106,6 +111,7 @@ import fr.gouv.etalab.mastodon.client.Entities.Emojis; import fr.gouv.etalab.mastodon.client.Entities.Error; import fr.gouv.etalab.mastodon.client.Entities.Status; import fr.gouv.etalab.mastodon.client.Entities.TagTimeline; +import fr.gouv.etalab.mastodon.client.Glide.GlideApp; import fr.gouv.etalab.mastodon.fragments.DisplayStatusFragment; import fr.gouv.etalab.mastodon.helper.CrossActions; import fr.gouv.etalab.mastodon.helper.CustomTextView; @@ -230,7 +236,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct @Override public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) { super.onViewAttachedToWindow(holder); - if( type != RetrieveFeedsAsyncTask.Type.ART && (tagTimeline == null || !tagTimeline.isART()) && (holder.getItemViewType() == DISPLAYED_STATUS || holder.getItemViewType() == COMPACT_STATUS)) { + if( type != RetrieveFeedsAsyncTask.Type.ART && type != RetrieveFeedsAsyncTask.Type.PIXELFED && (tagTimeline == null || !tagTimeline.isART()) && (holder.getItemViewType() == DISPLAYED_STATUS || holder.getItemViewType() == COMPACT_STATUS)) { final ViewHolder viewHolder = (ViewHolder) holder; // Bug workaround for losing text selection ability, see: // https://code.google.com/p/android/issues/detail?id=208169 @@ -247,6 +253,8 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct ImageView art_media, art_pp; TextView art_username, art_acct; LinearLayout art_author; + RelativeLayout status_show_more; + ImageView show_more_button_art; ViewHolderArt(View itemView) { super(itemView); art_media = itemView.findViewById(R.id.art_media); @@ -254,6 +262,8 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct art_username = itemView.findViewById(R.id.art_username); art_acct = itemView.findViewById(R.id.art_acct); art_author = itemView.findViewById(R.id.art_author); + status_show_more = itemView.findViewById(R.id.status_show_more); + show_more_button_art = itemView.findViewById(R.id.show_more_button_art); } } @@ -436,7 +446,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - if( type == RetrieveFeedsAsyncTask.Type.ART || (tagTimeline != null && tagTimeline.isART())) + if(type == RetrieveFeedsAsyncTask.Type.PIXELFED || type == RetrieveFeedsAsyncTask.Type.ART || (tagTimeline != null && tagTimeline.isART())) return new ViewHolderArt(layoutInflater.inflate(R.layout.drawer_art, parent, false)); else if( viewType == DISPLAYED_STATUS) return new ViewHolder(layoutInflater.inflate(R.layout.drawer_status, parent, false)); @@ -455,58 +465,125 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int i) { final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); final String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); - if( (type == RetrieveFeedsAsyncTask.Type.ART || (tagTimeline != null && tagTimeline.isART())) && viewHolder.getItemViewType() != HIDDEN_STATUS ) { + if( (type == RetrieveFeedsAsyncTask.Type.PIXELFED || type == RetrieveFeedsAsyncTask.Type.ART || (tagTimeline != null && tagTimeline.isART())) && viewHolder.getItemViewType() != HIDDEN_STATUS ) { final ViewHolderArt holder = (ViewHolderArt) viewHolder; final Status status = statuses.get(viewHolder.getAdapterPosition()); - if( !status.isClickable()) Status.transform(context, status); if( !status.isEmojiFound()) Status.makeEmojis(context, this, status); - if( status.getArt_attachment() != null) - Glide.with(context) - .load(status.getArt_attachment().getPreview_url()) - .into(holder.art_media); + if( status.getAccount() != null && status.getAccount().getAvatar() != null) Glide.with(context) .load(status.getAccount().getAvatar()) .apply(new RequestOptions().transforms(new FitCenter(), new RoundedCorners(10))) .into(holder.art_pp); - holder.art_pp.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(context, ShowAccountActivity.class); - Bundle b = new Bundle(); - b.putParcelable("account", status.getAccount()); - intent.putExtras(b); - context.startActivity(intent); + + if( type == RetrieveFeedsAsyncTask.Type.PIXELFED){ + boolean expand_media = sharedpreferences.getBoolean(Helper.SET_EXPAND_MEDIA, false); + if( status.getMedia_attachments() != null && status.getMedia_attachments().size() > 0) + GlideApp.with(context) + .asBitmap() + .load(status.getMedia_attachments().get(0).getPreview_url()) + .listener(new RequestListener(){ + @Override + public boolean onResourceReady(Bitmap resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + if(status.isSensitive()) + notifyStatusChanged(status); + return false; + } + + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + return false; + } + }) + .into(holder.art_media); + RelativeLayout.LayoutParams rel_btn = new RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, holder.art_media.getHeight()); + holder.status_show_more.setLayoutParams(rel_btn); + if (expand_media || !status.isSensitive()) { + status.setAttachmentShown(true); + holder.status_show_more.setVisibility(View.GONE); + } else { + if (!status.isAttachmentShown()) { + holder.status_show_more.setVisibility(View.VISIBLE); + } else { + holder.status_show_more.setVisibility(View.GONE); + } } - }); + + holder.show_more_button_art.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + status.setAttachmentShown(true); + notifyStatusChanged(status); + } + }); + }else{ + if( status.getArt_attachment() != null) + Glide.with(context) + .load(status.getArt_attachment().getPreview_url()) + .into(holder.art_media); + } + if( type == RetrieveFeedsAsyncTask.Type.PIXELFED){ + holder.art_pp.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CrossActions.doCrossProfile(context, status.getAccount()); + } + }); + }else { + holder.art_pp.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(context, ShowAccountActivity.class); + Bundle b = new Bundle(); + b.putParcelable("account", status.getAccount()); + intent.putExtras(b); + context.startActivity(intent); + } + }); + } + holder.art_media.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(context, MediaActivity.class); Bundle b = new Bundle(); ArrayList attachments = new ArrayList<>(); - attachments.add(status.getArt_attachment()); + if( status.getArt_attachment() != null) + attachments.add(status.getArt_attachment()); + else if( status.getMedia_attachments() != null && status.getMedia_attachments().size() > 0) + attachments.add(status.getMedia_attachments().get(0)); intent.putParcelableArrayListExtra("mediaArray", attachments); b.putInt("position", 0); intent.putExtras(b); context.startActivity(intent); } }); - holder.art_author.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(context, ShowConversationActivity.class); - Bundle b = new Bundle(); - b.putParcelable("status", status); - intent.putExtras(b); - if (type == RetrieveFeedsAsyncTask.Type.CONTEXT) - ((Activity) context).finish(); - context.startActivity(intent); - } - }); + if( type == RetrieveFeedsAsyncTask.Type.PIXELFED){ + holder.art_author.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CrossActions.doCrossConversation(context,status); + } + }); + }else { + holder.art_author.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(context, ShowConversationActivity.class); + Bundle b = new Bundle(); + b.putParcelable("status", status); + intent.putExtras(b); + if (type == RetrieveFeedsAsyncTask.Type.CONTEXT) + ((Activity) context).finish(); + context.startActivity(intent); + } + }); + } + if( status.getDisplayNameSpan() != null && status.getDisplayNameSpan().toString().trim().length() > 0) holder.art_username.setText( status.getDisplayNameSpan(), TextView.BufferType.SPANNABLE); else @@ -2237,7 +2314,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct ImageView imageView; if( i == 0) { imageView = fullAttachement?holder.status_prev1_h:holder.status_prev1; - if( attachment.getType().equals("image") || attachment.getType().equals("unknown")) + if( attachment.getType().toLowerCase().equals("image") || attachment.getType().equals("unknown")) if( fullAttachement) holder.status_prev1_play_h.setVisibility(View.GONE); else @@ -2249,7 +2326,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct holder.status_prev1_play.setVisibility(View.VISIBLE); }else if( i == 1) { imageView = fullAttachement?holder.status_prev2_h:holder.status_prev2; - if( attachment.getType().equals("image") || attachment.getType().equals("unknown")) + if( attachment.getType().toLowerCase().equals("image") || attachment.getType().equals("unknown")) if( fullAttachement) holder.status_prev2_play_h.setVisibility(View.GONE); else @@ -2261,7 +2338,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct holder.status_prev2_play.setVisibility(View.VISIBLE); }else if(i == 2) { imageView = fullAttachement?holder.status_prev3_h:holder.status_prev3; - if( attachment.getType().equals("image") || attachment.getType().equals("unknown")) + if( attachment.getType().toLowerCase().equals("image") || attachment.getType().equals("unknown")) if( fullAttachement) holder.status_prev3_play_h.setVisibility(View.GONE); else @@ -2273,7 +2350,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct holder.status_prev3_play.setVisibility(View.VISIBLE); }else { imageView = fullAttachement?holder.status_prev4_h:holder.status_prev4; - if( attachment.getType().equals("image") || attachment.getType().equals("unknown")) + if( attachment.getType().toLowerCase().equals("image") || attachment.getType().equals("unknown")) if( fullAttachement) holder.status_prev4_play_h.setVisibility(View.GONE); else diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java index 13ed2a757..af08c0600 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java @@ -179,8 +179,10 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn statusListAdapter = new StatusListAdapter(context, tagTimeline, targetedId, isOnWifi, this.statuses); lv_status.setAdapter(statusListAdapter); } - }else if( search_peertube == null && (instanceType == null || instanceType.equals("MASTODON"))) { + }else if( search_peertube == null && (instanceType == null || instanceType.equals("MASTODON") || instanceType.equals("PIXELFED"))) { BaseMainActivity.displayPeertube = null; + if( instanceType != null && instanceType.equals("PIXELFED")) + type = RetrieveFeedsAsyncTask.Type.PIXELFED; statusListAdapter = new StatusListAdapter(context, type, targetedId, isOnWifi, this.statuses); lv_status.setAdapter(statusListAdapter); }else { @@ -217,7 +219,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn asyncTask = new RetrieveFeedsAsyncTask(context, type, targetedId, max_id, showMediaOnly, showPinned, showReply, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else if( type == RetrieveFeedsAsyncTask.Type.TAG) asyncTask = new RetrieveFeedsAsyncTask(context, type, tag, targetedId, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - else if( type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE ) { + else if( type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE || type == RetrieveFeedsAsyncTask.Type.PIXELFED) { if( search_peertube == null) { if( remote_channel_name == null) asyncTask = new RetrieveFeedsAsyncTask(context, type, remoteInstance, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -249,7 +251,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn }); - if( instanceType == null || instanceType.equals("MASTODON")) + if( instanceType == null || instanceType.equals("MASTODON") || instanceType.equals("PIXELFED")) swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { @@ -305,12 +307,13 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn asyncTask = new RetrieveFeedsAsyncTask(context, type, targetedId, max_id, showMediaOnly, showPinned, showReply,DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else if (type == RetrieveFeedsAsyncTask.Type.TAG) asyncTask = new RetrieveFeedsAsyncTask(context, type, tag, targetedId, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - else if( type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE ) { + else if( type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE || type == RetrieveFeedsAsyncTask.Type.PIXELFED) { if( search_peertube == null) { - if( remote_channel_name == null) + if( remote_channel_name == null) { asyncTask = new RetrieveFeedsAsyncTask(context, type, remoteInstance, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else - asyncTask = new RetrieveFeedsAsyncTask(context, remoteInstance, remote_channel_name, null,DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + asyncTask = new RetrieveFeedsAsyncTask(context, remoteInstance, remote_channel_name, null, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else asyncTask = new RetrievePeertubeSearchAsyncTask(context, remoteInstance, search_peertube, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -332,7 +335,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn asyncTask = new RetrieveFeedsAsyncTask(context, type, targetedId, max_id, showMediaOnly, showPinned, showReply,DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else if (type == RetrieveFeedsAsyncTask.Type.TAG) asyncTask = new RetrieveFeedsAsyncTask(context, type, tag, targetedId, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - else if( type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE ) { + else if( type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE || type == RetrieveFeedsAsyncTask.Type.PIXELFED ) { if( search_peertube == null) { if( remote_channel_name == null) asyncTask = new RetrieveFeedsAsyncTask(context, type, remoteInstance, max_id, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -413,7 +416,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn return; } //For remote Peertube remote instances - if( type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE && peertubeAdapater != null){ + if(( type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE ) && peertubeAdapater != null){ int previousPosition = this.peertubes.size(); if( max_id == null) max_id = "0"; @@ -455,7 +458,16 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn int previousPosition = this.statuses.size(); List statuses = apiResponse.getStatuses(); //At this point all statuses are in "List statuses" - max_id = apiResponse.getMax_id(); + + //Pagination for Pixelfed + if(type == RetrieveFeedsAsyncTask.Type.PIXELFED) { + if( max_id == null) + max_id = "1"; + //max_id needs to work like an offset + max_id = String.valueOf(Integer.valueOf(max_id) + 1); + }else{ + max_id = apiResponse.getMax_id(); + } //while max_id is different from null, there are some more toots to load when scrolling flag_loading = (max_id == null ); //If it's the first load and the reply doesn't contain any toots, a message is displayed. @@ -520,7 +532,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn //Update the id of the last toot retrieved MainActivity.lastHomeId = status.getId(); statuses.add(0, status); - if (!status.getAccount().getId().equals(userId)) { + if (status.getAccount() != null && !status.getAccount().getId().equals(userId)) { MainActivity.countNewStatus++; } try { @@ -625,7 +637,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn if( type == RetrieveFeedsAsyncTask.Type.HOME) asyncTask = new RetrieveFeedsAfterBookmarkAsyncTask(context, null, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - if (type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE ) + if (type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE || type == RetrieveFeedsAsyncTask.Type.PIXELFED) asyncTask = new RetrieveMissingFeedsAsyncTask(context, remoteInstance, sinceId, type, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else if(type == RetrieveFeedsAsyncTask.Type.TAG) asyncTask = new RetrieveMissingFeedsAsyncTask(context, tag, sinceId, type, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/CrossActions.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/CrossActions.java index d8fd26d58..4649e1a09 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/helper/CrossActions.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/CrossActions.java @@ -266,11 +266,13 @@ public class CrossActions { @Override protected Void doInBackground(Void... voids) { API api = new API(contextReference.get(), account.getInstance(), account.getToken()); - String url; - if( remoteAccount.getHost() != null && remoteAccount.getAcct().split("@").length > 1) //Peertube compatibility - url = "https://" + remoteAccount.getHost() + "/accounts/" + remoteAccount.getAcct().split("@")[0]; - else - url = "https://" + remoteAccount.getInstance() + "/@" + remoteAccount.getAcct(); + String url = remoteAccount.getUrl(); + if( url == null) { + if (remoteAccount.getHost() != null && remoteAccount.getAcct().split("@").length > 1) //Peertube compatibility + url = "https://" + remoteAccount.getHost() + "/accounts/" + remoteAccount.getAcct().split("@")[0]; + else + url = "https://" + remoteAccount.getInstance() + "/@" + remoteAccount.getAcct(); + } response = api.search(url); return null; } 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 701c03d6e..4735c2a28 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 @@ -541,7 +541,15 @@ public class Helper { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(STRING_DATE_FORMAT, userLocale); simpleDateFormat.setTimeZone(TimeZone.getTimeZone("gmt")); simpleDateFormat.setLenient(true); - return simpleDateFormat.parse(date); + try { + return simpleDateFormat.parse(date); + }catch (Exception e){ + String newdate = date.split("\\+")[0]; + simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", userLocale); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone("gmt")); + simpleDateFormat.setLenient(true); + return simpleDateFormat.parse(newdate); + } } @@ -2564,7 +2572,7 @@ public class Helper { return; } } - if( url == null || url.contains("missing.png")) { + if( url == null || url.contains("missing.png") || url.contains(".svg")) { try { Glide.with(imageView.getContext()) .load(R.drawable.missing) diff --git a/app/src/main/res/drawable-hdpi/pixelfed.png b/app/src/main/res/drawable-hdpi/pixelfed.png new file mode 100644 index 0000000000000000000000000000000000000000..62324da98c007622cd527a4c9ddaa1926cbf3fc5 GIT binary patch literal 2045 zcmV`6f``?Yj(V-b zi^WlF|MD7XtVDJ$(-GpptG8bF`KVo@euSHVQ9(RZ^WTNWD-PPl>!E)u2Kp6I z81xUvBS{eSpSZF($_M`ZJ@62nE@K{sKN3P*yNcy^Mh@{x#i>?4c5`1tEwiPuTH7ss zqYjA}b*9s}(rFfKfOb(VbW7JkzdQ^ge1xPFu zGfrKR48LnlEBEW*ke6GSd~9QwlYB;RzuBPTZ={jMPerEnp@{D~XqQDn6G$sY3Qb}n zo+QPiXL~fpvwbo7nH!i)3rOpz(-f#qy|6j=iLnUCY5$;C3UhnuMaV>TC>K|wCb$$0 zfw$4P@(LQ0^JavMtO+f8CA>PfgVVne_5<-0ikpIX3JSG{Gs5Pu0is(FSKGBX)tDDp zhufizD3#QrT2zkuphDF9UqeIk^=Z%;!$8lNpf?$yG3imGZby9g0oXoH0Ov`<51_Rc z$S7=ze?YX0;!n$$9W`7HkwX^x0L7BKs1#M=Zcq{K`d>$Va{d&=Qsmjh1WtU@kBrCd zIM9)cKlGeJKvya_kGH^fFbSN&#FtQS9Jt*vQxgdk;p6tzXD$%6Us7a;{}-yf@J09x>eIcfq5P?sXZ zy=N+{m3Pv3`at@>15v)f>`obL*S?A6bZwwWGVH!h!rZ3`a2Sw+tK0y`&RFmoK45K1 zTb_`7vlB4~1X$OK&mGN==+RvdZ^y0BCKQKQ;;TS);4R3KWC$o~hjp_Oq;Hg#9;AB= zq)i8_=6c3fzMtjDe*p*jka9a?C=dy5<961eDh<~8&12+}F`HzWZKmFLpDjNtp-9X1 z@J{At*u$y#Dnxg1hpyAbxI%Dm_k#?mL3(r`3W~JQY8(fto5UMcBd{uOWam`pU`}N= zY|Bovv-2J>Z=6%H<7HLT0|5s)g{yqs1c zt(z3dqsV27oTqh~u}r~|zd=XRC?fRr`QP6Q^t50r?Zkr9fkiuuLmxI(hcswwMU`xY zqy)d+A!mg-Dp(b~n&K*Leu*|eOY0P!;!BLtNtERGioa6CW5zEa=T~169=6_`v;H@N zDnjZH)`@D`6q0)*b)n^BnTZXPqJ4uVUarA3=aO;K`W$1Jb%xQ9Q+PshkVP^SYiV5E zpZtAS8BsaADWHk_Fr+G|CAjcdXOOJ0Bj9Rlad<)N&P^?45jzLIa!(uDM6&5~a?Sj+ bnR@*PiVU-?9qXqP00000NkvXXu0mjf>apxS literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-ldpi/pixelfed.png b/app/src/main/res/drawable-ldpi/pixelfed.png new file mode 100644 index 0000000000000000000000000000000000000000..7df1a00595d375a111a52643f26697b82c681b76 GIT binary patch literal 704 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/pixelfed.png b/app/src/main/res/drawable-xxhdpi/pixelfed.png new file mode 100644 index 0000000000000000000000000000000000000000..a2cf0f68fd95ca8659aef8abaf5b482145748984 GIT binary patch literal 5886 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 UFcY;D4*&oF07*qoM6N<$f?;lAM*si- literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/pixelfed.png b/app/src/main/res/drawable-xxxhdpi/pixelfed.png new file mode 100644 index 0000000000000000000000000000000000000000..49703d27a4d4bfea5b348f1384c623426f9e8c30 GIT binary patch literal 8674 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 Aj{pDw literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/drawer_art.xml b/app/src/main/res/layout/drawer_art.xml index 2bb7df40e..8a3227c13 100644 --- a/app/src/main/res/layout/drawer_art.xml +++ b/app/src/main/res/layout/drawer_art.xml @@ -3,12 +3,35 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> - + android:layout_height="wrap_content"> + + + + + + - + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/remote_instances.xml b/app/src/main/res/menu/remote_instances.xml index bb29c908a..07ad2ed39 100644 --- a/app/src/main/res/menu/remote_instances.xml +++ b/app/src/main/res/menu/remote_instances.xml @@ -27,6 +27,16 @@ + + + + + Translation of the application About Crowdin Bot + Pixelfed instance + Mastodon instance + No Pixelfed instances \ No newline at end of file