Browse Source

v16.7

legacy
Austin Huang 4 years ago
parent
commit
394ffe19b7
No known key found for this signature in database GPG Key ID: 84C23AA04587A91F
  1. 7
      app/build.gradle
  2. 165
      app/src/main/java/awais/instagrabber/MainHelper.java
  3. 11
      app/src/main/java/awais/instagrabber/activities/DirectMessagesUserInbox.java
  4. 25
      app/src/main/java/awais/instagrabber/activities/FollowViewer.java
  5. 33
      app/src/main/java/awais/instagrabber/activities/Main.java
  6. 55
      app/src/main/java/awais/instagrabber/activities/PostViewer.java
  7. 3
      app/src/main/java/awais/instagrabber/activities/StoryViewer.java
  8. 2
      app/src/main/java/awais/instagrabber/adapters/DirectMessagesAdapter.java
  9. 2
      app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java
  10. 3
      app/src/main/java/awais/instagrabber/adapters/MessageItemsAdapter.java
  11. 1
      app/src/main/java/awais/instagrabber/adapters/SuggestionsAdapter.java
  12. 6
      app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java
  13. 2
      app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java
  14. 2
      app/src/main/java/awais/instagrabber/asyncs/FeedStoriesFetcher.java
  15. 6
      app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java
  16. 2
      app/src/main/java/awais/instagrabber/dialogs/SettingsDialog.java
  17. 4
      app/src/main/java/awais/instagrabber/models/BasePostModel.java
  18. 14
      app/src/main/java/awais/instagrabber/models/PostModel.java
  19. 28
      app/src/main/java/awais/instagrabber/models/ProfileModel.java
  20. 14
      app/src/main/java/awais/instagrabber/models/ViewerPostModel.java
  21. 138
      app/src/main/java/awais/instagrabber/utils/MyApps.java
  22. 2
      app/src/main/java/awais/instagrabber/utils/SettingsHelper.java
  23. 6
      app/src/main/java/awais/instagrabber/utils/Utils.java
  24. 26
      app/src/main/res/drawable/ic_cancel.xml
  25. 82
      app/src/main/res/layout/activity_main.xml
  26. 9
      app/src/main/res/layout/activity_viewer.xml
  27. 2
      app/src/main/res/menu/menu.xml
  28. 2
      app/src/main/res/values-es/arrays.xml
  29. 1
      app/src/main/res/values-es/strings.xml
  30. 2
      app/src/main/res/values-fr/arrays.xml
  31. 1
      app/src/main/res/values-fr/strings.xml
  32. 2
      app/src/main/res/values-in/arrays.xml
  33. 1
      app/src/main/res/values-in/strings.xml
  34. 2
      app/src/main/res/values-it/arrays.xml
  35. 1
      app/src/main/res/values-it/strings.xml
  36. 4
      app/src/main/res/values-zh/arrays.xml
  37. 58
      app/src/main/res/values-zh/strings.xml
  38. 2
      app/src/main/res/values/arrays.xml
  39. 5
      app/src/main/res/values/color.xml
  40. 13
      app/src/main/res/values/strings.xml
  41. 1
      fastlane/metadata/android/changelogs/1.txt
  42. 7
      fastlane/metadata/android/changelogs/31.txt
  43. BIN
      gradle/wrapper/gradle-wrapper.jar
  44. 4
      gradle/wrapper/gradle-wrapper.properties
  45. 51
      gradlew
  46. 18
      gradlew.bat

7
app/build.gradle

