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 00000000..39849b0d Binary files /dev/null and b/app/src/main/res/drawable/ic_location.png differ 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)