1
0
mirror of https://github.com/KokaKiwi/BarInsta synced 2024-11-22 22:57:29 +00:00

Merge branch 'master' into retrofit-intercept-errors

This commit is contained in:
Austin Huang 2021-04-02 09:36:33 -04:00 committed by GitHub
commit a3b3c54609
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 250 additions and 116 deletions

View File

@ -105,7 +105,7 @@ dependencies {
def nav_version = '2.3.4' def nav_version = '2.3.4'
def exoplayer_version = '2.13.2' 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-core:$exoplayer_version"
implementation "com.google.android.exoplayer:exoplayer-dash:$exoplayer_version" implementation "com.google.android.exoplayer:exoplayer-dash:$exoplayer_version"

View File

@ -47,6 +47,7 @@ import androidx.navigation.ui.NavigationUI;
import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout; 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.behavior.HideBottomViewOnScrollBehavior;
import com.google.android.material.bottomnavigation.BottomNavigationView; 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.utils.emoji.EmojiParser;
import awais.instagrabber.viewmodels.AppStateViewModel; import awais.instagrabber.viewmodels.AppStateViewModel;
import awais.instagrabber.webservices.RetrofitFactory; import awais.instagrabber.webservices.RetrofitFactory;
import awais.instagrabber.viewmodels.DirectInboxViewModel;
import awais.instagrabber.webservices.SearchService; import awais.instagrabber.webservices.SearchService;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -183,6 +185,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
initEmojiCompat(); initEmojiCompat();
searchService = SearchService.getInstance(); searchService = SearchService.getInstance();
// initDmService(); // initDmService();
initDmUnreadCount();
} }
private void initDmService() { private void initDmService() {
@ -192,6 +195,16 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
DMSyncAlarmReceiver.setAlarm(this); 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 @Override
public boolean onCreateOptionsMenu(final Menu menu) { public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu); getMenuInflater().inflate(R.menu.main_menu, menu);
@ -857,4 +870,19 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
public View getRootView() { public View getRootView() {
return binding.getRoot(); 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);
}
} }

View File

@ -17,6 +17,7 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.Function;
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemActionLogViewHolder; import awais.instagrabber.adapters.viewholder.directmessages.DirectItemActionLogViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemAnimatedMediaViewHolder; 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 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 { public interface DirectItemInternalLongClickListener {

View File

@ -8,8 +8,13 @@ import androidx.core.util.Pair;
import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.ItemTouchHelper;
import com.facebook.drawee.backends.pipeline.Fresco; 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.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.customviews.DirectItemContextMenu;
import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding; import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding;
import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.repositories.responses.AnimatedMediaFixedHeight; 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.DirectItemAnimatedMedia;
import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.NumberUtils; import awais.instagrabber.utils.NumberUtils;
import awais.instagrabber.utils.Utils;
public class DirectItemAnimatedMediaViewHolder extends DirectItemViewHolder { public class DirectItemAnimatedMediaViewHolder extends DirectItemViewHolder {
@ -65,4 +71,14 @@ public class DirectItemAnimatedMediaViewHolder extends DirectItemViewHolder {
public int getSwipeDirection() { public int getSwipeDirection() {
return ItemTouchHelper.ACTION_STATE_IDLE; 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;
})
);
}
} }

View File

@ -5,7 +5,13 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; 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.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.customviews.DirectItemContextMenu;
import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmLinkBinding; import awais.instagrabber.databinding.LayoutDmLinkBinding;
import awais.instagrabber.repositories.responses.User; 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.DirectItemLinkContext;
import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
public class DirectItemLinkViewHolder extends DirectItemViewHolder { public class DirectItemLinkViewHolder extends DirectItemViewHolder {
@ -80,4 +87,16 @@ public class DirectItemLinkViewHolder extends DirectItemViewHolder {
protected boolean showBackground() { protected boolean showBackground() {
return true; 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;
})
);
}
} }

View File

