From 4ef78bbe3f6eb5f658f77b4b1cb0eb13bf813860 Mon Sep 17 00:00:00 2001 From: Austin Huang Date: Fri, 26 Mar 2021 22:51:44 -0400 Subject: [PATCH 01/13] fix the dm colors for light theme --- app/src/main/res/values/color.xml | 4 ++-- app/src/main/res/values/themes.xml | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values/color.xml b/app/src/main/res/values/color.xml index 3a2893aa..fd773071 100755 --- a/app/src/main/res/values/color.xml +++ b/app/src/main/res/values/color.xml @@ -162,7 +162,7 @@ #ffddac #a17c4f #616161 - @color/white + #d63f44 @@ -172,5 +172,5 @@ #fff4e8 #8e2929 #000000 - @color/white + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index cd0d78a9..a0e7a3b8 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -64,6 +64,7 @@ @style/Widget.BottomNavigationView.Light.Barinsta @color/barinstaPrimaryTextColor @style/Widget.MaterialComponents.Toolbar.Light.Barinsta + @color/black From ec592074be0511dca5dfd918595bd6cf70f97d44 Mon Sep 17 00:00:00 2001 From: Austin Huang Date: Sat, 27 Mar 2021 10:41:31 -0400 Subject: [PATCH 02/13] fix graphql parse thumbnail --- .../instagrabber/utils/ResponseBodyUtils.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java b/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java index 3c5eb0f6..2722d11e 100644 --- a/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java +++ b/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java @@ -729,15 +729,19 @@ public final class ResponseBodyUtils { width = dimensions.optInt("width"); } String thumbnailUrl = null; - final JSONArray displayResources = feedItem.getJSONArray("display_resources"); final List candidates = new ArrayList(); - for (int i = 0; i < displayResources.length(); i++) { - final JSONObject displayResource = displayResources.getJSONObject(i); - candidates.add(new MediaCandidate( - displayResource.getInt("config_width"), - displayResource.getInt("config_height"), - displayResource.getString("src") - )); + if (feedItem.has("display_resources") || feedItem.has("thumbnail_resources")) { + final JSONArray displayResources = feedItem.has("display_resources") + ? feedItem.getJSONArray("display_resources") + : feedItem.getJSONArray("thumbnail_resources"); + for (int i = 0; i < displayResources.length(); i++) { + final JSONObject displayResource = displayResources.getJSONObject(i); + candidates.add(new MediaCandidate( + displayResource.getInt("config_width"), + displayResource.getInt("config_height"), + displayResource.getString("src") + )); + } } final ImageVersions2 imageVersions2 = new ImageVersions2(candidates); From c9f46a1986b955e20825d21fac8e736260905cd7 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Sun, 28 Mar 2021 16:41:53 +0900 Subject: [PATCH 03/13] Update root project name --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index bf7737cf..77b3c366 100755 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,2 @@ include ':app' -rootProject.name = "InstaGrabber" +rootProject.name = "Barinsta" From c5d55f366175e7421490fc571c43ab035e2e5dc9 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Mon, 29 Mar 2021 02:01:40 +0900 Subject: [PATCH 04/13] Added auto fetch more posts in feed at init. But disabled due to some weird list merging. --- .../customviews/PostsRecyclerView.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/awais/instagrabber/customviews/PostsRecyclerView.java b/app/src/main/java/awais/instagrabber/customviews/PostsRecyclerView.java index cdab91c9..b2456e0a 100644 --- a/app/src/main/java/awais/instagrabber/customviews/PostsRecyclerView.java +++ b/app/src/main/java/awais/instagrabber/customviews/PostsRecyclerView.java @@ -22,6 +22,7 @@ import androidx.work.WorkManager; import com.google.common.collect.ImmutableList; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -74,11 +75,10 @@ public class PostsRecyclerView extends RecyclerView { } final List models = mediaViewModel.getList().getValue(); final List modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models); - if (settingsHelper.getBoolean(Constants.TOGGLE_KEYWORD_FILTER)){ + if (settingsHelper.getBoolean(Constants.TOGGLE_KEYWORD_FILTER)) { final ArrayList items = new ArrayList<>(settingsHelper.getStringSet(Constants.KEYWORD_FILTERS)); modelsCopy.addAll(new KeywordsFilterUtils(items).filter(result)); - } - else { + } else { modelsCopy.addAll(result); } mediaViewModel.getList().postValue(modelsCopy); @@ -194,7 +194,9 @@ public class PostsRecyclerView extends RecyclerView { private void initSelf() { mediaViewModel = new ViewModelProvider(viewModelStoreOwner).get(MediaViewModel.class); mediaViewModel.getList().observe(lifeCycleOwner, list -> { - if (list.size() > 0) feedAdapter.submitList(list, () -> { + if (list.size() <= 0) return; + feedAdapter.submitList(list, () -> { + // postDelayed(this::fetchMoreIfPossible, 1000); if (!shouldScrollToTop) return; smoothScrollToPosition(0); shouldScrollToTop = false; @@ -217,6 +219,20 @@ public class PostsRecyclerView extends RecyclerView { dispatchFetchStatus(); } + private void fetchMoreIfPossible() { + if (!postFetcher.hasMore()) return; + if (feedAdapter.getItemCount() == 0) return; + final LayoutManager layoutManager = getLayoutManager(); + if (!(layoutManager instanceof StaggeredGridLayoutManager)) return; + final int[] itemPositions = ((StaggeredGridLayoutManager) layoutManager).findLastCompletelyVisibleItemPositions(null); + final boolean allNoPosition = Arrays.stream(itemPositions).allMatch(position -> position == RecyclerView.NO_POSITION); + if (allNoPosition) return; + final boolean match = Arrays.stream(itemPositions).anyMatch(position -> position == feedAdapter.getItemCount() - 1); + if (!match) return; + postFetcher.fetch(); + dispatchFetchStatus(); + } + private void initDownloadWorkerListener() { WorkManager.getInstance(getContext()) .getWorkInfosByTagLiveData("download") From 7dc9583e51dbb4517196c333e6d41044127d53f0 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Mon, 29 Mar 2021 22:48:55 +0900 Subject: [PATCH 05/13] Null checks. Fixes https://github.com/austinhuang0131/barinsta/issues/905 --- .../awais/instagrabber/viewmodels/DirectThreadViewModel.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java index 1ca3c263..3329d6c8 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java @@ -241,6 +241,7 @@ public class DirectThreadViewModel extends AndroidViewModel { if (users != null && users.getValue() != null) { final List userList = users.getValue(); match = userList.stream() + .filter(Objects::nonNull) .filter(user -> user.getPk() == userId) .findFirst() .orElse(null); @@ -250,6 +251,7 @@ public class DirectThreadViewModel extends AndroidViewModel { if (leftUsers != null && leftUsers.getValue() != null) { final List userList = leftUsers.getValue(); match = userList.stream() + .filter(Objects::nonNull) .filter(user -> user.getPk() == userId) .findFirst() .orElse(null); From 4507d8b5882e283c3e634ff11aa64a85f38c0dc0 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Mon, 29 Mar 2021 23:02:42 +0900 Subject: [PATCH 06/13] Handle unknown dm types. Fixes the crash in https://github.com/austinhuang0131/barinsta/issues/891 --- .../instagrabber/adapters/DirectItemsAdapter.java | 13 +++++++++++-- .../instagrabber/models/enums/DirectItemType.java | 4 ++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java b/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java index 9fa309f2..f28fb139 100644 --- a/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java +++ b/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java @@ -146,7 +146,12 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter Date: Tue, 30 Mar 2021 00:47:28 +0900 Subject: [PATCH 07/13] Add XMA type direct item and fix default viewholder not visible. Fixes https://github.com/austinhuang0131/barinsta/issues/891 --- .../adapters/DirectItemsAdapter.java | 13 ++- .../DirectItemDefaultViewHolder.java | 6 + .../directmessages/DirectItemViewHolder.java | 2 +- .../DirectItemXmaViewHolder.java | 69 ++++++++++++ .../models/enums/DirectItemType.java | 10 +- .../responses/directmessages/DirectItem.java | 10 +- .../directmessages/DirectItemXma.java | 104 ++++++++++++++++++ .../awais/instagrabber/utils/DMUtils.java | 18 ++- .../instagrabber/utils/DirectItemFactory.java | 4 + 9 files changed, 219 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemXmaViewHolder.java create mode 100644 app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectItemXma.java diff --git a/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java b/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java index f28fb139..e1469ac5 100644 --- a/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java +++ b/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java @@ -34,6 +34,7 @@ import awais.instagrabber.adapters.viewholder.directmessages.DirectItemTextViewH import awais.instagrabber.adapters.viewholder.directmessages.DirectItemVideoCallEventViewHolder; import awais.instagrabber.adapters.viewholder.directmessages.DirectItemViewHolder; import awais.instagrabber.adapters.viewholder.directmessages.DirectItemVoiceMediaViewHolder; +import awais.instagrabber.adapters.viewholder.directmessages.DirectItemXmaViewHolder; import awais.instagrabber.customviews.emoji.Emoji; import awais.instagrabber.databinding.LayoutDmActionLogBinding; import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding; @@ -146,12 +147,7 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter widthHeight = NumberUtils.calculateWidthHeight( + urlInfo.getHeight(), + urlInfo.getWidth(), + mediaImageMaxHeight, + mediaImageMaxWidth + ); + binding.ivAnimatedMessage.setVisibility(View.VISIBLE); + final ViewGroup.LayoutParams layoutParams = binding.ivAnimatedMessage.getLayoutParams(); + final int width = widthHeight.first != null ? widthHeight.first : 0; + final int height = widthHeight.second != null ? widthHeight.second : 0; + layoutParams.width = width; + layoutParams.height = height; + binding.ivAnimatedMessage.requestLayout(); + binding.ivAnimatedMessage.setController(Fresco.newDraweeControllerBuilder() + .setUri(url) + .setAutoPlayAnimations(true) + .build()); + } + + @Override + public int getSwipeDirection() { + return ItemTouchHelper.ACTION_STATE_IDLE; + } +} diff --git a/app/src/main/java/awais/instagrabber/models/enums/DirectItemType.java b/app/src/main/java/awais/instagrabber/models/enums/DirectItemType.java index 58821f5c..83d655f2 100755 --- a/app/src/main/java/awais/instagrabber/models/enums/DirectItemType.java +++ b/app/src/main/java/awais/instagrabber/models/enums/DirectItemType.java @@ -1,7 +1,5 @@ package awais.instagrabber.models.enums; -import androidx.annotation.Nullable; - import com.google.gson.annotations.SerializedName; import java.io.Serializable; @@ -9,6 +7,7 @@ import java.util.HashMap; import java.util.Map; public enum DirectItemType implements Serializable { + UNKNOWN(0), @SerializedName("text") TEXT(1), @SerializedName("like") @@ -42,7 +41,9 @@ public enum DirectItemType implements Serializable { @SerializedName("felix_share") FELIX_SHARE(16), // media_share but igtv @SerializedName("location") - LOCATION(17); + LOCATION(17), + @SerializedName("xma") + XMA(18); // self avatar stickers private final int id; private static final Map map = new HashMap<>(); @@ -61,9 +62,8 @@ public enum DirectItemType implements Serializable { return id; } - @Nullable public static DirectItemType valueOf(final int id) { - if (!map.containsKey(id)) return null; + if (!map.containsKey(id)) return DirectItemType.UNKNOWN; return map.get(id); } diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectItem.java b/app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectItem.java index 1845c61a..52ad8818 100644 --- a/app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectItem.java +++ b/app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectItem.java @@ -41,6 +41,7 @@ public class DirectItem implements Cloneable, Serializable { private final DirectItem repliedToMessage; private final DirectItemVoiceMedia voiceMedia; private final Location location; + private final DirectItemXma xma; private final int hideInThread; private Date date; private boolean isPending; @@ -72,6 +73,7 @@ public class DirectItem implements Cloneable, Serializable { final DirectItem repliedToMessage, final DirectItemVoiceMedia voiceMedia, final Location location, + final DirectItemXma xma, final int hideInThread, final boolean showForwardAttribution) { this.itemId = itemId; @@ -99,6 +101,7 @@ public class DirectItem implements Cloneable, Serializable { this.repliedToMessage = repliedToMessage; this.voiceMedia = voiceMedia; this.location = location; + this.xma = xma; this.hideInThread = hideInThread; this.showForwardAttribution = showForwardAttribution; } @@ -208,6 +211,10 @@ public class DirectItem implements Cloneable, Serializable { return location; } + public DirectItemXma getXma() { + return xma; + } + public int getHideInThread() { return hideInThread; } @@ -286,6 +293,7 @@ public class DirectItem implements Cloneable, Serializable { Objects.equals(repliedToMessage, that.repliedToMessage) && Objects.equals(voiceMedia, that.voiceMedia) && Objects.equals(location, that.location) && + Objects.equals(xma, that.xma) && Objects.equals(date, that.date); } @@ -294,6 +302,6 @@ public class DirectItem implements Cloneable, Serializable { return Objects .hash(itemId, userId, timestamp, itemType, text, like, link, clientContext, reelShare, storyShare, mediaShare, profile, placeholder, media, previewMedias, actionLog, videoCallEvent, clip, felixShare, visualMedia, animatedMedia, reactions, repliedToMessage, - voiceMedia, location, hideInThread, date, isPending, showForwardAttribution); + voiceMedia, location, xma, hideInThread, date, isPending, showForwardAttribution); } } diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectItemXma.java b/app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectItemXma.java new file mode 100644 index 00000000..518e6efc --- /dev/null +++ b/app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectItemXma.java @@ -0,0 +1,104 @@ +package awais.instagrabber.repositories.responses.directmessages; + +import androidx.annotation.NonNull; + +import java.io.Serializable; +import java.util.Objects; + +public class DirectItemXma { + private final XmaUrlInfo previewUrlInfo; + private final XmaUrlInfo playableUrlInfo; + + public DirectItemXma(final XmaUrlInfo previewUrlInfo, final XmaUrlInfo playableUrlInfo) { + this.previewUrlInfo = previewUrlInfo; + this.playableUrlInfo = playableUrlInfo; + } + + public XmaUrlInfo getPreviewUrlInfo() { + return previewUrlInfo; + } + + public XmaUrlInfo getPlayableUrlInfo() { + return playableUrlInfo; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final DirectItemXma that = (DirectItemXma) o; + return Objects.equals(previewUrlInfo, that.previewUrlInfo) && + Objects.equals(playableUrlInfo, that.playableUrlInfo); + } + + @Override + public int hashCode() { + return Objects.hash(previewUrlInfo, playableUrlInfo); + } + + @NonNull + @Override + public String toString() { + return "DirectItemXma{" + + "previewUrlInfo=" + previewUrlInfo + + ", playableUrlInfo=" + playableUrlInfo + + '}'; + } + + public static class XmaUrlInfo implements Serializable { + private final String url; + private final long urlExpirationTimestampUs; + private final int width; + private final int height; + + public XmaUrlInfo(final String url, final long urlExpirationTimestampUs, final int width, final int height) { + this.url = url; + this.urlExpirationTimestampUs = urlExpirationTimestampUs; + this.width = width; + this.height = height; + } + + public String getUrl() { + return url; + } + + public long getUrlExpirationTimestampUs() { + return urlExpirationTimestampUs; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final XmaUrlInfo that = (XmaUrlInfo) o; + return urlExpirationTimestampUs == that.urlExpirationTimestampUs && + width == that.width && + height == that.height && + Objects.equals(url, that.url); + } + + @Override + public int hashCode() { + return Objects.hash(url, urlExpirationTimestampUs, width, height); + } + + @NonNull + @Override + public String toString() { + return "XmaUrlInfo{" + + "url='" + url + '\'' + + ", urlExpirationTimestampUs=" + urlExpirationTimestampUs + + ", width=" + width + + ", height=" + height + + '}'; + } + } +} diff --git a/app/src/main/java/awais/instagrabber/utils/DMUtils.java b/app/src/main/java/awais/instagrabber/utils/DMUtils.java index 674e8722..12aa2e07 100644 --- a/app/src/main/java/awais/instagrabber/utils/DMUtils.java +++ b/app/src/main/java/awais/instagrabber/utils/DMUtils.java @@ -44,9 +44,9 @@ public final class DMUtils { public static boolean isRead(@NonNull final DirectThread thread) { final boolean read; -// if (thread.getDirectStory() != null) { -// return false; -// } + // if (thread.getDirectStory() != null) { + // return false; + // } final DirectItem item = thread.getFirstDirectItem(); final long viewerId = thread.getViewerId(); if (item != null && item.getUserId() == viewerId) { @@ -188,6 +188,9 @@ public final class DMUtils { break; } break; + case XMA: + subtitle = resources.getString(R.string.dms_inbox_shared_sticker, username != null ? username : ""); + break; default: message = resources.getString(R.string.dms_inbox_raven_message_unknown); } @@ -213,7 +216,14 @@ public final class DMUtils { .filter(Objects::nonNull) .filter(user -> user.getPk() == userId) .findFirst(); - return senderOptional.map(User::getUsername).orElse(null); + return senderOptional.map(user -> { + // return full name for fb users + final String username = user.getUsername(); + if (TextUtils.isEmpty(username)) { + return user.getFullName(); + } + return username; + }).orElse(null); } public static String getMediaSpecificSubtitle(final String username, final Resources resources, final MediaItemType mediaType) { diff --git a/app/src/main/java/awais/instagrabber/utils/DirectItemFactory.java b/app/src/main/java/awais/instagrabber/utils/DirectItemFactory.java index 85e6f9ae..3ef9ddee 100644 --- a/app/src/main/java/awais/instagrabber/utils/DirectItemFactory.java +++ b/app/src/main/java/awais/instagrabber/utils/DirectItemFactory.java @@ -51,6 +51,7 @@ public final class DirectItemFactory { repliedToMessage, null, null, + null, 0, false); } @@ -132,6 +133,7 @@ public final class DirectItemFactory { null, null, null, + null, 0, false); } @@ -213,6 +215,7 @@ public final class DirectItemFactory { null, voiceMedia, null, + null, 0, false); } @@ -253,6 +256,7 @@ public final class DirectItemFactory { null, null, null, + null, 0, false ); From 783acf417467bc74be88a8d5e2aa3737501df110 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Tue, 30 Mar 2021 21:27:15 +0900 Subject: [PATCH 08/13] Move dm unseen count observer to main activity. Fixes https://github.com/austinhuang0131/barinsta/issues/873 --- .../instagrabber/activities/MainActivity.java | 28 +++++++++++++++ .../DirectMessageInboxFragment.java | 36 ++----------------- .../DirectMessageSettingsFragment.java | 12 ++++--- .../DirectMessageThreadFragment.java | 12 ++++--- .../DirectPendingInboxFragment.java | 7 +--- 5 files changed, 46 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/awais/instagrabber/activities/MainActivity.java b/app/src/main/java/awais/instagrabber/activities/MainActivity.java index 408a841a..23a9929f 100644 --- a/app/src/main/java/awais/instagrabber/activities/MainActivity.java +++ b/app/src/main/java/awais/instagrabber/activities/MainActivity.java @@ -47,6 +47,7 @@ import androidx.navigation.ui.NavigationUI; import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.CollapsingToolbarLayout; +import com.google.android.material.badge.BadgeDrawable; import com.google.android.material.behavior.HideBottomViewOnScrollBehavior; import com.google.android.material.bottomnavigation.BottomNavigationView; @@ -82,6 +83,7 @@ import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.emoji.EmojiParser; import awais.instagrabber.viewmodels.AppStateViewModel; +import awais.instagrabber.viewmodels.DirectInboxViewModel; import awais.instagrabber.webservices.SearchService; import retrofit2.Call; import retrofit2.Callback; @@ -181,6 +183,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage initEmojiCompat(); searchService = SearchService.getInstance(); // initDmService(); + initDmUnreadCount(); } private void initDmService() { @@ -190,6 +193,16 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage DMSyncAlarmReceiver.setAlarm(this); } + private void initDmUnreadCount() { + if (!isLoggedIn) return; + final DirectInboxViewModel directInboxViewModel = new ViewModelProvider(this).get(DirectInboxViewModel.class); + directInboxViewModel.getUnseenCount().observe(this, unseenCountResource -> { + if (unseenCountResource == null) return; + final Integer unseenCount = unseenCountResource.data; + setNavBarDMUnreadCountBadge(unseenCount == null ? 0 : unseenCount); + }); + } + @Override public boolean onCreateOptionsMenu(final Menu menu) { getMenuInflater().inflate(R.menu.main_menu, menu); @@ -850,4 +863,19 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage public Toolbar getToolbar() { return binding.toolbar; } + + private void setNavBarDMUnreadCountBadge(final int unseenCount) { + final BadgeDrawable badge = binding.bottomNavView.getOrCreateBadge(R.id.direct_messages_nav_graph); + if (badge == null) return; + if (unseenCount == 0) { + badge.setVisible(false); + badge.clearNumber(); + return; + } + if (badge.getVerticalOffset() != 10) { + badge.setVerticalOffset(10); + } + badge.setNumber(unseenCount); + badge.setVisible(true); + } } \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java index 34d4ed1c..bf13abb6 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java @@ -20,8 +20,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.fragment.app.Fragment; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; -import androidx.lifecycle.ViewModelStoreOwner; -import androidx.navigation.NavController; import androidx.navigation.NavDirections; import androidx.navigation.fragment.NavHostFragment; import androidx.recyclerview.widget.LinearLayoutManager; @@ -29,7 +27,6 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.google.android.material.badge.BadgeDrawable; import com.google.android.material.badge.BadgeUtils; -import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.snackbar.Snackbar; import java.util.List; @@ -66,9 +63,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh super.onCreate(savedInstanceState); fragmentActivity = (MainActivity) getActivity(); if (fragmentActivity != null) { - final NavController navController = NavHostFragment.findNavController(this); - final ViewModelStoreOwner viewModelStoreOwner = navController.getViewModelStoreOwner(R.id.direct_messages_nav_graph); - viewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectInboxViewModel.class); + viewModel = new ViewModelProvider(fragmentActivity).get(DirectInboxViewModel.class); } setHasOptionsMenu(true); } @@ -101,6 +96,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh } } + @SuppressLint("UnsafeExperimentalUsageError") @Override public void onPause() { super.onPause(); @@ -201,11 +197,6 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh break; } }); - viewModel.getUnseenCount().observe(getViewLifecycleOwner(), unseenCountResource -> { - if (unseenCountResource == null) return; - final Integer unseenCount = unseenCountResource.data; - setBottomNavBarBadge(unseenCount == null ? 0 : unseenCount); - }); viewModel.getPendingRequestsTotal().observe(getViewLifecycleOwner(), this::attachPendingRequestsBadge); } @@ -213,12 +204,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh private void attachPendingRequestsBadge(@Nullable final Integer count) { if (pendingRequestsMenuItem == null) { final Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override - public void run() { - attachPendingRequestsBadge(count); - } - }, 500); + handler.postDelayed(() -> attachPendingRequestsBadge(count), 500); return; } if (pendingRequestTotalBadgeDrawable == null) { @@ -277,20 +263,4 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh }); binding.inboxList.addOnScrollListener(lazyLoader); } - - private void setBottomNavBarBadge(final int unseenCount) { - final BottomNavigationView bottomNavView = fragmentActivity.getBottomNavView(); - final BadgeDrawable badge = bottomNavView.getOrCreateBadge(R.id.direct_messages_nav_graph); - if (badge == null) return; - if (unseenCount == 0) { - badge.setVisible(false); - badge.clearNumber(); - return; - } - if (badge.getVerticalOffset() != 10) { - badge.setVerticalOffset(10); - } - badge.setNumber(unseenCount); - badge.setVisible(true); - } } diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java index a960cd36..fe36cdbf 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java @@ -79,11 +79,13 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi final DirectMessageSettingsFragmentArgs args = DirectMessageSettingsFragmentArgs.fromBundle(arguments); final MainActivity fragmentActivity = (MainActivity) requireActivity(); final AppStateViewModel appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class); - viewModel = new ViewModelProvider(this, new DirectSettingsViewModelFactory(fragmentActivity.getApplication(), - args.getThreadId(), - args.getPending(), - appStateViewModel.getCurrentUser())) - .get(DirectSettingsViewModel.class); + final DirectSettingsViewModelFactory viewModelFactory = new DirectSettingsViewModelFactory( + fragmentActivity.getApplication(), + args.getThreadId(), + args.getPending(), + appStateViewModel.getCurrentUser() + ); + viewModel = new ViewModelProvider(fragmentActivity, viewModelFactory).get(DirectSettingsViewModel.class); } @NonNull diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java index acb1dcde..1c7f3dde 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java @@ -329,11 +329,13 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact final Bundle arguments = getArguments(); if (arguments == null) return; final DirectMessageThreadFragmentArgs fragmentArgs = DirectMessageThreadFragmentArgs.fromBundle(arguments); - viewModel = new ViewModelProvider(this, new DirectThreadViewModelFactory(fragmentActivity.getApplication(), - fragmentArgs.getThreadId(), - fragmentArgs.getPending(), - appStateViewModel.getCurrentUser())) - .get(DirectThreadViewModel.class); + final DirectThreadViewModelFactory viewModelFactory = new DirectThreadViewModelFactory( + fragmentActivity.getApplication(), + fragmentArgs.getThreadId(), + fragmentArgs.getPending(), + appStateViewModel.getCurrentUser() + ); + viewModel = new ViewModelProvider(fragmentActivity, viewModelFactory).get(DirectThreadViewModel.class); setHasOptionsMenu(true); } diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectPendingInboxFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectPendingInboxFragment.java index 8ee0d1c4..bf459ef1 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectPendingInboxFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectPendingInboxFragment.java @@ -13,8 +13,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.fragment.app.Fragment; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; -import androidx.lifecycle.ViewModelStoreOwner; -import androidx.navigation.NavController; import androidx.navigation.fragment.NavHostFragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; @@ -24,7 +22,6 @@ import com.google.android.material.snackbar.Snackbar; import java.util.Collections; import java.util.List; -import awais.instagrabber.R; import awais.instagrabber.activities.MainActivity; import awais.instagrabber.adapters.DirectMessageInboxAdapter; import awais.instagrabber.customviews.helpers.RecyclerLazyLoaderAtEdge; @@ -51,9 +48,7 @@ public class DirectPendingInboxFragment extends Fragment implements SwipeRefresh super.onCreate(savedInstanceState); fragmentActivity = (MainActivity) getActivity(); if (fragmentActivity != null) { - final NavController navController = NavHostFragment.findNavController(this); - final ViewModelStoreOwner viewModelStoreOwner = navController.getViewModelStoreOwner(R.id.direct_messages_nav_graph); - viewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectPendingInboxViewModel.class); + viewModel = new ViewModelProvider(fragmentActivity).get(DirectPendingInboxViewModel.class); } } From 38bd1c9cbda1262a5d9c56aff874595090dd99d0 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Tue, 30 Mar 2021 22:08:24 +0900 Subject: [PATCH 09/13] Refactor giphy and voice options to their own viewholder, fix download when permission requested. --- .../adapters/DirectItemsAdapter.java | 3 +- .../DirectItemAnimatedMediaViewHolder.java | 16 +++++ .../directmessages/DirectItemViewHolder.java | 11 +--- .../DirectItemVoiceMediaViewHolder.java | 9 +++ .../customviews/DirectItemContextMenu.java | 20 ++++++- .../DirectMessageSettingsFragment.java | 2 +- .../DirectMessageThreadFragment.java | 59 +++++++++++-------- 7 files changed, 83 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java b/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java index e1469ac5..2b1f410e 100644 --- a/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java +++ b/app/src/main/java/awais/instagrabber/adapters/DirectItemsAdapter.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Objects; +import java.util.function.Function; import awais.instagrabber.adapters.viewholder.directmessages.DirectItemActionLogViewHolder; import awais.instagrabber.adapters.viewholder.directmessages.DirectItemAnimatedMediaViewHolder; @@ -404,7 +405,7 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter callback); } public interface DirectItemInternalLongClickListener { diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemAnimatedMediaViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemAnimatedMediaViewHolder.java index c08bb1d9..7bc5d173 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemAnimatedMediaViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemAnimatedMediaViewHolder.java @@ -8,8 +8,13 @@ import androidx.core.util.Pair; import androidx.recyclerview.widget.ItemTouchHelper; import com.facebook.drawee.backends.pipeline.Fresco; +import com.google.common.collect.ImmutableList; +import java.util.List; + +import awais.instagrabber.R; import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback; +import awais.instagrabber.customviews.DirectItemContextMenu; import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding; import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.repositories.responses.AnimatedMediaFixedHeight; @@ -19,6 +24,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectItem; import awais.instagrabber.repositories.responses.directmessages.DirectItemAnimatedMedia; import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.utils.NumberUtils; +import awais.instagrabber.utils.Utils; public class DirectItemAnimatedMediaViewHolder extends DirectItemViewHolder { @@ -65,4 +71,14 @@ public class DirectItemAnimatedMediaViewHolder extends DirectItemViewHolder { public int getSwipeDirection() { return ItemTouchHelper.ACTION_STATE_IDLE; } + + @Override + protected List getLongClickOptions() { + return ImmutableList.of( + new DirectItemContextMenu.MenuItem(R.id.detail, R.string.dms_inbox_giphy, item -> { + Utils.openURL(itemView.getContext(), "https://giphy.com/gifs/" + item.getAnimatedMedia().getId()); + return null; + }) + ); + } } diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemViewHolder.java index 15814b3c..96476b10 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemViewHolder.java @@ -543,22 +543,13 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder imple if (thread.getInputMode() != 1 && messageDirection == MessageDirection.OUTGOING) { builder.add(new DirectItemContextMenu.MenuItem(R.id.unsend, R.string.dms_inbox_unsend)); } - final DirectItemType itemType = item.getItemType(); - switch (itemType) { - case ANIMATED_MEDIA: - builder.add(new DirectItemContextMenu.MenuItem(R.id.detail, R.string.dms_inbox_giphy)); - break; - case VOICE_MEDIA: - builder.add(new DirectItemContextMenu.MenuItem(R.id.detail, R.string.action_download)); - break; - } final boolean showReactions = thread.getInputMode() != 1 && allowReaction(); final ImmutableList menuItems = builder.build(); if (!showReactions && menuItems.isEmpty()) return; final DirectItemContextMenu menu = new DirectItemContextMenu(itemView.getContext(), showReactions, menuItems); menu.setOnDismissListener(() -> setSelected(false)); menu.setOnReactionClickListener(emoji -> callback.onReaction(item, emoji)); - menu.setOnOptionSelectListener(itemId -> callback.onOptionSelect(item, itemId)); + menu.setOnOptionSelectListener((itemId, cb) -> callback.onOptionSelect(item, itemId, cb)); menu.show(itemView, location); } diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemVoiceMediaViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemVoiceMediaViewHolder.java index 13399b06..255cceae 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemVoiceMediaViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemVoiceMediaViewHolder.java @@ -12,12 +12,14 @@ import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; +import com.google.common.collect.ImmutableList; import com.google.common.primitives.Floats; import java.util.List; import awais.instagrabber.R; import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback; +import awais.instagrabber.customviews.DirectItemContextMenu; import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmVoiceMediaBinding; import awais.instagrabber.repositories.responses.Audio; @@ -174,6 +176,13 @@ public class DirectItemVoiceMediaViewHolder extends DirectItemViewHolder { return false; } + @Override + protected List getLongClickOptions() { + return ImmutableList.of( + new DirectItemContextMenu.MenuItem(R.id.download, R.string.action_download) + ); + } + private static class AudioItemState { private boolean prepared; diff --git a/app/src/main/java/awais/instagrabber/customviews/DirectItemContextMenu.java b/app/src/main/java/awais/instagrabber/customviews/DirectItemContextMenu.java index f615b7fc..65a18141 100644 --- a/app/src/main/java/awais/instagrabber/customviews/DirectItemContextMenu.java +++ b/app/src/main/java/awais/instagrabber/customviews/DirectItemContextMenu.java @@ -29,12 +29,14 @@ import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.util.Pair; import java.util.List; +import java.util.function.Function; import awais.instagrabber.R; import awais.instagrabber.animations.RoundedRectRevealOutlineProvider; import awais.instagrabber.customviews.emoji.Emoji; import awais.instagrabber.customviews.emoji.ReactionsManager; import awais.instagrabber.databinding.LayoutDirectItemOptionsBinding; +import awais.instagrabber.repositories.responses.directmessages.DirectItem; import static android.view.View.MeasureSpec.makeMeasureSpec; @@ -345,7 +347,7 @@ public class DirectItemContextMenu extends PopupWindow { textView.setText(context.getString(menuItem.getTitleRes())); textView.setOnClickListener(v -> { if (onOptionSelectListener != null) { - onOptionSelectListener.onSelect(menuItem.getItemId()); + onOptionSelectListener.onSelect(menuItem.getItemId(), menuItem.getCallback()); } dismiss(); }); @@ -397,9 +399,19 @@ public class DirectItemContextMenu extends PopupWindow { @StringRes private final int titleRes; + /** + * Callback function + */ + private final Function callback; + public MenuItem(@IdRes final int itemId, @StringRes final int titleRes) { + this(itemId, titleRes, null); + } + + public MenuItem(@IdRes final int itemId, @StringRes final int titleRes, @Nullable final Function callback) { this.itemId = itemId; this.titleRes = titleRes; + this.callback = callback; } public int getItemId() { @@ -409,10 +421,14 @@ public class DirectItemContextMenu extends PopupWindow { public int getTitleRes() { return titleRes; } + + public Function getCallback() { + return callback; + } } public interface OnOptionSelectListener { - void onSelect(int itemId); + void onSelect(int itemId, @Nullable Function callback); } public interface OnReactionClickListener { diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java index fe36cdbf..f98e4094 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java @@ -85,7 +85,7 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi args.getPending(), appStateViewModel.getCurrentUser() ); - viewModel = new ViewModelProvider(fragmentActivity, viewModelFactory).get(DirectSettingsViewModel.class); + viewModel = new ViewModelProvider(this, viewModelFactory).get(DirectSettingsViewModel.class); } @NonNull diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java index 1c7f3dde..a6b1cb4c 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java @@ -58,6 +58,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.function.Function; import awais.instagrabber.ProfileNavGraphDirections; import awais.instagrabber.R; @@ -258,7 +259,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact } @Override - public void onOptionSelect(final DirectItem item, final int itemId) { + public void onOptionSelect(final DirectItem item, final int itemId, final Function cb) { if (itemId == R.id.unsend) { handleSentMessage(viewModel.unsend(item)); return; @@ -275,21 +276,17 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact final NavController navController = NavHostFragment.findNavController(DirectMessageThreadFragment.this); navController.navigate(actionGlobalUserSearch); } - if (itemId == R.id.detail) { - final Context context = getContext(); - if (context == null) return; - final DirectItemType itemType = item.getItemType(); - switch (itemType) { - case ANIMATED_MEDIA: - Utils.openURL(context, "https://giphy.com/gifs/" + item.getAnimatedMedia().getId()); - break; - case VOICE_MEDIA: - downloadItem(item.getVoiceMedia() == null ? null : item.getVoiceMedia().getMedia(), context); - break; - } + if (itemId == R.id.download) { + downloadItem(item); + return; + } + // otherwise call callback if present + if (cb != null) { + cb.apply(item); } } }; + private final DirectItemLongClickListener directItemLongClickListener = position -> { // viewModel.setSelectedPosition(position); }; @@ -319,6 +316,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact }; private final MutableLiveData inputLength = new MutableLiveData<>(0); private MenuItem markAsSeenMenuItem; + private Media tempMedia; @Override public void onCreate(@Nullable final Bundle savedInstanceState) { @@ -335,7 +333,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact fragmentArgs.getPending(), appStateViewModel.getCurrentUser() ); - viewModel = new ViewModelProvider(fragmentActivity, viewModelFactory).get(DirectThreadViewModel.class); + viewModel = new ViewModelProvider(this, viewModelFactory).get(DirectThreadViewModel.class); setHasOptionsMenu(true); } @@ -456,7 +454,9 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact final Context context = getContext(); if (context == null) return; if (requestCode == STORAGE_PERM_REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - // downloadItem(context); + if (tempMedia == null) return; + downloadItem(context, tempMedia); + return; } if (requestCode == AUDIO_RECORD_PERM_REQUEST_CODE) { if (PermissionUtils.hasAudioRecordPerms(context)) { @@ -1319,18 +1319,31 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact appExecutors.mainThread().execute(prevTitleRunnable, 1000); } + private void downloadItem(final DirectItem item) { + final Context context = getContext(); + if (context == null) return; + final DirectItemType itemType = item.getItemType(); + //noinspection SwitchStatementWithTooFewBranches + switch (itemType) { + case VOICE_MEDIA: + downloadItem(context, item.getVoiceMedia() == null ? null : item.getVoiceMedia().getMedia()); + break; + } + } + // currently ONLY for voice - private void downloadItem(final Media media, final Context context) { + private void downloadItem(@NonNull final Context context, final Media media) { if (media == null) { Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); - } else { - if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) { - DownloadUtils.download(context, media); - } else { - requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); - } - Toast.makeText(context, R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show(); + return; } + if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) { + DownloadUtils.download(context, media); + Toast.makeText(context, R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show(); + return; + } + tempMedia = media; + requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); } @NonNull From 9cc019d2ae3522cab268f5ce6deee74887848b84 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Tue, 30 Mar 2021 22:32:05 +0900 Subject: [PATCH 10/13] Add copy options in dm --- .../DirectItemLinkViewHolder.java | 19 ++++++++++++++ .../DirectItemMediaShareViewHolder.java | 19 +++++++++++++- .../DirectItemReelShareViewHolder.java | 25 +++++++++++++++++-- .../DirectItemTextViewHolder.java | 19 ++++++++++++++ app/src/main/res/values/ids.xml | 1 + app/src/main/res/values/strings.xml | 2 ++ 6 files changed, 82 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemLinkViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemLinkViewHolder.java index 2129cc2b..98c9fb14 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemLinkViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemLinkViewHolder.java @@ -5,7 +5,13 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +import awais.instagrabber.R; import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback; +import awais.instagrabber.customviews.DirectItemContextMenu; import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmLinkBinding; import awais.instagrabber.repositories.responses.User; @@ -14,6 +20,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectItemLink; import awais.instagrabber.repositories.responses.directmessages.DirectItemLinkContext; import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.utils.TextUtils; +import awais.instagrabber.utils.Utils; public class DirectItemLinkViewHolder extends DirectItemViewHolder { @@ -80,4 +87,16 @@ public class DirectItemLinkViewHolder extends DirectItemViewHolder { protected boolean showBackground() { return true; } + + @Override + protected List getLongClickOptions() { + return ImmutableList.of( + new DirectItemContextMenu.MenuItem(R.id.copy, R.string.copy, item -> { + final DirectItemLink link = item.getLink(); + if (link == null || TextUtils.isEmpty(link.getText())) return null; + Utils.copyText(itemView.getContext(), link.getText()); + return null; + }) + ); + } } diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemMediaShareViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemMediaShareViewHolder.java index 8874e818..dddd9315 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemMediaShareViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemMediaShareViewHolder.java @@ -12,11 +12,14 @@ import androidx.recyclerview.widget.ItemTouchHelper; import com.facebook.drawee.drawable.ScalingUtils; import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; import com.facebook.drawee.generic.RoundingParams; +import com.google.common.collect.ImmutableList; +import java.util.List; import java.util.Objects; import awais.instagrabber.R; import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback; +import awais.instagrabber.customviews.DirectItemContextMenu; import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmMediaShareBinding; import awais.instagrabber.models.enums.DirectItemType; @@ -30,6 +33,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectItemFelixS import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.utils.NumberUtils; import awais.instagrabber.utils.ResponseBodyUtils; +import awais.instagrabber.utils.Utils; public class DirectItemMediaShareViewHolder extends DirectItemViewHolder { private static final String TAG = DirectItemMediaShareViewHolder.class.getSimpleName(); @@ -38,6 +42,7 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder { private final RoundingParams incomingRoundingParams; private final RoundingParams outgoingRoundingParams; private DirectItemType itemType; + private Caption caption; public DirectItemMediaShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding, @NonNull final LayoutDmMediaShareBinding binding, @@ -113,7 +118,7 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder { } private void setupCaption(@NonNull final Media media) { - final Caption caption = media.getCaption(); + caption = media.getCaption(); if (caption != null) { binding.caption.setVisibility(View.VISIBLE); binding.caption.setText(caption.getText()); @@ -177,4 +182,16 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder { } return super.getSwipeDirection(); } + + @Override + protected List getLongClickOptions() { + final ImmutableList.Builder builder = ImmutableList.builder(); + if (caption != null && !TextUtils.isEmpty(caption.getText())) { + builder.add(new DirectItemContextMenu.MenuItem(R.id.copy, R.string.copy_caption, item -> { + Utils.copyText(itemView.getContext(), caption.getText()); + return null; + })); + } + return builder.build(); + } } diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemReelShareViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemReelShareViewHolder.java index bb139332..aa1666ab 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemReelShareViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemReelShareViewHolder.java @@ -8,13 +8,16 @@ import androidx.constraintlayout.widget.ConstraintLayout; import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; import com.facebook.drawee.generic.RoundingParams; +import com.google.common.collect.ImmutableList; + +import java.util.List; import awais.instagrabber.R; import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback; +import awais.instagrabber.customviews.DirectItemContextMenu; import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmReelShareBinding; import awais.instagrabber.models.enums.MediaItemType; -import awais.instagrabber.repositories.responses.ImageVersions2; import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.directmessages.DirectItem; @@ -22,10 +25,12 @@ import awais.instagrabber.repositories.responses.directmessages.DirectItemReelSh import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.utils.ResponseBodyUtils; import awais.instagrabber.utils.TextUtils; +import awais.instagrabber.utils.Utils; public class DirectItemReelShareViewHolder extends DirectItemViewHolder { private final LayoutDmReelShareBinding binding; + private String type; public DirectItemReelShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding, @NonNull final LayoutDmReelShareBinding binding, @@ -40,7 +45,7 @@ public class DirectItemReelShareViewHolder extends DirectItemViewHolder { @Override public void bindItem(final DirectItem item, final MessageDirection messageDirection) { final DirectItemReelShare reelShare = item.getReelShare(); - final String type = reelShare.getType(); + type = reelShare.getType(); if (type == null) return; final boolean isSelf = isSelf(item); final Media media = reelShare.getMedia(); @@ -170,4 +175,20 @@ public class DirectItemReelShareViewHolder extends DirectItemViewHolder { protected boolean canForward() { return false; } + + @Override + protected List getLongClickOptions() { + final ImmutableList.Builder builder = ImmutableList.builder(); + if (type != null && type.equals("reply")) { + builder.add(new DirectItemContextMenu.MenuItem(R.id.copy, R.string.copy_reply, item -> { + final DirectItemReelShare reelShare = item.getReelShare(); + if (reelShare == null) return null; + final String text = reelShare.getText(); + if (TextUtils.isEmpty(text)) return null; + Utils.copyText(itemView.getContext(), text); + return null; + })); + } + return builder.build(); + } } diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemTextViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemTextViewHolder.java index b0eaa779..d95817ea 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemTextViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemTextViewHolder.java @@ -2,12 +2,20 @@ package awais.instagrabber.adapters.viewholder.directmessages; import androidx.annotation.NonNull; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +import awais.instagrabber.R; import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback; +import awais.instagrabber.customviews.DirectItemContextMenu; import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmTextBinding; import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.directmessages.DirectItem; import awais.instagrabber.repositories.responses.directmessages.DirectThread; +import awais.instagrabber.utils.TextUtils; +import awais.instagrabber.utils.Utils; public class DirectItemTextViewHolder extends DirectItemViewHolder { @@ -35,4 +43,15 @@ public class DirectItemTextViewHolder extends DirectItemViewHolder { protected boolean showBackground() { return true; } + + @Override + protected List getLongClickOptions() { + return ImmutableList.of( + new DirectItemContextMenu.MenuItem(R.id.copy, R.string.copy, item -> { + if (TextUtils.isEmpty(item.getText())) return null; + Utils.copyText(itemView.getContext(), item.getText()); + return null; + }) + ); + } } diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml index 7319700f..8f77fc7f 100644 --- a/app/src/main/res/values/ids.xml +++ b/app/src/main/res/values/ids.xml @@ -4,4 +4,5 @@ + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 40838c81..d3b7cf2b 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -475,4 +475,6 @@ Delete unsuccessful Barinsta Crash Report Select an email app to send crash logs + Copy caption + Copy reply From cbb7b8654ae20c2e45e546dede8643997d65e6e1 Mon Sep 17 00:00:00 2001 From: Austin Huang Date: Tue, 30 Mar 2021 12:23:32 -0400 Subject: [PATCH 11/13] Update NotificationsPreferencesFragment.java --- .../fragments/settings/NotificationsPreferencesFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/awais/instagrabber/fragments/settings/NotificationsPreferencesFragment.java b/app/src/main/java/awais/instagrabber/fragments/settings/NotificationsPreferencesFragment.java index 72f69f79..50d284e7 100644 --- a/app/src/main/java/awais/instagrabber/fragments/settings/NotificationsPreferencesFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/settings/NotificationsPreferencesFragment.java @@ -15,7 +15,7 @@ public class NotificationsPreferencesFragment extends BasePreferencesFragment { final Context context = getContext(); if (context == null) return; screen.addPreference(getActivityNotificationsPreference(context)); - screen.addPreference(getDMNotificationsPreference(context)); + // screen.addPreference(getDMNotificationsPreference(context)); } private Preference getActivityNotificationsPreference(@NonNull final Context context) { From 666a36ff2070b6ee0dae4da56a50560583a4eefc Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Wed, 31 Mar 2021 21:43:20 +0900 Subject: [PATCH 12/13] Fix crash when fetching self profile info is slow --- .../fragments/main/ProfileFragment.java | 51 ++++++++++--------- .../viewmodels/AppStateViewModel.java | 15 ++++-- 2 files changed, 39 insertions(+), 27 deletions(-) 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 4b3bfcfd..c0998f13 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java @@ -12,7 +12,6 @@ import android.text.style.RelativeSizeSpan; import android.text.style.StyleSpan; import android.util.Log; import android.view.ActionMode; -import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -604,12 +603,16 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe usernameTemp = usernameTemp.substring(1); } if (TextUtils.isEmpty(usernameTemp)) { - profileModel = appStateViewModel.getCurrentUser(); - username = profileModel.getUsername(); - setUsernameDelayed(); - setProfileDetails(); + appStateViewModel.getCurrentUserLiveData().observe(getViewLifecycleOwner(), user -> { + if (user == null) return; + profileModel = user; + username = profileModel.getUsername(); + setUsernameDelayed(); + setProfileDetails(); + }); + return; } - else if (isLoggedIn) { + if (isLoggedIn) { userService.getUsernameInfo(usernameTemp, new ServiceCallback() { @Override public void onSuccess(final User user) { @@ -643,26 +646,25 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe } catch (final Throwable ignored) {} } }); + return; } - else { - graphQLService.fetchUser(usernameTemp, new ServiceCallback() { - @Override - public void onSuccess(final User user) { - profileModel = user; - setProfileDetails(); - } + graphQLService.fetchUser(usernameTemp, new ServiceCallback() { + @Override + public void onSuccess(final User user) { + 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, R.string.error_loading_profile, Toast.LENGTH_LONG).show(); - else Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); - } catch (final Throwable ignored) {} - } - }); - } + @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, R.string.error_loading_profile, Toast.LENGTH_LONG).show(); + else Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); + } catch (final Throwable ignored) {} + } + }); } private void setProfileDetails() { @@ -987,6 +989,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe } private void updateAccountInfo() { + if (profileModel == null) return; accountRepository.insertOrUpdateAccount( profileModel.getPk(), profileModel.getUsername(), diff --git a/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java index dcea12ed..ab1cbabb 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java @@ -1,9 +1,12 @@ package awais.instagrabber.viewmodels; import android.app.Application; +import android.util.Log; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; import awais.instagrabber.db.datasources.AccountDataSource; import awais.instagrabber.db.repositories.AccountRepository; @@ -21,8 +24,8 @@ public class AppStateViewModel extends AndroidViewModel { private final String cookie; private final boolean isLoggedIn; + private final MutableLiveData currentUser = new MutableLiveData<>(); - private User currentUser; private AccountRepository accountRepository; private UserService userService; @@ -38,6 +41,10 @@ public class AppStateViewModel extends AndroidViewModel { } public User getCurrentUser() { + return currentUser.getValue(); + } + + public LiveData getCurrentUserLiveData() { return currentUser; } @@ -46,11 +53,13 @@ public class AppStateViewModel extends AndroidViewModel { userService.getUserInfo(uid, new ServiceCallback() { @Override public void onSuccess(final User user) { - currentUser = user; + currentUser.postValue(user); } @Override - public void onFailure(final Throwable t) {} + public void onFailure(final Throwable t) { + Log.e(TAG, "onFailure: ", t); + } }); } } From 2074045a19aee104360ed435cba91b964fece8b2 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 31 Mar 2021 17:37:25 +0000 Subject: [PATCH 13/13] Update dependency com.google.android.material:material to v1.4.0-alpha02 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 9b39a1a2..f6096214 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,7 +105,7 @@ dependencies { def nav_version = '2.3.4' def exoplayer_version = '2.13.2' - implementation 'com.google.android.material:material:1.4.0-alpha01' + implementation 'com.google.android.material:material:1.4.0-alpha02' implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version" implementation "com.google.android.exoplayer:exoplayer-dash:$exoplayer_version"