diff --git a/app/build.gradle b/app/build.gradle index 58e2788a..785b9daf 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,7 +11,7 @@ android { targetSdkVersion 29 versionCode 58 - versionName '19.1.0' + versionName '19.1.0-a1' multiDexEnabled true @@ -56,13 +56,13 @@ configurations.all { } dependencies { - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' def appcompat_version = "1.2.0" - def nav_version = '2.3.2' + def nav_version = '2.3.3' def exoplayer_version = '2.12.0' - implementation 'com.google.android.material:material:1.3.0-rc01' + implementation 'com.google.android.material:material:1.4.0-alpha01' implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version" implementation "com.google.android.exoplayer:exoplayer-dash:$exoplayer_version" @@ -70,14 +70,14 @@ dependencies { implementation "androidx.appcompat:appcompat:$appcompat_version" implementation "androidx.appcompat:appcompat-resources:$appcompat_version" - implementation "androidx.recyclerview:recyclerview:1.2.0-beta01" + implementation "androidx.recyclerview:recyclerview:1.2.0-beta02" implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation "androidx.viewpager2:viewpager2:1.0.0" implementation "androidx.navigation:navigation-fragment:$nav_version" implementation "androidx.navigation:navigation-ui:$nav_version" implementation "androidx.constraintlayout:constraintlayout:2.0.4" implementation "androidx.preference:preference:1.1.1" - implementation "androidx.work:work-runtime:2.4.0" + implementation "androidx.work:work-runtime:2.5.0" implementation 'androidx.palette:palette:1.0.0' implementation 'com.google.guava:guava:27.0.1-android' @@ -89,10 +89,10 @@ dependencies { annotationProcessor "androidx.room:room-compiler:$room_version" // CameraX - def camerax_version = "1.0.0-rc01" + def camerax_version = "1.0.0-alpha02" implementation "androidx.camera:camera-camera2:$camerax_version" implementation "androidx.camera:camera-lifecycle:$camerax_version" - implementation "androidx.camera:camera-view:1.0.0-alpha20" + implementation "androidx.camera:camera-view:1.0.0-alpha22" // EmojiCompat def emoji_compat_version = "1.1.0" diff --git a/app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java index 3d1516e6..6b9929c5 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java @@ -115,7 +115,7 @@ public final class CommentsFetcher extends AsyncTask { +public class CreateThreadAction extends AsyncTask { private static final String TAG = "CommentAction"; private final String cookie; private final long userId; private final OnTaskCompleteListener onTaskCompleteListener; + private final DirectMessagesService directMessagesService; public CreateThreadAction(final String cookie, final long userId, final OnTaskCompleteListener onTaskCompleteListener) { this.cookie = cookie; this.userId = userId; this.onTaskCompleteListener = onTaskCompleteListener; + directMessagesService = DirectMessagesService.getInstance(CookieUtils.getCsrfTokenFromCookie(cookie), + CookieUtils.getUserIdFromCookie(cookie), + Utils.settingsHelper.getString(Constants.DEVICE_UUID)); } - protected String doInBackground(Void... lmao) { - final String url = "https://i.instagram.com/api/v1/direct_v2/create_group_thread/"; - HttpURLConnection urlConnection = null; - try { - urlConnection = (HttpURLConnection) new URL(url).openConnection(); - urlConnection.setRequestMethod("POST"); - urlConnection.setRequestProperty("User-Agent", Utils.settingsHelper.getString(Constants.APP_UA)); - urlConnection.setUseCaches(false); - final String urlParameters = Utils.sign("{\"_csrftoken\":\"" + cookie.split("csrftoken=")[1].split(";")[0] - + "\",\"_uid\":\"" + CookieUtils.getUserIdFromCookie(cookie) - + "\",\"__uuid\":\"" + settingsHelper.getString(Constants.DEVICE_UUID) - + "\",\"recipient_users\":\"[" + userId // <- string of array of number (not joking) - + "]\"}"); - urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - if (urlParameters != null) { - urlConnection.setRequestProperty("Content-Length", "" + urlParameters.getBytes().length); + protected Void doInBackground(Void... lmao) { + final Call createThreadRequest = directMessagesService.createThread(Collections.singletonList(userId), null); + createThreadRequest.enqueue(new Callback() { + @Override + public void onResponse(@NonNull final Call call, @NonNull final Response response) { + if (!response.isSuccessful()) { + if (response.errorBody() != null) { + try { + final String string = response.errorBody().string(); + final String msg = String.format(Locale.US, + "onResponse: url: %s, responseCode: %d, errorBody: %s", + call.request().url().toString(), + response.code(), + string); + Log.e(TAG, msg); + } catch (IOException e) { + Log.e(TAG, "onResponse: ", e); + } + } + Log.e(TAG, "onResponse: request was not successful and response error body was null"); + } + onTaskCompleteListener.onTaskComplete(response.body()); + if (response.body() == null) { + Log.e(TAG, "onResponse: thread is null"); + } } - urlConnection.setDoOutput(true); - DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream()); - wr.writeBytes(urlParameters); - wr.flush(); - wr.close(); - urlConnection.connect(); - if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { - return new JSONObject(NetworkUtils.readFromConnection(urlConnection)).getString("thread_id"); + + @Override + public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { + onTaskCompleteListener.onTaskComplete(null); } - } catch (Throwable ex) { - Log.e(TAG, "reply (CT): " + ex); - } finally { - if (urlConnection != null) { - urlConnection.disconnect(); - } - } + }); return null; } - @Override - protected void onPostExecute(final String threadId) { - if (threadId == null || onTaskCompleteListener == null) { - return; - } - onTaskCompleteListener.onTaskComplete(threadId); - } +// @Override +// protected void onPostExecute() { +// } public interface OnTaskCompleteListener { - void onTaskComplete(final String threadId); + void onTaskComplete(final DirectThread thread); } } diff --git a/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java index 46559dfb..612259bd 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java @@ -5,9 +5,6 @@ import android.util.Log; import androidx.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; - import awais.instagrabber.interfaces.FetchListener; import awais.instagrabber.repositories.responses.FriendshipStatus; import awais.instagrabber.repositories.responses.User; @@ -15,7 +12,7 @@ import awais.instagrabber.webservices.GraphQLService; import awais.instagrabber.webservices.ServiceCallback; import awais.instagrabber.webservices.UserService; -public final class ProfileFetcher extends AsyncTask { +public final class ProfileFetcher extends AsyncTask { private static final String TAG = ProfileFetcher.class.getSimpleName(); private final UserService userService; private final GraphQLService graphQLService; @@ -36,12 +33,11 @@ public final class ProfileFetcher extends AsyncTask { @Nullable @Override - protected String doInBackground(final Void... voids) { + protected Void doInBackground(final Void... voids) { if (isLoggedIn) { userService.getUsernameInfo(userName, new ServiceCallback() { @Override public void onSuccess(final User user) { - Log.d("austin_debug", user.getUsername() + " " + userName); userService.getUserFriendship(user.getPk(), new ServiceCallback() { @Override public void onSuccess(final FriendshipStatus status) { @@ -52,6 +48,7 @@ public final class ProfileFetcher extends AsyncTask { @Override public void onFailure(final Throwable t) { Log.e(TAG, "Error", t); + fetchListener.onFailure(t); } }); } @@ -59,6 +56,7 @@ public final class ProfileFetcher extends AsyncTask { @Override public void onFailure(final Throwable t) { Log.e(TAG, "Error", t); + fetchListener.onFailure(t); } }); } @@ -72,10 +70,11 @@ public final class ProfileFetcher extends AsyncTask { @Override public void onFailure(final Throwable t) { Log.e(TAG, "Error", t); + fetchListener.onFailure(t); } }); } - return "yeah"; + return null; } @Override diff --git a/app/src/main/java/awais/instagrabber/dialogs/ProfilePicDialogFragment.java b/app/src/main/java/awais/instagrabber/dialogs/ProfilePicDialogFragment.java index e57e1f86..09862f49 100644 --- a/app/src/main/java/awais/instagrabber/dialogs/ProfilePicDialogFragment.java +++ b/app/src/main/java/awais/instagrabber/dialogs/ProfilePicDialogFragment.java @@ -120,14 +120,17 @@ public class ProfilePicDialogFragment extends DialogFragment { @Override public void onSuccess(final User result) { if (result != null) { - setupPhoto(result.getProfilePicUrl()); + setupPhoto(result.getHDProfilePicUrl()); } } @Override public void onFailure(final Throwable t) { final Context context = getContext(); - Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); + try { + Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + } + catch(final Throwable e) {} getDialog().dismiss(); } }); diff --git a/app/src/main/java/awais/instagrabber/fragments/CollectionPostsFragment.java b/app/src/main/java/awais/instagrabber/fragments/CollectionPostsFragment.java index ee154b63..bfedd70e 100644 --- a/app/src/main/java/awais/instagrabber/fragments/CollectionPostsFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/CollectionPostsFragment.java @@ -307,7 +307,10 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay @Override public void onFailure(final Throwable t) { Log.e(TAG, "Error deleting collection", t); - Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + try { + Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + } + catch(final Throwable e) {} } }); }) @@ -334,7 +337,10 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay @Override public void onFailure(final Throwable t) { Log.e(TAG, "Error editing collection", t); - Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + try { + Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + } + catch(final Throwable e) {} } }); }) diff --git a/app/src/main/java/awais/instagrabber/fragments/CommentsViewerFragment.java b/app/src/main/java/awais/instagrabber/fragments/CommentsViewerFragment.java index 18cc9762..d40f8608 100644 --- a/app/src/main/java/awais/instagrabber/fragments/CommentsViewerFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/CommentsViewerFragment.java @@ -371,7 +371,10 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl @Override public void onFailure(final Throwable t) { Log.e(TAG, "Error liking comment", t); - Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + try { + Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + } + catch(final Throwable e) {} } }); return; @@ -389,7 +392,10 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl @Override public void onFailure(final Throwable t) { Log.e(TAG, "Error unliking comment", t); - Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + try { + Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + } + catch(final Throwable e) {} } }); break; @@ -411,7 +417,10 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl @Override public void onFailure(final Throwable t) { Log.e(TAG, "Error translating comment", t); - Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + try { + Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + } + catch(final Throwable e) {} } }); break; @@ -432,7 +441,10 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment impl @Override public void onFailure(final Throwable t) { Log.e(TAG, "Error deleting comment", t); - Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + try { + Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + } + catch(final Throwable e) {} } }); break; diff --git a/app/src/main/java/awais/instagrabber/fragments/FollowViewerFragment.java b/app/src/main/java/awais/instagrabber/fragments/FollowViewerFragment.java index 115f5849..8112d497 100644 --- a/app/src/main/java/awais/instagrabber/fragments/FollowViewerFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/FollowViewerFragment.java @@ -44,7 +44,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh private final ArrayList followersModels = new ArrayList<>(); private final ArrayList allFollowing = new ArrayList<>(); - private boolean moreAvailable = true, isFollowersList, isCompare = false, loading = false, shouldRefresh = true; + private boolean moreAvailable = true, isFollowersList, isCompare = false, loading = false, shouldRefresh = true, searching = false; private long profileId; private String username; private String namePost; @@ -65,7 +65,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh final ServiceCallback followingFetchCb = new ServiceCallback() { @Override public void onSuccess(final FriendshipListFetchResponse result) { - if (result != null) { + if (result != null && isCompare) { followingModels.addAll(result.getItems()); if (!isFollowersList) followModels.addAll(result.getItems()); if (result.isMoreAvailable()) { @@ -78,7 +78,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh if (!isFollowersList) moreAvailable = false; showCompare(); } - } else binding.swipeRefreshLayout.setRefreshing(false); + } else if (isCompare) binding.swipeRefreshLayout.setRefreshing(false); } @Override @@ -94,7 +94,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh final ServiceCallback followersFetchCb = new ServiceCallback() { @Override public void onSuccess(final FriendshipListFetchResponse result) { - if (result != null) { + if (result != null && isCompare) { followersModels.addAll(result.getItems()); if (isFollowersList) followModels.addAll(result.getItems()); if (result.isMoreAvailable()) { @@ -107,7 +107,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh if (isFollowersList) moreAvailable = false; showCompare(); } - } + } else if (isCompare) binding.swipeRefreshLayout.setRefreshing(false); } @Override @@ -237,12 +237,12 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh }; layoutManager = new LinearLayoutManager(getContext()); lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { - if (!TextUtils.isEmpty(endCursor)) { + if (!TextUtils.isEmpty(endCursor) && !searching) { binding.swipeRefreshLayout.setRefreshing(true); layoutManager.setStackFromEnd(true); friendshipService.getList(isFollowersList, profileId, endCursor, cb); + endCursor = null; } - endCursor = null; }); binding.rvFollow.addOnScrollListener(lazyLoader); binding.rvFollow.setLayoutManager(layoutManager); @@ -303,68 +303,6 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh final SearchView searchView = (SearchView) menuSearch.getActionView(); searchView.setQueryHint(getResources().getString(R.string.action_search)); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { - // private final Filter filter = new Filter() { - // private final ArrayList searchFollowModels = new ArrayList<>(followModels.size() / 2); - // private final ArrayList searchFollowingModels = new ArrayList<>(followingModels.size() / 2); - // private final ArrayList searchFollowersModels = new ArrayList<>(followersModels.size() / 2); - // private final ArrayList searchAllFollowing = new ArrayList<>(allFollowing.size() / 2); - // - // @Nullable - // @Override - // protected FilterResults performFiltering(@NonNull final CharSequence constraint) { - // searchFollowModels.clear(); - // searchFollowingModels.clear(); - // searchFollowersModels.clear(); - // searchAllFollowing.clear(); - // - // final int followModelsSize = followModels.size(); - // final int followingModelsSize = followingModels.size(); - // final int followersModelsSize = followersModels.size(); - // final int allFollowingSize = allFollowing.size(); - // - // int maxSize = followModelsSize; - // if (maxSize < followingModelsSize) maxSize = followingModelsSize; - // if (maxSize < followersModelsSize) maxSize = followersModelsSize; - // if (maxSize < allFollowingSize) maxSize = allFollowingSize; - // - // final String query = constraint.toString().toLowerCase(); - // FollowModel followModel; - // while (maxSize != -1) { - // if (maxSize < followModelsSize) { - // followModel = followModels.get(maxSize); - // if (Utils.hasKey(query, followModel.getUsername(), followModel.getFullName())) - // searchFollowModels.add(followModel); - // } - // - // if (maxSize < followingModelsSize) { - // followModel = followingModels.get(maxSize); - // if (Utils.hasKey(query, followModel.getUsername(), followModel.getFullName())) - // searchFollowingModels.add(followModel); - // } - // - // if (maxSize < followersModelsSize) { - // followModel = followersModels.get(maxSize); - // if (Utils.hasKey(query, followModel.getUsername(), followModel.getFullName())) - // searchFollowersModels.add(followModel); - // } - // - // if (maxSize < allFollowingSize) { - // followModel = allFollowing.get(maxSize); - // if (Utils.hasKey(query, followModel.getUsername(), followModel.getFullName())) - // searchAllFollowing.add(followModel); - // } - // - // --maxSize; - // } - // - // return null; - // } - // - // @Override - // protected void publishResults(final CharSequence query, final FilterResults results) { - // refreshAdapter(searchFollowModels, searchFollowingModels, searchFollowersModels, searchAllFollowing); - // } - // }; @Override public boolean onQueryTextSubmit(final String query) { @@ -373,9 +311,15 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh @Override public boolean onQueryTextChange(final String query) { - // if (Utils.isEmpty(query)) refreshAdapter(followModels, followingModels, followersModels, allFollowing); + if (TextUtils.isEmpty(query)) { + searching = false; + // refreshAdapter(followModels, followingModels, followersModels, allFollowing); + } // else filter.filter(query.toLowerCase()); - if (adapter != null) adapter.getFilter().filter(query); + if (adapter != null) { + searching = true; + adapter.getFilter().filter(query); + } return true; } }); diff --git a/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java b/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java index ce3b1cf9..845da1c6 100644 --- a/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java @@ -376,7 +376,8 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe final Context context = getContext(); if (context == null) return; if (hashtagModel == null) { - Toast.makeText(context, R.string.error_loading_profile, Toast.LENGTH_SHORT).show(); + Toast.makeText(context, R.string.error_loading_hashtag, Toast.LENGTH_SHORT).show(); + binding.swipeRefreshLayout.setEnabled(false); return; } setTitle(); diff --git a/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java b/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java index 67b7e5d7..49e23159 100644 --- a/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java @@ -385,7 +385,8 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR if (locationModel == null) { final Context context = getContext(); if (context == null) return; - Toast.makeText(context, R.string.error_loading_profile, Toast.LENGTH_SHORT).show(); + Toast.makeText(context, R.string.error_loading_location, Toast.LENGTH_SHORT).show(); + binding.swipeRefreshLayout.setEnabled(false); return; } setTitle(); diff --git a/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java b/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java index 337f2754..c7345228 100644 --- a/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java @@ -216,10 +216,14 @@ public class StoryViewerFragment extends Fragment { new AlertDialog.Builder(context) .setTitle(R.string.reply_story) .setView(input) - .setPositiveButton(R.string.confirm, (d, w) -> new CreateThreadAction(cookie, currentStory.getUserId(), threadId -> { + .setPositiveButton(R.string.confirm, (d, w) -> new CreateThreadAction(cookie, currentStory.getUserId(), thread -> { + if (thread == null) { + Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); + return; + } try { final Call request = directMessagesService - .broadcastStoryReply(BroadcastOptions.ThreadIdOrUserIds.of(threadId), + .broadcastStoryReply(BroadcastOptions.ThreadIdOrUserIds.of(thread.getThreadId()), input.getText().toString(), currentStory.getStoryMediaId(), String.valueOf(currentStory.getUserId())); diff --git a/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java b/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java index d0567bfb..856a2164 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java @@ -305,9 +305,9 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); fragmentActivity = (MainActivity) requireActivity(); - friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, userId); - storiesService = StoriesService.getInstance(); - mediaService = MediaService.getInstance(null, null, 0); + friendshipService = isLoggedIn ? FriendshipService.getInstance(deviceUuid, csrfToken, userId) : null; + storiesService = isLoggedIn ? StoriesService.getInstance() : null; + mediaService = isLoggedIn ? MediaService.getInstance(null, null, 0) : null; accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext())); favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(getContext())); setHasOptionsMenu(true); @@ -538,10 +538,26 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe private void fetchProfileDetails() { if (TextUtils.isEmpty(username)) return; - new ProfileFetcher(username.trim().substring(1), isLoggedIn, profileModel -> { - if (getContext() == null) return; - this.profileModel = profileModel; - setProfileDetails(); + new ProfileFetcher(username.trim().substring(1), isLoggedIn, new FetchListener() { + @Override + public void onResult(final User user) { + if (getContext() == null) return; + profileModel = user; + setProfileDetails(); + } + + @Override + public void onFailure(final Throwable t) { + Log.e(TAG, "Error fetching profile", t); + final Context context = getContext(); + try { + if (t == null) Toast.makeText(context, + isLoggedIn ? R.string.error_loading_profile_loggedin : R.string.error_loading_profile, + Toast.LENGTH_LONG).show(); + else Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + } + catch(final Throwable e) {} + } }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -786,18 +802,19 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe private void setupButtons(final long profileId, final long myId) { profileDetailsBinding.btnTagged.setVisibility(isReallyPrivate() ? View.GONE : View.VISIBLE); + profileDetailsBinding.btnDM.setVisibility(View.GONE); // temporary measure if (isLoggedIn) { if (Objects.equals(profileId, myId)) { profileDetailsBinding.btnTagged.setVisibility(View.VISIBLE); profileDetailsBinding.btnSaved.setVisibility(View.VISIBLE); profileDetailsBinding.btnLiked.setVisibility(View.VISIBLE); - profileDetailsBinding.btnDM.setVisibility(View.GONE); +// profileDetailsBinding.btnDM.setVisibility(View.GONE); profileDetailsBinding.btnSaved.setText(R.string.saved); return; } profileDetailsBinding.btnSaved.setVisibility(View.GONE); profileDetailsBinding.btnLiked.setVisibility(View.GONE); - profileDetailsBinding.btnDM.setVisibility(View.VISIBLE); // maybe there is a judgment mechanism? +// profileDetailsBinding.btnDM.setVisibility(View.VISIBLE); profileDetailsBinding.btnFollow.setVisibility(View.VISIBLE); final Context context = getContext(); if (context == null) return; @@ -902,7 +919,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe @Override public void onSuccess(final FriendshipChangeResponse result) { // Log.d(TAG, "Unfollow success: " + result); - onRefresh(); + fetchProfileDetails(); } @Override @@ -920,7 +937,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe @Override public void onSuccess(final FriendshipChangeResponse result) { // Log.d(TAG, "Unfollow success: " + result); - onRefresh(); + fetchProfileDetails(); } @Override @@ -935,7 +952,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe @Override public void onSuccess(final FriendshipChangeResponse result) { // Log.d(TAG, "Follow success: " + result); - onRefresh(); + fetchProfileDetails(); } @Override @@ -961,17 +978,27 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe PostItemType.TAGGED); NavHostFragment.findNavController(this).navigate(action); }); - profileDetailsBinding.btnDM.setOnClickListener(v -> { - profileDetailsBinding.btnDM.setEnabled(false); - // new CreateThreadAction(cookie, profileModel.getPk(), threadId -> { - // if (isAdded()) { - // final NavDirections action = ProfileFragmentDirections - // .actionProfileFragmentToDMThreadFragment(threadId, profileModel.getUsername()); - // NavHostFragment.findNavController(this).navigate(action); - // } - // profileDetailsBinding.btnDM.setEnabled(true); - // }).execute(); - }); +// profileDetailsBinding.btnDM.setOnClickListener(v -> { +// profileDetailsBinding.btnDM.setEnabled(false); +// new CreateThreadAction(cookie, profileModel.getPk(), thread -> { +// if (thread == null) { +// Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); +// profileDetailsBinding.btnDM.setEnabled(true); +// return; +// } +// if (isAdded()) { +// final Bundle bundle = new Bundle(); +// bundle.putString("threadId", thread.getThreadId()); +// bundle.putString("title", thread.getThreadTitle()); +// if (isAdded()) { +// final NavDirections action = ProfileFragmentDirections +// .actionProfileFragmentToDMThreadFragment(thread.getThreadId(), profileModel.getUsername()); +// NavHostFragment.findNavController(this).navigate(action); +// } +// } +// profileDetailsBinding.btnDM.setEnabled(true); +// }).execute(); +// }); profileDetailsBinding.mainProfileImage.setOnClickListener(v -> { if (!hasStories) { // show profile pic diff --git a/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java b/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java index ad4d401b..55088c8b 100644 --- a/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java @@ -64,7 +64,7 @@ public class MorePreferencesFragment extends BasePreferencesFragment { screen.addPreference(accountCategory); if (isLoggedIn) { accountCategory.setSummary(R.string.account_hint); - accountCategory.addPreference(getAccountSwitcherPreference(cookie)); + accountCategory.addPreference(getAccountSwitcherPreference(cookie, context)); accountCategory.addPreference(getPreference(R.string.logout, R.string.logout_summary, R.drawable.ic_logout_24, preference -> { if (getContext() == null) return false; CookieUtils.setupCookies("LOGOUT"); @@ -79,7 +79,7 @@ public class MorePreferencesFragment extends BasePreferencesFragment { public void onSuccess(@NonNull final List accounts) { if (!isLoggedIn) { if (accounts.size() > 0) { - accountCategory.addPreference(getAccountSwitcherPreference(null)); + accountCategory.addPreference(getAccountSwitcherPreference(null, context)); } // Need to show something to trigger login activity accountCategory.addPreference(getPreference(R.string.add_account, R.drawable.ic_add, preference -> { @@ -235,8 +235,7 @@ public class MorePreferencesFragment extends BasePreferencesFragment { } } - private AccountSwitcherPreference getAccountSwitcherPreference(final String cookie) { - final Context context = getContext(); + private AccountSwitcherPreference getAccountSwitcherPreference(final String cookie, final Context context) { if (context == null) return null; return new AccountSwitcherPreference(context, cookie, accountRepository, v -> showAccountSwitcherDialog()); } diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/HdProfilePicUrlInfo.java b/app/src/main/java/awais/instagrabber/repositories/responses/HdProfilePicUrlInfo.java new file mode 100644 index 00000000..86787880 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/repositories/responses/HdProfilePicUrlInfo.java @@ -0,0 +1,16 @@ +package awais.instagrabber.repositories.responses; + +public class HdProfilePicUrlInfo { + private final String url; + private final int width, height; + + public HdProfilePicUrlInfo(final String url, final int width, final int height) { + this.url = url; + this.width = width; + this.height = height; + } + + public String getUrl() { + return url; + } +} diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/User.java b/app/src/main/java/awais/instagrabber/repositories/responses/User.java index 1897b8ca..2de6407f 100644 --- a/app/src/main/java/awais/instagrabber/repositories/responses/User.java +++ b/app/src/main/java/awais/instagrabber/repositories/responses/User.java @@ -26,6 +26,7 @@ public class User implements Serializable { private final String externalUrl; private final long usertagsCount; private final String publicEmail; + private final HdProfilePicUrlInfo hdProfilePicUrlInfo; public User(final long pk, @@ -49,7 +50,8 @@ public class User implements Serializable { final String biography, final String externalUrl, final long usertagsCount, - final String publicEmail) { + final String publicEmail, + final HdProfilePicUrlInfo hdProfilePicUrlInfo) { this.pk = pk; this.username = username; this.fullName = fullName; @@ -72,6 +74,7 @@ public class User implements Serializable { this.externalUrl = externalUrl; this.usertagsCount = usertagsCount; this.publicEmail = publicEmail; + this.hdProfilePicUrlInfo = hdProfilePicUrlInfo; } public long getPk() { @@ -94,6 +97,10 @@ public class User implements Serializable { return profilePicUrl; } + public String getHDProfilePicUrl() { + return hdProfilePicUrlInfo.getUrl(); + } + public String getProfilePicId() { return profilePicId; } diff --git a/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java b/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java index a23186e7..d9ef6d66 100644 --- a/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java +++ b/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java @@ -781,7 +781,7 @@ public final class ResponseBodyUtils { null, friendshipStatus, owner.optBoolean("is_verified"), - false, false, false, false, null, null, 0, 0, 0, 0, null, null, 0, null); + false, false, false, false, null, null, 0, 0, 0, 0, null, null, 0, null, null); } final String id = feedItem.getString(Constants.EXTRAS_ID); final ImageVersions2 imageVersions2 = new ImageVersions2( diff --git a/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java b/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java index 4b744ac2..74044d29 100644 --- a/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java +++ b/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java @@ -242,6 +242,7 @@ public class GraphQLService extends BaseService { null, null, 0, + null, null )); // userModels.add(new ProfileModel(userObject.optBoolean("is_private"), @@ -332,6 +333,7 @@ public class GraphQLService extends BaseService { userJson.getString("biography"), url, 0, + null, null)); } catch (JSONException e) { Log.e(TAG, "onResponse", e); diff --git a/app/src/main/java/awais/instagrabber/webservices/StoriesService.java b/app/src/main/java/awais/instagrabber/webservices/StoriesService.java index 07fbd448..6cd3e43e 100644 --- a/app/src/main/java/awais/instagrabber/webservices/StoriesService.java +++ b/app/src/main/java/awais/instagrabber/webservices/StoriesService.java @@ -113,51 +113,55 @@ public class StoriesService extends BaseService { for (int i = 0; i < feedStoriesReel.length(); ++i) { final JSONObject node = feedStoriesReel.getJSONObject(i); final JSONObject userJson = node.getJSONObject(node.has("user") ? "user" : "owner"); - final User user = new User(userJson.getLong("pk"), - userJson.getString("username"), - userJson.optString("full_name"), - userJson.optBoolean("is_private"), - userJson.getString("profile_pic_url"), - null, - new FriendshipStatus( - false, - false, - false, - false, - false, - false, - false, - false, - false, - false - ), - userJson.optBoolean("is_verified"), - false, - false, - false, - false, - null, - null, - 0, - 0, - 0, - 0, - null, - null, - 0, - null - ); - final String id = node.getString("id"); - final long timestamp = node.getLong("latest_reel_media"); - final int mediaCount = node.getInt("media_count"); - final boolean fullyRead = !node.isNull("seen") && node.getLong("seen") == timestamp; - final JSONObject itemJson = node.has("items") ? node.getJSONArray("items").optJSONObject(0) : null; - final boolean isBestie = node.optBoolean("has_besties_media", false); - StoryModel firstStoryModel = null; - if (itemJson != null) { - firstStoryModel = ResponseBodyUtils.parseStoryItem(itemJson, false, false, null); + try { + final User user = new User(userJson.getLong("pk"), + userJson.getString("username"), + userJson.optString("full_name"), + userJson.optBoolean("is_private"), + userJson.getString("profile_pic_url"), + null, + new FriendshipStatus( + false, + false, + false, + false, + false, + false, + false, + false, + false, + false + ), + userJson.optBoolean("is_verified"), + false, + false, + false, + false, + null, + null, + 0, + 0, + 0, + 0, + null, + null, + 0, + null, + null + ); + final String id = node.getString("id"); + final long timestamp = node.getLong("latest_reel_media"); + final int mediaCount = node.getInt("media_count"); + final boolean fullyRead = !node.isNull("seen") && node.getLong("seen") == timestamp; + final JSONObject itemJson = node.has("items") ? node.getJSONArray("items").optJSONObject(0) : null; + final boolean isBestie = node.optBoolean("has_besties_media", false); + StoryModel firstStoryModel = null; + if (itemJson != null) { + firstStoryModel = ResponseBodyUtils.parseStoryItem(itemJson, false, false, null); + } + feedStoryModels.add(new FeedStoryModel(id, user, fullyRead, timestamp, firstStoryModel, mediaCount, false, isBestie)); } - feedStoryModels.add(new FeedStoryModel(id, user, fullyRead, timestamp, firstStoryModel, mediaCount, false, isBestie)); + catch (Exception e) {} // to cover promotional reels with non-long user pk's } final JSONArray broadcasts = new JSONObject(body).getJSONArray("broadcasts"); for (int i = 0; i < broadcasts.length(); ++i) { @@ -201,6 +205,7 @@ public class StoriesService extends BaseService { null, null, 0, + null, null ); final String id = node.getString("id"); diff --git a/app/src/main/java/awais/instagrabber/webservices/UserService.java b/app/src/main/java/awais/instagrabber/webservices/UserService.java index 0aff3f32..52bb064d 100644 --- a/app/src/main/java/awais/instagrabber/webservices/UserService.java +++ b/app/src/main/java/awais/instagrabber/webservices/UserService.java @@ -62,7 +62,7 @@ public class UserService extends BaseService { public void onResponse(@NonNull final Call call, @NonNull final Response response) { final WrappedUser user = response.body(); if (user == null) { - callback.onSuccess(null); + callback.onFailure(null); return; } callback.onSuccess(user.getUser()); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f93975cb..cb7e3632 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -36,7 +36,10 @@ Other members will know you viewed it Enable activity notifications Feed stories sort - Error loading profile!\nTry logging in and search again. + Error loading profile! Is the username valid? If so, you may be ratelimited. + Error loading profile! Is the username valid? Or did they block you? + Error loading hashtag! Is the name valid? + Error loading hashtag! Is the URL valid? Error creating Download folder(s). Save to custom folder Select folder diff --git a/build.gradle b/build.gradle index 1c106f22..6e5fab7e 100755 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:4.1.2' - def nav_version = "2.3.2" + def nav_version = "2.3.3" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa54c83c..a93e645f 100755 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,8 +1,9 @@ +#Sun Feb 28 01:04:23 JST 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=0080de8491f0918e4f529a6db6820fa0b9e818ee2386117f4394f95feb1d5583 -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip -# https://gradle.org/releases/ -# https://gradle.org/release-checksums/ zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists \ No newline at end of file +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-all.zip +distributionSha256Sum=1433372d903ffba27496f8d5af24265310d2da0d78bf6b4e5138831d4fe066e9 +# https://gradle.org/releases/ +# https://gradle.org/release-checksums/ \ No newline at end of file