@ -12,11 +12,14 @@ import androidx.recyclerview.widget.ItemTouchHelper;
import com.facebook.drawee.drawable.ScalingUtils; import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.generic.RoundingParams; import com.facebook.drawee.generic.RoundingParams;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback; import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.customviews.DirectItemContextMenu;
import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmMediaShareBinding; import awais.instagrabber.databinding.LayoutDmMediaShareBinding;
import awais.instagrabber.models.enums.DirectItemType; 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.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.NumberUtils; import awais.instagrabber.utils.NumberUtils;
import awais.instagrabber.utils.ResponseBodyUtils; import awais.instagrabber.utils.ResponseBodyUtils;
import awais.instagrabber.utils.Utils;
public class DirectItemMediaShareViewHolder extends DirectItemViewHolder { public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
private static final String TAG = DirectItemMediaShareViewHolder.class.getSimpleName(); private static final String TAG = DirectItemMediaShareViewHolder.class.getSimpleName();
@ -38,6 +42,7 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
private final RoundingParams incomingRoundingParams; private final RoundingParams incomingRoundingParams;
private final RoundingParams outgoingRoundingParams; private final RoundingParams outgoingRoundingParams;
private DirectItemType itemType; private DirectItemType itemType;
private Caption caption;
public DirectItemMediaShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding, public DirectItemMediaShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmMediaShareBinding binding, @NonNull final LayoutDmMediaShareBinding binding,
@ -113,7 +118,7 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
} }
private void setupCaption(@NonNull final Media media) { private void setupCaption(@NonNull final Media media) {
final Caption caption = media.getCaption(); caption = media.getCaption();
if (caption != null) { if (caption != null) {
binding.caption.setVisibility(View.VISIBLE); binding.caption.setVisibility(View.VISIBLE);
binding.caption.setText(caption.getText()); binding.caption.setText(caption.getText());
@ -177,4 +182,16 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
} }
return super.getSwipeDirection(); 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();
}
} }

View File

