diff --git a/app/src/main/java/awais/instagrabber/activities/MainActivity.java b/app/src/main/java/awais/instagrabber/activities/MainActivity.java index 8879b05c..00935c2f 100644 --- a/app/src/main/java/awais/instagrabber/activities/MainActivity.java +++ b/app/src/main/java/awais/instagrabber/activities/MainActivity.java @@ -62,7 +62,6 @@ import java.util.stream.Collectors; import awais.instagrabber.BuildConfig; import awais.instagrabber.R; -import awais.instagrabber.asyncs.PostFetcher; import awais.instagrabber.customviews.emoji.EmojiVariantManager; import awais.instagrabber.customviews.helpers.RootViewDeferringInsetsCallback; import awais.instagrabber.customviews.helpers.TextWatcherAdapter; @@ -72,6 +71,7 @@ import awais.instagrabber.fragments.directmessages.DirectMessageInboxFragmentDir import awais.instagrabber.fragments.settings.PreferenceKeys; import awais.instagrabber.models.IntentModel; import awais.instagrabber.models.Tab; +import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.services.ActivityCheckerService; import awais.instagrabber.services.DMSyncAlarmReceiver; import awais.instagrabber.utils.AppExecutors; @@ -84,7 +84,10 @@ import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.emoji.EmojiParser; import awais.instagrabber.viewmodels.AppStateViewModel; import awais.instagrabber.viewmodels.DirectInboxViewModel; +import awais.instagrabber.webservices.GraphQLService; +import awais.instagrabber.webservices.MediaService; import awais.instagrabber.webservices.RetrofitFactory; +import awais.instagrabber.webservices.ServiceCallback; import static awais.instagrabber.utils.NavigationExtensions.setupWithNavController; import static awais.instagrabber.utils.Utils.settingsHelper; @@ -116,6 +119,8 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage private HideBottomViewOnScrollBehavior behavior; private List currentTabs; private List showBottomViewDestinations = Collections.emptyList(); + private GraphQLService graphQLService = null; + private MediaService mediaService = null; private final ServiceConnection serviceConnection = new ServiceConnection() { @Override @@ -679,24 +684,35 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage .setCancelable(false) .setView(R.layout.dialog_opening_post) .create(); - alertDialog.show(); - new PostFetcher(shortCode, feedModel -> { - if (feedModel != null) { - if (currentNavControllerLiveData == null) return; - final NavController navController = currentNavControllerLiveData.getValue(); - if (navController == null) return; - final Bundle bundle = new Bundle(); - bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel); - try { - navController.navigate(R.id.action_global_post_view, bundle); - } catch (Exception e) { - Log.e(TAG, "showPostView: ", e); + if (graphQLService == null) graphQLService = GraphQLService.getInstance(); + if (mediaService == null) mediaService = MediaService.getInstance(null, null, 0L); + final ServiceCallback postCb = new ServiceCallback() { + @Override + public void onSuccess(final Media feedModel){ + if (feedModel != null) { + if (currentNavControllerLiveData == null) return; + final NavController navController = currentNavControllerLiveData.getValue(); + if (navController == null) return; + final Bundle bundle = new Bundle(); + bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel); + try { + navController.navigate(R.id.action_global_post_view, bundle); + } catch (Exception e) { + Log.e(TAG, "showPostView: ", e); + } } - return; + Toast.makeText(getApplicationContext(), R.string.post_not_found, Toast.LENGTH_SHORT).show(); + alertDialog.dismiss(); } - Toast.makeText(getApplicationContext(), R.string.post_not_found, Toast.LENGTH_SHORT).show(); - alertDialog.dismiss(); - }).execute(); + + @Override + public void onFailure(final Throwable t) { + alertDialog.dismiss(); + } + }; + alertDialog.show(); + if (isLoggedIn) mediaService.fetch(TextUtils.shortcodeToId(shortCode), postCb); + else graphQLService.fetchPost(shortCode, postCb); } private void showLocationView(@NonNull final IntentModel intentModel) { diff --git a/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java deleted file mode 100755 index c0e63ea6..00000000 --- a/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java +++ /dev/null @@ -1,157 +0,0 @@ -package awais.instagrabber.asyncs; - -import android.os.AsyncTask; -import android.util.Log; - -import org.json.JSONObject; - -import java.net.HttpURLConnection; -import java.net.URL; - -import awais.instagrabber.interfaces.FetchListener; -import awais.instagrabber.repositories.responses.Media; -import awais.instagrabber.utils.NetworkUtils; -import awais.instagrabber.utils.ResponseBodyUtils; - -public final class PostFetcher extends AsyncTask { - private static final String TAG = "PostFetcher"; - - private final String shortCode; - private final FetchListener fetchListener; - - public PostFetcher(final String shortCode, final FetchListener fetchListener) { - this.shortCode = shortCode; - this.fetchListener = fetchListener; - } - - @Override - protected Media doInBackground(final Void... voids) { - HttpURLConnection conn = null; - try { - conn = (HttpURLConnection) new URL("https://www.instagram.com/p/" + shortCode + "/?__a=1").openConnection(); - conn.setUseCaches(false); - conn.connect(); - - if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { - - 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(); - return ResponseBodyUtils.parseGraphQLItem(media, null); - } - } catch (Exception e) { - // if (logCollector != null) { - // logCollector.appendException(e, LogCollector.LogFile.ASYNC_POST_FETCHER, "doInBackground"); - // } - Log.e(TAG, "Error fetching post", e); - } finally { - if (conn != null) { - conn.disconnect(); - } - } - return null; - } - - @Override - protected void onPreExecute() { - if (fetchListener != null) fetchListener.doBefore(); - } - - @Override - protected void onPostExecute(final Media feedModel) { - if (fetchListener != null) fetchListener.onResult(feedModel); - } -} diff --git a/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java b/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java index d8ac1c2a..617e4464 100644 --- a/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java @@ -46,7 +46,6 @@ import awais.instagrabber.R; import awais.instagrabber.activities.MainActivity; import awais.instagrabber.adapters.FeedAdapterV2; import awais.instagrabber.asyncs.HashtagPostFetchService; -import awais.instagrabber.asyncs.PostFetcher; import awais.instagrabber.customviews.PrimaryActionModeCallback; import awais.instagrabber.databinding.FragmentHashtagBinding; import awais.instagrabber.databinding.LayoutHashtagDetailsBinding; @@ -217,12 +216,22 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe final User user = feedModel.getUser(); if (user == null) return; if (TextUtils.isEmpty(user.getUsername())) { + // this only happens for anons opening = true; - new PostFetcher(feedModel.getCode(), newFeedModel -> { - opening = false; - if (newFeedModel == null) return; - openPostDialog(newFeedModel, profilePicView, mainPostImage, position); - }).execute(); + graphQLService.fetchPost(feedModel.getCode(), new ServiceCallback() { + @Override + public void onSuccess(final Media newFeedModel) { + opening = false; + if (newFeedModel == null) return; + openPostDialog(newFeedModel, profilePicView, mainPostImage, position); + } + + @Override + public void onFailure(final Throwable t) { + opening = false; + Log.e(TAG, "Error", t); + } + }); return; } opening = true; diff --git a/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java b/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java index 9f6da2c0..371d87eb 100644 --- a/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java @@ -44,7 +44,6 @@ import awais.instagrabber.R; import awais.instagrabber.activities.MainActivity; import awais.instagrabber.adapters.FeedAdapterV2; import awais.instagrabber.asyncs.LocationPostFetchService; -import awais.instagrabber.asyncs.PostFetcher; import awais.instagrabber.customviews.PrimaryActionModeCallback; import awais.instagrabber.databinding.FragmentLocationBinding; import awais.instagrabber.databinding.LayoutLocationDetailsBinding; @@ -209,11 +208,20 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR if (user == null) return; if (TextUtils.isEmpty(user.getUsername())) { opening = true; - new PostFetcher(feedModel.getCode(), newFeedModel -> { - opening = false; - if (newFeedModel == null) return; - openPostDialog(newFeedModel, profilePicView, mainPostImage, position); - }).execute(); + graphQLService.fetchPost(feedModel.getCode(), new ServiceCallback() { + @Override + public void onSuccess(final Media newFeedModel) { + opening = false; + if (newFeedModel == null) return; + openPostDialog(newFeedModel, profilePicView, mainPostImage, position); + } + + @Override + public void onFailure(final Throwable t) { + opening = false; + Log.e(TAG, "Error", t); + } + }); return; } opening = true; diff --git a/app/src/main/java/awais/instagrabber/repositories/GraphQLRepository.java b/app/src/main/java/awais/instagrabber/repositories/GraphQLRepository.java index efbc1c9a..199e44b4 100644 --- a/app/src/main/java/awais/instagrabber/repositories/GraphQLRepository.java +++ b/app/src/main/java/awais/instagrabber/repositories/GraphQLRepository.java @@ -14,6 +14,9 @@ public interface GraphQLRepository { @GET("/{username}/?__a=1") Call getUser(@Path("username") String username); + @GET("/p/{shortcode}/?__a=1") + Call getPost(@Path("shortcode") String shortcode); + @GET("/explore/tags/{tag}/?__a=1") Call getTag(@Path("tag") String tag); diff --git a/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java b/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java index ddb6da6b..a686a621 100644 --- a/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java +++ b/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java @@ -357,6 +357,40 @@ public class GraphQLService extends BaseService { }); } + public void fetchPost(final String shortcode, + final ServiceCallback callback) { + final Call request = repository.getPost(shortcode); + request.enqueue(new Callback() { + @Override + public void onResponse(@NonNull final Call call, @NonNull final Response response) { + final String rawBody = response.body(); + if (rawBody == null) { + Log.e(TAG, "Error occurred while fetching gql post of " + shortcode); + callback.onSuccess(null); + return; + } + try { + final JSONObject body = new JSONObject(rawBody); + final JSONObject media = body.getJSONObject("graphql") + .getJSONObject("shortcode_media"); + callback.onSuccess(ResponseBodyUtils.parseGraphQLItem(media, null)); + } catch (JSONException e) { + Log.e(TAG, "onResponse", e); + if (callback != null) { + callback.onFailure(e); + } + } + } + + @Override + public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { + if (callback != null) { + callback.onFailure(t); + } + } + }); + } + public void fetchTag(final String tag, final ServiceCallback callback) { final Call request = repository.getTag(tag);