@ -9,8 +9,11 @@ android {
minSdkVersion 16
targetSdkVersion 29
versionCode 27
versionName '16.6'
// REMEMBER TO CHANGE versionCode as well
// 16.7 is 31
versionCode 31
versionName '16.7'
multiDexEnabled true

165
app/src/main/java/awais/instagrabber/MainHelper.java

@ -26,7 +26,6 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.core.view.GravityCompat;
@ -34,15 +33,14 @@ import androidx.core.widget.ImageViewCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
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.SimpleExoPlayer;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.shape.MaterialShapeDrawable;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import awais.instagrabber.activities.FollowViewer;
@ -85,9 +83,6 @@ import static awais.instagrabber.utils.Constants.AUTOLOAD_POSTS;
import static awais.instagrabber.utils.Constants.BOTTOM_TOOLBAR;
import static awais.instagrabber.utils.Utils.logCollector;
import java.io.InputStream;
import java.net.URL;
public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
private static AsyncTask<?, ?, ?> currentlyExecuting;
private AsyncTask<Void, Void, FeedStoryModel[]> prevStoriesFetcher;
@ -148,6 +143,12 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
model.setPageCursor(false, null);
}
}
else {
main.mainBinding.swipeRefreshLayout.setRefreshing(false);
main.mainBinding.privatePage1.setImageResource(R.drawable.ic_cancel);
main.mainBinding.privatePage2.setText(R.string.empty_acc);
main.mainBinding.privatePage.setVisibility(View.VISIBLE);
}
}
};
private final FetchListener<FeedModel[]> feedFetchListener = new FetchListener<FeedModel[]>() {
@ -403,7 +404,6 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
}
if (color == -1 || color == 0) color = resources.getBoolean(R.bool.isNight) ? 0xff212121 : 0xfff5f5f5;
main.mainBinding.profileInfo.setBackgroundColor(color);
main.mainBinding.profileInfo.setClickable(true);
if (!isBottomToolbar) main.mainBinding.toolbar.toolbar.setBackgroundColor(color);
main.mainBinding.appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@ -628,6 +628,9 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
main.mainBinding.mainBiography.setMentionClickListener(null);
main.mainBinding.mainUrl.setVisibility(View.GONE);
main.mainBinding.isVerified.setVisibility(View.GONE);
main.mainBinding.btnFollow.setVisibility(View.GONE);
main.mainBinding.btnRestrict.setVisibility(View.GONE);
main.mainBinding.btnBlock.setVisibility(View.GONE);
main.mainBinding.mainPosts.setNestedScrollingEnabled(false);
main.mainBinding.highlightsList.setVisibility(View.GONE);
@ -666,7 +669,8 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
main.mainBinding.isVerified.setVisibility(profileModel.isVerified() ? View.VISIBLE : View.GONE);
final String profileId = profileModel.getId();
final boolean isLoggedIn = !Utils.isEmpty(Utils.settingsHelper.getString(Constants.COOKIE));
final String cookie = Utils.settingsHelper.getString(Constants.COOKIE);
final boolean isLoggedIn = !Utils.isEmpty(cookie);
if (isLoggedIn) {
new StoryStatusFetcher(profileId, result -> {
main.storyModels = result;
@ -679,6 +683,51 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
main.highlightsAdapter.setData(result);
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
final String myId = Utils.getUserIdFromCookie(Utils.settingsHelper.getString(Constants.COOKIE));
if (!profileId.equals(myId)) {
main.mainBinding.btnFollow.setVisibility(View.VISIBLE);
main.mainBinding.btnFollow.setOnClickListener(profileActionListener);
if (profileModel.getFollowing() == true) {
main.mainBinding.btnFollow.setText(R.string.unfollow);
main.mainBinding.btnFollow.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(
R.color.btn_purple_background, null)));
}
else if (profileModel.getRequested() == true) {
main.mainBinding.btnFollow.setText(R.string.cancel);
main.mainBinding.btnFollow.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(
R.color.btn_purple_background, null)));
}
else {
main.mainBinding.btnFollow.setText(R.string.follow);
main.mainBinding.btnFollow.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(
R.color.btn_pink_background, null)));
}
main.mainBinding.btnRestrict.setVisibility(View.VISIBLE);
main.mainBinding.btnRestrict.setOnClickListener(profileActionListener);
if (profileModel.getRestricted() == true) {
main.mainBinding.btnRestrict.setText(R.string.unrestrict);
main.mainBinding.btnRestrict.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(
R.color.btn_blue_background, null)));
}
else {
main.mainBinding.btnRestrict.setText(R.string.restrict);
main.mainBinding.btnRestrict.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(
R.color.btn_orange_background, null)));
}
main.mainBinding.btnBlock.setVisibility(View.VISIBLE);
main.mainBinding.btnBlock.setOnClickListener(profileActionListener);
if (profileModel.getBlocked() == true) {
main.mainBinding.btnBlock.setText(R.string.unblock);
main.mainBinding.btnBlock.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(
R.color.btn_green_background, null)));
}
else {
main.mainBinding.btnBlock.setText(R.string.block);
main.mainBinding.btnBlock.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(
R.color.btn_red_background, null)));
}
}
}
main.mainBinding.mainProfileImage.setEnabled(false);
@ -735,8 +784,8 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
main.mainBinding.mainBiography.setEnabled(true);
if (!profileModel.isPrivate()) {
main.mainBinding.swipeRefreshLayout.setRefreshing(true);
main.mainBinding.mainPosts.setVisibility(View.VISIBLE);
main.mainBinding.mainFollowing.setClickable(true);
main.mainBinding.mainFollowers.setClickable(true);
main.mainBinding.privatePage.setVisibility(View.GONE);
if (isLoggedIn) {
@ -749,10 +798,25 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
main.mainBinding.mainFollowing.setOnClickListener(followingCount > 0 ? followClickListener : null);
}
currentlyExecuting = new PostsFetcher(profileId, postsFetchListener).setUsername(profileModel.getUsername())
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
if (profileModel.getPostCount() == 0) {
main.mainBinding.swipeRefreshLayout.setRefreshing(false);
main.mainBinding.privatePage1.setImageResource(R.drawable.ic_cancel);
main.mainBinding.privatePage2.setText(R.string.empty_acc);
main.mainBinding.privatePage.setVisibility(View.VISIBLE);
}
else {
main.mainBinding.swipeRefreshLayout.setRefreshing(true);
main.mainBinding.mainPosts.setVisibility(View.VISIBLE);
currentlyExecuting = new PostsFetcher(profileId, postsFetchListener).setUsername(profileModel.getUsername())
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
} else {
main.mainBinding.mainFollowers.setClickable(false);
main.mainBinding.mainFollowing.setClickable(false);
main.mainBinding.swipeRefreshLayout.setRefreshing(false);
// error
main.mainBinding.privatePage1.setImageResource(R.drawable.lock);
main.mainBinding.privatePage2.setText(R.string.priv_acc);
main.mainBinding.privatePage.setVisibility(View.VISIBLE);
main.mainBinding.mainPosts.setVisibility(View.GONE);
}
@ -880,4 +944,75 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
main.mainBinding.mainProfileImage.setImageBitmap(mIcon_val);
}
}
private final View.OnClickListener profileActionListener = new View.OnClickListener() {
@Override
public void onClick(final View v) {
if (v == main.mainBinding.btnFollow) {
new ProfileAction().execute("follow");
} else if (v == main.mainBinding.btnRestrict) {
new ProfileAction().execute("restrict");
} else if (v == main.mainBinding.btnBlock) {
new ProfileAction().execute("block");
}
}
};
class ProfileAction extends AsyncTask<String, Void, Void> {
boolean ok = false;
String action;
// arg: follow / restrict / block
// restrict https://www.instagram.com/web/restrict_action/(un)restrict/
// requires form data "target_user_id: <id>"
protected Void doInBackground(String... rawAction) {
action = rawAction[0];
final String url = "https://www.instagram.com/web/"+
(action == "restrict" ? "restrict_action" : ("friendships/"+main.profileModel.getId()))+"/"+
(action == "follow" ?
((main.profileModel.getFollowing() == true ||
(main.profileModel.getFollowing() == false && main.profileModel.getRequested() == true))
? "unfollow/" : "follow/") :
(action == "restrict" ?
(main.profileModel.getRestricted() == true ? "unrestrict/" : "restrict/") :
(main.profileModel.getBlocked() == true ? "unblock/" : "block/")));
final String urlParameters = "target_user_id="+main.profileModel.getId();
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",
Utils.settingsHelper.getString(Constants.COOKIE).split("csrftoken=")[1].split(";")[0]);
if (action == "restrict") {
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();
}
else urlConnection.connect();
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
ok = true;
}
else Toast.makeText(main, R.string.downloader_unknown_error, Toast.LENGTH_SHORT);
urlConnection.disconnect();
} catch (Throwable ex) {
Log.e("austin_debug", action+": " + ex);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
if (ok == true) {
onRefresh();
}
}
}
}

11
app/src/main/java/awais/instagrabber/activities/DirectMessagesUserInbox.java

