v16.6: yes

This commit is contained in:
Austin Huang 2020-07-23 12:00:09 -04:00
parent 9626b9fa54
commit 06d2614680
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
40 changed files with 385 additions and 248 deletions

View File

@ -4,13 +4,13 @@ android {
compileSdkVersion 29
defaultConfig {
applicationId 'awais.instagrabber'
applicationId 'me.austinhuang.instagrabber'
minSdkVersion 16
targetSdkVersion 29
versionCode 27
versionName '16.6-a8'
versionName '16.6'
multiDexEnabled true

View File

@ -4,6 +4,7 @@ import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
@ -84,6 +85,9 @@ 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;
@ -278,12 +282,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
setupExplore();
final boolean showFeed = Utils.settingsHelper.getBoolean(Constants.SHOW_FEED);
if (showFeed) setupFeed();
else {
iconFeed.setAlpha(0.4f);
main.mainBinding.drawerLayout.removeView(main.mainBinding.feedLayout);
}
setupFeed();
final TypedValue resolvedAttr = new TypedValue();
main.getTheme().resolveAttribute(android.R.attr.textColorPrimary, resolvedAttr, true);
@ -333,18 +332,16 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
if (drawerOpening && alpha > 100)
ImageViewCompat.setImageTintList(iconDiscover, colorStateList.withAlpha(currentIconAlpha));
if (showFeed) ImageViewCompat.setImageTintList(iconFeed, colorStateList.withAlpha(otherIconAlpha));
ImageViewCompat.setImageTintList(iconFeed, colorStateList.withAlpha(otherIconAlpha));
} else {
// this changes toolbar title
main.mainBinding.toolbar.toolbar.setTitle(slideOffset >= 0.466 ? titleDiscover : main.userQuery);
if (showFeed) {
imageTintList = ImageViewCompat.getImageTintList(iconFeed);
alpha = imageTintList != null ? (imageTintList.getDefaultColor() & 0xFF_000000) >> 24 : 0;
imageTintList = ImageViewCompat.getImageTintList(iconFeed);
alpha = imageTintList != null ? (imageTintList.getDefaultColor() & 0xFF_000000) >> 24 : 0;
if (drawerOpening && alpha > 100)
ImageViewCompat.setImageTintList(iconFeed, colorStateList.withAlpha(currentIconAlpha));
}
if (drawerOpening && alpha > 100)
ImageViewCompat.setImageTintList(iconFeed, colorStateList.withAlpha(currentIconAlpha));
ImageViewCompat.setImageTintList(iconDiscover, colorStateList.withAlpha(otherIconAlpha));
}
@ -620,7 +617,6 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
main.mainBinding.appBarLayout.setExpanded(true, true);
main.mainBinding.privatePage.setVisibility(View.GONE);
main.mainBinding.mainProfileImage.setImageBitmap(null);
main.mainBinding.mainProfileImage.setImageDrawable(null);
main.mainBinding.mainUrl.setText(null);
main.mainBinding.mainFullName.setText(null);
main.mainBinding.mainPostCount.setText(null);
@ -686,19 +682,8 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
}
main.mainBinding.mainProfileImage.setEnabled(false);
Glide.with(main).load(profileModel.getSdProfilePic()).listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target<Drawable> target, final boolean isFirstResource) {
main.mainBinding.mainProfileImage.setEnabled(false);
return false;
}
@Override
public boolean onResourceReady(final Drawable resource, final Object model, final Target<Drawable> target, final DataSource dataSource, final boolean isFirstResource) {
main.mainBinding.mainProfileImage.setEnabled(true);
return false;
}
}).into(main.mainBinding.mainProfileImage);
new MyTask().execute();
main.mainBinding.mainProfileImage.setEnabled(true);
final long followersCount = profileModel.getFollowersCount();
final long followingCount = profileModel.getFollowingCount();
@ -877,4 +862,22 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener {
}
return returnvalue;
}
class MyTask extends AsyncTask<Void, Bitmap, Void> {
private Bitmap mIcon_val;
protected Void doInBackground(Void... voids) {
try {
mIcon_val = BitmapFactory.decodeStream((InputStream) new URL(main.profileModel.getSdProfilePic()).getContent());
} catch (Throwable ex) {
Log.e("austin_debug", "bitmap: " + ex);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
main.mainBinding.mainProfileImage.setImageBitmap(mIcon_val);
}
}
}

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@ -43,6 +44,8 @@ import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -65,6 +68,8 @@ import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.Utils;
import static awais.instagrabber.utils.Utils.settingsHelper;
public final class PostViewer extends BaseLanguageActivity {
private ActivityViewerBinding viewerBinding;
private String url, prevUsername, commentsEndCursor;
@ -151,7 +156,10 @@ public final class PostViewer extends BaseLanguageActivity {
viewerBinding.bottomPanel.btnMute.setImageResource(intVol == 0f ? R.drawable.vol : R.drawable.mute);
Utils.sessionVolumeFull = intVol == 1f;
}
} else if (v == viewerBinding.btnLike) {
new Like().execute();
} else if (v == viewerBinding.btnBookmark) {
new Bookmark().execute();
} else {
final Object tag = v.getTag();
if (tag instanceof ViewerPostModel) {
@ -203,6 +211,14 @@ public final class PostViewer extends BaseLanguageActivity {
viewerBinding.topPanel.ivProfilePic.setOnClickListener(onClickListener);
viewerBinding.ivToggleFullScreen.setOnClickListener(onClickListener);
if (Utils.isEmpty(settingsHelper.getString(Constants.COOKIE))) {
viewerBinding.btnLike.setVisibility(View.GONE);
viewerBinding.btnBookmark.setVisibility(View.GONE);
}
else {
viewerBinding.btnLike.setOnClickListener(onClickListener);
viewerBinding.btnBookmark.setOnClickListener(onClickListener);
}
viewerBinding.btnDownload.setOnClickListener(downloadClickListener);
profileDialogAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,
@ -345,6 +361,8 @@ public final class PostViewer extends BaseLanguageActivity {
postModel.setPostId(viewerPostModel.getPostId());
postModel.setTimestamp(viewerPostModel.getTimestamp());
postModel.setPostCaption(viewerPostModel.getPostCaption());
postModel.setLike(viewerPostModel.getLike());
postModel.setBookmark(viewerPostModel.getBookmark());
}
setupPostInfoBar(viewerPostModel.getUsername(), viewerPostModel.getItemType());
@ -555,6 +573,28 @@ public final class PostViewer extends BaseLanguageActivity {
postModel.setPostId(viewerPostModel.getPostId());
postModel.setTimestamp(viewerPostModel.getTimestamp());
postModel.setPostCaption(viewerPostModel.getPostCaption());
postModel.setLike(viewerPostModel.getLike());
postModel.setBookmark(viewerPostModel.getBookmark());
if (viewerPostModel.getLike() == true) {
viewerBinding.btnLike.setText(R.string.unlike);
viewerBinding.btnLike.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(
R.color.btn_pink_background, null)));
}
else {
viewerBinding.btnLike.setText(R.string.like);
viewerBinding.btnLike.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(
R.color.btn_lightpink_background, null)));
}
if (viewerPostModel.getBookmark() == true) {
viewerBinding.btnBookmark.setText(R.string.unbookmark);
viewerBinding.btnBookmark.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(
R.color.btn_orange_background, null)));
}
else {
viewerBinding.btnBookmark.setText(R.string.bookmark);
viewerBinding.btnBookmark.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(
R.color.btn_lightorange_background, null)));
}
}
viewerBinding.bottomPanel.tvPostDate.setText(viewerPostModel.getPostDate());
@ -639,4 +679,77 @@ public final class PostViewer extends BaseLanguageActivity {
newUiOptions ^= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(newUiOptions);
}
/*
Recommended for PERSONAL use only
Don't ever think about running a like farm with this
*/
class Like extends AsyncTask<Void, Void, Void> {
boolean ok = false;
protected Void doInBackground(Void... voids) {
final String url = "https://www.instagram.com/web/likes/"+postModel.getPostId()+"/"+
(postModel.getLike() == true ? "unlike/" : "like/");
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", "like: " + ex);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
if (ok == true) {
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) {
viewerPostModel.setBookmark(postModel.getBookmark() == true ? false : true);
postModel.setBookmark(postModel.getBookmark() == true ? false : true);
refreshPost();
}
}
}
}

