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 000000000..62324da98 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/pixelfed.png differ 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 000000000..7df1a0059 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/pixelfed.png differ diff --git a/app/src/main/res/drawable-mdpi/pixelfed.png b/app/src/main/res/drawable-mdpi/pixelfed.png new file mode 100644 index 000000000..d86bbb52f Binary files /dev/null and b/app/src/main/res/drawable-mdpi/pixelfed.png differ diff --git a/app/src/main/res/drawable-xhdpi/pixelfed.png b/app/src/main/res/drawable-xhdpi/pixelfed.png new file mode 100644 index 000000000..141c477e6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/pixelfed.png differ 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 000000000..a2cf0f68f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/pixelfed.png differ 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 000000000..49703d27a Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/pixelfed.png differ 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