diff --git a/app/src/main/java/awais/instagrabber/fragments/PostViewV2Fragment.java b/app/src/main/java/awais/instagrabber/fragments/PostViewV2Fragment.java index f2e4fac0..71e2a43c 100644 --- a/app/src/main/java/awais/instagrabber/fragments/PostViewV2Fragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/PostViewV2Fragment.java @@ -14,6 +14,7 @@ import android.text.SpannableStringBuilder; import android.text.Spanned; import android.util.Log; import android.view.LayoutInflater; +import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; @@ -68,8 +69,10 @@ import com.skydoves.balloon.overlay.BalloonOverlayCircle; import java.io.Serializable; import java.util.List; +import java.util.Set; import awais.instagrabber.R; +import awais.instagrabber.UserSearchNavGraphDirections; import awais.instagrabber.activities.MainActivity; import awais.instagrabber.adapters.SliderCallbackAdapter; import awais.instagrabber.adapters.SliderItemsAdapter; @@ -93,6 +96,7 @@ import awais.instagrabber.repositories.responses.Location; import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.VideoVersion; +import awais.instagrabber.repositories.responses.directmessages.RankedRecipient; import awais.instagrabber.utils.DownloadUtils; import awais.instagrabber.utils.NullSafePair; import awais.instagrabber.utils.NumberUtils; @@ -124,6 +128,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme private PopupMenu optionsPopup; private EditTextDialogFragment editTextDialogFragment; private boolean wasDeleted; + private MutableLiveData backStackSavedStateCollectionLiveData; private MutableLiveData backStackSavedStateResultLiveData; private OnDeleteListener onDeleteListener; @Nullable @@ -131,7 +136,6 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme private LayoutPostViewBottomBinding bottom; private View postView; private int originalHeight; - private int originalSystemUi; private boolean isInFullScreenMode; private StyledPlayerView playerView; private int playerViewOriginalHeight; @@ -145,8 +149,28 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme if (result instanceof String) { final String collection = (String) result; handleSaveUnsaveResourceLiveData(viewModel.toggleSave(collection, viewModel.getMedia().getHasViewerSaved())); + } else if ((result instanceof RankedRecipient)) { + // Log.d(TAG, "result: " + result); + final Context context = getContext(); + if (context != null) { + Toast.makeText(context, R.string.sending, Toast.LENGTH_SHORT).show(); + } + viewModel.shareDm((RankedRecipient) result); + } else if ((result instanceof Set)) { + try { + // Log.d(TAG, "result: " + result); + final Context context = getContext(); + if (context != null) { + Toast.makeText(context, R.string.sending, Toast.LENGTH_SHORT).show(); + } + //noinspection unchecked + viewModel.shareDm((Set) result); + } catch (Exception e) { + Log.e(TAG, "share: ", e); + } } // clear result + backStackSavedStateCollectionLiveData.postValue(null); backStackSavedStateResultLiveData.postValue(null); }; @@ -193,7 +217,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme // wasPaused = true; if (settingsHelper.getBoolean(PreferenceKeys.PLAY_IN_BACKGROUND)) return; final Media media = viewModel.getMedia(); - if (media == null) return; + if (media == null || media.getMediaType() == null) return; switch (media.getMediaType()) { case MEDIA_TYPE_VIDEO: if (videoPlayerViewHelper != null) { @@ -214,7 +238,9 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme final NavController navController = NavHostFragment.findNavController(this); final NavBackStackEntry backStackEntry = navController.getCurrentBackStackEntry(); if (backStackEntry != null) { - backStackSavedStateResultLiveData = backStackEntry.getSavedStateHandle().getLiveData("collection"); + backStackSavedStateCollectionLiveData = backStackEntry.getSavedStateHandle().getLiveData("collection"); + backStackSavedStateCollectionLiveData.observe(getViewLifecycleOwner(), backStackSavedStateObserver); + backStackSavedStateResultLiveData = backStackEntry.getSavedStateHandle().getLiveData("result"); backStackSavedStateResultLiveData.observe(getViewLifecycleOwner(), backStackSavedStateObserver); } } @@ -224,7 +250,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme super.onDestroyView(); showSystemUI(); final Media media = viewModel.getMedia(); - if (media == null) return; + if (media == null || media.getMediaType() == null) return; switch (media.getMediaType()) { case MEDIA_TYPE_VIDEO: if (videoPlayerViewHelper != null) { @@ -740,14 +766,55 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme // is this necessary? Toast.makeText(context, R.string.share_private_post, Toast.LENGTH_LONG).show(); } - final Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); - sharingIntent.setType("text/plain"); - sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, "https://instagram.com/p/" + media.getCode()); - startActivity(Intent.createChooser(sharingIntent, - isPrivate ? getString(R.string.share_private_post) : getString(R.string.share_public_post))); + if (viewModel.isLoggedIn()) { + final Context context = getContext(); + if (context == null) return; + final ContextThemeWrapper themeWrapper = new ContextThemeWrapper(context, R.style.popupMenuStyle); + final PopupMenu popupMenu = new PopupMenu(themeWrapper, bottom.share); + final Menu menu = popupMenu.getMenu(); + menu.add(0, R.id.share_dm, 0, R.string.share_via_dm); + menu.add(0, R.id.share, 1, R.string.share_link); + popupMenu.setOnMenuItemClickListener(item -> { + final int itemId = item.getItemId(); + if (itemId == R.id.share_dm) { + final UserSearchNavGraphDirections.ActionGlobalUserSearch actionGlobalUserSearch = UserSearchFragmentDirections + .actionGlobalUserSearch() + .setTitle(getString(R.string.share)) + .setActionLabel(getString(R.string.send)) + .setShowGroups(true) + .setMultiple(true) + .setSearchMode(UserSearchFragment.SearchMode.RAVEN); + final NavController navController = NavHostFragment.findNavController(PostViewV2Fragment.this); + try { + navController.navigate(actionGlobalUserSearch); + } catch (Exception e) { + Log.e(TAG, "setupShare: ", e); + } + return true; + } else if (itemId == R.id.share) { + shareLink(media, isPrivate); + return true; + } + return false; + }); + popupMenu.show(); + return; + } + shareLink(media, isPrivate); }); } + private void shareLink(@NonNull final Media media, final boolean isPrivate) { + final Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); + sharingIntent.setType("text/plain"); + sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, "https://instagram.com/p/" + media.getCode()); + startActivity(Intent.createChooser( + sharingIntent, + isPrivate ? getString(R.string.share_private_post) + : getString(R.string.share_public_post) + )); + } + private void setupPostTypeLayout(final MediaItemType type) { if (type == null) return; switch (type) { @@ -1246,7 +1313,9 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme } private void toggleDetails() { - final boolean hasBeenToggled = true; + // final boolean hasBeenToggled = true; + final MainActivity activity = (MainActivity) getActivity(); + if (activity == null) return; final Media media = viewModel.getMedia(); binding.getRoot().post(() -> { TransitionManager.beginDelayedTransition(binding.getRoot()); @@ -1268,8 +1337,9 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme playerView.getLayoutParams().height = fullHeight; } } + final BottomNavigationView bottomNavView = activity.getBottomNavView(); + bottomNavView.setVisibility(View.GONE); detailsVisible = false; - if (media.getUser() != null) { binding.profilePic.setVisibility(View.GONE); binding.title.setVisibility(View.GONE); @@ -1310,6 +1380,8 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme playerView = null; } } + final BottomNavigationView bottomNavView = activity.getBottomNavView(); + bottomNavView.setVisibility(View.VISIBLE); if (media.getUser() != null) { binding.profilePic.setVisibility(View.VISIBLE); binding.title.setVisibility(View.VISIBLE); @@ -1375,8 +1447,6 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme if (toolbar != null) { toolbar.setVisibility(View.GONE); } - final BottomNavigationView bottomNavView = activity.getBottomNavView(); - bottomNavView.setVisibility(View.GONE); binding.getRoot().setPadding(binding.getRoot().getPaddingLeft(), binding.getRoot().getPaddingTop(), binding.getRoot().getPaddingRight(), @@ -1404,8 +1474,6 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme if (toolbar != null) { toolbar.setVisibility(View.VISIBLE); } - final BottomNavigationView bottomNavView = activity.getBottomNavView(); - bottomNavView.setVisibility(View.VISIBLE); final Context context = getContext(); if (context == null) return; binding.getRoot().setPadding(binding.getRoot().getPaddingLeft(), diff --git a/app/src/main/java/awais/instagrabber/managers/DirectMessagesManager.java b/app/src/main/java/awais/instagrabber/managers/DirectMessagesManager.java index 6bc7f4da..10f700bf 100644 --- a/app/src/main/java/awais/instagrabber/managers/DirectMessagesManager.java +++ b/app/src/main/java/awais/instagrabber/managers/DirectMessagesManager.java @@ -1,16 +1,38 @@ package awais.instagrabber.managers; import android.content.ContentResolver; +import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; import com.google.common.collect.Iterables; +import java.io.IOException; +import java.util.Collections; import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.UUID; +import java.util.function.Function; +import awais.instagrabber.models.Resource; +import awais.instagrabber.repositories.requests.directmessages.BroadcastOptions; import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.directmessages.DirectItem; import awais.instagrabber.repositories.responses.directmessages.DirectThread; +import awais.instagrabber.repositories.responses.directmessages.DirectThreadBroadcastResponse; +import awais.instagrabber.repositories.responses.directmessages.RankedRecipient; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.CookieUtils; +import awais.instagrabber.webservices.DirectMessagesService; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +import static awais.instagrabber.utils.Utils.settingsHelper; public final class DirectMessagesManager { private static final String TAG = DirectMessagesManager.class.getSimpleName(); @@ -21,6 +43,8 @@ public final class DirectMessagesManager { private final InboxManager inboxManager; private final InboxManager pendingInboxManager; + private DirectMessagesService service; + public static DirectMessagesManager getInstance() { if (instance == null) { synchronized (LOCK) { @@ -35,26 +59,34 @@ public final class DirectMessagesManager { private DirectMessagesManager() { inboxManager = InboxManager.getInstance(false); pendingInboxManager = InboxManager.getInstance(true); + final String cookie = settingsHelper.getString(Constants.COOKIE); + final long viewerId = CookieUtils.getUserIdFromCookie(cookie); + final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID); + final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); + if (csrfToken == null) return; + service = DirectMessagesService.getInstance(csrfToken, viewerId, deviceUuid); } public void moveThreadFromPending(@NonNull final String threadId) { final List pendingThreads = pendingInboxManager.getThreads().getValue(); if (pendingThreads == null) return; - final int index = Iterables.indexOf(pendingThreads, t -> t.getThreadId().equals(threadId)); + final int index = Iterables.indexOf(pendingThreads, t -> t != null && t.getThreadId().equals(threadId)); if (index < 0) return; final DirectThread thread = pendingThreads.get(index); final DirectItem threadFirstDirectItem = thread.getFirstDirectItem(); if (threadFirstDirectItem == null) return; final List threads = inboxManager.getThreads().getValue(); int insertIndex = 0; - for (final DirectThread tempThread : threads) { - final DirectItem firstDirectItem = tempThread.getFirstDirectItem(); - if (firstDirectItem == null) continue; - final long timestamp = firstDirectItem.getTimestamp(); - if (timestamp < threadFirstDirectItem.getTimestamp()) { - break; + if (threads != null) { + for (final DirectThread tempThread : threads) { + final DirectItem firstDirectItem = tempThread.getFirstDirectItem(); + if (firstDirectItem == null) continue; + final long timestamp = firstDirectItem.getTimestamp(); + if (timestamp < threadFirstDirectItem.getTimestamp()) { + break; + } + insertIndex++; } - insertIndex++; } thread.setPending(false); inboxManager.addThread(thread, insertIndex); @@ -78,4 +110,166 @@ public final class DirectMessagesManager { @NonNull final ContentResolver contentResolver) { return ThreadManager.getInstance(threadId, pending, currentUser, contentResolver); } + + public void createThread(final long userPk, + @Nullable final Function callback) { + if (service == null) return; + final Call createThreadRequest = service.createThread(Collections.singletonList(userPk), null); + createThreadRequest.enqueue(new Callback() { + @Override + public void onResponse(@NonNull final Call call, @NonNull final Response response) { + if (!response.isSuccessful()) { + if (response.errorBody() != null) { + try { + final String string = response.errorBody().string(); + final String msg = String.format(Locale.US, + "onResponse: url: %s, responseCode: %d, errorBody: %s", + call.request().url().toString(), + response.code(), + string); + Log.e(TAG, msg); + } catch (IOException e) { + Log.e(TAG, "onResponse: ", e); + } + return; + } + Log.e(TAG, "onResponse: request was not successful and response error body was null"); + return; + } + final DirectThread thread = response.body(); + if (thread == null) { + Log.e(TAG, "onResponse: thread is null"); + return; + } + if (callback != null) { + callback.apply(thread); + } + } + + @Override + public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { + + } + }); + } + + public void sendMedia(@NonNull final Set recipients, final String mediaId) { + final int[] resultsCount = {0}; + final Function callback = unused -> { + resultsCount[0]++; + if (resultsCount[0] == recipients.size()) { + inboxManager.refresh(); + } + return null; + }; + for (final RankedRecipient recipient : recipients) { + if (recipient == null) continue; + sendMedia(recipient, mediaId, false, callback); + } + } + + public void sendMedia(@NonNull final RankedRecipient recipient, final String mediaId) { + sendMedia(recipient, mediaId, true, null); + } + + private void sendMedia(@NonNull final RankedRecipient recipient, + @NonNull final String mediaId, + final boolean refreshInbox, + @Nullable final Function callback) { + if (recipient.getThread() == null && recipient.getUser() != null) { + // create thread and forward + createThread(recipient.getUser().getPk(), directThread -> { + sendMedia(directThread, mediaId, unused -> { + if (refreshInbox) { + inboxManager.refresh(); + } + if (callback != null) { + callback.apply(null); + } + return null; + }); + return null; + }); + } + if (recipient.getThread() == null) return; + // just forward + final DirectThread thread = recipient.getThread(); + sendMedia(thread, mediaId, unused -> { + if (refreshInbox) { + inboxManager.refresh(); + } + if (callback != null) { + callback.apply(null); + } + return null; + }); + } + + @NonNull + public LiveData> sendMedia(@NonNull final DirectThread thread, + @NonNull final String mediaId, + @Nullable final Function callback) { + return sendMedia(thread.getThreadId(), mediaId, callback); + } + + @NonNull + public LiveData> sendMedia(@NonNull final String threadId, + @NonNull final String mediaId, + @Nullable final Function callback) { + final MutableLiveData> data = new MutableLiveData<>(); + data.postValue(Resource.loading(null)); + final Call request = service.broadcastMediaShare( + UUID.randomUUID().toString(), + BroadcastOptions.ThreadIdOrUserIds.of(threadId), + mediaId + ); + request.enqueue(new Callback() { + @Override + public void onResponse(@NonNull final Call call, + @NonNull final Response response) { + if (response.isSuccessful()) { + data.postValue(Resource.success(new Object())); + if (callback != null) { + callback.apply(null); + } + return; + } + if (response.errorBody() != null) { + try { + final String string = response.errorBody().string(); + final String msg = String.format(Locale.US, + "onResponse: url: %s, responseCode: %d, errorBody: %s", + call.request().url().toString(), + response.code(), + string); + Log.e(TAG, msg); + data.postValue(Resource.error(msg, null)); + } catch (IOException e) { + Log.e(TAG, "onResponse: ", e); + data.postValue(Resource.error(e.getMessage(), null)); + } + if (callback != null) { + callback.apply(null); + } + return; + } + final String msg = "onResponse: request was not successful and response error body was null"; + Log.e(TAG, msg); + data.postValue(Resource.error(msg, null)); + if (callback != null) { + callback.apply(null); + } + } + + @Override + public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { + Log.e(TAG, "onFailure: ", t); + data.postValue(Resource.error(t.getMessage(), null)); + if (callback != null) { + callback.apply(null); + } + } + }); + return data; + } } diff --git a/app/src/main/java/awais/instagrabber/managers/ThreadManager.java b/app/src/main/java/awais/instagrabber/managers/ThreadManager.java index a1e55dc7..f5089ce1 100644 --- a/app/src/main/java/awais/instagrabber/managers/ThreadManager.java +++ b/app/src/main/java/awais/instagrabber/managers/ThreadManager.java @@ -96,6 +96,7 @@ public final class ThreadManager { private final ThreadIdOrUserIds threadIdOrUserIds; private final User currentUser; private final ContentResolver contentResolver; + private final DirectMessagesManager messagesManager; private DirectMessagesService service; private MediaService mediaService; @@ -147,7 +148,7 @@ public final class ThreadManager { final boolean pending, @NonNull final User currentUser, @NonNull final ContentResolver contentResolver) { - final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance(); + messagesManager = DirectMessagesManager.getInstance(); this.inboxManager = pending ? messagesManager.getPendingInboxManager() : messagesManager.getInboxManager(); this.threadId = threadId; this.threadIdOrUserIds = ThreadIdOrUserIds.of(threadId); @@ -821,42 +822,10 @@ public final class ThreadManager { if (recipient == null || itemToForward == null) return; if (recipient.getThread() == null && recipient.getUser() != null) { // create thread and forward - final Call createThreadRequest = service.createThread(Collections.singletonList(recipient.getUser().getPk()), null); - createThreadRequest.enqueue(new Callback() { - @Override - public void onResponse(@NonNull final Call call, @NonNull final Response response) { - if (!response.isSuccessful()) { - if (response.errorBody() != null) { - try { - final String string = response.errorBody().string(); - final String msg = String.format(Locale.US, - "onResponse: url: %s, responseCode: %d, errorBody: %s", - call.request().url().toString(), - response.code(), - string); - Log.e(TAG, msg); - } catch (IOException e) { - Log.e(TAG, "onResponse: ", e); - } - return; - } - Log.e(TAG, "onResponse: request was not successful and response error body was null"); - return; - } - final DirectThread thread = response.body(); - if (thread == null) { - Log.e(TAG, "onResponse: thread is null"); - return; - } - forward(thread, itemToForward); - } - - @Override - public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { - - } + messagesManager.createThread(recipient.getUser().getPk(), directThread -> { + forward(directThread, itemToForward); + return null; }); - return; } if (recipient.getThread() != null) { // just forward @@ -870,13 +839,25 @@ public final class ThreadManager { replyToItem.postValue(item); } - private void forward(@NonNull final DirectThread thread, @NonNull final DirectItem itemToForward) { + @NonNull + private LiveData> forward(@NonNull final DirectThread thread, @NonNull final DirectItem itemToForward) { + final MutableLiveData> data = new MutableLiveData<>(); + if (itemToForward.getItemId() == null) { + data.postValue(Resource.error("item id is null", null)); + return data; + } final DirectItemType itemType = itemToForward.getItemType(); + if (itemType == null) { + data.postValue(Resource.error("item type is null", null)); + return data; + } final String itemTypeName = itemType.getName(); if (itemTypeName == null) { Log.e(TAG, "forward: itemTypeName was null!"); - return; + data.postValue(Resource.error("itemTypeName is null", null)); + return data; } + data.postValue(Resource.loading(null)); final Call request = service.forward(thread.getThreadId(), itemTypeName, threadId, @@ -885,7 +866,10 @@ public final class ThreadManager { @Override public void onResponse(@NonNull final Call call, @NonNull final Response response) { - if (response.isSuccessful()) return; + if (response.isSuccessful()) { + data.postValue(Resource.success(new Object())); + return; + } if (response.errorBody() != null) { try { final String string = response.errorBody().string(); @@ -895,19 +879,25 @@ public final class ThreadManager { response.code(), string); Log.e(TAG, msg); + data.postValue(Resource.error(msg, null)); } catch (IOException e) { Log.e(TAG, "onResponse: ", e); + data.postValue(Resource.error(e.getMessage(), null)); } return; } - Log.e(TAG, "onResponse: request was not successful and response error body was null"); + final String msg = "onResponse: request was not successful and response error body was null"; + Log.e(TAG, msg); + data.postValue(Resource.error(msg, null)); } @Override public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { Log.e(TAG, "onFailure: ", t); + data.postValue(Resource.error(t.getMessage(), null)); } }); + return data; } public LiveData> acceptRequest() { diff --git a/app/src/main/java/awais/instagrabber/models/enums/BroadcastItemType.java b/app/src/main/java/awais/instagrabber/models/enums/BroadcastItemType.java index 7fd57da0..5b2fe11e 100644 --- a/app/src/main/java/awais/instagrabber/models/enums/BroadcastItemType.java +++ b/app/src/main/java/awais/instagrabber/models/enums/BroadcastItemType.java @@ -8,7 +8,8 @@ public enum BroadcastItemType { LINK("link"), VIDEO("configure_video"), VOICE("share_voice"), - ANIMATED_MEDIA("animated_media"); + ANIMATED_MEDIA("animated_media"), + MEDIA_SHARE("media_share"); private final String value; diff --git a/app/src/main/java/awais/instagrabber/repositories/requests/directmessages/MediaShareBroadcastOptions.kt b/app/src/main/java/awais/instagrabber/repositories/requests/directmessages/MediaShareBroadcastOptions.kt new file mode 100644 index 00000000..70d34d6b --- /dev/null +++ b/app/src/main/java/awais/instagrabber/repositories/requests/directmessages/MediaShareBroadcastOptions.kt @@ -0,0 +1,18 @@ +package awais.instagrabber.repositories.requests.directmessages + +import awais.instagrabber.models.enums.BroadcastItemType + +class MediaShareBroadcastOptions( + clientContext: String?, + threadIdOrUserIds: ThreadIdOrUserIds, + val mediaId: String +) : BroadcastOptions( + clientContext, + threadIdOrUserIds, + BroadcastItemType.MEDIA_SHARE +) { + + override fun getFormMap(): Map { + return mapOf("media_id" to mediaId) + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/viewmodels/PostViewV2ViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/PostViewV2ViewModel.java index 3394d708..653428b9 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/PostViewV2ViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/PostViewV2ViewModel.java @@ -11,14 +11,17 @@ import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.List; +import java.util.Set; import awais.instagrabber.R; +import awais.instagrabber.managers.DirectMessagesManager; import awais.instagrabber.models.Resource; import awais.instagrabber.models.enums.MediaItemType; import awais.instagrabber.repositories.responses.Caption; import awais.instagrabber.repositories.responses.Location; import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.User; +import awais.instagrabber.repositories.responses.directmessages.RankedRecipient; import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.CookieUtils; import awais.instagrabber.utils.TextUtils; @@ -49,6 +52,7 @@ public class PostViewV2ViewModel extends ViewModel { private final boolean isLoggedIn; private Media media; + private DirectMessagesManager messageManager; public PostViewV2ViewModel() { final String cookie = settingsHelper.getString(Constants.COOKIE); @@ -326,4 +330,18 @@ public class PostViewV2ViewModel extends ViewModel { }); return data; } + + public void shareDm(@NonNull final RankedRecipient result) { + if (messageManager == null) { + messageManager = DirectMessagesManager.getInstance(); + } + messageManager.sendMedia(result, media.getId()); + } + + public void shareDm(@NonNull final Set recipients) { + if (messageManager == null) { + messageManager = DirectMessagesManager.getInstance(); + } + messageManager.sendMedia(recipients, media.getId()); + } } diff --git a/app/src/main/java/awais/instagrabber/webservices/DirectMessagesService.java b/app/src/main/java/awais/instagrabber/webservices/DirectMessagesService.java index 0688c761..68e58b99 100644 --- a/app/src/main/java/awais/instagrabber/webservices/DirectMessagesService.java +++ b/app/src/main/java/awais/instagrabber/webservices/DirectMessagesService.java @@ -21,6 +21,7 @@ import awais.instagrabber.repositories.requests.directmessages.AnimatedMediaBroa import awais.instagrabber.repositories.requests.directmessages.BroadcastOptions; import awais.instagrabber.repositories.requests.directmessages.BroadcastOptions.ThreadIdOrUserIds; import awais.instagrabber.repositories.requests.directmessages.LinkBroadcastOptions; +import awais.instagrabber.repositories.requests.directmessages.MediaShareBroadcastOptions; import awais.instagrabber.repositories.requests.directmessages.PhotoBroadcastOptions; import awais.instagrabber.repositories.requests.directmessages.ReactionBroadcastOptions; import awais.instagrabber.repositories.requests.directmessages.StoryReplyBroadcastOptions; @@ -190,6 +191,12 @@ public class DirectMessagesService extends BaseService { return broadcast(new AnimatedMediaBroadcastOptions(clientContext, threadIdOrUserIds, giphyGif)); } + public Call broadcastMediaShare(@NonNull final String clientContext, + @NonNull final ThreadIdOrUserIds threadIdOrUserIds, + @NonNull final String mediaId) { + return broadcast(new MediaShareBroadcastOptions(clientContext, threadIdOrUserIds, mediaId)); + } + private Call broadcast(@NonNull final BroadcastOptions broadcastOptions) { if (TextUtils.isEmpty(broadcastOptions.getClientContext())) { throw new IllegalArgumentException("Broadcast requires a valid client context value"); diff --git a/app/src/main/res/navigation/discover_nav_graph.xml b/app/src/main/res/navigation/discover_nav_graph.xml index ee13ef9b..49a07187 100644 --- a/app/src/main/res/navigation/discover_nav_graph.xml +++ b/app/src/main/res/navigation/discover_nav_graph.xml @@ -111,6 +111,12 @@ app:argType="integer" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 358fbc74..75f446e3 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -508,4 +508,7 @@ Click to show full like count No profile pic found! Are you sure you want to open this link? + Sending... + Share via DM + Share linkā€¦