aboutsummaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/VideoLinkFetcher.java20
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java39
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/PostOptionsBottomSheetFragment.java41
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/post/FetchPost.java25
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/post/FetchStreamableVideo.java30
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/post/ImgurMedia.java4
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/post/ParsePost.java22
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java82
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/thing/FetchRedgifsVideoLinks.java45
-rw-r--r--app/src/main/res/layout/fragment_post_options_bottom_sheet.xml21
-rw-r--r--app/src/main/res/values/strings.xml7
11 files changed, 293 insertions, 43 deletions
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/VideoLinkFetcher.java b/app/src/main/java/ml/docilealligator/infinityforreddit/VideoLinkFetcher.java
index 19d7e04b..54d072a5 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/VideoLinkFetcher.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/VideoLinkFetcher.java
@@ -7,6 +7,7 @@ import android.os.Handler;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
+import androidx.annotation.WorkerThread;
import androidx.media3.common.util.UnstableApi;
import org.apache.commons.io.FilenameUtils;
@@ -24,6 +25,7 @@ import ml.docilealligator.infinityforreddit.post.FetchPost;
import ml.docilealligator.infinityforreddit.post.FetchStreamableVideo;
import ml.docilealligator.infinityforreddit.post.Post;
import ml.docilealligator.infinityforreddit.thing.FetchRedgifsVideoLinks;
+import ml.docilealligator.infinityforreddit.thing.StreamableVideo;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@@ -51,6 +53,22 @@ public class VideoLinkFetcher {
}
}
+ @WorkerThread
+ @Nullable
+ public static String fetchVideoLinkSync(Retrofit redgifsRetrofit, Provider<StreamableAPI> streamableApiProvider,
+ SharedPreferences currentAccountSharedPreferences, int videoType,
+ @Nullable String redgifsId, @Nullable String shortCode) {
+ if (videoType == ViewVideoActivity.VIDEO_TYPE_STREAMABLE) {
+ StreamableVideo streamableVideo = FetchStreamableVideo.fetchStreamableVideoSync(streamableApiProvider, shortCode);
+ return streamableVideo == null ? null : (streamableVideo.mp4 == null ? null : streamableVideo.mp4.url);
+ } else if (videoType == ViewVideoActivity.VIDEO_TYPE_REDGIFS) {
+ return FetchRedgifsVideoLinks.fetchRedgifsVideoLinkSync(redgifsRetrofit,
+ currentAccountSharedPreferences, redgifsId);
+ }
+
+ return null;
+ }
+
public static void loadVReddItVideo(Executor executor, Handler handler, Retrofit retrofit, Retrofit mVReddItRetrofit,
Retrofit redgifsRetrofit, Provider<StreamableAPI> streamableApiProvider,
SharedPreferences currentAccountSharedPreferences,
@@ -87,7 +105,7 @@ public class VideoLinkFetcher {
FetchStreamableVideo.fetchStreamableVideo(executor, handler, streamableApiProvider, shortCode, fetchVideoLinkListener);
} else if (post.isImgur()) {
String videoDownloadUrl = post.getVideoDownloadUrl();
- String videoFileName = "imgur-" + FilenameUtils.getName(videoDownloadUrl);
+ String videoFileName = "Imgur-" + FilenameUtils.getName(videoDownloadUrl);
fetchVideoLinkListener.onFetchImgurVideoLinkSuccess(post.getVideoUrl(), post.getVideoDownloadUrl(), videoFileName);
} else {
if (post.getVideoUrl() != null) {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java
index e878196e..afb4a70d 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java
@@ -475,25 +475,22 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe
} else {
PlayerView videoPlayerView = findViewById(R.id.player_view_view_video_activity);
videoPlayerView.setPlayer(player);
- videoPlayerView.setControllerVisibilityListener(new PlayerView.ControllerVisibilityListener() {
- @Override
- public void onVisibilityChanged(int visibility) {
- switch (visibility) {
- case View.GONE:
- getWindow().getDecorView().setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_FULLSCREEN
- | View.SYSTEM_UI_FLAG_IMMERSIVE);
- break;
- case View.VISIBLE:
- getWindow().getDecorView().setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
- }
+ videoPlayerView.setControllerVisibilityListener((PlayerView.ControllerVisibilityListener) visibility -> {
+ switch (visibility) {
+ case View.GONE:
+ getWindow().getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_IMMERSIVE);
+ break;
+ case View.VISIBLE:
+ getWindow().getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
});
}
@@ -622,7 +619,7 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe
if (videoType == VIDEO_TYPE_DIRECT) {
videoFileName = FilenameUtils.getName(videoDownloadUrl);
} else {
- videoFileName = "imgur-" + FilenameUtils.getName(videoDownloadUrl);
+ videoFileName = "Imgur-" + FilenameUtils.getName(videoDownloadUrl);
}
} else {
videoDownloadUrl = intent.getStringExtra(EXTRA_VIDEO_DOWNLOAD_URL);
@@ -665,7 +662,7 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe
binding.getProgressBar().setVisibility(View.GONE);
mVideoUri = Uri.parse(videoUrl);
ViewVideoActivity.this.videoDownloadUrl = videoDownloadUrl;
- videoFileName = "imgur-" + FilenameUtils.getName(videoDownloadUrl);
+ videoFileName = "Imgur-" + FilenameUtils.getName(videoDownloadUrl);
// Prepare the player with the source.
player.prepare();
player.setMediaSource(new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(mVideoUri)));
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/PostOptionsBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/PostOptionsBottomSheetFragment.java
index de834388..d10e0d5d 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/PostOptionsBottomSheetFragment.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/PostOptionsBottomSheetFragment.java
@@ -1,8 +1,11 @@
package ml.docilealligator.infinityforreddit.bottomsheetfragments;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -24,6 +27,8 @@ import ml.docilealligator.infinityforreddit.activities.SubmitCrosspostActivity;
import ml.docilealligator.infinityforreddit.customviews.LandscapeExpandedRoundedBottomSheetDialogFragment;
import ml.docilealligator.infinityforreddit.databinding.FragmentPostOptionsBottomSheetBinding;
import ml.docilealligator.infinityforreddit.post.Post;
+import ml.docilealligator.infinityforreddit.services.DownloadMediaService;
+import ml.docilealligator.infinityforreddit.services.DownloadRedditVideoService;
/**
* A simple {@link Fragment} subclass.
@@ -33,6 +38,7 @@ import ml.docilealligator.infinityforreddit.post.Post;
public class PostOptionsBottomSheetFragment extends LandscapeExpandedRoundedBottomSheetDialogFragment {
private static final String EXTRA_POST = "EP";
+ private static final String EXTRA_GALLERY_INDEX = "EGI";
private BaseActivity mBaseActivity;
private Post mPost;
@@ -76,13 +82,44 @@ public class PostOptionsBottomSheetFragment extends LandscapeExpandedRoundedBott
if (mPost != null) {
switch (mPost.getPostType()) {
case Post.IMAGE_TYPE:
+ case Post.GALLERY_TYPE:
+ binding.downloadTextViewPostOptionsBottomSheetFragment.setVisibility(View.VISIBLE);
+ binding.downloadTextViewPostOptionsBottomSheetFragment.setText(R.string.download_image);
break;
case Post.GIF_TYPE:
+ binding.downloadTextViewPostOptionsBottomSheetFragment.setVisibility(View.VISIBLE);
+ binding.downloadTextViewPostOptionsBottomSheetFragment.setText(R.string.download_gif);
break;
case Post.VIDEO_TYPE:
+ binding.downloadTextViewPostOptionsBottomSheetFragment.setVisibility(View.VISIBLE);
+ binding.downloadTextViewPostOptionsBottomSheetFragment.setText(R.string.download_video);
break;
- case Post.GALLERY_TYPE:
- break;
+ }
+
+ if (binding.downloadTextViewPostOptionsBottomSheetFragment.getVisibility() == View.VISIBLE) {
+ binding.downloadTextViewPostOptionsBottomSheetFragment.setOnClickListener(view -> {
+ if (mPost.getPostType() == Post.VIDEO_TYPE) {
+ if (!mPost.isRedgifs() && !mPost.isStreamable() && !mPost.isImgur()) {
+ PersistableBundle extras = new PersistableBundle();
+ extras.putString(DownloadRedditVideoService.EXTRA_VIDEO_URL, mPost.getVideoDownloadUrl());
+ extras.putString(DownloadRedditVideoService.EXTRA_POST_ID, mPost.getId());
+ extras.putString(DownloadRedditVideoService.EXTRA_SUBREDDIT, mPost.getSubredditName());
+ extras.putInt(DownloadRedditVideoService.EXTRA_IS_NSFW, mPost.isNSFW() ? 1 : 0);
+
+ //TODO: contentEstimatedBytes
+ JobInfo jobInfo = DownloadRedditVideoService.constructJobInfo(mBaseActivity, 5000000, extras);
+ ((JobScheduler) mBaseActivity.getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
+
+ dismiss();
+ return;
+ }
+ }
+
+ JobInfo jobInfo = DownloadMediaService.constructJobInfo(mBaseActivity, 5000000, mPost, getArguments().getInt(EXTRA_GALLERY_INDEX, 0));
+ ((JobScheduler) mBaseActivity.getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
+
+ dismiss();
+ });
}
binding.addToPostFilterTextViewPostOptionsBottomSheetFragment.setOnClickListener(view -> {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/post/FetchPost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/post/FetchPost.java
index 57895e17..6dbaf519 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/post/FetchPost.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/post/FetchPost.java
@@ -4,7 +4,9 @@ import android.os.Handler;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+import java.io.IOException;
import java.util.concurrent.Executor;
import ml.docilealligator.infinityforreddit.account.Account;
@@ -52,6 +54,29 @@ public class FetchPost {
});
}
+ @WorkerThread
+ @Nullable
+ public static Post fetchPostSync(Retrofit retrofit, String id, @Nullable String accessToken,
+ @NonNull String accountName) {
+ Call<String> postCall;
+ if (accountName.equals(Account.ANONYMOUS_ACCOUNT)) {
+ postCall = retrofit.create(RedditAPI.class).getPost(id);
+ } else {
+ postCall = retrofit.create(RedditAPI.class).getPostOauth(id, APIUtils.getOAuthHeader(accessToken));
+ }
+ try {
+ Response<String> response = postCall.execute();
+ if (response.isSuccessful()) {
+ return ParsePost.parsePostSync(response.body());
+ } else {
+ return null;
+ }
+
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
public static void fetchRandomPost(Executor executor, Handler handler, Retrofit retrofit, boolean isNSFW,
FetchRandomPostListener fetchRandomPostListener) {
Call<String> call;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/post/FetchStreamableVideo.java b/app/src/main/java/ml/docilealligator/infinityforreddit/post/FetchStreamableVideo.java
index 747c7161..9e372d1b 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/post/FetchStreamableVideo.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/post/FetchStreamableVideo.java
@@ -3,6 +3,7 @@ package ml.docilealligator.infinityforreddit.post;
import android.os.Handler;
import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
import org.json.JSONException;
import org.json.JSONObject;
@@ -50,6 +51,35 @@ public class FetchStreamableVideo {
});
}
+ @WorkerThread
+ @Nullable
+ public static StreamableVideo fetchStreamableVideoSync(Provider<StreamableAPI> streamableApiProvider,
+ String videoUrl) {
+ try {
+ Response<String> response = streamableApiProvider.get().getStreamableData(videoUrl).execute();
+ if (response.isSuccessful()) {
+ JSONObject jsonObject = new JSONObject(response.body());
+ String title = jsonObject.getString(JSONUtils.TITLE_KEY);
+ JSONObject filesObject = jsonObject.getJSONObject(JSONUtils.FILES_KEY);
+ StreamableVideo.Media mp4 = parseMedia(filesObject.getJSONObject(JSONUtils.MP4_KEY));
+ StreamableVideo.Media mp4MobileTemp = null;
+ if (filesObject.has(JSONUtils.MP4_MOBILE_KEY)) {
+ mp4MobileTemp = parseMedia(filesObject.getJSONObject(JSONUtils.MP4_MOBILE_KEY));
+ }
+ if (mp4 == null && mp4MobileTemp == null) {
+ return null;
+ }
+ StreamableVideo.Media mp4Mobile = mp4MobileTemp;
+ return new StreamableVideo(title, mp4, mp4Mobile);
+ } else {
+ return null;
+ }
+ } catch (IOException | JSONException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
public static void fetchStreamableVideoInRecyclerViewAdapter(Executor executor, Handler handler, Call<String> streamableCall,
FetchVideoLinkListener fetchVideoLinkListener) {
executor.execute(() -> {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/post/ImgurMedia.java b/app/src/main/java/ml/docilealligator/infinityforreddit/post/ImgurMedia.java
index a9a09a50..e78838f1 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/post/ImgurMedia.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/post/ImgurMedia.java
@@ -64,10 +64,10 @@ public class ImgurMedia implements Parcelable {
public String getFileName() {
if (type == TYPE_VIDEO) {
- return "imgur-" + id + ".mp4";
+ return "Imgur-" + id + ".mp4";
}
- return "imgur-" + id + ".jpg";
+ return "Imgur-" + id + ".jpg";
}
@Override
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/post/ParsePost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/post/ParsePost.java
index e7dc35ed..6092d9e1 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/post/ParsePost.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/post/ParsePost.java
@@ -5,6 +5,9 @@ import android.os.Handler;
import android.text.Html;
import android.text.TextUtils;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -82,9 +85,6 @@ public class ParsePost {
public static void parsePost(Executor executor, Handler handler, String response, ParsePostListener parsePostListener) {
- PostFilter postFilter = new PostFilter();
- postFilter.allowNSFW = true;
-
executor.execute(() -> {
try {
JSONArray allData = new JSONArray(response).getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY);
@@ -102,6 +102,22 @@ public class ParsePost {
});
}
+ @WorkerThread
+ @Nullable
+ public static Post parsePostSync(String response) {
+ try {
+ JSONArray allData = new JSONArray(response).getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY);
+ if (allData.length() == 0) {
+ return null;
+ }
+ JSONObject data = allData.getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY);
+ return parseBasicData(data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
public static void parseRandomPost(Executor executor, Handler handler, String response, boolean isNSFW,
ParseRandomPostListener parseRandomPostListener) {
executor.execute(() -> {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java
index 331026c3..60194716 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java
@@ -26,22 +26,27 @@ import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.documentfile.provider.DocumentFile;
+import org.apache.commons.io.FilenameUtils;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.List;
import java.util.Random;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Named;
+import javax.inject.Provider;
import ml.docilealligator.infinityforreddit.DownloadProgressResponseBody;
import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R;
+import ml.docilealligator.infinityforreddit.VideoLinkFetcher;
+import ml.docilealligator.infinityforreddit.activities.ViewVideoActivity;
import ml.docilealligator.infinityforreddit.apis.DownloadFile;
+import ml.docilealligator.infinityforreddit.apis.StreamableAPI;
import ml.docilealligator.infinityforreddit.broadcastreceivers.DownloadedMediaDeleteActionBroadcastReceiver;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.post.ImgurMedia;
@@ -60,6 +65,8 @@ public class DownloadMediaService extends JobService {
public static final String EXTRA_SUBREDDIT_NAME = "ESN";
public static final String EXTRA_MEDIA_TYPE = "EIG";
public static final String EXTRA_IS_NSFW = "EIN";
+ public static final String EXTRA_REDGIFS_ID = "EGI";
+ public static final String EXTRA_STREAMABLE_SHORT_CODE = "ESSC";
public static final int EXTRA_MEDIA_TYPE_IMAGE = 0;
public static final int EXTRA_MEDIA_TYPE_GIF = 1;
public static final int EXTRA_MEDIA_TYPE_VIDEO = 2;
@@ -68,6 +75,8 @@ public class DownloadMediaService extends JobService {
private static final int ERROR_CANNOT_GET_DESTINATION_DIRECTORY = 0;
private static final int ERROR_FILE_CANNOT_DOWNLOAD = 1;
private static final int ERROR_FILE_CANNOT_SAVE = 2;
+ private static final int ERROR_FILE_CANNOT_FETCH_REDGIFS_VIDEO_LINK = 3;
+ private static final int ERROR_FILE_CANNOT_FETCH_STREAMABLE_VIDEO_LINK = 4;
private static int JOB_ID = 20000;
@@ -75,9 +84,17 @@ public class DownloadMediaService extends JobService {
@Named("download_media")
Retrofit retrofit;
@Inject
+ @Named("redgifs")
+ Retrofit mRedgifsRetrofit;
+ @Inject
+ Provider<StreamableAPI> mStreamableApiProvider;
+ @Inject
@Named("default")
SharedPreferences mSharedPreferences;
@Inject
+ @Named("current_account")
+ SharedPreferences mCurrentAccountSharedPreferences;
+ @Inject
CustomThemeWrapper mCustomThemeWrapper;
@Inject
Executor mExecutor;
@@ -102,15 +119,34 @@ public class DownloadMediaService extends JobService {
extras.putString(DownloadMediaService.EXTRA_SUBREDDIT_NAME, post.getSubredditName());
extras.putInt(DownloadMediaService.EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
} else if (post.getPostType() == Post.VIDEO_TYPE) {
- if (post.isImgur() || post.isRedgifs() || post.isStreamable()) {
- //TODO fetch download links first
- /*extras.putString(DownloadMediaService.EXTRA_URL, post.getVideoDownloadUrl());
- extras.putInt(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_VIDEO);
- extras.putString(DownloadMediaService.EXTRA_FILE_NAME, videoFileName);
+ if (post.isStreamable()) {
+ if (post.isLoadRedgifsOrStreamableVideoSuccess()) {
+ extras.putString(DownloadMediaService.EXTRA_URL, post.getVideoUrl());
+ } else {
+ extras.putString(DownloadMediaService.EXTRA_REDGIFS_ID, post.getRedgifsId());
+ }
- extras.putString(DownloadMediaService.EXTRA_SUBREDDIT_NAME, post.getSubredditName());
- extras.putInt(DownloadMediaService.EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);*/
+ extras.putString(DownloadMediaService.EXTRA_FILE_NAME, "Streamable-" + post.getStreamableShortCode() + ".mp4");
+ } else if (post.isRedgifs()) {
+ if (post.isLoadRedgifsOrStreamableVideoSuccess()) {
+ extras.putString(DownloadMediaService.EXTRA_URL, post.getVideoUrl());
+ } else {
+ extras.putString(DownloadMediaService.EXTRA_STREAMABLE_SHORT_CODE, post.getStreamableShortCode());
+ }
+
+ String redgifsId = post.getRedgifsId();
+ if (redgifsId != null && redgifsId.contains("-")) {
+ redgifsId = redgifsId.substring(0, redgifsId.indexOf('-'));
+ }
+ extras.putString(DownloadMediaService.EXTRA_FILE_NAME, "Redgifs-" + redgifsId + ".mp4");
+ } else if (post.isImgur()) {
+ extras.putString(DownloadMediaService.EXTRA_URL, post.getVideoUrl());
+ extras.putString(DownloadMediaService.EXTRA_FILE_NAME, "Imgur-" + FilenameUtils.getName(post.getVideoUrl()));
}
+
+ extras.putInt(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_VIDEO);
+ extras.putString(DownloadMediaService.EXTRA_SUBREDDIT_NAME, post.getSubredditName());
+ extras.putInt(DownloadMediaService.EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
} else if (post.getPostType() == Post.GALLERY_TYPE) {
Post.Gallery media = post.getGallery().get(galleryIndex);
if (media.mediaType == Post.Gallery.TYPE_VIDEO) {
@@ -145,14 +181,12 @@ public class DownloadMediaService extends JobService {
public static JobInfo constructJobInfo(Context context, long contentEstimatedBytes, ImgurMedia imgurMedia) {
PersistableBundle extras = new PersistableBundle();
+ extras.putString(DownloadMediaService.EXTRA_URL, imgurMedia.getLink());
+ extras.putString(DownloadMediaService.EXTRA_FILE_NAME, imgurMedia.getFileName());
if (imgurMedia.getType() == ImgurMedia.TYPE_VIDEO) {
- extras.putString(DownloadMediaService.EXTRA_URL, imgurMedia.getLink());
extras.putInt(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_VIDEO);
- extras.putString(DownloadMediaService.EXTRA_FILE_NAME, imgurMedia.getFileName());
} else {
- extras.putString(DownloadMediaService.EXTRA_URL, imgurMedia.getLink());
extras.putInt(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_IMAGE);
- extras.putString(DownloadMediaService.EXTRA_FILE_NAME, imgurMedia.getFileName());
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
@@ -249,6 +283,22 @@ public class DownloadMediaService extends JobService {
boolean isNsfw = intent.getInt(EXTRA_IS_NSFW, 0) == 1;
String mimeType = mediaType == EXTRA_MEDIA_TYPE_VIDEO ? "video/*" : "image/*";
+ if (fileUrl == null) {
+ // Only Redgifs and Streamble video can go inside this if clause.
+ String redgifsId = intent.getString(EXTRA_REDGIFS_ID, null);
+ String streamableShortCode = intent.getString(EXTRA_STREAMABLE_SHORT_CODE, null);
+ fileUrl = VideoLinkFetcher.fetchVideoLinkSync(mRedgifsRetrofit, mStreamableApiProvider, mCurrentAccountSharedPreferences,
+ redgifsId == null ? ViewVideoActivity.VIDEO_TYPE_STREAMABLE : ViewVideoActivity.VIDEO_TYPE_REDGIFS,
+ redgifsId, streamableShortCode);
+
+ if (fileUrl == null) {
+ downloadFinished(params, builder, mediaType, randomNotificationIdOffset, mimeType,
+ null,
+ redgifsId == null ? ERROR_FILE_CANNOT_FETCH_STREAMABLE_VIDEO_LINK : ERROR_FILE_CANNOT_FETCH_REDGIFS_VIDEO_LINK);
+ return;
+ }
+ }
+
final DownloadProgressResponseBody.ProgressListener progressListener = new DownloadProgressResponseBody.ProgressListener() {
long time = 0;
@@ -586,6 +636,14 @@ public class DownloadMediaService extends JobService {
updateNotification(builder, mediaType, R.string.downloading_media_failed_cannot_save_to_destination_directory,
-1, randomNotificationIdOffset, null, null);
break;
+ case ERROR_FILE_CANNOT_FETCH_REDGIFS_VIDEO_LINK:
+ updateNotification(builder, mediaType, R.string.downloading_media_failed_cannot_fetch_redgifs_url,
+ -1, randomNotificationIdOffset, null, null);
+ break;
+ case ERROR_FILE_CANNOT_FETCH_STREAMABLE_VIDEO_LINK:
+ updateNotification(builder, mediaType, R.string.downloading_media_failed_cannot_fetch_streamable_url,
+ -1, randomNotificationIdOffset, null, null);
+ break;
}
} else {
MediaScannerConnection.scanFile(
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/thing/FetchRedgifsVideoLinks.java b/app/src/main/java/ml/docilealligator/infinityforreddit/thing/FetchRedgifsVideoLinks.java
index ee2fc7ad..08c37f28 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/thing/FetchRedgifsVideoLinks.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/thing/FetchRedgifsVideoLinks.java
@@ -3,6 +3,9 @@ package ml.docilealligator.infinityforreddit.thing;
import android.content.SharedPreferences;
import android.os.Handler;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+
import org.json.JSONException;
import org.json.JSONObject;
@@ -25,8 +28,12 @@ public class FetchRedgifsVideoLinks {
FetchVideoLinkListener fetchVideoLinkListener) {
executor.execute(() -> {
try {
- Response<String> response = redgifsRetrofit.create(RedgifsAPI.class).getRedgifsData(APIUtils.getRedgifsOAuthHeader(currentAccountSharedPreferences.getString(SharedPreferencesUtils.REDGIFS_ACCESS_TOKEN, "")),
- redgifsId, APIUtils.USER_AGENT).execute();
+ Response<String> response = redgifsRetrofit
+ .create(RedgifsAPI.class)
+ .getRedgifsData(
+ APIUtils.getRedgifsOAuthHeader(currentAccountSharedPreferences.getString(SharedPreferencesUtils.REDGIFS_ACCESS_TOKEN, "")),
+ redgifsId, APIUtils.USER_AGENT)
+ .execute();
if (response.isSuccessful()) {
parseRedgifsVideoLinks(handler, response.body(), fetchVideoLinkListener);
} else {
@@ -39,6 +46,29 @@ public class FetchRedgifsVideoLinks {
});
}
+ @WorkerThread
+ @Nullable
+ public static String fetchRedgifsVideoLinkSync(Retrofit redgifsRetrofit,
+ SharedPreferences currentAccountSharedPreferences,
+ String redgifsId) {
+ try {
+ Response<String> response = redgifsRetrofit
+ .create(RedgifsAPI.class)
+ .getRedgifsData(
+ APIUtils.getRedgifsOAuthHeader(currentAccountSharedPreferences.getString(SharedPreferencesUtils.REDGIFS_ACCESS_TOKEN, "")),
+ redgifsId, APIUtils.USER_AGENT)
+ .execute();
+ if (response.isSuccessful()) {
+ return parseRedgifsVideoLinks(response.body());
+ } else {
+ return null;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
public static void fetchRedgifsVideoLinksInRecyclerViewAdapter(Executor executor, Handler handler,
Call<String> redgifsCall,
FetchVideoLinkListener fetchVideoLinkListener) {
@@ -68,4 +98,15 @@ public class FetchRedgifsVideoLinks {
handler.post(() -> fetchVideoLinkListener.failed(null));
}
}
+
+ @Nullable
+ private static String parseRedgifsVideoLinks(String response) {
+ try {
+ return new JSONObject(response).getJSONObject(JSONUtils.GIF_KEY).getJSONObject(JSONUtils.URLS_KEY)
+ .getString(JSONUtils.HD_KEY);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
}
diff --git a/app/src/main/res/layout/fragment_post_options_bottom_sheet.xml b/app/src/main/res/layout/fragment_post_options_bottom_sheet.xml
index cf5074b3..647819de 100644
--- a/app/src/main/res/layout/fragment_post_options_bottom_sheet.xml
+++ b/app/src/main/res/layout/fragment_post_options_bottom_sheet.xml
@@ -91,6 +91,27 @@
app:drawableTint="?attr/primaryTextColor" />
<androidx.appcompat.widget.AppCompatTextView
+ android:id="@+id/download_text_view_post_options_bottom_sheet_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:background="?attr/selectableItemBackground"
+ android:clickable="true"
+ android:drawableStart="@drawable/ic_download_day_night_24dp"
+ android:drawablePadding="48dp"
+ android:focusable="true"
+ android:fontFamily="?attr/font_family"
+ android:paddingStart="32dp"
+ android:paddingTop="16dp"
+ android:paddingEnd="32dp"
+ android:paddingBottom="16dp"
+ android:text="@string/action_crosspost"
+ android:textColor="?attr/primaryTextColor"
+ android:textSize="?attr/font_default"
+ android:visibility="gone"
+ app:drawableTint="?attr/primaryTextColor" />
+
+ <androidx.appcompat.widget.AppCompatTextView
android:id="@+id/report_text_view_post_options_bottom_sheet_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d2e88ef2..68c26e20 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1050,6 +1050,8 @@
<string name="downloading_image_or_gif_failed_cannot_get_destination_directory">Download failed: cannot access destination directory</string>
<string name="downloading_media_failed_cannot_download_media">Download failed</string>
<string name="downloading_media_failed_cannot_save_to_destination_directory">Download failed: cannot save the file to destination directory</string>
+ <string name="downloading_media_failed_cannot_fetch_redgifs_url">Download failed: cannot fetch Redgifs video url</string>
+ <string name="downloading_media_failed_cannot_fetch_streamable_url">Download failed: cannot fetch Streamable video url</string>
<string name="wallpaper_set">Wallpaper set</string>
<string name="error_set_wallpaper">Cannot set wallpaper</string>
@@ -1496,4 +1498,9 @@
<string name="toggle_reply_notifications_failed">Toggle reply notifications failed</string>
<string name="cannot_find_comment">Cannot find comment</string>
+ <string name="download_image">Download Image</string>
+ <string name="download_gif">Download Gif</string>
+ <string name="download_video">Download Video</string>
+ <string name="download_all_gallery_images">Download All Gallery Images</string>
+
</resources>