View File

@ -126,21 +126,24 @@ public final class StoryViewer extends BaseLanguageActivity {
&& intent.hasExtra(Constants.FEED)) {
final FeedStoryModel[] storyFeed = (FeedStoryModel[]) intent.getSerializableExtra(Constants.FEED);
final int index = intent.getIntExtra(Constants.FEED_ORDER, 1738);
final FeedStoryModel feedStoryModel = isRightSwipe ?
(storyFeed.length == 0 ? null : storyFeed[index-1]) :
(storyFeed.length == index+1 ? null : storyFeed[index+1]);
final StoryModel[] nextStoryModels = feedStoryModel.getStoryModels();
if ((isRightSwipe == true && index == 0) || (isRightSwipe == false && index == storyFeed.length - 1))
Toast.makeText(getApplicationContext(), R.string.no_more_stories, Toast.LENGTH_SHORT).show();
else {
final FeedStoryModel feedStoryModel = isRightSwipe ?
(index == 0 ? null : storyFeed[index - 1]) :
(storyFeed.length == index + 1 ? null : storyFeed[index + 1]);
final StoryModel[] nextStoryModels = feedStoryModel.getStoryModels();
if (feedStoryModel != null) {
final Intent newIntent = new Intent(getApplicationContext(), StoryViewer.class)
.putExtra(Constants.EXTRAS_STORIES, nextStoryModels)
.putExtra(Constants.EXTRAS_USERNAME, feedStoryModel.getProfileModel().getUsername())
.putExtra(Constants.FEED, storyFeed)
.putExtra(Constants.FEED_ORDER, isRightSwipe ? (index-1) : (index+1));
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(newIntent);
if (feedStoryModel != null) {
final Intent newIntent = new Intent(getApplicationContext(), StoryViewer.class)
.putExtra(Constants.EXTRAS_STORIES, nextStoryModels)
.putExtra(Constants.EXTRAS_USERNAME, feedStoryModel.getProfileModel().getUsername())
.putExtra(Constants.FEED, storyFeed)
.putExtra(Constants.FEED_ORDER, isRightSwipe ? (index - 1) : (index + 1));
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(newIntent);
}
}
else Toast.makeText(getApplicationContext(), R.string.no_more_stories, Toast.LENGTH_SHORT).show();
}
else {
if (isRightSwipe) {

View File

@ -76,7 +76,7 @@ public final class DiscoverFetcher extends AsyncTask<Void, Void, DiscoverItemMod
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Linux; Android 8.1.0; motorola one Build/OPKS28.63-18-3; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36 Instagram 72.0.0.21.98 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 132081645)");
urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT);
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
final JSONObject discoverResponse = new JSONObject(Utils.readFromConnection(urlConnection));

View File

@ -129,7 +129,9 @@ public final class FeedFetcher extends AsyncTask<Void, Void, FeedModel[]> {
feedItem.getString(Constants.EXTRAS_SHORTCODE),
captionText,
commentsCount,
feedItem.optLong("taken_at_timestamp", -1));
feedItem.optLong("taken_at_timestamp", -1),
feedItem.getBoolean("viewer_has_liked"),
feedItem.getBoolean("viewer_has_saved"));
final boolean isSlider = "GraphSidecar".equals(mediaType) && feedItem.has("edge_sidecar_to_children");
@ -150,7 +152,7 @@ public final class FeedFetcher extends AsyncTask<Void, Void, FeedModel[]> {
node.getString(Constants.EXTRAS_ID),
isChildVideo ? node.getString("video_url") : Utils.getHighQualityImage(node),
null, null, null,
node.optLong("video_view_count", -1), -1);
node.optLong("video_view_count", -1), -1, false, false);
sliderItems[j].setSliderDisplayUrl(node.getString("display_url"));
}

