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: 'com.android.application'
|
||||||
|
apply plugin: "androidx.navigation.safeargs"
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 29
|
||||||
@ -37,10 +38,14 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation('androidx.appcompat:appcompat:1.3.0-alpha01@aar') { transitive true }
|
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('com.google.android.material:material:1.3.0-alpha01@aar') { transitive true }
|
||||||
implementation('androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-rc01') { 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'
|
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
|
||||||
|
|
||||||
implementation('org.jsoup:jsoup:1.13.1') { transitive true }
|
implementation('org.jsoup:jsoup:1.13.1') { transitive true }
|
||||||
|
@ -215,7 +215,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.directmessages.DirectMessages"
|
android:name=".activities.DirectMessagesActivity"
|
||||||
android:parentActivityName=".activities.Main">
|
android:parentActivityName=".activities.Main">
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
@ -223,15 +223,6 @@
|
|||||||
android:value=".activities.Main" />
|
android:value=".activities.Main" />
|
||||||
</activity>
|
</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
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.provider"
|
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.BuildConfig;
|
||||||
import awais.instagrabber.MainHelper;
|
import awais.instagrabber.MainHelper;
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.activities.directmessages.DirectMessages;
|
|
||||||
import awais.instagrabber.adapters.HighlightsAdapter;
|
import awais.instagrabber.adapters.HighlightsAdapter;
|
||||||
import awais.instagrabber.adapters.SuggestionsAdapter;
|
import awais.instagrabber.adapters.SuggestionsAdapter;
|
||||||
import awais.instagrabber.asyncs.SuggestionsFetcher;
|
import awais.instagrabber.asyncs.SuggestionsFetcher;
|
||||||
@ -86,7 +85,8 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
.putExtra(Constants.EXTRAS_HIGHLIGHT, highlightModel.getTitle())
|
.putExtra(Constants.EXTRAS_HIGHLIGHT, highlightModel.getTitle())
|
||||||
.putExtra(Constants.EXTRAS_STORIES, result)
|
.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);
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,7 +143,7 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
if (mainHelper != null && !Utils.isEmpty(result)) {
|
if (mainHelper != null && !Utils.isEmpty(result)) {
|
||||||
closeAnyOpenDrawer();
|
closeAnyOpenDrawer();
|
||||||
addToStack();
|
addToStack();
|
||||||
userQuery = (result.contains("/") || result.startsWith("#") || result.startsWith("@")) ? result : ("@"+result);
|
userQuery = (result.contains("/") || result.startsWith("#") || result.startsWith("@")) ? result : ("@" + result);
|
||||||
mainHelper.onRefresh();
|
mainHelper.onRefresh();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -154,7 +154,8 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
if (!Utils.isEmpty(username)) {
|
if (!Utils.isEmpty(username)) {
|
||||||
if (!BuildConfig.DEBUG) {
|
if (!BuildConfig.DEBUG) {
|
||||||
userQuery = username;
|
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
|
// adds cookies to database for quick access
|
||||||
cookieModel = Utils.dataBox.getCookie(uid);
|
cookieModel = Utils.dataBox.getCookie(uid);
|
||||||
@ -168,7 +169,7 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
final String username = cookieModel.getUsername();
|
final String username = cookieModel.getUsername();
|
||||||
if (username != null) {
|
if (username != null) {
|
||||||
found = true;
|
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(
|
intent = new Intent(this, ProfilePicViewer.class).putExtra(
|
||||||
((hashtagModel != null) ? Constants.EXTRAS_HASHTAG : (locationModel != null ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_PROFILE)),
|
((hashtagModel != null) ? Constants.EXTRAS_HASHTAG : (locationModel != null ? Constants.EXTRAS_LOCATION : Constants.EXTRAS_PROFILE)),
|
||||||
((hashtagModel != null) ? hashtagModel : (locationModel != null ? locationModel : profileModel)));
|
((hashtagModel != null) ? hashtagModel : (locationModel != null ? locationModel : profileModel)));
|
||||||
}
|
} else
|
||||||
else intent = new Intent(this, StoryViewer.class).putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", ""))
|
intent = new Intent(this, StoryViewer.class).putExtra(Constants.EXTRAS_USERNAME, userQuery.replace("@", ""))
|
||||||
.putExtra(Constants.EXTRAS_STORIES, storyModels)
|
.putExtra(Constants.EXTRAS_STORIES, storyModels)
|
||||||
.putExtra(Constants.EXTRAS_HASHTAG, (hashtagModel != null));
|
.putExtra(Constants.EXTRAS_HASHTAG, (hashtagModel != null));
|
||||||
startActivity(intent);
|
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.privatePage2.setText(mainHelper.isLoggedIn ? R.string.no_acc_logged_in : R.string.no_acc);
|
||||||
mainBinding.profileView.privatePage.setVisibility(View.VISIBLE);
|
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());
|
mainHelper.onIntent(getIntent());
|
||||||
}
|
}
|
||||||
@ -301,7 +303,7 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
if (item == downloadAction)
|
if (item == downloadAction)
|
||||||
downloadSelectedItems();
|
downloadSelectedItems();
|
||||||
else if (item == dmsAction)
|
else if (item == dmsAction)
|
||||||
startActivity(new Intent(this, DirectMessages.class));
|
startActivity(new Intent(this, DirectMessagesActivity.class));
|
||||||
else if (item == notifAction)
|
else if (item == notifAction)
|
||||||
startActivity(new Intent(this, NotificationsViewer.class));
|
startActivity(new Intent(this, NotificationsViewer.class));
|
||||||
else if (item == settingsAction)
|
else if (item == settingsAction)
|
||||||
@ -336,7 +338,7 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
searchView.setQueryHint(getResources().getString(R.string.action_search));
|
searchView.setQueryHint(getResources().getString(R.string.action_search));
|
||||||
searchView.setSuggestionsAdapter(suggestionAdapter);
|
searchView.setSuggestionsAdapter(suggestionAdapter);
|
||||||
searchView.setOnSearchClickListener(v -> {
|
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_about).setVisible(false);
|
||||||
menu.findItem(R.id.action_settings).setVisible(false);
|
menu.findItem(R.id.action_settings).setVisible(false);
|
||||||
menu.findItem(R.id.action_dms).setVisible(false);
|
menu.findItem(R.id.action_dms).setVisible(false);
|
||||||
@ -400,7 +402,10 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
|
|
||||||
private void cancelSuggestionsAsync() {
|
private void cancelSuggestionsAsync() {
|
||||||
if (prevSuggestionAsync != null)
|
if (prevSuggestionAsync != null)
|
||||||
try { prevSuggestionAsync.cancel(true); } catch (final Exception ignored) { }
|
try {
|
||||||
|
prevSuggestionAsync.cancel(true);
|
||||||
|
} catch (final Exception ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -411,7 +416,7 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
|
|
||||||
closeAnyOpenDrawer();
|
closeAnyOpenDrawer();
|
||||||
addToStack();
|
addToStack();
|
||||||
userQuery = (query.contains("@") || query.contains("#")) ? query : ("@"+query);
|
userQuery = (query.contains("@") || query.contains("#")) ? query : ("@" + query);
|
||||||
searchAction.collapseActionView();
|
searchAction.collapseActionView();
|
||||||
searchView.setIconified(true);
|
searchView.setIconified(true);
|
||||||
searchView.setIconified(true);
|
searchView.setIconified(true);
|
||||||
@ -468,8 +473,7 @@ public final class Main extends BaseLanguageActivity {
|
|||||||
mainHelper.onRefresh();
|
mainHelper.onRefresh();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
finish();
|
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;
|
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.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
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.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
import androidx.core.text.HtmlCompat;
|
import androidx.recyclerview.widget.ListAdapter;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import java.util.List;
|
||||||
import com.bumptech.glide.RequestManager;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageViewHolder;
|
||||||
|
import awais.instagrabber.databinding.ItemMessageItemBinding;
|
||||||
import awais.instagrabber.R;
|
|
||||||
import awais.instagrabber.activities.Main;
|
|
||||||
import awais.instagrabber.adapters.viewholder.directmessages.TextMessageViewHolder;
|
|
||||||
import awais.instagrabber.interfaces.MentionClickListener;
|
import awais.instagrabber.interfaces.MentionClickListener;
|
||||||
import awais.instagrabber.models.ProfileModel;
|
import awais.instagrabber.models.ProfileModel;
|
||||||
import awais.instagrabber.models.direct_messages.DirectItemModel;
|
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;
|
public final class MessageItemsAdapter extends ListAdapter<DirectItemModel, DirectMessageViewHolder> {
|
||||||
import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemLinkModel;
|
private final List<ProfileModel> users;
|
||||||
import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemReelShareModel;
|
private final List<ProfileModel> leftUsers;
|
||||||
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;
|
|
||||||
private final View.OnClickListener onClickListener;
|
private final View.OnClickListener onClickListener;
|
||||||
private final MentionClickListener mentionClickListener;
|
private final MentionClickListener mentionClickListener;
|
||||||
private final View.OnClickListener openProfileClickListener = v -> {
|
|
||||||
final Object tag = v.getTag();
|
private static final DiffUtil.ItemCallback<DirectItemModel> diffCallback = new DiffUtil.ItemCallback<DirectItemModel>() {
|
||||||
if (tag instanceof ProfileModel) {
|
@Override
|
||||||
// todo do profile stuff
|
public boolean areItemsTheSame(@NonNull final DirectItemModel oldItem, @NonNull final DirectItemModel newItem) {
|
||||||
final ProfileModel profileModel = (ProfileModel) tag;
|
return oldItem.getItemId().equals(newItem.getItemId());
|
||||||
Log.d("AWAISKING_APP", "--> " + profileModel);
|
}
|
||||||
|
|
||||||
|
@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) {
|
public MessageItemsAdapter(final List<ProfileModel> users,
|
||||||
// todo pause / resume
|
final List<ProfileModel> leftUsers,
|
||||||
} else {
|
final View.OnClickListener onClickListener,
|
||||||
// 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,
|
|
||||||
final MentionClickListener mentionClickListener) {
|
final MentionClickListener mentionClickListener) {
|
||||||
|
super(diffCallback);
|
||||||
this.users = users;
|
this.users = users;
|
||||||
this.leftusers = leftusers;
|
this.leftUsers = leftUsers;
|
||||||
this.directItemModels = directItemModels;
|
|
||||||
this.onClickListener = onClickListener;
|
this.onClickListener = onClickListener;
|
||||||
this.mentionClickListener = mentionClickListener;
|
this.mentionClickListener = mentionClickListener;
|
||||||
this.itemMargin = Utils.displayMetrics.widthPixels / 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public TextMessageViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) {
|
public DirectMessageViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) {
|
||||||
if (context == null) context = parent.getContext();
|
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
|
||||||
if (strDmYou == null) strDmYou = context.getString(R.string.direct_messages_you);
|
final ItemMessageItemBinding binding = ItemMessageItemBinding.inflate(layoutInflater, parent, false);
|
||||||
if (layoutInflater == null) layoutInflater = LayoutInflater.from(context);
|
return new DirectMessageViewHolder(binding, users, leftUsers);
|
||||||
return new TextMessageViewHolder(layoutInflater.inflate(R.layout.item_message_item, parent, false),
|
|
||||||
onClickListener, mentionClickListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull final TextMessageViewHolder holder, final int position) {
|
public void onBindViewHolder(@NonNull final DirectMessageViewHolder holder, final int position) {
|
||||||
final DirectItemModel directItemModel = directItemModels.get(position);
|
final DirectItemModel directItemModel = getItem(position);
|
||||||
holder.itemView.setTag(directItemModel);
|
holder.bind(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(final int position) {
|
public int getItemViewType(final int position) {
|
||||||
return directItemModels.get(position).getItemType().ordinal();
|
return getItem(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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import awais.instagrabber.BuildConfig;
|
import awais.instagrabber.BuildConfig;
|
||||||
import awais.instagrabber.interfaces.FetchListener;
|
import awais.instagrabber.interfaces.FetchListener;
|
||||||
@ -21,17 +23,21 @@ import awais.instagrabber.utils.Utils;
|
|||||||
import static awais.instagrabber.utils.Utils.logCollector;
|
import static awais.instagrabber.utils.Utils.logCollector;
|
||||||
import static awaisomereport.LogCollector.LogFile;
|
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 id;
|
||||||
private final String endCursor;
|
private final String endCursor;
|
||||||
private final FetchListener<InboxThreadModel> fetchListener;
|
private final FetchListener<InboxThreadModel> fetchListener;
|
||||||
private final String direction;
|
private final UserInboxDirection direction;
|
||||||
|
|
||||||
public UserInboxFetcher(final String id, final UserInboxDirection direction, final String endCursor,
|
public DirectMessageInboxThreadFetcher(final String id,
|
||||||
final FetchListener<InboxThreadModel> fetchListener) {
|
final UserInboxDirection direction,
|
||||||
|
final String cursor,
|
||||||
|
final FetchListener<InboxThreadModel> fetchListener) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.direction = "&direction=" + (direction == UserInboxDirection.NEWER ? "newer" : "older");
|
this.direction = direction;
|
||||||
this.endCursor = !Utils.isEmpty(endCursor) ? "&cursor=" + endCursor : "";
|
this.endCursor = cursor;
|
||||||
this.fetchListener = fetchListener;
|
this.fetchListener = fetchListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,11 +45,14 @@ public final class UserInboxFetcher extends AsyncTask<Void, Void, InboxThreadMod
|
|||||||
@Override
|
@Override
|
||||||
protected InboxThreadModel doInBackground(final Void... voids) {
|
protected InboxThreadModel doInBackground(final Void... voids) {
|
||||||
InboxThreadModel result = null;
|
InboxThreadModel result = null;
|
||||||
final String url = "https://i.instagram.com/api/v1/direct_v2/threads/" + id + "/?visual_message_return_type=unseen"
|
final Map<String, String> queryParamsMap = new HashMap<>();
|
||||||
+ direction + endCursor;
|
queryParamsMap.put("visual_message_return_type", "unseen");
|
||||||
// todo probably
|
queryParamsMap.put("direction", direction.getValue());
|
||||||
// & seq_id = seqId
|
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 {
|
try {
|
||||||
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||||
conn.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
conn.setRequestProperty("User-Agent", Constants.I_USER_AGENT);
|
||||||
@ -60,9 +69,8 @@ public final class UserInboxFetcher extends AsyncTask<Void, Void, InboxThreadMod
|
|||||||
result = null;
|
result = null;
|
||||||
if (logCollector != null)
|
if (logCollector != null)
|
||||||
logCollector.appendException(e, LogFile.ASYNC_DMS_THREAD, "doInBackground");
|
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;
|
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.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
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.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
@ -25,24 +34,21 @@ import java.net.HttpURLConnection;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.activities.BaseLanguageActivity;
|
|
||||||
import awais.instagrabber.activities.PostViewer;
|
import awais.instagrabber.activities.PostViewer;
|
||||||
import awais.instagrabber.activities.ProfileViewer;
|
import awais.instagrabber.activities.ProfileViewer;
|
||||||
import awais.instagrabber.activities.StoryViewer;
|
import awais.instagrabber.activities.StoryViewer;
|
||||||
import awais.instagrabber.adapters.MessageItemsAdapter;
|
import awais.instagrabber.adapters.MessageItemsAdapter;
|
||||||
import awais.instagrabber.asyncs.ImageUploader;
|
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;
|
||||||
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.customviews.helpers.RecyclerLazyLoader;
|
||||||
import awais.instagrabber.databinding.ActivityDmsBinding;
|
import awais.instagrabber.databinding.FragmentDirectMessagesThreadBinding;
|
||||||
import awais.instagrabber.interfaces.FetchListener;
|
import awais.instagrabber.interfaces.FetchListener;
|
||||||
|
import awais.instagrabber.interfaces.MentionClickListener;
|
||||||
import awais.instagrabber.models.ImageUploadOptions;
|
import awais.instagrabber.models.ImageUploadOptions;
|
||||||
import awais.instagrabber.models.PostModel;
|
import awais.instagrabber.models.PostModel;
|
||||||
import awais.instagrabber.models.ProfileModel;
|
import awais.instagrabber.models.ProfileModel;
|
||||||
@ -55,72 +61,34 @@ import awais.instagrabber.models.enums.UserInboxDirection;
|
|||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
import static android.view.View.VISIBLE;
|
public class DirectMessageThreadFragment extends Fragment {
|
||||||
|
private static final String TAG = "DirectMessagesThreadFmt";
|
||||||
public final class DirectMessageThread extends BaseLanguageActivity {
|
|
||||||
private static final String TAG = "DirectMessageThread";
|
|
||||||
private static final int PICK_IMAGE = 100;
|
private static final int PICK_IMAGE = 100;
|
||||||
|
|
||||||
private DirectItemModel directItemModel;
|
private FragmentActivity fragmentActivity;
|
||||||
private String threadId;
|
private String threadId;
|
||||||
private String endCursor;
|
private String cursor;
|
||||||
private ActivityDmsBinding dmsBinding;
|
private FragmentDirectMessagesThreadBinding binding;
|
||||||
private MessageItemsAdapter messageItemsAdapter;
|
private DirectItemModelListViewModel listViewModel;
|
||||||
|
private RecyclerView messageList;
|
||||||
|
private boolean hasSentSomething;
|
||||||
|
private boolean hasOlder = true;
|
||||||
|
|
||||||
private final ProfileModel myProfileHolder = ProfileModel.getDefaultProfileModel();
|
private final ProfileModel myProfileHolder = ProfileModel.getDefaultProfileModel();
|
||||||
private final ArrayList<ProfileModel> users = new ArrayList<>();
|
private final List<ProfileModel> users = new ArrayList<>();
|
||||||
private final ArrayList<ProfileModel> leftUsers = new ArrayList<>();
|
private final List<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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@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 -> {
|
private final View.OnClickListener clickListener = v -> {
|
||||||
if (v == dmsBinding.commentSend) {
|
if (v == binding.commentSend) {
|
||||||
final String text = dmsBinding.commentText.getText().toString();
|
final String text = binding.commentText.getText().toString();
|
||||||
if (Utils.isEmpty(text)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
sendText(text);
|
sendText(text);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (v == dmsBinding.image) {
|
if (v == binding.image) {
|
||||||
final Intent intent = new Intent();
|
final Intent intent = new Intent();
|
||||||
intent.setType("image/*");
|
intent.setType("image/*");
|
||||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||||
@ -128,45 +96,95 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
private final FetchListener<InboxThreadModel> fetchListener = new FetchListener<InboxThreadModel>() {
|
||||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
@Override
|
||||||
super.onCreate(savedInstanceState);
|
public void doBefore() {
|
||||||
dmsBinding = ActivityDmsBinding.inflate(getLayoutInflater());
|
binding.swipeRefreshLayout.setRefreshing(true);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dmsBinding.swipeRefreshLayout.setEnabled(false);
|
@Override
|
||||||
dmsBinding.commentText.setVisibility(VISIBLE);
|
public void onResult(final InboxThreadModel result) {
|
||||||
dmsBinding.commentSend.setVisibility(VISIBLE);
|
if (result == null && ("MINCURSOR".equals(cursor) || "MAXCURSOR".equals(cursor) || Utils.isEmpty(cursor)))
|
||||||
dmsBinding.image.setVisibility(VISIBLE);
|
Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||||
dmsBinding.commentSend.setOnClickListener(clickListener);
|
|
||||||
dmsBinding.image.setOnClickListener(clickListener);
|
|
||||||
|
|
||||||
final LinearLayoutManager layoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, true);
|
if (result != null) {
|
||||||
dmsBinding.rvDirectMessages.setLayoutManager(layoutManager);
|
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) -> {
|
// thread title is already comma separated username, so no need to set by ourselves
|
||||||
if (!Utils.isEmpty(endCursor)) {
|
// String[] users = new String[result.getUsers().length];
|
||||||
new UserInboxFetcher(threadModel.getThreadId(), UserInboxDirection.OLDER,
|
// for (int i = 0; i < users.length; ++i) {
|
||||||
endCursor, fetchListener).execute(); // serial because we don't want messages to be randomly ordered
|
// 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();
|
Object tag = v.getTag();
|
||||||
if (tag instanceof DirectItemModel) {
|
if (tag instanceof DirectItemModel) {
|
||||||
directItemModel = (DirectItemModel) tag;
|
final DirectItemModel directItemModel = (DirectItemModel) tag;
|
||||||
final DirectItemType itemType = directItemModel.getItemType();
|
final DirectItemType itemType = directItemModel.getItemType();
|
||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
case MEDIA_SHARE:
|
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)));
|
.putExtra(Constants.EXTRAS_POST, new PostModel(directItemModel.getMediaModel().getCode(), false)));
|
||||||
break;
|
break;
|
||||||
case LINK:
|
case LINK:
|
||||||
@ -182,9 +200,7 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
|||||||
case RAVEN_MEDIA:
|
case RAVEN_MEDIA:
|
||||||
case MEDIA:
|
case MEDIA:
|
||||||
final ProfileModel user = getUser(directItemModel.getUserId());
|
final ProfileModel user = getUser(directItemModel.getUserId());
|
||||||
if (user != null) {
|
Utils.dmDownload(requireContext(), user.getUsername(), DownloadMethod.DOWNLOAD_DIRECT, Collections.singletonList(itemType == DirectItemType.MEDIA ? directItemModel.getMediaModel() : directItemModel.getRavenMediaModel().getMedia()));
|
||||||
Utils.dmDownload(this, 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();
|
Toast.makeText(v.getContext(), R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show();
|
||||||
break;
|
break;
|
||||||
case STORY_SHARE:
|
case STORY_SHARE:
|
||||||
@ -200,7 +216,7 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
|||||||
);
|
);
|
||||||
sm.setVideoUrl(directItemModel.getReelShare().getMedia().getVideoUrl());
|
sm.setVideoUrl(directItemModel.getReelShare().getMedia().getVideoUrl());
|
||||||
StoryModel[] sms = {sm};
|
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_USERNAME, directItemModel.getReelShare().getReelOwnerName())
|
||||||
.putExtra(Constants.EXTRAS_STORIES, sms)
|
.putExtra(Constants.EXTRAS_STORIES, sms)
|
||||||
);
|
);
|
||||||
@ -216,15 +232,18 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
|||||||
Log.d("austin_debug", "unsupported type " + itemType);
|
Log.d("austin_debug", "unsupported type " + itemType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, (view, text, isHashtag) -> searchUsername(text));
|
};
|
||||||
|
final MentionClickListener mentionClickListener = (view, text, isHashtag) -> searchUsername(text);
|
||||||
dmsBinding.rvDirectMessages.setAdapter(messageItemsAdapter);
|
final MessageItemsAdapter adapter = new MessageItemsAdapter(users, leftUsers, onClickListener, mentionClickListener);
|
||||||
|
messageList.setAdapter(adapter);
|
||||||
new UserInboxFetcher(threadModel.getThreadId(), UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
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
|
@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);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK) {
|
if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK) {
|
||||||
if (data == null || data.getData() == null) {
|
if (data == null || data.getData() == null) {
|
||||||
@ -236,61 +255,46 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Override
|
||||||
private ProfileModel getUser(final long userId) {
|
public void onDestroy() {
|
||||||
if (users != null) {
|
super.onDestroy();
|
||||||
ProfileModel result = myProfileHolder;
|
listViewModel.getList().postValue(Collections.emptyList());
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendText(final String text) {
|
private void sendText(final String text) {
|
||||||
final TextBroadcastOptions options;
|
final DirectThreadBroadcaster.TextBroadcastOptions options;
|
||||||
try {
|
try {
|
||||||
options = new TextBroadcastOptions(text);
|
options = new DirectThreadBroadcaster.TextBroadcastOptions(text);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
Log.e(TAG, "Error", e);
|
Log.e(TAG, "Error", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
broadcast(options, result -> {
|
broadcast(options, result -> {
|
||||||
if (result == null || result.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
dmsBinding.commentText.setText("");
|
binding.commentText.setText("");
|
||||||
dmsBinding.commentText.clearFocus();
|
// binding.commentText.clearFocus();
|
||||||
directItemModels.clear();
|
hasSentSomething = true;
|
||||||
messageItemsAdapter.notifyDataSetChanged();
|
new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
new UserInboxFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendImage(final Uri imageUri) {
|
private void sendImage(final Uri imageUri) {
|
||||||
try {
|
try {
|
||||||
final ParcelFileDescriptor fileDescriptor = getContentResolver().openFileDescriptor(imageUri, "r");
|
final ParcelFileDescriptor fileDescriptor = requireContext().getContentResolver().openFileDescriptor(imageUri, "r");
|
||||||
if (fileDescriptor == null) {
|
if (fileDescriptor == null) {
|
||||||
Log.e(TAG, "fileDescriptor is null!");
|
Log.e(TAG, "fileDescriptor is null!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final long contentLength = fileDescriptor.getStatSize();
|
final long contentLength = fileDescriptor.getStatSize();
|
||||||
final InputStream inputStream = getContentResolver().openInputStream(imageUri);
|
final InputStream inputStream = requireContext().getContentResolver().openInputStream(imageUri);
|
||||||
// Upload Image
|
// Upload Image
|
||||||
final ImageUploader imageUploader = new ImageUploader();
|
final ImageUploader imageUploader = new ImageUploader();
|
||||||
imageUploader.setOnTaskCompleteListener(response -> {
|
imageUploader.setOnTaskCompleteListener(response -> {
|
||||||
if (response == null || response.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
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) {
|
if (response != null && response.getResponse() != null) {
|
||||||
Log.e(TAG, response.getResponse().toString());
|
Log.e(TAG, response.getResponse().toString());
|
||||||
}
|
}
|
||||||
@ -300,12 +304,9 @@ public final class DirectMessageThread extends BaseLanguageActivity {
|
|||||||
try {
|
try {
|
||||||
final String uploadId = responseJson.getString("upload_id");
|
final String uploadId = responseJson.getString("upload_id");
|
||||||
// Broadcast
|
// Broadcast
|
||||||
final ImageBroadcastOptions options = new ImageBroadcastOptions(true, uploadId);
|
final DirectThreadBroadcaster.ImageBroadcastOptions options = new DirectThreadBroadcaster.ImageBroadcastOptions(true, uploadId);
|
||||||
broadcast(options, onBroadcastCompleteListener -> {
|
hasSentSomething = true;
|
||||||
directItemModels.clear();
|
broadcast(options, onBroadcastCompleteListener -> new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR));
|
||||||
messageItemsAdapter.notifyDataSetChanged();
|
|
||||||
new UserInboxFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
});
|
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
Log.e(TAG, "Error parsing json response", 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);
|
final DirectThreadBroadcaster broadcaster = new DirectThreadBroadcaster(threadId);
|
||||||
broadcaster.setOnTaskCompleteListener(listener);
|
broadcaster.setOnTaskCompleteListener(listener);
|
||||||
broadcaster.execute(broadcastOptions);
|
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);
|
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() {
|
public boolean isPrivate() {
|
||||||
return isPrivate;
|
return isPrivate;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package awais.instagrabber.models.direct_messages;
|
package awais.instagrabber.models.direct_messages;
|
||||||
|
|
||||||
|
import androidx.core.util.ObjectsCompat;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import awais.instagrabber.models.ProfileModel;
|
import awais.instagrabber.models.ProfileModel;
|
||||||
@ -123,7 +125,7 @@ public final class InboxThreadModel implements Serializable {
|
|||||||
return canonical;
|
return canonical;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHasOlder() {
|
public boolean hasOlder() {
|
||||||
return hasOlder;
|
return hasOlder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,4 +144,18 @@ public final class InboxThreadModel implements Serializable {
|
|||||||
public long getLastActivityAt() {
|
public long getLastActivityAt() {
|
||||||
return lastActivityAt;
|
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;
|
package awais.instagrabber.models.enums;
|
||||||
|
|
||||||
public enum UserInboxDirection {
|
public enum UserInboxDirection {
|
||||||
OLDER,
|
OLDER("older"),
|
||||||
NEWER,
|
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.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
import org.jsoup.internal.StringUtil;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -58,6 +59,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
@ -1371,4 +1373,24 @@ public final class Utils {
|
|||||||
connection.setRequestProperty(header.getKey(), header.getValue());
|
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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical">
|
||||||
tools:context=".activities.directmessages.DirectMessages">
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
layout="@layout/layout_include_toolbar" />
|
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:id="@+id/swipeRefreshLayout"
|
android:id="@+id/swipeRefreshLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="8">
|
android:layout_weight="1">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rvDirectMessages"
|
android:id="@+id/messageList"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
@ -31,7 +25,7 @@
|
|||||||
android:id="@+id/commentText"
|
android:id="@+id/commentText"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="2"
|
android:layout_weight="1"
|
||||||
android:gravity="bottom"
|
android:gravity="bottom"
|
||||||
android:hint="@string/dm_hint"
|
android:hint="@string/dm_hint"
|
||||||
android:importantForAutofill="no"
|
android:importantForAutofill="no"
|
||||||
@ -42,8 +36,7 @@
|
|||||||
android:paddingLeft="8dp"
|
android:paddingLeft="8dp"
|
||||||
android:paddingEnd="4dp"
|
android:paddingEnd="4dp"
|
||||||
android:paddingRight="4dp"
|
android:paddingRight="4dp"
|
||||||
android:scrollHorizontally="false"
|
android:scrollHorizontally="false" />
|
||||||
android:visibility="visible" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
android:id="@+id/image"
|
android:id="@+id/image"
|
||||||
@ -54,7 +47,6 @@
|
|||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:padding="4dp"
|
android:padding="4dp"
|
||||||
android:visibility="visible"
|
|
||||||
app:srcCompat="@drawable/ic_image_24" />
|
app:srcCompat="@drawable/ic_image_24" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
@ -71,7 +63,6 @@
|
|||||||
android:paddingEnd="8dp"
|
android:paddingEnd="8dp"
|
||||||
android:paddingRight="8dp"
|
android:paddingRight="8dp"
|
||||||
android:paddingBottom="4dp"
|
android:paddingBottom="4dp"
|
||||||
android:visibility="visible"
|
|
||||||
app:srcCompat="@drawable/ic_send_24" />
|
app:srcCompat="@drawable/ic_send_24" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -4,8 +4,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal">
|
||||||
tools:viewBindingIgnore="true">
|
|
||||||
|
|
||||||
<awais.instagrabber.customviews.CircularImageView
|
<awais.instagrabber.customviews.CircularImageView
|
||||||
android:id="@+id/ivProfilePic"
|
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_like_comment">Like comment</string>
|
||||||
<string name="comment_viewer_unlike_comment">Unlike comment</string>
|
<string name="comment_viewer_unlike_comment">Unlike comment</string>
|
||||||
<string name="comment_viewer_delete_comment">Delete 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_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_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>
|
<string name="comment_view_mention_location_search">Do you want to search the location?</string>
|
||||||
|
@ -6,6 +6,9 @@ buildscript {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.0.1'
|
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