Browse Source

Added post viewer fragment. Updated almost all places to use this

Remaining places are SavedViewer and DirectMessageThreadFragment
renovate/org.robolectric-robolectric-4.x
Ammar Githam 4 years ago
parent
commit
13cacf43f9
  1. 168
      app/src/main/java/awais/instagrabber/MainHelper.java
  2. 8
      app/src/main/java/awais/instagrabber/activities/MainActivityBackup.java
  3. 197
      app/src/main/java/awais/instagrabber/activities/PostViewer.java
  4. 92
      app/src/main/java/awais/instagrabber/activities/ProfileViewer.java
  5. 27
      app/src/main/java/awais/instagrabber/activities/SavedViewer.java
  6. 77
      app/src/main/java/awais/instagrabber/adapters/PostViewAdapter.java
  7. 203
      app/src/main/java/awais/instagrabber/adapters/PostViewerChildAdapter.java
  8. 199
      app/src/main/java/awais/instagrabber/adapters/viewholder/PostViewerViewHolder.java
  9. 24
      app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedItemViewHolder.java
  10. 22
      app/src/main/java/awais/instagrabber/asyncs/DiscoverFetcher.java
  11. 55
      app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java
  12. 44
      app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java
  13. 6
      app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java
  14. 33
      app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java
  15. 2
      app/src/main/java/awais/instagrabber/asyncs/direct_messages/DirectThreadBroadcaster.java
  16. 109
      app/src/main/java/awais/instagrabber/asyncs/i/iPostFetcher.java
  17. 112
      app/src/main/java/awais/instagrabber/customviews/helpers/NestedScrollableHost.java
  18. 13
      app/src/main/java/awais/instagrabber/customviews/helpers/RecyclerLazyLoader.java
  19. 2
      app/src/main/java/awais/instagrabber/directdownload/DirectDownload.java
  20. 2
      app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java
  21. 50
      app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java
  22. 113
      app/src/main/java/awais/instagrabber/fragments/LocationFragment.java
  23. 287
      app/src/main/java/awais/instagrabber/fragments/PostViewFragment.java
  24. 574
      app/src/main/java/awais/instagrabber/fragments/PostViewFragmentBackup.java
  25. 80
      app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java
  26. 16
      app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java
  27. 6
      app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java
  28. 42
      app/src/main/java/awais/instagrabber/fragments/main/DiscoverFragment.java
  29. 96
      app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java
  30. 516
      app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java
  31. 19
      app/src/main/java/awais/instagrabber/fragments/main/viewmodels/BasePostViewModel.java
  32. 3
      app/src/main/java/awais/instagrabber/fragments/main/viewmodels/DiscoverItemViewModel.java
  33. 3
      app/src/main/java/awais/instagrabber/fragments/main/viewmodels/FeedViewModel.java
  34. 3
      app/src/main/java/awais/instagrabber/fragments/main/viewmodels/PostsViewModel.java
  35. 18
      app/src/main/java/awais/instagrabber/fragments/main/viewmodels/ViewerPostViewModel.java
  36. 4
      app/src/main/java/awais/instagrabber/interfaces/ItemGetter.java
  37. 4
      app/src/main/java/awais/instagrabber/models/BasePostModel.java
  38. 54
      app/src/main/java/awais/instagrabber/models/FeedModel.java
  39. 31
      app/src/main/java/awais/instagrabber/models/LocationModel.java
  40. 4
      app/src/main/java/awais/instagrabber/models/ProfileModel.java
  41. 32
      app/src/main/java/awais/instagrabber/models/ViewerPostModel.java
  42. 23
      app/src/main/java/awais/instagrabber/models/ViewerPostModelWrapper.java
  43. 0
      app/src/main/java/awais/instagrabber/models/enums/PostItemType.java
  44. 12
      app/src/main/java/awais/instagrabber/services/LoggingInterceptor.java
  45. 4
      app/src/main/java/awais/instagrabber/utils/LocaleUtils.java
  46. 4
      app/src/main/res/layout/fragment_post_view.xml
  47. 5
      app/src/main/res/layout/item_feed_bottom.xml
  48. 4
      app/src/main/res/layout/item_feed_top.xml
  49. 105
      app/src/main/res/layout/item_full_post_view.xml
  50. 44
      app/src/main/res/layout/item_full_post_view_bk.xml
  51. 20
      app/src/main/res/navigation/discover_nav_graph.xml
  52. 40
      app/src/main/res/navigation/feed_nav_graph.xml
  53. 15
      app/src/main/res/navigation/hashtag_nav_graph.xml
  54. 42
      app/src/main/res/navigation/location_nav_graph.xml
  55. 67
      app/src/main/res/navigation/post_view_nav_graph.xml
  56. 25
      app/src/main/res/navigation/profile_nav_graph.xml

