mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-30 19:15:35 +00:00 
			
		
		
		
	Merge branch 'master' into retrofit-intercept-errors
This commit is contained in:
		
						commit
						a3b3c54609
					
				| @ -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" | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
| @ -83,6 +84,7 @@ import awais.instagrabber.utils.Utils; | ||||
| import awais.instagrabber.utils.emoji.EmojiParser; | ||||
| import awais.instagrabber.viewmodels.AppStateViewModel; | ||||
| import awais.instagrabber.webservices.RetrofitFactory; | ||||
| import awais.instagrabber.viewmodels.DirectInboxViewModel; | ||||
| import awais.instagrabber.webservices.SearchService; | ||||
| import retrofit2.Call; | ||||
| import retrofit2.Callback; | ||||
| @ -183,6 +185,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage | ||||
|         initEmojiCompat(); | ||||
|         searchService = SearchService.getInstance(); | ||||
|         // initDmService(); | ||||
|         initDmUnreadCount(); | ||||
|     } | ||||
| 
 | ||||
|     private void initDmService() { | ||||
| @ -192,6 +195,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); | ||||
| @ -857,4 +870,19 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage | ||||
|     public View getRootView() { | ||||
|         return binding.getRoot(); | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
|     } | ||||
| } | ||||
| @ -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<RecyclerView. | ||||
| 
 | ||||
|         void onReactionClick(DirectItem item, int position); | ||||
| 
 | ||||
|         void onOptionSelect(DirectItem item, @IdRes int itemId); | ||||
|         void onOptionSelect(DirectItem item, @IdRes int itemId, final Function<DirectItem, Void> callback); | ||||
|     } | ||||
| 
 | ||||
|     public interface DirectItemInternalLongClickListener { | ||||
|  | ||||
| @ -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<DirectItemContextMenu.MenuItem> 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; | ||||
|                 }) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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<DirectItemContextMenu.MenuItem> 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; | ||||
|                 }) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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<DirectItemContextMenu.MenuItem> getLongClickOptions() { | ||||
|         final ImmutableList.Builder<DirectItemContextMenu.MenuItem> 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(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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<DirectItemContextMenu.MenuItem> getLongClickOptions() { | ||||
|         final ImmutableList.Builder<DirectItemContextMenu.MenuItem> 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(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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<DirectItemContextMenu.MenuItem> 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; | ||||
|                 }) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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<DirectItemContextMenu.MenuItem> 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); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -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<DirectItemContextMenu.MenuItem> getLongClickOptions() { | ||||
|         return ImmutableList.of( | ||||
|                 new DirectItemContextMenu.MenuItem(R.id.download, R.string.action_download) | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     private static class AudioItemState { | ||||
|         private boolean prepared; | ||||
| 
 | ||||
|  | ||||
| @ -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<DirectItem, Void> 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<DirectItem, Void> 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<DirectItem, Void> getCallback() { | ||||
|             return callback; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public interface OnOptionSelectListener { | ||||
|         void onSelect(int itemId); | ||||
|         void onSelect(int itemId, @Nullable Function<DirectItem, Void> callback); | ||||
|     } | ||||
| 
 | ||||
|     public interface OnReactionClickListener { | ||||
|  | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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(this, viewModelFactory).get(DirectSettingsViewModel.class); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|  | ||||
| @ -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<DirectItem, Void> 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<Integer> inputLength = new MutableLiveData<>(0); | ||||
|     private MenuItem markAsSeenMenuItem; | ||||
|     private Media tempMedia; | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(@Nullable final Bundle savedInstanceState) { | ||||
| @ -329,11 +327,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(this, viewModelFactory).get(DirectThreadViewModel.class); | ||||
|         setHasOptionsMenu(true); | ||||
|     } | ||||
| 
 | ||||
| @ -454,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)) { | ||||
| @ -1317,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 | ||||
|  | ||||
| @ -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); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -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<User>() { | ||||
|                 @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<User>() { | ||||
|                 @Override | ||||
|                 public void onSuccess(final User user) { | ||||
|                     profileModel = user; | ||||
|                     setProfileDetails(); | ||||
|                 } | ||||
|         graphQLService.fetchUser(usernameTemp, new ServiceCallback<User>() { | ||||
|             @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(), | ||||
|  | ||||
| @ -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) { | ||||
|  | ||||
| @ -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<User> 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<User> getCurrentUserLiveData() { | ||||
|         return currentUser; | ||||
|     } | ||||
| 
 | ||||
| @ -46,11 +53,13 @@ public class AppStateViewModel extends AndroidViewModel { | ||||
|         userService.getUserInfo(uid, new ServiceCallback<User>() { | ||||
|             @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); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -4,4 +4,5 @@ | ||||
|     <item name="unsend" type="id" /> | ||||
|     <item name="forward" type="id" /> | ||||
|     <item name="detail" type="id" /> | ||||
|     <item name="copy" type="id" /> | ||||
| </resources> | ||||
| @ -483,4 +483,6 @@ | ||||
|     <string name="crash_report_title">Select an email app to send crash logs</string> | ||||
|     <string name="not_found">Not found!</string> | ||||
|     <string name="rate_limit">Your IP has been rate limited by Instagram. Wait for an hour and try again.</string> | ||||
|     <string name="copy_caption">Copy caption</string> | ||||
|     <string name="copy_reply">Copy reply</string> | ||||
| </resources> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user