From 73795dac08583fab5c99eeccf92d1dd0a2ca99ef Mon Sep 17 00:00:00 2001 From: Austin Huang Date: Tue, 28 Jul 2020 15:30:57 -0400 Subject: [PATCH] geotag time part 2 --- app/build.gradle | 4 +- .../java/awais/instagrabber/InstaApp.java | 5 +- .../java/awais/instagrabber/MainHelper.java | 163 ++++++++++++++++-- .../activities/CommentsViewer.java | 3 - .../awais/instagrabber/activities/Main.java | 28 ++- .../instagrabber/activities/PostViewer.java | 29 ++-- .../activities/ProfileViewer.java | 19 +- .../instagrabber/adapters/FeedAdapter.java | 30 +++- .../adapters/SuggestionsAdapter.java | 5 +- .../viewholder/FeedItemViewHolder.java | 3 +- .../instagrabber/asyncs/FeedFetcher.java | 5 +- .../instagrabber/asyncs/LocationFetcher.java | 79 +++++++++ .../instagrabber/asyncs/PostFetcher.java | 4 +- .../instagrabber/asyncs/PostsFetcher.java | 10 +- .../asyncs/StoryStatusFetcher.java | 9 +- .../asyncs/SuggestionsFetcher.java | 16 ++ .../helpers/VideoAwareRecyclerScroller.java | 12 +- .../dialogs/QuickAccessDialog.java | 7 +- .../awais/instagrabber/models/FeedModel.java | 10 +- .../instagrabber/models/LocationModel.java | 44 +++++ .../instagrabber/models/ViewerPostModel.java | 8 +- .../models/enums/SuggestionType.java | 1 + .../awais/instagrabber/utils/Constants.java | 2 + .../awais/instagrabber/utils/DataBox.java | 68 ++++++-- .../instagrabber/utils/ExportImportUtils.java | 3 +- .../awais/instagrabber/utils/FlavorTown.java | 2 + .../java/awaisomereport/LogCollector.java | 1 + app/src/main/res/drawable/ic_location.png | Bin 0 -> 8156 bytes app/src/main/res/layout/activity_main.xml | 120 +++++++++++-- app/src/main/res/values/strings.xml | 2 + .../android/changelogs/{34.txt => 35.txt} | 2 +- 31 files changed, 593 insertions(+), 101 deletions(-) create mode 100644 app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/models/LocationModel.java create mode 100644 app/src/main/res/drawable/ic_location.png rename fastlane/metadata/android/changelogs/{34.txt => 35.txt} (93%) diff --git a/app/build.gradle b/app/build.gradle index 2757b8d6..6f35bcaa 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,9 +10,9 @@ android { targetSdkVersion 29 // REMEMBER TO CHANGE versionCode AS WELL - // 16.7 is 32 + // 16.7 is 32, 16.9 is 35 (34 is public beta) - versionCode 34 + versionCode 35 versionName '16.9' multiDexEnabled true diff --git a/app/src/main/java/awais/instagrabber/InstaApp.java b/app/src/main/java/awais/instagrabber/InstaApp.java index 260eeeaf..9d9f67fe 100755 --- a/app/src/main/java/awais/instagrabber/InstaApp.java +++ b/app/src/main/java/awais/instagrabber/InstaApp.java @@ -59,7 +59,10 @@ public final class InstaApp extends MultiDexApplication { clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); if (datetimeParser == null) - datetimeParser = new SimpleDateFormat(settingsHelper.getString(Constants.DATE_TIME_FORMAT), LocaleUtils.getCurrentLocale()); + datetimeParser = new SimpleDateFormat( + settingsHelper.getBoolean(Constants.CUSTOM_DATE_TIME_FORMAT_ENABLED) ? + settingsHelper.getString(Constants.CUSTOM_DATE_TIME_FORMAT) : + settingsHelper.getString(Constants.DATE_TIME_FORMAT), LocaleUtils.getCurrentLocale()); changeTheme(); } diff --git a/app/src/main/java/awais/instagrabber/MainHelper.java b/app/src/main/java/awais/instagrabber/MainHelper.java index 42073157..88dcd225 100755 --- a/app/src/main/java/awais/instagrabber/MainHelper.java +++ b/app/src/main/java/awais/instagrabber/MainHelper.java @@ -56,6 +56,7 @@ import awais.instagrabber.asyncs.FeedFetcher; import awais.instagrabber.asyncs.FeedStoriesFetcher; import awais.instagrabber.asyncs.HashtagFetcher; import awais.instagrabber.asyncs.HighlightsFetcher; +import awais.instagrabber.asyncs.LocationFetcher; import awais.instagrabber.asyncs.PostsFetcher; import awais.instagrabber.asyncs.ProfileFetcher; import awais.instagrabber.asyncs.StoryStatusFetcher; @@ -109,8 +110,8 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { final String username; final String postFix; - if (!isHashtag) { - username = main.profileModel.getUsername(); + if (!isHashtag && !isLocation) { + username = "@"+main.profileModel.getUsername(); postFix = "/" + main.profileModel.getPostCount() + ')'; } else { username = null; @@ -119,6 +120,8 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { if (isHashtag) main.mainBinding.toolbar.toolbar.setTitle(main.userQuery); + else if (isLocation) + main.mainBinding.toolbar.toolbar.setTitle(main.locationModel.getName()); else main.mainBinding.toolbar.toolbar.setTitle(username + " (" + main.allItems.size() + postFix); final PostModel model = result[result.length - 1]; @@ -143,7 +146,6 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { .setUsername(main.profileModel.getUsername()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else { main.mainBinding.swipeRefreshLayout.setRefreshing(false); - main.mainBinding.tagToolbar.setVisibility(View.VISIBLE); } model.setPageCursor(false, null); } @@ -252,7 +254,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { private final Resources resources; private final View collapsingToolbar; private final RecyclerLazyLoader lazyLoader; - private boolean isHashtag; + private boolean isHashtag, isUser, isLocation; private PostsAdapter postsAdapter; private FeedAdapter feedAdapter; private RecyclerLazyLoader feedLazyLoader, discoverLazyLoader; @@ -599,7 +601,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { .putExtra(Constants.EXTRAS_POST, new PostModel(modelText)), 9629); } else { main.addToStack(); - main.userQuery = modelType == IntentModelType.HASHTAG ? '#' + modelText : modelText; + main.userQuery = modelType == IntentModelType.HASHTAG ? '#' + modelText : ("@"+modelText); onRefresh(); } } @@ -623,22 +625,36 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { main.mainBinding.privatePage.setVisibility(View.GONE); main.mainBinding.mainProfileImage.setImageBitmap(null); main.mainBinding.mainHashtagImage.setImageBitmap(null); + main.mainBinding.mainLocationImage.setImageBitmap(null); main.mainBinding.mainUrl.setText(null); + main.mainBinding.locationUrl.setText(null); main.mainBinding.mainFullName.setText(null); + main.mainBinding.locationFullName.setText(null); main.mainBinding.mainPostCount.setText(null); + main.mainBinding.mainLocPostCount.setText(null); + main.mainBinding.mainTagPostCount.setText(null); main.mainBinding.mainFollowers.setText(null); main.mainBinding.mainFollowing.setText(null); main.mainBinding.mainBiography.setText(null); + main.mainBinding.locationBiography.setText(null); main.mainBinding.mainBiography.setEnabled(false); + main.mainBinding.locationBiography.setEnabled(false); main.mainBinding.mainProfileImage.setEnabled(false); + main.mainBinding.mainLocationImage.setEnabled(false); main.mainBinding.mainHashtagImage.setEnabled(false); main.mainBinding.mainBiography.setMentionClickListener(null); + main.mainBinding.locationBiography.setMentionClickListener(null); main.mainBinding.mainUrl.setVisibility(View.GONE); - main.mainBinding.mainTagPostCount.setVisibility(View.GONE); + main.mainBinding.locationUrl.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.btnMap.setVisibility(View.GONE); + + main.mainBinding.infoContainer.setVisibility(View.GONE); + main.mainBinding.tagInfoContainer.setVisibility(View.GONE); + main.mainBinding.locInfoContainer.setVisibility(View.GONE); main.mainBinding.mainPosts.setNestedScrollingEnabled(false); main.mainBinding.highlightsList.setVisibility(View.GONE); @@ -652,12 +668,14 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { } isHashtag = main.userQuery.charAt(0) == '#'; - collapsingToolbar.setVisibility(isHashtag ? View.GONE : View.VISIBLE); + isUser = main.userQuery.charAt(0) == '@'; + isLocation = main.userQuery.contains("/"); + collapsingToolbar.setVisibility(isUser ? View.VISIBLE : View.GONE); if (isHashtag) { main.profileModel = null; + main.locationModel = null; main.mainBinding.toolbar.toolbar.setTitle(main.userQuery); - main.mainBinding.infoContainer.setVisibility(View.GONE); main.mainBinding.tagInfoContainer.setVisibility(View.VISIBLE); main.mainBinding.btnFollowTag.setVisibility(View.GONE); @@ -683,7 +701,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { main.mainBinding.btnFollowTag.setOnClickListener(profileActionListener); if (isLoggedIn) { - new StoryStatusFetcher(profileId, hashtagModel.getName(), result -> { + new StoryStatusFetcher(profileId, hashtagModel.getName(), false, result -> { main.storyModels = result; if (result != null && result.length > 0) main.mainBinding.mainHashtagImage.setStoriesBorder(); }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -723,13 +741,14 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { main.mainBinding.mainTagPostCount.setText(span); main.mainBinding.mainTagPostCount.setVisibility(View.VISIBLE); }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } else { + } else if (isUser) { main.hashtagModel = null; - main.mainBinding.tagInfoContainer.setVisibility(View.GONE); + main.locationModel = null; main.mainBinding.toolbar.toolbar.setTitle(main.userQuery); main.mainBinding.infoContainer.setVisibility(View.VISIBLE); + main.mainBinding.btnFollowTag.setVisibility(View.GONE); - currentlyExecuting = new ProfileFetcher(main.userQuery, profileModel -> { + currentlyExecuting = new ProfileFetcher(main.userQuery.substring(1), profileModel -> { main.profileModel = profileModel; if (profileModel == null) { @@ -745,7 +764,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { final String cookie = Utils.settingsHelper.getString(Constants.COOKIE); final boolean isLoggedIn = !Utils.isEmpty(cookie); if (isLoggedIn) { - new StoryStatusFetcher(profileId, "", result -> { + new StoryStatusFetcher(profileId, "", false, result -> { main.storyModels = result; if (result != null && result.length > 0) main.mainBinding.mainProfileImage.setStoriesBorder(); }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -907,7 +926,110 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { main.mainBinding.privatePage.setVisibility(View.VISIBLE); main.mainBinding.mainPosts.setVisibility(View.GONE); } - }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + ).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + else if (isLocation) { + main.profileModel = null; + main.hashtagModel = null; + main.mainBinding.toolbar.toolbar.setTitle(main.userQuery); + main.mainBinding.locInfoContainer.setVisibility(View.VISIBLE); + + currentlyExecuting = new LocationFetcher(main.userQuery, locationModel -> { + main.locationModel = locationModel; + + main.mainBinding.toolbar.toolbar.setTitle(locationModel.getName()); + + if (locationModel == null) { + main.mainBinding.swipeRefreshLayout.setRefreshing(false); + Toast.makeText(main, R.string.error_loading_profile, Toast.LENGTH_SHORT).show(); + main.mainBinding.toolbar.toolbar.setTitle(R.string.app_name); + return; + } + + final String profileId = locationModel.getId(); + + final String cookie = Utils.settingsHelper.getString(Constants.COOKIE); + final boolean isLoggedIn = !Utils.isEmpty(cookie); + if (isLoggedIn) { + new StoryStatusFetcher(profileId, "", true, result -> { + main.storyModels = result; + if (result != null && result.length > 0) main.mainBinding.mainLocationImage.setStoriesBorder(); + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + main.mainBinding.mainLocationImage.setEnabled(false); + new MyTask().execute(); + main.mainBinding.mainLocationImage.setEnabled(true); + + final String postCount = String.valueOf(locationModel.getPostCount()); + + SpannableStringBuilder span = new SpannableStringBuilder(resources.getString(R.string.main_posts_count, postCount)); + span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); + span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); + main.mainBinding.mainLocPostCount.setText(span); + + main.mainBinding.locationFullName.setText(locationModel.getName()); + + CharSequence biography = locationModel.getBio(); + main.mainBinding.locationBiography.setCaptionIsExpandable(true); + main.mainBinding.locationBiography.setCaptionIsExpanded(true); + + if (Utils.isEmpty(biography)) { + main.mainBinding.locationBiography.setVisibility(View.GONE); + } + else if (Utils.hasMentions(biography)) { + main.mainBinding.locationBiography.setVisibility(View.VISIBLE); + biography = Utils.getMentionText(biography); + main.mainBinding.locationBiography.setText(biography, TextView.BufferType.SPANNABLE); + main.mainBinding.locationBiography.setMentionClickListener(mentionClickListener); + } else { + main.mainBinding.locationBiography.setVisibility(View.VISIBLE); + main.mainBinding.locationBiography.setText(biography); + main.mainBinding.locationBiography.setMentionClickListener(null); + } + + if (!locationModel.getGeo().startsWith("geo:0.0,0.0?z=17")) { + main.mainBinding.btnMap.setVisibility(View.VISIBLE); + main.mainBinding.btnMap.setOnClickListener(v -> { + final Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(locationModel.getGeo())); + main.startActivity(intent); + }); + } + else { + main.mainBinding.btnMap.setVisibility(View.GONE); + main.mainBinding.btnMap.setOnClickListener(null); + } + + final String url = locationModel.getUrl(); + if (Utils.isEmpty(url)) { + main.mainBinding.locationUrl.setVisibility(View.GONE); + } else if (!url.startsWith("http")) { + main.mainBinding.locationUrl.setVisibility(View.VISIBLE); + main.mainBinding.locationUrl.setText(Utils.getSpannableUrl("http://"+url)); + } else { + main.mainBinding.locationUrl.setVisibility(View.VISIBLE); + main.mainBinding.locationUrl.setText(Utils.getSpannableUrl(url)); + } + + main.mainBinding.locationFullName.setSelected(true); + main.mainBinding.locationBiography.setEnabled(true); + + if (locationModel.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(locationModel.getName()) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } + ).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } } @@ -1020,7 +1142,9 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { protected Void doInBackground(Void... voids) { try { mIcon_val = BitmapFactory.decodeStream((InputStream) new URL( - (main.hashtagModel != null) ? main.hashtagModel.getSdProfilePic() : main.profileModel.getSdProfilePic() + (main.hashtagModel != null) ? main.hashtagModel.getSdProfilePic() : ( + (main.locationModel != null) ? main.locationModel.getSdProfilePic() : + main.profileModel.getSdProfilePic()) ).getContent()); } catch (Throwable ex) { Log.e("austin_debug", "bitmap: " + ex); @@ -1031,6 +1155,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { @Override protected void onPostExecute(Void result) { if (main.hashtagModel != null) main.mainBinding.mainHashtagImage.setImageBitmap(mIcon_val); + else if (main.locationModel != null) main.mainBinding.mainLocationImage.setImageBitmap(mIcon_val); else main.mainBinding.mainProfileImage.setImageBitmap(mIcon_val); } } @@ -1040,10 +1165,12 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { public void onClick(final View v) { if (!isLoggedIn && Utils.dataBox.getFavorite(main.userQuery) != null) { Utils.dataBox.delFavorite(new DataBox.FavoriteModel(main.userQuery, - Long.parseLong(Utils.dataBox.getFavorite(main.userQuery).split("/")[1]))); + Long.parseLong(Utils.dataBox.getFavorite(main.userQuery).split("/")[1]), + main.locationModel != null ? main.locationModel.getName() : main.userQuery)); onRefresh(); } else if (!isLoggedIn) { - Utils.dataBox.addFavorite(new DataBox.FavoriteModel(main.userQuery, System.currentTimeMillis())); + Utils.dataBox.addFavorite(new DataBox.FavoriteModel(main.userQuery, System.currentTimeMillis(), + main.locationModel != null ? main.locationModel.getName() : main.userQuery)); onRefresh(); } else if (v == main.mainBinding.btnFollow) { new ProfileAction().execute("follow"); @@ -1096,7 +1223,7 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { ok = true; } - else Toast.makeText(main, R.string.downloader_unknown_error, Toast.LENGTH_SHORT); + else Toast.makeText(main, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); urlConnection.disconnect(); } catch (Throwable ex) { Log.e("austin_debug", action+": " + ex); diff --git a/app/src/main/java/awais/instagrabber/activities/CommentsViewer.java b/app/src/main/java/awais/instagrabber/activities/CommentsViewer.java index ce0c0e37..5f031251 100755 --- a/app/src/main/java/awais/instagrabber/activities/CommentsViewer.java +++ b/app/src/main/java/awais/instagrabber/activities/CommentsViewer.java @@ -69,8 +69,6 @@ public final class CommentsViewer extends BaseLanguageActivity implements SwipeR return; } - Log.d("austin_debug", "f:"+postId); - commentsBinding.swipeRefreshLayout.setRefreshing(true); setSupportActionBar(commentsBinding.toolbar.toolbar); commentsBinding.toolbar.toolbar.setTitle(R.string.title_comments); @@ -253,7 +251,6 @@ public final class CommentsViewer extends BaseLanguageActivity implements SwipeR final String action = rawAction[0]; final String url = "https://www.instagram.com/web/comments/"+postId+"/"+action+"/"; try { - Log.d("austin_debug", url); final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); urlConnection.setRequestMethod("POST"); urlConnection.setUseCaches(false); diff --git a/app/src/main/java/awais/instagrabber/activities/Main.java b/app/src/main/java/awais/instagrabber/activities/Main.java index b8b4a532..79db2b40 100755 --- a/app/src/main/java/awais/instagrabber/activities/Main.java +++ b/app/src/main/java/awais/instagrabber/activities/Main.java @@ -9,6 +9,7 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.PersistableBundle; import android.provider.BaseColumns; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -43,6 +44,7 @@ import awais.instagrabber.models.DiscoverItemModel; import awais.instagrabber.models.FeedModel; import awais.instagrabber.models.HashtagModel; import awais.instagrabber.models.HighlightModel; +import awais.instagrabber.models.LocationModel; import awais.instagrabber.models.PostModel; import awais.instagrabber.models.ProfileModel; import awais.instagrabber.models.StoryModel; @@ -91,6 +93,7 @@ public final class Main extends BaseLanguageActivity { public MainHelper mainHelper; public ProfileModel profileModel; public HashtagModel hashtagModel; + public LocationModel locationModel; private AutoCompleteTextView searchAutoComplete; private ArrayAdapter profileDialogAdapter; private DialogInterface.OnClickListener profileDialogListener; @@ -139,7 +142,7 @@ public final class Main extends BaseLanguageActivity { if (mainHelper != null && !Utils.isEmpty(result)) { closeAnyOpenDrawer(); addToStack(); - userQuery = result; + userQuery = (result.contains("/") || result.startsWith("#")) ? result : ("@"+result); mainHelper.onRefresh(); } }; @@ -193,8 +196,8 @@ public final class Main extends BaseLanguageActivity { final Intent intent; if (which == 0 || storyModels == null || storyModels.length < 1) { intent = new Intent(this, ProfileViewer.class).putExtra( - ((hashtagModel != null) ? Constants.EXTRAS_HASHTAG : Constants.EXTRAS_PROFILE), - ((hashtagModel != null) ? hashtagModel : profileModel)); + ((hashtagModel != null) ? Constants.EXTRAS_HASHTAG : (locationModel != null ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_PROFILE)), + ((hashtagModel != null) ? hashtagModel : (locationModel != null ? locationModel : profileModel))); } else intent = new Intent(this, StoryViewer.class).putExtra(Constants.EXTRAS_USERNAME, userQuery) .putExtra(Constants.EXTRAS_STORIES, storyModels) @@ -205,7 +208,9 @@ public final class Main extends BaseLanguageActivity { final View.OnClickListener onClickListener = v -> { if (v == mainBinding.mainBiography) { Utils.copyText(this, mainBinding.mainBiography.getText().toString()); - } else if (v == mainBinding.mainProfileImage || v == mainBinding.mainHashtagImage) { + } else if (v == mainBinding.locationBiography) { + Utils.copyText(this, mainBinding.locationBiography.getText().toString()); + } else if (v == mainBinding.mainProfileImage || v == mainBinding.mainHashtagImage || v == mainBinding.mainLocationImage) { if (storyModels == null || storyModels.length <= 0) { profileDialogListener.onClick(null, 0); } else { @@ -217,16 +222,19 @@ public final class Main extends BaseLanguageActivity { }; mainBinding.mainBiography.setOnClickListener(onClickListener); + mainBinding.locationBiography.setOnClickListener(onClickListener); mainBinding.mainProfileImage.setOnClickListener(onClickListener); mainBinding.mainHashtagImage.setOnClickListener(onClickListener); + mainBinding.mainLocationImage.setOnClickListener(onClickListener); mainBinding.mainBiography.setEnabled(false); mainBinding.mainProfileImage.setEnabled(false); mainBinding.mainHashtagImage.setEnabled(false); + mainBinding.mainLocationImage.setEnabled(false); final boolean isQueryNull = userQuery == null; if (isQueryNull) allItems.clear(); - if (BuildConfig.DEBUG && isQueryNull) userQuery = "austinhuang.me"; + if (BuildConfig.DEBUG && isQueryNull) userQuery = "@austinhuang.me"; if (!mainBinding.swipeRefreshLayout.isRefreshing() && userQuery != null) mainHelper.onRefresh(); mainHelper.onIntent(getIntent()); @@ -291,7 +299,9 @@ public final class Main extends BaseLanguageActivity { else if (item == settingsAction) new SettingsDialog().show(fragmentManager, "settings"); else if (item == quickAccessAction) - new QuickAccessDialog().setQuery(userQuery).show(fragmentManager, "quickAccess"); + new QuickAccessDialog() + .setQuery(userQuery, locationModel != null ? locationModel.getName() : userQuery) + .show(fragmentManager, "quickAccess"); else new AboutDialog().show(fragmentManager, "about"); return true; @@ -359,7 +369,9 @@ public final class Main extends BaseLanguageActivity { final SuggestionModel suggestionModel = result[i]; if (suggestionModel != null) { final SuggestionType suggestionType = suggestionModel.getSuggestionType(); - final Object[] objects = {i, suggestionModel.getUsername(), suggestionModel.getName(), + final Object[] objects = {i, + (suggestionType == SuggestionType.TYPE_LOCATION) ? suggestionModel.getName() : suggestionModel.getUsername(), + (suggestionType == SuggestionType.TYPE_LOCATION) ? suggestionModel.getUsername() : suggestionModel.getName(), suggestionType, suggestionModel.getProfilePic(), suggestionModel.isVerified()}; if (!searchHash && !searchUser) cursor.addRow(objects); @@ -388,7 +400,7 @@ public final class Main extends BaseLanguageActivity { closeAnyOpenDrawer(); addToStack(); - userQuery = query; + userQuery = (query.contains("@") || query.contains("#")) ? query : ("@"+query); searchAction.collapseActionView(); searchView.setIconified(true); searchView.setIconified(true); diff --git a/app/src/main/java/awais/instagrabber/activities/PostViewer.java b/app/src/main/java/awais/instagrabber/activities/PostViewer.java index ad045362..d197a118 100755 --- a/app/src/main/java/awais/instagrabber/activities/PostViewer.java +++ b/app/src/main/java/awais/instagrabber/activities/PostViewer.java @@ -51,6 +51,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.json.JSONObject; + import awais.instagrabber.R; import awais.instagrabber.adapters.PostsMediaAdapter; import awais.instagrabber.asyncs.PostFetcher; @@ -404,7 +406,8 @@ public final class PostViewer extends BaseLanguageActivity { postModel.setBookmark(viewerPostModel.getBookmark()); } - setupPostInfoBar(viewerPostModel.getUsername(), viewerPostModel.getItemType(), viewerPostModel.getLocation()); + setupPostInfoBar("@"+viewerPostModel.getUsername(), viewerPostModel.getItemType(), + viewerPostModel.getLocation() == null ? null : viewerPostModel.getLocation()); postCaption = postModel.getPostCaption(); viewerCaptionParent.setVisibility(View.VISIBLE); @@ -609,7 +612,8 @@ public final class PostViewer extends BaseLanguageActivity { viewerBinding.bottomPanel.viewerCaption.setText(postCaption); } - setupPostInfoBar(viewerPostModel.getUsername(), viewerPostModel.getItemType(), viewerPostModel.getLocation()); + setupPostInfoBar("@"+viewerPostModel.getUsername(), viewerPostModel.getItemType(), + viewerPostModel.getLocation()); if (postModel instanceof PostModel) { final PostModel postModel = (PostModel) this.postModel; @@ -659,14 +663,14 @@ public final class PostViewer extends BaseLanguageActivity { } } - private void setupPostInfoBar(final String from, final MediaItemType mediaItemType, final String location) { + private void setupPostInfoBar(final String from, final MediaItemType mediaItemType, final JSONObject location) { if (prevUsername == null || !prevUsername.equals(from)) { viewerBinding.topPanel.ivProfilePic.setImageBitmap(null); viewerBinding.topPanel.ivProfilePic.setImageDrawable(null); viewerBinding.topPanel.ivProfilePic.setImageResource(0); - if (from.charAt(0) != '#') - new ProfileFetcher(from, result -> { + if (from.charAt(0) == '@') + new ProfileFetcher(from.substring(1), result -> { profileModel = result; if (result != null) { @@ -706,10 +710,9 @@ public final class PostViewer extends BaseLanguageActivity { R.string.post_viewer_video_post : R.string.post_viewer_image_post); if (Utils.isEmpty(from)) viewerBinding.topPanel.title.setText(titlePrefix); else { - final CharSequence titleText = resources.getString(R.string.post_viewer_post_from, titlePrefix, from) + " "; - final int titleLen = titleText.length(); - final SpannableString spannableString = new SpannableString(titleText); - spannableString.setSpan(new CommentMentionClickSpan(), titleLen - from.length() - 1, titleLen - 1, 0); + final int titleLen = from.length(); + final SpannableString spannableString = new SpannableString(from); + spannableString.setSpan(new CommentMentionClickSpan(), 0, titleLen, 0); viewerBinding.topPanel.title.setText(spannableString); } @@ -721,7 +724,13 @@ public final class PostViewer extends BaseLanguageActivity { } else { viewerBinding.topPanel.location.setVisibility(View.VISIBLE); - viewerBinding.topPanel.location.setText(location); + viewerBinding.topPanel.location.setText(location.optString("name")); + viewerBinding.topPanel.location.setOnClickListener(v -> + new AlertDialog.Builder(PostViewer.this).setTitle(location.optString("name")) + .setMessage(R.string.comment_view_mention_location_search) + .setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.ok, + (dialog, which) -> searchUsername(location.optString("id")+"/"+location.optString("slug"))).show() + ); viewerBinding.topPanel.title.setLayoutParams(new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT )); diff --git a/app/src/main/java/awais/instagrabber/activities/ProfileViewer.java b/app/src/main/java/awais/instagrabber/activities/ProfileViewer.java index 20f8bccd..9343abf9 100755 --- a/app/src/main/java/awais/instagrabber/activities/ProfileViewer.java +++ b/app/src/main/java/awais/instagrabber/activities/ProfileViewer.java @@ -32,6 +32,7 @@ import awais.instagrabber.databinding.ActivityProfileBinding; import awais.instagrabber.dialogs.ProfileSettingsDialog; import awais.instagrabber.interfaces.FetchListener; import awais.instagrabber.models.HashtagModel; +import awais.instagrabber.models.LocationModel; import awais.instagrabber.models.ProfileModel; import awais.instagrabber.models.enums.ProfilePictureFetchMode; import awais.instagrabber.utils.Constants; @@ -47,6 +48,7 @@ public final class ProfileViewer extends BaseLanguageActivity { private ActivityProfileBinding profileBinding; private ProfileModel profileModel; private HashtagModel hashtagModel; + private LocationModel locationModel; private MenuItem menuItemDownload; private String profilePicUrl; private FragmentManager fragmentManager; @@ -64,17 +66,18 @@ public final class ProfileViewer extends BaseLanguageActivity { setSupportActionBar(profileBinding.toolbar.toolbar); final Intent intent = getIntent(); - if (intent == null || (!intent.hasExtra(Constants.EXTRAS_PROFILE) && !intent.hasExtra(Constants.EXTRAS_HASHTAG)) + if (intent == null || (!intent.hasExtra(Constants.EXTRAS_PROFILE) && !intent.hasExtra(Constants.EXTRAS_HASHTAG) && !intent.hasExtra(Constants.EXTRAS_LOCATION)) || ((profileModel = (ProfileModel) intent.getSerializableExtra(Constants.EXTRAS_PROFILE)) == null - && (hashtagModel = (HashtagModel) intent.getSerializableExtra(Constants.EXTRAS_HASHTAG)) == null)) { + && (hashtagModel = (HashtagModel) intent.getSerializableExtra(Constants.EXTRAS_HASHTAG)) == null + && (locationModel = (LocationModel) intent.getSerializableExtra(Constants.EXTRAS_LOCATION)) == null)) { Utils.errorFinish(this); return; } fragmentManager = getSupportFragmentManager(); - final String id = hashtagModel != null ? hashtagModel.getId() : profileModel.getId(); - final String username = hashtagModel != null ? hashtagModel.getName() : profileModel.getUsername(); + final String id = hashtagModel != null ? hashtagModel.getId() : (locationModel != null ? locationModel.getId() : profileModel.getId()); + final String username = hashtagModel != null ? hashtagModel.getName() : (locationModel != null ? locationModel.getName() : profileModel.getUsername()); profileBinding.toolbar.toolbar.setTitle(username); @@ -93,12 +96,12 @@ public final class ProfileViewer extends BaseLanguageActivity { if (!fallbackToProfile && Utils.isEmpty(profilePicUrl)) { fallbackToProfile = true; - new ProfilePictureFetcher(username, id, fetchListener, fetchMode, profilePicUrl, hashtagModel != null).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new ProfilePictureFetcher(username, id, fetchListener, fetchMode, profilePicUrl, (hashtagModel != null || locationModel != null)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); return; } if (errorHandled && fallbackToProfile || Utils.isEmpty(profilePicUrl)) - profilePicUrl = hashtagModel != null ? hashtagModel.getSdProfilePic() : profileModel.getHdProfilePic(); + profilePicUrl = hashtagModel != null ? hashtagModel.getSdProfilePic() : (locationModel != null ? locationModel.getSdProfilePic() : profileModel.getHdProfilePic()); if (destroyed == true) return; @@ -110,7 +113,7 @@ public final class ProfileViewer extends BaseLanguageActivity { fallbackToProfile = true; if (!errorHandled) { errorHandled = true; - new ProfilePictureFetcher(username, id, fetchListener, fetchModes[Math.min(2, Math.max(0, fetchIndex + 1))], profilePicUrl, hashtagModel != null) + new ProfilePictureFetcher(username, id, fetchListener, fetchModes[Math.min(2, Math.max(0, fetchIndex + 1))], profilePicUrl, (hashtagModel != null || locationModel != null)) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else { glideRequestManager.load(profilePicUrl).into(profileBinding.imageViewer); @@ -165,7 +168,7 @@ public final class ProfileViewer extends BaseLanguageActivity { }).into(profileBinding.imageViewer); }; - new ProfilePictureFetcher(username, id, fetchListener, fetchMode, profilePicUrl, hashtagModel != null) + new ProfilePictureFetcher(username, id, fetchListener, fetchMode, profilePicUrl, (hashtagModel != null || locationModel != null)) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } diff --git a/app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java b/app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java index 5b5fa2fd..526984ab 100755 --- a/app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java +++ b/app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java @@ -15,6 +15,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.NonNull; @@ -35,6 +36,8 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import java.util.ArrayList; import java.util.Collections; +import org.json.JSONObject; + import awais.instagrabber.BuildConfig; import awais.instagrabber.R; import awais.instagrabber.activities.CommentsViewer; @@ -195,7 +198,7 @@ public final class FeedAdapter extends RecyclerView.Adapter final ProfileModel profileModel = feedModel.getProfileModel(); if (profileModel != null) { glideRequestManager.load(profileModel.getSdProfilePic()).into(viewHolder.profilePic); - viewHolder.username.setText(profileModel.getUsername()); + viewHolder.username.setText("@"+profileModel.getUsername()); } viewHolder.viewPost.setOnClickListener(clickListener); @@ -217,6 +220,22 @@ public final class FeedAdapter extends RecyclerView.Adapter viewHolder.btnComments.setEnabled(true); } + final JSONObject location = feedModel.getLocation(); + + if (location == null) { + viewHolder.location.setVisibility(View.GONE); + viewHolder.username.setLayoutParams(new RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT + )); + } + else { + viewHolder.location.setVisibility(View.VISIBLE); + viewHolder.location.setText(location.optString("name")); + viewHolder.username.setLayoutParams(new RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT + )); + } + final String thumbnailUrl = feedModel.getThumbnailUrl(); final String displayUrl = feedModel.getDisplayUrl(); CharSequence postCaption = feedModel.getPostCaption(); @@ -313,7 +332,7 @@ public final class FeedAdapter extends RecyclerView.Adapter }; viewHolder.btnMute.setOnClickListener(muteClickListener); - viewHolder.mediaList.setAdapter(new ChildMediaItemsAdapter(sliderItems, viewHolder.btnMute, muteClickListener, playerChangeListener)); + viewHolder.mediaList.setAdapter(new ChildMediaItemsAdapter(sliderItems, viewHolder.btnMute, playerChangeListener)); } } else { viewToChangeHeight = viewHolder.imageView; @@ -382,14 +401,12 @@ public final class FeedAdapter extends RecyclerView.Adapter private static final class ChildMediaItemsAdapter extends PagerAdapter { private final PlayerChangeListener playerChangeListener; - private final View.OnClickListener muteClickListener; private final ViewerPostModel[] sliderItems; private final View btnMute; private SimpleExoPlayer player; - private ChildMediaItemsAdapter(final ViewerPostModel[] sliderItems, final View btnMute, final View.OnClickListener muteClickListener, + private ChildMediaItemsAdapter(final ViewerPostModel[] sliderItems, final View btnMute, final PlayerChangeListener playerChangeListener) { - this.muteClickListener = muteClickListener; this.sliderItems = sliderItems; this.btnMute = btnMute; if (BuildConfig.DEBUG) this.playerChangeListener = playerChangeListener; @@ -408,6 +425,8 @@ public final class FeedAdapter extends RecyclerView.Adapter if (btnMute != null) btnMute.setVisibility(View.VISIBLE); final PlayerView playerView = new PlayerView(context); + Log.d("austin_debug","1"); + player = new SimpleExoPlayer.Builder(context).build(); playerView.setPlayer(player); @@ -424,7 +443,6 @@ public final class FeedAdapter extends RecyclerView.Adapter player.setVolume(vol); playerView.setTag(player); - playerView.setOnClickListener(muteClickListener); if (playerChangeListener != null) { //todo diff --git a/app/src/main/java/awais/instagrabber/adapters/SuggestionsAdapter.java b/app/src/main/java/awais/instagrabber/adapters/SuggestionsAdapter.java index f884e47f..a772e6a2 100755 --- a/app/src/main/java/awais/instagrabber/adapters/SuggestionsAdapter.java +++ b/app/src/main/java/awais/instagrabber/adapters/SuggestionsAdapter.java @@ -46,9 +46,10 @@ public final class SuggestionsAdapter extends CursorAdapter { final boolean verified = cursor.getString(5).charAt(0) == 't'; if ("TYPE_HASHTAG".equals(cursor.getString(3))) username = '#' + username; + else if ("TYPE_USER".equals(cursor.getString(3))) username = '@' + username; view.setOnClickListener(onClickListener); - view.setTag(username); + view.setTag("TYPE_LOCATION".equals(cursor.getString(3)) ? fullname : username); view.findViewById(R.id.isVerified).setVisibility(verified ? View.VISIBLE : View.GONE); @@ -56,6 +57,6 @@ public final class SuggestionsAdapter extends CursorAdapter { ((TextView) view.findViewById(R.id.tvFullName)).setText(fullname); glideRequestManager.applyDefaultRequestOptions(new RequestOptions().skipMemoryCache(true)) - .load(picUrl).into((ImageView) view.findViewById(R.id.ivProfilePic)); + .load(picUrl == null ? R.drawable.ic_location : picUrl).into((ImageView) view.findViewById(R.id.ivProfilePic)); } } \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/FeedItemViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/FeedItemViewHolder.java index 96aafd11..8f1e2d2e 100755 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/FeedItemViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/FeedItemViewHolder.java @@ -16,7 +16,7 @@ import awais.instagrabber.customviews.RamboTextView; public final class FeedItemViewHolder extends RecyclerView.ViewHolder { public final ImageView profilePic, btnMute, btnDownload; - public final TextView username, commentsCount, videoViews, mediaCounter, tvPostDate; + public final TextView username, commentsCount, videoViews, mediaCounter, tvPostDate, location; public final RamboTextView viewerCaption; public final View btnComments, videoViewsParent, viewPost; public final ViewPager mediaList; @@ -34,6 +34,7 @@ public final class FeedItemViewHolder extends RecyclerView.ViewHolder { tvPostDate = itemView.findViewById(R.id.tvPostDate); viewPost = itemView.findViewById(R.id.viewStoryPost); username = itemView.findViewById(R.id.title); + location = itemView.findViewById(R.id.location); // video view btnMute = itemView.findViewById(R.id.btnMute); diff --git a/app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java index c3b68209..b4e272ef 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java @@ -133,7 +133,8 @@ public final class FeedFetcher extends AsyncTask { feedItem.optLong("taken_at_timestamp", -1), feedItem.getBoolean("viewer_has_liked"), feedItem.getBoolean("viewer_has_saved"), - feedItem.getJSONObject("edge_media_preview_like").getLong("count")); + feedItem.getJSONObject("edge_media_preview_like").getLong("count"), + feedItem.optJSONObject("location")); final boolean isSlider = "GraphSidecar".equals(mediaType) && feedItem.has("edge_sidecar_to_children"); @@ -156,7 +157,7 @@ public final class FeedFetcher extends AsyncTask { null, null, null, node.optLong("video_view_count", -1), -1, false, false, feedItem.getJSONObject("edge_media_preview_like").getLong("count"), - feedItem.getJSONObject("location") == null ? null : feedItem.getJSONObject("location").optString("name")); + feedItem.optJSONObject("location")); sliderItems[j].setSliderDisplayUrl(node.getString("display_url")); } diff --git a/app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java new file mode 100644 index 00000000..6a2587a7 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/LocationFetcher.java @@ -0,0 +1,79 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.util.Log; + +import androidx.annotation.Nullable; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.math.BigDecimal; +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.LocationModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Utils.logCollector; + +public final class LocationFetcher extends AsyncTask { + private final FetchListener fetchListener; + private final String idSlug; + + public LocationFetcher(String idSlug, FetchListener fetchListener) { + Log.d("austin_debug", idSlug); + // idSlug = id + "/" + slug + this.idSlug = idSlug; + this.fetchListener = fetchListener; + } + + @Nullable + @Override + protected LocationModel doInBackground(final Void... voids) { + LocationModel result = null; + + try { + final HttpURLConnection conn = (HttpURLConnection) new URL("https://www.instagram.com/explore/locations/" + idSlug + "/?__a=1").openConnection(); + conn.setUseCaches(true); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + final JSONObject user = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("graphql").getJSONObject(Constants.EXTRAS_LOCATION); + + final JSONObject timelineMedia = user.getJSONObject("edge_location_to_media"); + if (timelineMedia.has("edges")) { + final JSONArray edges = timelineMedia.getJSONArray("edges"); + } + + result = new LocationModel( + user.getString(Constants.EXTRAS_ID) + "/" + user.getString("slug"), + user.getString("name"), + user.getString("blurb"), + user.getString("website"), + user.getString("profile_pic_url"), + timelineMedia.getLong("count"), + BigDecimal.valueOf(user.optDouble("lat", 0d)).toString(), + BigDecimal.valueOf(user.optDouble("lng", 0d)).toString() + ); + } + + conn.disconnect(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ASYNC_LOCATION_FETCHER, "doInBackground"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPostExecute(final LocationModel result) { + if (fetchListener != null) fetchListener.onResult(result); + } +} diff --git a/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java index 7d98afe7..c201f7a9 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java @@ -90,7 +90,7 @@ public final class PostFetcher extends AsyncTask isVideo && media.has("video_view_count") ? media.getLong("video_view_count") : -1, timestamp, media.getBoolean("viewer_has_liked"), media.getBoolean("viewer_has_saved"), media.getJSONObject("edge_media_preview_like").getLong("count"), - media.optJSONObject("location") == null ? null : media.getJSONObject("location").optString("name")); + media.optJSONObject("location")); postModel.setCommentsCount(commentsCount); postModel.setCommentsEndCursor(endCursor); @@ -116,7 +116,7 @@ public final class PostFetcher extends AsyncTask isChildVideo && node.has("video_view_count") ? node.getLong("video_view_count") : -1, timestamp, media.getBoolean("viewer_has_liked"), media.getBoolean("viewer_has_saved"), media.getJSONObject("edge_media_preview_like").getLong("count"), - media.optJSONObject("location") == null ? null : media.getJSONObject("location").optString("name")); + media.optJSONObject("location")); postModels[i].setSliderDisplayUrl(node.getString("display_url")); Utils.checkExistence(downloadDir, customDir, username, true, i, postModels[i]); diff --git a/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java index b23a7223..7d8696a5 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java @@ -49,11 +49,15 @@ public final class PostsFetcher extends AsyncTask { @Override protected PostModel[] doInBackground(final Void... voids) { final boolean isHashTag = id.charAt(0) == '#'; + final boolean isLocation = id.contains("/"); final String url; if (isHashTag) url = "https://www.instagram.com/graphql/query/?query_hash=ded47faa9a1aaded10161a2ff32abb6b&variables=" + "{\"tag_name\":\"" + id.substring(1).toLowerCase() + "\",\"first\":150,\"after\":\"" + endCursor + "\"}"; + else if (isLocation) + url = "https://www.instagram.com/graphql/query/?query_hash=36bd0f2bf5911908de389b8ceaa3be6d&variables=" + + "{\"id\":\""+ id.split("/")[0] +"\",\"first\":150,\"after\":\"" + endCursor + "\"}"; else url = "https://www.instagram.com/graphql/query/?query_id=17880160963012870&id=" + id + "&first=50&after=" + endCursor; @@ -73,8 +77,10 @@ public final class PostsFetcher extends AsyncTask { } final JSONObject mediaPosts = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("data") - .getJSONObject(isHashTag ? "hashtag" : Constants.EXTRAS_USER) - .getJSONObject(isHashTag ? "edge_hashtag_to_media" : "edge_owner_to_timeline_media"); + .getJSONObject(isHashTag ? Constants.EXTRAS_HASHTAG : + (isLocation ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_USER)) + .getJSONObject(isHashTag ? "edge_hashtag_to_media" : + (isLocation ? "edge_location_to_media" : "edge_owner_to_timeline_media")); final String endCursor; final boolean hasNextPage; diff --git a/app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java index 586fd086..f885d936 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java @@ -21,11 +21,13 @@ import static awais.instagrabber.utils.Utils.logCollector; public final class StoryStatusFetcher extends AsyncTask { private final String id, hashtag; + private final boolean location; private final FetchListener fetchListener; - public StoryStatusFetcher(final String id, final String hashtag, final FetchListener fetchListener) { + public StoryStatusFetcher(final String id, final String hashtag, final boolean location, final FetchListener fetchListener) { this.id = id; this.hashtag = hashtag; + this.location = location; this.fetchListener = fetchListener; } @@ -33,8 +35,9 @@ public final class StoryStatusFetcher extends AsyncTask suggestionModels = new ArrayList<>(usersLen + hashtagsLen); for (int i = 0; i < hashtagsLen; i++) { @@ -66,6 +68,20 @@ public final class SuggestionsFetcher extends AsyncTask { + if (player.getPlayWhenReady() == true) { + player.setPlayWhenReady(false); + player.getPlaybackState(); + } + else { + player.setPlayWhenReady(true); + player.getPlaybackState(); + } + }); } } diff --git a/app/src/main/java/awais/instagrabber/dialogs/QuickAccessDialog.java b/app/src/main/java/awais/instagrabber/dialogs/QuickAccessDialog.java index f459f440..1927c619 100755 --- a/app/src/main/java/awais/instagrabber/dialogs/QuickAccessDialog.java +++ b/app/src/main/java/awais/instagrabber/dialogs/QuickAccessDialog.java @@ -33,13 +33,14 @@ public final class QuickAccessDialog extends BottomSheetDialogFragment implement View.OnClickListener, View.OnLongClickListener { private boolean cookieChanged, isQuery; private Activity activity; - private String userQuery; + private String userQuery, displayName; private View btnFavorite, btnImportExport; private SimpleAdapter favoritesAdapter; private RecyclerView rvFavorites, rvQuickAccess; - public QuickAccessDialog setQuery(final String userQuery) { + public QuickAccessDialog setQuery(final String userQuery, final String displayName) { this.userQuery = userQuery; + this.displayName = displayName; return this; } @@ -102,7 +103,7 @@ public final class QuickAccessDialog extends BottomSheetDialogFragment implement final Object tag = v.getTag(); if (v == btnFavorite) { if (isQuery) { - Utils.dataBox.addFavorite(new DataBox.FavoriteModel(userQuery, System.currentTimeMillis())); + Utils.dataBox.addFavorite(new DataBox.FavoriteModel(userQuery, System.currentTimeMillis(), displayName)); favoritesAdapter.setItems(Utils.dataBox.getAllFavorites()); } } else if (v == btnImportExport) { diff --git a/app/src/main/java/awais/instagrabber/models/FeedModel.java b/app/src/main/java/awais/instagrabber/models/FeedModel.java index 99e22469..9eeeda1a 100755 --- a/app/src/main/java/awais/instagrabber/models/FeedModel.java +++ b/app/src/main/java/awais/instagrabber/models/FeedModel.java @@ -2,19 +2,23 @@ package awais.instagrabber.models; import awais.instagrabber.models.enums.MediaItemType; +import org.json.JSONObject; + public final class FeedModel extends PostModel { private final ProfileModel profileModel; private final long commentsCount, viewCount; private boolean captionExpanded = false, mentionClicked = false; + private final JSONObject location; private ViewerPostModel[] sliderItems; 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, boolean liked, boolean bookmarked, long likes) { + final long commentsCount, final long timestamp, boolean liked, boolean bookmarked, long likes, JSONObject location) { super(itemType, postId, displayUrl, thumbnailUrl, shortCode, postCaption, timestamp, liked, bookmarked, likes); this.profileModel = profileModel; this.commentsCount = commentsCount; this.viewCount = viewCount; + this.location = location; } public ProfileModel getProfileModel() { @@ -33,6 +37,10 @@ public final class FeedModel extends PostModel { return commentsCount; } + public JSONObject getLocation() { + return location; + } + public boolean isCaptionExpanded() { return captionExpanded; } diff --git a/app/src/main/java/awais/instagrabber/models/LocationModel.java b/app/src/main/java/awais/instagrabber/models/LocationModel.java new file mode 100755 index 00000000..e1b97399 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/LocationModel.java @@ -0,0 +1,44 @@ +package awais.instagrabber.models; + +import java.io.Serializable; + +public final class LocationModel implements Serializable { + private final long postCount; + private final String id, name, bio, url, sdProfilePic, lat, lng; + + public LocationModel(final String id, final String name, final String bio, final String url, + final String sdProfilePic, final long postCount, final String lat, final String lng) { + this.id = id; // <- id + "/" + slug + this.name = name; + this.bio = bio; + this.url = url; + this.sdProfilePic = sdProfilePic; + this.postCount = postCount; + this.lat = lat; + this.lng = lng; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getBio() { + return bio; + } + + public String getUrl() { + return url; + } + + public String getGeo() { return "geo:"+lat+","+lng+"?z=17&q="+lat+","+lng+"("+name+")"; } + + public String getSdProfilePic() { + return sdProfilePic; + } + + public long getPostCount() { return postCount; } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/ViewerPostModel.java b/app/src/main/java/awais/instagrabber/models/ViewerPostModel.java index 9b12ecd6..bf501364 100755 --- a/app/src/main/java/awais/instagrabber/models/ViewerPostModel.java +++ b/app/src/main/java/awais/instagrabber/models/ViewerPostModel.java @@ -1,9 +1,11 @@ package awais.instagrabber.models; +import org.json.JSONObject; import awais.instagrabber.models.enums.MediaItemType; public final class ViewerPostModel extends BasePostModel { - protected final String username, location; + protected final String username; + protected final JSONObject location; protected final long videoViews; protected String sliderDisplayUrl, commentsEndCursor; protected long commentsCount, likes; @@ -11,7 +13,7 @@ public final class ViewerPostModel extends BasePostModel { 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, - boolean liked, boolean bookmarked, long likes, final String location) { + boolean liked, boolean bookmarked, long likes, final JSONObject location) { this.itemType = itemType; this.postId = postId; this.displayUrl = displayUrl; @@ -38,7 +40,7 @@ public final class ViewerPostModel extends BasePostModel { return username; } - public String getLocation() { + public JSONObject getLocation() { return location; } diff --git a/app/src/main/java/awais/instagrabber/models/enums/SuggestionType.java b/app/src/main/java/awais/instagrabber/models/enums/SuggestionType.java index 917e1e60..eb38e033 100755 --- a/app/src/main/java/awais/instagrabber/models/enums/SuggestionType.java +++ b/app/src/main/java/awais/instagrabber/models/enums/SuggestionType.java @@ -3,4 +3,5 @@ package awais.instagrabber.models.enums; public enum SuggestionType { TYPE_USER, TYPE_HASHTAG, + TYPE_LOCATION } \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/Constants.java b/app/src/main/java/awais/instagrabber/utils/Constants.java index a886887d..614ea467 100755 --- a/app/src/main/java/awais/instagrabber/utils/Constants.java +++ b/app/src/main/java/awais/instagrabber/utils/Constants.java @@ -10,6 +10,7 @@ public final class Constants { public static final String APP_THEME = "app_theme"; public static final String APP_LANGUAGE = "app_language"; public static final String PREV_INSTALL_VERSION = "prevVersion"; + public static final String DB_TO_MIGRATE = "dbToMigrate"; public static final String PROFILE_FETCH_MODE = "profile_fetch_mode"; // boolean prefs public static final String DOWNLOAD_USER_FOLDER = "download_user_folder"; @@ -26,6 +27,7 @@ public final class Constants { //////////////////////// EXTRAS //////////////////////// public static final String EXTRAS_USER = "user"; public static final String EXTRAS_HASHTAG = "hashtag"; + public static final String EXTRAS_LOCATION = "location"; public static final String EXTRAS_USERNAME = "username"; public static final String EXTRAS_ID = "id"; public static final String EXTRAS_POST = "post"; diff --git a/app/src/main/java/awais/instagrabber/utils/DataBox.java b/app/src/main/java/awais/instagrabber/utils/DataBox.java index 53f966cd..4f3f801c 100755 --- a/app/src/main/java/awais/instagrabber/utils/DataBox.java +++ b/app/src/main/java/awais/instagrabber/utils/DataBox.java @@ -16,6 +16,7 @@ import awais.instagrabber.BuildConfig; import awaisomereport.LogCollector; import static awais.instagrabber.utils.Utils.logCollector; +import static awais.instagrabber.utils.Utils.settingsHelper; public final class DataBox extends SQLiteOpenHelper { private static DataBox sInstance; @@ -24,6 +25,7 @@ public final class DataBox extends SQLiteOpenHelper { private final static String TABLE_FAVORITES = "favorites"; private final static String KEY_DATE_ADDED = "date_added"; private final static String KEY_QUERY_TEXT = "query_text"; + private final static String KEY_QUERY_DISPLAY = "query_display"; private final static String KEY_USERNAME = Constants.EXTRAS_USERNAME; private final static String KEY_COOKIE = "cookie"; private final static String KEY_UID = "uid"; @@ -40,7 +42,7 @@ public final class DataBox extends SQLiteOpenHelper { @Override public void onCreate(@NonNull final SQLiteDatabase db) { db.execSQL("CREATE TABLE cookies (id INTEGER PRIMARY KEY, uid TEXT, username TEXT, cookie TEXT)"); - db.execSQL("CREATE TABLE favorites (id INTEGER PRIMARY KEY, query_text TEXT, date_added INTEGER)"); + db.execSQL("CREATE TABLE favorites (id INTEGER PRIMARY KEY, query_text TEXT, date_added INTEGER, query_display TEXT)"); } @Override @@ -49,6 +51,7 @@ public final class DataBox extends SQLiteOpenHelper { ///////////////////////////////////////// YOUR FAVORITES! HERE ///////////////////////////////////////// public final void addFavorite(@NonNull final FavoriteModel favoriteModel) { final String query = favoriteModel.getQuery(); + final String display = favoriteModel.getDisplayName(); if (!Utils.isEmpty(query)) { try (final SQLiteDatabase db = getWritableDatabase()) { db.beginTransaction(); @@ -56,6 +59,7 @@ public final class DataBox extends SQLiteOpenHelper { final ContentValues values = new ContentValues(); values.put(KEY_DATE_ADDED, favoriteModel.getDate()); values.put(KEY_QUERY_TEXT, query); + values.put(KEY_QUERY_DISPLAY, display); final int rows = db.update(TABLE_FAVORITES, values, KEY_QUERY_TEXT + "=?", new String[]{query}); @@ -76,12 +80,15 @@ public final class DataBox extends SQLiteOpenHelper { public final synchronized void delFavorite(@NonNull final FavoriteModel favoriteModel) { final String query = favoriteModel.getQuery(); + final String display = favoriteModel.getDisplayName(); if (!Utils.isEmpty(query)) { try (final SQLiteDatabase db = getWritableDatabase()) { db.beginTransaction(); try { - final int rowsDeleted = db.delete(TABLE_FAVORITES, KEY_QUERY_TEXT + "=? AND " + KEY_DATE_ADDED + "=?", - new String[]{query, Long.toString(favoriteModel.getDate())}); + final int rowsDeleted = db.delete(TABLE_FAVORITES, KEY_QUERY_TEXT + "=? AND " + + KEY_DATE_ADDED + "=? AND " + + KEY_QUERY_DISPLAY + "=?", + new String[]{query, Long.toString(favoriteModel.getDate()), display}); if (rowsDeleted > 0) db.setTransactionSuccessful(); } catch (final Exception e) { @@ -98,16 +105,50 @@ public final class DataBox extends SQLiteOpenHelper { @Nullable public final ArrayList getAllFavorites() { ArrayList favorites = null; + FavoriteModel tempFav; - try (final SQLiteDatabase db = getReadableDatabase(); - final Cursor cursor = db.rawQuery("SELECT query_text, date_added FROM favorites ORDER BY date_added DESC", null)) { + if (Utils.settingsHelper.getBoolean(Constants.DB_TO_MIGRATE)) { + try (final SQLiteDatabase db = getWritableDatabase()) { + db.execSQL("ALTER TABLE favorites ADD query_display TEXT"); + try { + db.beginTransaction(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "delFavorite"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } finally { + db.endTransaction(); + settingsHelper.putBoolean(Constants.DB_TO_MIGRATE, false); + } + } + } + + try (final SQLiteDatabase db = getWritableDatabase(); + final Cursor cursor = db.rawQuery("SELECT query_text, date_added, query_display FROM favorites ORDER BY date_added DESC", null)) { if (cursor != null && cursor.moveToFirst()) { favorites = new ArrayList<>(); do { - favorites.add(new FavoriteModel( + tempFav = new FavoriteModel( cursor.getString(0), // query text - cursor.getLong(1) // date added - )); + cursor.getLong(1), // date added + cursor.getString(2) == null ? cursor.getString(0) : cursor.getString(2) // display + ); + if (cursor.getString(2) == null) { + try { + db.beginTransaction(); + final int rowsDeleted = db.delete(TABLE_FAVORITES, KEY_QUERY_TEXT + "=? AND " + KEY_DATE_ADDED + "=? AND " + KEY_QUERY_DISPLAY + " IS NULL", + new String[]{cursor.getString(0), Long.toString(cursor.getLong(1))}); + if (rowsDeleted > 0) db.setTransactionSuccessful(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "delFavorite"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } finally { + db.endTransaction(); + } + addFavorite(tempFav); + } + favorites.add(tempFav); } while (cursor.moveToNext()); } } @@ -120,7 +161,7 @@ public final class DataBox extends SQLiteOpenHelper { try (final SQLiteDatabase db = getReadableDatabase(); final Cursor cursor = db.rawQuery("SELECT query_text, date_added FROM favorites WHERE " - +KEY_QUERY_TEXT+"='"+query+"' ORDER BY date_added DESC", null)) { + +KEY_QUERY_DISPLAY+"='"+query+"' ORDER BY date_added DESC", null)) { if (cursor != null && cursor.moveToFirst()) { return cursor.getString(0) + "/" + String.valueOf(cursor.getLong(1)); } @@ -260,18 +301,23 @@ public final class DataBox extends SQLiteOpenHelper { } public static class FavoriteModel { - private final String query; + private final String query, displayName; private final long date; - public FavoriteModel(final String query, final long date) { + public FavoriteModel(final String query, final long date, final String displayName) { this.query = query; this.date = date; + this.displayName = displayName; } public String getQuery() { return query; } + public String getDisplayName() { + return displayName; + } + public long getDate() { return date; } diff --git a/app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java b/app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java index aabecf5a..844b1dc7 100755 --- a/app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java +++ b/app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java @@ -167,7 +167,7 @@ public final class ExportImportUtils { for (int i = 0; i < favsLen; ++i) { final JSONObject favsObject = favs.getJSONObject(i); Utils.dataBox.addFavorite(new DataBox.FavoriteModel(favsObject.getString("q"), - favsObject.getLong("d"))); + favsObject.getLong("d"), favsObject.has("s") ? favsObject.getString("s") : favsObject.getString("q"))); } } @@ -265,6 +265,7 @@ public final class ExportImportUtils { final JSONObject jsonObject = new JSONObject(); jsonObject.put("q", favorite.getQuery()); jsonObject.put("d", favorite.getDate()); + jsonObject.put("s", favorite.getDisplayName()); jsonArray.put(jsonObject); } result = jsonArray.toString(); diff --git a/app/src/main/java/awais/instagrabber/utils/FlavorTown.java b/app/src/main/java/awais/instagrabber/utils/FlavorTown.java index f5a61259..1f820fb9 100755 --- a/app/src/main/java/awais/instagrabber/utils/FlavorTown.java +++ b/app/src/main/java/awais/instagrabber/utils/FlavorTown.java @@ -55,6 +55,8 @@ public final class FlavorTown { public static void changelogCheck(@NonNull final Context context) { if (settingsHelper.getInteger(Constants.PREV_INSTALL_VERSION) < BuildConfig.VERSION_CODE) { + if (settingsHelper.getInteger(Constants.PREV_INSTALL_VERSION) < 35) + settingsHelper.putBoolean(Constants.DB_TO_MIGRATE, true); Toast.makeText(context, R.string.updated, Toast.LENGTH_SHORT).show(); settingsHelper.putInteger(Constants.PREV_INSTALL_VERSION, BuildConfig.VERSION_CODE); } diff --git a/app/src/main/java/awaisomereport/LogCollector.java b/app/src/main/java/awaisomereport/LogCollector.java index 0ca77381..fb1ce720 100755 --- a/app/src/main/java/awaisomereport/LogCollector.java +++ b/app/src/main/java/awaisomereport/LogCollector.java @@ -107,6 +107,7 @@ public final class LogCollector { ASYNC_POST_FETCHER("async-single-post-fetcher.txt"), ASYNC_FEED_FETCHER("async-feed-fetcher.txt"), ASYNC_HASHTAG_FETCHER("async-hashtag-fetcher.txt"), + ASYNC_LOCATION_FETCHER("async-location-fetcher.txt"), ASYNC_PROFILE_FETCHER("async-profile-fetcher.txt"), ASYNC_PROFILE_PICTURE_FETCHER("async-pfp-fetcher.txt"), ASYNC_STORY_STATUS_FETCHER("async-story-status-fetcher.txt"), diff --git a/app/src/main/res/drawable/ic_location.png b/app/src/main/res/drawable/ic_location.png new file mode 100644 index 0000000000000000000000000000000000000000..39849b0dd6eb5e8c00564b7a3175693134399e5d GIT binary patch literal 8156 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 4a5b7c4b..94abacf5 100755 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -31,6 +31,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> + + + + app:layout_scrollFlags="scroll|exitUntilCollapsed"> + + + + + + + + + + + + + + android:paddingBottom="5dp" + android:visibility="gone"> + app:backgroundTint="@color/btn_green_background" /> + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3d3cd549..61ccd671 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -86,6 +86,7 @@ Unblock Restrict Unrestrict + Map Export Import Export Logins @@ -158,6 +159,7 @@ No empty comments, dawg! Do you want to search the username? Do you want to search the hashtag? + Do you want to search the location? Followers Following Comparing followers & following diff --git a/fastlane/metadata/android/changelogs/34.txt b/fastlane/metadata/android/changelogs/35.txt similarity index 93% rename from fastlane/metadata/android/changelogs/34.txt rename to fastlane/metadata/android/changelogs/35.txt index abad8485..2ff1628d 100644 --- a/fastlane/metadata/android/changelogs/34.txt +++ b/fastlane/metadata/android/changelogs/35.txt @@ -1,7 +1,7 @@ * You can now write comments, and reply/like/delete comments through the menu (by clicking the comment) * Liked comments are shown with a pink background * You can now share posts in the post viewer -* You can now see the geotag name of a post +* Geotag viewing/searching support * Search field is now empty if you're viewing your own profile while logged in * Post like counts are now displayed (The button texts are slightly reduced to accomodate @world_record_egg) (logged in only) * Mute buttons are changed to display the current status (i.e. muted icon when muted, sound icon when not muted)