Detailed changes
@@ -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<Thread> recentThreads() {
+ final ArrayList<Thread> 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();
+ }
}
}
@@ -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<Conversation.Thread> 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<ListItem.Tag> 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<Conversation.Thread> {
+ 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();
+ }
+ }
}
@@ -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<Uri> uris = extractUris(extras);
if (uris != null && uris.size() > 0) {
if (uris.size() == 1 && "geo".equals(uris.get(0).getScheme())) {
@@ -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";
@@ -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) {
@@ -420,6 +420,25 @@
android:textAppearance="@style/TextAppearance.Conversations.Caption"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/recent_threads_wrapper"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/activity_vertical_margin"
+ android:layout_marginLeft="@dimen/activity_horizontal_margin"
+ android:layout_marginRight="@dimen/activity_horizontal_margin"
+ android:layout_marginTop="@dimen/activity_vertical_margin">
+
+ <ListView
+ android:id="@+id/recent_threads"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:divider="@android:color/transparent"
+ android:dividerHeight="0dp"></ListView>
+
+ </androidx.cardview.widget.CardView>
+
<androidx.cardview.widget.CardView
android:id="@+id/media_wrapper"
android:layout_width="fill_parent"