From 69b0fb162aa1b09d4be657010510c54af8c8164e Mon Sep 17 00:00:00 2001 From: Austin Huang Date: Fri, 31 Jul 2020 11:53:30 -0400 Subject: [PATCH] saved viewer --- app/src/main/AndroidManifest.xml | 9 + .../java/awais/instagrabber/MainHelper.java | 79 ++++-- .../activities/CommentsViewer.java | 4 - .../awais/instagrabber/activities/Main.java | 3 + .../instagrabber/activities/PostViewer.java | 6 +- .../instagrabber/activities/SavedViewer.java | 234 ++++++++++++++++++ .../instagrabber/activities/StoryViewer.java | 13 + .../instagrabber/asyncs/PostsFetcher.java | 14 +- .../asyncs/StoryStatusFetcher.java | 3 + .../awais/instagrabber/models/StoryModel.java | 10 +- .../models/enums/DownloadMethod.java | 3 +- .../models/enums/ItemGetType.java | 1 + .../java/awais/instagrabber/utils/Utils.java | 40 ++- .../java/awaisomereport/LogCollector.java | 1 + .../main/res/drawable-anydpi/ic_bookmark.xml | 10 + app/src/main/res/drawable-anydpi/ic_like.xml | 10 + .../main/res/drawable-hdpi/ic_bookmark.png | Bin 0 -> 210 bytes app/src/main/res/drawable-hdpi/ic_like.png | Bin 0 -> 333 bytes .../main/res/drawable-mdpi/ic_bookmark.png | Bin 0 -> 160 bytes app/src/main/res/drawable-mdpi/ic_like.png | Bin 0 -> 239 bytes .../main/res/drawable-xhdpi/ic_bookmark.png | Bin 0 -> 264 bytes app/src/main/res/drawable-xhdpi/ic_like.png | Bin 0 -> 415 bytes .../main/res/drawable-xxhdpi/ic_bookmark.png | Bin 0 -> 380 bytes app/src/main/res/drawable-xxhdpi/ic_like.png | Bin 0 -> 570 bytes app/src/main/res/layout/activity_main.xml | 55 +++- app/src/main/res/layout/activity_saved.xml | 31 +++ .../main/res/layout/activity_story_viewer.xml | 11 +- .../res/layout/layout_include_toolbar.xml | 10 - app/src/main/res/menu/saved.xml | 9 + app/src/main/res/values/strings.xml | 6 + 30 files changed, 504 insertions(+), 58 deletions(-) create mode 100755 app/src/main/java/awais/instagrabber/activities/SavedViewer.java create mode 100644 app/src/main/res/drawable-anydpi/ic_bookmark.xml create mode 100644 app/src/main/res/drawable-anydpi/ic_like.xml create mode 100644 app/src/main/res/drawable-hdpi/ic_bookmark.png create mode 100644 app/src/main/res/drawable-hdpi/ic_like.png create mode 100644 app/src/main/res/drawable-mdpi/ic_bookmark.png create mode 100644 app/src/main/res/drawable-mdpi/ic_like.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_bookmark.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_like.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_bookmark.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_like.png create mode 100644 app/src/main/res/layout/activity_saved.xml create mode 100755 app/src/main/res/menu/saved.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 613d579d..9b389438 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -177,6 +177,15 @@ android:value=".activities.Main" /> + + + + + { @@ -779,8 +788,9 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { final String myId = Utils.getUserIdFromCookie(Utils.settingsHelper.getString(Constants.COOKIE)); if (!profileId.equals(myId)) { + main.mainBinding.btnTagged.setVisibility(View.GONE); + main.mainBinding.btnSaved.setVisibility(View.GONE); main.mainBinding.btnFollow.setVisibility(View.VISIBLE); - main.mainBinding.btnFollow.setOnClickListener(profileActionListener); if (profileModel.getFollowing() == true) { main.mainBinding.btnFollow.setText(R.string.unfollow); main.mainBinding.btnFollow.setBackgroundTintList(ColorStateList.valueOf(resources.getColor( @@ -797,30 +807,51 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { R.color.btn_pink_background, null))); } main.mainBinding.btnRestrict.setVisibility(View.VISIBLE); - main.mainBinding.btnRestrict.setOnClickListener(profileActionListener); if (profileModel.getRestricted() == true) { main.mainBinding.btnRestrict.setText(R.string.unrestrict); main.mainBinding.btnRestrict.setBackgroundTintList(ColorStateList.valueOf(resources.getColor( - R.color.btn_blue_background, null))); + R.color.btn_green_background, null))); } else { main.mainBinding.btnRestrict.setText(R.string.restrict); main.mainBinding.btnRestrict.setBackgroundTintList(ColorStateList.valueOf(resources.getColor( R.color.btn_orange_background, null))); } - main.mainBinding.btnBlock.setVisibility(View.VISIBLE); - main.mainBinding.btnBlock.setOnClickListener(profileActionListener); - if (profileModel.getBlocked() == true) { - main.mainBinding.btnBlock.setText(R.string.unblock); - main.mainBinding.btnBlock.setBackgroundTintList(ColorStateList.valueOf(resources.getColor( - R.color.btn_green_background, null))); - } - else { - main.mainBinding.btnBlock.setText(R.string.block); - main.mainBinding.btnBlock.setBackgroundTintList(ColorStateList.valueOf(resources.getColor( - R.color.btn_red_background, null))); + if (profileModel.isReallyPrivate()) { + main.mainBinding.btnBlock.setVisibility(View.VISIBLE); + main.mainBinding.btnSaved.setVisibility(View.GONE); + main.mainBinding.btnTagged.setVisibility(View.GONE); + if (profileModel.getBlocked() == true) { + main.mainBinding.btnBlock.setText(R.string.unblock); + main.mainBinding.btnBlock.setBackgroundTintList(ColorStateList.valueOf(resources.getColor( + R.color.btn_green_background, null))); + } else { + main.mainBinding.btnBlock.setText(R.string.block); + main.mainBinding.btnBlock.setBackgroundTintList(ColorStateList.valueOf(resources.getColor( + R.color.btn_red_background, null))); + } + } else { + main.mainBinding.btnBlock.setVisibility(View.GONE); + main.mainBinding.btnSaved.setVisibility(View.VISIBLE); + main.mainBinding.btnTagged.setVisibility(View.VISIBLE); + if (profileModel.getBlocked() == true) { + main.mainBinding.btnSaved.setText(R.string.unblock); + main.mainBinding.btnSaved.setBackgroundTintList(ColorStateList.valueOf(resources.getColor( + R.color.btn_green_background, null))); + } else { + main.mainBinding.btnSaved.setText(R.string.block); + main.mainBinding.btnSaved.setBackgroundTintList(ColorStateList.valueOf(resources.getColor( + R.color.btn_red_background, null))); + } } } + else { + main.mainBinding.btnTagged.setVisibility(View.VISIBLE); + main.mainBinding.btnSaved.setVisibility(View.VISIBLE); + main.mainBinding.btnSaved.setText(R.string.saved); + main.mainBinding.btnSaved.setBackgroundTintList(ColorStateList.valueOf(resources.getColor( + R.color.btn_orange_background, null))); + } } else { if (Utils.dataBox.getFavorite(main.userQuery) != null) { main.mainBinding.btnFollow.setText(R.string.unfavorite); @@ -832,7 +863,6 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { main.mainBinding.btnFollow.setBackgroundTintList(ColorStateList.valueOf(resources.getColor( R.color.btn_pink_background, null))); } - main.mainBinding.btnFollow.setOnClickListener(profileActionListener); main.mainBinding.btnFollow.setVisibility(View.VISIBLE); } @@ -864,7 +894,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { span.setSpan(new StyleSpan(Typeface.BOLD), 0, followingCountStrLen, 0); main.mainBinding.mainFollowing.setText(span); - main.mainBinding.mainFullName.setText(profileModel.getName()); + main.mainBinding.mainFullName.setText(Utils.isEmpty(profileModel.getName()) ? profileModel.getUsername() : profileModel.getName()); CharSequence biography = profileModel.getBiography(); main.mainBinding.mainBiography.setCaptionIsExpandable(true); @@ -1163,6 +1193,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { private final View.OnClickListener profileActionListener = new View.OnClickListener() { @Override public void onClick(final View v) { + final boolean iamme = Utils.getUserIdFromCookie(Utils.settingsHelper.getString(Constants.COOKIE)).equals(main.profileModel.getId()); if (!isLoggedIn && Utils.dataBox.getFavorite(main.userQuery) != null) { Utils.dataBox.delFavorite(new DataBox.FavoriteModel(main.userQuery, Long.parseLong(Utils.dataBox.getFavorite(main.userQuery).split("/")[1]), @@ -1176,10 +1207,20 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { new ProfileAction().execute("follow"); } else if (v == main.mainBinding.btnRestrict) { new ProfileAction().execute("restrict"); - } else if (v == main.mainBinding.btnBlock) { + } else if (v == main.mainBinding.btnSaved && !iamme) { new ProfileAction().execute("block"); } else if (v == main.mainBinding.btnFollowTag) { new ProfileAction().execute("followtag"); + } else if (v == main.mainBinding.btnTagged) { + main.startActivity(new Intent(main, SavedViewer.class) + .putExtra(Constants.EXTRAS_INDEX, "%"+main.profileModel.getId()) + .putExtra(Constants.EXTRAS_USER, "@"+main.profileModel.getUsername()) + ); + } else if (v == main.mainBinding.btnSaved) { + main.startActivity(new Intent(main, SavedViewer.class) + .putExtra(Constants.EXTRAS_INDEX, "$"+main.profileModel.getId()) + .putExtra(Constants.EXTRAS_USER, "@"+main.profileModel.getUsername()) + ); } } }; diff --git a/app/src/main/java/awais/instagrabber/activities/CommentsViewer.java b/app/src/main/java/awais/instagrabber/activities/CommentsViewer.java index 5f031251..bb458a34 100755 --- a/app/src/main/java/awais/instagrabber/activities/CommentsViewer.java +++ b/app/src/main/java/awais/instagrabber/activities/CommentsViewer.java @@ -87,8 +87,6 @@ public final class CommentsViewer extends BaseLanguageActivity implements SwipeR new CommentsFetcher(shortCode, new FetchListener() { @Override public void onResult(final CommentModel[] commentModels) { - commentsBinding.toolbar.progressCircular.setVisibility(View.GONE); - commentsAdapter = new CommentsAdapter(commentModels, true, clickListener, mentionClickListener); commentsBinding.rvComments.setAdapter(commentsAdapter); @@ -105,8 +103,6 @@ public final class CommentsViewer extends BaseLanguageActivity implements SwipeR public void onResult(final CommentModel[] commentModels) { commentsBinding.swipeRefreshLayout.setRefreshing(false); - commentsBinding.toolbar.progressCircular.setVisibility(View.GONE); - commentsAdapter = new CommentsAdapter(commentModels, true, clickListener, mentionClickListener); commentsBinding.rvComments.setAdapter(commentsAdapter); diff --git a/app/src/main/java/awais/instagrabber/activities/Main.java b/app/src/main/java/awais/instagrabber/activities/Main.java index 6a6079c6..10eaa5c5 100755 --- a/app/src/main/java/awais/instagrabber/activities/Main.java +++ b/app/src/main/java/awais/instagrabber/activities/Main.java @@ -458,6 +458,9 @@ public final class Main extends BaseLanguageActivity { return; } } + else { + finish(); + } } @Override diff --git a/app/src/main/java/awais/instagrabber/activities/PostViewer.java b/app/src/main/java/awais/instagrabber/activities/PostViewer.java index d197a118..6dc0c4ba 100755 --- a/app/src/main/java/awais/instagrabber/activities/PostViewer.java +++ b/app/src/main/java/awais/instagrabber/activities/PostViewer.java @@ -268,7 +268,11 @@ public final class PostViewer extends BaseLanguageActivity { final List itemGetterItems; final boolean isMainSwipe; - if (itemGetType != null && Main.itemGetter != null) { + 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 && Main.itemGetter != null) { itemGetterItems = Main.itemGetter.get(itemGetType); isMainSwipe = !(itemGetterItems.size() < 1 || itemGetType == ItemGetType.MAIN_ITEMS && isFromShare); } else { diff --git a/app/src/main/java/awais/instagrabber/activities/SavedViewer.java b/app/src/main/java/awais/instagrabber/activities/SavedViewer.java new file mode 100755 index 00000000..191d5f06 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/activities/SavedViewer.java @@ -0,0 +1,234 @@ +package awais.instagrabber.activities; + +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.os.AsyncTask; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import java.util.ArrayList; +import java.util.Arrays; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.R; +import awais.instagrabber.adapters.PostsAdapter; +import awais.instagrabber.asyncs.PostsFetcher; +import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager; +import awais.instagrabber.customviews.helpers.GridSpacingItemDecoration; +import awais.instagrabber.customviews.helpers.RecyclerLazyLoader; +import awais.instagrabber.databinding.ActivitySavedBinding; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.interfaces.ItemGetter; +import awais.instagrabber.models.BasePostModel; +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; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Constants.AUTOLOAD_POSTS; +import static awais.instagrabber.utils.Utils.logCollector; + +public final class SavedViewer extends BaseLanguageActivity implements SwipeRefreshLayout.OnRefreshListener { + private static AsyncTask currentlyExecuting; + public static ItemGetter itemGetter; + private PostsAdapter postsAdapter; + private boolean hasNextPage, autoloadPosts; + //private CommentModel commentModel; + private ActivitySavedBinding savedBinding; + private String action, username, endCursor; + private final String cookie = Utils.settingsHelper.getString(Constants.COOKIE); + private RecyclerLazyLoader lazyLoader; + private Resources resources; + private ArrayList selectedItems = new ArrayList<>(); + private final ArrayList allItems = new ArrayList<>(); + private MenuItem downloadAction; + + private final FetchListener postsFetchListener = new FetchListener() { + @Override + public void onResult(final PostModel[] result) { + if (result != null) { + final int oldSize = allItems.size(); + allItems.addAll(Arrays.asList(result)); + + postsAdapter.notifyItemRangeInserted(oldSize, result.length); + + savedBinding.mainPosts.post(() -> { + savedBinding.mainPosts.setNestedScrollingEnabled(true); + savedBinding.mainPosts.setVisibility(View.VISIBLE); + }); + + final PostModel model = result[result.length - 1]; + if (model != null) { + endCursor = model.getEndCursor(); + + hasNextPage = model.hasNextPage(); + if (autoloadPosts && hasNextPage) + currentlyExecuting = new PostsFetcher(action, endCursor, this) + .setUsername(username).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + else { + savedBinding.swipeRefreshLayout.setRefreshing(false); + } + model.setPageCursor(false, null); + } + } + else { + savedBinding.swipeRefreshLayout.setRefreshing(false); + Toast.makeText(getApplicationContext(), R.string.empty_list, Toast.LENGTH_SHORT).show(); + finish(); + } + } + }; + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + savedBinding = ActivitySavedBinding.inflate(getLayoutInflater()); + setContentView(savedBinding.getRoot()); + savedBinding.swipeRefreshLayout.setOnRefreshListener(this); + autoloadPosts = Utils.settingsHelper.getBoolean(AUTOLOAD_POSTS); + savedBinding.mainPosts.setNestedScrollingEnabled(false); + final GridAutofitLayoutManager layoutManager = new GridAutofitLayoutManager(this, Utils.convertDpToPx(110)); + savedBinding.mainPosts.setLayoutManager(layoutManager); + savedBinding.mainPosts.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4))); + + final Intent intent = getIntent(); + if (intent == null || !intent.hasExtra(Constants.EXTRAS_INDEX) + || Utils.isEmpty((action = intent.getStringExtra(Constants.EXTRAS_INDEX))) + || !intent.hasExtra(Constants.EXTRAS_USER) + || Utils.isEmpty((username = intent.getStringExtra(Constants.EXTRAS_USER)))) { + Utils.errorFinish(this); + return; + } + + savedBinding.mainPosts.setAdapter(postsAdapter = new PostsAdapter(allItems, v -> { + final Object tag = v.getTag(); + if (tag instanceof PostModel) { + final PostModel postModel = (PostModel) tag; + + if (postsAdapter.isSelecting) toggleSelection(postModel); + else startActivity(new Intent(this, PostViewer.class) + .putExtra(Constants.EXTRAS_INDEX, postModel.getPosition()) + .putExtra(Constants.EXTRAS_POST, postModel) + .putExtra(Constants.EXTRAS_USER, username) + .putExtra(Constants.EXTRAS_TYPE, ItemGetType.SAVED_ITEMS)); + } + }, v -> { + final Object tag = v.getTag(); + if (tag instanceof PostModel) { + postsAdapter.isSelecting = true; + toggleSelection((PostModel) tag); + } + return true; + })); + 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))); + savedBinding.toolbar.toolbar.setSubtitle(username); + + lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { + if (!autoloadPosts && hasNextPage) { + savedBinding.swipeRefreshLayout.setRefreshing(true); + stopCurrentExecutor(); + currentlyExecuting = new PostsFetcher(action, endCursor, postsFetchListener) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + endCursor = null; + } + }); + savedBinding.mainPosts.addOnScrollListener(lazyLoader); + + itemGetter = itemGetType -> { + if (itemGetType == ItemGetType.SAVED_ITEMS) return allItems; + return null; + }; + + new PostsFetcher(action, postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + @Override + public boolean onCreateOptionsMenu(final Menu menu) { + getMenuInflater().inflate(R.menu.saved, menu); + + downloadAction = menu.findItem(R.id.downloadAction); + downloadAction.setVisible(false); + + downloadAction.setOnMenuItemClickListener(item -> { + if (selectedItems.size() > 0) { + Utils.batchDownload(this, null, DownloadMethod.DOWNLOAD_SAVED, selectedItems); + } + return true; + }); + return true; + } + + public void deselectSelection(final BasePostModel postModel) { + if (postModel instanceof PostModel) { + selectedItems.remove(postModel); + postModel.setSelected(false); + if (postsAdapter != null) notifyAdapter((PostModel) postModel); + } + } + + @Override + public void onRefresh() { + if (lazyLoader != null) lazyLoader.resetState(); + stopCurrentExecutor(); + allItems.clear(); + selectedItems.clear(); + if (postsAdapter != null) { + postsAdapter.isSelecting = false; + postsAdapter.notifyDataSetChanged(); + } + savedBinding.swipeRefreshLayout.setRefreshing(true); + new PostsFetcher(action, postsFetchListener).setUsername(username).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + @Override + public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == 8020 && grantResults[0] == PackageManager.PERMISSION_GRANTED && selectedItems.size() > 0) + Utils.batchDownload(this, null, DownloadMethod.DOWNLOAD_SAVED, selectedItems); + } + + public static void stopCurrentExecutor() { + if (currentlyExecuting != null) { + try { + currentlyExecuting.cancel(true); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.MAIN_HELPER, "stopCurrentExecutor"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + } + + private void toggleSelection(final PostModel postModel) { + if (postModel != null && postsAdapter != null) { + if (postModel.isSelected()) selectedItems.remove(postModel); + else selectedItems.add(postModel); + postModel.setSelected(!postModel.isSelected()); + notifyAdapter(postModel); + } + } + + private void notifyAdapter(final PostModel postModel) { + if (selectedItems.size() < 1) postsAdapter.isSelecting = false; + if (postModel.getPosition() < 0) postsAdapter.notifyDataSetChanged(); + else postsAdapter.notifyItemChanged(postModel.getPosition(), postModel); + + if (downloadAction != null) { + downloadAction.setVisible(postsAdapter.isSelecting); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/activities/StoryViewer.java b/app/src/main/java/awais/instagrabber/activities/StoryViewer.java index d0adf0df..78c73cc2 100755 --- a/app/src/main/java/awais/instagrabber/activities/StoryViewer.java +++ b/app/src/main/java/awais/instagrabber/activities/StoryViewer.java @@ -194,6 +194,15 @@ public final class StoryViewer extends BaseLanguageActivity { return false; }); + storyViewerBinding.spotify.setOnClickListener(v -> { + final Object tag = v.getTag(); + if (tag instanceof CharSequence) { + final Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(tag.toString())); + startActivity(intent); + } + }); + storyViewerBinding.viewStoryPost.setOnClickListener(v -> { final Object tag = v.getTag(); if (tag instanceof CharSequence) startActivity(new Intent(this, PostViewer.class) @@ -397,6 +406,10 @@ public final class StoryViewer extends BaseLanguageActivity { storyViewerBinding.viewStoryPost.setVisibility(shortCode != null ? View.VISIBLE : View.GONE); storyViewerBinding.viewStoryPost.setTag(shortCode); + final String spotify = currentStory.getSpotify(); + storyViewerBinding.spotify.setVisibility(spotify != null ? View.VISIBLE : View.GONE); + storyViewerBinding.spotify.setTag(spotify); + final PollModel poll = currentStory.getPoll(); storyViewerBinding.interactStory.setVisibility(poll != null ? View.VISIBLE : View.GONE); storyViewerBinding.interactStory.setText(R.string.vote_story_poll); diff --git a/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java index 8a41325a..5a144d11 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java @@ -49,6 +49,9 @@ public final class PostsFetcher extends AsyncTask { @Override protected PostModel[] doInBackground(final Void... voids) { final boolean isHashTag = id.charAt(0) == '#'; + final boolean isSaved = id.charAt(0) == '$'; + final boolean isTagged = id.charAt(0) == '%'; + //final boolean isLiked = id.charAt(0) == '^'; final boolean isLocation = id.contains("/"); final String url; @@ -58,6 +61,12 @@ public final class PostsFetcher extends AsyncTask { else if (isLocation) url = "https://www.instagram.com/graphql/query/?query_hash=36bd0f2bf5911908de389b8ceaa3be6d&variables=" + "{\"id\":\""+ id.split("/")[0] +"\",\"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 + "\"}"; + else if (isTagged) + url = "https://www.instagram.com/graphql/query/?query_hash=ff260833edf142911047af6024eb634a&variables=" + + "{\"id\":\""+ id.substring(1) +"\",\"first\":150,\"after\":\"" + endCursor + "\"}"; else url = "https://www.instagram.com/graphql/query/?query_id=17880160963012870&id=" + id + "&first=50&after=" + endCursor; @@ -80,7 +89,9 @@ public final class PostsFetcher extends AsyncTask { .getJSONObject(isHashTag ? Constants.EXTRAS_HASHTAG : (isLocation ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_USER)) .getJSONObject(isHashTag ? "edge_hashtag_to_media" : - (isLocation ? "edge_location_to_media" : "edge_owner_to_timeline_media")); + (isLocation ? "edge_location_to_media" : + (isSaved ? "edge_saved_media" : + (isTagged ? "edge_user_to_photos_of_you" : "edge_owner_to_timeline_media")))); final String endCursor; final boolean hasNextPage; @@ -116,6 +127,7 @@ public final class PostsFetcher extends AsyncTask { mediaNode.optBoolean("viewer_has_saved"), mediaNode.getJSONObject("edge_liked_by").getLong("count")); Utils.checkExistence(downloadDir, customDir, username, isSlider, models[i]); + Utils.checkExistence(downloadDir, customDir, "@"+username, isSlider, models[i]); } if (models[models.length - 1] != null) diff --git a/app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java index 4c84fca1..2929c67a 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java @@ -74,6 +74,9 @@ public final class StoryStatusFetcher extends AsyncTask= 0; i--) { final BasePostModel selectedItem = itemsToDownload.get(i); - if (main == null) { + if (main == null && saved == null) { new DownloadAsync(context, selectedItem.getDisplayUrl(), getDownloadSaveFile(finalDir, selectedItem, ""), null).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else if (saved != null) { + new PostFetcher(selectedItem.getShortCode(), result -> { + if (result != null) { + final int resultsSize = result.length; + final boolean multiResult = resultsSize > 1; + + for (int j = 0; j < resultsSize; j++) { + final BasePostModel model = result[j]; + final File saveFile = getDownloadSaveFile(finalDir, model, multiResult ? "_slide_" + (j + 1) : ""); + + new DownloadAsync(context, + model.getDisplayUrl(), + saveFile, + file -> { + model.setDownloaded(true); + saved.deselectSelection(selectedItem); + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } else { + saved.deselectSelection(selectedItem); + } + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else { new PostFetcher(selectedItem.getShortCode(), result -> { if (result != null) { @@ -986,16 +1010,7 @@ public final class Utils { final String fileWithoutPrefix = fileName + '0' + extension; exists = new File(downloadDir, fileWithoutPrefix).exists(); if (!exists) { - if (customDir != null) exists = new File(customDir, fileWithoutPrefix).exists(); - if (!exists && !Utils.isEmpty(username)) { - exists = new File(new File(downloadDir, username), fileWithoutPrefix).exists(); - } - if (!exists && customDir != null) - exists = new File(new File(customDir, username), fileWithoutPrefix).exists(); - } - - if (!exists && isSlider) { - final String fileWithPrefix = fileName + "[\\d]+_slide_[\\d]+" + extension; + final String fileWithPrefix = fileName + "[\\d]+(|_slide_[\\d]+)(\\.mp4|\\" + extension + ")"; final FilenameFilter filenameFilter = (dir, name) -> Pattern.matches(fileWithPrefix, name); File[] files = downloadDir.listFiles(filenameFilter); @@ -1163,6 +1178,9 @@ public final class Utils { if (isVideo && data.has("video_resources")) storyModels[j].setVideoUrl(Utils.getHighQualityPost(data.getJSONArray("video_resources"), true)); + if (!data.isNull("story_app_attribution")) + storyModels[j].setSpotify(data.getJSONObject("story_app_attribution").optString("content_url").split("\\?")[0]); + if (hasTappableObjecs) { for (int k = 0; k < tappableLength; ++k) { JSONObject jsonObject = tappableObjects.getJSONObject(k); diff --git a/app/src/main/java/awaisomereport/LogCollector.java b/app/src/main/java/awaisomereport/LogCollector.java index fb1ce720..b0144c87 100755 --- a/app/src/main/java/awaisomereport/LogCollector.java +++ b/app/src/main/java/awaisomereport/LogCollector.java @@ -110,6 +110,7 @@ public final class LogCollector { ASYNC_LOCATION_FETCHER("async-location-fetcher.txt"), ASYNC_PROFILE_FETCHER("async-profile-fetcher.txt"), ASYNC_PROFILE_PICTURE_FETCHER("async-pfp-fetcher.txt"), + ASYNC_SAVED_FETCHER("async-saved-fetcher.txt"), ASYNC_STORY_STATUS_FETCHER("async-story-status-fetcher.txt"), ASYNC_DISCOVER_FETCHER("async-discover-fetcher.txt"), ASYNC_COMMENTS_FETCHER("async-comments-fetcher.txt"), diff --git a/app/src/main/res/drawable-anydpi/ic_bookmark.xml b/app/src/main/res/drawable-anydpi/ic_bookmark.xml new file mode 100644 index 00000000..69bc5089 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_bookmark.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable-anydpi/ic_like.xml b/app/src/main/res/drawable-anydpi/ic_like.xml new file mode 100644 index 00000000..f68e110e --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_like.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable-hdpi/ic_bookmark.png b/app/src/main/res/drawable-hdpi/ic_bookmark.png new file mode 100644 index 0000000000000000000000000000000000000000..8dbfafa9fca4c473cfde4a90e243238c63d275e5 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBW_r3fhE&{2PLN<-+`xC>%9W67 zXU?2y7veE$j_UI?Ff^R$$;)HZ{b<6%X~`30RJ}W!Ycd}w+z({$waU2SxR_6>^umf} zH(8Tc3!p+PY&kR19p=uE@nu!aPy2@8YD27|uQgI+DTD)z4*}Q$iB} D^bkys literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_like.png b/app/src/main/res/drawable-hdpi/ic_like.png new file mode 100644 index 0000000000000000000000000000000000000000..3984ecbbec2cbc2b941d9b0e88aaacefaf532c56 GIT binary patch literal 333 zcmV-T0kZyyP)qxfCaIgmsYES#N_=zTIIp5O?6AaE zRn@6&+Y9>@-ZV|ge)h$o5Bg4V&|#0D?v~!{16Inc1*&TolXnJsHx5cbjtuVx|Zvy4TLeRK-w^q z?+S=B^mZ*7WdI^qQ4bl4dhi{J+CXRD!AQGUt{hpC+-JQ4OfP+YP}ZeddJm7 z51I9ZgDd7CxVmmqLq&m!1r-%06e7Fi*Ar-fh6C_xlFbE3^mnJ7a zHdC;jEWs1H+HVW%5{bSXPEETRo_um!6RtD`a=YnDd=i^6YnB?rMx7NAY#Uc5F|OcX zlX}LzWakEvmr4OUIaQ(=u7vPh$#Gp%H6d!jyjvGn&C+3Dc$_c!bxHW|-9RfDJYD@< J);T3K0RR-;G_e2x literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_like.png b/app/src/main/res/drawable-mdpi/ic_like.png new file mode 100644 index 0000000000000000000000000000000000000000..ebc886077b1a425fe02b32ab03d4b1a82ec535a5 GIT binary patch literal 239 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gj+dN$yLn>~)4b>KFP!KSgyf%%W zLBv1#8(-L}usrR@hnpJK>DV>@zQ=MWu`Sll?5zBi2|?SUUI%J!wTLh`lXzTx!jVs= zz}e44CexxN+2LMs4wHe@B<=H^!W&$)KjvH1#w?=o}u2qvauM8J55PYg^Dc zZ=-AND>)yY)$@zCM@)IcTE*YH`t}`L!-Fzs_I{NM^!0cYGTHr6xo_8z^*#|tn1zE~ nZ7dFLZeQ_ryYST`_R`XgD)y)5F8loz=mQ2%S3j3^P6$qj literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_bookmark.png b/app/src/main/res/drawable-xhdpi/ic_bookmark.png new file mode 100644 index 0000000000000000000000000000000000000000..6dae74173c801ae11339abdfc9a3e0cc0104c656 GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUt^PVn_Ar-gY&NSp}au9G`xi)jH z?SXe@cN(oPWM$`icdy<4Rlo7r0?s$*lurIW>F>c|{J(W&+A1!^7Cz(SHEKtD4)f3`W5*_?Fw?u*&S-!Xiip>pMqRa_dw{$nan uKYg~06Z_s6nmnn%L-Kfcvz*fli7Mv9SK?ylubPqwvdPoc&t;ucLK6V_m}|xW literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_like.png b/app/src/main/res/drawable-xhdpi/ic_like.png new file mode 100644 index 0000000000000000000000000000000000000000..eadf8e7bf64eb5434a374583d2911492e1668ecb GIT binary patch literal 415 zcmV;Q0bu@#P)?{S_2E2ms#vn9K-hOalg3GsXwjlY z3&P5>Oq-@T^Xr}aR8`dzod0HUZ+n(1#$iI7NhOXd@C#3}?8&})UDvmF0N@@x!^D7G zkkgn5Pk0imt>6p1E5^YVK=e(OOdGsTQb~;#+$08IP$mJ=X;$8eZ%U*p)xS~!FQ|D% zSKqXC9QlG$!9vfvRH4NX7zq;?F)cJvB>>od5}*ox_x~rrWts`M5W^5)K@;F#dPjH_ z>M#mqgcZoJ|HdrH_7PU1oS*`^>UMf0)cb?ZB$jbs3AD~?GSn0Vs$ZCnmHmO>ds~A& zBfaV%N6gtH_}S{wicb61iUR0hk`dHK?1yV@;s<) z&d7k5KJLNE&eAi9-ud3f1Bq7aSdc1-;J{0xX`V!j7A@K*djUM7-4pfU!(IRY002ov JPDHLkV1hymx%~hD literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_bookmark.png b/app/src/main/res/drawable-xxhdpi/ic_bookmark.png new file mode 100644 index 0000000000000000000000000000000000000000..620babe101398b6a5f88670e604b71440afeac60 GIT binary patch literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2V089$aSW-r_4c-Z*C7LuhL26z zU%9H<%rZA>^FP?6{(uRxVgzbf(8NH}1o41%)WzKL?9bC%1F} z!HUzDOy;IXhV8z}61R1ZtMHi{vRSJcp5^T<&ONnBhK;?b{pXdo;^r@cBF80+FLxEk zUc05Eav{okLiFkh`|a-wGSs%R+;V5Q!oVWnz`)3Iq2GbMfq{ubp@E@G_(X0U3y1~g zLWmXR3xq-Hz=~l+CUX`8lLzmGO&VRDI+bre-_O3tWZ5#;Fm2-VpD#Xcerj3iyROn& zVQ1^X+K+oytvVQAeZsWpt@d_X7se9FnM=2p-72%M%%A-+nD@(ViLGyMehlXPat6rQ z|9CmuiQ^KbhII!UcS$JEe=PpSptfgX|3`0-&pT?$+3XKo6hFW&Sq=%A_P)Ejs5XG50cg@vi@*5++cNGPs;8v^?Sszwrx*1&(@c^&lm1B`x+m9;Pc@hWpUxF za!}aQqL42Q=g-%Dyz2+&n)(8)7+{WD3;V<-RQjDp&?C~s=0-V&N~fzOm}TLApQQti z;XjwYPg0Osr^_gMy2^(zBrkGWv2pu(OnFe~ zW!pKIr&_RghEnX0y!AUd?0N);lhXLe>pMZILy8VZG9)o@BtjAgM-n8la3nwy4<{z1 zWZ=YrlpLIpkdlQH0#fpDe9qmXe1nk+q-b-i6d+{_M_*4eS>MJrBEA8W2&pJI3rNG8 zAH|ggXR*dTtiTz(uOX)jiEvg1l-UdbeLx}{ilQirq9_^q2jC~hen~A1VgLXD07*qo IM6N<$f?`Sm+yDRo literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 94abacf5..aeabab5b 100755 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -112,26 +112,25 @@ android:id="@+id/profileActions" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_below="@id/mainUrl" - android:weightSum="3"> + android:layout_below="@id/mainUrl"> + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_story_viewer.xml b/app/src/main/res/layout/activity_story_viewer.xml index f332cb0b..d6a6a7f4 100755 --- a/app/src/main/res/layout/activity_story_viewer.xml +++ b/app/src/main/res/layout/activity_story_viewer.xml @@ -44,7 +44,7 @@ android:layout_height="wrap_content" android:layout_weight="0.3" android:background="#0000" - android:weightSum="2" + android:weightSum="3" android:layout_gravity="bottom"> + diff --git a/app/src/main/res/layout/layout_include_toolbar.xml b/app/src/main/res/layout/layout_include_toolbar.xml index 600dced8..8beaabe3 100755 --- a/app/src/main/res/layout/layout_include_toolbar.xml +++ b/app/src/main/res/layout/layout_include_toolbar.xml @@ -6,14 +6,4 @@ android:layout_height="?actionBarSize" android:background="@null" app:title="@string/app_name"> - - \ No newline at end of file diff --git a/app/src/main/res/menu/saved.xml b/app/src/main/res/menu/saved.xml new file mode 100755 index 00000000..1af65823 --- /dev/null +++ b/app/src/main/res/menu/saved.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7140ceef..7dfa1719 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -60,11 +60,13 @@ Show stories No more stories! View Story Post + Spotify Vote Vote successful! You have already voted! This Account is Private This Account has No Posts + No Such Posts! Current version: v%s read moreā€¦ Login @@ -75,6 +77,10 @@ Join Telegram Group Join Matrix Room + Liked + Saved + Tagged + Like (%s) Unlike (%s) Bookmark