From 13cacf43f964af71865a192237fc694981236624 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Thu, 3 Sep 2020 02:02:31 +0900 Subject: [PATCH] Added post viewer fragment. Updated almost all places to use this Remaining places are SavedViewer and DirectMessageThreadFragment --- .../java/awais/instagrabber/MainHelper.java | 168 +++-- .../activities/MainActivityBackup.java | 8 +- .../instagrabber/activities/PostViewer.java | 193 +++--- .../activities/ProfileViewer.java | 92 +-- .../instagrabber/activities/SavedViewer.java | 27 +- .../adapters/PostViewAdapter.java | 77 +++ .../adapters/PostViewerChildAdapter.java | 203 +++++++ .../viewholder/PostViewerViewHolder.java | 199 ++++++ .../viewholder/feed/FeedItemViewHolder.java | 24 +- .../instagrabber/asyncs/DiscoverFetcher.java | 22 +- .../instagrabber/asyncs/FeedFetcher.java | 55 +- .../instagrabber/asyncs/LocationFetcher.java | 46 +- .../instagrabber/asyncs/PostFetcher.java | 6 +- .../instagrabber/asyncs/PostsFetcher.java | 33 +- .../DirectThreadBroadcaster.java | 2 +- .../instagrabber/asyncs/i/iPostFetcher.java | 109 +++- .../helpers/NestedScrollableHost.java | 112 ++++ .../helpers/RecyclerLazyLoader.java | 13 +- .../directdownload/DirectDownload.java | 2 +- .../directdownload/MultiDirectDialog.java | 2 +- .../fragments/HashTagFragment.java | 50 +- .../fragments/LocationFragment.java | 113 ++-- .../fragments/PostViewFragment.java | 287 +++++++++ .../fragments/PostViewFragmentBackup.java | 574 ++++++++++++++++++ .../fragments/StoryViewerFragment.java | 80 ++- .../DirectMessageInboxFragment.java | 16 +- .../DirectMessageThreadFragment.java | 6 +- .../fragments/main/DiscoverFragment.java | 42 +- .../fragments/main/FeedFragment.java | 96 +-- .../fragments/main/ProfileFragment.java | 498 ++++++++------- .../main/viewmodels/BasePostViewModel.java | 19 + .../viewmodels/DiscoverItemViewModel.java | 3 +- .../main/viewmodels/FeedViewModel.java | 3 +- .../main/viewmodels/PostsViewModel.java | 3 +- .../main/viewmodels/ViewerPostViewModel.java | 18 + .../instagrabber/interfaces/ItemGetter.java | 4 +- .../instagrabber/models/BasePostModel.java | 4 +- .../awais/instagrabber/models/FeedModel.java | 52 +- .../instagrabber/models/LocationModel.java | 29 +- .../instagrabber/models/ProfileModel.java | 4 + .../instagrabber/models/ViewerPostModel.java | 32 +- .../models/ViewerPostModelWrapper.java | 23 + .../{ItemGetType.java => PostItemType.java} | 0 .../services/LoggingInterceptor.java | 12 +- .../awais/instagrabber/utils/LocaleUtils.java | 4 +- .../main/res/layout/fragment_post_view.xml | 4 + app/src/main/res/layout/item_feed_bottom.xml | 5 +- app/src/main/res/layout/item_feed_top.xml | 4 +- .../main/res/layout/item_full_post_view.xml | 105 ++++ ..._viewer.xml => item_full_post_view_bk.xml} | 44 +- .../res/navigation/discover_nav_graph.xml | 20 +- .../main/res/navigation/feed_nav_graph.xml | 40 +- .../main/res/navigation/hashtag_nav_graph.xml | 15 + .../res/navigation/location_nav_graph.xml | 42 ++ .../res/navigation/post_view_nav_graph.xml | 67 ++ .../main/res/navigation/profile_nav_graph.xml | 25 +- 56 files changed, 2991 insertions(+), 745 deletions(-) create mode 100644 app/src/main/java/awais/instagrabber/adapters/PostViewAdapter.java create mode 100644 app/src/main/java/awais/instagrabber/adapters/PostViewerChildAdapter.java create mode 100644 app/src/main/java/awais/instagrabber/adapters/viewholder/PostViewerViewHolder.java create mode 100644 app/src/main/java/awais/instagrabber/customviews/helpers/NestedScrollableHost.java create mode 100644 app/src/main/java/awais/instagrabber/fragments/PostViewFragment.java create mode 100644 app/src/main/java/awais/instagrabber/fragments/PostViewFragmentBackup.java create mode 100644 app/src/main/java/awais/instagrabber/fragments/main/viewmodels/BasePostViewModel.java create mode 100644 app/src/main/java/awais/instagrabber/fragments/main/viewmodels/ViewerPostViewModel.java create mode 100644 app/src/main/java/awais/instagrabber/models/ViewerPostModelWrapper.java rename app/src/main/java/awais/instagrabber/models/enums/{ItemGetType.java => PostItemType.java} (100%) mode change 100755 => 100644 create mode 100644 app/src/main/res/layout/fragment_post_view.xml create mode 100644 app/src/main/res/layout/item_full_post_view.xml rename app/src/main/res/layout/{activity_viewer.xml => item_full_post_view_bk.xml} (85%) mode change 100755 => 100644 create mode 100644 app/src/main/res/navigation/location_nav_graph.xml create mode 100644 app/src/main/res/navigation/post_view_nav_graph.xml diff --git a/app/src/main/java/awais/instagrabber/MainHelper.java b/app/src/main/java/awais/instagrabber/MainHelper.java index 28c6a5b6..8c0e3661 100755 --- a/app/src/main/java/awais/instagrabber/MainHelper.java +++ b/app/src/main/java/awais/instagrabber/MainHelper.java @@ -88,8 +88,8 @@ import awais.instagrabber.models.ProfileModel; import awais.instagrabber.models.ViewerPostModel; import awais.instagrabber.models.enums.DownloadMethod; import awais.instagrabber.models.enums.IntentModelType; -import awais.instagrabber.models.enums.ItemGetType; import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.models.enums.PostItemType; import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.DataBox; import awais.instagrabber.utils.Utils; @@ -149,7 +149,12 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { if (autoloadPosts && hasNextPage) currentlyExecuting = new PostsFetcher( mainActivity.profileModel != null ? mainActivity.profileModel.getId() - : (mainActivity.hashtagModel != null ? mainActivity.userQuery : mainActivity.locationModel.getId()), endCursor, this) + : (mainActivity.hashtagModel != null + ? mainActivity.userQuery + : mainActivity.locationModel.getId()), + false, + endCursor, + this) .setUsername((isLocation || isHashtag) ? null : mainActivity.profileModel.getUsername()) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else { @@ -168,7 +173,8 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { private final FetchListener feedFetchListener = new FetchListener() { @Override public void doBefore() { - mainActivity.mainBinding.feedView.feedSwipeRefreshLayout.post(() -> mainActivity.mainBinding.feedView.feedSwipeRefreshLayout.setRefreshing(true)); + mainActivity.mainBinding.feedView.feedSwipeRefreshLayout + .post(() -> mainActivity.mainBinding.feedView.feedSwipeRefreshLayout.setRefreshing(true)); } @Override @@ -232,7 +238,8 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { feedAdapter.submitList(mainActivity.feedItems); feedAdapter.notifyItemRangeInserted(oldSize, result.length); - mainActivity.mainBinding.feedView.feedPosts.post(() -> mainActivity.mainBinding.feedView.feedPosts.setNestedScrollingEnabled(true)); + mainActivity.mainBinding.feedView.feedPosts + .post(() -> mainActivity.mainBinding.feedView.feedPosts.setNestedScrollingEnabled(true)); final PostModel feedPostModel = result[result.length - 1]; if (feedPostModel != null) { @@ -308,8 +315,9 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { private final MentionClickListener mentionClickListener = new MentionClickListener() { @Override public void onClick(final RamboTextView view, final String text, final boolean isHashtag, final boolean isLocation) { - new AlertDialog.Builder(mainActivity).setMessage(isHashtag ? R.string.comment_view_mention_hash_search : R.string.comment_view_mention_user_search) - .setTitle(text).setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.ok, (dialog, which) -> { + new AlertDialog.Builder(mainActivity) + .setMessage(isHashtag ? R.string.comment_view_mention_hash_search : R.string.comment_view_mention_user_search) + .setTitle(text).setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.ok, (dialog, which) -> { if (MainActivityBackup.scanHack != null) MainActivityBackup.scanHack.onResult(text); }).show(); } @@ -433,7 +441,9 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { } else { // this changes toolbar title mainActivity.mainBinding.toolbar.toolbar.setTitle(slideOffset >= 0.466 ? titleDiscover : - (mainActivity.userQuery == null ? resources.getString(R.string.app_name) : mainActivity.userQuery)); + (mainActivity.userQuery == null + ? resources.getString(R.string.app_name) + : mainActivity.userQuery)); imageTintList = ImageViewCompat.getImageTintList(iconFeed); alpha = imageTintList != null ? (imageTintList.getDefaultColor() & 0xFF_000000) >> 24 : 0; @@ -482,7 +492,8 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { collapsingToolbar = mainActivity.mainBinding.profileView.appBarLayout.getChildAt(0); mainActivity.mainBinding.profileView.mainPosts.setNestedScrollingEnabled(false); - mainActivity.mainBinding.profileView.highlightsList.setLayoutManager(new LinearLayoutManager(mainActivity, LinearLayoutManager.HORIZONTAL, false)); + mainActivity.mainBinding.profileView.highlightsList + .setLayoutManager(new LinearLayoutManager(mainActivity, LinearLayoutManager.HORIZONTAL, false)); mainActivity.mainBinding.profileView.highlightsList.setAdapter(mainActivity.highlightsAdapter); // int color = -1; @@ -554,7 +565,12 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { mainActivity.mainBinding.profileView.swipeRefreshLayout.setRefreshing(true); stopCurrentExecutor(); currentlyExecuting = new PostsFetcher(mainActivity.profileModel != null ? mainActivity.profileModel.getId() - : (mainActivity.hashtagModel != null ? mainActivity.userQuery : mainActivity.locationModel.getId()), endCursor, postsFetchListener) + : (mainActivity.hashtagModel != null + ? mainActivity.userQuery + : mainActivity.locationModel.getId()), + false, + endCursor, + postsFetchListener) .setUsername((isHashtag || isLocation) ? null : mainActivity.profileModel.getUsername()) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); endCursor = null; @@ -585,16 +601,16 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { switch (id) { case R.id.btnComments: mainActivity.startActivityForResult(new Intent(mainActivity, CommentsViewer.class) - .putExtra(Constants.EXTRAS_SHORTCODE, feedModel.getShortCode()) - .putExtra(Constants.EXTRAS_POST, feedModel.getPostId()) - .putExtra(Constants.EXTRAS_USER, feedModel.getProfileModel().getId()), 6969); + .putExtra(Constants.EXTRAS_SHORTCODE, feedModel.getShortCode()) + .putExtra(Constants.EXTRAS_POST, feedModel.getPostId()) + .putExtra(Constants.EXTRAS_USER, feedModel.getProfileModel().getId()), 6969); break; case R.id.viewStoryPost: mainActivity.startActivity(new Intent(mainActivity, PostViewer.class) - .putExtra(Constants.EXTRAS_INDEX, feedModel.getPosition()) - .putExtra(Constants.EXTRAS_POST, new PostModel(feedModel.getShortCode(), false)) - .putExtra(Constants.EXTRAS_TYPE, ItemGetType.FEED_ITEMS)); + .putExtra(Constants.EXTRAS_INDEX, feedModel.getPosition()) + .putExtra(Constants.EXTRAS_POST, new PostModel(feedModel.getShortCode(), false)) + .putExtra(Constants.EXTRAS_TYPE, PostItemType.FEED)); break; case R.id.btnDownload: @@ -656,8 +672,9 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { mainActivity.mainBinding.feedView.feedPosts.setHasFixedSize(true); mainActivity.mainBinding.feedView.feedPosts.setLayoutManager(layoutManager); mainActivity.mainBinding.feedView.feedPosts.setAdapter(feedAdapter = new FeedAdapter(clickListener, (view, text, isHashtag, isLocation) -> - new AlertDialog.Builder(mainActivity).setMessage(isHashtag ? R.string.comment_view_mention_hash_search : R.string.comment_view_mention_user_search) - .setTitle(text).setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.ok, (dialog, which) -> { + new AlertDialog.Builder(mainActivity) + .setMessage(isHashtag ? R.string.comment_view_mention_hash_search : R.string.comment_view_mention_user_search) + .setTitle(text).setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.ok, (dialog, which) -> { if (MainActivityBackup.scanHack != null) { mainActivity.mainBinding.drawerLayout.closeDrawers(); MainActivityBackup.scanHack.onResult(text); @@ -673,13 +690,14 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { new FeedFetcher(feedFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }); - mainActivity.mainBinding.feedView.feedPosts.addOnScrollListener(feedLazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { - if (feedHasNextPage) { - mainActivity.mainBinding.feedView.feedSwipeRefreshLayout.setRefreshing(true); - new FeedFetcher(feedEndCursor, feedFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - feedEndCursor = null; - } - })); + mainActivity.mainBinding.feedView.feedPosts + .addOnScrollListener(feedLazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { + if (feedHasNextPage) { + mainActivity.mainBinding.feedView.feedSwipeRefreshLayout.setRefreshing(true); + new FeedFetcher(feedEndCursor, feedFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + feedEndCursor = null; + } + })); if (SHOULD_AUTO_PLAY) { videoAwareRecyclerScroller = new VideoAwareRecyclerScroller(); @@ -753,13 +771,15 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { // return true; // })); - mainActivity.mainBinding.discoverPosts.addOnScrollListener(discoverLazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { - if (discoverHasMore) { - mainActivity.mainBinding.discoverSwipeRefreshLayout.setRefreshing(true); - new DiscoverFetcher(topic, discoverEndMaxId, rankToken, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - discoverEndMaxId = null; - } - })); + mainActivity.mainBinding.discoverPosts + .addOnScrollListener(discoverLazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { + if (discoverHasMore) { + mainActivity.mainBinding.discoverSwipeRefreshLayout.setRefreshing(true); + new DiscoverFetcher(topic, discoverEndMaxId, rankToken, discoverFetchListener, false) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + discoverEndMaxId = null; + } + })); } public void onIntent(final Intent intent) { @@ -795,12 +815,12 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { if (modelType == IntentModelType.POST) { mainActivity.startActivityForResult(new Intent(mainActivity, PostViewer.class) - .putExtra(Constants.EXTRAS_USER, mainActivity.userQuery) - .putExtra(Constants.EXTRAS_POST, new PostModel(modelText, false)), 9629); + .putExtra(Constants.EXTRAS_USER, mainActivity.userQuery) + .putExtra(Constants.EXTRAS_POST, new PostModel(modelText, false)), 9629); } else { mainActivity.addToStack(); mainActivity.userQuery = modelType == IntentModelType.HASHTAG ? ('#' + modelText) : - (modelType == IntentModelType.LOCATION ? modelText : ('@' + modelText)); + (modelType == IntentModelType.LOCATION ? modelText : ('@' + modelText)); onRefresh(); } } @@ -968,12 +988,12 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { if (isLoggedIn || settingsHelper.getBoolean(Constants.STORIESIG)) { new iStoryStatusFetcher(profileId, profileModel.getUsername(), false, false, - (!isLoggedIn && settingsHelper.getBoolean(Constants.STORIESIG)), false, - result -> { - mainActivity.storyModels = result; - if (result != null && result.length > 0) - mainActivity.mainBinding.profileView.mainProfileImage.setStoriesBorder(); - }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + (!isLoggedIn && settingsHelper.getBoolean(Constants.STORIESIG)), false, + result -> { + mainActivity.storyModels = result; + if (result != null && result.length > 0) + mainActivity.mainBinding.profileView.mainProfileImage.setStoriesBorder(); + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new HighlightsFetcher(profileId, (!isLoggedIn && settingsHelper.getBoolean(Constants.STORIESIG)), result -> { if (result != null && result.length > 0) { @@ -1096,7 +1116,8 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { span.setSpan(new StyleSpan(Typeface.BOLD), 0, followingCountStrLen, 0); mainActivity.mainBinding.profileView.mainFollowing.setText(span); - mainActivity.mainBinding.profileView.mainFullName.setText(Utils.isEmpty(profileModel.getName()) ? profileModel.getUsername() : profileModel.getName()); + mainActivity.mainBinding.profileView.mainFullName + .setText(Utils.isEmpty(profileModel.getName()) ? profileModel.getUsername() : profileModel.getName()); CharSequence biography = profileModel.getBiography(); mainActivity.mainBinding.profileView.mainBiography.setCaptionIsExpandable(true); @@ -1127,9 +1148,12 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { if (isLoggedIn) { final View.OnClickListener followClickListener = v -> mainActivity.startActivity(new Intent(mainActivity, FollowViewer.class) - .putExtra(Constants.EXTRAS_FOLLOWERS, v == mainActivity.mainBinding.profileView.mainFollowers) - .putExtra(Constants.EXTRAS_NAME, profileModel.getUsername()) - .putExtra(Constants.EXTRAS_ID, profileId)); + .putExtra(Constants.EXTRAS_FOLLOWERS, + v == mainActivity.mainBinding.profileView.mainFollowers) + .putExtra(Constants.EXTRAS_NAME, + profileModel.getUsername()) + .putExtra(Constants.EXTRAS_ID, + profileId)); mainActivity.mainBinding.profileView.mainFollowers.setOnClickListener(followersCount > 0 ? followClickListener : null); mainActivity.mainBinding.profileView.mainFollowing.setOnClickListener(followingCount > 0 ? followClickListener : null); @@ -1372,18 +1396,23 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { @Override public void onClick(final View v) { final String userIdFromCookie = Utils.getUserIdFromCookie(MainHelper.this.cookie); - final boolean isSelf = (isLoggedIn && mainActivity.profileModel != null) && userIdFromCookie != null && userIdFromCookie.equals(mainActivity.profileModel.getId()); + final boolean isSelf = (isLoggedIn && mainActivity.profileModel != null) && userIdFromCookie != null && userIdFromCookie + .equals(mainActivity.profileModel.getId()); if (!isLoggedIn && Utils.dataBox.getFavorite(mainActivity.userQuery) != null && v == mainActivity.mainBinding.profileView.btnFollow) { Utils.dataBox.delFavorite(new DataBox.FavoriteModel(mainActivity.userQuery, - Long.parseLong(Utils.dataBox.getFavorite(mainActivity.userQuery).split("/")[1]), - mainActivity.locationModel != null ? mainActivity.locationModel.getName() : mainActivity.userQuery.replaceAll("^@", ""))); + Long.parseLong(Utils.dataBox.getFavorite(mainActivity.userQuery).split("/")[1]), + mainActivity.locationModel != null + ? mainActivity.locationModel.getName() + : mainActivity.userQuery.replaceAll("^@", ""))); onRefresh(); } else if (!isLoggedIn && (v == mainActivity.mainBinding.profileView.btnFollow || v == mainActivity.mainBinding.profileView.btnFollowTag)) { Utils.dataBox.addFavorite(new DataBox.FavoriteModel(mainActivity.userQuery, System.currentTimeMillis(), - mainActivity.locationModel != null ? mainActivity.locationModel.getName() : mainActivity.userQuery.replaceAll("^@", ""))); + mainActivity.locationModel != null + ? mainActivity.locationModel.getName() + : mainActivity.userQuery.replaceAll("^@", ""))); onRefresh(); } else if (v == mainActivity.mainBinding.profileView.btnFollow) { new ProfileAction().execute("follow"); @@ -1395,18 +1424,18 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { new ProfileAction().execute("followtag"); } else if (v == mainActivity.mainBinding.profileView.btnTagged || v == mainActivity.mainBinding.profileView.btnRestrict) { mainActivity.startActivity(new Intent(mainActivity, SavedViewer.class) - .putExtra(Constants.EXTRAS_INDEX, "%" + mainActivity.profileModel.getId()) - .putExtra(Constants.EXTRAS_USER, "@" + mainActivity.profileModel.getUsername()) + .putExtra(Constants.EXTRAS_INDEX, "%" + mainActivity.profileModel.getId()) + .putExtra(Constants.EXTRAS_USER, "@" + mainActivity.profileModel.getUsername()) ); } else if (v == mainActivity.mainBinding.profileView.btnSaved) { mainActivity.startActivity(new Intent(mainActivity, SavedViewer.class) - .putExtra(Constants.EXTRAS_INDEX, "$" + mainActivity.profileModel.getId()) - .putExtra(Constants.EXTRAS_USER, "@" + mainActivity.profileModel.getUsername()) + .putExtra(Constants.EXTRAS_INDEX, "$" + mainActivity.profileModel.getId()) + .putExtra(Constants.EXTRAS_USER, "@" + mainActivity.profileModel.getUsername()) ); } else if (v == mainActivity.mainBinding.profileView.btnLiked) { mainActivity.startActivity(new Intent(mainActivity, SavedViewer.class) - .putExtra(Constants.EXTRAS_INDEX, "^" + mainActivity.profileModel.getId()) - .putExtra(Constants.EXTRAS_USER, "@" + mainActivity.profileModel.getUsername()) + .putExtra(Constants.EXTRAS_INDEX, "^" + mainActivity.profileModel.getId()) + .putExtra(Constants.EXTRAS_USER, "@" + mainActivity.profileModel.getUsername()) ); } } @@ -1418,12 +1447,31 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { protected Void doInBackground(String... rawAction) { action = rawAction[0]; - final String url = "https://www.instagram.com/web/" + (action.equals("followtag") && mainActivity.hashtagModel != null ? "tags/" + (mainActivity.hashtagModel.getFollowing() ? "unfollow/" : "follow/") + mainActivity.hashtagModel.getName() + "/" : (action.equals("restrict") && mainActivity.profileModel != null ? "restrict_action" : "friendships/" + mainActivity.profileModel.getId()) + "/" + (action.equals("follow") ? - mainActivity.profileModel.getFollowing() || mainActivity.profileModel.getRequested() - ? "unfollow/" : "follow/" : - action.equals("restrict") ? - mainActivity.profileModel.getRestricted() ? "unrestrict/" : "restrict/" : - mainActivity.profileModel.getBlocked() ? "unblock/" : "block/")); + final String url = "https://www.instagram.com/web/" + (action.equals("followtag") && mainActivity.hashtagModel != null + ? "tags/" + (mainActivity.hashtagModel.getFollowing() + ? "unfollow/" + : "follow/") + mainActivity.hashtagModel.getName() + "/" + : (action.equals("restrict") && mainActivity.profileModel != null + ? "restrict_action" + : "friendships/" + mainActivity.profileModel.getId()) + "/" + (action.equals( + "follow") ? + mainActivity.profileModel + .getFollowing() || mainActivity.profileModel + .getRequested() + ? "unfollow/" + : "follow/" : + action.equals( + "restrict") + ? + mainActivity.profileModel + .getRestricted() + ? "unrestrict/" + : "restrict/" + : + mainActivity.profileModel + .getBlocked() + ? "unblock/" + : "block/")); try { final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); urlConnection.setRequestMethod("POST"); diff --git a/app/src/main/java/awais/instagrabber/activities/MainActivityBackup.java b/app/src/main/java/awais/instagrabber/activities/MainActivityBackup.java index cc3b598a..822b8878 100644 --- a/app/src/main/java/awais/instagrabber/activities/MainActivityBackup.java +++ b/app/src/main/java/awais/instagrabber/activities/MainActivityBackup.java @@ -57,7 +57,7 @@ import awais.instagrabber.models.ProfileModel; import awais.instagrabber.models.StoryModel; import awais.instagrabber.models.SuggestionModel; import awais.instagrabber.models.enums.DownloadMethod; -import awais.instagrabber.models.enums.ItemGetType; +import awais.instagrabber.models.enums.PostItemType; import awais.instagrabber.models.enums.SuggestionType; import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.DataBox; @@ -148,9 +148,9 @@ public final class MainActivityBackup extends BaseLanguageActivity { isLoggedIn = !Utils.isEmpty(cookie) && Utils.getUserIdFromCookie(cookie) != null; itemGetter = itemGetType -> { - if (itemGetType == ItemGetType.MAIN_ITEMS) return allItems; - if (itemGetType == ItemGetType.DISCOVER_ITEMS) return discoverItems; - if (itemGetType == ItemGetType.FEED_ITEMS) return feedItems; + if (itemGetType == PostItemType.MAIN) return allItems; + if (itemGetType == PostItemType.DISCOVER) return discoverItems; + if (itemGetType == PostItemType.FEED) return feedItems; return null; }; diff --git a/app/src/main/java/awais/instagrabber/activities/PostViewer.java b/app/src/main/java/awais/instagrabber/activities/PostViewer.java index 7632e810..e94d235c 100755 --- a/app/src/main/java/awais/instagrabber/activities/PostViewer.java +++ b/app/src/main/java/awais/instagrabber/activities/PostViewer.java @@ -6,7 +6,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.content.res.Resources; -import android.graphics.drawable.Drawable; +import android.graphics.drawable.Animatable; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; @@ -32,20 +32,17 @@ import androidx.core.view.GestureDetectorCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.load.DataSource; -import com.bumptech.glide.load.engine.GlideException; -import com.bumptech.glide.request.RequestListener; -import com.bumptech.glide.request.target.Target; +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.drawee.controller.BaseControllerListener; +import com.facebook.imagepipeline.image.ImageInfo; +import com.facebook.imagepipeline.request.ImageRequest; +import com.facebook.imagepipeline.request.ImageRequestBuilder; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSourceEventListener; import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; -import org.json.JSONObject; - import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; @@ -60,7 +57,7 @@ import awais.instagrabber.asyncs.ProfileFetcher; import awais.instagrabber.asyncs.i.iPostFetcher; import awais.instagrabber.customviews.CommentMentionClickSpan; import awais.instagrabber.customviews.helpers.SwipeGestureListener; -import awais.instagrabber.databinding.ActivityViewerBinding; +import awais.instagrabber.databinding.ItemFullPostViewBkBinding; import awais.instagrabber.interfaces.FetchListener; import awais.instagrabber.interfaces.SwipeEvent; import awais.instagrabber.models.BasePostModel; @@ -68,16 +65,17 @@ import awais.instagrabber.models.PostModel; import awais.instagrabber.models.ProfileModel; import awais.instagrabber.models.ViewerPostModel; import awais.instagrabber.models.enums.DownloadMethod; -import awais.instagrabber.models.enums.ItemGetType; import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.models.enums.PostItemType; import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Utils; import static awais.instagrabber.utils.Utils.settingsHelper; +@Deprecated public final class PostViewer extends BaseLanguageActivity { - private ActivityViewerBinding viewerBinding; - private String url, prevUsername, commentsEndCursor; + private ItemFullPostViewBkBinding viewerBinding; + private String url, prevUsername; private ProfileModel profileModel; private BasePostModel postModel; private ViewerPostModel viewerPostModel; @@ -90,7 +88,7 @@ public final class PostViewer extends BaseLanguageActivity { private Resources resources; private boolean session = false, isFromShare, liked, saved, ok = false; private int slidePos = 0, lastSlidePos = 0; - private ItemGetType itemGetType; + private PostItemType postItemType; @SuppressLint("ClickableViewAccessibility") final View.OnTouchListener gestureTouchListener = new View.OnTouchListener() { private float startX; @@ -117,13 +115,13 @@ public final class PostViewer extends BaseLanguageActivity { } }; private final DialogInterface.OnClickListener profileDialogListener = (dialog, which) -> { - final String username = viewerPostModel.getUsername(); + final String username = viewerPostModel.getProfileModel().getUsername(); if (which == 0) { searchUsername(username); } else if (profileModel != null && which == 1) { startActivity(new Intent(this, ProfilePicViewer.class) - .putExtra(Constants.EXTRAS_PROFILE, profileModel)); + .putExtra(Constants.EXTRAS_PROFILE, profileModel)); } }; private final View.OnClickListener onClickListener = new View.OnClickListener() { @@ -131,7 +129,8 @@ public final class PostViewer extends BaseLanguageActivity { public void onClick(final View v) { if (v == viewerBinding.topPanel.ivProfilePic) { new AlertDialog.Builder(PostViewer.this).setAdapter(profileDialogAdapter, profileDialogListener) - .setNeutralButton(R.string.cancel, null).setTitle(viewerPostModel.getUsername()).show(); + .setNeutralButton(R.string.cancel, null) + .setTitle(viewerPostModel.getProfileModel().getUsername()).show(); } else if (v == viewerBinding.ivToggleFullScreen) { toggleFullscreen(); @@ -185,7 +184,6 @@ public final class PostViewer extends BaseLanguageActivity { ActivityCompat.requestPermissions(this, Utils.PERMS, 8020); }; private final PostsMediaAdapter mediaAdapter = new PostsMediaAdapter(null, onClickListener); - private RequestManager glideRequestManager; private LinearLayout.LayoutParams containerLayoutParams; private final FetchListener pfl = result -> { if (result == null || result.length < 1) { @@ -208,25 +206,28 @@ public final class PostViewer extends BaseLanguageActivity { viewerCaptionParent.setOnTouchListener(gestureTouchListener); viewerBinding.playerView.setOnTouchListener(gestureTouchListener); - viewerBinding.imageViewer.setOnSingleFlingListener((e1, e2, velocityX, velocityY) -> { - final float diffX = e2.getX() - e1.getX(); - if (Math.abs(diffX) > Math.abs(e2.getY() - e1.getY()) && Math.abs(diffX) > SwipeGestureListener.SWIPE_THRESHOLD - && Math.abs(velocityX) > SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD) { - swipeEvent.onSwipe(diffX > 0); - return true; - } - return false; - }); + // viewerBinding.imageViewer.setOnSingleFlingListener((e1, e2, velocityX, velocityY) -> { + // final float diffX = e2.getX() - e1.getX(); + // if (Math.abs(diffX) > Math.abs(e2.getY() - e1.getY()) && Math.abs(diffX) > SwipeGestureListener.SWIPE_THRESHOLD + // && Math.abs(velocityX) > SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD) { + // swipeEvent.onSwipe(diffX > 0); + // return true; + // } + // return false; + // }); final long commentsCount = viewerPostModel.getCommentsCount(); viewerBinding.bottomPanel.commentsCount.setText(String.valueOf(commentsCount)); viewerBinding.bottomPanel.btnComments.setVisibility(View.VISIBLE); viewerBinding.bottomPanel.btnComments.setOnClickListener(v -> - startActivityForResult(new Intent(this, CommentsViewer.class) - .putExtra(Constants.EXTRAS_SHORTCODE, postModel.getShortCode()) - .putExtra(Constants.EXTRAS_POST, viewerPostModel.getPostId()) - .putExtra(Constants.EXTRAS_USER, postUserId), 6969)); + startActivityForResult(new Intent(this, CommentsViewer.class) + .putExtra(Constants.EXTRAS_SHORTCODE, + postModel.getShortCode()) + .putExtra(Constants.EXTRAS_POST, + viewerPostModel.getPostId()) + .putExtra(Constants.EXTRAS_USER, postUserId), + 6969)); viewerBinding.bottomPanel.btnComments.setClickable(true); viewerBinding.bottomPanel.btnComments.setEnabled(true); @@ -241,8 +242,8 @@ public final class PostViewer extends BaseLanguageActivity { } } - setupPostInfoBar("@" + viewerPostModel.getUsername(), viewerPostModel.getItemType(), - viewerPostModel.getLocationName(), viewerPostModel.getLocation()); + setupPostInfoBar("@" + viewerPostModel.getProfileModel().getUsername(), viewerPostModel.getItemType(), + viewerPostModel.getLocationName(), viewerPostModel.getLocation()); postCaption = postModel.getPostCaption(); viewerCaptionParent.setVisibility(View.VISIBLE); @@ -255,11 +256,9 @@ public final class PostViewer extends BaseLanguageActivity { @Override protected void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - viewerBinding = ActivityViewerBinding.inflate(getLayoutInflater()); + viewerBinding = ItemFullPostViewBkBinding.inflate(getLayoutInflater()); setContentView(viewerBinding.getRoot()); - glideRequestManager = Glide.with(this); - final Intent intent = getIntent(); if (intent == null || !intent.hasExtra(Constants.EXTRAS_POST) || (postModel = (PostModel) intent.getSerializableExtra(Constants.EXTRAS_POST)) == null) { @@ -270,7 +269,7 @@ public final class PostViewer extends BaseLanguageActivity { containerLayoutParams = (LinearLayout.LayoutParams) viewerBinding.container.getLayoutParams(); if (intent.hasExtra(Constants.EXTRAS_TYPE)) - itemGetType = (ItemGetType) intent.getSerializableExtra(Constants.EXTRAS_TYPE); + postItemType = (PostItemType) intent.getSerializableExtra(Constants.EXTRAS_TYPE); resources = getResources(); @@ -295,7 +294,7 @@ public final class PostViewer extends BaseLanguageActivity { viewerBinding.btnDownload.setOnClickListener(downloadClickListener); profileDialogAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, - new String[]{resources.getString(R.string.open_profile), resources.getString(R.string.view_pfp)}); + new String[]{resources.getString(R.string.open_profile), resources.getString(R.string.view_pfp)}); postModel.setPosition(intent.getIntExtra(Constants.EXTRAS_INDEX, -1)); @@ -314,17 +313,17 @@ public final class PostViewer extends BaseLanguageActivity { swipeEvent = isRight -> { final List itemGetterItems; - final boolean isMainSwipe; + final boolean isSwipeable; - if (itemGetType == ItemGetType.SAVED_ITEMS && SavedViewer.itemGetter != null) { - itemGetterItems = SavedViewer.itemGetter.get(itemGetType); - isMainSwipe = !(itemGetterItems.size() < 1 || itemGetType == ItemGetType.SAVED_ITEMS && isFromShare); - } else if (itemGetType != null && MainActivityBackup.itemGetter != null) { - itemGetterItems = MainActivityBackup.itemGetter.get(itemGetType); - isMainSwipe = !(itemGetterItems.size() < 1 || itemGetType == ItemGetType.MAIN_ITEMS && isFromShare); + if (postItemType == PostItemType.SAVED && SavedViewer.itemGetter != null) { + itemGetterItems = SavedViewer.itemGetter.get(postItemType); + isSwipeable = !(itemGetterItems.size() < 1 || postItemType == PostItemType.SAVED && isFromShare); + } else if (postItemType != null && MainActivityBackup.itemGetter != null) { + itemGetterItems = MainActivityBackup.itemGetter.get(postItemType); + isSwipeable = !(itemGetterItems.size() < 1 || postItemType == PostItemType.MAIN && isFromShare); } else { itemGetterItems = null; - isMainSwipe = false; + isSwipeable = false; } final BasePostModel[] basePostModels = mediaAdapter.getPostModels(); @@ -334,7 +333,7 @@ public final class PostViewer extends BaseLanguageActivity { if (isRight) { --slidePos; - if (!isMainSwipe && slidePos < 0) slidePos = 0; + if (!isSwipeable && slidePos < 0) slidePos = 0; if (slides > 0 && slidePos >= 0) { if (basePostModels[slidePos] instanceof ViewerPostModel) { viewerPostModel = (ViewerPostModel) basePostModels[slidePos]; @@ -342,10 +341,10 @@ public final class PostViewer extends BaseLanguageActivity { refreshPost(); return; } - if (isMainSwipe && --position < 0) position = itemGetterItems.size() - 1; + if (isSwipeable && --position < 0) position = itemGetterItems.size() - 1; } else { ++slidePos; - if (!isMainSwipe && slidePos >= slides) slidePos = slides - 1; + if (!isSwipeable && slidePos >= slides) slidePos = slides - 1; if (slides > 0 && slidePos < slides) { if (basePostModels[slidePos] instanceof ViewerPostModel) { viewerPostModel = (ViewerPostModel) basePostModels[slidePos]; @@ -353,10 +352,10 @@ public final class PostViewer extends BaseLanguageActivity { refreshPost(); return; } - if (isMainSwipe && ++position >= itemGetterItems.size()) position = 0; + if (isSwipeable && ++position >= itemGetterItems.size()) position = 0; } - if (isMainSwipe) { + if (isSwipeable) { slidePos = 0; ok = false; Log.d("AWAISKING_APP", "swipe left <<< post[" + position + "]: " + postModel + " -- " + slides); @@ -386,8 +385,7 @@ public final class PostViewer extends BaseLanguageActivity { viewerBinding.playerView.setVisibility(View.GONE); viewerBinding.playerView.setPlayer(null); - viewerBinding.imageViewer.setImageResource(0); - viewerBinding.imageViewer.setImageDrawable(null); + viewerBinding.imageViewer.setController(null); if (postModel.getShortCode() != null) new PostFetcher(postModel.getShortCode(), pfl).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -408,7 +406,7 @@ public final class PostViewer extends BaseLanguageActivity { viewerBinding.bottomPanel.btnMute.setVisibility(View.VISIBLE); viewerBinding.progressView.setVisibility(View.GONE); viewerBinding.imageViewer.setVisibility(View.GONE); - viewerBinding.imageViewer.setImageDrawable(null); + viewerBinding.imageViewer.setController(null); if (viewerPostModel.getVideoViews() > -1) { viewsContainer.setVisibility(View.VISIBLE); @@ -426,22 +424,36 @@ public final class PostViewer extends BaseLanguageActivity { .createMediaSource(Uri.parse(url)); mediaSource.addEventListener(new Handler(), new MediaSourceEventListener() { @Override - public void onLoadCompleted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + public void onLoadCompleted(final int windowIndex, + @Nullable final MediaSource.MediaPeriodId mediaPeriodId, + final LoadEventInfo loadEventInfo, + final MediaLoadData mediaLoadData) { viewerBinding.progressView.setVisibility(View.GONE); } @Override - public void onLoadStarted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + public void onLoadStarted(final int windowIndex, + @Nullable final MediaSource.MediaPeriodId mediaPeriodId, + final LoadEventInfo loadEventInfo, + final MediaLoadData mediaLoadData) { viewerBinding.progressView.setVisibility(View.VISIBLE); } @Override - public void onLoadCanceled(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + public void onLoadCanceled(final int windowIndex, + @Nullable final MediaSource.MediaPeriodId mediaPeriodId, + final LoadEventInfo loadEventInfo, + final MediaLoadData mediaLoadData) { viewerBinding.progressView.setVisibility(View.GONE); } @Override - public void onLoadError(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData, final IOException error, final boolean wasCanceled) { + public void onLoadError(final int windowIndex, + @Nullable final MediaSource.MediaPeriodId mediaPeriodId, + final LoadEventInfo loadEventInfo, + final MediaLoadData mediaLoadData, + final IOException error, + final boolean wasCanceled) { viewerBinding.progressView.setVisibility(View.GONE); } }); @@ -459,26 +471,31 @@ public final class PostViewer extends BaseLanguageActivity { viewerBinding.progressView.setVisibility(View.VISIBLE); viewerBinding.bottomPanel.btnMute.setVisibility(View.GONE); viewerBinding.bottomPanel.btnDownload.setVisibility(View.VISIBLE); - - viewerBinding.imageViewer.setImageDrawable(null); viewerBinding.imageViewer.setVisibility(View.VISIBLE); - viewerBinding.imageViewer.setZoomable(true); - viewerBinding.imageViewer.setZoomTransitionDuration(420); - viewerBinding.imageViewer.setMaximumScale(7.2f); - glideRequestManager.load(url).listener(new RequestListener() { - @Override - public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target target, final boolean isFirstResource) { - viewerBinding.progressView.setVisibility(View.GONE); - return false; - } + final ImageRequest requestBuilder = ImageRequestBuilder.newBuilderWithSource(Uri.parse(url)) + .setLocalThumbnailPreviewsEnabled(true) + .setProgressiveRenderingEnabled(true) + .build(); + viewerBinding.imageViewer.setController( + Fresco.newDraweeControllerBuilder() + .setImageRequest(requestBuilder) + .setOldController(viewerBinding.imageViewer.getController()) + .setLowResImageRequest(ImageRequest.fromUri(url)) + .setControllerListener(new BaseControllerListener() { - @Override - public boolean onResourceReady(final Drawable resource, final Object model, final Target target, final DataSource dataSource, final boolean isFirstResource) { - viewerBinding.progressView.setVisibility(View.GONE); - return false; - } - }).into(viewerBinding.imageViewer); + @Override + public void onFailure(final String id, final Throwable throwable) { + viewerBinding.progressView.setVisibility(View.GONE); + } + + @Override + public void onFinalImageSet(final String id, final ImageInfo imageInfo, final Animatable animatable) { + viewerBinding.progressView.setVisibility(View.GONE); + } + }) + .build() + ); } private void showDownloadDialog() { @@ -502,15 +519,17 @@ public final class PostViewer extends BaseLanguageActivity { } if (postModels.size() > 0) - Utils.batchDownload(this, viewerPostModel.getUsername(), DownloadMethod.DOWNLOAD_POST_VIEWER, postModels); + Utils.batchDownload(this, viewerPostModel.getProfileModel().getUsername(), DownloadMethod.DOWNLOAD_POST_VIEWER, postModels); }; new AlertDialog.Builder(this).setTitle(R.string.post_viewer_download_dialog_title) .setMessage(R.string.post_viewer_download_message) - .setNeutralButton(R.string.post_viewer_download_session, clickListener).setPositiveButton(R.string.post_viewer_download_current, clickListener) + .setNeutralButton(R.string.post_viewer_download_session, clickListener) + .setPositiveButton(R.string.post_viewer_download_current, clickListener) .setNegativeButton(R.string.post_viewer_download_album, clickListener).show(); } else { - Utils.batchDownload(this, viewerPostModel.getUsername(), DownloadMethod.DOWNLOAD_POST_VIEWER, Collections.singletonList(viewerPostModel)); + Utils.batchDownload(this, viewerPostModel.getProfileModel().getUsername(), DownloadMethod.DOWNLOAD_POST_VIEWER, + Collections.singletonList(viewerPostModel)); } } @@ -582,9 +601,9 @@ public final class PostViewer extends BaseLanguageActivity { viewerBinding.bottomPanel.viewerCaption.setMentionClickListener(null); viewerBinding.bottomPanel.viewerCaption.setText(postCaption); } - - setupPostInfoBar("@" + viewerPostModel.getUsername(), viewerPostModel.getItemType(), - viewerPostModel.getLocationName(), viewerPostModel.getLocation()); + + setupPostInfoBar("@" + viewerPostModel.getProfileModel().getUsername(), viewerPostModel.getItemType(), + viewerPostModel.getLocationName(), viewerPostModel.getLocation()); if (postModel instanceof PostModel) { final PostModel postModel = (PostModel) this.postModel; @@ -682,7 +701,9 @@ public final class PostViewer extends BaseLanguageActivity { sharingIntent.setType("text/plain"); sharingIntent.putExtra(Intent.EXTRA_TEXT, "https://instagram.com/p/" + postShortCode); startActivity(Intent.createChooser(sharingIntent, - (result.isPrivate()) ? getString(R.string.share_private_post) : getString(R.string.share_public_post))); + (result.isPrivate()) + ? getString(R.string.share_private_post) + : getString(R.string.share_public_post))); }); } } @@ -691,7 +712,7 @@ public final class PostViewer extends BaseLanguageActivity { } final String titlePrefix = resources.getString(mediaItemType == MediaItemType.MEDIA_TYPE_VIDEO ? - R.string.post_viewer_video_post : R.string.post_viewer_image_post); + R.string.post_viewer_video_post : R.string.post_viewer_image_post); if (Utils.isEmpty(from)) viewerBinding.topPanel.title.setText(titlePrefix); else { final int titleLen = from.length(); @@ -731,15 +752,15 @@ public final class PostViewer extends BaseLanguageActivity { protected Void doInBackground(String... rawAction) { action = rawAction[0]; final String url = "https://www.instagram.com/web/" + action + "/" + postModel.getPostId() + "/" + (action == "save" ? - (saved ? "unsave/" : "save/") : - (liked ? "unlike/" : "like/")); + (saved ? "unsave/" : "save/") : + (liked ? "unlike/" : "like/")); try { final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); urlConnection.setRequestMethod("POST"); urlConnection.setUseCaches(false); urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT); urlConnection.setRequestProperty("x-csrftoken", - settingsHelper.getString(Constants.COOKIE).split("csrftoken=")[1].split(";")[0]); + settingsHelper.getString(Constants.COOKIE).split("csrftoken=")[1].split(";")[0]); urlConnection.connect(); if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { ok = true; diff --git a/app/src/main/java/awais/instagrabber/activities/ProfileViewer.java b/app/src/main/java/awais/instagrabber/activities/ProfileViewer.java index c8f8a3de..5dd49e18 100755 --- a/app/src/main/java/awais/instagrabber/activities/ProfileViewer.java +++ b/app/src/main/java/awais/instagrabber/activities/ProfileViewer.java @@ -109,7 +109,10 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe if (autoloadPosts && hasNextPage) currentlyExecuting = new PostsFetcher( profileModel != null ? profileModel.getId() - : (hashtagModel != null ? ("#" + hashtagModel.getName()) : locationModel.getId()), endCursor, this) + : (hashtagModel != null ? ("#" + hashtagModel.getName()) : locationModel.getId()), + false, + endCursor, + this) .setUsername((isLocation || isHashtag) ? null : profileModel.getUsername()) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else { @@ -138,7 +141,7 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe if (tag instanceof HighlightModel) { final HighlightModel highlightModel = (HighlightModel) tag; new iStoryStatusFetcher(highlightModel.getId(), null, false, false, - (!isLoggedIn && Utils.settingsHelper.getBoolean(Constants.STORIESIG)), true, result -> { + (!isLoggedIn && Utils.settingsHelper.getBoolean(Constants.STORIESIG)), true, result -> { if (result != null && result.length > 0) { // startActivity(new Intent(ProfileViewer.this, StoryViewer.class) // .putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", "")) @@ -180,12 +183,14 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe resources = getResources(); profileDialogAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, - new String[]{resources.getString(R.string.view_pfp), resources.getString(R.string.show_stories)}); + new String[]{resources.getString(R.string.view_pfp), resources.getString(R.string.show_stories)}); profileDialogListener = (dialog, which) -> { final Intent newintent; if (which == 0 || storyModels == null || storyModels.length < 1) { newintent = new Intent(this, ProfilePicViewer.class).putExtra( - ((hashtagModel != null) ? Constants.EXTRAS_HASHTAG : (locationModel != null ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_PROFILE)), + ((hashtagModel != null) + ? Constants.EXTRAS_HASHTAG + : (locationModel != null ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_PROFILE)), ((hashtagModel != null) ? hashtagModel : (locationModel != null ? locationModel : profileModel))); } // else @@ -239,7 +244,11 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe profileBinding.profileView.swipeRefreshLayout.setRefreshing(true); stopCurrentExecutor(); currentlyExecuting = new PostsFetcher(profileModel != null ? profileModel.getId() - : (hashtagModel != null ? ("#" + hashtagModel.getName()) : locationModel.getId()), endCursor, postsFetchListener) + : (hashtagModel != null + ? ("#" + hashtagModel.getName()) + : locationModel.getId()), + isHashtag, + endCursor, postsFetchListener) .setUsername((isHashtag || isLocation) ? null : profileModel.getUsername()) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); endCursor = null; @@ -429,12 +438,12 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe if (isLoggedIn || Utils.settingsHelper.getBoolean(Constants.STORIESIG)) { new iStoryStatusFetcher(profileId, profileModel.getUsername(), false, false, - (!isLoggedIn && Utils.settingsHelper.getBoolean(Constants.STORIESIG)), false, - stories -> { - storyModels = stories; - if (stories != null && stories.length > 0) - profileBinding.profileView.mainProfileImage.setStoriesBorder(); - }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + (!isLoggedIn && Utils.settingsHelper.getBoolean(Constants.STORIESIG)), false, + stories -> { + storyModels = stories; + if (stories != null && stories.length > 0) + profileBinding.profileView.mainProfileImage.setStoriesBorder(); + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new HighlightsFetcher(profileId, (!isLoggedIn && Utils.settingsHelper.getBoolean(Constants.STORIESIG)), hls -> { if (hls != null && hls.length > 0) { @@ -555,7 +564,8 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe span.setSpan(new StyleSpan(Typeface.BOLD), 0, followingCountStrLen, 0); profileBinding.profileView.mainFollowing.setText(span); - profileBinding.profileView.mainFullName.setText(Utils.isEmpty(profileModel.getName()) ? profileModel.getUsername() : profileModel.getName()); + profileBinding.profileView.mainFullName + .setText(Utils.isEmpty(profileModel.getName()) ? profileModel.getUsername() : profileModel.getName()); CharSequence biography = profileModel.getBiography(); profileBinding.profileView.mainBiography.setCaptionIsExpandable(true); @@ -586,9 +596,11 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe if (isLoggedIn) { final View.OnClickListener followClickListener = v -> startActivity(new Intent(ProfileViewer.this, FollowViewer.class) - .putExtra(Constants.EXTRAS_FOLLOWERS, v == profileBinding.profileView.mainFollowers) - .putExtra(Constants.EXTRAS_NAME, profileModel.getUsername()) - .putExtra(Constants.EXTRAS_ID, profileId)); + .putExtra(Constants.EXTRAS_FOLLOWERS, + v == profileBinding.profileView.mainFollowers) + .putExtra(Constants.EXTRAS_NAME, + profileModel.getUsername()) + .putExtra(Constants.EXTRAS_ID, profileId)); profileBinding.profileView.mainFollowers.setOnClickListener(followersCount > 0 ? followClickListener : null); profileBinding.profileView.mainFollowing.setOnClickListener(followingCount > 0 ? followClickListener : null); @@ -749,12 +761,16 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe favouriteAction.setOnMenuItemClickListener(item -> { if (Utils.dataBox.getFavorite(userQuery) == null) { Utils.dataBox.addFavorite(new DataBox.FavoriteModel(userQuery, System.currentTimeMillis(), - locationModel != null ? locationModel.getName() : userQuery.replaceAll("^@", ""))); + locationModel != null + ? locationModel.getName() + : userQuery.replaceAll("^@", ""))); favouriteAction.setIcon(R.drawable.ic_like); } else { Utils.dataBox.delFavorite(new DataBox.FavoriteModel(userQuery, - Long.parseLong(Utils.dataBox.getFavorite(userQuery).split("/")[1]), - locationModel != null ? locationModel.getName() : userQuery.replaceAll("^@", ""))); + Long.parseLong(Utils.dataBox.getFavorite(userQuery).split("/")[1]), + locationModel != null + ? locationModel.getName() + : userQuery.replaceAll("^@", ""))); favouriteAction.setIcon(R.drawable.ic_not_liked); } return true; @@ -834,12 +850,16 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe final boolean iamme = (isLoggedIn && profileModel != null) && Utils.getUserIdFromCookie(cookie).equals(profileModel.getId()); if (!isLoggedIn && Utils.dataBox.getFavorite(userQuery) != null && v == profileBinding.profileView.btnFollow) { Utils.dataBox.delFavorite(new DataBox.FavoriteModel(userQuery, - Long.parseLong(Utils.dataBox.getFavorite(userQuery).split("/")[1]), - locationModel != null ? locationModel.getName() : userQuery.replaceAll("^@", ""))); + Long.parseLong(Utils.dataBox.getFavorite(userQuery).split("/")[1]), + locationModel != null + ? locationModel.getName() + : userQuery.replaceAll("^@", ""))); onRefresh(); } else if (!isLoggedIn && (v == profileBinding.profileView.btnFollow || v == profileBinding.profileView.btnFollowTag)) { Utils.dataBox.addFavorite(new DataBox.FavoriteModel(userQuery, System.currentTimeMillis(), - locationModel != null ? locationModel.getName() : userQuery.replaceAll("^@", ""))); + locationModel != null + ? locationModel.getName() + : userQuery.replaceAll("^@", ""))); onRefresh(); } else if (v == profileBinding.profileView.btnFollow) { new ProfileAction().execute("follow"); @@ -851,18 +871,18 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe new ProfileAction().execute("followtag"); } else if (v == profileBinding.profileView.btnTagged || (v == profileBinding.profileView.btnRestrict && !isLoggedIn)) { startActivity(new Intent(ProfileViewer.this, SavedViewer.class) - .putExtra(Constants.EXTRAS_INDEX, "%" + profileModel.getId()) - .putExtra(Constants.EXTRAS_USER, "@" + profileModel.getUsername()) + .putExtra(Constants.EXTRAS_INDEX, "%" + profileModel.getId()) + .putExtra(Constants.EXTRAS_USER, "@" + profileModel.getUsername()) ); } else if (v == profileBinding.profileView.btnSaved) { startActivity(new Intent(ProfileViewer.this, SavedViewer.class) - .putExtra(Constants.EXTRAS_INDEX, "$" + profileModel.getId()) - .putExtra(Constants.EXTRAS_USER, "@" + profileModel.getUsername()) + .putExtra(Constants.EXTRAS_INDEX, "$" + profileModel.getId()) + .putExtra(Constants.EXTRAS_USER, "@" + profileModel.getUsername()) ); } else if (v == profileBinding.profileView.btnLiked) { startActivity(new Intent(ProfileViewer.this, SavedViewer.class) - .putExtra(Constants.EXTRAS_INDEX, "^" + profileModel.getId()) - .putExtra(Constants.EXTRAS_USER, "@" + profileModel.getUsername()) + .putExtra(Constants.EXTRAS_INDEX, "^" + profileModel.getId()) + .putExtra(Constants.EXTRAS_USER, "@" + profileModel.getUsername()) ); } } @@ -877,14 +897,16 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe final String url = "https://www.instagram.com/web/" + ((action.equals("followtag") && hashtagModel != null) ? ("tags/" + (hashtagModel.getFollowing() ? "unfollow/" : "follow/") + hashtagModel.getName() + "/") : ( - ((action.equals("restrict") && profileModel != null) ? "restrict_action" : ("friendships/" + profileModel.getId())) + "/" + - ((action.equals("follow") && profileModel != null) ? - ((profileModel.getFollowing() || - (!profileModel.getFollowing() && profileModel.getRequested())) - ? "unfollow/" : "follow/") : - ((action.equals("restrict") && profileModel != null) ? - (profileModel.getRestricted() ? "unrestrict/" : "restrict/") : - (profileModel.getBlocked() ? "unblock/" : "block/"))))); + ((action.equals("restrict") && profileModel != null) + ? "restrict_action" + : ("friendships/" + profileModel.getId())) + "/" + + ((action.equals("follow") && profileModel != null) ? + ((profileModel.getFollowing() || + (!profileModel.getFollowing() && profileModel.getRequested())) + ? "unfollow/" : "follow/") : + ((action.equals("restrict") && profileModel != null) ? + (profileModel.getRestricted() ? "unrestrict/" : "restrict/") : + (profileModel.getBlocked() ? "unblock/" : "block/"))))); try { final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); urlConnection.setRequestMethod("POST"); diff --git a/app/src/main/java/awais/instagrabber/activities/SavedViewer.java b/app/src/main/java/awais/instagrabber/activities/SavedViewer.java index 16178f27..f2b8a214 100755 --- a/app/src/main/java/awais/instagrabber/activities/SavedViewer.java +++ b/app/src/main/java/awais/instagrabber/activities/SavedViewer.java @@ -38,7 +38,7 @@ import awais.instagrabber.interfaces.FetchListener; import awais.instagrabber.interfaces.ItemGetter; import awais.instagrabber.models.PostModel; import awais.instagrabber.models.enums.DownloadMethod; -import awais.instagrabber.models.enums.ItemGetType; +import awais.instagrabber.models.enums.PostItemType; import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Utils; import awaisomereport.LogCollector; @@ -87,9 +87,9 @@ public final class SavedViewer extends BaseLanguageActivity implements SwipeRefr return false; } Utils.batchDownload(SavedViewer.this, - username, - DownloadMethod.DOWNLOAD_MAIN, - postsAdapter.getSelectedModels()); + username, + DownloadMethod.DOWNLOAD_MAIN, + postsAdapter.getSelectedModels()); checkAndResetAction(); return true; } @@ -123,7 +123,7 @@ public final class SavedViewer extends BaseLanguageActivity implements SwipeRefr currentlyExecuting = new iLikedFetcher(endCursor, postsFetchListener) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else if (autoloadPosts && hasNextPage) - currentlyExecuting = new PostsFetcher(action, endCursor, this) + currentlyExecuting = new PostsFetcher(action, false, endCursor, this) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else { savedBinding.swipeRefreshLayout.setRefreshing(false); @@ -170,10 +170,10 @@ public final class SavedViewer extends BaseLanguageActivity implements SwipeRefr } if (checkAndResetAction()) return; startActivity(new Intent(this, PostViewer.class) - .putExtra(Constants.EXTRAS_INDEX, position) - .putExtra(Constants.EXTRAS_POST, postModel) - .putExtra(Constants.EXTRAS_USER, username) - .putExtra(Constants.EXTRAS_TYPE, ItemGetType.SAVED_ITEMS)); + .putExtra(Constants.EXTRAS_INDEX, position) + .putExtra(Constants.EXTRAS_POST, postModel) + .putExtra(Constants.EXTRAS_USER, username) + .putExtra(Constants.EXTRAS_TYPE, PostItemType.SAVED)); }, (model, position) -> { if (!postsAdapter.isSelecting()) { @@ -193,7 +193,7 @@ public final class SavedViewer extends BaseLanguageActivity implements SwipeRefr savedBinding.swipeRefreshLayout.setRefreshing(true); setSupportActionBar(savedBinding.toolbar.toolbar); savedBinding.toolbar.toolbar.setTitle((action.charAt(0) == '$' ? R.string.saved : - (action.charAt(0) == '%' ? R.string.tagged : R.string.liked))); + (action.charAt(0) == '%' ? R.string.tagged : R.string.liked))); savedBinding.toolbar.toolbar.setSubtitle(username); lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { @@ -202,15 +202,16 @@ public final class SavedViewer extends BaseLanguageActivity implements SwipeRefr stopCurrentExecutor(); currentlyExecuting = action.charAt(0) == '^' - ? new iLikedFetcher(endCursor, postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) - : new PostsFetcher(action, endCursor, postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + ? new iLikedFetcher(endCursor, postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) + : new PostsFetcher(action, false, endCursor, postsFetchListener) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); endCursor = null; } }); savedBinding.mainPosts.addOnScrollListener(lazyLoader); itemGetter = itemGetType -> { - if (itemGetType == ItemGetType.SAVED_ITEMS) + if (itemGetType == PostItemType.SAVED) return postsViewModel.getList().getValue(); return null; }; diff --git a/app/src/main/java/awais/instagrabber/adapters/PostViewAdapter.java b/app/src/main/java/awais/instagrabber/adapters/PostViewAdapter.java new file mode 100644 index 00000000..305f04cd --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/PostViewAdapter.java @@ -0,0 +1,77 @@ +package awais.instagrabber.adapters; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.ListAdapter; + +import java.util.Arrays; + +import awais.instagrabber.adapters.viewholder.PostViewerViewHolder; +import awais.instagrabber.databinding.ItemFullPostViewBinding; +import awais.instagrabber.interfaces.MentionClickListener; +import awais.instagrabber.models.ViewerPostModelWrapper; + +public class PostViewAdapter extends ListAdapter { + private final OnPostViewChildViewClickListener clickListener; + private final OnPostCaptionLongClickListener longClickListener; + private final MentionClickListener mentionClickListener; + + private static final DiffUtil.ItemCallback diffCallback = new DiffUtil.ItemCallback() { + @Override + public boolean areItemsTheSame(@NonNull final ViewerPostModelWrapper oldItem, + @NonNull final ViewerPostModelWrapper newItem) { + return oldItem.getPosition() == newItem.getPosition(); + } + + @Override + public boolean areContentsTheSame(@NonNull final ViewerPostModelWrapper oldItem, + @NonNull final ViewerPostModelWrapper newItem) { + return Arrays.equals(oldItem.getViewerPostModels(), newItem.getViewerPostModels()); + } + }; + + public PostViewAdapter(final OnPostViewChildViewClickListener clickListener, + final OnPostCaptionLongClickListener longClickListener, + final MentionClickListener mentionClickListener) { + super(diffCallback); + this.clickListener = clickListener; + this.longClickListener = longClickListener; + this.mentionClickListener = mentionClickListener; + } + + @Override + public void onViewDetachedFromWindow(@NonNull final PostViewerViewHolder holder) { + holder.stopPlayingVideo(); + } + + @NonNull + @Override + public PostViewerViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, + final int viewType) { + final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); + final ItemFullPostViewBinding binding = ItemFullPostViewBinding + .inflate(layoutInflater, parent, false); + return new PostViewerViewHolder(binding); + } + + @Override + public void onBindViewHolder(@NonNull final PostViewerViewHolder holder, final int position) { + final ViewerPostModelWrapper item = getItem(position); + holder.bind(item, position, clickListener, longClickListener, mentionClickListener); + } + + public interface OnPostViewChildViewClickListener { + void onClick(View v, + ViewerPostModelWrapper viewerPostModelWrapper, + int postPosition, + int childPosition); + } + + public interface OnPostCaptionLongClickListener { + void onLongClick(String text); + } +} diff --git a/app/src/main/java/awais/instagrabber/adapters/PostViewerChildAdapter.java b/app/src/main/java/awais/instagrabber/adapters/PostViewerChildAdapter.java new file mode 100644 index 00000000..ca3e59e0 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/PostViewerChildAdapter.java @@ -0,0 +1,203 @@ +package awais.instagrabber.adapters; + +import android.net.Uri; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.appcompat.widget.AppCompatTextView; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.ListAdapter; +import androidx.recyclerview.widget.RecyclerView; + +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.drawee.interfaces.DraweeController; +import com.facebook.imagepipeline.request.ImageRequest; +import com.facebook.imagepipeline.request.ImageRequestBuilder; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.source.ProgressiveMediaSource; +import com.google.android.exoplayer2.ui.PlayerView; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; + +import awais.instagrabber.customviews.drawee.ZoomableDraweeView; +import awais.instagrabber.models.ViewerPostModel; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +public class PostViewerChildAdapter extends ListAdapter { + + private static final DiffUtil.ItemCallback diffCallback = new DiffUtil.ItemCallback() { + @Override + public boolean areItemsTheSame(@NonNull final ViewerPostModel oldItem, @NonNull final ViewerPostModel newItem) { + return oldItem.getPostId().equals(newItem.getPostId()) && oldItem.getShortCode().equals(newItem.getShortCode()); + } + + @Override + public boolean areContentsTheSame(@NonNull final ViewerPostModel oldItem, @NonNull final ViewerPostModel newItem) { + return oldItem.getPostId().equals(newItem.getPostId()) && oldItem.getShortCode().equals(newItem.getShortCode()); + } + }; + + public PostViewerChildAdapter() { + super(diffCallback); + } + + @NonNull + @Override + public ChildViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { + // final AppCompatTextView textView = new AppCompatTextView(parent.getContext()); + // textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + // return new ChildViewHolder(textView); + final MediaItemType mediaItemType = MediaItemType.valueOf(viewType); + if (mediaItemType == null) return getPlaceholder(parent); + switch (mediaItemType) { + case MEDIA_TYPE_IMAGE: + return getImageViewHolder(parent); + case MEDIA_TYPE_VIDEO: + return getVideoViewHolder(parent); + default: + return getPlaceholder(parent); + } + } + + private ChildViewHolder getImageViewHolder(final ViewGroup parent) { + final ZoomableDraweeView view = new ZoomableDraweeView(parent.getContext()); + view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + return new ChildViewHolder(view); + } + + private ChildViewHolder getVideoViewHolder(final ViewGroup parent) { + final PlayerView view = new PlayerView(parent.getContext()); + view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + return new ChildViewHolder(view); + } + + private ChildViewHolder getPlaceholder(final ViewGroup parent) { + final AppCompatTextView textView = new AppCompatTextView(parent.getContext()); + textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + textView.setGravity(Gravity.CENTER); + textView.setText("Placeholder"); + return new ChildViewHolder(textView); + } + + @Override + public void onBindViewHolder(@NonNull final ChildViewHolder holder, final int position) { + holder.bind(getItem(position)); + } + + @Override + public int getItemViewType(final int position) { + final ViewerPostModel item = getItem(position); + return item.getItemType().getId(); + } + + @Override + public void onViewDetachedFromWindow(@NonNull final ChildViewHolder holder) { + if (holder.itemView instanceof PlayerView) { + final Player player = ((PlayerView) holder.itemView).getPlayer(); + if (player != null) { + player.setPlayWhenReady(false); + } + } + } + + @Override + public void onViewRecycled(@NonNull final ChildViewHolder holder) { + if (holder.itemView instanceof PlayerView) { + final Player player = ((PlayerView) holder.itemView).getPlayer(); + if (player != null) { + player.release(); + } + return; + } + if (holder.itemView instanceof ZoomableDraweeView) { + ((ZoomableDraweeView) holder.itemView).setController(null); + } + } + + public static class ChildViewHolder extends RecyclerView.ViewHolder { + + public ChildViewHolder(@NonNull final View itemView) { + super(itemView); + } + + public void bind(final ViewerPostModel item) { + final MediaItemType mediaItemType = item.getItemType(); + switch (mediaItemType) { + case MEDIA_TYPE_IMAGE: + bindImage(item); + break; + case MEDIA_TYPE_VIDEO: + bindVideo(item); + break; + default: + } + } + + private void bindImage(final ViewerPostModel item) { + final ZoomableDraweeView imageView = (ZoomableDraweeView) itemView; + imageView.setController(null); + final ImageRequest requestBuilder = ImageRequestBuilder.newBuilderWithSource(Uri.parse(item.getDisplayUrl())) + .setLocalThumbnailPreviewsEnabled(true) + .setProgressiveRenderingEnabled(true) + .build(); + final DraweeController controller = Fresco.newDraweeControllerBuilder() + .setImageRequest(requestBuilder) + .setOldController(imageView.getController()) + // .setControllerListener(new BaseControllerListener() { + // + // @Override + // public void onFailure(final String id, final Throwable throwable) { + // // viewerBinding.progressView.setVisibility(View.GONE); + // } + // + // @Override + // public void onFinalImageSet(final String id, final ImageInfo imageInfo, final Animatable animatable) { + // // viewerBinding.progressView.setVisibility(View.GONE); + // } + // }) + .build(); + imageView.setController(controller); + } + + private void bindVideo(final ViewerPostModel item) { + final SimpleExoPlayer player = new SimpleExoPlayer.Builder(itemView.getContext()).build(); + final PlayerView playerView = (PlayerView) itemView; + playerView.setPlayer(player); + float vol = Utils.settingsHelper.getBoolean(Constants.MUTED_VIDEOS) ? 0f : 1f; + if (vol == 0f && Utils.sessionVolumeFull) vol = 1f; + player.setVolume(vol); + player.setPlayWhenReady(Utils.settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS)); + final ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(new DefaultDataSourceFactory(itemView.getContext(), "instagram")) + .createMediaSource(Uri.parse(item.getDisplayUrl())); + // mediaSource.addEventListener(new Handler(), new MediaSourceEventListener() { + // @Override + // public void onLoadCompleted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + // viewerBinding.progressView.setVisibility(View.GONE); + // } + // + // @Override + // public void onLoadStarted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + // viewerBinding.progressView.setVisibility(View.VISIBLE); + // } + // + // @Override + // public void onLoadCanceled(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + // viewerBinding.progressView.setVisibility(View.GONE); + // } + // + // @Override + // public void onLoadError(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData, final IOException error, final boolean wasCanceled) { + // viewerBinding.progressView.setVisibility(View.GONE); + // } + // }); + player.prepare(mediaSource); + player.setVolume(vol); + // viewerBinding.bottomPanel.btnMute.setImageResource(vol == 0f ? R.drawable.ic_volume_up_24 : R.drawable.ic_volume_off_24); + // viewerBinding.bottomPanel.btnMute.setOnClickListener(onClickListener); + } + } +} diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/PostViewerViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/PostViewerViewHolder.java new file mode 100644 index 00000000..73f3fd8f --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/PostViewerViewHolder.java @@ -0,0 +1,199 @@ +package awais.instagrabber.adapters.viewholder; + +import android.util.Log; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager2.widget.ViewPager2; + +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.ui.PlayerView; + +import java.util.ArrayList; +import java.util.List; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.PostViewAdapter.OnPostCaptionLongClickListener; +import awais.instagrabber.adapters.PostViewAdapter.OnPostViewChildViewClickListener; +import awais.instagrabber.adapters.PostViewerChildAdapter; +import awais.instagrabber.databinding.ItemFullPostViewBinding; +import awais.instagrabber.interfaces.MentionClickListener; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.ViewerPostModel; +import awais.instagrabber.models.ViewerPostModelWrapper; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.utils.Utils; + +public class PostViewerViewHolder extends RecyclerView.ViewHolder { + private static final String TAG = "PostViewerViewHolder"; + + private final ItemFullPostViewBinding binding; + private int currentChildPosition; + + public PostViewerViewHolder(@NonNull final ItemFullPostViewBinding binding) { + super(binding.getRoot()); + this.binding = binding; + binding.topPanel.viewStoryPost.setVisibility(View.GONE); + } + + public void bind(final ViewerPostModelWrapper wrapper, + final int position, + final OnPostViewChildViewClickListener clickListener, + final OnPostCaptionLongClickListener longClickListener, + final MentionClickListener mentionClickListener) { + if (wrapper == null) return; + final ViewerPostModel[] items = wrapper.getViewerPostModels(); + if (items == null || items.length <= 0) return; + if (items[0] == null) return; + final PostViewerChildAdapter adapter = new PostViewerChildAdapter(); + binding.mediaViewPager.setAdapter(adapter); + final ViewerPostModel firstPost = items[0]; + setPostInfo(firstPost, mentionClickListener); + setMediaItems(items, adapter); + setupListeners(wrapper, + position, + clickListener, + longClickListener, + mentionClickListener, + firstPost.getLocation()); + } + + private void setPostInfo(final ViewerPostModel firstPost, + final MentionClickListener mentionClickListener) { + final ProfileModel profileModel = firstPost.getProfileModel(); + if (profileModel == null) return; + binding.topPanel.title.setText(profileModel.getUsername()); + final String locationName = firstPost.getLocationName(); + if (!Utils.isEmpty(locationName)) { + binding.topPanel.location.setVisibility(View.VISIBLE); + binding.topPanel.location.setText(locationName); + } else binding.topPanel.location.setVisibility(View.GONE); + binding.topPanel.ivProfilePic.setImageURI(profileModel.getSdProfilePic()); + binding.bottomPanel.commentsCount.setText(String.valueOf(firstPost.getCommentsCount())); + final CharSequence postCaption = firstPost.getPostCaption(); + if (Utils.hasMentions(postCaption)) { + binding.bottomPanel.viewerCaption + .setText(Utils.getMentionText(postCaption), TextView.BufferType.SPANNABLE); + binding.bottomPanel.viewerCaption.setMentionClickListener(mentionClickListener); + } else { + binding.bottomPanel.viewerCaption.setMentionClickListener(null); + binding.bottomPanel.viewerCaption.setText(postCaption); + } + binding.bottomPanel.tvPostDate.setText(firstPost.getPostDate()); + } + + private void setupListeners(final ViewerPostModelWrapper wrapper, + final int position, + final OnPostViewChildViewClickListener clickListener, + final OnPostCaptionLongClickListener longClickListener, + final MentionClickListener mentionClickListener, + final String location) { + final View.OnClickListener onClickListener = v -> clickListener + .onClick(v, wrapper, position, currentChildPosition); + binding.bottomPanel.btnComments.setOnClickListener(onClickListener); + binding.topPanel.title.setOnClickListener(onClickListener); + binding.topPanel.ivProfilePic.setOnClickListener(onClickListener); + binding.bottomPanel.btnDownload.setOnClickListener(onClickListener); + binding.bottomPanel.viewerCaption.setOnClickListener(onClickListener); + binding.bottomPanel.viewerCaption.setOnLongClickListener(v -> { + longClickListener.onLongClick(binding.bottomPanel.viewerCaption.getText().toString()); + return true; + }); + if (!Utils.isEmpty(location)) { + binding.topPanel.location.setOnClickListener(v -> mentionClickListener + .onClick(binding.topPanel.location, location, false, true)); + } + } + + private void setMediaItems(final ViewerPostModel[] items, + final PostViewerChildAdapter adapter) { + final List filteredList = new ArrayList<>(); + for (final ViewerPostModel model : items) { + final MediaItemType itemType = model.getItemType(); + if (itemType == MediaItemType.MEDIA_TYPE_VIDEO || itemType == MediaItemType.MEDIA_TYPE_IMAGE) { + filteredList.add(model); + } + } + binding.mediaCounter.setVisibility(filteredList.size() > 1 ? View.VISIBLE : View.GONE); + final String counter = "1/" + filteredList.size(); + binding.mediaCounter.setText(counter); + adapter.submitList(filteredList); + binding.mediaViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { + @Override + public void onPageSelected(final int position) { + if (filteredList.size() <= 0 || position >= filteredList.size()) return; + currentChildPosition = position; + final String counter = (position + 1) + "/" + filteredList.size(); + binding.mediaCounter.setText(counter); + final ViewerPostModel viewerPostModel = filteredList.get(position); + if (viewerPostModel.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO) { + setVideoDetails(viewerPostModel); + setVolumeListener(position); + return; + } + setImageDetails(); + } + }); + } + + private void setVolumeListener(final int position) { + binding.bottomPanel.btnMute.setOnClickListener(v -> { + try { + final RecyclerView.ViewHolder viewHolder = ((RecyclerView) binding.mediaViewPager + .getChildAt(0)).findViewHolderForAdapterPosition(position); + if (viewHolder != null) { + final View itemView = viewHolder.itemView; + if (itemView instanceof PlayerView) { + final SimpleExoPlayer player = (SimpleExoPlayer) ((PlayerView) itemView) + .getPlayer(); + if (player == null) return; + final float vol = player.getVolume() == 0f ? 1f : 0f; + player.setVolume(vol); + binding.bottomPanel.btnMute + .setImageResource(vol == 0f ? R.drawable.ic_volume_up_24 : R.drawable.ic_volume_off_24); + Utils.sessionVolumeFull = vol == 1f; + } + } + } catch (Exception e) { + Log.e(TAG, "Error", e); + } + }); + } + + private void setImageDetails() { + binding.bottomPanel.btnMute.setVisibility(View.GONE); + binding.bottomPanel.videoViewsContainer.setVisibility(View.GONE); + } + + private void setVideoDetails(final ViewerPostModel viewerPostModel) { + binding.bottomPanel.btnMute.setVisibility(View.VISIBLE); + final long videoViews = viewerPostModel.getVideoViews(); + if (videoViews < 0) { + binding.bottomPanel.videoViewsContainer.setVisibility(View.GONE); + return; + } + binding.bottomPanel.tvVideoViews.setText(String.valueOf(videoViews)); + binding.bottomPanel.videoViewsContainer.setVisibility(View.VISIBLE); + } + + public void stopPlayingVideo() { + try { + final RecyclerView.ViewHolder viewHolder = ((RecyclerView) binding.mediaViewPager + .getChildAt(0)).findViewHolderForAdapterPosition(currentChildPosition); + if (viewHolder != null) { + final View itemView = viewHolder.itemView; + if (itemView instanceof PlayerView) { + final Player player = ((PlayerView) itemView).getPlayer(); + if (player != null) { + player.setPlayWhenReady(false); + } + } + } + } catch (Exception e) { + Log.e(TAG, "Error", e); + } + } +} diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedItemViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedItemViewHolder.java index ea608ba9..f65bb88f 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedItemViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedItemViewHolder.java @@ -2,7 +2,6 @@ package awais.instagrabber.adapters.viewholder.feed; import android.text.SpannableString; import android.text.Spanned; -import android.text.method.LinkMovementMethod; import android.view.View; import android.widget.RelativeLayout; import android.widget.TextView; @@ -10,8 +9,6 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; -import org.json.JSONObject; - import awais.instagrabber.customviews.CommentMentionClickSpan; import awais.instagrabber.customviews.RamboTextView; import awais.instagrabber.databinding.ItemFeedBottomBinding; @@ -37,7 +34,7 @@ public abstract class FeedItemViewHolder extends RecyclerView.ViewHolder { this.topBinding = topBinding; this.bottomBinding = bottomBinding; this.mentionClickListener = mentionClickListener; - topBinding.title.setMovementMethod(new LinkMovementMethod()); + // topBinding.title.setMovementMethod(new LinkMovementMethod()); bottomBinding.btnComments.setOnClickListener(clickListener); topBinding.viewStoryPost.setOnClickListener(clickListener); topBinding.ivProfilePic.setOnClickListener(clickListener); @@ -63,14 +60,16 @@ public abstract class FeedItemViewHolder extends RecyclerView.ViewHolder { final SpannableString spannableString = new SpannableString("@" + profileModel.getUsername()); spannableString.setSpan(new CommentMentionClickSpan(), 0, titleLen, 0); topBinding.title.setText(spannableString); - topBinding.title.setMentionClickListener((view, text, isHashtag, isLocation) -> mentionClickListener.onClick(null, profileModel.getUsername(), false, false)); + topBinding.title.setMentionClickListener( + (view, text, isHashtag, isLocation) -> mentionClickListener.onClick(null, profileModel.getUsername(), false, false)); } bottomBinding.tvPostDate.setText(feedModel.getPostDate()); final long commentsCount = feedModel.getCommentsCount(); bottomBinding.commentsCount.setText(String.valueOf(commentsCount)); - final JSONObject location = feedModel.getLocation(); - setLocation(location); + final String locationName = feedModel.getLocationName(); + final String locationId = feedModel.getLocationId(); + setLocation(locationName, locationId); CharSequence postCaption = feedModel.getPostCaption(); final boolean captionEmpty = Utils.isEmpty(postCaption); bottomBinding.viewerCaption.setVisibility(captionEmpty ? View.GONE : View.VISIBLE); @@ -87,22 +86,19 @@ public abstract class FeedItemViewHolder extends RecyclerView.ViewHolder { bindItem(feedModel); } - private void setLocation(final JSONObject location) { - if (location == null) { + private void setLocation(final String locationName, final String locationId) { + if (Utils.isEmpty(locationName)) { topBinding.location.setVisibility(View.GONE); topBinding.title.setLayoutParams(new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT )); } else { topBinding.location.setVisibility(View.VISIBLE); - topBinding.location.setText(location.optString("name")); + topBinding.location.setText(locationName); topBinding.title.setLayoutParams(new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT )); - topBinding.location.setOnClickListener(v -> mentionClickListener.onClick(topBinding.location, - location.optString("id") + "/" + location.optString("slug"), - false, - true)); + topBinding.location.setOnClickListener(v -> mentionClickListener.onClick(topBinding.location, locationId, false, true)); } } diff --git a/app/src/main/java/awais/instagrabber/asyncs/DiscoverFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/DiscoverFetcher.java index 4c7c3821..3b2957f2 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/DiscoverFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/DiscoverFetcher.java @@ -67,7 +67,7 @@ public final class DiscoverFetcher extends AsyncTask fetchItems(ArrayList discoverItemModels, final String maxId) { try { final String url = "https://www.instagram.com/explore/grid/?is_prefetch=false&omit_cover_media=true&module=explore_popular" + - "&use_sectional_payload=false&cluster_id="+cluster+"&include_fixed_destinations=true&session_id="+rankToken+maxId; + "&use_sectional_payload=false&cluster_id=" + cluster + "&include_fixed_destinations=true&session_id=" + rankToken + maxId; final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); @@ -130,10 +130,10 @@ public final class DiscoverFetcher extends AsyncTask("maxId", maxId), - new Pair<>("lastId", lastId), - new Pair<>("isFirst", isFirst), - new Pair<>("nextMaxId", nextMaxId)); + new Pair<>("maxId", maxId), + new Pair<>("lastId", lastId), + new Pair<>("isFirst", isFirst), + new Pair<>("nextMaxId", nextMaxId)); if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); } @@ -163,19 +163,21 @@ public final class DiscoverFetcher extends AsyncTask { if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { final String json = Utils.readFromConnection(urlConnection); - Log.d(TAG, json); + // Log.d(TAG, json); final JSONObject timelineFeed = new JSONObject(json).getJSONObject("data") .getJSONObject(Constants.EXTRAS_USER).getJSONObject("edge_web_feed_timeline"); @@ -104,15 +104,24 @@ public final class FeedFetcher extends AsyncTask { ProfileModel profileModel = null; if (feedItem.has("owner")) { final JSONObject owner = feedItem.getJSONObject("owner"); - profileModel = new ProfileModel(owner.optBoolean("is_private"), + profileModel = new ProfileModel( + owner.optBoolean("is_private"), false, // if you can see it then you def follow owner.optBoolean("is_verified"), owner.getString(Constants.EXTRAS_ID), owner.getString(Constants.EXTRAS_USERNAME), owner.optString("full_name"), - null, null, + null, + null, owner.getString("profile_pic_url"), - null, 0, 0, 0, false, false, false, false); + null, + 0, + 0, + 0, + false, + false, + false, + false); } JSONObject tempJsonObject = feedItem.optJSONObject("edge_media_preview_comment"); @@ -128,7 +137,21 @@ public final class FeedFetcher extends AsyncTask { captionText = tempJsonObject.getString("text"); } - final FeedModel feedModel = new FeedModel(profileModel, + final JSONObject location = feedItem.optJSONObject("location"); + // Log.d(TAG, "location: " + (location == null ? null : location.toString())); + String locationId = null; + String locationName = null; + if (location != null) { + locationName = location.optString("name"); + if (location.has("id")) { + locationId = location.getString("id"); + } else if (location.has("pk")) { + locationId = location.getString("pk"); + } + // Log.d(TAG, "locationId: " + locationId); + } + final FeedModel feedModel = new FeedModel( + profileModel, isVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE, videoViews, feedItem.getString(Constants.EXTRAS_ID), @@ -141,7 +164,8 @@ public final class FeedFetcher extends AsyncTask { feedItem.getBoolean("viewer_has_liked"), feedItem.getBoolean("viewer_has_saved"), feedItem.getJSONObject("edge_media_preview_like").getLong("count"), - feedItem.optJSONObject("location")); + locationName, + locationId); final boolean isSlider = "GraphSidecar".equals(mediaType) && feedItem.has("edge_sidecar_to_children"); @@ -161,13 +185,16 @@ public final class FeedFetcher extends AsyncTask { isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE, node.getString(Constants.EXTRAS_ID), isChildVideo ? node.getString("video_url") : Utils.getHighQualityImage(node), - null, null, null, - node.optLong("video_view_count", -1), -1, false, false, + null, + null, + null, + node.optLong("video_view_count", -1), + -1, + false, + false, feedItem.getJSONObject("edge_media_preview_like").getLong("count"), - feedItem.isNull("location") ? null : feedItem.getJSONObject("location").optString("name"), - feedItem.isNull("location") ? null : - (feedItem.getJSONObject("location").optString("id") + "/" + - feedItem.getJSONObject("location").optString("slug"))); + locationName, + locationId); sliderItems[j].setSliderDisplayUrl(node.getString("display_url")); } @@ -193,7 +220,9 @@ public final class FeedFetcher extends AsyncTask { } catch (final Exception e) { if (logCollector != null) logCollector.appendException(e, LogCollector.LogFile.ASYNC_FEED_FETCHER, "doInBackground"); - if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + if (BuildConfig.DEBUG) { + Log.e(TAG, "", e); + } } return result; diff --git a/app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java index 3c0f3ece..e73c0bed 100644 --- a/app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java @@ -5,7 +5,6 @@ import android.util.Log; import androidx.annotation.Nullable; -import org.json.JSONArray; import org.json.JSONObject; import java.math.BigDecimal; @@ -22,12 +21,14 @@ import awaisomereport.LogCollector; import static awais.instagrabber.utils.Utils.logCollector; public final class LocationFetcher extends AsyncTask { - private final FetchListener fetchListener; - private final String idSlug; + private static final String TAG = "LocationFetcher"; - public LocationFetcher(String idSlug, FetchListener fetchListener) { + private final FetchListener fetchListener; + private final String id; + + public LocationFetcher(final String id, final FetchListener fetchListener) { // idSlug = id + "/" + slug UPDATE: slug can be ignored tbh - this.idSlug = idSlug; + this.id = id; this.fetchListener = fetchListener; } @@ -37,27 +38,29 @@ public final class LocationFetcher extends AsyncTask LocationModel result = null; try { - final HttpURLConnection conn = (HttpURLConnection) new URL("https://www.instagram.com/explore/locations/" + idSlug + "/?__a=1").openConnection(); + final HttpURLConnection conn = (HttpURLConnection) new URL("https://www.instagram.com/explore/locations/" + id + "/?__a=1") + .openConnection(); conn.setUseCaches(true); conn.connect(); if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { - final JSONObject user = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("graphql").getJSONObject(Constants.EXTRAS_LOCATION); - - final JSONObject timelineMedia = user.getJSONObject("edge_location_to_media"); - if (timelineMedia.has("edges")) { - final JSONArray edges = timelineMedia.getJSONArray("edges"); - } + final JSONObject location = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("graphql") + .getJSONObject(Constants.EXTRAS_LOCATION); + final JSONObject timelineMedia = location.getJSONObject("edge_location_to_media"); + // if (timelineMedia.has("edges")) { + // final JSONArray edges = timelineMedia.getJSONArray("edges"); + // } result = new LocationModel( - user.getString(Constants.EXTRAS_ID) + "/" + user.getString("slug"), - user.getString("name"), - user.getString("blurb"), - user.getString("website"), - user.getString("profile_pic_url"), + location.getString(Constants.EXTRAS_ID), + location.getString("slug"), + location.getString("name"), + location.getString("blurb"), + location.getString("website"), + location.getString("profile_pic_url"), timelineMedia.getLong("count"), - BigDecimal.valueOf(user.optDouble("lat", 0d)).toString(), - BigDecimal.valueOf(user.optDouble("lng", 0d)).toString() + BigDecimal.valueOf(location.optDouble("lat", 0d)).toString(), + BigDecimal.valueOf(location.optDouble("lng", 0d)).toString() ); } @@ -65,9 +68,10 @@ public final class LocationFetcher extends AsyncTask } catch (final Exception e) { if (logCollector != null) logCollector.appendException(e, LogCollector.LogFile.ASYNC_LOCATION_FETCHER, "doInBackground"); - if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + if (BuildConfig.DEBUG) { + Log.e(TAG, "", e); + } } - return result; } diff --git a/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java index 38a6e0b0..d032dcf4 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java @@ -13,6 +13,7 @@ import java.net.URL; import awais.instagrabber.BuildConfig; import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.ProfileModel; import awais.instagrabber.models.ViewerPostModel; import awais.instagrabber.models.enums.MediaItemType; import awais.instagrabber.utils.Constants; @@ -85,13 +86,14 @@ public final class PostFetcher extends AsyncTask if (commentObject != null && (commentObject = commentObject.optJSONObject("page_info")) != null) endCursor = commentObject.optString("end_cursor"); + final ProfileModel profileModel = ProfileModel.getDefaultProfileModel(null, username); if (mediaItemType != MediaItemType.MEDIA_TYPE_SLIDER) { final ViewerPostModel postModel = new ViewerPostModel(mediaItemType, media.getString(Constants.EXTRAS_ID), isVideo ? media.getString("video_url") : Utils.getHighQualityImage(media), shortCode, Utils.isEmpty(postCaption) ? null : postCaption, - username, + profileModel, isVideo && media.has("video_view_count") ? media.getLong("video_view_count") : -1, timestamp, media.getBoolean("viewer_has_liked"), media.getBoolean("viewer_has_saved"), media.getJSONObject("edge_media_preview_like").getLong("count"), @@ -119,7 +121,7 @@ public final class PostFetcher extends AsyncTask isChildVideo ? node.getString("video_url") : Utils.getHighQualityImage(node), node.getString(Constants.EXTRAS_SHORTCODE), postCaption, - username, + profileModel, isChildVideo && node.has("video_view_count") ? node.getLong("video_view_count") : -1, timestamp, media.getBoolean("viewer_has_liked"), media.getBoolean("viewer_has_saved"), media.getJSONObject("edge_media_preview_like").getLong("count"), diff --git a/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java index 5937708b..5861b990 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java @@ -26,6 +26,7 @@ import static awais.instagrabber.utils.Utils.logCollector; public final class PostsFetcher extends AsyncTask { private static final String TAG = "PostsFetcher"; + private boolean isLocation; private final String endCursor; private final String id; private final FetchListener fetchListener; @@ -37,8 +38,12 @@ public final class PostsFetcher extends AsyncTask { this.fetchListener = fetchListener; } - public PostsFetcher(final String id, final String endCursor, final FetchListener fetchListener) { + public PostsFetcher(final String id, + final boolean isLocation, + final String endCursor, + final FetchListener fetchListener) { this.id = id; + this.isLocation = isLocation; this.endCursor = endCursor == null ? "" : endCursor; this.fetchListener = fetchListener; } @@ -53,15 +58,15 @@ public final class PostsFetcher extends AsyncTask { final boolean isHashTag = id.charAt(0) == '#'; final boolean isSaved = id.charAt(0) == '$'; final boolean isTagged = id.charAt(0) == '%'; - final boolean isLocation = id.contains("/"); + // final boolean isLocation = id.contains("/"); final String url; if (isHashTag) - url = "https://www.instagram.com/graphql/query/?query_hash=ded47faa9a1aaded10161a2ff32abb6b&variables=" + + url = "https://www.instagram.com/graphql/query/?query_hash=9b498c08113f1e09617a1703c22b2f32&variables=" + "{\"tag_name\":\"" + id.substring(1).toLowerCase() + "\",\"first\":150,\"after\":\"" + endCursor + "\"}"; else if (isLocation) url = "https://www.instagram.com/graphql/query/?query_hash=36bd0f2bf5911908de389b8ceaa3be6d&variables=" + - "{\"id\":\"" + id.split("/")[0] + "\",\"first\":150,\"after\":\"" + endCursor + "\"}"; + "{\"id\":\"" + id + "\",\"first\":150,\"after\":\"" + endCursor + "\"}"; else if (isSaved) url = "https://www.instagram.com/graphql/query/?query_hash=8c86fed24fa03a8a2eea2a70a80c7b6b&variables=" + "{\"id\":\"" + id.substring(1) + "\",\"first\":150,\"after\":\"" + endCursor + "\"}"; @@ -84,18 +89,20 @@ public final class PostsFetcher extends AsyncTask { File customDir = null; if (Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) { final String customPath = Utils.settingsHelper.getString(FOLDER_PATH + - (Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/" + username) : "")); + (Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) + ? ("/" + username) + : "")); if (!Utils.isEmpty(customPath)) customDir = new File(customPath); } final JSONObject mediaPosts = new JSONObject(Utils.readFromConnection(conn)) .getJSONObject("data") .getJSONObject(isHashTag ? Constants.EXTRAS_HASHTAG : - (isLocation ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_USER)) + (isLocation ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_USER)) .getJSONObject(isHashTag ? "edge_hashtag_to_media" : - (isLocation ? "edge_location_to_media" : + (isLocation ? "edge_location_to_media" : (isSaved ? "edge_saved_media" : - (isTagged ? "edge_user_to_photos_of_you" : "edge_owner_to_timeline_media")))); + (isTagged ? "edge_user_to_photos_of_you" : "edge_owner_to_timeline_media")))); final String endCursor; final boolean hasNextPage; @@ -124,11 +131,11 @@ public final class PostsFetcher extends AsyncTask { else itemType = MediaItemType.MEDIA_TYPE_IMAGE; models[i] = new PostModel(itemType, mediaNode.getString(Constants.EXTRAS_ID), - mediaNode.getString("display_url"), mediaNode.getString("thumbnail_src"), - mediaNode.getString(Constants.EXTRAS_SHORTCODE), - captions.length() > 0 ? captions.getJSONObject(0).getJSONObject("node").getString("text") : null, - mediaNode.getLong("taken_at_timestamp"), mediaNode.optBoolean("viewer_has_liked"), - mediaNode.optBoolean("viewer_has_saved"), mediaNode.getJSONObject("edge_liked_by").getLong("count")); + mediaNode.getString("display_url"), mediaNode.getString("thumbnail_src"), + mediaNode.getString(Constants.EXTRAS_SHORTCODE), + captions.length() > 0 ? captions.getJSONObject(0).getJSONObject("node").getString("text") : null, + mediaNode.getLong("taken_at_timestamp"), mediaNode.optBoolean("viewer_has_liked"), + mediaNode.optBoolean("viewer_has_saved"), mediaNode.getJSONObject("edge_liked_by").getLong("count")); Utils.checkExistence(downloadDir, customDir, isSlider, models[i]); } diff --git a/app/src/main/java/awais/instagrabber/asyncs/direct_messages/DirectThreadBroadcaster.java b/app/src/main/java/awais/instagrabber/asyncs/direct_messages/DirectThreadBroadcaster.java index 561bb1ba..9b591849 100644 --- a/app/src/main/java/awais/instagrabber/asyncs/direct_messages/DirectThreadBroadcaster.java +++ b/app/src/main/java/awais/instagrabber/asyncs/direct_messages/DirectThreadBroadcaster.java @@ -43,7 +43,7 @@ public class DirectThreadBroadcaster extends AsyncTask form = new HashMap<>(); - form.put("_csrftoken", cookie.split("csrftoken=")[1].split(";")[0]); + form.put("_csrftoken", Utils.getCsrfTokenFromCookie(cookie)); form.put("_uid", Utils.getUserIdFromCookie(cookie)); form.put("__uuid", settingsHelper.getString(Constants.DEVICE_UUID)); form.put("client_context", cc); diff --git a/app/src/main/java/awais/instagrabber/asyncs/i/iPostFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/i/iPostFetcher.java index a2d4c4a2..3e8378f2 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/i/iPostFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/i/iPostFetcher.java @@ -13,6 +13,7 @@ import java.net.URL; import awais.instagrabber.BuildConfig; import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.ProfileModel; import awais.instagrabber.models.ViewerPostModel; import awais.instagrabber.models.enums.MediaItemType; import awais.instagrabber.utils.Constants; @@ -25,6 +26,8 @@ import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO; import static awais.instagrabber.utils.Utils.logCollector; public final class iPostFetcher extends AsyncTask { + private static final String TAG = "iPostFetcher"; + private final String id; private final FetchListener fetchListener; @@ -43,18 +46,54 @@ public final class iPostFetcher extends AsyncTask conn.connect(); if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { - - final JSONObject media = new JSONObject(Utils.readFromConnection(conn)).getJSONArray("items").getJSONObject(0); - - final String username = media.has("user") ? media.getJSONObject("user").getString(Constants.EXTRAS_USERNAME) : null; + final JSONObject media = new JSONObject(Utils.readFromConnection(conn)) + .getJSONArray("items") + .getJSONObject(0); + ProfileModel profileModel = null; + if (media.has("user")) { + final JSONObject user = media.getJSONObject("user"); + final JSONObject friendshipStatus = user.optJSONObject("friendship_status"); + boolean following = false; + boolean isRestricted = false; + boolean outgoingRequest = false; + if (friendshipStatus != null) { + following = friendshipStatus.optBoolean("following"); + isRestricted = friendshipStatus.optBoolean("is_restricted"); + outgoingRequest = friendshipStatus.optBoolean("outgoing_request"); + } + profileModel = new ProfileModel( + user.optBoolean("is_private"), + user.optBoolean("is_private"), + user.optBoolean("is_verified"), + null, + user.getString(Constants.EXTRAS_USERNAME), + user.optString("fullname"), + null, + null, + user.getString("profile_pic_url"), + null, + -1, + -1, + -1, + following, + isRestricted, + false, + outgoingRequest + ); + } + if (profileModel == null) { + return new ViewerPostModel[]{}; + } // to check if file exists - final File downloadDir = new File(Environment.getExternalStorageDirectory(), "Download" + - (Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/"+username) : "")); + final boolean shouldDownloadToUserFolder = Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER); + final File downloadDir = new File( + Environment.getExternalStorageDirectory(), + "Download" + (shouldDownloadToUserFolder ? "/" + profileModel.getUsername() : "")); File customDir = null; if (Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) { - final String customPath = Utils.settingsHelper.getString(FOLDER_PATH + - (Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/"+username) : "")); + final String customPath = Utils.settingsHelper.getString(FOLDER_PATH) + + (shouldDownloadToUserFolder ? "/" + profileModel.getUsername() : ""); if (!Utils.isEmpty(customPath)) customDir = new File(customPath); } @@ -75,22 +114,33 @@ public final class iPostFetcher extends AsyncTask final long commentsCount = media.optLong("comment_count"); + final JSONObject location = media.optJSONObject("location"); + String locationId = null; + String locationName = null; + if (location != null) { + locationName = location.optString("name"); + if (location.has("id")) { + locationId = location.getString("id"); + } else if (location.has("pk")) { + locationId = location.getString("pk"); + } + } + // final String locationString = location.optString("id") + "/" + location.optString("slug"); if (mediaItemType != MediaItemType.MEDIA_TYPE_SLIDER) { - final ViewerPostModel postModel = new ViewerPostModel(mediaItemType, + final ViewerPostModel postModel = new ViewerPostModel( + mediaItemType, media.getString(Constants.EXTRAS_ID), - isVideo - ? Utils.getHighQualityPost(media.optJSONArray("video_versions"), true, true, false) + isVideo ? Utils.getHighQualityPost(media.optJSONArray("video_versions"), true, true, false) : Utils.getHighQualityImage(media), media.getString("code"), Utils.isEmpty(postCaption) ? null : postCaption, - username, + profileModel, isVideo && media.has("view_count") ? media.getLong("view_count") : -1, - timestamp, media.optBoolean("has_liked"), media.optBoolean("has_viewer_saved"), + timestamp, media.optBoolean("has_liked"), + media.optBoolean("has_viewer_saved"), media.getLong("like_count"), - media.isNull("location") ? null : media.getJSONObject("location").optString("name"), - media.isNull("location") ? null : - (media.getJSONObject("location").optString("id") + "/" + - media.getJSONObject("location").optString("slug"))); + locationName, + locationId); postModel.setCommentsCount(commentsCount); @@ -106,23 +156,22 @@ public final class iPostFetcher extends AsyncTask final JSONObject node = children.getJSONObject(i); final boolean isChildVideo = node.has("video_duration"); - postModels[i] = new ViewerPostModel(isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE, + postModels[i] = new ViewerPostModel( + isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO + : MediaItemType.MEDIA_TYPE_IMAGE, media.getString(Constants.EXTRAS_ID), - isChildVideo - ? Utils.getHighQualityPost(node.optJSONArray("video_versions"), true, true, false) - : Utils.getHighQualityImage(node), + isChildVideo ? Utils.getHighQualityPost(node.optJSONArray("video_versions"), true, true, false) + : Utils.getHighQualityImage(node), media.getString("code"), postCaption, - username, + profileModel, -1, - timestamp, media.optBoolean("has_liked"), media.optBoolean("has_viewer_saved"), + timestamp, media.optBoolean("has_liked"), + media.optBoolean("has_viewer_saved"), media.getLong("like_count"), - media.isNull("location") ? null : media.getJSONObject("location").optString("name"), - media.isNull("location") ? null : - (media.getJSONObject("location").optString("id") + "/" + - media.getJSONObject("location").optString("slug"))); + locationName, + locationId); postModels[i].setSliderDisplayUrl(Utils.getHighQualityImage(node)); - Utils.checkExistence(downloadDir, customDir, true, postModels[i]); } @@ -135,7 +184,9 @@ public final class iPostFetcher extends AsyncTask } catch (Exception e) { if (logCollector != null) logCollector.appendException(e, LogCollector.LogFile.ASYNC_POST_FETCHER, "doInBackground (i)"); - if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + if (BuildConfig.DEBUG) { + Log.e(TAG, "", e); + } } return result; } diff --git a/app/src/main/java/awais/instagrabber/customviews/helpers/NestedScrollableHost.java b/app/src/main/java/awais/instagrabber/customviews/helpers/NestedScrollableHost.java new file mode 100644 index 00000000..c3e56ecf --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/helpers/NestedScrollableHost.java @@ -0,0 +1,112 @@ +package awais.instagrabber.customviews.helpers; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.viewpager2.widget.ViewPager2; + +import static androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL; + +public class NestedScrollableHost extends FrameLayout { + + private int touchSlop; + private float initialX = 0f; + private float initialY = 0f; + + public NestedScrollableHost(@NonNull final Context context) { + this(context, null); + } + + public NestedScrollableHost(@NonNull final Context context, @Nullable final AttributeSet attrs) { + super(context, attrs); + touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + } + + @Override + public boolean onInterceptTouchEvent(final MotionEvent ev) { + handleInterceptTouchEvent(ev); + return super.onInterceptTouchEvent(ev); + } + + private void handleInterceptTouchEvent(final MotionEvent e) { + if (getParentViewPager() == null) return; + final int orientation = getParentViewPager().getOrientation(); + // Early return if child can't scroll in same direction as parent + if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) return; + + if (e.getAction() == MotionEvent.ACTION_DOWN) { + initialX = e.getX(); + initialY = e.getY(); + getParent().requestDisallowInterceptTouchEvent(true); + } else if (e.getAction() == MotionEvent.ACTION_MOVE) { + final float dx = e.getX() - initialX; + final float dy = e.getY() - initialY; + final boolean isVpHorizontal = orientation == ORIENTATION_HORIZONTAL; + + // assuming ViewPager2 touch-slop is 2x touch-slop of child + final float scaledDx = Math.abs(dx) * (isVpHorizontal ? .5f : 1f); + final float scaledDy = Math.abs(dy) * (isVpHorizontal ? 1f : .5f); + + if (scaledDx > touchSlop || scaledDy > touchSlop) { + if (isVpHorizontal == (scaledDy > scaledDx)) { + // Gesture is perpendicular, allow all parents to intercept + getParent().requestDisallowInterceptTouchEvent(false); + } else { + // Gesture is parallel, query child if movement in that direction is possible + if (canChildScroll(orientation, (isVpHorizontal ? dx : dy))) { + // Child can scroll, disallow all parents to intercept + getParent().requestDisallowInterceptTouchEvent(true); + } else { + // Child cannot scroll, allow all parents to intercept + getParent().requestDisallowInterceptTouchEvent(false); + } + } + } + } + } + + private boolean canChildScroll(final int orientation, final float delta) { + final int direction = -(int) Math.signum(delta); + final View child = getChild(); + if (child == null) return false; + ViewPager2 viewPagerChild = null; + if (child instanceof ViewPager2) { + viewPagerChild = (ViewPager2) child; + } + + boolean canScroll; + switch (orientation) { + case 0: + canScroll = child.canScrollHorizontally(direction); + break; + case 1: + canScroll = child.canScrollVertically(direction); + break; + default: + throw new IllegalArgumentException(); + } + if (!canScroll || viewPagerChild == null || viewPagerChild.getAdapter() == null) + return canScroll; + // check if viewpager has reached its limits and decide accordingly + return (direction < 0 && viewPagerChild.getCurrentItem() > 0) + || (direction > 0 && viewPagerChild.getCurrentItem() < viewPagerChild.getAdapter().getItemCount() - 1); + } + + public ViewPager2 getParentViewPager() { + View v = (View) getParent(); + while (v != null && !(v instanceof ViewPager2)) { + v = (View) v.getParent(); + } + return (ViewPager2) v; + } + + public View getChild() { + return getChildCount() > 0 ? getChildAt(0) : null; + } +} diff --git a/app/src/main/java/awais/instagrabber/customviews/helpers/RecyclerLazyLoader.java b/app/src/main/java/awais/instagrabber/customviews/helpers/RecyclerLazyLoader.java index b71eed0b..6a165451 100755 --- a/app/src/main/java/awais/instagrabber/customviews/helpers/RecyclerLazyLoader.java +++ b/app/src/main/java/awais/instagrabber/customviews/helpers/RecyclerLazyLoader.java @@ -17,9 +17,13 @@ public final class RecyclerLazyLoader extends RecyclerView.OnScrollListener { private final LazyLoadListener lazyLoadListener; private final RecyclerView.LayoutManager layoutManager; - public RecyclerLazyLoader(@NonNull final RecyclerView.LayoutManager layoutManager, final LazyLoadListener lazyLoadListener) { + public RecyclerLazyLoader(@NonNull final RecyclerView.LayoutManager layoutManager, final LazyLoadListener lazyLoadListener, final int threshold) { this.layoutManager = layoutManager; this.lazyLoadListener = lazyLoadListener; + if (threshold > 0) { + this.visibleThreshold = threshold; + return; + } if (layoutManager instanceof GridLayoutManager) { this.visibleThreshold = 5 * Math.max(3, ((GridLayoutManager) layoutManager).getSpanCount()); } else if (layoutManager instanceof LinearLayoutManager) { @@ -29,6 +33,10 @@ public final class RecyclerLazyLoader extends RecyclerView.OnScrollListener { } } + public RecyclerLazyLoader(@NonNull final RecyclerView.LayoutManager layoutManager, final LazyLoadListener lazyLoadListener) { + this(layoutManager, lazyLoadListener, -1); + } + @Override public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) { final int totalItemCount = layoutManager.getItemCount(); @@ -54,7 +62,8 @@ public final class RecyclerLazyLoader extends RecyclerView.OnScrollListener { } if (!loading && lastVisibleItemPosition + visibleThreshold > totalItemCount) { - if (lazyLoadListener != null) lazyLoadListener.onLoadMore(++currentPage, totalItemCount); + if (lazyLoadListener != null) + lazyLoadListener.onLoadMore(++currentPage, totalItemCount); loading = true; } } diff --git a/app/src/main/java/awais/instagrabber/directdownload/DirectDownload.java b/app/src/main/java/awais/instagrabber/directdownload/DirectDownload.java index 005fda27..4cf51f65 100755 --- a/app/src/main/java/awais/instagrabber/directdownload/DirectDownload.java +++ b/app/src/main/java/awais/instagrabber/directdownload/DirectDownload.java @@ -136,7 +136,7 @@ public final class DirectDownload extends Activity { if (notificationManager != null) notificationManager.cancel(1900000000); if (result != null) { if (result.length == 1) { - Utils.batchDownload(context, result[0].getUsername(), DownloadMethod.DOWNLOAD_DIRECT, + Utils.batchDownload(context, result[0].getProfileModel().getUsername(), DownloadMethod.DOWNLOAD_DIRECT, Arrays.asList(result)); } else if (result.length > 1) { context.startActivity(new Intent(context, MultiDirectDialog.class) diff --git a/app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java b/app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java index f44374f9..159d477b 100755 --- a/app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java +++ b/app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java @@ -47,7 +47,7 @@ public final class MultiDirectDialog extends BaseLanguageActivity { return; } - username = postModels[0].getUsername(); + username = postModels[0].getProfileModel().getUsername(); toolbar.setTitle(username); toolbar.setSubtitle(postModels[0].getShortCode()); diff --git a/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java b/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java index e035ea07..3ba62570 100644 --- a/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java @@ -1,6 +1,5 @@ package awais.instagrabber.fragments; -import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.Typeface; import android.os.AsyncTask; @@ -25,6 +24,8 @@ import androidx.core.content.ContextCompat; import androidx.core.view.ViewCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; +import androidx.navigation.NavDirections; +import androidx.navigation.fragment.NavHostFragment; import java.util.ArrayList; import java.util.Arrays; @@ -33,7 +34,6 @@ import java.util.List; import awais.instagrabber.R; import awais.instagrabber.activities.MainActivity; -import awais.instagrabber.activities.PostViewer; import awais.instagrabber.adapters.PostsAdapter; import awais.instagrabber.asyncs.HashtagFetcher; import awais.instagrabber.asyncs.PostsFetcher; @@ -50,7 +50,6 @@ import awais.instagrabber.models.HashtagModel; import awais.instagrabber.models.PostModel; import awais.instagrabber.models.StoryModel; import awais.instagrabber.models.enums.DownloadMethod; -import awais.instagrabber.models.enums.ItemGetType; import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Utils; import awaisomereport.LogCollector; @@ -104,9 +103,9 @@ public class HashTagFragment extends Fragment { return false; } Utils.batchDownload(requireContext(), - hashtag, - DownloadMethod.DOWNLOAD_MAIN, - postsAdapter.getSelectedModels()); + hashtag, + DownloadMethod.DOWNLOAD_MAIN, + postsAdapter.getSelectedModels()); checkAndResetAction(); return true; } @@ -191,11 +190,26 @@ public class HashTagFragment extends Fragment { return; } if (checkAndResetAction()) return; - startActivity(new Intent(requireContext(), PostViewer.class) - .putExtra(Constants.EXTRAS_INDEX, position) - .putExtra(Constants.EXTRAS_POST, postModel) - .putExtra(Constants.EXTRAS_USER, hashtag) - .putExtra(Constants.EXTRAS_TYPE, ItemGetType.MAIN_ITEMS)); + // startActivity(new Intent(requireContext(), PostViewer.class) + // .putExtra(Constants.EXTRAS_INDEX, position) + // .putExtra(Constants.EXTRAS_POST, postModel) + // .putExtra(Constants.EXTRAS_USER, hashtag) + // .putExtra(Constants.EXTRAS_TYPE, PostItemType.MAIN)); + final List postModels = postsViewModel.getList().getValue(); + if (postModels == null || postModels.size() == 0) return; + if (postModels.get(0) == null) return; + final String postId = postModels.get(0).getPostId(); + final boolean isId = postId != null; + final String[] idsOrShortCodes = new String[postModels.size()]; + for (int i = 0; i < postModels.size(); i++) { + idsOrShortCodes[i] = isId ? postModels.get(i).getPostId() + : postModels.get(i).getShortCode(); + } + final NavDirections action = HashTagFragmentDirections.actionGlobalPostViewFragment( + position, + idsOrShortCodes, + isId); + NavHostFragment.findNavController(this).navigate(action); }, (model, position) -> { if (!postsAdapter.isSelecting()) { @@ -242,7 +256,7 @@ public class HashTagFragment extends Fragment { stopCurrentExecutor(); binding.btnFollowTag.setVisibility(View.VISIBLE); binding.swipeRefreshLayout.setRefreshing(true); - currentlyExecuting = new PostsFetcher(hashtag, endCursor, postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + currentlyExecuting = new PostsFetcher(hashtag, false, endCursor, postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); if (isLoggedIn) { new iStoryStatusFetcher(hashtagModel.getName(), null, false, true, false, false, stories -> { storyModels = stories; @@ -254,16 +268,16 @@ public class HashTagFragment extends Fragment { binding.btnFollowTag.setText(hashtagModel.getFollowing() ? R.string.unfollow : R.string.follow); ViewCompat.setBackgroundTintList(binding.btnFollowTag, ColorStateList.valueOf( ContextCompat.getColor(requireContext(), hashtagModel.getFollowing() - ? R.color.btn_purple_background - : R.color.btn_pink_background))); + ? R.color.btn_purple_background + : R.color.btn_pink_background))); } else { binding.btnFollowTag.setText(Utils.dataBox.getFavorite(hashtag) != null - ? R.string.unfavorite_short - : R.string.favorite_short); + ? R.string.unfavorite_short + : R.string.favorite_short); ViewCompat.setBackgroundTintList(binding.btnFollowTag, ColorStateList.valueOf( ContextCompat.getColor(requireContext(), Utils.dataBox.getFavorite(hashtag) != null - ? R.color.btn_purple_background - : R.color.btn_pink_background))); + ? R.color.btn_purple_background + : R.color.btn_pink_background))); } binding.mainHashtagImage.setImageURI(hashtagModel.getSdProfilePic()); final String postCount = String.valueOf(hashtagModel.getPostCount()); diff --git a/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java b/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java index 4c682c1c..2fee4e8f 100644 --- a/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java @@ -24,6 +24,8 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; +import androidx.navigation.NavDirections; +import androidx.navigation.fragment.NavHostFragment; import java.util.ArrayList; import java.util.Arrays; @@ -32,7 +34,6 @@ import java.util.List; import awais.instagrabber.R; import awais.instagrabber.activities.MainActivity; -import awais.instagrabber.activities.PostViewer; import awais.instagrabber.adapters.PostsAdapter; import awais.instagrabber.asyncs.LocationFetcher; import awais.instagrabber.asyncs.PostsFetcher; @@ -49,7 +50,6 @@ import awais.instagrabber.models.LocationModel; import awais.instagrabber.models.PostModel; import awais.instagrabber.models.StoryModel; import awais.instagrabber.models.enums.DownloadMethod; -import awais.instagrabber.models.enums.ItemGetType; import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Utils; import awaisomereport.LogCollector; @@ -64,7 +64,7 @@ public class LocationFragment extends Fragment { private FragmentLocationBinding binding; private NestedCoordinatorLayout root; private boolean shouldRefresh = true; - private String location; + private String locationId; private LocationModel locationModel; private PostsViewModel postsViewModel; private PostsAdapter postsAdapter; @@ -89,29 +89,29 @@ public class LocationFragment extends Fragment { } }; private final PrimaryActionModeCallback multiSelectAction = new PrimaryActionModeCallback( - R.menu.multi_select_download_menu, - new PrimaryActionModeCallback.CallbacksHelper() { - @Override - public void onDestroy(final ActionMode mode) { - onBackPressedCallback.handleOnBackPressed(); - } + R.menu.multi_select_download_menu, new PrimaryActionModeCallback.CallbacksHelper() { + @Override + public void onDestroy(final ActionMode mode) { + onBackPressedCallback.handleOnBackPressed(); + } - @Override - public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) { - if (item.getItemId() == R.id.action_download) { - if (postsAdapter == null || location == null) { - return false; - } - Utils.batchDownload(requireContext(), - location, - DownloadMethod.DOWNLOAD_MAIN, - postsAdapter.getSelectedModels()); - checkAndResetAction(); - return true; - } + @Override + public boolean onActionItemClicked(final ActionMode mode, + final MenuItem item) { + if (item.getItemId() == R.id.action_download) { + if (postsAdapter == null || locationId == null) { return false; } - }); + Utils.batchDownload(requireContext(), + locationId, + DownloadMethod.DOWNLOAD_MAIN, + postsAdapter.getSelectedModels()); + checkAndResetAction(); + return true; + } + return false; + } + }); private final FetchListener postsFetchListener = new FetchListener() { @Override public void onResult(final PostModel[] result) { @@ -119,7 +119,8 @@ public class LocationFragment extends Fragment { if (result == null) return; binding.mainPosts.post(() -> binding.mainPosts.setVisibility(View.VISIBLE)); final List postModels = postsViewModel.getList().getValue(); - final List finalList = postModels == null || postModels.isEmpty() ? new ArrayList<>() : new ArrayList<>(postModels); + final List finalList = postModels == null || postModels.isEmpty() ? new ArrayList<>() + : new ArrayList<>(postModels); finalList.addAll(Arrays.asList(result)); postsViewModel.getList().postValue(finalList); PostModel model = null; @@ -141,7 +142,9 @@ public class LocationFragment extends Fragment { @Nullable @Override - public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { + public View onCreateView(@NonNull final LayoutInflater inflater, + @Nullable final ViewGroup container, + @Nullable final Bundle savedInstanceState) { if (root != null) { shouldRefresh = false; return root; @@ -171,7 +174,7 @@ public class LocationFragment extends Fragment { final String cookie = settingsHelper.getString(Constants.COOKIE); isLoggedIn = !Utils.isEmpty(cookie) && Utils.getUserIdFromCookie(cookie) != null; final LocationFragmentArgs fragmentArgs = LocationFragmentArgs.fromBundle(getArguments()); - location = fragmentArgs.getLocation(); + locationId = fragmentArgs.getLocationId(); setTitle(); setupPosts(); fetchLocationModel(); @@ -190,11 +193,26 @@ public class LocationFragment extends Fragment { return; } if (checkAndResetAction()) return; - startActivity(new Intent(requireContext(), PostViewer.class) - .putExtra(Constants.EXTRAS_INDEX, position) - .putExtra(Constants.EXTRAS_POST, postModel) - .putExtra(Constants.EXTRAS_USER, location) - .putExtra(Constants.EXTRAS_TYPE, ItemGetType.MAIN_ITEMS)); + final List postModels = postsViewModel.getList().getValue(); + if (postModels == null || postModels.size() == 0) return; + if (postModels.get(0) == null) return; + final String postId = postModels.get(0).getPostId(); + final boolean isId = postId != null; + final String[] idsOrShortCodes = new String[postModels.size()]; + for (int i = 0; i < postModels.size(); i++) { + idsOrShortCodes[i] = isId ? postModels.get(i).getPostId() + : postModels.get(i).getShortCode(); + } + final NavDirections action = LocationFragmentDirections.actionGlobalPostViewFragment( + position, + idsOrShortCodes, + isId); + NavHostFragment.findNavController(this).navigate(action); + // startActivity(new Intent(requireContext(), PostViewer.class) + // .putExtra(Constants.EXTRAS_INDEX, position) + // .putExtra(Constants.EXTRAS_POST, postModel) + // .putExtra(Constants.EXTRAS_USER, locationId) + // .putExtra(Constants.EXTRAS_TYPE, PostItemType.MAIN)); }, (model, position) -> { if (!postsAdapter.isSelecting()) { @@ -204,7 +222,8 @@ public class LocationFragment extends Fragment { if (onBackPressedCallback.isEnabled()) { return true; } - final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher(); + final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity + .getOnBackPressedDispatcher(); onBackPressedCallback.setEnabled(true); actionMode = fragmentActivity.startActionMode(multiSelectAction); final String title = getString(R.string.number_selected, 1); @@ -226,7 +245,7 @@ public class LocationFragment extends Fragment { private void fetchLocationModel() { stopCurrentExecutor(); binding.swipeRefreshLayout.setRefreshing(true); - currentlyExecuting = new LocationFetcher(location.split("/")[0], result -> { + currentlyExecuting = new LocationFetcher(locationId, result -> { locationModel = result; binding.swipeRefreshLayout.setRefreshing(false); if (locationModel == null) { @@ -243,16 +262,24 @@ public class LocationFragment extends Fragment { final String locationId = locationModel.getId(); binding.swipeRefreshLayout.setRefreshing(true); if (isLoggedIn) { - new iStoryStatusFetcher(locationId.split("/")[0], null, true, false, false, false, stories -> { - storyModels = stories; - if (stories != null && stories.length > 0) { - binding.mainLocationImage.setStoriesBorder(); - } - }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new iStoryStatusFetcher( + locationId, + null, + true, + false, + false, + false, + stories -> { + storyModels = stories; + if (stories != null && stories.length > 0) { + binding.mainLocationImage.setStoriesBorder(); + } + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } binding.mainLocationImage.setImageURI(locationModel.getSdProfilePic()); final String postCount = String.valueOf(locationModel.getPostCount()); - final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count, postCount)); + final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count, + postCount)); span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); binding.mainLocPostCount.setText(span); @@ -301,7 +328,7 @@ public class LocationFragment extends Fragment { private void fetchPosts() { stopCurrentExecutor(); - currentlyExecuting = new PostsFetcher(locationModel.getId(), endCursor, postsFetchListener) + currentlyExecuting = new PostsFetcher(locationModel.getId(), true, endCursor, postsFetchListener) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -310,8 +337,8 @@ public class LocationFragment extends Fragment { try { currentlyExecuting.cancel(true); } catch (final Exception e) { - if (logCollector != null) - logCollector.appendException(e, LogCollector.LogFile.MAIN_HELPER, "stopCurrentExecutor"); + if (logCollector != null) logCollector.appendException( + e, LogCollector.LogFile.MAIN_HELPER, "stopCurrentExecutor"); Log.e(TAG, "", e); } } diff --git a/app/src/main/java/awais/instagrabber/fragments/PostViewFragment.java b/app/src/main/java/awais/instagrabber/fragments/PostViewFragment.java new file mode 100644 index 00000000..8f6e703c --- /dev/null +++ b/app/src/main/java/awais/instagrabber/fragments/PostViewFragment.java @@ -0,0 +1,287 @@ +package awais.instagrabber.fragments; + +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.AsyncTask; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.lifecycle.ViewModelProvider; +import androidx.navigation.NavDirections; +import androidx.navigation.fragment.NavHostFragment; +import androidx.viewpager2.widget.ViewPager2; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import awais.instagrabber.R; +import awais.instagrabber.activities.CommentsViewer; +import awais.instagrabber.adapters.PostViewAdapter; +import awais.instagrabber.adapters.PostViewAdapter.OnPostViewChildViewClickListener; +import awais.instagrabber.asyncs.PostFetcher; +import awais.instagrabber.asyncs.i.iPostFetcher; +import awais.instagrabber.databinding.FragmentPostViewBinding; +import awais.instagrabber.fragments.main.viewmodels.ViewerPostViewModel; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.interfaces.MentionClickListener; +import awais.instagrabber.models.ViewerPostModel; +import awais.instagrabber.models.ViewerPostModelWrapper; +import awais.instagrabber.models.enums.DownloadMethod; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +import static androidx.core.content.ContextCompat.checkSelfPermission; +import static awais.instagrabber.utils.Utils.settingsHelper; + +public class PostViewFragment extends Fragment { + private static final String TAG = "PostViewFragment"; + + private FragmentActivity fragmentActivity; + private FragmentPostViewBinding binding; + private ViewPager2 root; + private boolean shouldRefresh = true; + private ViewerPostViewModel viewerPostViewModel; + private boolean isId; + private int currentPostIndex; + private List idOrCodeList; + private boolean hasInitialResult = false; + private PostViewAdapter adapter; + private boolean session; + + private FetchListener pfl = result -> { + if (result == null) return; + if (result.length <= 0) return; + final List viewerPostModels = viewerPostViewModel.getList() + .getValue(); + final List temp = viewerPostModels == null ? new ArrayList<>( + idOrCodeList.size()) : new ArrayList<>(viewerPostModels); + final ViewerPostModel firstPost = result[0]; + if (firstPost == null) return; + String idOrCode = isId ? firstPost.getPostId() : firstPost.getShortCode(); + if (idOrCode == null) return; + // some values are appended to the post/short code with `_` + idOrCode = idOrCode.substring(0, idOrCode.indexOf('_')); + final int index = idOrCodeList.indexOf(idOrCode); + if (index < 0) return; + final ViewerPostModelWrapper viewerPostModelWrapper = temp.get(index); + viewerPostModelWrapper.setViewerPostModels(result); + temp.set(index, viewerPostModelWrapper); + viewerPostViewModel.getList().setValue(temp); + adapter.notifyItemChanged(index); + if (!hasInitialResult) { + Log.d(TAG, "setting delayed position to: " + currentPostIndex); + binding.getRoot() + .postDelayed(() -> binding.getRoot().setCurrentItem(currentPostIndex), 200); + } + hasInitialResult = true; + }; + private MentionClickListener mentionListener = (view, text, isHashtag, isLocation) -> { + if (isHashtag) { + final NavDirections action = PostViewFragmentDirections + .actionGlobalHashTagFragment(text); + NavHostFragment.findNavController(this).navigate(action); + return; + } + if (isLocation) { + final NavDirections action = PostViewFragmentDirections + .actionGlobalLocationFragment(text); + NavHostFragment.findNavController(this).navigate(action); + return; + } + final NavDirections action = PostViewFragmentDirections + .actionGlobalProfileFragment("@" + text); + NavHostFragment.findNavController(this).navigate(action); + }; + private OnPostViewChildViewClickListener clickListener = (v, wrapper, postPosition, childPosition) -> { + // final FeedModel feedModel = (FeedModel) tag; + // if (v.getId() == ) { + // if (feedModel.isMentionClicked()) + // feedModel.toggleCaption(); + // feedModel.setMentionClicked(false); + // if (!FeedItemViewHolder.expandCollapseTextView((RamboTextView) v, feedModel.getPostCaption())) + // feedModel.toggleCaption(); + // return; + // } + final ViewerPostModel postModel = wrapper.getViewerPostModels()[0]; + final String username = postModel.getProfileModel().getUsername(); + final int id = v.getId(); + switch (id) { + case R.id.viewerCaption: + break; + case R.id.btnComments: + startActivity(new Intent(requireContext(), CommentsViewer.class) + .putExtra(Constants.EXTRAS_SHORTCODE, + postModel.getShortCode()) + .putExtra(Constants.EXTRAS_POST, postModel.getPostId()) + .putExtra(Constants.EXTRAS_USER, + Utils.getUserIdFromCookie(settingsHelper.getString( + Constants.COOKIE)))); + break; + case R.id.btnDownload: + if (checkSelfPermission(requireContext(), + Utils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) { + showDownloadDialog(Arrays.asList(wrapper.getViewerPostModels()), + childPosition, + username); + return; + } + requestPermissions(Utils.PERMS, 8020); + break; + case R.id.ivProfilePic: + case R.id.title: + mentionListener.onClick(null, username, false, false); + break; + } + }; + private PostViewAdapter.OnPostCaptionLongClickListener captionLongClickListener = text -> Utils + .copyText(requireContext(), text); + + @Override + public void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + fragmentActivity = getActivity(); + } + + @Nullable + @Override + public View onCreateView(@NonNull final LayoutInflater inflater, + @Nullable final ViewGroup container, + @Nullable final Bundle savedInstanceState) { + if (root != null) { + shouldRefresh = false; + return root; + } + binding = FragmentPostViewBinding.inflate(inflater, container, false); + root = binding.getRoot(); + setupViewPager(); + return root; + } + + @Override + public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { + if (!shouldRefresh) return; + init(); + } + + private void setupViewPager() { + viewerPostViewModel = new ViewModelProvider(fragmentActivity) + .get(ViewerPostViewModel.class); + adapter = new PostViewAdapter(clickListener, captionLongClickListener, mentionListener); + root.setAdapter(adapter); + root.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { + + @Override + public void onPageSelected(final int position) { + // Log.d(TAG, "onPageSelected: " + position + ", hasInitialResult: " + hasInitialResult); + if (!hasInitialResult) { + return; + } + currentPostIndex = position; + fetchPost(); + } + }); + viewerPostViewModel.getList().observe(fragmentActivity, list -> adapter.submitList(list)); + } + + private void init() { + if (getArguments() == null) return; + final PostViewFragmentArgs fragmentArgs = PostViewFragmentArgs.fromBundle(getArguments()); + final String[] idOrCodeArray = fragmentArgs.getIdOrCodeArray(); + if (idOrCodeArray.length == 0) return; + currentPostIndex = fragmentArgs.getIndex(); + if (currentPostIndex < 0) return; + if (currentPostIndex >= idOrCodeArray.length) return; + idOrCodeList = Arrays.asList(idOrCodeArray); + viewerPostViewModel.getList().setValue(createPlaceholderModels(idOrCodeArray.length)); + isId = fragmentArgs.getIsId(); + // binding.getRoot().postDelayed(() -> binding.getRoot().setCurrentItem(currentPostIndex), 500); + fetchPost(); + // binding.getRoot().setCurrentItem(currentPostIndex); + } + + private List createPlaceholderModels(final int size) { + final List viewerPostModels = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + // viewerPostModels.add(new ViewerPostModel[]{ViewerPostModel.getDefaultModel(-i, "")}); + viewerPostModels.add(new ViewerPostModelWrapper(i, null)); + } + return viewerPostModels; + } + + private void fetchPost() { + // Log.d(TAG, "fetchPost, currentPostIndex: " + currentPostIndex); + final List list = viewerPostViewModel.getList().getValue(); + if (list != null) { + final ViewerPostModelWrapper viewerPostModels = list.get(currentPostIndex); + if (viewerPostModels != null && viewerPostModels + .getViewerPostModels() != null && viewerPostModels + .getViewerPostModels().length > 0) { + // final ViewerPostModel viewerPostModel = viewerPostModels[0]; + // if (viewerPostModel != null) { + // final String postId = viewerPostModel.getPostId(); + // try { + // if (postId != null && Integer.parseInt(postId) > 0) { + // // already fetched, don't fetch again + // Log.d(TAG, "returning without fetching"); + // return; + // } + // } catch (NumberFormatException ignored) {} + // } + Log.d(TAG, "returning without fetching"); + return; + } + } + final String idOrShortCode = idOrCodeList.get(currentPostIndex); + if (isId) { + new iPostFetcher(idOrShortCode, pfl).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + return; + } + new PostFetcher(idOrShortCode, pfl).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + private void showDownloadDialog(final List postModels, + final int childPosition, + final String username) { + final List postModelsToDownload = new ArrayList<>(); + if (!session && postModels.size() > 1) { + final DialogInterface.OnClickListener clickListener = (dialog, which) -> { + if (which == DialogInterface.BUTTON_NEGATIVE) { + postModelsToDownload.addAll(postModels); + } else if (which == DialogInterface.BUTTON_POSITIVE) { + postModelsToDownload.add(postModels.get(childPosition)); + } else { + session = true; + postModelsToDownload.add(postModels.get(childPosition)); + } + if (postModelsToDownload.size() > 0) { + Utils.batchDownload(requireContext(), + username, + DownloadMethod.DOWNLOAD_POST_VIEWER, + postModelsToDownload); + } + }; + new AlertDialog.Builder(requireContext()) + .setTitle(R.string.post_viewer_download_dialog_title) + .setMessage(R.string.post_viewer_download_message) + .setNeutralButton(R.string.post_viewer_download_session, clickListener) + .setPositiveButton(R.string.post_viewer_download_current, clickListener) + .setNegativeButton(R.string.post_viewer_download_album, clickListener).show(); + } else { + Utils.batchDownload(requireContext(), + username, + DownloadMethod.DOWNLOAD_POST_VIEWER, + Collections.singletonList(postModels.get(childPosition))); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/fragments/PostViewFragmentBackup.java b/app/src/main/java/awais/instagrabber/fragments/PostViewFragmentBackup.java new file mode 100644 index 00000000..d2670880 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/fragments/PostViewFragmentBackup.java @@ -0,0 +1,574 @@ +// package awais.instagrabber.fragments; +// +// import android.content.Context; +// import android.content.Intent; +// import android.graphics.drawable.Animatable; +// import android.net.Uri; +// import android.os.AsyncTask; +// import android.os.Bundle; +// import android.os.Handler; +// import android.text.SpannableString; +// import android.view.LayoutInflater; +// import android.view.View; +// import android.view.ViewGroup; +// import android.widget.LinearLayout; +// import android.widget.RelativeLayout; +// import android.widget.TextView; +// import android.widget.Toast; +// +// import androidx.annotation.NonNull; +// import androidx.annotation.Nullable; +// import androidx.appcompat.app.AppCompatActivity; +// import androidx.core.view.GestureDetectorCompat; +// import androidx.fragment.app.Fragment; +// import androidx.lifecycle.ViewModelProvider; +// import androidx.recyclerview.widget.LinearLayoutManager; +// import androidx.recyclerview.widget.RecyclerView; +// +// import com.facebook.drawee.backends.pipeline.Fresco; +// import com.facebook.drawee.controller.BaseControllerListener; +// import com.facebook.imagepipeline.image.ImageInfo; +// import com.facebook.imagepipeline.request.ImageRequest; +// import com.facebook.imagepipeline.request.ImageRequestBuilder; +// import com.google.android.exoplayer2.SimpleExoPlayer; +// import com.google.android.exoplayer2.source.MediaSource; +// import com.google.android.exoplayer2.source.MediaSourceEventListener; +// import com.google.android.exoplayer2.source.ProgressiveMediaSource; +// import com.google.android.exoplayer2.upstream.DataSource; +// import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; +// import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory; +// import com.google.android.exoplayer2.upstream.cache.SimpleCache; +// +// import java.io.IOException; +// import java.util.List; +// +// import awais.instagrabber.R; +// import awais.instagrabber.adapters.PostsMediaAdapter; +// import awais.instagrabber.asyncs.PostFetcher; +// import awais.instagrabber.asyncs.ProfileFetcher; +// import awais.instagrabber.asyncs.i.iPostFetcher; +// import awais.instagrabber.customviews.CommentMentionClickSpan; +// import awais.instagrabber.customviews.helpers.SwipeGestureListener; +// import awais.instagrabber.databinding.FragmentPostViewBinding; +// import awais.instagrabber.fragments.main.viewmodels.BasePostViewModel; +// import awais.instagrabber.fragments.main.viewmodels.DiscoverItemViewModel; +// import awais.instagrabber.fragments.main.viewmodels.FeedViewModel; +// import awais.instagrabber.interfaces.FetchListener; +// import awais.instagrabber.interfaces.SwipeEvent; +// import awais.instagrabber.models.BasePostModel; +// import awais.instagrabber.models.PostModel; +// import awais.instagrabber.models.ProfileModel; +// import awais.instagrabber.models.ViewerPostModel; +// import awais.instagrabber.models.enums.MediaItemType; +// import awais.instagrabber.models.enums.PostItemType; +// import awais.instagrabber.utils.Constants; +// import awais.instagrabber.utils.Utils; +// +// import static awais.instagrabber.utils.Utils.settingsHelper; +// +// public class PostViewFragmentBackup extends Fragment { +// +// private FragmentPostViewBinding binding; +// private LinearLayout root; +// private AppCompatActivity fragmentActivity; +// private PostItemType postType; +// private int postIndex; +// private String postId; +// private SimpleExoPlayer player; +// private String postShortCode; +// private BasePostViewModel postViewModel; +// private ViewerPostModel currentPost; +// private List postList; +// private LinearLayout.LayoutParams containerLayoutParams; +// private BasePostModel basePostModel; +// private String prevUsername; +// private ProfileModel profileModel; +// private String postUserId; +// private CharSequence postCaption; +// +// private final View.OnClickListener onClickListener = new View.OnClickListener() { +// @Override +// public void onClick(final View v) { +// // if (v == binding.topPanel.ivProfilePic) { +// // new AlertDialog.Builder(requireContext()).setAdapter(profileDialogAdapter, profileDialogListener) +// //.setNeutralButton(R.string.cancel, null).setTitle(viewerPostModel.getUsername()).show(); +// // return; +// // } +// if (v == binding.ivToggleFullScreen) { +// // toggleFullscreen(); +// +// final LinearLayout topPanelRoot = binding.topPanel.getRoot(); +// final int iconRes; +// +// if (containerLayoutParams.weight != 3.3f) { +// containerLayoutParams.weight = 3.3f; +// iconRes = R.drawable.ic_fullscreen_exit; +// topPanelRoot.setVisibility(View.GONE); +// binding.btnDownload.setVisibility(View.VISIBLE); +// binding.bottomPanel.tvPostDate.setVisibility(View.GONE); +// } else { +// containerLayoutParams.weight = (binding.mediaList.getVisibility() == View.VISIBLE) ? 1.35f : 1.9f; +// containerLayoutParams.weight += (Utils.isEmpty(settingsHelper.getString(Constants.COOKIE))) ? 0.3f : 0; +// iconRes = R.drawable.ic_fullscreen; +// topPanelRoot.setVisibility(View.VISIBLE); +// binding.btnDownload.setVisibility(View.GONE); +// binding.bottomPanel.tvPostDate.setVisibility(View.VISIBLE); +// } +// +// binding.ivToggleFullScreen.setImageResource(iconRes); +// binding.container.setLayoutParams(containerLayoutParams); +// +// } else if (v == binding.bottomPanel.btnMute) { +// if (player != null) { +// final float intVol = player.getVolume() == 0f ? 1f : 0f; +// player.setVolume(intVol); +// binding.bottomPanel.btnMute.setImageResource(intVol == 0f ? R.drawable.ic_volume_off_24 : R.drawable.ic_volume_up_24); +// Utils.sessionVolumeFull = intVol == 1f; +// } +// } else if (v == binding.btnLike) { +// // new PostViewer.PostAction().execute("likes"); +// } else if (v == binding.btnBookmark) { +// // new PostViewer.PostAction().execute("save"); +// } else { +// // final Object tag = v.getTag(); +// // if (tag instanceof ViewerPostModel) { +// // viewerPostModel = (ViewerPostModel) tag; +// // slidePos = Math.max(0, viewerPostModel.getPosition()); +// // refreshPost(); +// // } +// } +// } +// }; +// private final PostsMediaAdapter mediaAdapter = new PostsMediaAdapter(null, onClickListener); +// private final FetchListener pfl = result -> { +// final Context context = getContext(); +// if (result == null || result.length < 1 && context != null) { +// Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); +// return; +// } +// currentPost = result[0]; +// mediaAdapter.setData(result); +// if (result.length > 1) { +// binding.mediaList.setLayoutParams(new LinearLayout.LayoutParams( +// LinearLayout.LayoutParams.MATCH_PARENT, 0, 0.55f +// )); +// containerLayoutParams.weight = 1.35f; +// containerLayoutParams.weight += (Utils.isEmpty(settingsHelper.getString(Constants.COOKIE))) ? 0.3f : 0; +// binding.container.setLayoutParams(containerLayoutParams); +// binding.mediaList.setVisibility(View.VISIBLE); +// } +// +// // viewerCaptionParent.setOnTouchListener(gestureTouchListener); +// // binding.playerView.setOnTouchListener(gestureTouchListener); +// // binding.imageViewer.setOnSingleFlingListener((e1, e2, velocityX, velocityY) -> { +// // final float diffX = e2.getX() - e1.getX(); +// // if (Math.abs(diffX) > Math.abs(e2.getY() - e1.getY()) && Math.abs(diffX) > SwipeGestureListener.SWIPE_THRESHOLD +// // && Math.abs(velocityX) > SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD) { +// // swipeEvent.onSwipe(diffX > 0); +// // return true; +// // } +// // return false; +// // }); +// +// final long commentsCount = currentPost.getCommentsCount(); +// binding.bottomPanel.commentsCount.setText(String.valueOf(commentsCount)); +// binding.bottomPanel.btnComments.setVisibility(View.VISIBLE); +// +// // binding.bottomPanel.btnComments.setOnClickListener(v -> startActivityForResult( +// // new Intent(requireContext(), CommentsViewer.class) +// // .putExtra(Constants.EXTRAS_SHORTCODE, postModel.getShortCode()) +// // .putExtra(Constants.EXTRAS_POST, currentPost.getPostId()) +// // .putExtra(Constants.EXTRAS_USER, postUserId), 6969) +// binding.bottomPanel.btnComments.setClickable(true); +// binding.bottomPanel.btnComments.setEnabled(true); +// +// if (basePostModel instanceof PostModel) { +// final PostModel postModel = (PostModel) basePostModel; +// postModel.setPostId(currentPost.getPostId()); +// postModel.setTimestamp(currentPost.getTimestamp()); +// postModel.setPostCaption(currentPost.getPostCaption()); +// // if (!ok) { +// // liked = currentPost.getLike(); +// // saved = currentPost.getBookmark(); +// // } +// } +// showCurrentPost(); +// // refreshPost(); +// }; +// private int lastSlidePos; +// private int slidePos; +// private String url; +// private SwipeEvent swipeEvent; +// private GestureDetectorCompat gestureDetector; +// +// @Override +// public void onCreate(@Nullable final Bundle savedInstanceState) { +// super.onCreate(savedInstanceState); +// fragmentActivity = (AppCompatActivity) requireActivity(); +// if (fragmentActivity.getSupportActionBar() != null) { +// fragmentActivity.getSupportActionBar().setTitle(""); +// } +// setHasOptionsMenu(true); +// } +// +// @Nullable +// @Override +// public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { +// if (root != null) { +// return root; +// } +// binding = FragmentPostViewBinding.inflate(inflater, container, false); +// root = binding.getRoot(); +// binding.mediaList.setLayoutManager(new LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)); +// binding.mediaList.setAdapter(mediaAdapter); +// binding.mediaList.setVisibility(View.GONE); +// return root; +// } +// +// @Override +// public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { +// containerLayoutParams = (LinearLayout.LayoutParams) binding.container.getLayoutParams(); +// init(); +// } +// +// @Override +// public void onDestroy() { +// super.onDestroy(); +// } +// +// private void init() { +// final Bundle arguments = getArguments(); +// if (arguments == null) return; +// final PostViewFragmentArgs fragmentArgs = PostViewFragmentArgs.fromBundle(arguments); +// postType = fragmentArgs.getPostType() == null ? null : PostItemType.valueOf(fragmentArgs.getPostType()); +// postIndex = fragmentArgs.getPostIndex(); +// postId = fragmentArgs.getPostId(); +// postShortCode = fragmentArgs.getPostShortCode(); +// setupSwipe(); +// if (postType != null && postIndex >= 0) { +// basePostModel = getBasePostFromViewModel(); +// if (basePostModel != null) { +// if (basePostModel.getShortCode() != null) { +// fetchPostFromShortCode(basePostModel.getShortCode()); +// return; +// } +// fetchPostFromPostId(basePostModel.getPostId()); +// return; +// } +// } +// // getStartPost(); +// // showCurrentPost(); +// // setupTop(); +// // setupPost(); +// // setupBottom(); +// } +// +// private void setupSwipe() { +// swipeEvent = isRight -> { +// // final List itemGetterItems; +// // final boolean isMainSwipe; +// // +// // if (postType == PostItemType.SAVED && SavedViewer.itemGetter != null) { +// // itemGetterItems = SavedViewer.itemGetter.get(postType); +// // isMainSwipe = !(itemGetterItems.size() < 1 || postType == PostItemType.SAVED && isFromShare); +// // } else if (postType != null && MainActivityBackup.itemGetter != null) { +// // itemGetterItems = MainActivityBackup.itemGetter.get(postType); +// // isMainSwipe = !(itemGetterItems.size() < 1 || postType == PostItemType.MAIN && isFromShare); +// // } else { +// // itemGetterItems = null; +// // isMainSwipe = false; +// // } +// // +// // final BasePostModel[] basePostModels = mediaAdapter.getPostModels(); +// // final int slides = basePostModels.length; +// // +// // int position = basePostModel.getPosition(); +// // +// // if (isRight) { +// // --slidePos; +// // if (!isMainSwipe && slidePos < 0) slidePos = 0; +// // if (slides > 0 && slidePos >= 0) { +// // if (basePostModels[slidePos] instanceof ViewerPostModel) { +// // currentPost = (ViewerPostModel) basePostModels[slidePos]; +// // } +// // showCurrentPost(); +// // return; +// // } +// // if (isMainSwipe && --position < 0) position = itemGetterItems.size() - 1; +// // } else { +// // ++slidePos; +// // if (!isMainSwipe && slidePos >= slides) slidePos = slides - 1; +// // if (slides > 0 && slidePos < slides) { +// // if (basePostModels[slidePos] instanceof ViewerPostModel) { +// // currentPost = (ViewerPostModel) basePostModels[slidePos]; +// // } +// // showCurrentPost(); +// // return; +// // } +// // if (isMainSwipe && ++position >= itemGetterItems.size()) position = 0; +// // } +// // +// // if (isMainSwipe) { +// // slidePos = 0; +// // ok = false; +// // Log.d("AWAISKING_APP", "swipe left <<< post[" + position + "]: " + basePostModel + " -- " + slides); +// // basePostModel = itemGetterItems.get(position); +// // basePostModel.setPosition(position); +// // showCurrentPost(); +// // } +// }; +// gestureDetector = new GestureDetectorCompat(requireContext(), new SwipeGestureListener(swipeEvent)); +// } +// +// private void fetchPostFromPostId(final String postId) { +// new iPostFetcher(postId, pfl).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); +// } +// +// private void fetchPostFromShortCode(final String shortCode) { +// new PostFetcher(shortCode, pfl) +// .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); +// } +// +// private BasePostModel getBasePostFromViewModel() { +// switch (postType) { +// case FEED: +// postViewModel = new ViewModelProvider(fragmentActivity).get(FeedViewModel.class); +// break; +// case MAIN: +// // ??? +// break; +// case SAVED: +// // ??? +// break; +// case DISCOVER: +// postViewModel = new ViewModelProvider(fragmentActivity).get(DiscoverItemViewModel.class); +// } +// if (postViewModel == null) return null; +// postList = postViewModel.getList().getValue(); +// if (postList == null) return null; +// return postList.get(postIndex); +// } +// +// private void showCurrentPost() { +// setupPostInfoBar("@" + currentPost.getUsername(), +// currentPost.getItemType(), +// currentPost.getLocationName(), +// currentPost.getLocation()); +// // postCaption = basePostModel.getPostCaption(); +// ((View) binding.bottomPanel.viewerCaption.getParent()).setVisibility(View.VISIBLE); +// // binding.bottomPanel.btnDownload.setOnClickListener(downloadClickListener); +// if (containerLayoutParams.weight != 3.3f) { +// containerLayoutParams.weight = (binding.mediaList.getVisibility() == View.VISIBLE) ? 1.35f : 1.9f; +// binding.container.setLayoutParams(containerLayoutParams); +// } +// if (binding.mediaList.getVisibility() == View.VISIBLE) { +// ViewerPostModel item = mediaAdapter.getItemAt(lastSlidePos); +// if (item != null) { +// item.setCurrentSlide(false); +// mediaAdapter.notifyItemChanged(lastSlidePos, item); +// } +// +// item = mediaAdapter.getItemAt(slidePos); +// if (item != null) { +// item.setCurrentSlide(true); +// mediaAdapter.notifyItemChanged(slidePos, item); +// } +// } +// lastSlidePos = slidePos; +// postCaption = currentPost.getPostCaption(); +// +// if (Utils.hasMentions(postCaption)) { +// binding.bottomPanel.viewerCaption.setText(Utils.getMentionText(postCaption), TextView.BufferType.SPANNABLE); +// // binding.bottomPanel.viewerCaption.setMentionClickListener((view, text, isHashtag, isLocation) -> searchUsername(text)); +// } else { +// binding.bottomPanel.viewerCaption.setMentionClickListener(null); +// binding.bottomPanel.viewerCaption.setText(postCaption); +// } +// +// // setupPostInfoBar("@" + viewerPostModel.getUsername(), viewerPostModel.getItemType(), +// // viewerPostModel.getLocationName(), viewerPostModel.getLocation()); +// +// // if (postModel instanceof PostModel) { +// // final PostModel postModel = (PostModel) this.postModel; +// // postModel.setPostId(viewerPostModel.getPostId()); +// // postModel.setTimestamp(viewerPostModel.getTimestamp()); +// // postModel.setPostCaption(viewerPostModel.getPostCaption()); +// // if (liked == true) { +// // binding.btnLike.setText(resources.getString(R.string.unlike, viewerPostModel.getLikes() +// // + ((ok && viewerPostModel.getLike() != liked) ? (liked ? 1L : -1L) : 0L))); +// // binding.btnLike.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor( +// // getApplicationContext(), R.color.btn_pink_background))); +// // } else { +// // binding.btnLike.setText(resources.getString(R.string.like, viewerPostModel.getLikes() +// // + ((ok && viewerPostModel.getLike() != liked) ? (liked ? 1L : -1L) : 0L))); +// // binding.btnLike.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor( +// // getApplicationContext(), R.color.btn_lightpink_background))); +// // } +// // if (saved == true) { +// // binding.btnBookmark.setText(R.string.unbookmark); +// // binding.btnBookmark.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor( +// // getApplicationContext(), R.color.btn_orange_background))); +// // } else { +// // binding.btnBookmark.setText(R.string.bookmark); +// // binding.btnBookmark.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor( +// // getApplicationContext(), R.color.btn_lightorange_background))); +// // } +// // } +// +// binding.bottomPanel.tvPostDate.setText(currentPost.getPostDate()); +// binding.bottomPanel.tvPostDate.setVisibility(containerLayoutParams.weight != 3.3f ? View.VISIBLE : View.GONE); +// binding.bottomPanel.tvPostDate.setSelected(true); +// +// url = currentPost.getDisplayUrl(); +// // releasePlayer(); +// +// binding.btnDownload.setVisibility(containerLayoutParams.weight == 3.3f ? View.VISIBLE : View.GONE); +// if (currentPost.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO) setupVideo(); +// else setupImage(); +// } +// +// private void setupPostInfoBar(final String username, +// final MediaItemType itemType, +// final String locationName, +// final String location) { +// if (prevUsername == null || !prevUsername.equals(username)) { +// binding.topPanel.ivProfilePic.setImageRequest(null); +// if (!Utils.isEmpty(username) && username.charAt(0) == '@') { +// new ProfileFetcher(username.substring(1), result -> { +// profileModel = result; +// +// if (result != null) { +// // final String hdProfilePic = result.getHdProfilePic(); +// // final String sdProfilePic = result.getSdProfilePic(); +// postUserId = result.getId(); +// // final boolean hdPicEmpty = Utils.isEmpty(hdProfilePic); +// binding.topPanel.ivProfilePic.setImageURI(profileModel.getSdProfilePic()); +// binding.topPanel.viewStoryPost.setOnClickListener(v -> { +// if (result.isPrivate()) { +// Toast.makeText(requireContext(), R.string.share_private_post, Toast.LENGTH_LONG).show(); +// } +// Intent sharingIntent = new Intent(Intent.ACTION_SEND); +// sharingIntent.setType("text/plain"); +// sharingIntent.putExtra(Intent.EXTRA_TEXT, "https://instagram.com/p/" + postShortCode); +// startActivity(Intent.createChooser(sharingIntent, result.isPrivate() +// ? getString(R.string.share_private_post) +// : getString(R.string.share_public_post))); +// }); +// } +// }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); +// } +// prevUsername = username; +// } +// +// final String titlePrefix = getString(itemType == MediaItemType.MEDIA_TYPE_VIDEO ? R.string.post_viewer_video_post : R.string.post_viewer_image_post); +// if (Utils.isEmpty(username)) binding.topPanel.title.setText(titlePrefix); +// else { +// final int titleLen = username.length(); +// final SpannableString spannableString = new SpannableString(username); +// spannableString.setSpan(new CommentMentionClickSpan(), 0, titleLen, 0); +// binding.topPanel.title.setText(spannableString); +// } +// +// if (location == null) { +// binding.topPanel.location.setVisibility(View.GONE); +// binding.topPanel.title.setLayoutParams(new RelativeLayout.LayoutParams( +// RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)); +// } else { +// binding.topPanel.location.setVisibility(View.VISIBLE); +// binding.topPanel.location.setText(locationName); +// // binding.topPanel.location.setOnClickListener(v -> searchUsername(location)); +// binding.topPanel.title.setLayoutParams(new RelativeLayout.LayoutParams( +// RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT +// )); +// } +// } +// +// private void setupVideo() { +// binding.playerView.setVisibility(View.VISIBLE); +// binding.bottomPanel.btnDownload.setVisibility(View.VISIBLE); +// binding.bottomPanel.btnMute.setVisibility(View.VISIBLE); +// binding.progressView.setVisibility(View.GONE); +// binding.imageViewer.setVisibility(View.GONE); +// binding.imageViewer.setController(null); +// +// if (currentPost.getVideoViews() > -1) { +// binding.bottomPanel.videoViewsContainer.setVisibility(View.VISIBLE); +// binding.bottomPanel.tvVideoViews.setText(String.valueOf(currentPost.getVideoViews())); +// } +// +// player = new SimpleExoPlayer.Builder(requireContext()).build(); +// binding.playerView.setPlayer(player); +// float vol = Utils.settingsHelper.getBoolean(Constants.MUTED_VIDEOS) ? 0f : 1f; +// if (vol == 0f && Utils.sessionVolumeFull) vol = 1f; +// +// player.setVolume(vol); +// player.setPlayWhenReady(Utils.settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS)); +// final Context context = requireContext(); +// final DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(context, "instagram"); +// final SimpleCache simpleCache = Utils.getSimpleCacheInstance(context); +// CacheDataSourceFactory cacheDataSourceFactory = null; +// if (simpleCache != null) { +// cacheDataSourceFactory = new CacheDataSourceFactory(simpleCache, dataSourceFactory); +// } +// final DataSource.Factory factory = cacheDataSourceFactory != null ? cacheDataSourceFactory : dataSourceFactory; +// final ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(factory).createMediaSource(Uri.parse(url)); +// mediaSource.addEventListener(new Handler(), new MediaSourceEventListener() { +// @Override +// public void onLoadCompleted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { +// binding.progressView.setVisibility(View.GONE); +// } +// +// @Override +// public void onLoadStarted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { +// binding.progressView.setVisibility(View.VISIBLE); +// } +// +// @Override +// public void onLoadCanceled(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { +// binding.progressView.setVisibility(View.GONE); +// } +// +// @Override +// public void onLoadError(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData, final IOException error, final boolean wasCanceled) { +// binding.progressView.setVisibility(View.GONE); +// } +// }); +// player.prepare(mediaSource); +// player.setVolume(vol); +// binding.bottomPanel.btnMute.setImageResource(vol == 0f ? R.drawable.ic_volume_up_24 : R.drawable.ic_volume_off_24); +// binding.bottomPanel.btnMute.setOnClickListener(onClickListener); +// } +// +// private void setupImage() { +// binding.bottomPanel.videoViewsContainer.setVisibility(View.GONE); +// binding.playerView.setVisibility(View.GONE); +// binding.progressView.setVisibility(View.VISIBLE); +// binding.bottomPanel.btnMute.setVisibility(View.GONE); +// binding.bottomPanel.btnDownload.setVisibility(View.VISIBLE); +// binding.imageViewer.setVisibility(View.VISIBLE); +// +// final ImageRequest requestBuilder = ImageRequestBuilder.newBuilderWithSource(Uri.parse(url)) +// .setLocalThumbnailPreviewsEnabled(true) +// .setProgressiveRenderingEnabled(true) +// .build(); +// binding.imageViewer.setController( +// Fresco.newDraweeControllerBuilder() +// .setImageRequest(requestBuilder) +// .setOldController(binding.imageViewer.getController()) +// .setLowResImageRequest(ImageRequest.fromUri(url)) +// .setControllerListener(new BaseControllerListener() { +// +// @Override +// public void onFailure(final String id, final Throwable throwable) { +// binding.progressView.setVisibility(View.GONE); +// } +// +// @Override +// public void onFinalImageSet(final String id, final ImageInfo imageInfo, final Animatable animatable) { +// binding.progressView.setVisibility(View.GONE); +// } +// }) +// .build() +// ); +// } +// } diff --git a/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java b/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java index 7818c94f..0550fa1b 100644 --- a/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java @@ -33,6 +33,8 @@ import androidx.core.content.ContextCompat; import androidx.core.view.GestureDetectorCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; +import androidx.navigation.NavDirections; +import androidx.navigation.fragment.NavHostFragment; import androidx.recyclerview.widget.LinearLayoutManager; import com.facebook.drawee.backends.pipeline.Fresco; @@ -57,7 +59,6 @@ import java.util.List; import awais.instagrabber.BuildConfig; import awais.instagrabber.R; -import awais.instagrabber.activities.PostViewer; import awais.instagrabber.adapters.StoriesAdapter; import awais.instagrabber.asyncs.CommentAction; import awais.instagrabber.asyncs.DownloadAsync; @@ -72,7 +73,6 @@ import awais.instagrabber.fragments.main.viewmodels.FeedStoriesViewModel; import awais.instagrabber.fragments.main.viewmodels.StoriesViewModel; import awais.instagrabber.interfaces.SwipeEvent; import awais.instagrabber.models.FeedStoryModel; -import awais.instagrabber.models.PostModel; import awais.instagrabber.models.StoryModel; import awais.instagrabber.models.enums.MediaItemType; import awais.instagrabber.models.stickers.PollModel; @@ -121,6 +121,7 @@ public class StoryViewerFragment extends Fragment { private int currentFeedStoryIndex; private StoriesViewModel storiesViewModel; private String currentStoryMediaId; + private boolean shouldRefresh = true; private final String cookie = settingsHelper.getString(Constants.COOKIE); private StoryViewerFragmentArgs fragmentArgs; @@ -137,6 +138,7 @@ public class StoryViewerFragment extends Fragment { @Override public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { if (root != null) { + shouldRefresh = false; return root; } binding = ActivityStoryViewerBinding.inflate(inflater, container, false); @@ -146,6 +148,7 @@ public class StoryViewerFragment extends Fragment { @Override public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { + if (!shouldRefresh) return; init(); } @@ -274,8 +277,8 @@ public class StoryViewerFragment extends Fragment { return; } final FeedStoryModel feedStoryModel = isRightSwipe - ? feedStoryModels.get(index - 1) - : feedStoryModels.size() == index + 1 ? null : feedStoryModels.get(index + 1); + ? feedStoryModels.get(index - 1) + : feedStoryModels.size() == index + 1 ? null : feedStoryModels.get(index + 1); if (feedStoryModel != null) { if (fetching) { Toast.makeText(requireContext(), R.string.be_patient, Toast.LENGTH_SHORT).show(); @@ -324,8 +327,8 @@ public class StoryViewerFragment extends Fragment { } catch (final Exception e) { if (logCollector != null) logCollector.appendException(e, LogCollector.LogFile.ACTIVITY_STORY_VIEWER, "setupListeners", - new Pair<>("swipeEvent", swipeEvent), - new Pair<>("diffX", diffX)); + new Pair<>("swipeEvent", swipeEvent), + new Pair<>("diffX", diffX)); if (BuildConfig.DEBUG) Log.e(TAG, "Error", e); } return false; @@ -342,9 +345,17 @@ public class StoryViewerFragment extends Fragment { }); binding.viewStoryPost.setOnClickListener(v -> { final Object tag = v.getTag(); - if (tag instanceof CharSequence) - startActivity(new Intent(requireContext(), PostViewer.class) - .putExtra(Constants.EXTRAS_POST, new PostModel(tag.toString(), tag.toString().matches("^[\\d]+$")))); + if (!(tag instanceof CharSequence)) return; + final String postId = tag.toString(); + final boolean isId = tag.toString().matches("^[\\d]+$"); + final String[] idsOrShortCodes = new String[]{postId}; + final NavDirections action = HashTagFragmentDirections.actionGlobalPostViewFragment( + 0, + idsOrShortCodes, + isId); + NavHostFragment.findNavController(this).navigate(action); + // startActivity(new Intent(requireContext(), PostViewer.class) + // .putExtra(Constants.EXTRAS_POST, new PostModel(, )); }); final View.OnClickListener storyActionListener = v -> { final Object tag = v.getTag(); @@ -352,10 +363,15 @@ public class StoryViewerFragment extends Fragment { poll = (PollModel) tag; if (poll.getMyChoice() > -1) { new AlertDialog.Builder(requireContext()).setTitle(R.string.voted_story_poll) - .setAdapter(new ArrayAdapter<>(requireContext(), android.R.layout.simple_list_item_1, new String[]{ - (poll.getMyChoice() == 0 ? "√ " : "") + poll.getLeftChoice() + " (" + poll.getLeftCount() + ")", - (poll.getMyChoice() == 1 ? "√ " : "") + poll.getRightChoice() + " (" + poll.getRightCount() + ")" - }), null) + .setAdapter(new ArrayAdapter<>(requireContext(), android.R.layout.simple_list_item_1, + new String[]{ + (poll.getMyChoice() == 0 ? "√ " : "") + poll + .getLeftChoice() + " (" + poll + .getLeftCount() + ")", + (poll.getMyChoice() == 1 ? "√ " : "") + poll + .getRightChoice() + " (" + poll + .getRightCount() + ")" + }), null) .setPositiveButton(R.string.ok, null) .show(); } else { @@ -567,13 +583,15 @@ public class StoryViewerFragment extends Fragment { dir = new File(dir, currentStoryUsername); if (dir.exists() || dir.mkdirs()) { - final String storyUrl = currentStory.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO ? currentStory.getVideoUrl() : currentStory.getStoryUrl(); + final String storyUrl = currentStory.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO + ? currentStory.getVideoUrl() + : currentStory.getStoryUrl(); final File saveFile = new File(dir, currentStory.getStoryMediaId() + "_" + currentStory.getTimestamp() + Utils.getExtensionFromModel(storyUrl, currentStory)); new DownloadAsync(requireContext(), storyUrl, saveFile, result -> { final int toastRes = result != null && result.exists() ? R.string.downloader_complete - : R.string.downloader_error_download_file; + : R.string.downloader_error_download_file; Toast.makeText(requireContext(), toastRes, Toast.LENGTH_SHORT).show(); }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -598,8 +616,16 @@ public class StoryViewerFragment extends Fragment { .setImageRequest(requestBuilder) .setOldController(binding.imageViewer.getController()) .setControllerListener(new BaseControllerListener() { + @Override - public void onFinalImageSet(final String id, final ImageInfo imageInfo, final Animatable animatable) { + public void onFailure(final String id, final Throwable throwable) { + binding.progressView.setVisibility(View.GONE); + } + + @Override + public void onFinalImageSet(final String id, + final ImageInfo imageInfo, + final Animatable animatable) { if (menuDownload != null) { menuDownload.setVisible(true); } @@ -627,7 +653,10 @@ public class StoryViewerFragment extends Fragment { .createMediaSource(Uri.parse(url)); mediaSource.addEventListener(new Handler(), new MediaSourceEventListener() { @Override - public void onLoadCompleted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + public void onLoadCompleted(final int windowIndex, + @Nullable final MediaSource.MediaPeriodId mediaPeriodId, + final LoadEventInfo loadEventInfo, + final MediaLoadData mediaLoadData) { if (menuDownload != null) menuDownload.setVisible(true); if (currentStory.canReply() && menuDm != null && !Utils.isEmpty(cookie)) menuDm.setVisible(true); @@ -635,7 +664,10 @@ public class StoryViewerFragment extends Fragment { } @Override - public void onLoadStarted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + public void onLoadStarted(final int windowIndex, + @Nullable final MediaSource.MediaPeriodId mediaPeriodId, + final LoadEventInfo loadEventInfo, + final MediaLoadData mediaLoadData) { if (menuDownload != null) menuDownload.setVisible(true); if (currentStory.canReply() && menuDm != null && !Utils.isEmpty(cookie)) menuDm.setVisible(true); @@ -643,12 +675,20 @@ public class StoryViewerFragment extends Fragment { } @Override - public void onLoadCanceled(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + public void onLoadCanceled(final int windowIndex, + @Nullable final MediaSource.MediaPeriodId mediaPeriodId, + final LoadEventInfo loadEventInfo, + final MediaLoadData mediaLoadData) { binding.progressView.setVisibility(View.GONE); } @Override - public void onLoadError(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData, final IOException error, final boolean wasCanceled) { + public void onLoadError(final int windowIndex, + @Nullable final MediaSource.MediaPeriodId mediaPeriodId, + final LoadEventInfo loadEventInfo, + final MediaLoadData mediaLoadData, + final IOException error, + final boolean wasCanceled) { if (menuDownload != null) menuDownload.setVisible(false); if (menuDm != null) menuDm.setVisible(false); binding.progressView.setVisibility(View.GONE); diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java index 9519b02a..0a7e97fa 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java @@ -48,6 +48,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh private AsyncTask currentlyRunning; private InboxThreadModelListViewModel listViewModel; public static boolean refreshPlease = false; + private boolean shouldRefresh = true; private final FetchListener fetchListener = new FetchListener() { @Override @@ -89,6 +90,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh final ViewGroup container, final Bundle savedInstanceState) { if (root != null) { + shouldRefresh = false; return root; } binding = FragmentDirectMessagesInboxBinding.inflate(inflater, container, false); @@ -99,16 +101,22 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh layoutManager = new LinearLayoutManager(requireContext()); inboxList.setLayoutManager(layoutManager); final DirectMessageInboxAdapter inboxAdapter = new DirectMessageInboxAdapter(inboxThreadModel -> { - final NavDirections action = DirectMessageInboxFragmentDirections.actionDMInboxFragmentToDMThreadFragment(inboxThreadModel.getThreadId(), inboxThreadModel.getThreadTitle()); + final NavDirections action = DirectMessageInboxFragmentDirections + .actionDMInboxFragmentToDMThreadFragment(inboxThreadModel.getThreadId(), inboxThreadModel.getThreadTitle()); NavHostFragment.findNavController(this).navigate(action); }); inboxList.setAdapter(inboxAdapter); listViewModel = new ViewModelProvider(this).get(InboxThreadModelListViewModel.class); listViewModel.getList().observe(fragmentActivity, inboxAdapter::submitList); - initData(); return root; } + @Override + public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { + if (!shouldRefresh) return; + initData(); + } + @Override public void onRefresh() { endCursor = null; @@ -130,7 +138,9 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh @Override public void onDestroy() { super.onDestroy(); - listViewModel.getList().postValue(Collections.emptyList()); + if (listViewModel != null) { + listViewModel.getList().postValue(Collections.emptyList()); + } } private void initData() { diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java index 42fa0b73..952267c9 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java @@ -210,8 +210,10 @@ public class DirectMessageThreadFragment extends Fragment { switch (itemType) { case MEDIA_SHARE: case CLIP: - startActivity(new Intent(requireContext(), PostViewer.class) - .putExtra(Constants.EXTRAS_POST, new PostModel(directItemModel.getMediaModel().getCode(), false))); + final long postId = directItemModel.getMediaModel().getPk(); + final boolean isId = true; + // startActivity(new Intent(requireContext(), PostViewer.class) + // .putExtra(Constants.EXTRAS_POST, new PostModel(postId, false))); break; case LINK: Intent linkIntent = new Intent(Intent.ACTION_VIEW); diff --git a/app/src/main/java/awais/instagrabber/fragments/main/DiscoverFragment.java b/app/src/main/java/awais/instagrabber/fragments/main/DiscoverFragment.java index 846fa53d..09453b7b 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/DiscoverFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/DiscoverFragment.java @@ -1,6 +1,5 @@ package awais.instagrabber.fragments.main; -import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.view.ActionMode; @@ -19,6 +18,8 @@ import androidx.annotation.Nullable; import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; +import androidx.navigation.NavDirections; +import androidx.navigation.fragment.NavHostFragment; import java.util.ArrayList; import java.util.Arrays; @@ -27,7 +28,6 @@ import java.util.List; import awais.instagrabber.R; import awais.instagrabber.activities.MainActivity; -import awais.instagrabber.activities.PostViewer; import awais.instagrabber.adapters.DiscoverAdapter; import awais.instagrabber.asyncs.DiscoverFetcher; import awais.instagrabber.asyncs.i.iTopicFetcher; @@ -40,10 +40,7 @@ import awais.instagrabber.fragments.main.viewmodels.DiscoverItemViewModel; import awais.instagrabber.interfaces.FetchListener; import awais.instagrabber.models.DiscoverItemModel; import awais.instagrabber.models.DiscoverTopicModel; -import awais.instagrabber.models.PostModel; import awais.instagrabber.models.enums.DownloadMethod; -import awais.instagrabber.models.enums.ItemGetType; -import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Utils; public class DiscoverFragment extends Fragment { @@ -134,9 +131,9 @@ public class DiscoverFragment extends Fragment { if (item.getItemId() == R.id.action_download) { if (discoverAdapter == null) return false; Utils.batchDownload(requireContext(), - null, - DownloadMethod.DOWNLOAD_DISCOVER, - discoverAdapter.getSelectedModels()); + null, + DownloadMethod.DOWNLOAD_DISCOVER, + discoverAdapter.getSelectedModels()); checkAndResetAction(); return true; } @@ -183,7 +180,8 @@ public class DiscoverFragment extends Fragment { binding.discoverSwipeRefreshLayout.setRefreshing(true); if (lazyLoader != null) lazyLoader.resetState(); discoverItemViewModel.getList().postValue(Collections.emptyList()); - new DiscoverFetcher(currentTopic, null, rankToken, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new DiscoverFetcher(currentTopic, null, rankToken, discoverFetchListener, false) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } } @@ -205,10 +203,25 @@ public class DiscoverFragment extends Fragment { return; } if (checkAndResetAction()) return; - startActivity(new Intent(requireContext(), PostViewer.class) - .putExtra(Constants.EXTRAS_INDEX, position) - .putExtra(Constants.EXTRAS_TYPE, ItemGetType.DISCOVER_ITEMS) - .putExtra(Constants.EXTRAS_POST, new PostModel(model.getShortCode(), false))); + // startActivity(new Intent(requireContext(), PostViewer.class) + // .putExtra(Constants.EXTRAS_INDEX, position) + // .putExtra(Constants.EXTRAS_TYPE, PostItemType.DISCOVER) + // .putExtra(Constants.EXTRAS_POST, new PostModel(model.getShortCode(), false))); + final List discoverItemModels = discoverItemViewModel.getList().getValue(); + if (discoverItemModels == null || discoverItemModels.size() == 0) return; + if (discoverItemModels.get(0) == null) return; + final String postId = discoverItemModels.get(0).getPostId(); + final boolean isId = postId != null; + final String[] idsOrShortCodes = new String[discoverItemModels.size()]; + for (int i = 0; i < discoverItemModels.size(); i++) { + idsOrShortCodes[i] = isId ? discoverItemModels.get(i).getPostId() + : discoverItemModels.get(i).getShortCode(); + } + final NavDirections action = DiscoverFragmentDirections.actionGlobalPostViewFragment( + position, + idsOrShortCodes, + isId); + NavHostFragment.findNavController(this).navigate(action); }, (model, position) -> { if (!discoverAdapter.isSelecting()) { checkAndResetAction(); @@ -229,7 +242,8 @@ public class DiscoverFragment extends Fragment { lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { if (discoverHasMore) { binding.discoverSwipeRefreshLayout.setRefreshing(true); - new DiscoverFetcher(currentTopic, discoverEndMaxId, rankToken, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new DiscoverFetcher(currentTopic, discoverEndMaxId, rankToken, discoverFetchListener, false) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); discoverEndMaxId = null; } }); diff --git a/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java b/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java index 2e742a27..6f441bc4 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java @@ -37,7 +37,6 @@ import java.util.Map; import awais.instagrabber.R; import awais.instagrabber.activities.CommentsViewer; import awais.instagrabber.activities.MainActivity; -import awais.instagrabber.activities.PostViewer; import awais.instagrabber.adapters.FeedAdapter; import awais.instagrabber.adapters.FeedStoriesAdapter; import awais.instagrabber.adapters.viewholder.feed.FeedItemViewHolder; @@ -57,7 +56,6 @@ import awais.instagrabber.models.PostModel; import awais.instagrabber.models.ProfileModel; import awais.instagrabber.models.ViewerPostModel; import awais.instagrabber.models.enums.DownloadMethod; -import awais.instagrabber.models.enums.ItemGetType; import awais.instagrabber.models.enums.MediaItemType; import awais.instagrabber.services.ServiceCallback; import awais.instagrabber.services.StoriesService; @@ -70,7 +68,7 @@ public class FeedFragment extends Fragment { private static final String TAG = "FeedFragment"; private static final double MAX_VIDEO_HEIGHT = 0.9 * Utils.displayMetrics.heightPixels; private static final int RESIZED_VIDEO_HEIGHT = (int) (0.8 * Utils.displayMetrics.heightPixels); - public static final boolean SHOULD_AUTO_PLAY = settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS); + private static final boolean SHOULD_AUTO_PLAY = settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS); private MainActivity fragmentActivity; private CoordinatorLayout root; @@ -112,12 +110,16 @@ public class FeedFragment extends Fragment { final FeedModel feedModel = thumbToFeedMap.get(thumbUri.toString()); if (feedModel == null) return; int requiredWidth = Utils.displayMetrics.widthPixels; - int resultingHeight = Utils.getResultingHeight(requiredWidth, encodedHeight, encodedWidth); - if (feedModel.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO && resultingHeight >= MAX_VIDEO_HEIGHT) { + int resultingHeight = Utils + .getResultingHeight(requiredWidth, encodedHeight, encodedWidth); + if (feedModel + .getItemType() == MediaItemType.MEDIA_TYPE_VIDEO && resultingHeight >= MAX_VIDEO_HEIGHT) { // If its a video and the height is too large, need to reduce the height, // so that entire video fits on screen resultingHeight = RESIZED_VIDEO_HEIGHT; - requiredWidth = Utils.getResultingWidth(RESIZED_VIDEO_HEIGHT, resultingHeight, requiredWidth); + requiredWidth = Utils.getResultingWidth(RESIZED_VIDEO_HEIGHT, + resultingHeight, + requiredWidth); } feedModel.setImageWidth(requiredWidth); feedModel.setImageHeight(resultingHeight); @@ -133,7 +135,9 @@ public class FeedFragment extends Fragment { public void updateAdapter() { if (failed + success != result.length) return; - final List finalList = currentFeedModelList == null || currentFeedModelList.isEmpty() ? new ArrayList<>() : new ArrayList<>(currentFeedModelList); + final List finalList = currentFeedModelList == null || currentFeedModelList.isEmpty() + ? new ArrayList<>() + : new ArrayList<>(currentFeedModelList); finalList.addAll(Arrays.asList(result)); feedViewModel.getList().postValue(finalList); final PostModel feedPostModel = result[result.length - 1]; @@ -147,7 +151,8 @@ public class FeedFragment extends Fragment { }; for (final FeedModel feedModel : result) { - final DataSource ds = Fresco.getImagePipeline().prefetchToBitmapCache(ImageRequest.fromUri(feedModel.getThumbnailUrl()), null); + final DataSource ds = Fresco.getImagePipeline() + .prefetchToBitmapCache(ImageRequest.fromUri(feedModel.getThumbnailUrl()), null); ds.subscribe(subscriber, UiThreadImmediateExecutorService.getInstance()); } } @@ -159,7 +164,7 @@ public class FeedFragment extends Fragment { return; } if (isLocation) { - final NavDirections action = FeedFragmentDirections.actionFeedFragmentToLocationFragment(text); + final NavDirections action = FeedFragmentDirections.actionGlobalLocationFragment(text); NavHostFragment.findNavController(this).navigate(action); return; } @@ -172,8 +177,7 @@ public class FeedFragment extends Fragment { final FeedModel feedModel = (FeedModel) tag; if (v instanceof RamboTextView) { - if (feedModel.isMentionClicked()) - feedModel.toggleCaption(); + if (feedModel.isMentionClicked()) feedModel.toggleCaption(); feedModel.setMentionClicked(false); if (!FeedItemViewHolder.expandCollapseTextView((RamboTextView) v, feedModel.getPostCaption())) feedModel.toggleCaption(); @@ -184,16 +188,31 @@ public class FeedFragment extends Fragment { switch (id) { case R.id.btnComments: startActivity(new Intent(requireContext(), CommentsViewer.class) - .putExtra(Constants.EXTRAS_SHORTCODE, feedModel.getShortCode()) - .putExtra(Constants.EXTRAS_POST, feedModel.getPostId()) - .putExtra(Constants.EXTRAS_USER, feedModel.getProfileModel().getId())); + .putExtra(Constants.EXTRAS_SHORTCODE, feedModel.getShortCode()) + .putExtra(Constants.EXTRAS_POST, feedModel.getPostId()) + .putExtra(Constants.EXTRAS_USER, feedModel.getProfileModel().getId())); break; case R.id.viewStoryPost: - startActivity(new Intent(requireContext(), PostViewer.class) - .putExtra(Constants.EXTRAS_INDEX, feedModel.getPosition()) - .putExtra(Constants.EXTRAS_POST, new PostModel(feedModel.getShortCode(), false)) - .putExtra(Constants.EXTRAS_TYPE, ItemGetType.FEED_ITEMS)); + // startActivity(new Intent(requireContext(), PostViewer.class) + // .putExtra(Constants.EXTRAS_INDEX, feedModel.getPosition()) + // .putExtra(Constants.EXTRAS_POST, new PostModel(feedModel.getShortCode(), false)) + // .putExtra(Constants.EXTRAS_TYPE, ItemGetType.FEED_ITEMS)); + final List feedModels = feedViewModel.getList().getValue(); + if (feedModels == null || feedModels.size() == 0) return; + if (feedModels.get(0) == null) return; + final String postId = feedModels.get(0).getPostId(); + final boolean isId = postId != null; + final String[] idsOrShortCodes = new String[feedModels.size()]; + for (int i = 0; i < feedModels.size(); i++) { + idsOrShortCodes[i] = isId ? feedModels.get(i).getPostId() + : feedModels.get(i).getShortCode(); + } + final NavDirections action = FeedFragmentDirections.actionGlobalPostViewFragment( + feedModel.getPosition(), + idsOrShortCodes, + isId); + NavHostFragment.findNavController(this).navigate(action); break; case R.id.btnDownload: @@ -202,8 +221,12 @@ public class FeedFragment extends Fragment { final ViewerPostModel[] sliderItems = feedModel.getSliderItems(); - if (feedModel.getItemType() != MediaItemType.MEDIA_TYPE_SLIDER || sliderItems == null || sliderItems.length == 1) - Utils.batchDownload(requireContext(), username, DownloadMethod.DOWNLOAD_FEED, Collections.singletonList(feedModel)); + if (feedModel + .getItemType() != MediaItemType.MEDIA_TYPE_SLIDER || sliderItems == null || sliderItems.length == 1) + Utils.batchDownload(requireContext(), + username, + DownloadMethod.DOWNLOAD_FEED, + Collections.singletonList(feedModel)); else { final ArrayList postModels = new ArrayList<>(); final DialogInterface.OnClickListener clickListener1 = (dialog, which) -> { @@ -213,8 +236,7 @@ public class FeedFragment extends Fragment { for (final ViewerPostModel sliderItem : sliderItems) { if (sliderItem != null) { - if (!breakWhenFoundSelected) - postModels.add(sliderItem); + if (!breakWhenFoundSelected) postModels.add(sliderItem); else if (sliderItem.isSelected()) { postModels.add(sliderItem); break; @@ -223,16 +245,21 @@ public class FeedFragment extends Fragment { } // shows 0 items on first item of viewpager cause onPageSelected hasn't been called yet - if (breakWhenFoundSelected && postModels.size() == 0) + if (breakWhenFoundSelected && postModels.size() == 0) { postModels.add(sliderItems[0]); - - if (postModels.size() > 0) - Utils.batchDownload(requireContext(), username, DownloadMethod.DOWNLOAD_FEED, postModels); + } + if (postModels.size() > 0) { + Utils.batchDownload(requireContext(), + username, + DownloadMethod.DOWNLOAD_FEED, + postModels); + } }; new AlertDialog.Builder(requireContext()) - .setTitle(R.string.post_viewer_download_dialog_title) - .setPositiveButton(R.string.post_viewer_download_current, clickListener1) + .setTitle(R.string.post_viewer_download_dialog_title).setPositiveButton( + R.string.post_viewer_download_current, + clickListener1) .setNegativeButton(R.string.post_viewer_download_album, clickListener1) .show(); } @@ -240,8 +267,7 @@ public class FeedFragment extends Fragment { case R.id.ivProfilePic: profileModel = feedModel.getProfileModel(); - if (profileModel != null) - mentionClickListener.onClick(null, profileModel.getUsername(), false, false); + if (profileModel != null) mentionClickListener.onClick(null, profileModel.getUsername(), false, false); break; } }; @@ -251,6 +277,7 @@ public class FeedFragment extends Fragment { super.onCreate(savedInstanceState); fragmentActivity = (MainActivity) requireActivity(); storiesService = StoriesService.getInstance(); + // feedService = FeedService.getInstance(); } @Override @@ -273,6 +300,7 @@ public class FeedFragment extends Fragment { setupFeedStories(); setupFeed(); shouldRefresh = false; + // feedService.getFeed(11, null); } @Override @@ -315,17 +343,15 @@ public class FeedFragment extends Fragment { private void fetchFeed() { binding.feedSwipeRefreshLayout.setRefreshing(true); - new FeedFetcher(feedEndCursor, feedFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new FeedFetcher(feedEndCursor, feedFetchListener) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); feedEndCursor = null; } private void setupFeedStories() { final FeedStoriesViewModel feedStoriesViewModel = new ViewModelProvider(fragmentActivity).get(FeedStoriesViewModel.class); final FeedStoriesAdapter feedStoriesAdapter = new FeedStoriesAdapter((model, position) -> { - final NavDirections action = FeedFragmentDirections.actionFeedFragmentToStoryViewerFragment( - position, - null, - false); + final NavDirections action = FeedFragmentDirections.actionFeedFragmentToStoryViewerFragment(position, null, false); NavHostFragment.findNavController(this).navigate(action); }); binding.feedStoriesRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)); diff --git a/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java b/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java index 94614545..56e0cbd1 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java @@ -37,10 +37,10 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import awais.instagrabber.ProfileNavGraphDirections; import awais.instagrabber.R; import awais.instagrabber.activities.FollowViewer; import awais.instagrabber.activities.MainActivity; -import awais.instagrabber.activities.PostViewer; import awais.instagrabber.activities.SavedViewer; import awais.instagrabber.adapters.PostsAdapter; import awais.instagrabber.asyncs.HighlightsFetcher; @@ -61,7 +61,6 @@ import awais.instagrabber.models.PostModel; import awais.instagrabber.models.ProfileModel; import awais.instagrabber.models.StoryModel; import awais.instagrabber.models.enums.DownloadMethod; -import awais.instagrabber.models.enums.ItemGetType; import awais.instagrabber.repositories.responses.FriendshipRepoChangeRootResponse; import awais.instagrabber.repositories.responses.FriendshipRepoRestrictRootResponse; import awais.instagrabber.services.FriendshipService; @@ -97,8 +96,10 @@ public class ProfileFragment extends Fragment { ; private final Runnable usernameSettingRunnable = () -> { final ActionBar actionBar = fragmentActivity.getSupportActionBar(); - if (actionBar != null) { - actionBar.setTitle(username.substring(1)); + if (actionBar != null && !Utils.isEmpty(username)) { + final String finalUsername = username.startsWith("@") ? username.substring(1) + : username; + actionBar.setTitle(finalUsername); } }; private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) { @@ -112,28 +113,35 @@ public class ProfileFragment extends Fragment { remove(); } }; - private final PrimaryActionModeCallback multiSelectAction = new PrimaryActionModeCallback(R.menu.multi_select_download_menu, new CallbacksHelper() { - @Override - public void onDestroy(final ActionMode mode) { - onBackPressedCallback.handleOnBackPressed(); - } + private final PrimaryActionModeCallback multiSelectAction = new PrimaryActionModeCallback(R.menu.multi_select_download_menu, + new CallbacksHelper() { + @Override + public void onDestroy( + final ActionMode mode) { + onBackPressedCallback + .handleOnBackPressed(); + } - @Override - public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) { - if (item.getItemId() == R.id.action_download) { - if (postsAdapter == null || username == null) { - return false; - } - Utils.batchDownload(requireContext(), - username, - DownloadMethod.DOWNLOAD_MAIN, - postsAdapter.getSelectedModels()); - checkAndResetAction(); - return true; - } - return false; - } - }); + @Override + public boolean onActionItemClicked( + final ActionMode mode, + final MenuItem item) { + if (item.getItemId() == R.id.action_download) { + if (postsAdapter == null || username == null) { + return false; + } + Utils.batchDownload( + requireContext(), + username, + DownloadMethod.DOWNLOAD_MAIN, + postsAdapter + .getSelectedModels()); + checkAndResetAction(); + return true; + } + return false; + } + }); private final FetchListener postsFetchListener = new FetchListener() { @Override public void onResult(final PostModel[] result) { @@ -142,7 +150,8 @@ public class ProfileFragment extends Fragment { binding.mainPosts.post(() -> binding.mainPosts.setVisibility(View.VISIBLE)); // final int oldSize = mainActivity.allItems.size(); final List postModels = postsViewModel.getList().getValue(); - final List finalList = postModels == null || postModels.isEmpty() ? new ArrayList<>() : new ArrayList<>(postModels); + final List finalList = postModels == null || postModels + .isEmpty() ? new ArrayList<>() : new ArrayList<>(postModels); finalList.addAll(Arrays.asList(result)); postsViewModel.getList().postValue(finalList); PostModel model = null; @@ -163,16 +172,19 @@ public class ProfileFragment extends Fragment { private final MentionClickListener mentionClickListener = (view, text, isHashtag, isLocation) -> { Log.d(TAG, "action..."); if (isHashtag) { - final NavDirections action = ProfileFragmentDirections.actionGlobalHashTagFragment(text); + final NavDirections action = ProfileFragmentDirections + .actionGlobalHashTagFragment(text); NavHostFragment.findNavController(this).navigate(action); return; } if (isLocation) { - final NavDirections action = FeedFragmentDirections.actionFeedFragmentToLocationFragment(text); + final NavDirections action = FeedFragmentDirections.actionGlobalLocationFragment(text); NavHostFragment.findNavController(this).navigate(action); return; } - final NavDirections action = ProfileFragmentDirections.actionGlobalProfileFragment("@" + text); + final ProfileNavGraphDirections.ActionGlobalProfileFragment action = ProfileFragmentDirections + .actionGlobalProfileFragment(); + action.setUsername("@" + text); NavHostFragment.findNavController(this).navigate(action); }; @@ -189,7 +201,8 @@ public class ProfileFragment extends Fragment { final Bundle savedInstanceState) { if (root != null) { if (getArguments() != null) { - final ProfileFragmentArgs fragmentArgs = ProfileFragmentArgs.fromBundle(getArguments()); + final ProfileFragmentArgs fragmentArgs = ProfileFragmentArgs + .fromBundle(getArguments()); if (!fragmentArgs.getUsername().equals(username)) { shouldRefresh = true; return root; @@ -243,7 +256,7 @@ public class ProfileFragment extends Fragment { private void fetchUsername() { final String uid = Utils.getUserIdFromCookie(cookie); - if (username == null && uid != null) { + if (Utils.isEmpty(username) && uid != null) { final FetchListener fetchListener = username -> { if (Utils.isEmpty(username)) return; this.username = username; @@ -251,21 +264,23 @@ public class ProfileFragment extends Fragment { fetchProfileDetails(); // adds cookies to database for quick access final DataBox.CookieModel cookieModel = Utils.dataBox.getCookie(uid); - if (Utils.dataBox.getCookieCount() == 0 || cookieModel == null || Utils.isEmpty(cookieModel.getUsername())) + if (Utils.dataBox.getCookieCount() == 0 || cookieModel == null || Utils + .isEmpty(cookieModel.getUsername())) Utils.dataBox.addUserCookie(new DataBox.CookieModel(uid, username, cookie)); }; boolean found = false; final DataBox.CookieModel cookieModel = Utils.dataBox.getCookie(uid); if (cookieModel != null) { final String username = cookieModel.getUsername(); - if (username != null) { + if (!Utils.isEmpty(username)) { found = true; fetchListener.onResult("@" + username); } } if (!found) { // if not in database, fetch info from instagram - new UsernameFetcher(uid, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new UsernameFetcher(uid, fetchListener) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } return; } @@ -283,33 +298,34 @@ public class ProfileFragment extends Fragment { private void setProfileDetails() { if (profileModel == null) { binding.swipeRefreshLayout.setRefreshing(false); - Toast.makeText(requireContext(), R.string.error_loading_profile, Toast.LENGTH_SHORT).show(); + Toast.makeText(requireContext(), R.string.error_loading_profile, Toast.LENGTH_SHORT) + .show(); return; } binding.isVerified.setVisibility(profileModel.isVerified() ? View.VISIBLE : View.GONE); final String profileId = profileModel.getId(); if (settingsHelper.getBoolean(Constants.STORIESIG)) { - new iStoryStatusFetcher( - profileId, - profileModel.getUsername(), - false, - false, - (!isLoggedIn && settingsHelper.getBoolean(Constants.STORIESIG)), - false, - result -> { - storyModels = result; - if (result != null && result.length > 0) { - binding.mainProfileImage.setStoriesBorder(); - } - }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new iStoryStatusFetcher(profileId, + profileModel.getUsername(), + false, + false, + (!isLoggedIn && settingsHelper.getBoolean(Constants.STORIESIG)), + false, + result -> { + storyModels = result; + if (result != null && result.length > 0) { + binding.mainProfileImage.setStoriesBorder(); + } + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - new HighlightsFetcher(profileId, (!isLoggedIn && settingsHelper.getBoolean(Constants.STORIESIG)), result -> { - if (result != null && result.length > 0) { - binding.highlightsList.setVisibility(View.VISIBLE); - // highlightsAdapter.setData(result); - } else - binding.highlightsList.setVisibility(View.GONE); - }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new HighlightsFetcher(profileId, + (!isLoggedIn && settingsHelper.getBoolean(Constants.STORIESIG)), + result -> { + if (result != null && result.length > 0) { + binding.highlightsList.setVisibility(View.VISIBLE); + // highlightsAdapter.setData(result); + } else binding.highlightsList.setVisibility(View.GONE); + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } if (isLoggedIn) { @@ -319,9 +335,10 @@ public class ProfileFragment extends Fragment { binding.btnSaved.setVisibility(View.VISIBLE); binding.btnLiked.setVisibility(View.VISIBLE); binding.btnSaved.setText(R.string.saved); - ViewCompat.setBackgroundTintList( - binding.btnSaved, - ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_orange_background))); + ViewCompat.setBackgroundTintList(binding.btnSaved, + ColorStateList.valueOf(ContextCompat.getColor( + requireContext(), + R.color.btn_orange_background))); } else { binding.btnTagged.setVisibility(View.GONE); binding.btnSaved.setVisibility(View.GONE); @@ -329,65 +346,75 @@ public class ProfileFragment extends Fragment { binding.btnFollow.setVisibility(View.VISIBLE); if (profileModel.getFollowing()) { binding.btnFollow.setText(R.string.unfollow); - ViewCompat.setBackgroundTintList( - binding.btnFollow, - ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_purple_background))); + ViewCompat.setBackgroundTintList(binding.btnFollow, + ColorStateList.valueOf(ContextCompat.getColor( + requireContext(), + R.color.btn_purple_background))); } else if (profileModel.getRequested()) { binding.btnFollow.setText(R.string.cancel); - ViewCompat.setBackgroundTintList( - binding.btnFollow, - ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_purple_background))); + ViewCompat.setBackgroundTintList(binding.btnFollow, + ColorStateList.valueOf(ContextCompat.getColor( + requireContext(), + R.color.btn_purple_background))); } else { binding.btnFollow.setText(R.string.follow); - ViewCompat.setBackgroundTintList( - binding.btnFollow, - ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_pink_background))); + ViewCompat.setBackgroundTintList(binding.btnFollow, + ColorStateList.valueOf(ContextCompat.getColor( + requireContext(), + R.color.btn_pink_background))); } binding.btnRestrict.setVisibility(View.VISIBLE); if (profileModel.getRestricted()) { binding.btnRestrict.setText(R.string.unrestrict); - ViewCompat.setBackgroundTintList( - binding.btnRestrict, - ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_green_background))); + ViewCompat.setBackgroundTintList(binding.btnRestrict, + ColorStateList.valueOf(ContextCompat.getColor( + requireContext(), + R.color.btn_green_background))); } else { binding.btnRestrict.setText(R.string.restrict); - ViewCompat.setBackgroundTintList( - binding.btnRestrict, - ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_orange_background))); + ViewCompat.setBackgroundTintList(binding.btnRestrict, + ColorStateList.valueOf(ContextCompat.getColor( + requireContext(), + R.color.btn_orange_background))); } binding.btnBlock.setVisibility(View.VISIBLE); binding.btnTagged.setVisibility(View.VISIBLE); if (profileModel.getBlocked()) { binding.btnBlock.setText(R.string.unblock); - ViewCompat.setBackgroundTintList( - binding.btnBlock, - ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_green_background))); + ViewCompat.setBackgroundTintList(binding.btnBlock, + ColorStateList.valueOf(ContextCompat.getColor( + requireContext(), + R.color.btn_green_background))); } else { binding.btnBlock.setText(R.string.block); - ViewCompat.setBackgroundTintList( - binding.btnBlock, - ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_red_background))); + ViewCompat.setBackgroundTintList(binding.btnBlock, + ColorStateList.valueOf(ContextCompat.getColor( + requireContext(), + R.color.btn_red_background))); } } } else { if (Utils.dataBox.getFavorite(username) != null) { binding.btnFollow.setText(R.string.unfavorite_short); - ViewCompat.setBackgroundTintList( - binding.btnFollow, - ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_purple_background))); + ViewCompat.setBackgroundTintList(binding.btnFollow, + ColorStateList.valueOf(ContextCompat.getColor( + requireContext(), + R.color.btn_purple_background))); } else { binding.btnFollow.setText(R.string.favorite_short); - ViewCompat.setBackgroundTintList( - binding.btnFollow, - ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_pink_background))); + ViewCompat.setBackgroundTintList(binding.btnFollow, + ColorStateList.valueOf(ContextCompat.getColor( + requireContext(), + R.color.btn_pink_background))); } binding.btnFollow.setVisibility(View.VISIBLE); if (!profileModel.isReallyPrivate()) { binding.btnRestrict.setVisibility(View.VISIBLE); binding.btnRestrict.setText(R.string.tagged); - ViewCompat.setBackgroundTintList( - binding.btnRestrict, - ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_blue_background))); + ViewCompat.setBackgroundTintList(binding.btnRestrict, + ColorStateList.valueOf(ContextCompat.getColor( + requireContext(), + R.color.btn_blue_background))); } } @@ -398,26 +425,30 @@ public class ProfileFragment extends Fragment { final String postCount = String.valueOf(profileModel.getPostCount()); - SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count, postCount)); + SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count, + postCount)); span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); binding.mainPostCount.setText(span); final String followersCountStr = String.valueOf(followersCount); final int followersCountStrLen = followersCountStr.length(); - span = new SpannableStringBuilder(getString(R.string.main_posts_followers, followersCountStr)); + span = new SpannableStringBuilder(getString(R.string.main_posts_followers, + followersCountStr)); span.setSpan(new RelativeSizeSpan(1.2f), 0, followersCountStrLen, 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, followersCountStrLen, 0); binding.mainFollowers.setText(span); final String followingCountStr = String.valueOf(followingCount); final int followingCountStrLen = followingCountStr.length(); - span = new SpannableStringBuilder(getString(R.string.main_posts_following, followingCountStr)); + span = new SpannableStringBuilder(getString(R.string.main_posts_following, + followingCountStr)); span.setSpan(new RelativeSizeSpan(1.2f), 0, followingCountStrLen, 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, followingCountStrLen, 0); binding.mainFollowing.setText(span); - binding.mainFullName.setText(Utils.isEmpty(profileModel.getName()) ? profileModel.getUsername() : profileModel.getName()); + binding.mainFullName.setText(Utils.isEmpty(profileModel.getName()) ? profileModel + .getUsername() : profileModel.getName()); CharSequence biography = profileModel.getBiography(); binding.mainBiography.setCaptionIsExpandable(true); @@ -447,13 +478,18 @@ public class ProfileFragment extends Fragment { binding.mainFollowers.setClickable(true); if (isLoggedIn) { - final View.OnClickListener followClickListener = v -> startActivity(new Intent(requireContext(), FollowViewer.class) - .putExtra(Constants.EXTRAS_FOLLOWERS, v == binding.mainFollowers) - .putExtra(Constants.EXTRAS_NAME, profileModel.getUsername()) - .putExtra(Constants.EXTRAS_ID, profileId)); + final View.OnClickListener followClickListener = v -> startActivity(new Intent( + requireContext(), + FollowViewer.class).putExtra(Constants.EXTRAS_FOLLOWERS, + v == binding.mainFollowers) + .putExtra(Constants.EXTRAS_NAME, + profileModel.getUsername()) + .putExtra(Constants.EXTRAS_ID, profileId)); - binding.mainFollowers.setOnClickListener(followersCount > 0 ? followClickListener : null); - binding.mainFollowing.setOnClickListener(followingCount > 0 ? followClickListener : null); + binding.mainFollowers + .setOnClickListener(followersCount > 0 ? followClickListener : null); + binding.mainFollowing + .setOnClickListener(followingCount > 0 ? followClickListener : null); } if (profileModel.getPostCount() == 0) { @@ -481,137 +517,144 @@ public class ProfileFragment extends Fragment { private void setupCommonListeners() { final String userIdFromCookie = Utils.getUserIdFromCookie(cookie); - final boolean isSelf = isLoggedIn - && profileModel != null - && userIdFromCookie != null - && userIdFromCookie.equals(profileModel.getId()); + final boolean isSelf = isLoggedIn && profileModel != null && userIdFromCookie != null && userIdFromCookie + .equals(profileModel.getId()); final String favorite = Utils.dataBox.getFavorite(username); binding.btnFollow.setOnClickListener(v -> { if (!isLoggedIn) { if (favorite != null && v == binding.btnFollow) { - Utils.dataBox.delFavorite( - new DataBox.FavoriteModel(username, - Long.parseLong(favorite.split("/")[1]), - username.replaceAll("^@", "") - ) - ); + Utils.dataBox.delFavorite(new DataBox.FavoriteModel(username, + Long.parseLong(favorite.split( + "/")[1]), + username.replaceAll("^@", + ""))); } else if (v == binding.btnFollow) { - Utils.dataBox.addFavorite( - new DataBox.FavoriteModel(username, System.currentTimeMillis(), - username.replaceAll("^@", ""))); + Utils.dataBox.addFavorite(new DataBox.FavoriteModel(username, + System.currentTimeMillis(), + username.replaceAll("^@", + ""))); } fetchProfileDetails(); return; } if (profileModel.getFollowing() || profileModel.getRequested()) { - friendshipService.unfollow( - userIdFromCookie, - profileModel.getId(), - Utils.getCsrfTokenFromCookie(cookie), - new ServiceCallback() { - @Override - public void onSuccess(final FriendshipRepoChangeRootResponse result) { - Log.d(TAG, "Unfollow success: " + result); - fetchProfileDetails(); - } + friendshipService.unfollow(userIdFromCookie, + profileModel.getId(), + Utils.getCsrfTokenFromCookie(cookie), + new ServiceCallback() { + @Override + public void onSuccess(final FriendshipRepoChangeRootResponse result) { + Log.d(TAG, "Unfollow success: " + result); + fetchProfileDetails(); + } - @Override - public void onFailure(final Throwable t) { - Log.e(TAG, "Error unfollowing", t); - } - }); + @Override + public void onFailure(final Throwable t) { + Log.e(TAG, "Error unfollowing", t); + } + }); } else { - friendshipService.follow( - userIdFromCookie, - profileModel.getId(), - Utils.getCsrfTokenFromCookie(cookie), - new ServiceCallback() { - @Override - public void onSuccess(final FriendshipRepoChangeRootResponse result) { - Log.d(TAG, "Follow success: " + result); - fetchProfileDetails(); - } + friendshipService.follow(userIdFromCookie, + profileModel.getId(), + Utils.getCsrfTokenFromCookie(cookie), + new ServiceCallback() { + @Override + public void onSuccess(final FriendshipRepoChangeRootResponse result) { + Log.d(TAG, "Follow success: " + result); + fetchProfileDetails(); + } - @Override - public void onFailure(final Throwable t) { - Log.e(TAG, "Error following", t); - } - }); + @Override + public void onFailure(final Throwable t) { + Log.e(TAG, "Error following", t); + } + }); } }); binding.btnRestrict.setOnClickListener(v -> { if (!isLoggedIn) return; final String action = profileModel.getRestricted() ? "Unrestrict" : "Restrict"; - friendshipService.toggleRestrict( - profileModel.getId(), - !profileModel.getRestricted(), - Utils.getCsrfTokenFromCookie(cookie), - new ServiceCallback() { - @Override - public void onSuccess(final FriendshipRepoRestrictRootResponse result) { - Log.d(TAG, action + " success: " + result); - fetchProfileDetails(); - } + friendshipService.toggleRestrict(profileModel.getId(), + !profileModel.getRestricted(), + Utils.getCsrfTokenFromCookie(cookie), + new ServiceCallback() { + @Override + public void onSuccess(final FriendshipRepoRestrictRootResponse result) { + Log.d(TAG, action + " success: " + result); + fetchProfileDetails(); + } - @Override - public void onFailure(final Throwable t) { - Log.e(TAG, "Error while performing " + action, t); - } - }); + @Override + public void onFailure(final Throwable t) { + Log.e(TAG, + "Error while performing " + action, + t); + } + }); }); binding.btnBlock.setOnClickListener(v -> { if (!isLoggedIn) return; if (profileModel.getBlocked()) { - friendshipService.unblock( - userIdFromCookie, - profileModel.getId(), - Utils.getCsrfTokenFromCookie(cookie), - new ServiceCallback() { - @Override - public void onSuccess(final FriendshipRepoChangeRootResponse result) { - Log.d(TAG, "Unblock success: " + result); - fetchProfileDetails(); - } + friendshipService.unblock(userIdFromCookie, + profileModel.getId(), + Utils.getCsrfTokenFromCookie(cookie), + new ServiceCallback() { + @Override + public void onSuccess(final FriendshipRepoChangeRootResponse result) { + Log.d(TAG, "Unblock success: " + result); + fetchProfileDetails(); + } - @Override - public void onFailure(final Throwable t) { - Log.e(TAG, "Error unblocking", t); - } - }); + @Override + public void onFailure(final Throwable t) { + Log.e(TAG, "Error unblocking", t); + } + }); return; } - friendshipService.block( - userIdFromCookie, - profileModel.getId(), - Utils.getCsrfTokenFromCookie(cookie), - new ServiceCallback() { - @Override - public void onSuccess(final FriendshipRepoChangeRootResponse result) { - Log.d(TAG, "Block success: " + result); - fetchProfileDetails(); - } + friendshipService.block(userIdFromCookie, + profileModel.getId(), + Utils.getCsrfTokenFromCookie(cookie), + new ServiceCallback() { + @Override + public void onSuccess(final FriendshipRepoChangeRootResponse result) { + Log.d(TAG, "Block success: " + result); + fetchProfileDetails(); + } - @Override - public void onFailure(final Throwable t) { - Log.e(TAG, "Error blocking", t); - } - }); + @Override + public void onFailure(final Throwable t) { + Log.e(TAG, "Error blocking", t); + } + }); }); - binding.btnSaved.setOnClickListener(v -> startActivity(new Intent(requireContext(), SavedViewer.class) - .putExtra(Constants.EXTRAS_INDEX, "$" + profileModel.getId()) - .putExtra(Constants.EXTRAS_USER, "@" + profileModel.getUsername()) - )); - binding.btnLiked.setOnClickListener(v -> startActivity(new Intent(requireContext(), SavedViewer.class) - .putExtra(Constants.EXTRAS_INDEX, "^" + profileModel.getId()) - .putExtra(Constants.EXTRAS_USER, "@" + profileModel.getUsername()) - )); + binding.btnSaved.setOnClickListener(v -> startActivity(new Intent(requireContext(), + SavedViewer.class) + .putExtra(Constants.EXTRAS_INDEX, + "$" + profileModel + .getId()) + .putExtra(Constants.EXTRAS_USER, + "@" + profileModel + .getUsername()))); + binding.btnLiked.setOnClickListener(v -> startActivity(new Intent(requireContext(), + SavedViewer.class) + .putExtra(Constants.EXTRAS_INDEX, + "^" + profileModel + .getId()) + .putExtra(Constants.EXTRAS_USER, + "@" + profileModel + .getUsername()))); - binding.btnTagged.setOnClickListener(v -> startActivity(new Intent(requireContext(), SavedViewer.class) - .putExtra(Constants.EXTRAS_INDEX, "%" + profileModel.getId()) - .putExtra(Constants.EXTRAS_USER, "@" + profileModel.getUsername()) - )); + binding.btnTagged.setOnClickListener(v -> startActivity(new Intent(requireContext(), + SavedViewer.class) + .putExtra(Constants.EXTRAS_INDEX, + "%" + profileModel + .getId()) + .putExtra(Constants.EXTRAS_USER, + "@" + profileModel + .getUsername()))); } private void setUsernameDelayed() { @@ -623,29 +666,48 @@ public class ProfileFragment extends Fragment { private void setupPosts() { postsViewModel = new ViewModelProvider(this).get(PostsViewModel.class); - final GridAutofitLayoutManager layoutManager = new GridAutofitLayoutManager(requireContext(), Utils.convertDpToPx(110)); + final GridAutofitLayoutManager layoutManager = new GridAutofitLayoutManager(requireContext(), + Utils.convertDpToPx( + 110)); binding.mainPosts.setLayoutManager(layoutManager); binding.mainPosts.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4))); postsAdapter = new PostsAdapter((postModel, position) -> { if (postsAdapter.isSelecting()) { if (actionMode == null) return; - final String title = getString(R.string.number_selected, postsAdapter.getSelectedModels().size()); + final String title = getString(R.string.number_selected, + postsAdapter.getSelectedModels().size()); actionMode.setTitle(title); return; } if (checkAndResetAction()) return; - startActivity(new Intent(requireContext(), PostViewer.class) - .putExtra(Constants.EXTRAS_INDEX, position) - .putExtra(Constants.EXTRAS_POST, postModel) - .putExtra(Constants.EXTRAS_USER, username) - .putExtra(Constants.EXTRAS_TYPE, ItemGetType.MAIN_ITEMS)); + // startActivity(new Intent(requireContext(), PostViewer.class) + // .putExtra(Constants.EXTRAS_INDEX, position) + // .putExtra(Constants.EXTRAS_POST, postModel) + // .putExtra(Constants.EXTRAS_USER, username) + // .putExtra(Constants.EXTRAS_TYPE, PostItemType.MAIN)); + final List postModels = postsViewModel.getList().getValue(); + if (postModels == null || postModels.size() == 0) return; + if (postModels.get(0) == null) return; + final String postId = postModels.get(0).getPostId(); + final boolean isId = postId != null; + final String[] idsOrShortCodes = new String[postModels.size()]; + for (int i = 0; i < postModels.size(); i++) { + idsOrShortCodes[i] = isId ? postModels.get(i).getPostId() + : postModels.get(i).getShortCode(); + } + final NavDirections action = ProfileFragmentDirections.actionGlobalPostViewFragment( + position, + idsOrShortCodes, + isId); + NavHostFragment.findNavController(this).navigate(action); }, (model, position) -> { if (!postsAdapter.isSelecting()) { checkAndResetAction(); return true; } - final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher(); + final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity + .getOnBackPressedDispatcher(); if (onBackPressedDispatcher.hasEnabledCallbacks()) { return true; } @@ -657,18 +719,20 @@ public class ProfileFragment extends Fragment { }); postsViewModel.getList().observe(fragmentActivity, postsAdapter::submitList); binding.mainPosts.setAdapter(postsAdapter); - final RecyclerLazyLoader lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { - if (!hasNextPage) return; - binding.swipeRefreshLayout.setRefreshing(true); - fetchPosts(); - endCursor = null; - }); + final RecyclerLazyLoader lazyLoader = new RecyclerLazyLoader(layoutManager, + (page, totalItemsCount) -> { + if (!hasNextPage) return; + binding.swipeRefreshLayout + .setRefreshing(true); + fetchPosts(); + endCursor = null; + }); binding.mainPosts.addOnScrollListener(lazyLoader); } private void fetchPosts() { stopCurrentExecutor(); - currentlyExecuting = new PostsFetcher(profileModel.getId(), endCursor, postsFetchListener) + currentlyExecuting = new PostsFetcher(profileModel.getId(), false, endCursor, postsFetchListener) .setUsername(profileModel.getUsername()) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -678,15 +742,17 @@ public class ProfileFragment extends Fragment { try { currentlyExecuting.cancel(true); } catch (final Exception e) { - if (logCollector != null) - logCollector.appendException(e, LogCollector.LogFile.MAIN_HELPER, "stopCurrentExecutor"); + if (logCollector != null) logCollector.appendException(e, + LogCollector.LogFile.MAIN_HELPER, + "stopCurrentExecutor"); Log.e(TAG, "", e); } } } private boolean checkAndResetAction() { - final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher(); + final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity + .getOnBackPressedDispatcher(); if (!onBackPressedDispatcher.hasEnabledCallbacks() || actionMode == null) { return false; } diff --git a/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/BasePostViewModel.java b/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/BasePostViewModel.java new file mode 100644 index 00000000..5bd1eff0 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/BasePostViewModel.java @@ -0,0 +1,19 @@ +package awais.instagrabber.fragments.main.viewmodels; + +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +import java.util.List; + +import awais.instagrabber.models.DiscoverItemModel; + +public class DiscoverItemViewModel extends ViewModel { + private MutableLiveData> list; + + public MutableLiveData> getList() { + if (list == null) { + list = new MutableLiveData<>(); + } + return list; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/DiscoverItemViewModel.java b/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/DiscoverItemViewModel.java index 5bd1eff0..cd73a2b9 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/DiscoverItemViewModel.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/DiscoverItemViewModel.java @@ -1,13 +1,12 @@ package awais.instagrabber.fragments.main.viewmodels; import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; import java.util.List; import awais.instagrabber.models.DiscoverItemModel; -public class DiscoverItemViewModel extends ViewModel { +public class DiscoverItemViewModel extends BasePostViewModel { private MutableLiveData> list; public MutableLiveData> getList() { diff --git a/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/FeedViewModel.java b/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/FeedViewModel.java index a6782e7d..23565be4 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/FeedViewModel.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/FeedViewModel.java @@ -1,14 +1,13 @@ package awais.instagrabber.fragments.main.viewmodels; import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; import java.util.Collections; import java.util.List; import awais.instagrabber.models.FeedModel; -public class FeedViewModel extends ViewModel { +public class FeedViewModel extends BasePostViewModel { private MutableLiveData> list; public MutableLiveData> getList() { diff --git a/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/PostsViewModel.java b/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/PostsViewModel.java index d19d0140..fd6e3866 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/PostsViewModel.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/PostsViewModel.java @@ -1,13 +1,12 @@ package awais.instagrabber.fragments.main.viewmodels; import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; import java.util.List; import awais.instagrabber.models.PostModel; -public class PostsViewModel extends ViewModel { +public class PostsViewModel extends BasePostViewModel { private MutableLiveData> list; public MutableLiveData> getList() { diff --git a/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/ViewerPostViewModel.java b/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/ViewerPostViewModel.java new file mode 100644 index 00000000..d8352807 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/fragments/main/viewmodels/ViewerPostViewModel.java @@ -0,0 +1,18 @@ +package awais.instagrabber.fragments.main.viewmodels; + +import androidx.lifecycle.MutableLiveData; + +import java.util.List; + +import awais.instagrabber.models.ViewerPostModel; + +public class ViewPostViewModel extends BasePostViewModel { + private MutableLiveData> list; + + public MutableLiveData> getList() { + if (list == null) { + list = new MutableLiveData<>(); + } + return list; + } +} diff --git a/app/src/main/java/awais/instagrabber/interfaces/ItemGetter.java b/app/src/main/java/awais/instagrabber/interfaces/ItemGetter.java index c53c2491..20534cbf 100755 --- a/app/src/main/java/awais/instagrabber/interfaces/ItemGetter.java +++ b/app/src/main/java/awais/instagrabber/interfaces/ItemGetter.java @@ -4,8 +4,8 @@ import java.io.Serializable; import java.util.List; import awais.instagrabber.models.BasePostModel; -import awais.instagrabber.models.enums.ItemGetType; +import awais.instagrabber.models.enums.PostItemType; public interface ItemGetter extends Serializable { - List get(final ItemGetType itemGetType); + List get(final PostItemType postItemType); } \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/BasePostModel.java b/app/src/main/java/awais/instagrabber/models/BasePostModel.java index d693a5f7..016be019 100755 --- a/app/src/main/java/awais/instagrabber/models/BasePostModel.java +++ b/app/src/main/java/awais/instagrabber/models/BasePostModel.java @@ -96,11 +96,11 @@ public abstract class BasePostModel implements Serializable, Selectable { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final BasePostModel that = (BasePostModel) o; - return ObjectsCompat.equals(postId, that.postId); + return ObjectsCompat.equals(postId, that.postId) && ObjectsCompat.equals(shortCode, that.shortCode); } @Override public int hashCode() { - return ObjectsCompat.hash(postId); + return ObjectsCompat.hash(postId, shortCode); } } \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/FeedModel.java b/app/src/main/java/awais/instagrabber/models/FeedModel.java index 1a63233f..2106aa22 100755 --- a/app/src/main/java/awais/instagrabber/models/FeedModel.java +++ b/app/src/main/java/awais/instagrabber/models/FeedModel.java @@ -1,26 +1,40 @@ package awais.instagrabber.models; -import org.json.JSONObject; - import awais.instagrabber.models.enums.MediaItemType; public final class FeedModel extends PostModel { private final ProfileModel profileModel; - private final long commentsCount, viewCount; - private boolean captionExpanded = false, mentionClicked = false; - private final JSONObject location; + private final long commentsCount; + private final long viewCount; + private boolean captionExpanded = false; + private boolean mentionClicked = false; private ViewerPostModel[] sliderItems; private int imageWidth; private int imageHeight; + private String locationName; + private String locationId; - public FeedModel(final ProfileModel profileModel, final MediaItemType itemType, final long viewCount, final String postId, - final String displayUrl, final String thumbnailUrl, final String shortCode, final String postCaption, - final long commentsCount, final long timestamp, boolean liked, boolean bookmarked, long likes, JSONObject location) { + public FeedModel(final ProfileModel profileModel, + final MediaItemType itemType, + final long viewCount, + final String postId, + final String displayUrl, + final String thumbnailUrl, + final String shortCode, + final String postCaption, + final long commentsCount, + final long timestamp, + final boolean liked, + final boolean bookmarked, + final long likes, + final String locationName, + final String locationId) { super(itemType, postId, displayUrl, thumbnailUrl, shortCode, postCaption, timestamp, liked, bookmarked, likes); this.profileModel = profileModel; this.commentsCount = commentsCount; this.viewCount = viewCount; - this.location = location; + this.locationName = locationName; + this.locationId = locationId; } public ProfileModel getProfileModel() { @@ -39,10 +53,6 @@ public final class FeedModel extends PostModel { return commentsCount; } - public JSONObject getLocation() { - return location; - } - public boolean isCaptionExpanded() { return captionExpanded; } @@ -79,4 +89,20 @@ public final class FeedModel extends PostModel { public int getImageHeight() { return imageHeight; } + + public String getLocationName() { + return locationName; + } + + public void setLocationName(final String locationName) { + this.locationName = locationName; + } + + public String getLocationId() { + return locationId; + } + + public void setLocationId(final String locationId) { + this.locationId = locationId; + } } \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/LocationModel.java b/app/src/main/java/awais/instagrabber/models/LocationModel.java index e1b97399..fedaa773 100755 --- a/app/src/main/java/awais/instagrabber/models/LocationModel.java +++ b/app/src/main/java/awais/instagrabber/models/LocationModel.java @@ -4,11 +4,26 @@ import java.io.Serializable; public final class LocationModel implements Serializable { private final long postCount; - private final String id, name, bio, url, sdProfilePic, lat, lng; + private final String id; + private final String slug; + private final String name; + private final String bio; + private final String url; + private final String sdProfilePic; + private final String lat; + private final String lng; - public LocationModel(final String id, final String name, final String bio, final String url, - final String sdProfilePic, final long postCount, final String lat, final String lng) { - this.id = id; // <- id + "/" + slug + public LocationModel(final String id, + final String slug, + final String name, + final String bio, + final String url, + final String sdProfilePic, + final long postCount, + final String lat, + final String lng) { + this.id = id; + this.slug = slug; this.name = name; this.bio = bio; this.url = url; @@ -22,6 +37,10 @@ public final class LocationModel implements Serializable { return id; } + public String getSlug() { + return slug; + } + public String getName() { return name; } @@ -34,7 +53,7 @@ public final class LocationModel implements Serializable { return url; } - public String getGeo() { return "geo:"+lat+","+lng+"?z=17&q="+lat+","+lng+"("+name+")"; } + public String getGeo() { return "geo:" + lat + "," + lng + "?z=17&q=" + lat + "," + lng + "(" + name + ")"; } public String getSdProfilePic() { return sdProfilePic; diff --git a/app/src/main/java/awais/instagrabber/models/ProfileModel.java b/app/src/main/java/awais/instagrabber/models/ProfileModel.java index ac75527f..e6367ef6 100755 --- a/app/src/main/java/awais/instagrabber/models/ProfileModel.java +++ b/app/src/main/java/awais/instagrabber/models/ProfileModel.java @@ -39,6 +39,10 @@ public final class ProfileModel implements Serializable { return new ProfileModel(false, false, false, userId, null, null, null, null, null, null, 0, 0, 0, false, false, false, false); } + public static ProfileModel getDefaultProfileModel(final String userId, final String username) { + return new ProfileModel(false, false, false, userId, username, null, null, null, null, null, 0, 0, 0, false, false, false, false); + } + public boolean isPrivate() { return isPrivate; } diff --git a/app/src/main/java/awais/instagrabber/models/ViewerPostModel.java b/app/src/main/java/awais/instagrabber/models/ViewerPostModel.java index fdc062e4..64bb7f2a 100755 --- a/app/src/main/java/awais/instagrabber/models/ViewerPostModel.java +++ b/app/src/main/java/awais/instagrabber/models/ViewerPostModel.java @@ -1,24 +1,34 @@ package awais.instagrabber.models; -import org.json.JSONObject; - import awais.instagrabber.models.enums.MediaItemType; public final class ViewerPostModel extends BasePostModel { - protected final String username, locationName, location; + protected final ProfileModel profileModel; + protected final String locationName; + protected final String location; protected final long videoViews; protected String sliderDisplayUrl; protected long commentsCount, likes; private boolean isCurrentSlide = false; - public ViewerPostModel(final MediaItemType itemType, final String postId, final String displayUrl, final String shortCode, - final String postCaption, final String username, final long videoViews, final long timestamp, - boolean liked, boolean bookmarked, long likes, final String locationName, final String location) { + public ViewerPostModel(final MediaItemType itemType, + final String postId, + final String displayUrl, + final String shortCode, + final String postCaption, + final ProfileModel profileModel, + final long videoViews, + final long timestamp, + boolean liked, + boolean bookmarked, + long likes, + final String locationName, + final String location) { this.itemType = itemType; this.postId = postId; this.displayUrl = displayUrl; this.postCaption = postCaption; - this.username = username; + this.profileModel = profileModel; this.shortCode = shortCode; this.videoViews = videoViews; this.timestamp = timestamp; @@ -29,6 +39,10 @@ public final class ViewerPostModel extends BasePostModel { this.location = location; } + public static ViewerPostModel getDefaultModel(final int postId, final String shortCode) { + return new ViewerPostModel(null, String.valueOf(postId), null, "", null, null, -1, -1, false, false, -1, null, null); + } + public long getCommentsCount() { return commentsCount; } @@ -37,8 +51,8 @@ public final class ViewerPostModel extends BasePostModel { return sliderDisplayUrl; } - public String getUsername() { - return username; + public ProfileModel getProfileModel() { + return profileModel; } public String getLocationName() { diff --git a/app/src/main/java/awais/instagrabber/models/ViewerPostModelWrapper.java b/app/src/main/java/awais/instagrabber/models/ViewerPostModelWrapper.java new file mode 100644 index 00000000..170793ba --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/ViewerPostModelWrapper.java @@ -0,0 +1,23 @@ +package awais.instagrabber.models; + +public class ViewerPostModelWrapper { + private int position; + private ViewerPostModel[] viewerPostModels; + + public ViewerPostModelWrapper(final int position, final ViewerPostModel[] viewerPostModels) { + this.position = position; + this.viewerPostModels = viewerPostModels; + } + + public int getPosition() { + return position; + } + + public ViewerPostModel[] getViewerPostModels() { + return viewerPostModels; + } + + public void setViewerPostModels(final ViewerPostModel[] viewerPostModels) { + this.viewerPostModels = viewerPostModels; + } +} diff --git a/app/src/main/java/awais/instagrabber/models/enums/ItemGetType.java b/app/src/main/java/awais/instagrabber/models/enums/PostItemType.java old mode 100755 new mode 100644 similarity index 100% rename from app/src/main/java/awais/instagrabber/models/enums/ItemGetType.java rename to app/src/main/java/awais/instagrabber/models/enums/PostItemType.java diff --git a/app/src/main/java/awais/instagrabber/services/LoggingInterceptor.java b/app/src/main/java/awais/instagrabber/services/LoggingInterceptor.java index 0f008a07..3da71476 100644 --- a/app/src/main/java/awais/instagrabber/services/LoggingInterceptor.java +++ b/app/src/main/java/awais/instagrabber/services/LoggingInterceptor.java @@ -7,8 +7,10 @@ import androidx.annotation.NonNull; import java.io.IOException; import okhttp3.Interceptor; +import okhttp3.MediaType; import okhttp3.Request; import okhttp3.Response; +import okhttp3.ResponseBody; class LoggingInterceptor implements Interceptor { private static final String TAG = "LoggingInterceptor"; @@ -22,8 +24,12 @@ class LoggingInterceptor implements Interceptor { request.url(), chain.connection(), request.headers())); Response response = chain.proceed(request); long t2 = System.nanoTime(); - Log.i(TAG, String.format("Received response for %s in %.1fms%n%s\nbody: %s", - response.request().url(), (t2 - t1) / 1e6d, response.headers(), response.body())); - return response; + Log.i(TAG, String.format("Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1) / 1e6d, response.headers())); + MediaType contentType = response.body().contentType(); + String content = response.body().string(); + Log.d("OkHttp", content); + + ResponseBody wrappedBody = ResponseBody.create(contentType, content); + return response.newBuilder().body(wrappedBody).build(); } } diff --git a/app/src/main/java/awais/instagrabber/utils/LocaleUtils.java b/app/src/main/java/awais/instagrabber/utils/LocaleUtils.java index a3d7216e..a98ddc44 100755 --- a/app/src/main/java/awais/instagrabber/utils/LocaleUtils.java +++ b/app/src/main/java/awais/instagrabber/utils/LocaleUtils.java @@ -55,8 +55,10 @@ public final class LocaleUtils { if (Utils.settingsHelper == null) Utils.settingsHelper = new SettingsHelper(baseContext); - final int appLanguageIndex = Integer.parseInt(Utils.settingsHelper.getString(Constants.APP_LANGUAGE)); + final String appLanguageSettings = Utils.settingsHelper.getString(Constants.APP_LANGUAGE); + if (Utils.isEmpty(appLanguageSettings)) return null; + final int appLanguageIndex = Integer.parseInt(appLanguageSettings); if (appLanguageIndex == 1) return "en"; if (appLanguageIndex == 2) return "fr"; if (appLanguageIndex == 3) return "es"; diff --git a/app/src/main/res/layout/fragment_post_view.xml b/app/src/main/res/layout/fragment_post_view.xml new file mode 100644 index 00000000..7ce45884 --- /dev/null +++ b/app/src/main/res/layout/fragment_post_view.xml @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_feed_bottom.xml b/app/src/main/res/layout/item_feed_bottom.xml index d8bfaf4c..60f22cc0 100755 --- a/app/src/main/res/layout/item_feed_bottom.xml +++ b/app/src/main/res/layout/item_feed_bottom.xml @@ -42,7 +42,8 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" - android:orientation="horizontal"> + android:orientation="horizontal" + android:visibility="gone"> diff --git a/app/src/main/res/layout/item_feed_top.xml b/app/src/main/res/layout/item_feed_top.xml index 64845a80..3c3361b9 100755 --- a/app/src/main/res/layout/item_feed_top.xml +++ b/app/src/main/res/layout/item_feed_top.xml @@ -25,6 +25,7 @@ android:orientation="vertical" android:paddingStart="8dp" android:paddingLeft="8dp" + android:gravity="center" android:paddingEnd="8dp" android:paddingRight="8dp" android:weightSum="2"> @@ -46,7 +47,8 @@ android:gravity="center_vertical" android:textAppearance="@style/TextAppearance.AppCompat.Subhead" android:textColor="@color/feed_text_primary_color" - android:textSize="15sp" /> + android:textSize="15sp" + android:visibility="visible" tools:text="location" /> diff --git a/app/src/main/res/layout/item_full_post_view.xml b/app/src/main/res/layout/item_full_post_view.xml new file mode 100644 index 00000000..31090f49 --- /dev/null +++ b/app/src/main/res/layout/item_full_post_view.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_viewer.xml b/app/src/main/res/layout/item_full_post_view_bk.xml old mode 100755 new mode 100644 similarity index 85% rename from app/src/main/res/layout/activity_viewer.xml rename to app/src/main/res/layout/item_full_post_view_bk.xml index e280ef67..8216b777 --- a/app/src/main/res/layout/activity_viewer.xml +++ b/app/src/main/res/layout/item_full_post_view_bk.xml @@ -4,25 +4,15 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:weightSum="3.2" android:animateLayoutChanges="true" android:orientation="vertical" - tools:context=".activities.PostViewer"> + android:weightSum="3.2" + tools:context=".activities.PostViewer" + android:layout_marginTop="?attr/actionBarSize"> - - - - + - + app:srcCompat="@drawable/ic_fullscreen" + app:tint="?android:textColorPrimary" /> + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" + tools:listitem="@layout/item_child_post" /> + android:layout_weight="1" /> + android:weightSum="2"> + + app:backgroundTint="@color/btn_lightpink_background" + tools:text="@string/like" /> + + + + + + + + + android:label="DiscoverFragment" + tools:layout="@layout/fragment_discover" /> \ No newline at end of file diff --git a/app/src/main/res/navigation/feed_nav_graph.xml b/app/src/main/res/navigation/feed_nav_graph.xml index d081a60a..493f6022 100644 --- a/app/src/main/res/navigation/feed_nav_graph.xml +++ b/app/src/main/res/navigation/feed_nav_graph.xml @@ -24,9 +24,36 @@ + + + + + + + + + + + + + + - - - - \ No newline at end of file diff --git a/app/src/main/res/navigation/hashtag_nav_graph.xml b/app/src/main/res/navigation/hashtag_nav_graph.xml index b4eeefcc..9cda2b6a 100644 --- a/app/src/main/res/navigation/hashtag_nav_graph.xml +++ b/app/src/main/res/navigation/hashtag_nav_graph.xml @@ -4,6 +4,21 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/hashtag_nav_graph" app:startDestination="@id/hashTagFragment"> + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/post_view_nav_graph.xml b/app/src/main/res/navigation/post_view_nav_graph.xml new file mode 100644 index 00000000..eca6b4a7 --- /dev/null +++ b/app/src/main/res/navigation/post_view_nav_graph.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/profile_nav_graph.xml b/app/src/main/res/navigation/profile_nav_graph.xml index 1b3c63da..938d93b2 100644 --- a/app/src/main/res/navigation/profile_nav_graph.xml +++ b/app/src/main/res/navigation/profile_nav_graph.xml @@ -16,11 +16,28 @@ app:nullable="false" /> + + + + + + + + @@ -29,13 +46,11 @@ android:id="@+id/profileFragment" android:name="awais.instagrabber.fragments.main.ProfileFragment" android:label="@string/profile" - tools:layout="@layout/fragment_profile" > + tools:layout="@layout/fragment_profile"> - - - + app:nullable="true" /> \ No newline at end of file