168
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<FeedModel[]> feedFetchListener = new FetchListener<FeedModel[]>() {
@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");

8
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;
};

197
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<ViewerPostModel[]> 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<? extends BasePostModel> itemGetterItems;
final boolean isMainSwipe;
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);
final boolean isSwipeable;
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<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target<Drawable> target, final boolean isFirstResource) {
viewerBinding.progressView.setVisibility(View.GONE);
return false;
}
@Override
public boolean onResourceReady(final Drawable resource, final Object model, final Target<Drawable> target, final DataSource dataSource, final boolean isFirstResource) {
viewerBinding.progressView.setVisibility(View.GONE);
return false;
}
}).into(viewerBinding.imageViewer);
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<ImageInfo>() {
@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;

92
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");

27
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;
};

77
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<ViewerPostModelWrapper, PostViewerViewHolder> {
private final OnPostViewChildViewClickListener clickListener;
private final OnPostCaptionLongClickListener longClickListener;
private final MentionClickListener mentionClickListener;
private static final DiffUtil.ItemCallback<ViewerPostModelWrapper> diffCallback = new DiffUtil.ItemCallback<ViewerPostModelWrapper>() {
@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);
}
}

203
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<ViewerPostModel, PostViewerChildAdapter.ChildViewHolder> {
private static final DiffUtil.ItemCallback<ViewerPostModel> diffCallback = new DiffUtil.ItemCallback<ViewerPostModel>() {
@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<ImageInfo>() {
//
// @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);
}
}
}

199
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<ViewerPostModel> 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);
}
}
}

24
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));
}
}

22
app/src/main/java/awais/instagrabber/asyncs/DiscoverFetcher.java

@ -67,7 +67,7 @@ public final class DiscoverFetcher extends AsyncTask<Void, Void, DiscoverItemMod
private ArrayList<DiscoverItemModel> fetchItems(ArrayList<DiscoverItemModel> 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<Void, Void, DiscoverItemMod
} catch (final Exception e) {
if (logCollector != null)
logCollector.appendException(e, LogCollector.LogFile.ASYNC_DISCOVER_FETCHER, "fetchItems",
new Pair<>("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<Void, Void, DiscoverItemMod
final MediaItemType mediaType = Utils.getMediaItemType(media.getInt("media_type"));
final DiscoverItemModel model = new DiscoverItemModel(mediaType,
media.getString(Constants.EXTRAS_ID),
media.getString("code"),
Utils.getThumbnailUrl(media, mediaType));
media.getString("pk"),
media.getString("code"),
Utils.getThumbnailUrl(media, mediaType));
final File downloadDir = new File(Environment.getExternalStorageDirectory(), "Download" +
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/"+username) : ""));
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/" + username) : ""));
// to check if file exists
File customDir = null;
if (settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
final String customPath = settingsHelper.getString(FOLDER_PATH);
if (!Utils.isEmpty(customPath)) customDir = new File(customPath +
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/"+username) : ""));
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER)
? ("/" + username)
: ""));
}
Utils.checkExistence(downloadDir, customDir, mediaType == MediaItemType.MEDIA_TYPE_SLIDER, model);

55
app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java

@ -64,7 +64,7 @@ public final class FeedFetcher extends AsyncTask<Void, Void, FeedModel[]> {
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<Void, Void, FeedModel[]> {
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<Void, Void, FeedModel[]> {
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<Void, Void, FeedModel[]> {
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<Void, Void, FeedModel[]> {
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<Void, Void, FeedModel[]> {
} 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;

44
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<Void, Void, LocationModel> {
private static final String TAG = "LocationFetcher";
private final FetchListener<LocationModel> fetchListener;
private final String idSlug;
private final String id;
public LocationFetcher(String idSlug, FetchListener<LocationModel> fetchListener) {
public LocationFetcher(final String id, final FetchListener<LocationModel> 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<Void, Void, LocationModel>
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<Void, Void, LocationModel>
} 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;
}

6
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<Void, Void, ViewerPostModel[]>
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<Void, Void, ViewerPostModel[]>
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"),

33
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<Void, Void, PostModel[]> {
private static final String TAG = "PostsFetcher";
private boolean isLocation;
private final String endCursor;
private final String id;
private final FetchListener<PostModel[]> fetchListener;
@ -37,8 +38,12 @@ public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
this.fetchListener = fetchListener;
}
public PostsFetcher(final String id, final String endCursor, final FetchListener<PostModel[]> fetchListener) {
public PostsFetcher(final String id,
final boolean isLocation,
final String endCursor,
final FetchListener<PostModel[]> 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<Void, Void, PostModel[]> {
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<Void, Void, PostModel[]> {
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<Void, Void, PostModel[]> {
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]);
}

2
app/src/main/java/awais/instagrabber/asyncs/direct_messages/DirectThreadBroadcaster.java

@ -43,7 +43,7 @@ public class DirectThreadBroadcaster extends AsyncTask<DirectThreadBroadcaster.B
final String cookie = settingsHelper.getString(Constants.COOKIE);
final String cc = UUID.randomUUID().toString();
final Map<String, String> 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);

109
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<Void, Void, ViewerPostModel[]> {
private static final String TAG = "iPostFetcher";
private final String id;
private final FetchListener<ViewerPostModel[]> fetchListener;
@ -43,18 +46,54 @@ public final class iPostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]>
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<Void, Void, ViewerPostModel[]>
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<Void, Void, ViewerPostModel[]>
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<Void, Void, ViewerPostModel[]>
} 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;
}

112
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;
}
}

13
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;
}
}

2
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)

2
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());

