-
9app/src/main/AndroidManifest.xml
-
79app/src/main/java/awais/instagrabber/MainHelper.java
-
4app/src/main/java/awais/instagrabber/activities/CommentsViewer.java
-
3app/src/main/java/awais/instagrabber/activities/Main.java
-
6app/src/main/java/awais/instagrabber/activities/PostViewer.java
-
234app/src/main/java/awais/instagrabber/activities/SavedViewer.java
-
13app/src/main/java/awais/instagrabber/activities/StoryViewer.java
-
14app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java
-
3app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java
-
10app/src/main/java/awais/instagrabber/models/StoryModel.java
-
3app/src/main/java/awais/instagrabber/models/enums/DownloadMethod.java
-
1app/src/main/java/awais/instagrabber/models/enums/ItemGetType.java
-
40app/src/main/java/awais/instagrabber/utils/Utils.java
-
1app/src/main/java/awaisomereport/LogCollector.java
-
10app/src/main/res/drawable-anydpi/ic_bookmark.xml
-
10app/src/main/res/drawable-anydpi/ic_like.xml
-
BINapp/src/main/res/drawable-hdpi/ic_bookmark.png
-
BINapp/src/main/res/drawable-hdpi/ic_like.png
-
BINapp/src/main/res/drawable-mdpi/ic_bookmark.png
-
BINapp/src/main/res/drawable-mdpi/ic_like.png
-
BINapp/src/main/res/drawable-xhdpi/ic_bookmark.png
-
BINapp/src/main/res/drawable-xhdpi/ic_like.png
-
BINapp/src/main/res/drawable-xxhdpi/ic_bookmark.png
-
BINapp/src/main/res/drawable-xxhdpi/ic_like.png
-
55app/src/main/res/layout/activity_main.xml
-
31app/src/main/res/layout/activity_saved.xml
-
11app/src/main/res/layout/activity_story_viewer.xml
-
10app/src/main/res/layout/layout_include_toolbar.xml
-
9app/src/main/res/menu/saved.xml
-
6app/src/main/res/values/strings.xml
@ -0,0 +1,234 @@ |
|||
package awais.instagrabber.activities; |
|||
|
|||
import android.content.Intent; |
|||
import android.content.pm.PackageManager; |
|||
import android.content.res.Resources; |
|||
import android.os.AsyncTask; |
|||
import android.os.Bundle; |
|||
import android.util.Log; |
|||
import android.view.Menu; |
|||
import android.view.MenuItem; |
|||
import android.view.View; |
|||
import android.widget.Toast; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.annotation.Nullable; |
|||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.Arrays; |
|||
|
|||
import awais.instagrabber.BuildConfig; |
|||
import awais.instagrabber.R; |
|||
import awais.instagrabber.adapters.PostsAdapter; |
|||
import awais.instagrabber.asyncs.PostsFetcher; |
|||
import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager; |
|||
import awais.instagrabber.customviews.helpers.GridSpacingItemDecoration; |
|||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader; |
|||
import awais.instagrabber.databinding.ActivitySavedBinding; |
|||
import awais.instagrabber.interfaces.FetchListener; |
|||
import awais.instagrabber.interfaces.ItemGetter; |
|||
import awais.instagrabber.models.BasePostModel; |
|||
import awais.instagrabber.models.PostModel; |
|||
import awais.instagrabber.models.enums.DownloadMethod; |
|||
import awais.instagrabber.models.enums.ItemGetType; |
|||
import awais.instagrabber.utils.Constants; |
|||
import awais.instagrabber.utils.Utils; |
|||
import awaisomereport.LogCollector; |
|||
|
|||
import static awais.instagrabber.utils.Constants.AUTOLOAD_POSTS; |
|||
import static awais.instagrabber.utils.Utils.logCollector; |
|||
|
|||
public final class SavedViewer extends BaseLanguageActivity implements SwipeRefreshLayout.OnRefreshListener { |
|||
private static AsyncTask<?, ?, ?> currentlyExecuting; |
|||
public static ItemGetter itemGetter; |
|||
private PostsAdapter postsAdapter; |
|||
private boolean hasNextPage, autoloadPosts; |
|||
//private CommentModel commentModel; |
|||
private ActivitySavedBinding savedBinding; |
|||
private String action, username, endCursor; |
|||
private final String cookie = Utils.settingsHelper.getString(Constants.COOKIE); |
|||
private RecyclerLazyLoader lazyLoader; |
|||
private Resources resources; |
|||
private ArrayList<PostModel> selectedItems = new ArrayList<>(); |
|||
private final ArrayList<PostModel> allItems = new ArrayList<>(); |
|||
private MenuItem downloadAction; |
|||
|
|||
private final FetchListener<PostModel[]> postsFetchListener = new FetchListener<PostModel[]>() { |
|||
@Override |
|||
public void onResult(final PostModel[] result) { |
|||
if (result != null) { |
|||
final int oldSize = allItems.size(); |
|||
allItems.addAll(Arrays.asList(result)); |
|||
|
|||
postsAdapter.notifyItemRangeInserted(oldSize, result.length); |
|||
|
|||
savedBinding.mainPosts.post(() -> { |
|||
savedBinding.mainPosts.setNestedScrollingEnabled(true); |
|||
savedBinding.mainPosts.setVisibility(View.VISIBLE); |
|||
}); |
|||
|
|||
final PostModel model = result[result.length - 1]; |
|||
if (model != null) { |
|||
endCursor = model.getEndCursor(); |
|||
|
|||
hasNextPage = model.hasNextPage(); |
|||
if (autoloadPosts && hasNextPage) |
|||
currentlyExecuting = new PostsFetcher(action, endCursor, this) |
|||
.setUsername(username).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
|||
else { |
|||
savedBinding.swipeRefreshLayout.setRefreshing(false); |
|||
} |
|||
model.setPageCursor(false, null); |
|||
} |
|||
} |
|||
else { |
|||
savedBinding.swipeRefreshLayout.setRefreshing(false); |
|||
Toast.makeText(getApplicationContext(), R.string.empty_list, Toast.LENGTH_SHORT).show(); |
|||
finish(); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
@Override |
|||
protected void onCreate(@Nullable final Bundle savedInstanceState) { |
|||
super.onCreate(savedInstanceState); |
|||
savedBinding = ActivitySavedBinding.inflate(getLayoutInflater()); |
|||
setContentView(savedBinding.getRoot()); |
|||
savedBinding.swipeRefreshLayout.setOnRefreshListener(this); |
|||
autoloadPosts = Utils.settingsHelper.getBoolean(AUTOLOAD_POSTS); |
|||
savedBinding.mainPosts.setNestedScrollingEnabled(false); |
|||
final GridAutofitLayoutManager layoutManager = new GridAutofitLayoutManager(this, Utils.convertDpToPx(110)); |
|||
savedBinding.mainPosts.setLayoutManager(layoutManager); |
|||
savedBinding.mainPosts.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4))); |
|||
|
|||
final Intent intent = getIntent(); |
|||
if (intent == null || !intent.hasExtra(Constants.EXTRAS_INDEX) |
|||
|| Utils.isEmpty((action = intent.getStringExtra(Constants.EXTRAS_INDEX))) |
|||
|| !intent.hasExtra(Constants.EXTRAS_USER) |
|||
|| Utils.isEmpty((username = intent.getStringExtra(Constants.EXTRAS_USER)))) { |
|||
Utils.errorFinish(this); |
|||
return; |
|||
} |
|||
|
|||
savedBinding.mainPosts.setAdapter(postsAdapter = new PostsAdapter(allItems, v -> { |
|||
final Object tag = v.getTag(); |
|||
if (tag instanceof PostModel) { |
|||
final PostModel postModel = (PostModel) tag; |
|||
|
|||
if (postsAdapter.isSelecting) toggleSelection(postModel); |
|||
else startActivity(new Intent(this, PostViewer.class) |
|||
.putExtra(Constants.EXTRAS_INDEX, postModel.getPosition()) |
|||
.putExtra(Constants.EXTRAS_POST, postModel) |
|||
.putExtra(Constants.EXTRAS_USER, username) |
|||
.putExtra(Constants.EXTRAS_TYPE, ItemGetType.SAVED_ITEMS)); |
|||
} |
|||
}, v -> { |
|||
final Object tag = v.getTag(); |
|||
if (tag instanceof PostModel) { |
|||
postsAdapter.isSelecting = true; |
|||
toggleSelection((PostModel) tag); |
|||
} |
|||
return true; |
|||
})); |
|||
savedBinding.swipeRefreshLayout.setRefreshing(true); |
|||
setSupportActionBar(savedBinding.toolbar.toolbar); |
|||
savedBinding.toolbar.toolbar.setTitle((action.charAt(0) == '$' ? R.string.saved : |
|||
(action.charAt(0) == '%' ? R.string.tagged : R.string.liked))); |
|||
savedBinding.toolbar.toolbar.setSubtitle(username); |
|||
|
|||
lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { |
|||
if (!autoloadPosts && hasNextPage) { |
|||
savedBinding.swipeRefreshLayout.setRefreshing(true); |
|||
stopCurrentExecutor(); |
|||
currentlyExecuting = new PostsFetcher(action, endCursor, postsFetchListener) |
|||
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
|||
endCursor = null; |
|||
} |
|||
}); |
|||
savedBinding.mainPosts.addOnScrollListener(lazyLoader); |
|||
|
|||
itemGetter = itemGetType -> { |
|||
if (itemGetType == ItemGetType.SAVED_ITEMS) return allItems; |
|||
return null; |
|||
}; |
|||
|
|||
new PostsFetcher(action, postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
|||
} |
|||
|
|||
@Override |
|||
public boolean onCreateOptionsMenu(final Menu menu) { |
|||
getMenuInflater().inflate(R.menu.saved, menu); |
|||
|
|||
downloadAction = menu.findItem(R.id.downloadAction); |
|||
downloadAction.setVisible(false); |
|||
|
|||
downloadAction.setOnMenuItemClickListener(item -> { |
|||
if (selectedItems.size() > 0) { |
|||
Utils.batchDownload(this, null, DownloadMethod.DOWNLOAD_SAVED, selectedItems); |
|||
} |
|||
return true; |
|||
}); |
|||
return true; |
|||
} |
|||
|
|||
public void deselectSelection(final BasePostModel postModel) { |
|||
if (postModel instanceof PostModel) { |
|||
selectedItems.remove(postModel); |
|||
postModel.setSelected(false); |
|||
if (postsAdapter != null) notifyAdapter((PostModel) postModel); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onRefresh() { |
|||
if (lazyLoader != null) lazyLoader.resetState(); |
|||
stopCurrentExecutor(); |
|||
allItems.clear(); |
|||
selectedItems.clear(); |
|||
if (postsAdapter != null) { |
|||
postsAdapter.isSelecting = false; |
|||
postsAdapter.notifyDataSetChanged(); |
|||
} |
|||
savedBinding.swipeRefreshLayout.setRefreshing(true); |
|||
new PostsFetcher(action, postsFetchListener).setUsername(username).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
|||
} |
|||
|
|||
@Override |
|||
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) { |
|||
super.onRequestPermissionsResult(requestCode, permissions, grantResults); |
|||
if (requestCode == 8020 && grantResults[0] == PackageManager.PERMISSION_GRANTED && selectedItems.size() > 0) |
|||
Utils.batchDownload(this, null, DownloadMethod.DOWNLOAD_SAVED, selectedItems); |
|||
} |
|||
|
|||
public static void stopCurrentExecutor() { |
|||
if (currentlyExecuting != null) { |
|||
try { |
|||
currentlyExecuting.cancel(true); |
|||
} catch (final Exception e) { |
|||
if (logCollector != null) |
|||
logCollector.appendException(e, LogCollector.LogFile.MAIN_HELPER, "stopCurrentExecutor"); |
|||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void toggleSelection(final PostModel postModel) { |
|||
if (postModel != null && postsAdapter != null) { |
|||
if (postModel.isSelected()) selectedItems.remove(postModel); |
|||
else selectedItems.add(postModel); |
|||
postModel.setSelected(!postModel.isSelected()); |
|||
notifyAdapter(postModel); |
|||
} |
|||
} |
|||
|
|||
private void notifyAdapter(final PostModel postModel) { |
|||
if (selectedItems.size() < 1) postsAdapter.isSelecting = false; |
|||
if (postModel.getPosition() < 0) postsAdapter.notifyDataSetChanged(); |
|||
else postsAdapter.notifyItemChanged(postModel.getPosition(), postModel); |
|||
|
|||
if (downloadAction != null) { |
|||
downloadAction.setVisible(postsAdapter.isSelecting); |
|||
} |
|||
} |
|||
} |
@ -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="#333333"> |
|||
<path |
|||
android:fillColor="@android:color/white" |
|||
android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z"/> |
|||
</vector> |
@ -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="#333333"> |
|||
<path |
|||
android:fillColor="@android:color/white" |
|||
android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/> |
|||
</vector> |
After Width: 36 | Height: 36 | Size: 210 B |
After Width: 36 | Height: 36 | Size: 333 B |
After Width: 24 | Height: 24 | Size: 160 B |
After Width: 24 | Height: 24 | Size: 239 B |
After Width: 48 | Height: 48 | Size: 264 B |
After Width: 48 | Height: 48 | Size: 415 B |
After Width: 72 | Height: 72 | Size: 380 B |
After Width: 72 | Height: 72 | Size: 570 B |
@ -0,0 +1,31 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:app="http://schemas.android.com/apk/res-auto" |
|||
xmlns:tools="http://schemas.android.com/tools" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:orientation="vertical" |
|||
tools:context=".activities.SavedViewer"> |
|||
|
|||
<include |
|||
android:id="@+id/toolbar" |
|||
layout="@layout/layout_include_toolbar" /> |
|||
|
|||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout |
|||
android:id="@+id/swipeRefreshLayout" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:tag="@android:string/yes"> |
|||
|
|||
<androidx.recyclerview.widget.RecyclerView |
|||
android:id="@+id/mainPosts" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:clipToPadding="false" |
|||
android:paddingStart="8dp" |
|||
android:paddingLeft="8dp" |
|||
android:paddingEnd="8dp" |
|||
android:paddingRight="8dp" |
|||
tools:listitem="@layout/item_post" /> |
|||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> |
|||
</LinearLayout> |
@ -0,0 +1,9 @@ |
|||
<?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/downloadAction" |
|||
android:icon="@drawable/ic_download" |
|||
app:showAsAction="always|collapseActionView" /> |
|||
</menu> |