diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 1e8f7cef318b77f4736918ce0fde96e97024f4f1..0699cc658a42fae756b4611bbe9d72ecec4569a3 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -659,7 +659,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl if (mthread != null) { Thread thread = threads.get(mthread.getContent()); if (thread == null) { - thread = new Thread(); + thread = new Thread(mthread.getContent()); threads.put(mthread.getContent(), thread); } if (thread.subject == null && (m.getSubject() != null && (m.getRawBody() == null || m.getRawBody().length() == 0))) { @@ -684,6 +684,13 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl return threads.get(id); } + public List recentThreads() { + final ArrayList recent = new ArrayList<>(); + recent.addAll(threads.values()); + recent.sort((a, b) -> b.getLastTime() == a.getLastTime() ? 0 : (b.getLastTime() > a.getLastTime() ? 1 : -1)); + return recent.size() < 5 ? recent : recent.subList(0, 5); + } + @Override public boolean isBlocked() { return getContact().isBlocked(); @@ -3312,13 +3319,37 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl protected Message subject = null; protected Message first = null; protected Message last = null; + protected final String threadId; - protected Thread() {} + protected Thread(final String threadId) { + this.threadId = threadId; + } + + public String getThreadId() { + return threadId; + } public String getSubject() { if (subject == null) return null; return subject.getSubject(); } + + public String getDisplay() { + final String s = getSubject(); + if (s != null) return s; + + if (first != null) { + return first.getBody(); + } + + return ""; + } + + public long getLastTime() { + if (last == null) return 0; + + return last.getTimeSent(); + } } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index 1af16819d8305694a9ac6cbe42f3610a93827aff..0ac3bf69f7efb664944eb7be76ae8da542016400 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -18,13 +18,17 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; +import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.databinding.DataBindingUtil; +import com.cheogram.android.Util; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -36,6 +40,7 @@ import java.util.stream.Collectors; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.databinding.ActivityMucDetailsBinding; +import eu.siacs.conversations.databinding.ThreadRowBinding; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Bookmark; import eu.siacs.conversations.entities.Contact; @@ -61,6 +66,7 @@ import eu.siacs.conversations.utils.AccountUtils; import eu.siacs.conversations.utils.Compatibility; import eu.siacs.conversations.utils.StringUtils; import eu.siacs.conversations.utils.StylingHelper; +import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.XmppConnection; @@ -227,6 +233,10 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers this.binding.users.setAdapter(mUserPreviewAdapter); GridManager.setupLayoutManager(this, this.binding.media, R.dimen.media_size); GridManager.setupLayoutManager(this, this.binding.users, R.dimen.media_size); + this.binding.recentThreads.setOnItemClickListener((a0, v, pos, a3) -> { + final Conversation.Thread thread = (Conversation.Thread) binding.recentThreads.getAdapter().getItem(pos); + switchToConversation(mConversation, null, false, null, false, true, null, thread.getThreadId()); + }); this.binding.invite.setOnClickListener(v -> inviteToConversation(mConversation)); this.binding.showUsers.setOnClickListener(v -> { Intent intent = new Intent(this, MucUsersActivity.class); @@ -650,6 +660,17 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers return; } + final List recentThreads = mConversation.recentThreads(); + if (recentThreads.isEmpty()) { + this.binding.recentThreadsWrapper.setVisibility(View.GONE); + } else { + final ThreadAdapter threads = new ThreadAdapter(); + threads.addAll(recentThreads); + this.binding.recentThreads.setAdapter(threads); + this.binding.recentThreadsWrapper.setVisibility(View.VISIBLE); + Util.justifyListViewHeightBasedOnChildren(binding.recentThreads); + } + List tagList = bookmark.getTags(this); if (tagList.size() == 0 || !showDynamicTags) { binding.tags.setVisibility(View.GONE); @@ -746,4 +767,20 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } } + class ThreadAdapter extends ArrayAdapter { + ThreadAdapter() { super(ConferenceDetailsActivity.this, 0); } + + @Override + public View getView(int position, View view, @NonNull ViewGroup parent) { + final ThreadRowBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.thread_row, parent, false); + final Conversation.Thread item = getItem(position); + + binding.threadIdenticon.setColor(UIHelper.getColorForName(item.getThreadId())); + binding.threadIdenticon.setHash(UIHelper.identiconHash(item.getThreadId())); + + binding.threadSubject.setText(item.getDisplay()); + + return binding.getRoot(); + } + } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index a19058c5dba5a2c596a33b519d086cbaea266532..1885cd42a0c79dec9b5b8c287a2da24b1952e368 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -3240,6 +3240,15 @@ public class ConversationFragment extends XmppFragment final boolean doNotAppend = extras.getBoolean(ConversationsActivity.EXTRA_DO_NOT_APPEND, false); final String type = extras.getString(ConversationsActivity.EXTRA_TYPE); + + final String thread = extras.getString(ConversationsActivity.EXTRA_THREAD); + if (thread != null) { + conversation.setLockThread(true); + backPressedLeaveSingleThread.setEnabled(true); + setThread(new Element("thread").setContent(thread)); + refresh(); + } + final List uris = extractUris(extras); if (uris != null && uris.size() > 0) { if (uris.size() == 1 && "geo".equals(uris.get(0).getScheme())) { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java index efe1f06da23446fe1cde63626ba43e6c6dca419e..a33895906b8b8fb8ea69709142d4707fa1bccae3 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java @@ -116,6 +116,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio public static final String EXTRA_DO_NOT_APPEND = "do_not_append"; public static final String EXTRA_POST_INIT_ACTION = "post_init_action"; public static final String POST_ACTION_RECORD_VOICE = "record_voice"; + public static final String EXTRA_THREAD = "threadId"; public static final String EXTRA_TYPE = "type"; public static final String EXTRA_NODE = "node"; public static final String EXTRA_JID = "jid"; diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 3234b0058ea1f8a1b1bd7af9e09fa4726501458f..2ca05f819f13b82d168f0322148b13c8c008bb24 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -593,11 +593,16 @@ public abstract class XmppActivity extends ActionBarActivity { } public void switchToConversation(Conversation conversation, String text, boolean asQuote, String nick, boolean pm, boolean doNotAppend, String postInit) { + switchToConversation(conversation, text, asQuote, nick, pm, doNotAppend, postInit, null); + } + + public void switchToConversation(Conversation conversation, String text, boolean asQuote, String nick, boolean pm, boolean doNotAppend, String postInit, String thread) { if (conversation == null) return; Intent intent = new Intent(this, ConversationsActivity.class); intent.setAction(ConversationsActivity.ACTION_VIEW_CONVERSATION); intent.putExtra(ConversationsActivity.EXTRA_CONVERSATION, conversation.getUuid()); + intent.putExtra(ConversationsActivity.EXTRA_THREAD, thread); if (text != null) { intent.putExtra(Intent.EXTRA_TEXT, text); if (asQuote) { diff --git a/src/main/res/layout/activity_muc_details.xml b/src/main/res/layout/activity_muc_details.xml index e9febe0d360eefdefadc3387f086a4e85e0a0907..e61632f74b98052ef97445ab29b278a4e60c5272 100644 --- a/src/main/res/layout/activity_muc_details.xml +++ b/src/main/res/layout/activity_muc_details.xml @@ -420,6 +420,25 @@ android:textAppearance="@style/TextAppearance.Conversations.Caption"/> + + + + + + +