Skip to content

Commit

Permalink
Fixed a mix of animated and non-animated images in Reddit galleries #4
Browse files Browse the repository at this point in the history
  • Loading branch information
edgan committed Dec 22, 2024
1 parent b8a99ec commit 80cbe87
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 42 deletions.
118 changes: 113 additions & 5 deletions app/src/main/java/me/ccrama/redditslide/Activities/GalleryImage.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package me.ccrama.redditslide.Activities;


import com.fasterxml.jackson.databind.JsonNode;

import org.apache.commons.text.StringEscapeUtils;

import java.io.Serializable;
import java.util.Arrays;

/**
* Created by ccrama on 09/22/2020.
Expand All @@ -15,13 +13,123 @@ public class GalleryImage implements Serializable {
public int width;
public int height;

public String mediaId;
public MediaMetadata metadata;

public GalleryImage(JsonNode data) {
if(data.has("u")) {
url = StringEscapeUtils.unescapeHtml4(data.get("u").asText());
} else if(data.has("gif")) {
url = StringEscapeUtils.unescapeHtml4(data.get("gif").asText());
} else if(data.has("mp4")) {
url = StringEscapeUtils.unescapeHtml4(data.get("mp4").asText());
}
width = data.get("x").asInt();
height = data.get("y").asInt();

// Add metadata population
metadata = new MediaMetadata();
if(data.has("e")) {
metadata.e = data.get("e").asText();
}
if(data.has("m")) {
metadata.m = data.get("m").asText();
}
if(data.has("s")) {
JsonNode s = data.get("s");
metadata.source = new MediaMetadata.Source();
if(s.has("mp4")) {
metadata.source.mp4 = StringEscapeUtils.unescapeHtml4(s.get("mp4").asText());
}
if(s.has("gif")) {
metadata.source.gif = StringEscapeUtils.unescapeHtml4(s.get("gif").asText());
}
if(s.has("y")) {
metadata.source.y = s.get("y").asInt();
}
if(s.has("x")) {
metadata.source.x = s.get("x").asInt();
}
}

// Set animated based on type
metadata.animated = "AnimatedImage".equals(metadata.e);
}

public boolean isAnimated() {
if (metadata != null) {
// Check metadata first
if (metadata.animated) {
return true;
}
if ("AnimatedImage".equals(metadata.e)) {
return true;
}
if (metadata.m != null && metadata.m.contains("gif")) {
return true;
}
}

// Fallback to URL check if metadata is missing
return url != null && (url.endsWith(".gif") || url.endsWith(".gifv") || url.endsWith(".mp4"));
}

public String getImageUrl() {
// For animated content, use the direct MP4 URL from metadata
if (isAnimated() && metadata != null && metadata.source != null) {
if (metadata.source.mp4 != null && !metadata.source.mp4.isEmpty()) {
// Return the complete MP4 URL directly
return metadata.source.mp4;
}
}
// For non-animated content or if no MP4 URL exists
if (metadata != null && metadata.source != null && metadata.source.u != null) {
// Use the direct URL from source if available
return metadata.source.u;
}
// Fall back to original URL if nothing else works
return url;
}

public static class MediaMetadata implements Serializable {
private static final long serialVersionUID = 1L;

public String e; // type (e.g., "Image", "AnimatedImage")
public String m; // mimetype (e.g., "image/gif", "image/jpg")
public String s; // status
public long id; // media id
public boolean animated; // whether media is animated
public String ext; // file extension with dot (e.g., ".gif")

public Preview[] p; // array of preview images
public Source source; // source object containing URLs

@Override
public String toString() {
return "MediaMetadata{" +
"e='" + e + '\'' +
", m='" + m + '\'' +
", s='" + s + '\'' +
", id=" + id +
", animated=" + animated +
", ext='" + ext + '\'' +
", p=" + (p != null ? Arrays.toString(p) : "null") +
", source=" + source +
'}';
}

public static class Preview implements Serializable {
private static final long serialVersionUID = 1L;
public int y; // height
public int x; // width
public String u; // preview URL
}

public static class Source implements Serializable {
private static final long serialVersionUID = 1L;
public int y; // height
public int x; // width
public String u; // direct URL for non-animated
public String gif; // gif URL for animated
public String mp4; // mp4 URL for animated
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
import android.widget.ProgressBar;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
Expand Down Expand Up @@ -48,6 +49,9 @@
import me.ccrama.redditslide.util.LinkUtil;
import me.ccrama.redditslide.util.NetworkUtil;
import me.ccrama.redditslide.util.ShareUtil;
import me.ccrama.redditslide.Views.ExoVideoView;
import me.ccrama.redditslide.util.GifUtils;
import me.ccrama.redditslide.util.LogUtil;

import static me.ccrama.redditslide.Notifications.ImageDownloadNotificationService.EXTRA_SUBMISSION_TITLE;

Expand Down Expand Up @@ -251,12 +255,21 @@ public Fragment getItem(int i) {
}
i--;

Fragment f = new ImageFullNoSubmission();
Bundle args = new Bundle();
args.putInt("page", i);
f.setArguments(args);
GalleryImage current = images.get(i);

return f;
if (current.isAnimated()) {
Fragment f = new Gif();
Bundle args = new Bundle();
args.putInt("page", i);
f.setArguments(args);
return f;
} else {
Fragment f = new ImageFullNoSubmission();
Bundle args = new Bundle();
args.putInt("page", i);
f.setArguments(args);
return f;
}
}

@Override
Expand All @@ -268,6 +281,81 @@ public int getCount() {
}
}

public static class Gif extends Fragment {
private int i = 0;
private View gif;
ViewGroup rootView;
ProgressBar loader;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (this.isVisible()) {
if (!isVisibleToUser) {
((ExoVideoView) gif).pause();
gif.setVisibility(View.GONE);
}
if (isVisibleToUser) {
((ExoVideoView) gif).play();
gif.setVisibility(View.VISIBLE);
}
}
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = (ViewGroup) inflater.inflate(R.layout.submission_gifcard_album, container, false);
loader = rootView.findViewById(R.id.gifprogress);
gif = rootView.findViewById(R.id.gif);

gif.setVisibility(View.VISIBLE);
final ExoVideoView v = (ExoVideoView) gif;
v.clearFocus();

GalleryImage current = ((RedditGalleryPager) getActivity()).images.get(i);
final String url = current.getImageUrl(); // Now uses metadata-aware URL getter

LogUtil.i(url);

new GifUtils.AsyncLoadGif(getActivity(),
rootView.findViewById(R.id.gif),
loader,
null,
null,
false,
true,
rootView.findViewById(R.id.size),
((RedditGalleryPager)getActivity()).subreddit,
getActivity().getIntent().getStringExtra(EXTRA_SUBMISSION_TITLE)
).execute(url);

rootView.findViewById(R.id.more).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
((RedditGalleryPager) getActivity()).showBottomSheetImage(url, true, i);
}
});
rootView.findViewById(R.id.save).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaView.doOnClick.run();
}
});
if (!SettingValues.imageDownloadButton) {
rootView.findViewById(R.id.save).setVisibility(View.INVISIBLE);
}
return rootView;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = this.getArguments();
i = bundle.getInt("page", 0);
}
}

public void showBottomSheetImage(final String contentUrl, final boolean isGif,
final int index) {

Expand Down
53 changes: 29 additions & 24 deletions app/src/main/java/me/ccrama/redditslide/util/GifUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ protected void onPreExecute() {
Gson gson;

public enum VideoType {
IMGUR, STREAMABLE, GFYCAT, DIRECT, OTHER, VREDDIT;
IMGUR, STREAMABLE, GFYCAT, DIRECT, OTHER, VREDDIT, REDDIT_GALLERY;

public boolean shouldLoadPreview() {
return this == OTHER;
Expand Down Expand Up @@ -378,6 +378,9 @@ public static String formatUrl(String s) {
*/
public static VideoType getVideoType(String url) {
String realURL = url.toLowerCase(Locale.ENGLISH);
if (realURL.contains("i.redd.it")) {
return VideoType.REDDIT_GALLERY;
}
if (realURL.contains("v.redd.it")) {
return VideoType.VREDDIT;
}
Expand All @@ -392,36 +395,36 @@ public static VideoType getVideoType(String url) {
return VideoType.OTHER;
}

public static Map<String, String> makeHeaderMap(String domain){
Map<String, String> map = new HashMap<>();
map.put("Host", domain);
map.put("Sec-Fetch-Dest", "empty");
map.put("Sec-Fetch-Mode", "cors");
map.put("Sec-Fetch-Site", "same-origin");
map.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; rv:107.0) Gecko/20100101 Firefox/107.0");
return map;
}