@ -41,7 +41,8 @@ import awais.instagrabber.utils.Utils;
public final class DirectMessagesUserInbox extends AppCompatActivity {
private DirectItemModel directItemModel;
private final ProfileModel myProfileHolder = new ProfileModel(false, false, null, null, null, null, null, null, null, 0, 0, 0);
private final ProfileModel myProfileHolder =
new ProfileModel(false, false, null, null, null, null, null, null, null, 0, 0, 0, false, false, false, false);
private final ArrayList<ProfileModel> users = new ArrayList<>();
private final ArrayList<DirectItemModel> directItemModels = new ArrayList<>();
private final FetchListener<InboxThreadModel> fetchListener = new FetchListener<InboxThreadModel>() {
@ -160,12 +161,10 @@ public final class DirectMessagesUserInbox extends AppCompatActivity {
@Nullable
private ProfileModel getUser(final long userId) {
if (users != null) {
for (final ProfileModel user : users)
if (Long.toString(userId).equals(user.getId())) return user;
return myProfileHolder;
for (final ProfileModel user : users) {
if (Long.toString(userId).equals(user.getId())) return user;
}
return null;
return myProfileHolder;
}
private void searchUsername(final String text) {

25
app/src/main/java/awais/instagrabber/activities/FollowViewer.java

@ -72,28 +72,13 @@ public final class FollowViewer extends BaseLanguageActivity implements SwipeRef
followBinding.toolbar.toolbar.setTitle(name);
resources = getResources();
final ArrayAdapter<Object> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new String[]{
resources.getString(R.string.open_profile), resources.getString(R.string.followers_open_in_insta)});
final AlertDialog alertDialog = new AlertDialog.Builder(this).setAdapter(adapter, (dialog, which) -> {
if (model != null) {
if (which == 0) {
if (Main.scanHack != null) {
Main.scanHack.onResult(model.getUsername());
finish();
}
} else {
final Intent actIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://instagram.com/" + model.getUsername()));
if (Utils.isInstagramInstalled) actIntent.setPackage("com.instagram.android");
startActivity(actIntent);
}
}
}).setTitle(R.string.what_to_do_dialog).create();
clickListener = v -> {
final Object tag = v.getTag();
if (tag instanceof FollowModel) {
model = (FollowModel) tag;
if (!alertDialog.isShowing()) alertDialog.show();
Main.scanHack.onResult(model.getUsername());
finish();
}
};
@ -318,11 +303,11 @@ public final class FollowViewer extends BaseLanguageActivity implements SwipeRef
final ArrayList<ExpandableGroup> groups = new ArrayList<>(1);
if (isCompare) {
if (followingModels.size() > 0)
if (followingModels != null && followingModels.size() > 0)
groups.add(new ExpandableGroup(resources.getString(R.string.followers_not_following, name), followingModels));
if (followersModels.size() > 0)
if (followersModels != null && followersModels.size() > 0)
groups.add(new ExpandableGroup(resources.getString(R.string.followers_not_follower, namePost), followersModels));
if (allFollowing.size() > 0)
if (allFollowing != null && allFollowing.size() > 0)
groups.add(new ExpandableGroup(resources.getString(R.string.followers_both_following), allFollowing));
} else {
final ExpandableGroup group = new ExpandableGroup(type, followModels);

33
app/src/main/java/awais/instagrabber/activities/Main.java

@ -52,7 +52,6 @@ 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.MyApps;
import awais.instagrabber.utils.Utils;
import static awais.instagrabber.utils.Utils.settingsHelper;
@ -293,7 +292,7 @@ public final class Main extends BaseLanguageActivity {
downloadAction = menu.findItem(R.id.action_download).setOnMenuItemClickListener(clickListener);
if (!Utils.isEmpty(Utils.settingsHelper.getString(Constants.COOKIE))) {
settingsAction.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
//settingsAction.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
dmsAction.setVisible(true).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
@ -305,7 +304,28 @@ public final class Main extends BaseLanguageActivity {
searchView.setQueryHint(getResources().getString(R.string.action_search));
searchView.setSuggestionsAdapter(suggestionAdapter);
searchView.setOnSearchClickListener(v -> searchView.setQuery(userQuery, false));
searchView.setOnSearchClickListener(v -> {
searchView.setQuery(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);
});
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(true);
menu.findItem(R.id.action_quickaccess).setVisible(true);
return true;
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
private boolean searchUser, searchHash;
private AsyncTask<?, ?, ?> prevSuggestionAsync;
@ -351,6 +371,8 @@ public final class Main extends BaseLanguageActivity {
@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();
@ -412,11 +434,6 @@ public final class Main extends BaseLanguageActivity {
return;
}
}
MyApps.showAlertDialog(this, (parent, view, position, id) -> {
if (id == -1 && position == -1 && parent == null) super.onBackPressed();
else MyApps.openAppStore(this, position);
});
}
@Override

55
app/src/main/java/awais/instagrabber/activities/PostViewer.java

@ -157,9 +157,9 @@ public final class PostViewer extends BaseLanguageActivity {
Utils.sessionVolumeFull = intVol == 1f;
}
} else if (v == viewerBinding.btnLike) {
new Like().execute();
new PostAction().execute("likes");
} else if (v == viewerBinding.btnBookmark) {
new Bookmark().execute();
new PostAction().execute("save");
} else {
final Object tag = v.getTag();
if (tag instanceof ViewerPostModel) {
@ -252,8 +252,8 @@ public final class PostViewer extends BaseLanguageActivity {
isMainSwipe = false;
}
final BasePostModel[] basePostModels = mediaAdapter != null ? mediaAdapter.getPostModels() : null;
final int slides = basePostModels != null ? basePostModels.length : 0;
final BasePostModel[] basePostModels = mediaAdapter.getPostModels();
final int slides = basePostModels.length;
int position = postModel.getPosition();
@ -685,12 +685,15 @@ public final class PostViewer extends BaseLanguageActivity {
Don't ever think about running a like farm with this
*/
class Like extends AsyncTask<Void, Void, Void> {
class PostAction extends AsyncTask<String, Void, Void> {
boolean ok = false;
String action;
protected Void doInBackground(Void... voids) {
final String url = "https://www.instagram.com/web/likes/"+postModel.getPostId()+"/"+
(postModel.getLike() == true ? "unlike/" : "like/");
protected Void doInBackground(String... rawAction) {
action = rawAction[0];
final String url = "https://www.instagram.com/web/"+action+"/"+postModel.getPostId()+"/"+ (action == "save" ?
(postModel.getBookmark() == true ? "unsave/" : "save/") :
(postModel.getLike() == true ? "unlike/" : "like/"));
try {
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
urlConnection.setRequestMethod("POST");
@ -703,49 +706,21 @@ public final class PostViewer extends BaseLanguageActivity {
ok = true;
}
else Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT);
urlConnection.disconnect();
} catch (Throwable ex) {
Log.e("austin_debug", "like: " + ex);
Log.e("austin_debug", action+": " + ex);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
if (ok == true) {
if (ok == true && action == "likes") {
viewerPostModel.setLike(postModel.getLike() == true ? false : true);
postModel.setLike(postModel.getLike() == true ? false : true);
refreshPost();
}
}
}
class Bookmark extends AsyncTask<Void, Void, Void> {
boolean ok = false;
protected Void doInBackground(Void... voids) {
final String url = "https://www.instagram.com/web/save/"+postModel.getPostId()+"/"+
(postModel.getBookmark() == true ? "unsave/" : "save/");
try {
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT);
urlConnection.setRequestProperty("x-csrftoken",
settingsHelper.getString(Constants.COOKIE).split("csrftoken=")[1].split(";")[0]);
urlConnection.connect();
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
ok = true;
}
else Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT);
} catch (Throwable ex) {
Log.e("austin_debug", "bookmark: " + ex);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
if (ok == true) {
else if (ok == true && action == "save") {
viewerPostModel.setBookmark(postModel.getBookmark() == true ? false : true);
postModel.setBookmark(postModel.getBookmark() == true ? false : true);
refreshPost();

3
app/src/main/java/awais/instagrabber/activities/StoryViewer.java

@ -132,9 +132,8 @@ public final class StoryViewer extends BaseLanguageActivity {
final FeedStoryModel feedStoryModel = isRightSwipe ?
(index == 0 ? null : storyFeed[index - 1]) :
(storyFeed.length == index + 1 ? null : storyFeed[index + 1]);
final StoryModel[] nextStoryModels = feedStoryModel.getStoryModels();
if (feedStoryModel != null) {
final StoryModel[] nextStoryModels = feedStoryModel.getStoryModels();
final Intent newIntent = new Intent(getApplicationContext(), StoryViewer.class)
.putExtra(Constants.EXTRAS_STORIES, nextStoryModels)
.putExtra(Constants.EXTRAS_USERNAME, feedStoryModel.getProfileModel().getUsername())

2
app/src/main/java/awais/instagrabber/adapters/DirectMessagesAdapter.java

@ -106,7 +106,7 @@ public final class DirectMessagesAdapter extends RecyclerView.Adapter<DirectMess
}
else if (itemType == DirectItemType.RAVEN_MEDIA) {
messageText = context.getString(R.string.direct_messages_sent_media);
} else messageText = null;
} else messageText = "<i>Unsupported message</i>";
holder.tvMessage.setText(HtmlCompat.fromHtml(messageText.toString(), 63));

2
app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java

@ -227,7 +227,7 @@ public final class FeedAdapter extends RecyclerView.Adapter<FeedItemViewHolder>
if (!captionEmpty && Utils.hasMentions(postCaption)) {
postCaption = Utils.getMentionText(postCaption);
feedModel.setPostCaption(postCaption);
//feedModel.setPostCaption(postCaption);
viewHolder.viewerCaption.setText(postCaption, TextView.BufferType.SPANNABLE);
viewHolder.viewerCaption.setMentionClickListener(mentionClickListener);
} else {

3
app/src/main/java/awais/instagrabber/adapters/MessageItemsAdapter.java

@ -45,7 +45,8 @@ import static awais.instagrabber.models.direct_messages.DirectItemModel.RavenExp
public final class MessageItemsAdapter extends RecyclerView.Adapter<TextMessageViewHolder> {
private static final int MESSAGE_INCOMING = 69, MESSAGE_OUTGOING = 420;
private final ProfileModel myProfileHolder = new ProfileModel(false, false, null, null, null, null, null, null, null, 0, 0, 0);
private final ProfileModel myProfileHolder =
new ProfileModel(false, false, null, null, null, null, null, null, null, 0, 0, 0, false, false, false, false);
private final ArrayList<DirectItemModel> directItemModels;
private final ArrayList<ProfileModel> users;
private final View.OnClickListener onClickListener;

1
app/src/main/java/awais/instagrabber/adapters/SuggestionsAdapter.java

@ -2,6 +2,7 @@ package awais.instagrabber.adapters;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

6
app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java

@ -115,7 +115,7 @@ public final class CommentsFetcher extends AsyncTask<Void, Void, CommentModel[]>
owner.getString(Constants.EXTRAS_USERNAME),
null, null, null,
owner.getString("profile_pic_url"),
null, 0, 0, 0);
null, 0, 0, 0, false, false, false, false);
final JSONObject likedBy = childComment.optJSONObject("edge_liked_by");
@ -193,7 +193,7 @@ public final class CommentsFetcher extends AsyncTask<Void, Void, CommentModel[]>
owner.getString(Constants.EXTRAS_USERNAME),
null, null, null,
owner.getString("profile_pic_url"),
null, 0, 0, 0);
null, 0, 0, 0, false, false, false, false);
final JSONObject likedBy = comment.optJSONObject("edge_liked_by");
final String commentId = comment.getString(Constants.EXTRAS_ID);
@ -231,7 +231,7 @@ public final class CommentsFetcher extends AsyncTask<Void, Void, CommentModel[]>
tempJsonObject.getString(Constants.EXTRAS_USERNAME),
null, null, null,
tempJsonObject.getString("profile_pic_url"),
null, 0, 0, 0);
null, 0, 0, 0, false, false, false, false);
tempJsonObject = childComment.optJSONObject("edge_liked_by");
childCommentModels[j] = new CommentModel(childComment.getString(Constants.EXTRAS_ID),

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

@ -104,7 +104,7 @@ public final class FeedFetcher extends AsyncTask<Void, Void, FeedModel[]> {
owner.optString("full_name"),
null, null,
owner.getString("profile_pic_url"),
null, 0, 0, 0);
null, 0, 0, 0, false, false, false, false);
}
JSONObject tempJsonObject = feedItem.optJSONObject("edge_media_preview_comment");

2
app/src/main/java/awais/instagrabber/asyncs/FeedStoriesFetcher.java

@ -61,7 +61,7 @@ public final class FeedStoriesFetcher extends AsyncTask<Void, Void, FeedStoryMod
user.getString("username"),
null, null, null,
user.getString("profile_pic_url"),
null, 0, 0, 0);
null, 0, 0, 0, false, false, false, false);
final String id = node.getString("id");
feedStoryIDs[i] = id;

6
app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java

@ -63,7 +63,11 @@ public final class ProfileFetcher extends AsyncTask<Void, Void, ProfileModel> {
user.getString("profile_pic_url_hd"),
timelineMedia.getLong("count"),
user.getJSONObject("edge_followed_by").getLong("count"),
user.getJSONObject("edge_follow").getLong("count"));
user.getJSONObject("edge_follow").getLong("count"),
user.getBoolean("followed_by_viewer"),
user.getBoolean("restricted_by_viewer"),
user.getBoolean("blocked_by_viewer"),
user.getBoolean("requested_by_viewer"));
}
conn.disconnect();

2
app/src/main/java/awais/instagrabber/dialogs/SettingsDialog.java

@ -86,7 +86,7 @@ public final class SettingsDialog extends BottomSheetDialogFragment implements V
final View contentView = View.inflate(activity, R.layout.dialog_main_settings, null);
settingTitle = contentView.findViewById(R.id.settingTitle);
settingTitle.setText("Settings (v"+BuildConfig.VERSION_NAME+")");
settingTitle.setText(getString(R.string.action_setting, BuildConfig.VERSION_NAME));
btnLogin = contentView.findViewById(R.id.btnLogin);
btnLogout = contentView.findViewById(R.id.btnLogout);
btnSaveTo = contentView.findViewById(R.id.btnSaveTo);

4
app/src/main/java/awais/instagrabber/models/BasePostModel.java

@ -28,10 +28,10 @@ public abstract class BasePostModel implements Serializable {
}
public boolean setLike(final boolean like) {
liked = like; this.liked = liked; return liked;
liked = like; return liked;
}
public boolean setBookmark(final boolean bookmark) {
bookmarked = bookmark; this.bookmarked = bookmarked; return bookmarked;
bookmarked = bookmark; return bookmarked;
}
public MediaItemType getItemType() {

14
app/src/main/java/awais/instagrabber/models/PostModel.java

@ -33,20 +33,6 @@ public class PostModel extends BasePostModel {
return endCursor;
}
public boolean getLike() {
return liked;
}
public boolean getBookmark() {
return bookmarked;
}
public boolean setLike() {
liked = liked == true ? false : true; this.liked = liked; return liked;
}
public boolean setBookmark() {
bookmarked = bookmarked == true ? false : true; this.bookmarked = bookmarked; return bookmarked;
}
public boolean hasNextPage() {
return endCursor != null && hasNextPage;
}

28
app/src/main/java/awais/instagrabber/models/ProfileModel.java

@ -3,13 +3,14 @@ package awais.instagrabber.models;
import java.io.Serializable;
public final class ProfileModel implements Serializable {
private final boolean isPrivate, isVerified;
private final boolean isPrivate, isVerified, following, restricted, blocked, requested;
private final long postCount, followersCount, followingCount;
private final String id, username, name, biography, url, sdProfilePic, hdProfilePic;
public ProfileModel(final boolean isPrivate, final boolean isVerified, final String id, final String username,
final String name, final String biography, final String url, final String sdProfilePic, final String hdProfilePic,
final long postCount, final long followersCount, final long followingCount) {
final long postCount, final long followersCount, final long followingCount, final boolean following,
final boolean restricted, final boolean blocked, final boolean requested) {
this.isPrivate = isPrivate;
this.isVerified = isVerified;
this.id = id;
@ -22,6 +23,10 @@ public final class ProfileModel implements Serializable {
this.postCount = postCount;
this.followersCount = followersCount;
this.followingCount = followingCount;
this.following = following;
this.restricted = restricted;
this.blocked = blocked;
this.requested = requested;
}
public boolean isPrivate() {
@ -60,16 +65,23 @@ public final class ProfileModel implements Serializable {
return hdProfilePic;
}
public long getPostCount() {
return postCount;
}
public long getPostCount() { return postCount; }
public long getFollowersCount() {
return followersCount;
}
public long getFollowersCount() { return followersCount; }
public long getFollowingCount() {
return followingCount;
}
public boolean getFollowing() { return following; }
public boolean getRestricted() { return restricted; }
public boolean getBlocked() {
return blocked;
}
public boolean getRequested() {
return requested;
}
}

14
app/src/main/java/awais/instagrabber/models/ViewerPostModel.java

@ -24,20 +24,6 @@ public final class ViewerPostModel extends BasePostModel {
this.bookmarked = bookmarked;
}
public boolean getLike() {
return liked;
}
public boolean getBookmark() {
return bookmarked;
}
public boolean setLike() {
liked = liked == true ? false : true; this.liked = liked; return liked;
}
public boolean setBookmark() {
bookmarked = bookmarked == true ? false : true; this.bookmarked = bookmarked; return bookmarked;
}
public long getCommentsCount() {
return commentsCount;
}

138
app/src/main/java/awais/instagrabber/utils/MyApps.java

@ -1,138 +0,0 @@
package awais.instagrabber.utils;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import android.os.Process;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.AppCompatTextView;
import java.util.Random;
import awais.instagrabber.R;
public final class MyApps {
public final static Icons[] iconsList = Icons.values();
@SuppressWarnings("unused")
public enum Icons {
MEDIASCAN("awais.media.scanner", "mediaScanner", R.drawable.zzz_ms),
ADDME("awais.addme", "AddMe", R.drawable.zzz_adm),
LINKEDWORDS("awais.backworddictionary", "Linked Words", R.drawable.zzz_lw),
QUODB("awais.quodb", "QuoDB", R.drawable.zzz_qdb),
REVERSIFY("awais.reversify", "Reversify", R.drawable.zzz_rev),
REVERSIFY_LITE("awais.reversify.lite", "Reversify Lite", R.drawable.zzz_revl),
TESV("awais.skyrimconsole", "Skyrim Cheats", R.drawable.zzz_tesv);
private final int icon;
private final String name, pkg;
Icons(final String pkg, final String name, final int icon) {
this.name = name;
this.pkg = pkg;
this.icon = icon;
}
}
public static void openAppStore(@NonNull final Context context, final int position) {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + MyApps.iconsList[position].pkg)));
}
public static void showAlertDialog(final Context context, final AdapterView.OnItemClickListener clickListener) {
final DialogInterface.OnCancelListener cancelListener = d -> {
if (clickListener != null) clickListener.onItemClick(null, null, -1, -1);
else Process.killProcess(Process.myPid());
};
if (new Random().nextDouble() < 0.420D) {
cancelListener.onCancel(null);
return;
}
final GridView gridView = new GridView(context);
gridView.setAdapter(new ImageAdapter(context));
gridView.setNumColumns(3);
gridView.setOnItemClickListener(clickListener);
final AlertDialog dialog = new AlertDialog.Builder(context).setView(gridView).setTitle("Support my apps tho").create();
dialog.setOnCancelListener(cancelListener);
dialog.show();
}
public static class ImageAdapter extends BaseAdapter {
private final Context context;
private final int size;
public ImageAdapter(final Context context) {
this.context = context;
this.size = (int) (80 * Resources.getSystem().getDisplayMetrics().density);
}
@Override
public int getCount() {
return iconsList.length;
}
@Override
public Object getItem(final int position) {
return iconsList[position];
}
@Override
public long getItemId(final int position) {
return 0;
}
public View getView(final int position, View convertView, final ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
final LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.VERTICAL);
final AppCompatImageView imageView = new AppCompatImageView(context);
final AppCompatTextView textView = new AppCompatTextView(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
textView.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
textView.setGravity(Gravity.CENTER_HORIZONTAL);
imageView.setAdjustViewBounds(true);
linearLayout.addView(imageView, LinearLayout.LayoutParams.MATCH_PARENT, size);
linearLayout.addView(textView);
final int padding = size >> 2;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
linearLayout.setPaddingRelative(padding, padding, padding, padding);
else linearLayout.setPadding(padding, padding, padding, padding);
convertView = linearLayout;
convertView.setTag(holder = new ViewHolder(textView, imageView));
} else
holder = (ViewHolder) convertView.getTag();
final Object item = getItem(position);
if (item instanceof Icons) {
final Icons icons = (Icons) item;
holder.title.setText(icons.name);
holder.icon.setImageResource(icons.icon);
}
return convertView;
}
private final static class ViewHolder {
private final TextView title;
private final ImageView icon;
private ViewHolder(final TextView title, final ImageView icon) {
this.title = title;
this.icon = icon;
}
}
}
}

2
app/src/main/java/awais/instagrabber/utils/SettingsHelper.java

@ -81,7 +81,7 @@ public final class SettingsHelper {
themeCode = sharedPreferences.getInt(APP_THEME, themeCode);
if (themeCode == 1) themeCode = AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY;
else if (themeCode == 3) themeCode = AppCompatDelegate.MODE_NIGHT_NO;
else if (themeCode != 2) themeCode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
else if (themeCode == 0) themeCode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
}
if (themeCode == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM && Build.VERSION.SDK_INT < 29)

6
app/src/main/java/awais/instagrabber/utils/Utils.java

@ -388,7 +388,7 @@ public final class Utils {
userObj.getString("full_name"),
null, null,
userObj.getString("profile_pic_url"),
null, 0, 0, 0);
null, 0, 0, 0, false, false, false, false);
}
final MediaItemType mediaType = getMediaItemType(mediaObj.optInt("media_type", -1));
@ -465,7 +465,7 @@ public final class Utils {
userObject.getString("full_name"),
null, null,
userObject.getString("profile_pic_url"),
null, 0, 0, 0);
null, 0, 0, 0, false, false, false, false);
}
final JSONArray items = data.getJSONArray("items");
@ -614,7 +614,7 @@ public final class Utils {
profile.getString("full_name"),
null, null,
profile.getString("profile_pic_url"),
null, 0, 0, 0);
null, 0, 0, 0, false, false, false, false);
}
break;