@ -8,13 +8,16 @@ import androidx.constraintlayout.widget.ConstraintLayout;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.generic.RoundingParams; import com.facebook.drawee.generic.RoundingParams;
import com.google.common.collect.ImmutableList;
import java.util.List;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback; import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.customviews.DirectItemContextMenu;
import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmReelShareBinding; import awais.instagrabber.databinding.LayoutDmReelShareBinding;
import awais.instagrabber.models.enums.MediaItemType; import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.repositories.responses.ImageVersions2;
import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem; 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.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.ResponseBodyUtils; import awais.instagrabber.utils.ResponseBodyUtils;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
public class DirectItemReelShareViewHolder extends DirectItemViewHolder { public class DirectItemReelShareViewHolder extends DirectItemViewHolder {
private final LayoutDmReelShareBinding binding; private final LayoutDmReelShareBinding binding;
private String type;
public DirectItemReelShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding, public DirectItemReelShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmReelShareBinding binding, @NonNull final LayoutDmReelShareBinding binding,
@ -40,7 +45,7 @@ public class DirectItemReelShareViewHolder extends DirectItemViewHolder {
@Override @Override
public void bindItem(final DirectItem item, final MessageDirection messageDirection) { public void bindItem(final DirectItem item, final MessageDirection messageDirection) {
final DirectItemReelShare reelShare = item.getReelShare(); final DirectItemReelShare reelShare = item.getReelShare();
final String type = reelShare.getType(); type = reelShare.getType();
if (type == null) return; if (type == null) return;
final boolean isSelf = isSelf(item); final boolean isSelf = isSelf(item);
final Media media = reelShare.getMedia(); final Media media = reelShare.getMedia();
@ -170,4 +175,20 @@ public class DirectItemReelShareViewHolder extends DirectItemViewHolder {
protected boolean canForward() { protected boolean canForward() {
return false; 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();
}
} }

View File

@ -2,12 +2,20 @@ package awais.instagrabber.adapters.viewholder.directmessages;
import androidx.annotation.NonNull; 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.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.customviews.DirectItemContextMenu;
import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmTextBinding; import awais.instagrabber.databinding.LayoutDmTextBinding;
import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem; import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
public class DirectItemTextViewHolder extends DirectItemViewHolder { public class DirectItemTextViewHolder extends DirectItemViewHolder {
@ -35,4 +43,15 @@ public class DirectItemTextViewHolder extends DirectItemViewHolder {
protected boolean showBackground() { protected boolean showBackground() {
return true; 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;
})
);
}
} }

View File

@ -543,22 +543,13 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder imple
if (thread.getInputMode() != 1 && messageDirection == MessageDirection.OUTGOING) { if (thread.getInputMode() != 1 && messageDirection == MessageDirection.OUTGOING) {
builder.add(new DirectItemContextMenu.MenuItem(R.id.unsend, R.string.dms_inbox_unsend)); 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 boolean showReactions = thread.getInputMode() != 1 && allowReaction();
final ImmutableList<DirectItemContextMenu.MenuItem> menuItems = builder.build(); final ImmutableList<DirectItemContextMenu.MenuItem> menuItems = builder.build();
if (!showReactions && menuItems.isEmpty()) return; if (!showReactions && menuItems.isEmpty()) return;
final DirectItemContextMenu menu = new DirectItemContextMenu(itemView.getContext(), showReactions, menuItems); final DirectItemContextMenu menu = new DirectItemContextMenu(itemView.getContext(), showReactions, menuItems);
menu.setOnDismissListener(() -> setSelected(false)); menu.setOnDismissListener(() -> setSelected(false));
menu.setOnReactionClickListener(emoji -> callback.onReaction(item, emoji)); 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); menu.show(itemView, location);
} }

View File

@ -12,12 +12,14 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.Floats; import com.google.common.primitives.Floats;
import java.util.List; import java.util.List;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback; import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.customviews.DirectItemContextMenu;
import awais.instagrabber.databinding.LayoutDmBaseBinding; import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmVoiceMediaBinding; import awais.instagrabber.databinding.LayoutDmVoiceMediaBinding;
import awais.instagrabber.repositories.responses.Audio; import awais.instagrabber.repositories.responses.Audio;
@ -174,6 +176,13 @@ public class DirectItemVoiceMediaViewHolder extends DirectItemViewHolder {
return false; 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 static class AudioItemState {
private boolean prepared; private boolean prepared;

View File

@ -29,12 +29,14 @@ import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.util.Pair; import androidx.core.util.Pair;
import java.util.List; import java.util.List;
import java.util.function.Function;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.animations.RoundedRectRevealOutlineProvider; import awais.instagrabber.animations.RoundedRectRevealOutlineProvider;
import awais.instagrabber.customviews.emoji.Emoji; import awais.instagrabber.customviews.emoji.Emoji;
import awais.instagrabber.customviews.emoji.ReactionsManager; import awais.instagrabber.customviews.emoji.ReactionsManager;
import awais.instagrabber.databinding.LayoutDirectItemOptionsBinding; import awais.instagrabber.databinding.LayoutDirectItemOptionsBinding;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import static android.view.View.MeasureSpec.makeMeasureSpec; import static android.view.View.MeasureSpec.makeMeasureSpec;
@ -345,7 +347,7 @@ public class DirectItemContextMenu extends PopupWindow {
textView.setText(context.getString(menuItem.getTitleRes())); textView.setText(context.getString(menuItem.getTitleRes()));
textView.setOnClickListener(v -> { textView.setOnClickListener(v -> {
if (onOptionSelectListener != null) { if (onOptionSelectListener != null) {
onOptionSelectListener.onSelect(menuItem.getItemId()); onOptionSelectListener.onSelect(menuItem.getItemId(), menuItem.getCallback());
} }
dismiss(); dismiss();
}); });
@ -397,9 +399,19 @@ public class DirectItemContextMenu extends PopupWindow {
@StringRes @StringRes
private final int titleRes; private final int titleRes;
/**
* Callback function
*/
private final Function<DirectItem, Void> callback;
public MenuItem(@IdRes final int itemId, @StringRes final int titleRes) { 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.itemId = itemId;
this.titleRes = titleRes; this.titleRes = titleRes;
this.callback = callback;
} }
public int getItemId() { public int getItemId() {
@ -409,10 +421,14 @@ public class DirectItemContextMenu extends PopupWindow {
public int getTitleRes() { public int getTitleRes() {
return titleRes; return titleRes;
} }
public Function<DirectItem, Void> getCallback() {
return callback;
}
} }
public interface OnOptionSelectListener { public interface OnOptionSelectListener {
void onSelect(int itemId); void onSelect(int itemId, @Nullable Function<DirectItem, Void> callback);
} }
public interface OnReactionClickListener { public interface OnReactionClickListener {

View File

@ -20,8 +20,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections; import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager; 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.BadgeDrawable;
import com.google.android.material.badge.BadgeUtils; import com.google.android.material.badge.BadgeUtils;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import java.util.List; import java.util.List;
@ -66,9 +63,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
fragmentActivity = (MainActivity) getActivity(); fragmentActivity = (MainActivity) getActivity();
if (fragmentActivity != null) { if (fragmentActivity != null) {
final NavController navController = NavHostFragment.findNavController(this); viewModel = new ViewModelProvider(fragmentActivity).get(DirectInboxViewModel.class);
final ViewModelStoreOwner viewModelStoreOwner = navController.getViewModelStoreOwner(R.id.direct_messages_nav_graph);
viewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectInboxViewModel.class);
} }
setHasOptionsMenu(true); setHasOptionsMenu(true);
} }
@ -101,6 +96,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
} }
} }
@SuppressLint("UnsafeExperimentalUsageError")
@Override @Override
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
@ -201,11 +197,6 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
break; 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); viewModel.getPendingRequestsTotal().observe(getViewLifecycleOwner(), this::attachPendingRequestsBadge);
} }
@ -213,12 +204,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
private void attachPendingRequestsBadge(@Nullable final Integer count) { private void attachPendingRequestsBadge(@Nullable final Integer count) {
if (pendingRequestsMenuItem == null) { if (pendingRequestsMenuItem == null) {
final Handler handler = new Handler(); final Handler handler = new Handler();
handler.postDelayed(new Runnable() { handler.postDelayed(() -> attachPendingRequestsBadge(count), 500);
@Override
public void run() {
attachPendingRequestsBadge(count);
}
}, 500);
return; return;
} }
if (pendingRequestTotalBadgeDrawable == null) { if (pendingRequestTotalBadgeDrawable == null) {
@ -277,20 +263,4 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
}); });
binding.inboxList.addOnScrollListener(lazyLoader); 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);
}
} }

