mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-22 06:37:30 +00:00
Centralised syncing of inbox.
This commit is contained in:
parent
ea7236dcc1
commit
a7a595f8d4
@ -39,8 +39,8 @@ android {
|
|||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
minifyEnabled true
|
// minifyEnabled true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
|
|
||||||
release {
|
release {
|
||||||
@ -62,7 +62,7 @@ dependencies {
|
|||||||
def nav_version = '2.3.2'
|
def nav_version = '2.3.2'
|
||||||
def exoplayer_version = '2.12.0'
|
def exoplayer_version = '2.12.0'
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.3.0-beta01'
|
implementation 'com.google.android.material:material:1.3.0-rc01'
|
||||||
|
|
||||||
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"
|
||||||
|
@ -38,6 +38,7 @@ import androidx.emoji.text.FontRequestEmojiCompatConfig;
|
|||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.NavBackStackEntry;
|
import androidx.navigation.NavBackStackEntry;
|
||||||
import androidx.navigation.NavController;
|
import androidx.navigation.NavController;
|
||||||
import androidx.navigation.NavDestination;
|
import androidx.navigation.NavDestination;
|
||||||
@ -75,6 +76,7 @@ import awais.instagrabber.utils.IntentUtils;
|
|||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
import awais.instagrabber.utils.emoji.EmojiParser;
|
import awais.instagrabber.utils.emoji.EmojiParser;
|
||||||
|
import awais.instagrabber.viewmodels.AppStateViewModel;
|
||||||
|
|
||||||
import static awais.instagrabber.utils.NavigationExtensions.setupWithNavController;
|
import static awais.instagrabber.utils.NavigationExtensions.setupWithNavController;
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
@ -102,6 +104,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
private int firstFragmentGraphIndex;
|
private int firstFragmentGraphIndex;
|
||||||
private boolean isActivityCheckerServiceBound = false;
|
private boolean isActivityCheckerServiceBound = false;
|
||||||
private boolean isBackStackEmpty = false;
|
private boolean isBackStackEmpty = false;
|
||||||
|
private boolean isLoggedIn;
|
||||||
|
|
||||||
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
||||||
@Override
|
@Override
|
||||||
@ -131,6 +134,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||||
CookieUtils.setupCookies(cookie);
|
CookieUtils.setupCookies(cookie);
|
||||||
|
isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) != 0;
|
||||||
setContentView(binding.getRoot());
|
setContentView(binding.getRoot());
|
||||||
final Toolbar toolbar = binding.toolbar;
|
final Toolbar toolbar = binding.toolbar;
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
@ -142,6 +146,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
final boolean checkUpdates = settingsHelper.getBoolean(Constants.CHECK_UPDATES);
|
final boolean checkUpdates = settingsHelper.getBoolean(Constants.CHECK_UPDATES);
|
||||||
if (checkUpdates) FlavorTown.updateCheck(this);
|
if (checkUpdates) FlavorTown.updateCheck(this);
|
||||||
FlavorTown.changelogCheck(this);
|
FlavorTown.changelogCheck(this);
|
||||||
|
new ViewModelProvider(this).get(AppStateViewModel.class); // Just initiate the App state here
|
||||||
final Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
handleIntent(intent);
|
handleIntent(intent);
|
||||||
if (!TextUtils.isEmpty(cookie) && settingsHelper.getBoolean(Constants.CHECK_ACTIVITY)) {
|
if (!TextUtils.isEmpty(cookie) && settingsHelper.getBoolean(Constants.CHECK_ACTIVITY)) {
|
||||||
@ -387,8 +392,6 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
|
|
||||||
private void setupBottomNavigationBar(final boolean setDefaultFromSettings) {
|
private void setupBottomNavigationBar(final boolean setDefaultFromSettings) {
|
||||||
int main_nav_ids = R.array.main_nav_ids;
|
int main_nav_ids = R.array.main_nav_ids;
|
||||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
|
||||||
final boolean isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) != 0;
|
|
||||||
if (!isLoggedIn) {
|
if (!isLoggedIn) {
|
||||||
main_nav_ids = R.array.logged_out_main_nav_ids;
|
main_nav_ids = R.array.logged_out_main_nav_ids;
|
||||||
final int selectedItemId = binding.bottomNavView.getSelectedItemId();
|
final int selectedItemId = binding.bottomNavView.getSelectedItemId();
|
||||||
|
@ -258,7 +258,7 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView.
|
|||||||
public void setThread(final DirectThread thread) {
|
public void setThread(final DirectThread thread) {
|
||||||
if (thread == null) return;
|
if (thread == null) return;
|
||||||
this.thread = thread;
|
this.thread = thread;
|
||||||
notifyDataSetChanged();
|
// notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void submitList(@Nullable final List<DirectItem> list) {
|
public void submitList(@Nullable final List<DirectItem> list) {
|
||||||
|
@ -36,7 +36,9 @@ public final class DirectMessageInboxAdapter extends ListAdapter<DirectThread, D
|
|||||||
final DirectItem oldItemFirst = oldThread.getFirstDirectItem();
|
final DirectItem oldItemFirst = oldThread.getFirstDirectItem();
|
||||||
final DirectItem newItemFirst = newThread.getFirstDirectItem();
|
final DirectItem newItemFirst = newThread.getFirstDirectItem();
|
||||||
if (oldItemFirst == null || newItemFirst == null) return false;
|
if (oldItemFirst == null || newItemFirst == null) return false;
|
||||||
return oldItemFirst.getItemId().equals(newItemFirst.getItemId());
|
final boolean idsEqual = oldItemFirst.getItemId().equals(newItemFirst.getItemId());
|
||||||
|
if (!idsEqual) return false;
|
||||||
|
return oldItemFirst.getTimestamp() == newItemFirst.getTimestamp();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -349,9 +349,19 @@ public final class DirectInboxItemViewHolder extends RecyclerView.ViewHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setReadState(@NonNull final DirectThread thread) {
|
private void setReadState(@NonNull final DirectThread thread) {
|
||||||
final DirectItem item = thread.getItems().get(0);
|
final boolean read;
|
||||||
final Map<Long, DirectThreadLastSeenAt> lastSeenAtMap = thread.getLastSeenAt();
|
if (thread.getDirectStory() != null) {
|
||||||
final boolean read = ResponseBodyUtils.isRead(item, lastSeenAtMap, Collections.singletonList(thread.getViewerId()), thread.getDirectStory());
|
read = false;
|
||||||
|
} else {
|
||||||
|
final DirectItem item = thread.getFirstDirectItem();
|
||||||
|
if (item.getUserId() == thread.getViewerId()) {
|
||||||
|
// if last item was sent by user, then it is read (even though we have auto read unchecked?)
|
||||||
|
read = true;
|
||||||
|
} else {
|
||||||
|
final Map<Long, DirectThreadLastSeenAt> lastSeenAtMap = thread.getLastSeenAt();
|
||||||
|
read = ResponseBodyUtils.isRead(item, lastSeenAtMap, Collections.singletonList(thread.getViewerId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
binding.unread.setVisibility(read ? View.GONE : View.VISIBLE);
|
binding.unread.setVisibility(read ? View.GONE : View.VISIBLE);
|
||||||
binding.threadTitle.setTypeface(binding.threadTitle.getTypeface(), read ? Typeface.NORMAL : Typeface.BOLD);
|
binding.threadTitle.setTypeface(binding.threadTitle.getTypeface(), read ? Typeface.NORMAL : Typeface.BOLD);
|
||||||
binding.subtitle.setTypeface(binding.subtitle.getTypeface(), read ? Typeface.NORMAL : Typeface.BOLD);
|
binding.subtitle.setTypeface(binding.subtitle.getTypeface(), read ? Typeface.NORMAL : Typeface.BOLD);
|
||||||
|
@ -196,7 +196,10 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder imple
|
|||||||
if (item.isPending()) {
|
if (item.isPending()) {
|
||||||
binding.deliveryStatus.setImageResource(R.drawable.ic_check_24);
|
binding.deliveryStatus.setImageResource(R.drawable.ic_check_24);
|
||||||
} else {
|
} else {
|
||||||
final boolean read = ResponseBodyUtils.isRead(item, thread.getLastSeenAt(), userIds, null);
|
final boolean read = ResponseBodyUtils.isRead(item,
|
||||||
|
thread.getLastSeenAt(),
|
||||||
|
userIds
|
||||||
|
);
|
||||||
binding.deliveryStatus.setImageResource(R.drawable.ic_check_all_24);
|
binding.deliveryStatus.setImageResource(R.drawable.ic_check_all_24);
|
||||||
ImageViewCompat.setImageTintList(
|
ImageViewCompat.setImageTintList(
|
||||||
binding.deliveryStatus,
|
binding.deliveryStatus,
|
||||||
@ -358,7 +361,7 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder imple
|
|||||||
final DirectItemReactions reactions = item.getReactions();
|
final DirectItemReactions reactions = item.getReactions();
|
||||||
final List<DirectItemEmojiReaction> emojis = reactions != null ? reactions.getEmojis() : null;
|
final List<DirectItemEmojiReaction> emojis = reactions != null ? reactions.getEmojis() : null;
|
||||||
if (emojis == null || emojis.isEmpty()) {
|
if (emojis == null || emojis.isEmpty()) {
|
||||||
binding.container.setPadding(messageInfoPaddingSmall, messageInfoPaddingSmall, messageInfoPaddingSmall, messageInfoPaddingSmall);
|
binding.container.setPadding(messageInfoPaddingSmall, messageInfoPaddingSmall, messageInfoPaddingSmall, 0);
|
||||||
binding.reactionsWrapper.setVisibility(View.GONE);
|
binding.reactionsWrapper.setVisibility(View.GONE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ 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.bottomnavigation.BottomNavigationView;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -172,6 +173,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupObservers() {
|
private void setupObservers() {
|
||||||
|
removeViewModelObservers();
|
||||||
threadsObserver = list -> {
|
threadsObserver = list -> {
|
||||||
if (inboxAdapter == null) return;
|
if (inboxAdapter == null) return;
|
||||||
inboxAdapter.submitList(list, () -> {
|
inboxAdapter.submitList(list, () -> {
|
||||||
@ -181,8 +183,28 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
viewModel.getThreads().observe(fragmentActivity, threadsObserver);
|
viewModel.getThreads().observe(fragmentActivity, threadsObserver);
|
||||||
viewModel.getFetchingInbox().observe(getViewLifecycleOwner(), fetching -> binding.swipeRefreshLayout.setRefreshing(fetching));
|
viewModel.getInbox().observe(getViewLifecycleOwner(), inboxResource -> {
|
||||||
viewModel.getUnseenCount().observe(getViewLifecycleOwner(), this::setBottomNavBarBadge);
|
if (inboxResource == null) return;
|
||||||
|
switch (inboxResource.status) {
|
||||||
|
case SUCCESS:
|
||||||
|
binding.swipeRefreshLayout.setRefreshing(false);
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
if (inboxResource.message != null) {
|
||||||
|
Snackbar.make(binding.getRoot(), inboxResource.message, Snackbar.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
binding.swipeRefreshLayout.setRefreshing(false);
|
||||||
|
break;
|
||||||
|
case LOADING:
|
||||||
|
binding.swipeRefreshLayout.setRefreshing(true);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,11 +252,10 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
inboxAdapter = new DirectMessageInboxAdapter(thread -> {
|
inboxAdapter = new DirectMessageInboxAdapter(thread -> {
|
||||||
if (navigating) return;
|
if (navigating) return;
|
||||||
navigating = true;
|
navigating = true;
|
||||||
final Bundle bundle = new Bundle();
|
|
||||||
bundle.putString("threadId", thread.getThreadId());
|
|
||||||
bundle.putString("title", thread.getThreadTitle());
|
|
||||||
if (isAdded()) {
|
if (isAdded()) {
|
||||||
NavHostFragment.findNavController(this).navigate(R.id.action_inbox_to_thread, bundle);
|
final DirectMessageInboxFragmentDirections.ActionInboxToThread directions = DirectMessageInboxFragmentDirections
|
||||||
|
.actionInboxToThread(thread.getThreadId(), thread.getThreadTitle());
|
||||||
|
NavHostFragment.findNavController(this).navigate(directions);
|
||||||
}
|
}
|
||||||
navigating = false;
|
navigating = false;
|
||||||
});
|
});
|
||||||
|
@ -11,13 +11,11 @@ import android.widget.CompoundButton;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.util.Pair;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.lifecycle.ViewModelStoreOwner;
|
|
||||||
import androidx.navigation.NavBackStackEntry;
|
import androidx.navigation.NavBackStackEntry;
|
||||||
import androidx.navigation.NavController;
|
import androidx.navigation.NavController;
|
||||||
import androidx.navigation.NavDestination;
|
import androidx.navigation.NavDestination;
|
||||||
@ -31,13 +29,13 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import awais.instagrabber.ProfileNavGraphDirections;
|
import awais.instagrabber.ProfileNavGraphDirections;
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.UserSearchNavGraphDirections;
|
import awais.instagrabber.UserSearchNavGraphDirections;
|
||||||
|
import awais.instagrabber.activities.MainActivity;
|
||||||
import awais.instagrabber.adapters.DirectPendingUsersAdapter;
|
import awais.instagrabber.adapters.DirectPendingUsersAdapter;
|
||||||
import awais.instagrabber.adapters.DirectPendingUsersAdapter.PendingUser;
|
import awais.instagrabber.adapters.DirectPendingUsersAdapter.PendingUser;
|
||||||
import awais.instagrabber.adapters.DirectPendingUsersAdapter.PendingUserCallback;
|
import awais.instagrabber.adapters.DirectPendingUsersAdapter.PendingUserCallback;
|
||||||
@ -52,12 +50,11 @@ import awais.instagrabber.fragments.UserSearchFragment;
|
|||||||
import awais.instagrabber.fragments.UserSearchFragmentDirections;
|
import awais.instagrabber.fragments.UserSearchFragmentDirections;
|
||||||
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.DirectThread;
|
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThreadParticipantRequestsResponse;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThreadParticipantRequestsResponse;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
|
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
|
||||||
import awais.instagrabber.viewmodels.DirectInboxViewModel;
|
import awais.instagrabber.viewmodels.AppStateViewModel;
|
||||||
import awais.instagrabber.viewmodels.DirectPendingInboxViewModel;
|
|
||||||
import awais.instagrabber.viewmodels.DirectSettingsViewModel;
|
import awais.instagrabber.viewmodels.DirectSettingsViewModel;
|
||||||
|
import awais.instagrabber.viewmodels.factories.DirectSettingsViewModelFactory;
|
||||||
|
|
||||||
public class DirectMessageSettingsFragment extends Fragment implements ConfirmDialogFragmentCallback {
|
public class DirectMessageSettingsFragment extends Fragment implements ConfirmDialogFragmentCallback {
|
||||||
private static final String TAG = DirectMessageSettingsFragment.class.getSimpleName();
|
private static final String TAG = DirectMessageSettingsFragment.class.getSimpleName();
|
||||||
@ -77,33 +74,14 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
final Bundle arguments = getArguments();
|
final Bundle arguments = getArguments();
|
||||||
if (arguments == null) return;
|
if (arguments == null) return;
|
||||||
final NavController navController = NavHostFragment.findNavController(this);
|
|
||||||
final ViewModelStoreOwner viewModelStoreOwner = navController.getViewModelStoreOwner(R.id.direct_messages_nav_graph);
|
|
||||||
final DirectMessageSettingsFragmentArgs args = DirectMessageSettingsFragmentArgs.fromBundle(arguments);
|
final DirectMessageSettingsFragmentArgs args = DirectMessageSettingsFragmentArgs.fromBundle(arguments);
|
||||||
final boolean pending = args.getPending();
|
final MainActivity fragmentActivity = (MainActivity) requireActivity();
|
||||||
final List<DirectThread> threads;
|
final AppStateViewModel appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class);
|
||||||
final User viewer;
|
viewModel = new ViewModelProvider(this, new DirectSettingsViewModelFactory(fragmentActivity.getApplication(),
|
||||||
if (pending) {
|
args.getThreadId(),
|
||||||
final DirectPendingInboxViewModel inboxViewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectPendingInboxViewModel.class);
|
args.getPending(),
|
||||||
threads = inboxViewModel.getThreads().getValue();
|
appStateViewModel.getCurrentUser()))
|
||||||
viewer = inboxViewModel.getViewer();
|
.get(DirectSettingsViewModel.class);
|
||||||
} else {
|
|
||||||
final DirectInboxViewModel inboxViewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectInboxViewModel.class);
|
|
||||||
threads = inboxViewModel.getThreads().getValue();
|
|
||||||
viewer = inboxViewModel.getViewer();
|
|
||||||
}
|
|
||||||
final String threadId = args.getThreadId();
|
|
||||||
final Optional<DirectThread> first = threads != null ? threads.stream()
|
|
||||||
.filter(thread -> thread.getThreadId().equals(threadId))
|
|
||||||
.findFirst()
|
|
||||||
: Optional.empty();
|
|
||||||
if (!first.isPresent()) {
|
|
||||||
navController.navigateUp();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
viewModel = new ViewModelProvider(this).get(DirectSettingsViewModel.class);
|
|
||||||
viewModel.setViewer(viewer);
|
|
||||||
viewModel.setThread(first.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -143,21 +121,23 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
binding.muteMessages.setVisibility(View.GONE);
|
binding.muteMessages.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
viewModel.getUsers().observe(getViewLifecycleOwner(), users -> {
|
// Need to observe, so that getValue is correct
|
||||||
|
viewModel.getUsers().observe(getViewLifecycleOwner(), users -> {});
|
||||||
|
viewModel.getLeftUsers().observe(getViewLifecycleOwner(), users -> {});
|
||||||
|
viewModel.getUsersAndLeftUsers().observe(getViewLifecycleOwner(), usersPair -> {
|
||||||
if (usersAdapter == null) return;
|
if (usersAdapter == null) return;
|
||||||
usersAdapter.submitUsers(users.first, users.second);
|
usersAdapter.submitUsers(usersPair.first, usersPair.second);
|
||||||
});
|
});
|
||||||
viewModel.getTitle().observe(getViewLifecycleOwner(), title -> binding.titleEdit.setText(title));
|
viewModel.getTitle().observe(getViewLifecycleOwner(), title -> binding.titleEdit.setText(title));
|
||||||
viewModel.getAdminUserIds().observe(getViewLifecycleOwner(), adminUserIds -> {
|
viewModel.getAdminUserIds().observe(getViewLifecycleOwner(), adminUserIds -> {
|
||||||
if (usersAdapter == null) return;
|
if (usersAdapter == null) return;
|
||||||
usersAdapter.setAdminUserIds(adminUserIds);
|
usersAdapter.setAdminUserIds(adminUserIds);
|
||||||
});
|
});
|
||||||
viewModel.getMuted().observe(getViewLifecycleOwner(), muted -> binding.muteMessages.setChecked(muted));
|
viewModel.isMuted().observe(getViewLifecycleOwner(), muted -> binding.muteMessages.setChecked(muted));
|
||||||
viewModel.isPending().observe(getViewLifecycleOwner(), pending -> binding.muteMessages.setVisibility(pending ? View.GONE : View.VISIBLE));
|
viewModel.isPending().observe(getViewLifecycleOwner(), pending -> binding.muteMessages.setVisibility(pending ? View.GONE : View.VISIBLE));
|
||||||
if (viewModel.isViewerAdmin()) {
|
viewModel.isViewerAdmin().observe(getViewLifecycleOwner(), this::setApprovalRelatedUI);
|
||||||
viewModel.getApprovalRequiredToJoin().observe(getViewLifecycleOwner(), required -> binding.approvalRequired.setChecked(required));
|
viewModel.getApprovalRequiredToJoin().observe(getViewLifecycleOwner(), required -> binding.approvalRequired.setChecked(required));
|
||||||
viewModel.getPendingRequests().observe(getViewLifecycleOwner(), this::setPendingRequests);
|
viewModel.getPendingRequests().observe(getViewLifecycleOwner(), this::setPendingRequests);
|
||||||
}
|
|
||||||
final NavController navController = NavHostFragment.findNavController(this);
|
final NavController navController = NavHostFragment.findNavController(this);
|
||||||
final NavBackStackEntry backStackEntry = navController.getCurrentBackStackEntry();
|
final NavBackStackEntry backStackEntry = navController.getCurrentBackStackEntry();
|
||||||
if (backStackEntry != null) {
|
if (backStackEntry != null) {
|
||||||
@ -192,7 +172,11 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
|
|
||||||
private void addMembers(final Set<User> users) {
|
private void addMembers(final Set<User> users) {
|
||||||
final Boolean approvalRequired = viewModel.getApprovalRequiredToJoin().getValue();
|
final Boolean approvalRequired = viewModel.getApprovalRequiredToJoin().getValue();
|
||||||
if (!viewModel.isViewerAdmin() && approvalRequired != null && approvalRequired) {
|
Boolean isViewerAdmin = viewModel.isViewerAdmin().getValue();
|
||||||
|
if (isViewerAdmin == null) {
|
||||||
|
isViewerAdmin = false;
|
||||||
|
}
|
||||||
|
if (!isViewerAdmin && approvalRequired != null && approvalRequired) {
|
||||||
approvalRequiredUsers = users;
|
approvalRequiredUsers = users;
|
||||||
final ConfirmDialogFragment confirmDialogFragment = ConfirmDialogFragment.newInstance(
|
final ConfirmDialogFragment confirmDialogFragment = ConfirmDialogFragment.newInstance(
|
||||||
APPROVAL_REQUIRED_REQUEST_CODE,
|
APPROVAL_REQUIRED_REQUEST_CODE,
|
||||||
@ -226,13 +210,15 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupSettings() {
|
private void setupSettings() {
|
||||||
binding.groupSettings.setVisibility(viewModel.isGroup() ? View.VISIBLE : View.GONE);
|
Boolean isGroup = viewModel.isGroup().getValue();
|
||||||
|
if (isGroup == null) isGroup = false;
|
||||||
|
binding.groupSettings.setVisibility(isGroup ? View.VISIBLE : View.GONE);
|
||||||
binding.muteMessagesLabel.setOnClickListener(v -> binding.muteMessages.toggle());
|
binding.muteMessagesLabel.setOnClickListener(v -> binding.muteMessages.toggle());
|
||||||
binding.muteMessages.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
binding.muteMessages.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||||
final LiveData<Resource<Object>> resourceLiveData = isChecked ? viewModel.mute() : viewModel.unmute();
|
final LiveData<Resource<Object>> resourceLiveData = isChecked ? viewModel.mute() : viewModel.unmute();
|
||||||
handleSwitchChangeResource(resourceLiveData, buttonView);
|
handleSwitchChangeResource(resourceLiveData, buttonView);
|
||||||
});
|
});
|
||||||
if (!viewModel.isGroup()) return;
|
if (!isGroup) return;
|
||||||
binding.titleEdit.addTextChangedListener(new TextWatcherAdapter() {
|
binding.titleEdit.addTextChangedListener(new TextWatcherAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
|
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
|
||||||
@ -256,14 +242,13 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
final NavDestination currentDestination = navController.getCurrentDestination();
|
final NavDestination currentDestination = navController.getCurrentDestination();
|
||||||
if (currentDestination == null) return;
|
if (currentDestination == null) return;
|
||||||
if (currentDestination.getId() != R.id.directMessagesSettingsFragment) return;
|
if (currentDestination.getId() != R.id.directMessagesSettingsFragment) return;
|
||||||
final Pair<List<User>, List<User>> users = viewModel.getUsers().getValue();
|
final List<User> users = viewModel.getUsers().getValue();
|
||||||
final long[] currentUserIds;
|
final long[] currentUserIds;
|
||||||
if (users != null && users.first != null) {
|
if (users != null) {
|
||||||
final List<User> currentMembers = users.first;
|
currentUserIds = users.stream()
|
||||||
currentUserIds = currentMembers.stream()
|
.mapToLong(User::getPk)
|
||||||
.mapToLong(User::getPk)
|
.sorted()
|
||||||
.sorted()
|
.toArray();
|
||||||
.toArray();
|
|
||||||
} else {
|
} else {
|
||||||
currentUserIds = new long[0];
|
currentUserIds = new long[0];
|
||||||
}
|
}
|
||||||
@ -281,7 +266,6 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
final LiveData<Resource<Object>> resourceLiveData = isChecked ? viewModel.muteMentions() : viewModel.unmuteMentions();
|
final LiveData<Resource<Object>> resourceLiveData = isChecked ? viewModel.muteMentions() : viewModel.unmuteMentions();
|
||||||
handleSwitchChangeResource(resourceLiveData, buttonView);
|
handleSwitchChangeResource(resourceLiveData, buttonView);
|
||||||
});
|
});
|
||||||
setApprovalRelatedUI();
|
|
||||||
binding.leave.setOnClickListener(v -> {
|
binding.leave.setOnClickListener(v -> {
|
||||||
final ConfirmDialogFragment confirmDialogFragment = ConfirmDialogFragment.newInstance(
|
final ConfirmDialogFragment confirmDialogFragment = ConfirmDialogFragment.newInstance(
|
||||||
LEAVE_THREAD_REQUEST_CODE,
|
LEAVE_THREAD_REQUEST_CODE,
|
||||||
@ -293,7 +277,9 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
);
|
);
|
||||||
confirmDialogFragment.show(getChildFragmentManager(), "leave_thread_confirmation_dialog");
|
confirmDialogFragment.show(getChildFragmentManager(), "leave_thread_confirmation_dialog");
|
||||||
});
|
});
|
||||||
if (viewModel.isViewerAdmin()) {
|
Boolean isViewerAdmin = viewModel.isViewerAdmin().getValue();
|
||||||
|
if (isViewerAdmin == null) isViewerAdmin = false;
|
||||||
|
if (isViewerAdmin) {
|
||||||
binding.end.setVisibility(View.VISIBLE);
|
binding.end.setVisibility(View.VISIBLE);
|
||||||
binding.end.setOnClickListener(v -> {
|
binding.end.setOnClickListener(v -> {
|
||||||
final ConfirmDialogFragment confirmDialogFragment = ConfirmDialogFragment.newInstance(
|
final ConfirmDialogFragment confirmDialogFragment = ConfirmDialogFragment.newInstance(
|
||||||
@ -311,8 +297,8 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setApprovalRelatedUI() {
|
private void setApprovalRelatedUI(final boolean isViewerAdmin) {
|
||||||
if (!viewModel.isViewerAdmin()) {
|
if (!isViewerAdmin) {
|
||||||
binding.pendingMembersGroup.setVisibility(View.GONE);
|
binding.pendingMembersGroup.setVisibility(View.GONE);
|
||||||
binding.approvalRequired.setVisibility(View.GONE);
|
binding.approvalRequired.setVisibility(View.GONE);
|
||||||
binding.approvalRequiredLabel.setVisibility(View.GONE);
|
binding.approvalRequiredLabel.setVisibility(View.GONE);
|
||||||
@ -352,7 +338,7 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
if (context == null) return;
|
if (context == null) return;
|
||||||
binding.users.setLayoutManager(new LinearLayoutManager(context));
|
binding.users.setLayoutManager(new LinearLayoutManager(context));
|
||||||
final User inviter = viewModel.getThread().getInviter();
|
final User inviter = viewModel.getInviter().getValue();
|
||||||
usersAdapter = new DirectUsersAdapter(
|
usersAdapter = new DirectUsersAdapter(
|
||||||
inviter != null ? inviter.getPk() : -1,
|
inviter != null ? inviter.getPk() : -1,
|
||||||
(position, user, selected) -> {
|
(position, user, selected) -> {
|
||||||
|
@ -37,7 +37,6 @@ import androidx.lifecycle.MediatorLiveData;
|
|||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.lifecycle.ViewModelStoreOwner;
|
|
||||||
import androidx.navigation.NavBackStackEntry;
|
import androidx.navigation.NavBackStackEntry;
|
||||||
import androidx.navigation.NavController;
|
import androidx.navigation.NavController;
|
||||||
import androidx.navigation.NavDirections;
|
import androidx.navigation.NavDirections;
|
||||||
@ -58,7 +57,6 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import awais.instagrabber.ProfileNavGraphDirections;
|
import awais.instagrabber.ProfileNavGraphDirections;
|
||||||
@ -104,9 +102,8 @@ import awais.instagrabber.utils.ResponseBodyUtils;
|
|||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
import awais.instagrabber.viewmodels.AppStateViewModel;
|
import awais.instagrabber.viewmodels.AppStateViewModel;
|
||||||
import awais.instagrabber.viewmodels.DirectInboxViewModel;
|
|
||||||
import awais.instagrabber.viewmodels.DirectPendingInboxViewModel;
|
|
||||||
import awais.instagrabber.viewmodels.DirectThreadViewModel;
|
import awais.instagrabber.viewmodels.DirectThreadViewModel;
|
||||||
|
import awais.instagrabber.viewmodels.factories.DirectThreadViewModelFactory;
|
||||||
|
|
||||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
|
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
|
||||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
|
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
|
||||||
@ -235,7 +232,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
@Override
|
@Override
|
||||||
public void onReaction(final DirectItem item, final Emoji emoji) {
|
public void onReaction(final DirectItem item, final Emoji emoji) {
|
||||||
if (item == null) return;
|
if (item == null) return;
|
||||||
final LiveData<Resource<DirectItem>> resourceLiveData = viewModel.sendReaction(item, emoji);
|
final LiveData<Resource<Object>> resourceLiveData = viewModel.sendReaction(item, emoji);
|
||||||
if (resourceLiveData != null) {
|
if (resourceLiveData != null) {
|
||||||
resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData));
|
resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData));
|
||||||
}
|
}
|
||||||
@ -295,13 +292,29 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
};
|
};
|
||||||
private final MutableLiveData<Integer> inputLength = new MutableLiveData<>(0);
|
private final MutableLiveData<Integer> inputLength = new MutableLiveData<>(0);
|
||||||
private ItemTouchHelper itemTouchHelper;
|
private ItemTouchHelper itemTouchHelper;
|
||||||
|
private LiveData<Boolean> pendingLiveData;
|
||||||
|
private LiveData<DirectThread> threadLiveData;
|
||||||
|
private LiveData<Integer> inputModeLiveData;
|
||||||
|
private LiveData<String> threadTitleLiveData;
|
||||||
|
private LiveData<Resource<Object>> fetchingLiveData;
|
||||||
|
private LiveData<List<DirectItem>> itemsLiveData;
|
||||||
|
private LiveData<DirectItem> replyToItemLiveData;
|
||||||
|
private LiveData<Integer> pendingRequestsCountLiveData;
|
||||||
|
private LiveData<List<User>> usersLiveData;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
fragmentActivity = (MainActivity) requireActivity();
|
fragmentActivity = (MainActivity) requireActivity();
|
||||||
appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class);
|
appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class);
|
||||||
viewModel = new ViewModelProvider(this).get(DirectThreadViewModel.class);
|
final Bundle arguments = getArguments();
|
||||||
|
if (arguments == null) return;
|
||||||
|
final DirectMessageThreadFragmentArgs fragmentArgs = DirectMessageThreadFragmentArgs.fromBundle(arguments);
|
||||||
|
viewModel = new ViewModelProvider(this, new DirectThreadViewModelFactory(fragmentActivity.getApplication(),
|
||||||
|
fragmentArgs.getThreadId(),
|
||||||
|
fragmentArgs.getPending(),
|
||||||
|
appStateViewModel.getCurrentUser()))
|
||||||
|
.get(DirectThreadViewModel.class);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,7 +345,6 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
init();
|
init();
|
||||||
binding.send.post(() -> initialSendX = binding.send.getX());
|
binding.send.post(() -> initialSendX = binding.send.getX());
|
||||||
shouldRefresh = false;
|
shouldRefresh = false;
|
||||||
setObservers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -406,6 +418,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
wasKbShowing = true;
|
wasKbShowing = true;
|
||||||
binding.emojiPicker.setAlpha(0);
|
binding.emojiPicker.setAlpha(0);
|
||||||
}
|
}
|
||||||
|
removeObservers();
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,7 +436,8 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
}
|
}
|
||||||
binding.send.stopScale();
|
binding.send.stopScale();
|
||||||
setupBackStackResultObserver();
|
setupBackStackResultObserver();
|
||||||
attachPendingRequestsBadge(viewModel.getPendingRequestsCount().getValue());
|
setObservers();
|
||||||
|
// attachPendingRequestsBadge(viewModel.getPendingRequestsCount().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -463,42 +477,38 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
if (context == null) return;
|
if (context == null) return;
|
||||||
if (getArguments() == null) return;
|
if (getArguments() == null) return;
|
||||||
actionBar = fragmentActivity.getSupportActionBar();
|
actionBar = fragmentActivity.getSupportActionBar();
|
||||||
final DirectMessageThreadFragmentArgs fragmentArgs = DirectMessageThreadFragmentArgs.fromBundle(getArguments());
|
|
||||||
viewModel.getThreadTitle().postValue(fragmentArgs.getTitle());
|
|
||||||
final String threadId = fragmentArgs.getThreadId();
|
|
||||||
viewModel.setThreadId(threadId);
|
|
||||||
setupList();
|
setupList();
|
||||||
root.post(this::setupInput);
|
root.post(this::setupInput);
|
||||||
root.post(this::getInitialData);
|
// root.post(this::getInitialData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getInitialData() {
|
// private void getInitialData() {
|
||||||
final Bundle arguments = getArguments();
|
// final Bundle arguments = getArguments();
|
||||||
if (arguments == null) return;
|
// if (arguments == null) return;
|
||||||
final DirectMessageThreadFragmentArgs args = DirectMessageThreadFragmentArgs.fromBundle(arguments);
|
// final DirectMessageThreadFragmentArgs args = DirectMessageThreadFragmentArgs.fromBundle(arguments);
|
||||||
final boolean pending = args.getPending();
|
// final boolean pending = args.getPending();
|
||||||
final NavController navController = NavHostFragment.findNavController(this);
|
// final NavController navController = NavHostFragment.findNavController(this);
|
||||||
final ViewModelStoreOwner viewModelStoreOwner = navController.getViewModelStoreOwner(R.id.direct_messages_nav_graph);
|
// final ViewModelStoreOwner viewModelStoreOwner = navController.getViewModelStoreOwner(R.id.direct_messages_nav_graph);
|
||||||
final List<DirectThread> threads;
|
// final List<DirectThread> threads;
|
||||||
if (!pending) {
|
// if (!pending) {
|
||||||
final DirectInboxViewModel threadListViewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectInboxViewModel.class);
|
// final DirectInboxViewModel threadListViewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectInboxViewModel.class);
|
||||||
threads = threadListViewModel.getThreads().getValue();
|
// threads = threadListViewModel.getThreads().getValue();
|
||||||
} else {
|
// } else {
|
||||||
final DirectPendingInboxViewModel threadListViewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectPendingInboxViewModel.class);
|
// final DirectPendingInboxViewModel threadListViewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectPendingInboxViewModel.class);
|
||||||
threads = threadListViewModel.getThreads().getValue();
|
// threads = threadListViewModel.getThreads().getValue();
|
||||||
}
|
// }
|
||||||
final Optional<DirectThread> first = threads != null
|
// final Optional<DirectThread> first = threads != null
|
||||||
? threads.stream()
|
// ? threads.stream()
|
||||||
.filter(thread -> thread.getThreadId().equals(viewModel.getThreadId()))
|
// .filter(thread -> thread.getThreadId().equals(viewModel.getThreadId()))
|
||||||
.findFirst()
|
// .findFirst()
|
||||||
: Optional.empty();
|
// : Optional.empty();
|
||||||
if (first.isPresent()) {
|
// if (first.isPresent()) {
|
||||||
final DirectThread thread = first.get();
|
// final DirectThread thread = first.get();
|
||||||
viewModel.setThread(thread);
|
// viewModel.setThread(thread);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
viewModel.fetchChats();
|
// viewModel.fetchChats();
|
||||||
}
|
// }
|
||||||
|
|
||||||
private void setupList() {
|
private void setupList() {
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
@ -542,7 +552,14 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setObservers() {
|
private void setObservers() {
|
||||||
viewModel.isPending().observe(getViewLifecycleOwner(), isPending -> {
|
threadLiveData = viewModel.getThread();
|
||||||
|
if (threadLiveData == null) {
|
||||||
|
final NavController navController = NavHostFragment.findNavController(this);
|
||||||
|
navController.navigateUp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pendingLiveData = viewModel.isPending();
|
||||||
|
pendingLiveData.observe(getViewLifecycleOwner(), isPending -> {
|
||||||
if (isPending == null) {
|
if (isPending == null) {
|
||||||
hideInput();
|
hideInput();
|
||||||
return;
|
return;
|
||||||
@ -556,7 +573,8 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
if (inputMode != null && inputMode == 1) return;
|
if (inputMode != null && inputMode == 1) return;
|
||||||
showInput();
|
showInput();
|
||||||
});
|
});
|
||||||
viewModel.getInputMode().observe(getViewLifecycleOwner(), inputMode -> {
|
inputModeLiveData = viewModel.getInputMode();
|
||||||
|
inputModeLiveData.observe(getViewLifecycleOwner(), inputMode -> {
|
||||||
final Boolean isPending = viewModel.isPending().getValue();
|
final Boolean isPending = viewModel.isPending().getValue();
|
||||||
if (isPending != null && isPending) return;
|
if (isPending != null && isPending) return;
|
||||||
if (inputMode == null || inputMode == 0) return;
|
if (inputMode == null || inputMode == 0) return;
|
||||||
@ -564,21 +582,34 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
hideInput();
|
hideInput();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
viewModel.getThreadTitle().observe(getViewLifecycleOwner(), this::setTitle);
|
threadTitleLiveData = viewModel.getThreadTitle();
|
||||||
viewModel.getFetching().observe(getViewLifecycleOwner(), fetching -> {
|
threadTitleLiveData.observe(getViewLifecycleOwner(), this::setTitle);
|
||||||
if (fetching) {
|
fetchingLiveData = viewModel.isFetching();
|
||||||
setTitle(UPDATING_TITLE);
|
fetchingLiveData.observe(getViewLifecycleOwner(), fetchingResource -> {
|
||||||
return;
|
if (fetchingResource == null) return;
|
||||||
|
switch (fetchingResource.status) {
|
||||||
|
case SUCCESS:
|
||||||
|
case ERROR:
|
||||||
|
setTitle(viewModel.getThreadTitle().getValue());
|
||||||
|
if (fetchingResource.message != null) {
|
||||||
|
Snackbar.make(binding.getRoot(), fetchingResource.message, Snackbar.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LOADING:
|
||||||
|
setTitle(UPDATING_TITLE);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
setTitle(viewModel.getThreadTitle().getValue());
|
|
||||||
});
|
});
|
||||||
final ItemsAdapterDataMerger itemsAdapterDataMerger = new ItemsAdapterDataMerger(appStateViewModel.getCurrentUser(), viewModel.getThread());
|
// final ItemsAdapterDataMerger itemsAdapterDataMerger = new ItemsAdapterDataMerger(appStateViewModel.getCurrentUser(), viewModel.getThread());
|
||||||
itemsAdapterDataMerger.observe(getViewLifecycleOwner(), userThreadPair -> {
|
// itemsAdapterDataMerger.observe(getViewLifecycleOwner(), userThreadPair -> {
|
||||||
viewModel.setCurrentUser(userThreadPair.first);
|
// viewModel.setCurrentUser(userThreadPair.first);
|
||||||
setupItemsAdapter(userThreadPair.first, userThreadPair.second);
|
// setupItemsAdapter(userThreadPair.first, userThreadPair.second);
|
||||||
});
|
// });
|
||||||
viewModel.getItems().observe(getViewLifecycleOwner(), this::submitItemsToAdapter);
|
threadLiveData.observe(getViewLifecycleOwner(), this::setupItemsAdapter);
|
||||||
viewModel.getReplyToItem().observe(getViewLifecycleOwner(), item -> {
|
itemsLiveData = viewModel.getItems();
|
||||||
|
itemsLiveData.observe(getViewLifecycleOwner(), this::submitItemsToAdapter);
|
||||||
|
replyToItemLiveData = viewModel.getReplyToItem();
|
||||||
|
replyToItemLiveData.observe(getViewLifecycleOwner(), item -> {
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
if (binding.input.length() == 0) {
|
if (binding.input.length() == 0) {
|
||||||
showExtraInputOption(true);
|
showExtraInputOption(true);
|
||||||
@ -633,14 +664,30 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
}
|
}
|
||||||
prevLength = length;
|
prevLength = length;
|
||||||
});
|
});
|
||||||
viewModel.getPendingRequestsCount().observe(getViewLifecycleOwner(), this::attachPendingRequestsBadge);
|
pendingRequestsCountLiveData = viewModel.getPendingRequestsCount();
|
||||||
viewModel.getUsers().observe(getViewLifecycleOwner(), users -> {
|
pendingRequestsCountLiveData.observe(getViewLifecycleOwner(), this::attachPendingRequestsBadge);
|
||||||
|
usersLiveData = viewModel.getUsers();
|
||||||
|
usersLiveData.observe(getViewLifecycleOwner(), users -> {
|
||||||
if (users == null || users.isEmpty()) return;
|
if (users == null || users.isEmpty()) return;
|
||||||
final User user = users.get(0);
|
final User user = users.get(0);
|
||||||
binding.acceptPendingRequestQuestion.setText(getString(R.string.accept_request_from_user, user.getUsername(), user.getFullName()));
|
binding.acceptPendingRequestQuestion.setText(getString(R.string.accept_request_from_user, user.getUsername(), user.getFullName()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeObservers() {
|
||||||
|
pendingLiveData.removeObservers(getViewLifecycleOwner());
|
||||||
|
inputModeLiveData.removeObservers(getViewLifecycleOwner());
|
||||||
|
threadTitleLiveData.removeObservers(getViewLifecycleOwner());
|
||||||
|
fetchingLiveData.removeObservers(getViewLifecycleOwner());
|
||||||
|
threadLiveData.removeObservers(getViewLifecycleOwner());
|
||||||
|
itemsLiveData.removeObservers(getViewLifecycleOwner());
|
||||||
|
replyToItemLiveData.removeObservers(getViewLifecycleOwner());
|
||||||
|
inputLength.removeObservers(getViewLifecycleOwner());
|
||||||
|
pendingRequestsCountLiveData.removeObservers(getViewLifecycleOwner());
|
||||||
|
usersLiveData.removeObservers(getViewLifecycleOwner());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void hidePendingOptions() {
|
private void hidePendingOptions() {
|
||||||
binding.acceptPendingRequestQuestion.setVisibility(View.GONE);
|
binding.acceptPendingRequestQuestion.setVisibility(View.GONE);
|
||||||
binding.decline.setVisibility(View.GONE);
|
binding.decline.setVisibility(View.GONE);
|
||||||
@ -669,9 +716,15 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
resourceLiveData.removeObservers(getViewLifecycleOwner());
|
resourceLiveData.removeObservers(getViewLifecycleOwner());
|
||||||
if (isDecline) {
|
if (isDecline) {
|
||||||
|
removeObservers();
|
||||||
|
viewModel.removeThread();
|
||||||
final NavController navController = NavHostFragment.findNavController(this);
|
final NavController navController = NavHostFragment.findNavController(this);
|
||||||
navController.navigateUp();
|
navController.navigateUp();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
removeObservers();
|
||||||
|
viewModel.moveFromPending();
|
||||||
|
setObservers();
|
||||||
break;
|
break;
|
||||||
case LOADING:
|
case LOADING:
|
||||||
break;
|
break;
|
||||||
@ -838,12 +891,15 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupItemsAdapter(final User currentUser, final DirectThread thread) {
|
private void setupItemsAdapter(final DirectThread thread) {
|
||||||
|
if (thread == null) return;
|
||||||
if (itemsAdapter != null) {
|
if (itemsAdapter != null) {
|
||||||
if (itemsAdapter.getThread() == thread) return;
|
if (itemsAdapter.getThread() == thread) return;
|
||||||
itemsAdapter.setThread(thread);
|
itemsAdapter.setThread(thread);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final User currentUser = appStateViewModel.getCurrentUser();
|
||||||
|
if (currentUser == null) return;
|
||||||
itemsAdapter = new DirectItemsAdapter(currentUser, thread, directItemCallback, directItemLongClickListener);
|
itemsAdapter = new DirectItemsAdapter(currentUser, thread, directItemCallback, directItemLongClickListener);
|
||||||
itemsAdapter.setHasStableIds(true);
|
itemsAdapter.setHasStableIds(true);
|
||||||
itemsAdapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY);
|
itemsAdapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY);
|
||||||
@ -958,7 +1014,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
binding.send.setOnRecordClickListener(v -> {
|
binding.send.setOnRecordClickListener(v -> {
|
||||||
final Editable text = binding.input.getText();
|
final Editable text = binding.input.getText();
|
||||||
if (TextUtils.isEmpty(text)) return;
|
if (TextUtils.isEmpty(text)) return;
|
||||||
final LiveData<Resource<DirectItem>> resourceLiveData = viewModel.sendText(text.toString());
|
final LiveData<Resource<Object>> resourceLiveData = viewModel.sendText(text.toString());
|
||||||
resourceLiveData.observe(getViewLifecycleOwner(), resource -> handleSentMessage(resourceLiveData));
|
resourceLiveData.observe(getViewLifecycleOwner(), resource -> handleSentMessage(resourceLiveData));
|
||||||
binding.input.setText("");
|
binding.input.setText("");
|
||||||
viewModel.setReplyToItem(null);
|
viewModel.setReplyToItem(null);
|
||||||
@ -1031,8 +1087,8 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
navController.navigate(navDirections);
|
navController.navigate(navDirections);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSentMessage(final LiveData<Resource<DirectItem>> resourceLiveData) {
|
private void handleSentMessage(final LiveData<Resource<Object>> resourceLiveData) {
|
||||||
final Resource<DirectItem> resource = resourceLiveData.getValue();
|
final Resource<Object> resource = resourceLiveData.getValue();
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
final Resource.Status status = resource.status;
|
final Resource.Status status = resource.status;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@ -1380,10 +1436,6 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
animatorSet.start();
|
animatorSet.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showLongClickOptions(final View itemView) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showReactionsDialog(final DirectItem item) {
|
private void showReactionsDialog(final DirectItem item) {
|
||||||
final LiveData<List<User>> users = viewModel.getUsers();
|
final LiveData<List<User>> users = viewModel.getUsers();
|
||||||
final LiveData<List<User>> leftUsers = viewModel.getLeftUsers();
|
final LiveData<List<User>> leftUsers = viewModel.getLeftUsers();
|
||||||
@ -1410,7 +1462,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
}
|
}
|
||||||
if (reaction == null) return;
|
if (reaction == null) return;
|
||||||
if (reaction.getSenderId() == viewModel.getViewerId()) {
|
if (reaction.getSenderId() == viewModel.getViewerId()) {
|
||||||
final LiveData<Resource<DirectItem>> resourceLiveData = viewModel.sendDeleteReaction(itemId);
|
final LiveData<Resource<Object>> resourceLiveData = viewModel.sendDeleteReaction(itemId);
|
||||||
if (resourceLiveData != null) {
|
if (resourceLiveData != null) {
|
||||||
resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData));
|
resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData));
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,9 @@ 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;
|
||||||
|
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
@ -102,16 +105,41 @@ public class DirectPendingInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupObservers() {
|
private void setupObservers() {
|
||||||
|
removeViewModelObservers();
|
||||||
threadsObserver = list -> {
|
threadsObserver = list -> {
|
||||||
if (inboxAdapter == null) return;
|
if (inboxAdapter == null) return;
|
||||||
inboxAdapter.submitList(list, () -> {
|
if (binding.swipeRefreshLayout.getVisibility() == View.GONE) {
|
||||||
|
binding.swipeRefreshLayout.setVisibility(View.VISIBLE);
|
||||||
|
binding.empty.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
inboxAdapter.submitList(list == null ? Collections.emptyList() : list, () -> {
|
||||||
if (!scrollToTop) return;
|
if (!scrollToTop) return;
|
||||||
binding.pendingInboxList.smoothScrollToPosition(0);
|
binding.pendingInboxList.smoothScrollToPosition(0);
|
||||||
scrollToTop = false;
|
scrollToTop = false;
|
||||||
});
|
});
|
||||||
|
if (list == null || list.isEmpty()) {
|
||||||
|
binding.swipeRefreshLayout.setVisibility(View.GONE);
|
||||||
|
binding.empty.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
viewModel.getThreads().observe(fragmentActivity, threadsObserver);
|
viewModel.getThreads().observe(fragmentActivity, threadsObserver);
|
||||||
viewModel.getFetchingInbox().observe(getViewLifecycleOwner(), fetching -> binding.swipeRefreshLayout.setRefreshing(fetching));
|
viewModel.getInbox().observe(getViewLifecycleOwner(), inboxResource -> {
|
||||||
|
if (inboxResource == null) return;
|
||||||
|
switch (inboxResource.status) {
|
||||||
|
case SUCCESS:
|
||||||
|
binding.swipeRefreshLayout.setRefreshing(false);
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
if (inboxResource.message != null) {
|
||||||
|
Snackbar.make(binding.getRoot(), inboxResource.message, Snackbar.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
binding.swipeRefreshLayout.setRefreshing(false);
|
||||||
|
break;
|
||||||
|
case LOADING:
|
||||||
|
binding.swipeRefreshLayout.setRefreshing(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeViewModelObservers() {
|
private void removeViewModelObservers() {
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
package awais.instagrabber.managers;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.repositories.responses.User;
|
||||||
|
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||||
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
|
|
||||||
|
public final class DirectMessagesManager {
|
||||||
|
private static final String TAG = DirectMessagesManager.class.getSimpleName();
|
||||||
|
private static final Object LOCK = new Object();
|
||||||
|
|
||||||
|
private static DirectMessagesManager instance;
|
||||||
|
|
||||||
|
private final InboxManager inboxManager;
|
||||||
|
private final InboxManager pendingInboxManager;
|
||||||
|
|
||||||
|
public static DirectMessagesManager getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new DirectMessagesManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DirectMessagesManager() {
|
||||||
|
inboxManager = InboxManager.getInstance(false);
|
||||||
|
pendingInboxManager = InboxManager.getInstance(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveThreadFromPending(@NonNull final String threadId) {
|
||||||
|
final List<DirectThread> pendingThreads = pendingInboxManager.getThreads().getValue();
|
||||||
|
if (pendingThreads == null) return;
|
||||||
|
final int index = Iterables.indexOf(pendingThreads, t -> 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<DirectThread> 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;
|
||||||
|
}
|
||||||
|
insertIndex++;
|
||||||
|
}
|
||||||
|
thread.setPending(false);
|
||||||
|
inboxManager.addThread(thread, insertIndex);
|
||||||
|
pendingInboxManager.removeThread(threadId);
|
||||||
|
final Integer currentTotal = inboxManager.getPendingRequestsTotal().getValue();
|
||||||
|
if (currentTotal == null) return;
|
||||||
|
inboxManager.setPendingRequestsTotal(currentTotal - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InboxManager getInboxManager() {
|
||||||
|
return inboxManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InboxManager getPendingInboxManager() {
|
||||||
|
return pendingInboxManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThreadManager getThreadManager(@NonNull final String threadId,
|
||||||
|
final boolean pending,
|
||||||
|
@NonNull final User currentUser,
|
||||||
|
@NonNull final ContentResolver contentResolver) {
|
||||||
|
return ThreadManager.getInstance(threadId, pending, currentUser, contentResolver);
|
||||||
|
}
|
||||||
|
}
|
358
app/src/main/java/awais/instagrabber/managers/InboxManager.java
Normal file
358
app/src/main/java/awais/instagrabber/managers/InboxManager.java
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
package awais.instagrabber.managers;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
import androidx.lifecycle.Transformations;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import awais.instagrabber.models.Resource;
|
||||||
|
import awais.instagrabber.repositories.responses.User;
|
||||||
|
import awais.instagrabber.repositories.responses.directmessages.DirectBadgeCount;
|
||||||
|
import awais.instagrabber.repositories.responses.directmessages.DirectInbox;
|
||||||
|
import awais.instagrabber.repositories.responses.directmessages.DirectInboxResponse;
|
||||||
|
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||||
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
|
import awais.instagrabber.utils.Constants;
|
||||||
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
|
import awais.instagrabber.utils.TextUtils;
|
||||||
|
import awais.instagrabber.webservices.DirectMessagesService;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
import static androidx.lifecycle.Transformations.distinctUntilChanged;
|
||||||
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
|
public final class InboxManager {
|
||||||
|
private static final String TAG = InboxManager.class.getSimpleName();
|
||||||
|
private static final LoadingCache<String, Object> THREAD_LOCKS = CacheBuilder
|
||||||
|
.newBuilder()
|
||||||
|
.expireAfterAccess(1, TimeUnit.MINUTES) // max lock time ever expected
|
||||||
|
.build(CacheLoader.from(Object::new));
|
||||||
|
private static final Comparator<DirectThread> THREAD_COMPARATOR = (t1, t2) -> {
|
||||||
|
final DirectItem t1FirstDirectItem = t1.getFirstDirectItem();
|
||||||
|
final DirectItem t2FirstDirectItem = t2.getFirstDirectItem();
|
||||||
|
if (t1FirstDirectItem == null && t2FirstDirectItem == null) return 0;
|
||||||
|
if (t1FirstDirectItem == null) return 1;
|
||||||
|
if (t2FirstDirectItem == null) return -1;
|
||||||
|
return Long.compare(t2FirstDirectItem.getTimestamp(), t1FirstDirectItem.getTimestamp());
|
||||||
|
};
|
||||||
|
|
||||||
|
private final MutableLiveData<Resource<DirectInbox>> inbox = new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Resource<Integer>> unseenCount = new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Integer> pendingRequestsTotal = new MutableLiveData<>(0);
|
||||||
|
|
||||||
|
private final LiveData<List<DirectThread>> threads;
|
||||||
|
private final DirectMessagesService service;
|
||||||
|
private final boolean pending;
|
||||||
|
|
||||||
|
private Call<DirectInboxResponse> inboxRequest;
|
||||||
|
private Call<DirectBadgeCount> unseenCountRequest;
|
||||||
|
private long seqId;
|
||||||
|
private String cursor;
|
||||||
|
private boolean hasOlder = true;
|
||||||
|
private User viewer;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static InboxManager getInstance(final boolean pending) {
|
||||||
|
return new InboxManager(pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
private InboxManager(final boolean pending) {
|
||||||
|
this.pending = pending;
|
||||||
|
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||||
|
final long userId = CookieUtils.getUserIdFromCookie(cookie);
|
||||||
|
final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID);
|
||||||
|
final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
|
||||||
|
if (TextUtils.isEmpty(csrfToken) || userId <= 0 || TextUtils.isEmpty(deviceUuid)) {
|
||||||
|
throw new IllegalArgumentException("User is not logged in!");
|
||||||
|
}
|
||||||
|
service = DirectMessagesService.getInstance(csrfToken, userId, deviceUuid);
|
||||||
|
|
||||||
|
// Transformations
|
||||||
|
threads = distinctUntilChanged(Transformations.map(inbox, inboxResource -> {
|
||||||
|
if (inboxResource == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
final DirectInbox inbox = inboxResource.data;
|
||||||
|
if (inbox == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return ImmutableList.sortedCopyOf(THREAD_COMPARATOR, inbox.getThreads());
|
||||||
|
}));
|
||||||
|
|
||||||
|
fetchInbox();
|
||||||
|
if (!pending) {
|
||||||
|
fetchUnseenCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<Resource<DirectInbox>> getInbox() {
|
||||||
|
return distinctUntilChanged(inbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<List<DirectThread>> getThreads() {
|
||||||
|
return threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<Resource<Integer>> getUnseenCount() {
|
||||||
|
return distinctUntilChanged(unseenCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<Integer> getPendingRequestsTotal() {
|
||||||
|
return distinctUntilChanged(pendingRequestsTotal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getViewer() {
|
||||||
|
return viewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fetchInbox() {
|
||||||
|
final Resource<DirectInbox> inboxResource = inbox.getValue();
|
||||||
|
if ((inboxResource != null && inboxResource.status == Resource.Status.LOADING) || !hasOlder) return;
|
||||||
|
stopCurrentInboxRequest();
|
||||||
|
inbox.postValue(Resource.loading(getCurrentDirectInbox()));
|
||||||
|
inboxRequest = pending ? service.fetchPendingInbox(cursor, seqId) : service.fetchInbox(cursor, seqId);
|
||||||
|
inboxRequest.enqueue(new Callback<DirectInboxResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull final Call<DirectInboxResponse> call, @NonNull final Response<DirectInboxResponse> response) {
|
||||||
|
parseInboxResponse(response.body());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull final Call<DirectInboxResponse> call, @NonNull final Throwable t) {
|
||||||
|
Log.e(TAG, "Failed fetching dm inbox", t);
|
||||||
|
inbox.postValue(Resource.error(t.getMessage(), getCurrentDirectInbox()));
|
||||||
|
hasOlder = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fetchUnseenCount() {
|
||||||
|
final Resource<Integer> unseenCountResource = unseenCount.getValue();
|
||||||
|
if ((unseenCountResource != null && unseenCountResource.status == Resource.Status.LOADING)) return;
|
||||||
|
stopCurrentUnseenCountRequest();
|
||||||
|
unseenCount.postValue(Resource.loading(getCurrentUnseenCount()));
|
||||||
|
unseenCountRequest = service.fetchUnseenCount();
|
||||||
|
unseenCountRequest.enqueue(new Callback<DirectBadgeCount>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull final Call<DirectBadgeCount> call, @NonNull final Response<DirectBadgeCount> response) {
|
||||||
|
final DirectBadgeCount directBadgeCount = response.body();
|
||||||
|
if (directBadgeCount == null) {
|
||||||
|
Log.e(TAG, "onResponse: directBadgeCount Response is null");
|
||||||
|
unseenCount.postValue(Resource.error("Unseen count response is null", getCurrentUnseenCount()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unseenCount.postValue(Resource.success(directBadgeCount.getBadgeCount()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull final Call<DirectBadgeCount> call, @NonNull final Throwable t) {
|
||||||
|
Log.e(TAG, "Failed fetching unseen count", t);
|
||||||
|
unseenCount.postValue(Resource.error(t.getMessage(), getCurrentUnseenCount()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh() {
|
||||||
|
cursor = null;
|
||||||
|
seqId = 0;
|
||||||
|
hasOlder = true;
|
||||||
|
fetchInbox();
|
||||||
|
if (!pending) {
|
||||||
|
fetchUnseenCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DirectInbox getCurrentDirectInbox() {
|
||||||
|
final Resource<DirectInbox> inboxResource = inbox.getValue();
|
||||||
|
return inboxResource != null ? inboxResource.data : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseInboxResponse(final DirectInboxResponse response) {
|
||||||
|
if (response == null) {
|
||||||
|
Log.e(TAG, "parseInboxResponse: Response is null");
|
||||||
|
inbox.postValue(Resource.error("Response is null", getCurrentDirectInbox()));
|
||||||
|
hasOlder = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!response.getStatus().equals("ok")) {
|
||||||
|
final String msg = "DM inbox fetch response: status not ok";
|
||||||
|
Log.e(TAG, msg);
|
||||||
|
inbox.postValue(Resource.error(msg, getCurrentDirectInbox()));
|
||||||
|
hasOlder = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
seqId = response.getSeqId();
|
||||||
|
if (viewer == null) {
|
||||||
|
viewer = response.getViewer();
|
||||||
|
}
|
||||||
|
final DirectInbox inbox = response.getInbox();
|
||||||
|
if (!TextUtils.isEmpty(cursor)) {
|
||||||
|
final DirectInbox currentDirectInbox = getCurrentDirectInbox();
|
||||||
|
if (currentDirectInbox != null) {
|
||||||
|
List<DirectThread> threads = currentDirectInbox.getThreads();
|
||||||
|
threads = threads == null ? new LinkedList<>() : new LinkedList<>(threads);
|
||||||
|
threads.addAll(inbox.getThreads());
|
||||||
|
inbox.setThreads(threads);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.inbox.postValue(Resource.success(inbox));
|
||||||
|
cursor = inbox.getOldestCursor();
|
||||||
|
hasOlder = inbox.hasOlder();
|
||||||
|
pendingRequestsTotal.postValue(response.getPendingRequestsTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setThread(@NonNull final String threadId,
|
||||||
|
@NonNull final DirectThread thread) {
|
||||||
|
final DirectInbox inbox = getCurrentDirectInbox();
|
||||||
|
if (inbox == null) return;
|
||||||
|
final int index = getThreadIndex(threadId, inbox);
|
||||||
|
setThread(inbox, index, thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setThread(@NonNull final DirectInbox inbox,
|
||||||
|
final int index,
|
||||||
|
@NonNull final DirectThread thread) {
|
||||||
|
if (index < 0) return;
|
||||||
|
synchronized (this.inbox) {
|
||||||
|
final List<DirectThread> threadsCopy = new LinkedList<>(inbox.getThreads());
|
||||||
|
threadsCopy.set(index, thread);
|
||||||
|
try {
|
||||||
|
final DirectInbox clone = (DirectInbox) inbox.clone();
|
||||||
|
clone.setThreads(threadsCopy);
|
||||||
|
this.inbox.postValue(Resource.success(clone));
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
Log.e(TAG, "setThread: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItemsToThread(@NonNull final String threadId,
|
||||||
|
final int insertIndex,
|
||||||
|
@NonNull final Collection<DirectItem> items) {
|
||||||
|
final DirectInbox inbox = getCurrentDirectInbox();
|
||||||
|
if (inbox == null) return;
|
||||||
|
synchronized (THREAD_LOCKS.getUnchecked(threadId)) {
|
||||||
|
final int index = getThreadIndex(threadId, inbox);
|
||||||
|
if (index < 0) return;
|
||||||
|
final List<DirectThread> threads = inbox.getThreads();
|
||||||
|
final DirectThread thread = threads.get(index);
|
||||||
|
List<DirectItem> list = thread.getItems();
|
||||||
|
list = list == null ? new LinkedList<>() : new LinkedList<>(list);
|
||||||
|
if (insertIndex >= 0) {
|
||||||
|
list.addAll(insertIndex, items);
|
||||||
|
} else {
|
||||||
|
list.addAll(items);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final DirectThread threadClone = (DirectThread) thread.clone();
|
||||||
|
threadClone.setItems(list);
|
||||||
|
setThread(inbox, index, threadClone);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "addItemsToThread: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemsToThread(@NonNull final String threadId,
|
||||||
|
@NonNull final List<DirectItem> updatedItems) {
|
||||||
|
final DirectInbox inbox = getCurrentDirectInbox();
|
||||||
|
if (inbox == null) return;
|
||||||
|
synchronized (THREAD_LOCKS.getUnchecked(threadId)) {
|
||||||
|
final int index = getThreadIndex(threadId, inbox);
|
||||||
|
if (index < 0) return;
|
||||||
|
final List<DirectThread> threads = inbox.getThreads();
|
||||||
|
final DirectThread thread = threads.get(index);
|
||||||
|
thread.setItems(updatedItems);
|
||||||
|
setThread(inbox, index, thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getThreadIndex(@NonNull final String threadId,
|
||||||
|
@NonNull final DirectInbox inbox) {
|
||||||
|
final List<DirectThread> threads = inbox.getThreads();
|
||||||
|
if (threads == null || threads.isEmpty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return Iterables.indexOf(threads, t -> {
|
||||||
|
if (t == null) return false;
|
||||||
|
return t.getThreadId().equals(threadId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer getCurrentUnseenCount() {
|
||||||
|
final Resource<Integer> unseenCountResource = unseenCount.getValue();
|
||||||
|
return unseenCountResource != null ? unseenCountResource.data : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopCurrentInboxRequest() {
|
||||||
|
if (inboxRequest == null || inboxRequest.isCanceled() || inboxRequest.isExecuted()) return;
|
||||||
|
inboxRequest.cancel();
|
||||||
|
inboxRequest = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopCurrentUnseenCountRequest() {
|
||||||
|
if (unseenCountRequest == null || unseenCountRequest.isCanceled() || unseenCountRequest.isExecuted()) return;
|
||||||
|
unseenCountRequest.cancel();
|
||||||
|
unseenCountRequest = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDestroy() {
|
||||||
|
stopCurrentInboxRequest();
|
||||||
|
stopCurrentUnseenCountRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addThread(@NonNull final DirectThread thread, final int insertIndex) {
|
||||||
|
if (insertIndex < 0) return;
|
||||||
|
synchronized (this.inbox) {
|
||||||
|
final DirectInbox currentDirectInbox = getCurrentDirectInbox();
|
||||||
|
final List<DirectThread> threadsCopy = new LinkedList<>(currentDirectInbox.getThreads());
|
||||||
|
threadsCopy.add(insertIndex, thread);
|
||||||
|
try {
|
||||||
|
final DirectInbox clone = (DirectInbox) currentDirectInbox.clone();
|
||||||
|
clone.setThreads(threadsCopy);
|
||||||
|
this.inbox.setValue(Resource.success(clone));
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
Log.e(TAG, "setThread: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeThread(@NonNull final String threadId) {
|
||||||
|
synchronized (this.inbox) {
|
||||||
|
final DirectInbox currentDirectInbox = getCurrentDirectInbox();
|
||||||
|
final List<DirectThread> threadsCopy = currentDirectInbox.getThreads()
|
||||||
|
.stream()
|
||||||
|
.filter(t -> !t.getThreadId().equals(threadId))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
try {
|
||||||
|
final DirectInbox clone = (DirectInbox) currentDirectInbox.clone();
|
||||||
|
clone.setThreads(threadsCopy);
|
||||||
|
this.inbox.postValue(Resource.success(clone));
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
Log.e(TAG, "setThread: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPendingRequestsTotal(final int total) {
|
||||||
|
pendingRequestsTotal.postValue(total);
|
||||||
|
}
|
||||||
|
}
|
1780
app/src/main/java/awais/instagrabber/managers/ThreadManager.java
Normal file
1780
app/src/main/java/awais/instagrabber/managers/ThreadManager.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,8 @@ package awais.instagrabber.models;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Resource<T> {
|
public class Resource<T> {
|
||||||
public final Status status;
|
public final Status status;
|
||||||
public final T data;
|
public final T data;
|
||||||
@ -31,6 +33,21 @@ public class Resource<T> {
|
|||||||
return new Resource<>(Status.LOADING, data, null);
|
return new Resource<>(Status.LOADING, data, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final Resource<?> resource = (Resource<?>) o;
|
||||||
|
return status == resource.status &&
|
||||||
|
Objects.equals(data, resource.data) &&
|
||||||
|
Objects.equals(message, resource.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(status, data, message);
|
||||||
|
}
|
||||||
|
|
||||||
public enum Status {
|
public enum Status {
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
ERROR,
|
ERROR,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
package awais.instagrabber.repositories.responses;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class AnimatedMediaFixedHeight {
|
public class AnimatedMediaFixedHeight {
|
||||||
private final int height;
|
private final int height;
|
||||||
private final int width;
|
private final int width;
|
||||||
@ -34,4 +36,21 @@ public class AnimatedMediaFixedHeight {
|
|||||||
public String getWebp() {
|
public String getWebp() {
|
||||||
return webp;
|
return webp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final AnimatedMediaFixedHeight that = (AnimatedMediaFixedHeight) o;
|
||||||
|
return height == that.height &&
|
||||||
|
width == that.width &&
|
||||||
|
Objects.equals(mp4, that.mp4) &&
|
||||||
|
Objects.equals(url, that.url) &&
|
||||||
|
Objects.equals(webp, that.webp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(height, width, mp4, url, webp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
package awais.instagrabber.repositories.responses;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class AnimatedMediaImages {
|
public class AnimatedMediaImages {
|
||||||
private final AnimatedMediaFixedHeight fixedHeight;
|
private final AnimatedMediaFixedHeight fixedHeight;
|
||||||
|
|
||||||
@ -10,4 +12,17 @@ public class AnimatedMediaImages {
|
|||||||
public AnimatedMediaFixedHeight getFixedHeight() {
|
public AnimatedMediaFixedHeight getFixedHeight() {
|
||||||
return fixedHeight;
|
return fixedHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final AnimatedMediaImages that = (AnimatedMediaImages) o;
|
||||||
|
return Objects.equals(fixedHeight, that.fixedHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(fixedHeight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package awais.instagrabber.repositories.responses;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Audio implements Serializable {
|
public class Audio implements Serializable {
|
||||||
private final String audioSrc;
|
private final String audioSrc;
|
||||||
@ -41,4 +42,21 @@ public class Audio implements Serializable {
|
|||||||
public long getAudioSrcExpirationTimestampUs() {
|
public long getAudioSrcExpirationTimestampUs() {
|
||||||
return audioSrcExpirationTimestampUs;
|
return audioSrcExpirationTimestampUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final Audio audio = (Audio) o;
|
||||||
|
return duration == audio.duration &&
|
||||||
|
waveformSamplingFrequencyHz == audio.waveformSamplingFrequencyHz &&
|
||||||
|
audioSrcExpirationTimestampUs == audio.audioSrcExpirationTimestampUs &&
|
||||||
|
Objects.equals(audioSrc, audio.audioSrc) &&
|
||||||
|
Objects.equals(waveformData, audio.waveformData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(audioSrc, duration, waveformData, waveformSamplingFrequencyHz, audioSrcExpirationTimestampUs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import com.google.gson.JsonParseException;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Caption implements Serializable {
|
public class Caption implements Serializable {
|
||||||
private long mPk;
|
private long mPk;
|
||||||
@ -42,6 +43,21 @@ public class Caption implements Serializable {
|
|||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final Caption caption = (Caption) o;
|
||||||
|
return mPk == caption.mPk &&
|
||||||
|
userId == caption.userId &&
|
||||||
|
Objects.equals(text, caption.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(mPk, userId, text);
|
||||||
|
}
|
||||||
|
|
||||||
public static class CaptionDeserializer implements JsonDeserializer<Caption> {
|
public static class CaptionDeserializer implements JsonDeserializer<Caption> {
|
||||||
|
|
||||||
private static final String TAG = CaptionDeserializer.class.getSimpleName();
|
private static final String TAG = CaptionDeserializer.class.getSimpleName();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
package awais.instagrabber.repositories.responses;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class EndOfFeedDemarcator implements Serializable {
|
public class EndOfFeedDemarcator implements Serializable {
|
||||||
private final long id;
|
private final long id;
|
||||||
@ -18,4 +19,18 @@ public class EndOfFeedDemarcator implements Serializable {
|
|||||||
public EndOfFeedGroupSet getGroupSet() {
|
public EndOfFeedGroupSet getGroupSet() {
|
||||||
return groupSet;
|
return groupSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final EndOfFeedDemarcator that = (EndOfFeedDemarcator) o;
|
||||||
|
return id == that.id &&
|
||||||
|
Objects.equals(groupSet, that.groupSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id, groupSet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package awais.instagrabber.repositories.responses;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class EndOfFeedGroup implements Serializable {
|
public class EndOfFeedGroup implements Serializable {
|
||||||
private final String id;
|
private final String id;
|
||||||
@ -31,4 +32,20 @@ public class EndOfFeedGroup implements Serializable {
|
|||||||
public List<Media> getFeedItems() {
|
public List<Media> getFeedItems() {
|
||||||
return feedItems;
|
return feedItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final EndOfFeedGroup that = (EndOfFeedGroup) o;
|
||||||
|
return Objects.equals(id, that.id) &&
|
||||||
|
Objects.equals(title, that.title) &&
|
||||||
|
Objects.equals(nextMaxId, that.nextMaxId) &&
|
||||||
|
Objects.equals(feedItems, that.feedItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id, title, nextMaxId, feedItems);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package awais.instagrabber.repositories.responses;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class EndOfFeedGroupSet implements Serializable {
|
public class EndOfFeedGroupSet implements Serializable {
|
||||||
private final long id;
|
private final long id;
|
||||||
@ -48,4 +49,22 @@ public class EndOfFeedGroupSet implements Serializable {
|
|||||||
public List<EndOfFeedGroup> getGroups() {
|
public List<EndOfFeedGroup> getGroups() {
|
||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final EndOfFeedGroupSet that = (EndOfFeedGroupSet) o;
|
||||||
|
return id == that.id &&
|
||||||
|
Objects.equals(activeGroupId, that.activeGroupId) &&
|
||||||
|
Objects.equals(connectedGroupId, that.connectedGroupId) &&
|
||||||
|
Objects.equals(nextMaxId, that.nextMaxId) &&
|
||||||
|
Objects.equals(paginationSource, that.paginationSource) &&
|
||||||
|
Objects.equals(groups, that.groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id, activeGroupId, connectedGroupId, nextMaxId, paginationSource, groups);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package awais.instagrabber.repositories.responses;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class FriendshipStatus implements Serializable {
|
public class FriendshipStatus implements Serializable {
|
||||||
private final boolean following;
|
private final boolean following;
|
||||||
@ -78,6 +79,29 @@ public class FriendshipStatus implements Serializable {
|
|||||||
return isMutingReel;
|
return isMutingReel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final FriendshipStatus that = (FriendshipStatus) o;
|
||||||
|
return following == that.following &&
|
||||||
|
followedBy == that.followedBy &&
|
||||||
|
blocking == that.blocking &&
|
||||||
|
muting == that.muting &&
|
||||||
|
isPrivate == that.isPrivate &&
|
||||||
|
incomingRequest == that.incomingRequest &&
|
||||||
|
outgoingRequest == that.outgoingRequest &&
|
||||||
|
isBestie == that.isBestie &&
|
||||||
|
isRestricted == that.isRestricted &&
|
||||||
|
isMutingReel == that.isMutingReel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(following, followedBy, blocking, muting, isPrivate, incomingRequest, outgoingRequest, isBestie, isRestricted,
|
||||||
|
isMutingReel);
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
@ -2,6 +2,7 @@ package awais.instagrabber.repositories.responses;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ImageVersions2 implements Serializable {
|
public class ImageVersions2 implements Serializable {
|
||||||
private final List<MediaCandidate> candidates;
|
private final List<MediaCandidate> candidates;
|
||||||
@ -13,4 +14,17 @@ public class ImageVersions2 implements Serializable {
|
|||||||
public List<MediaCandidate> getCandidates() {
|
public List<MediaCandidate> getCandidates() {
|
||||||
return candidates;
|
return candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final ImageVersions2 that = (ImageVersions2) o;
|
||||||
|
return Objects.equals(candidates, that.candidates);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(candidates);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
package awais.instagrabber.repositories.responses;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Location implements Serializable {
|
public class Location implements Serializable {
|
||||||
private final long pk;
|
private final long pk;
|
||||||
@ -54,4 +55,23 @@ public class Location implements Serializable {
|
|||||||
public float getLat() {
|
public float getLat() {
|
||||||
return lat;
|
return lat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final Location location = (Location) o;
|
||||||
|
return pk == location.pk &&
|
||||||
|
Float.compare(location.lng, lng) == 0 &&
|
||||||
|
Float.compare(location.lat, lat) == 0 &&
|
||||||
|
Objects.equals(shortName, location.shortName) &&
|
||||||
|
Objects.equals(name, location.name) &&
|
||||||
|
Objects.equals(address, location.address) &&
|
||||||
|
Objects.equals(city, location.city);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(pk, shortName, name, address, city, lng, lat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import java.io.Serializable;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import awais.instagrabber.models.enums.MediaItemType;
|
import awais.instagrabber.models.enums.MediaItemType;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
@ -272,4 +273,52 @@ public class Media implements Serializable {
|
|||||||
final Caption caption1 = getCaption();
|
final Caption caption1 = getCaption();
|
||||||
caption1.setText(caption);
|
caption1.setText(caption);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final Media media = (Media) o;
|
||||||
|
return takenAt == media.takenAt &&
|
||||||
|
canViewerReshare == media.canViewerReshare &&
|
||||||
|
commentLikesEnabled == media.commentLikesEnabled &&
|
||||||
|
commentsDisabled == media.commentsDisabled &&
|
||||||
|
nextMaxId == media.nextMaxId &&
|
||||||
|
commentCount == media.commentCount &&
|
||||||
|
originalWidth == media.originalWidth &&
|
||||||
|
originalHeight == media.originalHeight &&
|
||||||
|
likeCount == media.likeCount &&
|
||||||
|
hasLiked == media.hasLiked &&
|
||||||
|
isReelMedia == media.isReelMedia &&
|
||||||
|
hasAudio == media.hasAudio &&
|
||||||
|
Double.compare(media.videoDuration, videoDuration) == 0 &&
|
||||||
|
viewCount == media.viewCount &&
|
||||||
|
canViewerSave == media.canViewerSave &&
|
||||||
|
isSidecarChild == media.isSidecarChild &&
|
||||||
|
hasViewerSaved == media.hasViewerSaved &&
|
||||||
|
Objects.equals(pk, media.pk) &&
|
||||||
|
Objects.equals(id, media.id) &&
|
||||||
|
Objects.equals(code, media.code) &&
|
||||||
|
Objects.equals(user, media.user) &&
|
||||||
|
mediaType == media.mediaType &&
|
||||||
|
Objects.equals(imageVersions2, media.imageVersions2) &&
|
||||||
|
Objects.equals(videoVersions, media.videoVersions) &&
|
||||||
|
Objects.equals(caption, media.caption) &&
|
||||||
|
Objects.equals(audio, media.audio) &&
|
||||||
|
Objects.equals(title, media.title) &&
|
||||||
|
Objects.equals(location, media.location) &&
|
||||||
|
Objects.equals(usertags, media.usertags) &&
|
||||||
|
Objects.equals(carouselMedia, media.carouselMedia) &&
|
||||||
|
Objects.equals(injected, media.injected) &&
|
||||||
|
Objects.equals(endOfFeedDemarcator, media.endOfFeedDemarcator) &&
|
||||||
|
Objects.equals(dateString, media.dateString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(pk, id, code, takenAt, user, mediaType, canViewerReshare, commentLikesEnabled, commentsDisabled, nextMaxId, commentCount,
|
||||||
|
imageVersions2, originalWidth, originalHeight, likeCount, hasLiked, isReelMedia, videoVersions, hasAudio, videoDuration,
|
||||||
|
viewCount, caption, canViewerSave, audio, title, location, usertags, carouselMedia, isSidecarChild, hasViewerSaved,
|
||||||
|
injected, endOfFeedDemarcator, dateString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
package awais.instagrabber.repositories.responses;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class MediaCandidate implements Serializable {
|
public class MediaCandidate implements Serializable {
|
||||||
private final int width;
|
private final int width;
|
||||||
@ -24,4 +25,19 @@ public class MediaCandidate implements Serializable {
|
|||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final MediaCandidate that = (MediaCandidate) o;
|
||||||
|
return width == that.width &&
|
||||||
|
height == that.height &&
|
||||||
|
Objects.equals(url, that.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(width, height, url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,17 +207,40 @@ public class User implements Serializable {
|
|||||||
// null);
|
// null);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object o) {
|
public boolean equals(final Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
final User that = (User) o;
|
final User user = (User) o;
|
||||||
return pk == that.pk &&
|
return pk == user.pk &&
|
||||||
Objects.equals(username, that.username);
|
isPrivate == user.isPrivate &&
|
||||||
|
isVerified == user.isVerified &&
|
||||||
|
hasAnonymousProfilePicture == user.hasAnonymousProfilePicture &&
|
||||||
|
isUnpublished == user.isUnpublished &&
|
||||||
|
isFavorite == user.isFavorite &&
|
||||||
|
isDirectappInstalled == user.isDirectappInstalled &&
|
||||||
|
mediaCount == user.mediaCount &&
|
||||||
|
followerCount == user.followerCount &&
|
||||||
|
followingCount == user.followingCount &&
|
||||||
|
followingTagCount == user.followingTagCount &&
|
||||||
|
usertagsCount == user.usertagsCount &&
|
||||||
|
Objects.equals(username, user.username) &&
|
||||||
|
Objects.equals(fullName, user.fullName) &&
|
||||||
|
Objects.equals(profilePicUrl, user.profilePicUrl) &&
|
||||||
|
Objects.equals(profilePicId, user.profilePicId) &&
|
||||||
|
Objects.equals(friendshipStatus, user.friendshipStatus) &&
|
||||||
|
Objects.equals(reelAutoArchive, user.reelAutoArchive) &&
|
||||||
|
Objects.equals(allowedCommenterType, user.allowedCommenterType) &&
|
||||||
|
Objects.equals(biography, user.biography) &&
|
||||||
|
Objects.equals(externalUrl, user.externalUrl) &&
|
||||||
|
Objects.equals(publicEmail, user.publicEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(pk, username);
|
return Objects.hash(pk, username, fullName, isPrivate, profilePicUrl, profilePicId, friendshipStatus, isVerified, hasAnonymousProfilePicture,
|
||||||
|
isUnpublished, isFavorite, isDirectappInstalled, reelAutoArchive, allowedCommenterType, mediaCount, followerCount,
|
||||||
|
followingCount, followingTagCount, biography, externalUrl, usertagsCount, publicEmail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package awais.instagrabber.repositories.responses;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class UsertagIn implements Serializable {
|
public class UsertagIn implements Serializable {
|
||||||
private final User user;
|
private final User user;
|
||||||
@ -19,4 +20,18 @@ public class UsertagIn implements Serializable {
|
|||||||
public List<String> getPosition() {
|
public List<String> getPosition() {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final UsertagIn usertagIn = (UsertagIn) o;
|
||||||
|
return Objects.equals(user, usertagIn.user) &&
|
||||||
|
Objects.equals(position, usertagIn.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(user, position);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package awais.instagrabber.repositories.responses;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Usertags implements Serializable {
|
public class Usertags implements Serializable {
|
||||||
private final List<UsertagIn> in;
|
private final List<UsertagIn> in;
|
||||||
@ -13,4 +14,17 @@ public class Usertags implements Serializable {
|
|||||||
public List<UsertagIn> getIn() {
|
public List<UsertagIn> getIn() {
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final Usertags usertags = (Usertags) o;
|
||||||
|
return Objects.equals(in, usertags.in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(in);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
package awais.instagrabber.repositories.responses;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class VideoVersion implements Serializable {
|
public class VideoVersion implements Serializable {
|
||||||
private final String id;
|
private final String id;
|
||||||
@ -36,4 +37,21 @@ public class VideoVersion implements Serializable {
|
|||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final VideoVersion that = (VideoVersion) o;
|
||||||
|
return width == that.width &&
|
||||||
|
height == that.height &&
|
||||||
|
Objects.equals(id, that.id) &&
|
||||||
|
Objects.equals(type, that.type) &&
|
||||||
|
Objects.equals(url, that.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id, type, width, height, url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class DirectInbox {
|
public class DirectInbox implements Cloneable {
|
||||||
private final List<DirectThread> threads;
|
private List<DirectThread> threads;
|
||||||
private final boolean hasOlder;
|
private final boolean hasOlder;
|
||||||
private final int unseenCount;
|
private final int unseenCount;
|
||||||
private final String unseenCountTs;
|
private final String unseenCountTs;
|
||||||
@ -28,6 +30,10 @@ public class DirectInbox {
|
|||||||
return threads;
|
return threads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setThreads(final List<DirectThread> threads) {
|
||||||
|
this.threads = threads;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasOlder() {
|
public boolean hasOlder() {
|
||||||
return hasOlder;
|
return hasOlder;
|
||||||
}
|
}
|
||||||
@ -47,4 +53,10 @@ public class DirectInbox {
|
|||||||
public boolean isBlendedInboxEnabled() {
|
public boolean isBlendedInboxEnabled() {
|
||||||
return blendedInboxEnabled;
|
return blendedInboxEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import androidx.annotation.NonNull;
|
|||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import awais.instagrabber.models.enums.DirectItemType;
|
import awais.instagrabber.models.enums.DirectItemType;
|
||||||
import awais.instagrabber.repositories.responses.Location;
|
import awais.instagrabber.repositories.responses.Location;
|
||||||
@ -239,21 +240,47 @@ public class DirectItem implements Cloneable {
|
|||||||
return super.clone();
|
return super.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
@Override
|
||||||
// public boolean equals(final Object o) {
|
public boolean equals(final Object o) {
|
||||||
// if (this == o) return true;
|
if (this == o) return true;
|
||||||
// if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
// final DirectItem that = (DirectItem) o;
|
final DirectItem that = (DirectItem) o;
|
||||||
// return userId == that.userId &&
|
return userId == that.userId &&
|
||||||
// timestamp == that.timestamp &&
|
timestamp == that.timestamp &&
|
||||||
// isPending == that.isPending &&
|
hideInThread == that.hideInThread &&
|
||||||
// Objects.equals(itemId, that.itemId) &&
|
isPending == that.isPending &&
|
||||||
// itemType == that.itemType &&
|
showForwardAttribution == that.showForwardAttribution &&
|
||||||
// Objects.equals(clientContext, that.clientContext);
|
Objects.equals(itemId, that.itemId) &&
|
||||||
// }
|
itemType == that.itemType &&
|
||||||
//
|
Objects.equals(text, that.text) &&
|
||||||
// @Override
|
Objects.equals(like, that.like) &&
|
||||||
// public int hashCode() {
|
Objects.equals(link, that.link) &&
|
||||||
// return Objects.hash(itemId, userId, timestamp, itemType, clientContext, isPending);
|
Objects.equals(clientContext, that.clientContext) &&
|
||||||
// }
|
Objects.equals(reelShare, that.reelShare) &&
|
||||||
|
Objects.equals(storyShare, that.storyShare) &&
|
||||||
|
Objects.equals(mediaShare, that.mediaShare) &&
|
||||||
|
Objects.equals(profile, that.profile) &&
|
||||||
|
Objects.equals(placeholder, that.placeholder) &&
|
||||||
|
Objects.equals(media, that.media) &&
|
||||||
|
Objects.equals(previewMedias, that.previewMedias) &&
|
||||||
|
Objects.equals(actionLog, that.actionLog) &&
|
||||||
|
Objects.equals(videoCallEvent, that.videoCallEvent) &&
|
||||||
|
Objects.equals(clip, that.clip) &&
|
||||||
|
Objects.equals(felixShare, that.felixShare) &&
|
||||||
|
Objects.equals(visualMedia, that.visualMedia) &&
|
||||||
|
Objects.equals(animatedMedia, that.animatedMedia) &&
|
||||||
|
Objects.equals(reactions, that.reactions) &&
|
||||||
|
Objects.equals(repliedToMessage, that.repliedToMessage) &&
|
||||||
|
Objects.equals(voiceMedia, that.voiceMedia) &&
|
||||||
|
Objects.equals(location, that.location) &&
|
||||||
|
Objects.equals(date, that.date);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects
|
||||||
|
.hash(itemId, userId, timestamp, itemType, text, like, link, clientContext, reelShare, storyShare, mediaShare, profile, placeholder,
|
||||||
|
media, previewMedias, actionLog, videoCallEvent, clip, felixShare, visualMedia, animatedMedia, reactions, repliedToMessage,
|
||||||
|
voiceMedia, location, hideInThread, date, isPending, showForwardAttribution);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class DirectItemActionLog {
|
public class DirectItemActionLog {
|
||||||
private final String description;
|
private final String description;
|
||||||
@ -27,6 +28,21 @@ public class DirectItemActionLog {
|
|||||||
return textAttributes;
|
return textAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemActionLog that = (DirectItemActionLog) o;
|
||||||
|
return Objects.equals(description, that.description) &&
|
||||||
|
Objects.equals(bold, that.bold) &&
|
||||||
|
Objects.equals(textAttributes, that.textAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(description, bold, textAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
public static class TextRange {
|
public static class TextRange {
|
||||||
private final int start;
|
private final int start;
|
||||||
private final int end;
|
private final int end;
|
||||||
@ -55,5 +71,21 @@ public class DirectItemActionLog {
|
|||||||
public String getIntent() {
|
public String getIntent() {
|
||||||
return intent;
|
return intent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final TextRange textRange = (TextRange) o;
|
||||||
|
return start == textRange.start &&
|
||||||
|
end == textRange.end &&
|
||||||
|
Objects.equals(color, textRange.color) &&
|
||||||
|
Objects.equals(intent, textRange.intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(start, end, color, intent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.AnimatedMediaImages;
|
import awais.instagrabber.repositories.responses.AnimatedMediaImages;
|
||||||
|
|
||||||
public final class DirectItemAnimatedMedia {
|
public final class DirectItemAnimatedMedia {
|
||||||
@ -31,4 +33,20 @@ public final class DirectItemAnimatedMedia {
|
|||||||
public boolean isSticker() {
|
public boolean isSticker() {
|
||||||
return isSticker;
|
return isSticker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemAnimatedMedia that = (DirectItemAnimatedMedia) o;
|
||||||
|
return isRandom == that.isRandom &&
|
||||||
|
isSticker == that.isSticker &&
|
||||||
|
Objects.equals(id, that.id) &&
|
||||||
|
Objects.equals(images, that.images);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id, images, isRandom, isSticker);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.Media;
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
|
|
||||||
public class DirectItemClip {
|
public class DirectItemClip {
|
||||||
@ -12,4 +14,17 @@ public class DirectItemClip {
|
|||||||
public Media getClip() {
|
public Media getClip() {
|
||||||
return clip;
|
return clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemClip that = (DirectItemClip) o;
|
||||||
|
return Objects.equals(clip, that.clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(clip);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.Media;
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
|
|
||||||
public class DirectItemFelixShare {
|
public class DirectItemFelixShare {
|
||||||
@ -12,4 +14,17 @@ public class DirectItemFelixShare {
|
|||||||
public Media getVideo() {
|
public Media getVideo() {
|
||||||
return video;
|
return video;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemFelixShare that = (DirectItemFelixShare) o;
|
||||||
|
return Objects.equals(video, that.video);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(video);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class DirectItemLink {
|
public class DirectItemLink {
|
||||||
private final String text;
|
private final String text;
|
||||||
private final DirectItemLinkContext linkContext;
|
private final DirectItemLinkContext linkContext;
|
||||||
@ -31,4 +33,20 @@ public class DirectItemLink {
|
|||||||
public String getMutationToken() {
|
public String getMutationToken() {
|
||||||
return mutationToken;
|
return mutationToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemLink that = (DirectItemLink) o;
|
||||||
|
return Objects.equals(text, that.text) &&
|
||||||
|
Objects.equals(linkContext, that.linkContext) &&
|
||||||
|
Objects.equals(clientContext, that.clientContext) &&
|
||||||
|
Objects.equals(mutationToken, that.mutationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(text, linkContext, clientContext, mutationToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class DirectItemLinkContext {
|
public class DirectItemLinkContext {
|
||||||
private final String linkUrl;
|
private final String linkUrl;
|
||||||
private final String linkTitle;
|
private final String linkTitle;
|
||||||
@ -31,4 +33,20 @@ public class DirectItemLinkContext {
|
|||||||
public String getLinkImageUrl() {
|
public String getLinkImageUrl() {
|
||||||
return linkImageUrl;
|
return linkImageUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemLinkContext that = (DirectItemLinkContext) o;
|
||||||
|
return Objects.equals(linkUrl, that.linkUrl) &&
|
||||||
|
Objects.equals(linkTitle, that.linkTitle) &&
|
||||||
|
Objects.equals(linkSummary, that.linkSummary) &&
|
||||||
|
Objects.equals(linkImageUrl, that.linkImageUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(linkUrl, linkTitle, linkSummary, linkImageUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class DirectItemPlaceholder {
|
public class DirectItemPlaceholder {
|
||||||
private final boolean isLinked;
|
private final boolean isLinked;
|
||||||
private final String title;
|
private final String title;
|
||||||
@ -24,4 +26,19 @@ public class DirectItemPlaceholder {
|
|||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemPlaceholder that = (DirectItemPlaceholder) o;
|
||||||
|
return isLinked == that.isLinked &&
|
||||||
|
Objects.equals(title, that.title) &&
|
||||||
|
Objects.equals(message, that.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(isLinked, title, message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.Media;
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
|
|
||||||
public class DirectItemReelShare {
|
public class DirectItemReelShare {
|
||||||
@ -61,4 +63,24 @@ public class DirectItemReelShare {
|
|||||||
public long getMentionedUserId() {
|
public long getMentionedUserId() {
|
||||||
return mentionedUserId;
|
return mentionedUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemReelShare that = (DirectItemReelShare) o;
|
||||||
|
return reelOwnerId == that.reelOwnerId &&
|
||||||
|
mentionedUserId == that.mentionedUserId &&
|
||||||
|
isReelPersisted == that.isReelPersisted &&
|
||||||
|
Objects.equals(text, that.text) &&
|
||||||
|
Objects.equals(type, that.type) &&
|
||||||
|
Objects.equals(reelType, that.reelType) &&
|
||||||
|
Objects.equals(media, that.media) &&
|
||||||
|
Objects.equals(reactionInfo, that.reactionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(text, type, reelOwnerId, mentionedUserId, isReelPersisted, reelType, media, reactionInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class DirectItemReelShareReactionInfo {
|
public class DirectItemReelShareReactionInfo {
|
||||||
private final String emoji;
|
private final String emoji;
|
||||||
private final String intensity;
|
private final String intensity;
|
||||||
@ -16,4 +18,18 @@ public class DirectItemReelShareReactionInfo {
|
|||||||
public String getIntensity() {
|
public String getIntensity() {
|
||||||
return intensity;
|
return intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemReelShareReactionInfo that = (DirectItemReelShareReactionInfo) o;
|
||||||
|
return Objects.equals(emoji, that.emoji) &&
|
||||||
|
Objects.equals(intensity, that.intensity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(emoji, intensity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.Media;
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
|
|
||||||
public class DirectItemStoryShare {
|
public class DirectItemStoryShare {
|
||||||
@ -54,4 +56,23 @@ public class DirectItemStoryShare {
|
|||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemStoryShare that = (DirectItemStoryShare) o;
|
||||||
|
return isReelPersisted == that.isReelPersisted &&
|
||||||
|
Objects.equals(reelId, that.reelId) &&
|
||||||
|
Objects.equals(reelType, that.reelType) &&
|
||||||
|
Objects.equals(text, that.text) &&
|
||||||
|
Objects.equals(media, that.media) &&
|
||||||
|
Objects.equals(title, that.title) &&
|
||||||
|
Objects.equals(message, that.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(reelId, reelType, text, isReelPersisted, media, title, message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public final class DirectItemVideoCallEvent {
|
public final class DirectItemVideoCallEvent {
|
||||||
private final String action;
|
private final String action;
|
||||||
@ -40,4 +41,21 @@ public final class DirectItemVideoCallEvent {
|
|||||||
public List<DirectItemActionLog.TextRange> getTextAttributes() {
|
public List<DirectItemActionLog.TextRange> getTextAttributes() {
|
||||||
return textAttributes;
|
return textAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemVideoCallEvent that = (DirectItemVideoCallEvent) o;
|
||||||
|
return threadHasAudioOnlyCall == that.threadHasAudioOnlyCall &&
|
||||||
|
Objects.equals(action, that.action) &&
|
||||||
|
Objects.equals(encodedServerDataInfo, that.encodedServerDataInfo) &&
|
||||||
|
Objects.equals(description, that.description) &&
|
||||||
|
Objects.equals(textAttributes, that.textAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(action, encodedServerDataInfo, description, threadHasAudioOnlyCall, textAttributes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import awais.instagrabber.models.enums.RavenMediaViewMode;
|
import awais.instagrabber.models.enums.RavenMediaViewMode;
|
||||||
import awais.instagrabber.repositories.responses.Media;
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
@ -64,4 +65,25 @@ public class DirectItemVisualMedia {
|
|||||||
public Media getMedia() {
|
public Media getMedia() {
|
||||||
return media;
|
return media;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemVisualMedia media1 = (DirectItemVisualMedia) o;
|
||||||
|
return urlExpireAtSecs == media1.urlExpireAtSecs &&
|
||||||
|
playbackDurationSecs == media1.playbackDurationSecs &&
|
||||||
|
seenCount == media1.seenCount &&
|
||||||
|
replayExpiringAtUs == media1.replayExpiringAtUs &&
|
||||||
|
Objects.equals(seenUserIds, media1.seenUserIds) &&
|
||||||
|
viewMode == media1.viewMode &&
|
||||||
|
Objects.equals(expiringMediaActionSummary, media1.expiringMediaActionSummary) &&
|
||||||
|
Objects.equals(media, media1.media);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects
|
||||||
|
.hash(urlExpireAtSecs, playbackDurationSecs, seenUserIds, viewMode, seenCount, replayExpiringAtUs, expiringMediaActionSummary, media);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.Media;
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
|
|
||||||
public class DirectItemVoiceMedia {
|
public class DirectItemVoiceMedia {
|
||||||
@ -24,4 +26,19 @@ public class DirectItemVoiceMedia {
|
|||||||
public String getViewMode() {
|
public String getViewMode() {
|
||||||
return viewMode;
|
return viewMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemVoiceMedia that = (DirectItemVoiceMedia) o;
|
||||||
|
return seenCount == that.seenCount &&
|
||||||
|
Objects.equals(media, that.media) &&
|
||||||
|
Objects.equals(viewMode, that.viewMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(media, seenCount, viewMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -9,13 +10,13 @@ import java.util.Objects;
|
|||||||
|
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
|
|
||||||
public class DirectThread implements Serializable {
|
public class DirectThread implements Serializable, Cloneable {
|
||||||
private final String threadId;
|
private final String threadId;
|
||||||
private final String threadV2Id;
|
private final String threadV2Id;
|
||||||
private final List<User> users;
|
private List<User> users;
|
||||||
private final List<User> leftUsers;
|
private List<User> leftUsers;
|
||||||
private final List<Long> adminUserIds;
|
private List<Long> adminUserIds;
|
||||||
private final List<DirectItem> items;
|
private List<DirectItem> items;
|
||||||
private final long lastActivityAt;
|
private final long lastActivityAt;
|
||||||
private boolean muted;
|
private boolean muted;
|
||||||
private final boolean isPin;
|
private final boolean isPin;
|
||||||
@ -127,18 +128,34 @@ public class DirectThread implements Serializable {
|
|||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setUsers(final List<User> users) {
|
||||||
|
this.users = users;
|
||||||
|
}
|
||||||
|
|
||||||
public List<User> getLeftUsers() {
|
public List<User> getLeftUsers() {
|
||||||
return leftUsers;
|
return leftUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLeftUsers(final List<User> leftUsers) {
|
||||||
|
this.leftUsers = leftUsers;
|
||||||
|
}
|
||||||
|
|
||||||
public List<Long> getAdminUserIds() {
|
public List<Long> getAdminUserIds() {
|
||||||
return adminUserIds;
|
return adminUserIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAdminUserIds(final List<Long> adminUserIds) {
|
||||||
|
this.adminUserIds = adminUserIds;
|
||||||
|
}
|
||||||
|
|
||||||
public List<DirectItem> getItems() {
|
public List<DirectItem> getItems() {
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setItems(final List<DirectItem> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
public long getLastActivityAt() {
|
public long getLastActivityAt() {
|
||||||
return lastActivityAt;
|
return lastActivityAt;
|
||||||
}
|
}
|
||||||
@ -284,17 +301,59 @@ public class DirectThread implements Serializable {
|
|||||||
return firstItem;
|
return firstItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object o) {
|
public boolean equals(final Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
final DirectThread that = (DirectThread) o;
|
final DirectThread that = (DirectThread) o;
|
||||||
return Objects.equals(threadId, that.threadId) &&
|
return lastActivityAt == that.lastActivityAt &&
|
||||||
Objects.equals(threadV2Id, that.threadV2Id);
|
muted == that.muted &&
|
||||||
|
isPin == that.isPin &&
|
||||||
|
named == that.named &&
|
||||||
|
canonical == that.canonical &&
|
||||||
|
pending == that.pending &&
|
||||||
|
archived == that.archived &&
|
||||||
|
valuedRequest == that.valuedRequest &&
|
||||||
|
viewerId == that.viewerId &&
|
||||||
|
folder == that.folder &&
|
||||||
|
vcMuted == that.vcMuted &&
|
||||||
|
isGroup == that.isGroup &&
|
||||||
|
mentionsMuted == that.mentionsMuted &&
|
||||||
|
hasOlder == that.hasOlder &&
|
||||||
|
hasNewer == that.hasNewer &&
|
||||||
|
isSpam == that.isSpam &&
|
||||||
|
approvalRequiredForNewMembers == that.approvalRequiredForNewMembers &&
|
||||||
|
inputMode == that.inputMode &&
|
||||||
|
Objects.equals(threadId, that.threadId) &&
|
||||||
|
Objects.equals(threadV2Id, that.threadV2Id) &&
|
||||||
|
Objects.equals(users, that.users) &&
|
||||||
|
Objects.equals(leftUsers, that.leftUsers) &&
|
||||||
|
Objects.equals(adminUserIds, that.adminUserIds) &&
|
||||||
|
Objects.equals(items, that.items) &&
|
||||||
|
Objects.equals(threadType, that.threadType) &&
|
||||||
|
Objects.equals(threadTitle, that.threadTitle) &&
|
||||||
|
Objects.equals(pendingScore, that.pendingScore) &&
|
||||||
|
Objects.equals(inviter, that.inviter) &&
|
||||||
|
Objects.equals(lastSeenAt, that.lastSeenAt) &&
|
||||||
|
Objects.equals(newestCursor, that.newestCursor) &&
|
||||||
|
Objects.equals(oldestCursor, that.oldestCursor) &&
|
||||||
|
Objects.equals(lastPermanentItem, that.lastPermanentItem) &&
|
||||||
|
Objects.equals(directStory, that.directStory) &&
|
||||||
|
Objects.equals(threadContextItems, that.threadContextItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(threadId, threadV2Id);
|
return Objects
|
||||||
|
.hash(threadId, threadV2Id, users, leftUsers, adminUserIds, items, lastActivityAt, muted, isPin, named, canonical, pending, archived,
|
||||||
|
valuedRequest, threadType, viewerId, threadTitle, pendingScore, folder, vcMuted, isGroup, mentionsMuted, inviter, hasOlder,
|
||||||
|
hasNewer, lastSeenAt, newestCursor, oldestCursor, isSpam, lastPermanentItem, directStory, approvalRequiredForNewMembers,
|
||||||
|
inputMode, threadContextItems);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class DirectThreadDirectStory {
|
public class DirectThreadDirectStory {
|
||||||
private final List<DirectItem> items;
|
private final List<DirectItem> items;
|
||||||
@ -18,4 +19,18 @@ public class DirectThreadDirectStory {
|
|||||||
public int getUnseenCount() {
|
public int getUnseenCount() {
|
||||||
return unseenCount;
|
return unseenCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectThreadDirectStory that = (DirectThreadDirectStory) o;
|
||||||
|
return unseenCount == that.unseenCount &&
|
||||||
|
Objects.equals(items, that.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(items, unseenCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class DirectThreadLastSeenAt {
|
public class DirectThreadLastSeenAt {
|
||||||
private final String timestamp;
|
private final String timestamp;
|
||||||
private final String itemId;
|
private final String itemId;
|
||||||
@ -16,4 +18,18 @@ public class DirectThreadLastSeenAt {
|
|||||||
public String getItemId() {
|
public String getItemId() {
|
||||||
return itemId;
|
return itemId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectThreadLastSeenAt that = (DirectThreadLastSeenAt) o;
|
||||||
|
return Objects.equals(timestamp, that.timestamp) &&
|
||||||
|
Objects.equals(itemId, that.itemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(timestamp, itemId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ public class DirectThreadParticipantRequestsResponse implements Serializable, Cl
|
|||||||
private final Map<Long, String> requesterUsernames;
|
private final Map<Long, String> requesterUsernames;
|
||||||
private final String cursor;
|
private final String cursor;
|
||||||
private final int totalThreadParticipants;
|
private final int totalThreadParticipants;
|
||||||
private final int totalParticipantRequests;
|
private int totalParticipantRequests;
|
||||||
private final String status;
|
private final String status;
|
||||||
|
|
||||||
public DirectThreadParticipantRequestsResponse(final List<User> users,
|
public DirectThreadParticipantRequestsResponse(final List<User> users,
|
||||||
@ -54,6 +54,10 @@ public class DirectThreadParticipantRequestsResponse implements Serializable, Cl
|
|||||||
return totalParticipantRequests;
|
return totalParticipantRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTotalParticipantRequests(final int totalParticipantRequests) {
|
||||||
|
this.totalParticipantRequests = totalParticipantRequests;
|
||||||
|
}
|
||||||
|
|
||||||
public String getStatus() {
|
public String getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package awais.instagrabber.repositories.responses.directmessages;
|
|||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public final class RavenExpiringMediaActionSummary {
|
public final class RavenExpiringMediaActionSummary {
|
||||||
private final ActionType type;
|
private final ActionType type;
|
||||||
private final long timestamp;
|
private final long timestamp;
|
||||||
@ -25,6 +27,21 @@ public final class RavenExpiringMediaActionSummary {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final RavenExpiringMediaActionSummary that = (RavenExpiringMediaActionSummary) o;
|
||||||
|
return timestamp == that.timestamp &&
|
||||||
|
count == that.count &&
|
||||||
|
type == that.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(type, timestamp, count);
|
||||||
|
}
|
||||||
|
|
||||||
// thanks to http://github.com/warifp/InstagramAutoPostImageUrl/blob/master/vendor/mgp25/instagram-php/src/Response/Model/ActionBadge.php
|
// thanks to http://github.com/warifp/InstagramAutoPostImageUrl/blob/master/vendor/mgp25/instagram-php/src/Response/Model/ActionBadge.php
|
||||||
public enum ActionType {
|
public enum ActionType {
|
||||||
@SerializedName("raven_delivered")
|
@SerializedName("raven_delivered")
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package awais.instagrabber.repositories.responses.directmessages;
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ThreadContext implements Serializable {
|
public class ThreadContext implements Serializable {
|
||||||
private final int type;
|
private final int type;
|
||||||
@ -18,4 +19,18 @@ public class ThreadContext implements Serializable {
|
|||||||
public String getText() {
|
public String getText() {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final ThreadContext that = (ThreadContext) o;
|
||||||
|
return type == that.type &&
|
||||||
|
Objects.equals(text, that.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(type, text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@ import android.graphics.BitmapFactory;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.LruCache;
|
import android.util.LruCache;
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.util.Pair;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
@ -32,7 +32,6 @@ import awais.instagrabber.repositories.responses.MediaCandidate;
|
|||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.VideoVersion;
|
import awais.instagrabber.repositories.responses.VideoVersion;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThreadDirectStory;
|
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThreadLastSeenAt;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThreadLastSeenAt;
|
||||||
import awaisomereport.LogCollector;
|
import awaisomereport.LogCollector;
|
||||||
|
|
||||||
@ -1126,34 +1125,32 @@ public final class ResponseBodyUtils {
|
|||||||
|
|
||||||
public static boolean isRead(final DirectItem item,
|
public static boolean isRead(final DirectItem item,
|
||||||
final Map<Long, DirectThreadLastSeenAt> lastSeenAt,
|
final Map<Long, DirectThreadLastSeenAt> lastSeenAt,
|
||||||
final List<Long> userIdsToCheck,
|
final List<Long> userIdsToCheck) {
|
||||||
final DirectThreadDirectStory directStory) {
|
|
||||||
boolean read = lastSeenAt.entrySet()
|
|
||||||
.stream()
|
|
||||||
.filter(entry -> userIdsToCheck.contains(entry.getKey()))
|
|
||||||
.anyMatch(entry -> {
|
|
||||||
final String userLastSeenTsString = entry.getValue().getTimestamp();
|
|
||||||
if (userLastSeenTsString == null) return false;
|
|
||||||
final long userTs = Long.parseLong(userLastSeenTsString);
|
|
||||||
final long itemTs = item.getTimestamp();
|
|
||||||
return userTs >= itemTs;
|
|
||||||
});
|
|
||||||
// Further check if directStory exists
|
// Further check if directStory exists
|
||||||
if (read && directStory != null) {
|
// if (read && directStory != null) {
|
||||||
read = false;
|
// read = false;
|
||||||
}
|
// }
|
||||||
return read;
|
return lastSeenAt.entrySet()
|
||||||
|
.stream()
|
||||||
|
.filter(entry -> userIdsToCheck.contains(entry.getKey()))
|
||||||
|
.anyMatch(entry -> {
|
||||||
|
final String userLastSeenTsString = entry.getValue().getTimestamp();
|
||||||
|
if (userLastSeenTsString == null) return false;
|
||||||
|
final long userTs = Long.parseLong(userLastSeenTsString);
|
||||||
|
final long itemTs = item.getTimestamp();
|
||||||
|
return userTs >= itemTs;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StoryModel parseBroadcastItem(final JSONObject data) throws JSONException {
|
public static StoryModel parseBroadcastItem(final JSONObject data) throws JSONException {
|
||||||
final StoryModel model = new StoryModel(data.getString("id"),
|
final StoryModel model = new StoryModel(data.getString("id"),
|
||||||
data.getString("cover_frame_url"),
|
data.getString("cover_frame_url"),
|
||||||
data.getString("cover_frame_url"),
|
data.getString("cover_frame_url"),
|
||||||
MediaItemType.MEDIA_TYPE_LIVE,
|
MediaItemType.MEDIA_TYPE_LIVE,
|
||||||
data.optLong("published_time", 0),
|
data.optLong("published_time", 0),
|
||||||
data.getJSONObject("broadcast_owner").getString("username"),
|
data.getJSONObject("broadcast_owner").getString("username"),
|
||||||
data.getJSONObject("broadcast_owner").getLong("pk"),
|
data.getJSONObject("broadcast_owner").getLong("pk"),
|
||||||
false);
|
false);
|
||||||
model.setVideoUrl(data.getString("dash_playback_url"));
|
model.setVideoUrl(data.getString("dash_playback_url"));
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,6 @@ import android.os.AsyncTask;
|
|||||||
|
|
||||||
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.asyncs.ProfileFetcher;
|
import awais.instagrabber.asyncs.ProfileFetcher;
|
||||||
import awais.instagrabber.asyncs.UsernameFetcher;
|
import awais.instagrabber.asyncs.UsernameFetcher;
|
||||||
@ -25,10 +23,10 @@ import static awais.instagrabber.utils.Utils.settingsHelper;
|
|||||||
public class AppStateViewModel extends AndroidViewModel {
|
public class AppStateViewModel extends AndroidViewModel {
|
||||||
private static final String TAG = AppStateViewModel.class.getSimpleName();
|
private static final String TAG = AppStateViewModel.class.getSimpleName();
|
||||||
|
|
||||||
private final MutableLiveData<User> currentUser = new MutableLiveData<>();
|
|
||||||
private final String cookie;
|
private final String cookie;
|
||||||
private final boolean isLoggedIn;
|
private final boolean isLoggedIn;
|
||||||
|
|
||||||
|
private User currentUser;
|
||||||
private AccountRepository accountRepository;
|
private AccountRepository accountRepository;
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
@ -52,7 +50,7 @@ public class AppStateViewModel extends AndroidViewModel {
|
|||||||
fetchUsername(usernameListener);
|
fetchUsername(usernameListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<User> getCurrentUser() {
|
public User getCurrentUser() {
|
||||||
return currentUser;
|
return currentUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +82,7 @@ public class AppStateViewModel extends AndroidViewModel {
|
|||||||
new ProfileFetcher(
|
new ProfileFetcher(
|
||||||
username.trim().substring(1),
|
username.trim().substring(1),
|
||||||
true,
|
true,
|
||||||
currentUser::postValue
|
user -> this.currentUser = user
|
||||||
).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,188 +1,56 @@
|
|||||||
package awais.instagrabber.viewmodels;
|
package awais.instagrabber.viewmodels;
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.managers.DirectMessagesManager;
|
||||||
|
import awais.instagrabber.managers.InboxManager;
|
||||||
|
import awais.instagrabber.models.Resource;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectBadgeCount;
|
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectInbox;
|
import awais.instagrabber.repositories.responses.directmessages.DirectInbox;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectInboxResponse;
|
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
import awais.instagrabber.utils.Constants;
|
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
|
||||||
import awais.instagrabber.utils.TextUtils;
|
|
||||||
import awais.instagrabber.webservices.DirectMessagesService;
|
|
||||||
import retrofit2.Call;
|
|
||||||
import retrofit2.Callback;
|
|
||||||
import retrofit2.Response;
|
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
|
||||||
|
|
||||||
public class DirectInboxViewModel extends ViewModel {
|
public class DirectInboxViewModel extends ViewModel {
|
||||||
private static final String TAG = DirectInboxViewModel.class.getSimpleName();
|
private static final String TAG = DirectInboxViewModel.class.getSimpleName();
|
||||||
|
|
||||||
private final DirectMessagesService service;
|
private final InboxManager inboxManager;
|
||||||
private final MutableLiveData<Boolean> fetchingInbox = new MutableLiveData<>(false);
|
|
||||||
private final MutableLiveData<List<DirectThread>> threads = new MutableLiveData<>();
|
|
||||||
private final MutableLiveData<Boolean> fetchingUnseenCount = new MutableLiveData<>(false);
|
|
||||||
private final MutableLiveData<Integer> unseenCount = new MutableLiveData<>(0);
|
|
||||||
private final MutableLiveData<Integer> pendingRequestsTotal = new MutableLiveData<>(0);
|
|
||||||
|
|
||||||
private Call<DirectInboxResponse> inboxRequest;
|
|
||||||
private Call<DirectBadgeCount> unseenCountRequest;
|
|
||||||
private long seqId;
|
|
||||||
private String cursor;
|
|
||||||
private boolean hasOlder = true;
|
|
||||||
private User viewer;
|
|
||||||
|
|
||||||
public DirectInboxViewModel() {
|
public DirectInboxViewModel() {
|
||||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
|
||||||
final long userId = CookieUtils.getUserIdFromCookie(cookie);
|
inboxManager = messagesManager.getInboxManager();
|
||||||
final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID);
|
}
|
||||||
final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
|
|
||||||
if (TextUtils.isEmpty(csrfToken) || userId <= 0 || TextUtils.isEmpty(deviceUuid)) {
|
public LiveData<Resource<DirectInbox>> getInbox() {
|
||||||
throw new IllegalArgumentException("User is not logged in!");
|
return inboxManager.getInbox();
|
||||||
}
|
|
||||||
service = DirectMessagesService.getInstance(csrfToken, userId, deviceUuid);
|
|
||||||
fetchInbox();
|
|
||||||
fetchUnseenCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<DirectThread>> getThreads() {
|
public LiveData<List<DirectThread>> getThreads() {
|
||||||
return threads;
|
return inboxManager.getThreads();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setThreads(final List<DirectThread> threads) {
|
public LiveData<Resource<Integer>> getUnseenCount() {
|
||||||
this.threads.postValue(threads);
|
return inboxManager.getUnseenCount();
|
||||||
}
|
|
||||||
|
|
||||||
public void addThreads(final Collection<DirectThread> threads) {
|
|
||||||
if (threads == null) return;
|
|
||||||
List<DirectThread> list = getThreads().getValue();
|
|
||||||
list = list == null ? new LinkedList<>() : new LinkedList<>(list);
|
|
||||||
list.addAll(threads);
|
|
||||||
this.threads.postValue(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LiveData<Integer> getUnseenCount() {
|
|
||||||
return unseenCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LiveData<Boolean> getFetchingInbox() {
|
|
||||||
return fetchingInbox;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Integer> getPendingRequestsTotal() {
|
public LiveData<Integer> getPendingRequestsTotal() {
|
||||||
return pendingRequestsTotal;
|
return inboxManager.getPendingRequestsTotal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public User getViewer() {
|
public User getViewer() {
|
||||||
return viewer;
|
return inboxManager.getViewer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fetchInbox() {
|
public void fetchInbox() {
|
||||||
if ((fetchingInbox.getValue() != null && fetchingInbox.getValue()) || !hasOlder) return;
|
inboxManager.fetchInbox();
|
||||||
stopCurrentInboxRequest();
|
|
||||||
fetchingInbox.postValue(true);
|
|
||||||
inboxRequest = service.fetchInbox(cursor, seqId);
|
|
||||||
inboxRequest.enqueue(new Callback<DirectInboxResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<DirectInboxResponse> call, @NonNull final Response<DirectInboxResponse> response) {
|
|
||||||
parseInboxResponse(response.body());
|
|
||||||
fetchingInbox.postValue(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<DirectInboxResponse> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "Failed fetching dm inbox", t);
|
|
||||||
fetchingInbox.postValue(false);
|
|
||||||
hasOlder = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseInboxResponse(final DirectInboxResponse response) {
|
|
||||||
if (response == null) {
|
|
||||||
hasOlder = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!response.getStatus().equals("ok")) {
|
|
||||||
Log.e(TAG, "DM inbox fetch response: status not ok");
|
|
||||||
hasOlder = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
seqId = response.getSeqId();
|
|
||||||
if (viewer == null) {
|
|
||||||
viewer = response.getViewer();
|
|
||||||
}
|
|
||||||
final DirectInbox inbox = response.getInbox();
|
|
||||||
final List<DirectThread> threads = inbox.getThreads();
|
|
||||||
if (!TextUtils.isEmpty(cursor)) {
|
|
||||||
addThreads(threads);
|
|
||||||
} else {
|
|
||||||
setThreads(threads);
|
|
||||||
}
|
|
||||||
cursor = inbox.getOldestCursor();
|
|
||||||
hasOlder = inbox.hasOlder();
|
|
||||||
pendingRequestsTotal.postValue(response.getPendingRequestsTotal());
|
|
||||||
// unseenCount.postValue(inbox.getUnseenCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopCurrentInboxRequest() {
|
|
||||||
if (inboxRequest == null || inboxRequest.isCanceled() || inboxRequest.isExecuted()) return;
|
|
||||||
inboxRequest.cancel();
|
|
||||||
inboxRequest = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fetchUnseenCount() {
|
|
||||||
if ((fetchingUnseenCount.getValue() != null && fetchingUnseenCount.getValue())) return;
|
|
||||||
stopCurrentUnseenCountRequest();
|
|
||||||
fetchingUnseenCount.postValue(true);
|
|
||||||
unseenCountRequest = service.fetchUnseenCount();
|
|
||||||
unseenCountRequest.enqueue(new Callback<DirectBadgeCount>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<DirectBadgeCount> call, @NonNull final Response<DirectBadgeCount> response) {
|
|
||||||
parseUnseenCountResponse(response.body());
|
|
||||||
fetchingUnseenCount.postValue(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<DirectBadgeCount> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "Failed fetching unseen count", t);
|
|
||||||
fetchingUnseenCount.postValue(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseUnseenCountResponse(final DirectBadgeCount directBadgeCount) {
|
|
||||||
if (directBadgeCount == null) return;
|
|
||||||
unseenCount.postValue(directBadgeCount.getBadgeCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopCurrentUnseenCountRequest() {
|
|
||||||
if (unseenCountRequest == null || unseenCountRequest.isCanceled() || unseenCountRequest.isExecuted()) return;
|
|
||||||
unseenCountRequest.cancel();
|
|
||||||
unseenCountRequest = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
cursor = null;
|
inboxManager.refresh();
|
||||||
seqId = 0;
|
|
||||||
hasOlder = true;
|
|
||||||
fetchInbox();
|
|
||||||
fetchUnseenCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
stopCurrentInboxRequest();
|
inboxManager.onDestroy();
|
||||||
// getThreads().postValue(Collections.emptyList());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,141 +1,48 @@
|
|||||||
package awais.instagrabber.viewmodels;
|
package awais.instagrabber.viewmodels;
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.managers.DirectMessagesManager;
|
||||||
|
import awais.instagrabber.managers.InboxManager;
|
||||||
|
import awais.instagrabber.models.Resource;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectBadgeCount;
|
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectInbox;
|
import awais.instagrabber.repositories.responses.directmessages.DirectInbox;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectInboxResponse;
|
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
import awais.instagrabber.utils.Constants;
|
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
|
||||||
import awais.instagrabber.utils.TextUtils;
|
|
||||||
import awais.instagrabber.webservices.DirectMessagesService;
|
|
||||||
import retrofit2.Call;
|
|
||||||
import retrofit2.Callback;
|
|
||||||
import retrofit2.Response;
|
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
|
||||||
|
|
||||||
public class DirectPendingInboxViewModel extends ViewModel {
|
public class DirectPendingInboxViewModel extends ViewModel {
|
||||||
private static final String TAG = DirectPendingInboxViewModel.class.getSimpleName();
|
private static final String TAG = DirectPendingInboxViewModel.class.getSimpleName();
|
||||||
|
|
||||||
private final DirectMessagesService service;
|
private final InboxManager inboxManager;
|
||||||
private final MutableLiveData<Boolean> fetchingInbox = new MutableLiveData<>(false);
|
|
||||||
private final MutableLiveData<List<DirectThread>> threads = new MutableLiveData<>();
|
|
||||||
|
|
||||||
private Call<DirectInboxResponse> inboxRequest;
|
|
||||||
private Call<DirectBadgeCount> unseenCountRequest;
|
|
||||||
private long seqId;
|
|
||||||
private String cursor;
|
|
||||||
private boolean hasOlder = true;
|
|
||||||
private User viewer;
|
|
||||||
|
|
||||||
public DirectPendingInboxViewModel() {
|
public DirectPendingInboxViewModel() {
|
||||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
inboxManager = DirectMessagesManager.getInstance().getPendingInboxManager();
|
||||||
final long userId = CookieUtils.getUserIdFromCookie(cookie);
|
inboxManager.fetchInbox();
|
||||||
final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID);
|
|
||||||
final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
|
|
||||||
if (TextUtils.isEmpty(csrfToken) || userId <= 0 || TextUtils.isEmpty(deviceUuid)) {
|
|
||||||
throw new IllegalArgumentException("User is not logged in!");
|
|
||||||
}
|
|
||||||
service = DirectMessagesService.getInstance(csrfToken, userId, deviceUuid);
|
|
||||||
fetchInbox();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<DirectThread>> getThreads() {
|
public LiveData<List<DirectThread>> getThreads() {
|
||||||
return threads;
|
return inboxManager.getThreads();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setThreads(final List<DirectThread> threads) {
|
public LiveData<Resource<DirectInbox>> getInbox() {
|
||||||
this.threads.postValue(threads);
|
return inboxManager.getInbox();
|
||||||
}
|
|
||||||
|
|
||||||
public void addThreads(final Collection<DirectThread> threads) {
|
|
||||||
if (threads == null) return;
|
|
||||||
List<DirectThread> list = getThreads().getValue();
|
|
||||||
list = list == null ? new LinkedList<>() : new LinkedList<>(list);
|
|
||||||
list.addAll(threads);
|
|
||||||
this.threads.postValue(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LiveData<Boolean> getFetchingInbox() {
|
|
||||||
return fetchingInbox;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public User getViewer() {
|
public User getViewer() {
|
||||||
return viewer;
|
return inboxManager.getViewer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fetchInbox() {
|
public void fetchInbox() {
|
||||||
if ((fetchingInbox.getValue() != null && fetchingInbox.getValue()) || !hasOlder) return;
|
inboxManager.fetchInbox();
|
||||||
stopCurrentInboxRequest();
|
|
||||||
fetchingInbox.postValue(true);
|
|
||||||
inboxRequest = service.fetchPendingInbox(cursor, seqId);
|
|
||||||
inboxRequest.enqueue(new Callback<DirectInboxResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<DirectInboxResponse> call, @NonNull final Response<DirectInboxResponse> response) {
|
|
||||||
parseInboxResponse(response.body());
|
|
||||||
fetchingInbox.postValue(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<DirectInboxResponse> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "Failed fetching pending inbox", t);
|
|
||||||
fetchingInbox.postValue(false);
|
|
||||||
hasOlder = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseInboxResponse(final DirectInboxResponse response) {
|
|
||||||
if (response == null) {
|
|
||||||
hasOlder = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!response.getStatus().equals("ok")) {
|
|
||||||
Log.e(TAG, "DM pending inbox fetch response: status not ok");
|
|
||||||
hasOlder = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
seqId = response.getSeqId();
|
|
||||||
if (viewer == null) {
|
|
||||||
viewer = response.getViewer();
|
|
||||||
}
|
|
||||||
final DirectInbox inbox = response.getInbox();
|
|
||||||
final List<DirectThread> threads = inbox.getThreads();
|
|
||||||
if (!TextUtils.isEmpty(cursor)) {
|
|
||||||
addThreads(threads);
|
|
||||||
} else {
|
|
||||||
setThreads(threads);
|
|
||||||
}
|
|
||||||
cursor = inbox.getOldestCursor();
|
|
||||||
hasOlder = inbox.hasOlder();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopCurrentInboxRequest() {
|
|
||||||
if (inboxRequest == null || inboxRequest.isCanceled() || inboxRequest.isExecuted()) return;
|
|
||||||
inboxRequest.cancel();
|
|
||||||
inboxRequest = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
cursor = null;
|
inboxManager.refresh();
|
||||||
seqId = 0;
|
|
||||||
hasOlder = true;
|
|
||||||
fetchInbox();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
stopCurrentInboxRequest();
|
inboxManager.onDestroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,49 +1,30 @@
|
|||||||
package awais.instagrabber.viewmodels;
|
package awais.instagrabber.viewmodels;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.core.util.Pair;
|
import androidx.core.util.Pair;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.dialogs.MultiOptionDialogFragment.Option;
|
import awais.instagrabber.dialogs.MultiOptionDialogFragment.Option;
|
||||||
|
import awais.instagrabber.managers.DirectMessagesManager;
|
||||||
|
import awais.instagrabber.managers.ThreadManager;
|
||||||
import awais.instagrabber.models.Resource;
|
import awais.instagrabber.models.Resource;
|
||||||
import awais.instagrabber.repositories.responses.FriendshipChangeResponse;
|
|
||||||
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse;
|
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThreadDetailsChangeResponse;
|
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThreadParticipantRequestsResponse;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThreadParticipantRequestsResponse;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.webservices.DirectMessagesService;
|
|
||||||
import awais.instagrabber.webservices.FriendshipService;
|
|
||||||
import awais.instagrabber.webservices.ServiceCallback;
|
|
||||||
import okhttp3.ResponseBody;
|
|
||||||
import retrofit2.Call;
|
|
||||||
import retrofit2.Callback;
|
|
||||||
import retrofit2.Response;
|
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
@ -58,573 +39,186 @@ public class DirectSettingsViewModel extends AndroidViewModel {
|
|||||||
private static final String ACTION_RESTRICT = "restrict";
|
private static final String ACTION_RESTRICT = "restrict";
|
||||||
private static final String ACTION_UNRESTRICT = "unrestrict";
|
private static final String ACTION_UNRESTRICT = "unrestrict";
|
||||||
|
|
||||||
private final MutableLiveData<Pair<List<User>, List<User>>> users = new MutableLiveData<>(
|
private final long viewerId;
|
||||||
new Pair<>(Collections.emptyList(), Collections.emptyList()));
|
|
||||||
private final MutableLiveData<String> title = new MutableLiveData<>("");
|
|
||||||
private final MutableLiveData<List<Long>> adminUserIds = new MutableLiveData<>(Collections.emptyList());
|
|
||||||
private final MutableLiveData<Boolean> muted = new MutableLiveData<>(false);
|
|
||||||
private final MutableLiveData<Boolean> mentionsMuted = new MutableLiveData<>(false);
|
|
||||||
private final MutableLiveData<Boolean> approvalRequiredToJoin = new MutableLiveData<>(false);
|
|
||||||
private final MutableLiveData<DirectThreadParticipantRequestsResponse> pendingRequests = new MutableLiveData<>(null);
|
|
||||||
private final MutableLiveData<Integer> inputMode = new MutableLiveData<>(null);
|
|
||||||
private final MutableLiveData<Boolean> isPending = new MutableLiveData<>(false);
|
|
||||||
private final DirectMessagesService directMessagesService;
|
|
||||||
private final long userId;
|
|
||||||
private final Resources resources;
|
private final Resources resources;
|
||||||
private final FriendshipService friendshipService;
|
private final ThreadManager threadManager;
|
||||||
private final String csrfToken;
|
|
||||||
|
|
||||||
private DirectThread thread;
|
public DirectSettingsViewModel(final Application application,
|
||||||
private boolean viewerIsAdmin;
|
@NonNull final String threadId,
|
||||||
private User viewer;
|
final boolean pending,
|
||||||
|
@NonNull final User currentUser) {
|
||||||
public DirectSettingsViewModel(final Application application) {
|
|
||||||
super(application);
|
super(application);
|
||||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||||
userId = CookieUtils.getUserIdFromCookie(cookie);
|
viewerId = CookieUtils.getUserIdFromCookie(cookie);
|
||||||
final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID);
|
final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID);
|
||||||
csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
|
final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
|
||||||
if (TextUtils.isEmpty(csrfToken) || userId <= 0 || TextUtils.isEmpty(deviceUuid)) {
|
if (TextUtils.isEmpty(csrfToken) || viewerId <= 0 || TextUtils.isEmpty(deviceUuid)) {
|
||||||
throw new IllegalArgumentException("User is not logged in!");
|
throw new IllegalArgumentException("User is not logged in!");
|
||||||
}
|
}
|
||||||
directMessagesService = DirectMessagesService.getInstance(csrfToken, userId, deviceUuid);
|
final ContentResolver contentResolver = application.getContentResolver();
|
||||||
friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, userId);
|
|
||||||
resources = getApplication().getResources();
|
resources = getApplication().getResources();
|
||||||
|
final DirectMessagesManager messagesManager = DirectMessagesManager.getInstance();
|
||||||
|
threadManager = messagesManager.getThreadManager(threadId, pending, currentUser, contentResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public DirectThread getThread() {
|
public LiveData<DirectThread> getThread() {
|
||||||
return thread;
|
return threadManager.getThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setThread(@NonNull final DirectThread thread) {
|
// public void setThread(@NonNull final DirectThread thread) {
|
||||||
this.thread = thread;
|
// this.thread = thread;
|
||||||
inputMode.postValue(thread.getInputMode());
|
// inputMode.postValue(thread.getInputMode());
|
||||||
List<User> users = thread.getUsers();
|
// List<User> users = thread.getUsers();
|
||||||
if (viewer != null) {
|
// final ImmutableList.Builder<User> builder = ImmutableList.<User>builder().add(currentUser);
|
||||||
final ImmutableList.Builder<User> builder = ImmutableList.<User>builder().add(viewer);
|
// if (users != null) {
|
||||||
if (users != null) {
|
// builder.addAll(users);
|
||||||
builder.addAll(users);
|
// }
|
||||||
}
|
// users = builder.build();
|
||||||
users = builder.build();
|
// this.users.postValue(new Pair<>(users, thread.getLeftUsers()));
|
||||||
}
|
// // setTitle(thread.getThreadTitle());
|
||||||
this.users.postValue(new Pair<>(users, thread.getLeftUsers()));
|
// final List<Long> adminUserIds = thread.getAdminUserIds();
|
||||||
setTitle(thread.getThreadTitle());
|
// this.adminUserIds.postValue(adminUserIds);
|
||||||
final List<Long> adminUserIds = thread.getAdminUserIds();
|
// viewerIsAdmin = adminUserIds.contains(viewerId);
|
||||||
this.adminUserIds.postValue(adminUserIds);
|
// muted.postValue(thread.isMuted());
|
||||||
viewerIsAdmin = adminUserIds.contains(userId);
|
// mentionsMuted.postValue(thread.isMentionsMuted());
|
||||||
muted.postValue(thread.isMuted());
|
// approvalRequiredToJoin.postValue(thread.isApprovalRequiredForNewMembers());
|
||||||
mentionsMuted.postValue(thread.isMentionsMuted());
|
// isPending.postValue(thread.isPending());
|
||||||
approvalRequiredToJoin.postValue(thread.isApprovalRequiredForNewMembers());
|
// if (thread.getInputMode() != 1 && thread.isGroup() && viewerIsAdmin) {
|
||||||
isPending.postValue(thread.isPending());
|
// fetchPendingRequests();
|
||||||
if (thread.getInputMode() != 1 && thread.isGroup() && viewerIsAdmin) {
|
// }
|
||||||
fetchPendingRequests();
|
// }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LiveData<Integer> getInputMode() {
|
public LiveData<Integer> getInputMode() {
|
||||||
return inputMode;
|
return threadManager.getInputMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGroup() {
|
public LiveData<Boolean> isGroup() {
|
||||||
if (thread != null) {
|
return threadManager.isGroup();
|
||||||
return thread.isGroup();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Pair<List<User>, List<User>>> getUsers() {
|
public LiveData<List<User>> getUsers() {
|
||||||
return users;
|
return threadManager.getUsersWithCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<List<User>> getLeftUsers() {
|
||||||
|
return threadManager.getLeftUsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<Pair<List<User>, List<User>>> getUsersAndLeftUsers() {
|
||||||
|
return threadManager.getUsersAndLeftUsers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<String> getTitle() {
|
public LiveData<String> getTitle() {
|
||||||
return title;
|
return threadManager.getThreadTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTitle(final String title) {
|
// public void setTitle(final String title) {
|
||||||
if (title == null) {
|
// if (title == null) {
|
||||||
this.title.postValue("");
|
// this.title.postValue("");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
this.title.postValue(title.trim());
|
// this.title.postValue(title.trim());
|
||||||
}
|
// }
|
||||||
|
|
||||||
public LiveData<List<Long>> getAdminUserIds() {
|
public LiveData<List<Long>> getAdminUserIds() {
|
||||||
return adminUserIds;
|
return threadManager.getAdminUserIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Boolean> getMuted() {
|
public LiveData<Boolean> isMuted() {
|
||||||
return muted;
|
return threadManager.isMuted();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Boolean> getApprovalRequiredToJoin() {
|
public LiveData<Boolean> getApprovalRequiredToJoin() {
|
||||||
return approvalRequiredToJoin;
|
return threadManager.isApprovalRequiredToJoin();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<DirectThreadParticipantRequestsResponse> getPendingRequests() {
|
public LiveData<DirectThreadParticipantRequestsResponse> getPendingRequests() {
|
||||||
return pendingRequests;
|
return threadManager.getPendingRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Boolean> isPending() {
|
public LiveData<Boolean> isPending() {
|
||||||
return isPending;
|
return threadManager.isPending();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isViewerAdmin() {
|
public LiveData<Boolean> isViewerAdmin() {
|
||||||
return viewerIsAdmin;
|
return threadManager.isViewerAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> updateTitle(final String newTitle) {
|
public LiveData<Resource<Object>> updateTitle(final String newTitle) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.updateTitle(newTitle);
|
||||||
final Call<DirectThreadDetailsChangeResponse> addUsersRequest = directMessagesService
|
|
||||||
.updateTitle(thread.getThreadId(), newTitle.trim());
|
|
||||||
handleDetailsChangeRequest(data, addUsersRequest);
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> addMembers(final Set<User> users) {
|
public LiveData<Resource<Object>> addMembers(final Set<User> users) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.addMembers(users);
|
||||||
final Call<DirectThreadDetailsChangeResponse> addUsersRequest = directMessagesService
|
|
||||||
.addUsers(thread.getThreadId(), users.stream().map(User::getPk).collect(Collectors.toList()));
|
|
||||||
handleDetailsChangeRequest(data, addUsersRequest);
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> removeMember(final User user) {
|
public LiveData<Resource<Object>> removeMember(final User user) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.removeMember(user);
|
||||||
final Call<String> request = directMessagesService
|
|
||||||
.removeUsers(thread.getThreadId(), Collections.singleton(user.getPk()));
|
|
||||||
request.enqueue(new Callback<String>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
handleSettingChangeResponseError(response, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Pair<List<User>, List<User>> usersValue = users.getValue();
|
|
||||||
if (usersValue == null) {
|
|
||||||
usersValue = new Pair<>(Collections.emptyList(), Collections.emptyList());
|
|
||||||
}
|
|
||||||
List<User> activeUsers = usersValue.first;
|
|
||||||
if (activeUsers == null) {
|
|
||||||
activeUsers = Collections.emptyList();
|
|
||||||
}
|
|
||||||
final List<User> updatedActiveUsers = activeUsers.stream()
|
|
||||||
.filter(user1 -> user1.getPk() != user.getPk())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
List<User> leftUsers = usersValue.second;
|
|
||||||
if (leftUsers == null) {
|
|
||||||
leftUsers = Collections.emptyList();
|
|
||||||
}
|
|
||||||
final ImmutableList<User> updateLeftUsers = ImmutableList.<User>builder()
|
|
||||||
.addAll(leftUsers)
|
|
||||||
.add(user)
|
|
||||||
.build();
|
|
||||||
users.postValue(new Pair<>(updatedActiveUsers, updateLeftUsers));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiveData<Resource<Object>> makeAdmin(final User user) {
|
private LiveData<Resource<Object>> makeAdmin(final User user) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.makeAdmin(user);
|
||||||
if (isAdmin(user)) return data;
|
|
||||||
final Call<String> request = directMessagesService.addAdmins(thread.getThreadId(), Collections.singleton(user.getPk()));
|
|
||||||
request.enqueue(new Callback<String>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
handleSettingChangeResponseError(response, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final List<Long> currentAdmins = adminUserIds.getValue();
|
|
||||||
adminUserIds.postValue(ImmutableList.<Long>builder()
|
|
||||||
.addAll(currentAdmins != null ? currentAdmins : Collections.emptyList())
|
|
||||||
.add(user.getPk())
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiveData<Resource<Object>> removeAdmin(final User user) {
|
private LiveData<Resource<Object>> removeAdmin(final User user) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.removeAdmin(user);
|
||||||
if (!isAdmin(user)) return data;
|
|
||||||
final Call<String> request = directMessagesService.removeAdmins(thread.getThreadId(), Collections.singleton(user.getPk()));
|
|
||||||
request.enqueue(new Callback<String>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
handleSettingChangeResponseError(response, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final List<Long> currentAdmins = adminUserIds.getValue();
|
|
||||||
if (currentAdmins == null) return;
|
|
||||||
adminUserIds.postValue(currentAdmins.stream()
|
|
||||||
.filter(userId1 -> userId1 != user.getPk())
|
|
||||||
.collect(Collectors.toList()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> mute() {
|
public LiveData<Resource<Object>> mute() {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.mute();
|
||||||
data.postValue(Resource.loading(null));
|
|
||||||
if (thread.isMuted()) {
|
|
||||||
data.postValue(Resource.success(new Object()));
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
final Call<String> request = directMessagesService.mute(thread.getThreadId());
|
|
||||||
request.enqueue(new Callback<String>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
handleSettingChangeResponseError(response, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
thread.setMuted(true);
|
|
||||||
muted.postValue(true);
|
|
||||||
data.postValue(Resource.success(new Object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> unmute() {
|
public LiveData<Resource<Object>> unmute() {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.unmute();
|
||||||
data.postValue(Resource.loading(null));
|
|
||||||
if (!thread.isMuted()) {
|
|
||||||
data.postValue(Resource.success(new Object()));
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
final Call<String> request = directMessagesService.unmute(thread.getThreadId());
|
|
||||||
request.enqueue(new Callback<String>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
handleSettingChangeResponseError(response, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
thread.setMuted(false);
|
|
||||||
muted.postValue(false);
|
|
||||||
data.postValue(Resource.success(new Object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> muteMentions() {
|
public LiveData<Resource<Object>> muteMentions() {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.muteMentions();
|
||||||
data.postValue(Resource.loading(null));
|
|
||||||
if (thread.isMentionsMuted()) {
|
|
||||||
data.postValue(Resource.success(new Object()));
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
final Call<String> request = directMessagesService.muteMentions(thread.getThreadId());
|
|
||||||
request.enqueue(new Callback<String>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
handleSettingChangeResponseError(response, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
thread.setMentionsMuted(true);
|
|
||||||
mentionsMuted.postValue(true);
|
|
||||||
data.postValue(Resource.success(new Object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> unmuteMentions() {
|
public LiveData<Resource<Object>> unmuteMentions() {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.unmuteMentions();
|
||||||
data.postValue(Resource.loading(null));
|
|
||||||
if (!thread.isMentionsMuted()) {
|
|
||||||
data.postValue(Resource.success(new Object()));
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
final Call<String> request = directMessagesService.unmuteMentions(thread.getThreadId());
|
|
||||||
request.enqueue(new Callback<String>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
handleSettingChangeResponseError(response, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
thread.setMentionsMuted(false);
|
|
||||||
mentionsMuted.postValue(false);
|
|
||||||
data.postValue(Resource.success(new Object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleSettingChangeResponseError(@NonNull final Response<String> response,
|
|
||||||
final MutableLiveData<Resource<Object>> data) {
|
|
||||||
final ResponseBody errorBody = response.errorBody();
|
|
||||||
if (errorBody == null) {
|
|
||||||
handleErrorResponse(response, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
final JSONObject json = new JSONObject(errorBody.string());
|
|
||||||
if (json.has("message")) {
|
|
||||||
data.postValue(Resource.error(json.getString("message"), null));
|
|
||||||
}
|
|
||||||
} catch (IOException | JSONException e) {
|
|
||||||
Log.e(TAG, "onResponse: ", e);
|
|
||||||
data.postValue(Resource.error(e.getMessage(), null));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiveData<Resource<Object>> blockUser(final User user) {
|
private LiveData<Resource<Object>> blockUser(final User user) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.blockUser(user);
|
||||||
friendshipService.block(user.getPk(), new ServiceCallback<FriendshipChangeResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(final FriendshipChangeResponse result) {
|
|
||||||
// refresh thread
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiveData<Resource<Object>> unblockUser(final User user) {
|
private LiveData<Resource<Object>> unblockUser(final User user) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.unblockUser(user);
|
||||||
friendshipService.unblock(user.getPk(), new ServiceCallback<FriendshipChangeResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(final FriendshipChangeResponse result) {
|
|
||||||
// refresh thread
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiveData<Resource<Object>> restrictUser(final User user) {
|
private LiveData<Resource<Object>> restrictUser(final User user) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.restrictUser(user);
|
||||||
friendshipService.toggleRestrict(user.getPk(), true, new ServiceCallback<FriendshipRestrictResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(final FriendshipRestrictResponse result) {
|
|
||||||
// refresh thread
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiveData<Resource<Object>> unRestrictUser(final User user) {
|
private LiveData<Resource<Object>> unRestrictUser(final User user) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.unRestrictUser(user);
|
||||||
friendshipService.toggleRestrict(user.getPk(), false, new ServiceCallback<FriendshipRestrictResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(final FriendshipRestrictResponse result) {
|
|
||||||
// refresh thread
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> approveUsers(final List<User> users) {
|
public LiveData<Resource<Object>> approveUsers(final List<User> users) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.approveUsers(users);
|
||||||
data.postValue(Resource.loading(null));
|
|
||||||
final Call<DirectThreadDetailsChangeResponse> approveUsersRequest = directMessagesService
|
|
||||||
.approveParticipantRequests(thread.getThreadId(), users.stream().map(User::getPk).collect(Collectors.toList()));
|
|
||||||
handleDetailsChangeRequest(data, approveUsersRequest);
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> denyUsers(final List<User> users) {
|
public LiveData<Resource<Object>> denyUsers(final List<User> users) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.denyUsers(users);
|
||||||
data.postValue(Resource.loading(null));
|
|
||||||
final Call<DirectThreadDetailsChangeResponse> approveUsersRequest = directMessagesService
|
|
||||||
.declineParticipantRequests(thread.getThreadId(), users.stream().map(User::getPk).collect(Collectors.toList()));
|
|
||||||
handleDetailsChangeRequest(data, approveUsersRequest, () -> {
|
|
||||||
final DirectThreadParticipantRequestsResponse pendingRequestsValue = pendingRequests.getValue();
|
|
||||||
if (pendingRequestsValue == null) return;
|
|
||||||
final List<User> pendingUsers = pendingRequestsValue.getUsers();
|
|
||||||
if (pendingUsers == null || pendingUsers.isEmpty()) return;
|
|
||||||
final List<User> filtered = pendingUsers.stream()
|
|
||||||
.filter(o -> !users.contains(o))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
try {
|
|
||||||
final DirectThreadParticipantRequestsResponse clone = (DirectThreadParticipantRequestsResponse) pendingRequestsValue.clone();
|
|
||||||
clone.setUsers(filtered);
|
|
||||||
pendingRequests.postValue(clone);
|
|
||||||
} catch (CloneNotSupportedException e) {
|
|
||||||
Log.e(TAG, "denyUsers: ", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> approvalRequired() {
|
public LiveData<Resource<Object>> approvalRequired() {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.approvalRequired();
|
||||||
data.postValue(Resource.loading(null));
|
|
||||||
if (thread.isApprovalRequiredForNewMembers()) {
|
|
||||||
data.postValue(Resource.success(new Object()));
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
final Call<DirectThreadDetailsChangeResponse> request = directMessagesService.approvalRequired(thread.getThreadId());
|
|
||||||
handleDetailsChangeRequest(data, request, () -> {
|
|
||||||
thread.setApprovalRequiredForNewMembers(true);
|
|
||||||
approvalRequiredToJoin.postValue(true);
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> approvalNotRequired() {
|
public LiveData<Resource<Object>> approvalNotRequired() {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.approvalNotRequired();
|
||||||
data.postValue(Resource.loading(null));
|
|
||||||
if (!thread.isApprovalRequiredForNewMembers()) {
|
|
||||||
data.postValue(Resource.success(new Object()));
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
final Call<DirectThreadDetailsChangeResponse> request = directMessagesService.approvalNotRequired(thread.getThreadId());
|
|
||||||
handleDetailsChangeRequest(data, request, () -> {
|
|
||||||
thread.setApprovalRequiredForNewMembers(false);
|
|
||||||
approvalRequiredToJoin.postValue(false);
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> leave() {
|
public LiveData<Resource<Object>> leave() {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.leave();
|
||||||
data.postValue(Resource.loading(null));
|
|
||||||
final Call<DirectThreadDetailsChangeResponse> request = directMessagesService.leave(thread.getThreadId());
|
|
||||||
handleDetailsChangeRequest(data, request);
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<Object>> end() {
|
public LiveData<Resource<Object>> end() {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
return threadManager.end();
|
||||||
data.postValue(Resource.loading(null));
|
|
||||||
final Call<DirectThreadDetailsChangeResponse> request = directMessagesService.end(thread.getThreadId());
|
|
||||||
handleDetailsChangeRequest(data, request, () -> {
|
|
||||||
thread.setInputMode(1);
|
|
||||||
inputMode.postValue(1);
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface OnSuccessAction {
|
|
||||||
void onSuccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleDetailsChangeRequest(final MutableLiveData<Resource<Object>> data,
|
|
||||||
final Call<DirectThreadDetailsChangeResponse> request) {
|
|
||||||
handleDetailsChangeRequest(data, request, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleDetailsChangeRequest(final MutableLiveData<Resource<Object>> data,
|
|
||||||
final Call<DirectThreadDetailsChangeResponse> request,
|
|
||||||
@Nullable final OnSuccessAction action) {
|
|
||||||
request.enqueue(new Callback<DirectThreadDetailsChangeResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<DirectThreadDetailsChangeResponse> call,
|
|
||||||
@NonNull final Response<DirectThreadDetailsChangeResponse> response) {
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
handleErrorResponse(response, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final DirectThreadDetailsChangeResponse changeResponse = response.body();
|
|
||||||
if (changeResponse == null) {
|
|
||||||
data.postValue(Resource.error("Response is null", null));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
data.postValue(Resource.success(new Object()));
|
|
||||||
final DirectThread thread = changeResponse.getThread();
|
|
||||||
if (thread != null) {
|
|
||||||
setThread(thread);
|
|
||||||
}
|
|
||||||
if (action != null) {
|
|
||||||
action.onSuccess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<DirectThreadDetailsChangeResponse> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
data.postValue(Resource.error(t.getMessage(), null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleErrorResponse(@NonNull final Response<?> response,
|
|
||||||
final MutableLiveData<Resource<Object>> data) {
|
|
||||||
final ResponseBody errorBody = response.errorBody();
|
|
||||||
if (errorBody == null) {
|
|
||||||
data.postValue(Resource.error("Request failed!", null));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
data.postValue(Resource.error(errorBody.string(), null));
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "onResponse: ", e);
|
|
||||||
data.postValue(Resource.error(e.getMessage(), null));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Option<String>> createUserOptions(final User user) {
|
public ArrayList<Option<String>> createUserOptions(final User user) {
|
||||||
@ -632,10 +226,11 @@ public class DirectSettingsViewModel extends AndroidViewModel {
|
|||||||
if (user == null || isSelf(user) || hasLeft(user)) {
|
if (user == null || isSelf(user) || hasLeft(user)) {
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
if (viewerIsAdmin) {
|
final Boolean viewerIsAdmin = threadManager.isViewerAdmin().getValue();
|
||||||
|
if (viewerIsAdmin != null && viewerIsAdmin) {
|
||||||
options.add(new Option<>(getString(R.string.dms_action_kick), ACTION_KICK));
|
options.add(new Option<>(getString(R.string.dms_action_kick), ACTION_KICK));
|
||||||
|
|
||||||
final boolean isAdmin = isAdmin(user);
|
final boolean isAdmin = threadManager.isAdmin(user);
|
||||||
options.add(new Option<>(
|
options.add(new Option<>(
|
||||||
isAdmin ? getString(R.string.dms_action_remove_admin) : getString(R.string.dms_action_make_admin),
|
isAdmin ? getString(R.string.dms_action_remove_admin) : getString(R.string.dms_action_make_admin),
|
||||||
isAdmin ? ACTION_REMOVE_ADMIN : ACTION_MAKE_ADMIN
|
isAdmin ? ACTION_REMOVE_ADMIN : ACTION_MAKE_ADMIN
|
||||||
@ -649,8 +244,8 @@ public class DirectSettingsViewModel extends AndroidViewModel {
|
|||||||
));
|
));
|
||||||
|
|
||||||
// options.add(new Option<>(getString(R.string.report), ACTION_REPORT));
|
// options.add(new Option<>(getString(R.string.report), ACTION_REPORT));
|
||||||
|
final Boolean isGroup = threadManager.isGroup().getValue();
|
||||||
if (!isGroup()) {
|
if (isGroup != null && isGroup) {
|
||||||
final boolean restricted = user.getFriendshipStatus().isRestricted();
|
final boolean restricted = user.getFriendshipStatus().isRestricted();
|
||||||
options.add(new Option<>(
|
options.add(new Option<>(
|
||||||
restricted ? getString(R.string.unrestrict) : getString(R.string.restrict),
|
restricted ? getString(R.string.unrestrict) : getString(R.string.restrict),
|
||||||
@ -661,18 +256,13 @@ public class DirectSettingsViewModel extends AndroidViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasLeft(final User user) {
|
private boolean hasLeft(final User user) {
|
||||||
final Pair<List<User>, List<User>> users = this.users.getValue();
|
final List<User> leftUsers = getLeftUsers().getValue();
|
||||||
if (users == null || users.second == null) return false;
|
if (leftUsers == null) return false;
|
||||||
return users.second.contains(user);
|
return leftUsers.contains(user);
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isAdmin(final User user) {
|
|
||||||
final List<Long> adminUserIdsValue = adminUserIds.getValue();
|
|
||||||
return adminUserIdsValue != null && adminUserIdsValue.contains(user.getPk());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSelf(final User user) {
|
private boolean isSelf(final User user) {
|
||||||
return user.getPk() == userId;
|
return user.getPk() == viewerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getString(@StringRes final int resId) {
|
private String getString(@StringRes final int resId) {
|
||||||
@ -703,47 +293,7 @@ public class DirectSettingsViewModel extends AndroidViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setViewer(final User viewer) {
|
public LiveData<User> getInviter() {
|
||||||
this.viewer = viewer;
|
return threadManager.getInviter();
|
||||||
}
|
|
||||||
|
|
||||||
private void fetchPendingRequests() {
|
|
||||||
final Call<DirectThreadParticipantRequestsResponse> request = directMessagesService.participantRequests(thread.getThreadId(), 5, null);
|
|
||||||
request.enqueue(new Callback<DirectThreadParticipantRequestsResponse>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull final Call<DirectThreadParticipantRequestsResponse> call,
|
|
||||||
@NonNull final Response<DirectThreadParticipantRequestsResponse> 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 DirectThreadParticipantRequestsResponse body = response.body();
|
|
||||||
if (body == null) {
|
|
||||||
Log.e(TAG, "onResponse: response body was null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pendingRequests.postValue(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull final Call<DirectThreadParticipantRequestsResponse> call, @NonNull final Throwable t) {
|
|
||||||
Log.e(TAG, "onFailure: ", t);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,35 @@
|
|||||||
|
package awais.instagrabber.viewmodels.factories;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
|
import awais.instagrabber.repositories.responses.User;
|
||||||
|
import awais.instagrabber.viewmodels.DirectSettingsViewModel;
|
||||||
|
|
||||||
|
public class DirectSettingsViewModelFactory implements ViewModelProvider.Factory {
|
||||||
|
|
||||||
|
private final Application application;
|
||||||
|
private final String threadId;
|
||||||
|
private final boolean pending;
|
||||||
|
private final User currentUser;
|
||||||
|
|
||||||
|
public DirectSettingsViewModelFactory(@NonNull final Application application,
|
||||||
|
@NonNull final String threadId,
|
||||||
|
final boolean pending,
|
||||||
|
@NonNull final User currentUser) {
|
||||||
|
this.application = application;
|
||||||
|
this.threadId = threadId;
|
||||||
|
this.pending = pending;
|
||||||
|
this.currentUser = currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public <T extends ViewModel> T create(@NonNull final Class<T> modelClass) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) new DirectSettingsViewModel(application, threadId, pending, currentUser);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package awais.instagrabber.viewmodels.factories;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
|
import awais.instagrabber.repositories.responses.User;
|
||||||
|
import awais.instagrabber.viewmodels.DirectThreadViewModel;
|
||||||
|
|
||||||
|
public class DirectThreadViewModelFactory implements ViewModelProvider.Factory {
|
||||||
|
|
||||||
|
private final Application application;
|
||||||
|
private final String threadId;
|
||||||
|
private final boolean pending;
|
||||||
|
private final User currentUser;
|
||||||
|
|
||||||
|
public DirectThreadViewModelFactory(@NonNull final Application application,
|
||||||
|
@NonNull final String threadId,
|
||||||
|
final boolean pending,
|
||||||
|
@NonNull final User currentUser) {
|
||||||
|
this.application = application;
|
||||||
|
this.threadId = threadId;
|
||||||
|
this.pending = pending;
|
||||||
|
this.currentUser = currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public <T extends ViewModel> T create(@NonNull final Class<T> modelClass) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) new DirectThreadViewModel(application, threadId, pending, currentUser);
|
||||||
|
}
|
||||||
|
}
|
@ -20,4 +20,14 @@
|
|||||||
android:paddingBottom="?attr/actionBarSize"
|
android:paddingBottom="?attr/actionBarSize"
|
||||||
tools:listitem="@layout/layout_dm_inbox_item" />
|
tools:listitem="@layout/layout_dm_inbox_item" />
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/empty"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:text="@string/no_pending_requests"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||||
|
android:visibility="gone" />
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
@ -428,4 +428,5 @@
|
|||||||
<string name="accept_request_from_user">Accept request from %1s (%2s)?</string>
|
<string name="accept_request_from_user">Accept request from %1s (%2s)?</string>
|
||||||
<string name="decline">Decline</string>
|
<string name="decline">Decline</string>
|
||||||
<string name="accept">Accept</string>
|
<string name="accept">Accept</string>
|
||||||
|
<string name="no_pending_requests">No pending requests</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -5,7 +5,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.1'
|
classpath 'com.android.tools.build:gradle:4.1.2'
|
||||||
def nav_version = "2.3.2"
|
def nav_version = "2.3.2"
|
||||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
|
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user