Tabs! Fragments! WIP!
@ -37,21 +37,28 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation('androidx.appcompat:appcompat:1.3.0-alpha01@aar') { transitive true }
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||
implementation('com.google.android.material:material:1.3.0-alpha02@aar') { transitive true }
|
||||
implementation('androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01') { transitive true }
|
||||
|
||||
def appcompat_version = "1.2.0"
|
||||
def nav_version = "2.3.0"
|
||||
|
||||
implementation "androidx.appcompat:appcompat:$appcompat_version"
|
||||
// For loading and tinting drawables on older versions of the platform
|
||||
implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
|
||||
implementation "androidx.recyclerview:recyclerview:1.2.0-alpha05"
|
||||
implementation 'com.google.android.material:material:1.2.0'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
implementation "androidx.viewpager2:viewpager2:1.0.0"
|
||||
implementation "androidx.navigation:navigation-fragment:$nav_version"
|
||||
implementation "androidx.navigation:navigation-ui:$nav_version"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.0.0"
|
||||
|
||||
implementation 'org.jsoup:jsoup:1.13.1'
|
||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||
implementation 'com.github.chrisbanes:PhotoView:v2.0.0'
|
||||
implementation 'com.google.android.exoplayer:exoplayer:2.11.1'
|
||||
implementation 'com.facebook.fresco:fresco:2.3.0'
|
||||
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
|
||||
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
|
||||
|
||||
implementation('org.jsoup:jsoup:1.13.1') { transitive true }
|
||||
implementation('com.github.bumptech.glide:glide:4.11.0') { transitive true }
|
||||
implementation('com.github.chrisbanes:PhotoView:v2.0.0@aar') { transitive true }
|
||||
implementation('com.google.android.exoplayer:exoplayer:2.11.1@aar') { transitive true }
|
||||
|
||||
implementation 'com.facebook.fresco:fresco:2.3.0'
|
||||
}
|
||||
|
@ -51,13 +51,11 @@ import java.util.Map;
|
||||
|
||||
import awais.instagrabber.activities.CommentsViewer;
|
||||
import awais.instagrabber.activities.FollowViewer;
|
||||
import awais.instagrabber.activities.MainActivity;
|
||||
import awais.instagrabber.activities.MainActivityBackup;
|
||||
import awais.instagrabber.activities.PostViewer;
|
||||
import awais.instagrabber.activities.SavedViewer;
|
||||
import awais.instagrabber.activities.StoryViewer;
|
||||
import awais.instagrabber.adapters.DiscoverAdapter;
|
||||
import awais.instagrabber.adapters.FeedAdapter;
|
||||
import awais.instagrabber.adapters.FeedStoriesAdapter;
|
||||
import awais.instagrabber.adapters.PostsAdapter;
|
||||
import awais.instagrabber.adapters.viewholder.feed.FeedItemViewHolder;
|
||||
import awais.instagrabber.asyncs.DiscoverFetcher;
|
||||
@ -111,8 +109,14 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private static AsyncTask<?, ?, ?> currentlyExecuting;
|
||||
private AsyncTask<Void, Void, FeedStoryModel[]> prevStoriesFetcher;
|
||||
private FeedStoryModel[] stories;
|
||||
private boolean hasNextPage = false, feedHasNextPage = false, discoverHasMore = false;
|
||||
private String endCursor = null, feedEndCursor = null, discoverEndMaxId = null, topic = null, rankToken = null;
|
||||
private boolean hasNextPage = false;
|
||||
private boolean feedHasNextPage = false;
|
||||
private boolean discoverHasMore = false;
|
||||
private String endCursor = null;
|
||||
private String feedEndCursor = null;
|
||||
private String discoverEndMaxId = null;
|
||||
private String topic = null;
|
||||
private String rankToken = null;
|
||||
private String[] topicIds = null;
|
||||
|
||||
private final boolean autoloadPosts;
|
||||
@ -293,7 +297,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
|
||||
@Override
|
||||
public void onResult(final FeedStoryModel[] result) {
|
||||
feedStoriesAdapter.setData(result);
|
||||
// feedStoriesAdapter.setData(result);
|
||||
if (result != null && result.length > 0) {
|
||||
mainActivity.mainBinding.feedView.feedStories.setVisibility(View.VISIBLE);
|
||||
stories = result;
|
||||
@ -305,32 +309,32 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
public void onClick(final RamboTextView view, final String text, final boolean isHashtag) {
|
||||
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 (MainActivity.scanHack != null) MainActivity.scanHack.onResult(text);
|
||||
if (MainActivityBackup.scanHack != null) MainActivityBackup.scanHack.onResult(text);
|
||||
}).show();
|
||||
}
|
||||
};
|
||||
private final FeedStoriesAdapter feedStoriesAdapter = new FeedStoriesAdapter(null, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof FeedStoryModel) {
|
||||
final FeedStoryModel feedStoryModel = (FeedStoryModel) tag;
|
||||
final int index = indexOfIntArray(stories, feedStoryModel);
|
||||
new iStoryStatusFetcher(feedStoryModel.getStoryMediaId(), null, false, false, false, false, result -> {
|
||||
if (result != null && result.length > 0)
|
||||
mainActivity.startActivity(new Intent(mainActivity, StoryViewer.class)
|
||||
.putExtra(Constants.EXTRAS_STORIES, result)
|
||||
.putExtra(Constants.EXTRAS_USERNAME, feedStoryModel.getProfileModel().getUsername())
|
||||
.putExtra(Constants.FEED, stories)
|
||||
.putExtra(Constants.FEED_ORDER, index)
|
||||
);
|
||||
else
|
||||
Toast.makeText(mainActivity, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
});
|
||||
private MainActivity mainActivity;
|
||||
// private final FeedStoriesAdapter feedStoriesAdapter = new FeedStoriesAdapter(null, new View.OnClickListener() {
|
||||
// @Override
|
||||
// public void onClick(final View v) {
|
||||
// final Object tag = v.getTag();
|
||||
// if (tag instanceof FeedStoryModel) {
|
||||
// final FeedStoryModel feedStoryModel = (FeedStoryModel) tag;
|
||||
// final int index = indexOfIntArray(stories, feedStoryModel);
|
||||
// new iStoryStatusFetcher(feedStoryModel.getStoryMediaId(), null, false, false, false, false, result -> {
|
||||
// if (result != null && result.length > 0)
|
||||
// mainActivity.startActivity(new Intent(mainActivity, StoryViewer.class)
|
||||
// .putExtra(Constants.EXTRAS_STORIES, result)
|
||||
// .putExtra(Constants.EXTRAS_USERNAME, feedStoryModel.getProfileModel().getUsername())
|
||||
// .putExtra(Constants.FEED, stories)
|
||||
// .putExtra(Constants.FEED_ORDER, index)
|
||||
// );
|
||||
// else
|
||||
// Toast.makeText(mainActivity, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
// }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
private MainActivityBackup mainActivity;
|
||||
private Resources resources;
|
||||
private final View collapsingToolbar;
|
||||
private final RecyclerLazyLoader lazyLoader;
|
||||
@ -345,7 +349,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private RequestManager glide;
|
||||
private VideoAwareRecyclerScroller videoAwareRecyclerScroller;
|
||||
|
||||
public MainHelper(@NonNull final MainActivity mainActivity) {
|
||||
public MainHelper(@NonNull final MainActivityBackup mainActivity) {
|
||||
stopCurrentExecutor();
|
||||
|
||||
this.mainActivity = mainActivity;
|
||||
@ -522,26 +526,27 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
final GridAutofitLayoutManager layoutManager = new GridAutofitLayoutManager(mainActivity, Utils.convertDpToPx(110));
|
||||
mainActivity.mainBinding.profileView.mainPosts.setLayoutManager(layoutManager);
|
||||
mainActivity.mainBinding.profileView.mainPosts.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4)));
|
||||
mainActivity.mainBinding.profileView.mainPosts.setAdapter(postsAdapter = new PostsAdapter(mainActivity.allItems, v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof PostModel) {
|
||||
final PostModel postModel = (PostModel) tag;
|
||||
|
||||
if (postsAdapter.isSelecting) toggleSelection(postModel);
|
||||
else mainActivity.startActivity(new Intent(mainActivity, PostViewer.class)
|
||||
.putExtra(Constants.EXTRAS_INDEX, postModel.getPosition())
|
||||
.putExtra(Constants.EXTRAS_POST, postModel)
|
||||
.putExtra(Constants.EXTRAS_USER, mainActivity.userQuery)
|
||||
.putExtra(Constants.EXTRAS_TYPE, ItemGetType.MAIN_ITEMS));
|
||||
}
|
||||
}, v -> { // long click listener
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof PostModel) {
|
||||
postsAdapter.isSelecting = true;
|
||||
toggleSelection((PostModel) tag);
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
// mainActivity.mainBinding.profileView.mainPosts.setAdapter(postsAdapter = new PostsAdapter(/*mainActivity.allItems,*/ v -> {
|
||||
// final Object tag = v.getTag();
|
||||
// if (tag instanceof PostModel) {
|
||||
// final PostModel postModel = (PostModel) tag;
|
||||
//
|
||||
// if (postsAdapter.isSelecting) toggleSelection(postModel);
|
||||
// else mainActivity.startActivity(new Intent(mainActivity, PostViewer.class)
|
||||
// .putExtra(Constants.EXTRAS_INDEX, postModel.getPosition())
|
||||
// .putExtra(Constants.EXTRAS_POST, postModel)
|
||||
// .putExtra(Constants.EXTRAS_USER, mainActivity.userQuery)
|
||||
// .putExtra(Constants.EXTRAS_TYPE, ItemGetType.MAIN_ITEMS));
|
||||
// }
|
||||
// }, v -> { // long click listener
|
||||
// // final Object tag = v.getTag();
|
||||
// // if (tag instanceof PostModel) {
|
||||
// // postsAdapter.isSelecting = true;
|
||||
// // toggleSelection((PostModel) tag);
|
||||
// // }
|
||||
// // return true;
|
||||
// return false;
|
||||
// }));
|
||||
|
||||
this.lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if ((!autoloadPosts || isHashtag) && hasNextPage) {
|
||||
@ -643,18 +648,18 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
|
||||
private void setupFeed() {
|
||||
mainActivity.mainBinding.feedView.feedStories.setLayoutManager(new LinearLayoutManager(mainActivity, LinearLayoutManager.HORIZONTAL, false));
|
||||
mainActivity.mainBinding.feedView.feedStories.setAdapter(feedStoriesAdapter);
|
||||
// mainActivity.mainBinding.feedView.feedStories.setAdapter(feedStoriesAdapter);
|
||||
refreshFeedStories();
|
||||
|
||||
final LinearLayoutManager layoutManager = new LinearLayoutManager(mainActivity);
|
||||
mainActivity.mainBinding.feedView.feedPosts.setHasFixedSize(true);
|
||||
mainActivity.mainBinding.feedView.feedPosts.setLayoutManager(layoutManager);
|
||||
mainActivity.mainBinding.feedView.feedPosts.setAdapter(feedAdapter = new FeedAdapter(glide, clickListener, (view, text, isHashtag) ->
|
||||
mainActivity.mainBinding.feedView.feedPosts.setAdapter(feedAdapter = new FeedAdapter(clickListener, (view, text, isHashtag) ->
|
||||
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 (MainActivity.scanHack != null) {
|
||||
if (MainActivityBackup.scanHack != null) {
|
||||
mainActivity.mainBinding.drawerLayout.closeDrawers();
|
||||
MainActivity.scanHack.onResult(text);
|
||||
MainActivityBackup.scanHack.onResult(text);
|
||||
}
|
||||
}).show()));
|
||||
|
||||
@ -727,25 +732,25 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
new DiscoverFetcher(topic, null, rankToken, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
});
|
||||
|
||||
mainActivity.mainBinding.discoverPosts.setAdapter(discoverAdapter = new DiscoverAdapter(mainActivity.discoverItems, v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof DiscoverItemModel) {
|
||||
final DiscoverItemModel itemModel = (DiscoverItemModel) tag;
|
||||
|
||||
if (discoverAdapter.isSelecting) toggleDiscoverSelection(itemModel);
|
||||
else mainActivity.startActivity(new Intent(mainActivity, PostViewer.class)
|
||||
.putExtra(Constants.EXTRAS_INDEX, itemModel.getPosition())
|
||||
.putExtra(Constants.EXTRAS_TYPE, ItemGetType.DISCOVER_ITEMS)
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(itemModel.getShortCode(), false)));
|
||||
}
|
||||
}, v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof DiscoverItemModel) {
|
||||
discoverAdapter.isSelecting = true;
|
||||
toggleDiscoverSelection((DiscoverItemModel) tag);
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
// mainActivity.mainBinding.discoverPosts.setAdapter(discoverAdapter = new DiscoverAdapter(mainActivity.discoverItems, v -> {
|
||||
// final Object tag = v.getTag();
|
||||
// if (tag instanceof DiscoverItemModel) {
|
||||
// final DiscoverItemModel itemModel = (DiscoverItemModel) tag;
|
||||
//
|
||||
// if (discoverAdapter.isSelecting) toggleDiscoverSelection(itemModel);
|
||||
// else mainActivity.startActivity(new Intent(mainActivity, PostViewer.class)
|
||||
// .putExtra(Constants.EXTRAS_INDEX, itemModel.getPosition())
|
||||
// .putExtra(Constants.EXTRAS_TYPE, ItemGetType.DISCOVER_ITEMS)
|
||||
// .putExtra(Constants.EXTRAS_POST, new PostModel(itemModel.getShortCode(), false)));
|
||||
// }
|
||||
// }, v -> {
|
||||
// final Object tag = v.getTag();
|
||||
// if (tag instanceof DiscoverItemModel) {
|
||||
// discoverAdapter.isSelecting = true;
|
||||
// toggleDiscoverSelection((DiscoverItemModel) tag);
|
||||
// }
|
||||
// return true;
|
||||
// }));
|
||||
|
||||
mainActivity.mainBinding.discoverPosts.addOnScrollListener(discoverLazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if (discoverHasMore) {
|
||||
@ -811,7 +816,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
mainActivity.allItems.clear();
|
||||
mainActivity.selectedItems.clear();
|
||||
if (postsAdapter != null) {
|
||||
postsAdapter.isSelecting = false;
|
||||
// postsAdapter.isSelecting = false;
|
||||
postsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
mainActivity.mainBinding.profileView.appBarLayout.setExpanded(true, true);
|
||||
@ -1279,12 +1284,12 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
}
|
||||
|
||||
private void notifyAdapter(final PostModel postModel) {
|
||||
if (mainActivity.selectedItems.size() < 1) postsAdapter.isSelecting = false;
|
||||
if (postModel.getPosition() < 0) postsAdapter.notifyDataSetChanged();
|
||||
else postsAdapter.notifyItemChanged(postModel.getPosition(), postModel);
|
||||
|
||||
if (mainActivity.downloadAction != null)
|
||||
mainActivity.downloadAction.setVisible(postsAdapter.isSelecting);
|
||||
// if (mainActivity.selectedItems.size() < 1) postsAdapter.isSelecting = false;
|
||||
// if (postModel.getPosition() < 0) postsAdapter.notifyDataSetChanged();
|
||||
// else postsAdapter.notifyItemChanged(postModel.getPosition(), postModel);
|
||||
//
|
||||
// if (mainActivity.downloadAction != null)
|
||||
// mainActivity.downloadAction.setVisible(postsAdapter.isSelecting);
|
||||
}
|
||||
|
||||
private void toggleDiscoverSelection(final DiscoverItemModel itemModel) {
|
||||
@ -1297,33 +1302,34 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
}
|
||||
|
||||
private void notifyDiscoverAdapter(final DiscoverItemModel itemModel) {
|
||||
if (mainActivity.selectedDiscoverItems.size() < 1) discoverAdapter.isSelecting = false;
|
||||
if (itemModel.getPosition() < 0) discoverAdapter.notifyDataSetChanged();
|
||||
else discoverAdapter.notifyItemChanged(itemModel.getPosition(), itemModel);
|
||||
|
||||
if (mainActivity.downloadAction != null)
|
||||
mainActivity.downloadAction.setVisible(discoverAdapter.isSelecting);
|
||||
// if (mainActivity.selectedDiscoverItems.size() < 1) discoverAdapter.isSelecting = false;
|
||||
// if (itemModel.getPosition() < 0) discoverAdapter.notifyDataSetChanged();
|
||||
// else discoverAdapter.notifyItemChanged(itemModel.getPosition(), itemModel);
|
||||
//
|
||||
// if (mainActivity.downloadAction != null)
|
||||
// mainActivity.downloadAction.setVisible(discoverAdapter.isSelecting);
|
||||
}
|
||||
|
||||
public boolean isSelectionCleared() {
|
||||
if (postsAdapter != null && postsAdapter.isSelecting) {
|
||||
for (final PostModel postModel : mainActivity.selectedItems)
|
||||
postModel.setSelected(false);
|
||||
mainActivity.selectedItems.clear();
|
||||
postsAdapter.isSelecting = false;
|
||||
postsAdapter.notifyDataSetChanged();
|
||||
if (mainActivity.downloadAction != null) mainActivity.downloadAction.setVisible(false);
|
||||
// if (postsAdapter != null && postsAdapter.isSelecting()) {
|
||||
// for (final PostModel postModel : mainActivity.selectedItems)
|
||||
// postModel.setSelected(false);
|
||||
// mainActivity.selectedItems.clear();
|
||||
// // postsAdapter.isSelecting = false;
|
||||
// postsAdapter.notifyDataSetChanged();
|
||||
// if (mainActivity.downloadAction != null) mainActivity.downloadAction.setVisible(false);
|
||||
// return false;
|
||||
// } else if (discoverAdapter != null && discoverAdapter.isSelecting) {
|
||||
// for (final DiscoverItemModel itemModel : mainActivity.selectedDiscoverItems)
|
||||
// itemModel.setSelected(false);
|
||||
// mainActivity.selectedDiscoverItems.clear();
|
||||
// discoverAdapter.isSelecting = false;
|
||||
// discoverAdapter.notifyDataSetChanged();
|
||||
// if (mainActivity.downloadAction != null) mainActivity.downloadAction.setVisible(false);
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
return false;
|
||||
} else if (discoverAdapter != null && discoverAdapter.isSelecting) {
|
||||
for (final DiscoverItemModel itemModel : mainActivity.selectedDiscoverItems)
|
||||
itemModel.setSelected(false);
|
||||
mainActivity.selectedDiscoverItems.clear();
|
||||
discoverAdapter.isSelecting = false;
|
||||
discoverAdapter.notifyDataSetChanged();
|
||||
if (mainActivity.downloadAction != null) mainActivity.downloadAction.setVisible(false);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void deselectSelection(final BasePostModel postModel) {
|
||||
@ -1364,7 +1370,8 @@ 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 = (isLoggedIn && mainActivity.profileModel != null) && Utils.getUserIdFromCookie(cookie).equals(mainActivity.profileModel.getId());
|
||||
final String userIdFromCookie = Utils.getUserIdFromCookie(MainHelper.this.cookie);
|
||||
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]),
|
||||
@ -1378,7 +1385,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
new ProfileAction().execute("follow");
|
||||
} else if (v == mainActivity.mainBinding.profileView.btnRestrict && isLoggedIn) {
|
||||
new ProfileAction().execute("restrict");
|
||||
} else if (v == mainActivity.mainBinding.profileView.btnSaved && !iamme) {
|
||||
} else if (v == mainActivity.mainBinding.profileView.btnSaved && !isSelf) {
|
||||
new ProfileAction().execute("block");
|
||||
} else if (v == mainActivity.mainBinding.profileView.btnFollowTag) {
|
||||
new ProfileAction().execute("followtag");
|
||||
@ -1407,17 +1414,12 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
|
||||
|
||||
protected Void doInBackground(String... rawAction) {
|
||||
action = rawAction[0];
|
||||
final String url = "https://www.instagram.com/web/" +
|
||||
((action == "followtag" && mainActivity.hashtagModel != null) ? ("tags/" +
|
||||
(mainActivity.hashtagModel.getFollowing() == true ? "unfollow/" : "follow/") + mainActivity.hashtagModel.getName() + "/") : (
|
||||
((action == "restrict" && mainActivity.profileModel != null) ? "restrict_action" : ("friendships/" + mainActivity.profileModel.getId())) + "/" +
|
||||
((action == "follow" && mainActivity.profileModel != null) ?
|
||||
((mainActivity.profileModel.getFollowing() == true ||
|
||||
(mainActivity.profileModel.getFollowing() == false && mainActivity.profileModel.getRequested() == true))
|
||||
? "unfollow/" : "follow/") :
|
||||
((action == "restrict" && mainActivity.profileModel != null) ?
|
||||
(mainActivity.profileModel.getRestricted() == true ? "unrestrict/" : "restrict/") :
|
||||
(mainActivity.profileModel.getBlocked() == true ? "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");
|
||||
|
@ -1,603 +1,132 @@
|
||||
package awais.instagrabber.activities;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.database.MatrixCursor;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.PersistableBundle;
|
||||
import android.provider.BaseColumns;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.ui.NavigationUI;
|
||||
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import awais.instagrabber.MainHelper;
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.HighlightsAdapter;
|
||||
import awais.instagrabber.adapters.SuggestionsAdapter;
|
||||
import awais.instagrabber.asyncs.GetActivityAsyncTask;
|
||||
import awais.instagrabber.asyncs.SuggestionsFetcher;
|
||||
import awais.instagrabber.asyncs.UsernameFetcher;
|
||||
import awais.instagrabber.asyncs.i.iStoryStatusFetcher;
|
||||
import awais.instagrabber.customviews.MouseDrawer;
|
||||
import awais.instagrabber.customviews.helpers.CustomHideBottomViewOnScrollBehavior;
|
||||
import awais.instagrabber.databinding.ActivityMainBinding;
|
||||
import awais.instagrabber.dialogs.AboutDialog;
|
||||
import awais.instagrabber.dialogs.QuickAccessDialog;
|
||||
import awais.instagrabber.dialogs.SettingsDialog;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.interfaces.ItemGetter;
|
||||
import awais.instagrabber.models.DiscoverItemModel;
|
||||
import awais.instagrabber.models.FeedModel;
|
||||
import awais.instagrabber.models.HashtagModel;
|
||||
import awais.instagrabber.models.HighlightModel;
|
||||
import awais.instagrabber.models.LocationModel;
|
||||
import awais.instagrabber.models.PostModel;
|
||||
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.SuggestionType;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
import awais.instagrabber.utils.FlavorTown;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.CHANNEL_ID;
|
||||
import static awais.instagrabber.utils.Utils.notificationManager;
|
||||
import static awais.instagrabber.utils.NavigationExtensions.setupWithNavController;
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public final class MainActivity extends BaseLanguageActivity {
|
||||
private static final int INITIAL_DELAY_MILLIS = 200;
|
||||
private static final int DELAY_MILLIS = 60000;
|
||||
public static FetchListener<String> scanHack;
|
||||
public static ItemGetter itemGetter;
|
||||
public class MainActivity extends BaseLanguageActivity {
|
||||
private static final String TAG = "MainActivity";
|
||||
|
||||
public final ArrayList<PostModel> allItems = new ArrayList<>();
|
||||
public final ArrayList<FeedModel> feedItems = new ArrayList<>();
|
||||
public final ArrayList<DiscoverItemModel> discoverItems = new ArrayList<>();
|
||||
public final ArrayList<PostModel> selectedItems = new ArrayList<>();
|
||||
public final ArrayList<DiscoverItemModel> selectedDiscoverItems = new ArrayList<>();
|
||||
|
||||
public final HighlightsAdapter highlightsAdapter = new HighlightsAdapter(null, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof HighlightModel) {
|
||||
final HighlightModel highlightModel = (HighlightModel) tag;
|
||||
new iStoryStatusFetcher(highlightModel.getId(), null, false, false,
|
||||
(!isLoggedIn && Utils.settingsHelper.getBoolean(Constants.STORIESIG)), true, result -> {
|
||||
if (result != null && result.length > 0)
|
||||
startActivity(new Intent(MainActivity.this, StoryViewer.class)
|
||||
.putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", ""))
|
||||
.putExtra(Constants.EXTRAS_HIGHLIGHT, highlightModel.getTitle())
|
||||
.putExtra(Constants.EXTRAS_STORIES, result)
|
||||
);
|
||||
else
|
||||
Toast.makeText(MainActivity.this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
private SuggestionsAdapter suggestionAdapter;
|
||||
private MenuItem searchAction;
|
||||
public ActivityMainBinding mainBinding;
|
||||
public SearchView searchView;
|
||||
public MenuItem downloadAction, settingsAction, dmsAction, notifAction;
|
||||
public StoryModel[] storyModels;
|
||||
public String userQuery = null, cookie, uid = null;
|
||||
public MainHelper mainHelper;
|
||||
public ProfileModel profileModel;
|
||||
public HashtagModel hashtagModel;
|
||||
public LocationModel locationModel;
|
||||
private AutoCompleteTextView searchAutoComplete;
|
||||
private ArrayAdapter<String> profileDialogAdapter;
|
||||
private DialogInterface.OnClickListener profileDialogListener;
|
||||
private Stack<String> queriesStack;
|
||||
private DataBox.CookieModel cookieModel;
|
||||
private Runnable runnable;
|
||||
private Handler handler;
|
||||
private boolean isLoggedIn;
|
||||
private ActivityMainBinding binding;
|
||||
private LiveData<NavController> currentNavControllerLiveData;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable final Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
mainBinding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(mainBinding.getRoot());
|
||||
|
||||
FlavorTown.updateCheck(this);
|
||||
FlavorTown.changelogCheck(this);
|
||||
|
||||
cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
uid = Utils.getUserIdFromCookie(cookie);
|
||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
Utils.setupCookies(cookie);
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
MainHelper.stopCurrentExecutor();
|
||||
mainHelper = new MainHelper(this);
|
||||
if (bundle == null) {
|
||||
queriesStack = new Stack<>();
|
||||
userQuery = null;
|
||||
} else {
|
||||
setStack(bundle);
|
||||
userQuery = bundle.getString("query");
|
||||
}
|
||||
isLoggedIn = !Utils.isEmpty(cookie) && Utils.getUserIdFromCookie(cookie) != null;
|
||||
final Toolbar toolbar = binding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
itemGetter = itemGetType -> {
|
||||
if (itemGetType == ItemGetType.MAIN_ITEMS) return allItems;
|
||||
if (itemGetType == ItemGetType.DISCOVER_ITEMS) return discoverItems;
|
||||
if (itemGetType == ItemGetType.FEED_ITEMS) return feedItems;
|
||||
return null;
|
||||
};
|
||||
|
||||
scanHack = result -> {
|
||||
if (mainHelper != null && !Utils.isEmpty(result)) {
|
||||
closeAnyOpenDrawer();
|
||||
addToStack();
|
||||
userQuery = (result.contains("/") || result.startsWith("#") || result.startsWith("@")) ? result : ("@" + result);
|
||||
mainHelper.onRefresh();
|
||||
}
|
||||
};
|
||||
|
||||
// searches for your userid and returns username
|
||||
if (uid != null) {
|
||||
final FetchListener<String> fetchListener = username -> {
|
||||
if (!Utils.isEmpty(username)) {
|
||||
// if (!BuildConfig.DEBUG) {
|
||||
userQuery = username;
|
||||
if (mainHelper != null && !mainBinding.profileView.swipeRefreshLayout.isRefreshing())
|
||||
mainHelper.onRefresh();
|
||||
// }
|
||||
// adds cookies to database for quick access
|
||||
cookieModel = Utils.dataBox.getCookie(uid);
|
||||
if (Utils.dataBox.getCookieCount() == 0 || cookieModel == null || Utils.isEmpty(cookieModel.getUsername()))
|
||||
Utils.dataBox.addUserCookie(new DataBox.CookieModel(uid, username, cookie));
|
||||
}
|
||||
};
|
||||
boolean found = false;
|
||||
cookieModel = Utils.dataBox.getCookie(uid);
|
||||
if (cookieModel != null) {
|
||||
final String username = cookieModel.getUsername();
|
||||
if (username != null) {
|
||||
found = true;
|
||||
fetchListener.onResult("@" + username);
|
||||
}
|
||||
if (savedInstanceState == null) {
|
||||
setupBottomNavigationBar();
|
||||
}
|
||||
|
||||
if (!found) // if not in database, fetch info from instagram
|
||||
new UsernameFetcher(uid, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
setupScrollingListener();
|
||||
}
|
||||
|
||||
suggestionAdapter = new SuggestionsAdapter(this, v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof CharSequence) {
|
||||
addToStack();
|
||||
userQuery = tag.toString();
|
||||
mainHelper.onRefresh();
|
||||
private void setupScrollingListener() {
|
||||
final CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) binding.bottomNavView.getLayoutParams();
|
||||
layoutParams.setBehavior(new CustomHideBottomViewOnScrollBehavior());
|
||||
binding.bottomNavView.requestLayout();
|
||||
}
|
||||
if (searchView != null && !searchView.isIconified()) {
|
||||
if (searchAction != null) searchAction.collapseActionView();
|
||||
searchView.setIconified(true);
|
||||
searchView.setIconified(true);
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.main_menu, menu);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
final Resources 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)});
|
||||
profileDialogListener = (dialog, which) -> {
|
||||
final Intent intent;
|
||||
if (which == 0 || storyModels == null || storyModels.length < 1) {
|
||||
intent = new Intent(this, ProfilePicViewer.class).putExtra(
|
||||
((hashtagModel != null) ? Constants.EXTRAS_HASHTAG : (locationModel != null ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_PROFILE)),
|
||||
((hashtagModel != null) ? hashtagModel : (locationModel != null ? locationModel : profileModel)));
|
||||
} else
|
||||
intent = new Intent(this, StoryViewer.class).putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", ""))
|
||||
.putExtra(Constants.EXTRAS_STORIES, storyModels)
|
||||
.putExtra(Constants.EXTRAS_HASHTAG, (hashtagModel != null));
|
||||
startActivity(intent);
|
||||
};
|
||||
private void setupBottomNavigationBar() {
|
||||
final List<Integer> navList = new ArrayList<>(Arrays.asList(
|
||||
R.navigation.direct_messages_nav_graph,
|
||||
R.navigation.feed_nav_graph,
|
||||
R.navigation.profile_nav_graph,
|
||||
R.navigation.discover_nav_graph
|
||||
));
|
||||
|
||||
final View.OnClickListener onClickListener = v -> {
|
||||
if (v == mainBinding.profileView.mainBiography) {
|
||||
Utils.copyText(this, mainBinding.profileView.mainBiography.getText().toString());
|
||||
} else if (v == mainBinding.profileView.locationBiography) {
|
||||
Utils.copyText(this, mainBinding.profileView.locationBiography.getText().toString());
|
||||
} else if (v == mainBinding.profileView.mainProfileImage || v == mainBinding.profileView.mainHashtagImage || v == mainBinding.profileView.mainLocationImage) {
|
||||
if (storyModels == null || storyModels.length <= 0) {
|
||||
profileDialogListener.onClick(null, 0);
|
||||
} else {
|
||||
// because sometimes configuration changes made this crash on some phones
|
||||
new AlertDialog.Builder(this).setAdapter(profileDialogAdapter, profileDialogListener)
|
||||
.setNeutralButton(R.string.cancel, null).show();
|
||||
binding.bottomNavView.setSelectedItemId(R.id.feed_nav_graph);
|
||||
final LiveData<NavController> navControllerLiveData = setupWithNavController(
|
||||
binding.bottomNavView,
|
||||
navList,
|
||||
getSupportFragmentManager(),
|
||||
R.id.main_nav_host,
|
||||
getIntent(),
|
||||
1);
|
||||
navControllerLiveData.observe(this, this::setupNavigation);
|
||||
currentNavControllerLiveData = navControllerLiveData;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mainBinding.profileView.mainBiography.setOnClickListener(onClickListener);
|
||||
mainBinding.profileView.locationBiography.setOnClickListener(onClickListener);
|
||||
mainBinding.profileView.mainProfileImage.setOnClickListener(onClickListener);
|
||||
mainBinding.profileView.mainHashtagImage.setOnClickListener(onClickListener);
|
||||
mainBinding.profileView.mainLocationImage.setOnClickListener(onClickListener);
|
||||
private void setupNavigation(final NavController navController) {
|
||||
NavigationUI.setupWithNavController(binding.toolbar, navController);
|
||||
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
|
||||
binding.appBarLayout.setExpanded(true, true);
|
||||
final int destinationId = destination.getId();
|
||||
final List<Integer> showBottomView = Arrays.asList(
|
||||
R.id.directMessagesInboxFragment,
|
||||
R.id.feedFragment,
|
||||
R.id.profileFragment,
|
||||
R.id.discoverFragment);
|
||||
|
||||
mainBinding.profileView.mainBiography.setEnabled(false);
|
||||
mainBinding.profileView.mainProfileImage.setEnabled(false);
|
||||
mainBinding.profileView.mainHashtagImage.setEnabled(false);
|
||||
mainBinding.profileView.mainLocationImage.setEnabled(false);
|
||||
|
||||
final boolean isQueryNull = userQuery == null;
|
||||
if (isQueryNull) {
|
||||
allItems.clear();
|
||||
mainBinding.profileView.privatePage1.setImageResource(R.drawable.ic_info);
|
||||
mainBinding.profileView.privatePage2.setTextSize(20);
|
||||
mainBinding.profileView.privatePage2.setText(isLoggedIn ? R.string.no_acc_logged_in : R.string.no_acc);
|
||||
mainBinding.profileView.privatePage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (!mainBinding.profileView.swipeRefreshLayout.isRefreshing() && userQuery != null)
|
||||
mainHelper.onRefresh();
|
||||
|
||||
mainHelper.onIntent(getIntent());
|
||||
|
||||
handler = new Handler();
|
||||
runnable = () -> {
|
||||
final GetActivityAsyncTask activityAsyncTask = new GetActivityAsyncTask(uid, cookie, result -> {
|
||||
if (result == null || notificationManager == null) {
|
||||
if (showBottomView.contains(destinationId)) {
|
||||
setScrollingBehaviour();
|
||||
binding.bottomNavView.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
final List<String> list = new ArrayList<>();
|
||||
if (result.getRelationshipsCount() != 0) {
|
||||
list.add(getString(R.string.activity_count_relationship, result.getRelationshipsCount()));
|
||||
}
|
||||
if (result.getUserTagsCount() != 0) {
|
||||
list.add(getString(R.string.activity_count_usertags, result.getUserTagsCount()));
|
||||
}
|
||||
if (result.getCommentsCount() != 0) {
|
||||
list.add(getString(R.string.activity_count_comments, result.getCommentsCount()));
|
||||
}
|
||||
if (result.getCommentLikesCount() != 0) {
|
||||
list.add(getString(R.string.activity_count_commentlikes, result.getCommentLikesCount()));
|
||||
}
|
||||
if (result.getLikesCount() != 0) {
|
||||
list.add(getString(R.string.activity_count_likes, result.getLikesCount()));
|
||||
}
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final String join = TextUtils.join(", ", list);
|
||||
final String notificationString = getString(R.string.activity_count_prefix) + " " + join + ".";
|
||||
final Intent intent = new Intent(getApplicationContext(), NotificationsViewer.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
final Notification notification = new NotificationCompat.Builder(MainActivity.this, CHANNEL_ID)
|
||||
.setCategory(NotificationCompat.CATEGORY_STATUS)
|
||||
.setSmallIcon(R.drawable.ic_notif)
|
||||
.setAutoCancel(true)
|
||||
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||
.setContentText(notificationString)
|
||||
.setContentIntent(PendingIntent.getActivity(getApplicationContext(), 1738, intent, PendingIntent.FLAG_UPDATE_CURRENT))
|
||||
.build();
|
||||
notificationManager.cancel(1800000000);
|
||||
notificationManager.notify(1800000000, notification);
|
||||
removeScrollingBehaviour();
|
||||
binding.bottomNavView.setVisibility(View.GONE);
|
||||
});
|
||||
activityAsyncTask.execute();
|
||||
if (!Utils.isEmpty(cookie) && Utils.settingsHelper.getBoolean(Constants.CHECK_ACTIVITY))
|
||||
activityAsyncTask.execute();
|
||||
handler.postDelayed(runnable, DELAY_MILLIS);
|
||||
};
|
||||
handler.postDelayed(runnable, INITIAL_DELAY_MILLIS);
|
||||
}
|
||||
|
||||
private void downloadSelectedItems() {
|
||||
if (selectedItems.size() > 0) {
|
||||
Utils.batchDownload(this, userQuery, DownloadMethod.DOWNLOAD_MAIN, selectedItems);
|
||||
} else if (selectedDiscoverItems.size() > 0) {
|
||||
Utils.batchDownload(this, null, DownloadMethod.DOWNLOAD_DISCOVER, selectedDiscoverItems);
|
||||
}
|
||||
private void setScrollingBehaviour() {
|
||||
final CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) binding.mainNavHost.getLayoutParams();
|
||||
layoutParams.setBehavior(new AppBarLayout.ScrollingViewBehavior());
|
||||
binding.mainNavHost.requestLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(final Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
mainHelper.onIntent(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull final Bundle outState, @NonNull final PersistableBundle outPersistentState) {
|
||||
outState.putString("query", userQuery);
|
||||
outState.putSerializable("stack", queriesStack);
|
||||
super.onSaveInstanceState(outState, outPersistentState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(@Nullable final Bundle savedInstanceState, @Nullable final PersistableBundle persistentState) {
|
||||
super.onRestoreInstanceState(savedInstanceState, persistentState);
|
||||
if (savedInstanceState != null) {
|
||||
userQuery = savedInstanceState.getString("query");
|
||||
setStack(savedInstanceState);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||
outState.putString("query", userQuery);
|
||||
outState.putSerializable("stack", queriesStack);
|
||||
super.onSaveInstanceState(outState);
|
||||
private void removeScrollingBehaviour() {
|
||||
final CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) binding.mainNavHost.getLayoutParams();
|
||||
layoutParams.setBehavior(null);
|
||||
binding.mainNavHost.requestLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
userQuery = savedInstanceState.getString("query");
|
||||
setStack(savedInstanceState);
|
||||
setupBottomNavigationBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu, menu);
|
||||
|
||||
final FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
final MenuItem quickAccessAction = menu.findItem(R.id.action_quickaccess).setVisible(true);
|
||||
|
||||
final MenuItem.OnMenuItemClickListener clickListener = item -> {
|
||||
if (item == downloadAction)
|
||||
downloadSelectedItems();
|
||||
else if (item == dmsAction)
|
||||
startActivity(new Intent(this, DirectMessagesActivity.class));
|
||||
else if (item == notifAction)
|
||||
startActivity(new Intent(this, NotificationsViewer.class));
|
||||
else if (item == settingsAction)
|
||||
new SettingsDialog().show(fragmentManager, "settings");
|
||||
else if (item == quickAccessAction)
|
||||
new QuickAccessDialog()
|
||||
.setQuery(userQuery, locationModel != null ? locationModel.getName() : userQuery)
|
||||
.show(fragmentManager, "quickAccess");
|
||||
else
|
||||
new AboutDialog().show(fragmentManager, "about");
|
||||
return true;
|
||||
};
|
||||
|
||||
quickAccessAction.setOnMenuItemClickListener(clickListener);
|
||||
menu.findItem(R.id.action_about).setVisible(true).setOnMenuItemClickListener(clickListener);
|
||||
dmsAction = menu.findItem(R.id.action_dms).setOnMenuItemClickListener(clickListener);
|
||||
notifAction = menu.findItem(R.id.action_notif).setOnMenuItemClickListener(clickListener);
|
||||
settingsAction = menu.findItem(R.id.action_settings).setVisible(true).setOnMenuItemClickListener(clickListener);
|
||||
downloadAction = menu.findItem(R.id.action_download).setOnMenuItemClickListener(clickListener);
|
||||
|
||||
if (!Utils.isEmpty(Utils.settingsHelper.getString(Constants.COOKIE))) {
|
||||
notifAction.setVisible(true);
|
||||
dmsAction.setVisible(true).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
}
|
||||
|
||||
searchAction = menu.findItem(R.id.action_search);
|
||||
searchView = (SearchView) searchAction.getActionView();
|
||||
final View searchText = searchView.findViewById(R.id.search_src_text);
|
||||
if (searchText instanceof AutoCompleteTextView)
|
||||
searchAutoComplete = (AutoCompleteTextView) searchText;
|
||||
|
||||
searchView.setQueryHint(getResources().getString(R.string.action_search));
|
||||
searchView.setSuggestionsAdapter(suggestionAdapter);
|
||||
searchView.setOnSearchClickListener(v -> {
|
||||
searchView.setQuery((cookieModel != null && userQuery != null && userQuery.equals("@" + cookieModel.getUsername())) ? "" : userQuery, false);
|
||||
menu.findItem(R.id.action_about).setVisible(false);
|
||||
menu.findItem(R.id.action_settings).setVisible(false);
|
||||
menu.findItem(R.id.action_dms).setVisible(false);
|
||||
menu.findItem(R.id.action_quickaccess).setVisible(false);
|
||||
menu.findItem(R.id.action_notif).setVisible(false);
|
||||
});
|
||||
searchAction.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
|
||||
@Override
|
||||
public boolean onMenuItemActionExpand(MenuItem item) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemActionCollapse(MenuItem item) {
|
||||
menu.findItem(R.id.action_about).setVisible(true);
|
||||
menu.findItem(R.id.action_settings).setVisible(true);
|
||||
menu.findItem(R.id.action_dms).setVisible(!Utils.isEmpty(Utils.settingsHelper.getString(Constants.COOKIE)));
|
||||
menu.findItem(R.id.action_quickaccess).setVisible(true);
|
||||
menu.findItem(R.id.action_notif).setVisible(true);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
private boolean searchUser, searchHash;
|
||||
private AsyncTask<?, ?, ?> prevSuggestionAsync;
|
||||
private final String[] COLUMNS = {BaseColumns._ID, Constants.EXTRAS_USERNAME, Constants.EXTRAS_NAME,
|
||||
Constants.EXTRAS_TYPE, "pfp", "verified"};
|
||||
private final FetchListener<SuggestionModel[]> fetchListener = new FetchListener<SuggestionModel[]>() {
|
||||
@Override
|
||||
public void doBefore() {
|
||||
suggestionAdapter.changeCursor(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(final SuggestionModel[] result) {
|
||||
final MatrixCursor cursor;
|
||||
if (result == null) cursor = null;
|
||||
else {
|
||||
cursor = new MatrixCursor(COLUMNS, 0);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
final SuggestionModel suggestionModel = result[i];
|
||||
if (suggestionModel != null) {
|
||||
final SuggestionType suggestionType = suggestionModel.getSuggestionType();
|
||||
final Object[] objects = {i,
|
||||
(suggestionType == SuggestionType.TYPE_LOCATION) ? suggestionModel.getName() : suggestionModel.getUsername(),
|
||||
(suggestionType == SuggestionType.TYPE_LOCATION) ? suggestionModel.getUsername() : suggestionModel.getName(),
|
||||
suggestionType, suggestionModel.getProfilePic(), suggestionModel.isVerified()};
|
||||
|
||||
if (!searchHash && !searchUser) cursor.addRow(objects);
|
||||
else {
|
||||
final boolean isCurrHash = suggestionType == SuggestionType.TYPE_HASHTAG;
|
||||
if (searchHash && isCurrHash || !searchHash && !isCurrHash)
|
||||
cursor.addRow(objects);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
suggestionAdapter.changeCursor(cursor);
|
||||
}
|
||||
};
|
||||
|
||||
private void cancelSuggestionsAsync() {
|
||||
if (prevSuggestionAsync != null)
|
||||
try {
|
||||
prevSuggestionAsync.cancel(true);
|
||||
} catch (final Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(final String query) {
|
||||
cancelSuggestionsAsync();
|
||||
menu.findItem(R.id.action_about).setVisible(true);
|
||||
menu.findItem(R.id.action_settings).setVisible(true);
|
||||
|
||||
closeAnyOpenDrawer();
|
||||
addToStack();
|
||||
userQuery = (query.contains("@") || query.contains("#")) ? query : ("@" + query);
|
||||
searchAction.collapseActionView();
|
||||
searchView.setIconified(true);
|
||||
searchView.setIconified(true);
|
||||
mainHelper.onRefresh();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(final String newText) {
|
||||
cancelSuggestionsAsync();
|
||||
|
||||
if (!Utils.isEmpty(newText)) {
|
||||
searchUser = newText.charAt(0) == '@';
|
||||
searchHash = newText.charAt(0) == '#';
|
||||
|
||||
if (newText.length() == 1 && (searchHash || searchUser)) {
|
||||
if (searchAutoComplete != null) searchAutoComplete.setThreshold(2);
|
||||
} else {
|
||||
if (searchAutoComplete != null) searchAutoComplete.setThreshold(1);
|
||||
prevSuggestionAsync = new SuggestionsFetcher(fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
|
||||
searchUser || searchHash ? newText.substring(1) : newText);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (closeAnyOpenDrawer()) return;
|
||||
|
||||
if (searchView != null && !searchView.isIconified()) {
|
||||
if (searchAction != null) searchAction.collapseActionView();
|
||||
searchView.setIconified(true);
|
||||
searchView.setIconified(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mainHelper.isSelectionCleared()) return;
|
||||
|
||||
final GridLayoutManager layoutManager = (GridLayoutManager) mainBinding.profileView.mainPosts.getLayoutManager();
|
||||
if (layoutManager != null && layoutManager.findFirstCompletelyVisibleItemPosition() >= layoutManager.getSpanCount()) {
|
||||
mainBinding.profileView.mainPosts.smoothScrollToPosition(0);
|
||||
mainBinding.profileView.appBarLayout.setExpanded(true, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (queriesStack != null && queriesStack.size() > 0) {
|
||||
userQuery = queriesStack.pop();
|
||||
if (userQuery != null) {
|
||||
mainHelper.onRefresh();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@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)
|
||||
downloadSelectedItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == 9629 && (resultCode == 1692 || resultCode == RESULT_CANCELED))
|
||||
finish();
|
||||
else if (requestCode == 6007)
|
||||
Utils.showImportExportDialog(this);
|
||||
// else if (requestCode == 6969 && mainHelper.currentFeedPlayer != null)
|
||||
// mainHelper.currentFeedPlayer.setPlayWhenReady(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
if (mainHelper != null) mainHelper.onPause();
|
||||
if (handler != null && runnable != null) {
|
||||
handler.removeCallbacks(runnable);
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
if (mainHelper != null) mainHelper.onResume();
|
||||
if (handler != null && runnable != null) {
|
||||
handler.postDelayed(runnable, INITIAL_DELAY_MILLIS);
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
private void setStack(final Bundle bundle) {
|
||||
final Object stack = bundle != null ? bundle.get("stack") : null;
|
||||
if (stack instanceof Stack) //noinspection unchecked
|
||||
queriesStack = (Stack<String>) stack;
|
||||
}
|
||||
|
||||
public void addToStack() {
|
||||
if (userQuery != null) {
|
||||
if (queriesStack == null) queriesStack = new Stack<>();
|
||||
queriesStack.add(userQuery);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean closeAnyOpenDrawer() {
|
||||
final int childCount = mainBinding.drawerLayout.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
final View child = mainBinding.drawerLayout.getChildAt(i);
|
||||
final MouseDrawer.LayoutParams childLp = (MouseDrawer.LayoutParams) child.getLayoutParams();
|
||||
|
||||
if ((childLp.openState & MouseDrawer.LayoutParams.FLAG_IS_OPENED) == 1 ||
|
||||
(childLp.openState & MouseDrawer.LayoutParams.FLAG_IS_OPENING) == 2 ||
|
||||
childLp.onScreen >= 0.6 || childLp.isPeeking) {
|
||||
mainBinding.drawerLayout.closeDrawer(child);
|
||||
return true;
|
||||
}
|
||||
public boolean onSupportNavigateUp() {
|
||||
if (currentNavControllerLiveData != null && currentNavControllerLiveData.getValue() != null) {
|
||||
return currentNavControllerLiveData.getValue().navigateUp();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -0,0 +1,607 @@
|
||||
package awais.instagrabber.activities;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.database.MatrixCursor;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.PersistableBundle;
|
||||
import android.provider.BaseColumns;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import awais.instagrabber.MainHelper;
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.HighlightsAdapter;
|
||||
import awais.instagrabber.adapters.SuggestionsAdapter;
|
||||
import awais.instagrabber.asyncs.GetActivityAsyncTask;
|
||||
import awais.instagrabber.asyncs.SuggestionsFetcher;
|
||||
import awais.instagrabber.asyncs.UsernameFetcher;
|
||||
import awais.instagrabber.asyncs.i.iStoryStatusFetcher;
|
||||
import awais.instagrabber.customviews.MouseDrawer;
|
||||
import awais.instagrabber.databinding.ActivityMainBinding;
|
||||
import awais.instagrabber.databinding.ActivityMainbackupBinding;
|
||||
import awais.instagrabber.dialogs.AboutDialog;
|
||||
import awais.instagrabber.dialogs.QuickAccessDialog;
|
||||
import awais.instagrabber.dialogs.SettingsDialog;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.interfaces.ItemGetter;
|
||||
import awais.instagrabber.models.DiscoverItemModel;
|
||||
import awais.instagrabber.models.FeedModel;
|
||||
import awais.instagrabber.models.HashtagModel;
|
||||
import awais.instagrabber.models.HighlightModel;
|
||||
import awais.instagrabber.models.LocationModel;
|
||||
import awais.instagrabber.models.PostModel;
|
||||
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.SuggestionType;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
import awais.instagrabber.utils.FlavorTown;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.CHANNEL_ID;
|
||||
import static awais.instagrabber.utils.Utils.notificationManager;
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public final class MainActivityBackup extends BaseLanguageActivity {
|
||||
private static final int INITIAL_DELAY_MILLIS = 200;
|
||||
private static final int DELAY_MILLIS = 60000;
|
||||
public static FetchListener<String> scanHack;
|
||||
public static ItemGetter itemGetter;
|
||||
|
||||
public final ArrayList<PostModel> allItems = new ArrayList<>();
|
||||
public final ArrayList<FeedModel> feedItems = new ArrayList<>();
|
||||
public final ArrayList<DiscoverItemModel> discoverItems = new ArrayList<>();
|
||||
public final ArrayList<PostModel> selectedItems = new ArrayList<>();
|
||||
public final ArrayList<DiscoverItemModel> selectedDiscoverItems = new ArrayList<>();
|
||||
|
||||
public final HighlightsAdapter highlightsAdapter = new HighlightsAdapter(null, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof HighlightModel) {
|
||||
final HighlightModel highlightModel = (HighlightModel) tag;
|
||||
new iStoryStatusFetcher(highlightModel.getId(), null, false, false,
|
||||
(!isLoggedIn && Utils.settingsHelper.getBoolean(Constants.STORIESIG)), true, result -> {
|
||||
if (result != null && result.length > 0) {
|
||||
// startActivity(new Intent(MainActivityBackup.this, StoryViewer.class)
|
||||
// .putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", ""))
|
||||
// .putExtra(Constants.EXTRAS_HIGHLIGHT, highlightModel.getTitle())
|
||||
// .putExtra(Constants.EXTRAS_STORIES, result)
|
||||
// );
|
||||
}
|
||||
else
|
||||
Toast.makeText(MainActivityBackup.this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
private SuggestionsAdapter suggestionAdapter;
|
||||
private MenuItem searchAction;
|
||||
public @NonNull ActivityMainbackupBinding mainBinding;
|
||||
public SearchView searchView;
|
||||
public MenuItem downloadAction, settingsAction, dmsAction, notifAction;
|
||||
public StoryModel[] storyModels;
|
||||
public String userQuery = null, cookie, uid = null;
|
||||
public MainHelper mainHelper;
|
||||
public ProfileModel profileModel;
|
||||
public HashtagModel hashtagModel;
|
||||
public LocationModel locationModel;
|
||||
private AutoCompleteTextView searchAutoComplete;
|
||||
private ArrayAdapter<String> profileDialogAdapter;
|
||||
private DialogInterface.OnClickListener profileDialogListener;
|
||||
private Stack<String> queriesStack;
|
||||
private DataBox.CookieModel cookieModel;
|
||||
private Runnable runnable;
|
||||
private Handler handler;
|
||||
private boolean isLoggedIn;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable final Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
mainBinding = ActivityMainbackupBinding.inflate(getLayoutInflater());
|
||||
setContentView(mainBinding.getRoot());
|
||||
|
||||
FlavorTown.updateCheck(this);
|
||||
FlavorTown.changelogCheck(this);
|
||||
|
||||
cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
uid = Utils.getUserIdFromCookie(cookie);
|
||||
Utils.setupCookies(cookie);
|
||||
|
||||
MainHelper.stopCurrentExecutor();
|
||||
mainHelper = new MainHelper(this);
|
||||
if (bundle == null) {
|
||||
queriesStack = new Stack<>();
|
||||
userQuery = null;
|
||||
} else {
|
||||
setStack(bundle);
|
||||
userQuery = bundle.getString("query");
|
||||
}
|
||||
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;
|
||||
return null;
|
||||
};
|
||||
|
||||
scanHack = result -> {
|
||||
if (mainHelper != null && !Utils.isEmpty(result)) {
|
||||
closeAnyOpenDrawer();
|
||||
addToStack();
|
||||
userQuery = (result.contains("/") || result.startsWith("#") || result.startsWith("@")) ? result : ("@" + result);
|
||||
mainHelper.onRefresh();
|
||||
}
|
||||
};
|
||||
|
||||
// searches for your userid and returns username
|
||||
if (uid != null) {
|
||||
final FetchListener<String> fetchListener = username -> {
|
||||
if (!Utils.isEmpty(username)) {
|
||||
// if (!BuildConfig.DEBUG) {
|
||||
userQuery = username;
|
||||
if (mainHelper != null && !mainBinding.profileView.swipeRefreshLayout.isRefreshing())
|
||||
mainHelper.onRefresh();
|
||||
// }
|
||||
// adds cookies to database for quick access
|
||||
cookieModel = Utils.dataBox.getCookie(uid);
|
||||
if (Utils.dataBox.getCookieCount() == 0 || cookieModel == null || Utils.isEmpty(cookieModel.getUsername()))
|
||||
Utils.dataBox.addUserCookie(new DataBox.CookieModel(uid, username, cookie));
|
||||
}
|
||||
};
|
||||
boolean found = false;
|
||||
cookieModel = Utils.dataBox.getCookie(uid);
|
||||
if (cookieModel != null) {
|
||||
final String username = cookieModel.getUsername();
|
||||
if (username != null) {
|
||||
found = true;
|
||||
fetchListener.onResult("@" + username);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) // if not in database, fetch info from instagram
|
||||
new UsernameFetcher(uid, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
suggestionAdapter = new SuggestionsAdapter(this, v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof CharSequence) {
|
||||
addToStack();
|
||||
userQuery = tag.toString();
|
||||
mainHelper.onRefresh();
|
||||
}
|
||||
if (searchView != null && !searchView.isIconified()) {
|
||||
if (searchAction != null) searchAction.collapseActionView();
|
||||
searchView.setIconified(true);
|
||||
searchView.setIconified(true);
|
||||
}
|
||||
});
|
||||
|
||||
final Resources 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)});
|
||||
profileDialogListener = (dialog, which) -> {
|
||||
final Intent intent;
|
||||
if (which == 0 || storyModels == null || storyModels.length < 1) {
|
||||
intent = new Intent(this, ProfilePicViewer.class).putExtra(
|
||||
((hashtagModel != null) ? Constants.EXTRAS_HASHTAG : (locationModel != null ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_PROFILE)),
|
||||
((hashtagModel != null) ? hashtagModel : (locationModel != null ? locationModel : profileModel)));
|
||||
} else {
|
||||
// intent = new Intent(this, StoryViewer.class).putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", ""))
|
||||
// .putExtra(Constants.EXTRAS_STORIES, storyModels)
|
||||
// .putExtra(Constants.EXTRAS_HASHTAG, (hashtagModel != null));
|
||||
}
|
||||
// startActivity(intent);
|
||||
};
|
||||
|
||||
final View.OnClickListener onClickListener = v -> {
|
||||
if (v == mainBinding.profileView.mainBiography) {
|
||||
Utils.copyText(this, mainBinding.profileView.mainBiography.getText().toString());
|
||||
} else if (v == mainBinding.profileView.locationBiography) {
|
||||
Utils.copyText(this, mainBinding.profileView.locationBiography.getText().toString());
|
||||
} else if (v == mainBinding.profileView.mainProfileImage || v == mainBinding.profileView.mainHashtagImage || v == mainBinding.profileView.mainLocationImage) {
|
||||
if (storyModels == null || storyModels.length <= 0) {
|
||||
profileDialogListener.onClick(null, 0);
|
||||
} else {
|
||||
// because sometimes configuration changes made this crash on some phones
|
||||
new AlertDialog.Builder(this).setAdapter(profileDialogAdapter, profileDialogListener)
|
||||
.setNeutralButton(R.string.cancel, null).show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mainBinding.profileView.mainBiography.setOnClickListener(onClickListener);
|
||||
mainBinding.profileView.locationBiography.setOnClickListener(onClickListener);
|
||||
mainBinding.profileView.mainProfileImage.setOnClickListener(onClickListener);
|
||||
mainBinding.profileView.mainHashtagImage.setOnClickListener(onClickListener);
|
||||
mainBinding.profileView.mainLocationImage.setOnClickListener(onClickListener);
|
||||
|
||||
mainBinding.profileView.mainBiography.setEnabled(false);
|
||||
mainBinding.profileView.mainProfileImage.setEnabled(false);
|
||||
mainBinding.profileView.mainHashtagImage.setEnabled(false);
|
||||
mainBinding.profileView.mainLocationImage.setEnabled(false);
|
||||
|
||||
final boolean isQueryNull = userQuery == null;
|
||||
if (isQueryNull) {
|
||||
allItems.clear();
|
||||
mainBinding.profileView.privatePage1.setImageResource(R.drawable.ic_info);
|
||||
mainBinding.profileView.privatePage2.setTextSize(20);
|
||||
mainBinding.profileView.privatePage2.setText(isLoggedIn ? R.string.no_acc_logged_in : R.string.no_acc);
|
||||
mainBinding.profileView.privatePage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (!mainBinding.profileView.swipeRefreshLayout.isRefreshing() && userQuery != null)
|
||||
mainHelper.onRefresh();
|
||||
|
||||
mainHelper.onIntent(getIntent());
|
||||
|
||||
handler = new Handler();
|
||||
runnable = () -> {
|
||||
final GetActivityAsyncTask activityAsyncTask = new GetActivityAsyncTask(uid, cookie, result -> {
|
||||
if (result == null || notificationManager == null) {
|
||||
return;
|
||||
}
|
||||
final List<String> list = new ArrayList<>();
|
||||
if (result.getRelationshipsCount() != 0) {
|
||||
list.add(getString(R.string.activity_count_relationship, result.getRelationshipsCount()));
|
||||
}
|
||||
if (result.getUserTagsCount() != 0) {
|
||||
list.add(getString(R.string.activity_count_usertags, result.getUserTagsCount()));
|
||||
}
|
||||
if (result.getCommentsCount() != 0) {
|
||||
list.add(getString(R.string.activity_count_comments, result.getCommentsCount()));
|
||||
}
|
||||
if (result.getCommentLikesCount() != 0) {
|
||||
list.add(getString(R.string.activity_count_commentlikes, result.getCommentLikesCount()));
|
||||
}
|
||||
if (result.getLikesCount() != 0) {
|
||||
list.add(getString(R.string.activity_count_likes, result.getLikesCount()));
|
||||
}
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final String join = TextUtils.join(", ", list);
|
||||
final String notificationString = getString(R.string.activity_count_prefix) + " " + join + ".";
|
||||
final Intent intent = new Intent(getApplicationContext(), NotificationsViewer.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
final Notification notification = new NotificationCompat.Builder(MainActivityBackup.this, CHANNEL_ID)
|
||||
.setCategory(NotificationCompat.CATEGORY_STATUS)
|
||||
.setSmallIcon(R.drawable.ic_notif)
|
||||
.setAutoCancel(true)
|
||||
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||
.setContentText(notificationString)
|
||||
.setContentIntent(PendingIntent.getActivity(getApplicationContext(), 1738, intent, PendingIntent.FLAG_UPDATE_CURRENT))
|
||||
.build();
|
||||
notificationManager.cancel(1800000000);
|
||||
notificationManager.notify(1800000000, notification);
|
||||
});
|
||||
activityAsyncTask.execute();
|
||||
if (!Utils.isEmpty(cookie) && Utils.settingsHelper.getBoolean(Constants.CHECK_ACTIVITY))
|
||||
activityAsyncTask.execute();
|
||||
handler.postDelayed(runnable, DELAY_MILLIS);
|
||||
};
|
||||
handler.postDelayed(runnable, INITIAL_DELAY_MILLIS);
|
||||
}
|
||||
|
||||
private void downloadSelectedItems() {
|
||||
if (selectedItems.size() > 0) {
|
||||
Utils.batchDownload(this, userQuery, DownloadMethod.DOWNLOAD_MAIN, selectedItems);
|
||||
} else if (selectedDiscoverItems.size() > 0) {
|
||||
Utils.batchDownload(this, null, DownloadMethod.DOWNLOAD_DISCOVER, selectedDiscoverItems);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(final Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
mainHelper.onIntent(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull final Bundle outState, @NonNull final PersistableBundle outPersistentState) {
|
||||
outState.putString("query", userQuery);
|
||||
outState.putSerializable("stack", queriesStack);
|
||||
super.onSaveInstanceState(outState, outPersistentState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(@Nullable final Bundle savedInstanceState, @Nullable final PersistableBundle persistentState) {
|
||||
super.onRestoreInstanceState(savedInstanceState, persistentState);
|
||||
if (savedInstanceState != null) {
|
||||
userQuery = savedInstanceState.getString("query");
|
||||
setStack(savedInstanceState);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||
outState.putString("query", userQuery);
|
||||
outState.putSerializable("stack", queriesStack);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
userQuery = savedInstanceState.getString("query");
|
||||
setStack(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu, menu);
|
||||
|
||||
final FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
final MenuItem quickAccessAction = menu.findItem(R.id.action_quickaccess).setVisible(true);
|
||||
|
||||
final MenuItem.OnMenuItemClickListener clickListener = item -> {
|
||||
if (item == downloadAction)
|
||||
downloadSelectedItems();
|
||||
else if (item == dmsAction)
|
||||
startActivity(new Intent(this, DirectMessagesActivity.class));
|
||||
else if (item == notifAction)
|
||||
startActivity(new Intent(this, NotificationsViewer.class));
|
||||
else if (item == settingsAction)
|
||||
new SettingsDialog().show(fragmentManager, "settings");
|
||||
else if (item == quickAccessAction)
|
||||
new QuickAccessDialog()
|
||||
.setQuery(userQuery, locationModel != null ? locationModel.getName() : userQuery)
|
||||
.show(fragmentManager, "quickAccess");
|
||||
else
|
||||
new AboutDialog().show(fragmentManager, "about");
|
||||
return true;
|
||||
};
|
||||
|
||||
quickAccessAction.setOnMenuItemClickListener(clickListener);
|
||||
menu.findItem(R.id.action_about).setVisible(true).setOnMenuItemClickListener(clickListener);
|
||||
dmsAction = menu.findItem(R.id.action_dms).setOnMenuItemClickListener(clickListener);
|
||||
notifAction = menu.findItem(R.id.action_notif).setOnMenuItemClickListener(clickListener);
|
||||
settingsAction = menu.findItem(R.id.action_settings).setVisible(true).setOnMenuItemClickListener(clickListener);
|
||||
downloadAction = menu.findItem(R.id.action_download).setOnMenuItemClickListener(clickListener);
|
||||
|
||||
if (!Utils.isEmpty(Utils.settingsHelper.getString(Constants.COOKIE))) {
|
||||
notifAction.setVisible(true);
|
||||
dmsAction.setVisible(true).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
}
|
||||
|
||||
searchAction = menu.findItem(R.id.action_search);
|
||||
searchView = (SearchView) searchAction.getActionView();
|
||||
final View searchText = searchView.findViewById(R.id.search_src_text);
|
||||
if (searchText instanceof AutoCompleteTextView)
|
||||
searchAutoComplete = (AutoCompleteTextView) searchText;
|
||||
|
||||
searchView.setQueryHint(getResources().getString(R.string.action_search));
|
||||
searchView.setSuggestionsAdapter(suggestionAdapter);
|
||||
searchView.setOnSearchClickListener(v -> {
|
||||
searchView.setQuery((cookieModel != null && userQuery != null && userQuery.equals("@" + cookieModel.getUsername())) ? "" : userQuery, false);
|
||||
menu.findItem(R.id.action_about).setVisible(false);
|
||||
menu.findItem(R.id.action_settings).setVisible(false);
|
||||
menu.findItem(R.id.action_dms).setVisible(false);
|
||||
menu.findItem(R.id.action_quickaccess).setVisible(false);
|
||||
menu.findItem(R.id.action_notif).setVisible(false);
|
||||
});
|
||||
searchAction.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
|
||||
@Override
|
||||
public boolean onMenuItemActionExpand(MenuItem item) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemActionCollapse(MenuItem item) {
|
||||
menu.findItem(R.id.action_about).setVisible(true);
|
||||
menu.findItem(R.id.action_settings).setVisible(true);
|
||||
menu.findItem(R.id.action_dms).setVisible(!Utils.isEmpty(Utils.settingsHelper.getString(Constants.COOKIE)));
|
||||
menu.findItem(R.id.action_quickaccess).setVisible(true);
|
||||
menu.findItem(R.id.action_notif).setVisible(true);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
private boolean searchUser, searchHash;
|
||||
private AsyncTask<?, ?, ?> prevSuggestionAsync;
|
||||
private final String[] COLUMNS = {BaseColumns._ID, Constants.EXTRAS_USERNAME, Constants.EXTRAS_NAME,
|
||||
Constants.EXTRAS_TYPE, "pfp", "verified"};
|
||||
private final FetchListener<SuggestionModel[]> fetchListener = new FetchListener<SuggestionModel[]>() {
|
||||
@Override
|
||||
public void doBefore() {
|
||||
suggestionAdapter.changeCursor(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(final SuggestionModel[] result) {
|
||||
final MatrixCursor cursor;
|
||||
if (result == null) cursor = null;
|
||||
else {
|
||||
cursor = new MatrixCursor(COLUMNS, 0);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
final SuggestionModel suggestionModel = result[i];
|
||||
if (suggestionModel != null) {
|
||||
final SuggestionType suggestionType = suggestionModel.getSuggestionType();
|
||||
final Object[] objects = {i,
|
||||
(suggestionType == SuggestionType.TYPE_LOCATION) ? suggestionModel.getName() : suggestionModel.getUsername(),
|
||||
(suggestionType == SuggestionType.TYPE_LOCATION) ? suggestionModel.getUsername() : suggestionModel.getName(),
|
||||
suggestionType, suggestionModel.getProfilePic(), suggestionModel.isVerified()};
|
||||
|
||||
if (!searchHash && !searchUser) cursor.addRow(objects);
|
||||
else {
|
||||
final boolean isCurrHash = suggestionType == SuggestionType.TYPE_HASHTAG;
|
||||
if (searchHash && isCurrHash || !searchHash && !isCurrHash)
|
||||
cursor.addRow(objects);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
suggestionAdapter.changeCursor(cursor);
|
||||
}
|
||||
};
|
||||
|
||||
private void cancelSuggestionsAsync() {
|
||||
if (prevSuggestionAsync != null)
|
||||
try {
|
||||
prevSuggestionAsync.cancel(true);
|
||||
} catch (final Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(final String query) {
|
||||
cancelSuggestionsAsync();
|
||||
menu.findItem(R.id.action_about).setVisible(true);
|
||||
menu.findItem(R.id.action_settings).setVisible(true);
|
||||
|
||||
closeAnyOpenDrawer();
|
||||
addToStack();
|
||||
userQuery = (query.contains("@") || query.contains("#")) ? query : ("@" + query);
|
||||
searchAction.collapseActionView();
|
||||
searchView.setIconified(true);
|
||||
searchView.setIconified(true);
|
||||
mainHelper.onRefresh();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(final String newText) {
|
||||
cancelSuggestionsAsync();
|
||||
|
||||
if (!Utils.isEmpty(newText)) {
|
||||
searchUser = newText.charAt(0) == '@';
|
||||
searchHash = newText.charAt(0) == '#';
|
||||
|
||||
if (newText.length() == 1 && (searchHash || searchUser)) {
|
||||
if (searchAutoComplete != null) searchAutoComplete.setThreshold(2);
|
||||
} else {
|
||||
if (searchAutoComplete != null) searchAutoComplete.setThreshold(1);
|
||||
prevSuggestionAsync = new SuggestionsFetcher(fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
|
||||
searchUser || searchHash ? newText.substring(1) : newText);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (closeAnyOpenDrawer()) return;
|
||||
|
||||
if (searchView != null && !searchView.isIconified()) {
|
||||
if (searchAction != null) searchAction.collapseActionView();
|
||||
searchView.setIconified(true);
|
||||
searchView.setIconified(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mainHelper.isSelectionCleared()) return;
|
||||
|
||||
final GridLayoutManager layoutManager = (GridLayoutManager) mainBinding.profileView.mainPosts.getLayoutManager();
|
||||
if (layoutManager != null && layoutManager.findFirstCompletelyVisibleItemPosition() >= layoutManager.getSpanCount()) {
|
||||
mainBinding.profileView.mainPosts.smoothScrollToPosition(0);
|
||||
mainBinding.profileView.appBarLayout.setExpanded(true, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (queriesStack != null && queriesStack.size() > 0) {
|
||||
userQuery = queriesStack.pop();
|
||||
if (userQuery != null) {
|
||||
mainHelper.onRefresh();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@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)
|
||||
downloadSelectedItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == 9629 && (resultCode == 1692 || resultCode == RESULT_CANCELED))
|
||||
finish();
|
||||
else if (requestCode == 6007)
|
||||
Utils.showImportExportDialog(this);
|
||||
// else if (requestCode == 6969 && mainHelper.currentFeedPlayer != null)
|
||||
// mainHelper.currentFeedPlayer.setPlayWhenReady(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
if (mainHelper != null) mainHelper.onPause();
|
||||
if (handler != null && runnable != null) {
|
||||
handler.removeCallbacks(runnable);
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
if (mainHelper != null) mainHelper.onResume();
|
||||
if (handler != null && runnable != null) {
|
||||
handler.postDelayed(runnable, INITIAL_DELAY_MILLIS);
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
private void setStack(final Bundle bundle) {
|
||||
final Object stack = bundle != null ? bundle.get("stack") : null;
|
||||
if (stack instanceof Stack) //noinspection unchecked
|
||||
queriesStack = (Stack<String>) stack;
|
||||
}
|
||||
|
||||
public void addToStack() {
|
||||
if (userQuery != null) {
|
||||
if (queriesStack == null) queriesStack = new Stack<>();
|
||||
queriesStack.add(userQuery);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean closeAnyOpenDrawer() {
|
||||
final int childCount = mainBinding.drawerLayout.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
final View child = mainBinding.drawerLayout.getChildAt(i);
|
||||
final MouseDrawer.LayoutParams childLp = (MouseDrawer.LayoutParams) child.getLayoutParams();
|
||||
|
||||
if ((childLp.openState & MouseDrawer.LayoutParams.FLAG_IS_OPENED) == 1 ||
|
||||
(childLp.openState & MouseDrawer.LayoutParams.FLAG_IS_OPENING) == 2 ||
|
||||
childLp.onScreen >= 0.6 || childLp.isPeeking) {
|
||||
mainBinding.drawerLayout.closeDrawer(child);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -161,7 +161,7 @@ public final class PostViewer extends BaseLanguageActivity {
|
||||
if (player != null) {
|
||||
final float intVol = player.getVolume() == 0f ? 1f : 0f;
|
||||
player.setVolume(intVol);
|
||||
viewerBinding.bottomPanel.btnMute.setImageResource(intVol == 0f ? R.drawable.mute : R.drawable.vol);
|
||||
viewerBinding.bottomPanel.btnMute.setImageResource(intVol == 0f ? R.drawable.ic_volume_off_24 : R.drawable.ic_volume_up_24);
|
||||
Utils.sessionVolumeFull = intVol == 1f;
|
||||
}
|
||||
} else if (v == viewerBinding.btnLike) {
|
||||
@ -307,7 +307,7 @@ public final class PostViewer extends BaseLanguageActivity {
|
||||
isFromShare = postModel.getPosition() == -1 || postIdNull;
|
||||
|
||||
viewerCaptionParent = (View) viewerBinding.bottomPanel.viewerCaption.getParent();
|
||||
viewsContainer = (View) viewerBinding.bottomPanel.tvVideoViews.getParent();
|
||||
viewsContainer = (View) viewerBinding.bottomPanel.videoViewsContainer;
|
||||
|
||||
viewerBinding.mediaList.setLayoutManager(new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false));
|
||||
viewerBinding.mediaList.setAdapter(mediaAdapter);
|
||||
@ -320,8 +320,8 @@ public final class PostViewer extends BaseLanguageActivity {
|
||||
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 && MainActivity.itemGetter != null) {
|
||||
itemGetterItems = MainActivity.itemGetter.get(itemGetType);
|
||||
} else if (itemGetType != null && MainActivityBackup.itemGetter != null) {
|
||||
itemGetterItems = MainActivityBackup.itemGetter.get(itemGetType);
|
||||
isMainSwipe = !(itemGetterItems.size() < 1 || itemGetType == ItemGetType.MAIN_ITEMS && isFromShare);
|
||||
} else {
|
||||
itemGetterItems = null;
|
||||
@ -449,7 +449,7 @@ public final class PostViewer extends BaseLanguageActivity {
|
||||
player.prepare(mediaSource);
|
||||
|
||||
player.setVolume(vol);
|
||||
viewerBinding.bottomPanel.btnMute.setImageResource(vol == 0f ? R.drawable.vol : R.drawable.mute);
|
||||
viewerBinding.bottomPanel.btnMute.setImageResource(vol == 0f ? R.drawable.ic_volume_up_24 : R.drawable.ic_volume_off_24);
|
||||
|
||||
viewerBinding.bottomPanel.btnMute.setOnClickListener(onClickListener);
|
||||
}
|
||||
|
@ -62,7 +62,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.utils.Constants;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
@ -140,13 +139,13 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe
|
||||
final HighlightModel highlightModel = (HighlightModel) tag;
|
||||
new iStoryStatusFetcher(highlightModel.getId(), null, false, false,
|
||||
(!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("@", ""))
|
||||
.putExtra(Constants.EXTRAS_HIGHLIGHT, highlightModel.getTitle())
|
||||
.putExtra(Constants.EXTRAS_STORIES, result)
|
||||
);
|
||||
else
|
||||
if (result != null && result.length > 0) {
|
||||
// startActivity(new Intent(ProfileViewer.this, StoryViewer.class)
|
||||
// .putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", ""))
|
||||
// .putExtra(Constants.EXTRAS_HIGHLIGHT, highlightModel.getTitle())
|
||||
// .putExtra(Constants.EXTRAS_STORIES, result)
|
||||
// );
|
||||
} else
|
||||
Toast.makeText(ProfileViewer.this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
@ -188,11 +187,12 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe
|
||||
newintent = new Intent(this, ProfilePicViewer.class).putExtra(
|
||||
((hashtagModel != null) ? Constants.EXTRAS_HASHTAG : (locationModel != null ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_PROFILE)),
|
||||
((hashtagModel != null) ? hashtagModel : (locationModel != null ? locationModel : profileModel)));
|
||||
} else
|
||||
newintent = new Intent(this, StoryViewer.class).putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", ""))
|
||||
.putExtra(Constants.EXTRAS_STORIES, storyModels)
|
||||
.putExtra(Constants.EXTRAS_HASHTAG, (hashtagModel != null));
|
||||
startActivity(newintent);
|
||||
}
|
||||
// else
|
||||
// newintent = new Intent(this, StoryViewer.class).putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", ""))
|
||||
// .putExtra(Constants.EXTRAS_STORIES, storyModels)
|
||||
// .putExtra(Constants.EXTRAS_HASHTAG, (hashtagModel != null));
|
||||
// startActivity(newintent);
|
||||
};
|
||||
|
||||
profileBinding.profileView.swipeRefreshLayout.setOnRefreshListener(this);
|
||||
@ -213,26 +213,26 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe
|
||||
final GridAutofitLayoutManager layoutManager = new GridAutofitLayoutManager(ProfileViewer.this, Utils.convertDpToPx(110));
|
||||
profileBinding.profileView.mainPosts.setLayoutManager(layoutManager);
|
||||
profileBinding.profileView.mainPosts.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4)));
|
||||
profileBinding.profileView.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(ProfileViewer.this, PostViewer.class)
|
||||
.putExtra(Constants.EXTRAS_INDEX, postModel.getPosition())
|
||||
.putExtra(Constants.EXTRAS_POST, postModel)
|
||||
.putExtra(Constants.EXTRAS_USER, userQuery)
|
||||
.putExtra(Constants.EXTRAS_TYPE, ItemGetType.MAIN_ITEMS));
|
||||
}
|
||||
}, v -> { // long click listener
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof PostModel) {
|
||||
postsAdapter.isSelecting = true;
|
||||
toggleSelection((PostModel) tag);
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
// profileBinding.profileView.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(ProfileViewer.this, PostViewer.class)
|
||||
// .putExtra(Constants.EXTRAS_INDEX, postModel.getPosition())
|
||||
// .putExtra(Constants.EXTRAS_POST, postModel)
|
||||
// .putExtra(Constants.EXTRAS_USER, userQuery)
|
||||
// .putExtra(Constants.EXTRAS_TYPE, ItemGetType.MAIN_ITEMS));
|
||||
// }
|
||||
// }, v -> { // long click listener
|
||||
// final Object tag = v.getTag();
|
||||
// if (tag instanceof PostModel) {
|
||||
// postsAdapter.isSelecting = true;
|
||||
// toggleSelection((PostModel) tag);
|
||||
// }
|
||||
// return true;
|
||||
// }));
|
||||
|
||||
this.lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if ((!autoloadPosts || isHashtag) && hasNextPage) {
|
||||
@ -279,7 +279,7 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe
|
||||
allItems.clear();
|
||||
selectedItems.clear();
|
||||
if (postsAdapter != null) {
|
||||
postsAdapter.isSelecting = false;
|
||||
// postsAdapter.isSelecting = false;
|
||||
postsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
profileBinding.profileView.appBarLayout.setExpanded(true, true);
|
||||
@ -776,11 +776,11 @@ public final class ProfileViewer extends BaseLanguageActivity implements SwipeRe
|
||||
}
|
||||
|
||||
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);
|
||||
// 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,30 +6,36 @@ import android.content.res.Resources;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.ActionMode;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.activity.OnBackPressedDispatcher;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.PostsAdapter;
|
||||
import awais.instagrabber.asyncs.PostsFetcher;
|
||||
import awais.instagrabber.asyncs.i.iLikedFetcher;
|
||||
import awais.instagrabber.customviews.PrimaryActionModeCallback;
|
||||
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.fragments.main.viewmodels.ProfilePostsViewModel;
|
||||
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;
|
||||
@ -48,22 +54,61 @@ public final class SavedViewer extends BaseLanguageActivity implements SwipeRefr
|
||||
//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<PostModel> selectedItems = new ArrayList<>();
|
||||
private final ArrayList<PostModel> allItems = new ArrayList<>();
|
||||
private MenuItem downloadAction;
|
||||
private ActionMode actionMode;
|
||||
private ProfilePostsViewModel profilePostsViewModel;
|
||||
|
||||
private final String cookie = Utils.settingsHelper.getString(Constants.COOKIE);
|
||||
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
if (postsAdapter == null) {
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
postsAdapter.clearSelection();
|
||||
remove();
|
||||
}
|
||||
};
|
||||
private final PrimaryActionModeCallback multiSelectAction = new PrimaryActionModeCallback(
|
||||
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 || username == null) {
|
||||
return false;
|
||||
}
|
||||
Utils.batchDownload(SavedViewer.this,
|
||||
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) {
|
||||
final int oldSize = allItems.size();
|
||||
if (result != null) {
|
||||
allItems.addAll(Arrays.asList(result));
|
||||
|
||||
postsAdapter.notifyItemRangeInserted(oldSize, result.length);
|
||||
|
||||
final List<PostModel> current = profilePostsViewModel.getList().getValue();
|
||||
final List<PostModel> resultList = Arrays.asList(result);
|
||||
if (current == null) {
|
||||
profilePostsViewModel.getList().postValue(resultList);
|
||||
} else {
|
||||
final List<PostModel> currentCopy = new ArrayList<>(current);
|
||||
currentCopy.addAll(resultList);
|
||||
profilePostsViewModel.getList().postValue(currentCopy);
|
||||
}
|
||||
savedBinding.mainPosts.post(() -> {
|
||||
savedBinding.mainPosts.setNestedScrollingEnabled(true);
|
||||
savedBinding.mainPosts.setVisibility(View.VISIBLE);
|
||||
@ -85,13 +130,12 @@ public final class SavedViewer extends BaseLanguageActivity implements SwipeRefr
|
||||
}
|
||||
model.setPageCursor(false, null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
savedBinding.swipeRefreshLayout.setRefreshing(false);
|
||||
if (oldSize == 0) {
|
||||
Toast.makeText(getApplicationContext(), R.string.empty_list, Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
// if (oldSize == 0) {
|
||||
// Toast.makeText(getApplicationContext(), R.string.empty_list, Toast.LENGTH_SHORT).show();
|
||||
// finish();
|
||||
// }
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -117,26 +161,36 @@ public final class SavedViewer extends BaseLanguageActivity implements SwipeRefr
|
||||
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())
|
||||
profilePostsViewModel = new ViewModelProvider(this).get(ProfilePostsViewModel.class);
|
||||
postsAdapter = new PostsAdapter((postModel, position) -> {
|
||||
if (postsAdapter.isSelecting()) {
|
||||
if (actionMode == null) return;
|
||||
final String title = getString(R.string.number_selected, postsAdapter.getSelectedModels().size());
|
||||
actionMode.setTitle(title);
|
||||
return;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}, v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof PostModel) {
|
||||
postsAdapter.isSelecting = true;
|
||||
toggleSelection((PostModel) tag);
|
||||
}
|
||||
|
||||
}, (model, position) -> {
|
||||
if (!postsAdapter.isSelecting()) {
|
||||
checkAndResetAction();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
final OnBackPressedDispatcher onBackPressedDispatcher = getOnBackPressedDispatcher();
|
||||
if (onBackPressedDispatcher.hasEnabledCallbacks()) return true;
|
||||
actionMode = startActionMode(multiSelectAction);
|
||||
final String title = getString(R.string.number_selected, 1);
|
||||
actionMode.setTitle(title);
|
||||
onBackPressedDispatcher.addCallback(onBackPressedCallback);
|
||||
return true;
|
||||
});
|
||||
savedBinding.mainPosts.setAdapter(postsAdapter);
|
||||
profilePostsViewModel.getList().observe(this, postsAdapter::submitList);
|
||||
savedBinding.swipeRefreshLayout.setRefreshing(true);
|
||||
setSupportActionBar(savedBinding.toolbar.toolbar);
|
||||
savedBinding.toolbar.toolbar.setTitle((action.charAt(0) == '$' ? R.string.saved :
|
||||
@ -157,19 +211,22 @@ public final class SavedViewer extends BaseLanguageActivity implements SwipeRefr
|
||||
savedBinding.mainPosts.addOnScrollListener(lazyLoader);
|
||||
|
||||
itemGetter = itemGetType -> {
|
||||
if (itemGetType == ItemGetType.SAVED_ITEMS) return allItems;
|
||||
if (itemGetType == ItemGetType.SAVED_ITEMS)
|
||||
return profilePostsViewModel.getList().getValue();
|
||||
return null;
|
||||
};
|
||||
|
||||
if (action.charAt(0) == '^') new iLikedFetcher(postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
else new PostsFetcher(action, postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
if (action.charAt(0) == '^')
|
||||
new iLikedFetcher(postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
else
|
||||
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);
|
||||
final MenuItem downloadAction = menu.findItem(R.id.downloadAction);
|
||||
downloadAction.setVisible(false);
|
||||
|
||||
menu.findItem(R.id.favouriteAction).setVisible(false);
|
||||
@ -183,27 +240,21 @@ public final class SavedViewer extends BaseLanguageActivity implements SwipeRefr
|
||||
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();
|
||||
profilePostsViewModel.getList().postValue(Collections.emptyList());
|
||||
selectedItems.clear();
|
||||
if (postsAdapter != null) {
|
||||
postsAdapter.isSelecting = false;
|
||||
// postsAdapter.isSelecting = false;
|
||||
postsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
savedBinding.swipeRefreshLayout.setRefreshing(true);
|
||||
if (action.charAt(0) == '^') new iLikedFetcher(postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
else new PostsFetcher(action, postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
if (action.charAt(0) == '^')
|
||||
new iLikedFetcher(postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
else
|
||||
new PostsFetcher(action, postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -225,26 +276,13 @@ public final class SavedViewer extends BaseLanguageActivity implements SwipeRefr
|
||||
}
|
||||
}
|
||||
|
||||
private void toggleSelection(final PostModel postModel) {
|
||||
if (postModel != null && postsAdapter != null) {
|
||||
if (postModel.isSelected()) selectedItems.remove(postModel);
|
||||
else if (selectedItems.size() >= 100) {
|
||||
Toast.makeText(SavedViewer.this, R.string.downloader_too_many, Toast.LENGTH_SHORT);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
private boolean checkAndResetAction() {
|
||||
final OnBackPressedDispatcher onBackPressedDispatcher = getOnBackPressedDispatcher();
|
||||
if (!onBackPressedDispatcher.hasEnabledCallbacks() || actionMode == null) {
|
||||
return false;
|
||||
}
|
||||
actionMode.finish();
|
||||
actionMode = null;
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,769 +1,167 @@
|
||||
package awais.instagrabber.activities;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.GestureDetectorCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
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.google.android.exoplayer2.Player;
|
||||
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.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.StoriesAdapter;
|
||||
import awais.instagrabber.asyncs.DownloadAsync;
|
||||
import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster;
|
||||
import awais.instagrabber.asyncs.i.iStoryStatusFetcher;
|
||||
import awais.instagrabber.customviews.helpers.SwipeGestureListener;
|
||||
import awais.instagrabber.databinding.ActivityStoryViewerBinding;
|
||||
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;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
import awais.instagrabber.models.stickers.QuizModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import awaisomereport.LogCollector;
|
||||
|
||||
import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_THRESHOLD;
|
||||
import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD;
|
||||
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
||||
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
||||
import static awais.instagrabber.utils.Constants.MARK_AS_SEEN;
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public final class StoryViewer extends BaseLanguageActivity {
|
||||
private final StoriesAdapter storiesAdapter = new StoriesAdapter(null, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof StoryModel) {
|
||||
currentStory = (StoryModel) tag;
|
||||
slidePos = currentStory.getPosition();
|
||||
refreshStory();
|
||||
}
|
||||
}
|
||||
});
|
||||
private ActivityStoryViewerBinding storyViewerBinding;
|
||||
private StoryModel[] storyModels;
|
||||
private GestureDetectorCompat gestureDetector;
|
||||
private SimpleExoPlayer player;
|
||||
private SwipeEvent swipeEvent;
|
||||
private MenuItem menuDownload, menuDm;
|
||||
private PollModel poll;
|
||||
private QuestionModel question;
|
||||
private String[] mentions;
|
||||
private QuizModel quiz;
|
||||
private StoryModel currentStory;
|
||||
private String url, username;
|
||||
private int slidePos = 0, lastSlidePos = 0;
|
||||
private final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
private boolean fetching = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
storyViewerBinding = ActivityStoryViewerBinding.inflate(getLayoutInflater());
|
||||
setContentView(storyViewerBinding.getRoot());
|
||||
|
||||
setSupportActionBar(storyViewerBinding.toolbar.toolbar);
|
||||
|
||||
final Intent intent = getIntent();
|
||||
if (intent == null || !intent.hasExtra(Constants.EXTRAS_STORIES)
|
||||
|| (storyModels = (StoryModel[]) intent.getSerializableExtra(Constants.EXTRAS_STORIES)) == null) {
|
||||
Utils.errorFinish(this);
|
||||
return;
|
||||
}
|
||||
|
||||
username = intent.getStringExtra(Constants.EXTRAS_USERNAME);
|
||||
final String highlight = intent.getStringExtra(Constants.EXTRAS_HIGHLIGHT);
|
||||
final boolean hasUsername = !Utils.isEmpty(username);
|
||||
final boolean hasHighlight = !Utils.isEmpty(highlight);
|
||||
|
||||
if (hasUsername) {
|
||||
username = username.replace("@", "");
|
||||
storyViewerBinding.toolbar.toolbar.setTitle(username);
|
||||
storyViewerBinding.toolbar.toolbar.setOnClickListener(v -> {
|
||||
searchUsername(username);
|
||||
});
|
||||
if (hasHighlight) storyViewerBinding.toolbar.toolbar.setSubtitle(getString(R.string.title_highlight, highlight));
|
||||
else storyViewerBinding.toolbar.toolbar.setSubtitle(R.string.title_user_story);
|
||||
}
|
||||
|
||||
storyViewerBinding.storiesList.setVisibility(View.GONE);
|
||||
storyViewerBinding.storiesList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
|
||||
storyViewerBinding.storiesList.setAdapter(storiesAdapter);
|
||||
|
||||
swipeEvent = new SwipeEvent() {
|
||||
private final int storiesLen = storyModels != null ? storyModels.length : 0;
|
||||
|
||||
@Override
|
||||
public void onSwipe(final boolean isRightSwipe) {
|
||||
if (storyModels != null && storiesLen > 0) {
|
||||
if (((slidePos + 1 >= storiesLen && isRightSwipe == false) || (slidePos == 0 && isRightSwipe == true))
|
||||
&& intent.hasExtra(Constants.FEED)) {
|
||||
final FeedStoryModel[] storyFeed = (FeedStoryModel[]) intent.getSerializableExtra(Constants.FEED);
|
||||
final int index = intent.getIntExtra(Constants.FEED_ORDER, 1738);
|
||||
if (settingsHelper.getBoolean(MARK_AS_SEEN)) new SeenAction().execute();
|
||||
if ((isRightSwipe == true && index == 0) || (isRightSwipe == false && index == storyFeed.length - 1))
|
||||
Toast.makeText(getApplicationContext(), R.string.no_more_stories, Toast.LENGTH_SHORT).show();
|
||||
else {
|
||||
final FeedStoryModel feedStoryModel = isRightSwipe ?
|
||||
(index == 0 ? null : storyFeed[index - 1]) :
|
||||
(storyFeed.length == index + 1 ? null : storyFeed[index + 1]);
|
||||
if (feedStoryModel != null) {
|
||||
if (fetching) {
|
||||
Toast.makeText(getApplicationContext(), R.string.be_patient, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
fetching = true;
|
||||
new iStoryStatusFetcher(feedStoryModel.getStoryMediaId(), null, false, false, false, false, result -> {
|
||||
if (result != null && result.length > 0) {
|
||||
final Intent newIntent = new Intent(getApplicationContext(), StoryViewer.class)
|
||||
.putExtra(Constants.EXTRAS_STORIES, result)
|
||||
.putExtra(Constants.EXTRAS_USERNAME, feedStoryModel.getProfileModel().getUsername())
|
||||
.putExtra(Constants.FEED, storyFeed)
|
||||
.putExtra(Constants.FEED_ORDER, isRightSwipe ? (index - 1) : (index + 1));
|
||||
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(newIntent);
|
||||
} else
|
||||
Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isRightSwipe) {
|
||||
if (--slidePos <= 0) slidePos = 0;
|
||||
} else if (++slidePos >= storiesLen) slidePos = storiesLen - 1;
|
||||
currentStory = storyModels[slidePos];
|
||||
refreshStory();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
gestureDetector = new GestureDetectorCompat(this, new SwipeGestureListener(swipeEvent));
|
||||
|
||||
viewPost();
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private void viewPost() {
|
||||
lastSlidePos = 0;
|
||||
storyViewerBinding.storiesList.setVisibility(View.GONE);
|
||||
storiesAdapter.setData(null);
|
||||
|
||||
if (menuDownload != null) menuDownload.setVisible(false);
|
||||
if (menuDm != null) menuDm.setVisible(false);
|
||||
|
||||
storyViewerBinding.playerView.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event));
|
||||
storyViewerBinding.imageViewer.setOnSingleFlingListener((e1, e2, velocityX, velocityY) -> {
|
||||
final float diffX = e2.getX() - e1.getX();
|
||||
try {
|
||||
if (Math.abs(diffX) > Math.abs(e2.getY() - e1.getY()) && Math.abs(diffX) > SWIPE_THRESHOLD
|
||||
&& Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
|
||||
swipeEvent.onSwipe(diffX > 0);
|
||||
return true;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.ACTIVITY_STORY_VIEWER, "viewPost",
|
||||
new Pair<>("swipeEvent", swipeEvent),
|
||||
new Pair<>("diffX", diffX));
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
}
|
||||
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)
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(tag.toString(), tag.toString().matches("^[\\d]+$"))));
|
||||
});
|
||||
|
||||
final View.OnClickListener storyActionListener = v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof PollModel) {
|
||||
poll = (PollModel) tag;
|
||||
if (poll.getMyChoice() > -1)
|
||||
new AlertDialog.Builder(this).setTitle(R.string.voted_story_poll)
|
||||
.setAdapter(new ArrayAdapter<>(this, 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 new AlertDialog.Builder(this).setTitle(poll.getQuestion())
|
||||
.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new String[]{
|
||||
poll.getLeftChoice() + " (" + poll.getLeftCount() + ")",
|
||||
poll.getRightChoice() + " (" + poll.getRightCount() + ")"
|
||||
}), (d, w) -> {
|
||||
if (!Utils.isEmpty(cookie)) new VoteAction().execute(w);
|
||||
})
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
else if (tag instanceof QuestionModel) {
|
||||
question = (QuestionModel) tag;
|
||||
final EditText input = new EditText(this);
|
||||
input.setHint(R.string.answer_hint);
|
||||
new AlertDialog.Builder(this).setTitle(question.getQuestion())
|
||||
.setView(input)
|
||||
.setPositiveButton(R.string.ok, (d,w) -> {
|
||||
new RespondAction().execute(input.getText().toString());
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
else if (tag instanceof String[]) {
|
||||
mentions = (String[]) tag;
|
||||
new AlertDialog.Builder(this).setTitle(R.string.story_mentions)
|
||||
.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mentions), (d,w) -> {
|
||||
searchUsername(mentions[w]);
|
||||
})
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
else if (tag instanceof QuizModel) {
|
||||
quiz = (QuizModel) quiz;
|
||||
String[] choices = new String[quiz.getChoices().length];
|
||||
for (int q = 0; q < choices.length; ++q) {
|
||||
choices[q] = (quiz.getMyChoice() == q ? "√ " :"") + quiz.getChoices()[q]+ " (" + quiz.getCounts()[q] + ")";
|
||||
}
|
||||
new AlertDialog.Builder(this).setTitle(quiz.getMyChoice() > -1 ? getString(R.string.story_quizzed) : quiz.getQuestion())
|
||||
.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, choices), (d,w) -> {
|
||||
if (quiz.getMyChoice() == -1 && !Utils.isEmpty(cookie)) new QuizAction().execute(w);
|
||||
})
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
};
|
||||
|
||||
storyViewerBinding.poll.setOnClickListener(storyActionListener);
|
||||
storyViewerBinding.answer.setOnClickListener(storyActionListener);
|
||||
storyViewerBinding.mention.setOnClickListener(storyActionListener);
|
||||
storyViewerBinding.quiz.setOnClickListener(storyActionListener);
|
||||
|
||||
storiesAdapter.setData(storyModels);
|
||||
if (storyModels.length > 1) storyViewerBinding.storiesList.setVisibility(View.VISIBLE);
|
||||
|
||||
currentStory = storyModels[0];
|
||||
refreshStory();
|
||||
}
|
||||
|
||||
private void setupVideo() {
|
||||
storyViewerBinding.playerView.setVisibility(View.VISIBLE);
|
||||
storyViewerBinding.progressView.setVisibility(View.GONE);
|
||||
storyViewerBinding.imageViewer.setVisibility(View.GONE);
|
||||
storyViewerBinding.imageViewer.setImageDrawable(null);
|
||||
|
||||
player = new SimpleExoPlayer.Builder(this).build();
|
||||
storyViewerBinding.playerView.setPlayer(player);
|
||||
player.setPlayWhenReady(settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS));
|
||||
|
||||
final ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(new DefaultDataSourceFactory(this, "instagram"))
|
||||
.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) {
|
||||
if (menuDownload != null) menuDownload.setVisible(true);
|
||||
if (currentStory.canReply() && menuDm != null && !Utils.isEmpty(cookie)) menuDm.setVisible(true);
|
||||
storyViewerBinding.progressView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
storyViewerBinding.progressView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadCanceled(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) {
|
||||
storyViewerBinding.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) {
|
||||
if (menuDownload != null) menuDownload.setVisible(false);
|
||||
if (menuDm != null) menuDm.setVisible(false);
|
||||
storyViewerBinding.progressView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
player.prepare(mediaSource);
|
||||
|
||||
storyViewerBinding.playerView.setOnClickListener(v -> {
|
||||
if (player != null) {
|
||||
if (player.getPlaybackState() == Player.STATE_ENDED) player.seekTo(0);
|
||||
player.setPlayWhenReady(player.getPlaybackState() == Player.STATE_ENDED || !player.isPlaying());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupImage() {
|
||||
storyViewerBinding.progressView.setVisibility(View.VISIBLE);
|
||||
storyViewerBinding.playerView.setVisibility(View.GONE);
|
||||
|
||||
storyViewerBinding.imageViewer.setImageDrawable(null);
|
||||
storyViewerBinding.imageViewer.setVisibility(View.VISIBLE);
|
||||
storyViewerBinding.imageViewer.setZoomable(true);
|
||||
storyViewerBinding.imageViewer.setZoomTransitionDuration(420);
|
||||
storyViewerBinding.imageViewer.setMaximumScale(7.2f);
|
||||
|
||||
Glide.with(this).load(url).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target<Drawable> target, final boolean isFirstResource) {
|
||||
storyViewerBinding.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) {
|
||||
if (menuDownload != null) menuDownload.setVisible(true);
|
||||
if (currentStory.canReply() && menuDm != null && !Utils.isEmpty(cookie)) menuDm.setVisible(true);
|
||||
storyViewerBinding.progressView.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
}).into(storyViewerBinding.imageViewer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu, menu);
|
||||
|
||||
menu.findItem(R.id.action_settings).setVisible(false);
|
||||
menu.findItem(R.id.action_search).setVisible(false);
|
||||
|
||||
menuDownload = menu.findItem(R.id.action_download);
|
||||
menuDm = menu.findItem(R.id.action_dms);
|
||||
menuDownload.setVisible(true);
|
||||
menuDm.setVisible(false);
|
||||
menuDownload.setOnMenuItemClickListener(item -> {
|
||||
if (ContextCompat.checkSelfPermission(this, Utils.PERMS[0]) == PackageManager.PERMISSION_GRANTED)
|
||||
downloadStory();
|
||||
else
|
||||
ActivityCompat.requestPermissions(this, Utils.PERMS, 8020);
|
||||
return true;
|
||||
});
|
||||
menuDm.setOnMenuItemClickListener(item -> {
|
||||
final EditText input = new EditText(this);
|
||||
input.setHint(R.string.reply_hint);
|
||||
new AlertDialog.Builder(this).setTitle(R.string.reply_story)
|
||||
.setView(input)
|
||||
.setPositiveButton(R.string.ok, (d,w) -> {
|
||||
new CommentAction().execute(input.getText().toString());
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
return true;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@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) downloadStory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (Build.VERSION.SDK_INT < 24) releasePlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
if (Build.VERSION.SDK_INT >= 24) releasePlayer();
|
||||
}
|
||||
|
||||
private void downloadStory() {
|
||||
int error = 0;
|
||||
if (currentStory != null) {
|
||||
File dir = new File(Environment.getExternalStorageDirectory(), "Download");
|
||||
|
||||
if (settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
|
||||
final String customPath = settingsHelper.getString(FOLDER_PATH);
|
||||
if (!Utils.isEmpty(customPath)) dir = new File(customPath);
|
||||
}
|
||||
|
||||
if (settingsHelper.getBoolean(Constants.DOWNLOAD_USER_FOLDER) && !Utils.isEmpty(username))
|
||||
dir = new File(dir, username);
|
||||
|
||||
if (dir.exists() || dir.mkdirs()) {
|
||||
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(this, storyUrl, saveFile, result -> {
|
||||
final int toastRes = result != null && result.exists() ? R.string.downloader_complete
|
||||
: R.string.downloader_error_download_file;
|
||||
Toast.makeText(this, toastRes, Toast.LENGTH_SHORT).show();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
|
||||
} else error = 1;
|
||||
} else error = 2;
|
||||
|
||||
if (error == 1) Toast.makeText(this, R.string.downloader_error_creating_folder, Toast.LENGTH_SHORT).show();
|
||||
else if (error == 2) Toast.makeText(this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
private void refreshStory() {
|
||||
if (storyViewerBinding.storiesList.getVisibility() == View.VISIBLE) {
|
||||
StoryModel item = storiesAdapter.getItemAt(lastSlidePos);
|
||||
if (item != null) {
|
||||
item.setCurrentSlide(false);
|
||||
storiesAdapter.notifyItemChanged(lastSlidePos, item);
|
||||
}
|
||||
|
||||
item = storiesAdapter.getItemAt(slidePos);
|
||||
if (item != null) {
|
||||
item.setCurrentSlide(true);
|
||||
storiesAdapter.notifyItemChanged(slidePos, item);
|
||||
}
|
||||
}
|
||||
lastSlidePos = slidePos;
|
||||
|
||||
final MediaItemType itemType = currentStory.getItemType();
|
||||
|
||||
if (menuDownload != null) menuDownload.setVisible(false);
|
||||
url = itemType == MediaItemType.MEDIA_TYPE_VIDEO ? currentStory.getVideoUrl() : currentStory.getStoryUrl();
|
||||
|
||||
final String shortCode = currentStory.getTappableShortCode();
|
||||
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);
|
||||
|
||||
poll = currentStory.getPoll();
|
||||
storyViewerBinding.poll.setVisibility(poll != null ? View.VISIBLE : View.GONE);
|
||||
storyViewerBinding.poll.setTag(poll);
|
||||
|
||||
question = currentStory.getQuestion();
|
||||
storyViewerBinding.answer.setVisibility((question != null && !Utils.isEmpty(cookie)) ? View.VISIBLE : View.GONE);
|
||||
storyViewerBinding.answer.setTag(question);
|
||||
|
||||
mentions = currentStory.getMentions();
|
||||
storyViewerBinding.mention.setVisibility((mentions != null && mentions.length > 0) ? View.VISIBLE : View.GONE);
|
||||
storyViewerBinding.mention.setTag(mentions);
|
||||
|
||||
quiz = currentStory.getQuiz();
|
||||
storyViewerBinding.quiz.setVisibility(quiz != null ? View.VISIBLE : View.GONE);
|
||||
storyViewerBinding.quiz.setTag(quiz);
|
||||
|
||||
releasePlayer();
|
||||
final Intent intent = getIntent();
|
||||
if (intent.getBooleanExtra(Constants.EXTRAS_HASHTAG, false)) {
|
||||
storyViewerBinding.toolbar.toolbar.setTitle(currentStory.getUsername() + " (" + intent.getStringExtra(Constants.EXTRAS_USERNAME) + ")");
|
||||
storyViewerBinding.toolbar.toolbar.setOnClickListener(v -> {
|
||||
searchUsername(currentStory.getUsername());
|
||||
});
|
||||
}
|
||||
if (itemType == MediaItemType.MEDIA_TYPE_VIDEO) setupVideo();
|
||||
else setupImage();
|
||||
|
||||
if (!intent.hasExtra(Constants.EXTRAS_HIGHLIGHT))
|
||||
storyViewerBinding.toolbar.toolbar.setSubtitle(Utils.datetimeParser.format(new Date(currentStory.getTimestamp() * 1000L)));
|
||||
|
||||
if (settingsHelper.getBoolean(MARK_AS_SEEN)) new SeenAction().execute();
|
||||
}
|
||||
|
||||
private void searchUsername(final String text) {
|
||||
startActivity(
|
||||
new Intent(getApplicationContext(), ProfileViewer.class)
|
||||
.putExtra(Constants.EXTRAS_USERNAME, text)
|
||||
);
|
||||
}
|
||||
|
||||
private void releasePlayer() {
|
||||
if (player != null) {
|
||||
try { player.stop(true); } catch (Exception ignored) { }
|
||||
try { player.release(); } catch (Exception ignored) { }
|
||||
player = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static int indexOfIntArray(Object[] array, Object key) {
|
||||
int returnvalue = -1;
|
||||
for (int i = 0; i < array.length; ++i) {
|
||||
if (key == array[i]) {
|
||||
returnvalue = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
class VoteAction extends AsyncTask<Integer, Void, Void> {
|
||||
int ok = -1;
|
||||
String action;
|
||||
|
||||
protected Void doInBackground(Integer... rawchoice) {
|
||||
int choice = rawchoice[0];
|
||||
final String url = "https://www.instagram.com/media/"+currentStory.getStoryMediaId().split("_")[0]+"/"+poll.getId()+"/story_poll_vote/";
|
||||
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", cookie.split("csrftoken=")[1].split(";")[0]);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
urlConnection.setRequestProperty("Content-Length", "6");
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes("vote="+choice);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
urlConnection.connect();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
ok = choice;
|
||||
}
|
||||
urlConnection.disconnect();
|
||||
} catch (Throwable ex) {
|
||||
Log.e("austin_debug", "vote: " + ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
if (ok > -1) {
|
||||
poll.setMyChoice(ok);
|
||||
Toast.makeText(getApplicationContext(), R.string.votef_story_poll, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
else Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
class QuizAction extends AsyncTask<Integer, Void, Void> {
|
||||
int ok = -1;
|
||||
String action;
|
||||
|
||||
protected Void doInBackground(Integer... rawchoice) {
|
||||
int choice = rawchoice[0];
|
||||
final String url = "https://i.instagram.com/api/v1/media/"+currentStory.getStoryMediaId().split("_")[0]+"/"+quiz.getId()+"/story_quiz_answer/";
|
||||
try {
|
||||
JSONObject ogbody = new JSONObject("{\"client_context\":\"" + UUID.randomUUID().toString()
|
||||
+"\",\"mutation_token\":\"" + UUID.randomUUID().toString()
|
||||
+"\",\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0]
|
||||
+"\",\"_uid\":\"" + Utils.getUserIdFromCookie(cookie)
|
||||
+"\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID)
|
||||
+"\"}");
|
||||
ogbody.put("answer", String.valueOf(choice));
|
||||
String urlParameters = Utils.sign(ogbody.toString());
|
||||
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
urlConnection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
Log.d("austin_debug", "quiz: "+url+" "+cookie+" "+urlParameters);
|
||||
urlConnection.connect();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
ok = choice;
|
||||
}
|
||||
urlConnection.disconnect();
|
||||
} catch (Throwable ex) {
|
||||
Log.e("austin_debug", "quiz: " + ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
if (ok > -1) {
|
||||
quiz.setMyChoice(ok);
|
||||
Toast.makeText(getApplicationContext(), R.string.answered_story, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
else Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
class RespondAction extends AsyncTask<String, Void, Void> {
|
||||
boolean ok = false;
|
||||
String action;
|
||||
|
||||
protected Void doInBackground(String... rawchoice) {
|
||||
final String url = "https://i.instagram.com/api/v1/media/"
|
||||
+currentStory.getStoryMediaId().split("_")[0]+"/"+question.getId()+"/story_question_response/";
|
||||
try {
|
||||
JSONObject ogbody = new JSONObject("{\"client_context\":\"" + UUID.randomUUID().toString()
|
||||
+"\",\"mutation_token\":\"" + UUID.randomUUID().toString()
|
||||
+"\",\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0]
|
||||
+"\",\"_uid\":\"" + Utils.getUserIdFromCookie(cookie)
|
||||
+"\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID)
|
||||
+"\"}");
|
||||
String choice = rawchoice[0].replaceAll("\"", ("\\\""));
|
||||
ogbody.put("response", choice);
|
||||
String urlParameters = Utils.sign(ogbody.toString());
|
||||
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
urlConnection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
urlConnection.connect();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
ok = true;
|
||||
}
|
||||
urlConnection.disconnect();
|
||||
} catch (Throwable ex) {
|
||||
Log.e("austin_debug", "respond: " + ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
if (ok) {
|
||||
Toast.makeText(getApplicationContext(), R.string.answered_story, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
else Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
class SeenAction extends AsyncTask<Void, Void, Void> {
|
||||
protected Void doInBackground(Void... lmao) {
|
||||
final String url = "https://www.instagram.com/stories/reel/seen";
|
||||
try {
|
||||
String urlParameters = "reelMediaId="+currentStory.getStoryMediaId().split("_")[0]
|
||||
+"&reelMediaOwnerId="+currentStory.getUserId()
|
||||
+"&reelId="+currentStory.getUserId()
|
||||
+"&reelMediaTakenAt="+ currentStory.getTimestamp()
|
||||
+"&viewSeenAt="+ currentStory.getTimestamp();
|
||||
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("x-csrftoken", cookie.split("csrftoken=")[1].split(";")[0]);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
urlConnection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
urlConnection.connect();
|
||||
Log.d("austin_debug", urlConnection.getResponseCode() + " " + Utils.readFromConnection(urlConnection));
|
||||
urlConnection.disconnect();
|
||||
} catch (Throwable ex) {
|
||||
Log.e("austin_debug", "seen: " + ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class CommentAction extends AsyncTask<String, Void, Void> {
|
||||
protected Void doInBackground(String... rawAction) {
|
||||
final String action = rawAction[0];
|
||||
final String url = "https://i.instagram.com/api/v1/direct_v2/create_group_thread/";
|
||||
try {
|
||||
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
||||
urlConnection.setUseCaches(false);
|
||||
final String urlParameters = Utils.sign("{\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0]
|
||||
+"\",\"_uid\":\"" + Utils.getUserIdFromCookie(cookie)
|
||||
+"\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID)
|
||||
+"\",\"recipient_users\":\"["+currentStory.getUserId() // <- string of array of number (not joking)
|
||||
+"]\"}");
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
urlConnection.setRequestProperty("Content-Length", "" + urlParameters.getBytes().length);
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
urlConnection.connect();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
final String threadid = new JSONObject(Utils.readFromConnection(urlConnection)).getString("thread_id");
|
||||
final DirectThreadBroadcaster.StoryReplyBroadcastOptions options =
|
||||
new DirectThreadBroadcaster.StoryReplyBroadcastOptions(
|
||||
action,
|
||||
currentStory.getStoryMediaId(),
|
||||
currentStory.getUserId()
|
||||
);
|
||||
final DirectThreadBroadcaster broadcast = new DirectThreadBroadcaster(threadid);
|
||||
broadcast.setOnTaskCompleteListener(result -> {
|
||||
Toast.makeText(getApplicationContext(),
|
||||
result != null ? R.string.answered_story : R.string.downloader_unknown_error,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
broadcast.execute(options);
|
||||
}
|
||||
urlConnection.disconnect();
|
||||
} catch (Throwable ex) {
|
||||
Log.e("austin_debug", "reply (CT): " + ex);
|
||||
Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// package awais.instagrabber.activities;
|
||||
//
|
||||
// import android.content.Intent;
|
||||
// import android.os.AsyncTask;
|
||||
// import android.os.Bundle;
|
||||
// import android.view.MenuItem;
|
||||
// import android.view.View;
|
||||
// import android.widget.Toast;
|
||||
//
|
||||
// import androidx.annotation.Nullable;
|
||||
// import androidx.core.view.GestureDetectorCompat;
|
||||
// import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
//
|
||||
// import awais.instagrabber.R;
|
||||
// import awais.instagrabber.adapters.StoriesAdapter;
|
||||
// import awais.instagrabber.asyncs.SeenAction;
|
||||
// import awais.instagrabber.asyncs.i.iStoryStatusFetcher;
|
||||
// import awais.instagrabber.customviews.helpers.SwipeGestureListener;
|
||||
// import awais.instagrabber.databinding.ActivityStoryViewerBinding;
|
||||
// import awais.instagrabber.interfaces.SwipeEvent;
|
||||
// import awais.instagrabber.models.FeedStoryModel;
|
||||
// import awais.instagrabber.models.StoryModel;
|
||||
// import awais.instagrabber.models.stickers.PollModel;
|
||||
// import awais.instagrabber.models.stickers.QuestionModel;
|
||||
// import awais.instagrabber.models.stickers.QuizModel;
|
||||
// import awais.instagrabber.utils.Constants;
|
||||
// import awais.instagrabber.utils.Utils;
|
||||
//
|
||||
// import static awais.instagrabber.utils.Constants.MARK_AS_SEEN;
|
||||
// import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
//
|
||||
// public final class StoryViewer extends BaseLanguageActivity {
|
||||
// private final StoriesAdapter storiesAdapter = new StoriesAdapter(null, new View.OnClickListener() {
|
||||
// @Override
|
||||
// public void onClick(final View v) {
|
||||
// final Object tag = v.getTag();
|
||||
// if (tag instanceof StoryModel) {
|
||||
// currentStory = (StoryModel) tag;
|
||||
// slidePos = currentStory.getPosition();
|
||||
// refreshStory();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// private ActivityStoryViewerBinding storyViewerBinding;
|
||||
// private StoryModel[] storyModels;
|
||||
// private GestureDetectorCompat gestureDetector;
|
||||
//
|
||||
// private SwipeEvent swipeEvent;
|
||||
// private MenuItem menuDownload, menuDm;
|
||||
// private PollModel poll;
|
||||
// private QuestionModel question;
|
||||
// private String[] mentions;
|
||||
// private QuizModel quiz;
|
||||
// private StoryModel currentStory;
|
||||
// private String url, username;
|
||||
// private int slidePos = 0, lastSlidePos = 0;
|
||||
// private final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
// private boolean fetching = false;
|
||||
//
|
||||
// @Override
|
||||
// protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
// super.onCreate(savedInstanceState);
|
||||
// storyViewerBinding = ActivityStoryViewerBinding.inflate(getLayoutInflater());
|
||||
// setContentView(storyViewerBinding.getRoot());
|
||||
//
|
||||
// setSupportActionBar(storyViewerBinding.toolbar.toolbar);
|
||||
//
|
||||
// final Intent intent = getIntent();
|
||||
// if (intent == null || !intent.hasExtra(Constants.EXTRAS_STORIES)
|
||||
// || (storyModels = (StoryModel[]) intent.getSerializableExtra(Constants.EXTRAS_STORIES)) == null) {
|
||||
// Utils.errorFinish(this);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// username = intent.getStringExtra(Constants.EXTRAS_USERNAME);
|
||||
// final String highlight = intent.getStringExtra(Constants.EXTRAS_HIGHLIGHT);
|
||||
// final boolean hasUsername = !Utils.isEmpty(username);
|
||||
// final boolean hasHighlight = !Utils.isEmpty(highlight);
|
||||
//
|
||||
// if (hasUsername) {
|
||||
// username = username.replace("@", "");
|
||||
// storyViewerBinding.toolbar.toolbar.setTitle(username);
|
||||
// storyViewerBinding.toolbar.toolbar.setOnClickListener(v -> {
|
||||
// searchUsername(username);
|
||||
// });
|
||||
// if (hasHighlight) storyViewerBinding.toolbar.toolbar.setSubtitle(getString(R.string.title_highlight, highlight));
|
||||
// else storyViewerBinding.toolbar.toolbar.setSubtitle(R.string.title_user_story);
|
||||
// }
|
||||
//
|
||||
// storyViewerBinding.storiesList.setVisibility(View.GONE);
|
||||
// storyViewerBinding.storiesList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
|
||||
// storyViewerBinding.storiesList.setAdapter(storiesAdapter);
|
||||
//
|
||||
// swipeEvent = new SwipeEvent() {
|
||||
// private final int storiesLen = storyModels != null ? storyModels.length : 0;
|
||||
//
|
||||
// @Override
|
||||
// public void onSwipe(final boolean isRightSwipe) {
|
||||
// if (storyModels != null && storiesLen > 0) {
|
||||
// if (((slidePos + 1 >= storiesLen && isRightSwipe == false) || (slidePos == 0 && isRightSwipe == true))
|
||||
// && intent.hasExtra(Constants.FEED)) {
|
||||
// final FeedStoryModel[] storyFeed = (FeedStoryModel[]) intent.getSerializableExtra(Constants.FEED);
|
||||
// final int index = intent.getIntExtra(Constants.FEED_ORDER, 1738);
|
||||
// if (settingsHelper.getBoolean(MARK_AS_SEEN)) new SeenAction(cookie, storyModel).execute();
|
||||
// if ((isRightSwipe == true && index == 0) || (isRightSwipe == false && index == storyFeed.length - 1))
|
||||
// Toast.makeText(getApplicationContext(), R.string.no_more_stories, Toast.LENGTH_SHORT).show();
|
||||
// else {
|
||||
// final FeedStoryModel feedStoryModel = isRightSwipe ?
|
||||
// (index == 0 ? null : storyFeed[index - 1]) :
|
||||
// (storyFeed.length == index + 1 ? null : storyFeed[index + 1]);
|
||||
// if (feedStoryModel != null) {
|
||||
// if (fetching) {
|
||||
// Toast.makeText(getApplicationContext(), R.string.be_patient, Toast.LENGTH_SHORT).show();
|
||||
// } else {
|
||||
// fetching = true;
|
||||
// new iStoryStatusFetcher(feedStoryModel.getStoryMediaId(), null, false, false, false, false, result -> {
|
||||
// if (result != null && result.length > 0) {
|
||||
// final Intent newIntent = new Intent(getApplicationContext(), StoryViewer.class)
|
||||
// .putExtra(Constants.EXTRAS_STORIES, result)
|
||||
// .putExtra(Constants.EXTRAS_USERNAME, feedStoryModel.getProfileModel().getUsername())
|
||||
// .putExtra(Constants.FEED, storyFeed)
|
||||
// .putExtra(Constants.FEED_ORDER, isRightSwipe ? (index - 1) : (index + 1));
|
||||
// newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
// startActivity(newIntent);
|
||||
// } else
|
||||
// Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
// }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// if (isRightSwipe) {
|
||||
// if (--slidePos <= 0) slidePos = 0;
|
||||
// } else if (++slidePos >= storiesLen) slidePos = storiesLen - 1;
|
||||
// currentStory = storyModels[slidePos];
|
||||
// refreshStory();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// gestureDetector = new GestureDetectorCompat(this, new SwipeGestureListener(swipeEvent));
|
||||
//
|
||||
// viewPost();
|
||||
// }
|
||||
//
|
||||
// private void searchUsername(final String text) {
|
||||
// startActivity(
|
||||
// new Intent(getApplicationContext(), ProfileViewer.class)
|
||||
// .putExtra(Constants.EXTRAS_USERNAME, text)
|
||||
// );
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// public static int indexOfIntArray(Object[] array, Object key) {
|
||||
// int returnvalue = -1;
|
||||
// for (int i = 0; i < array.length; ++i) {
|
||||
// if (key == array[i]) {
|
||||
// returnvalue = i;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// return returnvalue;
|
||||
// }
|
||||
//
|
||||
// }
|
@ -1,87 +1,56 @@
|
||||
package awais.instagrabber.adapters;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
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 java.util.ArrayList;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.viewholder.DiscoverViewHolder;
|
||||
import awais.instagrabber.models.DiscoverItemModel;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
|
||||
public final class DiscoverAdapter extends RecyclerView.Adapter<DiscoverViewHolder> {
|
||||
private final ArrayList<DiscoverItemModel> discoverItemModels;
|
||||
private final View.OnClickListener clickListener;
|
||||
private final View.OnLongClickListener longClickListener;
|
||||
private LayoutInflater layoutInflater;
|
||||
public boolean isSelecting = false;
|
||||
public final class DiscoverAdapter extends MultiSelectListAdapter<DiscoverItemModel, DiscoverViewHolder> {
|
||||
|
||||
public DiscoverAdapter(final ArrayList<DiscoverItemModel> discoverItemModels, final View.OnClickListener clickListener,
|
||||
final View.OnLongClickListener longClickListener) {
|
||||
this.discoverItemModels = discoverItemModels;
|
||||
this.longClickListener = longClickListener;
|
||||
this.clickListener = clickListener;
|
||||
private static final DiffUtil.ItemCallback<DiscoverItemModel> diffCallback = new DiffUtil.ItemCallback<DiscoverItemModel>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull final DiscoverItemModel oldItem, @NonNull final DiscoverItemModel newItem) {
|
||||
return oldItem.getPostId().equals(newItem.getPostId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull final DiscoverItemModel oldItem, @NonNull final DiscoverItemModel newItem) {
|
||||
return oldItem.getPostId().equals(newItem.getPostId());
|
||||
}
|
||||
};
|
||||
|
||||
public DiscoverAdapter(final OnItemClickListener<DiscoverItemModel> clickListener,
|
||||
final OnItemLongClickListener<DiscoverItemModel> longClickListener) {
|
||||
super(diffCallback, clickListener, longClickListener);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DiscoverViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
|
||||
if (layoutInflater == null) layoutInflater = LayoutInflater.from(parent.getContext());
|
||||
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
|
||||
return new DiscoverViewHolder(layoutInflater.inflate(R.layout.item_post, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final DiscoverViewHolder holder, final int position) {
|
||||
final DiscoverItemModel itemModel = discoverItemModels.get(position);
|
||||
final DiscoverItemModel itemModel = getItem(position);
|
||||
if (itemModel != null) {
|
||||
itemModel.setPosition(position);
|
||||
holder.itemView.setTag(itemModel);
|
||||
|
||||
holder.itemView.setOnClickListener(clickListener);
|
||||
holder.itemView.setOnLongClickListener(longClickListener);
|
||||
|
||||
holder.itemView.setOnClickListener(v -> internalOnItemClickListener.onItemClick(itemModel, position));
|
||||
holder.itemView.setOnLongClickListener(v -> internalOnLongItemClickListener.onItemLongClick(itemModel, position));
|
||||
final MediaItemType mediaType = itemModel.getItemType();
|
||||
|
||||
holder.typeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO || mediaType == MediaItemType.MEDIA_TYPE_SLIDER
|
||||
? View.VISIBLE : View.GONE);
|
||||
|
||||
holder.typeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO || mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
|
||||
holder.typeIcon.setImageResource(mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? R.drawable.slider : R.drawable.video);
|
||||
|
||||
holder.selectedView.setVisibility(itemModel.isSelected() ? View.VISIBLE : View.GONE);
|
||||
holder.progressView.setVisibility(View.VISIBLE);
|
||||
|
||||
Glide.with(layoutInflater.getContext()).load(itemModel.getDisplayUrl()).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target<Drawable> target, final boolean isFirstResource) {
|
||||
holder.progressView.setVisibility(View.GONE);
|
||||
return false;
|
||||
holder.postImage.setImageURI(itemModel.getDisplayUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(final Drawable resource, final Object model, final Target<Drawable> target, final DataSource dataSource, final boolean isFirstResource) {
|
||||
holder.progressView.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
}).into(holder.postImage);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return discoverItemModels == null ? 0 : discoverItemModels.size();
|
||||
}
|
||||
}
|
@ -9,9 +9,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.ListAdapter;
|
||||
|
||||
import com.bumptech.glide.RequestManager;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
|
||||
import awais.instagrabber.adapters.viewholder.feed.FeedItemViewHolder;
|
||||
import awais.instagrabber.adapters.viewholder.feed.FeedPhotoViewHolder;
|
||||
import awais.instagrabber.adapters.viewholder.feed.FeedSliderViewHolder;
|
||||
@ -27,11 +24,8 @@ import awais.instagrabber.utils.Utils;
|
||||
|
||||
public final class FeedAdapter extends ListAdapter<FeedModel, FeedItemViewHolder> {
|
||||
private static final String TAG = "FeedAdapter";
|
||||
// private final static String ellipsize = "… more";
|
||||
private final RequestManager glide;
|
||||
private final View.OnClickListener clickListener;
|
||||
private final MentionClickListener mentionClickListener;
|
||||
public SimpleExoPlayer pagerPlayer;
|
||||
private final View.OnLongClickListener longClickListener = v -> {
|
||||
final Object tag;
|
||||
if (v instanceof RamboTextView && (tag = v.getTag()) instanceof FeedModel)
|
||||
@ -51,11 +45,10 @@ public final class FeedAdapter extends ListAdapter<FeedModel, FeedItemViewHolder
|
||||
}
|
||||
};
|
||||
|
||||
public FeedAdapter(final RequestManager glide,
|
||||
final View.OnClickListener clickListener,
|
||||
public FeedAdapter(final View.OnClickListener clickListener,
|
||||
final MentionClickListener mentionClickListener) {
|
||||
super(diffCallback);
|
||||
this.glide = glide;
|
||||
// private final static String ellipsize = "… more";
|
||||
this.clickListener = clickListener;
|
||||
this.mentionClickListener = mentionClickListener;
|
||||
}
|
||||
@ -78,7 +71,7 @@ public final class FeedAdapter extends ListAdapter<FeedModel, FeedItemViewHolder
|
||||
default:
|
||||
case MEDIA_TYPE_IMAGE: {
|
||||
final ItemFeedPhotoBinding binding = ItemFeedPhotoBinding.inflate(layoutInflater, parent, false);
|
||||
return new FeedPhotoViewHolder(binding, glide, mentionClickListener, clickListener, longClickListener);
|
||||
return new FeedPhotoViewHolder(binding, mentionClickListener, clickListener, longClickListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +1,51 @@
|
||||
package awais.instagrabber.adapters;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.ListAdapter;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.viewholder.HighlightViewHolder;
|
||||
import awais.instagrabber.databinding.ItemHighlightBinding;
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
|
||||
public final class FeedStoriesAdapter extends RecyclerView.Adapter<HighlightViewHolder> {
|
||||
private final View.OnClickListener clickListener;
|
||||
private LayoutInflater layoutInflater;
|
||||
private FeedStoryModel[] feedStoryModels;
|
||||
public final class FeedStoriesAdapter extends ListAdapter<FeedStoryModel, HighlightViewHolder> {
|
||||
private final OnFeedStoryClickListener listener;
|
||||
|
||||
public FeedStoriesAdapter(final FeedStoryModel[] feedStoryModels, final View.OnClickListener clickListener) {
|
||||
this.feedStoryModels = feedStoryModels;
|
||||
this.clickListener = clickListener;
|
||||
private static final DiffUtil.ItemCallback<FeedStoryModel> diffCallback = new DiffUtil.ItemCallback<FeedStoryModel>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull final FeedStoryModel oldItem, @NonNull final FeedStoryModel newItem) {
|
||||
return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull final FeedStoryModel oldItem, @NonNull final FeedStoryModel newItem) {
|
||||
return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId());
|
||||
}
|
||||
};
|
||||
|
||||
public FeedStoriesAdapter(final OnFeedStoryClickListener listener) {
|
||||
super(diffCallback);
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public HighlightViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
|
||||
if (layoutInflater == null) layoutInflater = LayoutInflater.from(parent.getContext());
|
||||
return new HighlightViewHolder(layoutInflater.inflate(R.layout.item_highlight, parent, false));
|
||||
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
|
||||
final ItemHighlightBinding binding = ItemHighlightBinding.inflate(layoutInflater, parent, false);
|
||||
return new HighlightViewHolder(binding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final HighlightViewHolder holder, final int position) {
|
||||
final FeedStoryModel feedStoryModel = feedStoryModels[position];
|
||||
if (feedStoryModel != null) {
|
||||
holder.itemView.setTag(feedStoryModel);
|
||||
holder.itemView.setOnClickListener(clickListener);
|
||||
final ProfileModel profileModel = feedStoryModel.getProfileModel();
|
||||
holder.title.setText(profileModel.getUsername());
|
||||
holder.icon.setImageURI(profileModel.getSdProfilePic());
|
||||
holder.icon.setAlpha(feedStoryModel.getFullyRead() ? 0.5F : 1.0F);
|
||||
holder.title.setAlpha(feedStoryModel.getFullyRead() ? 0.5F : 1.0F);
|
||||
}
|
||||
final FeedStoryModel model = getItem(position);
|
||||
holder.bind(model, position, listener);
|
||||
}
|
||||
|
||||
public void setData(final FeedStoryModel[] feedStoryModels) {
|
||||
this.feedStoryModels = feedStoryModels;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return feedStoryModels == null ? 0 : feedStoryModels.length;
|
||||
public interface OnFeedStoryClickListener {
|
||||
void onFeedStoryClick(FeedStoryModel model, int position);
|
||||
}
|
||||
}
|
||||
|
@ -27,18 +27,19 @@ public final class HighlightsAdapter extends RecyclerView.Adapter<HighlightViewH
|
||||
@Override
|
||||
public HighlightViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
|
||||
if (layoutInflater == null) layoutInflater = LayoutInflater.from(parent.getContext());
|
||||
return new HighlightViewHolder(layoutInflater.inflate(R.layout.item_highlight, parent, false));
|
||||
// return new HighlightViewHolder(layoutInflater.inflate(R.layout.item_highlight, parent, false));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final HighlightViewHolder holder, final int position) {
|
||||
final HighlightModel highlightModel = highlightModels[position];
|
||||
if (highlightModel != null) {
|
||||
holder.itemView.setTag(highlightModel);
|
||||
holder.itemView.setOnClickListener(clickListener);
|
||||
holder.title.setText(highlightModel.getTitle());
|
||||
Glide.with(holder.itemView).load(highlightModel.getThumbnailUrl()).into(holder.icon);
|
||||
}
|
||||
// final HighlightModel highlightModel = highlightModels[position];
|
||||
// if (highlightModel != null) {
|
||||
// holder.itemView.setTag(highlightModel);
|
||||
// holder.itemView.setOnClickListener(clickListener);
|
||||
// holder.title.setText(highlightModel.getTitle());
|
||||
// Glide.with(holder.itemView).load(highlightModel.getThumbnailUrl()).into(holder.icon);
|
||||
// }
|
||||
}
|
||||
|
||||
public void setData(final HighlightModel[] highlightModels) {
|
||||
|
@ -0,0 +1,106 @@
|
||||
package awais.instagrabber.adapters;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.AsyncDifferConfig;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.ListAdapter;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class MultiSelectListAdapter<T extends MultiSelectListAdapter.Selectable, VH extends RecyclerView.ViewHolder> extends ListAdapter<T, VH> {
|
||||
|
||||
private boolean isSelecting = false;
|
||||
private OnItemClickListener<T> clickListener;
|
||||
private OnItemLongClickListener<T> longClickListener;
|
||||
|
||||
private final List<T> selectedItems = new ArrayList<>();
|
||||
protected final OnItemClickListener<T> internalOnItemClickListener = (item, position) -> {
|
||||
if (isSelecting) {
|
||||
toggleSelection(item, position);
|
||||
}
|
||||
if (clickListener == null) {
|
||||
return;
|
||||
}
|
||||
clickListener.onItemClick(item, position);
|
||||
};
|
||||
protected final OnItemLongClickListener<T> internalOnLongItemClickListener = (item, position) -> {
|
||||
if (!isSelecting) {
|
||||
isSelecting = true;
|
||||
}
|
||||
toggleSelection(item, position);
|
||||
if (longClickListener == null) {
|
||||
return true;
|
||||
}
|
||||
return longClickListener.onItemLongClick(item, position);
|
||||
};
|
||||
|
||||
protected MultiSelectListAdapter(@NonNull final DiffUtil.ItemCallback<T> diffCallback,
|
||||
final OnItemClickListener<T> clickListener,
|
||||
final OnItemLongClickListener<T> longClickListener) {
|
||||
super(diffCallback);
|
||||
this.clickListener = clickListener;
|
||||
this.longClickListener = longClickListener;
|
||||
}
|
||||
|
||||
protected MultiSelectListAdapter(@NonNull final AsyncDifferConfig<T> config,
|
||||
final OnItemClickListener<T> clickListener,
|
||||
final OnItemLongClickListener<T> longClickListener) {
|
||||
super(config);
|
||||
this.clickListener = clickListener;
|
||||
this.longClickListener = longClickListener;
|
||||
}
|
||||
|
||||
private void toggleSelection(final T item, final int position) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
if (selectedItems.size() >= 100) {
|
||||
// Toast.makeText(mainActivity, R.string.downloader_too_many, Toast.LENGTH_SHORT);
|
||||
return;
|
||||
}
|
||||
if (item.isSelected()) {
|
||||
item.setSelected(false);
|
||||
selectedItems.remove(item);
|
||||
} else {
|
||||
item.setSelected(true);
|
||||
selectedItems.add(item);
|
||||
}
|
||||
if (selectedItems.size() == 0) {
|
||||
isSelecting = false;
|
||||
}
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
|
||||
public boolean isSelecting() {
|
||||
return isSelecting;
|
||||
}
|
||||
|
||||
public List<T> getSelectedModels() {
|
||||
return selectedItems;
|
||||
}
|
||||
|
||||
public void clearSelection() {
|
||||
for (final T item : selectedItems) {
|
||||
item.setSelected(false);
|
||||
}
|
||||
selectedItems.clear();
|
||||
isSelecting = false;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public interface Selectable {
|
||||
boolean isSelected();
|
||||
|
||||
void setSelected(boolean selected);
|
||||
}
|
||||
|
||||
public interface OnItemClickListener<T> {
|
||||
void onItemClick(T item, int position);
|
||||
}
|
||||
|
||||
public interface OnItemLongClickListener<T> {
|
||||
boolean onItemLongClick(T item, int position);
|
||||
}
|
||||
}
|
@ -1,92 +1,45 @@
|
||||
package awais.instagrabber.adapters;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
|
||||
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 java.util.ArrayList;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.viewholder.PostViewHolder;
|
||||
import awais.instagrabber.databinding.ItemPostBinding;
|
||||
import awais.instagrabber.models.PostModel;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
|
||||
public final class PostsAdapter extends RecyclerView.Adapter<PostViewHolder> {
|
||||
private final ArrayList<PostModel> postModels;
|
||||
private final View.OnClickListener clickListener;
|
||||
private final View.OnLongClickListener longClickListener;
|
||||
private LayoutInflater layoutInflater;
|
||||
public boolean isSelecting = false;
|
||||
public final class PostsAdapter extends MultiSelectListAdapter<PostModel, PostViewHolder> {
|
||||
|
||||
public PostsAdapter(final ArrayList<PostModel> postModels, final View.OnClickListener clickListener,
|
||||
final View.OnLongClickListener longClickListener) {
|
||||
this.postModels = postModels;
|
||||
this.clickListener = clickListener;
|
||||
this.longClickListener = longClickListener;
|
||||
private static final DiffUtil.ItemCallback<PostModel> diffCallback = new DiffUtil.ItemCallback<PostModel>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull final PostModel oldItem, @NonNull final PostModel newItem) {
|
||||
return oldItem.getPostId().equals(newItem.getPostId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull final PostModel oldItem, @NonNull final PostModel newItem) {
|
||||
return oldItem.getPostId().equals(newItem.getPostId());
|
||||
}
|
||||
};
|
||||
|
||||
public PostsAdapter(final OnItemClickListener<PostModel> clickListener,
|
||||
final OnItemLongClickListener<PostModel> longClickListener) {
|
||||
super(diffCallback, clickListener, longClickListener);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public PostViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
|
||||
if (layoutInflater == null) layoutInflater = LayoutInflater.from(parent.getContext());
|
||||
return new PostViewHolder(layoutInflater.inflate(R.layout.item_post, parent, false));
|
||||
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
|
||||
final ItemPostBinding binding = ItemPostBinding.inflate(layoutInflater, parent, false);
|
||||
return new PostViewHolder(binding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final PostViewHolder holder, final int position) {
|
||||
final PostModel postModel = postModels.get(position);
|
||||
if (postModel != null) {
|
||||
postModel.setPosition(position);
|
||||
|
||||
holder.itemView.setTag(postModel);
|
||||
|
||||
holder.itemView.setOnClickListener(clickListener);
|
||||
holder.itemView.setOnLongClickListener(longClickListener);
|
||||
|
||||
final MediaItemType itemType = postModel.getItemType();
|
||||
final boolean isSlider = itemType == MediaItemType.MEDIA_TYPE_SLIDER;
|
||||
|
||||
holder.isDownloaded.setVisibility(postModel.isDownloaded() ? View.VISIBLE : View.GONE);
|
||||
|
||||
holder.typeIcon.setVisibility(itemType == MediaItemType.MEDIA_TYPE_VIDEO || isSlider ? View.VISIBLE : View.GONE);
|
||||
holder.typeIcon.setImageResource(isSlider ? R.drawable.slider : R.drawable.video);
|
||||
|
||||
holder.selectedView.setVisibility(postModel.isSelected() ? View.VISIBLE : View.GONE);
|
||||
holder.progressView.setVisibility(View.VISIBLE);
|
||||
|
||||
final RequestManager glideRequestManager = Glide.with(holder.postImage);
|
||||
|
||||
glideRequestManager.load(postModel.getThumbnailUrl()).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onResourceReady(final Drawable resource, final Object model, final Target<Drawable> target, final DataSource dataSource, final boolean isFirstResource) {
|
||||
holder.progressView.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target<Drawable> target, final boolean isFirstResource) {
|
||||
holder.progressView.setVisibility(View.GONE);
|
||||
// glideRequestManager.load(postModel.getDisplayUrl()).into(holder.postImage);
|
||||
return false;
|
||||
}
|
||||
}).into(holder.postImage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return postModels == null ? 0 : postModels.size();
|
||||
final PostModel postModel = getItem(position);
|
||||
holder.bind(postModel, position, internalOnItemClickListener, internalOnLongItemClickListener);
|
||||
}
|
||||
}
|
||||
|
@ -1,84 +1,80 @@
|
||||
package awais.instagrabber.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.ListAdapter;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.databinding.ItemStoryBinding;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
|
||||
public final class StoriesAdapter extends RecyclerView.Adapter<StoriesAdapter.StoryViewHolder> {
|
||||
private final View.OnClickListener clickListener;
|
||||
private LayoutInflater layoutInflater;
|
||||
private StoryModel[] storyModels;
|
||||
private Resources resources;
|
||||
private int width, height;
|
||||
public final class StoriesAdapter extends ListAdapter<StoryModel, StoriesAdapter.StoryViewHolder> {
|
||||
private final OnItemClickListener onItemClickListener;
|
||||
|
||||
public StoriesAdapter(final StoryModel[] storyModels, final View.OnClickListener clickListener) {
|
||||
this.storyModels = storyModels;
|
||||
this.clickListener = clickListener;
|
||||
private static final DiffUtil.ItemCallback<StoryModel> diffCallback = new DiffUtil.ItemCallback<StoryModel>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull final StoryModel oldItem, @NonNull final StoryModel newItem) {
|
||||
return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull final StoryModel oldItem, @NonNull final StoryModel newItem) {
|
||||
return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId());
|
||||
}
|
||||
};
|
||||
|
||||
public StoriesAdapter(final OnItemClickListener onItemClickListener) {
|
||||
super(diffCallback);
|
||||
this.onItemClickListener = onItemClickListener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public StoryViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
|
||||
final Context context = parent.getContext();
|
||||
if (layoutInflater == null) layoutInflater = LayoutInflater.from(context);
|
||||
if (resources == null) resources = context.getResources();
|
||||
|
||||
height = Math.round(resources.getDimension(R.dimen.story_item_height));
|
||||
width = Math.round(resources.getDimension(R.dimen.story_item_width));
|
||||
|
||||
return new StoryViewHolder(layoutInflater.inflate(R.layout.item_story, parent, false));
|
||||
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
|
||||
final ItemStoryBinding binding = ItemStoryBinding.inflate(layoutInflater, parent, false);
|
||||
return new StoryViewHolder(binding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final StoryViewHolder holder, final int position) {
|
||||
final StoryModel storyModel = storyModels[position];
|
||||
if (storyModel != null) {
|
||||
storyModel.setPosition(position);
|
||||
|
||||
holder.itemView.setTag(storyModel);
|
||||
holder.itemView.setOnClickListener(clickListener);
|
||||
|
||||
holder.selectedView.setVisibility(storyModel.isCurrentSlide() ? View.VISIBLE : View.GONE);
|
||||
|
||||
Glide.with(holder.itemView).load(storyModel.getStoryUrl())
|
||||
.apply(new RequestOptions().override(width, height))
|
||||
.into(holder.icon);
|
||||
}
|
||||
}
|
||||
|
||||
public void setData(final StoryModel[] storyModels) {
|
||||
this.storyModels = storyModels;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public StoryModel getItemAt(final int position) {
|
||||
return storyModels == null ? null : storyModels[position];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return storyModels == null ? 0 : storyModels.length;
|
||||
final StoryModel storyModel = getItem(position);
|
||||
holder.bind(storyModel, position, onItemClickListener);
|
||||
}
|
||||
|
||||
public final static class StoryViewHolder extends RecyclerView.ViewHolder {
|
||||
public final ImageView icon, selectedView;
|
||||
private final ItemStoryBinding binding;
|
||||
|
||||
public StoryViewHolder(@NonNull final View itemView) {
|
||||
super(itemView);
|
||||
selectedView = itemView.findViewById(R.id.selectedView);
|
||||
icon = itemView.findViewById(R.id.icon);
|
||||
public StoryViewHolder(final ItemStoryBinding binding) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
}
|
||||
|
||||
public void bind(final StoryModel model,
|
||||
final int position,
|
||||
final OnItemClickListener clickListener) {
|
||||
if (model == null) return;
|
||||
model.setPosition(position);
|
||||
|
||||
itemView.setTag(model);
|
||||
itemView.setOnClickListener(v -> {
|
||||
if (clickListener == null) return;
|
||||
clickListener.onItemClick(model, position);
|
||||
});
|
||||
|
||||
binding.selectedView.setVisibility(model.isCurrentSlide() ? View.VISIBLE : View.GONE);
|
||||
binding.icon.setImageURI(model.getStoryUrl());
|
||||
// Glide.with(itemView).load(model.getStoryUrl())
|
||||
// .apply(new RequestOptions().override(width, height))
|
||||
// .into(holder.icon);
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onItemClick(StoryModel storyModel, int position);
|
||||
}
|
||||
}
|
@ -6,17 +6,21 @@ import android.widget.ImageView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
|
||||
public final class DiscoverViewHolder extends RecyclerView.ViewHolder {
|
||||
public final ImageView postImage, typeIcon;
|
||||
public final View selectedView, progressView;
|
||||
public final SimpleDraweeView postImage;
|
||||
public final ImageView typeIcon;
|
||||
public final View selectedView;
|
||||
// public final View progressView;
|
||||
|
||||
public DiscoverViewHolder(@NonNull final View itemView) {
|
||||
super(itemView);
|
||||
typeIcon = itemView.findViewById(R.id.typeIcon);
|
||||
postImage = itemView.findViewById(R.id.postImage);
|
||||
selectedView = itemView.findViewById(R.id.selectedView);
|
||||
progressView = itemView.findViewById(R.id.progressView);
|
||||
// progressView = itemView.findViewById(R.id.progressView);
|
||||
}
|
||||
}
|
@ -1,22 +1,33 @@
|
||||
package awais.instagrabber.adapters.viewholder;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.customviews.CircularImageView;
|
||||
import awais.instagrabber.adapters.FeedStoriesAdapter;
|
||||
import awais.instagrabber.databinding.ItemHighlightBinding;
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
|
||||
public final class HighlightViewHolder extends RecyclerView.ViewHolder {
|
||||
public final CircularImageView icon;
|
||||
public final TextView title;
|
||||
|
||||
public HighlightViewHolder(@NonNull final View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.icon);
|
||||
title = itemView.findViewById(R.id.title);
|
||||
private final ItemHighlightBinding binding;
|
||||
|
||||
public HighlightViewHolder(final ItemHighlightBinding binding) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
}
|
||||
|
||||
public void bind(final FeedStoryModel model,
|
||||
final int position,
|
||||
final FeedStoriesAdapter.OnFeedStoryClickListener listener) {
|
||||
if (model == null) return;
|
||||
binding.getRoot().setOnClickListener(v -> {
|
||||
if (listener == null) return;
|
||||
listener.onFeedStoryClick(model, position);
|
||||
});
|
||||
final ProfileModel profileModel = model.getProfileModel();
|
||||
binding.title.setText(profileModel.getUsername());
|
||||
binding.title.setAlpha(model.getFullyRead() ? 0.5F : 1.0F);
|
||||
binding.icon.setImageURI(profileModel.getSdProfilePic());
|
||||
binding.icon.setAlpha(model.getFullyRead() ? 0.5F : 1.0F);
|
||||
}
|
||||
}
|
@ -1,23 +1,43 @@
|
||||
package awais.instagrabber.adapters.viewholder;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.MultiSelectListAdapter.OnItemClickListener;
|
||||
import awais.instagrabber.adapters.MultiSelectListAdapter.OnItemLongClickListener;
|
||||
import awais.instagrabber.databinding.ItemPostBinding;
|
||||
import awais.instagrabber.models.PostModel;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
|
||||
public final class PostViewHolder extends RecyclerView.ViewHolder {
|
||||
public final ImageView postImage, typeIcon;
|
||||
public final View selectedView, progressView, isDownloaded;
|
||||
private final ItemPostBinding binding;
|
||||
|
||||
public PostViewHolder(@NonNull final View itemView) {
|
||||
super(itemView);
|
||||
typeIcon = itemView.findViewById(R.id.typeIcon);
|
||||
postImage = itemView.findViewById(R.id.postImage);
|
||||
isDownloaded = itemView.findViewById(R.id.isDownloaded);
|
||||
selectedView = itemView.findViewById(R.id.selectedView);
|
||||
progressView = itemView.findViewById(R.id.progressView);
|
||||
public PostViewHolder(@NonNull final ItemPostBinding binding) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
}
|
||||
|
||||
public void bind(final PostModel postModel,
|
||||
final int position,
|
||||
final OnItemClickListener<PostModel> clickListener,
|
||||
final OnItemLongClickListener<PostModel> longClickListener) {
|
||||
if (postModel == null) return;
|
||||
postModel.setPosition(position);
|
||||
itemView.setOnClickListener(v -> clickListener.onItemClick(postModel, position));
|
||||
itemView.setOnLongClickListener(v -> longClickListener.onItemLongClick(postModel, position));
|
||||
|
||||
final MediaItemType itemType = postModel.getItemType();
|
||||
final boolean isSlider = itemType == MediaItemType.MEDIA_TYPE_SLIDER;
|
||||
|
||||
binding.isDownloaded.setVisibility(postModel.isDownloaded() ? View.VISIBLE : View.GONE);
|
||||
|
||||
binding.typeIcon.setVisibility(itemType == MediaItemType.MEDIA_TYPE_VIDEO || isSlider ? View.VISIBLE : View.GONE);
|
||||
binding.typeIcon.setImageResource(isSlider ? R.drawable.slider : R.drawable.video);
|
||||
|
||||
binding.selectedView.setVisibility(postModel.isSelected() ? View.VISIBLE : View.GONE);
|
||||
binding.postImage.setImageURI(postModel.getThumbnailUrl());
|
||||
}
|
||||
}
|
@ -11,8 +11,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.RequestManager;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
@ -31,8 +29,6 @@ public abstract class FeedItemViewHolder extends RecyclerView.ViewHolder {
|
||||
private final ItemFeedBottomBinding bottomBinding;
|
||||
private final MentionClickListener mentionClickListener;
|
||||
|
||||
boolean captionExpanded = false;
|
||||
|
||||
public FeedItemViewHolder(@NonNull final View root,
|
||||
final ItemFeedTopBinding topBinding,
|
||||
final ItemFeedBottomBinding bottomBinding,
|
||||
@ -64,9 +60,6 @@ public abstract class FeedItemViewHolder extends RecyclerView.ViewHolder {
|
||||
bottomBinding.btnComments.setTag(feedModel);
|
||||
final ProfileModel profileModel = feedModel.getProfileModel();
|
||||
if (profileModel != null) {
|
||||
// glide.load(profileModel.getSdProfilePic())
|
||||
// .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
|
||||
// .into(topBinding.ivProfilePic);
|
||||
topBinding.ivProfilePic.setImageURI(profileModel.getSdProfilePic());
|
||||
final int titleLen = profileModel.getUsername().length() + 1;
|
||||
final SpannableString spannableString = new SpannableString("@" + profileModel.getUsername());
|
||||
|
@ -1,14 +1,11 @@
|
||||
package awais.instagrabber.adapters.viewholder.feed;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.net.Uri;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.bumptech.glide.RequestManager;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.drawee.drawable.ScalingUtils;
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchy;
|
||||
@ -25,22 +22,15 @@ public class FeedPhotoViewHolder extends FeedItemViewHolder {
|
||||
private static final String TAG = "FeedPhotoViewHolder";
|
||||
|
||||
private final ItemFeedPhotoBinding binding;
|
||||
private final RequestManager glide;
|
||||
private final ColorDrawable drawable;
|
||||
// private final PipelineDraweeControllerBuilder controllerBuilder;
|
||||
// private final CustomTarget<Bitmap> customTarget;
|
||||
|
||||
public FeedPhotoViewHolder(@NonNull final ItemFeedPhotoBinding binding,
|
||||
final RequestManager glide,
|
||||
final MentionClickListener mentionClickListener,
|
||||
final View.OnClickListener clickListener,
|
||||
final View.OnLongClickListener longClickListener) {
|
||||
super(binding.getRoot(), binding.itemFeedTop, binding.itemFeedBottom, mentionClickListener, clickListener, longClickListener);
|
||||
this.binding = binding;
|
||||
this.glide = glide;
|
||||
binding.itemFeedBottom.videoViewsContainer.setVisibility(View.GONE);
|
||||
binding.itemFeedBottom.btnMute.setVisibility(View.GONE);
|
||||
drawable = new ColorDrawable(Color.WHITE);
|
||||
binding.imageViewer.setAllowTouchInterceptionWhileZoomed(false);
|
||||
final GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(itemView.getContext().getResources())
|
||||
.setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER)
|
||||
@ -50,15 +40,13 @@ public class FeedPhotoViewHolder extends FeedItemViewHolder {
|
||||
|
||||
@Override
|
||||
public void bindItem(final FeedModel feedModel) {
|
||||
// glide.clear(customTarget);
|
||||
if (feedModel == null) {
|
||||
return;
|
||||
}
|
||||
final ViewGroup.LayoutParams layoutParams = binding.imageViewer.getLayoutParams();
|
||||
final int requiredWidth = Utils.displayMetrics.widthPixels;
|
||||
final int resultingHeight = Utils.getResultingHeight(requiredWidth, feedModel.getImageHeight(), feedModel.getImageWidth());
|
||||
layoutParams.width = requiredWidth;
|
||||
layoutParams.height = resultingHeight;
|
||||
layoutParams.width = feedModel.getImageWidth() == 0 ? requiredWidth : feedModel.getImageWidth();
|
||||
layoutParams.height = feedModel.getImageHeight() == 0 ? requiredWidth + 1 : feedModel.getImageHeight();
|
||||
binding.imageViewer.requestLayout();
|
||||
final String thumbnailUrl = feedModel.getThumbnailUrl();
|
||||
String url = feedModel.getDisplayUrl();
|
||||
|
@ -151,14 +151,14 @@ public class FeedSliderViewHolder extends FeedItemViewHolder {
|
||||
final SimpleExoPlayer player = (SimpleExoPlayer) tag;
|
||||
final float intVol = player.getVolume() == 0f ? 1f : 0f;
|
||||
player.setVolume(intVol);
|
||||
binding.itemFeedBottom.btnMute.setImageResource(intVol == 0f ? R.drawable.vol : R.drawable.mute);
|
||||
binding.itemFeedBottom.btnMute.setImageResource(intVol == 0f ? R.drawable.ic_volume_up_24 : R.drawable.ic_volume_off_24);
|
||||
Utils.sessionVolumeFull = intVol == 1f;
|
||||
};
|
||||
final ViewerPostModel firstItem = sliderItems[0];
|
||||
if (firstItem.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO) {
|
||||
binding.itemFeedBottom.btnMute.setVisibility(View.VISIBLE);
|
||||
}
|
||||
binding.itemFeedBottom.btnMute.setImageResource(Utils.sessionVolumeFull ? R.drawable.mute : R.drawable.vol);
|
||||
binding.itemFeedBottom.btnMute.setImageResource(Utils.sessionVolumeFull ? R.drawable.ic_volume_off_24 : R.drawable.ic_volume_up_24);
|
||||
binding.itemFeedBottom.btnMute.setOnClickListener(muteClickListener);
|
||||
}
|
||||
|
||||
|
@ -74,8 +74,9 @@ public class FeedVideoViewHolder extends FeedItemViewHolder {
|
||||
|
||||
private void setThumbnail(final FeedModel feedModel) {
|
||||
final ViewGroup.LayoutParams layoutParams = binding.thumbnailParent.getLayoutParams();
|
||||
layoutParams.width = feedModel.getImageWidth();
|
||||
layoutParams.height = feedModel.getImageHeight();
|
||||
final int requiredWidth = Utils.displayMetrics.widthPixels;
|
||||
layoutParams.width = feedModel.getImageWidth() == 0 ? requiredWidth : feedModel.getImageWidth();
|
||||
layoutParams.height = feedModel.getImageHeight() == 0 ? requiredWidth + 1 : feedModel.getImageHeight();
|
||||
binding.thumbnailParent.requestLayout();
|
||||
final ImageRequest thumbnailRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(feedModel.getThumbnailUrl()))
|
||||
.setProgressiveRenderingEnabled(true)
|
||||
@ -131,7 +132,7 @@ public class FeedVideoViewHolder extends FeedItemViewHolder {
|
||||
}
|
||||
|
||||
private void setMuteIcon(final float vol) {
|
||||
binding.itemFeedBottom.btnMute.setImageResource(vol == 0f ? R.drawable.vol : R.drawable.mute);
|
||||
binding.itemFeedBottom.btnMute.setImageResource(vol == 0f ? R.drawable.ic_volume_up_24 : R.drawable.ic_volume_off_24);
|
||||
}
|
||||
|
||||
public FeedModel getCurrentFeedModel() {
|
||||
|
@ -0,0 +1,81 @@
|
||||
package awais.instagrabber.asyncs;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public class CommentAction extends AsyncTask<String, Void, String> {
|
||||
private static final String TAG = "CommentAction";
|
||||
|
||||
private final String cookie;
|
||||
private final StoryModel storyModel;
|
||||
private final OnTaskCompleteListener onTaskCompleteListener;
|
||||
|
||||
public CommentAction(final String cookie, final StoryModel storyModel, final OnTaskCompleteListener onTaskCompleteListener) {
|
||||
this.cookie = cookie;
|
||||
this.storyModel = storyModel;
|
||||
this.onTaskCompleteListener = onTaskCompleteListener;
|
||||
}
|
||||
|
||||
protected String doInBackground(String... rawAction) {
|
||||
final String action = rawAction[0];
|
||||
final String url = "https://i.instagram.com/api/v1/direct_v2/create_group_thread/";
|
||||
HttpURLConnection urlConnection = null;
|
||||
try {
|
||||
urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
||||
urlConnection.setUseCaches(false);
|
||||
final String urlParameters = Utils.sign("{\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0]
|
||||
+ "\",\"_uid\":\"" + Utils.getUserIdFromCookie(cookie)
|
||||
+ "\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID)
|
||||
+ "\",\"recipient_users\":\"[" + storyModel.getUserId() // <- string of array of number (not joking)
|
||||
+ "]\"}");
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
if (urlParameters != null) {
|
||||
urlConnection.setRequestProperty("Content-Length", "" + urlParameters.getBytes().length);
|
||||
}
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
urlConnection.connect();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
return new JSONObject(Utils.readFromConnection(urlConnection)).getString("thread_id");
|
||||
}
|
||||
|
||||
} catch (Throwable ex) {
|
||||
Log.e(TAG, "reply (CT): " + ex);
|
||||
// Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
} finally {
|
||||
if (urlConnection != null) {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final String threadId) {
|
||||
if (threadId == null || onTaskCompleteListener == null) {
|
||||
return;
|
||||
}
|
||||
onTaskCompleteListener.onTaskComplete(threadId);
|
||||
}
|
||||
|
||||
public interface OnTaskCompleteListener {
|
||||
void onTaskComplete(final String threadId);
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
|
||||
public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
private static final String TAG = "PostsFetcher";
|
||||
private final String endCursor;
|
||||
private final String id;
|
||||
private final FetchListener<PostModel[]> fetchListener;
|
||||
@ -60,13 +61,13 @@ public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
"{\"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.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 + "\"}";
|
||||
"{\"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 + "\"}";
|
||||
"{\"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;
|
||||
|
||||
@ -79,15 +80,16 @@ public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
// to check if file exists
|
||||
final File downloadDir = new File(Environment.getExternalStorageDirectory(), "Download" +
|
||||
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/"+username) : ""));
|
||||
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/" + username) : ""));
|
||||
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")
|
||||
final JSONObject mediaPosts = new JSONObject(Utils.readFromConnection(conn))
|
||||
.getJSONObject("data")
|
||||
.getJSONObject(isHashTag ? Constants.EXTRAS_HASHTAG :
|
||||
(isLocation ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_USER))
|
||||
.getJSONObject(isHashTag ? "edge_hashtag_to_media" :
|
||||
@ -131,7 +133,7 @@ public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
Utils.checkExistence(downloadDir, customDir, isSlider, models[i]);
|
||||
}
|
||||
|
||||
if (models[models.length - 1] != null)
|
||||
if (models.length != 0 && models[models.length - 1] != null)
|
||||
models[models.length - 1].setPageCursor(hasNextPage, endCursor);
|
||||
|
||||
result = models;
|
||||
@ -141,7 +143,7 @@ public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
} catch (Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.ASYNC_MAIN_POSTS_FETCHER, "doInBackground");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
88
app/src/main/java/awais/instagrabber/asyncs/QuizAction.java
Normal file
@ -0,0 +1,88 @@
|
||||
package awais.instagrabber.asyncs;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.stickers.QuizModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public class QuizAction extends AsyncTask<Integer, Void, Integer> {
|
||||
private static final String TAG = "QuizAction";
|
||||
|
||||
private final StoryModel storyModel;
|
||||
private final QuizModel quizModel;
|
||||
private final String cookie;
|
||||
private final OnTaskCompleteListener onTaskCompleteListener;
|
||||
|
||||
public QuizAction(final StoryModel storyModel,
|
||||
final QuizModel quizModel,
|
||||
final String cookie,
|
||||
final OnTaskCompleteListener onTaskCompleteListener) {
|
||||
this.storyModel = storyModel;
|
||||
this.quizModel = quizModel;
|
||||
this.cookie = cookie;
|
||||
this.onTaskCompleteListener = onTaskCompleteListener;
|
||||
}
|
||||
|
||||
protected Integer doInBackground(Integer... rawChoice) {
|
||||
int choice = rawChoice[0];
|
||||
final String url = "https://i.instagram.com/api/v1/media/" + storyModel.getStoryMediaId().split("_")[0] + "/" + quizModel.getId() + "/story_quiz_answer/";
|
||||
HttpURLConnection urlConnection = null;
|
||||
try {
|
||||
JSONObject ogBody = new JSONObject("{\"client_context\":\"" + UUID.randomUUID().toString()
|
||||
+ "\",\"mutation_token\":\"" + UUID.randomUUID().toString()
|
||||
+ "\",\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0]
|
||||
+ "\",\"_uid\":\"" + Utils.getUserIdFromCookie(cookie)
|
||||
+ "\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID)
|
||||
+ "\"}");
|
||||
ogBody.put("answer", String.valueOf(choice));
|
||||
String urlParameters = Utils.sign(ogBody.toString());
|
||||
urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
if (urlParameters != null) {
|
||||
urlConnection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
|
||||
}
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
Log.d(TAG, "quiz: " + url + " " + cookie + " " + urlParameters);
|
||||
urlConnection.connect();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
return choice;
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Log.e(TAG, "quiz: " + ex);
|
||||
} finally {
|
||||
if (urlConnection != null) {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Integer choice) {
|
||||
if (onTaskCompleteListener == null || choice == null) return;
|
||||
onTaskCompleteListener.onTaskComplete(choice);
|
||||
}
|
||||
|
||||
public interface OnTaskCompleteListener {
|
||||
void onTaskComplete(final int choice);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package awais.instagrabber.asyncs;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public class RespondAction extends AsyncTask<String, Void, Boolean> {
|
||||
|
||||
private final StoryModel storyModel;
|
||||
private final QuestionModel questionModel;
|
||||
private final String cookie;
|
||||
private final OnTaskCompleteListener onTaskCompleteListener;
|
||||
|
||||
public RespondAction(final StoryModel storyModel,
|
||||
final QuestionModel questionModel,
|
||||
final String cookie,
|
||||
final OnTaskCompleteListener onTaskCompleteListener) {
|
||||
this.storyModel = storyModel;
|
||||
this.questionModel = questionModel;
|
||||
this.cookie = cookie;
|
||||
this.onTaskCompleteListener = onTaskCompleteListener;
|
||||
}
|
||||
|
||||
protected Boolean doInBackground(String... rawChoice) {
|
||||
final String url = "https://i.instagram.com/api/v1/media/"
|
||||
+ storyModel.getStoryMediaId().split("_")[0] + "/" + questionModel.getId() + "/story_question_response/";
|
||||
HttpURLConnection urlConnection = null;
|
||||
try {
|
||||
JSONObject ogbody = new JSONObject("{\"client_context\":\"" + UUID.randomUUID().toString()
|
||||
+ "\",\"mutation_token\":\"" + UUID.randomUUID().toString()
|
||||
+ "\",\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0]
|
||||
+ "\",\"_uid\":\"" + Utils.getUserIdFromCookie(cookie)
|
||||
+ "\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID)
|
||||
+ "\"}");
|
||||
String choice = rawChoice[0].replaceAll("\"", ("\\\""));
|
||||
ogbody.put("response", choice);
|
||||
String urlParameters = Utils.sign(ogbody.toString());
|
||||
urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
urlConnection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
urlConnection.connect();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
return true;
|
||||
}
|
||||
|
||||
} catch (Throwable ex) {
|
||||
Log.e("austin_debug", "respond: " + ex);
|
||||
} finally {
|
||||
if (urlConnection != null) {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Boolean ok) {
|
||||
if (onTaskCompleteListener == null) return;
|
||||
onTaskCompleteListener.onTaskComplete(ok);
|
||||
|
||||
}
|
||||
|
||||
public interface OnTaskCompleteListener {
|
||||
void onTaskComplete(final boolean result);
|
||||
}
|
||||
}
|
51
app/src/main/java/awais/instagrabber/asyncs/SeenAction.java
Normal file
@ -0,0 +1,51 @@
|
||||
package awais.instagrabber.asyncs;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
public class SeenAction extends AsyncTask<Void, Void, Void> {
|
||||
private static final String TAG = "SeenAction";
|
||||
|
||||
private final String cookie;
|
||||
private final StoryModel storyModel;
|
||||
|
||||
public SeenAction(final String cookie, final StoryModel storyModel) {
|
||||
this.cookie = cookie;
|
||||
this.storyModel = storyModel;
|
||||
}
|
||||
|
||||
protected Void doInBackground(Void... voids) {
|
||||
final String url = "https://www.instagram.com/stories/reel/seen";
|
||||
try {
|
||||
String urlParameters = "reelMediaId=" + storyModel.getStoryMediaId().split("_")[0]
|
||||
+ "&reelMediaOwnerId=" + storyModel.getUserId()
|
||||
+ "&reelId=" + storyModel.getUserId()
|
||||
+ "&reelMediaTakenAt=" + storyModel.getTimestamp()
|
||||
+ "&viewSeenAt=" + storyModel.getTimestamp();
|
||||
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("x-csrftoken", cookie.split("csrftoken=")[1].split(";")[0]);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
urlConnection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
urlConnection.connect();
|
||||
Log.d(TAG, urlConnection.getResponseCode() + " " + Utils.readFromConnection(urlConnection));
|
||||
urlConnection.disconnect();
|
||||
} catch (Throwable ex) {
|
||||
Log.e(TAG, "Error", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
69
app/src/main/java/awais/instagrabber/asyncs/VoteAction.java
Normal file
@ -0,0 +1,69 @@
|
||||
package awais.instagrabber.asyncs;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.stickers.PollModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
|
||||
public class VoteAction extends AsyncTask<Integer, Void, Integer> {
|
||||
|
||||
private static final String TAG = "VoteAction";
|
||||
|
||||
private final StoryModel storyModel;
|
||||
private final PollModel pollModel;
|
||||
private final String cookie;
|
||||
private final OnTaskCompleteListener onTaskCompleteListener;
|
||||
|
||||
public VoteAction(final StoryModel storyModel,
|
||||
final PollModel pollModel,
|
||||
final String cookie,
|
||||
final OnTaskCompleteListener onTaskCompleteListener) {
|
||||
this.storyModel = storyModel;
|
||||
this.pollModel = pollModel;
|
||||
this.cookie = cookie;
|
||||
this.onTaskCompleteListener = onTaskCompleteListener;
|
||||
}
|
||||
|
||||
protected Integer doInBackground(Integer... rawChoice) {
|
||||
int choice = rawChoice[0];
|
||||
final String url = "https://www.instagram.com/media/" + storyModel.getStoryMediaId().split("_")[0] + "/" + pollModel.getId() + "/story_poll_vote/";
|
||||
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", cookie.split("csrftoken=")[1].split(";")[0]);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
urlConnection.setRequestProperty("Content-Length", "6");
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes("vote=" + choice);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
urlConnection.connect();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
return choice;
|
||||
}
|
||||
urlConnection.disconnect();
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG, "Error", ex);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Integer result) {
|
||||
if (result == null || onTaskCompleteListener == null) return;
|
||||
onTaskCompleteListener.onTaskComplete(result);
|
||||
}
|
||||
|
||||
public interface OnTaskCompleteListener {
|
||||
void onTaskComplete(final int choice);
|
||||
}
|
||||
}
|
@ -25,11 +25,18 @@ import static awais.instagrabber.utils.Utils.logCollector;
|
||||
public final class iStoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[]> {
|
||||
private final String id;
|
||||
private String username;
|
||||
private final boolean isLoc, isHashtag, storiesig, highlight;
|
||||
private final boolean isLoc;
|
||||
private final boolean isHashtag;
|
||||
private final boolean storiesig;
|
||||
private final boolean highlight;
|
||||
private final FetchListener<StoryModel[]> fetchListener;
|
||||
|
||||
public iStoryStatusFetcher(final String id, final String username, final boolean isLoc,
|
||||
final boolean isHashtag, final boolean storiesig, final boolean highlight,
|
||||
public iStoryStatusFetcher(final String id,
|
||||
final String username,
|
||||
final boolean isLoc,
|
||||
final boolean isHashtag,
|
||||
final boolean storiesig,
|
||||
final boolean highlight,
|
||||
final FetchListener<StoryModel[]> fetchListener) {
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
@ -43,9 +50,35 @@ public final class iStoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[
|
||||
@Override
|
||||
protected StoryModel[] doInBackground(final Void... voids) {
|
||||
StoryModel[] result = null;
|
||||
final String url = "https://" + (storiesig ? "storiesig" : "i.instagram") + ".com/api/v1/"
|
||||
+ (isLoc ? "locations/" : (isHashtag ? "tags/" : (highlight ? "feed/reels_media?user_ids=" : "feed/user/")))
|
||||
+ id.replace(":", "%3A") + (highlight ? "" : (storiesig ? "/reel_media/" : "/story/"));
|
||||
final String userId = id.replace(":", "%3A");
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("https://");
|
||||
if (storiesig) {
|
||||
builder.append("storiesig");
|
||||
} else {
|
||||
builder.append("i.instagram");
|
||||
}
|
||||
builder.append(".com/api/v1/");
|
||||
if (isLoc) {
|
||||
builder.append("locations/");
|
||||
}
|
||||
if (isHashtag) {
|
||||
builder.append("tags/");
|
||||
}
|
||||
if (highlight) {
|
||||
builder.append("feed/reels_media?user_ids=");
|
||||
} else {
|
||||
builder.append("feed/user/");
|
||||
}
|
||||
builder.append(userId);
|
||||
if (!highlight) {
|
||||
if (storiesig) {
|
||||
builder.append("/reel_media/");
|
||||
} else {
|
||||
builder.append("/story/");
|
||||
}
|
||||
}
|
||||
final String url = builder.toString();
|
||||
try {
|
||||
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
conn.setInstanceFollowRedirects(true);
|
||||
@ -55,10 +88,12 @@ public final class iStoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[
|
||||
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
JSONObject data = new JSONObject(Utils.readFromConnection(conn));
|
||||
if (!storiesig && !highlight) data = data.optJSONObject((isLoc || isHashtag) ? "story" : "reel");
|
||||
if (!storiesig && !highlight)
|
||||
data = data.optJSONObject((isLoc || isHashtag) ? "story" : "reel");
|
||||
else if (highlight) data = data.getJSONObject("reels").optJSONObject(id);
|
||||
|
||||
if (username == null && !isLoc && !isHashtag) username = data.getJSONObject("user").getString("username");
|
||||
if (username == null && !isLoc && !isHashtag)
|
||||
username = data.getJSONObject("user").getString("username");
|
||||
|
||||
JSONArray media;
|
||||
if (data != null && (media = data.optJSONArray("items")) != null
|
||||
@ -117,7 +152,7 @@ public final class iStoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[
|
||||
for (int q = 0; q < choices.length; ++q) {
|
||||
JSONObject tempchoice = tappableObject.getJSONArray("tallies").getJSONObject(q);
|
||||
choices[q] = (q == tappableObject.getInt("correct_answer") ? "*** " : "")
|
||||
+tempchoice.getString("text");
|
||||
+ tempchoice.getString("text");
|
||||
counts[q] = tempchoice.getLong("count");
|
||||
}
|
||||
models[i].setQuiz(new QuizModel(
|
||||
@ -137,20 +172,20 @@ public final class iStoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[
|
||||
+ (locations == null ? 0 : locations.length())];
|
||||
if (hashtags != null) {
|
||||
for (int h = 0; h < hashtags.length(); ++h) {
|
||||
mentions[h] = "#"+hashtags.getJSONObject(h).getJSONObject("hashtag").getString("name");
|
||||
mentions[h] = "#" + hashtags.getJSONObject(h).getJSONObject("hashtag").getString("name");
|
||||
}
|
||||
}
|
||||
if (atmarks != null) {
|
||||
for (int h = 0; h < atmarks.length(); ++h) {
|
||||
mentions[h + (hashtags == null ? 0 : hashtags.length())] =
|
||||
"@"+atmarks.getJSONObject(h).getJSONObject("user").getString("username");
|
||||
"@" + atmarks.getJSONObject(h).getJSONObject("user").getString("username");
|
||||
}
|
||||
}
|
||||
if (locations != null) {
|
||||
for (int h = 0; h < locations.length(); ++h) {
|
||||
mentions[h + (hashtags == null ? 0 : hashtags.length()) + (atmarks == null ? 0 : atmarks.length())] =
|
||||
locations.getJSONObject(h).getJSONObject("location").getLong("pk")
|
||||
+"/ ("+locations.getJSONObject(h).getJSONObject("location").getString("short_name")+")";
|
||||
+ "/ (" + locations.getJSONObject(h).getJSONObject("location").getString("short_name") + ")";
|
||||
}
|
||||
}
|
||||
if (mentions.length != 0) models[i].setMentions(mentions);
|
||||
|
@ -0,0 +1,71 @@
|
||||
package awais.instagrabber.customviews;
|
||||
|
||||
import android.view.ActionMode;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
public class PrimaryActionModeCallback implements ActionMode.Callback {
|
||||
private ActionMode mode;
|
||||
private int menuRes;
|
||||
private final Callbacks callbacks;
|
||||
|
||||
public PrimaryActionModeCallback(final int menuRes, final Callbacks callbacks) {
|
||||
this.menuRes = menuRes;
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(final ActionMode mode, final Menu menu) {
|
||||
this.mode = mode;
|
||||
mode.getMenuInflater().inflate(menuRes, menu);
|
||||
if (callbacks != null) {
|
||||
callbacks.onCreate(mode, menu);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(final ActionMode mode, final Menu menu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
|
||||
if (callbacks != null) {
|
||||
return callbacks.onActionItemClicked(mode, item);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(final ActionMode mode) {
|
||||
if (callbacks != null) {
|
||||
callbacks.onDestroy(mode);
|
||||
}
|
||||
this.mode = null;
|
||||
}
|
||||
|
||||
public abstract static class CallbacksHelper implements Callbacks {
|
||||
public void onCreate(final ActionMode mode, final Menu menu) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(final ActionMode mode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public interface Callbacks {
|
||||
void onCreate(final ActionMode mode, final Menu menu);
|
||||
|
||||
void onDestroy(final ActionMode mode);
|
||||
|
||||
boolean onActionItemClicked(final ActionMode mode, final MenuItem item);
|
||||
}
|
||||
}
|
@ -33,6 +33,8 @@ import com.facebook.drawee.generic.GenericDraweeHierarchyInflater;
|
||||
import com.facebook.drawee.interfaces.DraweeController;
|
||||
import com.facebook.drawee.view.DraweeView;
|
||||
|
||||
import awais.instagrabber.customviews.helpers.SwipeGestureListener;
|
||||
|
||||
|
||||
/**
|
||||
* DraweeView that has zoomable capabilities.
|
||||
|
@ -0,0 +1,33 @@
|
||||
package awais.instagrabber.customviews.helpers;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.google.android.material.behavior.HideBottomViewOnScrollBehavior;
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
|
||||
public class CustomHideBottomViewOnScrollBehavior extends HideBottomViewOnScrollBehavior<BottomNavigationView> {
|
||||
private static final String TAG = "CustomHideBottomView";
|
||||
|
||||
@Override
|
||||
public boolean onStartNestedScroll(@NonNull final CoordinatorLayout coordinatorLayout,
|
||||
@NonNull final BottomNavigationView child,
|
||||
@NonNull final View directTargetChild,
|
||||
@NonNull final View target,
|
||||
final int nestedScrollAxes,
|
||||
final int type) {
|
||||
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNestedPreScroll(@NonNull final CoordinatorLayout coordinatorLayout, @NonNull final BottomNavigationView child, @NonNull final View target, final int dx, final int dy, @NonNull final int[] consumed, final int type) {
|
||||
if (dy > 0) {
|
||||
slideDown(child);
|
||||
} else if (dy < 0) {
|
||||
slideUp(child);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
package awais.instagrabber.customviews.helpers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.core.view.NestedScrollingChild;
|
||||
import androidx.core.view.NestedScrollingChildHelper;
|
||||
|
||||
public class NestedCoordinatorLayout extends CoordinatorLayout implements NestedScrollingChild {
|
||||
|
||||
private NestedScrollingChildHelper mChildHelper;
|
||||
|
||||
public NestedCoordinatorLayout(Context context) {
|
||||
super(context);
|
||||
mChildHelper = new NestedScrollingChildHelper(this);
|
||||
setNestedScrollingEnabled(true);
|
||||
}
|
||||
|
||||
public NestedCoordinatorLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mChildHelper = new NestedScrollingChildHelper(this);
|
||||
setNestedScrollingEnabled(true);
|
||||
}
|
||||
|
||||
public NestedCoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mChildHelper = new NestedScrollingChildHelper(this);
|
||||
setNestedScrollingEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed, int type) {
|
||||
int[][] tConsumed = new int[2][2];
|
||||
super.onNestedPreScroll(target, dx, dy, consumed, type);
|
||||
dispatchNestedPreScroll(dx, dy, tConsumed[1], null);
|
||||
consumed[0] = tConsumed[0][0] + tConsumed[1][0];
|
||||
consumed[1] = tConsumed[0][1] + tConsumed[1][1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
|
||||
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
|
||||
dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopNestedScroll(View target, int type) {
|
||||
/* Disable the scrolling behavior of our own children */
|
||||
super.onStopNestedScroll(target, type);
|
||||
/* Disable the scrolling behavior of the parent's other children */
|
||||
stopNestedScroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes, int type) {
|
||||
/* Enable the scrolling behavior of our own children */
|
||||
boolean tHandled = super.onStartNestedScroll(child, target, nestedScrollAxes, type);
|
||||
/* Enable the scrolling behavior of the parent's other children */
|
||||
return startNestedScroll(nestedScrollAxes) || tHandled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
|
||||
/* Enable the scrolling behavior of our own children */
|
||||
boolean tHandled = super.onStartNestedScroll(child, target, nestedScrollAxes);
|
||||
/* Enable the scrolling behavior of the parent's other children */
|
||||
return startNestedScroll(nestedScrollAxes) || tHandled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopNestedScroll(View target) {
|
||||
/* Disable the scrolling behavior of our own children */
|
||||
super.onStopNestedScroll(target);
|
||||
/* Disable the scrolling behavior of the parent's other children */
|
||||
stopNestedScroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
|
||||
int[][] tConsumed = new int[2][2];
|
||||
super.onNestedPreScroll(target, dx, dy, tConsumed[0]);
|
||||
dispatchNestedPreScroll(dx, dy, tConsumed[1], null);
|
||||
consumed[0] = tConsumed[0][0] + tConsumed[1][0];
|
||||
consumed[1] = tConsumed[0][1] + tConsumed[1][1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
|
||||
int dxUnconsumed, int dyUnconsumed) {
|
||||
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
|
||||
dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
|
||||
boolean tHandled = super.onNestedPreFling(target, velocityX, velocityY);
|
||||
return dispatchNestedPreFling(velocityX, velocityY) || tHandled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
|
||||
boolean tHandled = super.onNestedFling(target, velocityX, velocityY, consumed);
|
||||
return dispatchNestedFling(velocityX, velocityY, consumed) || tHandled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNestedScrollingEnabled() {
|
||||
return mChildHelper.isNestedScrollingEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNestedScrollingEnabled(boolean enabled) {
|
||||
mChildHelper.setNestedScrollingEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startNestedScroll(int axes) {
|
||||
return mChildHelper.startNestedScroll(axes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopNestedScroll() {
|
||||
mChildHelper.stopNestedScroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNestedScrollingParent() {
|
||||
return mChildHelper.hasNestedScrollingParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
|
||||
int dyUnconsumed, int[] offsetInWindow) {
|
||||
return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed,
|
||||
dyUnconsumed, offsetInWindow);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
|
||||
return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
|
||||
return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
|
||||
return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.activities.MainActivity;
|
||||
import awais.instagrabber.activities.MainActivityBackup;
|
||||
import awais.instagrabber.adapters.SimpleAdapter;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
@ -112,8 +113,8 @@ public final class QuickAccessDialog extends BottomSheetDialogFragment implement
|
||||
else Utils.showImportExportDialog(v.getContext());
|
||||
|
||||
} else if (tag instanceof DataBox.FavoriteModel) {
|
||||
if (MainActivity.scanHack != null) {
|
||||
MainActivity.scanHack.onResult(((DataBox.FavoriteModel) tag).getQuery());
|
||||
if (MainActivityBackup.scanHack != null) {
|
||||
MainActivityBackup.scanHack.onResult(((DataBox.FavoriteModel) tag).getQuery());
|
||||
dismiss();
|
||||
}
|
||||
|
||||
|
@ -62,24 +62,24 @@ public final class MultiDirectDialog extends BaseLanguageActivity {
|
||||
postModel.getSliderDisplayUrl(), postModel.getShortCode(), postModel.getPostCaption(), postModel.getTimestamp(),
|
||||
postModel.getLike(), postModel.getBookmark(), postModel.getLikes()));
|
||||
|
||||
postsAdapter = new PostsAdapter(models, v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof PostModel) {
|
||||
final PostModel postModel = (PostModel) tag;
|
||||
if (postsAdapter.isSelecting) toggleSelection(postModel);
|
||||
else {
|
||||
Utils.batchDownload(this, username, DownloadMethod.DOWNLOAD_DIRECT, Collections.singletonList(postModel));
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}, v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof PostModel) {
|
||||
postsAdapter.isSelecting = true;
|
||||
toggleSelection((PostModel) tag);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
// postsAdapter = new PostsAdapter(models, v -> {
|
||||
// final Object tag = v.getTag();
|
||||
// if (tag instanceof PostModel) {
|
||||
// final PostModel postModel = (PostModel) tag;
|
||||
// if (postsAdapter.isSelecting) toggleSelection(postModel);
|
||||
// else {
|
||||
// Utils.batchDownload(this, username, DownloadMethod.DOWNLOAD_DIRECT, Collections.singletonList(postModel));
|
||||
// finish();
|
||||
// }
|
||||
// }
|
||||
// }, v -> {
|
||||
// final Object tag = v.getTag();
|
||||
// if (tag instanceof PostModel) {
|
||||
// postsAdapter.isSelecting = true;
|
||||
// toggleSelection((PostModel) tag);
|
||||
// }
|
||||
// return true;
|
||||
// });
|
||||
|
||||
recyclerView.setAdapter(postsAdapter);
|
||||
}
|
||||
@ -109,10 +109,10 @@ public final class MultiDirectDialog extends BaseLanguageActivity {
|
||||
}
|
||||
|
||||
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 (btnDownload != null) btnDownload.setVisible(postsAdapter.isSelecting);
|
||||
// if (selectedItems.size() < 1) postsAdapter.isSelecting = false;
|
||||
// if (postModel.getPosition() < 0) postsAdapter.notifyDataSetChanged();
|
||||
// else postsAdapter.notifyItemChanged(postModel.getPosition(), postModel);
|
||||
//
|
||||
// if (btnDownload != null) btnDownload.setVisible(postsAdapter.isSelecting);
|
||||
}
|
||||
}
|
@ -0,0 +1,673 @@
|
||||
package awais.instagrabber.fragments;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.GestureDetectorCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.drawee.controller.BaseControllerListener;
|
||||
import com.facebook.drawee.interfaces.DraweeController;
|
||||
import com.facebook.imagepipeline.image.ImageInfo;
|
||||
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.MediaSource;
|
||||
import com.google.android.exoplayer2.source.MediaSourceEventListener;
|
||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
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;
|
||||
import awais.instagrabber.asyncs.QuizAction;
|
||||
import awais.instagrabber.asyncs.RespondAction;
|
||||
import awais.instagrabber.asyncs.SeenAction;
|
||||
import awais.instagrabber.asyncs.VoteAction;
|
||||
import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster;
|
||||
import awais.instagrabber.customviews.helpers.SwipeGestureListener;
|
||||
import awais.instagrabber.databinding.ActivityStoryViewerBinding;
|
||||
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;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
import awais.instagrabber.models.stickers.QuizModel;
|
||||
import awais.instagrabber.services.ServiceCallback;
|
||||
import awais.instagrabber.services.StoriesService;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import awaisomereport.LogCollector;
|
||||
|
||||
import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_THRESHOLD;
|
||||
import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD;
|
||||
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
||||
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
||||
import static awais.instagrabber.utils.Constants.MARK_AS_SEEN;
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public class StoryViewerFragment extends Fragment {
|
||||
private static final String TAG = "StoryViewerFragment";
|
||||
|
||||
private AppCompatActivity fragmentActivity;
|
||||
private View root;
|
||||
private ActivityStoryViewerBinding binding;
|
||||
private String currentStoryUsername;
|
||||
private StoriesAdapter storiesAdapter;
|
||||
private SwipeEvent swipeEvent;
|
||||
private GestureDetectorCompat gestureDetector;
|
||||
private StoriesService storiesService;
|
||||
private List<FeedStoryModel> feedStoryModels;
|
||||
private StoryModel currentStory;
|
||||
private int slidePos;
|
||||
private int lastSlidePos;
|
||||
private String url;
|
||||
private PollModel poll;
|
||||
private QuestionModel question;
|
||||
private String[] mentions;
|
||||
private QuizModel quiz;
|
||||
private MenuItem menuDownload;
|
||||
private MenuItem menuDm;
|
||||
private SimpleExoPlayer player;
|
||||
private boolean isHashtag;
|
||||
private String highlight;
|
||||
private boolean fetching = false;
|
||||
private int currentFeedStoryIndex;
|
||||
private StoriesViewModel storiesViewModel;
|
||||
private String currentStoryMediaId;
|
||||
|
||||
private final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
private StoryViewerFragmentArgs fragmentArgs;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = (AppCompatActivity) requireActivity();
|
||||
storiesService = StoriesService.getInstance();
|
||||
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 = ActivityStoryViewerBinding.inflate(inflater, container, false);
|
||||
root = binding.getRoot();
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(@NonNull final Menu menu, final MenuInflater menuInflater) {
|
||||
menuInflater.inflate(R.menu.story_menu, menu);
|
||||
menuDownload = menu.findItem(R.id.action_download);
|
||||
menuDm = menu.findItem(R.id.action_dms);
|
||||
menuDownload.setVisible(false);
|
||||
menuDm.setVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(@NonNull final Menu menu) {
|
||||
// hide menu items from activity
|
||||
final MenuItem item = menu.findItem(R.id.favourites);
|
||||
if (item != null) {
|
||||
item.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_download:
|
||||
if (ContextCompat.checkSelfPermission(requireContext(), Utils.PERMS[0]) == PackageManager.PERMISSION_GRANTED)
|
||||
downloadStory();
|
||||
else
|
||||
ActivityCompat.requestPermissions(requireActivity(), Utils.PERMS, 8020);
|
||||
return true;
|
||||
case R.id.action_dms:
|
||||
final EditText input = new EditText(requireContext());
|
||||
input.setHint(R.string.reply_hint);
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.reply_story)
|
||||
.setView(input)
|
||||
.setPositiveButton(R.string.ok, (d, w) -> new CommentAction(cookie, currentStory, threadId -> {
|
||||
try {
|
||||
final DirectThreadBroadcaster.StoryReplyBroadcastOptions options = new DirectThreadBroadcaster.StoryReplyBroadcastOptions(
|
||||
input.getText().toString(),
|
||||
currentStory.getStoryMediaId(),
|
||||
currentStory.getUserId()
|
||||
);
|
||||
final DirectThreadBroadcaster broadcast = new DirectThreadBroadcaster(threadId);
|
||||
broadcast.setOnTaskCompleteListener(result -> Toast.makeText(
|
||||
requireContext(),
|
||||
result != null ? R.string.answered_story : R.string.downloader_unknown_error,
|
||||
Toast.LENGTH_SHORT
|
||||
).show());
|
||||
broadcast.execute(options);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.e(TAG, "Error", e);
|
||||
}
|
||||
}).execute())
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@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)
|
||||
downloadStory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
releasePlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
releasePlayer();
|
||||
// reset subtitle
|
||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setSubtitle(null);
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
final FeedStoriesViewModel feedStoriesViewModel = new ViewModelProvider(fragmentActivity).get(FeedStoriesViewModel.class);
|
||||
feedStoryModels = feedStoriesViewModel.getList().getValue();
|
||||
if (feedStoryModels == null || feedStoryModels.isEmpty() || getArguments() == null) return;
|
||||
fragmentArgs = StoryViewerFragmentArgs.fromBundle(getArguments());
|
||||
currentFeedStoryIndex = fragmentArgs.getFeedStoryIndex();
|
||||
setupStories();
|
||||
}
|
||||
|
||||
private void setupStories() {
|
||||
storiesViewModel = new ViewModelProvider(this).get(StoriesViewModel.class);
|
||||
setupListeners();
|
||||
binding.storiesList.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||
storiesAdapter = new StoriesAdapter((model, position) -> {
|
||||
currentStory = model;
|
||||
slidePos = position;
|
||||
refreshStory();
|
||||
});
|
||||
binding.storiesList.setAdapter(storiesAdapter);
|
||||
storiesViewModel.getList().observe(fragmentActivity, storiesAdapter::submitList);
|
||||
resetView();
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private void setupListeners() {
|
||||
swipeEvent = isRightSwipe -> {
|
||||
final List<StoryModel> storyModels = storiesViewModel.getList().getValue();
|
||||
final int storiesLen = storyModels == null ? 0 : storyModels.size();
|
||||
if (storiesLen <= 0) return;
|
||||
final boolean hasFeedStories = feedStoryModels != null && !feedStoryModels.isEmpty();
|
||||
final boolean isLeftSwipe = !isRightSwipe;
|
||||
final boolean endOfCurrentStories = slidePos + 1 >= storiesLen;
|
||||
final boolean swipingBeyondCurrentStories = (endOfCurrentStories && isLeftSwipe) || (slidePos == 0 && isRightSwipe);
|
||||
if (swipingBeyondCurrentStories && hasFeedStories) {
|
||||
final int index = currentFeedStoryIndex;
|
||||
if (settingsHelper.getBoolean(MARK_AS_SEEN)) {
|
||||
new SeenAction(cookie, currentStory).execute();
|
||||
}
|
||||
if ((isRightSwipe && index == 0) || (isLeftSwipe && index == feedStoryModels.size() - 1)) {
|
||||
Toast.makeText(requireContext(), R.string.no_more_stories, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
final FeedStoryModel feedStoryModel = isRightSwipe
|
||||
? 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();
|
||||
return;
|
||||
}
|
||||
fetching = true;
|
||||
currentFeedStoryIndex = isRightSwipe ? (index - 1) : (index + 1);
|
||||
resetView();
|
||||
// new iStoryStatusFetcher(feedStoryModel.getStoryMediaId(), null, false, false, false, false, result -> {
|
||||
// if (result != null && result.length > 0) {
|
||||
// final Intent newIntent = new Intent(requireContext(), StoryViewer.class)
|
||||
// .putExtra(Constants.EXTRAS_STORIES, result)
|
||||
// .putExtra(Constants.EXTRAS_USERNAME, feedStoryModel.getProfileModel().getUsername())
|
||||
// .putExtra(Constants.FEED, storyFeed)
|
||||
// .putExtra(Constants.FEED_ORDER, isRightSwipe ? (index - 1) : (index + 1));
|
||||
// newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
// startActivity(newIntent);
|
||||
// } else
|
||||
// Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
// }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (isRightSwipe) {
|
||||
if (--slidePos <= 0) {
|
||||
slidePos = 0;
|
||||
}
|
||||
} else if (++slidePos >= storiesLen) {
|
||||
slidePos = storiesLen - 1;
|
||||
}
|
||||
currentStory = storyModels.get(slidePos);
|
||||
refreshStory();
|
||||
};
|
||||
gestureDetector = new GestureDetectorCompat(requireContext(), new SwipeGestureListener(swipeEvent));
|
||||
binding.playerView.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event));
|
||||
final GestureDetector.SimpleOnGestureListener simpleOnGestureListener = new GestureDetector.SimpleOnGestureListener() {
|
||||
@Override
|
||||
public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, final float velocityY) {
|
||||
final float diffX = e2.getX() - e1.getX();
|
||||
try {
|
||||
if (Math.abs(diffX) > Math.abs(e2.getY() - e1.getY()) && Math.abs(diffX) > SWIPE_THRESHOLD
|
||||
&& Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
|
||||
swipeEvent.onSwipe(diffX > 0);
|
||||
return true;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.ACTIVITY_STORY_VIEWER, "setupListeners",
|
||||
new Pair<>("swipeEvent", swipeEvent),
|
||||
new Pair<>("diffX", diffX));
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "Error", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
binding.imageViewer.setTapListener(simpleOnGestureListener);
|
||||
binding.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);
|
||||
}
|
||||
});
|
||||
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]+$"))));
|
||||
});
|
||||
final View.OnClickListener storyActionListener = v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof PollModel) {
|
||||
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)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show();
|
||||
} else {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle(poll.getQuestion())
|
||||
.setAdapter(new ArrayAdapter<>(requireContext(), android.R.layout.simple_list_item_1, new String[]{
|
||||
poll.getLeftChoice() + " (" + poll.getLeftCount() + ")",
|
||||
poll.getRightChoice() + " (" + poll.getRightCount() + ")"
|
||||
}), (d, w) -> {
|
||||
if (!Utils.isEmpty(cookie))
|
||||
new VoteAction(currentStory, poll, cookie, choice -> {
|
||||
if (choice > -1) {
|
||||
poll.setMyChoice(choice);
|
||||
Toast.makeText(requireContext(), R.string.votef_story_poll, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).execute(w);
|
||||
})
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
} else if (tag instanceof QuestionModel) {
|
||||
question = (QuestionModel) tag;
|
||||
final EditText input = new EditText(requireContext());
|
||||
input.setHint(R.string.answer_hint);
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle(question.getQuestion())
|
||||
.setView(input)
|
||||
.setPositiveButton(R.string.ok, (d, w) -> new RespondAction(currentStory, question, cookie, result -> {
|
||||
if (result) {
|
||||
Toast.makeText(requireContext(), R.string.answered_story, Toast.LENGTH_SHORT).show();
|
||||
} else
|
||||
Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).execute(input.getText().toString()))
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
} else if (tag instanceof String[]) {
|
||||
mentions = (String[]) tag;
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.story_mentions)
|
||||
.setAdapter(new ArrayAdapter<>(requireContext(), android.R.layout.simple_list_item_1, mentions), (d, w) -> {
|
||||
// searchUsername(mentions[w]);
|
||||
})
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
} else if (tag instanceof QuizModel) {
|
||||
String[] choices = new String[quiz.getChoices().length];
|
||||
for (int q = 0; q < choices.length; ++q) {
|
||||
choices[q] = (quiz.getMyChoice() == q ? "√ " : "") + quiz.getChoices()[q] + " (" + quiz.getCounts()[q] + ")";
|
||||
}
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle(quiz.getMyChoice() > -1 ? getString(R.string.story_quizzed) : quiz.getQuestion())
|
||||
.setAdapter(new ArrayAdapter<>(requireContext(), android.R.layout.simple_list_item_1, choices), (d, w) -> {
|
||||
if (quiz.getMyChoice() == -1 && !Utils.isEmpty(cookie))
|
||||
new QuizAction(currentStory, quiz, cookie, choice -> {
|
||||
if (choice > -1) {
|
||||
quiz.setMyChoice(choice);
|
||||
Toast.makeText(requireContext(), R.string.answered_story, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).execute(w);
|
||||
})
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
};
|
||||
binding.poll.setOnClickListener(storyActionListener);
|
||||
binding.answer.setOnClickListener(storyActionListener);
|
||||
binding.mention.setOnClickListener(storyActionListener);
|
||||
binding.quiz.setOnClickListener(storyActionListener);
|
||||
}
|
||||
|
||||
private void resetView() {
|
||||
slidePos = 0;
|
||||
lastSlidePos = 0;
|
||||
if (menuDownload != null) menuDownload.setVisible(false);
|
||||
if (menuDm != null) menuDm.setVisible(false);
|
||||
binding.imageViewer.setController(null);
|
||||
releasePlayer();
|
||||
final FeedStoryModel feedStoryModel = feedStoryModels.get(currentFeedStoryIndex);
|
||||
currentStoryMediaId = feedStoryModel.getStoryMediaId();
|
||||
currentStoryUsername = feedStoryModel.getProfileModel().getUsername();
|
||||
isHashtag = fragmentArgs.getIsHashtag();
|
||||
highlight = fragmentArgs.getHighlight();
|
||||
final boolean hasUsername = !Utils.isEmpty(currentStoryUsername);
|
||||
final boolean hasHighlight = !Utils.isEmpty(highlight);
|
||||
if (hasUsername) {
|
||||
currentStoryUsername = currentStoryUsername.replace("@", "");
|
||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(currentStoryUsername);
|
||||
// actionBar.setOnClickListener(v -> {
|
||||
// searchUsername(username);
|
||||
// });
|
||||
if (hasHighlight) {
|
||||
actionBar.setSubtitle(getString(R.string.title_highlight, highlight));
|
||||
} else {
|
||||
actionBar.setSubtitle(R.string.title_user_story);
|
||||
}
|
||||
}
|
||||
}
|
||||
storiesViewModel.getList().setValue(Collections.emptyList());
|
||||
storiesService.getUserStory(currentStoryMediaId, null, false, false, false, false, new ServiceCallback<List<StoryModel>>() {
|
||||
@Override
|
||||
public void onSuccess(final List<StoryModel> storyModels) {
|
||||
fetching = false;
|
||||
if (storyModels == null || storyModels.isEmpty()) {
|
||||
storiesViewModel.getList().setValue(Collections.emptyList());
|
||||
currentStory = null;
|
||||
binding.storiesList.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
binding.storiesList.setVisibility(View.VISIBLE);
|
||||
storiesViewModel.getList().setValue(storyModels);
|
||||
currentStory = storyModels.get(0);
|
||||
refreshStory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
Log.e(TAG, "Error", t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void refreshStory() {
|
||||
if (binding.storiesList.getVisibility() == View.VISIBLE) {
|
||||
final List<StoryModel> storyModels = storiesViewModel.getList().getValue();
|
||||
if (storyModels != null) {
|
||||
StoryModel item = storyModels.get(lastSlidePos);
|
||||
if (item != null) {
|
||||
item.setCurrentSlide(false);
|
||||
storiesAdapter.notifyItemChanged(lastSlidePos, item);
|
||||
}
|
||||
item = storyModels.get(slidePos);
|
||||
if (item != null) {
|
||||
item.setCurrentSlide(true);
|
||||
storiesAdapter.notifyItemChanged(slidePos, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
lastSlidePos = slidePos;
|
||||
|
||||
final MediaItemType itemType = currentStory.getItemType();
|
||||
|
||||
if (menuDownload != null) menuDownload.setVisible(false);
|
||||
url = itemType == MediaItemType.MEDIA_TYPE_VIDEO ? currentStory.getVideoUrl() : currentStory.getStoryUrl();
|
||||
|
||||
final String shortCode = currentStory.getTappableShortCode();
|
||||
binding.viewStoryPost.setVisibility(shortCode != null ? View.VISIBLE : View.GONE);
|
||||
binding.viewStoryPost.setTag(shortCode);
|
||||
|
||||
final String spotify = currentStory.getSpotify();
|
||||
binding.spotify.setVisibility(spotify != null ? View.VISIBLE : View.GONE);
|
||||
binding.spotify.setTag(spotify);
|
||||
|
||||
poll = currentStory.getPoll();
|
||||
binding.poll.setVisibility(poll != null ? View.VISIBLE : View.GONE);
|
||||
binding.poll.setTag(poll);
|
||||
|
||||
question = currentStory.getQuestion();
|
||||
binding.answer.setVisibility((question != null && !Utils.isEmpty(cookie)) ? View.VISIBLE : View.GONE);
|
||||
binding.answer.setTag(question);
|
||||
|
||||
mentions = currentStory.getMentions();
|
||||
binding.mention.setVisibility((mentions != null && mentions.length > 0) ? View.VISIBLE : View.GONE);
|
||||
binding.mention.setTag(mentions);
|
||||
|
||||
quiz = currentStory.getQuiz();
|
||||
binding.quiz.setVisibility(quiz != null ? View.VISIBLE : View.GONE);
|
||||
binding.quiz.setTag(quiz);
|
||||
|
||||
releasePlayer();
|
||||
if (isHashtag) {
|
||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(currentStory.getUsername() + " (" + currentStoryUsername + ")");
|
||||
}
|
||||
// binding.toolbar.toolbar.setOnClickListener(v -> {
|
||||
// searchUsername(currentStory.getUsername());
|
||||
// });
|
||||
}
|
||||
if (itemType == MediaItemType.MEDIA_TYPE_VIDEO) setupVideo();
|
||||
else setupImage();
|
||||
|
||||
if (Utils.isEmpty(highlight)) {
|
||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setSubtitle(Utils.datetimeParser.format(new Date(currentStory.getTimestamp() * 1000L)));
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsHelper.getBoolean(MARK_AS_SEEN)) new SeenAction(cookie, currentStory).execute();
|
||||
}
|
||||
|
||||
private void downloadStory() {
|
||||
int error = 0;
|
||||
if (currentStory != null) {
|
||||
File dir = new File(Environment.getExternalStorageDirectory(), "Download");
|
||||
|
||||
if (settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
|
||||
final String customPath = settingsHelper.getString(FOLDER_PATH);
|
||||
if (!Utils.isEmpty(customPath)) dir = new File(customPath);
|
||||
}
|
||||
|
||||
if (settingsHelper.getBoolean(Constants.DOWNLOAD_USER_FOLDER) && !Utils.isEmpty(currentStoryUsername))
|
||||
dir = new File(dir, currentStoryUsername);
|
||||
|
||||
if (dir.exists() || dir.mkdirs()) {
|
||||
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;
|
||||
Toast.makeText(requireContext(), toastRes, Toast.LENGTH_SHORT).show();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
|
||||
} else error = 1;
|
||||
} else error = 2;
|
||||
|
||||
if (error == 1)
|
||||
Toast.makeText(requireContext(), R.string.downloader_error_creating_folder, Toast.LENGTH_SHORT).show();
|
||||
else if (error == 2)
|
||||
Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
private void setupImage() {
|
||||
binding.progressView.setVisibility(View.VISIBLE);
|
||||
binding.playerView.setVisibility(View.GONE);
|
||||
binding.imageViewer.setVisibility(View.VISIBLE);
|
||||
final ImageRequest requestBuilder = ImageRequestBuilder.newBuilderWithSource(Uri.parse(url))
|
||||
.setLocalThumbnailPreviewsEnabled(true)
|
||||
.setProgressiveRenderingEnabled(true)
|
||||
.build();
|
||||
final DraweeController controller = Fresco.newDraweeControllerBuilder()
|
||||
.setImageRequest(requestBuilder)
|
||||
.setOldController(binding.imageViewer.getController())
|
||||
.setControllerListener(new BaseControllerListener<ImageInfo>() {
|
||||
@Override
|
||||
public void onFinalImageSet(final String id, final ImageInfo imageInfo, final Animatable animatable) {
|
||||
if (menuDownload != null) {
|
||||
menuDownload.setVisible(true);
|
||||
}
|
||||
if (currentStory.canReply() && menuDm != null && !Utils.isEmpty(cookie)) {
|
||||
menuDm.setVisible(true);
|
||||
}
|
||||
binding.progressView.setVisibility(View.GONE);
|
||||
}
|
||||
})
|
||||
.build();
|
||||
binding.imageViewer.setController(controller);
|
||||
}
|
||||
|
||||
private void setupVideo() {
|
||||
binding.playerView.setVisibility(View.VISIBLE);
|
||||
binding.progressView.setVisibility(View.GONE);
|
||||
binding.imageViewer.setVisibility(View.GONE);
|
||||
binding.imageViewer.setController(null);
|
||||
|
||||
player = new SimpleExoPlayer.Builder(requireContext()).build();
|
||||
binding.playerView.setPlayer(player);
|
||||
player.setPlayWhenReady(settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS));
|
||||
|
||||
final ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(new DefaultDataSourceFactory(requireContext(), "instagram"))
|
||||
.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) {
|
||||
if (menuDownload != null) menuDownload.setVisible(true);
|
||||
if (currentStory.canReply() && menuDm != null && !Utils.isEmpty(cookie))
|
||||
menuDm.setVisible(true);
|
||||
binding.progressView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
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) {
|
||||
if (menuDownload != null) menuDownload.setVisible(false);
|
||||
if (menuDm != null) menuDm.setVisible(false);
|
||||
binding.progressView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
player.prepare(mediaSource);
|
||||
|
||||
binding.playerView.setOnClickListener(v -> {
|
||||
if (player != null) {
|
||||
if (player.getPlaybackState() == Player.STATE_ENDED) player.seekTo(0);
|
||||
player.setPlayWhenReady(player.getPlaybackState() == Player.STATE_ENDED || !player.isPlaying());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void releasePlayer() {
|
||||
if (player == null) return;
|
||||
try { player.stop(true); } catch (Exception ignored) { }
|
||||
try { player.release(); } catch (Exception ignored) { }
|
||||
player = null;
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ import java.util.List;
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.adapters.DirectMessageInboxAdapter;
|
||||
import awais.instagrabber.asyncs.direct_messages.InboxFetcher;
|
||||
import awais.instagrabber.customviews.helpers.NestedCoordinatorLayout;
|
||||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
|
||||
import awais.instagrabber.databinding.FragmentDirectMessagesInboxBinding;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
@ -39,7 +40,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
||||
private static final String TAG = "DirectMessagesInboxFrag";
|
||||
|
||||
private FragmentActivity fragmentActivity;
|
||||
private SwipeRefreshLayout root;
|
||||
private NestedCoordinatorLayout root;
|
||||
private RecyclerView inboxList;
|
||||
private RecyclerLazyLoader lazyLoader;
|
||||
private LinearLayoutManager layoutManager;
|
||||
@ -51,7 +52,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
||||
private final FetchListener<InboxModel> fetchListener = new FetchListener<InboxModel>() {
|
||||
@Override
|
||||
public void doBefore() {
|
||||
root.setRefreshing(true);
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -71,10 +72,11 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
||||
listViewModel.getList().postValue(list);
|
||||
}
|
||||
}
|
||||
root.setRefreshing(false);
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
stopCurrentExecutor();
|
||||
}
|
||||
};
|
||||
private FragmentDirectMessagesInboxBinding binding;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
@ -89,9 +91,9 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
||||
if (root != null) {
|
||||
return root;
|
||||
}
|
||||
final FragmentDirectMessagesInboxBinding binding = FragmentDirectMessagesInboxBinding.inflate(inflater, container, false);
|
||||
binding = FragmentDirectMessagesInboxBinding.inflate(inflater, container, false);
|
||||
root = binding.getRoot();
|
||||
root.setOnRefreshListener(this);
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||
inboxList = binding.inboxList;
|
||||
inboxList.setHasFixedSize(true);
|
||||
layoutManager = new LinearLayoutManager(requireContext());
|
||||
|
@ -50,7 +50,6 @@ import java.util.List;
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.activities.PostViewer;
|
||||
import awais.instagrabber.activities.ProfileViewer;
|
||||
import awais.instagrabber.activities.StoryViewer;
|
||||
import awais.instagrabber.adapters.DirectMessageItemsAdapter;
|
||||
import awais.instagrabber.asyncs.ImageUploader;
|
||||
import awais.instagrabber.asyncs.direct_messages.DirectMessageInboxThreadFetcher;
|
||||
@ -225,21 +224,21 @@ public class DirectMessageThreadFragment extends Fragment {
|
||||
break;
|
||||
case STORY_SHARE:
|
||||
if (directItemModel.getReelShare() != null) {
|
||||
StoryModel sm = new StoryModel(
|
||||
directItemModel.getReelShare().getReelId(),
|
||||
directItemModel.getReelShare().getMedia().getVideoUrl(),
|
||||
directItemModel.getReelShare().getMedia().getMediaType(),
|
||||
directItemModel.getTimestamp(),
|
||||
directItemModel.getReelShare().getReelOwnerName(),
|
||||
String.valueOf(directItemModel.getReelShare().getReelOwnerId()),
|
||||
false
|
||||
);
|
||||
sm.setVideoUrl(directItemModel.getReelShare().getMedia().getVideoUrl());
|
||||
StoryModel[] sms = {sm};
|
||||
startActivity(new Intent(requireContext(), StoryViewer.class)
|
||||
.putExtra(Constants.EXTRAS_USERNAME, directItemModel.getReelShare().getReelOwnerName())
|
||||
.putExtra(Constants.EXTRAS_STORIES, sms)
|
||||
);
|
||||
// StoryModel sm = new StoryModel(
|
||||
// directItemModel.getReelShare().getReelId(),
|
||||
// directItemModel.getReelShare().getMedia().getVideoUrl(),
|
||||
// directItemModel.getReelShare().getMedia().getMediaType(),
|
||||
// directItemModel.getTimestamp(),
|
||||
// directItemModel.getReelShare().getReelOwnerName(),
|
||||
// String.valueOf(directItemModel.getReelShare().getReelOwnerId()),
|
||||
// false
|
||||
// );
|
||||
// sm.setVideoUrl(directItemModel.getReelShare().getMedia().getVideoUrl());
|
||||
// StoryModel[] sms = {sm};
|
||||
// startActivity(new Intent(requireContext(), StoryViewer.class)
|
||||
// .putExtra(Constants.EXTRAS_USERNAME, directItemModel.getReelShare().getReelOwnerName())
|
||||
// .putExtra(Constants.EXTRAS_STORIES, sms)
|
||||
// );
|
||||
} else if (directItemModel.getText() != null && directItemModel.getText().toString().contains("@")) {
|
||||
searchUsername(directItemModel.getText().toString().split("@")[1].split(" ")[0]);
|
||||
}
|
||||
|
@ -0,0 +1,241 @@
|
||||
package awais.instagrabber.fragments.main;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.ActionMode;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.activity.OnBackPressedDispatcher;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
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;
|
||||
import awais.instagrabber.customviews.PrimaryActionModeCallback;
|
||||
import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager;
|
||||
import awais.instagrabber.customviews.helpers.GridSpacingItemDecoration;
|
||||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
|
||||
import awais.instagrabber.databinding.FragmentDiscoverBinding;
|
||||
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 {
|
||||
|
||||
private MainActivity fragmentActivity;
|
||||
private CoordinatorLayout root;
|
||||
private FragmentDiscoverBinding binding;
|
||||
private DiscoverAdapter discoverAdapter;
|
||||
private RecyclerLazyLoader lazyLoader;
|
||||
private boolean discoverHasMore = false;
|
||||
private String[] topicIds;
|
||||
private String rankToken;
|
||||
private String currentTopic;
|
||||
private String discoverEndMaxId;
|
||||
private ActionMode actionMode;
|
||||
private DiscoverItemViewModel discoverItemViewModel;
|
||||
|
||||
private final FetchListener<DiscoverTopicModel> topicFetchListener = new FetchListener<DiscoverTopicModel>() {
|
||||
@Override
|
||||
public void doBefore() {}
|
||||
|
||||
@Override
|
||||
public void onResult(final DiscoverTopicModel result) {
|
||||
if (result != null) {
|
||||
topicIds = result.getIds();
|
||||
rankToken = result.getToken();
|
||||
final ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(
|
||||
requireContext(),
|
||||
android.R.layout.simple_spinner_dropdown_item,
|
||||
result.getNames()
|
||||
);
|
||||
binding.discoverType.setAdapter(spinnerArrayAdapter);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final FetchListener<DiscoverItemModel[]> discoverFetchListener = new FetchListener<DiscoverItemModel[]>() {
|
||||
@Override
|
||||
public void doBefore() {
|
||||
binding.discoverSwipeRefreshLayout.setRefreshing(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(final DiscoverItemModel[] result) {
|
||||
binding.discoverSwipeRefreshLayout.setRefreshing(false);
|
||||
if (result == null || result.length == 0) {
|
||||
Toast.makeText(requireContext(), R.string.discover_empty, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
final List<DiscoverItemModel> current = discoverItemViewModel.getList().getValue();
|
||||
final List<DiscoverItemModel> resultList = Arrays.asList(result);
|
||||
if (current == null) {
|
||||
discoverItemViewModel.getList().postValue(resultList);
|
||||
} else {
|
||||
final List<DiscoverItemModel> currentCopy = new ArrayList<>(current);
|
||||
currentCopy.addAll(resultList);
|
||||
discoverItemViewModel.getList().postValue(currentCopy);
|
||||
}
|
||||
final DiscoverItemModel discoverItemModel = result[result.length - 1];
|
||||
if (discoverItemModel != null) {
|
||||
discoverEndMaxId = discoverItemModel.getNextMaxId();
|
||||
discoverHasMore = discoverItemModel.hasMore();
|
||||
discoverItemModel.setMore(false, null);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
if (discoverAdapter == null) {
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
discoverAdapter.clearSelection();
|
||||
remove();
|
||||
}
|
||||
};
|
||||
private final PrimaryActionModeCallback multiSelectAction = new PrimaryActionModeCallback(
|
||||
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 (discoverAdapter == null) return false;
|
||||
Utils.batchDownload(requireContext(),
|
||||
null,
|
||||
DownloadMethod.DOWNLOAD_DISCOVER,
|
||||
discoverAdapter.getSelectedModels());
|
||||
checkAndResetAction();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = (MainActivity) requireActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater,
|
||||
final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
if (root != null) {
|
||||
return root;
|
||||
}
|
||||
binding = FragmentDiscoverBinding.inflate(inflater, container, false);
|
||||
root = binding.getRoot();
|
||||
setupExplore();
|
||||
return root;
|
||||
}
|
||||
|
||||
private void setupExplore() {
|
||||
discoverItemViewModel = new ViewModelProvider(fragmentActivity).get(DiscoverItemViewModel.class);
|
||||
final GridAutofitLayoutManager layoutManager = new GridAutofitLayoutManager(requireContext(), Utils.convertDpToPx(110));
|
||||
binding.discoverPosts.setLayoutManager(layoutManager);
|
||||
binding.discoverPosts.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4)));
|
||||
new iTopicFetcher(topicFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
binding.discoverType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
|
||||
if (topicIds != null) {
|
||||
currentTopic = topicIds[pos];
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {}
|
||||
});
|
||||
|
||||
binding.discoverSwipeRefreshLayout.setOnRefreshListener(() -> {
|
||||
lazyLoader.resetState();
|
||||
discoverItemViewModel.getList().postValue(Collections.emptyList());
|
||||
new DiscoverFetcher(currentTopic, null, rankToken, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
});
|
||||
|
||||
discoverAdapter = new DiscoverAdapter((model, position) -> {
|
||||
if (discoverAdapter.isSelecting()) {
|
||||
if (actionMode == null) return;
|
||||
final String title = getString(R.string.number_selected, discoverAdapter.getSelectedModels().size());
|
||||
actionMode.setTitle(title);
|
||||
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)));
|
||||
}, (model, position) -> {
|
||||
if (!discoverAdapter.isSelecting()) {
|
||||
checkAndResetAction();
|
||||
return true;
|
||||
}
|
||||
final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher();
|
||||
if (onBackPressedDispatcher.hasEnabledCallbacks()) {
|
||||
return true;
|
||||
}
|
||||
actionMode = fragmentActivity.startActionMode(multiSelectAction);
|
||||
final String title = getString(R.string.number_selected, 1);
|
||||
actionMode.setTitle(title);
|
||||
onBackPressedDispatcher.addCallback(onBackPressedCallback);
|
||||
return true;
|
||||
});
|
||||
binding.discoverPosts.setAdapter(discoverAdapter);
|
||||
discoverItemViewModel.getList().observe(fragmentActivity, discoverAdapter::submitList);
|
||||
lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if (discoverHasMore) {
|
||||
binding.discoverSwipeRefreshLayout.setRefreshing(true);
|
||||
new DiscoverFetcher(currentTopic, discoverEndMaxId, rankToken, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
discoverEndMaxId = null;
|
||||
}
|
||||
});
|
||||
binding.discoverPosts.addOnScrollListener(lazyLoader);
|
||||
}
|
||||
|
||||
private boolean checkAndResetAction() {
|
||||
final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher();
|
||||
if (!onBackPressedDispatcher.hasEnabledCallbacks() || actionMode == null) {
|
||||
return false;
|
||||
}
|
||||
actionMode.finish();
|
||||
actionMode = null;
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,345 @@
|
||||
package awais.instagrabber.fragments.main;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
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.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.NavDirections;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.facebook.common.executors.UiThreadImmediateExecutorService;
|
||||
import com.facebook.datasource.BaseDataSubscriber;
|
||||
import com.facebook.datasource.DataSource;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
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;
|
||||
import awais.instagrabber.asyncs.FeedFetcher;
|
||||
import awais.instagrabber.customviews.RamboTextView;
|
||||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
|
||||
import awais.instagrabber.customviews.helpers.VideoAwareRecyclerScroller;
|
||||
import awais.instagrabber.databinding.FragmentFeedBinding;
|
||||
import awais.instagrabber.fragments.main.viewmodels.FeedStoriesViewModel;
|
||||
import awais.instagrabber.fragments.main.viewmodels.FeedViewModel;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.interfaces.MentionClickListener;
|
||||
import awais.instagrabber.models.BasePostModel;
|
||||
import awais.instagrabber.models.FeedModel;
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
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;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
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 MainActivity fragmentActivity;
|
||||
private CoordinatorLayout root;
|
||||
private FragmentFeedBinding binding;
|
||||
private StoriesService storiesService;
|
||||
private boolean feedHasNextPage = false;
|
||||
private String feedEndCursor = null;
|
||||
private FeedViewModel feedViewModel;
|
||||
private VideoAwareRecyclerScroller videoAwareRecyclerScroller;
|
||||
|
||||
private final FetchListener<FeedModel[]> feedFetchListener = new FetchListener<FeedModel[]>() {
|
||||
@Override
|
||||
public void doBefore() {
|
||||
binding.feedSwipeRefreshLayout.post(() -> binding.feedSwipeRefreshLayout.setRefreshing(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(final FeedModel[] result) {
|
||||
if (result == null) return;
|
||||
final List<FeedModel> currentFeedModelList = feedViewModel.getList().getValue();
|
||||
final Map<String, FeedModel> thumbToFeedMap = new HashMap<>();
|
||||
for (final FeedModel feedModel : result) {
|
||||
thumbToFeedMap.put(feedModel.getThumbnailUrl(), feedModel);
|
||||
}
|
||||
final BaseDataSubscriber<Void> subscriber = new BaseDataSubscriber<Void>() {
|
||||
int success = 0;
|
||||
int failed = 0;
|
||||
|
||||
@Override
|
||||
protected void onNewResultImpl(@NonNull final DataSource<Void> dataSource) {
|
||||
final Map<String, Object> extras = dataSource.getExtras();
|
||||
if (extras == null) return;
|
||||
final Uri thumbUri = (Uri) extras.get("uri_source");
|
||||
if (thumbUri == null) return;
|
||||
final Integer encodedWidth = (Integer) extras.get("encoded_width");
|
||||
final Integer encodedHeight = (Integer) extras.get("encoded_height");
|
||||
if (encodedWidth == null || encodedHeight == null) return;
|
||||
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) {
|
||||
// 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);
|
||||
}
|
||||
feedModel.setImageWidth(requiredWidth);
|
||||
feedModel.setImageHeight(resultingHeight);
|
||||
success++;
|
||||
updateAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailureImpl(@NonNull final DataSource<Void> dataSource) {
|
||||
failed++;
|
||||
updateAdapter();
|
||||
}
|
||||
|
||||
public void updateAdapter() {
|
||||
if (failed + success != result.length) return;
|
||||
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];
|
||||
if (feedPostModel != null) {
|
||||
feedEndCursor = feedPostModel.getEndCursor();
|
||||
feedHasNextPage = feedPostModel.hasNextPage();
|
||||
feedPostModel.setPageCursor(false, null);
|
||||
}
|
||||
binding.feedSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
};
|
||||
|
||||
for (final FeedModel feedModel : result) {
|
||||
final DataSource<Void> ds = Fresco.getImagePipeline().prefetchToBitmapCache(ImageRequest.fromUri(feedModel.getThumbnailUrl()), null);
|
||||
ds.subscribe(subscriber, UiThreadImmediateExecutorService.getInstance());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = (MainActivity) requireActivity();
|
||||
storiesService = StoriesService.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater,
|
||||
final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
if (root != null) {
|
||||
return root;
|
||||
}
|
||||
binding = FragmentFeedBinding.inflate(inflater, container, false);
|
||||
root = binding.getRoot();
|
||||
// setupActionBar();
|
||||
setupFeedStories();
|
||||
setupFeed();
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (videoAwareRecyclerScroller != null) {
|
||||
videoAwareRecyclerScroller.stopPlaying();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (videoAwareRecyclerScroller != null && SHOULD_AUTO_PLAY) {
|
||||
videoAwareRecyclerScroller.startPlaying();
|
||||
}
|
||||
}
|
||||
|
||||
final MentionClickListener mentionClickListener = (view, text, isHashtag) -> {
|
||||
// final AlertDialog.Builder builder = new AlertDialog.Builder(requireContext())
|
||||
// .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);
|
||||
// // }
|
||||
// });
|
||||
// builder.show();
|
||||
if (isHashtag) {
|
||||
// hashtag...
|
||||
return;
|
||||
}
|
||||
final NavDirections action = FeedFragmentDirections.actionFeedFragmentToProfileFragment("@" + text);
|
||||
NavHostFragment.findNavController(this).navigate(action);
|
||||
};
|
||||
|
||||
private final View.OnClickListener postViewClickListener = v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (!(tag instanceof FeedModel)) return;
|
||||
|
||||
final FeedModel feedModel = (FeedModel) tag;
|
||||
if (v instanceof RamboTextView) {
|
||||
if (feedModel.isMentionClicked())
|
||||
feedModel.toggleCaption();
|
||||
feedModel.setMentionClicked(false);
|
||||
if (!FeedItemViewHolder.expandCollapseTextView((RamboTextView) v, feedModel.getPostCaption()))
|
||||
feedModel.toggleCaption();
|
||||
return;
|
||||
}
|
||||
|
||||
final int id = v.getId();
|
||||
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()));
|
||||
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));
|
||||
break;
|
||||
|
||||
case R.id.btnDownload:
|
||||
ProfileModel profileModel = feedModel.getProfileModel();
|
||||
final String username = profileModel != null ? profileModel.getUsername() : null;
|
||||
|
||||
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));
|
||||
else {
|
||||
final ArrayList<BasePostModel> postModels = new ArrayList<>();
|
||||
final DialogInterface.OnClickListener clickListener1 = (dialog, which) -> {
|
||||
postModels.clear();
|
||||
|
||||
final boolean breakWhenFoundSelected = which == DialogInterface.BUTTON_POSITIVE;
|
||||
|
||||
for (final ViewerPostModel sliderItem : sliderItems) {
|
||||
if (sliderItem != null) {
|
||||
if (!breakWhenFoundSelected)
|
||||
postModels.add(sliderItem);
|
||||
else if (sliderItem.isSelected()) {
|
||||
postModels.add(sliderItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// shows 0 items on first item of viewpager cause onPageSelected hasn't been called yet
|
||||
if (breakWhenFoundSelected && postModels.size() == 0)
|
||||
postModels.add(sliderItems[0]);
|
||||
|
||||
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)
|
||||
.setNegativeButton(R.string.post_viewer_download_album, clickListener1)
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
|
||||
case R.id.ivProfilePic:
|
||||
profileModel = feedModel.getProfileModel();
|
||||
if (profileModel != null)
|
||||
mentionClickListener.onClick(null, profileModel.getUsername(), false);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
private void setupFeed() {
|
||||
feedViewModel = new ViewModelProvider(fragmentActivity).get(FeedViewModel.class);
|
||||
final LinearLayoutManager layoutManager = new LinearLayoutManager(requireContext());
|
||||
binding.feedRecyclerView.setLayoutManager(layoutManager);
|
||||
binding.feedRecyclerView.setHasFixedSize(true);
|
||||
final FeedAdapter feedAdapter = new FeedAdapter(postViewClickListener, mentionClickListener);
|
||||
feedAdapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY);
|
||||
binding.feedRecyclerView.setAdapter(feedAdapter);
|
||||
feedViewModel.getList().observe(fragmentActivity, feedAdapter::submitList);
|
||||
final RecyclerLazyLoader lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if (feedHasNextPage) {
|
||||
fetchFeed();
|
||||
}
|
||||
});
|
||||
if (SHOULD_AUTO_PLAY) {
|
||||
videoAwareRecyclerScroller = new VideoAwareRecyclerScroller();
|
||||
binding.feedRecyclerView.addOnScrollListener(videoAwareRecyclerScroller);
|
||||
}
|
||||
binding.feedRecyclerView.addOnScrollListener(lazyLoader);
|
||||
fetchFeed();
|
||||
}
|
||||
|
||||
private void fetchFeed() {
|
||||
binding.feedSwipeRefreshLayout.setRefreshing(true);
|
||||
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);
|
||||
NavHostFragment.findNavController(this).navigate(action);
|
||||
});
|
||||
binding.feedStoriesRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false));
|
||||
binding.feedStoriesRecyclerView.setAdapter(feedStoriesAdapter);
|
||||
feedStoriesViewModel.getList().observe(fragmentActivity, feedStoriesAdapter::submitList);
|
||||
storiesService.getFeedStories(new ServiceCallback<List<FeedStoryModel>>() {
|
||||
@Override
|
||||
public void onSuccess(final List<FeedStoryModel> result) {
|
||||
feedStoriesViewModel.getList().postValue(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
Log.e(TAG, "failed", t);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package awais.instagrabber.fragments.main;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import awais.instagrabber.MainHelper;
|
||||
import awais.instagrabber.activities.SavedViewer;
|
||||
import awais.instagrabber.databinding.FragmentProfileBinding;
|
||||
import awais.instagrabber.models.LocationModel;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
public class ProfileActionListener implements View.OnClickListener {
|
||||
|
||||
private String cookie;
|
||||
private boolean isLoggedIn;
|
||||
private ProfileModel profileModel;
|
||||
private String userQuery;
|
||||
private FragmentProfileBinding binding;
|
||||
private LocationModel locationModel;
|
||||
|
||||
public ProfileActionListener(final String cookie, final boolean isLoggedIn, final ProfileModel profileModel, final String userQuery, final FragmentProfileBinding binding, final LocationModel locationModel) {
|
||||
this.cookie = cookie;
|
||||
this.isLoggedIn = isLoggedIn;
|
||||
this.profileModel = profileModel;
|
||||
this.userQuery = userQuery;
|
||||
this.binding = binding;
|
||||
this.locationModel = locationModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
|
||||
|
||||
|
||||
// else if (v == binding.btnFollow) {
|
||||
//
|
||||
// } else if (v == mainActivity.mainBinding.profileView.btnRestrict && isLoggedIn) {
|
||||
// new ProfileAction().execute("restrict");
|
||||
// } else if (v == mainActivity.mainBinding.profileView.btnSaved && !isSelf) {
|
||||
// new ProfileAction().execute("block");
|
||||
// } else if (v == mainActivity.mainBinding.profileView.btnFollowTag) {
|
||||
// new ProfileAction().execute("followtag");
|
||||
// } else if (v == mainActivity.mainBinding.profileView.btnTagged || (v == mainActivity.mainBinding.profileView.btnRestrict && !isLoggedIn)) {
|
||||
// mainActivity.startActivity(new Intent(mainActivity, SavedViewer.class)
|
||||
// .putExtra(Constants.EXTRAS_INDEX, "%" + mainActivity.profileModel.getId())
|
||||
// .putExtra(Constants.EXTRAS_USER, "@" + mainActivity.profileModel.getUsername())
|
||||
// );
|
||||
// } else if (v == mainActivity.mainBinding.profileView.btnSaved) {
|
||||
//
|
||||
// } else if (v == mainActivity.mainBinding.profileView.btnLiked) {
|
||||
//
|
||||
// }
|
||||
}
|
||||
}
|
@ -0,0 +1,532 @@
|
||||
package awais.instagrabber.fragments.main;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.view.ActionMode;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.activity.OnBackPressedDispatcher;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
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;
|
||||
import awais.instagrabber.asyncs.PostsFetcher;
|
||||
import awais.instagrabber.asyncs.ProfileFetcher;
|
||||
import awais.instagrabber.asyncs.UsernameFetcher;
|
||||
import awais.instagrabber.asyncs.i.iStoryStatusFetcher;
|
||||
import awais.instagrabber.customviews.PrimaryActionModeCallback;
|
||||
import awais.instagrabber.customviews.PrimaryActionModeCallback.CallbacksHelper;
|
||||
import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager;
|
||||
import awais.instagrabber.customviews.helpers.GridSpacingItemDecoration;
|
||||
import awais.instagrabber.databinding.FragmentProfileBinding;
|
||||
import awais.instagrabber.fragments.main.viewmodels.ProfilePostsViewModel;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
import awais.instagrabber.models.enums.DownloadMethod;
|
||||
import awais.instagrabber.models.enums.ItemGetType;
|
||||
import awais.instagrabber.services.ProfileService;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public class ProfileFragment extends Fragment {
|
||||
private static final String TAG = "ProfileFragment";
|
||||
|
||||
private MainActivity fragmentActivity;
|
||||
private CoordinatorLayout root;
|
||||
private FragmentProfileBinding binding;
|
||||
private boolean isLoggedIn;
|
||||
private String cookie;
|
||||
private String username;
|
||||
private ProfileModel profileModel;
|
||||
private ProfilePostsViewModel profilePostsViewModel;
|
||||
private PostsAdapter postsAdapter;
|
||||
private ActionMode actionMode;
|
||||
private Handler usernameSettingHandler;
|
||||
private ProfileService profileService;
|
||||
|
||||
private final Runnable usernameSettingRunnable = () -> {
|
||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(username.substring(1));
|
||||
}
|
||||
};
|
||||
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
if (postsAdapter == null) {
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
postsAdapter.clearSelection();
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = (MainActivity) requireActivity();
|
||||
profileService = ProfileService.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater,
|
||||
final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
if (root != null) {
|
||||
return root;
|
||||
}
|
||||
binding = FragmentProfileBinding.inflate(inflater, container, false);
|
||||
root = binding.getRoot();
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (usernameSettingHandler != null) {
|
||||
usernameSettingHandler.removeCallbacks(usernameSettingRunnable);
|
||||
}
|
||||
if (profilePostsViewModel != null) {
|
||||
profilePostsViewModel.getList().postValue(Collections.emptyList());
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
isLoggedIn = !Utils.isEmpty(cookie) && Utils.getUserIdFromCookie(cookie) != null;
|
||||
if (getArguments() != null) {
|
||||
final ProfileFragmentArgs fragmentArgs = ProfileFragmentArgs.fromBundle(getArguments());
|
||||
username = fragmentArgs.getUsername();
|
||||
setUsernameDelayed();
|
||||
}
|
||||
if (!isLoggedIn) {
|
||||
binding.privatePage1.setImageResource(R.drawable.ic_info);
|
||||
binding.privatePage2.setText(R.string.no_acc);
|
||||
binding.privatePage.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
setupPosts();
|
||||
fetchProfile();
|
||||
}
|
||||
|
||||
private void fetchProfile() {
|
||||
final String uid = Utils.getUserIdFromCookie(cookie);
|
||||
if (username == null && uid != null) {
|
||||
final FetchListener<String> fetchListener = username -> {
|
||||
if (Utils.isEmpty(username)) return;
|
||||
this.username = username;
|
||||
setUsernameDelayed();
|
||||
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()))
|
||||
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) {
|
||||
found = true;
|
||||
fetchListener.onResult("@" + username);
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// if not in database, fetch info from instagram
|
||||
new UsernameFetcher(uid, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
return;
|
||||
}
|
||||
fetchProfileDetails();
|
||||
}
|
||||
|
||||
private void fetchProfileDetails() {
|
||||
new ProfileFetcher(username.substring(1), profileModel -> {
|
||||
this.profileModel = profileModel;
|
||||
new PostsFetcher(profileModel.getId(),
|
||||
null,
|
||||
result -> profilePostsViewModel.getList().postValue(Arrays.asList(result)))
|
||||
.setUsername(profileModel.getUsername())
|
||||
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
setProfileDetails();
|
||||
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void setProfileDetails() {
|
||||
setupCommonListeners();
|
||||
if (profileModel == null) {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
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 -> {
|
||||
// mainActivity.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) {
|
||||
final String myId = Utils.getUserIdFromCookie(cookie);
|
||||
if (profileId.equals(myId)) {
|
||||
binding.btnTagged.setVisibility(View.VISIBLE);
|
||||
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)));
|
||||
} else {
|
||||
binding.btnTagged.setVisibility(View.GONE);
|
||||
binding.btnSaved.setVisibility(View.GONE);
|
||||
binding.btnLiked.setVisibility(View.GONE);
|
||||
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)));
|
||||
} else if (profileModel.getRequested()) {
|
||||
binding.btnFollow.setText(R.string.cancel);
|
||||
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)));
|
||||
}
|
||||
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)));
|
||||
} else {
|
||||
binding.btnRestrict.setText(R.string.restrict);
|
||||
ViewCompat.setBackgroundTintList(
|
||||
binding.btnRestrict,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_orange_background)));
|
||||
}
|
||||
if (profileModel.isReallyPrivate()) {
|
||||
binding.btnBlock.setVisibility(View.VISIBLE);
|
||||
binding.btnTagged.setVisibility(View.GONE);
|
||||
if (profileModel.getBlocked()) {
|
||||
binding.btnBlock.setText(R.string.unblock);
|
||||
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)));
|
||||
}
|
||||
} else {
|
||||
binding.btnBlock.setVisibility(View.GONE);
|
||||
binding.btnSaved.setVisibility(View.VISIBLE);
|
||||
binding.btnTagged.setVisibility(View.VISIBLE);
|
||||
if (profileModel.getBlocked()) {
|
||||
binding.btnSaved.setText(R.string.unblock);
|
||||
ViewCompat.setBackgroundTintList(
|
||||
binding.btnSaved,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.btn_green_background)));
|
||||
} else {
|
||||
binding.btnSaved.setText(R.string.block);
|
||||
ViewCompat.setBackgroundTintList(
|
||||
binding.btnSaved,
|
||||
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)));
|
||||
} else {
|
||||
binding.btnFollow.setText(R.string.favorite_short);
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
binding.mainProfileImage.setImageURI(profileModel.getSdProfilePic());
|
||||
|
||||
final long followersCount = profileModel.getFollowersCount();
|
||||
final long followingCount = profileModel.getFollowingCount();
|
||||
|
||||
final String postCount = String.valueOf(profileModel.getPostCount());
|
||||
|
||||
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.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.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());
|
||||
|
||||
CharSequence biography = profileModel.getBiography();
|
||||
binding.mainBiography.setCaptionIsExpandable(true);
|
||||
binding.mainBiography.setCaptionIsExpanded(true);
|
||||
if (Utils.hasMentions(biography)) {
|
||||
biography = Utils.getMentionText(biography);
|
||||
binding.mainBiography.setText(biography, TextView.BufferType.SPANNABLE);
|
||||
// binding.mainBiography.setMentionClickListener(mentionClickListener);
|
||||
} else {
|
||||
binding.mainBiography.setText(biography);
|
||||
binding.mainBiography.setMentionClickListener(null);
|
||||
}
|
||||
|
||||
final String url = profileModel.getUrl();
|
||||
if (Utils.isEmpty(url)) {
|
||||
binding.mainUrl.setVisibility(View.GONE);
|
||||
} else {
|
||||
binding.mainUrl.setVisibility(View.VISIBLE);
|
||||
binding.mainUrl.setText(Utils.getSpannableUrl(url));
|
||||
}
|
||||
|
||||
binding.mainFullName.setSelected(true);
|
||||
binding.mainBiography.setEnabled(true);
|
||||
|
||||
if (!profileModel.isReallyPrivate()) {
|
||||
binding.mainFollowing.setClickable(true);
|
||||
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);
|
||||
}
|
||||
|
||||
if (profileModel.getPostCount() == 0) {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
binding.privatePage1.setImageResource(R.drawable.ic_cancel);
|
||||
binding.privatePage2.setText(R.string.empty_acc);
|
||||
binding.privatePage.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
binding.mainPosts.setVisibility(View.VISIBLE);
|
||||
// currentlyExecuting = new PostsFetcher(profileId, postsFetchListener)
|
||||
// .setUsername(profileModel.getUsername())
|
||||
// .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
} else {
|
||||
binding.mainFollowers.setClickable(false);
|
||||
binding.mainFollowing.setClickable(false);
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
// error
|
||||
binding.privatePage1.setImageResource(R.drawable.lock);
|
||||
binding.privatePage2.setText(R.string.priv_acc);
|
||||
binding.privatePage.setVisibility(View.VISIBLE);
|
||||
binding.mainPosts.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupCommonListeners() {
|
||||
|
||||
final String userIdFromCookie = Utils.getUserIdFromCookie(cookie);
|
||||
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("^@", "")
|
||||
)
|
||||
);
|
||||
} else if (v == binding.btnFollow) {
|
||||
Utils.dataBox.addFavorite(
|
||||
new DataBox.FavoriteModel(username, System.currentTimeMillis(),
|
||||
username.replaceAll("^@", "")));
|
||||
}
|
||||
// onRefresh();
|
||||
return;
|
||||
}
|
||||
profileService.followProfile(username);
|
||||
});
|
||||
|
||||
// binding.btnRestrict.setOnClickListener(profileActionListener);
|
||||
// binding.btnBlock.setOnClickListener(profileActionListener);
|
||||
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.btnFollowTag.setOnClickListener(profileActionListener);
|
||||
}
|
||||
|
||||
private void setUsernameDelayed() {
|
||||
if (usernameSettingHandler == null) {
|
||||
usernameSettingHandler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
usernameSettingHandler.postDelayed(usernameSettingRunnable, 200);
|
||||
}
|
||||
|
||||
private void setupPosts() {
|
||||
profilePostsViewModel = new ViewModelProvider(this).get(ProfilePostsViewModel.class);
|
||||
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());
|
||||
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));
|
||||
|
||||
}, (model, position) -> {
|
||||
if (!postsAdapter.isSelecting()) {
|
||||
checkAndResetAction();
|
||||
return true;
|
||||
}
|
||||
final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher();
|
||||
if (onBackPressedDispatcher.hasEnabledCallbacks()) {
|
||||
return true;
|
||||
}
|
||||
actionMode = fragmentActivity.startActionMode(multiSelectAction);
|
||||
final String title = getString(R.string.number_selected, 1);
|
||||
actionMode.setTitle(title);
|
||||
onBackPressedDispatcher.addCallback(onBackPressedCallback);
|
||||
return true;
|
||||
});
|
||||
binding.mainPosts.setAdapter(postsAdapter);
|
||||
profilePostsViewModel.getList().observe(fragmentActivity, postsAdapter::submitList);
|
||||
}
|
||||
|
||||
private boolean checkAndResetAction() {
|
||||
final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher();
|
||||
if (!onBackPressedDispatcher.hasEnabledCallbacks() || actionMode == null) {
|
||||
return false;
|
||||
}
|
||||
actionMode.finish();
|
||||
actionMode = null;
|
||||
return true;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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.FeedStoryModel;
|
||||
|
||||
public class FeedStoriesViewModel extends ViewModel {
|
||||
private MutableLiveData<List<FeedStoryModel>> list;
|
||||
|
||||
public MutableLiveData<List<FeedStoryModel>> getList() {
|
||||
if (list == null) {
|
||||
list = new MutableLiveData<>();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
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 {
|
||||
private MutableLiveData<List<FeedModel>> list;
|
||||
|
||||
public MutableLiveData<List<FeedModel>> getList() {
|
||||
if (list == null) {
|
||||
list = new MutableLiveData<>(Collections.emptyList());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
@ -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.PostModel;
|
||||
|
||||
public class ProfilePostsViewModel extends ViewModel {
|
||||
private MutableLiveData<List<PostModel>> list;
|
||||
|
||||
public MutableLiveData<List<PostModel>> getList() {
|
||||
if (list == null) {
|
||||
list = new MutableLiveData<>();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
@ -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.StoryModel;
|
||||
|
||||
public class StoriesViewModel extends ViewModel {
|
||||
private MutableLiveData<List<StoryModel>> list;
|
||||
|
||||
public MutableLiveData<List<StoryModel>> getList() {
|
||||
if (list == null) {
|
||||
list = new MutableLiveData<>();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,14 +1,16 @@
|
||||
package awais.instagrabber.models;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.util.ObjectsCompat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import awais.instagrabber.adapters.MultiSelectListAdapter.Selectable;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
public abstract class BasePostModel implements Serializable {
|
||||
public abstract class BasePostModel implements Serializable, Selectable {
|
||||
protected String postId;
|
||||
protected String displayUrl;
|
||||
protected String shortCode;
|
||||
@ -88,4 +90,17 @@ public abstract class BasePostModel implements Serializable {
|
||||
public final String getPostDate() {
|
||||
return Utils.datetimeParser.format(new Date(timestamp * 1000L));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final BasePostModel that = (BasePostModel) o;
|
||||
return ObjectsCompat.equals(postId, that.postId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectsCompat.hash(postId);
|
||||
}
|
||||
}
|
@ -51,4 +51,6 @@ public class PostModel extends BasePostModel {
|
||||
this.endCursor = endCursor;
|
||||
this.hasNextPage = hasNextPage;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package awais.instagrabber.repositories;
|
||||
|
||||
public interface ProfileRepository {
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package awais.instagrabber.repositories;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Header;
|
||||
import retrofit2.http.QueryMap;
|
||||
import retrofit2.http.Url;
|
||||
|
||||
public interface StoriesRepository {
|
||||
|
||||
@GET("graphql/query/")
|
||||
Call<String> getStories(@QueryMap(encoded = true) Map<String, String> variables);
|
||||
|
||||
@GET
|
||||
Call<String> getUserStory(@Header("User-Agent") String userAgent, @Url String url);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package awais.instagrabber.services;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class AddCookiesInterceptor implements Interceptor {
|
||||
@NonNull
|
||||
@Override
|
||||
public Response intercept(@NonNull final Chain chain) throws IOException {
|
||||
final Request request = chain.request();
|
||||
final Request.Builder builder = request.newBuilder();
|
||||
final String cookie = Utils.settingsHelper.getString(Constants.COOKIE);
|
||||
builder.addHeader("Cookie", cookie);
|
||||
final Request updatedRequest = builder.build();
|
||||
return chain.proceed(updatedRequest);
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package awais.instagrabber.services;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.scalars.ScalarsConverterFactory;
|
||||
|
||||
public abstract class BaseService {
|
||||
|
||||
private Retrofit.Builder builder;
|
||||
|
||||
Retrofit.Builder getRetrofitBuilder() {
|
||||
if (builder == null) {
|
||||
final OkHttpClient client = new OkHttpClient.Builder()
|
||||
.addInterceptor(new AddCookiesInterceptor())
|
||||
.followRedirects(false)
|
||||
.followSslRedirects(false)
|
||||
.build();
|
||||
builder = new Retrofit.Builder()
|
||||
.addConverterFactory(ScalarsConverterFactory.create())
|
||||
.client(client);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package awais.instagrabber.services;
|
||||
|
||||
public interface FeedService {
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package awais.instagrabber.services;
|
||||
|
||||
import awais.instagrabber.repositories.ProfileRepository;
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
public class ProfileService extends BaseService {
|
||||
private static final String TAG = "ProfileService";
|
||||
|
||||
private final ProfileRepository repository;
|
||||
|
||||
private static ProfileService instance;
|
||||
|
||||
private ProfileService() {
|
||||
final Retrofit retrofit = getRetrofitBuilder()
|
||||
.baseUrl("https://i.instagram.com")
|
||||
.build();
|
||||
repository = retrofit.create(ProfileRepository.class);
|
||||
}
|
||||
|
||||
public static ProfileService getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ProfileService();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void followProfile(final String username) {
|
||||
// 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/"));
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package awais.instagrabber.services;
|
||||
|
||||
public interface ServiceCallback<T> {
|
||||
void onSuccess(T result);
|
||||
|
||||
void onFailure(Throwable t);
|
||||
}
|
@ -0,0 +1,277 @@
|
||||
package awais.instagrabber.services;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.models.stickers.PollModel;
|
||||
import awais.instagrabber.models.stickers.QuestionModel;
|
||||
import awais.instagrabber.models.stickers.QuizModel;
|
||||
import awais.instagrabber.repositories.StoriesRepository;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
public class StoriesService extends BaseService {
|
||||
private static final String TAG = "StoriesService";
|
||||
|
||||
private final StoriesRepository repository;
|
||||
|
||||
private static StoriesService instance;
|
||||
|
||||
private StoriesService() {
|
||||
final Retrofit retrofit = getRetrofitBuilder()
|
||||
.baseUrl("https://www.instagram.com")
|
||||
.build();
|
||||
repository = retrofit.create(StoriesRepository.class);
|
||||
}
|
||||
|
||||
public static StoriesService getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new StoriesService();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void getFeedStories(final ServiceCallback<List<FeedStoryModel>> callback) {
|
||||
final Map<String, String> queryMap = new HashMap<>();
|
||||
queryMap.put("query_hash", "b7b84d884400bc5aa7cfe12ae843a091");
|
||||
queryMap.put("variables", "{\"only_stories\":true,\"stories_prefetch\":false,\"stories_video_dash_manifest\":false}");
|
||||
final Call<String> response = repository.getStories(queryMap);
|
||||
response.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
||||
final String body = response.body();
|
||||
if (body == null) {
|
||||
Log.e(TAG, "getFeedStories: body is empty");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final List<FeedStoryModel> feedStoryModels = new ArrayList<>();
|
||||
final JSONArray feedStoriesReel = new JSONObject(body)
|
||||
.getJSONObject("data")
|
||||
.getJSONObject(Constants.EXTRAS_USER)
|
||||
.getJSONObject("feed_reels_tray")
|
||||
.getJSONObject("edge_reels_tray_to_reel")
|
||||
.getJSONArray("edges");
|
||||
for (int i = 0; i < feedStoriesReel.length(); ++i) {
|
||||
final JSONObject node = feedStoriesReel.getJSONObject(i).getJSONObject("node");
|
||||
final JSONObject user = node.getJSONObject(node.has("user") ? "user" : "owner");
|
||||
final ProfileModel profileModel = new ProfileModel(false, false, false,
|
||||
user.getString("id"),
|
||||
user.getString("username"),
|
||||
null, null, null,
|
||||
user.getString("profile_pic_url"),
|
||||
null, 0, 0, 0, false, false, false, false);
|
||||
final String id = node.getString("id");
|
||||
final boolean fullyRead = !node.isNull("seen") && node.getLong("seen") == node.getLong("latest_reel_media");
|
||||
feedStoryModels.add(new FeedStoryModel(id, profileModel, fullyRead));
|
||||
}
|
||||
callback.onSuccess(feedStoryModels);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error parsing json", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
||||
callback.onFailure(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void getUserStory(final String id,
|
||||
final String username,
|
||||
final boolean storiesig,
|
||||
final boolean isLoc,
|
||||
final boolean isHashtag,
|
||||
final boolean highlight,
|
||||
final ServiceCallback<List<StoryModel>> callback) {
|
||||
final String url = buildUrl(id, storiesig, isLoc, isHashtag, highlight);
|
||||
final String userAgent = storiesig ? Constants.A_USER_AGENT : Constants.I_USER_AGENT;
|
||||
final Call<String> userStoryCall = repository.getUserStory(userAgent, url);
|
||||
userStoryCall.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
||||
JSONObject data;
|
||||
String localUsername = username;
|
||||
try {
|
||||
final String body = response.body();
|
||||
if (body == null) {
|
||||
Log.e(TAG, "body is null");
|
||||
return;
|
||||
}
|
||||
data = new JSONObject(body);
|
||||
|
||||
if (!storiesig && !highlight)
|
||||
data = data.optJSONObject((isLoc || isHashtag) ? "story" : "reel");
|
||||
else if (highlight) data = data.getJSONObject("reels").optJSONObject(id);
|
||||
|
||||
if (data != null
|
||||
&& localUsername == null
|
||||
&& !isLoc
|
||||
&& !isHashtag)
|
||||
localUsername = data.getJSONObject("user").getString("username");
|
||||
|
||||
JSONArray media;
|
||||
if (data != null
|
||||
&& (media = data.optJSONArray("items")) != null
|
||||
&& media.length() > 0 && media.optJSONObject(0) != null) {
|
||||
|
||||
final int mediaLen = media.length();
|
||||
final List<StoryModel> models = new ArrayList<>();
|
||||
for (int i = 0; i < mediaLen; ++i) {
|
||||
data = media.getJSONObject(i);
|
||||
final boolean isVideo = data.has("video_duration");
|
||||
final StoryModel model = new StoryModel(data.getString("id"),
|
||||
data.getJSONObject("image_versions2").getJSONArray("candidates").getJSONObject(0).getString("url"),
|
||||
isVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE,
|
||||
data.optLong("taken_at", 0),
|
||||
(isLoc || isHashtag) ? data.getJSONObject("user").getString("username") : localUsername,
|
||||
data.getJSONObject("user").getString("pk"),
|
||||
data.getBoolean("can_reply"));
|
||||
|
||||
final JSONArray videoResources = data.optJSONArray("video_versions");
|
||||
if (isVideo && videoResources != null)
|
||||
model.setVideoUrl(Utils.getHighQualityPost(videoResources, true, true, false));
|
||||
|
||||
if (data.has("story_feed_media")) {
|
||||
model.setTappableShortCode(data.getJSONArray("story_feed_media").getJSONObject(0).optString("media_id"));
|
||||
}
|
||||
|
||||
if (!data.isNull("story_app_attribution"))
|
||||
model.setSpotify(data.getJSONObject("story_app_attribution").optString("content_url").split("\\?")[0]);
|
||||
|
||||
if (data.has("story_polls")) {
|
||||
final JSONArray storyPolls = data.optJSONArray("story_polls");
|
||||
JSONObject tappableObject = null;
|
||||
if (storyPolls != null) {
|
||||
tappableObject = storyPolls.getJSONObject(0).optJSONObject("poll_sticker");
|
||||
}
|
||||
if (tappableObject != null) model.setPoll(new PollModel(
|
||||
String.valueOf(tappableObject.getLong("poll_id")),
|
||||
tappableObject.getString("question"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(0).getString("text"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(0).getInt("count"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(1).getString("text"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(1).getInt("count"),
|
||||
tappableObject.optInt("viewer_vote", -1)
|
||||
));
|
||||
}
|
||||
if (data.has("story_questions")) {
|
||||
JSONObject tappableObject = data.getJSONArray("story_questions").getJSONObject(0).optJSONObject("question_sticker");
|
||||
if (tappableObject != null && !tappableObject.getString("question_type").equals("music"))
|
||||
model.setQuestion(new QuestionModel(
|
||||
String.valueOf(tappableObject.getLong("question_id")),
|
||||
tappableObject.getString("question")
|
||||
));
|
||||
}
|
||||
if (data.has("story_quizs")) {
|
||||
JSONObject tappableObject = data.getJSONArray("story_quizs").getJSONObject(0).optJSONObject("quiz_sticker");
|
||||
if (tappableObject != null) {
|
||||
String[] choices = new String[tappableObject.getJSONArray("tallies").length()];
|
||||
Long[] counts = new Long[choices.length];
|
||||
for (int q = 0; q < choices.length; ++q) {
|
||||
JSONObject tempchoice = tappableObject.getJSONArray("tallies").getJSONObject(q);
|
||||
choices[q] = (q == tappableObject.getInt("correct_answer") ? "*** " : "")
|
||||
+ tempchoice.getString("text");
|
||||
counts[q] = tempchoice.getLong("count");
|
||||
}
|
||||
model.setQuiz(new QuizModel(
|
||||
String.valueOf(tappableObject.getLong("quiz_id")),
|
||||
tappableObject.getString("question"),
|
||||
choices,
|
||||
counts,
|
||||
tappableObject.optInt("viewer_answer", -1)
|
||||
));
|
||||
}
|
||||
}
|
||||
JSONArray hashtags = data.optJSONArray("story_hashtags");
|
||||
JSONArray locations = data.optJSONArray("story_locations");
|
||||
JSONArray atmarks = data.optJSONArray("reel_mentions");
|
||||
String[] mentions = new String[(hashtags == null ? 0 : hashtags.length())
|
||||
+ (atmarks == null ? 0 : atmarks.length())
|
||||
+ (locations == null ? 0 : locations.length())];
|
||||
if (hashtags != null) {
|
||||
for (int h = 0; h < hashtags.length(); ++h) {
|
||||
mentions[h] = "#" + hashtags.getJSONObject(h).getJSONObject("hashtag").getString("name");
|
||||
}
|
||||
}
|
||||
if (atmarks != null) {
|
||||
for (int h = 0; h < atmarks.length(); ++h) {
|
||||
mentions[h + (hashtags == null ? 0 : hashtags.length())] =
|
||||
"@" + atmarks.getJSONObject(h).getJSONObject("user").getString("username");
|
||||
}
|
||||
}
|
||||
if (locations != null) {
|
||||
for (int h = 0; h < locations.length(); ++h) {
|
||||
mentions[h + (hashtags == null ? 0 : hashtags.length()) + (atmarks == null ? 0 : atmarks.length())] =
|
||||
locations.getJSONObject(h).getJSONObject("location").getLong("pk")
|
||||
+ "/ (" + locations.getJSONObject(h).getJSONObject("location").getString("short_name") + ")";
|
||||
}
|
||||
}
|
||||
if (mentions.length != 0) model.setMentions(mentions);
|
||||
models.add(model);
|
||||
}
|
||||
callback.onSuccess(models);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error parsing string");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
||||
callback.onFailure(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String buildUrl(final String id, final boolean storiesig, final boolean isLoc, final boolean isHashtag, final boolean highlight) {
|
||||
final String userId = id.replace(":", "%3A");
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("https://");
|
||||
if (storiesig) {
|
||||
builder.append("storiesig");
|
||||
} else {
|
||||
builder.append("i.instagram");
|
||||
}
|
||||
builder.append(".com/api/v1/");
|
||||
if (isLoc) {
|
||||
builder.append("locations/");
|
||||
}
|
||||
if (isHashtag) {
|
||||
builder.append("tags/");
|
||||
}
|
||||
if (highlight) {
|
||||
builder.append("feed/reels_media?user_ids=");
|
||||
} else {
|
||||
builder.append("feed/user/");
|
||||
}
|
||||
builder.append(userId);
|
||||
if (!highlight) {
|
||||
if (storiesig) {
|
||||
builder.append("/reel_media/");
|
||||
} else {
|
||||
builder.append("/story/");
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,207 @@
|
||||
package awais.instagrabber.utils;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.NavGraph;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
|
||||
public class NavigationExtensions {
|
||||
|
||||
@NonNull
|
||||
public static LiveData<NavController> setupWithNavController(@NonNull final BottomNavigationView bottomNavigationView,
|
||||
@NonNull List<Integer> navGraphIds,
|
||||
@NonNull final FragmentManager fragmentManager,
|
||||
final int containerId,
|
||||
@NonNull Intent intent,
|
||||
final int firstFragmentGraphIndex) {
|
||||
final SparseArray<String> graphIdToTagMap = new SparseArray<>();
|
||||
final MutableLiveData<NavController> selectedNavController = new MutableLiveData<>();
|
||||
int firstFragmentGraphId = 0;
|
||||
for (int i = 0; i < navGraphIds.size(); i++) {
|
||||
final int navGraphId = navGraphIds.get(i);
|
||||
final String fragmentTag = getFragmentTag(i);
|
||||
final NavHostFragment navHostFragment = obtainNavHostFragment(fragmentManager, fragmentTag, navGraphId, containerId);
|
||||
final NavController navController = navHostFragment.getNavController();
|
||||
final int graphId = navController.getGraph().getId();
|
||||
if (i == firstFragmentGraphIndex) {
|
||||
firstFragmentGraphId = graphId;
|
||||
}
|
||||
graphIdToTagMap.put(graphId, fragmentTag);
|
||||
if (bottomNavigationView.getSelectedItemId() == graphId) {
|
||||
selectedNavController.setValue(navHostFragment.getNavController());
|
||||
attachNavHostFragment(fragmentManager, navHostFragment, i == firstFragmentGraphIndex);
|
||||
} else {
|
||||
detachNavHostFragment(fragmentManager, navHostFragment);
|
||||
}
|
||||
}
|
||||
|
||||
final String[] selectedItemTag = {graphIdToTagMap.get(bottomNavigationView.getSelectedItemId())};
|
||||
final String firstFragmentTag = graphIdToTagMap.get(firstFragmentGraphId);
|
||||
final boolean[] isOnFirstFragment = {selectedItemTag[0] != null && selectedItemTag[0].equals(firstFragmentTag)};
|
||||
bottomNavigationView.setOnNavigationItemSelectedListener(item -> {
|
||||
if (fragmentManager.isStateSaved()) {
|
||||
return false;
|
||||
}
|
||||
String newlySelectedItemTag = graphIdToTagMap.get(item.getItemId());
|
||||
if (!selectedItemTag[0].equals(newlySelectedItemTag)) {
|
||||
fragmentManager.popBackStack(firstFragmentTag, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
Fragment fragment = fragmentManager.findFragmentByTag(newlySelectedItemTag);
|
||||
if (fragment == null) {
|
||||
throw new RuntimeException("null cannot be cast to non-null NavHostFragment");
|
||||
}
|
||||
final NavHostFragment selectedFragment = (NavHostFragment) fragment;
|
||||
if (!firstFragmentTag.equals(newlySelectedItemTag)) {
|
||||
FragmentTransaction fragmentTransaction = fragmentManager
|
||||
.beginTransaction()
|
||||
.setCustomAnimations(
|
||||
R.anim.nav_default_enter_anim,
|
||||
R.anim.nav_default_exit_anim,
|
||||
R.anim.nav_default_pop_enter_anim,
|
||||
R.anim.nav_default_pop_exit_anim
|
||||
)
|
||||
.attach(selectedFragment)
|
||||
.setPrimaryNavigationFragment(selectedFragment);
|
||||
for (int i = 0; i < graphIdToTagMap.size(); i++) {
|
||||
final int key = graphIdToTagMap.keyAt(i);
|
||||
final String fragmentTagForId = graphIdToTagMap.get(key);
|
||||
if (!fragmentTagForId.equals(newlySelectedItemTag)) {
|
||||
final Fragment fragmentByTag = fragmentManager.findFragmentByTag(firstFragmentTag);
|
||||
if (fragmentByTag == null) {
|
||||
continue;
|
||||
}
|
||||
fragmentTransaction.detach(fragmentByTag);
|
||||
}
|
||||
}
|
||||
fragmentTransaction.addToBackStack(firstFragmentTag)
|
||||
.setReorderingAllowed(true)
|
||||
.commit();
|
||||
}
|
||||
selectedItemTag[0] = newlySelectedItemTag;
|
||||
isOnFirstFragment[0] = selectedItemTag[0].equals(firstFragmentTag);
|
||||
selectedNavController.setValue(selectedFragment.getNavController());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
setupItemReselected(bottomNavigationView, graphIdToTagMap, fragmentManager);
|
||||
setupDeepLinks(bottomNavigationView, navGraphIds, fragmentManager, containerId, intent);
|
||||
final int finalFirstFragmentGraphId = firstFragmentGraphId;
|
||||
fragmentManager.addOnBackStackChangedListener(() -> {
|
||||
if (!isOnFirstFragment[0]) {
|
||||
if (firstFragmentTag == null) {
|
||||
return;
|
||||
}
|
||||
if (!isOnBackStack(fragmentManager, firstFragmentTag)) {
|
||||
bottomNavigationView.setSelectedItemId(finalFirstFragmentGraphId);
|
||||
}
|
||||
}
|
||||
|
||||
final NavController navController = selectedNavController.getValue();
|
||||
if (navController != null && navController.getCurrentDestination() == null) {
|
||||
final NavGraph navControllerGraph = navController.getGraph();
|
||||
navController.navigate(navControllerGraph.getId());
|
||||
}
|
||||
});
|
||||
return selectedNavController;
|
||||
}
|
||||
|
||||
private static NavHostFragment obtainNavHostFragment(final FragmentManager fragmentManager,
|
||||
final String fragmentTag,
|
||||
final int navGraphId,
|
||||
final int containerId) {
|
||||
final NavHostFragment existingFragment = (NavHostFragment) fragmentManager.findFragmentByTag(fragmentTag);
|
||||
if (existingFragment != null) {
|
||||
return existingFragment;
|
||||
}
|
||||
final NavHostFragment navHostFragment = NavHostFragment.create(navGraphId);
|
||||
fragmentManager.beginTransaction()
|
||||
.add(containerId, navHostFragment, fragmentTag)
|
||||
.commitNow();
|
||||
return navHostFragment;
|
||||
}
|
||||
|
||||
private static void attachNavHostFragment(final FragmentManager fragmentManager,
|
||||
final NavHostFragment navHostFragment,
|
||||
final boolean isPrimaryNavFragment) {
|
||||
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
|
||||
.attach(navHostFragment);
|
||||
if (isPrimaryNavFragment) {
|
||||
fragmentTransaction.setPrimaryNavigationFragment(navHostFragment);
|
||||
}
|
||||
fragmentTransaction.commitNow();
|
||||
}
|
||||
|
||||
private static void detachNavHostFragment(final FragmentManager fragmentManager, final NavHostFragment navHostFragment) {
|
||||
fragmentManager.beginTransaction()
|
||||
.detach(navHostFragment)
|
||||
.commitNow();
|
||||
}
|
||||
|
||||
private static void setupItemReselected(final BottomNavigationView bottomNavigationView,
|
||||
final SparseArray<String> graphIdToTagMap,
|
||||
final FragmentManager fragmentManager) {
|
||||
bottomNavigationView.setOnNavigationItemReselectedListener(item -> {
|
||||
final String newlySelectedItemTag = graphIdToTagMap.get(item.getItemId());
|
||||
final Fragment fragmentByTag = fragmentManager.findFragmentByTag(newlySelectedItemTag);
|
||||
if (fragmentByTag == null) {
|
||||
throw new NullPointerException("null cannot be cast to non-null type NavHostFragment");
|
||||
}
|
||||
final NavHostFragment selectedFragment = (NavHostFragment) fragmentByTag;
|
||||
final NavController navController = selectedFragment.getNavController();
|
||||
final NavGraph navControllerGraph = navController.getGraph();
|
||||
navController.popBackStack(navControllerGraph.getStartDestination(), false);
|
||||
});
|
||||
}
|
||||
|
||||
private static void setupDeepLinks(final BottomNavigationView bottomNavigationView,
|
||||
final List<Integer> navGraphIds,
|
||||
final FragmentManager fragmentManager,
|
||||
final int containerId,
|
||||
final Intent intent) {
|
||||
for (int i = 0; i < navGraphIds.size(); i++) {
|
||||
final int navGraphId = navGraphIds.get(i);
|
||||
final String fragmentTag = getFragmentTag(i);
|
||||
final NavHostFragment navHostFragment = obtainNavHostFragment(fragmentManager, fragmentTag, navGraphId, containerId);
|
||||
if (navHostFragment.getNavController().handleDeepLink(intent)) {
|
||||
final int selectedItemId = bottomNavigationView.getSelectedItemId();
|
||||
NavController navController = navHostFragment.getNavController();
|
||||
NavGraph graph = navController.getGraph();
|
||||
if (selectedItemId != graph.getId()) {
|
||||
navController = navHostFragment.getNavController();
|
||||
graph = navController.getGraph();
|
||||
bottomNavigationView.setSelectedItemId(graph.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isOnBackStack(final FragmentManager fragmentManager, final String backStackName) {
|
||||
int backStackCount = fragmentManager.getBackStackEntryCount();
|
||||
for (int i = 0; i < backStackCount; i++) {
|
||||
final FragmentManager.BackStackEntry backStackEntry = fragmentManager.getBackStackEntryAt(i);
|
||||
final String name = backStackEntry.getName();
|
||||
if (name != null && name.equals(backStackName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getFragmentTag(final int index) {
|
||||
return "bottomNavigation#" + index;
|
||||
}
|
||||
}
|
@ -71,6 +71,7 @@ import javax.crypto.spec.SecretKeySpec;
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.activities.MainActivity;
|
||||
import awais.instagrabber.activities.MainActivityBackup;
|
||||
import awais.instagrabber.activities.ProfileViewer;
|
||||
import awais.instagrabber.activities.SavedViewer;
|
||||
import awais.instagrabber.asyncs.DownloadAsync;
|
||||
@ -942,7 +943,7 @@ public final class Utils {
|
||||
dir = new File(dir, username);
|
||||
|
||||
if (dir.exists() || dir.mkdirs()) {
|
||||
final MainActivity mainActivity = method != DownloadMethod.DOWNLOAD_FEED && context instanceof MainActivity ? (MainActivity) context : null;
|
||||
final MainActivityBackup mainActivity = method != DownloadMethod.DOWNLOAD_FEED && context instanceof MainActivityBackup ? (MainActivityBackup) context : null;
|
||||
final ProfileViewer pv = method == DownloadMethod.DOWNLOAD_MAIN && context instanceof ProfileViewer ? (ProfileViewer) context : null;
|
||||
final SavedViewer saved = method == DownloadMethod.DOWNLOAD_SAVED && context instanceof SavedViewer ? (SavedViewer) context : null;
|
||||
|
||||
@ -973,19 +974,20 @@ public final class Utils {
|
||||
saveFile,
|
||||
file -> {
|
||||
model.setDownloaded(true);
|
||||
if (saved != null)
|
||||
saved.deselectSelection(selectedItem);
|
||||
else if (mainActivity != null)
|
||||
mainActivity.mainHelper.deselectSelection(selectedItem);
|
||||
else if (pv != null) pv.deselectSelection(selectedItem);
|
||||
// if (saved != null)
|
||||
// saved.deselectSelection(selectedItem);
|
||||
// else if (mainActivity != null)
|
||||
// mainActivity.mainHelper.deselectSelection(selectedItem);
|
||||
// else pv.deselectSelection(selectedItem);
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
} else {
|
||||
if (saved != null) saved.deselectSelection(selectedItem);
|
||||
else if (mainActivity != null)
|
||||
mainActivity.mainHelper.deselectSelection(selectedItem);
|
||||
else if (pv != null) pv.deselectSelection(selectedItem);
|
||||
}
|
||||
// else {
|
||||
// if (saved != null) saved.deselectSelection(selectedItem);
|
||||
// else if (mainActivity != null)
|
||||
// mainActivity.mainHelper.deselectSelection(selectedItem);
|
||||
// else if (pv != null) pv.deselectSelection(selectedItem);
|
||||
// }
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 4.6 KiB |
10
app/src/main/res/drawable/ic_close_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_more_horiz_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M6,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_open_in_new_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,19H5V5h7V3H5c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2v7zM14,3v2h3.59l-9.83,9.83 1.41,1.41L19,6.41V10h2V3h-7z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_comments_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,17.17L18.83,16H4V4h16v13.17zM20,2H4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h14l4,4V4c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_views_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,6.5c3.79,0 7.17,2.13 8.82,5.5 -1.65,3.37 -5.02,5.5 -8.82,5.5S4.83,15.37 3.18,12C4.83,8.63 8.21,6.5 12,6.5m0,-2C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,9.5c1.38,0 2.5,1.12 2.5,2.5s-1.12,2.5 -2.5,2.5 -2.5,-1.12 -2.5,-2.5 1.12,-2.5 2.5,-2.5m0,-2c-2.48,0 -4.5,2.02 -4.5,4.5s2.02,4.5 4.5,4.5 4.5,-2.02 4.5,-4.5 -2.02,-4.5 -4.5,-4.5z"/>
|
||||
</vector>
|
9
app/src/main/res/drawable/ic_star_24.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_volume_off_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v2.21l2.45,2.45c0.03,-0.2 0.05,-0.41 0.05,-0.63zM19,12c0,0.94 -0.2,1.82 -0.54,2.64l1.51,1.51C20.63,14.91 21,13.5 21,12c0,-4.28 -2.99,-7.86 -7,-8.77v2.06c2.89,0.86 5,3.54 5,6.71zM4.27,3L3,4.27 7.73,9L3,9v6h4l5,5v-6.73l4.25,4.25c-0.67,0.52 -1.42,0.93 -2.25,1.18v2.06c1.38,-0.31 2.63,-0.95 3.69,-1.81L19.73,21 21,19.73l-9,-9L4.27,3zM12,4L9.91,6.09 12,8.18L12,4z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_volume_up_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z"/>
|
||||
</vector>
|
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 5.7 KiB |
@ -1,104 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout 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/main_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
tools:context=".activities.MainActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include
|
||||
android:id="@+id/toolbar"
|
||||
layout="@layout/layout_include_toolbar" />
|
||||
|
||||
<awais.instagrabber.customviews.RemixDrawerLayout
|
||||
android:id="@+id/drawerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<!-- Profile View -->
|
||||
<include
|
||||
android:id="@+id/profile_view"
|
||||
layout="@layout/layout_profile_view" />
|
||||
|
||||
<!-- Feed View -->
|
||||
<include
|
||||
android:id="@+id/feed_view"
|
||||
layout="@layout/layout_feed_view" />
|
||||
|
||||
<!-- Discover View -->
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/discoverLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:animateLayoutChanges="true"
|
||||
android:tag="@android:string/yes">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
app:elevation="0dp">
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|snap|enterAlways">
|
||||
app:layout_scrollFlags="scroll|snap|enterAlways"
|
||||
app:titleEnabled="false">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatSpinner
|
||||
android:id="@+id/discoverType"
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Widget.MaterialComponents.Toolbar.PrimarySurface"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:entries="@array/discover_placeholder"/>
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:layout_collapseMode="none"
|
||||
app:popupTheme="@style/Widget.MaterialComponents.Toolbar.PrimarySurface"
|
||||
app:title="@string/app_name" />
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/discoverSwipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:tag="@android:string/yes"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/discoverPosts"
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/main_nav_host"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
tools:listitem="@layout/item_feed_photo" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</awais.instagrabber.customviews.RemixDrawerLayout>
|
||||
</LinearLayout>
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/iconSlider"
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/bottomNavView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
app:srcCompat="@drawable/ic_feed"
|
||||
app:tint="?android:textColorSecondary" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
app:srcCompat="@drawable/ic_profile"
|
||||
app:tint="?android:textColorPrimary" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
app:srcCompat="@drawable/ic_discover"
|
||||
app:tint="?android:textColorSecondary" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
android:layout_gravity="bottom"
|
||||
app:labelVisibilityMode="labeled"
|
||||
app:menu="@menu/main_bottom_navigation_menu" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
104
app/src/main/res/layout/activity_mainbackup.xml
Normal file
@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout 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"
|
||||
tools:context=".activities.MainActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include
|
||||
android:id="@+id/toolbar"
|
||||
layout="@layout/layout_include_toolbar" />
|
||||
|
||||
<awais.instagrabber.customviews.RemixDrawerLayout
|
||||
android:id="@+id/drawerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<!-- Profile View -->
|
||||
<include
|
||||
android:id="@+id/profile_view"
|
||||
layout="@layout/layout_profile_view" />
|
||||
|
||||
<!-- Feed View -->
|
||||
<include
|
||||
android:id="@+id/feed_view"
|
||||
layout="@layout/layout_feed_view" />
|
||||
|
||||
<!-- Discover View -->
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/discoverLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:animateLayoutChanges="true"
|
||||
android:tag="@android:string/yes">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
app:elevation="0dp">
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|snap|enterAlways">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatSpinner
|
||||
android:id="@+id/discoverType"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:entries="@array/discover_placeholder"/>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/discoverSwipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:tag="@android:string/yes"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/discoverPosts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
tools:listitem="@layout/item_feed_photo" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</awais.instagrabber.customviews.RemixDrawerLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/iconSlider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
app:srcCompat="@drawable/ic_feed"
|
||||
app:tint="?android:textColorSecondary" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
app:srcCompat="@drawable/ic_profile"
|
||||
app:tint="?android:textColorPrimary" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
app:srcCompat="@drawable/ic_discover"
|
||||
app:tint="?android:textColorSecondary" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
@ -1,20 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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:orientation="vertical"
|
||||
tools:context=".activities.PostViewer">
|
||||
|
||||
<include
|
||||
android:id="@+id/toolbar"
|
||||
layout="@layout/layout_include_toolbar" />
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/story_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:layout_weight="1"
|
||||
app:layout_constraintBottom_toTopOf="@id/storiesList"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.exoplayer2.ui.PlayerView
|
||||
android:id="@+id/playerView"
|
||||
@ -25,7 +25,7 @@
|
||||
app:controller_layout_id="@layout/layout_controls"
|
||||
app:repeat_toggle_modes="none" />
|
||||
|
||||
<com.github.chrisbanes.photoview.PhotoView
|
||||
<awais.instagrabber.customviews.drawee.ZoomableDraweeView
|
||||
android:id="@+id/imageViewer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@ -42,9 +42,9 @@
|
||||
android:id="@+id/postActions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.3"
|
||||
android:background="#0000"
|
||||
android:layout_gravity="bottom">
|
||||
android:layout_gravity="bottom"
|
||||
android:background="#0000">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/viewStoryPost"
|
||||
android:layout_width="match_parent"
|
||||
@ -54,6 +54,7 @@
|
||||
android:textColor="@color/btn_green_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_green_background" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/poll"
|
||||
android:layout_width="match_parent"
|
||||
@ -63,6 +64,7 @@
|
||||
android:textColor="@color/btn_blue_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_blue_background" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/answer"
|
||||
android:layout_width="match_parent"
|
||||
@ -72,6 +74,7 @@
|
||||
android:textColor="@color/btn_blue_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_blue_background" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/quiz"
|
||||
android:layout_width="match_parent"
|
||||
@ -81,6 +84,7 @@
|
||||
android:textColor="@color/btn_blue_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_blue_background" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/mention"
|
||||
android:layout_width="match_parent"
|
||||
@ -90,6 +94,7 @@
|
||||
android:textColor="@color/btn_orange_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_orange_background" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/spotify"
|
||||
android:layout_width="match_parent"
|
||||
@ -107,9 +112,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:paddingRight="5dp" />
|
||||
</LinearLayout>
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,10 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
<awais.instagrabber.customviews.helpers.NestedCoordinatorLayout 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">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorOnPrimarySurface"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/inbox_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/layout_include_simple_item" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</awais.instagrabber.customviews.helpers.NestedCoordinatorLayout>
|
||||
|
@ -3,6 +3,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
@ -14,7 +15,8 @@
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/messageList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/layout_dm_base"/>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
43
app/src/main/res/layout/fragment_discover.xml
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<awais.instagrabber.customviews.helpers.NestedCoordinatorLayout 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:animateLayoutChanges="true"
|
||||
android:background="?attr/colorOnPrimarySurface">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorOnPrimarySurface"
|
||||
app:elevation="0dp">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|snap|enterAlways">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatSpinner
|
||||
android:id="@+id/discoverType"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:entries="@array/discover_placeholder"
|
||||
android:spinnerMode="dialog" />
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/discoverSwipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/discoverPosts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
tools:listitem="@layout/item_post" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</awais.instagrabber.customviews.helpers.NestedCoordinatorLayout>
|
41
app/src/main/res/layout/fragment_feed.xml
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<awais.instagrabber.customviews.helpers.NestedCoordinatorLayout 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:animateLayoutChanges="true"
|
||||
android:background="?attr/colorOnPrimarySurface">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/stories_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|snap">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/feed_stories_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false" />
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/feed_swipe_refresh_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/feed_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
tools:listitem="@layout/item_feed_photo" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</awais.instagrabber.customviews.helpers.NestedCoordinatorLayout>
|
304
app/src/main/res/layout/fragment_profile.xml
Normal file
@ -0,0 +1,304 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<awais.instagrabber.customviews.helpers.NestedCoordinatorLayout 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:background="?attr/colorOnPrimarySurface">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorOnPrimarySurface">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/infoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/profileInfoText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/profileInfo"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/isVerified"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone"
|
||||
app:srcCompat="@drawable/verified" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainFullName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="marquee"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
||||
android:textSize="16sp"
|
||||
tools:text="Austin Huang" />
|
||||
</LinearLayout>
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
android:id="@+id/mainBiography"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/profileInfoText"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textSize="16sp"
|
||||
tools:text="THE GLORIOUS (step)OWNER OF THIS APP" />
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
android:id="@+id/mainUrl"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/mainBiography"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
tools:text="https://austinhuang.me/" />
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/profileActions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/mainUrl">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnFollow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/follow"
|
||||
android:textColor="@color/btn_pink_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_pink_background" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnRestrict"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/restrict"
|
||||
android:textColor="@color/btn_orange_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_orange_background" />
|
||||
|
||||
<!-- only for invisible private accounts -->
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnBlock"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/block"
|
||||
android:textColor="@color/btn_red_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_red_background" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/myActions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/profileActions">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnTagged"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/tagged"
|
||||
android:textColor="@color/btn_blue_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_blue_background" />
|
||||
|
||||
<!-- also used as block -->
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnSaved"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/saved"
|
||||
android:textColor="@color/btn_orange_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_orange_background" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnLiked"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/liked"
|
||||
android:textColor="@color/btn_lightpink_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_lightpink_background" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/highlightsList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/myActions"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:paddingRight="5dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/profileInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/profile_info_container_bottom_space">
|
||||
|
||||
<awais.instagrabber.customviews.CircularImageView
|
||||
android:id="@+id/mainProfileImage"
|
||||
android:layout_width="@dimen/profile_picture_size"
|
||||
android:layout_height="@dimen/profile_picture_size" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainPostCount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
android:textSize="15sp"
|
||||
tools:text="35\nPosts" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainFollowers"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
android:textSize="15sp"
|
||||
tools:text="68\nFollowers" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainFollowing"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_weight="1"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
android:textSize="15sp"
|
||||
tools:text="64\nFollowing" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/mainPosts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
tools:listitem="@layout/item_post" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/privatePage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="@dimen/private_page_margins"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/privatePage1"
|
||||
android:layout_width="@dimen/private_page_margins"
|
||||
android:layout_height="@dimen/private_page_margins"
|
||||
app:srcCompat="@drawable/lock" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/privatePage2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/priv_acc"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
</LinearLayout>
|
||||
</awais.instagrabber.customviews.helpers.NestedCoordinatorLayout>
|
@ -1,117 +1,100 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<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="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/top_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/btnComments"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:orientation="horizontal">
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="4dp">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
app:srcCompat="@drawable/comments" />
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="4dp"
|
||||
app:srcCompat="@drawable/ic_outline_comments_24"
|
||||
app:tint="?android:textColorPrimary" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/commentsCount"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="2dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textAppearance="?attr/textAppearanceButton"
|
||||
tools:text="690000" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/videoViewsContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_toEndOf="@id/btnComments"
|
||||
android:layout_toRightOf="@id/btnComments"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="48dp"
|
||||
app:srcCompat="@drawable/video_views" />
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="4dp"
|
||||
app:srcCompat="@drawable/ic_outline_views_24"
|
||||
app:tint="?android:textColorPrimary" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/tvVideoViews"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="2dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textAppearance="?attr/textAppearanceButton"
|
||||
tools:text="690000" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignEnd="@id/btnMute"
|
||||
android:layout_alignRight="@id/btnMute"
|
||||
android:layout_marginEnd="48dp"
|
||||
android:layout_marginRight="48dp"
|
||||
android:layout_toEndOf="@id/videoViewsContainer"
|
||||
android:layout_toRightOf="@id/videoViewsContainer">
|
||||
|
||||
<View
|
||||
android:layout_width="1dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="2dp"
|
||||
android:layout_marginLeft="2dp"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:layout_marginRight="2dp"
|
||||
android:background="?android:attr/dividerVertical" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/tvPostDate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="4dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:maxLines="1"
|
||||
android:padding="8dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||
tools:text="690000" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/btnMute"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
android:layout_toStartOf="@id/btnDownload"
|
||||
android:layout_toLeftOf="@id/btnDownload"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="8dp"
|
||||
android:visibility="gone"
|
||||
app:srcCompat="@drawable/vol" />
|
||||
android:padding="4dp"
|
||||
android:visibility="visible"
|
||||
app:srcCompat="@drawable/ic_volume_up_24"
|
||||
app:tint="?android:textColorPrimary" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/btnDownload"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="4dp"
|
||||
app:srcCompat="@drawable/ic_download" />
|
||||
app:srcCompat="@drawable/ic_download"
|
||||
app:tint="?android:textColorPrimary" />
|
||||
</LinearLayout>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/btnDownload"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:isScrollContainer="true"
|
||||
android:scrollbars="vertical"
|
||||
android:scrollHorizontally="false">
|
||||
@ -129,10 +112,13 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:clipToPadding="false"
|
||||
android:padding="12dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textSize="16sp"
|
||||
tools:text="BOTTOM TEXT" />
|
||||
</FrameLayout>
|
||||
</ScrollView>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
@ -8,11 +8,6 @@
|
||||
android:id="@+id/item_feed_top"
|
||||
layout="@layout/item_feed_top" />
|
||||
|
||||
<!--<com.github.chrisbanes.photoview.PhotoView-->
|
||||
<!-- android:id="@+id/imageViewer"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="wrap_content" />-->
|
||||
|
||||
<awais.instagrabber.customviews.drawee.ZoomableDraweeView
|
||||
android:id="@+id/imageViewer"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -1,17 +1,19 @@
|
||||
<?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:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.facebook.drawee.view.SimpleDraweeView
|
||||
android:id="@+id/ivProfilePic"
|
||||
android:layout_width="@dimen/feed_profile_size"
|
||||
android:layout_height="@dimen/feed_profile_size"
|
||||
app:roundAsCircle="true"
|
||||
android:background="?selectableItemBackgroundBorderless" />
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
app:roundAsCircle="true" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/infoContainer"
|
||||
@ -21,10 +23,10 @@
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@null"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:weightSum="2">
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
@ -32,8 +34,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:textColor="@color/feed_text_primary_color"
|
||||
android:textSize="18sp" />
|
||||
tools:text="username" />
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
android:id="@+id/location"
|
||||
@ -41,14 +44,17 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/title"
|
||||
android:gravity="center_vertical"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||
android:textColor="@color/feed_text_primary_color"
|
||||
android:textSize="18sp" />
|
||||
tools:text="location" />
|
||||
</RelativeLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/viewStoryPost"
|
||||
android:layout_width="40dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
app:srcCompat="@android:drawable/ic_menu_set_as" />
|
||||
app:srcCompat="@drawable/ic_open_in_new_24"
|
||||
app:tint="?android:textColorPrimary" />
|
||||
</LinearLayout>
|
@ -3,11 +3,9 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="@dimen/profile_picture_size"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_margin="8dp"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:orientation="vertical"
|
||||
tools:viewBindingIgnore="true">
|
||||
android:orientation="vertical">
|
||||
|
||||
<awais.instagrabber.customviews.CircularImageView
|
||||
android:id="@+id/icon"
|
||||
@ -20,11 +18,10 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:padding="2dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textStyle="bold" />
|
||||
android:textColor="?android:textColorPrimaryInverse"
|
||||
android:textStyle="bold"
|
||||
tools:text="@string/app_name" />
|
||||
</LinearLayout>
|
@ -1,18 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout 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="wrap_content"
|
||||
android:foreground="?android:selectableItemBackground"
|
||||
tools:viewBindingIgnore="true">
|
||||
android:foreground="?android:selectableItemBackground">
|
||||
|
||||
<awais.instagrabber.customviews.FixedImageView
|
||||
<com.facebook.drawee.view.SimpleDraweeView
|
||||
android:id="@+id/postImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitCenter" />
|
||||
app:actualImageScaleType="fitCenter"
|
||||
app:viewAspectRatio="1"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/isDownloaded"
|
||||
@ -31,12 +29,12 @@
|
||||
android:layout_margin="8dp"
|
||||
app:srcCompat="@drawable/video" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressView"
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="45dp"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone" />
|
||||
<!--<ProgressBar-->
|
||||
<!-- android:id="@+id/progressView"-->
|
||||
<!-- android:layout_width="45dp"-->
|
||||
<!-- android:layout_height="45dp"-->
|
||||
<!-- android:layout_gravity="center"-->
|
||||
<!-- android:visibility="gone" />-->
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/selectedView"
|
||||
|
@ -1,24 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="@dimen/story_item_width"
|
||||
android:layout_height="@dimen/story_item_height"
|
||||
android:layout_marginStart="2dp"
|
||||
android:layout_marginLeft="2dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:layout_marginRight="2dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?android:selectableItemBackground"
|
||||
tools:viewBindingIgnore="true">
|
||||
android:layout_margin="8dp"
|
||||
android:foreground="?android:selectableItemBackground">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
<com.facebook.drawee.view.SimpleDraweeView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitCenter" />
|
||||
app:actualImageScaleType="fitCenter" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/selectedView"
|
||||
|
30
app/src/main/res/menu/main_bottom_navigation_menu.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/direct_messages_nav_graph"
|
||||
android:icon="@drawable/ic_send_24"
|
||||
android:title="@string/title_dm" />
|
||||
<item
|
||||
android:id="@+id/feed_nav_graph"
|
||||
android:icon="@drawable/ic_feed"
|
||||
android:title="@string/feed" />
|
||||
<item
|
||||
android:id="@+id/profile_nav_graph"
|
||||
android:icon="@drawable/ic_profile"
|
||||
android:title="@string/profile" />
|
||||
|
||||
<item
|
||||
android:id="@+id/discover_nav_graph"
|
||||
android:icon="@drawable/ic_discover"
|
||||
android:title="@string/title_discover" />
|
||||
|
||||
<!--<item-->
|
||||
<!-- android:id="@+id/favouritesFragment"-->
|
||||
<!-- android:icon="@drawable/ic_star_24"-->
|
||||
<!-- android:title="@string/title_favorites"/>-->
|
||||
|
||||
<item
|
||||
android:id="@+id/moreFragment"
|
||||
android:icon="@drawable/ic_more_horiz_24"
|
||||
android:title="@string/more" />
|
||||
</menu>
|
18
app/src/main/res/menu/main_menu.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/favourites"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_star_24"
|
||||
android:title="@string/title_favorites"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<!--<item-->
|
||||
<!-- android:id="@+id/direct_messages"-->
|
||||
<!-- android:enabled="true"-->
|
||||
<!-- android:icon="@drawable/ic_send_24"-->
|
||||
<!-- android:title="@string/action_dms"-->
|
||||
<!-- app:showAsAction="always" />-->
|
||||
|
||||
</menu>
|
11
app/src/main/res/menu/multi_select_download_menu.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
|
||||
android:id="@+id/action_download"
|
||||
android:icon="@drawable/ic_download"
|
||||
android:title="@string/action_download"
|
||||
android:titleCondensed="@string/action_download"
|
||||
app:showAsAction="always" />
|
||||
</menu>
|
17
app/src/main/res/menu/story_menu.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_download"
|
||||
android:icon="@drawable/ic_download"
|
||||
android:title="@string/action_download"
|
||||
android:titleCondensed="@string/action_download"
|
||||
app:showAsAction="always" />
|
||||
<item
|
||||
android:id="@+id/action_dms"
|
||||
android:icon="@drawable/ic_send_24"
|
||||
android:title="@string/action_dms"
|
||||
android:titleCondensed="@string/action_dms"
|
||||
app:showAsAction="ifRoom" />
|
||||
</menu>
|
@ -1,13 +1,15 @@
|
||||
<?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/direct_messages_nav_graph"
|
||||
app:startDestination="@id/directMessagesInboxFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/directMessagesInboxFragment"
|
||||
android:name="awais.instagrabber.fragments.directmessages.DirectMessageInboxFragment"
|
||||
android:label="DirectMessagesInboxFragment" >
|
||||
android:label="@string/action_dms"
|
||||
tools:layout="@layout/fragment_direct_messages_inbox">
|
||||
<action
|
||||
android:id="@+id/action_dMInboxFragment_to_dMThreadFragment"
|
||||
app:destination="@id/directMessagesThreadFragment" />
|
||||
@ -15,7 +17,8 @@
|
||||
<fragment
|
||||
android:id="@+id/directMessagesThreadFragment"
|
||||
android:name="awais.instagrabber.fragments.directmessages.DirectMessageThreadFragment"
|
||||
android:label="DirectMessagesThreadFragment">
|
||||
android:label="DirectMessagesThreadFragment"
|
||||
tools:layout="@layout/fragment_direct_messages_thread">
|
||||
<argument
|
||||
android:name="threadId"
|
||||
app:argType="string" />
|
||||
@ -29,7 +32,8 @@
|
||||
<fragment
|
||||
android:id="@+id/directMessagesSettingsFragment"
|
||||
android:name="awais.instagrabber.fragments.directmessages.DirectMessageSettingsFragment"
|
||||
android:label="DirectMessagesSettingsFragment">
|
||||
android:label="DirectMessagesSettingsFragment"
|
||||
tools:layout="@layout/fragment_direct_messages_settings">
|
||||
<argument
|
||||
android:name="threadId"
|
||||
app:argType="string" />
|
||||
|
11
app/src/main/res/navigation/discover_nav_graph.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?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"
|
||||
android:id="@+id/discover_nav_graph"
|
||||
app:startDestination="@id/discoverFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/discoverFragment"
|
||||
android:name="awais.instagrabber.fragments.main.DiscoverFragment"
|
||||
android:label="DiscoverFragment" />
|
||||
</navigation>
|
47
app/src/main/res/navigation/feed_nav_graph.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?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/feed_nav_graph"
|
||||
app:startDestination="@id/feedFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/feedFragment"
|
||||
android:name="awais.instagrabber.fragments.main.FeedFragment"
|
||||
android:label="FeedFragment"
|
||||
tools:layout="@layout/fragment_feed">
|
||||
<action
|
||||
android:id="@+id/action_feedFragment_to_storyViewerFragment"
|
||||
app:destination="@id/storyViewerFragment" />
|
||||
<action
|
||||
android:id="@+id/action_feedFragment_to_profileFragment"
|
||||
app:destination="@id/profileFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/storyViewerFragment"
|
||||
android:name="awais.instagrabber.fragments.StoryViewerFragment"
|
||||
android:label="StoryViewerFragment"
|
||||
tools:layout="@layout/activity_story_viewer">
|
||||
<argument
|
||||
android:name="feedStoryIndex"
|
||||
app:argType="integer"
|
||||
app:nullable="false" />
|
||||
<argument
|
||||
android:name="highlight"
|
||||
app:argType="string"
|
||||
app:nullable="true" />
|
||||
<argument
|
||||
android:name="isHashtag"
|
||||
app:argType="boolean" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/profileFragment"
|
||||
android:name="awais.instagrabber.fragments.main.ProfileFragment"
|
||||
android:label="ProfileFragment"
|
||||
tools:layout="@layout/fragment_profile">
|
||||
<argument
|
||||
android:name="username"
|
||||
app:argType="string"
|
||||
app:nullable="false" />
|
||||
</fragment>
|
||||
</navigation>
|
12
app/src/main/res/navigation/profile_nav_graph.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?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/profile_nav_graph"
|
||||
app:startDestination="@id/profileFragment">
|
||||
<fragment
|
||||
android:id="@+id/profileFragment"
|
||||
android:name="awais.instagrabber.fragments.main.ProfileFragment"
|
||||
android:label="@string/profile"
|
||||
tools:layout="@layout/fragment_profile" />
|
||||
</navigation>
|
@ -19,4 +19,6 @@
|
||||
<dimen name="message_item_profile_size">@dimen/feed_profile_size</dimen>
|
||||
<dimen name="dm_media_img_max_height">500dp</dimen>
|
||||
<dimen name="dm_message_card_radius">8dp</dimen>
|
||||
|
||||
<dimen name="feed_item_bottom_icon_size">32dp</dimen>
|
||||
</resources>
|
@ -234,4 +234,9 @@
|
||||
<string name="activity_count_usertags">%d usertags</string>
|
||||
<string name="activity_count_likes">%d likes</string>
|
||||
<string name="activity_notloggedin">You logged out before clicking this notification?!</string>
|
||||
<string name="feed">Feed</string>
|
||||
<string name="profile">Profile</string>
|
||||
<string name="more">More</string>
|
||||
<string name="title_dm">DM</string>
|
||||
<string name="number_selected">%d selected</string>
|
||||
</resources>
|
||||
|
@ -1,11 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<item name="bottomSheetDialogTheme">@style/AppTheme.BottomSheetDialog</item>
|
||||
<item name="android:windowAnimationStyle">@style/AppTheme.WindowAnimationTransition</item>
|
||||
</style>
|
||||
|
||||
<style name="CompletelyTransparent" parent="Theme.AppCompat.NoActionBar">
|
||||
<item name="android:background">@null</item>
|
||||
<item name="android:backgroundDimEnabled">false</item>
|
||||
@ -34,4 +29,16 @@
|
||||
<item name="android:windowEnterAnimation">@android:anim/fade_in</item>
|
||||
<item name="android:windowExitAnimation">@android:anim/fade_out</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.BottomNavigationView" parent="@style/Widget.MaterialComponents.BottomNavigationView.PrimarySurface">
|
||||
<item name="materialThemeOverlay">@style/ThemeOverlay.App.BottomNavigationView</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.App.BottomNavigationView" parent="" />
|
||||
|
||||
<style name="Widget.App.ActionMode" parent="Widget.AppCompat.ActionMode">
|
||||
<item name="titleTextStyle">?attr/textAppearanceHeadline6</item>
|
||||
<item name="subtitleTextStyle">?attr/textAppearanceSubtitle1</item>
|
||||
<item name="background">?attr/colorPrimary</item>
|
||||
</style>
|
||||
</resources>
|
||||
|