/**
* Get an API response for a given host and gfy name
*
* @param host the host to send the req to
* @param name the name of the gfy
* @return the result
*/
public static Map<String, String> makeHeaderMap(String domain){
Map<String, String> map = new HashMap<>();
map.put("Host", domain);
map.put("Sec-Fetch-Dest", "empty");
map.put("Sec-Fetch-Mode", "cors");
map.put("Sec-Fetch-Site", "same-origin");
map.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; rv:107.0) Gecko/20100101 Firefox/107.0");
return map;
}

/**
* Get an API response for a given host and gfy name
*
* @param host the host to send the req to
* @param name the name of the gfy
* @return the result
*/
JsonObject getApiResponse(String host, String name){
String domain = "api." + host + ".com";
String gfycatUrl = "https://" + domain + "/v1/gfycats" + name;

return HttpUtil.getJsonObject(client, gson, gfycatUrl, makeHeaderMap(domain));
}

/**
* Get the correct mp4/mobile url from a given result JsonObject
*
* @param result the result to check
* @return the video url
*/
/**
* Get the correct mp4/mobile url from a given result JsonObject
*
* @param result the result to check
* @return the video url
*/
String getUrlFromApi(JsonObject result){
if (!SettingValues.hqgif && result.getAsJsonObject("gfyItem").has("mobileUrl")) {
return result.getAsJsonObject("gfyItem").get("mobileUrl").getAsString();
Expand Down Expand Up @@ -611,6 +614,8 @@ protected Uri doInBackground(String... sub) {
+ "]");
}
break;
case REDDIT_GALLERY:
return Uri.parse(url);
case DIRECT:
case IMGUR:
try {
Expand Down
Loading

0 comments on commit 80cbe87

Please sign in to comment.