diff --git a/app/src/main/java/app/fedilab/android/activities/MediaActivity.java b/app/src/main/java/app/fedilab/android/activities/MediaActivity.java index 1c1c02aff..415024cab 100644 --- a/app/src/main/java/app/fedilab/android/activities/MediaActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/MediaActivity.java @@ -14,6 +14,8 @@ package app.fedilab.android.activities; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ +import static app.fedilab.android.ui.fragment.media.FragmentMediaProfile.mediaAttachmentProfile; + import android.Manifest; import android.app.DownloadManager; import android.content.BroadcastReceiver; @@ -26,6 +28,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; @@ -95,6 +98,7 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload private ActivityMediaPagerBinding binding; private FragmentMedia mCurrentFragment; private Status status; + private boolean mediaFromProfile; @Override protected void onCreate(Bundle savedInstanceState) { @@ -105,14 +109,21 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload binding = ActivityMediaPagerBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); + fullscreen = false; flags = getWindow().getDecorView().getSystemUiVisibility(); Bundle b = getIntent().getExtras(); if (b != null) { mediaPosition = b.getInt(Helper.ARG_MEDIA_POSITION, 1); attachments = (ArrayList) b.getSerializable(Helper.ARG_MEDIA_ARRAY); + mediaFromProfile = b.getBoolean(Helper.ARG_MEDIA_ARRAY_PROFILE, false); status = (Status) b.getSerializable(Helper.ARG_STATUS); } + Log.v(Helper.TAG, "mediaPosition: " + mediaPosition); + if (mediaFromProfile && mediaAttachmentProfile != null) { + attachments = new ArrayList<>(); + attachments.addAll(mediaAttachmentProfile); + } if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true); @@ -130,10 +141,10 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); String description = attachments.get(mediaPosition - 1).description; handler = new Handler(); - if (status != null) { + if (attachments.get(mediaPosition - 1).status != null) { binding.originalMessage.setOnClickListener(v -> { Intent intentContext = new Intent(MediaActivity.this, ContextActivity.class); - intentContext.putExtra(Helper.ARG_STATUS, status); + intentContext.putExtra(Helper.ARG_STATUS, attachments.get(mediaPosition - 1).status); intentContext.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intentContext); }); @@ -171,6 +182,7 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload } public void onPageSelected(int position) { + mediaPosition = position; String description = attachments.get(position).description; if (handler != null) { handler.removeCallbacksAndMessages(null); @@ -386,7 +398,7 @@ public class MediaActivity extends BaseTransparentActivity implements OnDownload showSystemUI(); binding.mediaDescription.setVisibility(View.VISIBLE); binding.translate.setVisibility(View.VISIBLE); - if (status != null) { + if (mediaFromProfile) { binding.originalMessage.setVisibility(View.VISIBLE); } } else { diff --git a/app/src/main/java/app/fedilab/android/client/entities/api/Attachment.java b/app/src/main/java/app/fedilab/android/client/entities/api/Attachment.java index 0ccbacc27..7447f9330 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/api/Attachment.java +++ b/app/src/main/java/app/fedilab/android/client/entities/api/Attachment.java @@ -14,6 +14,8 @@ package app.fedilab.android.client.entities.api; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ +import androidx.annotation.Nullable; + import com.google.gson.annotations.SerializedName; import java.io.Serializable; @@ -52,7 +54,7 @@ public class Attachment implements Serializable { public String peertubeId = null; public String focus = null; public String translation = null; - + public transient Status status = null; public static class Meta implements Serializable { @SerializedName("focus") @@ -80,4 +82,15 @@ public class Attachment implements Serializable { @SerializedName("aspect") public float aspect; } + + + @Override + public boolean equals(@Nullable Object obj) { + boolean same = false; + if (obj instanceof Attachment) { + same = this.id.equals(((Attachment) obj).id); + } + return same; + } + } diff --git a/app/src/main/java/app/fedilab/android/helper/Helper.java b/app/src/main/java/app/fedilab/android/helper/Helper.java index 8ee91e3a8..37b127885 100644 --- a/app/src/main/java/app/fedilab/android/helper/Helper.java +++ b/app/src/main/java/app/fedilab/android/helper/Helper.java @@ -272,6 +272,7 @@ public class Helper { public static final String ARG_CHECK_REMOTELY = "ARG_CHECK_REMOTELY"; public static final String ARG_USER_ID = "ARG_USER_ID"; public static final String ARG_MEDIA_ARRAY = "ARG_MEDIA_ARRAY"; + public static final String ARG_MEDIA_ARRAY_PROFILE = "ARG_MEDIA_ARRAY_PROFILE"; public static final String ARG_VISIBILITY = "ARG_VISIBILITY"; public static final String ARG_SCHEDULED_DATE = "ARG_SCHEDULED_DATE"; diff --git a/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java b/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java index e030eeae9..44686006f 100644 --- a/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java @@ -56,6 +56,7 @@ import com.bumptech.glide.Glide; import java.io.IOException; import java.lang.ref.WeakReference; +import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; @@ -370,64 +371,126 @@ public class SpannableHelper { new Thread(() -> { try { String redirect = null; - HttpsURLConnection httpsURLConnection = (HttpsURLConnection) finalUrlCheck.openConnection(); - httpsURLConnection.setConnectTimeout(10 * 1000); - httpsURLConnection.setRequestProperty("http.keepAlive", "false"); - //httpsURLConnection.setRequestProperty("User-Agent", USER_AGENT); - httpsURLConnection.setRequestMethod("HEAD"); - httpsURLConnection.setInstanceFollowRedirects(false); - if (httpsURLConnection.getResponseCode() == 301 || httpsURLConnection.getResponseCode() == 302) { - Map> map = httpsURLConnection.getHeaderFields(); - for (Map.Entry> entry : map.entrySet()) { - if (entry.toString().toLowerCase().startsWith("location")) { - Matcher matcher = Patterns.WEB_URL.matcher(entry.toString()); - if (matcher.find()) { - redirect = matcher.group(1); + if (finalUrl.startsWith("http://")) { + HttpURLConnection httpURLConnection = (HttpURLConnection) finalUrlCheck.openConnection(); + httpURLConnection.setConnectTimeout(10 * 1000); + httpURLConnection.setRequestProperty("http.keepAlive", "false"); + //httpsURLConnection.setRequestProperty("User-Agent", USER_AGENT); + httpURLConnection.setRequestMethod("HEAD"); + httpURLConnection.setInstanceFollowRedirects(false); + if (httpURLConnection.getResponseCode() == 301 || httpURLConnection.getResponseCode() == 302) { + Map> map = httpURLConnection.getHeaderFields(); + for (Map.Entry> entry : map.entrySet()) { + if (entry.toString().toLowerCase().startsWith("location")) { + Matcher matcher = Patterns.WEB_URL.matcher(entry.toString()); + if (matcher.find()) { + redirect = matcher.group(1); + } } } } - } - httpsURLConnection.getInputStream().close(); - if (redirect != null && redirect.compareTo(finalUrl) != 0) { - URL redirectURL = new URL(redirect); - String host = redirectURL.getHost(); - String protocol = redirectURL.getProtocol(); - if (protocol == null || host == null) { - redirect = null; + httpURLConnection.getInputStream().close(); + if (redirect != null && redirect.compareTo(finalUrl) != 0) { + URL redirectURL = new URL(redirect); + String host = redirectURL.getHost(); + String protocol = redirectURL.getProtocol(); + if (protocol == null || host == null) { + redirect = null; + } } - } - Handler mainHandler = new Handler(context.getMainLooper()); - String finalRedirect = redirect; - Runnable myRunnable = () -> { - AlertDialog.Builder builder1 = new AlertDialog.Builder(view.getContext()); - if (finalRedirect != null) { - builder1.setMessage(context.getString(R.string.redirect_detected, finalUrl, finalRedirect)); - builder1.setNegativeButton(R.string.copy_link, (dialog, which) -> { - ClipboardManager clipboard1 = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip1 = ClipData.newPlainText(Helper.CLIP_BOARD, finalRedirect); - if (clipboard1 != null) { - clipboard1.setPrimaryClip(clip1); - Toasty.info(context, context.getString(R.string.clipboard_url), Toast.LENGTH_LONG).show(); - } - dialog.dismiss(); - }); - builder1.setNeutralButton(R.string.share_link, (dialog, which) -> { - Intent sendIntent1 = new Intent(Intent.ACTION_SEND); - sendIntent1.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via)); - sendIntent1.putExtra(Intent.EXTRA_TEXT, finalUrl); - sendIntent1.setType("text/plain"); - context.startActivity(Intent.createChooser(sendIntent1, context.getString(R.string.share_with))); - dialog.dismiss(); - }); - } else { - builder1.setMessage(R.string.no_redirect); - } - builder1.setTitle(context.getString(R.string.check_redirect)); - builder1.setPositiveButton(R.string.close, (dialog, which) -> dialog.dismiss()) - .show(); + Handler mainHandler = new Handler(context.getMainLooper()); + String finalRedirect = redirect; + Runnable myRunnable = () -> { + AlertDialog.Builder builder1 = new AlertDialog.Builder(view.getContext()); + if (finalRedirect != null) { + builder1.setMessage(context.getString(R.string.redirect_detected, finalUrl, finalRedirect)); + builder1.setNegativeButton(R.string.copy_link, (dialog, which) -> { + ClipboardManager clipboard1 = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip1 = ClipData.newPlainText(Helper.CLIP_BOARD, finalRedirect); + if (clipboard1 != null) { + clipboard1.setPrimaryClip(clip1); + Toasty.info(context, context.getString(R.string.clipboard_url), Toast.LENGTH_LONG).show(); + } + dialog.dismiss(); + }); + builder1.setNeutralButton(R.string.share_link, (dialog, which) -> { + Intent sendIntent1 = new Intent(Intent.ACTION_SEND); + sendIntent1.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via)); + sendIntent1.putExtra(Intent.EXTRA_TEXT, finalUrl); + sendIntent1.setType("text/plain"); + context.startActivity(Intent.createChooser(sendIntent1, context.getString(R.string.share_with))); + dialog.dismiss(); + }); + } else { + builder1.setMessage(R.string.no_redirect); + } + builder1.setTitle(context.getString(R.string.check_redirect)); + builder1.setPositiveButton(R.string.close, (dialog, which) -> dialog.dismiss()) + .show(); + + }; + mainHandler.post(myRunnable); + } else { + HttpsURLConnection httpsURLConnection = (HttpsURLConnection) finalUrlCheck.openConnection(); + httpsURLConnection.setConnectTimeout(10 * 1000); + httpsURLConnection.setRequestProperty("http.keepAlive", "false"); + //httpsURLConnection.setRequestProperty("User-Agent", USER_AGENT); + httpsURLConnection.setRequestMethod("HEAD"); + httpsURLConnection.setInstanceFollowRedirects(false); + if (httpsURLConnection.getResponseCode() == 301 || httpsURLConnection.getResponseCode() == 302) { + Map> map = httpsURLConnection.getHeaderFields(); + for (Map.Entry> entry : map.entrySet()) { + if (entry.toString().toLowerCase().startsWith("location")) { + Matcher matcher = Patterns.WEB_URL.matcher(entry.toString()); + if (matcher.find()) { + redirect = matcher.group(1); + } + } + } + } + httpsURLConnection.getInputStream().close(); + if (redirect != null && redirect.compareTo(finalUrl) != 0) { + URL redirectURL = new URL(redirect); + String host = redirectURL.getHost(); + String protocol = redirectURL.getProtocol(); + if (protocol == null || host == null) { + redirect = null; + } + } + Handler mainHandler = new Handler(context.getMainLooper()); + String finalRedirect = redirect; + Runnable myRunnable = () -> { + AlertDialog.Builder builder1 = new AlertDialog.Builder(view.getContext()); + if (finalRedirect != null) { + builder1.setMessage(context.getString(R.string.redirect_detected, finalUrl, finalRedirect)); + builder1.setNegativeButton(R.string.copy_link, (dialog, which) -> { + ClipboardManager clipboard1 = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip1 = ClipData.newPlainText(Helper.CLIP_BOARD, finalRedirect); + if (clipboard1 != null) { + clipboard1.setPrimaryClip(clip1); + Toasty.info(context, context.getString(R.string.clipboard_url), Toast.LENGTH_LONG).show(); + } + dialog.dismiss(); + }); + builder1.setNeutralButton(R.string.share_link, (dialog, which) -> { + Intent sendIntent1 = new Intent(Intent.ACTION_SEND); + sendIntent1.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via)); + sendIntent1.putExtra(Intent.EXTRA_TEXT, finalUrl); + sendIntent1.setType("text/plain"); + context.startActivity(Intent.createChooser(sendIntent1, context.getString(R.string.share_with))); + dialog.dismiss(); + }); + } else { + builder1.setMessage(R.string.no_redirect); + } + builder1.setTitle(context.getString(R.string.check_redirect)); + builder1.setPositiveButton(R.string.close, (dialog, which) -> dialog.dismiss()) + .show(); + + }; + mainHandler.post(myRunnable); + } - }; - mainHandler.post(myRunnable); } catch (IOException e) { e.printStackTrace(); } diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/ImageAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/ImageAdapter.java index 41d482188..29da98430 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/ImageAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/ImageAdapter.java @@ -14,6 +14,8 @@ package app.fedilab.android.ui.drawer; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ +import static app.fedilab.android.ui.fragment.media.FragmentMediaProfile.mediaAttachmentProfile; + import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -27,31 +29,26 @@ import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; -import java.util.ArrayList; -import java.util.List; - import app.fedilab.android.activities.ContextActivity; import app.fedilab.android.activities.MediaActivity; import app.fedilab.android.client.entities.api.Attachment; -import app.fedilab.android.client.entities.api.Status; import app.fedilab.android.databinding.DrawerMediaBinding; import app.fedilab.android.helper.Helper; public class ImageAdapter extends RecyclerView.Adapter { - private final List statuses; + private Context context; - public ImageAdapter(List statuses) { - this.statuses = statuses; + public ImageAdapter() { } public int getCount() { - return statuses.size(); + return mediaAttachmentProfile.size(); } - public Status getItem(int position) { - return statuses.get(position); + public Attachment getItem(int position) { + return mediaAttachmentProfile.get(position); } @NonNull @@ -64,35 +61,40 @@ public class ImageAdapter extends RecyclerView.Adapter @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { - Status status = statuses.get(position); + Attachment attachment = mediaAttachmentProfile.get(position); final ViewHolder holder = (ViewHolder) viewHolder; - - if (Helper.isValidContextForGlide(context) && status.art_attachment != null) { - if (status.art_attachment.preview_url != null) { - Glide.with(context).load(status.art_attachment.preview_url).into(holder.binding.media); - } else if (status.art_attachment.url != null) { - Glide.with(context).load(status.art_attachment.url).into(holder.binding.media); + if (Helper.isValidContextForGlide(context) && attachment != null) { + if (attachment.preview_url != null) { + Glide.with(context).load(attachment.preview_url).into(holder.binding.media); + } else if (attachment.url != null) { + Glide.with(context).load(attachment.url).into(holder.binding.media); } } holder.binding.media.setOnClickListener(v -> { Intent mediaIntent = new Intent(context, MediaActivity.class); Bundle b = new Bundle(); - b.putInt(Helper.ARG_MEDIA_POSITION, 1); - ArrayList attachmentsTmp = new ArrayList<>(); - attachmentsTmp.add(status.art_attachment); - b.putSerializable(Helper.ARG_STATUS, status); - b.putSerializable(Helper.ARG_MEDIA_ARRAY, new ArrayList<>(attachmentsTmp)); + b.putInt(Helper.ARG_MEDIA_POSITION, position + 1); + b.putBoolean(Helper.ARG_MEDIA_ARRAY_PROFILE, true); mediaIntent.putExtras(b); - ActivityOptionsCompat options = ActivityOptionsCompat - .makeSceneTransitionAnimation((Activity) context, holder.binding.media, status.media_attachments.get(0).url); + ActivityOptionsCompat options = null; + if (attachment != null) { + options = ActivityOptionsCompat + .makeSceneTransitionAnimation((Activity) context, holder.binding.media, attachment.url); + } else { + return; + } // start the new activity context.startActivity(mediaIntent, options.toBundle()); }); holder.binding.media.setOnLongClickListener(v -> { Intent intentContext = new Intent(context, ContextActivity.class); - intentContext.putExtra(Helper.ARG_STATUS, status); + if (attachment != null) { + intentContext.putExtra(Helper.ARG_STATUS, attachment.status); + } else { + return false; + } intentContext.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intentContext); return false; @@ -105,7 +107,7 @@ public class ImageAdapter extends RecyclerView.Adapter @Override public int getItemCount() { - return statuses.size(); + return mediaAttachmentProfile.size(); } diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java b/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java index cabcdc9d1..f12ef94a5 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java @@ -149,7 +149,7 @@ public class FragmentMedia extends Fragment { binding.mediaPicture.setVisibility(View.VISIBLE); final Handler handler = new Handler(); handler.postDelayed(() -> { - if (Helper.isValidContextForGlide(requireActivity()) && isAdded()) { + if (isAdded() && Helper.isValidContextForGlide(requireActivity())) { Glide.with(requireActivity()) .asBitmap() .dontTransform() diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMediaProfile.java b/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMediaProfile.java index 160ca0187..39193f5ed 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMediaProfile.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMediaProfile.java @@ -57,6 +57,8 @@ public class FragmentMediaProfile extends Fragment { private ImageAdapter imageAdapter; private boolean checkRemotely; private String accountId; + public static List mediaAttachmentProfile; + @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -115,7 +117,7 @@ public class FragmentMediaProfile extends Fragment { * @param statuses {@link Statuses} */ private void initializeStatusesCommonView(final Statuses statuses) { - + mediaAttachmentProfile = new ArrayList<>(); flagLoading = false; if (binding == null || !isAdded() || getActivity() == null) { return; @@ -139,7 +141,7 @@ public class FragmentMediaProfile extends Fragment { } } } - imageAdapter = new ImageAdapter(mediaStatuses); + imageAdapter = new ImageAdapter(); flagLoading = statuses.pagination.max_id == null; binding.recyclerView.setVisibility(View.VISIBLE); @@ -179,7 +181,7 @@ public class FragmentMediaProfile extends Fragment { } } }); - + fillWithMedia(); } @@ -223,5 +225,23 @@ public class FragmentMediaProfile extends Fragment { } else { flagLoading = true; } + fillWithMedia(); + } + + + public void fillWithMedia() { + + if (mediaStatuses != null && mediaStatuses.size() > 0) { + for (Status status : mediaStatuses) { + if (status.media_attachments != null && status.media_attachments.size() > 0) { + for (Attachment attachment : status.media_attachments) { + attachment.status = status; + if (!mediaAttachmentProfile.contains(attachment)) { + mediaAttachmentProfile.add(attachment); + } + } + } + } + } } } diff --git a/src/fdroid/fastlane/metadata/android/en/changelogs/467.txt b/src/fdroid/fastlane/metadata/android/en/changelogs/467.txt new file mode 100644 index 000000000..8e9e5f3bc --- /dev/null +++ b/src/fdroid/fastlane/metadata/android/en/changelogs/467.txt @@ -0,0 +1,7 @@ +Changed: +- Allow to swipe media for profiles + +Fixed: +- Fix crashes with pinch zoom +- Fix crash when checking redirection on http links +- Displaying options for media reset zoom \ No newline at end of file