View File

@ -79,11 +79,13 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
final DirectMessageSettingsFragmentArgs args = DirectMessageSettingsFragmentArgs.fromBundle(arguments); final DirectMessageSettingsFragmentArgs args = DirectMessageSettingsFragmentArgs.fromBundle(arguments);
final MainActivity fragmentActivity = (MainActivity) requireActivity(); final MainActivity fragmentActivity = (MainActivity) requireActivity();
final AppStateViewModel appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class); final AppStateViewModel appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class);
viewModel = new ViewModelProvider(this, new DirectSettingsViewModelFactory(fragmentActivity.getApplication(), final DirectSettingsViewModelFactory viewModelFactory = new DirectSettingsViewModelFactory(
fragmentActivity.getApplication(),
args.getThreadId(), args.getThreadId(),
args.getPending(), args.getPending(),
appStateViewModel.getCurrentUser())) appStateViewModel.getCurrentUser()
.get(DirectSettingsViewModel.class); );
viewModel = new ViewModelProvider(this, viewModelFactory).get(DirectSettingsViewModel.class);
} }
@NonNull @NonNull

View File

@ -58,6 +58,7 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import awais.instagrabber.ProfileNavGraphDirections; import awais.instagrabber.ProfileNavGraphDirections;
import awais.instagrabber.R; import awais.instagrabber.R;
@ -258,7 +259,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
} }
@Override @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) { if (itemId == R.id.unsend) {
handleSentMessage(viewModel.unsend(item)); handleSentMessage(viewModel.unsend(item));
return; return;
@ -275,21 +276,17 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
final NavController navController = NavHostFragment.findNavController(DirectMessageThreadFragment.this); final NavController navController = NavHostFragment.findNavController(DirectMessageThreadFragment.this);
navController.navigate(actionGlobalUserSearch); navController.navigate(actionGlobalUserSearch);
} }
if (itemId == R.id.detail) { if (itemId == R.id.download) {
final Context context = getContext(); downloadItem(item);
if (context == null) return; 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;
} }
// otherwise call callback if present
if (cb != null) {
cb.apply(item);
} }
} }
}; };
private final DirectItemLongClickListener directItemLongClickListener = position -> { private final DirectItemLongClickListener directItemLongClickListener = position -> {
// viewModel.setSelectedPosition(position); // viewModel.setSelectedPosition(position);
}; };
@ -319,6 +316,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
}; };
private final MutableLiveData<Integer> inputLength = new MutableLiveData<>(0); private final MutableLiveData<Integer> inputLength = new MutableLiveData<>(0);
private MenuItem markAsSeenMenuItem; private MenuItem markAsSeenMenuItem;
private Media tempMedia;
@Override @Override
public void onCreate(@Nullable final Bundle savedInstanceState) { public void onCreate(@Nullable final Bundle savedInstanceState) {
@ -329,11 +327,13 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
final Bundle arguments = getArguments(); final Bundle arguments = getArguments();
if (arguments == null) return; if (arguments == null) return;
final DirectMessageThreadFragmentArgs fragmentArgs = DirectMessageThreadFragmentArgs.fromBundle(arguments); final DirectMessageThreadFragmentArgs fragmentArgs = DirectMessageThreadFragmentArgs.fromBundle(arguments);
viewModel = new ViewModelProvider(this, new DirectThreadViewModelFactory(fragmentActivity.getApplication(), final DirectThreadViewModelFactory viewModelFactory = new DirectThreadViewModelFactory(
fragmentActivity.getApplication(),
fragmentArgs.getThreadId(), fragmentArgs.getThreadId(),
fragmentArgs.getPending(), fragmentArgs.getPending(),
appStateViewModel.getCurrentUser())) appStateViewModel.getCurrentUser()
.get(DirectThreadViewModel.class); );
viewModel = new ViewModelProvider(this, viewModelFactory).get(DirectThreadViewModel.class);
setHasOptionsMenu(true); setHasOptionsMenu(true);
} }
@ -454,7 +454,9 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
if (requestCode == STORAGE_PERM_REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 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 (requestCode == AUDIO_RECORD_PERM_REQUEST_CODE) {
if (PermissionUtils.hasAudioRecordPerms(context)) { if (PermissionUtils.hasAudioRecordPerms(context)) {
@ -1317,18 +1319,31 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
appExecutors.mainThread().execute(prevTitleRunnable, 1000); 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 // 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) { if (media == null) {
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
} else { return;
}
if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
DownloadUtils.download(context, media); DownloadUtils.download(context, media);
} else {
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
}
Toast.makeText(context, R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show();
return;
} }
tempMedia = media;
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
} }
@NonNull @NonNull

