videoVersions = media.getVideoVersions();
+ if (videoVersions != null && !videoVersions.isEmpty()) {
+ final VideoVersion videoVersion = videoVersions.get(0);
+ videoUrl = videoVersion.getUrl();
+ }
final VideoPlayerViewHelper videoPlayerViewHelper = new VideoPlayerViewHelper(binding.getRoot().getContext(),
binding.videoPost,
- feedModel.getDisplayUrl(),
+ videoUrl,
vol,
aspectRatio,
- feedModel.getThumbnailUrl(),
+ ResponseBodyUtils.getThumbUrl(media),
false,
null,
videoPlayerCallback);
binding.videoPost.thumbnail.post(() -> {
- if (feedModel.getImageHeight() > 0.8 * Utils.displayMetrics.heightPixels) {
+ if (media.getOriginalHeight() > 0.8 * Utils.displayMetrics.heightPixels) {
final ViewGroup.LayoutParams layoutParams = binding.videoPost.thumbnail.getLayoutParams();
layoutParams.height = (int) (0.8 * Utils.displayMetrics.heightPixels);
binding.videoPost.thumbnail.requestLayout();
}
});
- // binding.itemFeedBottom.btnMute.setOnClickListener(v -> {
- // final float newVol = videoPlayerViewHelper.toggleMute();
- // setMuteIcon(newVol);
- // Utils.sessionVolumeFull = newVol == 1f;
- // });
- // binding.videoPost.playerView.setOnClickListener(v -> videoPlayerViewHelper.togglePlayback());
}
-
- private void setMuteIcon(final float vol) {
- // binding.itemFeedBottom.btnMute.setImageResource(vol == 0f ? R.drawable.ic_volume_up_24 : R.drawable.ic_volume_off_24);
- }
-
- public FeedModel getCurrentFeedModel() {
- return feedModel;
+ public Media getCurrentFeedModel() {
+ return media;
}
// public void stopPlaying() {
diff --git a/app/src/main/java/awais/instagrabber/animations/CubicBezierInterpolator.java b/app/src/main/java/awais/instagrabber/animations/CubicBezierInterpolator.java
new file mode 100644
index 00000000..3c137d74
--- /dev/null
+++ b/app/src/main/java/awais/instagrabber/animations/CubicBezierInterpolator.java
@@ -0,0 +1,74 @@
+package awais.instagrabber.animations;
+
+import android.graphics.PointF;
+import android.view.animation.Interpolator;
+
+public class CubicBezierInterpolator implements Interpolator {
+
+ public static final CubicBezierInterpolator DEFAULT = new CubicBezierInterpolator(0.25, 0.1, 0.25, 1);
+ public static final CubicBezierInterpolator EASE_OUT = new CubicBezierInterpolator(0, 0, .58, 1);
+ public static final CubicBezierInterpolator EASE_OUT_QUINT = new CubicBezierInterpolator(.23, 1, .32, 1);
+ public static final CubicBezierInterpolator EASE_IN = new CubicBezierInterpolator(.42, 0, 1, 1);
+ public static final CubicBezierInterpolator EASE_BOTH = new CubicBezierInterpolator(.42, 0, .58, 1);
+
+ protected PointF start;
+ protected PointF end;
+ protected PointF a = new PointF();
+ protected PointF b = new PointF();
+ protected PointF c = new PointF();
+
+ public CubicBezierInterpolator(PointF start, PointF end) throws IllegalArgumentException {
+ if (start.x < 0 || start.x > 1) {
+ throw new IllegalArgumentException("startX value must be in the range [0, 1]");
+ }
+ if (end.x < 0 || end.x > 1) {
+ throw new IllegalArgumentException("endX value must be in the range [0, 1]");
+ }
+ this.start = start;
+ this.end = end;
+ }
+
+ public CubicBezierInterpolator(float startX, float startY, float endX, float endY) {
+ this(new PointF(startX, startY), new PointF(endX, endY));
+ }
+
+ public CubicBezierInterpolator(double startX, double startY, double endX, double endY) {
+ this((float) startX, (float) startY, (float) endX, (float) endY);
+ }
+
+ @Override
+ public float getInterpolation(float time) {
+ return getBezierCoordinateY(getXForTime(time));
+ }
+
+ protected float getBezierCoordinateY(float time) {
+ c.y = 3 * start.y;
+ b.y = 3 * (end.y - start.y) - c.y;
+ a.y = 1 - c.y - b.y;
+ return time * (c.y + time * (b.y + time * a.y));
+ }
+
+ protected float getXForTime(float time) {
+ float x = time;
+ float z;
+ for (int i = 1; i < 14; i++) {
+ z = getBezierCoordinateX(x) - time;
+ if (Math.abs(z) < 1e-3) {
+ break;
+ }
+ x -= z / getXDerivate(x);
+ }
+ return x;
+ }
+
+ private float getXDerivate(float t) {
+ return c.x + t * (2 * b.x + 3 * a.x * t);
+ }
+
+ private float getBezierCoordinateX(float time) {
+ c.x = 3 * start.x;
+ b.x = 3 * (end.x - start.x) - c.x;
+ a.x = 1 - c.x - b.x;
+ return time * (c.x + time * (b.x + time * a.x));
+ }
+}
diff --git a/app/src/main/java/awais/instagrabber/animations/FabAnimation.java b/app/src/main/java/awais/instagrabber/animations/FabAnimation.java
new file mode 100644
index 00000000..1df54dcc
--- /dev/null
+++ b/app/src/main/java/awais/instagrabber/animations/FabAnimation.java
@@ -0,0 +1,61 @@
+package awais.instagrabber.animations;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.view.View;
+
+// https://medium.com/better-programming/animated-fab-button-with-more-options-2dcf7118fff6
+
+public class FabAnimation {
+ public static boolean rotateFab(final View v, boolean rotate) {
+ v.animate().setDuration(200)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ }
+ })
+ .rotation(rotate ? 135f : 0f);
+ return rotate;
+ }
+
+ public static void showIn(final View v) {
+ v.setVisibility(View.VISIBLE);
+ v.setAlpha(0f);
+ v.setTranslationY(v.getHeight());
+ v.animate()
+ .setDuration(200)
+ .translationY(0)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ }
+ })
+ .alpha(1f)
+ .start();
+ }
+
+ public static void showOut(final View v) {
+ v.setVisibility(View.VISIBLE);
+ v.setAlpha(1f);
+ v.setTranslationY(0);
+ v.animate()
+ .setDuration(200)
+ .translationY(v.getHeight())
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ v.setVisibility(View.GONE);
+ super.onAnimationEnd(animation);
+ }
+ }).alpha(0f)
+ .start();
+ }
+
+ public static void init(final View v) {
+ v.setVisibility(View.GONE);
+ v.setTranslationY(v.getHeight());
+ v.setAlpha(0f);
+ }
+}
diff --git a/app/src/main/java/awais/instagrabber/animations/RevealOutlineAnimation.java b/app/src/main/java/awais/instagrabber/animations/RevealOutlineAnimation.java
new file mode 100644
index 00000000..16661719
--- /dev/null
+++ b/app/src/main/java/awais/instagrabber/animations/RevealOutlineAnimation.java
@@ -0,0 +1,84 @@
+package awais.instagrabber.animations;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+/**
+ * A {@link ViewOutlineProvider} that has helper functions to create reveal animations.
+ * This class should be extended so that subclasses can define the reveal shape as the
+ * animation progresses from 0 to 1.
+ */
+public abstract class RevealOutlineAnimation extends ViewOutlineProvider {
+ protected Rect mOutline;
+ protected float mOutlineRadius;
+
+ public RevealOutlineAnimation() {
+ mOutline = new Rect();
+ }
+
+ /**
+ * Returns whether elevation should be removed for the duration of the reveal animation.
+ */
+ abstract boolean shouldRemoveElevationDuringAnimation();
+
+ /**
+ * Sets the progress, from 0 to 1, of the reveal animation.
+ */
+ abstract void setProgress(float progress);
+
+ public ValueAnimator createRevealAnimator(final View revealView, boolean isReversed) {
+ ValueAnimator va =
+ isReversed ? ValueAnimator.ofFloat(1f, 0f) : ValueAnimator.ofFloat(0f, 1f);
+ final float elevation = revealView.getElevation();
+
+ va.addListener(new AnimatorListenerAdapter() {
+ private boolean mIsClippedToOutline;
+ private ViewOutlineProvider mOldOutlineProvider;
+
+ public void onAnimationStart(Animator animation) {
+ mIsClippedToOutline = revealView.getClipToOutline();
+ mOldOutlineProvider = revealView.getOutlineProvider();
+
+ revealView.setOutlineProvider(RevealOutlineAnimation.this);
+ revealView.setClipToOutline(true);
+ if (shouldRemoveElevationDuringAnimation()) {
+ revealView.setTranslationZ(-elevation);
+ }
+ }
+
+ public void onAnimationEnd(Animator animation) {
+ revealView.setOutlineProvider(mOldOutlineProvider);
+ revealView.setClipToOutline(mIsClippedToOutline);
+ if (shouldRemoveElevationDuringAnimation()) {
+ revealView.setTranslationZ(0);
+ }
+ }
+
+ });
+
+ va.addUpdateListener(v -> {
+ float progress = (Float) v.getAnimatedValue();
+ setProgress(progress);
+ revealView.invalidateOutline();
+ });
+ return va;
+ }
+
+ @Override
+ public void getOutline(View v, Outline outline) {
+ outline.setRoundRect(mOutline, mOutlineRadius);
+ }
+
+ public float getRadius() {
+ return mOutlineRadius;
+ }
+
+ public void getOutline(Rect out) {
+ out.set(mOutline);
+ }
+}
diff --git a/app/src/main/java/awais/instagrabber/animations/RoundedRectRevealOutlineProvider.java b/app/src/main/java/awais/instagrabber/animations/RoundedRectRevealOutlineProvider.java
new file mode 100644
index 00000000..c5cf0439
--- /dev/null
+++ b/app/src/main/java/awais/instagrabber/animations/RoundedRectRevealOutlineProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package awais.instagrabber.animations;
+
+import android.graphics.Rect;
+
+/**
+ * A {@link RevealOutlineAnimation} that provides an outline that interpolates between two radii
+ * and two {@link Rect}s.
+ *
+ * An example usage of this provider is an outline that starts out as a circle and ends
+ * as a rounded rectangle.
+ */
+public class RoundedRectRevealOutlineProvider extends RevealOutlineAnimation {
+ private final float mStartRadius;
+ private final float mEndRadius;
+
+ private final Rect mStartRect;
+ private final Rect mEndRect;
+
+ public RoundedRectRevealOutlineProvider(float startRadius, float endRadius, Rect startRect, Rect endRect) {
+ mStartRadius = startRadius;
+ mEndRadius = endRadius;
+ mStartRect = startRect;
+ mEndRect = endRect;
+ }
+
+ @Override
+ public boolean shouldRemoveElevationDuringAnimation() {
+ return false;
+ }
+
+ @Override
+ public void setProgress(float progress) {
+ mOutlineRadius = (1 - progress) * mStartRadius + progress * mEndRadius;
+
+ mOutline.left = (int) ((1 - progress) * mStartRect.left + progress * mEndRect.left);
+ mOutline.top = (int) ((1 - progress) * mStartRect.top + progress * mEndRect.top);
+ mOutline.right = (int) ((1 - progress) * mStartRect.right + progress * mEndRect.right);
+ mOutline.bottom = (int) ((1 - progress) * mStartRect.bottom + progress * mEndRect.bottom);
+ }
+}
diff --git a/app/src/main/java/awais/instagrabber/animations/ScaleAnimation.java b/app/src/main/java/awais/instagrabber/animations/ScaleAnimation.java
new file mode 100644
index 00000000..c4e8193b
--- /dev/null
+++ b/app/src/main/java/awais/instagrabber/animations/ScaleAnimation.java
@@ -0,0 +1,45 @@
+package awais.instagrabber.animations;
+
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.view.View;
+import android.view.animation.AccelerateDecelerateInterpolator;
+
+public class ScaleAnimation {
+
+ private final View view;
+
+ public ScaleAnimation(View view) {
+ this.view = view;
+ }
+
+
+ public void start() {
+ AnimatorSet set = new AnimatorSet();
+ ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 2.0f);
+
+ ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 2.0f);
+ set.setDuration(150);
+ set.setInterpolator(new AccelerateDecelerateInterpolator());
+ set.playTogether(scaleY, scaleX);
+ set.start();
+ }
+
+ public void stop() {
+ AnimatorSet set = new AnimatorSet();
+ ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1.0f);
+ // scaleY.setDuration(250);
+ // scaleY.setInterpolator(new DecelerateInterpolator());
+
+
+ ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1.0f);
+ // scaleX.setDuration(250);
+ // scaleX.setInterpolator(new DecelerateInterpolator());
+
+
+ set.setDuration(150);
+ set.setInterpolator(new AccelerateDecelerateInterpolator());
+ set.playTogether(scaleY, scaleX);
+ set.start();
+ }
+}
diff --git a/app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java
index d9f3cb65..6b9929c5 100755
--- a/app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java
@@ -17,7 +17,8 @@ import java.util.List;
import awais.instagrabber.BuildConfig;
import awais.instagrabber.interfaces.FetchListener;
import awais.instagrabber.models.CommentModel;
-import awais.instagrabber.models.ProfileModel;
+import awais.instagrabber.repositories.responses.FriendshipStatus;
+import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.NetworkUtils;
import awais.instagrabber.utils.TextUtils;
@@ -106,33 +107,22 @@ public final class CommentsFetcher extends AsyncTask getParentComments() {
final List commentModels = new ArrayList<>();
- final String url = "https://www.instagram.com/graphql/query/?query_hash=bc3296d1ce80a24b1b6e40b1e72903f5&variables=" +
- "{\"shortcode\":\"" + shortCode + "\",\"first\":50,\"after\":\"" + endCursor.replace("\"", "\\\"") + "\"}";
+ final String url = "https://www.instagram.com/graphql/query/?query_hash=bc3296d1ce80a24b1b6e40b1e72903f5&variables=" +
+ "{\"shortcode\":\"" + shortCode + "\",\"first\":50,\"after\":\"" + endCursor.replace("\"", "\\\"") + "\"}";
try {
- final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
- conn.setUseCaches(false);
- conn.connect();
+ final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
+ conn.setUseCaches(false);
+ conn.connect();
- if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) return null;
- else {
- final JSONObject parentComments = new JSONObject(NetworkUtils.readFromConnection(conn)).getJSONObject("data")
- .getJSONObject("shortcode_media")
- .getJSONObject(
- "edge_media_to_parent_comment");
+ if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) return null;
+ else {
+ final JSONObject parentComments = new JSONObject(NetworkUtils.readFromConnection(conn)).getJSONObject("data")
+ .getJSONObject("shortcode_media")
+ .getJSONObject(
+ "edge_media_to_parent_comment");
- final JSONObject pageInfo = parentComments.getJSONObject("page_info");
- final String foundEndCursor = pageInfo.optString("end_cursor");
- final boolean hasNextPage = pageInfo.optBoolean("has_next_page", !TextUtils.isEmpty(foundEndCursor));
+ final JSONObject pageInfo = parentComments.getJSONObject("page_info");
+ final String foundEndCursor = pageInfo.optString("end_cursor");
+ final boolean hasNextPage = pageInfo.optBoolean("has_next_page", !TextUtils.isEmpty(foundEndCursor));
- // final boolean containsToken = endCursor.contains("bifilter_token");
- // if (!Utils.isEmpty(endCursor) && (containsToken || endCursor.contains("cached_comments_cursor"))) {
- // final JSONObject endCursorObject = new JSONObject(endCursor);
- // endCursor = endCursorObject.optString("cached_comments_cursor");
- //
- // if (!Utils.isEmpty(endCursor))
- // endCursor = "{\\\"cached_comments_cursor\\\": \\\"" + endCursor + "\\\", ";
- // else
- // endCursor = "{";
- //
- // endCursor = endCursor + "\\\"bifilter_token\\\": \\\"" + endCursorObject.getString("bifilter_token") + "\\\"}";
- // }
- // else if (containsToken) endCursor = null;
+ // final boolean containsToken = endCursor.contains("bifilter_token");
+ // if (!Utils.isEmpty(endCursor) && (containsToken || endCursor.contains("cached_comments_cursor"))) {
+ // final JSONObject endCursorObject = new JSONObject(endCursor);
+ // endCursor = endCursorObject.optString("cached_comments_cursor");
+ //
+ // if (!Utils.isEmpty(endCursor))
+ // endCursor = "{\\\"cached_comments_cursor\\\": \\\"" + endCursor + "\\\", ";
+ // else
+ // endCursor = "{";
+ //
+ // endCursor = endCursor + "\\\"bifilter_token\\\": \\\"" + endCursorObject.getString("bifilter_token") + "\\\"}";
+ // }
+ // else if (containsToken) endCursor = null;
- final JSONArray comments = parentComments.getJSONArray("edges");
- final int commentsLen = comments.length();
- for (int i = 0; i < commentsLen; ++i) {
- final JSONObject comment = comments.getJSONObject(i).getJSONObject("node");
+ final JSONArray comments = parentComments.getJSONArray("edges");
+ final int commentsLen = comments.length();
+ for (int i = 0; i < commentsLen; ++i) {
+ final JSONObject comment = comments.getJSONObject(i).getJSONObject("node");
- final JSONObject owner = comment.getJSONObject("owner");
- final ProfileModel profileModel = new ProfileModel(false,
- false,
- owner.optBoolean("is_verified"),
- owner.getString(Constants.EXTRAS_ID),
- owner.getString(Constants.EXTRAS_USERNAME),
- null,
- null,
- null,
- owner.getString("profile_pic_url"),
- null,
- 0,
- 0,
- 0,
- false,
- false,
- false,
- false,
- false);
+ final JSONObject owner = comment.getJSONObject("owner");
+ final User user = new User(
+ owner.optLong(Constants.EXTRAS_ID, 0),
+ owner.getString(Constants.EXTRAS_USERNAME),
+ null,
+ false,
+ owner.getString("profile_pic_url"),
+ null,
+ new FriendshipStatus(false, false, false, false, false, false, false, false, false, false),
+ owner.optBoolean("is_verified"),
+ false, false, false, false, null, null, 0, 0, 0, 0, null, null, 0, null, null);
+ final JSONObject likedBy = comment.optJSONObject("edge_liked_by");
+ final String commentId = comment.getString(Constants.EXTRAS_ID);
+ final CommentModel commentModel = new CommentModel(commentId,
+ comment.getString("text"),
+ comment.getLong("created_at"),
+ likedBy != null ? likedBy.optLong("count", 0) : 0,
+ comment.getBoolean("viewer_has_liked"),
+ user);
+ if (i == 0 && !foundEndCursor.contains("tao_cursor"))
+ commentModel.setPageCursor(hasNextPage, TextUtils.isEmpty(foundEndCursor) ? null : foundEndCursor);
+ JSONObject tempJsonObject;
+ final JSONArray childCommentsArray;
+ final int childCommentsLen;
+ if ((tempJsonObject = comment.optJSONObject("edge_threaded_comments")) != null &&
+ (childCommentsArray = tempJsonObject.optJSONArray("edges")) != null
+ && (childCommentsLen = childCommentsArray.length()) > 0) {
- final JSONObject likedBy = comment.optJSONObject("edge_liked_by");
- final String commentId = comment.getString(Constants.EXTRAS_ID);
- final CommentModel commentModel = new CommentModel(commentId,
- comment.getString("text"),
- comment.getLong("created_at"),
- likedBy != null ? likedBy.optLong("count", 0) : 0,
- comment.getBoolean("viewer_has_liked"),
- profileModel);
- if (i == 0 && !foundEndCursor.contains("tao_cursor"))
- commentModel.setPageCursor(hasNextPage, TextUtils.isEmpty(foundEndCursor) ? null : foundEndCursor);
- JSONObject tempJsonObject;
- final JSONArray childCommentsArray;
- final int childCommentsLen;
- if ((tempJsonObject = comment.optJSONObject("edge_threaded_comments")) != null &&
- (childCommentsArray = tempJsonObject.optJSONArray("edges")) != null
- && (childCommentsLen = childCommentsArray.length()) > 0) {
-
- final String childEndCursor;
- final boolean childHasNextPage;
- if ((tempJsonObject = tempJsonObject.optJSONObject("page_info")) != null) {
- childEndCursor = tempJsonObject.optString("end_cursor");
- childHasNextPage = tempJsonObject.optBoolean("has_next_page", !TextUtils.isEmpty(childEndCursor));
- } else {
- childEndCursor = null;
- childHasNextPage = false;
- }
-
- final List childCommentModels = new ArrayList<>();
- for (int j = 0; j < childCommentsLen; ++j) {
- final JSONObject childComment = childCommentsArray.getJSONObject(j).getJSONObject("node");
-
- tempJsonObject = childComment.getJSONObject("owner");
- final ProfileModel childProfileModel = new ProfileModel(false,
- false,
- tempJsonObject.optBoolean("is_verified"),
- tempJsonObject.getString(Constants.EXTRAS_ID),
- tempJsonObject.getString(Constants.EXTRAS_USERNAME),
- null,
- null,
- null,
- tempJsonObject.getString("profile_pic_url"),
- null,
- 0,
- 0,
- 0,
- false,
- false,
- false,
- false,
- false);
-
- tempJsonObject = childComment.optJSONObject("edge_liked_by");
- childCommentModels.add(new CommentModel(childComment.getString(Constants.EXTRAS_ID),
- childComment.getString("text"),
- childComment.getLong("created_at"),
- tempJsonObject != null ? tempJsonObject.optLong("count", 0) : 0,
- childComment.getBoolean("viewer_has_liked"),
- childProfileModel));
- }
- childCommentModels.get(childCommentsLen - 1).setPageCursor(childHasNextPage, childEndCursor);
- commentModel.setChildCommentModels(childCommentModels);
+ final String childEndCursor;
+ final boolean childHasNextPage;
+ if ((tempJsonObject = tempJsonObject.optJSONObject("page_info")) != null) {
+ childEndCursor = tempJsonObject.optString("end_cursor");
+ childHasNextPage = tempJsonObject.optBoolean("has_next_page", !TextUtils.isEmpty(childEndCursor));
+ } else {
+ childEndCursor = null;
+ childHasNextPage = false;
}
- commentModels.add(commentModel);
- }
- }
- conn.disconnect();
- } catch (final Exception e) {
- if (logCollector != null)
- logCollector.appendException(e, LogCollector.LogFile.ASYNC_COMMENTS_FETCHER, "getParentComments",
- new Pair<>("commentModelsList.size", commentModels.size()));
- if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
- if (fetchListener != null) fetchListener.onFailure(e);
- return null;
+ final List childCommentModels = new ArrayList<>();
+ for (int j = 0; j < childCommentsLen; ++j) {
+ final JSONObject childComment = childCommentsArray.getJSONObject(j).getJSONObject("node");
+
+ tempJsonObject = childComment.getJSONObject("owner");
+ final User childUser = new User(
+ tempJsonObject.optLong(Constants.EXTRAS_ID, 0),
+ tempJsonObject.getString(Constants.EXTRAS_USERNAME),
+ null,
+ false,
+ tempJsonObject.getString("profile_pic_url"),
+ null,
+ new FriendshipStatus(false, false, false, false, false, false, false, false, false, false),
+ tempJsonObject.optBoolean("is_verified"), false, false, false, false, null, null, 0, 0, 0, 0, null, null, 0,
+ null, null);
+
+ tempJsonObject = childComment.optJSONObject("edge_liked_by");
+ childCommentModels.add(new CommentModel(childComment.getString(Constants.EXTRAS_ID),
+ childComment.getString("text"),
+ childComment.getLong("created_at"),
+ tempJsonObject != null ? tempJsonObject.optLong("count", 0) : 0,
+ childComment.getBoolean("viewer_has_liked"),
+ childUser));
+ }
+ childCommentModels.get(childCommentsLen - 1).setPageCursor(childHasNextPage, childEndCursor);
+ commentModel.setChildCommentModels(childCommentModels);
+ }
+ commentModels.add(commentModel);
+ }
}
+
+ conn.disconnect();
+ } catch (final Exception e) {
+ if (logCollector != null)
+ logCollector.appendException(e, LogCollector.LogFile.ASYNC_COMMENTS_FETCHER, "getParentComments",
+ new Pair<>("commentModelsList.size", commentModels.size()));
+ if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
+ if (fetchListener != null) fetchListener.onFailure(e);
+ return null;
+ }
return commentModels;
}
}
diff --git a/app/src/main/java/awais/instagrabber/asyncs/CreateThreadAction.java b/app/src/main/java/awais/instagrabber/asyncs/CreateThreadAction.java
new file mode 100644
index 00000000..ba35ef7e
--- /dev/null
+++ b/app/src/main/java/awais/instagrabber/asyncs/CreateThreadAction.java
@@ -0,0 +1,84 @@
+package awais.instagrabber.asyncs;
+
+import android.os.AsyncTask;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Locale;
+
+import awais.instagrabber.repositories.responses.directmessages.DirectThread;
+import awais.instagrabber.utils.Constants;
+import awais.instagrabber.utils.CookieUtils;
+import awais.instagrabber.utils.NetworkUtils;
+import awais.instagrabber.utils.Utils;
+import awais.instagrabber.webservices.DirectMessagesService;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+import static awais.instagrabber.utils.Utils.settingsHelper;
+
+public class CreateThreadAction extends AsyncTask {
+ private static final String TAG = "CommentAction";
+
+ private final String cookie;
+ private final long userId;
+ private final OnTaskCompleteListener onTaskCompleteListener;
+ private final DirectMessagesService directMessagesService;
+
+ public CreateThreadAction(final String cookie, final long userId, final OnTaskCompleteListener onTaskCompleteListener) {
+ this.cookie = cookie;
+ this.userId = userId;
+ this.onTaskCompleteListener = onTaskCompleteListener;
+ directMessagesService = DirectMessagesService.getInstance(CookieUtils.getCsrfTokenFromCookie(cookie),
+ CookieUtils.getUserIdFromCookie(cookie),
+ Utils.settingsHelper.getString(Constants.DEVICE_UUID));
+ }
+
+ protected Void doInBackground(Void... lmao) {
+ final Call createThreadRequest = directMessagesService.createThread(Collections.singletonList(userId), null);
+ createThreadRequest.enqueue(new Callback() {
+ @Override
+ public void onResponse(@NonNull final Call call, @NonNull final Response response) {
+ if (!response.isSuccessful()) {
+ if (response.errorBody() != null) {
+ try {
+ final String string = response.errorBody().string();
+ final String msg = String.format(Locale.US,
+ "onResponse: url: %s, responseCode: %d, errorBody: %s",
+ call.request().url().toString(),
+ response.code(),
+ string);
+ Log.e(TAG, msg);
+ } catch (IOException e) {
+ Log.e(TAG, "onResponse: ", e);
+ }
+ }
+ Log.e(TAG, "onResponse: request was not successful and response error body was null");
+ }
+ onTaskCompleteListener.onTaskComplete(response.body());
+ if (response.body() == null) {
+ Log.e(TAG, "onResponse: thread is null");
+ }
+ }
+
+ @Override
+ public void onFailure(@NonNull final Call call, @NonNull final Throwable t) {
+ onTaskCompleteListener.onTaskComplete(null);
+ }
+ });
+ return null;
+ }
+
+// @Override
+// protected void onPostExecute() {
+// }
+
+ public interface OnTaskCompleteListener {
+ void onTaskComplete(final DirectThread thread);
+ }
+}
diff --git a/app/src/main/java/awais/instagrabber/asyncs/DiscoverPostFetchService.java b/app/src/main/java/awais/instagrabber/asyncs/DiscoverPostFetchService.java
index a8c83dc8..9416e787 100644
--- a/app/src/main/java/awais/instagrabber/asyncs/DiscoverPostFetchService.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/DiscoverPostFetchService.java
@@ -1,10 +1,15 @@
package awais.instagrabber.asyncs;
+import java.util.Collections;
import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
import awais.instagrabber.customviews.helpers.PostFetcher;
import awais.instagrabber.interfaces.FetchListener;
-import awais.instagrabber.models.FeedModel;
+import awais.instagrabber.repositories.responses.Media;
+import awais.instagrabber.repositories.responses.discover.TopicalExploreFeedResponse;
+import awais.instagrabber.repositories.responses.WrappedMedia;
import awais.instagrabber.webservices.DiscoverService;
import awais.instagrabber.webservices.ServiceCallback;
@@ -20,18 +25,28 @@ public class DiscoverPostFetchService implements PostFetcher.PostFetchService {
}
@Override
- public void fetch(final FetchListener> fetchListener) {
- discoverService.topicalExplore(topicalExploreRequest, new ServiceCallback() {
+ public void fetch(final FetchListener> fetchListener) {
+ discoverService.topicalExplore(topicalExploreRequest, new ServiceCallback() {
@Override
- public void onSuccess(final DiscoverService.TopicalExploreResponse result) {
+ public void onSuccess(final TopicalExploreFeedResponse result) {
if (result == null) {
onFailure(new RuntimeException("result is null"));
return;
}
moreAvailable = result.isMoreAvailable();
topicalExploreRequest.setMaxId(result.getNextMaxId());
+ final List items = result.getItems();
+ final List posts;
+ if (items == null) {
+ posts = Collections.emptyList();
+ } else {
+ posts = items.stream()
+ .map(WrappedMedia::getMedia)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ }
if (fetchListener != null) {
- fetchListener.onResult(result.getItems());
+ fetchListener.onResult(posts);
}
}
@@ -46,7 +61,7 @@ public class DiscoverPostFetchService implements PostFetcher.PostFetchService {
@Override
public void reset() {
- topicalExploreRequest.setMaxId(-1);
+ topicalExploreRequest.setMaxId(null);
}
@Override
diff --git a/app/src/main/java/awais/instagrabber/asyncs/DownloadedCheckerAsyncTask.java b/app/src/main/java/awais/instagrabber/asyncs/DownloadedCheckerAsyncTask.java
index 49e1ae0e..605bed3f 100644
--- a/app/src/main/java/awais/instagrabber/asyncs/DownloadedCheckerAsyncTask.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/DownloadedCheckerAsyncTask.java
@@ -6,10 +6,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import awais.instagrabber.models.FeedModel;
+import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.utils.DownloadUtils;
-public final class DownloadedCheckerAsyncTask extends AsyncTask>> {
+public final class DownloadedCheckerAsyncTask extends AsyncTask>> {
private static final String TAG = "DownloadedCheckerAsyncTask";
private final OnCheckResultListener listener;
@@ -19,13 +19,13 @@ public final class DownloadedCheckerAsyncTask extends AsyncTask> doInBackground(final FeedModel... feedModels) {
+ protected Map> doInBackground(final Media... feedModels) {
if (feedModels == null) {
return null;
}
final Map> map = new HashMap<>();
- for (final FeedModel feedModel : feedModels) {
- map.put(feedModel.getPostId(), DownloadUtils.checkDownloaded(feedModel));
+ for (final Media media : feedModels) {
+ map.put(media.getPk(), DownloadUtils.checkDownloaded(media));
}
return map;
}
diff --git a/app/src/main/java/awais/instagrabber/asyncs/FeedPostFetchService.java b/app/src/main/java/awais/instagrabber/asyncs/FeedPostFetchService.java
index b45a224a..b07b7b45 100644
--- a/app/src/main/java/awais/instagrabber/asyncs/FeedPostFetchService.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/FeedPostFetchService.java
@@ -1,14 +1,11 @@
package awais.instagrabber.asyncs;
-//import android.os.Handler;
-//import android.util.Log;
-
import java.util.ArrayList;
import java.util.List;
import awais.instagrabber.customviews.helpers.PostFetcher;
import awais.instagrabber.interfaces.FetchListener;
-import awais.instagrabber.models.FeedModel;
+import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.PostsFetchResponse;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
@@ -21,47 +18,40 @@ public class FeedPostFetchService implements PostFetcher.PostFetchService {
private static final String TAG = "FeedPostFetchService";
private final FeedService feedService;
private String nextCursor;
-// private final Handler handler;
private boolean hasNextPage;
-// private static final int DELAY_MILLIS = 500;
public FeedPostFetchService() {
feedService = FeedService.getInstance();
-// handler = new Handler();
}
@Override
- public void fetch(final FetchListener> fetchListener) {
- final List feedModels = new ArrayList<>();
+ public void fetch(final FetchListener> fetchListener) {
+ final List feedModels = new ArrayList<>();
final String cookie = settingsHelper.getString(Constants.COOKIE);
final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
+ final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID);
feedModels.clear();
- feedService.fetch(csrfToken, nextCursor, new ServiceCallback() {
+ feedService.fetch(csrfToken, deviceUuid, nextCursor, new ServiceCallback() {
@Override
public void onSuccess(final PostsFetchResponse result) {
if (result == null && feedModels.size() > 0) {
fetchListener.onResult(feedModels);
return;
- }
- else if (result == null) return;
+ } else if (result == null) return;
nextCursor = result.getNextCursor();
hasNextPage = result.hasNextPage();
feedModels.addAll(result.getFeedModels());
if (fetchListener != null) {
- if (feedModels.size() < 15 && hasNextPage) {
-// handler.postDelayed(() -> {
- feedService.fetch(csrfToken, nextCursor, this);
-// }, DELAY_MILLIS);
- }
- else {
- fetchListener.onResult(feedModels);
- }
+ // if (feedModels.size() < 15 && hasNextPage) {
+ // feedService.fetch(csrfToken, nextCursor, this);
+ // } else {
+ fetchListener.onResult(feedModels);
+ // }
}
}
@Override
public void onFailure(final Throwable t) {
- // Log.e(TAG, "onFailure: ", t);
if (fetchListener != null) {
fetchListener.onFailure(t);
}
diff --git a/app/src/main/java/awais/instagrabber/asyncs/GetActivityAsyncTask.java b/app/src/main/java/awais/instagrabber/asyncs/GetActivityAsyncTask.java
index 1987443b..13a88ee4 100644
--- a/app/src/main/java/awais/instagrabber/asyncs/GetActivityAsyncTask.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/GetActivityAsyncTask.java
@@ -3,6 +3,8 @@ package awais.instagrabber.asyncs;
import android.os.AsyncTask;
import android.util.Log;
+import androidx.annotation.NonNull;
+
import org.json.JSONObject;
import java.net.HttpURLConnection;
@@ -12,6 +14,7 @@ import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.NetworkUtils;
import awais.instagrabber.utils.TextUtils;
+import awais.instagrabber.utils.Utils;
public class GetActivityAsyncTask extends AsyncTask {
private static final String TAG = "GetActivityAsyncTask";
@@ -35,14 +38,14 @@ public class GetActivityAsyncTask extends AsyncTask> fetchListener) {
- final ServiceCallback cb = new ServiceCallback() {
+ public void fetch(final FetchListener> fetchListener) {
+ final ServiceCallback cb = new ServiceCallback() {
@Override
public void onSuccess(final PostsFetchResponse result) {
if (result == null) return;
diff --git a/app/src/main/java/awais/instagrabber/asyncs/ImageUploader.java b/app/src/main/java/awais/instagrabber/asyncs/ImageUploader.java
deleted file mode 100644
index 386cb4de..00000000
--- a/app/src/main/java/awais/instagrabber/asyncs/ImageUploader.java
+++ /dev/null
@@ -1,176 +0,0 @@
-package awais.instagrabber.asyncs;
-
-import android.graphics.Bitmap;
-import android.os.AsyncTask;
-import android.util.Log;
-
-import org.json.JSONObject;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-import awais.instagrabber.models.ImageUploadOptions;
-import awais.instagrabber.utils.NetworkUtils;
-import awais.instagrabber.utils.NumberUtils;
-
-public class ImageUploader extends AsyncTask {
- private static final String TAG = "ImageUploader";
- private static final long LOWER = 1000000000L;
- private static final long UPPER = 9999999999L;
- private OnImageUploadCompleteListener listener;
-
- protected ImageUploadResponse doInBackground(final ImageUploadOptions... imageUploadOptions) {
- if (imageUploadOptions == null || imageUploadOptions.length == 0 || imageUploadOptions[0] == null) {
- return null;
- }
- HttpURLConnection connection = null;
- OutputStream out = null;
- InputStream inputStream = null;
- BufferedReader r = null;
- ByteArrayOutputStream baos = null;
- try {
- final ImageUploadOptions options = imageUploadOptions[0];
- final Bitmap bitmap = options.getBitmap();
- baos = new ByteArrayOutputStream();
- final boolean compressResult = bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
- if (!compressResult) {
- Log.e(TAG, "Compress result was false!");
- return null;
- }
- final byte[] bytes = baos.toByteArray();
- final String contentLength = String.valueOf(bytes.length);
- final Map headers = new HashMap<>();
- final String uploadId = String.valueOf(new Date().getTime());
- final long random = NumberUtils.random(LOWER, UPPER + 1);
- final String name = String.format("%s_0_%s", uploadId, random);
- final String waterfallId = options.getWaterfallId() != null ? options.getWaterfallId() : UUID.randomUUID().toString();
- headers.put("X-Entity-Type", "image/jpeg");
- headers.put("Offset", "0");
- headers.put("X_FB_PHOTO_WATERFALL_ID", waterfallId);
- headers.put("X-Instagram-Rupload-Params", new JSONObject(createPhotoRuploadParams(options, uploadId)).toString());
- headers.put("X-Entity-Name", name);
- headers.put("X-Entity-Length", contentLength);
- headers.put("Content-Type", "application/octet-stream");
- headers.put("Content-Length", contentLength);
- headers.put("Accept-Encoding", "gzip");
- final String url = "https://www.instagram.com/rupload_igphoto/" + name + "/";
- connection = (HttpURLConnection) new URL(url).openConnection();
- connection.setRequestMethod("POST");
- connection.setUseCaches(false);
- connection.setDoOutput(true);
- NetworkUtils.setConnectionHeaders(connection, headers);
- out = new BufferedOutputStream(connection.getOutputStream());
- out.write(bytes);
- out.flush();
- final int responseCode = connection.getResponseCode();
- Log.d(TAG, "response: " + responseCode);
- final String responseCodeString = String.valueOf(responseCode);
- final InputStream responseInputStream = responseCodeString.startsWith("4") || responseCodeString.startsWith("5")
- ? connection.getErrorStream() : connection.getInputStream();
- r = new BufferedReader(new InputStreamReader(responseInputStream));
- final StringBuilder builder = new StringBuilder();
- for (String line = r.readLine(); line != null; line = r.readLine()) {
- if (builder.length() != 0) {
- builder.append("\n");
- }
- builder.append(line);
- }
- return new ImageUploadResponse(responseCode, new JSONObject(builder.toString()));
- } catch (Exception ex) {
- Log.e(TAG, "Image upload error:", ex);
- } finally {
- if (r != null) {
- try {
- r.close();
- } catch (IOException ignored) {}
- }
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException ignored) {}
- }
- if (out != null) {
- try {
- out.close();
- } catch (IOException ignored) {}
- }
- if (connection != null) {
- connection.disconnect();
- }
- if (baos != null) {
- try {
- baos.close();
- } catch (IOException ignored) {}
- }
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(final ImageUploadResponse response) {
- if (listener != null) {
- listener.onImageUploadComplete(response);
- }
- }
-
- private Map createPhotoRuploadParams(final ImageUploadOptions options, final String uploadId) {
- final Map retryContext = new HashMap<>();
- retryContext.put("num_step_auto_retry", 0);
- retryContext.put("num_reupload", 0);
- retryContext.put("num_step_manual_retry", 0);
- final String retryContextString = new JSONObject(retryContext).toString();
- final Map params = new HashMap<>();
- params.put("retry_context", retryContextString);
- params.put("media_type", "1");
- params.put("upload_id", uploadId);
- params.put("xsharing_user_ids", "[]");
- final Map imageCompression = new HashMap<>();
- imageCompression.put("lib_name", "moz");
- imageCompression.put("lib_version", "3.1.m");
- imageCompression.put("quality", "80");
- params.put("image_compression", new JSONObject(imageCompression).toString());
- if (options.isSidecar()) {
- params.put("is_sidecar", "1");
- }
- return params;
- }
-
- public void setOnTaskCompleteListener(final OnImageUploadCompleteListener listener) {
- if (listener != null) {
- this.listener = listener;
- }
- }
-
- public interface OnImageUploadCompleteListener {
- void onImageUploadComplete(ImageUploadResponse response);
- }
-
- public static class ImageUploadResponse {
- private int responseCode;
- private JSONObject response;
-
- public ImageUploadResponse(int responseCode, JSONObject response) {
- this.responseCode = responseCode;
- this.response = response;
- }
-
- public int getResponseCode() {
- return responseCode;
- }
-
- public JSONObject getResponse() {
- return response;
- }
- }
-}
diff --git a/app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java
index 7025c224..8ccd47ce 100644
--- a/app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java
@@ -24,9 +24,9 @@ public final class LocationFetcher extends AsyncTask
private static final String TAG = "LocationFetcher";
private final FetchListener fetchListener;
- private final String id;
+ private final long id;
- public LocationFetcher(final String id, final FetchListener fetchListener) {
+ public LocationFetcher(final long id, final FetchListener fetchListener) {
// idSlug = id + "/" + slug UPDATE: slug can be ignored tbh
this.id = id;
this.fetchListener = fetchListener;
@@ -52,8 +52,7 @@ public final class LocationFetcher extends AsyncTask
// final JSONArray edges = timelineMedia.getJSONArray("edges");
// }
result = new LocationModel(
- location.getString(Constants.EXTRAS_ID),
- location.getString("slug"),
+ location.getLong(Constants.EXTRAS_ID),
location.getString("name"),
location.getString("blurb"),
location.getString("website"),
diff --git a/app/src/main/java/awais/instagrabber/asyncs/LocationPostFetchService.java b/app/src/main/java/awais/instagrabber/asyncs/LocationPostFetchService.java
index 7c7a12ce..7613c9d2 100644
--- a/app/src/main/java/awais/instagrabber/asyncs/LocationPostFetchService.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/LocationPostFetchService.java
@@ -4,8 +4,8 @@ import java.util.List;
import awais.instagrabber.customviews.helpers.PostFetcher;
import awais.instagrabber.interfaces.FetchListener;
-import awais.instagrabber.models.FeedModel;
import awais.instagrabber.models.LocationModel;
+import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.PostsFetchResponse;
import awais.instagrabber.webservices.GraphQLService;
import awais.instagrabber.webservices.LocationService;
@@ -27,8 +27,8 @@ public class LocationPostFetchService implements PostFetcher.PostFetchService {
}
@Override
- public void fetch(final FetchListener> fetchListener) {
- final ServiceCallback cb = new ServiceCallback() {
+ public void fetch(final FetchListener> fetchListener) {
+ final ServiceCallback cb = new ServiceCallback() {
@Override
public void onSuccess(final PostsFetchResponse result) {
if (result == null) return;
diff --git a/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java
index 2a721a61..c22954b5 100755
--- a/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java
@@ -3,40 +3,32 @@ package awais.instagrabber.asyncs;
import android.os.AsyncTask;
import android.util.Log;
-import org.json.JSONArray;
import org.json.JSONObject;
import java.net.HttpURLConnection;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
import awais.instagrabber.interfaces.FetchListener;
-import awais.instagrabber.models.FeedModel;
-import awais.instagrabber.models.PostChild;
-import awais.instagrabber.models.ProfileModel;
-import awais.instagrabber.models.enums.MediaItemType;
-import awais.instagrabber.utils.Constants;
+import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.utils.NetworkUtils;
import awais.instagrabber.utils.ResponseBodyUtils;
-import awais.instagrabber.utils.TextUtils;
import awaisomereport.LogCollector;
import static awais.instagrabber.utils.Utils.logCollector;
-public final class PostFetcher extends AsyncTask {
+public final class PostFetcher extends AsyncTask {
private static final String TAG = "PostFetcher";
private final String shortCode;
- private final FetchListener fetchListener;
+ private final FetchListener fetchListener;
- public PostFetcher(final String shortCode, final FetchListener fetchListener) {
+ public PostFetcher(final String shortCode, final FetchListener fetchListener) {
this.shortCode = shortCode;
this.fetchListener = fetchListener;
}
@Override
- protected FeedModel doInBackground(final Void... voids) {
+ protected Media doInBackground(final Void... voids) {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL("https://www.instagram.com/p/" + shortCode + "/?__a=1").openConnection();
@@ -47,100 +39,101 @@ public final class PostFetcher extends AsyncTask {
final JSONObject media = new JSONObject(NetworkUtils.readFromConnection(conn)).getJSONObject("graphql")
.getJSONObject("shortcode_media");
- ProfileModel profileModel = null;
- if (media.has("owner")) {
- final JSONObject owner = media.getJSONObject("owner");
- profileModel = new ProfileModel(
- owner.optBoolean("is_private"),
- owner.optBoolean("is_private"),
- owner.optBoolean("is_verified"),
- owner.optString("id"),
- owner.optString("username"),
- owner.optString("full_name"),
- null,
- null,
- owner.optString("profile_pic_url"),
- owner.optString("profile_pic_url"),
- owner.optInt("edge_owner_to_timeline_media"),
- owner.optInt("edge_followed_by"),
- -1,
- owner.optBoolean("followed_by_viewer"),
- false,
- owner.optBoolean("restricted_by_viewer"),
- owner.optBoolean("blocked_by_viewer"),
- owner.optBoolean("requested_by_viewer")
- );
- }
- final long timestamp = media.getLong("taken_at_timestamp");
-
- final boolean isVideo = media.has("is_video") && media.optBoolean("is_video");
- final boolean isSlider = media.has("edge_sidecar_to_children");
-
- final MediaItemType mediaItemType;
- if (isSlider) mediaItemType = MediaItemType.MEDIA_TYPE_SLIDER;
- else if (isVideo) mediaItemType = MediaItemType.MEDIA_TYPE_VIDEO;
- else mediaItemType = MediaItemType.MEDIA_TYPE_IMAGE;
-
- final String postCaption;
- final JSONObject mediaToCaption = media.optJSONObject("edge_media_to_caption");
- if (mediaToCaption == null) postCaption = null;
- else {
- final JSONArray captions = mediaToCaption.optJSONArray("edges");
- postCaption = captions != null && captions.length() > 0 ?
- captions.getJSONObject(0).getJSONObject("node").optString("text") : null;
- }
-
- JSONObject commentObject = media.optJSONObject("edge_media_to_parent_comment");
- final long commentsCount = commentObject != null ? commentObject.optLong("count") : 0;
- final FeedModel.Builder feedModelBuilder = new FeedModel.Builder()
- .setItemType(mediaItemType)
- .setPostId(media.getString(Constants.EXTRAS_ID))
- .setDisplayUrl(isVideo ? media.getString("video_url")
- : ResponseBodyUtils.getHighQualityImage(media))
- .setThumbnailUrl(media.getString("display_url"))
- .setImageHeight(media.getJSONObject("dimensions").getInt("height"))
- .setImageWidth(media.getJSONObject("dimensions").getInt("width"))
- .setShortCode(shortCode)
- .setPostCaption(TextUtils.isEmpty(postCaption) ? null : postCaption)
- .setProfileModel(profileModel)
- .setViewCount(isVideo && media.has("video_view_count")
- ? media.getLong("video_view_count")
- : -1)
- .setTimestamp(timestamp)
- .setLiked(media.getBoolean("viewer_has_liked"))
- .setBookmarked(media.getBoolean("viewer_has_saved"))
- .setLikesCount(media.getJSONObject("edge_media_preview_like")
- .getLong("count"))
- .setLocationName(media.isNull("location")
- ? null
- : media.getJSONObject("location").optString("name"))
- .setLocationId(media.isNull("location")
- ? null
- : media.getJSONObject("location").optString("id"))
- .setCommentsCount(commentsCount);
- if (isSlider) {
- final JSONArray children = media.getJSONObject("edge_sidecar_to_children").getJSONArray("edges");
- final List postModels = new ArrayList<>();
- for (int i = 0; i < children.length(); ++i) {
- final JSONObject childNode = children.getJSONObject(i).getJSONObject("node");
- final boolean isChildVideo = childNode.getBoolean("is_video");
- postModels.add(new PostChild.Builder()
- .setItemType(isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO
- : MediaItemType.MEDIA_TYPE_IMAGE)
- .setDisplayUrl(isChildVideo ? childNode.getString("video_url")
- : childNode.getString("display_url"))
- .setShortCode(media.getString(Constants.EXTRAS_SHORTCODE))
- .setVideoViews(isChildVideo && childNode.has("video_view_count")
- ? childNode.getLong("video_view_count")
- : -1)
- .setThumbnailUrl(childNode.getString("display_url"))
- .setHeight(childNode.getJSONObject("dimensions").getInt("height"))
- .setWidth(childNode.getJSONObject("dimensions").getInt("width"))
- .build());
- }
- feedModelBuilder.setSliderItems(postModels);
- }
- return feedModelBuilder.build();
+ // ProfileModel profileModel = null;
+ // if (media.has("owner")) {
+ // final JSONObject owner = media.getJSONObject("owner");
+ // profileModel = new ProfileModel(
+ // owner.optBoolean("is_private"),
+ // owner.optBoolean("is_private"),
+ // owner.optBoolean("is_verified"),
+ // owner.optString("id"),
+ // owner.optString("username"),
+ // owner.optString("full_name"),
+ // null,
+ // null,
+ // owner.optString("profile_pic_url"),
+ // owner.optString("profile_pic_url"),
+ // owner.optInt("edge_owner_to_timeline_media"),
+ // owner.optInt("edge_followed_by"),
+ // -1,
+ // owner.optBoolean("followed_by_viewer"),
+ // false,
+ // owner.optBoolean("restricted_by_viewer"),
+ // owner.optBoolean("blocked_by_viewer"),
+ // owner.optBoolean("requested_by_viewer")
+ // );
+ // }
+ // final long timestamp = media.getLong("taken_at_timestamp");
+ //
+ // final boolean isVideo = media.has("is_video") && media.optBoolean("is_video");
+ // final boolean isSlider = media.has("edge_sidecar_to_children");
+ //
+ // final MediaItemType mediaItemType;
+ // if (isSlider) mediaItemType = MediaItemType.MEDIA_TYPE_SLIDER;
+ // else if (isVideo) mediaItemType = MediaItemType.MEDIA_TYPE_VIDEO;
+ // else mediaItemType = MediaItemType.MEDIA_TYPE_IMAGE;
+ //
+ // final String postCaption;
+ // final JSONObject mediaToCaption = media.optJSONObject("edge_media_to_caption");
+ // if (mediaToCaption == null) postCaption = null;
+ // else {
+ // final JSONArray captions = mediaToCaption.optJSONArray("edges");
+ // postCaption = captions != null && captions.length() > 0 ?
+ // captions.getJSONObject(0).getJSONObject("node").optString("text") : null;
+ // }
+ //
+ // JSONObject commentObject = media.optJSONObject("edge_media_to_parent_comment");
+ // final long commentsCount = commentObject != null ? commentObject.optLong("count") : 0;
+ // final FeedModel.Builder feedModelBuilder = new FeedModel.Builder()
+ // .setItemType(mediaItemType)
+ // .setPostId(media.getString(Constants.EXTRAS_ID))
+ // .setDisplayUrl(isVideo ? media.getString("video_url")
+ // : ResponseBodyUtils.getHighQualityImage(media))
+ // .setThumbnailUrl(media.getString("display_url"))
+ // .setImageHeight(media.getJSONObject("dimensions").getInt("height"))
+ // .setImageWidth(media.getJSONObject("dimensions").getInt("width"))
+ // .setShortCode(shortCode)
+ // .setPostCaption(TextUtils.isEmpty(postCaption) ? null : postCaption)
+ // .setProfileModel(profileModel)
+ // .setViewCount(isVideo && media.has("video_view_count")
+ // ? media.getLong("video_view_count")
+ // : -1)
+ // .setTimestamp(timestamp)
+ // .setLiked(media.getBoolean("viewer_has_liked"))
+ // .setBookmarked(media.getBoolean("viewer_has_saved"))
+ // .setLikesCount(media.getJSONObject("edge_media_preview_like")
+ // .getLong("count"))
+ // .setLocationName(media.isNull("location")
+ // ? null
+ // : media.getJSONObject("location").optString("name"))
+ // .setLocationId(media.isNull("location")
+ // ? null
+ // : media.getJSONObject("location").optString("id"))
+ // .setCommentsCount(commentsCount);
+ // if (isSlider) {
+ // final JSONArray children = media.getJSONObject("edge_sidecar_to_children").getJSONArray("edges");
+ // final List postModels = new ArrayList<>();
+ // for (int i = 0; i < children.length(); ++i) {
+ // final JSONObject childNode = children.getJSONObject(i).getJSONObject("node");
+ // final boolean isChildVideo = childNode.getBoolean("is_video");
+ // postModels.add(new PostChild.Builder()
+ // .setItemType(isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO
+ // : MediaItemType.MEDIA_TYPE_IMAGE)
+ // .setDisplayUrl(isChildVideo ? childNode.getString("video_url")
+ // : childNode.getString("display_url"))
+ // .setShortCode(media.getString(Constants.EXTRAS_SHORTCODE))
+ // .setVideoViews(isChildVideo && childNode.has("video_view_count")
+ // ? childNode.getLong("video_view_count")
+ // : -1)
+ // .setThumbnailUrl(childNode.getString("display_url"))
+ // .setHeight(childNode.getJSONObject("dimensions").getInt("height"))
+ // .setWidth(childNode.getJSONObject("dimensions").getInt("width"))
+ // .build());
+ // }
+ // feedModelBuilder.setSliderItems(postModels);
+ // }
+ // return feedModelBuilder.build();
+ return ResponseBodyUtils.parseGraphQLItem(media);
}
} catch (Exception e) {
if (logCollector != null) {
@@ -161,7 +154,7 @@ public final class PostFetcher extends AsyncTask {
}
@Override
- protected void onPostExecute(final FeedModel feedModel) {
+ protected void onPostExecute(final Media feedModel) {
if (fetchListener != null) fetchListener.onResult(feedModel);
}
}
diff --git a/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java
index 7e78b0b2..5da3b5aa 100755
--- a/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java
@@ -5,91 +5,83 @@ import android.util.Log;
import androidx.annotation.Nullable;
-import org.json.JSONArray;
-import org.json.JSONObject;
+import java.util.ArrayList;
+import java.util.List;
-import java.net.HttpURLConnection;
-import java.net.URL;
-
-import awais.instagrabber.BuildConfig;
import awais.instagrabber.interfaces.FetchListener;
-import awais.instagrabber.models.ProfileModel;
-import awais.instagrabber.utils.Constants;
-import awais.instagrabber.utils.CookieUtils;
-import awais.instagrabber.utils.NetworkUtils;
-import awais.instagrabber.utils.TextUtils;
-import awaisomereport.LogCollector;
+import awais.instagrabber.repositories.responses.FriendshipStatus;
+import awais.instagrabber.repositories.responses.User;
+import awais.instagrabber.webservices.GraphQLService;
+import awais.instagrabber.webservices.ServiceCallback;
+import awais.instagrabber.webservices.UserService;
-import static awais.instagrabber.utils.Utils.logCollector;
-import static awais.instagrabber.utils.Utils.settingsHelper;
+public final class ProfileFetcher extends AsyncTask {
+ private static final String TAG = ProfileFetcher.class.getSimpleName();
+ private final UserService userService;
+ private final GraphQLService graphQLService;
-public final class ProfileFetcher extends AsyncTask {
- private final FetchListener fetchListener;
+ private final FetchListener fetchListener;
+ private final boolean isLoggedIn;
private final String userName;
- public ProfileFetcher(String userName, FetchListener fetchListener) {
+ public ProfileFetcher(final String userName,
+ final boolean isLoggedIn,
+ final FetchListener fetchListener) {
this.userName = userName;
+ this.isLoggedIn = isLoggedIn;
this.fetchListener = fetchListener;
+ userService = isLoggedIn ? UserService.getInstance() : null;
+ graphQLService = isLoggedIn ? null : GraphQLService.getInstance();
}
@Nullable
@Override
- protected ProfileModel doInBackground(final Void... voids) {
- ProfileModel result = null;
+ protected Void doInBackground(final Void... voids) {
+ if (isLoggedIn) {
+ userService.getUsernameInfo(userName, new ServiceCallback() {
+ @Override
+ public void onSuccess(final User user) {
+ userService.getUserFriendship(user.getPk(), new ServiceCallback() {
+ @Override
+ public void onSuccess(final FriendshipStatus status) {
+ user.setFriendshipStatus(status);
+ fetchListener.onResult(user);
+ }
- try {
- final HttpURLConnection conn = (HttpURLConnection) new URL("https://www.instagram.com/" + userName + "/?__a=1").openConnection();
- conn.setUseCaches(true);
- conn.connect();
-
- if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
- final JSONObject user = new JSONObject(NetworkUtils.readFromConnection(conn)).getJSONObject("graphql").getJSONObject(Constants.EXTRAS_USER);
-
- final String cookie = settingsHelper.getString(Constants.COOKIE);
-
- boolean isPrivate = user.getBoolean("is_private");
- final String id = user.getString(Constants.EXTRAS_ID);
- final String uid = CookieUtils.getUserIdFromCookie(cookie);
- final JSONObject timelineMedia = user.getJSONObject("edge_owner_to_timeline_media");
- if (timelineMedia.has("edges")) {
- final JSONArray edges = timelineMedia.getJSONArray("edges");
+ @Override
+ public void onFailure(final Throwable t) {
+ Log.e(TAG, "Error", t);
+ fetchListener.onFailure(t);
+ }
+ });
}
- String url = user.optString("external_url");
- if (TextUtils.isEmpty(url)) url = null;
-
- result = new ProfileModel(isPrivate,
- user.optBoolean("followed_by_viewer") ? false : (id.equals(uid) ? false : isPrivate),
- user.getBoolean("is_verified"),
- id,
- userName,
- user.getString("full_name"),
- user.getString("biography"),
- url,
- user.getString("profile_pic_url"),
- user.getString("profile_pic_url_hd"),
- timelineMedia.getLong("count"),
- user.getJSONObject("edge_followed_by").getLong("count"),
- user.getJSONObject("edge_follow").getLong("count"),
- user.optBoolean("followed_by_viewer"),
- user.optBoolean("follows_viewer"),
- user.optBoolean("restricted_by_viewer"),
- user.optBoolean("blocked_by_viewer"),
- user.optBoolean("requested_by_viewer"));
- }
-
- conn.disconnect();
- } catch (final Exception e) {
- if (logCollector != null)
- logCollector.appendException(e, LogCollector.LogFile.ASYNC_PROFILE_FETCHER, "doInBackground");
- if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
+ @Override
+ public void onFailure(final Throwable t) {
+ Log.e(TAG, "Error", t);
+ fetchListener.onFailure(t);
+ }
+ });
}
+ else {
+ graphQLService.fetchUser(userName, new ServiceCallback() {
+ @Override
+ public void onSuccess(final User user) {
+ fetchListener.onResult(user);
+ }
- return result;
+ @Override
+ public void onFailure(final Throwable t) {
+ Log.e(TAG, "Error", t);
+ fetchListener.onFailure(t);
+ }
+ });
+ }
+ return null;
}
@Override
- protected void onPostExecute(final ProfileModel result) {
- if (fetchListener != null) fetchListener.onResult(result);
+ protected void onPreExecute() {
+ if (fetchListener != null) fetchListener.doBefore();
}
}
diff --git a/app/src/main/java/awais/instagrabber/asyncs/ProfilePostFetchService.java b/app/src/main/java/awais/instagrabber/asyncs/ProfilePostFetchService.java
index 649d28d8..e2cfa10c 100644
--- a/app/src/main/java/awais/instagrabber/asyncs/ProfilePostFetchService.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/ProfilePostFetchService.java
@@ -4,9 +4,9 @@ import java.util.List;
import awais.instagrabber.customviews.helpers.PostFetcher;
import awais.instagrabber.interfaces.FetchListener;
-import awais.instagrabber.models.FeedModel;
-import awais.instagrabber.models.ProfileModel;
+import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.PostsFetchResponse;
+import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.webservices.GraphQLService;
import awais.instagrabber.webservices.ProfileService;
import awais.instagrabber.webservices.ServiceCallback;
@@ -15,12 +15,12 @@ public class ProfilePostFetchService implements PostFetcher.PostFetchService {
private static final String TAG = "ProfilePostFetchService";
private final ProfileService profileService;
private final GraphQLService graphQLService;
- private final ProfileModel profileModel;
+ private final User profileModel;
private final boolean isLoggedIn;
private String nextMaxId;
private boolean moreAvailable;
- public ProfilePostFetchService(final ProfileModel profileModel, final boolean isLoggedIn) {
+ public ProfilePostFetchService(final User profileModel, final boolean isLoggedIn) {
this.profileModel = profileModel;
this.isLoggedIn = isLoggedIn;
graphQLService = isLoggedIn ? null : GraphQLService.getInstance();
@@ -28,8 +28,8 @@ public class ProfilePostFetchService implements PostFetcher.PostFetchService {
}
@Override
- public void fetch(final FetchListener> fetchListener) {
- final ServiceCallback cb = new ServiceCallback() {
+ public void fetch(final FetchListener> fetchListener) {
+ final ServiceCallback cb = new ServiceCallback() {
@Override
public void onSuccess(final PostsFetchResponse result) {
if (result == null) return;
@@ -48,8 +48,8 @@ public class ProfilePostFetchService implements PostFetcher.PostFetchService {
}
}
};
- if (isLoggedIn) profileService.fetchPosts(profileModel.getId(), nextMaxId, cb);
- else graphQLService.fetchProfilePosts(profileModel.getId(), 30, nextMaxId, cb);
+ if (isLoggedIn) profileService.fetchPosts(profileModel.getPk(), nextMaxId, cb);
+ else graphQLService.fetchProfilePosts(profileModel.getPk(), 30, nextMaxId, cb);
}
@Override
diff --git a/app/src/main/java/awais/instagrabber/asyncs/SavedPostFetchService.java b/app/src/main/java/awais/instagrabber/asyncs/SavedPostFetchService.java
index b13d842d..9b3511a9 100644
--- a/app/src/main/java/awais/instagrabber/asyncs/SavedPostFetchService.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/SavedPostFetchService.java
@@ -4,8 +4,8 @@ import java.util.List;
import awais.instagrabber.customviews.helpers.PostFetcher;
import awais.instagrabber.interfaces.FetchListener;
-import awais.instagrabber.models.FeedModel;
import awais.instagrabber.models.enums.PostItemType;
+import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.PostsFetchResponse;
import awais.instagrabber.webservices.GraphQLService;
import awais.instagrabber.webservices.ProfileService;
@@ -14,23 +14,25 @@ import awais.instagrabber.webservices.ServiceCallback;
public class SavedPostFetchService implements PostFetcher.PostFetchService {
private final ProfileService profileService;
private final GraphQLService graphQLService;
- private final String profileId;
+ private final long profileId;
private final PostItemType type;
private final boolean isLoggedIn;
private String nextMaxId;
+ private final String collectionId;
private boolean moreAvailable;
- public SavedPostFetchService(final String profileId, final PostItemType type, final boolean isLoggedIn) {
+ public SavedPostFetchService(final long profileId, final PostItemType type, final boolean isLoggedIn, final String collectionId) {
this.profileId = profileId;
this.type = type;
this.isLoggedIn = isLoggedIn;
+ this.collectionId = collectionId;
graphQLService = isLoggedIn ? null : GraphQLService.getInstance();
profileService = isLoggedIn ? ProfileService.getInstance() : null;
}
@Override
- public void fetch(final FetchListener> fetchListener) {
+ public void fetch(final FetchListener> fetchListener) {
final ServiceCallback callback = new ServiceCallback() {
@Override
public void onSuccess(final PostsFetchResponse result) {
@@ -58,10 +60,12 @@ public class SavedPostFetchService implements PostFetcher.PostFetchService {
if (isLoggedIn) profileService.fetchTagged(profileId, nextMaxId, callback);
else graphQLService.fetchTaggedPosts(profileId, 30, nextMaxId, callback);
break;
+ case COLLECTION:
case SAVED:
- default:
- profileService.fetchSaved(nextMaxId, callback);
+ profileService.fetchSaved(nextMaxId, collectionId, callback);
break;
+ default:
+ callback.onFailure(null);
}
}
diff --git a/app/src/main/java/awais/instagrabber/asyncs/UsernameFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/UsernameFetcher.java
index 6b7b3bd8..d0feb459 100755
--- a/app/src/main/java/awais/instagrabber/asyncs/UsernameFetcher.java
+++ b/app/src/main/java/awais/instagrabber/asyncs/UsernameFetcher.java
@@ -14,12 +14,13 @@ import awais.instagrabber.BuildConfig;
import awais.instagrabber.interfaces.FetchListener;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.NetworkUtils;
+import awais.instagrabber.utils.Utils;
public final class UsernameFetcher extends AsyncTask {
private final FetchListener fetchListener;
- private final String uid;
+ private final long uid;
- public UsernameFetcher(final String uid, final FetchListener fetchListener) {
+ public UsernameFetcher(final long uid, final FetchListener fetchListener) {
this.uid = uid;
this.fetchListener = fetchListener;
}
@@ -31,7 +32,7 @@ public final class UsernameFetcher extends AsyncTask {
try {
final HttpURLConnection conn = (HttpURLConnection) new URL("https://i.instagram.com/api/v1/users/" + uid + "/info/").openConnection();
- conn.setRequestProperty("User-Agent", Constants.USER_AGENT);
+ conn.setRequestProperty("User-Agent", Utils.settingsHelper.getString(Constants.BROWSER_UA));
conn.setUseCaches(true);
final JSONObject user;
diff --git a/app/src/main/java/awais/instagrabber/asyncs/direct_messages/CreateThreadAction.java b/app/src/main/java/awais/instagrabber/asyncs/direct_messages/CreateThreadAction.java
deleted file mode 100644
index cda2ef34..00000000
--- a/app/src/main/java/awais/instagrabber/asyncs/direct_messages/CreateThreadAction.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package awais.instagrabber.asyncs.direct_messages;
-
-import android.os.AsyncTask;
-import android.util.Log;
-
-import org.json.JSONObject;
-
-import java.io.DataOutputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-
-import awais.instagrabber.utils.Constants;
-import awais.instagrabber.utils.CookieUtils;
-import awais.instagrabber.utils.NetworkUtils;
-import awais.instagrabber.utils.Utils;
-
-import static awais.instagrabber.utils.Utils.settingsHelper;
-
-public class CreateThreadAction extends AsyncTask