50
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<PostModel> 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());

113
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<PostModel[]> postsFetchListener = new FetchListener<PostModel[]>() {
@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<PostModel> postModels = postsViewModel.getList().getValue();
final List<PostModel> finalList = postModels == null || postModels.isEmpty() ? new ArrayList<>() : new ArrayList<>(postModels);
final List<PostModel> 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<PostModel> 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);
}
}

287
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<String> idOrCodeList;
private boolean hasInitialResult = false;
private PostViewAdapter adapter;
private boolean session;
private FetchListener<ViewerPostModel[]> pfl = result -> {
if (result == null) return;
if (result.length <= 0) return;
final List<ViewerPostModelWrapper> viewerPostModels = viewerPostViewModel.getList()
.getValue();
final List<ViewerPostModelWrapper> 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<ViewerPostModelWrapper> createPlaceholderModels(final int size) {
final List<ViewerPostModelWrapper> 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<ViewerPostModelWrapper> 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<ViewerPostModel> postModels,
final int childPosition,
final String username) {
final List<ViewerPostModel> 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)));
}
}
}

574
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<? extends BasePostModel> 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<ViewerPostModel[]> 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<? extends BasePostModel> 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<ImageInfo>() {
//
// @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()
// );
// }
// }

80
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<ImageInfo>() {
@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) {
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);

16
app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java

@ -48,6 +48,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
private AsyncTask<Void, Void, InboxModel> currentlyRunning;
private InboxThreadModelListViewModel listViewModel;
public static boolean refreshPlease = false;
private boolean shouldRefresh = true;
private final FetchListener<InboxModel> fetchListener = new FetchListener<InboxModel>() {
@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() {

6
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);

42
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<DiscoverItemModel> 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;
}
});

96
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<FeedModel> finalList = currentFeedModelList == null || currentFeedModelList.isEmpty() ? new ArrayList<>() : new ArrayList<>(currentFeedModelList);
final List<FeedModel> 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<Void> ds = Fresco.getImagePipeline().prefetchToBitmapCache(ImageRequest.fromUri(feedModel.getThumbnailUrl()), null);
final DataSource<Void> 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<FeedModel> 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<BasePostModel> 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));

