mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 02:39:05 +01:00
Refactor ConversationAdapter and its ConversationItems
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
android:id="@+id/msgLayout"
|
||||
android:id="@+id/layout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -11,7 +11,7 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/msgBody"
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/briar_text_primary"
|
||||
@@ -20,7 +20,7 @@
|
||||
tools:text="Short message"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/msgTime"
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right|end"
|
||||
@@ -7,7 +7,7 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/msgLayout"
|
||||
android:id="@+id/layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right|end"
|
||||
@@ -16,7 +16,7 @@
|
||||
android:background="@drawable/msg_out">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/msgBody"
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/briar_text_primary_inverse"
|
||||
@@ -25,12 +25,12 @@
|
||||
tools:text="This is a long long long message that spans over several lines.\n\nIt ends here."/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/msgTime"
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/msgBody"
|
||||
android:layout_below="@+id/text"
|
||||
android:layout_marginTop="@dimen/message_bubble_timestamp_margin"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/private_message_date_inverse"
|
||||
@@ -38,13 +38,13 @@
|
||||
tools:text="Dec 24, 13:37"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/msgStatus"
|
||||
android:id="@+id/status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@+id/msgTime"
|
||||
android:layout_alignBottom="@+id/time"
|
||||
android:layout_marginLeft="@dimen/margin_medium"
|
||||
android:layout_toEndOf="@+id/msgTime"
|
||||
android:layout_toRightOf="@+id/msgTime"
|
||||
android:layout_toEndOf="@+id/time"
|
||||
android:layout_toRightOf="@+id/time"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/message_delivered_white"/>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/msgBody"
|
||||
android:id="@+id/msgText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left|start"
|
||||
@@ -20,7 +20,7 @@
|
||||
tools:text="Short message"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/noticeLayout"
|
||||
android:id="@+id/layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/message_bubble_margin_tail"
|
||||
@@ -28,7 +28,7 @@
|
||||
android:background="@drawable/notice_in_bottom">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/introductionText"
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="80dp"
|
||||
@@ -39,28 +39,17 @@
|
||||
tools:text="@string/forum_invitation_received"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/introductionTime"
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignEnd="@+id/introductionText"
|
||||
android:layout_alignRight="@+id/introductionText"
|
||||
android:layout_below="@+id/showInvitationsButton"
|
||||
android:layout_alignEnd="@+id/text"
|
||||
android:layout_alignRight="@+id/text"
|
||||
android:layout_below="@+id/text"
|
||||
android:layout_marginTop="@dimen/message_bubble_timestamp_margin"
|
||||
android:textColor="@color/private_message_date"
|
||||
android:textSize="@dimen/text_size_tiny"
|
||||
tools:text="Dec 24, 13:37"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/showInvitationsButton"
|
||||
style="@style/BriarButtonFlat.Positive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignEnd="@+id/introductionText"
|
||||
android:layout_alignRight="@+id/introductionText"
|
||||
android:layout_below="@+id/introductionText"
|
||||
android:layout_marginBottom="-15dp"
|
||||
tools:text="@string/forum_show_invitations"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -7,7 +7,7 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/msgBody"
|
||||
android:id="@+id/msgText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/message_bubble_margin_non_tail"
|
||||
@@ -19,7 +19,7 @@
|
||||
tools:text="This is a long long long message that spans over several lines.\n\nIt ends here."/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/noticeLayout"
|
||||
android:id="@+id/layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/message_bubble_margin_non_tail"
|
||||
@@ -27,7 +27,7 @@
|
||||
android:background="@drawable/notice_out_bottom">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/introductionText"
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/briar_text_secondary"
|
||||
@@ -37,25 +37,25 @@
|
||||
tools:text="@string/introduction_request_received"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/introductionTime"
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/introductionText"
|
||||
android:layout_below="@+id/text"
|
||||
android:layout_marginTop="@dimen/message_bubble_timestamp_margin"
|
||||
android:textColor="@color/private_message_date"
|
||||
android:textSize="@dimen/text_size_tiny"
|
||||
tools:text="Dec 24, 13:37"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/introductionStatus"
|
||||
android:id="@+id/status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@+id/introductionTime"
|
||||
android:layout_alignBottom="@+id/time"
|
||||
android:layout_marginLeft="@dimen/margin_medium"
|
||||
android:layout_toEndOf="@+id/introductionTime"
|
||||
android:layout_toRightOf="@+id/introductionTime"
|
||||
android:layout_toEndOf="@+id/time"
|
||||
android:layout_toRightOf="@+id/time"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/message_delivered"/>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/msgBody"
|
||||
android:id="@+id/msgText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/message_bubble_margin_tail"
|
||||
@@ -19,7 +19,7 @@
|
||||
tools:text="Short message"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/noticeLayout"
|
||||
android:id="@+id/layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/message_bubble_margin_tail"
|
||||
@@ -27,7 +27,7 @@
|
||||
android:background="@drawable/notice_in_bottom">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/introductionText"
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="80dp"
|
||||
@@ -38,11 +38,11 @@
|
||||
tools:text="@string/introduction_request_received"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/introductionTime"
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignEnd="@+id/introductionText"
|
||||
android:layout_alignRight="@+id/introductionText"
|
||||
android:layout_alignEnd="@+id/text"
|
||||
android:layout_alignRight="@+id/text"
|
||||
android:layout_below="@+id/declineButton"
|
||||
android:layout_marginTop="@dimen/message_bubble_timestamp_margin"
|
||||
android:textColor="@color/private_message_date"
|
||||
@@ -54,9 +54,9 @@
|
||||
style="@style/BriarButtonFlat.Positive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignEnd="@+id/introductionText"
|
||||
android:layout_alignRight="@+id/introductionText"
|
||||
android:layout_below="@+id/introductionText"
|
||||
android:layout_alignEnd="@+id/text"
|
||||
android:layout_alignRight="@+id/text"
|
||||
android:layout_below="@+id/text"
|
||||
android:text="@string/accept"/>
|
||||
|
||||
<Button
|
||||
@@ -64,7 +64,7 @@
|
||||
style="@style/BriarButtonFlat.Negative"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/introductionText"
|
||||
android:layout_below="@+id/text"
|
||||
android:layout_marginBottom="-15dp"
|
||||
android:layout_toLeftOf="@+id/acceptButton"
|
||||
android:layout_toStartOf="@+id/acceptButton"
|
||||
@@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/notice_in"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginLeft="@dimen/message_bubble_margin_tail"
|
||||
android:layout_marginRight="@dimen/message_bubble_margin_non_tail">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/noticeText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="italic"
|
||||
android:textColor="@color/briar_text_secondary"
|
||||
tools:text="@string/introduction_response_accepted_received"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/noticeTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right|end"
|
||||
android:layout_marginTop="@dimen/message_bubble_timestamp_margin"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/private_message_date"
|
||||
android:textSize="@dimen/text_size_tiny"
|
||||
tools:text="Dec 24, 13:37"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,52 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right|end"
|
||||
android:background="@drawable/notice_out"
|
||||
android:layout_marginLeft="@dimen/message_bubble_margin_non_tail"
|
||||
android:layout_marginRight="@dimen/message_bubble_margin_tail">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/noticeText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="italic"
|
||||
android:textColor="@color/briar_text_secondary"
|
||||
tools:text="@string/introduction_response_accepted_sent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/noticeTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/message_bubble_timestamp_margin"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/noticeText"
|
||||
android:textColor="@color/private_message_date"
|
||||
android:textSize="@dimen/text_size_tiny"
|
||||
tools:text="Dec 24, 13:37"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/noticeStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@+id/noticeTime"
|
||||
android:layout_marginLeft="@dimen/margin_medium"
|
||||
android:layout_toEndOf="@+id/noticeTime"
|
||||
android:layout_toRightOf="@+id/noticeTime"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/message_delivered"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -133,7 +133,6 @@
|
||||
<string name="introduction_request_sent">You have asked to introduce %1$s to %2$s.</string>
|
||||
<string name="introduction_request_received">%1$s has asked to introduce you to %2$s. Do you want to add %2$s to your contact list?</string>
|
||||
<string name="introduction_request_exists_received">%1$s has asked to introduce you to %2$s, but %2$s is already in your contact list. Since %1$s might not know that, you can still respond:</string>
|
||||
<string name="introduction_request_for_our_identity_received">%1$s has asked to introduce you to %2$s, but %2$s is one of your other identities, so you cannot accept the introduction:</string>
|
||||
<string name="introduction_request_answered_received">%1$s has asked to introduce you to %2$s.</string>
|
||||
<string name="introduction_response_accepted_sent">You accepted the introduction to %1$s.</string>
|
||||
<string name="introduction_response_declined_sent">You declined the introduction to %1$s.</string>
|
||||
@@ -215,7 +214,6 @@
|
||||
<string name="forum_share_error">There was an error sharing this forum.</string>
|
||||
<string name="forum_invitation_received">%1$s has shared the forum \"%2$s\" with you.</string>
|
||||
<string name="forum_invitation_sent">You have shared the forum \"%1$s\" with %2$s.</string>
|
||||
<string name="forum_show_invitations">Show Forum Invitations</string>
|
||||
<string name="forum_invitations_title">Forum Invitations</string>
|
||||
<string name="forum_invitation_exists">You accepted an invitation to this forum already. Accepting more invitations will grow and strengthen the communication in the forum.</string>
|
||||
<string name="forum_joined_toast">Joined Forum</string>
|
||||
@@ -279,7 +277,6 @@
|
||||
<string name="blogs_sharing_response_declined_received">%s declined the blog invitation.</string>
|
||||
<string name="blogs_sharing_invitation_received">%1$s has shared the personal blog of %2$s with you.</string>
|
||||
<string name="blogs_sharing_invitation_sent">You have shared the personal blog of %1$s with %2$s.</string>
|
||||
<string name="blogs_sharing_show_invitations">Show Blog Invitations</string>
|
||||
<string name="blogs_sharing_invitations_title">Blog Invitations</string>
|
||||
<string name="blogs_sharing_exists">You are subscribed to this blog already. Accepting again can lead to faster blog post delivery.</string>
|
||||
<string name="blogs_sharing_joined_toast">Subscribed to Blog</string>
|
||||
|
||||
@@ -276,24 +276,28 @@ public class ContactListFragment extends BaseFragment implements EventListener {
|
||||
IntroductionRequestReceivedEvent m =
|
||||
(IntroductionRequestReceivedEvent) e;
|
||||
IntroductionRequest ir = m.getIntroductionRequest();
|
||||
updateItem(m.getContactId(), ConversationItem.from(ir));
|
||||
updateItem(m.getContactId(),
|
||||
ConversationItem.from(getContext(), "", ir));
|
||||
} else if (e instanceof IntroductionResponseReceivedEvent) {
|
||||
LOG.info("Introduction response received, updating item");
|
||||
IntroductionResponseReceivedEvent m =
|
||||
(IntroductionResponseReceivedEvent) e;
|
||||
IntroductionResponse ir = m.getIntroductionResponse();
|
||||
updateItem(m.getContactId(), ConversationItem.from(ir));
|
||||
updateItem(m.getContactId(),
|
||||
ConversationItem.from(getContext(), "", ir));
|
||||
} else if (e instanceof InvitationRequestReceivedEvent) {
|
||||
LOG.info("Invitation request received, updating item");
|
||||
InvitationRequestReceivedEvent m = (InvitationRequestReceivedEvent) e;
|
||||
InvitationRequest ir = m.getRequest();
|
||||
updateItem(m.getContactId(), ConversationItem.from(ir));
|
||||
updateItem(m.getContactId(),
|
||||
ConversationItem.from(getContext(), "", ir));
|
||||
} else if (e instanceof InvitationResponseReceivedEvent) {
|
||||
LOG.info("Invitation response received, updating item");
|
||||
InvitationResponseReceivedEvent m =
|
||||
(InvitationResponseReceivedEvent) e;
|
||||
InvitationResponse ir = m.getResponse();
|
||||
updateItem(m.getContactId(), ConversationItem.from(ir));
|
||||
updateItem(m.getContactId(),
|
||||
ConversationItem.from(getContext(), "", ir));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static org.briarproject.android.contact.ConversationItem.IncomingItem;
|
||||
|
||||
// This class is NOT thread-safe
|
||||
public class ContactListItem {
|
||||
|
||||
@@ -34,8 +32,8 @@ public class ContactListItem {
|
||||
empty = empty && message == null;
|
||||
if (message != null) {
|
||||
if (message.getTime() > timestamp) timestamp = message.getTime();
|
||||
if (message instanceof IncomingItem &&
|
||||
!((IncomingItem) message).isRead())
|
||||
if (message instanceof ConversationInItem &&
|
||||
!((ConversationInItem) message).isRead())
|
||||
unread++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.android.contact;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.ActivityOptionsCompat;
|
||||
@@ -27,7 +28,8 @@ import org.briarproject.R;
|
||||
import org.briarproject.android.ActivityComponent;
|
||||
import org.briarproject.android.BriarActivity;
|
||||
import org.briarproject.android.api.AndroidNotificationManager;
|
||||
import org.briarproject.android.contact.ConversationAdapter.IntroductionHandler;
|
||||
import org.briarproject.android.contact.ConversationAdapter.RequestListener;
|
||||
import org.briarproject.android.contact.ConversationItem.PartialItem;
|
||||
import org.briarproject.android.introduction.IntroductionActivity;
|
||||
import org.briarproject.android.view.BriarRecyclerView;
|
||||
import org.briarproject.android.view.TextInputView;
|
||||
@@ -39,6 +41,7 @@ import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.NoSuchContactException;
|
||||
import org.briarproject.api.event.ContactConnectedEvent;
|
||||
@@ -92,16 +95,15 @@ import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt;
|
||||
import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.OnHidePromptListener;
|
||||
|
||||
import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
|
||||
import static android.support.v7.util.SortedList.INVALID_POSITION;
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.android.contact.ConversationItem.IncomingItem;
|
||||
import static org.briarproject.android.contact.ConversationItem.OutgoingItem;
|
||||
import static org.briarproject.android.fragment.SettingsFragment.SETTINGS_NAMESPACE;
|
||||
import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
|
||||
|
||||
public class ConversationActivity extends BriarActivity
|
||||
implements EventListener, IntroductionHandler, TextInputListener {
|
||||
implements EventListener, RequestListener, TextInputListener {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(ConversationActivity.class.getName());
|
||||
@@ -117,7 +119,7 @@ public class ConversationActivity extends BriarActivity
|
||||
@CryptoExecutor
|
||||
Executor cryptoExecutor;
|
||||
|
||||
private final Map<MessageId, byte[]> bodyCache = new ConcurrentHashMap<>();
|
||||
private final Map<MessageId, String> bodyCache = new ConcurrentHashMap<>();
|
||||
|
||||
private ConversationAdapter adapter;
|
||||
private Toolbar toolbar;
|
||||
@@ -325,7 +327,6 @@ public class ConversationActivity extends BriarActivity
|
||||
toolbarStatus
|
||||
.setContentDescription(getString(R.string.offline));
|
||||
}
|
||||
adapter.setContactName(contactName);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -399,33 +400,42 @@ public class ConversationActivity extends BriarActivity
|
||||
Collection<InvitationMessage> invitations) {
|
||||
int size = headers.size() + introductions.size() + invitations.size();
|
||||
List<ConversationItem> items = new ArrayList<>(size);
|
||||
for (PrivateMessageHeader h : headers) {
|
||||
ConversationMessageItem item = ConversationItem.from(h);
|
||||
byte[] body = bodyCache.get(h.getId());
|
||||
if (body == null) loadMessageBody(h.getId());
|
||||
else item.setBody(body);
|
||||
items.add(item);
|
||||
}
|
||||
for (IntroductionMessage im : introductions) {
|
||||
if (im instanceof IntroductionRequest) {
|
||||
IntroductionRequest ir = (IntroductionRequest) im;
|
||||
items.add(ConversationItem.from(ir));
|
||||
} else {
|
||||
IntroductionResponse ir = (IntroductionResponse) im;
|
||||
items.add(ConversationItem.from(ConversationActivity.this,
|
||||
contactName, ir));
|
||||
|
||||
for (PrivateMessageHeader h : headers) {
|
||||
ConversationItem item = ConversationItem.from(h);
|
||||
String body = bodyCache.get(h.getId());
|
||||
if (body == null) loadMessageBody(h.getId());
|
||||
else ((PartialItem) item).setText(body);
|
||||
items.add(item);
|
||||
}
|
||||
}
|
||||
for (InvitationMessage im : invitations) {
|
||||
if (im instanceof InvitationRequest) {
|
||||
InvitationRequest ir = (InvitationRequest) im;
|
||||
items.add(ConversationItem.from(ir));
|
||||
} else if (im instanceof InvitationResponse) {
|
||||
InvitationResponse ir = (InvitationResponse) im;
|
||||
items.add(ConversationItem.from(ConversationActivity.this,
|
||||
contactName, ir));
|
||||
for (IntroductionMessage m : introductions) {
|
||||
ConversationItem item;
|
||||
if (m instanceof IntroductionRequest) {
|
||||
item = ConversationItem
|
||||
.from(ConversationActivity.this,
|
||||
contactName,
|
||||
(IntroductionRequest) m);
|
||||
} else {
|
||||
item = ConversationItem
|
||||
.from(ConversationActivity.this,
|
||||
contactName,
|
||||
(IntroductionResponse) m);
|
||||
}
|
||||
items.add(item);
|
||||
}
|
||||
for (InvitationMessage i : invitations) {
|
||||
if (i instanceof InvitationRequest) {
|
||||
InvitationRequest r = (InvitationRequest) i;
|
||||
items.add(ConversationItem
|
||||
.from(ConversationActivity.this,
|
||||
contactName, r));
|
||||
} else if (i instanceof InvitationResponse) {
|
||||
InvitationResponse r = (InvitationResponse) i;
|
||||
items.add(ConversationItem
|
||||
.from(ConversationActivity.this,
|
||||
contactName, r));
|
||||
}
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@@ -439,7 +449,7 @@ public class ConversationActivity extends BriarActivity
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading body took " + duration + " ms");
|
||||
displayMessageBody(m, body);
|
||||
displayMessageBody(m, StringUtils.fromUtf8(body));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
@@ -448,17 +458,17 @@ public class ConversationActivity extends BriarActivity
|
||||
});
|
||||
}
|
||||
|
||||
private void displayMessageBody(final MessageId m, final byte[] body) {
|
||||
private void displayMessageBody(final MessageId m, final String body) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
bodyCache.put(m, body);
|
||||
SparseArray<ConversationMessageItem> messages =
|
||||
SparseArray<ConversationItem> messages =
|
||||
adapter.getPrivateMessages();
|
||||
for (int i = 0; i < messages.size(); i++) {
|
||||
ConversationMessageItem item = messages.valueAt(i);
|
||||
ConversationItem item = messages.valueAt(i);
|
||||
if (item.getId().equals(m)) {
|
||||
item.setBody(body);
|
||||
((PartialItem) item).setText(body);
|
||||
adapter.notifyItemChanged(messages.keyAt(i));
|
||||
list.scrollToPosition(adapter.getItemCount() - 1);
|
||||
return;
|
||||
@@ -482,9 +492,9 @@ public class ConversationActivity extends BriarActivity
|
||||
|
||||
private void markMessagesRead() {
|
||||
Map<MessageId, GroupId> unread = new HashMap<>();
|
||||
SparseArray<IncomingItem> list = adapter.getIncomingMessages();
|
||||
SparseArray<ConversationInItem> list = adapter.getIncomingMessages();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
IncomingItem item = list.valueAt(i);
|
||||
ConversationInItem item = list.valueAt(i);
|
||||
if (!item.isRead())
|
||||
unread.put(item.getId(), item.getGroupId());
|
||||
}
|
||||
@@ -561,7 +571,8 @@ public class ConversationActivity extends BriarActivity
|
||||
if (event.getContactId().equals(contactId)) {
|
||||
LOG.info("Introduction request received, adding...");
|
||||
IntroductionRequest ir = event.getIntroductionRequest();
|
||||
ConversationItem item = new ConversationIntroductionInItem(ir);
|
||||
ConversationItem item =
|
||||
ConversationRequestItem.from(this, contactName, ir);
|
||||
addConversationItem(item);
|
||||
}
|
||||
} else if (e instanceof IntroductionResponseReceivedEvent) {
|
||||
@@ -580,7 +591,8 @@ public class ConversationActivity extends BriarActivity
|
||||
if (event.getContactId().equals(contactId)) {
|
||||
LOG.info("Invitation received, adding...");
|
||||
InvitationRequest ir = event.getRequest();
|
||||
ConversationItem item = ConversationItem.from(ir);
|
||||
ConversationItem item =
|
||||
ConversationItem.from(this, contactName, ir);
|
||||
addConversationItem(item);
|
||||
}
|
||||
} else if (e instanceof InvitationResponseReceivedEvent) {
|
||||
@@ -603,9 +615,10 @@ public class ConversationActivity extends BriarActivity
|
||||
public void run() {
|
||||
adapter.incrementRevision();
|
||||
Set<MessageId> messages = new HashSet<>(messageIds);
|
||||
SparseArray<OutgoingItem> list = adapter.getOutgoingMessages();
|
||||
SparseArray<ConversationOutItem> list =
|
||||
adapter.getOutgoingMessages();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
OutgoingItem item = list.valueAt(i);
|
||||
ConversationOutItem item = list.valueAt(i);
|
||||
if (messages.contains(item.getId())) {
|
||||
item.setSent(sent);
|
||||
item.setSeen(seen);
|
||||
@@ -622,7 +635,7 @@ public class ConversationActivity extends BriarActivity
|
||||
text = StringUtils.truncateUtf8(text, MAX_PRIVATE_MESSAGE_BODY_LENGTH);
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.max(timestamp, getMinTimestampForNewMessage());
|
||||
createMessage(StringUtils.toUtf8(text), timestamp);
|
||||
createMessage(text, timestamp);
|
||||
textInputView.setText("");
|
||||
}
|
||||
|
||||
@@ -632,14 +645,14 @@ public class ConversationActivity extends BriarActivity
|
||||
return item == null ? 0 : item.getTime() + 1;
|
||||
}
|
||||
|
||||
private void createMessage(final byte[] body, final long timestamp) {
|
||||
private void createMessage(final String body, final long timestamp) {
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
storeMessage(privateMessageFactory.createPrivateMessage(
|
||||
groupId, timestamp, null, "text/plain", body),
|
||||
body);
|
||||
groupId, timestamp, null, "text/plain",
|
||||
StringUtils.toUtf8(body)), body);
|
||||
} catch (FormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -647,7 +660,7 @@ public class ConversationActivity extends BriarActivity
|
||||
});
|
||||
}
|
||||
|
||||
private void storeMessage(final PrivateMessage m, final byte[] body) {
|
||||
private void storeMessage(final PrivateMessage m, final String body) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -661,8 +674,8 @@ public class ConversationActivity extends BriarActivity
|
||||
PrivateMessageHeader h = new PrivateMessageHeader(id,
|
||||
groupId, m.getMessage().getTimestamp(),
|
||||
m.getContentType(), true, false, false, false);
|
||||
ConversationMessageItem item = ConversationItem.from(h);
|
||||
item.setBody(body);
|
||||
ConversationItem item = ConversationItem.from(h);
|
||||
((PartialItem) item).setText(body);
|
||||
bodyCache.put(id, body);
|
||||
addConversationItem(item);
|
||||
} catch (DbException e) {
|
||||
@@ -812,23 +825,35 @@ public class ConversationActivity extends BriarActivity
|
||||
});
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@Override
|
||||
public void respondToIntroduction(final SessionId sessionId,
|
||||
public void respondToRequest(final ConversationRequestItem item,
|
||||
final boolean accept) {
|
||||
int position = adapter.findItemPosition(item);
|
||||
if (position != INVALID_POSITION) {
|
||||
adapter.notifyItemChanged(position, item);
|
||||
}
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.max(timestamp, getMinTimestampForNewMessage());
|
||||
try {
|
||||
if (accept) {
|
||||
introductionManager.acceptIntroduction(contactId,
|
||||
sessionId, timestamp);
|
||||
} else {
|
||||
introductionManager.declineIntroduction(contactId,
|
||||
sessionId, timestamp);
|
||||
switch (item.getRequestType()) {
|
||||
case INTRODUCTION:
|
||||
respondToIntroductionRequest(item.getSessionId(),
|
||||
accept, timestamp);
|
||||
break;
|
||||
case FORUM:
|
||||
respondToForumRequest(item.getSessionId(), accept);
|
||||
break;
|
||||
case BLOG:
|
||||
respondToBlogRequest(item.getSessionId(), accept);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown Request Type");
|
||||
}
|
||||
loadMessages();
|
||||
} catch (DbException | FormatException e) {
|
||||
introductionResponseError();
|
||||
if (LOG.isLoggable(WARNING))
|
||||
@@ -839,6 +864,31 @@ public class ConversationActivity extends BriarActivity
|
||||
});
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
private void respondToIntroductionRequest(SessionId sessionId,
|
||||
boolean accept, long time) throws DbException, FormatException {
|
||||
if (accept) {
|
||||
introductionManager.acceptIntroduction(contactId, sessionId, time);
|
||||
} else {
|
||||
introductionManager.declineIntroduction(contactId, sessionId, time);
|
||||
}
|
||||
loadMessages();
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
private void respondToForumRequest(SessionId id, boolean accept)
|
||||
throws DbException {
|
||||
forumSharingManager.respondToInvitation(id, accept);
|
||||
loadMessages();
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
private void respondToBlogRequest(SessionId id, boolean accept)
|
||||
throws DbException {
|
||||
blogSharingManager.respondToInvitation(id, accept);
|
||||
loadMessages();
|
||||
}
|
||||
|
||||
private void introductionResponseError() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -1,365 +1,74 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.LayoutRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.sharing.InvitationsBlogActivity;
|
||||
import org.briarproject.android.sharing.InvitationsForumActivity;
|
||||
import org.briarproject.android.util.AndroidUtils;
|
||||
import org.briarproject.android.util.BriarAdapter;
|
||||
import org.briarproject.api.blogs.BlogInvitationRequest;
|
||||
import org.briarproject.api.clients.SessionId;
|
||||
import org.briarproject.api.forum.ForumInvitationRequest;
|
||||
import org.briarproject.api.introduction.IntroductionRequest;
|
||||
import org.briarproject.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.api.sharing.InvitationRequest;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import static android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.android.contact.ConversationItem.BLOG_INVITATION_IN;
|
||||
import static org.briarproject.android.contact.ConversationItem.BLOG_INVITATION_OUT;
|
||||
import static org.briarproject.android.contact.ConversationItem.FORUM_INVITATION_IN;
|
||||
import static org.briarproject.android.contact.ConversationItem.FORUM_INVITATION_OUT;
|
||||
import static org.briarproject.android.contact.ConversationItem.INTRODUCTION_IN;
|
||||
import static org.briarproject.android.contact.ConversationItem.INTRODUCTION_OUT;
|
||||
import static org.briarproject.android.contact.ConversationItem.IncomingItem;
|
||||
import static org.briarproject.android.contact.ConversationItem.MSG_IN_UNREAD;
|
||||
import static org.briarproject.android.contact.ConversationItem.MSG_OUT;
|
||||
import static org.briarproject.android.contact.ConversationItem.NOTICE_IN;
|
||||
import static org.briarproject.android.contact.ConversationItem.NOTICE_OUT;
|
||||
import static org.briarproject.android.contact.ConversationItem.OutgoingItem;
|
||||
class ConversationAdapter
|
||||
extends BriarAdapter<ConversationItem, ConversationItemViewHolder> {
|
||||
|
||||
class ConversationAdapter extends BriarAdapter<ConversationItem, ViewHolder> {
|
||||
private RequestListener listener;
|
||||
|
||||
private IntroductionHandler intro;
|
||||
private String contactName;
|
||||
|
||||
ConversationAdapter(Context ctx, IntroductionHandler introductionHandler) {
|
||||
ConversationAdapter(Context ctx, RequestListener requestListener) {
|
||||
super(ctx, ConversationItem.class);
|
||||
intro = introductionHandler;
|
||||
}
|
||||
|
||||
void setContactName(String contactName) {
|
||||
this.contactName = contactName;
|
||||
notifyDataSetChanged();
|
||||
listener = requestListener;
|
||||
}
|
||||
|
||||
@LayoutRes
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return items.get(position).getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
|
||||
View v;
|
||||
|
||||
// outgoing message (local)
|
||||
if (type == MSG_OUT) {
|
||||
v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
||||
R.layout.list_item_msg_out, viewGroup, false);
|
||||
return new MessageHolder(v, type);
|
||||
} else if (type == INTRODUCTION_IN) {
|
||||
v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
||||
R.layout.list_item_introduction_in, viewGroup, false);
|
||||
return new IntroductionHolder(v, type);
|
||||
} else if (type == INTRODUCTION_OUT) {
|
||||
v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
||||
R.layout.list_item_msg_notice_out, viewGroup, false);
|
||||
return new IntroductionHolder(v, type);
|
||||
} else if (type == NOTICE_IN) {
|
||||
v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
||||
R.layout.list_item_notice_in, viewGroup, false);
|
||||
return new NoticeHolder(v, type);
|
||||
} else if (type == NOTICE_OUT) {
|
||||
v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
||||
R.layout.list_item_notice_out, viewGroup, false);
|
||||
return new NoticeHolder(v, type);
|
||||
} else if (type == FORUM_INVITATION_IN || type == BLOG_INVITATION_IN) {
|
||||
v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
||||
R.layout.list_item_shareable_invitation_in, viewGroup,
|
||||
false);
|
||||
return new InvitationHolder(v, type);
|
||||
} else if (type == FORUM_INVITATION_OUT ||
|
||||
type == BLOG_INVITATION_OUT) {
|
||||
v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
||||
R.layout.list_item_msg_notice_out, viewGroup, false);
|
||||
return new InvitationHolder(v, type);
|
||||
}
|
||||
// incoming message (non-local)
|
||||
else {
|
||||
v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
||||
R.layout.list_item_msg_in, viewGroup, false);
|
||||
return new MessageHolder(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder ui, int position) {
|
||||
ConversationItem item = getItemAt(position);
|
||||
if (item instanceof ConversationMessageItem) {
|
||||
bindMessage((MessageHolder) ui, (ConversationMessageItem) item);
|
||||
} else if (item instanceof ConversationIntroductionOutItem) {
|
||||
bindIntroduction((IntroductionHolder) ui,
|
||||
(ConversationIntroductionOutItem) item, position);
|
||||
} else if (item instanceof ConversationIntroductionInItem) {
|
||||
bindIntroduction((IntroductionHolder) ui,
|
||||
(ConversationIntroductionInItem) item, position);
|
||||
ConversationItem item = items.get(position);
|
||||
if (item instanceof ConversationRequestItem) {
|
||||
return R.layout.list_item_conversation_request;
|
||||
} else if (item instanceof ConversationNoticeOutItem) {
|
||||
bindNotice((NoticeHolder) ui, (ConversationNoticeOutItem) item);
|
||||
return R.layout.list_item_conversation_notice_out;
|
||||
} else if (item instanceof ConversationNoticeInItem) {
|
||||
bindNotice((NoticeHolder) ui, (ConversationNoticeInItem) item);
|
||||
} else if (item instanceof ConversationShareableInvitationOutItem) {
|
||||
bindInvitation((InvitationHolder) ui,
|
||||
(ConversationShareableInvitationOutItem) item);
|
||||
} else if (item instanceof ConversationShareableInvitationInItem) {
|
||||
bindInvitation((InvitationHolder) ui,
|
||||
(ConversationShareableInvitationInItem) item);
|
||||
return R.layout.list_item_conversation_notice_in;
|
||||
} else if (item instanceof ConversationMessageOutItem) {
|
||||
return R.layout.list_item_conversation_msg_out;
|
||||
} else if (item instanceof ConversationMessageInItem) {
|
||||
return R.layout.list_item_conversation_msg_in;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unhandled Conversation Item");
|
||||
throw new IllegalArgumentException("Unknown ConversationItem");
|
||||
}
|
||||
}
|
||||
|
||||
private void bindMessage(MessageHolder ui, ConversationMessageItem item) {
|
||||
PrivateMessageHeader header = item.getHeader();
|
||||
|
||||
if (item instanceof ConversationItem.OutgoingItem) {
|
||||
if (((OutgoingItem) item).isSeen()) {
|
||||
ui.status.setImageResource(R.drawable.message_delivered_white);
|
||||
} else if (((OutgoingItem) item).isSent()) {
|
||||
ui.status.setImageResource(R.drawable.message_sent_white);
|
||||
} else {
|
||||
ui.status.setImageResource(R.drawable.message_stored_white);
|
||||
}
|
||||
} else {
|
||||
if (item.getType() == MSG_IN_UNREAD) {
|
||||
// TODO implement new unread message highlight according to #232
|
||||
/* int left = ui.layout.getPaddingLeft();
|
||||
int top = ui.layout.getPaddingTop();
|
||||
int right = ui.layout.getPaddingRight();
|
||||
int bottom = ui.layout.getPaddingBottom();
|
||||
|
||||
// show unread messages in different color to not miss them
|
||||
ui.layout.setBackgroundResource(R.drawable.msg_in_unread);
|
||||
|
||||
// re-apply the previous padding due to bug in some Android versions
|
||||
// see: https://code.google.com/p/android/issues/detail?id=17885
|
||||
ui.layout.setPadding(left, top, right, bottom);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getBody() == null) {
|
||||
ui.body.setText("\u2026");
|
||||
} else if (header.getContentType().equals("text/plain")) {
|
||||
ui.body.setText(
|
||||
StringUtils.trim(StringUtils.fromUtf8(item.getBody())));
|
||||
} else {
|
||||
// TODO support other content types
|
||||
}
|
||||
|
||||
long timestamp = header.getTimestamp();
|
||||
ui.date.setText(AndroidUtils.formatDate(ctx, timestamp));
|
||||
}
|
||||
|
||||
private void bindIntroduction(IntroductionHolder ui,
|
||||
final ConversationIntroductionItem item, final int position) {
|
||||
|
||||
final IntroductionRequest ir = item.getIntroductionRequest();
|
||||
int backgroundRes;
|
||||
|
||||
String message = ir.getMessage();
|
||||
if (StringUtils.isNullOrEmpty(message)) {
|
||||
ui.message.setVisibility(GONE);
|
||||
if (item instanceof ConversationIntroductionOutItem) {
|
||||
backgroundRes = R.drawable.notice_out;
|
||||
} else {
|
||||
backgroundRes = R.drawable.notice_in;
|
||||
}
|
||||
} else {
|
||||
ui.message.setText(StringUtils.trim(message));
|
||||
ui.message.setVisibility(VISIBLE);
|
||||
if (item instanceof ConversationIntroductionOutItem) {
|
||||
backgroundRes = R.drawable.notice_out_bottom;
|
||||
} else {
|
||||
backgroundRes = R.drawable.notice_in_bottom;
|
||||
}
|
||||
}
|
||||
|
||||
// Outgoing Introduction Request
|
||||
if (item instanceof ConversationIntroductionOutItem) {
|
||||
ui.text.setText(ctx.getString(R.string.introduction_request_sent,
|
||||
contactName, ir.getName()));
|
||||
ConversationIntroductionOutItem i =
|
||||
(ConversationIntroductionOutItem) item;
|
||||
if (i.isSeen()) {
|
||||
//noinspection ConstantConditions
|
||||
ui.status.setImageResource(R.drawable.message_delivered);
|
||||
} else if (i.isSent()) {
|
||||
//noinspection ConstantConditions
|
||||
ui.status.setImageResource(R.drawable.message_sent);
|
||||
} else {
|
||||
//noinspection ConstantConditions
|
||||
ui.status.setImageResource(R.drawable.message_stored);
|
||||
}
|
||||
}
|
||||
// Incoming Introduction Request (Answered)
|
||||
else if (item.wasAnswered()) {
|
||||
ui.text.setText(ctx.getString(
|
||||
R.string.introduction_request_answered_received,
|
||||
contactName, ir.getName()));
|
||||
ui.acceptButton.setVisibility(GONE);
|
||||
ui.declineButton.setVisibility(GONE);
|
||||
}
|
||||
// Incoming Introduction Request (Not Answered)
|
||||
else {
|
||||
if (item.getIntroductionRequest().contactExists()) {
|
||||
ui.text.setText(ctx.getString(
|
||||
R.string.introduction_request_exists_received,
|
||||
contactName, ir.getName()));
|
||||
} else {
|
||||
ui.text.setText(
|
||||
ctx.getString(R.string.introduction_request_received,
|
||||
contactName, ir.getName()));
|
||||
}
|
||||
|
||||
if (item.getIntroductionRequest().doesIntroduceOtherIdentity()) {
|
||||
// don't allow accept when one of our identities is introduced
|
||||
ui.acceptButton.setVisibility(GONE);
|
||||
ui.text.setText(ctx.getString(
|
||||
R.string.introduction_request_for_our_identity_received,
|
||||
contactName, ir.getName()));
|
||||
} else {
|
||||
ui.acceptButton.setVisibility(VISIBLE);
|
||||
ui.acceptButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
intro.respondToIntroduction(ir.getSessionId(), true);
|
||||
item.setAnswered(true);
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
});
|
||||
}
|
||||
ui.declineButton.setVisibility(VISIBLE);
|
||||
ui.declineButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
intro.respondToIntroduction(ir.getSessionId(), false);
|
||||
item.setAnswered(true);
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
});
|
||||
}
|
||||
ui.date.setText(AndroidUtils.formatDate(ctx, item.getTime()));
|
||||
ui.notice.setBackgroundResource(backgroundRes);
|
||||
}
|
||||
|
||||
private void bindNotice(NoticeHolder ui, ConversationNoticeItem item) {
|
||||
ui.text.setText(item.getText());
|
||||
ui.date.setText(AndroidUtils.formatDate(ctx, item.getTime()));
|
||||
|
||||
if (item instanceof ConversationNoticeOutItem) {
|
||||
ConversationNoticeOutItem n = (ConversationNoticeOutItem) item;
|
||||
if (n.isSeen()) {
|
||||
//noinspection ConstantConditions
|
||||
ui.status.setImageResource(R.drawable.message_delivered);
|
||||
} else if (n.isSent()) {
|
||||
//noinspection ConstantConditions
|
||||
ui.status.setImageResource(R.drawable.message_sent);
|
||||
} else {
|
||||
//noinspection ConstantConditions
|
||||
ui.status.setImageResource(R.drawable.message_stored);
|
||||
}
|
||||
@Override
|
||||
public ConversationItemViewHolder onCreateViewHolder(ViewGroup viewGroup,
|
||||
@LayoutRes int type) {
|
||||
View v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
||||
type, viewGroup, false);
|
||||
switch (type) {
|
||||
case R.layout.list_item_conversation_msg_in:
|
||||
return new ConversationItemViewHolder(v);
|
||||
case R.layout.list_item_conversation_msg_out:
|
||||
return new ConversationMessageOutViewHolder(v);
|
||||
case R.layout.list_item_conversation_notice_in:
|
||||
return new ConversationNoticeInViewHolder(v);
|
||||
case R.layout.list_item_conversation_notice_out:
|
||||
return new ConversationNoticeOutViewHolder(v);
|
||||
case R.layout.list_item_conversation_request:
|
||||
return new ConversationRequestViewHolder(v);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown ConversationItem");
|
||||
}
|
||||
}
|
||||
|
||||
private void bindInvitation(InvitationHolder ui,
|
||||
final ConversationShareableInvitationItem item) {
|
||||
|
||||
final InvitationRequest ir = item.getInvitationRequest();
|
||||
String name = "";
|
||||
int receivedRes = 0, sentRes = 0, buttonRes = 0, backgroundRes;
|
||||
if (ir instanceof ForumInvitationRequest) {
|
||||
name = ((ForumInvitationRequest) ir).getForumName();
|
||||
receivedRes = R.string.forum_invitation_received;
|
||||
sentRes = R.string.forum_invitation_sent;
|
||||
buttonRes = R.string.forum_show_invitations;
|
||||
} else if (ir instanceof BlogInvitationRequest) {
|
||||
name = ((BlogInvitationRequest) ir).getBlogAuthorName();
|
||||
receivedRes = R.string.blogs_sharing_invitation_received;
|
||||
sentRes = R.string.blogs_sharing_invitation_sent;
|
||||
buttonRes = R.string.blogs_sharing_show_invitations;
|
||||
}
|
||||
|
||||
String message = ir.getMessage();
|
||||
if (StringUtils.isNullOrEmpty(message)) {
|
||||
ui.message.setVisibility(GONE);
|
||||
if (item instanceof ConversationShareableInvitationOutItem) {
|
||||
backgroundRes = R.drawable.notice_out;
|
||||
} else {
|
||||
backgroundRes = R.drawable.notice_in;
|
||||
}
|
||||
@Override
|
||||
public void onBindViewHolder(ConversationItemViewHolder ui, int position) {
|
||||
ConversationItem item = items.get(position);
|
||||
if (item instanceof ConversationRequestItem) {
|
||||
((ConversationRequestViewHolder) ui).bind(item, listener);
|
||||
} else {
|
||||
ui.message.setVisibility(VISIBLE);
|
||||
ui.message.setText(StringUtils.trim(message));
|
||||
if (item instanceof ConversationShareableInvitationOutItem) {
|
||||
backgroundRes = R.drawable.notice_out_bottom;
|
||||
} else {
|
||||
backgroundRes = R.drawable.notice_in_bottom;
|
||||
}
|
||||
ui.bind(item);
|
||||
}
|
||||
|
||||
// Outgoing Invitation
|
||||
if (item instanceof ConversationShareableInvitationOutItem) {
|
||||
ui.text.setText(ctx.getString(sentRes, name, contactName));
|
||||
ConversationShareableInvitationOutItem i =
|
||||
(ConversationShareableInvitationOutItem) item;
|
||||
if (i.isSeen()) {
|
||||
//noinspection ConstantConditions
|
||||
ui.status.setImageResource(R.drawable.message_delivered);
|
||||
} else if (i.isSent()) {
|
||||
//noinspection ConstantConditions
|
||||
ui.status.setImageResource(R.drawable.message_sent);
|
||||
} else {
|
||||
//noinspection ConstantConditions
|
||||
ui.status.setImageResource(R.drawable.message_stored);
|
||||
}
|
||||
}
|
||||
// Incoming Invitation
|
||||
else {
|
||||
ui.text.setText(ctx.getString(receivedRes, contactName, name));
|
||||
|
||||
if (ir.isAvailable()) {
|
||||
final Class c = ir instanceof ForumInvitationRequest ?
|
||||
InvitationsForumActivity.class :
|
||||
InvitationsBlogActivity.class;
|
||||
ui.showInvitationsButton.setText(ctx.getString(buttonRes));
|
||||
ui.showInvitationsButton.setVisibility(VISIBLE);
|
||||
ui.showInvitationsButton
|
||||
.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent i = new Intent(ctx, c);
|
||||
ctx.startActivity(i);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ui.showInvitationsButton.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
ui.date.setText(AndroidUtils.formatDate(ctx, item.getTime()));
|
||||
ui.notice.setBackgroundResource(backgroundRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -393,138 +102,46 @@ class ConversationAdapter extends BriarAdapter<ConversationItem, ViewHolder> {
|
||||
}
|
||||
}
|
||||
|
||||
SparseArray<IncomingItem> getIncomingMessages() {
|
||||
SparseArray<IncomingItem> messages = new SparseArray<>();
|
||||
SparseArray<ConversationInItem> getIncomingMessages() {
|
||||
SparseArray<ConversationInItem> messages = new SparseArray<>();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
ConversationItem item = items.get(i);
|
||||
if (item instanceof IncomingItem) {
|
||||
messages.put(i, (IncomingItem) item);
|
||||
if (item instanceof ConversationInItem) {
|
||||
messages.put(i, (ConversationInItem) item);
|
||||
}
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
SparseArray<OutgoingItem> getOutgoingMessages() {
|
||||
SparseArray<OutgoingItem> messages = new SparseArray<>();
|
||||
SparseArray<ConversationOutItem> getOutgoingMessages() {
|
||||
SparseArray<ConversationOutItem> messages = new SparseArray<>();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
ConversationItem item = items.get(i);
|
||||
if (item instanceof OutgoingItem) {
|
||||
messages.put(i, (OutgoingItem) item);
|
||||
if (item instanceof ConversationOutItem) {
|
||||
messages.put(i, (ConversationOutItem) item);
|
||||
}
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
SparseArray<ConversationMessageItem> getPrivateMessages() {
|
||||
SparseArray<ConversationMessageItem> messages = new SparseArray<>();
|
||||
SparseArray<ConversationItem> getPrivateMessages() {
|
||||
SparseArray<ConversationItem> messages = new SparseArray<>();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
ConversationItem item = items.get(i);
|
||||
if (item instanceof ConversationMessageItem) {
|
||||
messages.put(i, (ConversationMessageItem) item);
|
||||
if (item instanceof ConversationMessageInItem) {
|
||||
messages.put(i, item);
|
||||
} else if (item instanceof ConversationMessageOutItem) {
|
||||
messages.put(i, item);
|
||||
}
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
private static class MessageHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public ViewGroup layout;
|
||||
public TextView body;
|
||||
private TextView date;
|
||||
public ImageView status;
|
||||
|
||||
private MessageHolder(View v, int type) {
|
||||
super(v);
|
||||
|
||||
layout = (ViewGroup) v.findViewById(R.id.msgLayout);
|
||||
body = (TextView) v.findViewById(R.id.msgBody);
|
||||
date = (TextView) v.findViewById(R.id.msgTime);
|
||||
|
||||
// outgoing message (local)
|
||||
if (type == MSG_OUT) {
|
||||
status = (ImageView) v.findViewById(R.id.msgStatus);
|
||||
}
|
||||
}
|
||||
interface RequestListener {
|
||||
void respondToRequest(ConversationRequestItem item, boolean accept);
|
||||
}
|
||||
|
||||
private static class IntroductionHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private final TextView message;
|
||||
private final ViewGroup notice;
|
||||
private final TextView text;
|
||||
private final Button acceptButton;
|
||||
private final Button declineButton;
|
||||
private final TextView date;
|
||||
private final ImageView status;
|
||||
|
||||
private IntroductionHolder(View v, int type) {
|
||||
super(v);
|
||||
|
||||
message = (TextView) v.findViewById(R.id.msgBody);
|
||||
notice = (ViewGroup) v.findViewById(R.id.noticeLayout);
|
||||
text = (TextView) v.findViewById(R.id.introductionText);
|
||||
acceptButton = (Button) v.findViewById(R.id.acceptButton);
|
||||
declineButton = (Button) v.findViewById(R.id.declineButton);
|
||||
date = (TextView) v.findViewById(R.id.introductionTime);
|
||||
|
||||
if (type == INTRODUCTION_OUT) {
|
||||
status = (ImageView) v.findViewById(R.id.introductionStatus);
|
||||
} else {
|
||||
status = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class NoticeHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private final TextView text;
|
||||
private final TextView date;
|
||||
private final ImageView status;
|
||||
|
||||
private NoticeHolder(View v, int type) {
|
||||
super(v);
|
||||
|
||||
text = (TextView) v.findViewById(R.id.noticeText);
|
||||
date = (TextView) v.findViewById(R.id.noticeTime);
|
||||
|
||||
if (type == NOTICE_OUT) {
|
||||
status = (ImageView) v.findViewById(R.id.noticeStatus);
|
||||
} else {
|
||||
status = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class InvitationHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private final TextView message;
|
||||
private final View notice;
|
||||
private final TextView text;
|
||||
private final Button showInvitationsButton;
|
||||
private final TextView date;
|
||||
private final ImageView status;
|
||||
|
||||
private InvitationHolder(View v, int type) {
|
||||
super(v);
|
||||
|
||||
message = (TextView) v.findViewById(R.id.msgBody);
|
||||
text = (TextView) v.findViewById(R.id.introductionText);
|
||||
notice = v.findViewById(R.id.noticeLayout);
|
||||
showInvitationsButton = (Button) v.findViewById(R.id.showInvitationsButton);
|
||||
date = (TextView) v.findViewById(R.id.introductionTime);
|
||||
|
||||
if (type == FORUM_INVITATION_OUT || type == BLOG_INVITATION_OUT) {
|
||||
status = (ImageView) v.findViewById(R.id.introductionStatus);
|
||||
} else {
|
||||
status = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface IntroductionHandler {
|
||||
void respondToIntroduction(SessionId sessionId, boolean accept);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
abstract class ConversationInItem extends ConversationItem {
|
||||
|
||||
private boolean read;
|
||||
|
||||
ConversationInItem(MessageId id, GroupId groupId, @Nullable String text,
|
||||
long time, boolean read) {
|
||||
super(id, groupId, text, time);
|
||||
|
||||
this.read = read;
|
||||
}
|
||||
|
||||
public boolean isRead() {
|
||||
return read;
|
||||
}
|
||||
|
||||
public void setRead(boolean read) {
|
||||
this.read = read;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.android.contact.ConversationItem.IncomingItem;
|
||||
import org.briarproject.api.introduction.IntroductionRequest;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
// This class is not thread-safe
|
||||
class ConversationIntroductionInItem extends ConversationIntroductionItem
|
||||
implements IncomingItem {
|
||||
|
||||
private boolean read;
|
||||
|
||||
ConversationIntroductionInItem(@NotNull IntroductionRequest ir) {
|
||||
super(ir);
|
||||
|
||||
this.read = ir.isRead();
|
||||
}
|
||||
|
||||
@Override
|
||||
int getType() {
|
||||
return INTRODUCTION_IN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRead() {
|
||||
return read;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRead(boolean read) {
|
||||
this.read = read;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.introduction.IntroductionRequest;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
// This class is not thread-safe
|
||||
abstract class ConversationIntroductionItem extends ConversationItem {
|
||||
|
||||
private final IntroductionRequest ir;
|
||||
private boolean answered;
|
||||
|
||||
ConversationIntroductionItem(@NotNull IntroductionRequest ir) {
|
||||
super(ir.getMessageId(), ir.getGroupId(), ir.getTimestamp());
|
||||
|
||||
this.ir = ir;
|
||||
this.answered = ir.wasAnswered();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
IntroductionRequest getIntroductionRequest() {
|
||||
return ir;
|
||||
}
|
||||
|
||||
boolean wasAnswered() {
|
||||
return answered;
|
||||
}
|
||||
|
||||
void setAnswered(boolean answered) {
|
||||
this.answered = answered;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.introduction.IntroductionRequest;
|
||||
|
||||
/**
|
||||
* This class is needed and can not be replaced by an ConversationNoticeOutItem,
|
||||
* because it carries the optional introduction message
|
||||
* to be displayed as a regular private message.
|
||||
*
|
||||
* This class is not thread-safe
|
||||
*/
|
||||
class ConversationIntroductionOutItem extends ConversationIntroductionItem
|
||||
implements ConversationItem.OutgoingItem {
|
||||
|
||||
private boolean sent, seen;
|
||||
|
||||
ConversationIntroductionOutItem(IntroductionRequest ir) {
|
||||
super(ir);
|
||||
this.sent = ir.isSent();
|
||||
this.seen = ir.isSeen();
|
||||
}
|
||||
|
||||
@Override
|
||||
int getType() {
|
||||
return INTRODUCTION_OUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSent() {
|
||||
return sent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSent(boolean sent) {
|
||||
this.sent = sent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSeen() {
|
||||
return seen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSeen(boolean seen) {
|
||||
this.seen = seen;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +1,64 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.StringRes;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.api.blogs.BlogInvitationResponse;
|
||||
import org.briarproject.android.contact.ConversationRequestItem.RequestType;
|
||||
import org.briarproject.api.blogs.BlogInvitationRequest;
|
||||
import org.briarproject.api.forum.ForumInvitationRequest;
|
||||
import org.briarproject.api.forum.ForumInvitationResponse;
|
||||
import org.briarproject.api.introduction.IntroductionMessage;
|
||||
import org.briarproject.api.introduction.IntroductionRequest;
|
||||
import org.briarproject.api.introduction.IntroductionResponse;
|
||||
import org.briarproject.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.api.sharing.InvitationMessage;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.api.sharing.InvitationRequest;
|
||||
import org.briarproject.api.sharing.InvitationResponse;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
// This class is not thread-safe
|
||||
public abstract class ConversationItem {
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
// this is needed for RecyclerView adapter which requires an int type
|
||||
final static int MSG_IN = 0;
|
||||
final static int MSG_IN_UNREAD = 1;
|
||||
final static int MSG_OUT = 2;
|
||||
final static int INTRODUCTION_IN = 3;
|
||||
final static int INTRODUCTION_OUT = 4;
|
||||
final static int NOTICE_IN = 5;
|
||||
final static int NOTICE_OUT = 6;
|
||||
final static int FORUM_INVITATION_IN = 7;
|
||||
final static int FORUM_INVITATION_OUT = 8;
|
||||
final static int BLOG_INVITATION_IN = 9;
|
||||
final static int BLOG_INVITATION_OUT = 10;
|
||||
import static org.briarproject.android.contact.ConversationRequestItem.RequestType.BLOG;
|
||||
import static org.briarproject.android.contact.ConversationRequestItem.RequestType.FORUM;
|
||||
import static org.briarproject.android.contact.ConversationRequestItem.RequestType.INTRODUCTION;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
abstract class ConversationItem {
|
||||
|
||||
final private MessageId id;
|
||||
final private GroupId groupId;
|
||||
protected @Nullable String text;
|
||||
final private long time;
|
||||
|
||||
public ConversationItem(@NotNull MessageId id, @NotNull GroupId groupId,
|
||||
long time) {
|
||||
ConversationItem(MessageId id, GroupId groupId,
|
||||
@Nullable String text, long time) {
|
||||
this.id = id;
|
||||
this.groupId = groupId;
|
||||
this.text = text;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
abstract int getType();
|
||||
|
||||
@NotNull
|
||||
public MessageId getId() {
|
||||
MessageId getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GroupId getGroupId() {
|
||||
GroupId getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public static ConversationMessageItem from(PrivateMessageHeader h) {
|
||||
static ConversationItem from(PrivateMessageHeader h) {
|
||||
if (h.isLocal()) {
|
||||
return new ConversationMessageOutItem(h);
|
||||
} else {
|
||||
@@ -67,17 +66,40 @@ public abstract class ConversationItem {
|
||||
}
|
||||
}
|
||||
|
||||
public static ConversationIntroductionItem from(IntroductionRequest ir) {
|
||||
static ConversationItem from(Context ctx, String contactName,
|
||||
IntroductionRequest ir) {
|
||||
if (ir.isLocal()) {
|
||||
return new ConversationIntroductionOutItem(ir);
|
||||
String text = ctx.getString(R.string.introduction_request_sent,
|
||||
contactName, ir.getName());
|
||||
return new ConversationNoticeOutItem(ir.getMessageId(),
|
||||
ir.getGroupId(), text, ir.getMessage(), ir.getTimestamp(),
|
||||
ir.isSent(), ir.isSeen());
|
||||
} else {
|
||||
return new ConversationIntroductionInItem(ir);
|
||||
String text;
|
||||
if (ir.wasAnswered()) {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_request_answered_received,
|
||||
contactName, ir.getName());
|
||||
return new ConversationNoticeInItem(ir.getMessageId(),
|
||||
ir.getGroupId(), text, ir.getMessage(), ir.getTimestamp(),
|
||||
ir.isRead());
|
||||
} else if (ir.contactExists()){
|
||||
text = ctx.getString(
|
||||
R.string.introduction_request_exists_received,
|
||||
contactName, ir.getName());
|
||||
} else {
|
||||
text = ctx.getString(R.string.introduction_request_received,
|
||||
contactName, ir.getName());
|
||||
}
|
||||
return new ConversationRequestItem(ir.getMessageId(),
|
||||
ir.getGroupId(), INTRODUCTION, ir.getSessionId(), text,
|
||||
ir.getMessage(), ir.getTimestamp(), ir.isRead(),
|
||||
ir.wasAnswered());
|
||||
}
|
||||
}
|
||||
|
||||
public static ConversationNoticeItem from(Context ctx, String contactName,
|
||||
static ConversationItem from(Context ctx, String contactName,
|
||||
IntroductionResponse ir) {
|
||||
|
||||
if (ir.isLocal()) {
|
||||
String text;
|
||||
if (ir.wasAccepted()) {
|
||||
@@ -90,7 +112,7 @@ public abstract class ConversationItem {
|
||||
ir.getName());
|
||||
}
|
||||
return new ConversationNoticeOutItem(ir.getMessageId(),
|
||||
ir.getGroupId(), text, ir.getTimestamp(), ir.isSent(),
|
||||
ir.getGroupId(), text, null, ir.getTimestamp(), ir.isSent(),
|
||||
ir.isSeen());
|
||||
} else {
|
||||
String text;
|
||||
@@ -110,143 +132,99 @@ public abstract class ConversationItem {
|
||||
}
|
||||
}
|
||||
return new ConversationNoticeInItem(ir.getMessageId(),
|
||||
ir.getGroupId(), text, ir.getTimestamp(), ir.isRead());
|
||||
ir.getGroupId(), text, null, ir.getTimestamp(),
|
||||
ir.isRead());
|
||||
}
|
||||
}
|
||||
|
||||
public static ConversationShareableInvitationItem from(
|
||||
InvitationRequest fim) {
|
||||
if (fim.isLocal()) {
|
||||
return new ConversationShareableInvitationOutItem(fim);
|
||||
static ConversationItem from(Context ctx, String contactName,
|
||||
InvitationRequest ir) {
|
||||
if (ir.isLocal()) {
|
||||
String text;
|
||||
if (ir instanceof ForumInvitationRequest) {
|
||||
text = ctx.getString(R.string.forum_invitation_sent,
|
||||
((ForumInvitationRequest) ir).getForumName(),
|
||||
contactName);
|
||||
} else {
|
||||
text = ctx.getString(R.string.blogs_sharing_invitation_sent,
|
||||
((BlogInvitationRequest) ir).getBlogAuthorName(),
|
||||
contactName);
|
||||
}
|
||||
return new ConversationNoticeOutItem(ir.getId(), ir.getGroupId(),
|
||||
text, ir.getMessage(), ir.getTimestamp(), ir.isSent(),
|
||||
ir.isSeen());
|
||||
} else {
|
||||
return new ConversationShareableInvitationInItem(fim);
|
||||
String text;
|
||||
RequestType type;
|
||||
if (ir instanceof ForumInvitationRequest) {
|
||||
text = ctx.getString(R.string.forum_invitation_received,
|
||||
contactName,
|
||||
((ForumInvitationRequest) ir).getForumName());
|
||||
type = FORUM;
|
||||
} else {
|
||||
text = ctx.getString(R.string.blogs_sharing_invitation_received,
|
||||
contactName,
|
||||
((BlogInvitationRequest) ir).getBlogAuthorName());
|
||||
type = BLOG;
|
||||
}
|
||||
if (!ir.isAvailable()) {
|
||||
return new ConversationNoticeInItem(ir.getId(), ir.getGroupId(),
|
||||
text, ir.getMessage(), ir.getTimestamp(), ir.isRead());
|
||||
}
|
||||
return new ConversationRequestItem(ir.getId(),
|
||||
ir.getGroupId(), type, ir.getSessionId(), text,
|
||||
ir.getMessage(), ir.getTimestamp(), ir.isRead(),
|
||||
!ir.isAvailable());
|
||||
}
|
||||
}
|
||||
|
||||
public static ConversationNoticeItem from(Context ctx, String contactName,
|
||||
static ConversationItem from(Context ctx, String contactName,
|
||||
InvitationResponse ir) {
|
||||
|
||||
if (ir instanceof ForumInvitationResponse) {
|
||||
return from(ctx, contactName, (ForumInvitationResponse) ir);
|
||||
} else if (ir instanceof BlogInvitationResponse) {
|
||||
return from(ctx, contactName, (BlogInvitationResponse) ir);
|
||||
@StringRes int res;
|
||||
if (ir.isLocal()) {
|
||||
if (ir.wasAccepted()) {
|
||||
if (ir instanceof ForumInvitationResponse) {
|
||||
res = R.string.forum_invitation_response_accepted_sent;
|
||||
} else {
|
||||
res = R.string.blogs_sharing_response_accepted_sent;
|
||||
}
|
||||
} else {
|
||||
if (ir instanceof ForumInvitationResponse) {
|
||||
res = R.string.forum_invitation_response_declined_sent;
|
||||
} else {
|
||||
res = R.string.blogs_sharing_response_declined_sent;
|
||||
}
|
||||
}
|
||||
String text = ctx.getString(res, contactName);
|
||||
return new ConversationNoticeOutItem(ir.getId(), ir.getGroupId(),
|
||||
text, null, ir.getTimestamp(), ir.isSent(), ir.isSeen());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown Invitation Response.");
|
||||
if (ir.wasAccepted()) {
|
||||
if (ir instanceof ForumInvitationResponse) {
|
||||
res = R.string.forum_invitation_response_accepted_received;
|
||||
} else {
|
||||
res = R.string.blogs_sharing_response_accepted_received;
|
||||
}
|
||||
} else {
|
||||
if (ir instanceof ForumInvitationResponse) {
|
||||
res = R.string.forum_invitation_response_declined_received;
|
||||
} else {
|
||||
res = R.string.blogs_sharing_response_declined_received;
|
||||
}
|
||||
}
|
||||
String text = ctx.getString(res, contactName);
|
||||
return new ConversationNoticeInItem(ir.getId(), ir.getGroupId(),
|
||||
text, null, ir.getTimestamp(), ir.isRead());
|
||||
}
|
||||
}
|
||||
|
||||
private static ConversationNoticeItem from(Context ctx, String contactName,
|
||||
ForumInvitationResponse fir) {
|
||||
interface PartialItem {
|
||||
|
||||
@Nullable
|
||||
String getText();
|
||||
|
||||
void setText(String text);
|
||||
|
||||
if (fir.isLocal()) {
|
||||
String text;
|
||||
if (fir.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.forum_invitation_response_accepted_sent,
|
||||
contactName);
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.forum_invitation_response_declined_sent,
|
||||
contactName);
|
||||
}
|
||||
return new ConversationNoticeOutItem(fir.getId(), fir.getGroupId(),
|
||||
text, fir.getTimestamp(), fir.isSent(), fir.isSeen());
|
||||
} else {
|
||||
String text;
|
||||
if (fir.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.forum_invitation_response_accepted_received,
|
||||
contactName);
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.forum_invitation_response_declined_received,
|
||||
contactName);
|
||||
}
|
||||
return new ConversationNoticeInItem(fir.getId(), fir.getGroupId(),
|
||||
text, fir.getTimestamp(), fir.isRead());
|
||||
}
|
||||
}
|
||||
|
||||
private static ConversationNoticeItem from(Context ctx, String contactName,
|
||||
BlogInvitationResponse fir) {
|
||||
|
||||
if (fir.isLocal()) {
|
||||
String text;
|
||||
if (fir.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.blogs_sharing_response_accepted_sent,
|
||||
contactName);
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.blogs_sharing_response_declined_sent,
|
||||
contactName);
|
||||
}
|
||||
return new ConversationNoticeOutItem(fir.getId(), fir.getGroupId(),
|
||||
text, fir.getTimestamp(), fir.isSent(), fir.isSeen());
|
||||
} else {
|
||||
String text;
|
||||
if (fir.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.blogs_sharing_response_accepted_received,
|
||||
contactName);
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.blogs_sharing_response_declined_received,
|
||||
contactName);
|
||||
}
|
||||
return new ConversationNoticeInItem(fir.getId(), fir.getGroupId(),
|
||||
text, fir.getTimestamp(), fir.isRead());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be used to get user-facing objects,
|
||||
* Its purpose is only to provide data for the contact list.
|
||||
*/
|
||||
public static ConversationItem from(IntroductionMessage im) {
|
||||
if (im.isLocal())
|
||||
return new ConversationNoticeOutItem(im.getMessageId(),
|
||||
im.getGroupId(), "", im.getTimestamp(), false, false);
|
||||
return new ConversationNoticeInItem(im.getMessageId(), im.getGroupId(),
|
||||
"", im.getTimestamp(), im.isRead());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be used to get user-facing objects,
|
||||
* Its purpose is only to provide data for the contact list.
|
||||
*/
|
||||
public static ConversationItem from(InvitationMessage im) {
|
||||
if (im.isLocal())
|
||||
return new ConversationNoticeOutItem(im.getId(), im.getGroupId(),
|
||||
"", im.getTimestamp(), false, false);
|
||||
return new ConversationNoticeInItem(im.getId(), im.getGroupId(), "",
|
||||
im.getTimestamp(), im.isRead());
|
||||
}
|
||||
|
||||
interface OutgoingItem {
|
||||
|
||||
@NotNull
|
||||
MessageId getId();
|
||||
|
||||
boolean isSent();
|
||||
|
||||
void setSent(boolean sent);
|
||||
|
||||
boolean isSeen();
|
||||
|
||||
void setSeen(boolean seen);
|
||||
}
|
||||
|
||||
interface IncomingItem {
|
||||
|
||||
@NotNull
|
||||
MessageId getId();
|
||||
|
||||
@NotNull
|
||||
GroupId getGroupId();
|
||||
|
||||
boolean isRead();
|
||||
|
||||
void setRead(boolean read);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import android.support.annotation.CallSuper;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.util.AndroidUtils;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class ConversationItemViewHolder extends ViewHolder {
|
||||
|
||||
protected final ViewGroup layout;
|
||||
private final TextView text;
|
||||
private final TextView time;
|
||||
|
||||
ConversationItemViewHolder(View v) {
|
||||
super(v);
|
||||
layout = (ViewGroup) v.findViewById(R.id.layout);
|
||||
text = (TextView) v.findViewById(R.id.text);
|
||||
time = (TextView) v.findViewById(R.id.time);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
void bind(ConversationItem item) {
|
||||
if (item.getText() == null) {
|
||||
text.setText("\u2026");
|
||||
} else {
|
||||
text.setText(StringUtils.trim(item.getText()));
|
||||
}
|
||||
|
||||
long timestamp = item.getTime();
|
||||
time.setText(AndroidUtils.formatDate(time.getContext(), timestamp));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +1,22 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.android.contact.ConversationItem.PartialItem;
|
||||
import org.briarproject.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
|
||||
// This class is not thread-safe
|
||||
class ConversationMessageInItem extends ConversationMessageItem
|
||||
implements ConversationItem.IncomingItem {
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
private boolean read;
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
class ConversationMessageInItem extends ConversationInItem
|
||||
implements PartialItem {
|
||||
|
||||
ConversationMessageInItem(PrivateMessageHeader header) {
|
||||
super(header);
|
||||
|
||||
read = header.isRead();
|
||||
ConversationMessageInItem(PrivateMessageHeader h) {
|
||||
super(h.getId(), h.getGroupId(), null, h.getTimestamp(), h.isRead());
|
||||
}
|
||||
|
||||
@Override
|
||||
int getType() {
|
||||
return MSG_IN;
|
||||
public void setText(String body) {
|
||||
text = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRead() {
|
||||
return read;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRead(boolean read) {
|
||||
this.read = read;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.messaging.PrivateMessageHeader;
|
||||
|
||||
// This class is not thread-safe
|
||||
abstract class ConversationMessageItem extends ConversationItem {
|
||||
|
||||
private final PrivateMessageHeader header;
|
||||
private byte[] body;
|
||||
|
||||
ConversationMessageItem(PrivateMessageHeader header) {
|
||||
super(header.getId(), header.getGroupId(), header.getTimestamp());
|
||||
|
||||
this.header = header;
|
||||
body = null;
|
||||
}
|
||||
|
||||
PrivateMessageHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
byte[] getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
void setBody(byte[] body) {
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,23 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.android.contact.ConversationItem.PartialItem;
|
||||
import org.briarproject.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
|
||||
// This class is not thread-safe
|
||||
class ConversationMessageOutItem extends ConversationMessageItem
|
||||
implements ConversationItem.OutgoingItem {
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
private boolean sent, seen;
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
class ConversationMessageOutItem extends ConversationOutItem
|
||||
implements PartialItem {
|
||||
|
||||
ConversationMessageOutItem(PrivateMessageHeader header) {
|
||||
super(header);
|
||||
|
||||
sent = header.isSent();
|
||||
seen = header.isSeen();
|
||||
ConversationMessageOutItem(PrivateMessageHeader h) {
|
||||
super(h.getId(), h.getGroupId(), null, h.getTimestamp(), h.isSent(),
|
||||
h.isSeen());
|
||||
}
|
||||
|
||||
@Override
|
||||
int getType() {
|
||||
return MSG_OUT;
|
||||
public void setText(String body) {
|
||||
text = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSent() {
|
||||
return sent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSent(boolean sent) {
|
||||
this.sent = sent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSeen() {
|
||||
return seen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSeen(boolean seen) {
|
||||
this.seen = seen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
class ConversationMessageOutViewHolder extends ConversationOutItemViewHolder {
|
||||
|
||||
ConversationMessageOutViewHolder(View v) {
|
||||
super(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasDarkBackground() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +1,29 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
// This class is not thread-safe
|
||||
class ConversationNoticeInItem extends ConversationNoticeItem
|
||||
implements ConversationItem.IncomingItem {
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
private boolean read;
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
class ConversationNoticeInItem extends ConversationInItem {
|
||||
|
||||
ConversationNoticeInItem(MessageId id, GroupId groupId, String text,
|
||||
long time, boolean read) {
|
||||
super(id, groupId, text, time);
|
||||
@Nullable
|
||||
private final String msgText;
|
||||
|
||||
this.read = read;
|
||||
ConversationNoticeInItem(MessageId id, GroupId groupId,
|
||||
String text, @Nullable String msgText, long time,
|
||||
boolean read) {
|
||||
super(id, groupId, text, time, read);
|
||||
this.msgText = msgText;
|
||||
}
|
||||
|
||||
@Override
|
||||
int getType() {
|
||||
return NOTICE_IN;
|
||||
@Nullable
|
||||
public String getMsgText() {
|
||||
return msgText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRead() {
|
||||
return read;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRead(boolean read) {
|
||||
this.read = read;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class ConversationNoticeInViewHolder extends ConversationItemViewHolder {
|
||||
|
||||
private final TextView msgText;
|
||||
|
||||
ConversationNoticeInViewHolder(View v) {
|
||||
super(v);
|
||||
msgText = (TextView) v.findViewById(R.id.msgText);
|
||||
}
|
||||
|
||||
@Override
|
||||
void bind(ConversationItem conversationItem) {
|
||||
super.bind(conversationItem);
|
||||
|
||||
ConversationNoticeInItem item =
|
||||
(ConversationNoticeInItem) conversationItem;
|
||||
|
||||
String message = item.getMsgText();
|
||||
if (StringUtils.isNullOrEmpty(message)) {
|
||||
msgText.setVisibility(GONE);
|
||||
layout.setBackgroundResource(R.drawable.notice_in);
|
||||
} else {
|
||||
msgText.setVisibility(VISIBLE);
|
||||
msgText.setText(StringUtils.trim(message));
|
||||
layout.setBackgroundResource(R.drawable.notice_in_bottom);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
|
||||
abstract class ConversationNoticeItem extends ConversationItem {
|
||||
|
||||
private final String text;
|
||||
|
||||
ConversationNoticeItem(MessageId id, GroupId groupId, String text,
|
||||
long time) {
|
||||
super(id, groupId, time);
|
||||
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +1,29 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
// This class is not thread-safe
|
||||
class ConversationNoticeOutItem extends ConversationNoticeItem
|
||||
implements ConversationItem.OutgoingItem {
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
private boolean sent, seen;
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
class ConversationNoticeOutItem extends ConversationOutItem {
|
||||
|
||||
ConversationNoticeOutItem(MessageId id, GroupId groupId, String text,
|
||||
long time, boolean sent, boolean seen) {
|
||||
super(id, groupId, text, time);
|
||||
@Nullable
|
||||
private final String msgText;
|
||||
|
||||
this.sent = sent;
|
||||
this.seen = seen;
|
||||
ConversationNoticeOutItem(MessageId id, GroupId groupId,
|
||||
String text, @Nullable String msgText, long time,
|
||||
boolean sent, boolean seen) {
|
||||
super(id, groupId, text, time, sent, seen);
|
||||
this.msgText = msgText;
|
||||
}
|
||||
|
||||
@Override
|
||||
int getType() {
|
||||
return NOTICE_OUT;
|
||||
@Nullable
|
||||
public String getMsgText() {
|
||||
return msgText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSent() {
|
||||
return sent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSent(boolean sent) {
|
||||
this.sent = sent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSeen() {
|
||||
return seen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSeen(boolean seen) {
|
||||
this.seen = seen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class ConversationNoticeOutViewHolder extends ConversationOutItemViewHolder {
|
||||
|
||||
private final TextView msgText;
|
||||
|
||||
ConversationNoticeOutViewHolder(View v) {
|
||||
super(v);
|
||||
msgText = (TextView) v.findViewById(R.id.msgText);
|
||||
}
|
||||
|
||||
@Override
|
||||
void bind(ConversationItem conversationItem) {
|
||||
super.bind(conversationItem);
|
||||
|
||||
ConversationNoticeOutItem item =
|
||||
(ConversationNoticeOutItem) conversationItem;
|
||||
|
||||
String message = item.getMsgText();
|
||||
if (StringUtils.isNullOrEmpty(message)) {
|
||||
msgText.setVisibility(GONE);
|
||||
layout.setBackgroundResource(R.drawable.notice_out);
|
||||
} else {
|
||||
msgText.setVisibility(VISIBLE);
|
||||
msgText.setText(StringUtils.trim(message));
|
||||
layout.setBackgroundResource(R.drawable.notice_out_bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasDarkBackground() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
abstract class ConversationOutItem extends ConversationItem {
|
||||
|
||||
private boolean sent, seen;
|
||||
|
||||
ConversationOutItem(MessageId id, GroupId groupId, @Nullable String text,
|
||||
long time, boolean sent, boolean seen) {
|
||||
super(id, groupId, text, time);
|
||||
|
||||
this.sent = sent;
|
||||
this.seen = seen;
|
||||
}
|
||||
|
||||
public boolean isSent() {
|
||||
return sent;
|
||||
}
|
||||
|
||||
public void setSent(boolean sent) {
|
||||
this.sent = sent;
|
||||
}
|
||||
|
||||
public boolean isSeen() {
|
||||
return seen;
|
||||
}
|
||||
|
||||
public void setSeen(boolean seen) {
|
||||
this.seen = seen;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
abstract class ConversationOutItemViewHolder
|
||||
extends ConversationItemViewHolder {
|
||||
|
||||
private final ImageView status;
|
||||
|
||||
ConversationOutItemViewHolder(View v) {
|
||||
super(v);
|
||||
status = (ImageView) v.findViewById(R.id.status);
|
||||
}
|
||||
|
||||
@Override
|
||||
void bind(ConversationItem conversationItem) {
|
||||
super.bind(conversationItem);
|
||||
|
||||
ConversationOutItem item = (ConversationOutItem) conversationItem;
|
||||
|
||||
int res;
|
||||
if (item.isSeen()) {
|
||||
if (hasDarkBackground()) res = R.drawable.message_delivered_white;
|
||||
else res = R.drawable.message_delivered;
|
||||
} else if (item.isSent()) {
|
||||
if (hasDarkBackground()) res = R.drawable.message_sent_white;
|
||||
else res = R.drawable.message_sent;
|
||||
} else {
|
||||
if (hasDarkBackground()) res = R.drawable.message_stored_white;
|
||||
else res = R.drawable.message_stored;
|
||||
}
|
||||
status.setImageResource(res);
|
||||
}
|
||||
|
||||
protected abstract boolean hasDarkBackground();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.clients.SessionId;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
class ConversationRequestItem extends ConversationNoticeInItem {
|
||||
|
||||
enum RequestType { INTRODUCTION, FORUM, BLOG };
|
||||
private final RequestType requestType;
|
||||
private final SessionId sessionId;
|
||||
private boolean answered;
|
||||
|
||||
ConversationRequestItem(MessageId id, GroupId groupId,
|
||||
RequestType requestType, SessionId sessionId, String text,
|
||||
@Nullable String msgText, long time, boolean read,
|
||||
boolean answered) {
|
||||
super(id, groupId, text, msgText, time, read);
|
||||
this.requestType = requestType;
|
||||
this.sessionId = sessionId;
|
||||
this.answered = answered;
|
||||
}
|
||||
|
||||
public RequestType getRequestType() {
|
||||
return requestType;
|
||||
}
|
||||
|
||||
public SessionId getSessionId() {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
boolean wasAnswered() {
|
||||
return answered;
|
||||
}
|
||||
|
||||
void setAnswered(boolean answered) {
|
||||
this.answered = answered;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.contact.ConversationAdapter.RequestListener;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class ConversationRequestViewHolder extends ConversationNoticeInViewHolder {
|
||||
|
||||
private final Button acceptButton;
|
||||
private final Button declineButton;
|
||||
|
||||
ConversationRequestViewHolder(View v) {
|
||||
super(v);
|
||||
acceptButton = (Button) v.findViewById(R.id.acceptButton);
|
||||
declineButton = (Button) v.findViewById(R.id.declineButton);
|
||||
}
|
||||
|
||||
void bind(ConversationItem conversationItem,
|
||||
final RequestListener listener) {
|
||||
super.bind(conversationItem);
|
||||
|
||||
final ConversationRequestItem item =
|
||||
(ConversationRequestItem) conversationItem;
|
||||
|
||||
if (item.wasAnswered()) {
|
||||
acceptButton.setVisibility(GONE);
|
||||
declineButton.setVisibility(GONE);
|
||||
} else {
|
||||
acceptButton.setVisibility(VISIBLE);
|
||||
acceptButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
item.setAnswered(true);
|
||||
listener.respondToRequest(item, true);
|
||||
}
|
||||
});
|
||||
declineButton.setVisibility(VISIBLE);
|
||||
declineButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
item.setAnswered(true);
|
||||
listener.respondToRequest(item, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.blogs.BlogInvitationRequest;
|
||||
import org.briarproject.api.forum.ForumInvitationRequest;
|
||||
import org.briarproject.api.sharing.InvitationRequest;
|
||||
|
||||
// This class is not thread-safe
|
||||
class ConversationShareableInvitationInItem
|
||||
extends ConversationShareableInvitationItem
|
||||
implements ConversationItem.IncomingItem {
|
||||
|
||||
private final int type;
|
||||
private boolean read;
|
||||
|
||||
ConversationShareableInvitationInItem(InvitationRequest ir) {
|
||||
super(ir);
|
||||
|
||||
if (ir instanceof ForumInvitationRequest) {
|
||||
this.type = FORUM_INVITATION_IN;
|
||||
} else if (ir instanceof BlogInvitationRequest) {
|
||||
this.type = BLOG_INVITATION_IN;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown Invitation Type.");
|
||||
}
|
||||
|
||||
this.read = ir.isRead();
|
||||
}
|
||||
|
||||
@Override
|
||||
int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRead() {
|
||||
return read;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRead(boolean read) {
|
||||
this.read = read;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.sharing.InvitationRequest;
|
||||
|
||||
abstract class ConversationShareableInvitationItem extends ConversationItem {
|
||||
|
||||
private final InvitationRequest fim;
|
||||
|
||||
ConversationShareableInvitationItem(InvitationRequest fim) {
|
||||
super(fim.getId(), fim.getGroupId(), fim.getTimestamp());
|
||||
|
||||
this.fim = fim;
|
||||
}
|
||||
|
||||
InvitationRequest getInvitationRequest() {
|
||||
return fim;
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package org.briarproject.android.contact;
|
||||
|
||||
import org.briarproject.api.blogs.BlogInvitationRequest;
|
||||
import org.briarproject.api.forum.ForumInvitationRequest;
|
||||
import org.briarproject.api.sharing.InvitationRequest;
|
||||
|
||||
/**
|
||||
* This class is needed and can not be replaced by an ConversationNoticeOutItem,
|
||||
* because it carries the optional invitation message
|
||||
* to be displayed as a regular private message.
|
||||
* <p/>
|
||||
* This class is not thread-safe
|
||||
*/
|
||||
class ConversationShareableInvitationOutItem
|
||||
extends ConversationShareableInvitationItem
|
||||
implements ConversationItem.OutgoingItem {
|
||||
|
||||
private final int type;
|
||||
private boolean sent, seen;
|
||||
|
||||
ConversationShareableInvitationOutItem(InvitationRequest ir) {
|
||||
super(ir);
|
||||
|
||||
if (ir instanceof ForumInvitationRequest) {
|
||||
this.type = FORUM_INVITATION_OUT;
|
||||
} else if (ir instanceof BlogInvitationRequest) {
|
||||
this.type = BLOG_INVITATION_OUT;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown Invitation Type.");
|
||||
}
|
||||
|
||||
this.sent = ir.isSent();
|
||||
this.seen = ir.isSeen();
|
||||
}
|
||||
|
||||
@Override
|
||||
int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSent() {
|
||||
return sent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSent(boolean sent) {
|
||||
this.sent = sent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSeen() {
|
||||
return seen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSeen(boolean seen) {
|
||||
this.seen = seen;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user