View File

@ -88,7 +88,7 @@ public final class PostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]>
Utils.isEmpty(postCaption) ? null : postCaption,
username,
isVideo && media.has("video_view_count") ? media.getLong("video_view_count") : -1,
timestamp);
timestamp, media.getBoolean("viewer_has_liked"), media.getBoolean("viewer_has_saved"));
postModel.setCommentsCount(commentsCount);
postModel.setCommentsEndCursor(endCursor);
@ -112,7 +112,7 @@ public final class PostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]>
postCaption,
username,
isChildVideo && node.has("video_view_count") ? node.getLong("video_view_count") : -1,
timestamp);
timestamp, media.getBoolean("viewer_has_liked"), media.getBoolean("viewer_has_saved"));
postModels[i].setSliderDisplayUrl(node.getString("display_url"));
Utils.checkExistence(downloadDir, customDir, username, true, i, postModels[i]);

View File

@ -106,7 +106,8 @@ public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
mediaNode.getString("display_url"), mediaNode.getString("thumbnail_src"),
mediaNode.getString(Constants.EXTRAS_SHORTCODE),
captions.length() > 0 ? captions.getJSONObject(0).getJSONObject("node").getString("text") : null,
mediaNode.getLong("taken_at_timestamp"));
mediaNode.getLong("taken_at_timestamp"), mediaNode.optBoolean("viewer_has_liked"),
mediaNode.optBoolean("viewer_has_saved"));
Utils.checkExistence(downloadDir, customDir, username, isSlider, -1, models[i]);
}

View File

@ -30,19 +30,24 @@ public final class AboutDialog extends BottomSheetDialogFragment {
final LinearLayoutCompat infoContainer = contentView.findViewById(R.id.infoContainer);
final View btnTelegram = infoContainer.getChildAt(1);
final View btnProject = infoContainer.getChildAt(2);
final View btnMatrix = infoContainer.getChildAt(2);
final View btnProject = infoContainer.getChildAt(3);
final View.OnClickListener onClickListener = v -> {
final Intent intent = new Intent(Intent.ACTION_VIEW);
if (v == btnTelegram) {
intent.setData(Uri.parse("https://t.me/grabber_app"));
if (!Utils.isEmpty(Utils.telegramPackage))
intent.setPackage(Utils.telegramPackage);
}
else if (v == btnMatrix) {
intent.setData(Uri.parse("https://matrix.to/#/#instagrabber:matrix.org"));
} else
intent.setData(Uri.parse("https://github.com/austinhuang0131/instagrabber/"));
startActivity(intent);
};
btnProject.setOnClickListener(onClickListener);
btnTelegram.setOnClickListener(onClickListener);
btnMatrix.setOnClickListener(onClickListener);
final String description = getString(R.string.description);
if (!Utils.isEmpty(description)) {
@ -60,32 +65,15 @@ public final class AboutDialog extends BottomSheetDialogFragment {
c = descriptionText.charAt(i);
if (c == ']') {
descriptionText.delete(i, i + 1);
descriptionText.setSpan(new RelativeSizeSpan(0.5f), smallTextStart, i, 0);
descriptionText.setSpan(new RelativeSizeSpan(0.6f), smallTextStart, i, 0);
}
++i;
} while (c != ']' || i == descriptionText.length() - 1);
} else if (c == '{') {
final int smallerTextStart = i;
descriptionText.delete(i, i + 1);
i = smallerTextStart;
do {
c = descriptionText.charAt(i);
if (c == '}') {
descriptionText.delete(i, i + 1);
descriptionText.setSpan(new RelativeSizeSpan(0.35f), smallerTextStart, i, 0);
}
++i;
lastIndex = i;
} while (c != '}' || i == descriptionText.length() - 1);
}
}
lastIndex = Utils.indexOfChar(descriptionText, '@', lastIndex);
descriptionText.setSpan(new URLSpan("https://t.me/awais404"), lastIndex, lastIndex + 9, 0);
lastIndex = Utils.indexOfChar(descriptionText, ':', lastIndex + 9) + 2;
descriptionText.setSpan(new URLSpan("mailto:chapter50000@hotmail.com"), lastIndex, lastIndex + 24, 0);
lastIndex = Utils.indexOfChar(descriptionText, '@', lastIndex) - 12;
descriptionText.setSpan(new URLSpan("mailto:instagrabber@austinhuang.me"), lastIndex, lastIndex + 27, 0);
final TextView textView = (TextView) infoContainer.getChildAt(0);
textView.setMovementMethod(new LinkMovementMethod());

View File