516
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();
}
@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 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;
}
});
private final FetchListener<PostModel[]> postsFetchListener = new FetchListener<PostModel[]>() {
@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<PostModel> postModels = postsViewModel.getList().getValue();
final List<PostModel> finalList = postModels == null || postModels.isEmpty() ? new ArrayList<>() : new ArrayList<>(postModels);
final List<PostModel> 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<String> 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 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 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);
}
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));
binding.mainFollowers.setOnClickListener(followersCount > 0 ? followClickListener : null);
binding.mainFollowing.setOnClickListener(followingCount > 0 ? followClickListener : null);
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);
}
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<FriendshipRepoChangeRootResponse>() {
@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);
}
});
friendshipService.unfollow(userIdFromCookie,
profileModel.getId(),
Utils.getCsrfTokenFromCookie(cookie),
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
@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);
}
});
} else {
friendshipService.follow(
userIdFromCookie,
profileModel.getId(),
Utils.getCsrfTokenFromCookie(cookie),
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
@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);
}
});
friendshipService.follow(userIdFromCookie,
profileModel.getId(),
Utils.getCsrfTokenFromCookie(cookie),
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
@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);
}
});
}
});
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<FriendshipRepoRestrictRootResponse>() {
@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);
}
});
friendshipService.toggleRestrict(profileModel.getId(),
!profileModel.getRestricted(),
Utils.getCsrfTokenFromCookie(cookie),
new ServiceCallback<FriendshipRepoRestrictRootResponse>() {
@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);
}
});
});
binding.btnBlock.setOnClickListener(v -> {
if (!isLoggedIn) return;
if (profileModel.getBlocked()) {
friendshipService.unblock(
userIdFromCookie,
profileModel.getId(),
Utils.getCsrfTokenFromCookie(cookie),
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
@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);
}
});
friendshipService.unblock(userIdFromCookie,
profileModel.getId(),
Utils.getCsrfTokenFromCookie(cookie),
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
@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);
}
});
return;
}
friendshipService.block(
userIdFromCookie,
profileModel.getId(),
Utils.getCsrfTokenFromCookie(cookie),
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
@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);
}
});
friendshipService.block(userIdFromCookie,
profileModel.getId(),
Utils.getCsrfTokenFromCookie(cookie),
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
@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);
}
});
});
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.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())));
}
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<PostModel> 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;
}

19
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<DiscoverItemModel>> list;
public MutableLiveData<List<DiscoverItemModel>> getList() {
if (list == null) {
list = new MutableLiveData<>();
}
return list;
}
}

3
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<DiscoverItemModel> {
private MutableLiveData<List<DiscoverItemModel>> list;
public MutableLiveData<List<DiscoverItemModel>> getList() {

3
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<FeedModel> {
private MutableLiveData<List<FeedModel>> list;
public MutableLiveData<List<FeedModel>> getList() {

3
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<PostModel> {
private MutableLiveData<List<PostModel>> list;
public MutableLiveData<List<PostModel>> getList() {

18
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<ViewerPostModel> {
private MutableLiveData<List<ViewerPostModel>> list;
public MutableLiveData<List<ViewerPostModel>> getList() {
if (list == null) {
list = new MutableLiveData<>();
}
return list;
}
}

4
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<? extends BasePostModel> get(final ItemGetType itemGetType);
List<? extends BasePostModel> get(final PostItemType postItemType);
}

4
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);
}
}

54
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;
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) {
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,
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;
}
}

31
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;
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
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 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;

4
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;
}

32
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() {

23
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;
}
}

0
app/src/main/java/awais/instagrabber/models/enums/ItemGetType.java → app/src/main/java/awais/instagrabber/models/enums/PostItemType.java

12
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();
}
}

4
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";

4
app/src/main/res/layout/fragment_post_view.xml

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.viewpager2.widget.ViewPager2 xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" />

5
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">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
@ -77,7 +78,7 @@
android:layout_height="match_parent"
android:background="?selectableItemBackgroundBorderless"
android:padding="4dp"
android:visibility="visible"
android:visibility="gone"
app:srcCompat="@drawable/ic_volume_up_24"
app:tint="?android:textColorPrimary" />

4
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" />
</RelativeLayout>

