mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 13:19:52 +01:00
Show timer change notices in private conversations
This commit is contained in:
@@ -13,6 +13,8 @@ import org.briarproject.briar.R;
|
|||||||
import org.briarproject.briar.android.util.BriarAdapter;
|
import org.briarproject.briar.android.util.BriarAdapter;
|
||||||
import org.briarproject.briar.android.util.ItemReturningAdapter;
|
import org.briarproject.briar.android.util.ItemReturningAdapter;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import androidx.annotation.LayoutRes;
|
import androidx.annotation.LayoutRes;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.recyclerview.selection.SelectionTracker;
|
import androidx.recyclerview.selection.SelectionTracker;
|
||||||
@@ -20,13 +22,14 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
|||||||
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool;
|
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool;
|
||||||
|
|
||||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||||
|
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class ConversationAdapter
|
class ConversationAdapter
|
||||||
extends BriarAdapter<ConversationItem, ConversationItemViewHolder>
|
extends BriarAdapter<ConversationItem, ConversationItemViewHolder>
|
||||||
implements ItemReturningAdapter<ConversationItem> {
|
implements ItemReturningAdapter<ConversationItem> {
|
||||||
|
|
||||||
private ConversationListener listener;
|
private final ConversationListener listener;
|
||||||
private final RecycledViewPool imageViewPool;
|
private final RecycledViewPool imageViewPool;
|
||||||
private final ImageItemDecoration imageItemDecoration;
|
private final ImageItemDecoration imageItemDecoration;
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -65,22 +68,20 @@ class ConversationAdapter
|
|||||||
@LayoutRes int type) {
|
@LayoutRes int type) {
|
||||||
View v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
View v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
||||||
type, viewGroup, false);
|
type, viewGroup, false);
|
||||||
switch (type) {
|
if (type == R.layout.list_item_conversation_msg_in) {
|
||||||
case R.layout.list_item_conversation_msg_in:
|
return new ConversationMessageViewHolder(v, listener, true,
|
||||||
return new ConversationMessageViewHolder(v, listener, true,
|
imageViewPool, imageItemDecoration);
|
||||||
imageViewPool, imageItemDecoration);
|
} else if (type == R.layout.list_item_conversation_msg_out) {
|
||||||
case R.layout.list_item_conversation_msg_out:
|
return new ConversationMessageViewHolder(v, listener, false,
|
||||||
return new ConversationMessageViewHolder(v, listener, false,
|
imageViewPool, imageItemDecoration);
|
||||||
imageViewPool, imageItemDecoration);
|
} else if (type == R.layout.list_item_conversation_notice_in) {
|
||||||
case R.layout.list_item_conversation_notice_in:
|
return new ConversationNoticeViewHolder(v, listener, true);
|
||||||
return new ConversationNoticeViewHolder(v, listener, true);
|
} else if (type == R.layout.list_item_conversation_notice_out) {
|
||||||
case R.layout.list_item_conversation_notice_out:
|
return new ConversationNoticeViewHolder(v, listener, false);
|
||||||
return new ConversationNoticeViewHolder(v, listener, false);
|
} else if (type == R.layout.list_item_conversation_request) {
|
||||||
case R.layout.list_item_conversation_request:
|
return new ConversationRequestViewHolder(v, listener, true);
|
||||||
return new ConversationRequestViewHolder(v, listener, true);
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unknown ConversationItem");
|
|
||||||
}
|
}
|
||||||
|
throw new IllegalArgumentException("Unknown ConversationItem");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -107,22 +108,53 @@ class ConversationAdapter
|
|||||||
return c1.equals(c2);
|
return c1.equals(c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(ConversationItem item) {
|
||||||
|
items.beginBatchedUpdates();
|
||||||
|
items.add(item);
|
||||||
|
updateTimersInBatch(true);
|
||||||
|
items.endBatchedUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAll(Collection<ConversationItem> itemsToAdd) {
|
||||||
|
items.beginBatchedUpdates();
|
||||||
|
items.addAll(itemsToAdd);
|
||||||
|
updateTimersInBatch(false);
|
||||||
|
items.endBatchedUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTimersInBatch(boolean updateItems) {
|
||||||
|
long lastTimerIncoming = NO_AUTO_DELETE_TIMER;
|
||||||
|
long lastTimerOutgoing = NO_AUTO_DELETE_TIMER;
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
ConversationItem c = items.get(i);
|
||||||
|
boolean itemChanged;
|
||||||
|
boolean timerChanged;
|
||||||
|
boolean timerMirrored;
|
||||||
|
if (c.isIncoming()) {
|
||||||
|
timerChanged = lastTimerIncoming != c.getAutoDeleteTimer();
|
||||||
|
timerMirrored = timerChanged &&
|
||||||
|
lastTimerOutgoing == c.getAutoDeleteTimer();
|
||||||
|
lastTimerIncoming = c.getAutoDeleteTimer();
|
||||||
|
} else {
|
||||||
|
timerChanged = lastTimerOutgoing != c.getAutoDeleteTimer();
|
||||||
|
timerMirrored = timerChanged &&
|
||||||
|
lastTimerIncoming == c.getAutoDeleteTimer();
|
||||||
|
lastTimerOutgoing = c.getAutoDeleteTimer();
|
||||||
|
}
|
||||||
|
itemChanged = c.setTimerNoticeVisible(timerChanged);
|
||||||
|
itemChanged |= c.setTimerMirrored(timerMirrored);
|
||||||
|
if (itemChanged && updateItems) items.updateItemAt(i, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void setSelectionTracker(SelectionTracker<String> tracker) {
|
void setSelectionTracker(SelectionTracker<String> tracker) {
|
||||||
this.tracker = tracker;
|
this.tracker = tracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
ConversationItem getLastItem() {
|
|
||||||
if (items.size() > 0) {
|
|
||||||
return items.get(items.size() - 1);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SparseArray<ConversationItem> getOutgoingMessages() {
|
SparseArray<ConversationItem> getOutgoingMessages() {
|
||||||
SparseArray<ConversationItem> messages = new SparseArray<>();
|
SparseArray<ConversationItem> messages = new SparseArray<>();
|
||||||
|
|
||||||
for (int i = 0; i < items.size(); i++) {
|
for (int i = 0; i < items.size(); i++) {
|
||||||
ConversationItem item = items.get(i);
|
ConversationItem item = items.get(i);
|
||||||
if (!item.isIncoming()) {
|
if (!item.isIncoming()) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import javax.annotation.Nullable;
|
|||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
import androidx.annotation.LayoutRes;
|
import androidx.annotation.LayoutRes;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
|
||||||
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
||||||
|
|
||||||
@@ -24,9 +25,11 @@ abstract class ConversationItem {
|
|||||||
private final GroupId groupId;
|
private final GroupId groupId;
|
||||||
private final long time, autoDeleteTimer;
|
private final long time, autoDeleteTimer;
|
||||||
private final boolean isIncoming;
|
private final boolean isIncoming;
|
||||||
private boolean read, sent, seen;
|
private final LiveData<String> contactName;
|
||||||
|
private boolean read, sent, seen, showTimerNotice, timerMirrored;
|
||||||
|
|
||||||
ConversationItem(@LayoutRes int layoutRes, ConversationMessageHeader h) {
|
ConversationItem(@LayoutRes int layoutRes, ConversationMessageHeader h,
|
||||||
|
LiveData<String> contactName) {
|
||||||
this.layoutRes = layoutRes;
|
this.layoutRes = layoutRes;
|
||||||
this.text = null;
|
this.text = null;
|
||||||
this.id = h.getId();
|
this.id = h.getId();
|
||||||
@@ -37,6 +40,9 @@ abstract class ConversationItem {
|
|||||||
this.sent = h.isSent();
|
this.sent = h.isSent();
|
||||||
this.seen = h.isSeen();
|
this.seen = h.isSeen();
|
||||||
this.isIncoming = !h.isLocal();
|
this.isIncoming = !h.isLocal();
|
||||||
|
this.contactName = contactName;
|
||||||
|
this.showTimerNotice = false;
|
||||||
|
this.timerMirrored = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@LayoutRes
|
@LayoutRes
|
||||||
@@ -116,4 +122,44 @@ abstract class ConversationItem {
|
|||||||
return isIncoming;
|
return isIncoming;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<String> getContactName() {
|
||||||
|
return contactName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this to true when {@link #getAutoDeleteTimer()} has changed
|
||||||
|
* since the last message from the same peer.
|
||||||
|
*
|
||||||
|
* @return true if the value was set, false if it was already set.
|
||||||
|
*/
|
||||||
|
boolean setTimerNoticeVisible(boolean visible) {
|
||||||
|
if (this.showTimerNotice != visible) {
|
||||||
|
this.showTimerNotice = visible;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isTimerNoticeVisible() {
|
||||||
|
return showTimerNotice;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this to true when {@link #getAutoDeleteTimer()} has changed
|
||||||
|
* to the same timer of the last message
|
||||||
|
* from the other peer in this conversation.
|
||||||
|
*
|
||||||
|
* @return true if the value was set, false if it was already set.
|
||||||
|
*/
|
||||||
|
public boolean setTimerMirrored(boolean timerMirrored) {
|
||||||
|
if (this.timerMirrored != timerMirrored) {
|
||||||
|
this.timerMirrored = timerMirrored;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean wasTimerMirrored() {
|
||||||
|
return timerMirrored;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.briar.android.conversation;
|
package org.briarproject.briar.android.conversation;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ abstract class ConversationItemViewHolder extends ViewHolder {
|
|||||||
protected final ConstraintLayout layout;
|
protected final ConstraintLayout layout;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final OutItemViewHolder outViewHolder;
|
private final OutItemViewHolder outViewHolder;
|
||||||
private final TextView text;
|
private final TextView topNotice, text;
|
||||||
protected final TextView time;
|
protected final TextView time;
|
||||||
private final View bomb;
|
private final View bomb;
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -39,6 +40,7 @@ abstract class ConversationItemViewHolder extends ViewHolder {
|
|||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.outViewHolder = isIncoming ? null : new OutItemViewHolder(v);
|
this.outViewHolder = isIncoming ? null : new OutItemViewHolder(v);
|
||||||
root = v;
|
root = v;
|
||||||
|
topNotice = v.findViewById(R.id.topNotice);
|
||||||
layout = v.findViewById(R.id.layout);
|
layout = v.findViewById(R.id.layout);
|
||||||
text = v.findViewById(R.id.text);
|
text = v.findViewById(R.id.text);
|
||||||
time = v.findViewById(R.id.time);
|
time = v.findViewById(R.id.time);
|
||||||
@@ -50,6 +52,8 @@ abstract class ConversationItemViewHolder extends ViewHolder {
|
|||||||
itemKey = item.getKey();
|
itemKey = item.getKey();
|
||||||
root.setActivated(selected);
|
root.setActivated(selected);
|
||||||
|
|
||||||
|
setTopNotice(item);
|
||||||
|
|
||||||
if (item.getText() != null) {
|
if (item.getText() != null) {
|
||||||
text.setText(trim(item.getText()));
|
text.setText(trim(item.getText()));
|
||||||
}
|
}
|
||||||
@@ -72,4 +76,42 @@ abstract class ConversationItemViewHolder extends ViewHolder {
|
|||||||
return itemKey;
|
return itemKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setTopNotice(ConversationItem item) {
|
||||||
|
if (item.isTimerNoticeVisible()) {
|
||||||
|
Context ctx = itemView.getContext();
|
||||||
|
topNotice.setVisibility(VISIBLE);
|
||||||
|
boolean enabled = item.getAutoDeleteTimer() != NO_AUTO_DELETE_TIMER;
|
||||||
|
String text;
|
||||||
|
if (item.isIncoming()) {
|
||||||
|
String name = item.getContactName().getValue();
|
||||||
|
if (item.wasTimerMirrored()) {
|
||||||
|
int strRes = enabled ?
|
||||||
|
R.string.auto_delete_msg_contact_enabled_mirrored :
|
||||||
|
R.string.auto_delete_msg_contact_disabled_mirrored;
|
||||||
|
text = ctx.getString(strRes, name);
|
||||||
|
} else {
|
||||||
|
int strRes = enabled ?
|
||||||
|
R.string.auto_delete_msg_contact_enabled :
|
||||||
|
R.string.auto_delete_msg_contact_disabled;
|
||||||
|
text = ctx.getString(strRes, name, name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int strRes;
|
||||||
|
if (item.wasTimerMirrored()) {
|
||||||
|
strRes = enabled ?
|
||||||
|
R.string.auto_delete_msg_you_enabled_mirrored :
|
||||||
|
R.string.auto_delete_msg_you_disabled_mirrored;
|
||||||
|
} else {
|
||||||
|
strRes = enabled ?
|
||||||
|
R.string.auto_delete_msg_you_enabled :
|
||||||
|
R.string.auto_delete_msg_you_disabled;
|
||||||
|
}
|
||||||
|
text = ctx.getString(strRes);
|
||||||
|
}
|
||||||
|
topNotice.setText(text);
|
||||||
|
} else {
|
||||||
|
topNotice.setVisibility(GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import javax.annotation.concurrent.NotThreadSafe;
|
|||||||
|
|
||||||
import androidx.annotation.LayoutRes;
|
import androidx.annotation.LayoutRes;
|
||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -18,8 +19,8 @@ class ConversationMessageItem extends ConversationItem {
|
|||||||
private final List<AttachmentItem> attachments;
|
private final List<AttachmentItem> attachments;
|
||||||
|
|
||||||
ConversationMessageItem(@LayoutRes int layoutRes, PrivateMessageHeader h,
|
ConversationMessageItem(@LayoutRes int layoutRes, PrivateMessageHeader h,
|
||||||
List<AttachmentItem> attachments) {
|
LiveData<String> contactName, List<AttachmentItem> attachments) {
|
||||||
super(layoutRes, h);
|
super(layoutRes, h, contactName);
|
||||||
this.attachments = attachments;
|
this.attachments = attachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import javax.annotation.Nullable;
|
|||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
import androidx.annotation.LayoutRes;
|
import androidx.annotation.LayoutRes;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -17,15 +18,15 @@ class ConversationNoticeItem extends ConversationItem {
|
|||||||
private final String msgText;
|
private final String msgText;
|
||||||
|
|
||||||
ConversationNoticeItem(@LayoutRes int layoutRes, String text,
|
ConversationNoticeItem(@LayoutRes int layoutRes, String text,
|
||||||
ConversationRequest r) {
|
LiveData<String> contactName, ConversationRequest<?> r) {
|
||||||
super(layoutRes, r);
|
super(layoutRes, r, contactName);
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.msgText = r.getText();
|
this.msgText = r.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConversationNoticeItem(@LayoutRes int layoutRes, String text,
|
ConversationNoticeItem(@LayoutRes int layoutRes, String text,
|
||||||
ConversationResponse r) {
|
LiveData<String> contactName, ConversationResponse r) {
|
||||||
super(layoutRes, r);
|
super(layoutRes, r, contactName);
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.msgText = null;
|
this.msgText = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import javax.annotation.Nullable;
|
|||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
import androidx.annotation.LayoutRes;
|
import androidx.annotation.LayoutRes;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -26,14 +27,15 @@ class ConversationRequestItem extends ConversationNoticeItem {
|
|||||||
private boolean answered;
|
private boolean answered;
|
||||||
|
|
||||||
ConversationRequestItem(@LayoutRes int layoutRes, String text,
|
ConversationRequestItem(@LayoutRes int layoutRes, String text,
|
||||||
RequestType type, ConversationRequest r) {
|
LiveData<String> contactName, RequestType type,
|
||||||
super(layoutRes, text, r);
|
ConversationRequest<?> r) {
|
||||||
|
super(layoutRes, text, contactName, r);
|
||||||
this.requestType = type;
|
this.requestType = type;
|
||||||
this.sessionId = r.getSessionId();
|
this.sessionId = r.getSessionId();
|
||||||
this.answered = r.wasAnswered();
|
this.answered = r.wasAnswered();
|
||||||
if (r instanceof InvitationRequest) {
|
if (r instanceof InvitationRequest) {
|
||||||
this.requestedGroupId = ((Shareable) r.getNameable()).getId();
|
this.requestedGroupId = ((Shareable) r.getNameable()).getId();
|
||||||
this.canBeOpened = ((InvitationRequest) r).canBeOpened();
|
this.canBeOpened = ((InvitationRequest<?>) r).canBeOpened();
|
||||||
} else {
|
} else {
|
||||||
this.requestedGroupId = null;
|
this.requestedGroupId = null;
|
||||||
this.canBeOpened = false;
|
this.canBeOpened = false;
|
||||||
|
|||||||
@@ -60,10 +60,12 @@ class ConversationVisitor implements
|
|||||||
}
|
}
|
||||||
if (h.isLocal()) {
|
if (h.isLocal()) {
|
||||||
item = new ConversationMessageItem(
|
item = new ConversationMessageItem(
|
||||||
R.layout.list_item_conversation_msg_out, h, attachments);
|
R.layout.list_item_conversation_msg_out, h, contactName,
|
||||||
|
attachments);
|
||||||
} else {
|
} else {
|
||||||
item = new ConversationMessageItem(
|
item = new ConversationMessageItem(
|
||||||
R.layout.list_item_conversation_msg_in, h, attachments);
|
R.layout.list_item_conversation_msg_in, h, contactName,
|
||||||
|
attachments);
|
||||||
}
|
}
|
||||||
if (h.hasText()) {
|
if (h.hasText()) {
|
||||||
String text = textCache.getText(h.getId());
|
String text = textCache.getText(h.getId());
|
||||||
@@ -79,13 +81,15 @@ class ConversationVisitor implements
|
|||||||
String text = ctx.getString(R.string.blogs_sharing_invitation_sent,
|
String text = ctx.getString(R.string.blogs_sharing_invitation_sent,
|
||||||
r.getName(), contactName.getValue());
|
r.getName(), contactName.getValue());
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_out, text, r);
|
R.layout.list_item_conversation_notice_out, text,
|
||||||
|
contactName, r);
|
||||||
} else {
|
} else {
|
||||||
String text = ctx.getString(
|
String text = ctx.getString(
|
||||||
R.string.blogs_sharing_invitation_received,
|
R.string.blogs_sharing_invitation_received,
|
||||||
contactName.getValue(), r.getName());
|
contactName.getValue(), r.getName());
|
||||||
return new ConversationRequestItem(
|
return new ConversationRequestItem(
|
||||||
R.layout.list_item_conversation_request, text, BLOG, r);
|
R.layout.list_item_conversation_request, text, contactName,
|
||||||
|
BLOG, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +108,8 @@ class ConversationVisitor implements
|
|||||||
contactName.getValue());
|
contactName.getValue());
|
||||||
}
|
}
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_out, text, r);
|
R.layout.list_item_conversation_notice_out, text,
|
||||||
|
contactName, r);
|
||||||
} else {
|
} else {
|
||||||
String text;
|
String text;
|
||||||
if (r.wasAccepted()) {
|
if (r.wasAccepted()) {
|
||||||
@@ -117,7 +122,8 @@ class ConversationVisitor implements
|
|||||||
contactName.getValue());
|
contactName.getValue());
|
||||||
}
|
}
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_in, text, r);
|
R.layout.list_item_conversation_notice_in, text,
|
||||||
|
contactName, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,13 +134,15 @@ class ConversationVisitor implements
|
|||||||
String text = ctx.getString(R.string.forum_invitation_sent,
|
String text = ctx.getString(R.string.forum_invitation_sent,
|
||||||
r.getName(), contactName.getValue());
|
r.getName(), contactName.getValue());
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_out, text, r);
|
R.layout.list_item_conversation_notice_out, text,
|
||||||
|
contactName, r);
|
||||||
} else {
|
} else {
|
||||||
String text = ctx.getString(
|
String text = ctx.getString(
|
||||||
R.string.forum_invitation_received,
|
R.string.forum_invitation_received,
|
||||||
contactName.getValue(), r.getName());
|
contactName.getValue(), r.getName());
|
||||||
return new ConversationRequestItem(
|
return new ConversationRequestItem(
|
||||||
R.layout.list_item_conversation_request, text, FORUM, r);
|
R.layout.list_item_conversation_request, text, contactName,
|
||||||
|
FORUM, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +161,8 @@ class ConversationVisitor implements
|
|||||||
contactName.getValue());
|
contactName.getValue());
|
||||||
}
|
}
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_out, text, r);
|
R.layout.list_item_conversation_notice_out, text,
|
||||||
|
contactName, r);
|
||||||
} else {
|
} else {
|
||||||
String text;
|
String text;
|
||||||
if (r.wasAccepted()) {
|
if (r.wasAccepted()) {
|
||||||
@@ -166,7 +175,8 @@ class ConversationVisitor implements
|
|||||||
contactName.getValue());
|
contactName.getValue());
|
||||||
}
|
}
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_in, text, r);
|
R.layout.list_item_conversation_notice_in, text,
|
||||||
|
contactName, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,13 +188,15 @@ class ConversationVisitor implements
|
|||||||
R.string.groups_invitations_invitation_sent,
|
R.string.groups_invitations_invitation_sent,
|
||||||
contactName.getValue(), r.getName());
|
contactName.getValue(), r.getName());
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_out, text, r);
|
R.layout.list_item_conversation_notice_out, text,
|
||||||
|
contactName, r);
|
||||||
} else {
|
} else {
|
||||||
String text = ctx.getString(
|
String text = ctx.getString(
|
||||||
R.string.groups_invitations_invitation_received,
|
R.string.groups_invitations_invitation_received,
|
||||||
contactName.getValue(), r.getName());
|
contactName.getValue(), r.getName());
|
||||||
return new ConversationRequestItem(
|
return new ConversationRequestItem(
|
||||||
R.layout.list_item_conversation_request, text, GROUP, r);
|
R.layout.list_item_conversation_request, text, contactName,
|
||||||
|
GROUP, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +215,8 @@ class ConversationVisitor implements
|
|||||||
contactName.getValue());
|
contactName.getValue());
|
||||||
}
|
}
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_out, text, r);
|
R.layout.list_item_conversation_notice_out, text,
|
||||||
|
contactName, r);
|
||||||
} else {
|
} else {
|
||||||
String text;
|
String text;
|
||||||
if (r.wasAccepted()) {
|
if (r.wasAccepted()) {
|
||||||
@@ -216,7 +229,8 @@ class ConversationVisitor implements
|
|||||||
contactName.getValue());
|
contactName.getValue());
|
||||||
}
|
}
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_in, text, r);
|
R.layout.list_item_conversation_notice_in, text,
|
||||||
|
contactName, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +241,8 @@ class ConversationVisitor implements
|
|||||||
String text = ctx.getString(R.string.introduction_request_sent,
|
String text = ctx.getString(R.string.introduction_request_sent,
|
||||||
contactName.getValue(), name);
|
contactName.getValue(), name);
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_out, text, r);
|
R.layout.list_item_conversation_notice_out, text,
|
||||||
|
contactName, r);
|
||||||
} else {
|
} else {
|
||||||
String text;
|
String text;
|
||||||
if (r.wasAnswered()) {
|
if (r.wasAnswered()) {
|
||||||
@@ -243,7 +258,7 @@ class ConversationVisitor implements
|
|||||||
contactName.getValue(), name);
|
contactName.getValue(), name);
|
||||||
}
|
}
|
||||||
return new ConversationRequestItem(
|
return new ConversationRequestItem(
|
||||||
R.layout.list_item_conversation_request, text,
|
R.layout.list_item_conversation_request, text, contactName,
|
||||||
INTRODUCTION, r);
|
INTRODUCTION, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,7 +283,8 @@ class ConversationVisitor implements
|
|||||||
introducedAuthor);
|
introducedAuthor);
|
||||||
}
|
}
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_out, text, r);
|
R.layout.list_item_conversation_notice_out, text,
|
||||||
|
contactName, r);
|
||||||
} else {
|
} else {
|
||||||
String text;
|
String text;
|
||||||
if (r.wasAccepted()) {
|
if (r.wasAccepted()) {
|
||||||
@@ -288,7 +304,8 @@ class ConversationVisitor implements
|
|||||||
introducedAuthor);
|
introducedAuthor);
|
||||||
}
|
}
|
||||||
return new ConversationNoticeItem(
|
return new ConversationNoticeItem(
|
||||||
R.layout.list_item_conversation_notice_in, text, r);
|
R.layout.list_item_conversation_notice_in, text,
|
||||||
|
contactName, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!-- This layout is only used indirectly by cloning and setting its ConstraintSet -->
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!-- This layout is only used indirectly by cloning and setting its ConstraintSet -->
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/list_item_background_selectable">
|
android:background="@drawable/list_item_background_selectable"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
We need to wrap the actual layout, because
|
We need to wrap the actual layout, because we want to
|
||||||
* we want to clone the ConstraintLayout's constraints in the ViewHolder
|
* clone the ConstraintLayout's constraints in the ViewHolder
|
||||||
* we want to have a selectable frame around the message bubble
|
* have a selectable frame around the message bubble
|
||||||
|
* insert a top notice with its own independent width
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<include layout="@layout/list_item_conversation_top_notice_in" />
|
||||||
|
|
||||||
<include layout="@layout/list_item_conversation_msg_in_content" />
|
<include layout="@layout/list_item_conversation_msg_in_content" />
|
||||||
|
|
||||||
</FrameLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!-- This layout gets wrapped in *_msg_in.xml -->
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout 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"
|
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:background="@drawable/list_item_background_selectable">
|
android:background="@drawable/list_item_background_selectable"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingTop="@dimen/message_bubble_margin">
|
||||||
|
|
||||||
|
<include layout="@layout/list_item_conversation_top_notice_out" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/layout"
|
android:id="@+id/layout"
|
||||||
@@ -98,4 +102,4 @@
|
|||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</LinearLayout>
|
||||||
@@ -5,8 +5,9 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/list_item_background_selectable"
|
android:background="@drawable/list_item_background_selectable"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical">
|
||||||
android:paddingTop="@dimen/message_bubble_margin">
|
|
||||||
|
<include layout="@layout/list_item_conversation_top_notice_in" />
|
||||||
|
|
||||||
<com.vanniktech.emoji.EmojiTextView
|
<com.vanniktech.emoji.EmojiTextView
|
||||||
android:id="@+id/msgText"
|
android:id="@+id/msgText"
|
||||||
@@ -15,11 +16,13 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/message_bubble_margin_tail"
|
android:layout_marginStart="@dimen/message_bubble_margin_tail"
|
||||||
android:layout_marginLeft="@dimen/message_bubble_margin_tail"
|
android:layout_marginLeft="@dimen/message_bubble_margin_tail"
|
||||||
|
android:layout_marginTop="@dimen/message_bubble_margin"
|
||||||
android:layout_marginEnd="@dimen/message_bubble_margin_non_tail"
|
android:layout_marginEnd="@dimen/message_bubble_margin_non_tail"
|
||||||
android:layout_marginRight="@dimen/message_bubble_margin_non_tail"
|
android:layout_marginRight="@dimen/message_bubble_margin_non_tail"
|
||||||
android:background="@drawable/msg_in_top"
|
android:background="@drawable/msg_in_top"
|
||||||
android:elevation="@dimen/message_bubble_elevation"
|
android:elevation="@dimen/message_bubble_elevation"
|
||||||
tools:text="Short message" />
|
tools:text="Short message"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/layout"
|
android:id="@+id/layout"
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingTop="@dimen/message_bubble_margin">
|
android:paddingTop="@dimen/message_bubble_margin">
|
||||||
|
|
||||||
|
<include layout="@layout/list_item_conversation_top_notice_out" />
|
||||||
|
|
||||||
<com.vanniktech.emoji.EmojiTextView
|
<com.vanniktech.emoji.EmojiTextView
|
||||||
android:id="@+id/msgText"
|
android:id="@+id/msgText"
|
||||||
style="@style/TextMessage"
|
style="@style/TextMessage"
|
||||||
@@ -15,12 +17,14 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/message_bubble_margin_non_tail"
|
android:layout_marginStart="@dimen/message_bubble_margin_non_tail"
|
||||||
android:layout_marginLeft="@dimen/message_bubble_margin_non_tail"
|
android:layout_marginLeft="@dimen/message_bubble_margin_non_tail"
|
||||||
|
android:layout_marginTop="@dimen/message_bubble_margin"
|
||||||
android:layout_marginEnd="@dimen/message_bubble_margin_tail"
|
android:layout_marginEnd="@dimen/message_bubble_margin_tail"
|
||||||
android:layout_marginRight="@dimen/message_bubble_margin_tail"
|
android:layout_marginRight="@dimen/message_bubble_margin_tail"
|
||||||
android:background="@drawable/msg_out_top"
|
android:background="@drawable/msg_out_top"
|
||||||
android:elevation="@dimen/message_bubble_elevation"
|
android:elevation="@dimen/message_bubble_elevation"
|
||||||
android:textColor="@color/briar_text_primary_inverse"
|
android:textColor="@color/briar_text_primary_inverse"
|
||||||
tools:text="This is a long long long message that spans over several lines.\n\nIt ends here." />
|
tools:text="This is a long long long message that spans over several lines.\n\nIt ends here."
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/layout"
|
android:id="@+id/layout"
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/list_item_background_selectable"
|
android:background="@drawable/list_item_background_selectable"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical">
|
||||||
android:paddingTop="@dimen/message_bubble_margin">
|
|
||||||
|
<include layout="@layout/list_item_conversation_top_notice_in" />
|
||||||
|
|
||||||
<com.vanniktech.emoji.EmojiTextView
|
<com.vanniktech.emoji.EmojiTextView
|
||||||
android:id="@+id/msgText"
|
android:id="@+id/msgText"
|
||||||
@@ -15,6 +16,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/message_bubble_margin_tail"
|
android:layout_marginStart="@dimen/message_bubble_margin_tail"
|
||||||
android:layout_marginLeft="@dimen/message_bubble_margin_tail"
|
android:layout_marginLeft="@dimen/message_bubble_margin_tail"
|
||||||
|
android:layout_marginTop="@dimen/message_bubble_margin"
|
||||||
android:layout_marginEnd="@dimen/message_bubble_margin_non_tail"
|
android:layout_marginEnd="@dimen/message_bubble_margin_non_tail"
|
||||||
android:layout_marginRight="@dimen/message_bubble_margin_non_tail"
|
android:layout_marginRight="@dimen/message_bubble_margin_non_tail"
|
||||||
android:background="@drawable/msg_in_top"
|
android:background="@drawable/msg_in_top"
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.vanniktech.emoji.EmojiTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/topNotice"
|
||||||
|
style="@style/TextMessage.Notice"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/message_bubble_margin_tail"
|
||||||
|
android:layout_marginLeft="@dimen/message_bubble_margin_tail"
|
||||||
|
android:layout_marginTop="@dimen/message_bubble_margin"
|
||||||
|
android:layout_marginEnd="@dimen/message_bubble_margin_non_tail"
|
||||||
|
android:layout_marginRight="@dimen/message_bubble_margin_non_tail"
|
||||||
|
android:layout_marginBottom="@dimen/message_bubble_margin"
|
||||||
|
android:background="@drawable/notice_in"
|
||||||
|
android:elevation="@dimen/message_bubble_elevation"
|
||||||
|
android:paddingBottom="@dimen/message_bubble_padding_top"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:text="@string/auto_delete_msg_contact_enabled"
|
||||||
|
tools:visibility="visible" />
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.vanniktech.emoji.EmojiTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/topNotice"
|
||||||
|
style="@style/TextMessage.Notice"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end|right"
|
||||||
|
android:layout_marginStart="@dimen/message_bubble_margin_non_tail"
|
||||||
|
android:layout_marginLeft="@dimen/message_bubble_margin_non_tail"
|
||||||
|
android:layout_marginEnd="@dimen/message_bubble_margin_tail"
|
||||||
|
android:layout_marginRight="@dimen/message_bubble_margin_tail"
|
||||||
|
android:layout_marginBottom="@dimen/message_bubble_margin"
|
||||||
|
android:background="@drawable/notice_out"
|
||||||
|
android:elevation="@dimen/message_bubble_elevation"
|
||||||
|
android:paddingBottom="@dimen/message_bubble_padding_top"
|
||||||
|
android:textColor="@color/private_message_date_inverse"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:showIn="@layout/list_item_conversation_msg_out"
|
||||||
|
tools:text="@string/auto_delete_msg_you_enabled"
|
||||||
|
tools:visibility="visible" />
|
||||||
@@ -166,6 +166,14 @@
|
|||||||
<string name="set_contact_alias">Change contact name</string>
|
<string name="set_contact_alias">Change contact name</string>
|
||||||
<string name="set_contact_alias_hint">Contact name</string>
|
<string name="set_contact_alias_hint">Contact name</string>
|
||||||
<string name="menu_item_auto_delete">Disappearing messages</string>
|
<string name="menu_item_auto_delete">Disappearing messages</string>
|
||||||
|
<string name="auto_delete_msg_you_enabled">You turned on disappearing messages. Your messages will disappear after 7 days.</string>
|
||||||
|
<string name="auto_delete_msg_you_disabled">You turned off disappearing messages. Your messages will not disappear.</string>
|
||||||
|
<string name="auto_delete_msg_you_enabled_mirrored">Your messages will disappear after 7 days.</string>
|
||||||
|
<string name="auto_delete_msg_you_disabled_mirrored">Your messages will not disappear.</string>
|
||||||
|
<string name="auto_delete_msg_contact_enabled">%1$s turned on disappearing messages. %2$s\'s messages will disappear after 7 days.</string>
|
||||||
|
<string name="auto_delete_msg_contact_disabled">%1$s turned off disappearing messages. %2$s\'s messages will not disappear.</string>
|
||||||
|
<string name="auto_delete_msg_contact_enabled_mirrored">%1$s\'s messages will disappear after 7 days.</string>
|
||||||
|
<string name="auto_delete_msg_contact_disabled_mirrored">%1$s\'s messages will not disappear.</string>
|
||||||
<string name="delete_all_messages">Delete all messages</string>
|
<string name="delete_all_messages">Delete all messages</string>
|
||||||
<string name="dialog_title_delete_all_messages">Confirm Message Deletion</string>
|
<string name="dialog_title_delete_all_messages">Confirm Message Deletion</string>
|
||||||
<string name="dialog_message_delete_all_messages">Are you sure that you want to delete all messages?</string>
|
<string name="dialog_message_delete_all_messages">Are you sure that you want to delete all messages?</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user