2014-02-28 17:46:01 +00:00
package eu.siacs.conversations.ui ;
2014-01-24 01:04:05 +00:00
2014-09-27 09:46:56 +00:00
import android.annotation.SuppressLint ;
2014-02-20 16:00:50 +00:00
import android.app.AlertDialog ;
2014-01-24 01:04:05 +00:00
import android.app.FragmentTransaction ;
2014-05-06 19:34:30 +00:00
import android.app.PendingIntent ;
2016-04-29 11:58:37 +00:00
import android.content.ActivityNotFoundException ;
2015-04-11 12:53:10 +00:00
import android.content.ClipData ;
2014-02-20 16:00:50 +00:00
import android.content.DialogInterface ;
2014-04-16 16:16:23 +00:00
import android.content.DialogInterface.OnClickListener ;
2014-01-24 01:04:05 +00:00
import android.content.Intent ;
2014-11-03 19:00:20 +00:00
import android.content.IntentSender.SendIntentException ;
2015-12-06 17:23:59 +00:00
import android.content.pm.PackageManager ;
2014-11-03 19:00:20 +00:00
import android.net.Uri ;
2015-01-22 04:00:35 +00:00
import android.os.Build ;
2014-11-03 19:00:20 +00:00
import android.os.Bundle ;
2016-09-08 09:01:27 +00:00
import android.os.Handler ;
2014-11-03 19:00:20 +00:00
import android.provider.MediaStore ;
2016-01-11 10:17:45 +00:00
import android.provider.Settings ;
2014-01-24 01:04:05 +00:00
import android.support.v4.widget.SlidingPaneLayout ;
import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener ;
2018-02-16 11:06:05 +00:00
import android.support.v7.app.ActionBar ;
2015-06-25 15:01:42 +00:00
import android.util.Log ;
2015-12-01 13:18:07 +00:00
import android.util.Pair ;
2015-11-25 19:47:02 +00:00
import android.view.Gravity ;
2015-09-07 13:46:22 +00:00
import android.view.KeyEvent ;
2014-01-24 01:04:05 +00:00
import android.view.Menu ;
import android.view.MenuItem ;
2015-09-07 18:45:21 +00:00
import android.view.Surface ;
2014-01-24 01:04:05 +00:00
import android.view.View ;
import android.widget.AdapterView ;
import android.widget.AdapterView.OnItemClickListener ;
2014-01-24 22:58:51 +00:00
import android.widget.ArrayAdapter ;
2014-04-20 18:48:16 +00:00
import android.widget.CheckBox ;
2014-02-16 15:32:15 +00:00
import android.widget.PopupMenu ;
import android.widget.PopupMenu.OnMenuItemClickListener ;
2014-05-09 18:46:43 +00:00
import android.widget.Toast ;
2014-01-24 01:04:05 +00:00
2015-01-02 00:21:14 +00:00
import net.java.otr4j.session.SessionStatus ;
2016-01-11 10:17:45 +00:00
import org.openintents.openpgp.util.OpenPgpApi ;
2014-11-03 19:00:20 +00:00
import java.util.ArrayList ;
2015-04-11 12:53:10 +00:00
import java.util.Iterator ;
2014-11-03 19:00:20 +00:00
import java.util.List ;
2015-10-20 13:27:33 +00:00
import java.util.concurrent.atomic.AtomicBoolean ;
2014-11-03 19:00:20 +00:00
2015-07-20 12:26:29 +00:00
import de.timroes.android.listview.EnhancedListView ;
2015-06-25 15:01:42 +00:00
import eu.siacs.conversations.Config ;
2014-11-03 19:00:20 +00:00
import eu.siacs.conversations.R ;
2015-07-10 01:02:49 +00:00
import eu.siacs.conversations.crypto.axolotl.AxolotlService ;
2016-11-14 21:27:41 +00:00
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus ;
2015-06-28 11:14:21 +00:00
import eu.siacs.conversations.entities.Account ;
2014-12-21 20:43:58 +00:00
import eu.siacs.conversations.entities.Blockable ;
2014-11-03 19:00:20 +00:00
import eu.siacs.conversations.entities.Contact ;
import eu.siacs.conversations.entities.Conversation ;
import eu.siacs.conversations.entities.Message ;
2015-12-06 17:23:59 +00:00
import eu.siacs.conversations.entities.Transferable ;
2016-03-31 22:03:14 +00:00
import eu.siacs.conversations.persistance.FileBackend ;
2015-07-10 11:28:50 +00:00
import eu.siacs.conversations.services.XmppConnectionService ;
2014-11-03 19:00:20 +00:00
import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate ;
import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate ;
import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate ;
import eu.siacs.conversations.ui.adapter.ConversationAdapter ;
2017-09-29 17:44:30 +00:00
import eu.siacs.conversations.ui.service.EmojiService ;
2014-11-03 19:00:20 +00:00
import eu.siacs.conversations.utils.ExceptionHelper ;
2017-03-03 11:26:33 +00:00
import eu.siacs.conversations.utils.UIHelper ;
2014-12-21 20:43:58 +00:00
import eu.siacs.conversations.xmpp.OnUpdateBlocklist ;
2016-11-02 14:21:26 +00:00
import eu.siacs.conversations.xmpp.XmppConnection ;
2015-07-21 11:15:59 +00:00
import eu.siacs.conversations.xmpp.jid.InvalidJidException ;
import eu.siacs.conversations.xmpp.jid.Jid ;
2014-11-03 19:00:20 +00:00
2014-12-21 20:43:58 +00:00
public class ConversationActivity extends XmppActivity
2015-07-10 11:28:50 +00:00
implements OnAccountUpdate , OnConversationUpdate , OnRosterUpdate , OnUpdateBlocklist , XmppConnectionService . OnShowErrorToast {
2014-01-24 09:50:18 +00:00
2017-09-18 09:51:47 +00:00
public static final String RECENTLY_USED_QUICK_ACTION = " recently_used_quick_action " ;
2016-07-25 12:15:47 +00:00
public static final String ACTION_VIEW_CONVERSATION = " eu.siacs.conversations.action.VIEW " ;
2014-02-03 17:38:47 +00:00
public static final String CONVERSATION = " conversationUuid " ;
2016-07-25 12:15:47 +00:00
public static final String EXTRA_DOWNLOAD_UUID = " eu.siacs.conversations.download_uuid " ;
2014-03-13 20:37:27 +00:00
public static final String TEXT = " text " ;
2014-11-17 00:54:01 +00:00
public static final String NICK = " nick " ;
2015-07-21 11:15:59 +00:00
public static final String PRIVATE_MESSAGE = " pm " ;
2014-04-10 12:12:08 +00:00
2014-08-13 09:22:32 +00:00
public static final int REQUEST_SEND_MESSAGE = 0x0201 ;
public static final int REQUEST_DECRYPT_PGP = 0x0202 ;
2014-11-06 16:25:14 +00:00
public static final int REQUEST_ENCRYPT_MESSAGE = 0x0207 ;
2015-07-19 16:36:28 +00:00
public static final int REQUEST_TRUST_KEYS_TEXT = 0x0208 ;
public static final int REQUEST_TRUST_KEYS_MENU = 0x0209 ;
2015-12-06 17:23:59 +00:00
public static final int REQUEST_START_DOWNLOAD = 0x0210 ;
2017-08-22 14:51:42 +00:00
public static final int REQUEST_ADD_EDITOR_CONTENT = 0x0211 ;
2015-05-02 09:38:56 +00:00
public static final int ATTACHMENT_CHOICE_CHOOSE_IMAGE = 0x0301 ;
public static final int ATTACHMENT_CHOICE_TAKE_PHOTO = 0x0302 ;
public static final int ATTACHMENT_CHOICE_CHOOSE_FILE = 0x0303 ;
public static final int ATTACHMENT_CHOICE_RECORD_VOICE = 0x0304 ;
public static final int ATTACHMENT_CHOICE_LOCATION = 0x0305 ;
2015-07-19 16:36:28 +00:00
public static final int ATTACHMENT_CHOICE_INVALID = 0x0306 ;
2017-09-18 09:51:47 +00:00
public static final int ATTACHMENT_CHOICE_RECORD_VIDEO = 0x0307 ;
2014-10-03 13:00:29 +00:00
private static final String STATE_OPEN_CONVERSATION = " state_open_conversation " ;
private static final String STATE_PANEL_OPEN = " state_panel_open " ;
2014-11-06 16:25:14 +00:00
private static final String STATE_PENDING_URI = " state_pending_uri " ;
2016-09-12 19:18:56 +00:00
private static final String STATE_FIRST_VISIBLE = " first_visible " ;
private static final String STATE_OFFSET_FROM_TOP = " offset_from_top " ;
2014-01-24 01:04:05 +00:00
2016-09-12 19:18:56 +00:00
private String mOpenConversation = null ;
2014-10-03 13:00:29 +00:00
private boolean mPanelOpen = true ;
2017-01-20 09:43:50 +00:00
private AtomicBoolean mShouldPanelBeOpen = new AtomicBoolean ( false ) ;
2016-09-12 19:18:56 +00:00
private Pair < Integer , Integer > mScrollPosition = null ;
2015-04-11 12:53:10 +00:00
final private List < Uri > mPendingImageUris = new ArrayList < > ( ) ;
final private List < Uri > mPendingFileUris = new ArrayList < > ( ) ;
2015-03-07 13:15:38 +00:00
private Uri mPendingGeoUri = null ;
2015-07-19 16:36:28 +00:00
private boolean forbidProcessingPendings = false ;
2015-12-06 17:23:59 +00:00
private Message mPendingDownloadableMessage = null ;
2014-10-03 13:00:29 +00:00
2015-09-07 13:46:22 +00:00
private boolean conversationWasSelectedByKeyboard = false ;
2014-10-03 13:00:29 +00:00
private View mContentView ;
2014-01-24 09:50:18 +00:00
2014-11-07 14:09:28 +00:00
private List < Conversation > conversationList = new ArrayList < > ( ) ;
2015-04-02 22:06:37 +00:00
private Conversation swipedConversation = null ;
2014-11-17 23:07:27 +00:00
private Conversation mSelectedConversation = null ;
2015-04-02 22:06:37 +00:00
private EnhancedListView listView ;
2014-11-07 14:38:20 +00:00
private ConversationFragment mConversationFragment ;
2014-06-06 09:39:17 +00:00
2014-02-01 14:07:20 +00:00
private ArrayAdapter < Conversation > listAdapter ;
2014-06-06 09:39:17 +00:00
2015-01-02 11:04:33 +00:00
private boolean mActivityPaused = false ;
2015-10-20 13:27:33 +00:00
private AtomicBoolean mRedirected = new AtomicBoolean ( false ) ;
2015-12-01 13:18:07 +00:00
private Pair < Integer , Intent > mPostponedActivityResult ;
2016-11-08 11:42:13 +00:00
private boolean mUnprocessedNewIntent = false ;
2017-08-22 14:51:42 +00:00
public Uri mPendingEditorContent = null ;
2015-01-02 11:04:33 +00:00
2014-02-07 01:57:36 +00:00
public Conversation getSelectedConversation ( ) {
2014-11-17 23:07:27 +00:00
return this . mSelectedConversation ;
2014-01-27 19:40:42 +00:00
}
2014-06-06 09:39:17 +00:00
2014-05-13 15:11:27 +00:00
public void setSelectedConversation ( Conversation conversation ) {
2014-11-17 23:07:27 +00:00
this . mSelectedConversation = conversation ;
2014-05-13 15:11:27 +00:00
}
2014-04-10 12:12:08 +00:00
2014-10-03 13:00:29 +00:00
public void showConversationsOverview ( ) {
2017-11-17 20:00:01 +00:00
if ( mConversationFragment ! = null ) {
mConversationFragment . stopScrolling ( ) ;
}
2014-10-03 13:00:29 +00:00
if ( mContentView instanceof SlidingPaneLayout ) {
SlidingPaneLayout mSlidingPaneLayout = ( SlidingPaneLayout ) mContentView ;
2017-01-20 09:43:50 +00:00
mShouldPanelBeOpen . set ( true ) ;
2014-10-03 13:00:29 +00:00
mSlidingPaneLayout . openPane ( ) ;
}
}
2014-10-05 22:33:52 +00:00
2014-11-04 11:15:14 +00:00
@Override
protected String getShareableUri ( ) {
Conversation conversation = getSelectedConversation ( ) ;
2014-11-06 16:25:14 +00:00
if ( conversation ! = null ) {
2014-11-15 23:20:20 +00:00
return conversation . getAccount ( ) . getShareableUri ( ) ;
2014-11-04 11:15:14 +00:00
} else {
2014-11-04 16:10:35 +00:00
return " " ;
2014-11-04 11:15:14 +00:00
}
}
2014-10-03 13:00:29 +00:00
public void hideConversationsOverview ( ) {
if ( mContentView instanceof SlidingPaneLayout ) {
SlidingPaneLayout mSlidingPaneLayout = ( SlidingPaneLayout ) mContentView ;
2017-01-20 09:43:50 +00:00
mShouldPanelBeOpen . set ( false ) ;
2014-10-03 13:00:29 +00:00
mSlidingPaneLayout . closePane ( ) ;
}
}
2014-10-05 22:33:52 +00:00
2014-10-03 13:00:29 +00:00
public boolean isConversationsOverviewHideable ( ) {
2016-10-03 08:13:45 +00:00
return mContentView instanceof SlidingPaneLayout ;
2014-10-03 13:00:29 +00:00
}
2014-10-05 22:33:52 +00:00
2014-10-03 13:00:29 +00:00
public boolean isConversationsOverviewVisable ( ) {
if ( mContentView instanceof SlidingPaneLayout ) {
2017-01-20 09:43:50 +00:00
return mShouldPanelBeOpen . get ( ) ;
2014-10-03 13:00:29 +00:00
} else {
return true ;
}
}
2014-04-10 12:12:08 +00:00
2014-01-24 01:04:05 +00:00
@Override
2015-01-14 20:28:27 +00:00
protected void onCreate ( final Bundle savedInstanceState ) {
2014-01-25 18:33:12 +00:00
super . onCreate ( savedInstanceState ) ;
2017-09-29 17:44:30 +00:00
new EmojiService ( this ) . init ( ) ;
2015-04-11 12:53:10 +00:00
if ( savedInstanceState ! = null ) {
2016-09-12 19:18:56 +00:00
mOpenConversation = savedInstanceState . getString ( STATE_OPEN_CONVERSATION , null ) ;
2015-04-11 12:53:10 +00:00
mPanelOpen = savedInstanceState . getBoolean ( STATE_PANEL_OPEN , true ) ;
2016-09-12 19:18:56 +00:00
int pos = savedInstanceState . getInt ( STATE_FIRST_VISIBLE , - 1 ) ;
int offset = savedInstanceState . getInt ( STATE_OFFSET_FROM_TOP , 1 ) ;
if ( pos > = 0 & & offset < = 0 ) {
Log . d ( Config . LOGTAG , " retrieved scroll position from instanceState " + pos + " : " + offset ) ;
mScrollPosition = new Pair < > ( pos , offset ) ;
} else {
mScrollPosition = null ;
}
2015-04-11 12:53:10 +00:00
String pending = savedInstanceState . getString ( STATE_PENDING_URI , null ) ;
if ( pending ! = null ) {
2016-10-03 09:13:04 +00:00
Log . d ( Config . LOGTAG , " ConversationsActivity.onCreate() - restoring pending image uri " ) ;
2015-04-11 12:53:10 +00:00
mPendingImageUris . clear ( ) ;
mPendingImageUris . add ( Uri . parse ( pending ) ) ;
}
2014-10-03 13:00:29 +00:00
}
2014-01-24 22:58:51 +00:00
setContentView ( R . layout . fragment_conversations_overview ) ;
2014-01-24 09:50:18 +00:00
2014-11-07 14:38:20 +00:00
this . mConversationFragment = new ConversationFragment ( ) ;
FragmentTransaction transaction = getFragmentManager ( ) . beginTransaction ( ) ;
transaction . replace ( R . id . selected_conversation , this . mConversationFragment , " conversation " ) ;
transaction . commit ( ) ;
2017-11-13 13:51:45 +00:00
this . listView = findViewById ( R . id . list ) ;
2014-11-07 20:49:31 +00:00
this . listAdapter = new ConversationAdapter ( this , conversationList ) ;
2017-11-13 13:51:45 +00:00
this . listView . setAdapter ( this . listAdapter ) ;
this . listView . setSwipeDirection ( EnhancedListView . SwipeDirection . END ) ;
2014-08-31 14:28:21 +00:00
2018-02-16 11:06:05 +00:00
final ActionBar actionBar = getSupportActionBar ( ) ;
2017-02-18 17:08:37 +00:00
if ( actionBar ! = null ) {
actionBar . setDisplayOptions ( ActionBar . DISPLAY_SHOW_TITLE ) ;
2014-11-07 14:09:28 +00:00
}
2014-01-25 18:33:12 +00:00
2014-01-24 01:04:05 +00:00
listView . setOnItemClickListener ( new OnItemClickListener ( ) {
@Override
2014-01-24 09:50:18 +00:00
public void onItemClick ( AdapterView < ? > arg0 , View clickedView ,
2016-01-11 10:17:45 +00:00
int position , long arg3 ) {
2014-05-13 15:11:27 +00:00
if ( getSelectedConversation ( ) ! = conversationList . get ( position ) ) {
2017-11-17 20:00:01 +00:00
ConversationActivity . this . mConversationFragment . stopScrolling ( ) ;
2014-05-13 15:11:27 +00:00
setSelectedConversation ( conversationList . get ( position ) ) ;
2014-11-07 14:38:20 +00:00
ConversationActivity . this . mConversationFragment . reInit ( getSelectedConversation ( ) ) ;
2015-09-07 13:46:22 +00:00
conversationWasSelectedByKeyboard = false ;
2014-01-27 19:40:42 +00:00
}
2014-11-07 14:38:20 +00:00
hideConversationsOverview ( ) ;
2015-01-09 21:24:50 +00:00
openConversation ( ) ;
2014-01-24 01:04:05 +00:00
}
} ) ;
2015-04-02 22:06:37 +00:00
listView . setDismissCallback ( new EnhancedListView . OnDismissCallback ( ) {
@Override
public EnhancedListView . Undoable onDismiss ( final EnhancedListView enhancedListView , final int position ) {
final int index = listView . getFirstVisiblePosition ( ) ;
View v = listView . getChildAt ( 0 ) ;
final int top = ( v = = null ) ? 0 : ( v . getTop ( ) - listView . getPaddingTop ( ) ) ;
2015-09-17 12:02:28 +00:00
try {
swipedConversation = listAdapter . getItem ( position ) ;
} catch ( IndexOutOfBoundsException e ) {
return null ;
}
2015-04-02 22:06:37 +00:00
listAdapter . remove ( swipedConversation ) ;
2015-10-14 19:18:34 +00:00
xmppConnectionService . markRead ( swipedConversation ) ;
2015-04-02 22:06:37 +00:00
final boolean formerlySelected = ( getSelectedConversation ( ) = = swipedConversation ) ;
if ( position = = 0 & & listAdapter . getCount ( ) = = 0 ) {
endConversation ( swipedConversation , false , true ) ;
return null ;
} else if ( formerlySelected ) {
setSelectedConversation ( listAdapter . getItem ( 0 ) ) ;
ConversationActivity . this . mConversationFragment
. reInit ( getSelectedConversation ( ) ) ;
}
return new EnhancedListView . Undoable ( ) {
@Override
public void undo ( ) {
listAdapter . insert ( swipedConversation , position ) ;
if ( formerlySelected ) {
setSelectedConversation ( swipedConversation ) ;
ConversationActivity . this . mConversationFragment
. reInit ( getSelectedConversation ( ) ) ;
}
swipedConversation = null ;
listView . setSelectionFromTop ( index + ( listView . getChildCount ( ) < position ? 1 : 0 ) , top ) ;
}
@Override
public void discard ( ) {
if ( ! swipedConversation . isRead ( )
& & swipedConversation . getMode ( ) = = Conversation . MODE_SINGLE ) {
swipedConversation = null ;
return ;
}
endConversation ( swipedConversation , false , false ) ;
swipedConversation = null ;
}
@Override
public String getTitle ( ) {
if ( swipedConversation . getMode ( ) = = Conversation . MODE_MULTI ) {
return getResources ( ) . getString ( R . string . title_undo_swipe_out_muc ) ;
} else {
return getResources ( ) . getString ( R . string . title_undo_swipe_out_conversation ) ;
}
}
} ;
}
} ) ;
listView . enableSwipeToDismiss ( ) ;
listView . setSwipingLayout ( R . id . swipeable_item ) ;
listView . setUndoStyle ( EnhancedListView . UndoStyle . SINGLE_POPUP ) ;
2015-04-28 07:25:58 +00:00
listView . setUndoHideDelay ( 5000 ) ;
2015-04-02 22:06:37 +00:00
listView . setRequireTouchBeforeDismiss ( false ) ;
2014-10-03 13:00:29 +00:00
mContentView = findViewById ( R . id . content_view_spl ) ;
2014-10-05 22:33:52 +00:00
if ( mContentView = = null ) {
2014-10-03 13:00:29 +00:00
mContentView = findViewById ( R . id . content_view_ll ) ;
}
if ( mContentView instanceof SlidingPaneLayout ) {
SlidingPaneLayout mSlidingPaneLayout = ( SlidingPaneLayout ) mContentView ;
2016-12-25 17:57:30 +00:00
mSlidingPaneLayout . setShadowResource ( R . drawable . es_slidingpane_shadow ) ;
2014-10-03 13:00:29 +00:00
mSlidingPaneLayout . setSliderFadeColor ( 0 ) ;
mSlidingPaneLayout . setPanelSlideListener ( new PanelSlideListener ( ) {
2014-01-24 09:50:18 +00:00
2014-10-03 13:00:29 +00:00
@Override
public void onPanelOpened ( View arg0 ) {
2017-01-20 12:44:29 +00:00
mShouldPanelBeOpen . set ( true ) ;
2014-11-21 19:02:13 +00:00
updateActionBarTitle ( ) ;
2014-10-03 13:00:29 +00:00
invalidateOptionsMenu ( ) ;
hideKeyboard ( ) ;
if ( xmppConnectionServiceBound ) {
2017-01-20 12:44:29 +00:00
xmppConnectionService . getNotificationService ( ) . setOpenConversation ( null ) ;
2014-10-03 13:00:29 +00:00
}
2014-10-23 19:27:41 +00:00
closeContextMenu ( ) ;
2014-09-29 16:28:13 +00:00
}
2014-01-24 09:50:18 +00:00
2014-10-03 13:00:29 +00:00
@Override
public void onPanelClosed ( View arg0 ) {
2017-01-20 12:44:29 +00:00
mShouldPanelBeOpen . set ( false ) ;
2015-04-02 22:06:37 +00:00
listView . discardUndo ( ) ;
2014-11-07 20:49:31 +00:00
openConversation ( ) ;
2014-01-24 09:50:18 +00:00
}
2014-01-24 01:04:05 +00:00
2014-10-03 13:00:29 +00:00
@Override
public void onPanelSlide ( View arg0 , float arg1 ) {
// TODO Auto-generated method stub
2014-01-24 09:50:18 +00:00
2014-10-03 13:00:29 +00:00
}
} ) ;
}
2014-01-24 01:04:05 +00:00
}
2014-10-03 13:00:29 +00:00
2014-11-20 17:20:42 +00:00
@Override
public void switchToConversation ( Conversation conversation ) {
setSelectedConversation ( conversation ) ;
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
ConversationActivity . this . mConversationFragment . reInit ( getSelectedConversation ( ) ) ;
openConversation ( ) ;
}
} ) ;
}
2014-11-21 19:02:13 +00:00
private void updateActionBarTitle ( ) {
updateActionBarTitle ( isConversationsOverviewHideable ( ) & & ! isConversationsOverviewVisable ( ) ) ;
}
private void updateActionBarTitle ( boolean titleShouldBeName ) {
2018-02-16 11:06:05 +00:00
final ActionBar ab = getSupportActionBar ( ) ;
2014-11-27 09:30:06 +00:00
final Conversation conversation = getSelectedConversation ( ) ;
2014-09-29 16:28:13 +00:00
if ( ab ! = null ) {
2014-11-27 09:30:06 +00:00
if ( titleShouldBeName & & conversation ! = null ) {
2017-02-18 17:08:37 +00:00
if ( ( ab . getDisplayOptions ( ) & ActionBar . DISPLAY_HOME_AS_UP ) ! = ActionBar . DISPLAY_HOME_AS_UP ) {
ab . setDisplayOptions ( ActionBar . DISPLAY_HOME_AS_UP | ActionBar . DISPLAY_SHOW_TITLE ) ;
}
2014-11-27 09:30:06 +00:00
if ( conversation . getMode ( ) = = Conversation . MODE_SINGLE | | useSubjectToIdentifyConference ( ) ) {
ab . setTitle ( conversation . getName ( ) ) ;
2014-11-21 19:02:13 +00:00
} else {
2014-12-21 20:43:58 +00:00
ab . setTitle ( conversation . getJid ( ) . toBareJid ( ) . toString ( ) ) ;
2014-11-21 19:02:13 +00:00
}
2014-09-29 16:28:13 +00:00
} else {
2017-02-18 17:08:37 +00:00
if ( ( ab . getDisplayOptions ( ) & ActionBar . DISPLAY_HOME_AS_UP ) = = ActionBar . DISPLAY_HOME_AS_UP ) {
ab . setDisplayOptions ( ActionBar . DISPLAY_SHOW_TITLE ) ;
}
2014-11-21 19:02:13 +00:00
ab . setTitle ( R . string . app_name ) ;
2014-09-29 16:28:13 +00:00
}
}
2014-11-21 19:02:13 +00:00
}
private void openConversation ( ) {
this . updateActionBarTitle ( ) ;
this . invalidateOptionsMenu ( ) ;
2014-09-29 16:28:13 +00:00
if ( xmppConnectionServiceBound ) {
2015-01-02 11:04:33 +00:00
final Conversation conversation = getSelectedConversation ( ) ;
xmppConnectionService . getNotificationService ( ) . setOpenConversation ( conversation ) ;
sendReadMarkerIfNecessary ( conversation ) ;
}
2015-01-09 21:24:50 +00:00
listAdapter . notifyDataSetChanged ( ) ;
2015-01-02 11:04:33 +00:00
}
public void sendReadMarkerIfNecessary ( final Conversation conversation ) {
2016-11-08 11:42:13 +00:00
if ( ! mActivityPaused & & ! mUnprocessedNewIntent & & conversation ! = null ) {
2016-02-15 22:09:42 +00:00
xmppConnectionService . sendReadMarker ( conversation ) ;
2014-09-29 16:28:13 +00:00
}
}
2014-01-24 09:50:18 +00:00
2014-01-24 01:04:05 +00:00
@Override
public boolean onCreateOptionsMenu ( Menu menu ) {
getMenuInflater ( ) . inflate ( R . menu . conversations , menu ) ;
2014-12-21 20:43:58 +00:00
final MenuItem menuSecure = menu . findItem ( R . id . action_security ) ;
final MenuItem menuArchive = menu . findItem ( R . id . action_archive ) ;
final MenuItem menuMucDetails = menu . findItem ( R . id . action_muc_details ) ;
final MenuItem menuContactDetails = menu . findItem ( R . id . action_contact_details ) ;
final MenuItem menuAttach = menu . findItem ( R . id . action_attach_file ) ;
final MenuItem menuClearHistory = menu . findItem ( R . id . action_clear_history ) ;
final MenuItem menuAdd = menu . findItem ( R . id . action_add ) ;
final MenuItem menuInviteContact = menu . findItem ( R . id . action_invite ) ;
final MenuItem menuMute = menu . findItem ( R . id . action_mute ) ;
final MenuItem menuUnmute = menu . findItem ( R . id . action_unmute ) ;
2014-04-10 12:12:08 +00:00
2015-01-07 17:34:24 +00:00
if ( isConversationsOverviewVisable ( ) & & isConversationsOverviewHideable ( ) ) {
2014-02-28 17:46:01 +00:00
menuArchive . setVisible ( false ) ;
menuMucDetails . setVisible ( false ) ;
menuContactDetails . setVisible ( false ) ;
2014-02-13 22:40:08 +00:00
menuSecure . setVisible ( false ) ;
2014-07-16 22:03:37 +00:00
menuInviteContact . setVisible ( false ) ;
2014-04-05 10:49:43 +00:00
menuAttach . setVisible ( false ) ;
2014-04-16 16:16:23 +00:00
menuClearHistory . setVisible ( false ) ;
2014-09-03 10:36:54 +00:00
menuMute . setVisible ( false ) ;
2014-11-18 12:51:04 +00:00
menuUnmute . setVisible ( false ) ;
2014-01-24 01:04:05 +00:00
} else {
2014-10-03 13:00:29 +00:00
menuAdd . setVisible ( ! isConversationsOverviewHideable ( ) ) ;
2014-04-10 12:12:08 +00:00
if ( this . getSelectedConversation ( ) ! = null ) {
2015-07-30 22:52:46 +00:00
if ( this . getSelectedConversation ( ) . getNextEncryption ( ) ! = Message . ENCRYPTION_NONE ) {
2015-01-22 04:00:35 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . LOLLIPOP ) {
2015-04-28 12:28:51 +00:00
menuSecure . setIcon ( R . drawable . ic_lock_white_24dp ) ;
2015-01-22 04:00:35 +00:00
} else {
menuSecure . setIcon ( R . drawable . ic_action_secure ) ;
}
}
2014-02-07 01:57:36 +00:00
if ( this . getSelectedConversation ( ) . getMode ( ) = = Conversation . MODE_MULTI ) {
2014-02-28 17:46:01 +00:00
menuContactDetails . setVisible ( false ) ;
2015-09-13 15:13:46 +00:00
menuAttach . setVisible ( getSelectedConversation ( ) . getAccount ( ) . httpUploadAvailable ( ) & & getSelectedConversation ( ) . getMucOptions ( ) . participating ( ) ) ;
2015-01-07 17:34:24 +00:00
menuInviteContact . setVisible ( getSelectedConversation ( ) . getMucOptions ( ) . canInvite ( ) ) ;
2016-02-29 12:18:07 +00:00
menuSecure . setVisible ( ( Config . supportOpenPgp ( ) | | Config . supportOmemo ( ) ) & & Config . multipleEncryptionChoices ( ) ) ; //only if pgp is supported we have a choice
2014-02-13 22:40:08 +00:00
} else {
2016-04-09 08:59:54 +00:00
menuContactDetails . setVisible ( ! this . getSelectedConversation ( ) . withSelf ( ) ) ;
2014-02-28 17:46:01 +00:00
menuMucDetails . setVisible ( false ) ;
2016-02-24 13:47:49 +00:00
menuSecure . setVisible ( Config . multipleEncryptionChoices ( ) ) ;
2017-02-13 16:32:26 +00:00
menuInviteContact . setVisible ( xmppConnectionService ! = null & & xmppConnectionService . findConferenceServer ( getSelectedConversation ( ) . getAccount ( ) ) ! = null ) ;
2014-02-07 01:57:36 +00:00
}
2014-11-18 12:51:04 +00:00
if ( this . getSelectedConversation ( ) . isMuted ( ) ) {
menuMute . setVisible ( false ) ;
} else {
menuUnmute . setVisible ( false ) ;
}
2014-02-07 01:57:36 +00:00
}
2014-01-24 01:04:05 +00:00
}
2016-09-08 09:01:27 +00:00
if ( Config . supportOmemo ( ) ) {
2017-09-19 08:43:25 +00:00
new Handler ( ) . post ( addOmemoDebuggerRunnable ) ;
2016-09-08 09:01:27 +00:00
}
2016-02-27 09:25:31 +00:00
return super . onCreateOptionsMenu ( menu ) ;
2014-01-24 01:04:05 +00:00
}
2014-06-06 09:39:17 +00:00
2017-09-19 08:43:25 +00:00
private Runnable addOmemoDebuggerRunnable = new Runnable ( ) {
@Override
public void run ( ) {
View view = findViewById ( R . id . action_security ) ;
if ( view ! = null ) {
view . setOnLongClickListener ( new View . OnLongClickListener ( ) {
@Override
public boolean onLongClick ( View v ) {
return v . getId ( ) = = R . id . action_security & & quickOmemoDebugger ( getSelectedConversation ( ) ) ;
}
} ) ;
}
}
} ;
2016-09-08 09:01:27 +00:00
private boolean quickOmemoDebugger ( Conversation c ) {
if ( c ! = null ) {
2016-10-03 19:04:10 +00:00
boolean single = c . getMode ( ) = = Conversation . MODE_SINGLE ;
2016-09-08 09:01:27 +00:00
AxolotlService axolotlService = c . getAccount ( ) . getAxolotlService ( ) ;
Pair < AxolotlService . AxolotlCapability , Jid > capabilityJidPair = axolotlService . isConversationAxolotlCapableDetailed ( c ) ;
switch ( capabilityJidPair . first ) {
case MISSING_PRESENCE :
2016-10-03 19:04:10 +00:00
Toast . makeText ( ConversationActivity . this , single ? getString ( R . string . missing_presence_subscription ) : getString ( R . string . missing_presence_subscription_with_x , capabilityJidPair . second . toBareJid ( ) . toString ( ) ) , Toast . LENGTH_SHORT ) . show ( ) ;
2016-09-08 09:01:27 +00:00
return true ;
case MISSING_KEYS :
2016-10-03 19:04:10 +00:00
Toast . makeText ( ConversationActivity . this , single ? getString ( R . string . missing_omemo_keys ) : getString ( R . string . missing_keys_from_x , capabilityJidPair . second . toBareJid ( ) . toString ( ) ) , Toast . LENGTH_SHORT ) . show ( ) ;
2016-09-08 09:01:27 +00:00
return true ;
case WRONG_CONFIGURATION :
Toast . makeText ( ConversationActivity . this , R . string . wrong_conference_configuration , Toast . LENGTH_SHORT ) . show ( ) ;
return true ;
case NO_MEMBERS :
Toast . makeText ( ConversationActivity . this , R . string . this_conference_has_no_members , Toast . LENGTH_SHORT ) . show ( ) ;
return true ;
}
}
return false ;
}
2015-07-19 16:36:28 +00:00
protected void selectPresenceToAttachFile ( final int attachmentChoice , final int encryption ) {
2015-06-28 11:14:21 +00:00
final Conversation conversation = getSelectedConversation ( ) ;
final Account account = conversation . getAccount ( ) ;
2015-05-04 07:54:10 +00:00
final OnPresenceSelected callback = new OnPresenceSelected ( ) {
2014-06-06 09:39:17 +00:00
2015-05-04 07:54:10 +00:00
@Override
public void onPresenceSelected ( ) {
Intent intent = new Intent ( ) ;
boolean chooser = false ;
String fallbackPackageId = null ;
switch ( attachmentChoice ) {
case ATTACHMENT_CHOICE_CHOOSE_IMAGE :
intent . setAction ( Intent . ACTION_GET_CONTENT ) ;
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . JELLY_BEAN_MR2 ) {
2016-01-11 10:17:45 +00:00
intent . putExtra ( Intent . EXTRA_ALLOW_MULTIPLE , true ) ;
2015-03-07 13:15:38 +00:00
}
2015-05-04 07:54:10 +00:00
intent . setType ( " image/* " ) ;
chooser = true ;
break ;
2017-09-18 09:51:47 +00:00
case ATTACHMENT_CHOICE_RECORD_VIDEO :
intent . setAction ( MediaStore . ACTION_VIDEO_CAPTURE ) ;
break ;
2015-05-04 07:54:10 +00:00
case ATTACHMENT_CHOICE_TAKE_PHOTO :
Uri uri = xmppConnectionService . getFileBackend ( ) . getTakePhotoUri ( ) ;
2017-09-18 09:51:47 +00:00
mPendingImageUris . clear ( ) ;
mPendingImageUris . add ( uri ) ;
intent . putExtra ( MediaStore . EXTRA_OUTPUT , uri ) ;
2016-08-30 11:14:38 +00:00
intent . addFlags ( Intent . FLAG_GRANT_WRITE_URI_PERMISSION ) ;
2016-11-08 10:45:20 +00:00
intent . addFlags ( Intent . FLAG_GRANT_READ_URI_PERMISSION ) ;
2015-05-04 07:54:10 +00:00
intent . setAction ( MediaStore . ACTION_IMAGE_CAPTURE ) ;
break ;
case ATTACHMENT_CHOICE_CHOOSE_FILE :
chooser = true ;
intent . setType ( " */* " ) ;
intent . addCategory ( Intent . CATEGORY_OPENABLE ) ;
intent . setAction ( Intent . ACTION_GET_CONTENT ) ;
break ;
case ATTACHMENT_CHOICE_RECORD_VOICE :
intent . setAction ( MediaStore . Audio . Media . RECORD_SOUND_ACTION ) ;
2015-05-20 01:27:52 +00:00
fallbackPackageId = " eu.siacs.conversations.voicerecorder " ;
2015-05-04 07:54:10 +00:00
break ;
case ATTACHMENT_CHOICE_LOCATION :
intent . setAction ( " eu.siacs.conversations.location.request " ) ;
fallbackPackageId = " eu.siacs.conversations.sharelocation " ;
break ;
}
if ( intent . resolveActivity ( getPackageManager ( ) ) ! = null ) {
if ( chooser ) {
startActivityForResult (
Intent . createChooser ( intent , getString ( R . string . perform_action_with ) ) ,
attachmentChoice ) ;
} else {
startActivityForResult ( intent , attachmentChoice ) ;
2014-05-13 15:42:23 +00:00
}
2015-05-04 07:54:10 +00:00
} else if ( fallbackPackageId ! = null ) {
startActivity ( getInstallApkIntent ( fallbackPackageId ) ) ;
2014-05-13 15:42:23 +00:00
}
2015-05-04 07:54:10 +00:00
}
} ;
2015-06-28 11:14:21 +00:00
if ( ( account . httpUploadAvailable ( ) | | attachmentChoice = = ATTACHMENT_CHOICE_LOCATION ) & & encryption ! = Message . ENCRYPTION_OTR ) {
conversation . setNextCounterpart ( null ) ;
2015-05-04 07:54:10 +00:00
callback . onPresenceSelected ( ) ;
} else {
2015-07-21 11:15:59 +00:00
selectPresence ( conversation , callback ) ;
2015-03-07 13:15:38 +00:00
}
2014-05-13 13:25:04 +00:00
}
2014-01-24 09:50:18 +00:00
2015-05-04 02:38:12 +00:00
private Intent getInstallApkIntent ( final String packageId ) {
Intent intent = new Intent ( Intent . ACTION_VIEW ) ;
2015-09-07 13:46:22 +00:00
intent . setData ( Uri . parse ( " market://details?id= " + packageId ) ) ;
2015-05-04 02:38:12 +00:00
if ( intent . resolveActivity ( getPackageManager ( ) ) ! = null ) {
return intent ;
} else {
2015-07-21 11:15:59 +00:00
intent . setData ( Uri . parse ( " http://play.google.com/store/apps/details?id= " + packageId ) ) ;
2015-05-04 02:38:12 +00:00
return intent ;
}
}
2015-05-02 09:38:56 +00:00
public void attachFile ( final int attachmentChoice ) {
2015-12-06 17:23:59 +00:00
if ( attachmentChoice ! = ATTACHMENT_CHOICE_LOCATION ) {
2016-12-02 10:25:14 +00:00
if ( ! Config . ONLY_INTERNAL_STORAGE & & ! hasStoragePermission ( attachmentChoice ) ) {
2015-12-06 17:23:59 +00:00
return ;
}
}
2017-09-18 09:51:47 +00:00
final ConversationFragment . SendButtonAction action ;
2015-05-02 09:38:56 +00:00
switch ( attachmentChoice ) {
case ATTACHMENT_CHOICE_LOCATION :
2017-09-18 09:51:47 +00:00
action = ConversationFragment . SendButtonAction . SEND_LOCATION ;
2015-05-02 09:38:56 +00:00
break ;
case ATTACHMENT_CHOICE_RECORD_VOICE :
2017-09-18 09:51:47 +00:00
action = ConversationFragment . SendButtonAction . RECORD_VOICE ;
break ;
case ATTACHMENT_CHOICE_RECORD_VIDEO :
action = ConversationFragment . SendButtonAction . RECORD_VIDEO ;
2015-05-02 09:38:56 +00:00
break ;
case ATTACHMENT_CHOICE_TAKE_PHOTO :
2017-09-18 09:51:47 +00:00
action = ConversationFragment . SendButtonAction . TAKE_PHOTO ;
2015-05-02 09:38:56 +00:00
break ;
2015-05-26 03:34:58 +00:00
case ATTACHMENT_CHOICE_CHOOSE_IMAGE :
2017-09-18 09:51:47 +00:00
action = ConversationFragment . SendButtonAction . CHOOSE_PICTURE ;
break ;
default :
action = null ;
2015-05-26 03:34:58 +00:00
break ;
2015-05-02 09:38:56 +00:00
}
2017-09-18 09:51:47 +00:00
if ( action ! = null ) {
getPreferences ( ) . edit ( ) . putString ( RECENTLY_USED_QUICK_ACTION , action . toString ( ) ) . apply ( ) ;
}
2014-05-08 12:23:09 +00:00
final Conversation conversation = getSelectedConversation ( ) ;
2015-07-30 22:52:46 +00:00
final int encryption = conversation . getNextEncryption ( ) ;
2015-11-25 19:47:02 +00:00
final int mode = conversation . getMode ( ) ;
2015-03-07 13:15:38 +00:00
if ( encryption = = Message . ENCRYPTION_PGP ) {
2014-05-07 10:33:55 +00:00
if ( hasPgp ( ) ) {
2015-11-25 19:47:02 +00:00
if ( mode = = Conversation . MODE_SINGLE & & conversation . getContact ( ) . getPgpKeyId ( ) ! = 0 ) {
2014-06-06 09:39:17 +00:00
xmppConnectionService . getPgpEngine ( ) . hasKey (
2014-06-07 11:25:27 +00:00
conversation . getContact ( ) ,
new UiCallback < Contact > ( ) {
2014-06-06 09:39:17 +00:00
@Override
2015-11-25 19:47:02 +00:00
public void userInputRequried ( PendingIntent pi , Contact contact ) {
ConversationActivity . this . runIntent ( pi , attachmentChoice ) ;
2014-06-06 09:39:17 +00:00
}
@Override
2014-06-07 11:25:27 +00:00
public void success ( Contact contact ) {
2015-11-25 19:47:02 +00:00
selectPresenceToAttachFile ( attachmentChoice , encryption ) ;
2014-06-06 09:39:17 +00:00
}
@Override
2014-06-07 11:25:27 +00:00
public void error ( int error , Contact contact ) {
2016-06-19 09:08:17 +00:00
replaceToast ( getString ( error ) ) ;
2014-06-06 09:39:17 +00:00
}
} ) ;
2015-11-25 19:47:02 +00:00
} else if ( mode = = Conversation . MODE_MULTI & & conversation . getMucOptions ( ) . pgpKeysInUse ( ) ) {
if ( ! conversation . getMucOptions ( ) . everybodyHasKeys ( ) ) {
Toast warning = Toast
. makeText ( this ,
R . string . missing_public_keys ,
Toast . LENGTH_LONG ) ;
warning . setGravity ( Gravity . CENTER_VERTICAL , 0 , 0 ) ;
warning . show ( ) ;
}
selectPresenceToAttachFile ( attachmentChoice , encryption ) ;
2014-05-08 12:23:09 +00:00
} else {
final ConversationFragment fragment = ( ConversationFragment ) getFragmentManager ( )
2016-01-11 10:17:45 +00:00
. findFragmentByTag ( " conversation " ) ;
2014-05-08 12:23:09 +00:00
if ( fragment ! = null ) {
2014-06-06 09:39:17 +00:00
fragment . showNoPGPKeyDialog ( false ,
new OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog ,
2016-01-11 10:17:45 +00:00
int which ) {
2016-10-18 11:06:24 +00:00
conversation . setNextEncryption ( Message . ENCRYPTION_NONE ) ;
xmppConnectionService . updateConversation ( conversation ) ;
2016-01-11 10:17:45 +00:00
selectPresenceToAttachFile ( attachmentChoice , Message . ENCRYPTION_NONE ) ;
2014-06-06 09:39:17 +00:00
}
} ) ;
2014-05-07 10:33:55 +00:00
}
2014-05-08 12:23:09 +00:00
}
2014-06-09 19:25:01 +00:00
} else {
showInstallPgpDialog ( ) ;
2014-05-07 10:33:55 +00:00
}
2014-05-09 19:20:34 +00:00
} else {
2015-07-19 16:36:28 +00:00
if ( encryption ! = Message . ENCRYPTION_AXOLOTL | | ! trustKeysIfNeeded ( REQUEST_TRUST_KEYS_MENU , attachmentChoice ) ) {
selectPresenceToAttachFile ( attachmentChoice , encryption ) ;
}
2014-05-07 10:33:55 +00:00
}
}
2014-06-06 09:39:17 +00:00
2014-01-24 01:04:05 +00:00
@Override
2015-12-06 17:23:59 +00:00
public void onRequestPermissionsResult ( int requestCode , String permissions [ ] , int [ ] grantResults ) {
if ( grantResults . length > 0 )
if ( grantResults [ 0 ] = = PackageManager . PERMISSION_GRANTED ) {
if ( requestCode = = REQUEST_START_DOWNLOAD ) {
if ( this . mPendingDownloadableMessage ! = null ) {
startDownloadable ( this . mPendingDownloadableMessage ) ;
}
2017-08-22 14:51:42 +00:00
} else if ( requestCode = = REQUEST_ADD_EDITOR_CONTENT ) {
if ( this . mPendingEditorContent ! = null ) {
attachImageToConversation ( this . mPendingEditorContent ) ;
}
2015-12-06 17:23:59 +00:00
} else {
attachFile ( requestCode ) ;
}
} else {
2016-01-11 10:17:45 +00:00
Toast . makeText ( this , R . string . no_storage_permission , Toast . LENGTH_SHORT ) . show ( ) ;
}
2015-12-06 17:23:59 +00:00
}
public void startDownloadable ( Message message ) {
2016-12-02 10:25:14 +00:00
if ( ! Config . ONLY_INTERNAL_STORAGE & & ! hasStoragePermission ( ConversationActivity . REQUEST_START_DOWNLOAD ) ) {
2015-12-06 17:23:59 +00:00
this . mPendingDownloadableMessage = message ;
return ;
}
Transferable transferable = message . getTransferable ( ) ;
if ( transferable ! = null ) {
if ( ! transferable . start ( ) ) {
2016-01-11 10:17:45 +00:00
Toast . makeText ( this , R . string . not_connected_try_again , Toast . LENGTH_SHORT ) . show ( ) ;
2015-12-06 17:23:59 +00:00
}
2017-04-05 20:32:02 +00:00
} else if ( message . treatAsDownloadable ( ) ) {
2015-12-06 17:23:59 +00:00
xmppConnectionService . getHttpConnectionManager ( ) . createNewDownloadConnection ( message , true ) ;
}
}
2016-01-11 10:17:45 +00:00
@Override
2014-12-21 20:43:58 +00:00
public boolean onOptionsItemSelected ( final MenuItem item ) {
2014-09-23 13:06:49 +00:00
if ( item . getItemId ( ) = = android . R . id . home ) {
2014-10-03 13:00:29 +00:00
showConversationsOverview ( ) ;
2014-08-15 11:18:15 +00:00
return true ;
2014-09-23 13:06:49 +00:00
} else if ( item . getItemId ( ) = = R . id . action_add ) {
2014-07-16 22:03:37 +00:00
startActivity ( new Intent ( this , StartConversationActivity . class ) ) ;
2014-09-23 13:06:49 +00:00
return true ;
} else if ( getSelectedConversation ( ) ! = null ) {
switch ( item . getItemId ( ) ) {
2014-11-03 19:00:20 +00:00
case R . id . action_attach_file :
attachFileDialog ( ) ;
break ;
case R . id . action_archive :
this . endConversation ( getSelectedConversation ( ) ) ;
break ;
case R . id . action_contact_details :
2015-01-21 14:31:40 +00:00
switchToContactDetails ( getSelectedConversation ( ) . getContact ( ) ) ;
2014-11-03 19:00:20 +00:00
break ;
case R . id . action_muc_details :
Intent intent = new Intent ( this ,
ConferenceDetailsActivity . class ) ;
intent . setAction ( ConferenceDetailsActivity . ACTION_VIEW_MUC ) ;
intent . putExtra ( " uuid " , getSelectedConversation ( ) . getUuid ( ) ) ;
startActivity ( intent ) ;
break ;
case R . id . action_invite :
inviteToConversation ( getSelectedConversation ( ) ) ;
break ;
case R . id . action_security :
selectEncryptionDialog ( getSelectedConversation ( ) ) ;
break ;
case R . id . action_clear_history :
clearHistoryDialog ( getSelectedConversation ( ) ) ;
break ;
case R . id . action_mute :
muteConversationDialog ( getSelectedConversation ( ) ) ;
break ;
2014-11-18 12:51:04 +00:00
case R . id . action_unmute :
unmuteConversation ( getSelectedConversation ( ) ) ;
break ;
2014-12-21 20:43:58 +00:00
case R . id . action_block :
2017-03-06 15:53:54 +00:00
BlockContactDialog . show ( this , getSelectedConversation ( ) ) ;
2014-12-21 20:43:58 +00:00
break ;
case R . id . action_unblock :
2017-03-06 15:53:54 +00:00
BlockContactDialog . show ( this , getSelectedConversation ( ) ) ;
2014-12-21 20:43:58 +00:00
break ;
2014-11-03 19:00:20 +00:00
default :
break ;
2014-04-10 12:12:08 +00:00
}
2014-09-23 13:06:49 +00:00
return super . onOptionsItemSelected ( item ) ;
} else {
return super . onOptionsItemSelected ( item ) ;
2014-01-24 01:04:05 +00:00
}
}
2014-06-06 09:39:17 +00:00
2014-07-18 10:44:33 +00:00
public void endConversation ( Conversation conversation ) {
2015-04-02 22:06:37 +00:00
endConversation ( conversation , true , true ) ;
}
public void endConversation ( Conversation conversation , boolean showOverview , boolean reinit ) {
if ( showOverview ) {
showConversationsOverview ( ) ;
}
2014-04-20 18:48:16 +00:00
xmppConnectionService . archiveConversation ( conversation ) ;
2015-04-02 22:06:37 +00:00
if ( reinit ) {
if ( conversationList . size ( ) > 0 ) {
setSelectedConversation ( conversationList . get ( 0 ) ) ;
this . mConversationFragment . reInit ( getSelectedConversation ( ) ) ;
} else {
setSelectedConversation ( null ) ;
2016-01-11 10:17:45 +00:00
if ( mRedirected . compareAndSet ( false , true ) ) {
2015-10-20 13:27:33 +00:00
Intent intent = new Intent ( this , StartConversationActivity . class ) ;
2016-01-11 10:17:45 +00:00
intent . putExtra ( " init " , true ) ;
2015-10-20 13:27:33 +00:00
startActivity ( intent ) ;
finish ( ) ;
}
2015-04-02 22:06:37 +00:00
}
2014-04-20 18:48:16 +00:00
}
}
2014-09-27 09:46:56 +00:00
@SuppressLint ( " InflateParams " )
2014-04-20 18:48:16 +00:00
protected void clearHistoryDialog ( final Conversation conversation ) {
2014-04-16 16:16:23 +00:00
AlertDialog . Builder builder = new AlertDialog . Builder ( this ) ;
builder . setTitle ( getString ( R . string . clear_conversation_history ) ) ;
2014-06-06 09:39:17 +00:00
View dialogView = getLayoutInflater ( ) . inflate (
R . layout . dialog_clear_history , null ) ;
final CheckBox endConversationCheckBox = ( CheckBox ) dialogView
2016-01-11 10:17:45 +00:00
. findViewById ( R . id . end_conversation_checkbox ) ;
2014-04-16 16:16:23 +00:00
builder . setView ( dialogView ) ;
builder . setNegativeButton ( getString ( R . string . cancel ) , null ) ;
2014-06-06 09:39:17 +00:00
builder . setPositiveButton ( getString ( R . string . delete_messages ) ,
new OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
2014-12-15 16:14:27 +00:00
ConversationActivity . this . xmppConnectionService . clearConversationHistory ( conversation ) ;
2014-06-06 09:39:17 +00:00
if ( endConversationCheckBox . isChecked ( ) ) {
endConversation ( conversation ) ;
2014-12-14 17:10:46 +00:00
} else {
updateConversationList ( ) ;
ConversationActivity . this . mConversationFragment . updateMessages ( ) ;
2014-06-06 09:39:17 +00:00
}
}
} ) ;
2014-04-16 16:16:23 +00:00
builder . create ( ) . show ( ) ;
}
2014-09-28 13:21:56 +00:00
2014-09-23 13:06:49 +00:00
protected void attachFileDialog ( ) {
View menuAttachFile = findViewById ( R . id . action_attach_file ) ;
if ( menuAttachFile = = null ) {
return ;
}
PopupMenu attachFilePopup = new PopupMenu ( this , menuAttachFile ) ;
attachFilePopup . inflate ( R . menu . attachment_choices ) ;
2015-01-03 15:06:59 +00:00
if ( new Intent ( MediaStore . Audio . Media . RECORD_SOUND_ACTION ) . resolveActivity ( getPackageManager ( ) ) = = null ) {
attachFilePopup . getMenu ( ) . findItem ( R . id . attach_record_voice ) . setVisible ( false ) ;
}
2015-03-07 13:15:38 +00:00
if ( new Intent ( " eu.siacs.conversations.location.request " ) . resolveActivity ( getPackageManager ( ) ) = = null ) {
attachFilePopup . getMenu ( ) . findItem ( R . id . attach_location ) . setVisible ( false ) ;
}
2015-01-03 15:06:59 +00:00
attachFilePopup . setOnMenuItemClickListener ( new OnMenuItemClickListener ( ) {
2014-09-23 13:06:49 +00:00
2015-01-14 20:28:27 +00:00
@Override
public boolean onMenuItemClick ( MenuItem item ) {
switch ( item . getItemId ( ) ) {
case R . id . attach_choose_picture :
attachFile ( ATTACHMENT_CHOICE_CHOOSE_IMAGE ) ;
break ;
case R . id . attach_take_picture :
attachFile ( ATTACHMENT_CHOICE_TAKE_PHOTO ) ;
break ;
2017-09-18 09:51:47 +00:00
case R . id . attach_record_video :
attachFile ( ATTACHMENT_CHOICE_RECORD_VIDEO ) ;
break ;
2015-01-14 20:28:27 +00:00
case R . id . attach_choose_file :
attachFile ( ATTACHMENT_CHOICE_CHOOSE_FILE ) ;
break ;
case R . id . attach_record_voice :
attachFile ( ATTACHMENT_CHOICE_RECORD_VOICE ) ;
break ;
2015-03-07 13:15:38 +00:00
case R . id . attach_location :
attachFile ( ATTACHMENT_CHOICE_LOCATION ) ;
break ;
2014-12-21 20:43:58 +00:00
}
2015-01-14 20:28:27 +00:00
return false ;
}
} ) ;
2017-03-03 11:26:33 +00:00
UIHelper . showIconsInPopup ( attachFilePopup ) ;
2014-09-23 13:06:49 +00:00
attachFilePopup . show ( ) ;
}
2015-01-02 00:21:14 +00:00
public void verifyOtrSessionDialog ( final Conversation conversation , View view ) {
if ( ! conversation . hasValidOtrSession ( ) | | conversation . getOtrSession ( ) . getSessionStatus ( ) ! = SessionStatus . ENCRYPTED ) {
Toast . makeText ( this , R . string . otr_session_not_started , Toast . LENGTH_LONG ) . show ( ) ;
return ;
}
if ( view = = null ) {
return ;
}
PopupMenu popup = new PopupMenu ( this , view ) ;
popup . inflate ( R . menu . verification_choices ) ;
popup . setOnMenuItemClickListener ( new OnMenuItemClickListener ( ) {
@Override
public boolean onMenuItemClick ( MenuItem menuItem ) {
Intent intent = new Intent ( ConversationActivity . this , VerifyOTRActivity . class ) ;
intent . setAction ( VerifyOTRActivity . ACTION_VERIFY_CONTACT ) ;
intent . putExtra ( " contact " , conversation . getContact ( ) . getJid ( ) . toBareJid ( ) . toString ( ) ) ;
2016-01-22 19:46:24 +00:00
intent . putExtra ( EXTRA_ACCOUNT , conversation . getAccount ( ) . getJid ( ) . toBareJid ( ) . toString ( ) ) ;
2015-01-02 00:21:14 +00:00
switch ( menuItem . getItemId ( ) ) {
case R . id . scan_fingerprint :
2015-09-07 13:46:22 +00:00
intent . putExtra ( " mode " , VerifyOTRActivity . MODE_SCAN_FINGERPRINT ) ;
2015-01-02 00:21:14 +00:00
break ;
case R . id . ask_question :
2015-09-07 13:46:22 +00:00
intent . putExtra ( " mode " , VerifyOTRActivity . MODE_ASK_QUESTION ) ;
2015-01-02 00:21:14 +00:00
break ;
case R . id . manual_verification :
2015-09-07 13:46:22 +00:00
intent . putExtra ( " mode " , VerifyOTRActivity . MODE_MANUAL_VERIFICATION ) ;
2015-01-02 00:21:14 +00:00
break ;
}
startActivity ( intent ) ;
return true ;
}
} ) ;
popup . show ( ) ;
}
2014-09-23 13:06:49 +00:00
protected void selectEncryptionDialog ( final Conversation conversation ) {
View menuItemView = findViewById ( R . id . action_security ) ;
if ( menuItemView = = null ) {
return ;
}
PopupMenu popup = new PopupMenu ( this , menuItemView ) ;
final ConversationFragment fragment = ( ConversationFragment ) getFragmentManager ( )
2016-01-11 10:17:45 +00:00
. findFragmentByTag ( " conversation " ) ;
2014-09-23 13:06:49 +00:00
if ( fragment ! = null ) {
popup . setOnMenuItemClickListener ( new OnMenuItemClickListener ( ) {
@Override
public boolean onMenuItemClick ( MenuItem item ) {
switch ( item . getItemId ( ) ) {
2014-11-03 19:00:20 +00:00
case R . id . encryption_choice_none :
conversation . setNextEncryption ( Message . ENCRYPTION_NONE ) ;
item . setChecked ( true ) ;
break ;
case R . id . encryption_choice_otr :
conversation . setNextEncryption ( Message . ENCRYPTION_OTR ) ;
item . setChecked ( true ) ;
break ;
case R . id . encryption_choice_pgp :
if ( hasPgp ( ) ) {
2015-10-29 13:03:41 +00:00
if ( conversation . getAccount ( ) . getPgpSignature ( ) ! = null ) {
2015-07-12 15:59:22 +00:00
conversation . setNextEncryption ( Message . ENCRYPTION_PGP ) ;
2014-11-03 19:00:20 +00:00
item . setChecked ( true ) ;
} else {
2017-12-05 18:16:53 +00:00
announcePgp ( conversation . getAccount ( ) , conversation , null , onOpenPGPKeyPublished ) ;
2014-11-03 19:00:20 +00:00
}
2014-09-23 13:06:49 +00:00
} else {
2014-11-03 19:00:20 +00:00
showInstallPgpDialog ( ) ;
2014-09-23 13:06:49 +00:00
}
2014-11-03 19:00:20 +00:00
break ;
2015-06-25 15:01:42 +00:00
case R . id . encryption_choice_axolotl :
2015-07-10 01:02:49 +00:00
Log . d ( Config . LOGTAG , AxolotlService . getLogprefix ( conversation . getAccount ( ) )
+ " Enabled axolotl for Contact " + conversation . getContact ( ) . getJid ( ) ) ;
conversation . setNextEncryption ( Message . ENCRYPTION_AXOLOTL ) ;
item . setChecked ( true ) ;
2015-06-26 13:41:02 +00:00
break ;
2014-11-03 19:00:20 +00:00
default :
conversation . setNextEncryption ( Message . ENCRYPTION_NONE ) ;
break ;
2014-09-23 13:06:49 +00:00
}
2016-10-18 11:06:24 +00:00
xmppConnectionService . updateConversation ( conversation ) ;
2014-09-23 13:06:49 +00:00
fragment . updateChatMsgHint ( ) ;
2015-07-12 15:59:22 +00:00
invalidateOptionsMenu ( ) ;
2015-07-29 18:10:21 +00:00
refreshUi ( ) ;
2014-09-23 13:06:49 +00:00
return true ;
}
} ) ;
popup . inflate ( R . menu . encryption_choices ) ;
MenuItem otr = popup . getMenu ( ) . findItem ( R . id . encryption_choice_otr ) ;
2015-07-12 15:59:22 +00:00
MenuItem none = popup . getMenu ( ) . findItem ( R . id . encryption_choice_none ) ;
MenuItem pgp = popup . getMenu ( ) . findItem ( R . id . encryption_choice_pgp ) ;
2015-07-10 01:02:49 +00:00
MenuItem axolotl = popup . getMenu ( ) . findItem ( R . id . encryption_choice_axolotl ) ;
2016-02-24 13:47:49 +00:00
pgp . setVisible ( Config . supportOpenPgp ( ) ) ;
none . setVisible ( Config . supportUnencrypted ( ) | | conversation . getMode ( ) = = Conversation . MODE_MULTI ) ;
otr . setVisible ( Config . supportOtr ( ) ) ;
axolotl . setVisible ( Config . supportOmemo ( ) ) ;
2014-09-23 13:06:49 +00:00
if ( conversation . getMode ( ) = = Conversation . MODE_MULTI ) {
2015-08-06 11:09:53 +00:00
otr . setVisible ( false ) ;
2016-02-29 12:18:07 +00:00
}
if ( ! conversation . getAccount ( ) . getAxolotlService ( ) . isConversationAxolotlCapable ( conversation ) ) {
2015-07-10 01:02:49 +00:00
axolotl . setEnabled ( false ) ;
}
2015-07-30 22:52:46 +00:00
switch ( conversation . getNextEncryption ( ) ) {
2014-11-03 19:00:20 +00:00
case Message . ENCRYPTION_NONE :
none . setChecked ( true ) ;
break ;
case Message . ENCRYPTION_OTR :
otr . setChecked ( true ) ;
break ;
case Message . ENCRYPTION_PGP :
2015-07-12 15:59:22 +00:00
pgp . setChecked ( true ) ;
2014-11-03 19:00:20 +00:00
break ;
2015-06-25 15:01:42 +00:00
case Message . ENCRYPTION_AXOLOTL :
2015-07-30 22:52:46 +00:00
axolotl . setChecked ( true ) ;
2015-06-25 15:01:42 +00:00
break ;
2014-11-03 19:00:20 +00:00
default :
2015-07-12 15:59:22 +00:00
none . setChecked ( true ) ;
2014-11-03 19:00:20 +00:00
break ;
2014-09-23 13:06:49 +00:00
}
popup . show ( ) ;
}
}
2014-09-08 11:37:22 +00:00
2014-09-03 10:36:54 +00:00
protected void muteConversationDialog ( final Conversation conversation ) {
AlertDialog . Builder builder = new AlertDialog . Builder ( this ) ;
2014-11-17 23:07:27 +00:00
builder . setTitle ( R . string . disable_notifications ) ;
2015-07-30 22:52:46 +00:00
final int [ ] durations = getResources ( ) . getIntArray ( R . array . mute_options_durations ) ;
2014-09-08 11:37:22 +00:00
builder . setItems ( R . array . mute_options_descriptions ,
new OnClickListener ( ) {
@Override
2014-12-21 20:43:58 +00:00
public void onClick ( final DialogInterface dialog , final int which ) {
final long till ;
2014-09-08 11:37:22 +00:00
if ( durations [ which ] = = - 1 ) {
till = Long . MAX_VALUE ;
} else {
2015-02-12 17:52:10 +00:00
till = System . currentTimeMillis ( ) + ( durations [ which ] * 1000 ) ;
2014-09-08 11:37:22 +00:00
}
conversation . setMutedTill ( till ) ;
2016-10-18 11:06:24 +00:00
ConversationActivity . this . xmppConnectionService . updateConversation ( conversation ) ;
2014-11-17 23:07:27 +00:00
updateConversationList ( ) ;
ConversationActivity . this . mConversationFragment . updateMessages ( ) ;
2014-11-18 12:51:04 +00:00
invalidateOptionsMenu ( ) ;
2014-09-08 11:37:22 +00:00
}
} ) ;
2014-09-03 10:36:54 +00:00
builder . create ( ) . show ( ) ;
}
2014-01-24 01:04:05 +00:00
2014-11-18 12:51:04 +00:00
public void unmuteConversation ( final Conversation conversation ) {
conversation . setMutedTill ( 0 ) ;
2016-10-18 11:06:24 +00:00
this . xmppConnectionService . updateConversation ( conversation ) ;
2014-11-18 12:51:04 +00:00
updateConversationList ( ) ;
ConversationActivity . this . mConversationFragment . updateMessages ( ) ;
invalidateOptionsMenu ( ) ;
}
2014-01-24 09:50:18 +00:00
@Override
2014-11-21 17:57:27 +00:00
public void onBackPressed ( ) {
if ( ! isConversationsOverviewVisable ( ) ) {
showConversationsOverview ( ) ;
} else {
2017-01-22 17:26:47 +00:00
super . onBackPressed ( ) ;
2014-01-24 09:50:18 +00:00
}
}
2014-04-10 12:12:08 +00:00
2015-09-07 13:46:22 +00:00
@Override
public boolean onKeyUp ( int key , KeyEvent event ) {
2015-09-07 18:45:21 +00:00
int rotation = getWindowManager ( ) . getDefaultDisplay ( ) . getRotation ( ) ;
final int upKey ;
final int downKey ;
2016-01-11 10:17:45 +00:00
switch ( rotation ) {
2015-09-07 18:45:21 +00:00
case Surface . ROTATION_90 :
upKey = KeyEvent . KEYCODE_DPAD_LEFT ;
downKey = KeyEvent . KEYCODE_DPAD_RIGHT ;
break ;
case Surface . ROTATION_180 :
upKey = KeyEvent . KEYCODE_DPAD_DOWN ;
downKey = KeyEvent . KEYCODE_DPAD_UP ;
break ;
case Surface . ROTATION_270 :
upKey = KeyEvent . KEYCODE_DPAD_RIGHT ;
downKey = KeyEvent . KEYCODE_DPAD_LEFT ;
break ;
2017-01-22 17:26:47 +00:00
case Surface . ROTATION_0 :
2015-09-07 18:45:21 +00:00
default :
upKey = KeyEvent . KEYCODE_DPAD_UP ;
downKey = KeyEvent . KEYCODE_DPAD_DOWN ;
}
2016-06-05 18:21:44 +00:00
final boolean modifier = event . isCtrlPressed ( ) | | ( event . getMetaState ( ) & KeyEvent . META_ALT_LEFT_ON ) ! = 0 ;
2015-09-07 13:46:22 +00:00
if ( modifier & & key = = KeyEvent . KEYCODE_TAB & & isConversationsOverviewHideable ( ) ) {
toggleConversationsOverview ( ) ;
return true ;
2016-05-12 16:49:54 +00:00
} else if ( modifier & & key = = KeyEvent . KEYCODE_SPACE ) {
startActivity ( new Intent ( this , StartConversationActivity . class ) ) ;
return true ;
2015-09-07 18:45:21 +00:00
} else if ( modifier & & key = = downKey ) {
2015-09-07 13:46:22 +00:00
if ( isConversationsOverviewHideable ( ) & & ! isConversationsOverviewVisable ( ) ) {
2016-01-11 10:17:45 +00:00
showConversationsOverview ( ) ;
;
2015-09-07 13:46:22 +00:00
}
2015-09-09 21:28:37 +00:00
return selectDownConversation ( ) ;
2015-09-07 18:45:21 +00:00
} else if ( modifier & & key = = upKey ) {
2015-09-07 13:46:22 +00:00
if ( isConversationsOverviewHideable ( ) & & ! isConversationsOverviewVisable ( ) ) {
2015-09-09 21:28:37 +00:00
showConversationsOverview ( ) ;
2015-09-07 13:46:22 +00:00
}
2015-09-09 21:28:37 +00:00
return selectUpConversation ( ) ;
} else if ( modifier & & key = = KeyEvent . KEYCODE_1 ) {
return openConversationByIndex ( 0 ) ;
} else if ( modifier & & key = = KeyEvent . KEYCODE_2 ) {
return openConversationByIndex ( 1 ) ;
} else if ( modifier & & key = = KeyEvent . KEYCODE_3 ) {
return openConversationByIndex ( 2 ) ;
} else if ( modifier & & key = = KeyEvent . KEYCODE_4 ) {
return openConversationByIndex ( 3 ) ;
} else if ( modifier & & key = = KeyEvent . KEYCODE_5 ) {
return openConversationByIndex ( 4 ) ;
} else if ( modifier & & key = = KeyEvent . KEYCODE_6 ) {
return openConversationByIndex ( 5 ) ;
} else if ( modifier & & key = = KeyEvent . KEYCODE_7 ) {
return openConversationByIndex ( 6 ) ;
} else if ( modifier & & key = = KeyEvent . KEYCODE_8 ) {
return openConversationByIndex ( 7 ) ;
} else if ( modifier & & key = = KeyEvent . KEYCODE_9 ) {
return openConversationByIndex ( 8 ) ;
} else if ( modifier & & key = = KeyEvent . KEYCODE_0 ) {
return openConversationByIndex ( 9 ) ;
2015-09-07 13:46:22 +00:00
} else {
return super . onKeyUp ( key , event ) ;
}
}
private void toggleConversationsOverview ( ) {
if ( isConversationsOverviewVisable ( ) ) {
hideConversationsOverview ( ) ;
if ( mConversationFragment ! = null ) {
mConversationFragment . setFocusOnInputField ( ) ;
}
} else {
showConversationsOverview ( ) ;
}
}
2015-09-09 21:28:37 +00:00
private boolean selectUpConversation ( ) {
2015-09-07 13:46:22 +00:00
if ( this . mSelectedConversation ! = null ) {
int index = this . conversationList . indexOf ( this . mSelectedConversation ) ;
if ( index > 0 ) {
2015-09-09 21:28:37 +00:00
return openConversationByIndex ( index - 1 ) ;
2015-09-07 13:46:22 +00:00
}
}
2015-09-09 21:28:37 +00:00
return false ;
2015-09-07 13:46:22 +00:00
}
2015-09-09 21:28:37 +00:00
private boolean selectDownConversation ( ) {
2015-09-07 13:46:22 +00:00
if ( this . mSelectedConversation ! = null ) {
int index = this . conversationList . indexOf ( this . mSelectedConversation ) ;
if ( index ! = - 1 & & index < this . conversationList . size ( ) - 1 ) {
2015-09-09 21:28:37 +00:00
return openConversationByIndex ( index + 1 ) ;
2015-09-07 13:46:22 +00:00
}
}
2015-09-09 21:28:37 +00:00
return false ;
}
private boolean openConversationByIndex ( int index ) {
try {
this . conversationWasSelectedByKeyboard = true ;
2017-11-17 20:00:01 +00:00
this . mConversationFragment . stopScrolling ( ) ;
2015-09-09 21:28:37 +00:00
setSelectedConversation ( this . conversationList . get ( index ) ) ;
this . mConversationFragment . reInit ( getSelectedConversation ( ) ) ;
if ( index > listView . getLastVisiblePosition ( ) - 1 | | index < listView . getFirstVisiblePosition ( ) + 1 ) {
this . listView . setSelection ( index ) ;
}
openConversation ( ) ;
return true ;
} catch ( IndexOutOfBoundsException e ) {
return false ;
}
2015-09-07 13:46:22 +00:00
}
2014-05-21 14:43:19 +00:00
@Override
2014-11-07 14:09:28 +00:00
protected void onNewIntent ( final Intent intent ) {
2016-07-25 12:15:47 +00:00
if ( intent ! = null & & ACTION_VIEW_CONVERSATION . equals ( intent . getAction ( ) ) ) {
2016-09-12 19:18:56 +00:00
mOpenConversation = null ;
2016-11-08 11:42:13 +00:00
mUnprocessedNewIntent = true ;
2016-07-25 12:15:47 +00:00
if ( xmppConnectionServiceBound ) {
2014-10-24 12:34:46 +00:00
handleViewConversationIntent ( intent ) ;
2016-07-25 12:15:47 +00:00
intent . setAction ( Intent . ACTION_MAIN ) ;
} else {
setIntent ( intent ) ;
2014-05-21 14:43:19 +00:00
}
}
}
2014-06-06 09:39:17 +00:00
2014-03-28 11:22:09 +00:00
@Override
2014-02-04 21:26:46 +00:00
public void onStart ( ) {
super . onStart ( ) ;
2015-10-20 13:27:33 +00:00
this . mRedirected . set ( false ) ;
2014-03-28 11:22:09 +00:00
if ( this . xmppConnectionServiceBound ) {
this . onBackendConnected ( ) ;
}
2014-04-10 12:12:08 +00:00
if ( conversationList . size ( ) > = 1 ) {
2014-09-10 15:59:57 +00:00
this . onConversationUpdate ( ) ;
2014-02-05 21:33:39 +00:00
}
2014-02-04 21:26:46 +00:00
}
2014-04-10 12:12:08 +00:00
2015-01-02 11:04:33 +00:00
@Override
public void onPause ( ) {
2015-04-02 22:06:37 +00:00
listView . discardUndo ( ) ;
2015-01-02 11:04:33 +00:00
super . onPause ( ) ;
this . mActivityPaused = true ;
}
2014-12-09 19:22:21 +00:00
@Override
public void onResume ( ) {
super . onResume ( ) ;
2015-01-14 20:28:27 +00:00
final int theme = findTheme ( ) ;
final boolean usingEnterKey = usingEnterKey ( ) ;
if ( this . mTheme ! = theme | | usingEnterKey ! = mUsingEnterKey ) {
2014-12-09 19:22:21 +00:00
recreate ( ) ;
}
2015-01-02 11:04:33 +00:00
this . mActivityPaused = false ;
2015-01-29 12:20:18 +00:00
2016-11-08 11:42:13 +00:00
2015-01-15 15:32:24 +00:00
if ( ! isConversationsOverviewVisable ( ) | | ! isConversationsOverviewHideable ( ) ) {
sendReadMarkerIfNecessary ( getSelectedConversation ( ) ) ;
}
2015-01-29 12:20:18 +00:00
2014-12-09 19:22:21 +00:00
}
2014-10-03 13:00:29 +00:00
@Override
2014-11-07 14:09:28 +00:00
public void onSaveInstanceState ( final Bundle savedInstanceState ) {
2014-10-06 17:27:58 +00:00
Conversation conversation = getSelectedConversation ( ) ;
2014-10-06 20:03:01 +00:00
if ( conversation ! = null ) {
2016-01-11 10:17:45 +00:00
savedInstanceState . putString ( STATE_OPEN_CONVERSATION , conversation . getUuid ( ) ) ;
2016-09-12 19:18:56 +00:00
Pair < Integer , Integer > scrollPosition = mConversationFragment . getScrollPosition ( ) ;
if ( scrollPosition ! = null ) {
savedInstanceState . putInt ( STATE_FIRST_VISIBLE , scrollPosition . first ) ;
savedInstanceState . putInt ( STATE_OFFSET_FROM_TOP , scrollPosition . second ) ;
}
2015-12-05 18:02:57 +00:00
} else {
savedInstanceState . remove ( STATE_OPEN_CONVERSATION ) ;
2014-10-06 17:27:58 +00:00
}
2016-01-11 10:17:45 +00:00
savedInstanceState . putBoolean ( STATE_PANEL_OPEN , isConversationsOverviewVisable ( ) ) ;
2015-04-11 12:53:10 +00:00
if ( this . mPendingImageUris . size ( ) > = 1 ) {
2016-10-03 09:13:04 +00:00
Log . d ( Config . LOGTAG , " ConversationsActivity.onSaveInstanceState() - saving pending image uri " ) ;
2015-04-11 12:53:10 +00:00
savedInstanceState . putString ( STATE_PENDING_URI , this . mPendingImageUris . get ( 0 ) . toString ( ) ) ;
2015-12-05 18:02:57 +00:00
} else {
savedInstanceState . remove ( STATE_PENDING_URI ) ;
2014-11-06 16:25:14 +00:00
}
2014-10-03 13:00:29 +00:00
super . onSaveInstanceState ( savedInstanceState ) ;
}
2015-12-05 18:02:57 +00:00
private void clearPending ( ) {
mPendingImageUris . clear ( ) ;
mPendingFileUris . clear ( ) ;
mPendingGeoUri = null ;
mPostponedActivityResult = null ;
}
2018-02-09 21:19:13 +00:00
private void redirectToStartConversationActivity ( boolean noAnimation ) {
2017-03-06 15:53:54 +00:00
Account pendingAccount = xmppConnectionService . getPendingAccount ( ) ;
if ( pendingAccount = = null ) {
Intent startConversationActivity = new Intent ( this , StartConversationActivity . class ) ;
2018-02-09 21:19:13 +00:00
startConversationActivity . setFlags ( Intent . FLAG_ACTIVITY_NEW_TASK | Intent . FLAG_ACTIVITY_CLEAR_TASK ) ;
if ( noAnimation ) {
startConversationActivity . addFlags ( Intent . FLAG_ACTIVITY_NO_ANIMATION ) ;
}
2017-03-06 15:53:54 +00:00
startConversationActivity . putExtra ( " init " , true ) ;
startActivity ( startConversationActivity ) ;
2018-02-09 21:19:13 +00:00
if ( noAnimation ) {
overridePendingTransition ( 0 , 0 ) ;
}
2017-03-06 15:53:54 +00:00
} else {
switchToAccount ( pendingAccount , true ) ;
}
}
2014-01-25 18:33:12 +00:00
@Override
2014-01-27 19:40:42 +00:00
void onBackendConnected ( ) {
2015-01-02 11:04:33 +00:00
this . xmppConnectionService . getNotificationService ( ) . setIsInForeground ( true ) ;
2014-10-03 13:00:29 +00:00
updateConversationList ( ) ;
2015-05-12 02:33:04 +00:00
if ( mPendingConferenceInvite ! = null ) {
2016-06-28 08:34:43 +00:00
if ( mPendingConferenceInvite . execute ( this ) ) {
mToast = Toast . makeText ( this , R . string . creating_conference , Toast . LENGTH_LONG ) ;
mToast . show ( ) ;
}
2015-05-12 02:33:04 +00:00
mPendingConferenceInvite = null ;
}
2016-07-25 12:15:47 +00:00
final Intent intent = getIntent ( ) ;
2014-10-03 13:00:29 +00:00
if ( xmppConnectionService . getAccounts ( ) . size ( ) = = 0 ) {
2016-01-11 10:17:45 +00:00
if ( mRedirected . compareAndSet ( false , true ) ) {
2015-10-20 13:27:33 +00:00
if ( Config . X509_VERIFICATION ) {
2018-02-09 19:09:58 +00:00
Intent redirectionIntent = new Intent ( this , ManageAccountActivity . class ) ;
redirectionIntent . setFlags ( Intent . FLAG_ACTIVITY_NEW_TASK | Intent . FLAG_ACTIVITY_CLEAR_TASK | Intent . FLAG_ACTIVITY_NO_ANIMATION ) ;
startActivity ( redirectionIntent ) ;
2018-02-09 21:19:13 +00:00
overridePendingTransition ( 0 , 0 ) ;
2016-04-19 16:03:24 +00:00
} else if ( Config . MAGIC_CREATE_DOMAIN ! = null ) {
2018-02-10 09:45:33 +00:00
WelcomeActivity . launch ( this ) ;
2015-10-20 13:27:33 +00:00
} else {
2016-08-26 07:10:59 +00:00
Intent editAccount = new Intent ( this , EditAccountActivity . class ) ;
editAccount . putExtra ( " init " , true ) ;
2018-02-09 19:09:58 +00:00
editAccount . setFlags ( Intent . FLAG_ACTIVITY_NEW_TASK | Intent . FLAG_ACTIVITY_CLEAR_TASK | Intent . FLAG_ACTIVITY_NO_ANIMATION ) ;
2016-08-26 07:10:59 +00:00
startActivity ( editAccount ) ;
2018-02-09 21:19:13 +00:00
overridePendingTransition ( 0 , 0 ) ;
2015-10-20 13:27:33 +00:00
}
2015-02-22 12:24:29 +00:00
}
2014-10-03 13:00:29 +00:00
} else if ( conversationList . size ( ) < = 0 ) {
2016-01-11 10:17:45 +00:00
if ( mRedirected . compareAndSet ( false , true ) ) {
2018-02-09 21:19:13 +00:00
redirectToStartConversationActivity ( true ) ;
2015-02-22 12:24:29 +00:00
}
2016-09-12 19:18:56 +00:00
} else if ( selectConversationByUuid ( mOpenConversation ) ) {
2014-11-07 14:38:20 +00:00
if ( mPanelOpen ) {
2014-10-03 13:00:29 +00:00
showConversationsOverview ( ) ;
2014-11-07 20:49:31 +00:00
} else {
if ( isConversationsOverviewHideable ( ) ) {
openConversation ( ) ;
2016-01-16 20:18:59 +00:00
updateActionBarTitle ( true ) ;
2014-11-07 20:49:31 +00:00
}
2014-10-03 13:00:29 +00:00
}
2016-09-12 19:18:56 +00:00
if ( this . mConversationFragment . reInit ( getSelectedConversation ( ) ) ) {
Log . d ( Config . LOGTAG , " setting scroll position on fragment " ) ;
this . mConversationFragment . setScrollPosition ( mScrollPosition ) ;
}
mOpenConversation = null ;
2016-07-25 12:15:47 +00:00
} else if ( intent ! = null & & ACTION_VIEW_CONVERSATION . equals ( intent . getAction ( ) ) ) {
clearPending ( ) ;
handleViewConversationIntent ( intent ) ;
intent . setAction ( Intent . ACTION_MAIN ) ;
2015-05-12 01:56:13 +00:00
} else if ( getSelectedConversation ( ) = = null ) {
2017-03-06 15:53:54 +00:00
reInitLatestConversation ( ) ;
2015-08-24 18:56:25 +00:00
} else {
this . mConversationFragment . messageListAdapter . updatePreferences ( ) ;
this . mConversationFragment . messagesView . invalidateViews ( ) ;
2015-09-04 12:48:00 +00:00
this . mConversationFragment . setupIme ( ) ;
2014-01-27 19:40:42 +00:00
}
2014-08-31 14:28:21 +00:00
2015-12-01 13:18:07 +00:00
if ( this . mPostponedActivityResult ! = null ) {
this . onActivityResult ( mPostponedActivityResult . first , RESULT_OK , mPostponedActivityResult . second ) ;
}
2017-03-06 15:53:54 +00:00
final boolean stopping = isStopping ( ) ;
2016-10-03 09:13:04 +00:00
2016-01-11 10:17:45 +00:00
if ( ! forbidProcessingPendings ) {
2015-07-19 16:36:28 +00:00
for ( Iterator < Uri > i = mPendingImageUris . iterator ( ) ; i . hasNext ( ) ; i . remove ( ) ) {
Uri foo = i . next ( ) ;
2016-10-03 09:13:04 +00:00
Log . d ( Config . LOGTAG , " ConversationsActivity.onBackendConnected() - attaching image to conversations. stopping= " + Boolean . toString ( stopping ) ) ;
2015-07-19 16:36:28 +00:00
attachImageToConversation ( getSelectedConversation ( ) , foo ) ;
}
2015-04-11 12:53:10 +00:00
2015-07-19 16:36:28 +00:00
for ( Iterator < Uri > i = mPendingFileUris . iterator ( ) ; i . hasNext ( ) ; i . remove ( ) ) {
2016-10-03 09:13:04 +00:00
Log . d ( Config . LOGTAG , " ConversationsActivity.onBackendConnected() - attaching file to conversations. stopping= " + Boolean . toString ( stopping ) ) ;
2015-07-19 16:36:28 +00:00
attachFileToConversation ( getSelectedConversation ( ) , i . next ( ) ) ;
}
2015-04-11 12:53:10 +00:00
2015-07-19 16:36:28 +00:00
if ( mPendingGeoUri ! = null ) {
attachLocationToConversation ( getSelectedConversation ( ) , mPendingGeoUri ) ;
mPendingGeoUri = null ;
}
2014-08-21 07:19:18 +00:00
}
2015-07-19 16:36:28 +00:00
forbidProcessingPendings = false ;
2017-07-01 11:41:24 +00:00
if ( ! ExceptionHelper . checkForCrash ( this , this . xmppConnectionService ) & & ! mRedirected . get ( ) ) {
2016-01-11 10:17:45 +00:00
openBatteryOptimizationDialogIfNeeded ( ) ;
}
2017-01-20 12:44:29 +00:00
if ( isConversationsOverviewVisable ( ) & & isConversationsOverviewHideable ( ) ) {
xmppConnectionService . getNotificationService ( ) . setOpenConversation ( null ) ;
2017-01-22 12:08:21 +00:00
} else {
xmppConnectionService . getNotificationService ( ) . setOpenConversation ( getSelectedConversation ( ) ) ;
2017-01-20 12:44:29 +00:00
}
2014-10-03 13:00:29 +00:00
}
2014-10-29 08:57:03 +00:00
2017-03-06 15:53:54 +00:00
private boolean isStopping ( ) {
if ( Build . VERSION . SDK_INT > = 17 ) {
return isFinishing ( ) | | isDestroyed ( ) ;
} else {
return isFinishing ( ) ;
}
}
private void reInitLatestConversation ( ) {
showConversationsOverview ( ) ;
clearPending ( ) ;
setSelectedConversation ( conversationList . get ( 0 ) ) ;
this . mConversationFragment . reInit ( getSelectedConversation ( ) ) ;
}
2015-01-16 05:36:11 +00:00
private void handleViewConversationIntent ( final Intent intent ) {
2015-04-19 17:11:32 +00:00
final String uuid = intent . getStringExtra ( CONVERSATION ) ;
2016-07-25 12:15:47 +00:00
final String downloadUuid = intent . getStringExtra ( EXTRA_DOWNLOAD_UUID ) ;
2015-04-19 17:11:32 +00:00
final String text = intent . getStringExtra ( TEXT ) ;
final String nick = intent . getStringExtra ( NICK ) ;
2016-01-11 10:17:45 +00:00
final boolean pm = intent . getBooleanExtra ( PRIVATE_MESSAGE , false ) ;
2017-11-17 20:00:01 +00:00
this . mConversationFragment . stopScrolling ( ) ;
2015-01-10 18:43:23 +00:00
if ( selectConversationByUuid ( uuid ) ) {
this . mConversationFragment . reInit ( getSelectedConversation ( ) ) ;
if ( nick ! = null ) {
2015-07-21 11:15:59 +00:00
if ( pm ) {
Jid jid = getSelectedConversation ( ) . getJid ( ) ;
try {
2016-01-11 10:17:45 +00:00
Jid next = Jid . fromParts ( jid . getLocalpart ( ) , jid . getDomainpart ( ) , nick ) ;
2015-07-21 11:15:59 +00:00
this . mConversationFragment . privateMessageWith ( next ) ;
} catch ( final InvalidJidException ignored ) {
//do nothing
}
} else {
this . mConversationFragment . highlightInConference ( nick ) ;
}
2015-01-10 18:43:23 +00:00
} else {
this . mConversationFragment . appendText ( text ) ;
}
hideConversationsOverview ( ) ;
2016-11-08 11:42:13 +00:00
mUnprocessedNewIntent = false ;
2015-01-10 18:43:23 +00:00
openConversation ( ) ;
if ( mContentView instanceof SlidingPaneLayout ) {
updateActionBarTitle ( true ) ; //fixes bug where slp isn't properly closed yet
}
2015-01-16 05:36:11 +00:00
if ( downloadUuid ! = null ) {
final Message message = mSelectedConversation . findMessageWithFileAndUuid ( downloadUuid ) ;
if ( message ! = null ) {
2015-12-06 17:23:59 +00:00
startDownloadable ( message ) ;
2015-01-16 05:36:11 +00:00
}
}
2016-11-08 11:42:13 +00:00
} else {
mUnprocessedNewIntent = false ;
2014-11-07 20:49:31 +00:00
}
2014-10-24 12:34:46 +00:00
}
2014-01-25 18:33:12 +00:00
2015-01-10 18:43:23 +00:00
private boolean selectConversationByUuid ( String uuid ) {
if ( uuid = = null ) {
return false ;
}
2014-12-21 20:43:58 +00:00
for ( Conversation aConversationList : conversationList ) {
if ( aConversationList . getUuid ( ) . equals ( uuid ) ) {
setSelectedConversation ( aConversationList ) ;
2015-01-10 18:43:23 +00:00
return true ;
2014-12-21 20:43:58 +00:00
}
}
2015-01-10 18:43:23 +00:00
return false ;
2014-01-25 18:33:12 +00:00
}
2014-04-10 12:12:08 +00:00
2014-11-11 16:39:28 +00:00
@Override
protected void unregisterListeners ( ) {
super . unregisterListeners ( ) ;
xmppConnectionService . getNotificationService ( ) . setOpenConversation ( null ) ;
2014-03-10 20:52:58 +00:00
}
2015-04-13 15:35:20 +00:00
@SuppressLint ( " NewApi " )
2015-04-11 12:53:10 +00:00
private static List < Uri > extractUriFromIntent ( final Intent intent ) {
List < Uri > uris = new ArrayList < > ( ) ;
2016-01-15 22:47:55 +00:00
if ( intent = = null ) {
return uris ;
}
2015-04-11 12:53:10 +00:00
Uri uri = intent . getData ( ) ;
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . JELLY_BEAN_MR2 & & uri = = null ) {
2016-08-19 19:46:47 +00:00
final ClipData clipData = intent . getClipData ( ) ;
if ( clipData ! = null ) {
for ( int i = 0 ; i < clipData . getItemCount ( ) ; + + i ) {
uris . add ( clipData . getItemAt ( i ) . getUri ( ) ) ;
}
2015-04-11 12:53:10 +00:00
}
} else {
uris . add ( uri ) ;
}
return uris ;
}
2014-03-10 20:52:58 +00:00
@Override
2016-01-11 10:17:45 +00:00
protected void onActivityResult ( int requestCode , int resultCode , final Intent data ) {
2014-04-10 12:12:08 +00:00
super . onActivityResult ( requestCode , resultCode , data ) ;
if ( resultCode = = RESULT_OK ) {
2014-02-28 01:58:15 +00:00
if ( requestCode = = REQUEST_DECRYPT_PGP ) {
2015-10-15 22:21:47 +00:00
mConversationFragment . onActivityResult ( requestCode , resultCode , data ) ;
2015-10-29 13:03:41 +00:00
} else if ( requestCode = = REQUEST_CHOOSE_PGP_ID ) {
2016-01-15 21:54:29 +00:00
// the user chose OpenPGP for encryption and selected his key in the PGP provider
2015-12-01 13:18:07 +00:00
if ( xmppConnectionServiceBound ) {
if ( data . getExtras ( ) . containsKey ( OpenPgpApi . EXTRA_SIGN_KEY_ID ) ) {
2016-01-15 21:54:29 +00:00
// associate selected PGP keyId with the account
2015-12-01 13:18:07 +00:00
mSelectedConversation . getAccount ( ) . setPgpSignId ( data . getExtras ( ) . getLong ( OpenPgpApi . EXTRA_SIGN_KEY_ID ) ) ;
2016-01-15 21:54:29 +00:00
// we need to announce the key as described in XEP-027
2017-12-05 18:16:53 +00:00
announcePgp ( mSelectedConversation . getAccount ( ) , null , null , onOpenPGPKeyPublished ) ;
2015-12-01 13:18:07 +00:00
} else {
choosePgpSignId ( mSelectedConversation . getAccount ( ) ) ;
}
this . mPostponedActivityResult = null ;
2015-10-29 13:03:41 +00:00
} else {
2015-12-01 13:18:07 +00:00
this . mPostponedActivityResult = new Pair < > ( requestCode , data ) ;
2015-10-29 13:03:41 +00:00
}
} else if ( requestCode = = REQUEST_ANNOUNCE_PGP ) {
2015-12-01 13:18:07 +00:00
if ( xmppConnectionServiceBound ) {
2017-12-05 18:16:53 +00:00
announcePgp ( mSelectedConversation . getAccount ( ) , mSelectedConversation , data , onOpenPGPKeyPublished ) ;
2015-12-01 13:18:07 +00:00
this . mPostponedActivityResult = null ;
} else {
this . mPostponedActivityResult = new Pair < > ( requestCode , data ) ;
}
2015-01-03 15:06:59 +00:00
} else if ( requestCode = = ATTACHMENT_CHOICE_CHOOSE_IMAGE ) {
2015-04-11 12:53:10 +00:00
mPendingImageUris . clear ( ) ;
mPendingImageUris . addAll ( extractUriFromIntent ( data ) ) ;
2014-08-21 07:19:18 +00:00
if ( xmppConnectionServiceBound ) {
2016-01-11 10:17:45 +00:00
for ( Iterator < Uri > i = mPendingImageUris . iterator ( ) ; i . hasNext ( ) ; i . remove ( ) ) {
2016-10-03 09:13:04 +00:00
Log . d ( Config . LOGTAG , " ConversationsActivity.onActivityResult() - attaching image to conversations. CHOOSE_IMAGE " ) ;
2016-01-11 10:17:45 +00:00
attachImageToConversation ( getSelectedConversation ( ) , i . next ( ) ) ;
2015-04-11 12:53:10 +00:00
}
2014-08-21 07:19:18 +00:00
}
2017-09-18 09:51:47 +00:00
} else if ( requestCode = = ATTACHMENT_CHOICE_CHOOSE_FILE | | requestCode = = ATTACHMENT_CHOICE_RECORD_VOICE | | requestCode = = ATTACHMENT_CHOICE_RECORD_VIDEO ) {
2016-03-31 22:03:14 +00:00
final List < Uri > uris = extractUriFromIntent ( data ) ;
2017-09-18 09:51:47 +00:00
Log . d ( Config . LOGTAG , " uris " + uris . toString ( ) ) ;
2016-03-31 22:03:14 +00:00
final Conversation c = getSelectedConversation ( ) ;
final OnPresenceSelected callback = new OnPresenceSelected ( ) {
@Override
public void onPresenceSelected ( ) {
mPendingFileUris . clear ( ) ;
mPendingFileUris . addAll ( uris ) ;
if ( xmppConnectionServiceBound ) {
for ( Iterator < Uri > i = mPendingFileUris . iterator ( ) ; i . hasNext ( ) ; i . remove ( ) ) {
2017-09-18 09:51:47 +00:00
Log . d ( Config . LOGTAG , " ConversationsActivity.onActivityResult() - attaching file to conversations. CHOOSE_FILE/RECORD_VOICE/RECORD_VIDEO " ) ;
2016-03-31 22:03:14 +00:00
attachFileToConversation ( c , i . next ( ) ) ;
}
}
2015-04-11 12:53:10 +00:00
}
2016-03-31 22:03:14 +00:00
} ;
2016-04-07 17:20:45 +00:00
if ( c = = null | | c . getMode ( ) = = Conversation . MODE_MULTI
| | FileBackend . allFilesUnderSize ( this , uris , getMaxHttpUploadSize ( c ) )
2016-03-31 22:03:14 +00:00
| | c . getNextEncryption ( ) = = Message . ENCRYPTION_OTR ) {
callback . onPresenceSelected ( ) ;
} else {
selectPresence ( c , callback ) ;
2014-11-13 20:04:05 +00:00
}
2015-04-11 12:53:10 +00:00
} else if ( requestCode = = ATTACHMENT_CHOICE_TAKE_PHOTO ) {
if ( mPendingImageUris . size ( ) = = 1 ) {
2016-10-03 16:26:11 +00:00
Uri uri = FileBackend . getIndexableTakePhotoUri ( mPendingImageUris . get ( 0 ) ) ;
mPendingImageUris . set ( 0 , uri ) ;
2015-04-11 12:53:10 +00:00
if ( xmppConnectionServiceBound ) {
2016-10-03 09:13:04 +00:00
Log . d ( Config . LOGTAG , " ConversationsActivity.onActivityResult() - attaching image to conversations. TAKE_PHOTO " ) ;
2015-04-11 12:53:10 +00:00
attachImageToConversation ( getSelectedConversation ( ) , uri ) ;
mPendingImageUris . clear ( ) ;
}
2016-11-08 10:45:20 +00:00
if ( ! Config . ONLY_INTERNAL_STORAGE ) {
Intent intent = new Intent ( Intent . ACTION_MEDIA_SCANNER_SCAN_FILE ) ;
intent . setData ( uri ) ;
sendBroadcast ( intent ) ;
}
2015-04-11 12:53:10 +00:00
} else {
mPendingImageUris . clear ( ) ;
2014-08-21 07:19:18 +00:00
}
2015-03-07 13:15:38 +00:00
} else if ( requestCode = = ATTACHMENT_CHOICE_LOCATION ) {
2016-01-11 10:17:45 +00:00
double latitude = data . getDoubleExtra ( " latitude " , 0 ) ;
double longitude = data . getDoubleExtra ( " longitude " , 0 ) ;
this . mPendingGeoUri = Uri . parse ( " geo: " + String . valueOf ( latitude ) + " , " + String . valueOf ( longitude ) ) ;
2015-03-07 13:15:38 +00:00
if ( xmppConnectionServiceBound ) {
attachLocationToConversation ( getSelectedConversation ( ) , mPendingGeoUri ) ;
this . mPendingGeoUri = null ;
}
2015-07-19 16:36:28 +00:00
} else if ( requestCode = = REQUEST_TRUST_KEYS_TEXT | | requestCode = = REQUEST_TRUST_KEYS_MENU ) {
2017-11-06 16:27:48 +00:00
this . forbidProcessingPendings = true ;
2016-01-16 20:18:59 +00:00
if ( xmppConnectionServiceBound ) {
mConversationFragment . onActivityResult ( requestCode , resultCode , data ) ;
this . mPostponedActivityResult = null ;
} else {
this . mPostponedActivityResult = new Pair < > ( requestCode , data ) ;
}
2014-02-28 01:58:15 +00:00
}
2015-04-27 10:18:27 +00:00
} else {
mPendingImageUris . clear ( ) ;
mPendingFileUris . clear ( ) ;
2015-10-15 22:21:47 +00:00
if ( requestCode = = ConversationActivity . REQUEST_DECRYPT_PGP ) {
mConversationFragment . onActivityResult ( requestCode , resultCode , data ) ;
}
2016-01-11 10:17:45 +00:00
if ( requestCode = = REQUEST_BATTERY_OP ) {
setNeverAskForBatteryOptimizationsAgain ( ) ;
}
}
}
2016-04-07 17:20:45 +00:00
private long getMaxHttpUploadSize ( Conversation conversation ) {
2016-11-02 14:21:26 +00:00
final XmppConnection connection = conversation . getAccount ( ) . getXmppConnection ( ) ;
return connection = = null ? - 1 : connection . getFeatures ( ) . getMaxHttpUploadSize ( ) ;
2016-04-07 17:20:45 +00:00
}
2017-12-06 15:57:43 +00:00
private String getBatteryOptimizationPreferenceKey ( ) {
@SuppressLint ( " HardwareIds " ) String device = Settings . Secure . getString ( getContentResolver ( ) , Settings . Secure . ANDROID_ID ) ;
return " show_battery_optimization " + ( device = = null ? " " : device ) ;
}
2016-01-11 10:17:45 +00:00
private void setNeverAskForBatteryOptimizationsAgain ( ) {
2017-12-06 15:57:43 +00:00
getPreferences ( ) . edit ( ) . putBoolean ( getBatteryOptimizationPreferenceKey ( ) , false ) . apply ( ) ;
2016-01-11 10:17:45 +00:00
}
private void openBatteryOptimizationDialogIfNeeded ( ) {
2016-03-06 14:53:49 +00:00
if ( hasAccountWithoutPush ( )
& & isOptimizingBattery ( )
2017-12-06 15:57:43 +00:00
& & getPreferences ( ) . getBoolean ( getBatteryOptimizationPreferenceKey ( ) , true ) ) {
2016-01-11 10:17:45 +00:00
AlertDialog . Builder builder = new AlertDialog . Builder ( this ) ;
builder . setTitle ( R . string . battery_optimizations_enabled ) ;
builder . setMessage ( R . string . battery_optimizations_enabled_dialog ) ;
builder . setPositiveButton ( R . string . next , new OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
Intent intent = new Intent ( Settings . ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS ) ;
Uri uri = Uri . parse ( " package: " + getPackageName ( ) ) ;
intent . setData ( uri ) ;
2016-04-29 11:58:37 +00:00
try {
startActivityForResult ( intent , REQUEST_BATTERY_OP ) ;
} catch ( ActivityNotFoundException e ) {
Toast . makeText ( ConversationActivity . this , R . string . device_does_not_support_battery_op , Toast . LENGTH_SHORT ) . show ( ) ;
}
2016-01-11 10:17:45 +00:00
}
} ) ;
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . JELLY_BEAN_MR2 ) {
builder . setOnDismissListener ( new DialogInterface . OnDismissListener ( ) {
@Override
public void onDismiss ( DialogInterface dialog ) {
setNeverAskForBatteryOptimizationsAgain ( ) ;
}
} ) ;
}
2017-06-03 22:05:02 +00:00
AlertDialog dialog = builder . create ( ) ;
dialog . setCanceledOnTouchOutside ( false ) ;
dialog . show ( ) ;
2014-04-10 12:12:08 +00:00
}
}
2014-06-06 09:39:17 +00:00
2016-03-06 14:53:49 +00:00
private boolean hasAccountWithoutPush ( ) {
for ( Account account : xmppConnectionService . getAccounts ( ) ) {
2017-12-06 15:57:43 +00:00
if ( account . getStatus ( ) = = Account . State . ONLINE & & ! xmppConnectionService . getPushManagementService ( ) . available ( account ) ) {
2016-03-06 14:53:49 +00:00
return true ;
}
}
return false ;
}
2015-03-07 13:15:38 +00:00
private void attachLocationToConversation ( Conversation conversation , Uri uri ) {
2015-07-16 11:14:51 +00:00
if ( conversation = = null ) {
return ;
}
2015-03-07 13:15:38 +00:00
xmppConnectionService . attachLocationToConversation ( conversation , uri , new UiCallback < Message > ( ) {
@Override
public void success ( Message message ) {
xmppConnectionService . sendMessage ( message ) ;
}
@Override
public void error ( int errorCode , Message object ) {
}
@Override
public void userInputRequried ( PendingIntent pi , Message object ) {
}
} ) ;
}
2014-11-13 20:04:05 +00:00
private void attachFileToConversation ( Conversation conversation , Uri uri ) {
2015-07-16 11:14:51 +00:00
if ( conversation = = null ) {
return ;
}
2016-01-15 22:47:55 +00:00
final Toast prepareFileToast = Toast . makeText ( getApplicationContext ( ) , getText ( R . string . preparing_file ) , Toast . LENGTH_LONG ) ;
2014-11-14 11:31:57 +00:00
prepareFileToast . show ( ) ;
2018-01-23 21:02:28 +00:00
delegateUriPermissionsToService ( uri ) ;
2017-01-24 19:17:36 +00:00
xmppConnectionService . attachFileToConversation ( conversation , uri , new UiInformableCallback < Message > ( ) {
@Override
public void inform ( final String text ) {
hidePrepareFileToast ( prepareFileToast ) ;
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
replaceToast ( text ) ;
}
} ) ;
}
2014-11-13 23:28:39 +00:00
@Override
public void success ( Message message ) {
2017-01-24 19:17:36 +00:00
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
hideToast ( ) ;
}
} ) ;
2016-01-15 22:47:55 +00:00
hidePrepareFileToast ( prepareFileToast ) ;
2014-11-13 23:28:39 +00:00
xmppConnectionService . sendMessage ( message ) ;
}
@Override
2016-06-24 11:36:06 +00:00
public void error ( final int errorCode , Message message ) {
hidePrepareFileToast ( prepareFileToast ) ;
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
replaceToast ( getString ( errorCode ) ) ;
}
} ) ;
2014-11-13 23:28:39 +00:00
}
@Override
public void userInputRequried ( PendingIntent pi , Message message ) {
2016-06-24 11:36:06 +00:00
hidePrepareFileToast ( prepareFileToast ) ;
2014-11-13 23:28:39 +00:00
}
} ) ;
2014-05-18 15:32:20 +00:00
}
2016-12-30 20:48:39 +00:00
public void attachImageToConversation ( Uri uri ) {
this . attachImageToConversation ( getSelectedConversation ( ) , uri ) ;
}
2014-05-14 09:49:43 +00:00
private void attachImageToConversation ( Conversation conversation , Uri uri ) {
2015-07-16 11:14:51 +00:00
if ( conversation = = null ) {
return ;
}
2016-01-15 22:47:55 +00:00
final Toast prepareFileToast = Toast . makeText ( getApplicationContext ( ) , getText ( R . string . preparing_image ) , Toast . LENGTH_LONG ) ;
2014-11-14 11:31:57 +00:00
prepareFileToast . show ( ) ;
2018-01-23 21:02:28 +00:00
delegateUriPermissionsToService ( uri ) ;
2014-06-07 11:25:27 +00:00
xmppConnectionService . attachImageToConversation ( conversation , uri ,
new UiCallback < Message > ( ) {
2014-06-06 09:39:17 +00:00
@Override
2016-01-15 22:47:55 +00:00
public void userInputRequried ( PendingIntent pi , Message object ) {
hidePrepareFileToast ( prepareFileToast ) ;
2014-06-06 09:39:17 +00:00
}
@Override
2014-06-07 11:25:27 +00:00
public void success ( Message message ) {
2016-01-15 22:47:55 +00:00
hidePrepareFileToast ( prepareFileToast ) ;
2014-06-11 19:53:25 +00:00
xmppConnectionService . sendMessage ( message ) ;
2014-06-06 09:39:17 +00:00
}
@Override
2016-06-24 11:36:06 +00:00
public void error ( final int error , Message message ) {
hidePrepareFileToast ( prepareFileToast ) ;
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
replaceToast ( getString ( error ) ) ;
}
} ) ;
2014-06-06 09:39:17 +00:00
}
} ) ;
2014-05-08 14:52:19 +00:00
}
2014-06-06 09:39:17 +00:00
2016-01-15 22:47:55 +00:00
private void hidePrepareFileToast ( final Toast prepareFileToast ) {
2014-11-14 11:31:57 +00:00
if ( prepareFileToast ! = null ) {
2014-05-14 16:43:58 +00:00
runOnUiThread ( new Runnable ( ) {
2014-06-06 09:39:17 +00:00
2014-05-14 16:43:58 +00:00
@Override
public void run ( ) {
2014-11-14 11:31:57 +00:00
prepareFileToast . cancel ( ) ;
2014-05-14 16:43:58 +00:00
}
} ) ;
}
}
2014-03-19 15:16:40 +00:00
public void updateConversationList ( ) {
2017-03-06 15:53:54 +00:00
xmppConnectionService . populateWithOrderedConversations ( conversationList ) ;
if ( ! conversationList . contains ( mSelectedConversation ) ) {
mSelectedConversation = null ;
}
2015-04-02 22:06:37 +00:00
if ( swipedConversation ! = null ) {
if ( swipedConversation . isRead ( ) ) {
conversationList . remove ( swipedConversation ) ;
} else {
listView . discardUndo ( ) ;
}
}
2014-09-08 10:46:48 +00:00
listAdapter . notifyDataSetChanged ( ) ;
2014-03-19 15:16:40 +00:00
}
2014-06-06 09:39:17 +00:00
2014-05-07 10:33:55 +00:00
public void runIntent ( PendingIntent pi , int requestCode ) {
try {
2014-06-06 09:39:17 +00:00
this . startIntentSenderForResult ( pi . getIntentSender ( ) , requestCode ,
null , 0 , 0 , 0 ) ;
2014-11-07 14:09:28 +00:00
} catch ( final SendIntentException ignored ) {
2014-08-31 14:28:21 +00:00
}
2014-05-07 10:33:55 +00:00
}
2014-06-06 09:39:17 +00:00
2014-06-07 11:25:27 +00:00
public void encryptTextMessage ( Message message ) {
xmppConnectionService . getPgpEngine ( ) . encrypt ( message ,
new UiCallback < Message > ( ) {
2014-05-08 15:31:53 +00:00
@Override
2016-06-15 11:53:34 +00:00
public void userInputRequried ( PendingIntent pi , Message message ) {
ConversationActivity . this . runIntent ( pi , ConversationActivity . REQUEST_SEND_MESSAGE ) ;
2014-05-08 15:31:53 +00:00
}
@Override
2014-06-07 11:25:27 +00:00
public void success ( Message message ) {
2014-06-22 15:24:47 +00:00
message . setEncryption ( Message . ENCRYPTION_DECRYPTED ) ;
2014-06-11 19:53:25 +00:00
xmppConnectionService . sendMessage ( message ) ;
2017-03-19 19:15:07 +00:00
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
mConversationFragment . messageSent ( ) ;
}
} ) ;
2014-05-08 15:31:53 +00:00
}
@Override
2016-06-15 11:53:34 +00:00
public void error ( final int error , Message message ) {
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
2017-03-19 19:15:07 +00:00
mConversationFragment . doneSendingPgpMessage ( ) ;
2016-06-15 11:53:34 +00:00
Toast . makeText ( ConversationActivity . this ,
R . string . unable_to_connect_to_keychain ,
Toast . LENGTH_SHORT
) . show ( ) ;
}
} ) ;
2017-03-19 19:15:07 +00:00
2014-05-08 15:31:53 +00:00
}
} ) ;
}
2014-09-08 11:37:22 +00:00
2014-09-10 15:59:57 +00:00
public boolean useSendButtonToIndicateStatus ( ) {
2017-06-30 19:22:35 +00:00
return getPreferences ( ) . getBoolean ( " send_button_status " , getResources ( ) . getBoolean ( R . bool . send_button_status ) ) ;
2014-09-10 15:59:57 +00:00
}
2014-09-20 13:49:25 +00:00
public boolean indicateReceived ( ) {
2017-06-30 19:22:35 +00:00
return getPreferences ( ) . getBoolean ( " indicate_received " , getResources ( ) . getBoolean ( R . bool . indicate_received ) ) ;
2014-09-20 13:49:25 +00:00
}
Dark theme, theme switch, icons, style, strings
added some white icons,
changed hardcoded icons to theme attributes,
changed icon_edit_dark to icon_edit_body to reflect icons position,
grey message bubbles in dark theme,
misc
purged ic_action_chat as it wasn't used
preference use_white_background changed to use_green_background, default true
grey chat bubbles darker, text white
replaced all grey600 with black icons and 0.54 alpha attribute
highlightColor in dark grey chat bubble now darker than background
2016-05-12 18:00:18 +00:00
public boolean useGreenBackground ( ) {
2017-06-30 19:22:35 +00:00
return getPreferences ( ) . getBoolean ( " use_green_background " , getResources ( ) . getBoolean ( R . bool . use_green_background ) ) ;
2015-08-24 18:56:25 +00:00
}
2015-07-19 16:36:28 +00:00
protected boolean trustKeysIfNeeded ( int requestCode ) {
return trustKeysIfNeeded ( requestCode , ATTACHMENT_CHOICE_INVALID ) ;
}
protected boolean trustKeysIfNeeded ( int requestCode , int attachmentChoice ) {
AxolotlService axolotlService = mSelectedConversation . getAccount ( ) . getAxolotlService ( ) ;
2016-02-29 12:18:07 +00:00
final List < Jid > targets = axolotlService . getCryptoTargets ( mSelectedConversation ) ;
2016-03-01 10:26:59 +00:00
boolean hasUnaccepted = ! mSelectedConversation . getAcceptedCryptoTargets ( ) . containsAll ( targets ) ;
2016-11-14 21:27:41 +00:00
boolean hasUndecidedOwn = ! axolotlService . getKeysWithTrust ( FingerprintStatus . createActiveUndecided ( ) ) . isEmpty ( ) ;
boolean hasUndecidedContacts = ! axolotlService . getKeysWithTrust ( FingerprintStatus . createActiveUndecided ( ) , targets ) . isEmpty ( ) ;
2016-01-04 11:11:58 +00:00
boolean hasPendingKeys = ! axolotlService . findDevicesWithoutSession ( mSelectedConversation ) . isEmpty ( ) ;
2016-02-29 12:18:07 +00:00
boolean hasNoTrustedKeys = axolotlService . anyTargetHasNoTrustedKeys ( targets ) ;
2016-03-01 10:26:59 +00:00
if ( hasUndecidedOwn | | hasUndecidedContacts | | hasPendingKeys | | hasNoTrustedKeys | | hasUnaccepted ) {
2015-07-31 19:12:34 +00:00
axolotlService . createSessionsIfNeeded ( mSelectedConversation ) ;
2015-07-19 16:36:28 +00:00
Intent intent = new Intent ( getApplicationContext ( ) , TrustKeysActivity . class ) ;
2016-02-29 12:18:07 +00:00
String [ ] contacts = new String [ targets . size ( ) ] ;
for ( int i = 0 ; i < contacts . length ; + + i ) {
contacts [ i ] = targets . get ( i ) . toString ( ) ;
}
intent . putExtra ( " contacts " , contacts ) ;
2016-01-22 19:46:24 +00:00
intent . putExtra ( EXTRA_ACCOUNT , mSelectedConversation . getAccount ( ) . getJid ( ) . toBareJid ( ) . toString ( ) ) ;
2015-07-19 16:36:28 +00:00
intent . putExtra ( " choice " , attachmentChoice ) ;
2016-03-01 10:26:59 +00:00
intent . putExtra ( " conversation " , mSelectedConversation . getUuid ( ) ) ;
2015-07-19 16:36:28 +00:00
startActivityForResult ( intent , requestCode ) ;
return true ;
} else {
return false ;
}
}
2014-09-10 15:59:57 +00:00
@Override
2015-02-17 13:18:35 +00:00
protected void refreshUiReal ( ) {
updateConversationList ( ) ;
2015-10-20 13:27:33 +00:00
if ( conversationList . size ( ) > 0 ) {
2016-03-13 16:41:38 +00:00
if ( ! this . mConversationFragment . isAdded ( ) ) {
Log . d ( Config . LOGTAG , " fragment NOT added to activity. detached= " + Boolean . toString ( mConversationFragment . isDetached ( ) ) ) ;
}
2017-03-06 15:53:54 +00:00
if ( getSelectedConversation ( ) = = null ) {
reInitLatestConversation ( ) ;
} else {
ConversationActivity . this . mConversationFragment . updateMessages ( ) ;
updateActionBarTitle ( ) ;
invalidateOptionsMenu ( ) ;
}
2016-03-13 16:41:38 +00:00
} else {
2017-03-06 15:53:54 +00:00
if ( ! isStopping ( ) & & mRedirected . compareAndSet ( false , true ) ) {
2018-02-09 21:19:13 +00:00
redirectToStartConversationActivity ( false ) ;
2017-03-06 15:53:54 +00:00
}
2016-03-13 16:41:38 +00:00
Log . d ( Config . LOGTAG , " not updating conversations fragment because conversations list size was 0 " ) ;
2015-02-17 13:18:35 +00:00
}
}
2014-09-10 15:59:57 +00:00
2015-02-17 13:18:35 +00:00
@Override
public void onAccountUpdate ( ) {
this . refreshUi ( ) ;
2014-09-10 15:59:57 +00:00
}
@Override
public void onConversationUpdate ( ) {
2015-02-17 13:18:35 +00:00
this . refreshUi ( ) ;
2014-09-10 15:59:57 +00:00
}
@Override
public void onRosterUpdate ( ) {
2015-02-17 13:18:35 +00:00
this . refreshUi ( ) ;
2014-12-21 20:43:58 +00:00
}
@Override
public void OnUpdateBlocklist ( Status status ) {
2015-02-17 13:18:35 +00:00
this . refreshUi ( ) ;
2014-12-21 20:43:58 +00:00
}
public void unblockConversation ( final Blockable conversation ) {
xmppConnectionService . sendUnblockRequest ( conversation ) ;
}
2015-01-09 18:23:26 +00:00
public boolean enterIsSend ( ) {
2017-03-02 12:03:30 +00:00
return getPreferences ( ) . getBoolean ( " enter_is_send " , getResources ( ) . getBoolean ( R . bool . enter_is_send ) ) ;
2015-01-09 18:23:26 +00:00
}
2015-07-10 11:28:50 +00:00
@Override
public void onShowErrorToast ( final int resId ) {
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
Toast . makeText ( ConversationActivity . this , resId , Toast . LENGTH_SHORT ) . show ( ) ;
}
} ) ;
}
2015-09-07 13:46:22 +00:00
public boolean highlightSelectedConversations ( ) {
return ! isConversationsOverviewHideable ( ) | | this . conversationWasSelectedByKeyboard ;
}
2014-01-24 01:04:05 +00:00
}