View File

@ -13,8 +13,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;
import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@ -24,7 +22,6 @@ import com.google.android.material.snackbar.Snackbar;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import awais.instagrabber.R;
import awais.instagrabber.activities.MainActivity; import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.DirectMessageInboxAdapter; import awais.instagrabber.adapters.DirectMessageInboxAdapter;
import awais.instagrabber.customviews.helpers.RecyclerLazyLoaderAtEdge; import awais.instagrabber.customviews.helpers.RecyclerLazyLoaderAtEdge;
@ -51,9 +48,7 @@ public class DirectPendingInboxFragment extends Fragment implements SwipeRefresh
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
fragmentActivity = (MainActivity) getActivity(); fragmentActivity = (MainActivity) getActivity();
if (fragmentActivity != null) { if (fragmentActivity != null) {
final NavController navController = NavHostFragment.findNavController(this); viewModel = new ViewModelProvider(fragmentActivity).get(DirectPendingInboxViewModel.class);
final ViewModelStoreOwner viewModelStoreOwner = navController.getViewModelStoreOwner(R.id.direct_messages_nav_graph);
viewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectPendingInboxViewModel.class);
} }
} }

View File

@ -12,7 +12,6 @@ import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.util.Log; import android.util.Log;
import android.view.ActionMode; import android.view.ActionMode;
import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
@ -604,12 +603,16 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
usernameTemp = usernameTemp.substring(1); usernameTemp = usernameTemp.substring(1);
} }
if (TextUtils.isEmpty(usernameTemp)) { if (TextUtils.isEmpty(usernameTemp)) {
profileModel = appStateViewModel.getCurrentUser(); appStateViewModel.getCurrentUserLiveData().observe(getViewLifecycleOwner(), user -> {
if (user == null) return;
profileModel = user;
username = profileModel.getUsername(); username = profileModel.getUsername();
setUsernameDelayed(); setUsernameDelayed();
setProfileDetails(); setProfileDetails();
});
return;
} }
else if (isLoggedIn) { if (isLoggedIn) {
userService.getUsernameInfo(usernameTemp, new ServiceCallback<User>() { userService.getUsernameInfo(usernameTemp, new ServiceCallback<User>() {
@Override @Override
public void onSuccess(final User user) { public void onSuccess(final User user) {
@ -643,8 +646,8 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
} catch (final Throwable ignored) {} } catch (final Throwable ignored) {}
} }
}); });
return;
} }
else {
graphQLService.fetchUser(usernameTemp, new ServiceCallback<User>() { graphQLService.fetchUser(usernameTemp, new ServiceCallback<User>() {
@Override @Override
public void onSuccess(final User user) { public void onSuccess(final User user) {
@ -663,7 +666,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
} }
}); });
} }
}
private void setProfileDetails() { private void setProfileDetails() {
final Context context = getContext(); final Context context = getContext();
@ -987,6 +989,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
} }
private void updateAccountInfo() { private void updateAccountInfo() {
if (profileModel == null) return;
accountRepository.insertOrUpdateAccount( accountRepository.insertOrUpdateAccount(
profileModel.getPk(), profileModel.getPk(),
profileModel.getUsername(), profileModel.getUsername(),

View File

@ -15,7 +15,7 @@ public class NotificationsPreferencesFragment extends BasePreferencesFragment {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
screen.addPreference(getActivityNotificationsPreference(context)); screen.addPreference(getActivityNotificationsPreference(context));
screen.addPreference(getDMNotificationsPreference(context)); // screen.addPreference(getDMNotificationsPreference(context));
} }
private Preference getActivityNotificationsPreference(@NonNull final Context context) { private Preference getActivityNotificationsPreference(@NonNull final Context context) {

View File

@ -1,9 +1,12 @@
package awais.instagrabber.viewmodels; package awais.instagrabber.viewmodels;
import android.app.Application; import android.app.Application;
import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import awais.instagrabber.db.datasources.AccountDataSource; import awais.instagrabber.db.datasources.AccountDataSource;
import awais.instagrabber.db.repositories.AccountRepository; import awais.instagrabber.db.repositories.AccountRepository;
@ -21,8 +24,8 @@ public class AppStateViewModel extends AndroidViewModel {
private final String cookie; private final String cookie;
private final boolean isLoggedIn; private final boolean isLoggedIn;
private final MutableLiveData<User> currentUser = new MutableLiveData<>();
private User currentUser;
private AccountRepository accountRepository; private AccountRepository accountRepository;
private UserService userService; private UserService userService;
@ -38,6 +41,10 @@ public class AppStateViewModel extends AndroidViewModel {
} }
public User getCurrentUser() { public User getCurrentUser() {
return currentUser.getValue();
}
public LiveData<User> getCurrentUserLiveData() {
return currentUser; return currentUser;
} }
@ -46,11 +53,13 @@ public class AppStateViewModel extends AndroidViewModel {
userService.getUserInfo(uid, new ServiceCallback<User>() { userService.getUserInfo(uid, new ServiceCallback<User>() {
@Override @Override
public void onSuccess(final User user) { public void onSuccess(final User user) {
currentUser = user; currentUser.postValue(user);
} }
@Override @Override
public void onFailure(final Throwable t) {} public void onFailure(final Throwable t) {
Log.e(TAG, "onFailure: ", t);
}
}); });
} }
} }

View File

@ -4,4 +4,5 @@
<item name="unsend" type="id" /> <item name="unsend" type="id" />
<item name="forward" type="id" /> <item name="forward" type="id" />
<item name="detail" type="id" /> <item name="detail" type="id" />
<item name="copy" type="id" />
</resources> </resources>

View File

@ -483,4 +483,6 @@
<string name="crash_report_title">Select an email app to send crash logs</string> <string name="crash_report_title">Select an email app to send crash logs</string>
<string name="not_found">Not found!</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="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> </resources>