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

share profile by dm: preparation

This commit is contained in:
Austin Huang 2021-06-15 13:27:58 -04:00
parent 8edac65015
commit d76018596d
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
6 changed files with 250 additions and 125 deletions

View File

@ -2,6 +2,7 @@ package awais.instagrabber.fragments.main;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.os.Bundle; import android.os.Bundle;
@ -33,6 +34,8 @@ import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDirections; import androidx.navigation.NavDirections;
@ -52,6 +55,7 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.UserSearchNavGraphDirections;
import awais.instagrabber.activities.MainActivity; import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.FeedAdapterV2; import awais.instagrabber.adapters.FeedAdapterV2;
import awais.instagrabber.adapters.HighlightsAdapter; import awais.instagrabber.adapters.HighlightsAdapter;
@ -66,6 +70,8 @@ import awais.instagrabber.db.repositories.FavoriteRepository;
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.dialogs.ProfilePicDialogFragment; import awais.instagrabber.dialogs.ProfilePicDialogFragment;
import awais.instagrabber.fragments.PostViewV2Fragment; import awais.instagrabber.fragments.PostViewV2Fragment;
import awais.instagrabber.fragments.UserSearchFragment;
import awais.instagrabber.fragments.UserSearchFragmentDirections;
import awais.instagrabber.managers.DirectMessagesManager; import awais.instagrabber.managers.DirectMessagesManager;
import awais.instagrabber.managers.InboxManager; import awais.instagrabber.managers.InboxManager;
import awais.instagrabber.models.HighlightModel; import awais.instagrabber.models.HighlightModel;
@ -78,6 +84,7 @@ import awais.instagrabber.repositories.responses.FriendshipStatus;
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.UserProfileContextLink; import awais.instagrabber.repositories.responses.UserProfileContextLink;
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
import awais.instagrabber.utils.AppExecutors; import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils; import awais.instagrabber.utils.CookieUtils;
@ -128,6 +135,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
private HighlightsViewModel highlightsViewModel; private HighlightsViewModel highlightsViewModel;
private MenuItem blockMenuItem, restrictMenuItem, chainingMenuItem; private MenuItem blockMenuItem, restrictMenuItem, chainingMenuItem;
private MenuItem muteStoriesMenuItem, mutePostsMenuItem, removeFollowerMenuItem; private MenuItem muteStoriesMenuItem, mutePostsMenuItem, removeFollowerMenuItem;
private MenuItem shareLinkMenuItem, shareDmMenuItem;
private boolean accountIsUpdated = false; private boolean accountIsUpdated = false;
private boolean postsSetupDone = false; private boolean postsSetupDone = false;
private Set<Media> selectedFeedModels; private Set<Media> selectedFeedModels;
@ -143,6 +151,8 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
private ProfileFragmentViewModel viewModel; private ProfileFragmentViewModel viewModel;
private String csrfToken; private String csrfToken;
private String deviceUuid; private String deviceUuid;
private MutableLiveData<Object> backStackSavedStateCollectionLiveData;
private MutableLiveData<Object> backStackSavedStateResultLiveData;
private final ServiceCallback<FriendshipChangeResponse> changeCb = new ServiceCallback<FriendshipChangeResponse>() { private final ServiceCallback<FriendshipChangeResponse> changeCb = new ServiceCallback<FriendshipChangeResponse>() {
@Override @Override
@ -321,6 +331,32 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
} }
} }
}; };
private final Observer<Object> backStackSavedStateObserver = result -> {
if (result == null) return;
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<RankedRecipient>) result);
} catch (Exception e) {
Log.e(TAG, "share: ", e);
}
}
// clear result
backStackSavedStateCollectionLiveData.postValue(null);
backStackSavedStateResultLiveData.postValue(null);
};
@Override @Override
public void onCreate(@Nullable final Bundle savedInstanceState) { public void onCreate(@Nullable final Bundle savedInstanceState) {
@ -446,15 +482,24 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (removeFollowerMenuItem != null) { if (removeFollowerMenuItem != null) {
removeFollowerMenuItem.setVisible(isNotMe && profileModel.getFriendshipStatus().getFollowedBy()); removeFollowerMenuItem.setVisible(isNotMe && profileModel.getFriendshipStatus().getFollowedBy());
} }
shareLinkMenuItem = menu.findItem(R.id.share_link);
if (shareLinkMenuItem != null) {
shareLinkMenuItem.setVisible(profileModel != null && !TextUtils.isEmpty(profileModel.getUsername()));
}
shareDmMenuItem = menu.findItem(R.id.share_dm);
if (shareDmMenuItem != null) {
shareDmMenuItem.setVisible(profileModel != null && profileModel.getPk() != 0L);
}
} }
@Override @Override
public boolean onOptionsItemSelected(@NonNull final MenuItem item) { public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
if (item.getItemId() == R.id.layout) { switch (item.getItemId()) {
case R.id.layout: {
showPostsLayoutPreferences(); showPostsLayoutPreferences();
return true; return true;
} }
if (item.getItemId() == R.id.restrict) { case R.id.restrict: {
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
final String action = profileModel.getFriendshipStatus().isRestricted() ? "Unrestrict" : "Restrict"; final String action = profileModel.getFriendshipStatus().isRestricted() ? "Unrestrict" : "Restrict";
friendshipRepository.toggleRestrict( friendshipRepository.toggleRestrict(
@ -473,7 +518,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
); );
return true; return true;
} }
if (item.getItemId() == R.id.block) { case R.id.block: {
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
// changeCb // changeCb
friendshipRepository.changeBlock( friendshipRepository.changeBlock(
@ -492,7 +537,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
); );
return true; return true;
} }
if (item.getItemId() == R.id.chaining) { case R.id.chaining: {
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
final Bundle bundle = new Bundle(); final Bundle bundle = new Bundle();
bundle.putString("type", "chaining"); bundle.putString("type", "chaining");
@ -500,7 +545,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
NavHostFragment.findNavController(this).navigate(R.id.action_global_notificationsViewerFragment, bundle); NavHostFragment.findNavController(this).navigate(R.id.action_global_notificationsViewerFragment, bundle);
return true; return true;
} }
if (item.getItemId() == R.id.mute_stories) { case R.id.mute_stories: {
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
final String action = profileModel.getFriendshipStatus().isMutingReel() ? "Unmute stories" : "Mute stories"; final String action = profileModel.getFriendshipStatus().isMutingReel() ? "Unmute stories" : "Mute stories";
friendshipRepository.changeMute( friendshipRepository.changeMute(
@ -520,7 +565,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
); );
return true; return true;
} }
if (item.getItemId() == R.id.mute_posts) { case R.id.mute_posts: {
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
final String action = profileModel.getFriendshipStatus().getMuting() ? "Unmute stories" : "Mute stories"; final String action = profileModel.getFriendshipStatus().getMuting() ? "Unmute stories" : "Mute stories";
friendshipRepository.changeMute( friendshipRepository.changeMute(
@ -540,7 +585,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
); );
return true; return true;
} }
if (item.getItemId() == R.id.remove_follower) { case R.id.remove_follower: {
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
friendshipRepository.removeFollower( friendshipRepository.removeFollower(
csrfToken, csrfToken,
@ -557,8 +602,33 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
); );
return true; return true;
} }
case R.id.share_link: {
final Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, "https://instagram.com/" + profileModel.getUsername());
startActivity(sharingIntent);
return true;
}
case 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(ProfileFragment.this);
try {
navController.navigate(actionGlobalUserSearch);
} catch (Exception e) {
Log.e(TAG, "setupShare: ", e);
}
return true;
}
default:
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
}
@Override @Override
public void onRefresh() { public void onRefresh() {
@ -1029,6 +1099,12 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (removeFollowerMenuItem != null) { if (removeFollowerMenuItem != null) {
removeFollowerMenuItem.setVisible(profileModel.getFriendshipStatus().getFollowedBy()); removeFollowerMenuItem.setVisible(profileModel.getFriendshipStatus().getFollowedBy());
} }
if (shareLinkMenuItem != null) {
shareLinkMenuItem.setVisible(!TextUtils.isEmpty(profileModel.getUsername()));
}
if (shareDmMenuItem != null) {
shareDmMenuItem.setVisible(profileModel.getPk() != 0L);
}
} }
} }

