mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-12-22 21:16:57 +00:00
update direct messages
This commit sets up the base for future enhancements in direct messages. The changes are: 1. Introducing fragments and navigation using androidx.navigation.fragment.NavHostFragment. 2. Using ListAdapter and LiveData for the RecyclerViews. 3. Fixes a bug where a single direct message was lost when querying older messages.
This commit is contained in:
parent
650062646d
commit
30695ae02f
@ -1,4 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: "androidx.navigation.safeargs"
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
@ -37,10 +38,14 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation('androidx.appcompat:appcompat:1.3.0-alpha01@aar') { transitive true }
|
||||
implementation('androidx.recyclerview:recyclerview:1.2.0-alpha03@aar') { transitive true }
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||
implementation('com.google.android.material:material:1.3.0-alpha01@aar') { transitive true }
|
||||
implementation('androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-rc01') { transitive true }
|
||||
|
||||
def nav_version = "2.3.0"
|
||||
implementation "androidx.navigation:navigation-fragment:$nav_version"
|
||||
implementation "androidx.navigation:navigation-ui:$nav_version"
|
||||
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
|
||||
|
||||
implementation('org.jsoup:jsoup:1.13.1') { transitive true }
|
||||
|
@ -215,7 +215,7 @@
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activities.directmessages.DirectMessages"
|
||||
android:name=".activities.DirectMessagesActivity"
|
||||
android:parentActivityName=".activities.Main">
|
||||
|
||||
<meta-data
|
||||
@ -223,15 +223,6 @@
|
||||
android:value=".activities.Main" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activities.directmessages.DirectMessageThread"
|
||||
android:parentActivityName=".activities.directmessages.DirectMessages">
|
||||
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activities.directmessages.DirectMessages" />
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
|
@ -0,0 +1,73 @@
|
||||
package awais.instagrabber.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.NavDestination;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.navigation.ui.AppBarConfiguration;
|
||||
import androidx.navigation.ui.NavigationUI;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.databinding.ActivityDirectMessagesBinding;
|
||||
import awais.instagrabber.fragments.directmessages.DirectMessagesThreadFragmentArgs;
|
||||
|
||||
public class DirectMessagesActivity extends BaseLanguageActivity implements NavController.OnDestinationChangedListener {
|
||||
|
||||
private TextView toolbarTitle;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final ActivityDirectMessagesBinding binding = ActivityDirectMessagesBinding.inflate(getLayoutInflater());
|
||||
final CoordinatorLayout root = binding.getRoot();
|
||||
setContentView(root);
|
||||
|
||||
toolbarTitle = binding.toolbarTitle;
|
||||
|
||||
final Toolbar toolbar = binding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
final NavController navController = Navigation.findNavController(this, R.id.direct_messages_nav_host_fragment);
|
||||
navController.addOnDestinationChangedListener(this);
|
||||
final AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
|
||||
NavigationUI.setupWithNavController(toolbar, navController, appBarConfiguration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestinationChanged(@NonNull final NavController controller,
|
||||
@NonNull final NavDestination destination,
|
||||
@Nullable final Bundle arguments) {
|
||||
switch (destination.getId()) {
|
||||
case R.id.directMessagesInboxFragment:
|
||||
setToolbarTitle(R.string.action_dms);
|
||||
return;
|
||||
case R.id.directMessagesThreadFragment:
|
||||
if (arguments == null) {
|
||||
return;
|
||||
}
|
||||
final String title = DirectMessagesThreadFragmentArgs.fromBundle(arguments).getTitle();
|
||||
setToolbarTitle(title);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void setToolbarTitle(final String text) {
|
||||
if (toolbarTitle == null) {
|
||||
return;
|
||||
}
|
||||
toolbarTitle.setText(text);
|
||||
}
|
||||
|
||||
private void setToolbarTitle(final int resourceId) {
|
||||
if (toolbarTitle == null) {
|
||||
return;
|
||||
}
|
||||
toolbarTitle.setText(resourceId);
|
||||
}
|
||||
}
|
@ -29,7 +29,6 @@ import java.util.Stack;
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.MainHelper;
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.activities.directmessages.DirectMessages;
|
||||
import awais.instagrabber.adapters.HighlightsAdapter;
|
||||
import awais.instagrabber.adapters.SuggestionsAdapter;
|
||||
import awais.instagrabber.asyncs.SuggestionsFetcher;
|
||||
@ -86,7 +85,8 @@ public final class Main extends BaseLanguageActivity {
|
||||
.putExtra(Constants.EXTRAS_HIGHLIGHT, highlightModel.getTitle())
|
||||
.putExtra(Constants.EXTRAS_STORIES, result)
|
||||
);
|
||||
else Toast.makeText(Main.this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
else
|
||||
Toast.makeText(Main.this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
@ -143,7 +143,7 @@ public final class Main extends BaseLanguageActivity {
|
||||
if (mainHelper != null && !Utils.isEmpty(result)) {
|
||||
closeAnyOpenDrawer();
|
||||
addToStack();
|
||||
userQuery = (result.contains("/") || result.startsWith("#") || result.startsWith("@")) ? result : ("@"+result);
|
||||
userQuery = (result.contains("/") || result.startsWith("#") || result.startsWith("@")) ? result : ("@" + result);
|
||||
mainHelper.onRefresh();
|
||||
}
|
||||
};
|
||||
@ -154,7 +154,8 @@ public final class Main extends BaseLanguageActivity {
|
||||
if (!Utils.isEmpty(username)) {
|
||||
if (!BuildConfig.DEBUG) {
|
||||
userQuery = username;
|
||||
if (mainHelper != null && !mainBinding.profileView.swipeRefreshLayout.isRefreshing()) mainHelper.onRefresh();
|
||||
if (mainHelper != null && !mainBinding.profileView.swipeRefreshLayout.isRefreshing())
|
||||
mainHelper.onRefresh();
|
||||
}
|
||||
// adds cookies to database for quick access
|
||||
cookieModel = Utils.dataBox.getCookie(uid);
|
||||
@ -168,7 +169,7 @@ public final class Main extends BaseLanguageActivity {
|
||||
final String username = cookieModel.getUsername();
|
||||
if (username != null) {
|
||||
found = true;
|
||||
fetchListener.onResult("@"+username);
|
||||
fetchListener.onResult("@" + username);
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,10 +200,10 @@ public final class Main extends BaseLanguageActivity {
|
||||
intent = new Intent(this, ProfilePicViewer.class).putExtra(
|
||||
((hashtagModel != null) ? Constants.EXTRAS_HASHTAG : (locationModel != null ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_PROFILE)),
|
||||
((hashtagModel != null) ? hashtagModel : (locationModel != null ? locationModel : profileModel)));
|
||||
}
|
||||
else intent = new Intent(this, StoryViewer.class).putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", ""))
|
||||
.putExtra(Constants.EXTRAS_STORIES, storyModels)
|
||||
.putExtra(Constants.EXTRAS_HASHTAG, (hashtagModel != null));
|
||||
} else
|
||||
intent = new Intent(this, StoryViewer.class).putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", ""))
|
||||
.putExtra(Constants.EXTRAS_STORIES, storyModels)
|
||||
.putExtra(Constants.EXTRAS_HASHTAG, (hashtagModel != null));
|
||||
startActivity(intent);
|
||||
};
|
||||
|
||||
@ -241,7 +242,8 @@ public final class Main extends BaseLanguageActivity {
|
||||
mainBinding.profileView.privatePage2.setText(mainHelper.isLoggedIn ? R.string.no_acc_logged_in : R.string.no_acc);
|
||||
mainBinding.profileView.privatePage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (!mainBinding.profileView.swipeRefreshLayout.isRefreshing() && userQuery != null) mainHelper.onRefresh();
|
||||
if (!mainBinding.profileView.swipeRefreshLayout.isRefreshing() && userQuery != null)
|
||||
mainHelper.onRefresh();
|
||||
|
||||
mainHelper.onIntent(getIntent());
|
||||
}
|
||||
@ -301,7 +303,7 @@ public final class Main extends BaseLanguageActivity {
|
||||
if (item == downloadAction)
|
||||
downloadSelectedItems();
|
||||
else if (item == dmsAction)
|
||||
startActivity(new Intent(this, DirectMessages.class));
|
||||
startActivity(new Intent(this, DirectMessagesActivity.class));
|
||||
else if (item == notifAction)
|
||||
startActivity(new Intent(this, NotificationsViewer.class));
|
||||
else if (item == settingsAction)
|
||||
@ -336,7 +338,7 @@ public final class Main extends BaseLanguageActivity {
|
||||
searchView.setQueryHint(getResources().getString(R.string.action_search));
|
||||
searchView.setSuggestionsAdapter(suggestionAdapter);
|
||||
searchView.setOnSearchClickListener(v -> {
|
||||
searchView.setQuery((cookieModel != null && userQuery != null && userQuery.equals("@"+cookieModel.getUsername())) ? "" : userQuery, false);
|
||||
searchView.setQuery((cookieModel != null && userQuery != null && userQuery.equals("@" + cookieModel.getUsername())) ? "" : userQuery, false);
|
||||
menu.findItem(R.id.action_about).setVisible(false);
|
||||
menu.findItem(R.id.action_settings).setVisible(false);
|
||||
menu.findItem(R.id.action_dms).setVisible(false);
|
||||
@ -400,7 +402,10 @@ public final class Main extends BaseLanguageActivity {
|
||||
|
||||
private void cancelSuggestionsAsync() {
|
||||
if (prevSuggestionAsync != null)
|
||||
try { prevSuggestionAsync.cancel(true); } catch (final Exception ignored) { }
|
||||
try {
|
||||
prevSuggestionAsync.cancel(true);
|
||||
} catch (final Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -411,7 +416,7 @@ public final class Main extends BaseLanguageActivity {
|
||||
|
||||
closeAnyOpenDrawer();
|
||||
addToStack();
|
||||
userQuery = (query.contains("@") || query.contains("#")) ? query : ("@"+query);
|
||||
userQuery = (query.contains("@") || query.contains("#")) ? query : ("@" + query);
|
||||
searchAction.collapseActionView();
|
||||
searchView.setIconified(true);
|
||||
searchView.setIconified(true);
|
||||
@ -468,8 +473,7 @@ public final class Main extends BaseLanguageActivity {
|
||||
mainHelper.onRefresh();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@ -1,119 +0,0 @@
|
||||
package awais.instagrabber.activities.directmessages;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.activities.BaseLanguageActivity;
|
||||
import awais.instagrabber.adapters.DirectMessagesAdapter;
|
||||
import awais.instagrabber.asyncs.direct_messages.InboxFetcher;
|
||||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
|
||||
import awais.instagrabber.databinding.ActivityDmsBinding;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.direct_messages.InboxModel;
|
||||
import awais.instagrabber.models.direct_messages.InboxThreadModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
public final class DirectMessages extends BaseLanguageActivity implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private final ArrayList<InboxThreadModel> inboxThreadModelList = new ArrayList<>();
|
||||
private final DirectMessagesAdapter messagesAdapter = new DirectMessagesAdapter(inboxThreadModelList, v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof InboxThreadModel) {
|
||||
startActivity(new Intent(this, DirectMessageThread.class)
|
||||
.putExtra(Constants.EXTRAS_THREAD_MODEL, (InboxThreadModel) tag)
|
||||
);
|
||||
}
|
||||
});
|
||||
private final FetchListener<InboxModel> fetchListener = new FetchListener<InboxModel>() {
|
||||
@Override
|
||||
public void doBefore() {
|
||||
dmsBinding.swipeRefreshLayout.setRefreshing(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(final InboxModel inboxModel) {
|
||||
if (inboxModel != null) {
|
||||
endCursor = inboxModel.getOldestCursor();
|
||||
if ("MINCURSOR".equals(endCursor) || "MAXCURSOR".equals(endCursor)) endCursor = null;
|
||||
// todo get request / unseen count from inboxModel
|
||||
|
||||
final InboxThreadModel[] threads = inboxModel.getThreads();
|
||||
if (threads != null && threads.length > 0) {
|
||||
final int oldSize = inboxThreadModelList.size();
|
||||
inboxThreadModelList.addAll(Arrays.asList(threads));
|
||||
|
||||
messagesAdapter.notifyItemRangeInserted(oldSize, threads.length);
|
||||
}
|
||||
}
|
||||
|
||||
dmsBinding.swipeRefreshLayout.setRefreshing(false);
|
||||
stopCurrentExecutor();
|
||||
}
|
||||
};
|
||||
private String endCursor;
|
||||
private RecyclerLazyLoader lazyLoader;
|
||||
private AsyncTask<Void, Void, InboxModel> currentlyRunning;
|
||||
private ActivityDmsBinding dmsBinding;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
dmsBinding = ActivityDmsBinding.inflate(getLayoutInflater());
|
||||
setContentView(dmsBinding.getRoot());
|
||||
|
||||
dmsBinding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||
dmsBinding.toolbar.toolbar.setTitle(R.string.action_dms);
|
||||
dmsBinding.commentText.setVisibility(View.GONE);
|
||||
dmsBinding.commentSend.setVisibility(View.GONE);
|
||||
|
||||
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
|
||||
dmsBinding.rvDirectMessages.setLayoutManager(layoutManager);
|
||||
dmsBinding.rvDirectMessages.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
|
||||
dmsBinding.rvDirectMessages.setAdapter(messagesAdapter);
|
||||
|
||||
lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if (!Utils.isEmpty(endCursor))
|
||||
currentlyRunning = new InboxFetcher(endCursor, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
endCursor = null;
|
||||
});
|
||||
|
||||
dmsBinding.rvDirectMessages.addOnScrollListener(lazyLoader);
|
||||
|
||||
stopCurrentExecutor();
|
||||
currentlyRunning = new InboxFetcher(null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
endCursor = null;
|
||||
lazyLoader.resetState();
|
||||
inboxThreadModelList.clear();
|
||||
messagesAdapter.notifyDataSetChanged();
|
||||
|
||||
stopCurrentExecutor();
|
||||
currentlyRunning = new InboxFetcher(null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void stopCurrentExecutor() {
|
||||
if (currentlyRunning != null) {
|
||||
try {
|
||||
currentlyRunning.cancel(true);
|
||||
} catch (final Exception e) {
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package awais.instagrabber.adapters;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.ListAdapter;
|
||||
|
||||
import awais.instagrabber.adapters.viewholder.DirectMessageInboxItemViewHolder;
|
||||
import awais.instagrabber.databinding.LayoutIncludeSimpleItemBinding;
|
||||
import awais.instagrabber.models.direct_messages.InboxThreadModel;
|
||||
|
||||
public final class DirectMessageInboxAdapter extends ListAdapter<InboxThreadModel, DirectMessageInboxItemViewHolder> {
|
||||
private final OnItemClickListener onClickListener;
|
||||
|
||||
private static final DiffUtil.ItemCallback<InboxThreadModel> diffCallback = new DiffUtil.ItemCallback<InboxThreadModel>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull final InboxThreadModel oldItem, @NonNull final InboxThreadModel newItem) {
|
||||
return oldItem.getThreadId().equals(newItem.getThreadId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull final InboxThreadModel oldItem, @NonNull final InboxThreadModel newItem) {
|
||||
return oldItem.equals(newItem);
|
||||
}
|
||||
};
|
||||
|
||||
public DirectMessageInboxAdapter(final OnItemClickListener onClickListener) {
|
||||
super(diffCallback);
|
||||
this.onClickListener = onClickListener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DirectMessageInboxItemViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) {
|
||||
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
|
||||
final LayoutIncludeSimpleItemBinding binding = LayoutIncludeSimpleItemBinding.inflate(layoutInflater, parent, false);
|
||||
return new DirectMessageInboxItemViewHolder(binding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final DirectMessageInboxItemViewHolder holder, final int position) {
|
||||
final InboxThreadModel threadModel = getItem(position);
|
||||
if (onClickListener != null) {
|
||||
holder.itemView.setOnClickListener((v) -> onClickListener.onItemClick(threadModel));
|
||||
}
|
||||
holder.bind(threadModel);
|
||||
}
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onItemClick(final InboxThreadModel inboxThreadModel);
|
||||
}
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
package awais.instagrabber.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.text.HtmlCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.RequestManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.viewholder.DirectMessageViewHolder;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
import awais.instagrabber.models.direct_messages.DirectItemModel;
|
||||
import awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemActionLogModel;
|
||||
import awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemReelShareModel;
|
||||
import awais.instagrabber.models.direct_messages.InboxThreadModel;
|
||||
import awais.instagrabber.models.enums.DirectItemType;
|
||||
|
||||
public final class DirectMessagesAdapter extends RecyclerView.Adapter<DirectMessageViewHolder> {
|
||||
private final ArrayList<InboxThreadModel> inboxThreadModels;
|
||||
private final View.OnClickListener onClickListener;
|
||||
private LayoutInflater layoutInflater;
|
||||
|
||||
public DirectMessagesAdapter(final ArrayList<InboxThreadModel> inboxThreadModels, final View.OnClickListener onClickListener) {
|
||||
this.inboxThreadModels = inboxThreadModels;
|
||||
this.onClickListener = onClickListener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DirectMessageViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) {
|
||||
if (layoutInflater == null) layoutInflater = LayoutInflater.from(parent.getContext());
|
||||
return new DirectMessageViewHolder(layoutInflater.inflate(R.layout.layout_include_simple_item, parent, false),
|
||||
onClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final DirectMessageViewHolder holder, final int position) {
|
||||
final InboxThreadModel threadModel = inboxThreadModels.get(position);
|
||||
final DirectItemModel[] itemModels;
|
||||
|
||||
holder.itemView.setTag(threadModel);
|
||||
|
||||
final RequestManager glideRequestManager = Glide.with(holder.itemView);
|
||||
|
||||
if (threadModel != null && (itemModels = threadModel.getItems()) != null) {
|
||||
final ProfileModel[] users = threadModel.getUsers();
|
||||
|
||||
if (users.length > 1) {
|
||||
holder.ivProfilePic.setVisibility(View.GONE);
|
||||
holder.multipleProfilePicsContainer.setVisibility(View.VISIBLE);
|
||||
|
||||
for (int i = 0; i < Math.min(3, users.length); ++i)
|
||||
glideRequestManager.load(users[i].getSdProfilePic()).into(holder.multipleProfilePics[i]);
|
||||
|
||||
} else {
|
||||
holder.ivProfilePic.setVisibility(View.VISIBLE);
|
||||
holder.multipleProfilePicsContainer.setVisibility(View.GONE);
|
||||
|
||||
glideRequestManager.load(users.length == 1 ? users[0].getSdProfilePic() : null).into(holder.ivProfilePic);
|
||||
}
|
||||
|
||||
holder.tvUsername.setText(threadModel.getThreadTitle());
|
||||
|
||||
final DirectItemModel lastItemModel = itemModels[itemModels.length - 1];
|
||||
final DirectItemType itemType = lastItemModel.getItemType();
|
||||
|
||||
holder.notTextType.setVisibility(itemType != DirectItemType.TEXT ? View.VISIBLE : View.GONE);
|
||||
|
||||
final Context context = layoutInflater.getContext();
|
||||
|
||||
final CharSequence messageText;
|
||||
switch (itemType) {
|
||||
case TEXT:
|
||||
case LIKE:
|
||||
messageText = lastItemModel.getText();
|
||||
break;
|
||||
case LINK:
|
||||
messageText = context.getString(R.string.direct_messages_sent_link);
|
||||
break;
|
||||
case MEDIA:
|
||||
case MEDIA_SHARE:
|
||||
messageText = context.getString(R.string.direct_messages_sent_media);
|
||||
break;
|
||||
case ACTION_LOG:
|
||||
final DirectItemActionLogModel logModel = lastItemModel.getActionLogModel();
|
||||
messageText = logModel != null ? logModel.getDescription() : "...";
|
||||
break;
|
||||
case REEL_SHARE:
|
||||
final DirectItemReelShareModel reelShare = lastItemModel.getReelShare();
|
||||
if (reelShare == null)
|
||||
messageText = context.getString(R.string.direct_messages_sent_media);
|
||||
else {
|
||||
final String reelType = reelShare.getType();
|
||||
final int textRes;
|
||||
if ("reply".equals(reelType))
|
||||
textRes = R.string.direct_messages_replied_story;
|
||||
else if ("mention".equals(reelType))
|
||||
textRes = R.string.direct_messages_mention_story;
|
||||
else if ("reaction".equals(reelType))
|
||||
textRes = R.string.direct_messages_reacted_story;
|
||||
else textRes = R.string.direct_messages_sent_media;
|
||||
|
||||
messageText = context.getString(textRes) + " : " + reelShare.getText();
|
||||
}
|
||||
break;
|
||||
case RAVEN_MEDIA:
|
||||
messageText = context.getString(R.string.direct_messages_sent_media);
|
||||
break;
|
||||
default:
|
||||
messageText = "<i>Unsupported message</i>";
|
||||
}
|
||||
|
||||
holder.tvMessage.setText(HtmlCompat.fromHtml(messageText.toString(), 63));
|
||||
|
||||
holder.tvDate.setText(lastItemModel.getDateTime());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return inboxThreadModels == null ? 0 : inboxThreadModels.size();
|
||||
}
|
||||
}
|
@ -1,410 +1,66 @@
|
||||
package awais.instagrabber.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.text.Spanned;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.text.HtmlCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.ListAdapter;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.RequestManager;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.activities.Main;
|
||||
import awais.instagrabber.adapters.viewholder.directmessages.TextMessageViewHolder;
|
||||
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageViewHolder;
|
||||
import awais.instagrabber.databinding.ItemMessageItemBinding;
|
||||
import awais.instagrabber.interfaces.MentionClickListener;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
import awais.instagrabber.models.direct_messages.DirectItemModel;
|
||||
import awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemMediaModel;
|
||||
import awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemRavenMediaModel;
|
||||
import awais.instagrabber.models.enums.DirectItemType;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.models.enums.RavenExpiringMediaType;
|
||||
import awais.instagrabber.models.enums.RavenMediaViewType;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemLinkContext;
|
||||
import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemLinkModel;
|
||||
import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemReelShareModel;
|
||||
import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemVoiceMediaModel;
|
||||
import static awais.instagrabber.models.direct_messages.DirectItemModel.RavenExpiringMediaActionSummaryModel;
|
||||
|
||||
public final class MessageItemsAdapter extends RecyclerView.Adapter<TextMessageViewHolder> {
|
||||
private static final int MESSAGE_INCOMING = 69, MESSAGE_OUTGOING = 420;
|
||||
private final ProfileModel myProfileHolder =
|
||||
new ProfileModel(false, false, false,
|
||||
Utils.getUserIdFromCookie(Utils.settingsHelper.getString(Constants.COOKIE)),
|
||||
null, null, null, null, null, null, 0, 0, 0, false, false, false, false);
|
||||
private final ArrayList<DirectItemModel> directItemModels;
|
||||
private final ArrayList<ProfileModel> users, leftusers;
|
||||
public final class MessageItemsAdapter extends ListAdapter<DirectItemModel, DirectMessageViewHolder> {
|
||||
private final List<ProfileModel> users;
|
||||
private final List<ProfileModel> leftUsers;
|
||||
private final View.OnClickListener onClickListener;
|
||||
private final MentionClickListener mentionClickListener;
|
||||
private final View.OnClickListener openProfileClickListener = v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof ProfileModel) {
|
||||
// todo do profile stuff
|
||||
final ProfileModel profileModel = (ProfileModel) tag;
|
||||
Log.d("AWAISKING_APP", "--> " + profileModel);
|
||||
|
||||
private static final DiffUtil.ItemCallback<DirectItemModel> diffCallback = new DiffUtil.ItemCallback<DirectItemModel>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull final DirectItemModel oldItem, @NonNull final DirectItemModel newItem) {
|
||||
return oldItem.getItemId().equals(newItem.getItemId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull final DirectItemModel oldItem, @NonNull final DirectItemModel newItem) {
|
||||
return oldItem.getItemId().equals(newItem.getItemId());
|
||||
}
|
||||
};
|
||||
private final int itemMargin;
|
||||
private DirectItemVoiceMediaModel prevVoiceModel;
|
||||
private ImageView prevPlayIcon;
|
||||
private final View.OnClickListener voicePlayClickListener = v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (v instanceof ViewGroup && tag instanceof DirectItemVoiceMediaModel) {
|
||||
final ImageView playIcon = (ImageView) ((ViewGroup) v).getChildAt(0);
|
||||
final DirectItemVoiceMediaModel voiceMediaModel = (DirectItemVoiceMediaModel) tag;
|
||||
final boolean voicePlaying = voiceMediaModel.isPlaying();
|
||||
voiceMediaModel.setPlaying(!voicePlaying);
|
||||
|
||||
if (voiceMediaModel == prevVoiceModel) {
|
||||
// todo pause / resume
|
||||
} else {
|
||||
// todo release prev audio, start new voice
|
||||
if (prevVoiceModel != null) prevVoiceModel.setPlaying(false);
|
||||
if (prevPlayIcon != null) prevPlayIcon.setImageResource(android.R.drawable.ic_media_play);
|
||||
}
|
||||
|
||||
if (voicePlaying) {
|
||||
playIcon.setImageResource(android.R.drawable.ic_media_play);
|
||||
} else {
|
||||
playIcon.setImageResource(android.R.drawable.ic_media_pause);
|
||||
}
|
||||
|
||||
prevVoiceModel = voiceMediaModel;
|
||||
prevPlayIcon = playIcon;
|
||||
}
|
||||
};
|
||||
private Context context;
|
||||
private LayoutInflater layoutInflater;
|
||||
private String strDmYou;
|
||||
|
||||
public MessageItemsAdapter(final ArrayList<DirectItemModel> directItemModels, final ArrayList<ProfileModel> users,
|
||||
final ArrayList<ProfileModel> leftusers, final View.OnClickListener onClickListener,
|
||||
public MessageItemsAdapter(final List<ProfileModel> users,
|
||||
final List<ProfileModel> leftUsers,
|
||||
final View.OnClickListener onClickListener,
|
||||
final MentionClickListener mentionClickListener) {
|
||||
super(diffCallback);
|
||||
this.users = users;
|
||||
this.leftusers = leftusers;
|
||||
this.directItemModels = directItemModels;
|
||||
this.leftUsers = leftUsers;
|
||||
this.onClickListener = onClickListener;
|
||||
this.mentionClickListener = mentionClickListener;
|
||||
this.itemMargin = Utils.displayMetrics.widthPixels / 5;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public TextMessageViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) {
|
||||
if (context == null) context = parent.getContext();
|
||||
if (strDmYou == null) strDmYou = context.getString(R.string.direct_messages_you);
|
||||
if (layoutInflater == null) layoutInflater = LayoutInflater.from(context);
|
||||
return new TextMessageViewHolder(layoutInflater.inflate(R.layout.item_message_item, parent, false),
|
||||
onClickListener, mentionClickListener);
|
||||
public DirectMessageViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) {
|
||||
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
|
||||
final ItemMessageItemBinding binding = ItemMessageItemBinding.inflate(layoutInflater, parent, false);
|
||||
return new DirectMessageViewHolder(binding, users, leftUsers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final TextMessageViewHolder holder, final int position) {
|
||||
final DirectItemModel directItemModel = directItemModels.get(position);
|
||||
holder.itemView.setTag(directItemModel);
|
||||
|
||||
if (directItemModel != null) {
|
||||
final DirectItemType itemType = directItemModel.getItemType();
|
||||
|
||||
final ProfileModel user = getUser(directItemModel.getUserId());
|
||||
final int type = user == myProfileHolder ? MESSAGE_OUTGOING : MESSAGE_INCOMING;
|
||||
|
||||
final RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) holder.itemView.getLayoutParams();
|
||||
layoutParams.setMargins(type == MESSAGE_OUTGOING ? itemMargin : 0, 0,
|
||||
type == MESSAGE_INCOMING ? itemMargin : 0, 0);
|
||||
|
||||
holder.tvMessage.setVisibility(View.GONE);
|
||||
holder.voiceMessageContainer.setVisibility(View.GONE);
|
||||
holder.ivAnimatedMessage.setVisibility(View.GONE);
|
||||
holder.linkMessageContainer.setVisibility(View.GONE);
|
||||
|
||||
holder.mediaMessageContainer.setVisibility(View.GONE);
|
||||
holder.mediaTypeIcon.setVisibility(View.GONE);
|
||||
holder.mediaExpiredIcon.setVisibility(View.GONE);
|
||||
|
||||
holder.profileMessageContainer.setVisibility(View.GONE);
|
||||
holder.isVerified.setVisibility(View.GONE);
|
||||
|
||||
holder.btnOpenProfile.setVisibility(View.GONE);
|
||||
holder.btnOpenProfile.setOnClickListener(null);
|
||||
holder.btnOpenProfile.setTag(null);
|
||||
|
||||
CharSequence text = "?";
|
||||
if (user != null && user != myProfileHolder) text = user.getUsername();
|
||||
else if (user == myProfileHolder) text = strDmYou;
|
||||
text = text + " - " + directItemModel.getDateTime();
|
||||
|
||||
holder.tvUsername.setText(text);
|
||||
|
||||
holder.ivProfilePic.setVisibility(type == MESSAGE_INCOMING ? View.VISIBLE : View.GONE);
|
||||
|
||||
final RequestManager glideRequestManager = Glide.with(holder.itemView);
|
||||
|
||||
if (type == MESSAGE_INCOMING && user != null)
|
||||
glideRequestManager.load(user.getSdProfilePic()).into(holder.ivProfilePic);
|
||||
|
||||
DirectItemMediaModel mediaModel = directItemModel.getMediaModel();
|
||||
switch (itemType) {
|
||||
case PLACEHOLDER:
|
||||
holder.tvMessage.setText(HtmlCompat.fromHtml(directItemModel.getText().toString(), 63));
|
||||
holder.tvMessage.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case TEXT:
|
||||
case LIKE:
|
||||
text = directItemModel.getText();
|
||||
text = Utils.getSpannableUrl(text.toString()); // for urls
|
||||
if (Utils.hasMentions(text)) text = Utils.getMentionText(text); // for mentions
|
||||
|
||||
if (text instanceof Spanned) holder.tvMessage.setText(text, TextView.BufferType.SPANNABLE);
|
||||
else if (text == "") holder.tvMessage.setText(context.getText(R.string.dms_inbox_raven_message_unknown));
|
||||
else holder.tvMessage.setText(text);
|
||||
|
||||
holder.tvMessage.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
|
||||
case LINK: {
|
||||
final DirectItemLinkModel link = directItemModel.getLinkModel();
|
||||
final DirectItemLinkContext linkContext = link.getLinkContext();
|
||||
|
||||
final String linkImageUrl = linkContext.getLinkImageUrl();
|
||||
if (!Utils.isEmpty(linkImageUrl)) {
|
||||
glideRequestManager.load(linkImageUrl).into(holder.ivLinkPreview);
|
||||
holder.tvLinkTitle.setText(linkContext.getLinkTitle());
|
||||
holder.tvLinkSummary.setText(linkContext.getLinkSummary());
|
||||
holder.ivLinkPreview.setVisibility(View.VISIBLE);
|
||||
holder.linkMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
holder.tvMessage.setText(Utils.getSpannableUrl(link.getText()));
|
||||
holder.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
|
||||
case MEDIA_SHARE:
|
||||
{
|
||||
final ProfileModel modelUser = mediaModel.getUser();
|
||||
if (modelUser != null) {
|
||||
holder.tvMessage.setText(HtmlCompat.fromHtml("<small>"+context.getString(R.string.dms_inbox_media_shared_from, modelUser.getUsername())+"</small>", 63));
|
||||
holder.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
case MEDIA: {
|
||||
glideRequestManager.load(mediaModel.getThumbUrl()).into(holder.ivMediaPreview);
|
||||
|
||||
final MediaItemType modelMediaType = mediaModel.getMediaType();
|
||||
holder.mediaTypeIcon.setVisibility(modelMediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
|
||||
modelMediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
|
||||
|
||||
holder.mediaMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
|
||||
case RAVEN_MEDIA: {
|
||||
final DirectItemRavenMediaModel ravenMediaModel = directItemModel.getRavenMediaModel();
|
||||
|
||||
final boolean isExpired = ravenMediaModel == null || (mediaModel = ravenMediaModel.getMedia()) == null ||
|
||||
Utils.isEmpty(mediaModel.getThumbUrl()) && mediaModel.getPk() < 1;
|
||||
|
||||
final RavenExpiringMediaActionSummaryModel mediaActionSummary = ravenMediaModel.getExpiringMediaActionSummary();
|
||||
holder.mediaExpiredIcon.setVisibility(isExpired ? View.VISIBLE : View.GONE);
|
||||
|
||||
int textRes = R.string.dms_inbox_raven_media_unknown;
|
||||
if (isExpired) textRes = R.string.dms_inbox_raven_media_expired;
|
||||
|
||||
if (!isExpired) {
|
||||
if (mediaActionSummary != null) {
|
||||
final RavenExpiringMediaType expiringMediaType = mediaActionSummary.getType();
|
||||
|
||||
if (expiringMediaType == RavenExpiringMediaType.RAVEN_DELIVERED)
|
||||
textRes = R.string.dms_inbox_raven_media_delivered;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SENT)
|
||||
textRes = R.string.dms_inbox_raven_media_sent;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_OPENED)
|
||||
textRes = R.string.dms_inbox_raven_media_opened;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_REPLAYED)
|
||||
textRes = R.string.dms_inbox_raven_media_replayed;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SENDING)
|
||||
textRes = R.string.dms_inbox_raven_media_sending;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_BLOCKED)
|
||||
textRes = R.string.dms_inbox_raven_media_blocked;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SUGGESTED)
|
||||
textRes = R.string.dms_inbox_raven_media_suggested;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SCREENSHOT)
|
||||
textRes = R.string.dms_inbox_raven_media_screenshot;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_CANNOT_DELIVER)
|
||||
textRes = R.string.dms_inbox_raven_media_cant_deliver;
|
||||
}
|
||||
|
||||
final RavenMediaViewType ravenMediaViewType = ravenMediaModel.getViewType();
|
||||
if (ravenMediaViewType == RavenMediaViewType.PERMANENT || ravenMediaViewType == RavenMediaViewType.REPLAYABLE) {
|
||||
final MediaItemType mediaType = mediaModel.getMediaType();
|
||||
textRes = -1;
|
||||
holder.mediaTypeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
|
||||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
|
||||
|
||||
glideRequestManager.load(mediaModel.getThumbUrl()).into(holder.ivMediaPreview);
|
||||
holder.mediaMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
if (textRes != -1) {
|
||||
holder.tvMessage.setText(context.getText(textRes));
|
||||
holder.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REEL_SHARE: {
|
||||
final DirectItemReelShareModel reelShare = directItemModel.getReelShare();
|
||||
if (!Utils.isEmpty(text = reelShare.getText())) {
|
||||
holder.tvMessage.setText(text);
|
||||
holder.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
final DirectItemMediaModel reelShareMedia = reelShare.getMedia();
|
||||
final MediaItemType mediaType = reelShareMedia.getMediaType();
|
||||
|
||||
if (mediaType == null)
|
||||
holder.mediaExpiredIcon.setVisibility(View.VISIBLE);
|
||||
else {
|
||||
holder.mediaTypeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
|
||||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
|
||||
|
||||
glideRequestManager.load(reelShareMedia.getThumbUrl()).into(holder.ivMediaPreview);
|
||||
holder.mediaMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STORY_SHARE: {
|
||||
final DirectItemReelShareModel reelShare = directItemModel.getReelShare();
|
||||
if (reelShare == null) {
|
||||
holder.tvMessage.setText(HtmlCompat.fromHtml(directItemModel.getText().toString(), 63));
|
||||
holder.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
else {
|
||||
if (!Utils.isEmpty(text = reelShare.getText())) {
|
||||
holder.tvMessage.setText(text);
|
||||
holder.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
final DirectItemMediaModel reelShareMedia = reelShare.getMedia();
|
||||
final MediaItemType mediaType = reelShareMedia.getMediaType();
|
||||
|
||||
holder.mediaTypeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
|
||||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
|
||||
|
||||
glideRequestManager.load(reelShareMedia.getThumbUrl()).into(holder.ivMediaPreview);
|
||||
holder.mediaMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VOICE_MEDIA: {
|
||||
final DirectItemVoiceMediaModel voiceMediaModel = directItemModel.getVoiceMediaModel();
|
||||
|
||||
if (voiceMediaModel != null) {
|
||||
final int[] waveformData = voiceMediaModel.getWaveformData();
|
||||
if (waveformData != null) holder.waveformSeekBar.setSample(waveformData);
|
||||
|
||||
final long durationMs = voiceMediaModel.getDurationMs();
|
||||
holder.tvVoiceDuration.setText(Utils.millisToString(durationMs));
|
||||
holder.waveformSeekBar.setProgress(voiceMediaModel.getProgress());
|
||||
holder.waveformSeekBar.setProgressChangeListener((waveformSeekBar, progress, fromUser) -> {
|
||||
// todo progress audio player
|
||||
voiceMediaModel.setProgress(progress);
|
||||
if (fromUser)
|
||||
holder.tvVoiceDuration.setText(Utils.millisToString(durationMs * progress / 100));
|
||||
});
|
||||
holder.btnPlayVoice.setTag(voiceMediaModel);
|
||||
holder.btnPlayVoice.setOnClickListener(voicePlayClickListener);
|
||||
} else {
|
||||
holder.waveformSeekBar.setProgress(0);
|
||||
}
|
||||
|
||||
holder.voiceMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANIMATED_MEDIA: {
|
||||
glideRequestManager.asGif().load(directItemModel.getAnimatedMediaModel().getGifUrl())
|
||||
.into(holder.ivAnimatedMessage);
|
||||
holder.ivAnimatedMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROFILE: {
|
||||
final ProfileModel profileModel = directItemModel.getProfileModel();
|
||||
Glide.with(holder.ivMessageProfilePic).load(profileModel.getSdProfilePic())
|
||||
.into(holder.ivMessageProfilePic);
|
||||
holder.btnOpenProfile.setTag(profileModel);
|
||||
holder.btnOpenProfile.setOnClickListener(openProfileClickListener);
|
||||
|
||||
holder.tvProfileName.setText(profileModel.getName());
|
||||
holder.tvProfileUsername.setText(profileModel.getUsername());
|
||||
holder.isVerified.setVisibility(profileModel.isVerified() ? View.VISIBLE : View.GONE);
|
||||
|
||||
holder.btnOpenProfile.setVisibility(View.VISIBLE);
|
||||
holder.profileMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
|
||||
case VIDEO_CALL_EVENT: {
|
||||
// todo add call event info
|
||||
holder.tvMessage.setVisibility(View.VISIBLE);
|
||||
holder.itemView.setBackgroundColor(0xFF_1F90E6);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTION_LOG: {
|
||||
text = directItemModel.getActionLogModel().getDescription();
|
||||
holder.tvMessage.setText(HtmlCompat.fromHtml("<small>"+text+"</small>", 63));
|
||||
holder.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
public void onBindViewHolder(@NonNull final DirectMessageViewHolder holder, final int position) {
|
||||
final DirectItemModel directItemModel = getItem(position);
|
||||
holder.bind(directItemModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(final int position) {
|
||||
return directItemModels.get(position).getItemType().ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return directItemModels == null ? 0 : directItemModels.size();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ProfileModel getUser(final long userId) {
|
||||
if (users != null) {
|
||||
ProfileModel result = myProfileHolder;
|
||||
for (final ProfileModel user : users) {
|
||||
if (Long.toString(userId).equals(user.getId())) result = user;
|
||||
}
|
||||
if (leftusers != null)
|
||||
for (final ProfileModel leftuser : leftusers) {
|
||||
if (Long.toString(userId).equals(leftuser.getId())) result = leftuser;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
return getItem(position).getItemType().ordinal();
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
package awais.instagrabber.adapters.viewholder;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.text.HtmlCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.RequestManager;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.databinding.LayoutIncludeSimpleItemBinding;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
import awais.instagrabber.models.direct_messages.DirectItemModel;
|
||||
import awais.instagrabber.models.direct_messages.InboxThreadModel;
|
||||
import awais.instagrabber.models.enums.DirectItemType;
|
||||
|
||||
public final class DirectMessageInboxItemViewHolder extends RecyclerView.ViewHolder {
|
||||
private final LinearLayout multipleProfilePicsContainer;
|
||||
private final ImageView[] multipleProfilePics;
|
||||
private final LayoutIncludeSimpleItemBinding binding;
|
||||
|
||||
public DirectMessageInboxItemViewHolder(@NonNull final LayoutIncludeSimpleItemBinding binding) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
binding.tvLikes.setVisibility(View.GONE);
|
||||
multipleProfilePicsContainer = binding.container;
|
||||
final LinearLayout containerChild = (LinearLayout) multipleProfilePicsContainer.getChildAt(1);
|
||||
multipleProfilePics = new ImageView[]{
|
||||
(ImageView) multipleProfilePicsContainer.getChildAt(0),
|
||||
(ImageView) containerChild.getChildAt(0),
|
||||
(ImageView) containerChild.getChildAt(1)
|
||||
};
|
||||
binding.tvDate.setSelected(true);
|
||||
binding.tvUsername.setSelected(true);
|
||||
}
|
||||
|
||||
public void bind(final InboxThreadModel model) {
|
||||
final DirectItemModel[] itemModels;
|
||||
if (model == null || (itemModels = model.getItems()) == null) {
|
||||
return;
|
||||
}
|
||||
itemView.setTag(model);
|
||||
final RequestManager glideRequestManager = Glide.with(itemView);
|
||||
final ProfileModel[] users = model.getUsers();
|
||||
if (users.length > 1) {
|
||||
binding.ivProfilePic.setVisibility(View.GONE);
|
||||
multipleProfilePicsContainer.setVisibility(View.VISIBLE);
|
||||
for (int i = 0; i < Math.min(3, users.length); ++i)
|
||||
glideRequestManager.load(users[i].getSdProfilePic()).into(multipleProfilePics[i]);
|
||||
} else {
|
||||
binding.ivProfilePic.setVisibility(View.VISIBLE);
|
||||
multipleProfilePicsContainer.setVisibility(View.GONE);
|
||||
glideRequestManager.load(users.length == 1 ? users[0].getSdProfilePic() : null).into(binding.ivProfilePic);
|
||||
}
|
||||
binding.tvUsername.setText(model.getThreadTitle());
|
||||
final DirectItemModel lastItemModel = itemModels[itemModels.length - 1];
|
||||
final DirectItemType itemType = lastItemModel.getItemType();
|
||||
binding.notTextType.setVisibility(itemType != DirectItemType.TEXT ? View.VISIBLE : View.GONE);
|
||||
final Context context = itemView.getContext();
|
||||
final CharSequence messageText;
|
||||
switch (itemType) {
|
||||
case TEXT:
|
||||
case LIKE:
|
||||
messageText = lastItemModel.getText();
|
||||
break;
|
||||
case LINK:
|
||||
messageText = context.getString(R.string.direct_messages_sent_link);
|
||||
break;
|
||||
case MEDIA:
|
||||
case MEDIA_SHARE:
|
||||
case RAVEN_MEDIA:
|
||||
messageText = context.getString(R.string.direct_messages_sent_media);
|
||||
break;
|
||||
case ACTION_LOG:
|
||||
final DirectItemModel.DirectItemActionLogModel logModel = lastItemModel.getActionLogModel();
|
||||
messageText = logModel != null ? logModel.getDescription() : "...";
|
||||
break;
|
||||
case REEL_SHARE:
|
||||
final DirectItemModel.DirectItemReelShareModel reelShare = lastItemModel.getReelShare();
|
||||
if (reelShare == null)
|
||||
messageText = context.getString(R.string.direct_messages_sent_media);
|
||||
else {
|
||||
final String reelType = reelShare.getType();
|
||||
final int textRes;
|
||||
if ("reply".equals(reelType))
|
||||
textRes = R.string.direct_messages_replied_story;
|
||||
else if ("mention".equals(reelType))
|
||||
textRes = R.string.direct_messages_mention_story;
|
||||
else if ("reaction".equals(reelType))
|
||||
textRes = R.string.direct_messages_reacted_story;
|
||||
else textRes = R.string.direct_messages_sent_media;
|
||||
|
||||
messageText = context.getString(textRes) + " : " + reelShare.getText();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
messageText = "<i>Unsupported message</i>";
|
||||
}
|
||||
binding.tvComment.setText(HtmlCompat.fromHtml(messageText.toString(), HtmlCompat.FROM_HTML_MODE_COMPACT));
|
||||
binding.tvDate.setText(lastItemModel.getDateTime());
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package awais.instagrabber.adapters.viewholder;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
|
||||
public final class DirectMessageViewHolder extends RecyclerView.ViewHolder {
|
||||
public final LinearLayout multipleProfilePicsContainer;
|
||||
public final ImageView[] multipleProfilePics;
|
||||
public final ImageView ivProfilePic, notTextType;
|
||||
public final TextView tvUsername, tvDate, tvMessage;
|
||||
|
||||
public DirectMessageViewHolder(@NonNull final View itemView, final View.OnClickListener clickListener) {
|
||||
super(itemView);
|
||||
|
||||
if (clickListener != null) itemView.setOnClickListener(clickListener);
|
||||
|
||||
itemView.findViewById(R.id.tvLikes).setVisibility(View.GONE);
|
||||
|
||||
tvDate = itemView.findViewById(R.id.tvDate);
|
||||
tvMessage = itemView.findViewById(R.id.tvComment);
|
||||
tvUsername = itemView.findViewById(R.id.tvUsername);
|
||||
notTextType = itemView.findViewById(R.id.notTextType);
|
||||
ivProfilePic = itemView.findViewById(R.id.ivProfilePic);
|
||||
|
||||
multipleProfilePicsContainer = itemView.findViewById(R.id.container);
|
||||
final LinearLayout containerChild = (LinearLayout) multipleProfilePicsContainer.getChildAt(1);
|
||||
multipleProfilePics = new ImageView[]{
|
||||
(ImageView) multipleProfilePicsContainer.getChildAt(0),
|
||||
(ImageView) containerChild.getChildAt(0),
|
||||
(ImageView) containerChild.getChildAt(1)
|
||||
};
|
||||
|
||||
tvDate.setSelected(true);
|
||||
tvUsername.setSelected(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,383 @@
|
||||
package awais.instagrabber.adapters.viewholder.directmessages;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Spanned;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.text.HtmlCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.RequestManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.databinding.ItemMessageItemBinding;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
import awais.instagrabber.models.direct_messages.DirectItemModel;
|
||||
import awais.instagrabber.models.enums.DirectItemType;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.models.enums.RavenExpiringMediaType;
|
||||
import awais.instagrabber.models.enums.RavenMediaViewType;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_COMPACT;
|
||||
|
||||
public final class DirectMessageViewHolder extends RecyclerView.ViewHolder {
|
||||
private static final String TAG = "DirectMessageViewHolder";
|
||||
private static final int MESSAGE_INCOMING = 69;
|
||||
private static final int MESSAGE_OUTGOING = 420;
|
||||
|
||||
private final ProfileModel myProfileHolder = ProfileModel.getDefaultProfileModel(Utils.getUserIdFromCookie(Utils.settingsHelper.getString(Constants.COOKIE)));
|
||||
private final ItemMessageItemBinding binding;
|
||||
private final List<ProfileModel> users;
|
||||
private final List<ProfileModel> leftUsers;
|
||||
private final int itemMargin;
|
||||
private final String strDmYou;
|
||||
private DirectItemModel.DirectItemVoiceMediaModel prevVoiceModel;
|
||||
private ImageView prevPlayIcon;
|
||||
|
||||
private final View.OnClickListener voicePlayClickListener = v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (v instanceof ViewGroup && tag instanceof DirectItemModel.DirectItemVoiceMediaModel) {
|
||||
final ImageView playIcon = (ImageView) ((ViewGroup) v).getChildAt(0);
|
||||
final DirectItemModel.DirectItemVoiceMediaModel voiceMediaModel = (DirectItemModel.DirectItemVoiceMediaModel) tag;
|
||||
final boolean voicePlaying = voiceMediaModel.isPlaying();
|
||||
voiceMediaModel.setPlaying(!voicePlaying);
|
||||
|
||||
if (voiceMediaModel == prevVoiceModel) {
|
||||
// todo pause / resume
|
||||
} else {
|
||||
// todo release prev audio, start new voice
|
||||
if (prevVoiceModel != null) prevVoiceModel.setPlaying(false);
|
||||
if (prevPlayIcon != null)
|
||||
prevPlayIcon.setImageResource(android.R.drawable.ic_media_play);
|
||||
}
|
||||
|
||||
if (voicePlaying) {
|
||||
playIcon.setImageResource(android.R.drawable.ic_media_play);
|
||||
} else {
|
||||
playIcon.setImageResource(android.R.drawable.ic_media_pause);
|
||||
}
|
||||
|
||||
prevVoiceModel = voiceMediaModel;
|
||||
prevPlayIcon = playIcon;
|
||||
}
|
||||
};
|
||||
|
||||
private final View.OnClickListener openProfileClickListener = v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof ProfileModel) {
|
||||
// todo do profile stuff
|
||||
final ProfileModel profileModel = (ProfileModel) tag;
|
||||
Log.d(TAG, "--> " + profileModel);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public DirectMessageViewHolder(final ItemMessageItemBinding binding,
|
||||
final List<ProfileModel> users,
|
||||
final List<ProfileModel> leftUsers) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
this.users = users;
|
||||
this.leftUsers = leftUsers;
|
||||
this.itemMargin = Utils.displayMetrics.widthPixels / 5;
|
||||
strDmYou = binding.getRoot().getContext().getString(R.string.direct_messages_you);
|
||||
}
|
||||
|
||||
public void bind(final DirectItemModel directItemModel) {
|
||||
if (directItemModel == null) {
|
||||
return;
|
||||
}
|
||||
final Context context = itemView.getContext();
|
||||
itemView.setTag(directItemModel);
|
||||
final DirectItemType itemType = directItemModel.getItemType();
|
||||
final ProfileModel user = getUser(directItemModel.getUserId());
|
||||
final int type = user == myProfileHolder ? MESSAGE_OUTGOING : MESSAGE_INCOMING;
|
||||
|
||||
final RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) itemView.getLayoutParams();
|
||||
layoutParams.setMargins(type == MESSAGE_OUTGOING ? itemMargin : 0, 0,
|
||||
type == MESSAGE_INCOMING ? itemMargin : 0, 0);
|
||||
|
||||
binding.tvMessage.setVisibility(View.GONE);
|
||||
final View voiceMessageContainer = (View) binding.waveformSeekBar.getParent();
|
||||
final View linkMessageContainer = (View) binding.ivLinkPreview.getParent();
|
||||
final View mediaMessageContainer = (View) binding.ivMediaPreview.getParent();
|
||||
final View mediaTypeIcon = binding.typeIcon;
|
||||
final View profileMessageContainer = (View) binding.profileInfo.getParent();
|
||||
|
||||
voiceMessageContainer.setVisibility(View.GONE);
|
||||
binding.ivAnimatedMessage.setVisibility(View.GONE);
|
||||
linkMessageContainer.setVisibility(View.GONE);
|
||||
mediaMessageContainer.setVisibility(View.GONE);
|
||||
mediaTypeIcon.setVisibility(View.GONE);
|
||||
binding.mediaExpiredIcon.setVisibility(View.GONE);
|
||||
profileMessageContainer.setVisibility(View.GONE);
|
||||
binding.isVerified.setVisibility(View.GONE);
|
||||
|
||||
final FrameLayout btnOpenProfile = binding.btnInfo;
|
||||
btnOpenProfile.setVisibility(View.GONE);
|
||||
btnOpenProfile.setOnClickListener(null);
|
||||
btnOpenProfile.setTag(null);
|
||||
|
||||
CharSequence text = "?";
|
||||
if (user != null && user != myProfileHolder) text = user.getUsername();
|
||||
else if (user == myProfileHolder) text = strDmYou;
|
||||
text = text + " - " + directItemModel.getDateTime();
|
||||
|
||||
binding.tvUsername.setText(text);
|
||||
|
||||
binding.ivProfilePic.setVisibility(type == MESSAGE_INCOMING ? View.VISIBLE : View.GONE);
|
||||
|
||||
final RequestManager glideRequestManager = Glide.with(itemView);
|
||||
|
||||
if (type == MESSAGE_INCOMING && user != null)
|
||||
glideRequestManager.load(user.getSdProfilePic()).into(binding.ivProfilePic);
|
||||
|
||||
DirectItemModel.DirectItemMediaModel mediaModel = directItemModel.getMediaModel();
|
||||
switch (itemType) {
|
||||
case PLACEHOLDER:
|
||||
binding.tvMessage.setText(HtmlCompat.fromHtml(directItemModel.getText().toString(), FROM_HTML_MODE_COMPACT));
|
||||
binding.tvMessage.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case TEXT:
|
||||
case LIKE:
|
||||
text = directItemModel.getText();
|
||||
text = Utils.getSpannableUrl(text.toString()); // for urls
|
||||
if (Utils.hasMentions(text)) text = Utils.getMentionText(text); // for mentions
|
||||
|
||||
if (text instanceof Spanned)
|
||||
binding.tvMessage.setText(text, TextView.BufferType.SPANNABLE);
|
||||
else if (text == "") {
|
||||
binding.tvMessage.setText(context.getText(R.string.dms_inbox_raven_message_unknown));
|
||||
} else binding.tvMessage.setText(text);
|
||||
|
||||
binding.tvMessage.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
|
||||
case LINK: {
|
||||
final DirectItemModel.DirectItemLinkModel link = directItemModel.getLinkModel();
|
||||
final DirectItemModel.DirectItemLinkContext linkContext = link.getLinkContext();
|
||||
|
||||
final String linkImageUrl = linkContext.getLinkImageUrl();
|
||||
if (!Utils.isEmpty(linkImageUrl)) {
|
||||
glideRequestManager.load(linkImageUrl).into(binding.ivLinkPreview);
|
||||
binding.tvLinkTitle.setText(linkContext.getLinkTitle());
|
||||
binding.tvLinkSummary.setText(linkContext.getLinkSummary());
|
||||
binding.ivLinkPreview.setVisibility(View.VISIBLE);
|
||||
linkMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
binding.tvMessage.setText(Utils.getSpannableUrl(link.getText()));
|
||||
binding.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
|
||||
case MEDIA_SHARE: {
|
||||
final ProfileModel modelUser = mediaModel.getUser();
|
||||
if (modelUser != null) {
|
||||
binding.tvMessage.setText(HtmlCompat.fromHtml("<small>" + context.getString(R.string.dms_inbox_media_shared_from, modelUser.getUsername()) + "</small>", FROM_HTML_MODE_COMPACT));
|
||||
binding.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
case MEDIA: {
|
||||
glideRequestManager.load(mediaModel.getThumbUrl()).into(binding.ivMediaPreview);
|
||||
|
||||
final MediaItemType modelMediaType = mediaModel.getMediaType();
|
||||
mediaTypeIcon.setVisibility(modelMediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
|
||||
modelMediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
|
||||
mediaMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
|
||||
case RAVEN_MEDIA: {
|
||||
final DirectItemModel.DirectItemRavenMediaModel ravenMediaModel = directItemModel.getRavenMediaModel();
|
||||
|
||||
final boolean isExpired = ravenMediaModel == null || (mediaModel = ravenMediaModel.getMedia()) == null ||
|
||||
Utils.isEmpty(mediaModel.getThumbUrl()) && mediaModel.getPk() < 1;
|
||||
|
||||
DirectItemModel.RavenExpiringMediaActionSummaryModel mediaActionSummary = null;
|
||||
if (ravenMediaModel != null) {
|
||||
mediaActionSummary = ravenMediaModel.getExpiringMediaActionSummary();
|
||||
}
|
||||
binding.mediaExpiredIcon.setVisibility(isExpired ? View.VISIBLE : View.GONE);
|
||||
|
||||
int textRes = R.string.dms_inbox_raven_media_unknown;
|
||||
if (isExpired) textRes = R.string.dms_inbox_raven_media_expired;
|
||||
|
||||
if (!isExpired) {
|
||||
if (mediaActionSummary != null) {
|
||||
final RavenExpiringMediaType expiringMediaType = mediaActionSummary.getType();
|
||||
|
||||
if (expiringMediaType == RavenExpiringMediaType.RAVEN_DELIVERED)
|
||||
textRes = R.string.dms_inbox_raven_media_delivered;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SENT)
|
||||
textRes = R.string.dms_inbox_raven_media_sent;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_OPENED)
|
||||
textRes = R.string.dms_inbox_raven_media_opened;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_REPLAYED)
|
||||
textRes = R.string.dms_inbox_raven_media_replayed;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SENDING)
|
||||
textRes = R.string.dms_inbox_raven_media_sending;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_BLOCKED)
|
||||
textRes = R.string.dms_inbox_raven_media_blocked;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SUGGESTED)
|
||||
textRes = R.string.dms_inbox_raven_media_suggested;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SCREENSHOT)
|
||||
textRes = R.string.dms_inbox_raven_media_screenshot;
|
||||
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_CANNOT_DELIVER)
|
||||
textRes = R.string.dms_inbox_raven_media_cant_deliver;
|
||||
}
|
||||
|
||||
final RavenMediaViewType ravenMediaViewType = ravenMediaModel.getViewType();
|
||||
if (ravenMediaViewType == RavenMediaViewType.PERMANENT || ravenMediaViewType == RavenMediaViewType.REPLAYABLE) {
|
||||
final MediaItemType mediaType = mediaModel.getMediaType();
|
||||
textRes = -1;
|
||||
mediaTypeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
|
||||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
|
||||
|
||||
glideRequestManager.load(mediaModel.getThumbUrl()).into(binding.ivMediaPreview);
|
||||
mediaMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
if (textRes != -1) {
|
||||
binding.tvMessage.setText(context.getText(textRes));
|
||||
binding.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REEL_SHARE: {
|
||||
final DirectItemModel.DirectItemReelShareModel reelShare = directItemModel.getReelShare();
|
||||
if (!Utils.isEmpty(text = reelShare.getText())) {
|
||||
binding.tvMessage.setText(text);
|
||||
binding.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
final DirectItemModel.DirectItemMediaModel reelShareMedia = reelShare.getMedia();
|
||||
final MediaItemType mediaType = reelShareMedia.getMediaType();
|
||||
|
||||
if (mediaType == null)
|
||||
binding.mediaExpiredIcon.setVisibility(View.VISIBLE);
|
||||
else {
|
||||
mediaTypeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
|
||||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
|
||||
|
||||
glideRequestManager.load(reelShareMedia.getThumbUrl()).into(binding.ivMediaPreview);
|
||||
mediaMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STORY_SHARE: {
|
||||
final DirectItemModel.DirectItemReelShareModel reelShare = directItemModel.getReelShare();
|
||||
if (reelShare == null) {
|
||||
binding.tvMessage.setText(HtmlCompat.fromHtml(directItemModel.getText().toString(), FROM_HTML_MODE_COMPACT));
|
||||
binding.tvMessage.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
if (!Utils.isEmpty(text = reelShare.getText())) {
|
||||
binding.tvMessage.setText(text);
|
||||
binding.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
final DirectItemModel.DirectItemMediaModel reelShareMedia = reelShare.getMedia();
|
||||
final MediaItemType mediaType = reelShareMedia.getMediaType();
|
||||
|
||||
mediaTypeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
|
||||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
|
||||
|
||||
glideRequestManager.load(reelShareMedia.getThumbUrl()).into(binding.ivMediaPreview);
|
||||
mediaMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VOICE_MEDIA: {
|
||||
final DirectItemModel.DirectItemVoiceMediaModel voiceMediaModel = directItemModel.getVoiceMediaModel();
|
||||
|
||||
if (voiceMediaModel != null) {
|
||||
final int[] waveformData = voiceMediaModel.getWaveformData();
|
||||
if (waveformData != null) binding.waveformSeekBar.setSample(waveformData);
|
||||
|
||||
final long durationMs = voiceMediaModel.getDurationMs();
|
||||
binding.tvVoiceDuration.setText(Utils.millisToString(durationMs));
|
||||
binding.waveformSeekBar.setProgress(voiceMediaModel.getProgress());
|
||||
binding.waveformSeekBar.setProgressChangeListener((waveformSeekBar, progress, fromUser) -> {
|
||||
// todo progress audio player
|
||||
voiceMediaModel.setProgress(progress);
|
||||
if (fromUser)
|
||||
binding.tvVoiceDuration.setText(Utils.millisToString(durationMs * progress / 100));
|
||||
});
|
||||
binding.btnPlayVoice.setTag(voiceMediaModel);
|
||||
binding.btnPlayVoice.setOnClickListener(voicePlayClickListener);
|
||||
} else {
|
||||
binding.waveformSeekBar.setProgress(0);
|
||||
}
|
||||
voiceMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANIMATED_MEDIA: {
|
||||
glideRequestManager.asGif().load(directItemModel.getAnimatedMediaModel().getGifUrl())
|
||||
.into(binding.ivAnimatedMessage);
|
||||
binding.ivAnimatedMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROFILE: {
|
||||
final ProfileModel profileModel = directItemModel.getProfileModel();
|
||||
Glide.with(binding.profileInfo).load(profileModel.getSdProfilePic())
|
||||
.into(binding.profileInfo);
|
||||
btnOpenProfile.setTag(profileModel);
|
||||
btnOpenProfile.setOnClickListener(openProfileClickListener);
|
||||
|
||||
binding.tvFullName.setText(profileModel.getName());
|
||||
binding.profileInfoText.setText(profileModel.getUsername());
|
||||
binding.isVerified.setVisibility(profileModel.isVerified() ? View.VISIBLE : View.GONE);
|
||||
|
||||
btnOpenProfile.setVisibility(View.VISIBLE);
|
||||
profileMessageContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
|
||||
case VIDEO_CALL_EVENT: {
|
||||
// todo add call event info
|
||||
binding.tvMessage.setVisibility(View.VISIBLE);
|
||||
binding.profileInfoText.setBackgroundColor(0xFF_1F90E6);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTION_LOG: {
|
||||
text = directItemModel.getActionLogModel().getDescription();
|
||||
binding.tvMessage.setText(HtmlCompat.fromHtml("<small>" + text + "</small>", FROM_HTML_MODE_COMPACT));
|
||||
binding.tvMessage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ProfileModel getUser(final long userId) {
|
||||
if (users != null) {
|
||||
ProfileModel result = myProfileHolder;
|
||||
for (final ProfileModel user : users) {
|
||||
if (Long.toString(userId).equals(user.getId())) result = user;
|
||||
}
|
||||
if (leftUsers != null)
|
||||
for (final ProfileModel leftUser : leftUsers) {
|
||||
if (Long.toString(userId).equals(leftUser.getId())) result = leftUser;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package awais.instagrabber.adapters.viewholder.directmessages;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.customviews.RamboTextView;
|
||||
import awais.instagrabber.customviews.masoudss_waveform.WaveformSeekBar;
|
||||
import awais.instagrabber.interfaces.MentionClickListener;
|
||||
|
||||
public final class TextMessageViewHolder extends RecyclerView.ViewHolder {
|
||||
public final CardView rootCardView;
|
||||
public final TextView tvUsername;
|
||||
public final ImageView ivProfilePic;
|
||||
// text message
|
||||
public final RamboTextView tvMessage;
|
||||
// expired message icon
|
||||
public final View mediaExpiredIcon;
|
||||
// media message
|
||||
public final View mediaMessageContainer;
|
||||
public final ImageView ivMediaPreview, mediaTypeIcon;
|
||||
// profile messag
|
||||
public final View profileMessageContainer, isVerified, btnOpenProfile;
|
||||
public final TextView tvProfileUsername, tvProfileName;
|
||||
public final ImageView ivMessageProfilePic;
|
||||
// animated message
|
||||
public final ImageView ivAnimatedMessage;
|
||||
// link message
|
||||
public final View linkMessageContainer;
|
||||
public final ImageView ivLinkPreview;
|
||||
public final TextView tvLinkTitle, tvLinkSummary;
|
||||
// voice message
|
||||
public final View voiceMessageContainer, btnPlayVoice;
|
||||
public final WaveformSeekBar waveformSeekBar;
|
||||
public final TextView tvVoiceDuration;
|
||||
|
||||
public TextMessageViewHolder(@NonNull final View itemView, final View.OnClickListener clickListener,
|
||||
final MentionClickListener mentionClickListener) {
|
||||
super(itemView);
|
||||
|
||||
if (clickListener != null) itemView.setOnClickListener(clickListener);
|
||||
|
||||
tvUsername = itemView.findViewById(R.id.tvUsername);
|
||||
ivProfilePic = itemView.findViewById(R.id.ivProfilePic);
|
||||
|
||||
// text message
|
||||
tvMessage = itemView.findViewById(R.id.tvMessage);
|
||||
tvMessage.setCaptionIsExpandable(true);
|
||||
tvMessage.setCaptionIsExpanded(true);
|
||||
if (mentionClickListener != null) tvMessage.setMentionClickListener(mentionClickListener);
|
||||
|
||||
// root view
|
||||
rootCardView = (CardView) tvMessage.getParent().getParent();
|
||||
|
||||
// expired message icon
|
||||
mediaExpiredIcon = itemView.findViewById(R.id.mediaExpiredIcon);
|
||||
|
||||
// media message
|
||||
ivMediaPreview = itemView.findViewById(R.id.ivMediaPreview);
|
||||
mediaMessageContainer = (View) ivMediaPreview.getParent();
|
||||
mediaTypeIcon = mediaMessageContainer.findViewById(R.id.typeIcon);
|
||||
|
||||
// profile message
|
||||
btnOpenProfile = itemView.findViewById(R.id.btnInfo);
|
||||
ivMessageProfilePic = itemView.findViewById(R.id.profileInfo);
|
||||
profileMessageContainer = (View) ivMessageProfilePic.getParent();
|
||||
isVerified = profileMessageContainer.findViewById(R.id.isVerified);
|
||||
tvProfileName = profileMessageContainer.findViewById(R.id.tvFullName);
|
||||
tvProfileUsername = profileMessageContainer.findViewById(R.id.profileInfoText);
|
||||
|
||||
// animated message
|
||||
ivAnimatedMessage = itemView.findViewById(R.id.ivAnimatedMessage);
|
||||
|
||||
// link message
|
||||
ivLinkPreview = itemView.findViewById(R.id.ivLinkPreview);
|
||||
linkMessageContainer = (View) ivLinkPreview.getParent();
|
||||
tvLinkTitle = linkMessageContainer.findViewById(R.id.tvLinkTitle);
|
||||
tvLinkSummary = linkMessageContainer.findViewById(R.id.tvLinkSummary);
|
||||
|
||||
// voice message
|
||||
waveformSeekBar = itemView.findViewById(R.id.waveformSeekBar);
|
||||
voiceMessageContainer = (View) waveformSeekBar.getParent();
|
||||
btnPlayVoice = voiceMessageContainer.findViewById(R.id.btnPlayVoice);
|
||||
tvVoiceDuration = voiceMessageContainer.findViewById(R.id.tvVoiceDuration);
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@ import org.json.JSONObject;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
@ -21,17 +23,21 @@ import awais.instagrabber.utils.Utils;
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
import static awaisomereport.LogCollector.LogFile;
|
||||
|
||||
public final class UserInboxFetcher extends AsyncTask<Void, Void, InboxThreadModel> {
|
||||
public final class DirectMessageInboxThreadFetcher extends AsyncTask<Void, Void, InboxThreadModel> {
|
||||
private static final String TAG = "DMInboxThreadFetcher";
|
||||
|
||||
private final String id;
|
||||
private final String endCursor;
|
||||
private final FetchListener<InboxThreadModel> fetchListener;
|
||||
private final String direction;
|
||||
private final UserInboxDirection direction;
|
||||
|
||||
public UserInboxFetcher(final String id, final UserInboxDirection direction, final String endCursor,
|
||||
final FetchListener<InboxThreadModel> fetchListener) {
|
||||
public DirectMessageInboxThreadFetcher(final String id,
|
||||
final UserInboxDirection direction,
|
||||
final String cursor,
|
||||
final FetchListener<InboxThreadModel> fetchListener) {
|
||||
this.id = id;
|
||||
this.direction = "&direction=" + (direction == UserInboxDirection.NEWER ? "newer" : "older");
|
||||
this.endCursor = !Utils.isEmpty(endCursor) ? "&cursor=" + endCursor : "";
|
||||
this.direction = direction;
|
||||
this.endCursor = cursor;
|
||||
this.fetchListener = fetchListener;
|
||||
}
|
||||
|
||||
@ -39,11 +45,14 @@ public final class UserInboxFetcher extends AsyncTask<Void, Void, InboxThreadMod
|
||||
@Override
|
||||
protected InboxThreadModel doInBackground(final Void... voids) {
|
||||
InboxThreadModel result = null;
|
||||
final String url = "https://i.instagram.com/api/v1/direct_v2/threads/" + id + "/?visual_message_return_type=unseen"
|
||||
+ direction + endCursor;
|
||||
// todo probably
|
||||
// & seq_id = seqId
|
||||
|
||||
final Map<String, String> queryParamsMap = new HashMap<>();
|
||||
queryParamsMap.put("visual_message_return_type", "unseen");
|
||||
queryParamsMap.put("direction", direction.getValue());
|
||||
if (!Utils.isEmpty(endCursor)) {
|
||||
queryParamsMap.put("cursor", endCursor);
|
||||
}
|
||||
final String queryString = Utils.getQueryString(queryParamsMap);
|
||||
final String url = "https://i.instagram.com/api/v1/direct_v2/threads/" + id + "/?" + queryString;
|
||||
try {
|
||||
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
conn.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
||||
@ -60,9 +69,8 @@ public final class UserInboxFetcher extends AsyncTask<Void, Void, InboxThreadMod
|
||||
result = null;
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogFile.ASYNC_DMS_THREAD, "doInBackground");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -0,0 +1,149 @@
|
||||
package awais.instagrabber.fragments.directmessages;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.NavDirections;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.adapters.DirectMessageInboxAdapter;
|
||||
import awais.instagrabber.asyncs.direct_messages.InboxFetcher;
|
||||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
|
||||
import awais.instagrabber.databinding.FragmentDirectMessagesInboxBinding;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.direct_messages.InboxModel;
|
||||
import awais.instagrabber.models.direct_messages.InboxThreadModel;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
public class DirectMessageInboxFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private static final String TAG = "DirectMessagesInboxFrag";
|
||||
|
||||
private FragmentActivity fragmentActivity;
|
||||
private SwipeRefreshLayout root;
|
||||
private RecyclerView inboxList;
|
||||
private RecyclerLazyLoader lazyLoader;
|
||||
private LinearLayoutManager layoutManager;
|
||||
private String endCursor;
|
||||
private AsyncTask<Void, Void, InboxModel> currentlyRunning;
|
||||
private InboxThreadModelListViewModel listViewModel;
|
||||
|
||||
private final FetchListener<InboxModel> fetchListener = new FetchListener<InboxModel>() {
|
||||
@Override
|
||||
public void doBefore() {
|
||||
root.setRefreshing(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(final InboxModel inboxModel) {
|
||||
if (inboxModel != null) {
|
||||
endCursor = inboxModel.getOldestCursor();
|
||||
if ("MINCURSOR".equals(endCursor) || "MAXCURSOR".equals(endCursor))
|
||||
endCursor = null;
|
||||
// todo get request / unseen count from inboxModel
|
||||
final InboxThreadModel[] threads = inboxModel.getThreads();
|
||||
if (threads != null && threads.length > 0) {
|
||||
List<InboxThreadModel> list = listViewModel.getList().getValue();
|
||||
list = list != null ? new LinkedList<>(list) : new LinkedList<>();
|
||||
// final int oldSize = list != null ? list.size() : 0;
|
||||
final List<InboxThreadModel> newList = Arrays.asList(threads);
|
||||
list.addAll(newList);
|
||||
listViewModel.getList().postValue(list);
|
||||
}
|
||||
}
|
||||
root.setRefreshing(false);
|
||||
stopCurrentExecutor();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = requireActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater,
|
||||
final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
if (root != null) {
|
||||
return root;
|
||||
}
|
||||
final FragmentDirectMessagesInboxBinding binding = FragmentDirectMessagesInboxBinding.inflate(inflater, container, false);
|
||||
root = binding.getRoot();
|
||||
root.setOnRefreshListener(this);
|
||||
inboxList = binding.inboxList;
|
||||
inboxList.setHasFixedSize(true);
|
||||
layoutManager = new LinearLayoutManager(requireContext());
|
||||
inboxList.setLayoutManager(layoutManager);
|
||||
final DirectMessageInboxAdapter inboxAdapter = new DirectMessageInboxAdapter(inboxThreadModel -> {
|
||||
final NavDirections action = DirectMessagesInboxFragmentDirections.actionDMInboxFragmentToDMThreadFragment(inboxThreadModel.getThreadId(), inboxThreadModel.getThreadTitle());
|
||||
NavHostFragment.findNavController(this).navigate(action);
|
||||
});
|
||||
inboxList.setAdapter(inboxAdapter);
|
||||
listViewModel = new ViewModelProvider(fragmentActivity).get(InboxThreadModelListViewModel.class);
|
||||
listViewModel.getList().observe(fragmentActivity, inboxAdapter::submitList);
|
||||
initData();
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
endCursor = null;
|
||||
lazyLoader.resetState();
|
||||
listViewModel.getList().postValue(Collections.emptyList());
|
||||
stopCurrentExecutor();
|
||||
currentlyRunning = new InboxFetcher(null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if (!Utils.isEmpty(endCursor))
|
||||
currentlyRunning = new InboxFetcher(endCursor, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
endCursor = null;
|
||||
});
|
||||
inboxList.addOnScrollListener(lazyLoader);
|
||||
stopCurrentExecutor();
|
||||
currentlyRunning = new InboxFetcher(null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void stopCurrentExecutor() {
|
||||
if (currentlyRunning != null) {
|
||||
try {
|
||||
currentlyRunning.cancel(true);
|
||||
} catch (final Exception e) {
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class InboxThreadModelListViewModel extends ViewModel {
|
||||
private MutableLiveData<List<InboxThreadModel>> list;
|
||||
|
||||
public MutableLiveData<List<InboxThreadModel>> getList() {
|
||||
if (list == null) {
|
||||
list = new MutableLiveData<>();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,26 @@
|
||||
package awais.instagrabber.activities.directmessages;
|
||||
package awais.instagrabber.fragments.directmessages;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
@ -25,24 +34,21 @@ import java.net.HttpURLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.activities.BaseLanguageActivity;
|
||||
import awais.instagrabber.activities.PostViewer;
|
||||
import awais.instagrabber.activities.ProfileViewer;
|
||||
import awais.instagrabber.activities.StoryViewer;
|
||||
import awais.instagrabber.adapters.MessageItemsAdapter;
|
||||
import awais.instagrabber.asyncs.ImageUploader;
|
||||
import awais.instagrabber.asyncs.direct_messages.DirectMessageInboxThreadFetcher;
|
||||
import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster;
|
||||
import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster.BroadcastOptions;
|
||||
import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster.ImageBroadcastOptions;
|
||||
import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster.OnBroadcastCompleteListener;
|
||||
import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster.TextBroadcastOptions;
|
||||
import awais.instagrabber.asyncs.direct_messages.UserInboxFetcher;
|
||||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
|
||||
import awais.instagrabber.databinding.ActivityDmsBinding;
|
||||
import awais.instagrabber.databinding.FragmentDirectMessagesThreadBinding;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.interfaces.MentionClickListener;
|
||||
import awais.instagrabber.models.ImageUploadOptions;
|
||||
import awais.instagrabber.models.PostModel;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
@ -55,72 +61,34 @@ import awais.instagrabber.models.enums.UserInboxDirection;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
public final class DirectMessageThread extends BaseLanguageActivity {
|
||||
private static final String TAG = "DirectMessageThread";
|
||||
public class DirectMessageThreadFragment extends Fragment {
|
||||
private static final String TAG = "DirectMessagesThreadFmt";
|
||||
private static final int PICK_IMAGE = 100;
|
||||
|
||||
private DirectItemModel directItemModel;
|
||||
private FragmentActivity fragmentActivity;
|
||||
private String threadId;
|
||||
private String endCursor;
|
||||
private ActivityDmsBinding dmsBinding;
|
||||
private MessageItemsAdapter messageItemsAdapter;
|
||||
private String cursor;
|
||||
private FragmentDirectMessagesThreadBinding binding;
|
||||
private DirectItemModelListViewModel listViewModel;
|
||||
private RecyclerView messageList;
|
||||
private boolean hasSentSomething;
|
||||
private boolean hasOlder = true;
|
||||
|
||||
private final ProfileModel myProfileHolder = ProfileModel.getDefaultProfileModel();
|
||||
private final ArrayList<ProfileModel> users = new ArrayList<>();
|
||||
private final ArrayList<ProfileModel> leftUsers = new ArrayList<>();
|
||||
private final ArrayList<DirectItemModel> directItemModels = new ArrayList<>();
|
||||
private final FetchListener<InboxThreadModel> fetchListener = new FetchListener<InboxThreadModel>() {
|
||||
@Override
|
||||
public void doBefore() {
|
||||
dmsBinding.swipeRefreshLayout.setRefreshing(true);
|
||||
}
|
||||
private final List<ProfileModel> users = new ArrayList<>();
|
||||
private final List<ProfileModel> leftUsers = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onResult(final InboxThreadModel result) {
|
||||
if (result == null && ("MINCURSOR".equals(endCursor) || "MAXCURSOR".equals(endCursor) || Utils.isEmpty(endCursor)))
|
||||
Toast.makeText(DirectMessageThread.this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
|
||||
if (result != null) {
|
||||
endCursor = result.getPrevCursor();
|
||||
if ("MINCURSOR".equals(endCursor) || "MAXCURSOR".equals(endCursor))
|
||||
endCursor = null;
|
||||
|
||||
users.clear();
|
||||
users.addAll(Arrays.asList(result.getUsers()));
|
||||
|
||||
leftUsers.clear();
|
||||
leftUsers.addAll(Arrays.asList(result.getLeftUsers()));
|
||||
|
||||
threadId = result.getThreadId();
|
||||
dmsBinding.toolbar.toolbar.setTitle(result.getThreadTitle());
|
||||
String[] users = new String[result.getUsers().length];
|
||||
for (int i = 0; i < users.length; ++i) {
|
||||
users[i] = result.getUsers()[i].getUsername();
|
||||
}
|
||||
dmsBinding.toolbar.toolbar.setSubtitle(TextUtils.join(", ", users));
|
||||
|
||||
final int oldSize = directItemModels.size();
|
||||
final List<DirectItemModel> itemModels = Arrays.asList(result.getItems());
|
||||
directItemModels.addAll(itemModels);
|
||||
messageItemsAdapter.notifyItemRangeInserted(oldSize, itemModels.size());
|
||||
}
|
||||
|
||||
dmsBinding.swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
};
|
||||
private final View.OnClickListener clickListener = v -> {
|
||||
if (v == dmsBinding.commentSend) {
|
||||
final String text = dmsBinding.commentText.getText().toString();
|
||||
if (v == binding.commentSend) {
|
||||
final String text = binding.commentText.getText().toString();
|
||||
if (Utils.isEmpty(text)) {
|
||||
Toast.makeText(getApplicationContext(), R.string.comment_send_empty_comment, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(requireContext(), R.string.comment_send_empty_comment, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
sendText(text);
|
||||
return;
|
||||
}
|
||||
if (v == dmsBinding.image) {
|
||||
if (v == binding.image) {
|
||||
final Intent intent = new Intent();
|
||||
intent.setType("image/*");
|
||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||
@ -128,45 +96,95 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
dmsBinding = ActivityDmsBinding.inflate(getLayoutInflater());
|
||||
setContentView(dmsBinding.getRoot());
|
||||
|
||||
final InboxThreadModel threadModel;
|
||||
final Intent intent = getIntent();
|
||||
if (intent == null || !intent.hasExtra(Constants.EXTRAS_THREAD_MODEL) ||
|
||||
(threadModel = (InboxThreadModel) intent.getSerializableExtra(Constants.EXTRAS_THREAD_MODEL)) == null) {
|
||||
Utils.errorFinish(this);
|
||||
return;
|
||||
private final FetchListener<InboxThreadModel> fetchListener = new FetchListener<InboxThreadModel>() {
|
||||
@Override
|
||||
public void doBefore() {
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
}
|
||||
|
||||
dmsBinding.swipeRefreshLayout.setEnabled(false);
|
||||
dmsBinding.commentText.setVisibility(VISIBLE);
|
||||
dmsBinding.commentSend.setVisibility(VISIBLE);
|
||||
dmsBinding.image.setVisibility(VISIBLE);
|
||||
dmsBinding.commentSend.setOnClickListener(clickListener);
|
||||
dmsBinding.image.setOnClickListener(clickListener);
|
||||
@Override
|
||||
public void onResult(final InboxThreadModel result) {
|
||||
if (result == null && ("MINCURSOR".equals(cursor) || "MAXCURSOR".equals(cursor) || Utils.isEmpty(cursor)))
|
||||
Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
|
||||
final LinearLayoutManager layoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, true);
|
||||
dmsBinding.rvDirectMessages.setLayoutManager(layoutManager);
|
||||
if (result != null) {
|
||||
cursor = result.getOldestCursor();
|
||||
hasOlder = result.hasOlder();
|
||||
if ("MINCURSOR".equals(cursor) || "MAXCURSOR".equals(cursor)) {
|
||||
cursor = null;
|
||||
}
|
||||
users.clear();
|
||||
users.addAll(Arrays.asList(result.getUsers()));
|
||||
leftUsers.clear();
|
||||
leftUsers.addAll(Arrays.asList(result.getLeftUsers()));
|
||||
|
||||
dmsBinding.rvDirectMessages.addOnScrollListener(new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if (!Utils.isEmpty(endCursor)) {
|
||||
new UserInboxFetcher(threadModel.getThreadId(), UserInboxDirection.OLDER,
|
||||
endCursor, fetchListener).execute(); // serial because we don't want messages to be randomly ordered
|
||||
// thread title is already comma separated username, so no need to set by ourselves
|
||||
// String[] users = new String[result.getUsers().length];
|
||||
// for (int i = 0; i < users.length; ++i) {
|
||||
// users[i] = result.getUsers()[i].getUsername();
|
||||
// }
|
||||
|
||||
List<DirectItemModel> list = listViewModel.getList().getValue();
|
||||
final List<DirectItemModel> newList = Arrays.asList(result.getItems());
|
||||
list = list != null ? new LinkedList<>(list) : new LinkedList<>();
|
||||
if (hasSentSomething) {
|
||||
list = newList;
|
||||
hasSentSomething = false;
|
||||
final Handler handler = new Handler();
|
||||
handler.postDelayed(() -> {
|
||||
if (messageList != null) {
|
||||
messageList.smoothScrollToPosition(0);
|
||||
}
|
||||
}, 200);
|
||||
} else {
|
||||
list.addAll(newList);
|
||||
}
|
||||
listViewModel.getList().postValue(list);
|
||||
}
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = requireActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater,
|
||||
final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
binding = FragmentDirectMessagesThreadBinding.inflate(inflater, container, false);
|
||||
final LinearLayout root = binding.getRoot();
|
||||
if (getArguments() == null) {
|
||||
return root;
|
||||
}
|
||||
threadId = DirectMessagesThreadFragmentArgs.fromBundle(getArguments()).getThreadId();
|
||||
binding.swipeRefreshLayout.setEnabled(false);
|
||||
messageList = binding.messageList;
|
||||
messageList.setHasFixedSize(true);
|
||||
binding.commentSend.setOnClickListener(clickListener);
|
||||
binding.image.setOnClickListener(clickListener);
|
||||
final LinearLayoutManager layoutManager = new LinearLayoutManager(requireContext());
|
||||
layoutManager.setReverseLayout(true);
|
||||
// layoutManager.setStackFromEnd(true);
|
||||
messageList.setLayoutManager(layoutManager);
|
||||
messageList.addOnScrollListener(new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if (Utils.isEmpty(cursor) || !hasOlder) {
|
||||
return;
|
||||
}
|
||||
new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, cursor, fetchListener).execute(); // serial because we don't want messages to be randomly ordered
|
||||
}));
|
||||
|
||||
messageItemsAdapter = new MessageItemsAdapter(directItemModels, users, leftUsers, v -> {
|
||||
final View.OnClickListener onClickListener = v -> {
|
||||
Object tag = v.getTag();
|
||||
if (tag instanceof DirectItemModel) {
|
||||
directItemModel = (DirectItemModel) tag;
|
||||
final DirectItemModel directItemModel = (DirectItemModel) tag;
|
||||
final DirectItemType itemType = directItemModel.getItemType();
|
||||
switch (itemType) {
|
||||
case MEDIA_SHARE:
|
||||
startActivity(new Intent(this, PostViewer.class)
|
||||
startActivity(new Intent(requireContext(), PostViewer.class)
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(directItemModel.getMediaModel().getCode(), false)));
|
||||
break;
|
||||
case LINK:
|
||||
@ -182,9 +200,7 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
||||
case RAVEN_MEDIA:
|
||||
case MEDIA:
|
||||
final ProfileModel user = getUser(directItemModel.getUserId());
|
||||
if (user != null) {
|
||||
Utils.dmDownload(this, user.getUsername(), DownloadMethod.DOWNLOAD_DIRECT, Collections.singletonList(itemType == DirectItemType.MEDIA ? directItemModel.getMediaModel() : directItemModel.getRavenMediaModel().getMedia()));
|
||||
}
|
||||
Utils.dmDownload(requireContext(), user.getUsername(), DownloadMethod.DOWNLOAD_DIRECT, Collections.singletonList(itemType == DirectItemType.MEDIA ? directItemModel.getMediaModel() : directItemModel.getRavenMediaModel().getMedia()));
|
||||
Toast.makeText(v.getContext(), R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
case STORY_SHARE:
|
||||
@ -200,7 +216,7 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
||||
);
|
||||
sm.setVideoUrl(directItemModel.getReelShare().getMedia().getVideoUrl());
|
||||
StoryModel[] sms = {sm};
|
||||
startActivity(new Intent(this, StoryViewer.class)
|
||||
startActivity(new Intent(requireContext(), StoryViewer.class)
|
||||
.putExtra(Constants.EXTRAS_USERNAME, directItemModel.getReelShare().getReelOwnerName())
|
||||
.putExtra(Constants.EXTRAS_STORIES, sms)
|
||||
);
|
||||
@ -216,15 +232,18 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
||||
Log.d("austin_debug", "unsupported type " + itemType);
|
||||
}
|
||||
}
|
||||
}, (view, text, isHashtag) -> searchUsername(text));
|
||||
|
||||
dmsBinding.rvDirectMessages.setAdapter(messageItemsAdapter);
|
||||
|
||||
new UserInboxFetcher(threadModel.getThreadId(), UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
};
|
||||
final MentionClickListener mentionClickListener = (view, text, isHashtag) -> searchUsername(text);
|
||||
final MessageItemsAdapter adapter = new MessageItemsAdapter(users, leftUsers, onClickListener, mentionClickListener);
|
||||
messageList.setAdapter(adapter);
|
||||
listViewModel = new ViewModelProvider(fragmentActivity).get(DirectItemModelListViewModel.class);
|
||||
listViewModel.getList().observe(fragmentActivity, adapter::submitList);
|
||||
new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK) {
|
||||
if (data == null || data.getData() == null) {
|
||||
@ -236,61 +255,46 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ProfileModel getUser(final long userId) {
|
||||
if (users != null) {
|
||||
ProfileModel result = myProfileHolder;
|
||||
for (final ProfileModel user : users) {
|
||||
if (Long.toString(userId).equals(user.getId())) result = user;
|
||||
}
|
||||
if (leftUsers != null)
|
||||
for (final ProfileModel leftUser : leftUsers) {
|
||||
if (Long.toString(userId).equals(leftUser.getId())) result = leftUser;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void searchUsername(final String text) {
|
||||
startActivity(new Intent(getApplicationContext(), ProfileViewer.class).putExtra(Constants.EXTRAS_USERNAME, text));
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
listViewModel.getList().postValue(Collections.emptyList());
|
||||
}
|
||||
|
||||
private void sendText(final String text) {
|
||||
final TextBroadcastOptions options;
|
||||
final DirectThreadBroadcaster.TextBroadcastOptions options;
|
||||
try {
|
||||
options = new TextBroadcastOptions(text);
|
||||
options = new DirectThreadBroadcaster.TextBroadcastOptions(text);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.e(TAG, "Error", e);
|
||||
return;
|
||||
}
|
||||
broadcast(options, result -> {
|
||||
if (result == null || result.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
||||
Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
dmsBinding.commentText.setText("");
|
||||
dmsBinding.commentText.clearFocus();
|
||||
directItemModels.clear();
|
||||
messageItemsAdapter.notifyDataSetChanged();
|
||||
new UserInboxFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
binding.commentText.setText("");
|
||||
// binding.commentText.clearFocus();
|
||||
hasSentSomething = true;
|
||||
new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
});
|
||||
}
|
||||
|
||||
private void sendImage(final Uri imageUri) {
|
||||
try {
|
||||
final ParcelFileDescriptor fileDescriptor = getContentResolver().openFileDescriptor(imageUri, "r");
|
||||
final ParcelFileDescriptor fileDescriptor = requireContext().getContentResolver().openFileDescriptor(imageUri, "r");
|
||||
if (fileDescriptor == null) {
|
||||
Log.e(TAG, "fileDescriptor is null!");
|
||||
return;
|
||||
}
|
||||
final long contentLength = fileDescriptor.getStatSize();
|
||||
final InputStream inputStream = getContentResolver().openInputStream(imageUri);
|
||||
final InputStream inputStream = requireContext().getContentResolver().openInputStream(imageUri);
|
||||
// Upload Image
|
||||
final ImageUploader imageUploader = new ImageUploader();
|
||||
imageUploader.setOnTaskCompleteListener(response -> {
|
||||
if (response == null || response.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
||||
Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
if (response != null && response.getResponse() != null) {
|
||||
Log.e(TAG, response.getResponse().toString());
|
||||
}
|
||||
@ -300,12 +304,9 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
||||
try {
|
||||
final String uploadId = responseJson.getString("upload_id");
|
||||
// Broadcast
|
||||
final ImageBroadcastOptions options = new ImageBroadcastOptions(true, uploadId);
|
||||
broadcast(options, onBroadcastCompleteListener -> {
|
||||
directItemModels.clear();
|
||||
messageItemsAdapter.notifyDataSetChanged();
|
||||
new UserInboxFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
});
|
||||
final DirectThreadBroadcaster.ImageBroadcastOptions options = new DirectThreadBroadcaster.ImageBroadcastOptions(true, uploadId);
|
||||
hasSentSomething = true;
|
||||
broadcast(options, onBroadcastCompleteListener -> new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR));
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error parsing json response", e);
|
||||
}
|
||||
@ -317,9 +318,36 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcast(final BroadcastOptions broadcastOptions, final OnBroadcastCompleteListener listener) {
|
||||
private void broadcast(final DirectThreadBroadcaster.BroadcastOptions broadcastOptions, final DirectThreadBroadcaster.OnBroadcastCompleteListener listener) {
|
||||
final DirectThreadBroadcaster broadcaster = new DirectThreadBroadcaster(threadId);
|
||||
broadcaster.setOnTaskCompleteListener(listener);
|
||||
broadcaster.execute(broadcastOptions);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private ProfileModel getUser(final long userId) {
|
||||
ProfileModel result = myProfileHolder;
|
||||
for (final ProfileModel user : users) {
|
||||
if (Long.toString(userId).equals(user.getId())) result = user;
|
||||
}
|
||||
for (final ProfileModel leftUser : leftUsers) {
|
||||
if (Long.toString(userId).equals(leftUser.getId())) result = leftUser;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void searchUsername(final String text) {
|
||||
startActivity(new Intent(requireContext(), ProfileViewer.class).putExtra(Constants.EXTRAS_USERNAME, text));
|
||||
}
|
||||
|
||||
public static class DirectItemModelListViewModel extends ViewModel {
|
||||
private MutableLiveData<List<DirectItemModel>> list;
|
||||
|
||||
public MutableLiveData<List<DirectItemModel>> getList() {
|
||||
if (list == null) {
|
||||
list = new MutableLiveData<>();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
@ -35,6 +35,10 @@ public final class ProfileModel implements Serializable {
|
||||
return new ProfileModel(false, false, false, null, null, null, null, null, null, null, 0, 0, 0, false, false, false, false);
|
||||
}
|
||||
|
||||
public static ProfileModel getDefaultProfileModel(final String userId) {
|
||||
return new ProfileModel(false, false, false, userId, null, null, null, null, null, null, 0, 0, 0, false, false, false, false);
|
||||
}
|
||||
|
||||
public boolean isPrivate() {
|
||||
return isPrivate;
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package awais.instagrabber.models.direct_messages;
|
||||
|
||||
import androidx.core.util.ObjectsCompat;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
@ -123,7 +125,7 @@ public final class InboxThreadModel implements Serializable {
|
||||
return canonical;
|
||||
}
|
||||
|
||||
public boolean isHasOlder() {
|
||||
public boolean hasOlder() {
|
||||
return hasOlder;
|
||||
}
|
||||
|
||||
@ -142,4 +144,18 @@ public final class InboxThreadModel implements Serializable {
|
||||
public long getLastActivityAt() {
|
||||
return lastActivityAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final InboxThreadModel that = (InboxThreadModel) o;
|
||||
return ObjectsCompat.equals(threadId, that.threadId) &&
|
||||
ObjectsCompat.equals(threadV2Id, that.threadV2Id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectsCompat.hash(threadId, threadV2Id);
|
||||
}
|
||||
}
|
@ -1,6 +1,16 @@
|
||||
package awais.instagrabber.models.enums;
|
||||
|
||||
public enum UserInboxDirection {
|
||||
OLDER,
|
||||
NEWER,
|
||||
OLDER("older"),
|
||||
NEWER("newer");
|
||||
|
||||
private final String value;
|
||||
|
||||
UserInboxDirection(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
@ -42,6 +42,7 @@ import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.jsoup.internal.StringUtil;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
@ -58,6 +59,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
@ -1371,4 +1373,24 @@ public final class Utils {
|
||||
connection.setRequestProperty(header.getKey(), header.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public static String getQueryString(final Map<String, String> queryParamsMap) {
|
||||
if (queryParamsMap == null || queryParamsMap.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
final Set<Map.Entry<String, String>> params = queryParamsMap.entrySet();
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (final Map.Entry<String, String> param : params) {
|
||||
if (isEmpty(param.getKey())) {
|
||||
continue;
|
||||
}
|
||||
if (builder.length() != 0) {
|
||||
builder.append("&");
|
||||
}
|
||||
builder.append(param.getKey());
|
||||
builder.append("=");
|
||||
builder.append(param.getValue() != null ? param.getValue() : "");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
54
app/src/main/res/layout/activity_direct_messages.xml
Normal file
54
app/src/main/res/layout/activity_direct_messages.xml
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/homeCoordinator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".activities.DirectMessagesActivity">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/direct_messages_nav_host_fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:defaultNavHost="true"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
app:navGraph="@navigation/direct_messages_nav_graph"
|
||||
tools:ignore="FragmentTagUsage" />
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:liftOnScroll="true">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:id="@+id/collapsingToolbarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
app:contentScrim="?attr/colorPrimary"
|
||||
app:layout_scrollFlags="scroll|enterAlways|exitUntilCollapsed|snap"
|
||||
app:scrimAnimationDuration="10">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:layout_collapseMode="pin"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/toolbar_title"
|
||||
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/app_name" />
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
10
app/src/main/res/layout/fragment_direct_messages_inbox.xml
Normal file
10
app/src/main/res/layout/fragment_direct_messages_inbox.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/inbox_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
19
app/src/main/res/layout/activity_dms.xml → app/src/main/res/layout/fragment_direct_messages_thread.xml
Executable file → Normal file
19
app/src/main/res/layout/activity_dms.xml → app/src/main/res/layout/fragment_direct_messages_thread.xml
Executable file → Normal file
@ -1,24 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".activities.directmessages.DirectMessages">
|
||||
|
||||
<include
|
||||
android:id="@+id/toolbar"
|
||||
layout="@layout/layout_include_toolbar" />
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="8">
|
||||
android:layout_weight="1">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvDirectMessages"
|
||||
android:id="@+id/messageList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
@ -31,7 +25,7 @@
|
||||
android:id="@+id/commentText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="2"
|
||||
android:layout_weight="1"
|
||||
android:gravity="bottom"
|
||||
android:hint="@string/dm_hint"
|
||||
android:importantForAutofill="no"
|
||||
@ -42,8 +36,7 @@
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:scrollHorizontally="false"
|
||||
android:visibility="visible" />
|
||||
android:scrollHorizontally="false" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/image"
|
||||
@ -54,7 +47,6 @@
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="4dp"
|
||||
android:visibility="visible"
|
||||
app:srcCompat="@drawable/ic_image_24" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
@ -71,7 +63,6 @@
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:visibility="visible"
|
||||
app:srcCompat="@drawable/ic_send_24" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
@ -4,8 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
tools:viewBindingIgnore="true">
|
||||
android:orientation="horizontal">
|
||||
|
||||
<awais.instagrabber.customviews.CircularImageView
|
||||
android:id="@+id/ivProfilePic"
|
||||
|
26
app/src/main/res/navigation/direct_messages_nav_graph.xml
Normal file
26
app/src/main/res/navigation/direct_messages_nav_graph.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/direct_messages_nav_graph"
|
||||
app:startDestination="@id/directMessagesInboxFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/directMessagesInboxFragment"
|
||||
android:name="awais.instagrabber.fragments.directmessages.DirectMessageInboxFragment"
|
||||
android:label="DirectMessagesInboxFragment" >
|
||||
<action
|
||||
android:id="@+id/action_dMInboxFragment_to_dMThreadFragment"
|
||||
app:destination="@id/directMessagesThreadFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/directMessagesThreadFragment"
|
||||
android:name="awais.instagrabber.fragments.directmessages.DirectMessageThreadFragment"
|
||||
android:label="DirectMessagesThreadFragment">
|
||||
<argument
|
||||
android:name="threadId"
|
||||
app:argType="string" />
|
||||
<argument
|
||||
android:name="title"
|
||||
app:argType="string" />
|
||||
</fragment>
|
||||
</navigation>
|
@ -181,7 +181,7 @@
|
||||
<string name="comment_viewer_like_comment">Like comment</string>
|
||||
<string name="comment_viewer_unlike_comment">Unlike comment</string>
|
||||
<string name="comment_viewer_delete_comment">Delete comment</string>
|
||||
<string name="comment_send_empty_comment">No empty comments, dawg!</string>
|
||||
<string name="comment_send_empty_comment">No empty comments!</string>
|
||||
<string name="comment_view_mention_user_search">Do you want to search the username?</string>
|
||||
<string name="comment_view_mention_hash_search">Do you want to search the hashtag?</string>
|
||||
<string name="comment_view_mention_location_search">Do you want to search the location?</string>
|
||||
|
@ -6,6 +6,9 @@ buildscript {
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||
def nav_version = "2.3.0"
|
||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user