@ -40,17 +40,23 @@ import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.Dialogs ;
import org.thoughtcrime.securesms.util.Dialogs ;
import org.thoughtcrime.securesms.util.DirectoryHelper ;
import org.thoughtcrime.securesms.util.DirectoryHelper ;
import org.thoughtcrime.securesms.util.FutureTaskListener ;
import org.thoughtcrime.securesms.util.FutureTaskListener ;
import org.thoughtcrime.securesms.util.ProgressDialogAsyncTask ;
import org.thoughtcrime.securesms.util.SaveAttachmentTask ;
import org.thoughtcrime.securesms.util.SaveAttachmentTask ;
import org.thoughtcrime.securesms.util.SaveAttachmentTask.Attachment ;
import org.thoughtcrime.securesms.util.SaveAttachmentTask.Attachment ;
import java.sql.Date ;
import java.sql.Date ;
import java.text.SimpleDateFormat ;
import java.text.SimpleDateFormat ;
import java.util.LinkedList ;
import java.util.List ;
public class ConversationFragment extends ListFragment
public class ConversationFragment extends ListFragment
implements LoaderManager . LoaderCallbacks < Cursor >
implements LoaderManager . LoaderCallbacks < Cursor >
{
{
private static final String TAG = ConversationFragment . class . getSimpleName ( ) ;
private static final String TAG = ConversationFragment . class . getSimpleName ( ) ;
private final ActionModeCallback actionModeCallback = new ActionModeCallback ( ) ;
private final SelectionClickListener selectionClickListener = new SelectionClickListener ( ) ;
private ConversationFragmentListener listener ;
private ConversationFragmentListener listener ;
private MasterSecret masterSecret ;
private MasterSecret masterSecret ;
@ -96,7 +102,7 @@ public class ConversationFragment extends ListFragment
private void initializeListAdapter ( ) {
private void initializeListAdapter ( ) {
if ( this . recipients ! = null & & this . threadId ! = - 1 ) {
if ( this . recipients ! = null & & this . threadId ! = - 1 ) {
this . setListAdapter ( new ConversationAdapter ( getActivity ( ) , masterSecret ,
this . setListAdapter ( new ConversationAdapter ( getActivity ( ) , masterSecret , selectionClickListener ,
new FailedIconClickHandler ( ) ,
new FailedIconClickHandler ( ) ,
( ! this . recipients . isSingleRecipient ( ) ) | | this . recipients . isGroupRecipient ( ) ,
( ! this . recipients . isSingleRecipient ( ) ) | | this . recipients . isGroupRecipient ( ) ,
DirectoryHelper . isPushDestination ( getActivity ( ) , this . recipients ) ) ) ;
DirectoryHelper . isPushDestination ( getActivity ( ) , this . recipients ) ) ) ;
@ -106,49 +112,50 @@ public class ConversationFragment extends ListFragment
}
}
private void initializeContextualActionBar ( ) {
private void initializeContextualActionBar ( ) {
getListView ( ) . setOnItemLongClickListener ( new AdapterView . OnItemLongClickListener ( ) {
getListView ( ) . setOnItemClickListener ( selectionClickListener ) ;
@Override
getListView ( ) . setOnItemLongClickListener ( selectionClickListener ) ;
public boolean onItemLongClick ( AdapterView < ? > parent , View view , int position , long id ) {
if ( actionMode ! = null ) {
view . setSelected ( true ) ;
return false ;
}
}
actionMode = ( ( ActionBarActivity ) getActivity ( ) ) . startSupportActionMode ( actionModeCallback ) ;
private void setCorrectMenuVisibility ( Menu menu ) {
view . setSelected ( true ) ;
ConversationAdapter adapter = ( ConversationAdapter ) getListAdapter ( ) ;
return true ;
List < MessageRecord > messageRecords = getSelectedMessageRecords ( ) ;
}
} ) ;
getListView ( ) . setOnItemClickListener ( new AdapterView . OnItemClickListener ( ) {
if ( actionMode ! = null & & messageRecords . size ( ) = = 0 ) {
@Override
adapter . getBatchSelected ( ) . clear ( ) ;
public void onItemClick ( AdapterView < ? > parent , View view , int position , long id ) {
adapter . notifyDataSetChanged ( ) ;
if ( actionMode ! = null ) {
actionMode . finish ( ) ;
view . setSelected ( true ) ;
return ;
setCorrectMenuVisibility ( getMessageRecord ( ) , actionMode . getMenu ( ) ) ;
}
}
} ) ;
}
}
private void setCorrectMenuVisibility ( MessageRecord messageRecord , Menu menu ) {
if ( messageRecords . size ( ) > 1 ) {
MenuItem resend = menu . findItem ( R . id . menu_context_resend ) ;
menu . findItem ( R . id . menu_context_forward ) . setVisible ( false ) ;
MenuItem saveAttachment = menu . findItem ( R . id . menu_context_save_attachment ) ;
menu . findItem ( R . id . menu_context_copy ) . setVisible ( false ) ;
menu . findItem ( R . id . menu_context_details ) . setVisible ( false ) ;
menu . findItem ( R . id . menu_context_save_attachment ) . setVisible ( false ) ;
menu . findItem ( R . id . menu_context_resend ) . setVisible ( false ) ;
} else {
MessageRecord messageRecord = messageRecords . get ( 0 ) ;
if ( messageRecord . isFailed ( ) ) resend . setVisible ( true ) ;
menu . findItem ( R . id . menu_context_resend ) . setVisible ( messageRecord . isFailed ( ) ) ;
else resend . setVisible ( false ) ;
menu . findItem ( R . id . menu_context_save_attachment ) . setVisible ( messageRecord . isMms ( ) & &
! messageRecord . isMmsNotification ( ) & &
( ( MediaMmsMessageRecord ) messageRecord ) . containsMediaSlide ( ) ) ;
if ( messageRecord . isMms ( ) & & ! messageRecord . isMmsNotification ( ) ) {
menu . findItem ( R . id . menu_context_forward ) . setVisible ( true ) ;
saveAttachment . setVisible ( ( ( MediaMmsMessageRecord ) messageRecord ) . containsMediaSlide ( ) ) ;
menu . findItem ( R . id . menu_context_details ) . setVisible ( true ) ;
} else {
menu . findItem ( R . id . menu_context_copy ) . setVisible ( true ) ;
saveAttachment . setVisible ( false ) ;
}
}
}
}
private MessageRecord getMessageRecord ( ) {
private MessageRecord getSelectedMessageRecord ( ) {
Cursor cursor = ( ( CursorAdapter ) getListAdapter ( ) ) . getCursor ( ) ;
List < MessageRecord > messageRecords = getSelectedMessageRecords ( ) ;
ConversationItem conversationItem = ( ConversationItem ) ( ( ( ConversationAdapter ) getListAdapter ( ) ) . newView ( getActivity ( ) , cursor , null ) ) ;
return conversationItem . getMessageRecord ( ) ;
if ( messageRecords . size ( ) = = 1 ) return messageRecords . get ( 0 ) ;
else throw new AssertionError ( ) ;
}
private List < MessageRecord > getSelectedMessageRecords ( ) {
return new LinkedList < > ( ( ( ConversationAdapter ) getListAdapter ( ) ) . getBatchSelected ( ) ) ;
}
}
public void reload ( Recipients recipients , long threadId ) {
public void reload ( Recipients recipients , long threadId ) {
@ -177,24 +184,33 @@ public class ConversationFragment extends ListFragment
clipboard . setText ( body ) ;
clipboard . setText ( body ) ;
}
}
private void handleDeleteMessage ( final MessageRecord message ) {
private void handleDeleteMessages ( final List < MessageRecord > messageRecords ) {
final long messageId = message . getId ( ) ;
AlertDialog . Builder builder = new AlertDialog . Builder ( getActivity ( ) ) ;
AlertDialog . Builder builder = new AlertDialog . Builder ( getActivity ( ) ) ;
builder . setTitle ( R . string . ConversationFragment_confirm_message_delete ) ;
builder . setTitle ( R . string . ConversationFragment_confirm_message_delete ) ;
builder . setIcon ( Dialogs . resolveIcon ( getActivity ( ) , R . attr . dialog_alert_icon ) ) ;
builder . setIcon ( Dialogs . resolveIcon ( getActivity ( ) , R . attr . dialog_alert_icon ) ) ;
builder . setCancelable ( true ) ;
builder . setCancelable ( true ) ;
builder . setMessage ( R . string . ConversationFragment_are_you_sure_you_want_to_permanently_delete_this_message ) ;
builder . setMessage ( R . string . ConversationFragment_are_you_sure_you_want_to_permanently_delete_all_selected_messages ) ;
builder . setPositiveButton ( R . string . yes , new DialogInterface . OnClickListener ( ) {
builder . setPositiveButton ( R . string . yes , new DialogInterface . OnClickListener ( ) {
@Override
@Override
public void onClick ( DialogInterface dialog , int which ) {
public void onClick ( DialogInterface dialog , int which ) {
if ( message . isMms ( ) ) {
new ProgressDialogAsyncTask < MessageRecord , Void , Void > ( getActivity ( ) ,
DatabaseFactory . getMmsDatabase ( getActivity ( ) ) . delete ( messageId ) ;
R . string . ConversationFragment_deleting ,
R . string . ConversationFragment_deleting_messages )
{
@Override
protected Void doInBackground ( MessageRecord . . . messageRecords ) {
for ( MessageRecord messageRecord : messageRecords ) {
if ( messageRecord . isMms ( ) ) {
DatabaseFactory . getMmsDatabase ( getActivity ( ) ) . delete ( messageRecord . getId ( ) ) ;
} else {
} else {
DatabaseFactory . getSmsDatabase ( getActivity ( ) ) . deleteMessage ( messageId ) ;
DatabaseFactory . getSmsDatabase ( getActivity ( ) ) . deleteMessage ( message Record. get Id( ) ) ;
}
}
}
}
return null ;
}
} . execute ( messageRecords . toArray ( new MessageRecord [ messageRecords . size ( ) ] ) ) ;
}
} ) ;
} ) ;
builder . setNegativeButton ( R . string . no , null ) ;
builder . setNegativeButton ( R . string . no , null ) ;
@ -312,16 +328,43 @@ public class ConversationFragment extends ListFragment
public void setComposeText ( String text ) ;
public void setComposeText ( String text ) ;
}
}
private ActionMode . Callback actionModeCallback = new ActionMode . Callback ( ) {
public class SelectionClickListener
implements AdapterView . OnItemLongClickListener , AdapterView . OnItemClickListener
{
@Override
public void onItemClick ( AdapterView < ? > parent , View view , int position , long id ) {
if ( actionMode ! = null & & view instanceof ConversationItem ) {
MessageRecord messageRecord = ( ( ConversationItem ) view ) . getMessageRecord ( ) ;
( ( ConversationAdapter ) getListAdapter ( ) ) . toggleBatchSelected ( messageRecord ) ;
( ( ConversationAdapter ) getListAdapter ( ) ) . notifyDataSetChanged ( ) ;
setCorrectMenuVisibility ( actionMode . getMenu ( ) ) ;
}
}
@Override
public boolean onItemLongClick ( AdapterView < ? > parent , View view , int position , long id ) {
if ( actionMode = = null & & view instanceof ConversationItem ) {
MessageRecord messageRecord = ( ( ConversationItem ) view ) . getMessageRecord ( ) ;
( ( ConversationAdapter ) getListAdapter ( ) ) . toggleBatchSelected ( messageRecord ) ;
( ( ConversationAdapter ) getListAdapter ( ) ) . notifyDataSetChanged ( ) ;
actionMode = ( ( ActionBarActivity ) getActivity ( ) ) . startSupportActionMode ( actionModeCallback ) ;
return true ;
}
return false ;
}
}
private class ActionModeCallback implements ActionMode . Callback {
@Override
@Override
public boolean onCreateActionMode ( ActionMode mode , Menu menu ) {
public boolean onCreateActionMode ( ActionMode mode , Menu menu ) {
MenuInflater inflater = mode . getMenuInflater ( ) ;
MenuInflater inflater = mode . getMenuInflater ( ) ;
inflater . inflate ( R . menu . conversation_context , menu ) ;
inflater . inflate ( R . menu . conversation_context , menu ) ;
MessageRecord messageRecord = getMessageRecord ( ) ;
setCorrectMenuVisibility ( menu ) ;
setCorrectMenuVisibility ( messageRecord , menu ) ;
return true ;
return true ;
}
}
@ -332,41 +375,37 @@ public class ConversationFragment extends ListFragment
@Override
@Override
public void onDestroyActionMode ( ActionMode mode ) {
public void onDestroyActionMode ( ActionMode mode ) {
if ( getListView ( ) ! = null & & getListView ( ) . getChildCount ( ) > 0 ) {
( ( ConversationAdapter ) getListAdapter ( ) ) . getBatchSelected ( ) . clear ( ) ;
for ( int i = 0 ; i < getListView ( ) . getChildCount ( ) ; i + + ) {
( ( ConversationAdapter ) getListAdapter ( ) ) . notifyDataSetChanged ( ) ;
getListView ( ) . getChildAt ( i ) . setSelected ( false ) ;
}
}
actionMode = null ;
actionMode = null ;
}
}
@Override
@Override
public boolean onActionItemClicked ( ActionMode mode , MenuItem item ) {
public boolean onActionItemClicked ( ActionMode mode , MenuItem item ) {
MessageRecord messageRecord = getMessageRecord ( ) ;
switch ( item . getItemId ( ) ) {
switch ( item . getItemId ( ) ) {
case R . id . menu_context_copy :
case R . id . menu_context_copy :
handleCopyMessage ( messageRecord ) ;
handleCopyMessage ( getSelectedMessageRecord( ) ) ;
actionMode . finish ( ) ;
actionMode . finish ( ) ;
return true ;
return true ;
case R . id . menu_context_delete_message :
case R . id . menu_context_delete_message :
handleDeleteMessage ( messageRecord ) ;
handleDeleteMessage s( getSelectedMessageRecords ( ) ) ;
actionMode . finish ( ) ;
actionMode . finish ( ) ;
return true ;
return true ;
case R . id . menu_context_details :
case R . id . menu_context_details :
handleDisplayDetails ( messageRecord ) ;
handleDisplayDetails ( getSelectedMessageRecord( ) ) ;
actionMode . finish ( ) ;
actionMode . finish ( ) ;
return true ;
return true ;
case R . id . menu_context_forward :
case R . id . menu_context_forward :
handleForwardMessage ( messageRecord ) ;
handleForwardMessage ( getSelectedMessageRecord( ) ) ;
actionMode . finish ( ) ;
actionMode . finish ( ) ;
return true ;
return true ;
case R . id . menu_context_resend :
case R . id . menu_context_resend :
handleResendMessage ( messageRecord ) ;
handleResendMessage ( getSelectedMessageRecord( ) ) ;
actionMode . finish ( ) ;
actionMode . finish ( ) ;
return true ;
return true ;
case R . id . menu_context_save_attachment :
case R . id . menu_context_save_attachment :
handleSaveAttachment ( ( MediaMmsMessageRecord ) messageRecord ) ;
handleSaveAttachment ( ( MediaMmsMessageRecord ) getSelectedMessageRecord( ) ) ;
actionMode . finish ( ) ;
actionMode . finish ( ) ;
return true ;
return true ;
}
}