105
app/src/main/res/layout/item_full_post_view.xml

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
android:animateLayoutChanges="true"
android:orientation="vertical"
android:weightSum="3.2"
tools:context=".activities.PostViewer">
<include
android:id="@+id/topPanel"
layout="@layout/item_feed_top" />
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.9">
<awais.instagrabber.customviews.helpers.NestedScrollableHost
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/mediaViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</awais.instagrabber.customviews.helpers.NestedScrollableHost>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/mediaCounter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="@drawable/rounder_corner_semi_black_bg"
android:gravity="center"
android:padding="5dp"
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
android:textColor="@android:color/white"
android:visibility="gone" />
<ProgressBar
android:id="@+id/progressView"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:visibility="gone" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivToggleFullScreen"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="end|top"
android:background="?selectableItemBackgroundBorderless"
android:padding="4dp"
app:srcCompat="@drawable/ic_fullscreen"
app:tint="?android:textColorPrimary" />
</FrameLayout>
<include
android:id="@+id/bottomPanel"
layout="@layout/item_feed_bottom"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/postActions"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.3"
android:background="#0000"
android:weightSum="2">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnLike"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:textColor="@color/btn_lightpink_text_color"
android:textSize="18sp"
app:backgroundTint="@color/btn_lightpink_background"
tools:text="@string/like" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnBookmark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="8dp"
android:layout_marginEnd="6dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:text="@string/bookmark"
android:textColor="@color/btn_lightorange_text_color"
android:textSize="18sp"
app:backgroundTint="@color/btn_lightorange_background" />
</androidx.appcompat.widget.LinearLayoutCompat>
</LinearLayout>

44
app/src/main/res/layout/activity_viewer.xml → 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">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="4dp"
android:paddingLeft="4dp"
android:paddingTop="4dp"
android:paddingEnd="4dp"
android:paddingRight="4dp"
android:paddingBottom="6dp">
android:weightSum="3.2"
tools:context=".activities.PostViewer"
android:layout_marginTop="?attr/actionBarSize">
<include
android:id="@+id/topPanel"
layout="@layout/item_feed_top" />
</FrameLayout>
<include
android:id="@+id/topPanel"
layout="@layout/item_feed_top" />
<FrameLayout
android:id="@+id/container"
@ -38,7 +28,7 @@
app:auto_show="true"
app:repeat_toggle_modes="all" />
<com.github.chrisbanes.photoview.PhotoView
<awais.instagrabber.customviews.drawee.ZoomableDraweeView
android:id="@+id/imageViewer"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -63,7 +53,8 @@
android:layout_gravity="end|top"
android:background="?selectableItemBackgroundBorderless"
android:padding="4dp"
app:srcCompat="@drawable/ic_fullscreen" />
app:srcCompat="@drawable/ic_fullscreen"
app:tint="?android:textColorPrimary" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/btnDownload"
@ -89,14 +80,15 @@
android:paddingLeft="5dp"
android:paddingEnd="5dp"
android:paddingRight="5dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_child_post" />
<include
android:id="@+id/bottomPanel"
layout="@layout/item_feed_bottom"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
android:layout_weight="1" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/postActions"
@ -104,26 +96,26 @@
android:layout_height="0dp"
android:layout_weight="0.3"
android:background="#0000"
android:weightSum="2"
android:layout_alignParentBottom="true">
android:weightSum="2">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnLike"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="6dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:text="@string/like"
android:textColor="@color/btn_lightpink_text_color"
android:textSize="18sp"
app:backgroundTint="@color/btn_lightpink_background" />
app:backgroundTint="@color/btn_lightpink_background"
tools:text="@string/like" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnBookmark"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="8dp"
android:layout_marginEnd="6dp"
android:layout_marginRight="8dp"

20
app/src/main/res/navigation/discover_nav_graph.xml

@ -1,11 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/discover_nav_graph"
app:startDestination="@id/discoverFragment">
<include app:graph="@navigation/post_view_nav_graph" />
<action
android:id="@+id/action_global_postViewFragment"
app:destination="@id/post_view_nav_graph">
<argument
android:name="index"
app:argType="integer" />
<argument
android:name="idOrCodeArray"
app:argType="string[]" />
<argument
android:name="isId"
app:argType="boolean" />
</action>
<fragment
android:id="@+id/discoverFragment"
android:name="awais.instagrabber.fragments.main.DiscoverFragment"
android:label="DiscoverFragment" />
android:label="DiscoverFragment"
tools:layout="@layout/fragment_discover" />
</navigation>

40
app/src/main/res/navigation/feed_nav_graph.xml