@ -17,13 +17,16 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatCheckBox;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentManager;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import awais.instagrabber.BuildConfig;
import awais.instagrabber.R;
import awais.instagrabber.activities.Login;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DirectoryChooser;
import awais.instagrabber.utils.LocaleUtils;
import awais.instagrabber.utils.Utils;
@ -45,7 +48,8 @@ public final class SettingsDialog extends BottomSheetDialogFragment implements V
CompoundButton.OnCheckedChangeListener {
private Activity activity;
private FragmentManager fragmentManager;
private View btnSaveTo, btnImportExport, btnLogin, btnTimeSettings, btnReport;
private View btnSaveTo, btnImportExport, btnLogin, btnLogout, btnTimeSettings, btnReport;
private AppCompatTextView settingTitle;
private Spinner spAppTheme, spLanguage;
private boolean somethingChanged = false;
private int currentTheme, currentLanguage, selectedLanguage;
@ -81,7 +85,10 @@ 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+")");
btnLogin = contentView.findViewById(R.id.btnLogin);
btnLogout = contentView.findViewById(R.id.btnLogout);
btnSaveTo = contentView.findViewById(R.id.btnSaveTo);
btnImportExport = contentView.findViewById(R.id.importExport);
btnTimeSettings = contentView.findViewById(R.id.btnTimeSettings);
@ -90,11 +97,14 @@ public final class SettingsDialog extends BottomSheetDialogFragment implements V
Utils.setTooltipText(btnImportExport, R.string.import_export);
btnLogin.setOnClickListener(this);
btnLogout.setOnClickListener(this);
btnReport.setOnClickListener(this);
btnSaveTo.setOnClickListener(this);
btnImportExport.setOnClickListener(this);
btnTimeSettings.setOnClickListener(this);
if (Utils.isEmpty(settingsHelper.getString(Constants.COOKIE))) btnLogout.setEnabled(false);
spAppTheme = contentView.findViewById(R.id.spAppTheme);
currentTheme = settingsHelper.getInteger(APP_THEME);
spAppTheme.setSelection(currentTheme);
@ -106,7 +116,6 @@ public final class SettingsDialog extends BottomSheetDialogFragment implements V
spLanguage.setOnItemSelectedListener(this);
final AppCompatCheckBox cbSaveTo = contentView.findViewById(R.id.cbSaveTo);
final AppCompatCheckBox cbShowFeed = contentView.findViewById(R.id.cbShowFeed);
final AppCompatCheckBox cbMuteVideos = contentView.findViewById(R.id.cbMuteVideos);
final AppCompatCheckBox cbBottomToolbar = contentView.findViewById(R.id.cbBottomToolbar);
final AppCompatCheckBox cbAutoloadPosts = contentView.findViewById(R.id.cbAutoloadPosts);
@ -118,12 +127,10 @@ public final class SettingsDialog extends BottomSheetDialogFragment implements V
cbBottomToolbar.setChecked(settingsHelper.getBoolean(BOTTOM_TOOLBAR));
cbAutoplayVideos.setChecked(settingsHelper.getBoolean(AUTOPLAY_VIDEOS));
cbShowFeed.setChecked(settingsHelper.getBoolean(SHOW_FEED));
cbAutoloadPosts.setChecked(settingsHelper.getBoolean(AUTOLOAD_POSTS));
cbDownloadUsername.setChecked(settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER));
setupListener(cbSaveTo);
setupListener(cbShowFeed);
setupListener(cbMuteVideos);
setupListener(cbBottomToolbar);
setupListener(cbAutoloadPosts);
@ -163,7 +170,11 @@ public final class SettingsDialog extends BottomSheetDialogFragment implements V
if (v == btnLogin) {
startActivity(new Intent(v.getContext(), Login.class));
somethingChanged = true;
} else if (v == btnLogout) {
Utils.setupCookies("LOGOUT");
settingsHelper.putString(Constants.COOKIE, null);
this.dismiss();
activity.recreate();
} else if (v == btnImportExport) {
if (ContextCompat.checkSelfPermission(activity, Utils.PERMS[0]) == PackageManager.PERMISSION_DENIED)
requestPermissions(Utils.PERMS, 6007);
@ -192,7 +203,6 @@ public final class SettingsDialog extends BottomSheetDialogFragment implements V
else if (id == R.id.cbAutoplayVideos) settingsHelper.putBoolean(AUTOPLAY_VIDEOS, checked);
else if (id == R.id.cbMuteVideos) settingsHelper.putBoolean(MUTED_VIDEOS, checked);
else if (id == R.id.cbAutoloadPosts) settingsHelper.putBoolean(AUTOLOAD_POSTS, checked);
else if (id == R.id.cbShowFeed) settingsHelper.putBoolean(SHOW_FEED, checked);
else if (id == R.id.cbSaveTo) {
settingsHelper.putBoolean(FOLDER_SAVE_TO, checked);
btnSaveTo.setEnabled(checked);

View File

@ -59,7 +59,8 @@ public final class MultiDirectDialog extends BaseLanguageActivity {
final ArrayList<PostModel> models = new ArrayList<>(postModels.length - 1);
for (final ViewerPostModel postModel : postModels)
models.add(new PostModel(postModel.getItemType(), postModel.getPostId(), postModel.getDisplayUrl(),
postModel.getSliderDisplayUrl(), postModel.getShortCode(), postModel.getPostCaption(), postModel.getTimestamp()));
postModel.getSliderDisplayUrl(), postModel.getShortCode(), postModel.getPostCaption(), postModel.getTimestamp(),
postModel.getLike(), postModel.getBookmark()));
postsAdapter = new PostsAdapter(models, v -> {
final Object tag = v.getTag();

View File

@ -18,6 +18,21 @@ public abstract class BasePostModel implements Serializable {
protected boolean isDownloaded;
protected long timestamp;
protected int position;
boolean liked, bookmarked;
public boolean getLike() {
return liked;
}
public boolean getBookmark() {
return bookmarked;
}
public boolean setLike(final boolean like) {
liked = like; this.liked = liked; return liked;
}
public boolean setBookmark(final boolean bookmark) {
bookmarked = bookmark; this.bookmarked = bookmarked; return bookmarked;
}
public MediaItemType getItemType() {
return itemType;

View File

@ -10,8 +10,8 @@ public final class FeedModel extends PostModel {
public FeedModel(final ProfileModel profileModel, final MediaItemType itemType, final long viewCount, final String postId,
final String displayUrl, final String thumbnailUrl, final String shortCode, final String postCaption,
final long commentsCount, final long timestamp) {
super(itemType, postId, displayUrl, thumbnailUrl, shortCode, postCaption, timestamp);
final long commentsCount, final long timestamp, boolean liked, boolean bookmarked) {
super(itemType, postId, displayUrl, thumbnailUrl, shortCode, postCaption, timestamp, liked, bookmarked);
this.profileModel = profileModel;
this.commentsCount = commentsCount;
this.viewCount = viewCount;

View File

@ -13,7 +13,7 @@ public class PostModel extends BasePostModel {
}
public PostModel(final MediaItemType itemType, final String postId, final String displayUrl, final String thumbnailUrl,
final String shortCode, final CharSequence postCaption, long timestamp) {
final String shortCode, final CharSequence postCaption, long timestamp, boolean liked, boolean bookmarked) {
this.itemType = itemType;
this.postId = postId;
this.displayUrl = displayUrl;
@ -21,6 +21,8 @@ public class PostModel extends BasePostModel {
this.shortCode = shortCode;
this.postCaption = postCaption;
this.timestamp = timestamp;
this.liked = liked;
this.bookmarked = bookmarked;
}
public String getThumbnailUrl() {
@ -31,6 +33,20 @@ 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;
}

View File

@ -10,7 +10,8 @@ public final class ViewerPostModel extends BasePostModel {
private boolean isCurrentSlide = false;
public ViewerPostModel(final MediaItemType itemType, final String postId, final String displayUrl, final String shortCode,
final String postCaption, final String username, final long videoViews, final long timestamp) {
final String postCaption, final String username, final long videoViews, final long timestamp,
boolean liked, boolean bookmarked) {
this.itemType = itemType;
this.postId = postId;
this.displayUrl = displayUrl;
@ -19,6 +20,22 @@ public final class ViewerPostModel extends BasePostModel {
this.shortCode = shortCode;
this.videoViews = videoViews;
this.timestamp = timestamp;
this.liked = liked;
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() {

View File

@ -1,50 +0,0 @@
package awais.instagrabber.utils;
import android.os.AsyncTask;
import android.util.Log;
import java.net.HttpURLConnection;
import java.net.URL;
import awais.instagrabber.BuildConfig;
import awais.instagrabber.interfaces.FetchListener;
public final class ChangelogFetcher extends AsyncTask<Void, Void, String> {
private final FetchListener<CharSequence> fetchListener;
public ChangelogFetcher(final FetchListener<CharSequence> fetchListener) {
this.fetchListener = fetchListener;
}
@Override
protected String doInBackground(final Void... voids) {
String result = null;
final String changelogUrl = "https://gitlab.com/AwaisKing/instagrabber/-/raw/master/CHANGELOG";
try {
final HttpURLConnection conn = (HttpURLConnection) new URL(changelogUrl).openConnection();
conn.setUseCaches(false);
conn.connect();
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
result = Utils.readFromConnection(conn);
}
conn.disconnect();
} catch (final Exception e) {
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
}
return result;
}
@Override
protected void onPreExecute() {
if (fetchListener != null) fetchListener.doBefore();
}
@Override
protected void onPostExecute(final String result) {
if (fetchListener != null) fetchListener.onResult(result);
}
}

View File

@ -237,7 +237,6 @@ public final class ExportImportUtils {
json.put(Constants.MUTED_VIDEOS, settingsHelper.getBoolean(Constants.MUTED_VIDEOS));
json.put(Constants.BOTTOM_TOOLBAR, settingsHelper.getBoolean(Constants.BOTTOM_TOOLBAR));
json.put(Constants.AUTOPLAY_VIDEOS, settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS));
json.put(Constants.SHOW_FEED, settingsHelper.getBoolean(Constants.SHOW_FEED));
json.put(Constants.AUTOLOAD_POSTS, settingsHelper.getBoolean(Constants.AUTOLOAD_POSTS));
json.put(Constants.FOLDER_SAVE_TO, settingsHelper.getBoolean(Constants.FOLDER_SAVE_TO));

View File

@ -13,6 +13,7 @@ import android.text.style.URLSpan;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
@ -39,60 +40,8 @@ public final class FlavorTown {
public static void changelogCheck(@NonNull final Context context) {
if (settingsHelper.getInteger(Constants.PREV_INSTALL_VERSION) < BuildConfig.VERSION_CODE) {
new ChangelogFetcher(new FetchListener<CharSequence>() {
private AlertDialog alertDialog;
private TextView textView;
@Override
public void doBefore() {
final ViewGroup rootView = (ViewGroup) View.inflate(context, R.layout.layout_changelog_textview, null);
textView = (TextView) rootView.getChildAt(0);
textView.setMovementMethod(new LinkMovementMethod());
alertDialog = new AlertDialog.Builder(context).setTitle(R.string.title_changelog).setView(rootView).create();
}
@Override
public void onResult(final CharSequence result) {
if (alertDialog != null && textView != null && !Utils.isEmpty(result)) {
final Resources resources = context.getResources();
final SpannableStringBuilder stringBuilder = new SpannableStringBuilder(
resources.getString(R.string.curr_version, BuildConfig.VERSION_NAME))
.append('\n');
stringBuilder.setSpan(new RelativeSizeSpan(1.3f), 0, stringBuilder.length() - 1, 0);
final int resLen = result.length();
int versionTimes = 0;
for (int i = 0; i < resLen; ++i) {
final char c = result.charAt(i);
if (c == 'v' && i > 0) {
final char c1 = result.charAt(i - 1);
if (c1 == '\r' || c1 == '\n') {
if (++versionTimes == 4) break;
}
}
stringBuilder.append(c);
}
final String strReadMore = resources.getString(R.string.read_more);
stringBuilder.append('\n').append(strReadMore);
final int sbLen = stringBuilder.length();
stringBuilder.setSpan(new URLSpan("https://gitlab.com/AwaisKing/instagrabber/-/blob/master/CHANGELOG"),
sbLen - strReadMore.length(), sbLen, 0);
textView.setText(stringBuilder, TextView.BufferType.SPANNABLE);
alertDialog.show();
}
settingsHelper.putInteger(Constants.PREV_INSTALL_VERSION, BuildConfig.VERSION_CODE);
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
Toast.makeText(context, R.string.updated, Toast.LENGTH_SHORT).show();
settingsHelper.putInteger(Constants.PREV_INSTALL_VERSION, BuildConfig.VERSION_CODE);
}
}
}

View File

@ -24,7 +24,6 @@ import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
import static awais.instagrabber.utils.Constants.MUTED_VIDEOS;
import static awais.instagrabber.utils.Constants.PREV_INSTALL_VERSION;
import static awais.instagrabber.utils.Constants.PROFILE_FETCH_MODE;
import static awais.instagrabber.utils.Constants.SHOW_FEED;
import static awais.instagrabber.utils.Constants.SHOW_QUICK_ACCESS_DIALOG;
public final class SettingsHelper {
@ -107,7 +106,7 @@ public final class SettingsHelper {
public @interface StringSettings {}
@StringDef({DOWNLOAD_USER_FOLDER, BOTTOM_TOOLBAR, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS,
AUTOLOAD_POSTS, SHOW_FEED, CUSTOM_DATE_TIME_FORMAT_ENABLED})
AUTOLOAD_POSTS, CUSTOM_DATE_TIME_FORMAT_ENABLED})
public @interface BooleanSettings {}
@StringDef({APP_THEME, APP_LANGUAGE, PROFILE_FETCH_MODE, PREV_INSTALL_VERSION})

View File

@ -117,7 +117,11 @@ public final class Utils {
public static SimpleDateFormat datetimeParser;
public static void setupCookies(final String cookieRaw) {
if (cookieRaw != null && !isEmpty(cookieRaw)) {
if (cookieRaw == "LOGOUT") {
final CookieStore cookieStore = NET_COOKIE_MANAGER.getCookieStore();
cookieStore.removeAll();
}
else if (cookieRaw != null && !isEmpty(cookieRaw)) {
final CookieStore cookieStore = NET_COOKIE_MANAGER.getCookieStore();
try {
final URI uri1 = new URI("https://instagram.com");

View File

@ -97,9 +97,36 @@
android:layout_height="0dp"
android:layout_weight="1.4" />
<FrameLayout
android:layout_width="0dp"
android:layout_height="0dp"
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_weight="0.26"
android:background="#0000" />
android:background="#0000"
android:weightSum="2">
<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_marginRight="8dp"
android:layout_weight="1"
android:text="@string/like"
android:textColor="@color/btn_lightpink_text_color"
android:textSize="20sp"
app:backgroundTint="@color/btn_lightpink_background" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnBookmark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:text="@string/bookmark"
android:textColor="@color/btn_lightorange_text_color"
android:textSize="20sp"
app:backgroundTint="@color/btn_lightorange_background" />
</androidx.appcompat.widget.LinearLayoutCompat>
</LinearLayout>

View File

@ -37,6 +37,7 @@
android:gravity="center_vertical"
android:padding="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="20sp"
android:textColor="?android:textColorPrimary" />
<androidx.appcompat.widget.AppCompatButton
@ -47,9 +48,21 @@
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@string/telegram_link"
android:textColor="@color/btn_green_text_color"
android:textSize="16sp"
app:backgroundTint="@color/btn_green_background" />
android:textColor="@color/btn_blue_text_color"
android:textSize="20sp"
app:backgroundTint="@color/btn_blue_background" />
<androidx.appcompat.widget.AppCompatButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@string/matrix_link"
android:textColor="@color/btn_black_text_color"
android:textSize="20sp"
app:backgroundTint="@color/btn_black_background" />
<androidx.appcompat.widget.AppCompatButton
android:layout_width="match_parent"
@ -59,9 +72,9 @@
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@string/project_link"
android:textColor="@color/btn_blue_text_color"
android:textSize="16sp"
app:backgroundTint="@color/btn_blue_background" />
android:textColor="@color/btn_green_text_color"
android:textSize="20sp"
app:backgroundTint="@color/btn_green_background" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.core.widget.NestedScrollView>
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@ -12,6 +12,7 @@
<androidx.appcompat.widget.AppCompatTextView
style="@style/TextAppearance.AppCompat.Headline"
android:id="@+id/settingTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -259,42 +260,40 @@
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:background="?android:selectableItemBackground"
android:orientation="horizontal"
android:padding="5dp">
<androidx.appcompat.widget.AppCompatCheckBox
android:id="@+id/cbShowFeed"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@string/show_feed" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:padding="5dp"
android:text="@string/show_feed"
android:textColor="?android:textColorPrimary"
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@string/login"
android:textColor="@color/btn_green_text_color"
android:textSize="20sp"
app:backgroundTint="@color/btn_green_background" />
android:background="?android:selectableItemBackground"
android:orientation="horizontal"
android:weightSum="2">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:text="@string/login"
android:textColor="@color/btn_green_text_color"
android:textSize="20sp"
app:backgroundTint="@color/btn_green_background" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnLogout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:text="@string/logout"
android:textColor="@color/btn_red_text_color"
android:textSize="20sp"
app:backgroundTint="@color/btn_red_background" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnTimeSettings"
@ -318,9 +317,9 @@
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@string/send_logs"
android:textColor="@color/btn_red_text_color"
android:textColor="@color/btn_black_text_color"
android:textSize="20sp"
app:backgroundTint="@color/btn_red_background" />
app:backgroundTint="@color/btn_black_background" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.core.widget.NestedScrollView>
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@ -132,7 +132,7 @@
android:padding="12dp"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="16sp"
tools:text="Fuck y'all for real." />
tools:text="BOTTOM TEXT HAHA FUNNY MEME" />
</FrameLayout>
</ScrollView>
</RelativeLayout>

View File

@ -24,7 +24,7 @@
android:paddingEnd="4dp"
android:paddingRight="4dp"
android:textColor="@color/feed_text_primary_color"
android:textSize="18sp" />
android:textSize="18sp"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/viewStoryPost"

View File

@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="description">Esto comenzó como una pequeña y básica aplicación personal con intenciones de [copia-]descargar publicaciones de Instagram.\nAparentemente tengo un temperamento rápido y soy bastante impaciente a veces… \{frecuentemente… la mayoría del tiempo… ¡OK! todo el tiempo!} Y gracias a Dios casi todos los descargadores de Instagram tienen al menos un proveedor de anuncios, así que decidí hacer mi propio descargador.\nEntonces aquí está, la pequeña y estúpida aplicación para hacer que eso suceda.\n\nDe todas formas, si tienes \{como si tu mamá te hiciera} una pregunta, sugerencia, corrección de errores o cualquier otra pregunta, hmu en un Telegram o correo electrónico\nTelegram: @awais404\nCorreo electrónico: chapter50000@hotmail.com (sí, 50.000 capítulos! 😎🤘)</string>
<string name="action_quickaccess">Acceso rápido</string>
<string name="action_about">Sobre</string>
<string name="action_dms">Mensajes Directos</string>

View File

@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="description">Ça a commencé comme une petite application personnelle de base avec l\'intention de télécharger (voler) des posts sur Instagram.\nApparemment, j\'ai un tempérament nerveux et je suis parfois assez impatient\{… généralement… la plupart du temps… OK ! tout le temps ! }et Dieu merci, presque tous les téléchargeurs d\'insta ont au moins un fournisseur de publicité, j\'ai donc décidé de créer le mien.\nAlors voilà ma petite application assez stupide.\n\nQuoi qu\'il en soit, si vous avez\{ ou ta mère }une question, suggestion, rapport ou correction de bogues, ou n\'importe quelle autre question, contactez-moi par Telegram ou par mail.\nTelegram: @awais404\nEmail: chapter50000@hotmail.com (ouais 50000 chapitres ! 😎🤘)</string>
<string name="action_quickaccess">Accès rapide</string>
<string name="action_about">À propos</string>
<string name="action_dms">Messages privés</string>

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">InstaGrabber</string>
<string name="description"> Aplikasi ini diawali sebagai aplikasi personal yang kecil dan sederhana dengan niat [mencu-]mengunduh kiriman dari Instagram. \nTernyata aku cepat marah dan terkadang gak sabaran\{… biasanya sih… sering gitu… OK! Hampir setiap saat! }dan syukurnya (/s) hampir setiap pengunduh Instagram punya paling nggak satu penyedia iklan, jadi aku memutuskan untuk membuatnya sendiri.\nDan, inilah hasilnya, suatu aplikasi sejadi-jadinya untuk mewujudkan hal itu.\n\nBagaimanapun, kalau kamu\{ atau ibumu }punya pertanyaan, saran, perbaikan bug/masalah, laporan, atau lainnya, kirim pesan via telegram atau surel.\nTelegram: @awais404\nSurel: chapter50000@hotmail.com (iya 50.000 chapters! 😎🤘)</string>
<string name="action_quickaccess">Akses Cepat</string>
<string name="action_about">Tentang</string>

View File

@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="description">Questo è iniziato come una piccola app personale con le intenzioni di [rub-] scaricare post da Instagram. \nApparentemente ho un temperamento rapido e sono\ piuttosto impaziente a volte\{… di solito… il più delle volte… OK! tutto il tempo! } e grazie a Dio /s a quasi tutti i downloader di insta hanno almeno un fornitore di annunci, quindi ho deciso di creare il mio downloader.\nCosì, ecco la stupida piccola app per farlo accadere. \n\nIn ogni caso, se hai \{o la tua mamma ha} una domanda, un suggerimento, una correzione/segnalazione di bug o qualsiasi altra domanda, contattami su telegram o e-mail.\nTelegram: @ awais404\nEmail: chapter50000@hotmail.com (yeah 50,000 chapters! 😎🤘)</string>
<string name="action_quickaccess">Accesso rapido</string>
<string name="action_about">Riguardo</string>
<string name="action_dms">Direct Messaggi</string>

View File

@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="description">这是从带着以[偷-]下载 Instagram 帖子为目的而开始的小而简的个人应用程式。\n显然地我脾气不好有时也不怎么有耐性\{…通常… 大多数的时间… OK所有时候 }然后感谢老天 (讽) 几乎所有下载器都有至少一个广告商, 所以我决定做一个自己的下载器。\n于是乎这个愚蠢的小应用让一切变得可能。\n\n无论如何若你\{ 或你老妈 }有任何问题、建议、bug 修复/报告或任何疑问请在telegram或电邮敲我。\nTelegram: @awais404\nEmail: chapter50000@hotmail.com (没错50,000章! 😎🤘)</string>
<string name="action_quickaccess">快捷道</string>
<string name="action_about">关于</string>
<string name="action_dms">Direct消息</string>

View File

@ -8,12 +8,25 @@
<color name="btn_green_background">#5CE362</color>
<color name="btn_green_text_color">@color/text_color_light</color>
<color name="btn_black_background">#000000</color>
<color name="btn_black_text_color">@color/text_color_dark</color>
<color name="btn_blue_background">#0288D1</color>
<color name="btn_blue_text_color">@color/text_color_light</color>
<color name="btn_red_background">#E62323</color>
<color name="btn_red_text_color">@color/text_color_dark</color>
<color name="btn_pink_background">#FF69B4</color>
<color name="btn_pink_text_color">#FFFFFFFF</color>
<color name="btn_lightpink_background">#FFB6C1</color>
<color name="btn_lightpink_text_color">#FF000000</color>
<color name="btn_orange_background">#FF5500</color>
<color name="btn_orange_text_color">#FFFFFFFF</color>
<color name="btn_lightorange_background">#FFBB00</color>
<color name="btn_lightorange_text_color">#FF000000</color>
<color name="feed_text_primary_color">@color/text_color_light</color>
<color name="dm_profile_button_color">#efefef</color>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">InstaGrabber</string>
<string name="description">This started off as a small and basic little personal app with intentions of [steali-]downloading posts off Instagram.\nApparently i have a quick temper and I\'m pretty impatient sometimes\{… usually… most of the time… OK! all the time! }and thank God /s almost every insta downloader has at least one ad provider, so i decided to make my own downloader.\nSo here it is, the stupid little app to make that happen.\n\nAnyhow, if you have\{ or ur mom has }a question, suggestion, bug fix/report or any other query, hmu on telegram or email.\nTelegram: @awais404\nEmail: chapter50000@hotmail.com (yeah 50,000 chapters! 😎🤘)</string>
<string name="description">The original maintainer, AWAiS, made InstaGrabber as a small and basic little personal app with intentions of [steali-]downloading posts off Instagram. Very unfortunately, this was abandoned and me, Austin Huang, took over the ship. [Let\'s hope that\'s at least a lil\' bit cash money.] After all, this app is fully open source, ad-less, and tracking-less [aside from what Instagram knows]. Even if you don\'t care about downloading stuff [like me], it\'s still a great Instagram client to use!\n\nGot questions [or just wanna talk]? Contact instagrabber@austinhuang.me or click one of the buttons below.</string>
<string name="action_quickaccess">Quick Access</string>
<string name="action_about">About</string>
@ -64,6 +64,7 @@
<string name="post_viewer_download_album">Whole Album</string>
<string name="show_stories">Show stories</string>
<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>
@ -71,10 +72,18 @@
<string name="read_more">read more…</string>
<string name="login">Login</string>
<string name="send_logs">Send Logs [if something\'s not working]</string>
<string name="logout">Logout</string>
<string name="send_logs">Send Debug Logs</string>
<string name="time_settings">Post Time Settings</string>
<string name="project_link">Visit Project Page</string>
<string name="telegram_link">Join Telegram Group</string>
<string name="matrix_link">Join Matrix Room</string>
<string name="like">Like</string>
<string name="unlike">Unlike</string>
<string name="bookmark">Bookmark</string>
<string name="unbookmark">Unbookmark</string>
<string name="dialog_export_btn_export">Export</string>
<string name="dialog_export_btn_import">Import</string>
@ -92,7 +101,7 @@
<string name="refresh">Refresh</string>
<string name="get_cookies">Get cookies</string>
<string name="desktop_2fa">Desktop Mode\nfor 2FA</string>
<string name="desktop_2fa">Desktop Mode</string>
<string name="time_settings_title_custom">Custom Format</string>
<string name="time_settings_title_separator">Separator</string>
@ -166,6 +175,7 @@
<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="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>
</resources>

View File

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

View File

@ -0,0 +1,12 @@
InstaGrabber is an app that allows...
* Viewing **and downloading** Instagram posts, stories (including highlights)\*, DM\*, and profile pictures, **without** letting people know you viewed it! Works for followed private accounts\*!
* Like/bookmark posts\*!
* Downloading multiple posts at once (hold & select)!
* **Copy** post captions, comments, DM messages\*, and profile bios.
* **Compare** follower/following list!
* Searching usernames and hashtags.
<sub>* Requires [login](https://github.com/austinhuang0131/instagrabber/blob/master/README.md#how-to-log-in). You must be a current follower of the desired private accounts, this app cannot hack people (which I have to state despite the obvious)!</sub>
It can be used as a drop-in replacement for read functionalities of the official Instagram app, with unnecessary components stripped.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -0,0 +1 @@
A simple yet advanced viewer/downloader app for Instagram (+login support).

View File

@ -0,0 +1 @@
InstaGrabber Revived