26
app/src/main/res/drawable/ic_cancel.xml

@ -0,0 +1,26 @@
<!--
Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:alpha="0.8"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.47,2 2,6.47 2,12c0,5.53 4.47,10 10,10c5.53,0 10,-4.47 10,-10C22,6.47 17.53,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8S16.41,20 12,20z"/>
<path
android:fillColor="@android:color/white"
android:pathData="M15.59,7l-3.59,3.59l-3.59,-3.59l-1.41,1.41l3.59,3.59l-3.59,3.59l1.41,1.41l3.59,-3.59l3.59,3.59l1.41,-1.41l-3.59,-3.59l3.59,-3.59z"/>
</vector>

82
app/src/main/res/layout/activity_main.xml

@ -75,44 +75,94 @@
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textSize="16sp"
tools:text="retro nugget" />
tools:text="Austin Huang" />
</LinearLayout>
<awais.instagrabber.customviews.RamboTextView
android:id="@+id/mainUrl"
android:id="@+id/mainBiography"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/profileInfoText"
android:ellipsize="marquee"
android:background="?android:selectableItemBackground"
android:paddingStart="10dp"
android:paddingLeft="10dp"
android:paddingEnd="10dp"
android:paddingRight="10dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="16sp"
android:visibility="gone"
tools:text="http://bigdickbitch.com/" />
tools:text="THE GLORIOUS (step)OWNER OF THIS APP" />
<awais.instagrabber.customviews.RamboTextView
android:id="@+id/mainBiography"
android:id="@+id/mainUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/mainUrl"
android:background="?android:selectableItemBackground"
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"
tools:text="Fuck y'all for real." />
tools:text="https://austinhuang.me/"
android:visibility="gone" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/profileActions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/mainUrl"
android:weightSum="3">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnFollow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="2dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:text="@string/follow"
android:textColor="@color/btn_pink_text_color"
android:textSize="18sp"
app:backgroundTint="@color/btn_pink_background"
android:visibility="gone" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnRestrict"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginEnd="1dp"
android:layout_marginStart="1dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:text="@string/restrict"
android:textColor="@color/btn_orange_text_color"
android:textSize="18sp"
app:backgroundTint="@color/btn_orange_background"
android:visibility="gone" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnBlock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginEnd="2dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:text="@string/block"
android:textColor="@color/btn_red_text_color"
android:textSize="18sp"
app:backgroundTint="@color/btn_red_background"
android:visibility="gone" />
</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/mainBiography"
android:layout_below="@id/profileActions"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="5dp"
@ -146,7 +196,7 @@
android:layout_weight="1"
android:gravity="center"
android:textAppearance="@style/TextAppearance.AppCompat"
android:textSize="16sp"
android:textSize="15sp"
tools:text="35\nPosts" />
<androidx.appcompat.widget.AppCompatTextView
@ -157,7 +207,7 @@
android:background="?selectableItemBackgroundBorderless"
android:gravity="center"
android:textAppearance="@style/TextAppearance.AppCompat"
android:textSize="16sp"
android:textSize="15sp"
tools:text="68\nFollowers" />
<androidx.appcompat.widget.AppCompatTextView
@ -172,7 +222,7 @@
android:background="?selectableItemBackgroundBorderless"
android:gravity="center"
android:textAppearance="@style/TextAppearance.AppCompat"
android:textSize="16sp"
android:textSize="15sp"
tools:text="64\nFollowing" />
</LinearLayout>
</RelativeLayout>
@ -212,11 +262,13 @@
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"