View File

@ -4,6 +4,7 @@ import android.content.ContentResolver
import android.util.Log import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import awais.instagrabber.models.enums.BroadcastItemType
import awais.instagrabber.models.Resource import awais.instagrabber.models.Resource
import awais.instagrabber.models.Resource.Companion.error import awais.instagrabber.models.Resource.Companion.error
import awais.instagrabber.models.Resource.Companion.loading import awais.instagrabber.models.Resource.Companion.loading
@ -67,19 +68,20 @@ object DirectMessagesManager {
suspend fun createThread(userPk: Long): DirectThread = DirectMessagesService.createThread(csrfToken, viewerId, deviceUuid, listOf(userPk), null) suspend fun createThread(userPk: Long): DirectThread = DirectMessagesService.createThread(csrfToken, viewerId, deviceUuid, listOf(userPk), null)
fun sendMedia(recipient: RankedRecipient, mediaId: String, scope: CoroutineScope) { fun sendMedia(recipient: RankedRecipient, mediaId: String, itemType: BroadcastItemType, scope: CoroutineScope) {
sendMedia(setOf(recipient), mediaId, scope) sendMedia(setOf(recipient), mediaId, itemType, scope)
} }
fun sendMedia( fun sendMedia(
recipients: Set<RankedRecipient>, recipients: Set<RankedRecipient>,
mediaId: String, mediaId: String,
itemType: BroadcastItemType,
scope: CoroutineScope, scope: CoroutineScope,
) { ) {
val threadIds = recipients.mapNotNull{ it.thread?.threadId } val threadIds = recipients.mapNotNull{ it.thread?.threadId }
val userIdsTemp = recipients.mapNotNull{ it.user?.pk } val userIdsTemp = recipients.mapNotNull{ it.user?.pk }
val userIds = userIdsTemp.map{ listOf(it.toString(10)) } val userIds = userIdsTemp.map{ listOf(it.toString(10)) }
sendMedia(threadIds, userIds, mediaId, scope) { sendMedia(threadIds, userIds, mediaId, itemType, scope) {
inboxManager.refresh(scope) inboxManager.refresh(scope)
} }
} }
@ -88,6 +90,7 @@ object DirectMessagesManager {
threadIds: List<String>, threadIds: List<String>,
userIds: List<List<String>>, userIds: List<List<String>>,
mediaId: String, mediaId: String,
itemType: BroadcastItemType,
scope: CoroutineScope, scope: CoroutineScope,
callback: (() -> Unit)?, callback: (() -> Unit)?,
): LiveData<Resource<Any?>> { ): LiveData<Resource<Any?>> {
@ -95,6 +98,7 @@ object DirectMessagesManager {
data.postValue(loading(null)) data.postValue(loading(null))
scope.launch(Dispatchers.IO) { scope.launch(Dispatchers.IO) {
try { try {
if (itemType == BroadcastItemType.MEDIA_SHARE)
DirectMessagesService.broadcastMediaShare( DirectMessagesService.broadcastMediaShare(
csrfToken, csrfToken,
viewerId, viewerId,
@ -103,6 +107,15 @@ object DirectMessagesManager {
ThreadIdsOrUserIds(threadIds, userIds), ThreadIdsOrUserIds(threadIds, userIds),
mediaId mediaId
) )
if (itemType == BroadcastItemType.PROFILE)
DirectMessagesService.broadcastProfile(
csrfToken,
viewerId,
deviceUuid,
UUID.randomUUID().toString(),
ThreadIdsOrUserIds(threadIds, userIds),
mediaId
)
data.postValue(success(Any())) data.postValue(success(Any()))
callback?.invoke() callback?.invoke()
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import awais.instagrabber.R import awais.instagrabber.R
import awais.instagrabber.managers.DirectMessagesManager import awais.instagrabber.managers.DirectMessagesManager
import awais.instagrabber.models.enums.BroadcastItemType
import awais.instagrabber.models.Resource import awais.instagrabber.models.Resource
import awais.instagrabber.models.Resource.Companion.error import awais.instagrabber.models.Resource.Companion.error
import awais.instagrabber.models.Resource.Companion.loading import awais.instagrabber.models.Resource.Companion.loading
@ -335,7 +336,7 @@ class PostViewV2ViewModel : ViewModel() {
messageManager = DirectMessagesManager messageManager = DirectMessagesManager
} }
val mediaId = media.id ?: return val mediaId = media.id ?: return
messageManager?.sendMedia(result, mediaId, viewModelScope) messageManager?.sendMedia(result, mediaId, BroadcastItemType.MEDIA_SHARE, viewModelScope)
} }
fun shareDm(recipients: Set<RankedRecipient>) { fun shareDm(recipients: Set<RankedRecipient>) {
@ -343,6 +344,6 @@ class PostViewV2ViewModel : ViewModel() {
messageManager = DirectMessagesManager messageManager = DirectMessagesManager
} }
val mediaId = media.id ?: return val mediaId = media.id ?: return
messageManager?.sendMedia(recipients, mediaId, viewModelScope) messageManager?.sendMedia(recipients, mediaId, BroadcastItemType.MEDIA_SHARE, viewModelScope)
} }
} }

View File

@ -5,8 +5,11 @@ import androidx.lifecycle.*
import androidx.savedstate.SavedStateRegistryOwner import androidx.savedstate.SavedStateRegistryOwner
import awais.instagrabber.db.repositories.AccountRepository import awais.instagrabber.db.repositories.AccountRepository
import awais.instagrabber.db.repositories.FavoriteRepository import awais.instagrabber.db.repositories.FavoriteRepository
import awais.instagrabber.managers.DirectMessagesManager
import awais.instagrabber.models.enums.BroadcastItemType
import awais.instagrabber.models.Resource import awais.instagrabber.models.Resource
import awais.instagrabber.repositories.responses.User import awais.instagrabber.repositories.responses.User
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient
import awais.instagrabber.webservices.* import awais.instagrabber.webservices.*
class ProfileFragmentViewModel( class ProfileFragmentViewModel(
@ -21,6 +24,7 @@ class ProfileFragmentViewModel(
) : ViewModel() { ) : ViewModel() {
private val _profile = MutableLiveData<Resource<User?>>(Resource.loading(null)) private val _profile = MutableLiveData<Resource<User?>>(Resource.loading(null))
private val _isLoggedIn = MutableLiveData(false) private val _isLoggedIn = MutableLiveData(false)
private var messageManager: DirectMessagesManager? = null
val profile: LiveData<Resource<User?>> = _profile val profile: LiveData<Resource<User?>> = _profile
@ -58,6 +62,20 @@ class ProfileFragmentViewModel(
_profile.postValue(Resource.success(null)) _profile.postValue(Resource.success(null))
} }
} }
fun shareDm(result: RankedRecipient) {
if (messageManager == null) {
messageManager = DirectMessagesManager
}
// messageManager?.sendMedia(result, mediaId, BroadcastItemType.PROFILE, viewModelScope)
}
fun shareDm(recipients: Set<RankedRecipient>) {
if (messageManager == null) {
messageManager = DirectMessagesManager
}
// messageManager?.sendMedia(recipients, mediaId, BroadcastItemType.PROFILE, viewModelScope)
}
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")

View File

@ -167,6 +167,16 @@ object DirectMessagesService {
): DirectThreadBroadcastResponse = ): DirectThreadBroadcastResponse =
broadcast(csrfToken, userId, deviceUuid, MediaShareBroadcastOptions(clientContext, threadIdsOrUserIds, mediaId)) broadcast(csrfToken, userId, deviceUuid, MediaShareBroadcastOptions(clientContext, threadIdsOrUserIds, mediaId))
suspend fun broadcastProfile(
csrfToken: String,
userId: Long,
deviceUuid: String,
clientContext: String,
threadIdsOrUserIds: ThreadIdsOrUserIds,
profileId: String,
): DirectThreadBroadcastResponse =
broadcast(csrfToken, userId, deviceUuid, ProfileBroadcastOptions(clientContext, threadIdsOrUserIds, profileId))
private suspend fun broadcast( private suspend fun broadcast(
csrfToken: String, csrfToken: String,
userId: Long, userId: Long,

View File

@ -15,36 +15,43 @@
<item <item
android:id="@+id/block" android:id="@+id/block"
android:icon="@drawable/ic_block_24"
android:title="@string/block" android:title="@string/block"
android:visible="false" android:visible="false"
app:showAsAction="never" /> app:showAsAction="never" />
<item <item
android:id="@+id/restrict" android:id="@+id/restrict"
android:icon="@drawable/ic_highlight_off_24"
android:title="@string/restrict" android:title="@string/restrict"
android:visible="false" android:visible="false"
app:showAsAction="never" /> app:showAsAction="never" />
<item <item
android:id="@+id/remove_follower" android:id="@+id/remove_follower"
android:icon="@drawable/ic_block_24"
android:title="@string/remove_follower" android:title="@string/remove_follower"
android:visible="false" android:visible="false"
app:showAsAction="never" /> app:showAsAction="never" />
<item <item
android:id="@+id/mute_stories" android:id="@+id/mute_stories"
android:icon="@drawable/ic_highlight_off_24"
android:title="@string/mute_stories" android:title="@string/mute_stories"
android:visible="false" android:visible="false"
app:showAsAction="never" /> app:showAsAction="never" />
<item <item
android:id="@+id/mute_posts" android:id="@+id/mute_posts"
android:icon="@drawable/ic_highlight_off_24"
android:title="@string/mute_posts" android:title="@string/mute_posts"
android:visible="false" android:visible="false"
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:id="@+id/share_link"
android:title="@string/share_link"
android:visible="false"
app:showAsAction="never" />
<item
android:id="@+id/share_dm"
android:title="@string/share_via_dm"
android:visible="false"
app:showAsAction="never" />
</menu> </menu>