@ -24,9 +24,36 @@
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<include app:graph="@navigation/location_nav_graph" />
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/location_nav_graph">
<argument
android:name="locationId"
app:argType="string"
app:nullable="false" />
</action>
<include app:graph="@navigation/post_view_nav_graph" />
<action
android:id="@+id/action_global_postViewFragment"
app:destination="@id/post_view_nav_graph">
<argument
android:name="index"
app:argType="integer" />
<argument
android:name="idOrCodeArray"
app:argType="string[]" />
<argument
android:name="isId"
app:argType="boolean" />
</action>
<fragment
android:id="@+id/feedFragment"
android:name="awais.instagrabber.fragments.main.FeedFragment"
@ -35,9 +62,6 @@
<action
android:id="@+id/action_feedFragment_to_storyViewerFragment"
app:destination="@id/storyViewerFragment" />
<action
android:id="@+id/action_feedFragment_to_locationFragment"
app:destination="@id/locationFragment" />
</fragment>
<fragment
android:id="@+id/storyViewerFragment"
@ -56,14 +80,4 @@
android:name="isHashtag"
app:argType="boolean" />
</fragment>
<fragment
android:id="@+id/locationFragment"
android:name="awais.instagrabber.fragments.LocationFragment"
android:label=""
tools:layout="@layout/fragment_location">
<argument
android:name="location"
app:argType="string"
app:nullable="false" />
</fragment>
</navigation>

15
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">
<action
android:id="@+id/action_global_postViewFragment"
app:destination="@id/post_view_nav_graph">
<argument
android:name="index"
app:argType="integer" />
<argument
android:name="idOrCodeArray"
app:argType="string[]" />
<argument
android:name="isId"
app:argType="boolean" />
</action>
<fragment
android:id="@+id/hashTagFragment"
android:name="awais.instagrabber.fragments.HashTagFragment"

42
app/src/main/res/navigation/location_nav_graph.xml

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/location_nav_graph"
app:startDestination="@id/locationFragment">
<!--<include app:graph="@navigation/post_view_nav_graph" />-->
<action
android:id="@+id/action_global_postViewFragment"
app:destination="@id/post_view_nav_graph">
<argument
android:name="index"
app:argType="integer" />
<argument
android:name="idOrCodeArray"
app:argType="string[]" />
<argument
android:name="isId"
app:argType="boolean" />
</action>
<fragment
android:id="@+id/locationFragment"
android:name="awais.instagrabber.fragments.LocationFragment"
android:label=""
tools:layout="@layout/fragment_location">
<argument
android:name="locationId"
app:argType="string"
app:nullable="false" />
</fragment>
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/locationFragment">
<argument
android:name="locationId"
app:argType="string"
app:nullable="false" />
</action>
</navigation>

67
app/src/main/res/navigation/post_view_nav_graph.xml

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/post_view_nav_graph"
app:startDestination="@id/postViewFragment">
<include app:graph="@navigation/hashtag_nav_graph" />
<action
android:id="@+id/action_global_hashTagFragment"
app:destination="@id/hashtag_nav_graph">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
</action>
<!--<include app:graph="@navigation/profile_nav_graph" />-->
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<include app:graph="@navigation/location_nav_graph" />
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/location_nav_graph">
<argument
android:name="locationId"
app:argType="string"
app:nullable="false" />
</action>
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewFragment"
tools:layout="@layout/item_full_post_view">
<argument
android:name="index"
app:argType="integer" />
<argument
android:name="idOrCodeArray"
app:argType="string[]" />
<argument
android:name="isId"
app:argType="boolean" />
</fragment>
<action
android:id="@+id/action_global_postViewFragment"
app:destination="@id/postViewFragment">
<argument
android:name="index"
app:argType="integer" />
<argument
android:name="idOrCodeArray"
app:argType="string[]" />
<argument
android:name="isId"
app:argType="boolean" />
</action>
</navigation>

25
app/src/main/res/navigation/profile_nav_graph.xml

@ -16,11 +16,28 @@
app:nullable="false" />
</action>
<include app:graph="@navigation/post_view_nav_graph" />
<action
android:id="@+id/action_global_postViewFragment"
app:destination="@id/post_view_nav_graph">
<argument
android:name="index"
app:argType="integer" />
<argument
android:name="idOrCodeArray"
app:argType="string[]" />
<argument
android:name="isId"
app:argType="boolean" />
</action>
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profileFragment">
<argument
android:name="username"
android:defaultValue=""
app:argType="string"
app:nullable="false" />
</action>
@ -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">
<argument
android:name="username"
android:defaultValue=""
app:argType="string"
app:nullable="false" />
<!--<action-->
<!-- android:id="@+id/action_profileFragment_self"-->
<!-- app:destination="@id/profileFragment" />-->
app:nullable="true" />
</fragment>
</navigation>
Loading…
Cancel
Save