9
app/src/main/res/layout/activity_viewer.xml

@ -99,16 +99,17 @@
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_height="0dp"
android:layout_weight="0.26"
android:background="#0000"
android:weightSum="2">
android:weightSum="2"
android:layout_alignParentBottom="true">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnLike"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="6dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:text="@string/like"
@ -121,7 +122,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginEnd="6dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:text="@string/bookmark"

2
app/src/main/res/menu/menu.xml

@ -34,7 +34,7 @@
android:title="@string/action_settings"
android:titleCondensed="@string/action_settings"
android:visible="false"
app:showAsAction="always" />
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_dms"

2
app/src/main/res/values-es/arrays.xml

@ -5,7 +5,7 @@
<item>Inglés</item>
<item>Francés [Gracias a @kernoeb (Telegram)]</item>
<item>Español [Gracias a @sguinetti (GitLab)]</item>
<item>Chino Simplificado [Gracias a @laiboonsing (GitLab)]</item>
<item>Chino Simplificado</item>
<item>Indonesio [Gracias a @Galang23 (GitLab)]</item>
<item>Italiano [Gracias a @RAR_Ramar (Telegram)]</item>
</string-array>

1
app/src/main/res/values-es/strings.xml

@ -129,7 +129,6 @@
<string name="comment_view_mention_user_search">¿Quieres buscar el nombre de usuario?</string>
<string name="comment_view_mention_hash_search">¿Quieres buscar el hashtag?</string>
<string name="followers_open_in_insta">Abrir en Instagram</string>
<string name="followers_type_followers">Seguidores</string>
<string name="followers_type_following">Siguiendo</string>
<string name="followers_compare">Comparar seguidores &amp; siguiendo</string>

