diff --git a/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java b/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java index 6d3d4f7d..c5cd0d69 100644 --- a/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java +++ b/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java @@ -12,13 +12,11 @@ import com.facebook.imagepipeline.core.ImagePipelineConfig; import java.net.CookieHandler; import java.text.SimpleDateFormat; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.LocaleUtils; import awais.instagrabber.utils.SettingsHelper; import awais.instagrabber.utils.TextUtils; -import awais.instagrabber.utils.UserAgentUtils; import awaisomereport.CrashReporter; import awaisomereport.LogCollector; @@ -87,15 +85,5 @@ public final class InstaGrabberApplication extends Application { if (TextUtils.isEmpty(settingsHelper.getString(Constants.DEVICE_UUID))) { settingsHelper.putString(Constants.DEVICE_UUID, UUID.randomUUID().toString()); } - - if (settingsHelper.getInteger(Constants.BROWSER_UA_CODE) == -1) { - int randomNum = ThreadLocalRandom.current().nextInt(0, UserAgentUtils.browsers.length); - settingsHelper.putInteger(Constants.BROWSER_UA_CODE, randomNum); - } - - if (settingsHelper.getInteger(Constants.APP_UA_CODE) == -1) { - int randomNum = ThreadLocalRandom.current().nextInt(0, UserAgentUtils.devices.length); - settingsHelper.putInteger(Constants.APP_UA_CODE, randomNum); - } } } \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/FeedGridItemViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/FeedGridItemViewHolder.java index 81e60562..c6e1d571 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/FeedGridItemViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/FeedGridItemViewHolder.java @@ -83,6 +83,10 @@ public class FeedGridItemViewHolder extends RecyclerView.ViewHolder { final Media child = sliderItems.get(0); if (child != null) { thumbnailUrl = ResponseBodyUtils.getThumbUrl(child); + if (layoutPreferences.getType() == STAGGERED_GRID) { + final float childAspectRatio = (float) child.getOriginalWidth() / child.getOriginalHeight(); + binding.postImage.setAspectRatio(childAspectRatio); + } } } typeIconRes = R.drawable.ic_checkbox_multiple_blank_stroke; diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectInboxItemViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectInboxItemViewHolder.java index 9ce8ed84..a4e9042e 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectInboxItemViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectInboxItemViewHolder.java @@ -1,5 +1,6 @@ package awais.instagrabber.adapters.viewholder.directmessages; +import android.content.res.Resources; import android.graphics.Typeface; import android.view.View; @@ -126,13 +127,14 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder { private void setSubtitle(@NonNull final DirectThread thread) { // If there is an unopened raven media, give it highest priority + final Resources resources = itemView.getResources(); final DirectThreadDirectStory directStory = thread.getDirectStory(); final long viewerId = thread.getViewerId(); if (directStory != null && !directStory.getItems().isEmpty()) { final DirectItem item = directStory.getItems().get(0); final MediaItemType mediaType = item.getVisualMedia().getMedia().getMediaType(); - final String username = getUsername(thread.getUsers(), item.getUserId(), viewerId); - final String subtitle = getMediaSpecificSubtitle(username, mediaType); + final String username = getUsername(thread.getUsers(), item.getUserId(), viewerId, resources); + final String subtitle = getMediaSpecificSubtitle(username, resources, mediaType); binding.subtitle.setText(subtitle); return; } @@ -144,7 +146,7 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder { final String username = getUsername(thread.getUsers(), senderId, viewerId); String message = ""; if (itemType == null) { - message = "Unsupported message"; + message = resources.getString(R.string.dms_inbox_raven_message_unknown); } else { switch (itemType) { case TEXT: @@ -160,20 +162,20 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder { message = item.getPlaceholder().getMessage(); break; case MEDIA_SHARE: - subtitle = String.format("%s shared a post", username != null ? username : ""); + subtitle = resources.getString(R.string.dms_inbox_shared_post, username != null ? username : "", item.getMediaShare().getUser().getUsername()); break; case ANIMATED_MEDIA: - subtitle = String.format("%s shared a gif", username != null ? username : ""); + subtitle = resources.getString(R.string.dms_inbox_shared_gif, username != null ? username : ""); break; case PROFILE: - subtitle = String.format("%s shared a profile: @%s", username != null ? username : "", item.getProfile().getUsername()); + subtitle = resources.getString(R.string.dms_inbox_shared_profile, username != null ? username : "", item.getProfile().getUsername()); break; case LOCATION: - subtitle = String.format("%s shared a location: %s", username != null ? username : "", item.getLocation().getName()); + subtitle = resources.getString(R.string.dms_inbox_shared_location, username != null ? username : "", item.getLocation().getName()); break; case MEDIA: { final MediaItemType mediaType = item.getMedia().getMediaType(); - subtitle = getMediaSpecificSubtitle(username, mediaType); + subtitle = getMediaSpecificSubtitle(username, resources, mediaType); break; } case STORY_SHARE: { @@ -181,17 +183,16 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder { if (reelType == null) { subtitle = item.getStoryShare().getTitle(); } else { - String format = "%s shared a story by @%s"; - if (reelType.equals("highlight_reel")) { - format = "%s shared a story highlight by @%s"; - } - subtitle = String.format(format, username != null ? username : "", + final int format = reelType.equals("highlight_reel") + ? R.string.dms_inbox_shared_highlight + : R.string.dms_inbox_shared_story; + subtitle = resources.getString(format, username != null ? username : "", item.getStoryShare().getMedia().getUser().getUsername()); } break; } case VOICE_MEDIA: - subtitle = String.format("%s sent a voice message", username != null ? username : ""); + subtitle = resources.getString(R.string.dms_inbox_shared_voice, username != null ? username : ""); break; case ACTION_LOG: subtitle = item.getActionLog().getDescription(); @@ -200,15 +201,15 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder { subtitle = item.getVideoCallEvent().getDescription(); break; case CLIP: - subtitle = String.format("%s shared a clip by @%s", username != null ? username : "", - item.getClip().getClip().getUser().getUsername()); + subtitle = resources.getString(R.string.dms_inbox_shared_clip, username != null ? username : "", + item.getClip().getClip().getUser().getUsername()); break; case FELIX_SHARE: - subtitle = String.format("%s shared an IGTV video by @%s", username != null ? username : "", - item.getFelixShare().getVideo().getUser().getUsername()); + subtitle = resources.getString(R.string.dms_inbox_shared_igtv, username != null ? username : "", + item.getFelixShare().getVideo().getUser().getUsername()); break; case RAVEN_MEDIA: - subtitle = getRavenMediaSubtitle(item, username); + subtitle = getRavenMediaSubtitle(item, resources, username); break; case REEL_SHARE: final DirectItemReelShare reelShare = item.getReelShare(); @@ -220,9 +221,9 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder { switch (reelType) { case "reply": if (viewerId == item.getUserId()) { - subtitle = String.format("You replied to their story: %s", reelShare.getText()); + subtitle = resources.getString(R.string.dms_inbox_replied_story_outgoing, reelShare.getText()); } else { - subtitle = String.format("%s replied to your story: %s", username != null ? username : "", reelShare.getText()); + subtitle = resources.getString(R.string.dms_inbox_replied_story_incoming, username != null ? username : "", reelShare.getText()); } break; case "mention": @@ -230,17 +231,17 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder { // You mentioned the other person final long mentionedUserId = item.getReelShare().getMentionedUserId(); final String otherUsername = getUsername(thread.getUsers(), mentionedUserId, viewerId); - subtitle = String.format("You mentioned @%s in your story", otherUsername); + subtitle = resources.getString(R.string.dms_inbox_mentioned_story_outgoing, otherUsername); } else { // They mentioned you - subtitle = String.format("%s mentioned you in their story", username != null ? username : ""); + subtitle = resources.getString(R.string.dms_inbox_mentioned_story_incoming, username != null ? username : ""); } break; case "reaction": if (viewerId == item.getUserId()) { - subtitle = String.format("You reacted to their story: %s", reelShare.getText()); + subtitle = resources.getString(R.string.dms_inbox_reacted_story_outgoing, reelShare.getText()); } else { - subtitle = String.format("%s reacted to your story: %s", username != null ? username : "", reelShare.getText()); + subtitle = resources.getString(R.string.dms_inbox_reacted_story_incoming, username != null ? username : "", reelShare.getText()); } break; default: @@ -249,7 +250,7 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder { } break; default: - message = "Unsupported message"; + message = resources.getString(R.string.dms_inbox_raven_message_unknown); } } if (subtitle == null) { @@ -263,10 +264,10 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder { binding.subtitle.setText(subtitle != null ? subtitle : ""); } - private String getMediaSpecificSubtitle(final String username, final MediaItemType mediaType) { - final String userSharedAnImage = String.format("%s shared an image", username != null ? username : ""); - final String userSharedAVideo = String.format("%s shared a video", username != null ? username : ""); - final String userSentAMessage = String.format("%s sent a message", username != null ? username : ""); + private String getMediaSpecificSubtitle(final String username, final Resources resources, final MediaItemType mediaType) { + final String userSharedAnImage = resources.getString(R.string.dms_inbox_shared_image, username != null ? username : ""); + final String userSharedAVideo = resources.getString(R.string.dms_inbox_shared_video, username != null ? username : ""); + final String userSentAMessage = resources.getString(R.string.dms_inbox_shared_message, username != null ? username : ""); String subtitle; switch (mediaType) { case MEDIA_TYPE_IMAGE: @@ -283,6 +284,7 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder { } private String getRavenMediaSubtitle(final DirectItem item, + final Resources resources, final String username) { String subtitle = "↗ "; final DirectItemVisualMedia visualMedia = item.getVisualMedia(); @@ -325,15 +327,16 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder { return subtitle; } final MediaItemType mediaType = visualMedia.getMedia().getMediaType(); - subtitle = getMediaSpecificSubtitle(username, mediaType); + subtitle = getMediaSpecificSubtitle(username, resources, mediaType); return subtitle; } private String getUsername(final List users, final long userId, - final long viewerId) { + final long viewerId, + final Resources resources) { if (userId == viewerId) { - return "You"; + return resources.getString(R.string.you); } final Optional senderOptional = users.stream() .filter(Objects::nonNull) diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedItemViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedItemViewHolder.java index 9184b895..2def1d07 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedItemViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedItemViewHolder.java @@ -115,19 +115,21 @@ public abstract class FeedItemViewHolder extends RecyclerView.ViewHolder { private void setupLocation(@NonNull final Media media) { final Location location = media.getLocation(); - final String locationName = location.getName(); - if (TextUtils.isEmpty(locationName)) { - topBinding.location.setVisibility(View.GONE); - topBinding.title.setLayoutParams(new RelativeLayout.LayoutParams( - RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT - )); - } else { - topBinding.location.setVisibility(View.VISIBLE); - topBinding.location.setText(locationName); - topBinding.title.setLayoutParams(new RelativeLayout.LayoutParams( - RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT - )); - topBinding.location.setOnClickListener(v -> feedItemCallback.onLocationClick(media)); + if (location != null) { + final String locationName = location.getName(); + if (TextUtils.isEmpty(locationName)) { + topBinding.location.setVisibility(View.GONE); + topBinding.title.setLayoutParams(new RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT + )); + } else { + topBinding.location.setVisibility(View.VISIBLE); + topBinding.location.setText(locationName); + topBinding.title.setLayoutParams(new RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT + )); + topBinding.location.setOnClickListener(v -> feedItemCallback.onLocationClick(media)); + } } } diff --git a/app/src/main/java/awais/instagrabber/fragments/StoryListViewerFragment.java b/app/src/main/java/awais/instagrabber/fragments/StoryListViewerFragment.java index c712c058..880af8f5 100644 --- a/app/src/main/java/awais/instagrabber/fragments/StoryListViewerFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/StoryListViewerFragment.java @@ -87,12 +87,20 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr private final ServiceCallback cb = new ServiceCallback() { @Override public void onSuccess(final ArchiveFetchResponse result) { - endCursor = result.getNextCursor(); - final List models = archivesViewModel.getList().getValue(); - final List modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models); - modelsCopy.addAll(result.getResult()); - archivesViewModel.getList().postValue(modelsCopy); binding.swipeRefreshLayout.setRefreshing(false); + if (result == null) { + try { + final Context context = getContext(); + Toast.makeText(context, R.string.empty_list, Toast.LENGTH_SHORT).show(); + } catch (Exception ignored) {} + } + else { + endCursor = result.getNextCursor(); + final List models = archivesViewModel.getList().getValue(); + final List modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models); + modelsCopy.addAll(result.getResult()); + archivesViewModel.getList().postValue(modelsCopy); + } } @Override diff --git a/app/src/main/java/awais/instagrabber/utils/FlavorTown.java b/app/src/main/java/awais/instagrabber/utils/FlavorTown.java index d37d1ce9..de4f7cb6 100755 --- a/app/src/main/java/awais/instagrabber/utils/FlavorTown.java +++ b/app/src/main/java/awais/instagrabber/utils/FlavorTown.java @@ -21,6 +21,7 @@ import androidx.appcompat.app.AppCompatActivity; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Locale; +import java.util.concurrent.ThreadLocalRandom; import javax.security.cert.CertificateException; import javax.security.cert.X509Certificate; @@ -103,10 +104,18 @@ public final class FlavorTown { public static void changelogCheck(@NonNull final Context context) { if (settingsHelper.getInteger(Constants.PREV_INSTALL_VERSION) < BuildConfig.VERSION_CODE) { - final int appUaCode = settingsHelper.getInteger(Constants.APP_UA_CODE); + int appUaCode = settingsHelper.getInteger(Constants.APP_UA_CODE); + int browserUaCode = settingsHelper.getInteger(Constants.BROWSER_UA_CODE); + if (browserUaCode == -1) { + browserUaCode = ThreadLocalRandom.current().nextInt(0, UserAgentUtils.browsers.length); + settingsHelper.putInteger(Constants.BROWSER_UA_CODE, browserUaCode); + } + if (appUaCode == -1) { + appUaCode = ThreadLocalRandom.current().nextInt(0, UserAgentUtils.devices.length); + settingsHelper.putInteger(Constants.APP_UA_CODE, appUaCode); + } final String appUa = UserAgentUtils.generateAppUA(appUaCode, LocaleUtils.getCurrentLocale().getLanguage()); settingsHelper.putString(Constants.APP_UA, appUa); - final int browserUaCode = settingsHelper.getInteger(Constants.BROWSER_UA_CODE); final String browserUa = UserAgentUtils.generateBrowserUA(browserUaCode); settingsHelper.putString(Constants.BROWSER_UA, browserUa); Toast.makeText(context, R.string.updated, Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/java/awais/instagrabber/utils/LocaleUtils.java b/app/src/main/java/awais/instagrabber/utils/LocaleUtils.java index b9b25462..960bd8a6 100755 --- a/app/src/main/java/awais/instagrabber/utils/LocaleUtils.java +++ b/app/src/main/java/awais/instagrabber/utils/LocaleUtils.java @@ -57,26 +57,30 @@ public final class LocaleUtils { if (TextUtils.isEmpty(appLanguageSettings)) return null; final int appLanguageIndex = Integer.parseInt(appLanguageSettings); - if (appLanguageIndex == 1) return "en"; - if (appLanguageIndex == 2) return "fr"; - if (appLanguageIndex == 3) return "es"; - if (appLanguageIndex == 4) return "zh_CN"; - if (appLanguageIndex == 5) return "in"; - if (appLanguageIndex == 6) return "it"; - if (appLanguageIndex == 7) return "de"; - if (appLanguageIndex == 8) return "pl"; - if (appLanguageIndex == 9) return "tr"; - if (appLanguageIndex == 10) return "pt"; - if (appLanguageIndex == 11) return "fa"; - if (appLanguageIndex == 12) return "mk"; - if (appLanguageIndex == 13) return "vi"; - if (appLanguageIndex == 14) return "zh_TW"; - if (appLanguageIndex == 15) return "ca"; - if (appLanguageIndex == 16) return "ru"; - if (appLanguageIndex == 17) return "hi"; - if (appLanguageIndex == 18) return "nl"; - if (appLanguageIndex == 19) return "sk"; - if (appLanguageIndex == 20) return "ja"; + switch (appLanguageIndex) { + case 1: return "en"; + case 2: return "fr"; + case 3: return "es"; + case 4: return "zh_CN"; + case 5: return "in"; + case 6: return "it"; + case 7: return "de"; + case 8: return "pl"; + case 9: return "tr"; + case 10: return "pt"; + case 11: return "fa"; + case 12: return "mk"; + case 13: return "vi"; + case 14: return "zh_TW"; + case 15: return "ca"; + case 16: return "ru"; + case 17: return "hi"; + case 18: return "nl"; + case 19: return "sk"; + case 20: return "ja"; + case 21: return "el"; + case 22: return "eu"; + } return null; } diff --git a/app/src/main/java/awais/instagrabber/utils/UserAgentUtils.java b/app/src/main/java/awais/instagrabber/utils/UserAgentUtils.java index c9397cdc..63c1f0a1 100644 --- a/app/src/main/java/awais/instagrabber/utils/UserAgentUtils.java +++ b/app/src/main/java/awais/instagrabber/utils/UserAgentUtils.java @@ -18,8 +18,8 @@ public class UserAgentUtils { "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15" }; // use APKpure, assume x86 - private static final String igVersion = "169.3.0.30.135"; - private static final String igVersionCode = "264009054"; + private static final String igVersion = "175.1.0.25.119"; + private static final String igVersionCode = "273907115"; // only pick the ones that has width 1440 for maximum download quality public static final String[] devices = { // https://github.com/dilame/instagram-private-api/blob/master/src/samples/devices.json diff --git a/app/src/main/java/awais/instagrabber/webservices/StoriesService.java b/app/src/main/java/awais/instagrabber/webservices/StoriesService.java index 6cd3e43e..bc6ca65a 100644 --- a/app/src/main/java/awais/instagrabber/webservices/StoriesService.java +++ b/app/src/main/java/awais/instagrabber/webservices/StoriesService.java @@ -276,7 +276,6 @@ public class StoriesService extends BaseService { form.put("include_suggested_highlights", "false"); form.put("is_in_archive_home", "true"); form.put("include_cover", "1"); - form.put("timezone_offset", String.valueOf((float) TimeZone.getDefault().getRawOffset() / 1000)); if (!TextUtils.isEmpty(maxId)) { form.put("max_id", maxId); // NOT TESTED } diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 3b5e8a70..49bcf692 100755 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -22,6 +22,8 @@ Nederlands Slovenčina 日本語 + Ελληνικά + Euskara Auto / Follow System diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4c1c4078..433a642a 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -39,7 +39,7 @@ 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 loading location! Is the URL valid? Error creating Download folder(s). Save to custom folder Select folder @@ -166,7 +166,7 @@ Replied to a story Reacted on a story Mentioned in a story - Unsupported message type + Unsupported message type Open link Copy text Download attachment @@ -174,7 +174,24 @@ Unlike message Unsend message View author profile - Post shared from %s + %s shared a post by @%s + %s shared an image + %s shared a video + %s sent a message + %s shared a gif + %s shared a profile: @%s + %s shared a location: %s + %s shared a story highlight by @%s + %s shared a story by @%s + %s sent a voice message + %s shared a clip by @%s + %s shared an IGTV video by @%s + You replied to their story: %s + %s replied to your story: %s + You reacted to their story: %s + %s reacted to your story: %s + You mentioned @%s in your story + %s mentioned you in their story Unknown media type Media expired! Delivered @@ -431,4 +448,5 @@ Accept request from %1s (%2s)? Decline Accept + You