@ -25,10 +25,8 @@ import android.content.res.TypedArray;
import android.graphics.Bitmap ;
import android.graphics.Bitmap ;
import android.graphics.Color ;
import android.graphics.Color ;
import android.graphics.drawable.ColorDrawable ;
import android.graphics.drawable.ColorDrawable ;
import android.net.Uri ;
import android.os.Handler ;
import android.os.Handler ;
import android.os.Message ;
import android.os.Message ;
import android.provider.Contacts.Intents ;
import android.provider.ContactsContract ;
import android.provider.ContactsContract ;
import android.provider.ContactsContract.QuickContact ;
import android.provider.ContactsContract.QuickContact ;
import android.util.AttributeSet ;
import android.util.AttributeSet ;
@ -40,9 +38,10 @@ import android.widget.LinearLayout;
import android.widget.TextView ;
import android.widget.TextView ;
import android.widget.Toast ;
import android.widget.Toast ;
import org.thoughtcrime.securesms.ConversationFragment.SelectionClickListener ;
import org.thoughtcrime.securesms.contacts.ContactPhotoFactory ;
import org.thoughtcrime.securesms.crypto.MasterSecret ;
import org.thoughtcrime.securesms.crypto.MasterSecret ;
import org.thoughtcrime.securesms.database.DatabaseFactory ;
import org.thoughtcrime.securesms.database.DatabaseFactory ;
import org.thoughtcrime.securesms.contacts.ContactPhotoFactory ;
import org.thoughtcrime.securesms.database.MmsDatabase ;
import org.thoughtcrime.securesms.database.MmsDatabase ;
import org.thoughtcrime.securesms.database.SmsDatabase ;
import org.thoughtcrime.securesms.database.SmsDatabase ;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord ;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord ;
@ -61,6 +60,8 @@ import org.thoughtcrime.securesms.util.Emoji;
import org.thoughtcrime.securesms.util.FutureTaskListener ;
import org.thoughtcrime.securesms.util.FutureTaskListener ;
import org.thoughtcrime.securesms.util.ListenableFutureTask ;
import org.thoughtcrime.securesms.util.ListenableFutureTask ;
import java.util.Set ;
/ * *
/ * *
* A view that displays an individual conversation item within a conversation
* A view that displays an individual conversation item within a conversation
* thread . Used by ComposeMessageActivity ' s ListActivity via a ConversationAdapter .
* thread . Used by ComposeMessageActivity ' s ListActivity via a ConversationAdapter .
@ -81,13 +82,13 @@ public class ConversationItem extends LinearLayout {
R . attr . conversation_item_sent_push_pending_background ,
R . attr . conversation_item_sent_push_pending_background ,
R . attr . conversation_item_sent_push_pending_triangle_background } ;
R . attr . conversation_item_sent_push_pending_triangle_background } ;
private final static int SENT_PUSH = 0 ;
private final static int SENT_PUSH = 0 ;
private final static int SENT_PUSH_TRIANGLE = 1 ;
private final static int SENT_PUSH_TRIANGLE = 1 ;
private final static int SENT_SMS = 2 ;
private final static int SENT_SMS = 2 ;
private final static int SENT_SMS_TRIANGLE = 3 ;
private final static int SENT_SMS_TRIANGLE = 3 ;
private final static int SENT_SMS_PENDING = 4 ;
private final static int SENT_SMS_PENDING = 4 ;
private final static int SENT_SMS_PENDING_TRIANGLE = 5 ;
private final static int SENT_SMS_PENDING_TRIANGLE = 5 ;
private final static int SENT_PUSH_PENDING = 6 ;
private final static int SENT_PUSH_PENDING = 6 ;
private final static int SENT_PUSH_PENDING_TRIANGLE = 7 ;
private final static int SENT_PUSH_PENDING_TRIANGLE = 7 ;
private Handler failedIconHandler ;
private Handler failedIconHandler ;
@ -108,19 +109,21 @@ public class ConversationItem extends LinearLayout {
private View triangleTick ;
private View triangleTick ;
private ImageView pendingIndicator ;
private ImageView pendingIndicator ;
private View mmsContainer ;
private Set < MessageRecord > batchSelected ;
private ImageView mmsThumbnail ;
private SelectionClickListener selectionClickListener ;
private Button mmsDownloadButton ;
private View mmsContainer ;
private TextView mmsDownloadingLabel ;
private ImageView mmsThumbnail ;
private ListenableFutureTask < SlideDeck > slideDeck ;
private Button mmsDownloadButton ;
private FutureTaskListener < SlideDeck > slideDeckListener ;
private TextView mmsDownloadingLabel ;
private TypedArray backgroundDrawables ;
private ListenableFutureTask < SlideDeck > slideDeck ;
private FutureTaskListener < SlideDeck > slideDeckListener ;
private final FailedIconClickListener failedIconClickListener = new FailedIconClickListener ( ) ;
private TypedArray backgroundDrawables ;
private final MmsDownloadClickListener mmsDownloadClickListener = new MmsDownloadClickListener ( ) ;
private final FailedIconClickListener failedIconClickListener = new FailedIconClickListener ( ) ;
private final MmsDownloadClickListener mmsDownloadClickListener = new MmsDownloadClickListener ( ) ;
private final MmsPreferencesClickListener mmsPreferencesClickListener = new MmsPreferencesClickListener ( ) ;
private final MmsPreferencesClickListener mmsPreferencesClickListener = new MmsPreferencesClickListener ( ) ;
private final ClickListener clickListener = new ClickListener ( ) ;
private final ClickListener clickListener = new ClickListener ( ) ;
private final Handler handler = new Handler ( ) ;
private final Handler handler = new Handler ( ) ;
private final Context context ;
private final Context context ;
public ConversationItem ( Context context ) {
public ConversationItem ( Context context ) {
@ -157,19 +160,23 @@ public class ConversationItem extends LinearLayout {
setOnClickListener ( clickListener ) ;
setOnClickListener ( clickListener ) ;
if ( failedImage ! = null ) failedImage . setOnClickListener ( failedIconClickListener ) ;
if ( failedImage ! = null ) failedImage . setOnClickListener ( failedIconClickListener ) ;
if ( mmsDownloadButton ! = null ) mmsDownloadButton . setOnClickListener ( mmsDownloadClickListener ) ;
if ( mmsDownloadButton ! = null ) mmsDownloadButton . setOnClickListener ( mmsDownloadClickListener ) ;
if ( mmsThumbnail ! = null ) mmsThumbnail . setOnLongClickListener ( new MultiSelectLongClickListener ( ) ) ;
}
}
public void set ( MasterSecret masterSecret , MessageRecord messageRecord ,
public void set ( MasterSecret masterSecret , MessageRecord messageRecord ,
Set < MessageRecord > batchSelected , SelectionClickListener selectionClickListener ,
Handler failedIconHandler , boolean groupThread , boolean pushDestination )
Handler failedIconHandler , boolean groupThread , boolean pushDestination )
{
{
this . masterSecret = masterSecret ;
this . messageRecord = messageRecord ;
this . messageRecord = messageRecord ;
this . masterSecret = masterSecret ;
this . batchSelected = batchSelected ;
this . failedIconHandler = failedIconHandler ;
this . selectionClickListener = selectionClickListener ;
this . groupThread = groupThread ;
this . failedIconHandler = failedIconHandler ;
this . pushDestination = pushDestination ;
this . groupThread = groupThread ;
this . pushDestination = pushDestination ;
setBackgroundDrawables ( messageRecord ) ;
setConversationBackgroundDrawables ( messageRecord ) ;
setSelectionBackgroundDrawables ( messageRecord ) ;
setBodyText ( messageRecord ) ;
setBodyText ( messageRecord ) ;
if ( ! messageRecord . isGroupAction ( ) ) {
if ( ! messageRecord . isGroupAction ( ) ) {
@ -211,33 +218,57 @@ public class ConversationItem extends LinearLayout {
/// MessageRecord Attribute Parsers
/// MessageRecord Attribute Parsers
private void set BackgroundDrawables( MessageRecord messageRecord ) {
private void set Conversation BackgroundDrawables( MessageRecord messageRecord ) {
if ( conversationParent ! = null & & backgroundDrawables ! = null ) {
if ( conversationParent ! = null & & backgroundDrawables ! = null ) {
if ( messageRecord . isOutgoing ( ) ) {
if ( messageRecord . isOutgoing ( ) ) {
final int background ;
final int background ;
final int triangleBackground ;
final int triangleBackground ;
if ( messageRecord . isPending ( ) & & pushDestination & & ! messageRecord . isForcedSms ( ) ) {
if ( messageRecord . isPending ( ) & & pushDestination & & ! messageRecord . isForcedSms ( ) ) {
background = SENT_PUSH_PENDING ;
background = SENT_PUSH_PENDING ;
triangleBackground = SENT_PUSH_PENDING_TRIANGLE ;
triangleBackground = SENT_PUSH_PENDING_TRIANGLE ;
} else if ( messageRecord . isPending ( ) | | messageRecord . isPendingSmsFallback ( ) ) {
} else if ( messageRecord . isPending ( ) | | messageRecord . isPendingSmsFallback ( ) ) {
background = SENT_SMS_PENDING ;
background = SENT_SMS_PENDING ;
triangleBackground = SENT_SMS_PENDING_TRIANGLE ;
triangleBackground = SENT_SMS_PENDING_TRIANGLE ;
} else if ( messageRecord . isPush ( ) ) {
} else if ( messageRecord . isPush ( ) ) {
background = SENT_PUSH ;
background = SENT_PUSH ;
triangleBackground = SENT_PUSH_TRIANGLE ;
triangleBackground = SENT_PUSH_TRIANGLE ;
} else {
} else {
background = SENT_SMS ;
background = SENT_SMS ;
triangleBackground = SENT_SMS_TRIANGLE ;
triangleBackground = SENT_SMS_TRIANGLE ;
}
}
setViewBackgroundWithoutResettingPadding ( conversationParent , backgroundDrawables . getResourceId ( background , - 1 ) ) ;
setViewBackgroundWithoutResettingPadding ( conversationParent , backgroundDrawables . getResourceId ( background , - 1 ) ) ;
setViewBackgroundWithoutResettingPadding ( triangleTick , backgroundDrawables . getResourceId ( triangleBackground , - 1 ) ) ;
setViewBackgroundWithoutResettingPadding ( triangleTick , backgroundDrawables . getResourceId ( triangleBackground , - 1 ) ) ;
}
}
}
}
}
}
private void setSelectionBackgroundDrawables ( MessageRecord messageRecord ) {
int [ ] attributes = new int [ ] { R . attr . conversation_list_item_background_selected ,
R . attr . conversation_item_background } ;
TypedArray drawables = context . obtainStyledAttributes ( attributes ) ;
if ( batchSelected . contains ( messageRecord ) ) {
setBackgroundDrawable ( drawables . getDrawable ( 0 ) ) ;
} else {
setBackgroundDrawable ( drawables . getDrawable ( 1 ) ) ;
}
drawables . recycle ( ) ;
}
private void setBodyText ( MessageRecord messageRecord ) {
private void setBodyText ( MessageRecord messageRecord ) {
bodyText . setText ( Emoji . getInstance ( context ) . emojify ( messageRecord . getDisplayBody ( ) , new Emoji . InvalidatingPageLoadedListener ( bodyText ) ) ,
bodyText . setClickable ( false ) ;
TextView . BufferType . SPANNABLE ) ;
bodyText . setFocusable ( false ) ;
bodyText . setText ( Emoji . getInstance ( context ) . emojify ( messageRecord . getDisplayBody ( ) ,
new Emoji . InvalidatingPageLoadedListener ( bodyText ) ) ,
TextView . BufferType . SPANNABLE ) ;
if ( bodyText . isClickable ( ) & & bodyText . isFocusable ( ) ) {
bodyText . setOnLongClickListener ( new MultiSelectLongClickListener ( ) ) ;
bodyText . setOnClickListener ( new MultiSelectLongClickListener ( ) ) ;
}
}
}
private void setContactPhoto ( MessageRecord messageRecord ) {
private void setContactPhoto ( MessageRecord messageRecord ) {
@ -365,12 +396,6 @@ public class ConversationItem extends LinearLayout {
if ( slide . hasImage ( ) ) {
if ( slide . hasImage ( ) ) {
slide . setThumbnailOn ( mmsThumbnail ) ;
slide . setThumbnailOn ( mmsThumbnail ) ;
mmsThumbnail . setOnClickListener ( new ThumbnailClickListener ( slide ) ) ;
mmsThumbnail . setOnClickListener ( new ThumbnailClickListener ( slide ) ) ;
mmsThumbnail . setOnLongClickListener ( new OnLongClickListener ( ) {
@Override
public boolean onLongClick ( View v ) {
return false ;
}
} ) ;
mmsThumbnail . setVisibility ( View . VISIBLE ) ;
mmsThumbnail . setVisibility ( View . VISIBLE ) ;
return ;
return ;
}
}
@ -474,7 +499,9 @@ public class ConversationItem extends LinearLayout {
}
}
public void onClick ( View v ) {
public void onClick ( View v ) {
if ( MediaPreviewActivity . isContentTypeSupported ( slide . getContentType ( ) ) ) {
if ( ! batchSelected . isEmpty ( ) ) {
selectionClickListener . onItemClick ( null , ConversationItem . this , - 1 , - 1 ) ;
} else if ( MediaPreviewActivity . isContentTypeSupported ( slide . getContentType ( ) ) ) {
Intent intent = new Intent ( context , MediaPreviewActivity . class ) ;
Intent intent = new Intent ( context , MediaPreviewActivity . class ) ;
intent . addFlags ( Intent . FLAG_GRANT_READ_URI_PERMISSION ) ;
intent . addFlags ( Intent . FLAG_GRANT_READ_URI_PERMISSION ) ;
intent . setDataAndType ( slide . getUri ( ) , slide . getContentType ( ) ) ;
intent . setDataAndType ( slide . getUri ( ) , slide . getContentType ( ) ) ;
@ -545,6 +572,19 @@ public class ConversationItem extends LinearLayout {
}
}
}
}
private class MultiSelectLongClickListener implements OnLongClickListener , OnClickListener {
@Override
public boolean onLongClick ( View view ) {
selectionClickListener . onItemLongClick ( null , ConversationItem . this , - 1 , - 1 ) ;
return true ;
}
@Override
public void onClick ( View view ) {
selectionClickListener . onItemClick ( null , ConversationItem . this , - 1 , - 1 ) ;
}
}
private void handleMessageApproval ( ) {
private void handleMessageApproval ( ) {
final int title ;
final int title ;
final int message ;
final int message ;