2
app/src/main/res/values-fr/arrays.xml

@ -5,7 +5,7 @@
<item>Anglais</item>
<item>Français [Merci à @kernoeb (Telegram)]</item>
<item>Espagnol [Merci à @sguinetti (GitLab)]</item>
<item>Chinois Simplifié [Merci à @laiboonsing (GitLab)]</item>
<item>Chinois Simplifié</item>
<item>Indonésien [Merci à @Galang23 (GitLab)]</item>
<item>Italien [Merci à @RAR_Ramar (Telegram)]</item>
</string-array>

1
app/src/main/res/values-fr/strings.xml

@ -129,7 +129,6 @@
<string name="comment_view_mention_user_search">Souhaitez-vous faire une recherche sur le nom d\'utilisateur ?</string>
<string name="comment_view_mention_hash_search">Souhaitez-vous faire une recherch sur le hashtag ?</string>
<string name="followers_open_in_insta">Ouvrir dans Instagram</string>
<string name="followers_type_followers">Abonnés</string>
<string name="followers_type_following">Abonnements</string>
<string name="followers_compare">Comparer les abonnés et abonnements</string>

2
app/src/main/res/values-in/arrays.xml

@ -5,7 +5,7 @@
<item>Inggris</item>
<item>Prancis [Terima kasih @kernoeb (Telegram)]</item>
<item>Spanyol [Terima kasih @sguinetti (GitLab)]</item>
<item>Tiongkok Sederhana [Terima kasih @laiboonsing (GitLab)]</item>
<item>Tiongkok Sederhana</item>
<item>Bahasa Indonesia [Terima kasih @Galang23 (GitLab)]</item>
<item>Italia [Terima kasih @RAR_Ramar (Telegram)]</item>
</string-array>

1
app/src/main/res/values-in/strings.xml

@ -129,7 +129,6 @@
<string name="comment_view_mention_user_search">Apakah anda ingin mencari nama pengguna ini?</string>
<string name="comment_view_mention_hash_search">Apakah anda ingin mencari hashtag ini?</string>
<string name="followers_open_in_insta">Buka di Instagram</string>
<string name="followers_type_followers">Pengikut</string>
<string name="followers_type_following">Diikuti</string>
<string name="followers_compare">Membandingkan pengikut &amp; yang diikuti</string>

2
app/src/main/res/values-it/arrays.xml

@ -5,7 +5,7 @@
<item>Inglese</item>
<item>Francese [Grazie a @kernoeb (Telegram)]</item>
<item>Spagnolo [Grazie a @sguinetti (GitLab)]</item>
<item>Cinese Semplificato [Grazie a @laiboonsing (GitLab)]</item>
<item>Cinese Semplificato</item>
<item>Indonesiano [Grazie a @Galang23 (GitLab)]</item>
<item>Italiano [Grazie a @RAR_Ramar (Telegram)]</item>
</string-array>

