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