1
app/src/main/res/values-it/strings.xml

@ -129,7 +129,6 @@
<string name="comment_view_mention_user_search">Vuoi cercare il nome utente?</string>
<string name="comment_view_mention_hash_search">Vuoi cercare l\'hashtag?</string>
<string name="followers_open_in_insta">Apri in Instagram</string>
<string name="followers_type_followers">Followers</string>
<string name="followers_type_following">Following</string>
<string name="followers_compare">Confronto followers &amp; following</string>

4
app/src/main/res/values-zh/arrays.xml

@ -5,9 +5,9 @@
<item>英文</item>
<item>法文 [感谢 @kernoeb (Telegram)]</item>
<item>西班牙文 [感谢 @sguinetti (GitLab)]</item>
<item>简体中文 [感谢 @laiboonsing (GitLab)] </item>
<item>简体中文</item>
<item>印度尼西亚 [感谢 @Galang23 (GitLab)]</item>
<item>大利文 [感谢 @RAR_Ramar (Telegram)]</item>
<item>大利文 [感谢 @RAR_Ramar (Telegram)]</item>
</string-array>
<string-array name="theme_presets">

58
app/src/main/res/values-zh/strings.xml

@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="action_quickaccess">快捷道</string>
<string name="action_quickaccess">快捷</string>
<string name="action_about">关于</string>
<string name="action_dms">Direct消息</string>
<string name="action_dms">私聊</string>
<string name="action_settings">设定</string>
<string name="action_download">下载</string>
<string name="action_search">用户名…</string>
<string name="action_search">用户名…</string>
<string name="action_compare">比较</string>
<string name="single_like">次赞</string>
<string name="multiple_likes">次赞</string>
<string name="clipboard_error">复制文字时出错</string>
<string name="clipboard_copied">复制到剪贴板!</string>
<string name="clipboard_copied">复制到剪贴板!</string>
<string name="report">报告</string>
<string name="password">密码 (最多32字符)</string>
<string name="ok">OK</string>
@ -36,7 +36,7 @@
<string name="bottom_toolbar">底下显示工具栏</string>
<string name="download_user_folder">下载帖子到下载里的用户名文件夹</string>
<string name="autoload_posts">自动加载用户所有帖子</string>
<string name="error_loading_profile">载入主页时出错!\n尝试再次登录并搜寻</string>
<string name="error_loading_profile">载入主页时出错!\n请尝试再次登录并搜索</string>
<string name="error_creating_folders">创建下载文件夹时出错</string>
<string name="show_feed">显示用户动态 (只在登录后有效)</string>
<string name="save_to_folder">保存至自定义文件夹</string>
@ -50,10 +50,10 @@
<string name="main_posts_followers">%s\n粉丝</string>
<string name="main_posts_following">%s\n已关注</string>
<string name="post_viewer_video_post">视频</string>
<string name="post_viewer_image_post">图片</string>
<string name="post_viewer_video_post">视频</string>
<string name="post_viewer_image_post">图片</string>
<string name="post_viewer_autoplay_video">自动播放视频</string>
<string name="post_viewer_muted_autoplay">总是静音视频</string>
<string name="post_viewer_muted_autoplay">视频默认静音</string>
<string name="post_viewer_post_from">%s - %s</string>
<string name="post_viewer_download_message">注: 当前[时段]直到你的到来都不会显示此对话,且总是下载以显示的帖子片</string>
<string name="post_viewer_download_dialog_title">选择要下载的</string>
@ -69,7 +69,7 @@
<string name="read_more">阅读更多…</string>
<string name="login">登录</string>
<string name="send_logs">发送日志[出了什么差错的话]</string>
<string name="send_logs">发送调试日志</string>
<string name="time_settings">发帖时间设定</string>
<string name="project_link">参观项目页面</string>
<string name="telegram_link">加入 Telegram 群组</string>
@ -89,8 +89,8 @@
<string name="dialog_export_err_password_empty">密码为空! 密码不能是空的,笨蛋!</string>
<string name="refresh">刷新</string>
<string name="get_cookies"> cookies</string>
<string name="desktop_2fa">桌面版\n用于 2FA</string>
<string name="get_cookies"> cookies</string>
<string name="desktop_2fa">桌面版</string>
<string name="time_settings_title_custom">自定义格式</string>
<string name="time_settings_title_separator">分界</string>
@ -99,15 +99,15 @@
<string name="time_settings_title_preview">预览</string>
<string name="time_settings_swap_time">时间和日期\n位置交换</string>
<string name="quick_access_info_dialog">最爱面板是用来添加你最爱的标签和/或用户。\n\n而快捷道是用来迅速切换账户的。\n\n注1: 确保登录各个账户 [设定 > 登录] 让账户写进列表!\n\n注2: 登出当前账户才登录另一个账户。\n如果多账户对你没用你我都做不了什么</string>
<string name="quick_access_info_dialog">最爱面板让您添加您最爱的标签和用户。\n\n而快捷通道是用来迅速切换账户的。\n\n注1: 请确保各个账户已登录 [设定 > 登录] 来添加账户!\n\n注2: 登出当前账户之后再登录另一个账户。</string>
<string name="quick_access_cannot_delete_curr">无法删除正在使用的账户</string>
<string name="quick_access_confirm_delete">你真的要删除 %s?</string>
<string name="profile_viewer_imageinfo">宽: %d\n高: %d</string>
<string name="profile_viewer_colordepth_prefix">\n色深:</string>
<string name="profile_endpoint">选择大头照终点</string>
<string name="profile_endpoint">选择头像服务</string>
<string name="open_profile">打开主页</string>
<string name="view_pfp">看大头照</string>
<string name="view_pfp">查看头像</string>
<string name="direct_download">直接下载</string>
<string name="direct_download_desc">直接下载至手机!</string>
@ -125,21 +125,33 @@
<string name="downloader_error_download_file">下载文件时出错</string>
<string name="comment_viewer_copy_user">复制用户名</string>
<string name="comment_viewer_copy_comment">复制留言</string>
<string name="comment_view_mention_user_search">你要搜寻用户名吗?</string>
<string name="comment_view_mention_hash_search">你要搜寻标签吗?</string>
<string name="comment_viewer_copy_comment">复制评论</string>
<string name="comment_view_mention_user_search">要搜索用户名吗?</string>
<string name="comment_view_mention_hash_search">要搜索标签吗?</string>
<string name="followers_open_in_insta">于 Instagram 打开</string>
<string name="followers_type_followers">粉丝</string>
<string name="followers_type_following">关注</string>
<string name="followers_compare">比较粉丝 &amp; 关注</string>
<string name="followers_compare">比较粉丝关注</string>
<string name="followers_both_following">互粉</string>
<string name="followers_not_following">关注 %s</string>
<string name="followers_not_follower">%s 不是粉丝</string>
<string name="followers_not_following">关注 %s</string>
<string name="followers_not_follower">%s 未关注</string>
<string name="login_error_loading_cookies">载入 cookies 时出错</string>
<string name="login_success_loading_cookies">成功载入 cookies!\n若你仍不能查看私密 页面/帖子,重新登录!</string>
<string name="login_success_loading_cookies">成功载入 cookies!\n若你仍不能查看私密页面/帖子,重新登录!</string>
<string name="crash_title">应用崩溃</string>
<string name="crash_title">应用崩溃</string>
<string name="crash_descr">糟糕..应用崩溃了,不过别担心,你可以向开发者发送错误报告来帮助他修复问题。 (:</string>
<string name="update_available">检测到有新版本… 请点击下载来打开浏览器。</string>
<string name="updated">感谢阁下更新InstaGrabber!</string>
<string name="downloader_downloading_media">媒体下载中</string>
<string name="matrix_link">加入 Matrix 群组</string>
<string name="like"></string>
<string name="unlike">取消赞</string>
<string name="bookmark">加入收藏</string>
<string name="unbookmark">解除收藏</string>
<string name="logout">退出</string>
<string name="no_more_stories">到底啦!</string>
<string name="description">原作者 AWAiS 将 InstaGrabber 做成了一个小巧玲珑的 Instagram 帖子下载 [写作下载读作剽窃] 程序,不过他跳槽了,所以我(Austin Huang)就把它接了下来。 [希望此举有所值得。] 不管怎样,InstaGrabber 完全开源,无广告,无跟踪 [Instagram 原生跟踪除外],998都不要,你还等啥???\n有问题 [或者只是想谈谈心] ?请联系 [email protected] 或点击下方各按钮。</string>
<string name="direct_messages_you"></string>
<string name="direct_messages_sent_link">分享了</string>
</resources>

2
app/src/main/res/values/arrays.xml

@ -5,7 +5,7 @@
<item>English</item>
<item>French [Thanks to @kernoeb (Telegram)]</item>
<item>Spanish [Thanks to @sguinetti (GitLab)]</item>
<item>Chinese Simplified [Thanks to @laiboonsing (GitLab)]</item>
<item>Chinese Simplified</item>
<item>Indonesian [Thanks to @Galang23 (GitLab)]</item>
<item>Italian [Thanks to @RAR_Ramar (Telegram)]</item>
</string-array>

5
app/src/main/res/values/color.xml

@ -17,10 +17,11 @@
<color name="btn_red_background">#E62323</color>
<color name="btn_red_text_color">@color/text_color_dark</color>
<color name="btn_purple_background">#909090</color>
<color name="btn_pink_background">#FF69B4</color>
<color name="btn_pink_text_color">#FFFFFFFF</color>
<color name="btn_pink_text_color">@color/text_color_dark</color>
<color name="btn_lightpink_background">#FFB6C1</color>
<color name="btn_lightpink_text_color">#FF000000</color>
<color name="btn_lightpink_text_color">@color/text_color_light</color>
<color name="btn_orange_background">#FF5500</color>
<color name="btn_orange_text_color">#FFFFFFFF</color>

13
app/src/main/res/values/strings.xml

@ -6,6 +6,7 @@
<string name="action_quickaccess">Quick Access</string>
<string name="action_about">About</string>
<string name="action_dms">Direct Messages</string>
<string name="action_setting">Settings (v%s)</string>
<string name="action_settings">Settings</string>
<string name="action_download">Download</string>
<string name="action_search">Search username…</string>
@ -67,6 +68,7 @@
<string name="no_more_stories">No more stories!</string>
<string name="view_story_post">View Story Post</string>
<string name="priv_acc">This Account is Private</string>
<string name="empty_acc">This Account has No Posts</string>
<string name="curr_version">Current version: v%s</string>
<string name="read_more">read more…</string>
@ -84,6 +86,12 @@
<string name="bookmark">Bookmark</string>
<string name="unbookmark">Unbookmark</string>
<string name="follow">Follow</string>
<string name="unfollow">Unfollow</string>
<string name="block">Block</string>
<string name="unblock">Unblock</string>
<string name="restrict">Restrict</string>
<string name="unrestrict">Unrestrict</string>
<string name="dialog_export_btn_export">Export</string>
<string name="dialog_export_btn_import">Import</string>
@ -110,7 +118,7 @@
<string name="time_settings_title_preview">Preview</string>
<string name="time_settings_swap_time">Swap Time and\nDate positions</string>
<string name="quick_access_info_dialog">Favorites panel is for adding your favorite hashtags and/or usernames.\n\nAnd the Quick Access panel is for quickly switching between accounts.\n\nNote 1: Make sure to Login into each account [Settings > Login] to add account to the list!\n\nNote 2: Log out of the current account and then log into the other account.\nIf multiple accounts don\'t work for you there\'s nothing we both can do!</string>
<string name="quick_access_info_dialog">Favorites panel is for adding your favorite hashtags and/or usernames.\n\nAnd the Quick Access panel is for quickly switching between accounts.\n\nNote 1: Make sure to Login into each account [Settings > Login] to add account to the list!\n\nNote 2: Log out of the current account and then log into the other account.</string>
<string name="quick_access_cannot_delete_curr">Cannot delete currently in use account</string>
<string name="quick_access_confirm_delete">Are you sure you want to delete %s?</string>
@ -163,7 +171,6 @@
<string name="comment_view_mention_user_search">Do you want to search the username?</string>
<string name="comment_view_mention_hash_search">Do you want to search the hashtag?</string>
<string name="followers_open_in_insta">Open in Instagram</string>
<string name="followers_type_followers">Followers</string>
<string name="followers_type_following">Following</string>
<string name="followers_compare">Comparing followers &amp; following</string>
@ -174,7 +181,7 @@
<string name="login_error_loading_cookies">Error loading cookies</string>
<string name="login_success_loading_cookies">Successfully loaded cookies!\nIf you still can\'t open private pages/posts, re-login!</string>
<string name="update_available">An update is available…\nPress Download to open browser.</string>
<string name="update_available">An update is available… Press Download to open browser.</string>
<string name="updated">Thank you for updating InstaGrabber!</string>
<string name="crash_title">App crashed</string>
<string name="crash_descr">Oops.. the app crashed, but don\'t worry you can send error report to the developer to help him fix the issue. (:</string>

1
fastlane/metadata/android/changelogs/1.txt

@ -1 +0,0 @@
Please read https://github.com/austinhuang0131/instagrabber/releases for info.

7
fastlane/metadata/android/changelogs/31.txt

@ -0,0 +1,7 @@
* You can now (un)follow/restrict/block people
* For this reason, "Open in Instagram" for following/follower list is removed
* Link in bio is now under bio text (like the actual Instagram app)
* Accounts with no posts will be indicated instead of having infinite refresh
* When searching, all other buttons will be hidden to expand suggestion width
* Remove AWAiS advertisement
* Implement LGTM advice to improve stability

BIN
gradle/wrapper/gradle-wrapper.jar

4
gradle/wrapper/gradle-wrapper.properties

@ -1,6 +1,6 @@
#Mon Mar 16 19:24:49 PKT 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=10065868c78f1207afb3a92176f99a37d753a513dff453abb6b5cceda4058cda
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip

51
gradlew

@ -1,5 +1,21 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@ -109,8 +125,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
@ -138,19 +154,19 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $i + 1`
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@ -159,14 +175,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

18
gradlew.bat

@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

Loading…
Cancel
Save