diff options
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/ui')
49 files changed, 37 insertions, 12535 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/AboutActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/AboutActivity.java deleted file mode 100644 index fd8a187a..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/AboutActivity.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.Activity; -import android.os.Bundle; - -import de.thedevstack.conversationsplus.R; - -public class AboutActivity extends Activity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_about); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/AboutPreference.java b/src/main/java/de/thedevstack/conversationsplus/ui/AboutPreference.java deleted file mode 100644 index 8a02b680..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/AboutPreference.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.content.Context; -import android.content.Intent; -import android.preference.Preference; -import android.util.AttributeSet; - -import de.thedevstack.conversationsplus.ConversationsPlusApplication; - -public class AboutPreference extends Preference { - public AboutPreference(final Context context, final AttributeSet attrs, final int defStyle) { - super(context, attrs, defStyle); - setSummary(); - } - - public AboutPreference(final Context context, final AttributeSet attrs) { - super(context, attrs); - setSummary(); - } - - @Override - protected void onClick() { - super.onClick(); - final Intent intent = new Intent(getContext(), AboutActivity.class); - getContext().startActivity(intent); - } - - private void setSummary() { - setSummary(ConversationsPlusApplication.getNameAndVersion()); - } -} - diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/AbstractSearchableListItemActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/AbstractSearchableListItemActivity.java deleted file mode 100644 index b8e57f47..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/AbstractSearchableListItemActivity.java +++ /dev/null @@ -1,124 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.content.Context; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import android.widget.ArrayAdapter; -import android.widget.EditText; -import android.widget.ListView; - -import java.util.ArrayList; -import java.util.List; - -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.ListItem; -import de.thedevstack.conversationsplus.ui.adapter.ListItemAdapter; - -public abstract class AbstractSearchableListItemActivity extends XmppActivity { - private ListView mListView; - private final List<ListItem> listItems = new ArrayList<>(); - private ArrayAdapter<ListItem> mListItemsAdapter; - - private EditText mSearchEditText; - - private final MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() { - - @Override - public boolean onMenuItemActionExpand(final MenuItem item) { - mSearchEditText.post(new Runnable() { - - @Override - public void run() { - mSearchEditText.requestFocus(); - final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(mSearchEditText, - InputMethodManager.SHOW_IMPLICIT); - } - }); - - return true; - } - - @Override - public boolean onMenuItemActionCollapse(final MenuItem item) { - final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(), - InputMethodManager.HIDE_IMPLICIT_ONLY); - mSearchEditText.setText(""); - filterContacts(); - return true; - } - }; - - private final TextWatcher mSearchTextWatcher = new TextWatcher() { - - @Override - public void afterTextChanged(final Editable editable) { - filterContacts(editable.toString()); - } - - @Override - public void beforeTextChanged(final CharSequence s, final int start, final int count, - final int after) { - } - - @Override - public void onTextChanged(final CharSequence s, final int start, final int before, - final int count) { - } - }; - - public ListView getListView() { - return mListView; - } - - public List<ListItem> getListItems() { - return listItems; - } - - public EditText getSearchEditText() { - return mSearchEditText; - } - - public ArrayAdapter<ListItem> getListItemAdapter() { - return mListItemsAdapter; - } - - @Override - public void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_choose_contact); - mListView = (ListView) findViewById(R.id.choose_contact_list); - mListView.setFastScrollEnabled(true); - mListItemsAdapter = new ListItemAdapter(this, listItems); - mListView.setAdapter(mListItemsAdapter); - } - - @Override - public boolean onCreateOptionsMenu(final Menu menu) { - getMenuInflater().inflate(R.menu.choose_contact, menu); - final MenuItem menuSearchView = menu.findItem(R.id.action_search); - final View mSearchView = menuSearchView.getActionView(); - mSearchEditText = (EditText) mSearchView - .findViewById(R.id.search_field); - mSearchEditText.addTextChangedListener(mSearchTextWatcher); - menuSearchView.setOnActionExpandListener(mOnActionExpandListener); - return true; - } - - protected void filterContacts() { - filterContacts(null); - } - - protected abstract void filterContacts(final String needle); - - @Override - void onBackendConnected() { - filterContacts(); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/BlockContactDialog.java b/src/main/java/de/thedevstack/conversationsplus/ui/BlockContactDialog.java deleted file mode 100644 index 589f565c..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/BlockContactDialog.java +++ /dev/null @@ -1,41 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; - -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Blockable; -import de.thedevstack.conversationsplus.services.XmppConnectionService; - -public final class BlockContactDialog { - public static void show(final Context context, - final XmppConnectionService xmppConnectionService, - final Blockable blockable) { - final AlertDialog.Builder builder = new AlertDialog.Builder(context); - final boolean isBlocked = blockable.isBlocked(); - builder.setNegativeButton(R.string.cancel, null); - - if (blockable.getJid().isDomainJid() || blockable.getAccount().isBlocked(blockable.getJid().toDomainJid())) { - builder.setTitle(isBlocked ? R.string.action_unblock_domain : R.string.action_block_domain); - builder.setMessage(context.getResources().getString(isBlocked ? R.string.unblock_domain_text : R.string.block_domain_text, - blockable.getJid().toDomainJid())); - } else { - builder.setTitle(isBlocked ? R.string.action_unblock_contact : R.string.action_block_contact); - builder.setMessage(context.getResources().getString(isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text, - blockable.getJid().toBareJid())); - } - builder.setPositiveButton(isBlocked ? R.string.unblock : R.string.block, new DialogInterface.OnClickListener() { - - @Override - public void onClick(final DialogInterface dialog, final int which) { - if (isBlocked) { - xmppConnectionService.sendUnblockRequest(blockable); - } else { - xmppConnectionService.sendBlockRequest(blockable); - } - } - }); - builder.create().show(); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/BlocklistActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/BlocklistActivity.java deleted file mode 100644 index 377d0e02..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/BlocklistActivity.java +++ /dev/null @@ -1,74 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.os.Bundle; -import android.text.Editable; -import android.view.View; -import android.widget.AdapterView; - -import java.util.Collections; - -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Contact; -import de.thedevstack.conversationsplus.xmpp.OnUpdateBlocklist; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class BlocklistActivity extends AbstractSearchableListItemActivity implements OnUpdateBlocklist { - - private Account account = null; - - @Override - public void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { - - @Override - public boolean onItemLongClick(final AdapterView<?> parent, - final View view, - final int position, - final long id) { - BlockContactDialog.show(parent.getContext(), xmppConnectionService,(Contact) getListItems().get(position)); - return true; - } - }); - } - - @Override - public void onBackendConnected() { - for (final Account account : xmppConnectionService.getAccounts()) { - if (account.getJid().toString().equals(getIntent().getStringExtra(EXTRA_ACCOUNT))) { - this.account = account; - break; - } - } - filterContacts(); - } - - @Override - protected void filterContacts(final String needle) { - getListItems().clear(); - if (account != null) { - for (final Jid jid : account.getBlocklist()) { - final Contact contact = account.getRoster().getContact(jid); - if (contact.match(needle) && contact.isBlocked()) { - getListItems().add(contact); - } - } - Collections.sort(getListItems()); - } - getListItemAdapter().notifyDataSetChanged(); - } - - protected void refreshUiReal() { - final Editable editable = getSearchEditText().getText(); - if (editable != null) { - filterContacts(editable.toString()); - } else { - filterContacts(); - } - } - - @Override - public void OnUpdateBlocklist(final OnUpdateBlocklist.Status status) { - refreshUi(); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ChangePasswordActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/ChangePasswordActivity.java deleted file mode 100644 index 2e063757..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ChangePasswordActivity.java +++ /dev/null @@ -1,102 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.os.Bundle; -import android.view.View; -import android.widget.Button; -import android.widget.EditText; -import android.widget.Toast; - -import de.thedevstack.conversationsplus.ConversationsPlusColors; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.utils.ui.TextViewUtil; - -public class ChangePasswordActivity extends XmppActivity implements XmppConnectionService.OnAccountPasswordChanged { - - private Button mChangePasswordButton; - private View.OnClickListener mOnChangePasswordButtonClicked = new View.OnClickListener() { - @Override - public void onClick(View view) { - if (mAccount != null) { - final String currentPassword = mCurrentPassword.getText().toString(); - final String newPassword = mNewPassword.getText().toString(); - final String newPasswordConfirm = mNewPasswordConfirm.getText().toString(); - if (!currentPassword.equals(mAccount.getPassword())) { - mCurrentPassword.requestFocus(); - mCurrentPassword.setError(getString(R.string.account_status_unauthorized)); - } else if (!newPassword.equals(newPasswordConfirm)) { - mNewPasswordConfirm.requestFocus(); - mNewPasswordConfirm.setError(getString(R.string.passwords_do_not_match)); - } else if (newPassword.isEmpty()) { - mNewPassword.requestFocus(); - mNewPassword.setError(getString(R.string.password_should_not_be_empty)); - } else if (newPassword.trim().isEmpty()) { - mNewPassword.requestFocus(); - mNewPassword.setError(getString(R.string.password_should_not_contain_only_spaces)); - } else { - mCurrentPassword.setError(null); - mNewPassword.setError(null); - mNewPasswordConfirm.setError(null); - xmppConnectionService.updateAccountPasswordOnServer(mAccount, newPassword, ChangePasswordActivity.this); - TextViewUtil.disable(mChangePasswordButton, ConversationsPlusColors.secondaryText(), R.string.updating); - } - } - } - }; - private EditText mCurrentPassword; - private EditText mNewPassword; - private EditText mNewPasswordConfirm; - private Account mAccount; - - @Override - void onBackendConnected() { - this.mAccount = extractAccount(getIntent()); - - } - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_change_password); - Button mCancelButton = (Button) findViewById(R.id.left_button); - mCancelButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - finish(); - } - }); - this.mChangePasswordButton = (Button) findViewById(R.id.right_button); - this.mChangePasswordButton.setOnClickListener(this.mOnChangePasswordButtonClicked); - this.mCurrentPassword = (EditText) findViewById(R.id.current_password); - this.mNewPassword = (EditText) findViewById(R.id.new_password); - this.mNewPasswordConfirm = (EditText) findViewById(R.id.new_password_confirm); - } - - @Override - public void onPasswordChangeSucceeded() { - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(ChangePasswordActivity.this,R.string.password_changed,Toast.LENGTH_LONG).show(); - finish(); - } - }); - } - - @Override - public void onPasswordChangeFailed() { - runOnUiThread(new Runnable() { - @Override - public void run() { - mNewPassword.setError(getString(R.string.could_not_change_password)); - TextViewUtil.enable(mChangePasswordButton, ConversationsPlusColors.primaryText(), R.string.change_password); - } - }); - - } - - public void refreshUiReal() { - - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ChooseContactActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/ChooseContactActivity.java deleted file mode 100644 index 29860434..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ChooseContactActivity.java +++ /dev/null @@ -1,223 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.view.ActionMode; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import android.widget.AbsListView.MultiChoiceModeListener; -import android.widget.AdapterView; -import android.widget.ListView; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Contact; -import de.thedevstack.conversationsplus.entities.ListItem; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class ChooseContactActivity extends AbstractSearchableListItemActivity { - private List<String> mActivatedAccounts = new ArrayList<String>(); - private List<String> mKnownHosts; - - private Set<Contact> selected; - private Set<String> filterContacts; - - @Override - public void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - filterContacts = new HashSet<>(); - String[] contacts = getIntent().getStringArrayExtra("filter_contacts"); - if (contacts != null) { - Collections.addAll(filterContacts, contacts); - } - - if (getIntent().getBooleanExtra("multiple", false)) { - getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); - getListView().setMultiChoiceModeListener(new MultiChoiceModeListener() { - - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - return false; - } - - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(getSearchEditText().getWindowToken(), - InputMethodManager.HIDE_IMPLICIT_ONLY); - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.select_multiple, menu); - selected = new HashSet<Contact>(); - return true; - } - - @Override - public void onDestroyActionMode(ActionMode mode) { - } - - @Override - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - switch(item.getItemId()) { - case R.id.selection_submit: - final Intent request = getIntent(); - final Intent data = new Intent(); - data.putExtra("conversation", - request.getStringExtra("conversation")); - String[] selection = getSelectedContactJids(); - data.putExtra("contacts", selection); - data.putExtra("multiple", true); - setResult(RESULT_OK, data); - finish(); - return true; - } - return false; - } - - @Override - public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { - Contact item = (Contact) getListItems().get(position); - if (checked) { - selected.add(item); - } else { - selected.remove(item); - } - int numSelected = selected.size(); - MenuItem selectButton = mode.getMenu().findItem(R.id.selection_submit); - String buttonText = getResources().getQuantityString(R.plurals.select_contact, - numSelected, numSelected); - selectButton.setTitle(buttonText); - } - }); - } - - getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() { - - @Override - public void onItemClick(final AdapterView<?> parent, final View view, - final int position, final long id) { - final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(getSearchEditText().getWindowToken(), - InputMethodManager.HIDE_IMPLICIT_ONLY); - final Intent request = getIntent(); - final Intent data = new Intent(); - final ListItem mListItem = getListItems().get(position); - data.putExtra("contact", mListItem.getJid().toString()); - String account = request.getStringExtra(EXTRA_ACCOUNT); - if (account == null && mListItem instanceof Contact) { - account = ((Contact) mListItem).getAccount().getJid().toBareJid().toString(); - } - data.putExtra(EXTRA_ACCOUNT, account); - data.putExtra("conversation", - request.getStringExtra("conversation")); - data.putExtra("multiple", false); - setResult(RESULT_OK, data); - finish(); - } - }); - - } - - @Override - public boolean onCreateOptionsMenu(final Menu menu) { - super.onCreateOptionsMenu(menu); - final Intent i = getIntent(); - boolean showEnterJid = i != null && i.getBooleanExtra("show_enter_jid", false); - menu.findItem(R.id.action_create_contact).setVisible(showEnterJid); - return true; - } - - protected void filterContacts(final String needle) { - getListItems().clear(); - for (final Account account : xmppConnectionService.getAccounts()) { - if (account.getStatus() != Account.State.DISABLED) { - for (final Contact contact : account.getRoster().getContacts()) { - if (contact.showInRoster() && - !filterContacts.contains(contact.getJid().toBareJid().toString()) - && contact.match(needle)) { - getListItems().add(contact); - } - } - } - } - Collections.sort(getListItems()); - getListItemAdapter().notifyDataSetChanged(); - } - - private String[] getSelectedContactJids() { - List<String> result = new ArrayList<>(); - for (Contact contact : selected) { - result.add(contact.getJid().toString()); - } - return result.toArray(new String[result.size()]); - } - - - public void refreshUiReal() { - //nothing to do. This Activity doesn't implement any listeners - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.action_create_contact: - showEnterJidDialog(); - return true; - } - return super.onOptionsItemSelected(item); - } - - protected void showEnterJidDialog() { - EnterJidDialog dialog = new EnterJidDialog( - this, mKnownHosts, mActivatedAccounts, - getString(R.string.enter_contact), getString(R.string.select), - null, getIntent().getStringExtra(EXTRA_ACCOUNT), true - ); - - dialog.setOnEnterJidDialogPositiveListener(new EnterJidDialog.OnEnterJidDialogPositiveListener() { - @Override - public boolean onEnterJidDialogPositive(Jid accountJid, Jid contactJid) throws EnterJidDialog.JidError { - final Intent request = getIntent(); - final Intent data = new Intent(); - data.putExtra("contact", contactJid.toString()); - data.putExtra(EXTRA_ACCOUNT, accountJid.toString()); - data.putExtra("conversation", - request.getStringExtra("conversation")); - data.putExtra("multiple", false); - setResult(RESULT_OK, data); - finish(); - - return true; - } - }); - - dialog.show(); - } - - @Override - void onBackendConnected() { - filterContacts(); - - this.mActivatedAccounts.clear(); - for (Account account : xmppConnectionService.getAccounts()) { - if (account.getStatus() != Account.State.DISABLED) { - if (Config.DOMAIN_LOCK != null) { - this.mActivatedAccounts.add(account.getJid().getLocalpart()); - } else { - this.mActivatedAccounts.add(account.getJid().toBareJid().toString()); - } - } - } - this.mKnownHosts = xmppConnectionService.getKnownHosts(); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ConferenceDetailsActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/ConferenceDetailsActivity.java deleted file mode 100644 index 2a3cd7fe..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ConferenceDetailsActivity.java +++ /dev/null @@ -1,713 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.annotation.TargetApi; -import android.app.AlertDialog; -import android.app.PendingIntent; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentSender.SendIntentException; -import android.os.Build; -import android.os.Bundle; -import android.view.ContextMenu; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TableLayout; -import android.widget.TextView; -import android.widget.Toast; - -import org.openintents.openpgp.util.OpenPgpUtils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.concurrent.atomic.AtomicInteger; - -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.crypto.PgpEngine; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Bookmark; -import de.thedevstack.conversationsplus.entities.Contact; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.entities.MucOptions; -import de.thedevstack.conversationsplus.entities.MucOptions.User; -import de.thedevstack.conversationsplus.services.AvatarService; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.services.XmppConnectionService.OnConversationUpdate; -import de.thedevstack.conversationsplus.services.XmppConnectionService.OnMucRosterUpdate; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate, OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged, XmppConnectionService.OnRoleChanged, XmppConnectionService.OnConferenceOptionsPushed { - public static final String ACTION_VIEW_MUC = "view_muc"; - private Conversation mConversation; - private OnClickListener inviteListener = new OnClickListener() { - - @Override - public void onClick(View v) { - inviteToConversation(mConversation); - } - }; - private TextView mYourNick; - private ImageView mYourPhoto; - private ImageButton mEditNickButton; - private TextView mRoleAffiliaton; - private TextView mFullJid; - private TextView mAccountJid; - private LinearLayout membersView; - private LinearLayout mMoreDetails; - private TextView mConferenceType; - private TableLayout mConferenceInfoTable; - private TextView mConferenceInfoMam; - private TextView mNotifyStatusText; - private ImageButton mChangeConferenceSettingsButton; - private ImageButton mNotifyStatusButton; - private Button mInviteButton; - private String uuid = null; - private User mSelectedUser = null; - - private boolean mAdvancedMode = false; - - private UiCallback<Conversation> renameCallback = new UiCallback<Conversation>() { - @Override - public void success(Conversation object) { - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(ConferenceDetailsActivity.this,getString(R.string.your_nick_has_been_changed),Toast.LENGTH_SHORT).show(); - updateView(); - } - }); - - } - - @Override - public void error(final int errorCode, Conversation object) { - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(ConferenceDetailsActivity.this,getString(errorCode),Toast.LENGTH_SHORT).show(); - } - }); - } - - @Override - public void userInputRequried(PendingIntent pi, Conversation object) { - - } - }; - - private OnClickListener mNotifyStatusClickListener = new OnClickListener() { - @Override - public void onClick(View v) { - AlertDialog.Builder builder = new AlertDialog.Builder(ConferenceDetailsActivity.this); - builder.setTitle(R.string.pref_notification_settings); - String[] choices = { - getString(R.string.notify_on_all_messages), - getString(R.string.notify_only_when_highlighted), - getString(R.string.notify_never) - }; - final AtomicInteger choice; - if (mConversation.getLongAttribute(Conversation.ATTRIBUTE_MUTED_TILL,0) == Long.MAX_VALUE) { - choice = new AtomicInteger(2); - } else { - choice = new AtomicInteger(mConversation.alwaysNotify() ? 0 : 1); - } - builder.setSingleChoiceItems(choices, choice.get(), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - choice.set(which); - } - }); - builder.setNegativeButton(R.string.cancel, null); - builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (choice.get() == 2) { - mConversation.setMutedTill(Long.MAX_VALUE); - } else { - mConversation.setMutedTill(0); - mConversation.setAttribute(Conversation.ATTRIBUTE_ALWAYS_NOTIFY,String.valueOf(choice.get() == 0)); - } - xmppConnectionService.updateConversation(mConversation); - updateView(); - } - }); - builder.create().show(); - } - }; - - private OnClickListener mChangeConferenceSettings = new OnClickListener() { - @Override - public void onClick(View v) { - final MucOptions mucOptions = mConversation.getMucOptions(); - AlertDialog.Builder builder = new AlertDialog.Builder(ConferenceDetailsActivity.this); - builder.setTitle(R.string.conference_options); - final String[] options; - final boolean[] values; - if (mAdvancedMode) { - options = new String[]{ - getString(R.string.members_only), - getString(R.string.moderated), - getString(R.string.non_anonymous) - }; - values = new boolean[]{ - mucOptions.membersOnly(), - mucOptions.moderated(), - mucOptions.nonanonymous() - }; - } else { - options = new String[]{ - getString(R.string.members_only), - getString(R.string.non_anonymous) - }; - values = new boolean[]{ - mucOptions.membersOnly(), - mucOptions.nonanonymous() - }; - } - builder.setMultiChoiceItems(options,values,new DialogInterface.OnMultiChoiceClickListener() { - @Override - public void onClick(DialogInterface dialog, int which, boolean isChecked) { - values[which] = isChecked; - } - }); - builder.setNegativeButton(R.string.cancel, null); - builder.setPositiveButton(R.string.confirm,new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (!mucOptions.membersOnly() && values[0]) { - xmppConnectionService.changeAffiliationsInConference(mConversation, - MucOptions.Affiliation.NONE, - MucOptions.Affiliation.MEMBER); - } - Bundle options = new Bundle(); - options.putString("muc#roomconfig_membersonly", values[0] ? "1" : "0"); - if (values.length == 2) { - options.putString("muc#roomconfig_whois", values[1] ? "anyone" : "moderators"); - } else if (values.length == 3) { - options.putString("muc#roomconfig_moderatedroom", values[1] ? "1" : "0"); - options.putString("muc#roomconfig_whois", values[2] ? "anyone" : "moderators"); - } - options.putString("muc#roomconfig_persistentroom", "1"); - xmppConnectionService.pushConferenceConfiguration(mConversation, - options, - ConferenceDetailsActivity.this); - } - }); - builder.create().show(); - } - }; - private OnValueEdited onSubjectEdited = new OnValueEdited() { - - @Override - public void onValueEdited(String value) { - xmppConnectionService.pushSubjectToConference(mConversation,value); - } - }; - - @Override - public void onConversationUpdate() { - refreshUi(); - } - - @Override - public void onMucRosterUpdate() { - refreshUi(); - } - - @Override - protected void refreshUiReal() { - updateView(); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_muc_details); - mYourNick = (TextView) findViewById(R.id.muc_your_nick); - mYourPhoto = (ImageView) findViewById(R.id.your_photo); - mEditNickButton = (ImageButton) findViewById(R.id.edit_nick_button); - mFullJid = (TextView) findViewById(R.id.muc_jabberid); - membersView = (LinearLayout) findViewById(R.id.muc_members); - mAccountJid = (TextView) findViewById(R.id.details_account); - mMoreDetails = (LinearLayout) findViewById(R.id.muc_more_details); - mMoreDetails.setVisibility(View.GONE); - mChangeConferenceSettingsButton = (ImageButton) findViewById(R.id.change_conference_button); - mChangeConferenceSettingsButton.setOnClickListener(this.mChangeConferenceSettings); - mInviteButton = (Button) findViewById(R.id.invite); - mInviteButton.setOnClickListener(inviteListener); - mConferenceType = (TextView) findViewById(R.id.muc_conference_type); - if (getActionBar() != null) { - getActionBar().setHomeButtonEnabled(true); - getActionBar().setDisplayHomeAsUpEnabled(true); - } - mEditNickButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - quickEdit(mConversation.getMucOptions().getActualNick(), - new OnValueEdited() { - - @Override - public void onValueEdited(String value) { - xmppConnectionService.renameInMuc(mConversation,value,renameCallback); - } - }); - } - }); - this.mAdvancedMode = ConversationsPlusPreferences.advancedMucMode(); - this.mConferenceInfoTable = (TableLayout) findViewById(R.id.muc_info_more); - mConferenceInfoTable.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE); - this.mConferenceInfoMam = (TextView) findViewById(R.id.muc_info_mam); - this.mNotifyStatusButton = (ImageButton) findViewById(R.id.notification_status_button); - this.mNotifyStatusButton.setOnClickListener(this.mNotifyStatusClickListener); - this.mNotifyStatusText = (TextView) findViewById(R.id.notification_status_text); - } - - @Override - public boolean onOptionsItemSelected(MenuItem menuItem) { - switch (menuItem.getItemId()) { - case android.R.id.home: - finish(); - break; - case R.id.action_edit_subject: - if (mConversation != null) { - quickEdit(mConversation.getName(),this.onSubjectEdited); - } - break; - case R.id.action_share: - share(); - break; - case R.id.action_save_as_bookmark: - saveAsBookmark(); - break; - case R.id.action_delete_bookmark: - deleteBookmark(); - break; - case R.id.action_advanced_mode: - this.mAdvancedMode = !menuItem.isChecked(); - menuItem.setChecked(this.mAdvancedMode); - ConversationsPlusPreferences.commitAdvancedMucMode(mAdvancedMode); - mConferenceInfoTable.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE); - invalidateOptionsMenu(); - updateView(); - break; - } - return super.onOptionsItemSelected(menuItem); - } - - @Override - protected String getShareableUri() { - if (mConversation != null) { - return "xmpp:" + mConversation.getJid().toBareJid().toString() + "?join"; - } else { - return ""; - } - } - - private void share() { - Intent shareIntent = new Intent(); - shareIntent.setAction(Intent.ACTION_SEND); - shareIntent.putExtra(Intent.EXTRA_TEXT, getShareableUri()); - shareIntent.setType("text/plain"); - try { - startActivity(Intent.createChooser(shareIntent, getText(R.string.share_uri_with))); - } catch (ActivityNotFoundException e) { - Toast.makeText(this, R.string.no_application_to_share_uri, Toast.LENGTH_SHORT).show(); - } - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - MenuItem menuItemSaveBookmark = menu.findItem(R.id.action_save_as_bookmark); - MenuItem menuItemDeleteBookmark = menu.findItem(R.id.action_delete_bookmark); - MenuItem menuItemAdvancedMode = menu.findItem(R.id.action_advanced_mode); - MenuItem menuItemChangeSubject = menu.findItem(R.id.action_edit_subject); - menuItemAdvancedMode.setChecked(mAdvancedMode); - if (mConversation == null) { - return true; - } - Account account = mConversation.getAccount(); - if (account.hasBookmarkFor(mConversation.getJid().toBareJid())) { - menuItemSaveBookmark.setVisible(false); - menuItemDeleteBookmark.setVisible(true); - } else { - menuItemDeleteBookmark.setVisible(false); - menuItemSaveBookmark.setVisible(true); - } - menuItemChangeSubject.setVisible(mConversation.getMucOptions().canChangeSubject()); - return true; - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.muc_details, menu); - return super.onCreateOptionsMenu(menu); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - Object tag = v.getTag(); - if (tag instanceof User) { - getMenuInflater().inflate(R.menu.muc_details_context,menu); - final User user = (User) tag; - final User self = mConversation.getMucOptions().getSelf(); - this.mSelectedUser = user; - String name; - final Contact contact = user.getContact(); - if (contact != null) { - name = contact.getDisplayName(); - } else if (user.getJid() != null){ - name = user.getJid().toBareJid().toString(); - } else { - name = user.getName(); - } - menu.setHeaderTitle(name); - if (user.getJid() != null) { - MenuItem showContactDetails = menu.findItem(R.id.action_contact_details); - MenuItem startConversation = menu.findItem(R.id.start_conversation); - MenuItem giveMembership = menu.findItem(R.id.give_membership); - MenuItem removeMembership = menu.findItem(R.id.remove_membership); - MenuItem giveAdminPrivileges = menu.findItem(R.id.give_admin_privileges); - MenuItem removeAdminPrivileges = menu.findItem(R.id.remove_admin_privileges); - MenuItem removeFromRoom = menu.findItem(R.id.remove_from_room); - MenuItem banFromConference = menu.findItem(R.id.ban_from_conference); - startConversation.setVisible(true); - if (contact != null) { - showContactDetails.setVisible(true); - } - if (self.getAffiliation().ranks(MucOptions.Affiliation.ADMIN) && - self.getAffiliation().outranks(user.getAffiliation())) { - if (mAdvancedMode) { - if (user.getAffiliation() == MucOptions.Affiliation.NONE) { - giveMembership.setVisible(true); - } else { - removeMembership.setVisible(true); - } - banFromConference.setVisible(true); - } else { - removeFromRoom.setVisible(true); - } - if (user.getAffiliation() != MucOptions.Affiliation.ADMIN) { - giveAdminPrivileges.setVisible(true); - } else { - removeAdminPrivileges.setVisible(true); - } - } - } else { - MenuItem sendPrivateMessage = menu.findItem(R.id.send_private_message); - sendPrivateMessage.setVisible(true); - } - - } - super.onCreateContextMenu(menu, v, menuInfo); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.action_contact_details: - Contact contact = mSelectedUser.getContact(); - if (contact != null) { - switchToContactDetails(contact); - } - return true; - case R.id.start_conversation: - startConversation(mSelectedUser); - return true; - case R.id.give_admin_privileges: - xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.ADMIN,this); - return true; - case R.id.give_membership: - xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this); - return true; - case R.id.remove_membership: - xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.NONE,this); - return true; - case R.id.remove_admin_privileges: - xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this); - return true; - case R.id.remove_from_room: - removeFromRoom(mSelectedUser); - return true; - case R.id.ban_from_conference: - xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.OUTCAST,this); - xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,this); - return true; - case R.id.send_private_message: - privateMsgInMuc(mConversation,mSelectedUser.getName()); - return true; - default: - return super.onContextItemSelected(item); - } - } - - private void removeFromRoom(final User user) { - if (mConversation.getMucOptions().membersOnly()) { - xmppConnectionService.changeAffiliationInConference(mConversation,user.getJid(), MucOptions.Affiliation.NONE,this); - xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,ConferenceDetailsActivity.this); - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.ban_from_conference); - builder.setMessage(getString(R.string.removing_from_public_conference,user.getName())); - builder.setNegativeButton(R.string.cancel,null); - builder.setPositiveButton(R.string.ban_now,new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - xmppConnectionService.changeAffiliationInConference(mConversation,user.getJid(), MucOptions.Affiliation.OUTCAST,ConferenceDetailsActivity.this); - xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,ConferenceDetailsActivity.this); - } - }); - builder.create().show(); - } - } - - protected void startConversation(User user) { - if (user.getJid() != null) { - Conversation conversation = xmppConnectionService.findOrCreateConversation(this.mConversation.getAccount(),user.getJid().toBareJid(),false); - switchToConversation(conversation); - } - } - - protected void saveAsBookmark() { - Account account = mConversation.getAccount(); - Bookmark bookmark = new Bookmark(account, mConversation.getJid().toBareJid()); - if (!mConversation.getJid().isBareJid()) { - bookmark.setNick(mConversation.getJid().getResourcepart()); - } - bookmark.setBookmarkName(mConversation.getMucOptions().getSubject()); - bookmark.setAutojoin(ConversationsPlusPreferences.autojoin()); - account.getBookmarks().add(bookmark); - xmppConnectionService.pushBookmarks(account); - mConversation.setBookmark(bookmark); - } - - protected void deleteBookmark() { - Account account = mConversation.getAccount(); - Bookmark bookmark = mConversation.getBookmark(); - bookmark.unregisterConversation(); - account.getBookmarks().remove(bookmark); - xmppConnectionService.pushBookmarks(account); - } - - @Override - void onBackendConnected() { - if (mPendingConferenceInvite != null) { - mPendingConferenceInvite.execute(this); - mPendingConferenceInvite = null; - } - if (getIntent().getAction().equals(ACTION_VIEW_MUC)) { - this.uuid = getIntent().getExtras().getString("uuid"); - } - if (uuid != null) { - this.mConversation = xmppConnectionService - .findConversationByUuid(uuid); - if (this.mConversation != null) { - updateView(); - } - } - } - - private void updateView() { - final MucOptions mucOptions = mConversation.getMucOptions(); - final User self = mucOptions.getSelf(); - String account; - if (Config.DOMAIN_LOCK != null) { - account = mConversation.getAccount().getJid().getLocalpart(); - } else { - account = mConversation.getAccount().getJid().toBareJid().toString(); - } - mAccountJid.setText(getString(R.string.using_account, account)); - mYourPhoto.setImageBitmap(AvatarService.getInstance().get(mConversation.getAccount(), getPixel(48))); - setTitle(mConversation.getName()); - if (Config.LOCK_DOMAINS_IN_CONVERSATIONS && mConversation.getJid().getDomainpart().equals(Config.CONFERENCE_DOMAIN_LOCK)) { - mFullJid.setText(mConversation.getJid().getLocalpart()); - } else { - mFullJid.setText(mConversation.getJid().toBareJid().toString()); - } - mYourNick.setText(mucOptions.getActualNick()); - mRoleAffiliaton = (TextView) findViewById(R.id.muc_role); - if (mucOptions.online()) { - mMoreDetails.setVisibility(View.VISIBLE); - final String status = getStatus(self); - if (status != null) { - mRoleAffiliaton.setVisibility(View.VISIBLE); - mRoleAffiliaton.setText(status); - } else { - mRoleAffiliaton.setVisibility(View.GONE); - } - if (mucOptions.membersOnly()) { - mConferenceType.setText(R.string.private_conference); - } else { - mConferenceType.setText(R.string.public_conference); - } - if (mucOptions.mamSupport()) { - mConferenceInfoMam.setText(R.string.server_info_available); - } else { - mConferenceInfoMam.setText(R.string.server_info_unavailable); - } - if (self.getAffiliation().ranks(MucOptions.Affiliation.OWNER)) { - mChangeConferenceSettingsButton.setVisibility(View.VISIBLE); - } else { - mChangeConferenceSettingsButton.setVisibility(View.GONE); - } - } - - long mutedTill = mConversation.getLongAttribute(Conversation.ATTRIBUTE_MUTED_TILL,0); - if (mutedTill == Long.MAX_VALUE) { - mNotifyStatusText.setText(R.string.notify_never); - mNotifyStatusButton.setImageResource(R.drawable.ic_notifications_off_grey600_24dp); - } else if (System.currentTimeMillis() < mutedTill) { - mNotifyStatusText.setText(R.string.notify_paused); - mNotifyStatusButton.setImageResource(R.drawable.ic_notifications_paused_grey600_24dp); - } else if (mConversation.alwaysNotify()) { - mNotifyStatusButton.setImageResource(R.drawable.ic_notifications_grey600_24dp); - mNotifyStatusText.setText(R.string.notify_on_all_messages); - } else { - mNotifyStatusButton.setImageResource(R.drawable.ic_notifications_none_grey600_24dp); - mNotifyStatusText.setText(R.string.notify_only_when_highlighted); - } - - LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); - membersView.removeAllViews(); - final ArrayList<User> users = mucOptions.getUsers(); - Collections.sort(users,new Comparator<User>() { - @Override - public int compare(User lhs, User rhs) { - return lhs.getName().compareToIgnoreCase(rhs.getName()); - } - }); - for (final User user : users) { - View view = inflater.inflate(R.layout.contact, membersView,false); - this.setListItemBackgroundOnView(view); - view.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - highlightInMuc(mConversation, user.getName()); - } - }); - registerForContextMenu(view); - view.setTag(user); - TextView tvDisplayName = (TextView) view.findViewById(R.id.contact_display_name); - TextView tvKey = (TextView) view.findViewById(R.id.key); - TextView tvStatus = (TextView) view.findViewById(R.id.contact_jid); - if (mAdvancedMode && user.getPgpKeyId() != 0) { - tvKey.setVisibility(View.VISIBLE); - tvKey.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - viewPgpKey(user); - } - }); - tvKey.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId())); - } - Contact contact = user.getContact(); - if (contact != null) { - tvDisplayName.setText(contact.getDisplayName()); - tvStatus.setText(user.getName() + " \u2022 " + getStatus(user)); - } else { - tvDisplayName.setText(user.getName()); - tvStatus.setText(getStatus(user)); - - } - ImageView iv = (ImageView) view.findViewById(R.id.contact_photo); - iv.setImageBitmap(AvatarService.getInstance().get(user, getPixel(48), false)); - membersView.addView(view); - if (mConversation.getMucOptions().canInvite()) { - mInviteButton.setVisibility(View.VISIBLE); - } else { - mInviteButton.setVisibility(View.GONE); - } - } - } - - private String getStatus(User user) { - if (mAdvancedMode) { - StringBuilder builder = new StringBuilder(); - builder.append(getString(user.getAffiliation().getResId())); - builder.append(" ("); - builder.append(getString(user.getRole().getResId())); - builder.append(')'); - return builder.toString(); - } else { - return getString(user.getAffiliation().getResId()); - } - } - - @SuppressWarnings("deprecation") - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private void setListItemBackgroundOnView(View view) { - int sdk = android.os.Build.VERSION.SDK_INT; - if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) { - view.setBackgroundDrawable(getResources().getDrawable(R.drawable.greybackground)); - } else { - view.setBackground(getResources().getDrawable(R.drawable.greybackground)); - } - } - - private void viewPgpKey(User user) { - PgpEngine pgp = xmppConnectionService.getPgpEngine(); - if (pgp != null) { - PendingIntent intent = pgp.getIntentForKey( - mConversation.getAccount(), user.getPgpKeyId()); - if (intent != null) { - try { - startIntentSenderForResult(intent.getIntentSender(), 0, - null, 0, 0, 0); - } catch (SendIntentException ignored) { - - } - } - } - } - - @Override - public void onAffiliationChangedSuccessful(Jid jid) { - - } - - @Override - public void onAffiliationChangeFailed(Jid jid, int resId) { - displayToast(getString(resId,jid.toBareJid().toString())); - } - - @Override - public void onRoleChangedSuccessful(String nick) { - - } - - @Override - public void onRoleChangeFailed(String nick, int resId) { - displayToast(getString(resId,nick)); - } - - @Override - public void onPushSucceeded() { - displayToast(getString(R.string.modified_conference_options)); - } - - @Override - public void onPushFailed() { - displayToast(getString(R.string.could_not_modify_conference_options)); - } - - private void displayToast(final String msg) { - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(ConferenceDetailsActivity.this,msg,Toast.LENGTH_SHORT).show(); - } - }); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ContactDetailsActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/ContactDetailsActivity.java deleted file mode 100644 index 3ca9fce7..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ContactDetailsActivity.java +++ /dev/null @@ -1,529 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.AlertDialog; -import android.app.PendingIntent; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentSender.SendIntentException; -import android.net.Uri; -import android.os.Bundle; -import android.provider.ContactsContract; -import android.provider.ContactsContract.CommonDataKinds; -import android.provider.ContactsContract.Contacts; -import android.provider.ContactsContract.Intents; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; -import android.widget.ImageButton; -import android.widget.LinearLayout; -import android.widget.QuickContactBadge; -import android.widget.TextView; -import android.widget.Toast; - -import org.openintents.openpgp.util.OpenPgpUtils; - -import java.security.cert.X509Certificate; -import java.util.List; - -import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.thedevstack.conversationsplus.ui.listeners.ShowResourcesListDialogListener; -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.crypto.PgpEngine; -import de.thedevstack.conversationsplus.crypto.axolotl.AxolotlService; -import de.thedevstack.conversationsplus.crypto.axolotl.XmppAxolotlSession; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Contact; -import de.thedevstack.conversationsplus.entities.ListItem; -import de.thedevstack.conversationsplus.services.AvatarService; -import de.thedevstack.conversationsplus.services.XmppConnectionService.OnAccountUpdate; -import de.thedevstack.conversationsplus.services.XmppConnectionService.OnRosterUpdate; -import de.thedevstack.conversationsplus.utils.CryptoHelper; -import de.thedevstack.conversationsplus.utils.UIHelper; -import de.thedevstack.conversationsplus.xmpp.OnKeyStatusUpdated; -import de.thedevstack.conversationsplus.xmpp.OnUpdateBlocklist; -import de.thedevstack.conversationsplus.xmpp.XmppConnection; -import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class ContactDetailsActivity extends XmppActivity implements OnAccountUpdate, OnRosterUpdate, OnUpdateBlocklist, OnKeyStatusUpdated { - public static final String ACTION_VIEW_CONTACT = "view_contact"; - - private Contact contact; - private DialogInterface.OnClickListener removeFromRoster = new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - xmppConnectionService.deleteContactOnServer(contact); - } - }; - private OnCheckedChangeListener mOnSendCheckedChange = new OnCheckedChangeListener() { - - @Override - public void onCheckedChanged(CompoundButton buttonView, - boolean isChecked) { - if (isChecked) { - if (contact - .getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { - xmppConnectionService.sendPresencePacket(contact - .getAccount(), - xmppConnectionService.getPresenceGenerator() - .sendPresenceUpdatesTo(contact)); - } else { - contact.setOption(Contact.Options.PREEMPTIVE_GRANT); - } - } else { - contact.resetOption(Contact.Options.PREEMPTIVE_GRANT); - xmppConnectionService.sendPresencePacket(contact.getAccount(), - xmppConnectionService.getPresenceGenerator() - .stopPresenceUpdatesTo(contact)); - } - } - }; - private OnCheckedChangeListener mOnReceiveCheckedChange = new OnCheckedChangeListener() { - - @Override - public void onCheckedChanged(CompoundButton buttonView, - boolean isChecked) { - if (isChecked) { - xmppConnectionService.sendPresencePacket(contact.getAccount(), - xmppConnectionService.getPresenceGenerator() - .requestPresenceUpdatesFrom(contact)); - } else { - xmppConnectionService.sendPresencePacket(contact.getAccount(), - xmppConnectionService.getPresenceGenerator() - .stopPresenceUpdatesFrom(contact)); - } - } - }; - private Jid accountJid; - private Jid contactJid; - private TextView contactJidTv; - private TextView accountJidTv; - private TextView lastseen; - private CheckBox send; - private CheckBox receive; - private Button addContactButton; - private QuickContactBadge badge; - private LinearLayout keys; - private LinearLayout tags; - private boolean showDynamicTags; - private String messageFingerprint; - - private DialogInterface.OnClickListener addToPhonebook = new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); - intent.setType(Contacts.CONTENT_ITEM_TYPE); - intent.putExtra(Intents.Insert.IM_HANDLE, contact.getJid().toString()); - intent.putExtra(Intents.Insert.IM_PROTOCOL, - CommonDataKinds.Im.PROTOCOL_JABBER); - intent.putExtra("finishActivityOnSaveCompleted", true); - ContactDetailsActivity.this.startActivityForResult(intent, 0); - } - }; - - private OnClickListener onBadgeClick = new OnClickListener() { - - @Override - public void onClick(View v) { - if (contact.getSystemAccount() == null) { - AlertDialog.Builder builder = new AlertDialog.Builder( - ContactDetailsActivity.this); - builder.setTitle(getString(R.string.action_add_phone_book)); - builder.setMessage(getString(R.string.add_phone_book_text, - contact.getDisplayJid())); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.setPositiveButton(getString(R.string.add), addToPhonebook); - builder.create().show(); - } else { - String[] systemAccount = contact.getSystemAccount().split("#"); - long id = Long.parseLong(systemAccount[0]); - Uri uri = ContactsContract.Contacts.getLookupUri(id, systemAccount[1]); - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(uri); - startActivity(intent); - } - } - }; - - @Override - public void onRosterUpdate() { - refreshUi(); - } - - @Override - public void onAccountUpdate() { - refreshUi(); - } - - @Override - public void OnUpdateBlocklist(final Status status) { - refreshUi(); - } - - @Override - protected void refreshUiReal() { - invalidateOptionsMenu(); - populateView(); - } - - @Override - protected String getShareableUri() { - if (contact != null) { - return contact.getShareableUri(); - } else { - return ""; - } - } - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) { - try { - this.accountJid = Jid.fromString(getIntent().getExtras().getString(EXTRA_ACCOUNT)); - } catch (final InvalidJidException ignored) { - } - try { - this.contactJid = Jid.fromString(getIntent().getExtras().getString("contact")); - } catch (final InvalidJidException ignored) { - } - } - this.messageFingerprint = getIntent().getStringExtra("fingerprint"); - setContentView(R.layout.activity_contact_details); - - contactJidTv = (TextView) findViewById(R.id.details_contactjid); - accountJidTv = (TextView) findViewById(R.id.details_account); - lastseen = (TextView) findViewById(R.id.details_lastseen); - send = (CheckBox) findViewById(R.id.details_send_presence); - receive = (CheckBox) findViewById(R.id.details_receive_presence); - badge = (QuickContactBadge) findViewById(R.id.details_contact_badge); - addContactButton = (Button) findViewById(R.id.add_contact_button); - addContactButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - showAddToRosterDialog(contact); - } - }); - keys = (LinearLayout) findViewById(R.id.details_contact_keys); - tags = (LinearLayout) findViewById(R.id.tags); - if (getActionBar() != null) { - getActionBar().setHomeButtonEnabled(true); - getActionBar().setDisplayHomeAsUpEnabled(true); - } - - this.showDynamicTags = ConversationsPlusPreferences.showDynamicTags(); - } - - @Override - public boolean onOptionsItemSelected(final MenuItem menuItem) { - final AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setNegativeButton(getString(R.string.cancel), null); - switch (menuItem.getItemId()) { - case android.R.id.home: - finish(); - break; - case R.id.action_delete_contact: - builder.setTitle(getString(R.string.action_delete_contact)) - .setMessage( - getString(R.string.remove_contact_text, - contact.getDisplayJid())) - .setPositiveButton(getString(R.string.delete), - removeFromRoster).create().show(); - break; - case R.id.action_edit_contact: - if (contact.getSystemAccount() == null) { - quickEdit(contact.getDisplayName(), new OnValueEdited() { - - @Override - public void onValueEdited(String value) { - contact.setServerName(value); - ContactDetailsActivity.this.xmppConnectionService - .pushContactToServer(contact); - populateView(); - } - }); - } else { - Intent intent = new Intent(Intent.ACTION_EDIT); - String[] systemAccount = contact.getSystemAccount().split("#"); - long id = Long.parseLong(systemAccount[0]); - Uri uri = Contacts.getLookupUri(id, systemAccount[1]); - intent.setDataAndType(uri, Contacts.CONTENT_ITEM_TYPE); - intent.putExtra("finishActivityOnSaveCompleted", true); - startActivity(intent); - } - break; - case R.id.action_block: - BlockContactDialog.show(this, xmppConnectionService, contact); - break; - case R.id.action_unblock: - BlockContactDialog.show(this, xmppConnectionService, contact); - break; - } - return super.onOptionsItemSelected(menuItem); - } - - @Override - public boolean onCreateOptionsMenu(final Menu menu) { - getMenuInflater().inflate(R.menu.contact_details, menu); - MenuItem block = menu.findItem(R.id.action_block); - MenuItem unblock = menu.findItem(R.id.action_unblock); - MenuItem edit = menu.findItem(R.id.action_edit_contact); - MenuItem delete = menu.findItem(R.id.action_delete_contact); - if (contact == null) { - return true; - } - final XmppConnection connection = contact.getAccount().getXmppConnection(); - if (connection != null && connection.getFeatures().blocking()) { - if (this.contact.isBlocked()) { - block.setVisible(false); - } else { - unblock.setVisible(false); - } - } else { - unblock.setVisible(false); - block.setVisible(false); - } - if (!contact.showInRoster()) { - edit.setVisible(false); - delete.setVisible(false); - } - return super.onCreateOptionsMenu(menu); - } - - private void populateView() { - invalidateOptionsMenu(); - setTitle(contact.getDisplayName()); - if (contact.showInRoster()) { - send.setVisibility(View.VISIBLE); - receive.setVisibility(View.VISIBLE); - addContactButton.setVisibility(View.GONE); - send.setOnCheckedChangeListener(null); - receive.setOnCheckedChangeListener(null); - - if (contact.getOption(Contact.Options.FROM)) { - send.setText(R.string.send_presence_updates); - send.setChecked(true); - } else if (contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { - send.setChecked(false); - send.setText(R.string.send_presence_updates); - } else { - send.setText(R.string.preemptively_grant); - if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) { - send.setChecked(true); - } else { - send.setChecked(false); - } - } - if (contact.getOption(Contact.Options.TO)) { - receive.setText(R.string.receive_presence_updates); - receive.setChecked(true); - } else { - receive.setText(R.string.ask_for_presence_updates); - if (contact.getOption(Contact.Options.ASKING)) { - receive.setChecked(true); - } else { - receive.setChecked(false); - } - } - if (contact.getAccount().isOnlineAndConnected()) { - receive.setEnabled(true); - send.setEnabled(true); - } else { - receive.setEnabled(false); - send.setEnabled(false); - } - - send.setOnCheckedChangeListener(this.mOnSendCheckedChange); - receive.setOnCheckedChangeListener(this.mOnReceiveCheckedChange); - } else { - addContactButton.setVisibility(View.VISIBLE); - send.setVisibility(View.GONE); - receive.setVisibility(View.GONE); - } - - if (contact.isBlocked() && !this.showDynamicTags) { - lastseen.setText(R.string.contact_blocked); - } else { - lastseen.setText(UIHelper.lastseen(getApplicationContext(), contact.lastseen.time)); - } - - if (contact.getPresences().size() > 1) { - contactJidTv.setText(contact.getDisplayJid() + " (" - + contact.getPresences().size() + ")"); - } else { - contactJidTv.setText(contact.getDisplayJid()); - } - String account; - if (Config.DOMAIN_LOCK != null) { - account = contact.getAccount().getJid().getLocalpart(); - } else { - account = contact.getAccount().getJid().toBareJid().toString(); - } - contactJidTv.setOnClickListener(new ShowResourcesListDialogListener(ContactDetailsActivity.this, contact)); - accountJidTv.setText(getString(R.string.using_account, account)); - badge.setImageBitmap(AvatarService.getInstance().get(contact, getPixel(72))); - badge.setOnClickListener(this.onBadgeClick); - - keys.removeAllViews(); - boolean hasKeys = false; - LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); - for(final String otrFingerprint : contact.getOtrFingerprints()) { - hasKeys = true; - View view = inflater.inflate(R.layout.contact_key, keys, false); - TextView key = (TextView) view.findViewById(R.id.key); - TextView keyType = (TextView) view.findViewById(R.id.key_type); - ImageButton removeButton = (ImageButton) view - .findViewById(R.id.button_remove); - removeButton.setVisibility(View.VISIBLE); - keyType.setText("OTR Fingerprint"); - key.setText(CryptoHelper.prettifyFingerprint(otrFingerprint)); - keys.addView(view); - removeButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - confirmToDeleteFingerprint(otrFingerprint); - } - }); - } - for (final String fingerprint : contact.getAccount().getAxolotlService().getFingerprintsForContact(contact)) { - boolean highlight = fingerprint.equals(messageFingerprint); - hasKeys |= addFingerprintRow(keys, contact.getAccount(), fingerprint, highlight, new OnClickListener() { - @Override - public void onClick(View v) { - onOmemoKeyClicked(contact.getAccount(), fingerprint); - } - }); - } - if (contact.getPgpKeyId() != 0) { - hasKeys = true; - View view = inflater.inflate(R.layout.contact_key, keys, false); - TextView key = (TextView) view.findViewById(R.id.key); - TextView keyType = (TextView) view.findViewById(R.id.key_type); - keyType.setText("PGP Key ID"); - key.setText(OpenPgpUtils.convertKeyIdToHex(contact.getPgpKeyId())); - view.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - PgpEngine pgp = ContactDetailsActivity.this.xmppConnectionService - .getPgpEngine(); - if (pgp != null) { - PendingIntent intent = pgp.getIntentForKey(contact); - if (intent != null) { - try { - startIntentSenderForResult( - intent.getIntentSender(), 0, null, 0, - 0, 0); - } catch (SendIntentException e) { - - } - } - } - } - }); - keys.addView(view); - } - if (hasKeys) { - keys.setVisibility(View.VISIBLE); - } else { - keys.setVisibility(View.GONE); - } - - List<ListItem.Tag> tagList = contact.getTags(); - if (tagList.size() == 0 || !this.showDynamicTags) { - tags.setVisibility(View.GONE); - } else { - tags.setVisibility(View.VISIBLE); - tags.removeAllViewsInLayout(); - for(final ListItem.Tag tag : tagList) { - final TextView tv = (TextView) inflater.inflate(R.layout.list_item_tag,tags,false); - tv.setText(tag.getName()); - tv.setBackgroundColor(tag.getColor()); - tags.addView(tv); - } - } - } - - private void onOmemoKeyClicked(Account account, String fingerprint) { - final XmppAxolotlSession.Trust trust = account.getAxolotlService().getFingerprintTrust(fingerprint); - if (Config.X509_VERIFICATION && trust != null && trust == XmppAxolotlSession.Trust.TRUSTED_X509) { - X509Certificate x509Certificate = account.getAxolotlService().getFingerprintCertificate(fingerprint); - if (x509Certificate != null) { - showCertificateInformationDialog(CryptoHelper.extractCertificateInformation(x509Certificate)); - } else { - Toast.makeText(this,R.string.certificate_not_found, Toast.LENGTH_SHORT).show(); - } - } - } - - private void showCertificateInformationDialog(Bundle bundle) { - View view = getLayoutInflater().inflate(R.layout.certificate_information, null); - final String not_available = getString(R.string.certicate_info_not_available); - TextView subject_cn = (TextView) view.findViewById(R.id.subject_cn); - TextView subject_o = (TextView) view.findViewById(R.id.subject_o); - TextView issuer_cn = (TextView) view.findViewById(R.id.issuer_cn); - TextView issuer_o = (TextView) view.findViewById(R.id.issuer_o); - TextView sha1 = (TextView) view.findViewById(R.id.sha1); - - subject_cn.setText(bundle.getString("subject_cn", not_available)); - subject_o.setText(bundle.getString("subject_o", not_available)); - issuer_cn.setText(bundle.getString("issuer_cn", not_available)); - issuer_o.setText(bundle.getString("issuer_o", not_available)); - sha1.setText(bundle.getString("sha1", not_available)); - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.certificate_information); - builder.setView(view); - builder.setPositiveButton(R.string.ok, null); - builder.create().show(); - } - - protected void confirmToDeleteFingerprint(final String fingerprint) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.delete_fingerprint); - builder.setMessage(R.string.sure_delete_fingerprint); - builder.setNegativeButton(R.string.cancel, null); - builder.setPositiveButton(R.string.delete, - new android.content.DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - if (contact.deleteOtrFingerprint(fingerprint)) { - populateView(); - xmppConnectionService.syncRosterToDisk(contact.getAccount()); - } - } - - }); - builder.create().show(); - } - - @Override - public void onBackendConnected() { - if ((accountJid != null) && (contactJid != null)) { - Account account = xmppConnectionService - .findAccountByJid(accountJid); - if (account == null) { - return; - } - this.contact = account.getRoster().getContact(contactJid); - populateView(); - } - } - - @Override - public void onKeyStatusUpdated(AxolotlService.FetchStatus report) { - refreshUi(); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ConversationActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/ConversationActivity.java deleted file mode 100644 index bca0851a..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ConversationActivity.java +++ /dev/null @@ -1,1620 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.annotation.SuppressLint; -import android.app.ActionBar; -import android.app.AlertDialog; -import android.app.FragmentTransaction; -import android.app.PendingIntent; -import android.content.ClipData; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.content.IntentSender.SendIntentException; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.provider.MediaStore; -import android.provider.Settings; -import android.support.v4.widget.SlidingPaneLayout; -import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener; -import android.util.Log; -import android.util.Pair; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.Surface; -import android.view.View; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ArrayAdapter; -import android.widget.CheckBox; -import android.widget.PopupMenu; -import android.widget.PopupMenu.OnMenuItemClickListener; -import android.widget.Toast; - -import net.java.otr4j.session.SessionStatus; - -import org.openintents.openpgp.util.OpenPgpApi; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -import de.thedevstack.android.logcat.Logging; -import de.thedevstack.conversationsplus.utils.AccountUtil; -import de.timroes.android.listview.EnhancedListView; - -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.crypto.axolotl.AxolotlService; -import de.thedevstack.conversationsplus.crypto.axolotl.AxolotlServiceImpl; -import de.thedevstack.conversationsplus.crypto.axolotl.XmppAxolotlSession; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Blockable; -import de.thedevstack.conversationsplus.entities.Contact; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.entities.Message; -import de.thedevstack.conversationsplus.entities.Transferable; -import de.thedevstack.conversationsplus.http.HttpConnectionManager; -import de.thedevstack.conversationsplus.http.HttpDownloadConnection; -import de.thedevstack.conversationsplus.persistance.FileBackend; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.services.XmppConnectionService.OnAccountUpdate; -import de.thedevstack.conversationsplus.services.XmppConnectionService.OnConversationUpdate; -import de.thedevstack.conversationsplus.services.XmppConnectionService.OnRosterUpdate; -import de.thedevstack.conversationsplus.ui.adapter.ConversationAdapter; -import de.thedevstack.conversationsplus.ui.dialogs.UserDecisionDialog; -import de.thedevstack.conversationsplus.ui.listeners.ResizePictureUserDecisionListener; -import de.thedevstack.conversationsplus.utils.ConversationUtil; -import de.thedevstack.conversationsplus.utils.ExceptionHelper; -import de.thedevstack.conversationsplus.utils.FileUtils; -import de.thedevstack.conversationsplus.xmpp.OnUpdateBlocklist; -import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class ConversationActivity extends XmppActivity - implements OnAccountUpdate, OnConversationUpdate, OnRosterUpdate, OnUpdateBlocklist, XmppConnectionService.OnShowErrorToast { - - public static final String ACTION_DOWNLOAD = "eu.siacs.conversations.action.DOWNLOAD"; - - public static final String VIEW_CONVERSATION = "viewConversation"; - public static final String CONVERSATION = "conversationUuid"; - public static final String MESSAGE = "messageUuid"; - public static final String TEXT = "text"; - public static final String NICK = "nick"; - public static final String PRIVATE_MESSAGE = "pm"; - - public static final int REQUEST_SEND_MESSAGE = 0x0201; - public static final int REQUEST_DECRYPT_PGP = 0x0202; - public static final int REQUEST_ENCRYPT_MESSAGE = 0x0207; - public static final int REQUEST_TRUST_KEYS_TEXT = 0x0208; - public static final int REQUEST_TRUST_KEYS_MENU = 0x0209; - public static final int REQUEST_START_DOWNLOAD = 0x0210; - 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; - public static final int ATTACHMENT_CHOICE_INVALID = 0x0306; - private static final String STATE_OPEN_CONVERSATION = "state_open_conversation"; - private static final String STATE_PANEL_OPEN = "state_panel_open"; - private static final String STATE_PENDING_URI = "state_pending_uri"; - - private String mOpenConverstaion = null; - private boolean mPanelOpen = true; - final private List<Uri> mPendingImageUris = new ArrayList<>(); - final private List<Uri> mPendingFileUris = new ArrayList<>(); - private Uri mPendingGeoUri = null; - private boolean forbidProcessingPendings = false; - private Message mPendingDownloadableMessage = null; - - private boolean conversationWasSelectedByKeyboard = false; - protected boolean mUsingEnterKey = false; - - private View mContentView; - - private List<Conversation> conversationList = new ArrayList<>(); - private Conversation swipedConversation = null; - private Conversation mSelectedConversation = null; - private EnhancedListView listView; - private ConversationFragment mConversationFragment; - - private ArrayAdapter<Conversation> listAdapter; - - private boolean mActivityPaused = false; - private AtomicBoolean mRedirected = new AtomicBoolean(false); - private Pair<Integer, Intent> mPostponedActivityResult; - - public Conversation getSelectedConversation() { - return this.mSelectedConversation; - } - - public void setSelectedConversation(Conversation conversation) { - this.mSelectedConversation = conversation; - } - - public void showConversationsOverview() { - if (mContentView instanceof SlidingPaneLayout) { - SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView; - mSlidingPaneLayout.openPane(); - } - } - - @Override - protected String getShareableUri() { - Conversation conversation = getSelectedConversation(); - if (conversation != null) { - return conversation.getAccount().getShareableUri(); - } else { - return ""; - } - } - - public void hideConversationsOverview() { - if (mContentView instanceof SlidingPaneLayout) { - SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView; - mSlidingPaneLayout.closePane(); - } - } - - public boolean isConversationsOverviewHideable() { - if (mContentView instanceof SlidingPaneLayout) { - return true; - } else { - return false; - } - } - - public boolean isConversationsOverviewVisable() { - if (mContentView instanceof SlidingPaneLayout) { - SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView; - return mSlidingPaneLayout.isOpen(); - } else { - return true; - } - } - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState != null) { - mOpenConverstaion = savedInstanceState.getString(STATE_OPEN_CONVERSATION, null); - mPanelOpen = savedInstanceState.getBoolean(STATE_PANEL_OPEN, true); - String pending = savedInstanceState.getString(STATE_PENDING_URI, null); - if (pending != null) { - mPendingImageUris.clear(); - mPendingImageUris.add(Uri.parse(pending)); - } - } - this.mUsingEnterKey = ConversationsPlusPreferences.displayEnterKey(); - - setContentView(R.layout.fragment_conversations_overview); - - this.mConversationFragment = new ConversationFragment(); - FragmentTransaction transaction = getFragmentManager().beginTransaction(); - transaction.replace(R.id.selected_conversation, this.mConversationFragment, "conversation"); - transaction.commit(); - - listView = (EnhancedListView) findViewById(R.id.list); - this.listAdapter = new ConversationAdapter(this, conversationList); - listView.setAdapter(this.listAdapter); - - if (getActionBar() != null) { - getActionBar().setDisplayHomeAsUpEnabled(false); - getActionBar().setHomeButtonEnabled(false); - } - - listView.setOnItemClickListener(new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView<?> arg0, View clickedView, - int position, long arg3) { - if (getSelectedConversation() != conversationList.get(position)) { - setSelectedConversation(conversationList.get(position)); - ConversationActivity.this.mConversationFragment.reInit(getSelectedConversation()); - conversationWasSelectedByKeyboard = false; - } - hideConversationsOverview(); - openConversation(); - } - }); - - 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()); - - try { - swipedConversation = listAdapter.getItem(position); - } catch (IndexOutOfBoundsException e) { - return null; - } - listAdapter.remove(swipedConversation); - Logging.d("markRead", "EnhancedListView.OnDismissCallback.onDismiss (" + swipedConversation.getName() + ")"); - xmppConnectionService.markRead(swipedConversation); - - 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.setSwipeDirection(EnhancedListView.SwipeDirection.START); - listView.setSwipingLayout(R.id.swipeable_item); - listView.setUndoStyle(EnhancedListView.UndoStyle.SINGLE_POPUP); - listView.setUndoHideDelay(5000); - listView.setRequireTouchBeforeDismiss(false); - - mContentView = findViewById(R.id.content_view_spl); - if (mContentView == null) { - mContentView = findViewById(R.id.content_view_ll); - } - if (mContentView instanceof SlidingPaneLayout) { - SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView; - // Move the conversation list when sliding the selected conversation - mSlidingPaneLayout.setParallaxDistance(150); - // The shadow between conversation list and selected conversation - mSlidingPaneLayout.setShadowResourceLeft(R.drawable.es_slidingpane_shadow); - mSlidingPaneLayout.setSliderFadeColor(0); - mSlidingPaneLayout.setPanelSlideListener(new PanelSlideListener() { - - @Override - public void onPanelOpened(View arg0) { - updateActionBarTitle(); - invalidateOptionsMenu(); - hideKeyboard(); - if (xmppConnectionServiceBound) { - xmppConnectionService.getNotificationService() - .setOpenConversation(null); - } - closeContextMenu(); - } - - @Override - public void onPanelClosed(View arg0) { - listView.discardUndo(); - openConversation(); - } - - @Override - public void onPanelSlide(View arg0, float arg1) { - // TODO Auto-generated method stub - - } - }); - } - } - - @Override - public void switchToConversation(Conversation conversation) { - setSelectedConversation(conversation); - runOnUiThread(new Runnable() { - @Override - public void run() { - ConversationActivity.this.mConversationFragment.reInit(getSelectedConversation()); - openConversation(); - } - }); - } - - private void updateActionBarTitle() { - updateActionBarTitle(isConversationsOverviewHideable() && !isConversationsOverviewVisable()); - } - - private void updateActionBarTitle(boolean titleShouldBeName) { - final ActionBar ab = getActionBar(); - final Conversation conversation = getSelectedConversation(); - if (ab != null) { - if (titleShouldBeName && conversation != null) { - ab.setDisplayHomeAsUpEnabled(true); - ab.setHomeButtonEnabled(true); - if (conversation.getMode() == Conversation.MODE_SINGLE || ConversationsPlusPreferences.useSubject()) { - ab.setTitle(conversation.getName()); - } else { - ab.setTitle(conversation.getJid().toBareJid().toString()); - } - } else { - ab.setDisplayHomeAsUpEnabled(false); - ab.setHomeButtonEnabled(false); - ab.setTitle(R.string.app_name); - } - } - } - - private void openConversation() { - this.updateActionBarTitle(); - this.invalidateOptionsMenu(); - if (xmppConnectionServiceBound) { - final Conversation conversation = getSelectedConversation(); - xmppConnectionService.getNotificationService().setOpenConversation(conversation); - sendReadMarkerIfNecessary(conversation); - } - listAdapter.notifyDataSetChanged(); - } - - public void sendReadMarkerIfNecessary(final Conversation conversation) { - if (!mActivityPaused && conversation != null) { - xmppConnectionService.sendReadMarker(conversation); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.conversations, menu); - 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); - - if (isConversationsOverviewVisable() && isConversationsOverviewHideable()) { - menuArchive.setVisible(false); - menuMucDetails.setVisible(false); - menuContactDetails.setVisible(false); - menuSecure.setVisible(false); - menuInviteContact.setVisible(false); - menuAttach.setVisible(false); - menuClearHistory.setVisible(false); - menuMute.setVisible(false); - menuUnmute.setVisible(false); - } else { - menuAdd.setVisible(!isConversationsOverviewHideable()); - if (this.getSelectedConversation() != null) { - if (this.getSelectedConversation().getNextEncryption() != Message.ENCRYPTION_NONE) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - menuSecure.setIcon(R.drawable.ic_lock_white_24dp); - } else { - menuSecure.setIcon(R.drawable.ic_action_secure); - } - } - if (this.getSelectedConversation().getMode() == Conversation.MODE_MULTI) { - menuContactDetails.setVisible(false); - menuAttach.setVisible(AccountUtil.isHttpUploadAvailable(getSelectedConversation().getAccount()) && getSelectedConversation().getMucOptions().participating()); - menuInviteContact.setVisible(getSelectedConversation().getMucOptions().canInvite()); - menuSecure.setVisible((Config.supportOpenPgp() || Config.supportOmemo()) && Config.multipleEncryptionChoices()); //only if pgp is supported we have a choice - } else { - menuMucDetails.setVisible(false); - menuSecure.setVisible(Config.multipleEncryptionChoices()); - } - if (this.getSelectedConversation().isMuted()) { - menuMute.setVisible(false); - } else { - menuUnmute.setVisible(false); - } - } - } - return super.onCreateOptionsMenu(menu); - } - - protected void selectPresenceToAttachFile(final int attachmentChoice, final int encryption) { - final Conversation conversation = getSelectedConversation(); - final Account account = conversation.getAccount(); - final OnPresenceSelected callback = new OnPresenceSelected() { - - @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) { - intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); - } - intent.setType("image/*"); - chooser = true; - break; - case ATTACHMENT_CHOICE_TAKE_PHOTO: - Uri uri = FileBackend.getTakePhotoUri(); - intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); - intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - mPendingImageUris.clear(); - mPendingImageUris.add(uri); - 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); - fallbackPackageId = "eu.siacs.conversations.voicerecorder"; - 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); - } - } else if (fallbackPackageId != null) { - startActivity(getInstallApkIntent(fallbackPackageId)); - } - } - }; - if ((AccountUtil.isHttpUploadAvailable(account) || attachmentChoice == ATTACHMENT_CHOICE_LOCATION) && encryption != Message.ENCRYPTION_OTR) { - conversation.setNextCounterpart(null); - callback.onPresenceSelected(); - } else { - selectPresence(conversation, callback); - } - } - - private Intent getInstallApkIntent(final String packageId) { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse("market://details?id=" + packageId)); - if (intent.resolveActivity(getPackageManager()) != null) { - return intent; - } else { - intent.setData(Uri.parse("http://play.google.com/store/apps/details?id=" + packageId)); - return intent; - } - } - - public void attachFile(final int attachmentChoice) { - if (attachmentChoice != ATTACHMENT_CHOICE_LOCATION) { - if (!hasStoragePermission(attachmentChoice)) { - return; - } - } - switch (attachmentChoice) { - case ATTACHMENT_CHOICE_LOCATION: - ConversationsPlusPreferences.applyRecentlyUsedQuickAction("location"); - break; - case ATTACHMENT_CHOICE_RECORD_VOICE: - ConversationsPlusPreferences.applyRecentlyUsedQuickAction("voice"); - break; - case ATTACHMENT_CHOICE_TAKE_PHOTO: - ConversationsPlusPreferences.applyRecentlyUsedQuickAction("photo"); - break; - case ATTACHMENT_CHOICE_CHOOSE_IMAGE: - ConversationsPlusPreferences.applyRecentlyUsedQuickAction("picture"); - break; - } - final Conversation conversation = getSelectedConversation(); - final int encryption = conversation.getNextEncryption(); - final int mode = conversation.getMode(); - if (encryption == Message.ENCRYPTION_PGP) { - if (hasPgp()) { - if (mode == Conversation.MODE_SINGLE && conversation.getContact().getPgpKeyId() != 0) { - xmppConnectionService.getPgpEngine().hasKey( - conversation.getContact(), - new UiCallback<Contact>() { - - @Override - public void userInputRequried(PendingIntent pi, Contact contact) { - ConversationActivity.this.runIntent(pi, attachmentChoice); - } - - @Override - public void success(Contact contact) { - selectPresenceToAttachFile(attachmentChoice, encryption); - } - - @Override - public void error(int error, Contact contact) { - displayErrorDialog(error); - } - }); - } 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); - } else { - final ConversationFragment fragment = (ConversationFragment) getFragmentManager() - .findFragmentByTag("conversation"); - if (fragment != null) { - fragment.showNoPGPKeyDialog(false, - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, - int which) { - conversation - .setNextEncryption(Message.ENCRYPTION_NONE); - xmppConnectionService.databaseBackend - .updateConversation(conversation); - selectPresenceToAttachFile(attachmentChoice, Message.ENCRYPTION_NONE); - } - }); - } - } - } else { - showInstallPgpDialog(); - } - } else { - if (encryption != Message.ENCRYPTION_AXOLOTL || !trustKeysIfNeeded(REQUEST_TRUST_KEYS_MENU, attachmentChoice)) { - selectPresenceToAttachFile(attachmentChoice, encryption); - } - } - } - - @Override - 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); - } - } else { - attachFile(requestCode); - } - } else { - Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show(); - } - } - - public void startDownloadable(Message message) { - if (!hasStoragePermission(ConversationActivity.REQUEST_START_DOWNLOAD)) { - this.mPendingDownloadableMessage = message; - return; - } - Transferable transferable = message.getTransferable(); - if (transferable != null) { - if (!transferable.start()) { - Toast.makeText(this, R.string.not_connected_try_again, Toast.LENGTH_SHORT).show(); - } - } else if (message.treatAsDownloadable() != Message.Decision.NEVER) { - HttpDownloadConnection downloadConnection = HttpConnectionManager.createNewDownloadConnection(message, true); - if (null == downloadConnection) { - Toast.makeText(this, R.string.file_not_on_remote_host, Toast.LENGTH_LONG).show(); - } - } - } - - @Override - public boolean onOptionsItemSelected(final MenuItem item) { - if (item.getItemId() == android.R.id.home) { - showConversationsOverview(); - return true; - } else if (item.getItemId() == R.id.action_add) { - startActivity(new Intent(this, StartConversationActivity.class)); - return true; - } else if (getSelectedConversation() != null) { - switch (item.getItemId()) { - case R.id.action_attach_file: - attachFileDialog(); - break; - case R.id.action_archive: - this.endConversation(getSelectedConversation()); - break; - case R.id.action_contact_details: - switchToContactDetails(getSelectedConversation().getContact()); - 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; - case R.id.action_unmute: - unmuteConversation(getSelectedConversation()); - break; - case R.id.action_block: - BlockContactDialog.show(this, xmppConnectionService, getSelectedConversation()); - break; - case R.id.action_unblock: - BlockContactDialog.show(this, xmppConnectionService, getSelectedConversation()); - break; - default: - break; - } - return super.onOptionsItemSelected(item); - } else { - return super.onOptionsItemSelected(item); - } - } - - public void endConversation(Conversation conversation) { - endConversation(conversation, true, true); - } - - public void endConversation(Conversation conversation, boolean showOverview, boolean reinit) { - if (showOverview) { - showConversationsOverview(); - } - xmppConnectionService.archiveConversation(conversation); - if (reinit) { - if (conversationList.size() > 0) { - setSelectedConversation(conversationList.get(0)); - this.mConversationFragment.reInit(getSelectedConversation()); - } else { - setSelectedConversation(null); - if (mRedirected.compareAndSet(false, true)) { - Intent intent = new Intent(this, StartConversationActivity.class); - intent.putExtra("init", true); - startActivity(intent); - finish(); - } - } - } - } - - @SuppressLint("InflateParams") - protected void clearHistoryDialog(final Conversation conversation) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(getString(R.string.clear_conversation_history)); - View dialogView = getLayoutInflater().inflate( - R.layout.dialog_clear_history, null); - final CheckBox endConversationCheckBox = (CheckBox) dialogView - .findViewById(R.id.end_conversation_checkbox); - builder.setView(dialogView); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.setPositiveButton(getString(R.string.delete_messages), - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - ConversationActivity.this.xmppConnectionService.clearConversationHistory(conversation); - if (endConversationCheckBox.isChecked()) { - endConversation(conversation); - } else { - updateConversationList(); - ConversationActivity.this.mConversationFragment.updateMessages(); - } - } - }); - builder.create().show(); - } - - 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); - if (new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION).resolveActivity(getPackageManager()) == null) { - attachFilePopup.getMenu().findItem(R.id.attach_record_voice).setVisible(false); - } - if (new Intent("eu.siacs.conversations.location.request").resolveActivity(getPackageManager()) == null) { - attachFilePopup.getMenu().findItem(R.id.attach_location).setVisible(false); - } - attachFilePopup.setOnMenuItemClickListener(new OnMenuItemClickListener() { - - @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; - case R.id.attach_choose_file: - attachFile(ATTACHMENT_CHOICE_CHOOSE_FILE); - break; - case R.id.attach_record_voice: - attachFile(ATTACHMENT_CHOICE_RECORD_VOICE); - break; - case R.id.attach_location: - attachFile(ATTACHMENT_CHOICE_LOCATION); - break; - } - return false; - } - }); - attachFilePopup.show(); - } - - 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()); - intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().toBareJid().toString()); - switch (menuItem.getItemId()) { - case R.id.scan_fingerprint: - intent.putExtra("mode", VerifyOTRActivity.MODE_SCAN_FINGERPRINT); - break; - case R.id.ask_question: - intent.putExtra("mode", VerifyOTRActivity.MODE_ASK_QUESTION); - break; - case R.id.manual_verification: - intent.putExtra("mode", VerifyOTRActivity.MODE_MANUAL_VERIFICATION); - break; - } - startActivity(intent); - return true; - } - }); - popup.show(); - } - - 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() - .findFragmentByTag("conversation"); - if (fragment != null) { - popup.setOnMenuItemClickListener(new OnMenuItemClickListener() { - - @Override - public boolean onMenuItemClick(MenuItem item) { - switch (item.getItemId()) { - 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()) { - if (conversation.getAccount().getPgpSignature() != null) { - conversation.setNextEncryption(Message.ENCRYPTION_PGP); - item.setChecked(true); - } else { - announcePgp(conversation.getAccount(), conversation); - } - } else { - showInstallPgpDialog(); - } - break; - case R.id.encryption_choice_axolotl: - Log.d(Config.LOGTAG, AxolotlServiceImpl.getLogprefix(conversation.getAccount()) - + "Enabled axolotl for Contact " + conversation.getContact().getJid()); - conversation.setNextEncryption(Message.ENCRYPTION_AXOLOTL); - item.setChecked(true); - break; - default: - conversation.setNextEncryption(Message.ENCRYPTION_NONE); - break; - } - xmppConnectionService.databaseBackend.updateConversation(conversation); - fragment.updateChatMsgHint(); - invalidateOptionsMenu(); - refreshUi(); - return true; - } - }); - popup.inflate(R.menu.encryption_choices); - MenuItem otr = popup.getMenu().findItem(R.id.encryption_choice_otr); - MenuItem none = popup.getMenu().findItem(R.id.encryption_choice_none); - MenuItem pgp = popup.getMenu().findItem(R.id.encryption_choice_pgp); - MenuItem axolotl = popup.getMenu().findItem(R.id.encryption_choice_axolotl); - pgp.setVisible(Config.supportOpenPgp()); - none.setVisible(Config.supportUnencrypted() || conversation.getMode() == Conversation.MODE_MULTI); - otr.setVisible(Config.supportOtr()); - axolotl.setVisible(Config.supportOmemo()); - if (conversation.getMode() == Conversation.MODE_MULTI) { - otr.setVisible(false); - } - if (!conversation.getAccount().getAxolotlService().isConversationAxolotlCapable(conversation)) { - axolotl.setEnabled(false); - } - switch (conversation.getNextEncryption()) { - case Message.ENCRYPTION_NONE: - none.setChecked(true); - break; - case Message.ENCRYPTION_OTR: - otr.setChecked(true); - break; - case Message.ENCRYPTION_PGP: - pgp.setChecked(true); - break; - case Message.ENCRYPTION_AXOLOTL: - axolotl.setChecked(true); - break; - default: - none.setChecked(true); - break; - } - popup.show(); - } - } - - protected void muteConversationDialog(final Conversation conversation) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.disable_notifications); - final int[] durations = getResources().getIntArray(R.array.mute_options_durations); - builder.setItems(R.array.mute_options_descriptions, - new OnClickListener() { - - @Override - public void onClick(final DialogInterface dialog, final int which) { - final long till; - if (durations[which] == -1) { - till = Long.MAX_VALUE; - } else { - till = System.currentTimeMillis() + (durations[which] * 1000); - } - conversation.setMutedTill(till); - ConversationActivity.this.xmppConnectionService.databaseBackend - .updateConversation(conversation); - updateConversationList(); - ConversationActivity.this.mConversationFragment.updateMessages(); - invalidateOptionsMenu(); - } - }); - builder.create().show(); - } - - public void unmuteConversation(final Conversation conversation) { - conversation.setMutedTill(0); - this.xmppConnectionService.databaseBackend.updateConversation(conversation); - updateConversationList(); - ConversationActivity.this.mConversationFragment.updateMessages(); - invalidateOptionsMenu(); - } - - @Override - public void onBackPressed() { - if (!isConversationsOverviewVisable()) { - showConversationsOverview(); - } else { - moveTaskToBack(true); - } - } - - @Override - public boolean onKeyUp(int key, KeyEvent event) { - int rotation = getWindowManager().getDefaultDisplay().getRotation(); - final int upKey; - final int downKey; - switch (rotation) { - 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; - default: - upKey = KeyEvent.KEYCODE_DPAD_UP; - downKey = KeyEvent.KEYCODE_DPAD_DOWN; - } - final boolean modifier = event.isCtrlPressed() || event.isAltPressed(); - if (modifier && key == KeyEvent.KEYCODE_TAB && isConversationsOverviewHideable()) { - toggleConversationsOverview(); - return true; - } else if (modifier && key == downKey) { - if (isConversationsOverviewHideable() && !isConversationsOverviewVisable()) { - showConversationsOverview(); - ; - } - return selectDownConversation(); - } else if (modifier && key == upKey) { - if (isConversationsOverviewHideable() && !isConversationsOverviewVisable()) { - showConversationsOverview(); - } - 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); - } else { - return super.onKeyUp(key, event); - } - } - - private void toggleConversationsOverview() { - if (isConversationsOverviewVisable()) { - hideConversationsOverview(); - if (mConversationFragment != null) { - mConversationFragment.setFocusOnInputField(); - } - } else { - showConversationsOverview(); - } - } - - private boolean selectUpConversation() { - if (this.mSelectedConversation != null) { - int index = this.conversationList.indexOf(this.mSelectedConversation); - if (index > 0) { - return openConversationByIndex(index - 1); - } - } - return false; - } - - private boolean selectDownConversation() { - if (this.mSelectedConversation != null) { - int index = this.conversationList.indexOf(this.mSelectedConversation); - if (index != -1 && index < this.conversationList.size() - 1) { - return openConversationByIndex(index + 1); - } - } - return false; - } - - private boolean openConversationByIndex(int index) { - try { - this.conversationWasSelectedByKeyboard = true; - 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; - } - } - - @Override - protected void onNewIntent(final Intent intent) { - if (xmppConnectionServiceBound) { - if (intent != null && VIEW_CONVERSATION.equals(intent.getType())) { - handleViewConversationIntent(intent); - setIntent(new Intent()); - } - } else { - setIntent(intent); - } - } - - @Override - public void onStart() { - super.onStart(); - this.mRedirected.set(false); - if (this.xmppConnectionServiceBound) { - this.onBackendConnected(); - } - if (conversationList.size() >= 1) { - this.onConversationUpdate(); - } - } - - @Override - public void onPause() { - listView.discardUndo(); - super.onPause(); - this.mActivityPaused = true; - if (this.xmppConnectionServiceBound) { - this.xmppConnectionService.getNotificationService().setIsInForeground(false); - } - } - - @Override - public void onResume() { - super.onResume(); - final int theme = findTheme(); - final boolean usingEnterKey = ConversationsPlusPreferences.displayEnterKey(); - if (this.mTheme != theme || usingEnterKey != mUsingEnterKey) { - recreate(); - } - this.mActivityPaused = false; - if (this.xmppConnectionServiceBound) { - this.xmppConnectionService.getNotificationService().setIsInForeground(true); - } - - if (!isConversationsOverviewVisable() || !isConversationsOverviewHideable()) { - sendReadMarkerIfNecessary(getSelectedConversation()); - } - - } - - @Override - public void onSaveInstanceState(final Bundle savedInstanceState) { - Conversation conversation = getSelectedConversation(); - if (conversation != null) { - savedInstanceState.putString(STATE_OPEN_CONVERSATION, conversation.getUuid()); - } else { - savedInstanceState.remove(STATE_OPEN_CONVERSATION); - } - savedInstanceState.putBoolean(STATE_PANEL_OPEN, isConversationsOverviewVisable()); - if (this.mPendingImageUris.size() >= 1) { - savedInstanceState.putString(STATE_PENDING_URI, this.mPendingImageUris.get(0).toString()); - } else { - savedInstanceState.remove(STATE_PENDING_URI); - } - super.onSaveInstanceState(savedInstanceState); - } - - private void clearPending() { - mPendingImageUris.clear(); - mPendingFileUris.clear(); - mPendingGeoUri = null; - mPostponedActivityResult = null; - } - - @Override - void onBackendConnected() { - this.xmppConnectionService.getNotificationService().setIsInForeground(true); - updateConversationList(); - - if (mPendingConferenceInvite != null) { - mPendingConferenceInvite.execute(this); - mPendingConferenceInvite = null; - } - - if (xmppConnectionService.getAccounts().size() == 0) { - if (mRedirected.compareAndSet(false, true)) { - if (Config.X509_VERIFICATION) { - startActivity(new Intent(this, ManageAccountActivity.class)); - } else { - startActivity(new Intent(this, EditAccountActivity.class)); - } - finish(); - } - } else if (conversationList.size() <= 0) { - if (mRedirected.compareAndSet(false, true)) { - Intent intent = new Intent(this, StartConversationActivity.class); - intent.putExtra("init", true); - startActivity(intent); - finish(); - } - } else if (getIntent() != null && VIEW_CONVERSATION.equals(getIntent().getType())) { - clearPending(); - handleViewConversationIntent(getIntent()); - } else if (selectConversationByUuid(mOpenConverstaion)) { - if (mPanelOpen) { - showConversationsOverview(); - } else { - if (isConversationsOverviewHideable()) { - openConversation(); - updateActionBarTitle(true); - } - } - this.mConversationFragment.reInit(getSelectedConversation()); - mOpenConverstaion = null; - } else if (getSelectedConversation() == null) { - showConversationsOverview(); - clearPending(); - setSelectedConversation(conversationList.get(0)); - this.mConversationFragment.reInit(getSelectedConversation()); - } else { - this.mConversationFragment.messagesView.invalidateViews(); - this.mConversationFragment.setupIme(); - } - - if (this.mPostponedActivityResult != null) { - this.onActivityResult(mPostponedActivityResult.first, RESULT_OK, mPostponedActivityResult.second); - } - - if (!forbidProcessingPendings) { - for (Iterator<Uri> i = mPendingImageUris.iterator(); i.hasNext(); i.remove()) { - Uri foo = i.next(); - attachImageToConversation(getSelectedConversation(), foo); - } - - for (Iterator<Uri> i = mPendingFileUris.iterator(); i.hasNext(); i.remove()) { - attachFileToConversation(getSelectedConversation(), i.next()); - } - - if (mPendingGeoUri != null) { - attachLocationToConversation(getSelectedConversation(), mPendingGeoUri); - mPendingGeoUri = null; - } - } - forbidProcessingPendings = false; - - if (!ExceptionHelper.checkForCrash(this, this.xmppConnectionService)) { - openBatteryOptimizationDialogIfNeeded(); - } - setIntent(new Intent()); - } - - private void handleViewConversationIntent(final Intent intent) { - final String uuid = intent.getStringExtra(CONVERSATION); - final String downloadUuid = intent.getStringExtra(MESSAGE); - final String text = intent.getStringExtra(TEXT); - final String nick = intent.getStringExtra(NICK); - final boolean pm = intent.getBooleanExtra(PRIVATE_MESSAGE, false); - if (selectConversationByUuid(uuid)) { - this.mConversationFragment.reInit(getSelectedConversation()); - if (nick != null) { - if (pm) { - Jid jid = getSelectedConversation().getJid(); - try { - Jid next = Jid.fromParts(jid.getLocalpart(), jid.getDomainpart(), nick); - this.mConversationFragment.privateMessageWith(next); - } catch (final InvalidJidException ignored) { - //do nothing - } - } else { - this.mConversationFragment.highlightInConference(nick); - } - } else { - this.mConversationFragment.appendText(text); - } - hideConversationsOverview(); - openConversation(); - if (mContentView instanceof SlidingPaneLayout) { - updateActionBarTitle(true); //fixes bug where slp isn't properly closed yet - } - if (downloadUuid != null) { - final Message message = mSelectedConversation.findMessageWithFileAndUuid(downloadUuid); - if (message != null) { - startDownloadable(message); - } - } - } - } - - private boolean selectConversationByUuid(String uuid) { - if (uuid == null) { - return false; - } - for (Conversation aConversationList : conversationList) { - if (aConversationList.getUuid().equals(uuid)) { - setSelectedConversation(aConversationList); - return true; - } - } - return false; - } - - @Override - protected void unregisterListeners() { - super.unregisterListeners(); - xmppConnectionService.getNotificationService().setOpenConversation(null); - } - - @SuppressLint("NewApi") - private static List<Uri> extractUriFromIntent(final Intent intent) { - List<Uri> uris = new ArrayList<>(); - if (intent == null) { - return uris; - } - Uri uri = intent.getData(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && uri == null) { - ClipData clipData = intent.getClipData(); - for (int i = 0; i < clipData.getItemCount(); ++i) { - uris.add(clipData.getItemAt(i).getUri()); - } - } else { - uris.add(uri); - } - return uris; - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, final Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK) { - if (requestCode == REQUEST_DECRYPT_PGP) { - mConversationFragment.onActivityResult(requestCode, resultCode, data); - } else if (requestCode == REQUEST_CHOOSE_PGP_ID) { - // the user chose OpenPGP for encryption and selected his key in the PGP provider - if (xmppConnectionServiceBound) { - if (data.getExtras().containsKey(OpenPgpApi.EXTRA_SIGN_KEY_ID)) { - // associate selected PGP keyId with the account - mSelectedConversation.getAccount().setPgpSignId(data.getExtras().getLong(OpenPgpApi.EXTRA_SIGN_KEY_ID)); - // we need to announce the key as described in XEP-027 - announcePgp(mSelectedConversation.getAccount(), null); - } else { - choosePgpSignId(mSelectedConversation.getAccount()); - } - this.mPostponedActivityResult = null; - } else { - this.mPostponedActivityResult = new Pair<>(requestCode, data); - } - } else if (requestCode == REQUEST_ANNOUNCE_PGP) { - if (xmppConnectionServiceBound) { - announcePgp(mSelectedConversation.getAccount(), mSelectedConversation); - this.mPostponedActivityResult = null; - } else { - this.mPostponedActivityResult = new Pair<>(requestCode, data); - } - } else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_IMAGE) { - mPendingImageUris.clear(); - mPendingImageUris.addAll(extractUriFromIntent(data)); - if (xmppConnectionServiceBound) { - for (Iterator<Uri> i = mPendingImageUris.iterator(); i.hasNext(); i.remove()) { - attachImageToConversation(getSelectedConversation(), i.next()); - } - } - } else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_FILE || requestCode == ATTACHMENT_CHOICE_RECORD_VOICE) { - final List<Uri> uris = extractUriFromIntent(data); - 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()) { - attachFileToConversation(c, i.next()); - } - } - } - }; - if (c.getMode() == Conversation.MODE_MULTI - || FileUtils.allFilesUnderSize(this, uris, getMaxHttpUploadSize(c)) - || c.getNextEncryption() == Message.ENCRYPTION_OTR) { - callback.onPresenceSelected(); - } else { - selectPresence(c, callback); - } - } else if (requestCode == ATTACHMENT_CHOICE_TAKE_PHOTO) { - if (mPendingImageUris.size() == 1) { - Uri uri = mPendingImageUris.get(0); - if (xmppConnectionServiceBound) { - attachImageToConversation(getSelectedConversation(), uri); - mPendingImageUris.clear(); - } - Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - intent.setData(uri); - sendBroadcast(intent); - } else { - mPendingImageUris.clear(); - } - } else if (requestCode == ATTACHMENT_CHOICE_LOCATION) { - double latitude = data.getDoubleExtra("latitude", 0); - double longitude = data.getDoubleExtra("longitude", 0); - this.mPendingGeoUri = Uri.parse("geo:" + String.valueOf(latitude) + "," + String.valueOf(longitude)); - if (xmppConnectionServiceBound) { - attachLocationToConversation(getSelectedConversation(), mPendingGeoUri); - this.mPendingGeoUri = null; - } - } else if (requestCode == REQUEST_TRUST_KEYS_TEXT || requestCode == REQUEST_TRUST_KEYS_MENU) { - this.forbidProcessingPendings = !xmppConnectionServiceBound; - if (xmppConnectionServiceBound) { - mConversationFragment.onActivityResult(requestCode, resultCode, data); - this.mPostponedActivityResult = null; - } else { - this.mPostponedActivityResult = new Pair<>(requestCode, data); - } - - } - } else { - mPendingImageUris.clear(); - mPendingFileUris.clear(); - if (requestCode == ConversationActivity.REQUEST_DECRYPT_PGP) { - mConversationFragment.onActivityResult(requestCode, resultCode, data); - } - if (requestCode == REQUEST_BATTERY_OP) { - // Never Ask For Battery Optimizations Again - ConversationsPlusPreferences.commitShowBatteryOptimization(false); - } - } - } - - private long getMaxHttpUploadSize(Conversation conversation) { - return conversation.getAccount().getXmppConnection().getFeatures().getMaxHttpUploadSize(); - } - - private void openBatteryOptimizationDialogIfNeeded() { - if (hasAccountWithoutPush() - && isOptimizingBattery() - && ConversationsPlusPreferences.showBatteryOptimization()) { - 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); - startActivityForResult(intent, REQUEST_BATTERY_OP); - } - }); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - builder.setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - ConversationsPlusPreferences.commitShowBatteryOptimization(false); - } - }); - } - builder.create().show(); - } - } - - private boolean hasAccountWithoutPush() { - for(Account account : xmppConnectionService.getAccounts()) { - if (account.getStatus() != Account.State.DISABLED - && !xmppConnectionService.getPushManagementService().available(account)) { - return true; - } - } - return false; - } - - private void attachLocationToConversation(Conversation conversation, Uri uri) { - if (conversation == null) { - return; - } - ConversationUtil.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) { - - } - }); - } - - private void attachFileToConversation(Conversation conversation, Uri uri) { - if (conversation == null) { - return; - } - final Toast prepareFileToast = Toast.makeText(getApplicationContext(),getText(R.string.preparing_file), Toast.LENGTH_LONG); - prepareFileToast.show(); - ConversationUtil.attachFileToConversation(conversation, uri, new UiCallback<Message>() { - @Override - public void success(Message message) { - hidePrepareFileToast(prepareFileToast); - xmppConnectionService.sendMessage(message); - } - - @Override - public void error(int errorCode, Message message) { - hidePrepareFileToast(prepareFileToast); - displayErrorDialog(errorCode); - } - - @Override - public void userInputRequried(PendingIntent pi, Message message) { - - } - }); - } - - private void attachImageToConversation(Conversation conversation, Uri uri) { - if (conversation == null) { - return; - } - ResizePictureUserDecisionListener userDecisionListener = new ResizePictureUserDecisionListener(this, conversation, uri, xmppConnectionService); - UserDecisionDialog userDecisionDialog = new UserDecisionDialog(this, R.string.userdecision_question_resize_picture, userDecisionListener); - userDecisionDialog.decide(ConversationsPlusPreferences.resizePicture()); - } - - private void hidePrepareFileToast(final Toast prepareFileToast) { - if (prepareFileToast != null) { - runOnUiThread(new Runnable() { - - @Override - public void run() { - prepareFileToast.cancel(); - } - }); - } - } - - public void updateConversationList() { - xmppConnectionService - .populateWithOrderedConversations(conversationList); - if (swipedConversation != null) { - if (swipedConversation.isRead()) { - conversationList.remove(swipedConversation); - } else { - listView.discardUndo(); - } - } - listAdapter.notifyDataSetChanged(); - } - - public void runIntent(PendingIntent pi, int requestCode) { - try { - this.startIntentSenderForResult(pi.getIntentSender(), requestCode, - null, 0, 0, 0); - } catch (final SendIntentException ignored) { - } - } - - public void encryptTextMessage(Message message) { - xmppConnectionService.getPgpEngine().encrypt(message, - new UiCallback<Message>() { - - @Override - public void userInputRequried(PendingIntent pi, - Message message) { - ConversationActivity.this.runIntent(pi, - ConversationActivity.REQUEST_SEND_MESSAGE); - } - - @Override - public void success(Message message) { - message.setEncryption(Message.ENCRYPTION_DECRYPTED); - xmppConnectionService.sendMessage(message); - } - - @Override - public void error(int error, Message message) { - - } - }); - } - - protected boolean trustKeysIfNeeded(int requestCode) { - return trustKeysIfNeeded(requestCode, ATTACHMENT_CHOICE_INVALID); - } - - protected boolean trustKeysIfNeeded(int requestCode, int attachmentChoice) { - AxolotlService axolotlService = mSelectedConversation.getAccount().getAxolotlService(); - final List<Jid> targets = axolotlService.getCryptoTargets(mSelectedConversation); - boolean hasUnaccepted = !mSelectedConversation.getAcceptedCryptoTargets().containsAll(targets); - boolean hasUndecidedOwn = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED).isEmpty(); - boolean hasUndecidedContacts = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, targets).isEmpty(); - boolean hasPendingKeys = !axolotlService.findDevicesWithoutSession(mSelectedConversation).isEmpty(); - boolean hasNoTrustedKeys = axolotlService.anyTargetHasNoTrustedKeys(targets); - if(hasUndecidedOwn || hasUndecidedContacts || hasPendingKeys || hasNoTrustedKeys || hasUnaccepted) { - axolotlService.createSessionsIfNeeded(mSelectedConversation); - Intent intent = new Intent(getApplicationContext(), TrustKeysActivity.class); - String[] contacts = new String[targets.size()]; - for(int i = 0; i < contacts.length; ++i) { - contacts[i] = targets.get(i).toString(); - } - intent.putExtra("contacts", contacts); - intent.putExtra(EXTRA_ACCOUNT, mSelectedConversation.getAccount().getJid().toBareJid().toString()); - intent.putExtra("choice", attachmentChoice); - intent.putExtra("conversation",mSelectedConversation.getUuid()); - startActivityForResult(intent, requestCode); - return true; - } else { - return false; - } - } - - @Override - protected void refreshUiReal() { - updateConversationList(); - if (conversationList.size() > 0) { - if (!this.mConversationFragment.isAdded()) { - Log.d(Config.LOGTAG,"fragment NOT added to activity. detached="+Boolean.toString(mConversationFragment.isDetached())); - } - ConversationActivity.this.mConversationFragment.updateMessages(); - updateActionBarTitle(); - invalidateOptionsMenu(); - } else { - Log.d(Config.LOGTAG,"not updating conversations fragment because conversations list size was 0"); - } - } - - @Override - public void onAccountUpdate() { - this.refreshUi(); - } - - @Override - public void onConversationUpdate() { - this.refreshUi(); - } - - @Override - public void onRosterUpdate() { - this.refreshUi(); - } - - @Override - public void OnUpdateBlocklist(Status status) { - this.refreshUi(); - } - - public void unblockConversation(final Blockable conversation) { - xmppConnectionService.sendUnblockRequest(conversation); - } - - @Override - public void onShowErrorToast(final int resId) { - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(ConversationActivity.this,resId,Toast.LENGTH_SHORT).show(); - } - }); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ConversationFragment.java b/src/main/java/de/thedevstack/conversationsplus/ui/ConversationFragment.java deleted file mode 100644 index 157e6dc3..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ConversationFragment.java +++ /dev/null @@ -1,1383 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Fragment; -import android.app.PendingIntent; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentSender.SendIntentException; -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.text.InputType; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodManager; -import android.widget.AdapterView; -import android.widget.AdapterView.AdapterContextMenuInfo; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.PopupWindow; -import android.widget.RelativeLayout; -import android.widget.TextView; -import android.widget.TextView.OnEditorActionListener; -import android.widget.Toast; - -import com.orangegangsters.github.swipyrefreshlayout.library.SwipyRefreshLayout; - -import net.java.otr4j.session.SessionStatus; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.thedevstack.conversationsplus.http.HttpConnectionManager; -import de.thedevstack.conversationsplus.http.HttpDownloadConnection; -import de.thedevstack.conversationsplus.services.filetransfer.http.delete.DeleteRemoteFileService; -import de.thedevstack.conversationsplus.ui.dialogs.SimpleConfirmDialog; -import de.thedevstack.conversationsplus.ui.dialogs.MessageDetailsDialog; -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.crypto.axolotl.AxolotlService; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Contact; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.entities.DownloadableFile; -import de.thedevstack.conversationsplus.entities.Message; -import de.thedevstack.conversationsplus.entities.MucOptions; -import de.thedevstack.conversationsplus.entities.Presence; -import de.thedevstack.conversationsplus.entities.Transferable; -import de.thedevstack.conversationsplus.entities.TransferablePlaceholder; -import de.thedevstack.conversationsplus.persistance.FileBackend; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.ui.XmppActivity.OnPresenceSelected; -import de.thedevstack.conversationsplus.ui.XmppActivity.OnValueEdited; -import de.thedevstack.conversationsplus.ui.adapter.MessageAdapter; -import de.thedevstack.conversationsplus.ui.adapter.MessageAdapter.OnContactPictureClicked; -import de.thedevstack.conversationsplus.ui.adapter.MessageAdapter.OnContactPictureLongClicked; -import de.thedevstack.conversationsplus.ui.listeners.ConversationSwipeRefreshListener; -import de.thedevstack.conversationsplus.ui.listeners.DeleteFileCallback; -import de.thedevstack.conversationsplus.utils.AccountUtil; -import de.thedevstack.conversationsplus.utils.GeoHelper; -import de.thedevstack.conversationsplus.utils.MessageUtil; -import de.thedevstack.conversationsplus.utils.UIHelper; -import de.thedevstack.conversationsplus.xmpp.chatstate.ChatState; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; -import github.ankushsachdeva.emojicon.EmojiconGridView; -import github.ankushsachdeva.emojicon.EmojiconsPopup; -import github.ankushsachdeva.emojicon.emoji.Emojicon; - -public class ConversationFragment extends Fragment implements EditMessage.KeyboardListener { - - protected Conversation conversation; - private OnClickListener leaveMuc = new OnClickListener() { - - @Override - public void onClick(View v) { - activity.endConversation(conversation); - } - }; - private OnClickListener joinMuc = new OnClickListener() { - - @Override - public void onClick(View v) { - activity.xmppConnectionService.joinMuc(conversation); - } - }; - private OnClickListener enterPassword = new OnClickListener() { - - @Override - public void onClick(View v) { - MucOptions muc = conversation.getMucOptions(); - String password = muc.getPassword(); - if (password == null) { - password = ""; - } - activity.quickPasswordEdit(password, new OnValueEdited() { - - @Override - public void onValueEdited(String value) { - activity.xmppConnectionService.providePasswordForMuc( - conversation, value); - } - }); - } - }; - protected ListView messagesView; - protected SwipyRefreshLayout swipeLayout; - final protected List<Message> messageList = new ArrayList<>(); - protected MessageAdapter messageListAdapter; - private EditMessage mEditMessage; - private ImageButton mSendButton; - private ImageView mEmojButton; - private View mRootView; - private EmojiconsPopup mEmojPopup; - private RelativeLayout snackbar; - private TextView snackbarMessage; - private TextView snackbarAction; - private boolean messagesLoaded = true; - private Toast messageLoaderToast; - private final int KEYCHAIN_UNLOCK_NOT_REQUIRED = 0; - private final int KEYCHAIN_UNLOCK_REQUIRED = 1; - private final int KEYCHAIN_UNLOCK_PENDING = 2; - private int keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED; - protected OnClickListener clickToDecryptListener = new OnClickListener() { - - @Override - public void onClick(View v) { - if (keychainUnlock == KEYCHAIN_UNLOCK_REQUIRED - && activity.hasPgp() && !conversation.getAccount().getPgpDecryptionService().isRunning()) { - keychainUnlock = KEYCHAIN_UNLOCK_PENDING; - updateSnackBar(conversation); - Message message = getLastPgpDecryptableMessage(); - if (message != null) { - activity.xmppConnectionService.getPgpEngine().decrypt(message, new UiCallback<Message>() { - @Override - public void success(Message object) { - conversation.getAccount().getPgpDecryptionService().onKeychainUnlocked(); - keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED; - } - - @Override - public void error(int errorCode, Message object) { - keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED; - } - - @Override - public void userInputRequried(PendingIntent pi, Message object) { - try { - activity.startIntentSenderForResult(pi.getIntentSender(), - ConversationActivity.REQUEST_DECRYPT_PGP, null, 0, 0, 0); - } catch (SendIntentException e) { - keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED; - updatePgpMessages(); - } - } - }); - } - } else { - keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED; - updatePgpMessages(); - } - } - }; - protected OnClickListener clickToVerify = new OnClickListener() { - - @Override - public void onClick(View v) { - activity.verifyOtrSessionDialog(conversation, v); - } - }; - private OnEditorActionListener mEditorActionListener = new OnEditorActionListener() { - - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (actionId == EditorInfo.IME_ACTION_SEND) { - InputMethodManager imm = (InputMethodManager) v.getContext() - .getSystemService(Context.INPUT_METHOD_SERVICE); - if (imm.isFullscreenMode()) { - imm.hideSoftInputFromWindow(v.getWindowToken(), 0); - } - sendMessage(); - return true; - } else { - return false; - } - } - }; - private OnClickListener mSendButtonListener = new OnClickListener() { - - @Override - public void onClick(View v) { - Object tag = v.getTag(); - if (tag instanceof SendButtonAction) { - SendButtonAction action = (SendButtonAction) tag; - switch (action) { - case TAKE_PHOTO: - activity.attachFile(ConversationActivity.ATTACHMENT_CHOICE_TAKE_PHOTO); - break; - case SEND_LOCATION: - activity.attachFile(ConversationActivity.ATTACHMENT_CHOICE_LOCATION); - break; - case RECORD_VOICE: - activity.attachFile(ConversationActivity.ATTACHMENT_CHOICE_RECORD_VOICE); - break; - case CHOOSE_PICTURE: - activity.attachFile(ConversationActivity.ATTACHMENT_CHOICE_CHOOSE_IMAGE); - break; - case CANCEL: - if (conversation != null && conversation.getMode() == Conversation.MODE_MULTI) { - conversation.setNextCounterpart(null); - updateChatMsgHint(); - updateSendButton(); - } - break; - default: - sendMessage(); - } - } else { - sendMessage(); - } - } - }; - private OnClickListener clickToMuc = new OnClickListener() { - - @Override - public void onClick(View v) { - Intent intent = new Intent(getActivity(), ConferenceDetailsActivity.class); - intent.setAction(ConferenceDetailsActivity.ACTION_VIEW_MUC); - intent.putExtra("uuid", conversation.getUuid()); - startActivity(intent); - } - }; - private ConversationActivity activity; - private Message selectedMessage; - - public void setMessagesLoaded() { - this.messagesLoaded = true; - } - - private void sendMessage() { - final String body = mEditMessage.getText().toString(); - if (body.length() == 0 || this.conversation == null) { - return; - } - Message message = new Message(conversation, body, conversation.getNextEncryption()); - if (conversation.getMode() == Conversation.MODE_MULTI) { - if (conversation.getNextCounterpart() != null) { - message.setCounterpart(conversation.getNextCounterpart()); - message.setType(Message.TYPE_PRIVATE); - } - } - switch (conversation.getNextEncryption()) { - case Message.ENCRYPTION_OTR: - sendOtrMessage(message); - break; - case Message.ENCRYPTION_PGP: - sendPgpMessage(message); - break; - case Message.ENCRYPTION_AXOLOTL: - if(!activity.trustKeysIfNeeded(ConversationActivity.REQUEST_TRUST_KEYS_TEXT)) { - sendAxolotlMessage(message); - } - break; - default: - sendPlainTextMessage(message); - } - } - - public void updateChatMsgHint() { - final boolean multi = conversation.getMode() == Conversation.MODE_MULTI; - if (multi && conversation.getNextCounterpart() != null) { - this.mEditMessage.setHint(getString( - R.string.send_private_message_to, - conversation.getNextCounterpart().getResourcepart())); - } else if (multi && !conversation.getMucOptions().participating()) { - this.mEditMessage.setHint(R.string.you_are_not_participating); - } else { - switch (conversation.getNextEncryption()) { - case Message.ENCRYPTION_NONE: - mEditMessage - .setHint(getString(R.string.send_unencrypted_message)); - break; - case Message.ENCRYPTION_OTR: - mEditMessage.setHint(getString(R.string.send_otr_message)); - break; - case Message.ENCRYPTION_AXOLOTL: - AxolotlService axolotlService = conversation.getAccount().getAxolotlService(); - if (axolotlService != null && axolotlService.trustedSessionVerified(conversation)) { - mEditMessage.setHint(getString(R.string.send_omemo_x509_message)); - } else { - mEditMessage.setHint(getString(R.string.send_omemo_message)); - } - break; - case Message.ENCRYPTION_PGP: - mEditMessage.setHint(getString(R.string.send_pgp_message)); - break; - default: - break; - } - getActivity().invalidateOptionsMenu(); - } - } - - public void setupIme() { - if (activity == null) { - return; - } else if (ConversationsPlusPreferences.displayEnterKey() && ConversationsPlusPreferences.enterIsSend()) { - mEditMessage.setInputType(mEditMessage.getInputType() & (~InputType.TYPE_TEXT_FLAG_MULTI_LINE)); - mEditMessage.setInputType(mEditMessage.getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE)); - } else if (ConversationsPlusPreferences.displayEnterKey()) { - mEditMessage.setInputType(mEditMessage.getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); - mEditMessage.setInputType(mEditMessage.getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE)); - } else { - mEditMessage.setInputType(mEditMessage.getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); - mEditMessage.setInputType(mEditMessage.getInputType() | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE); - } - } - - @Override - public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - final View view = inflater.inflate(R.layout.fragment_conversation, container, false); - view.setOnClickListener(null); - mEditMessage = (EditMessage) view.findViewById(R.id.textinput); - mEditMessage.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - if (activity != null) { - activity.hideConversationsOverview(); - } - } - }); - mEditMessage.setOnEditorActionListener(mEditorActionListener); - - // Start of emojicon - mEmojButton = (ImageView) view.findViewById(R.id.emoji_btn); - mRootView = view.findViewById(R.id.textsend); - - // Give the topmost view of your activity layout hierarchy. This will be used to measure soft keyboard height - mEmojPopup = new EmojiconsPopup(mRootView, this.getActivity()); - - //Will automatically set size according to the soft keyboard size - mEmojPopup.setSizeForSoftKeyboard(); - - //If the emoji popup is dismissed, change emojiButton to smiley icon - mEmojPopup.setOnDismissListener(new PopupWindow.OnDismissListener() { - - @Override - public void onDismiss() { - changeEmojiKeyboardIcon(mEmojButton, R.drawable.smiley); - } - }); - - //If the text keyboard closes, also dismiss the emoji popup - mEmojPopup.setOnSoftKeyboardOpenCloseListener(new EmojiconsPopup.OnSoftKeyboardOpenCloseListener() { - - @Override - public void onKeyboardOpen(int keyBoardHeight) { - - } - - @Override - public void onKeyboardClose() { - if (mEmojPopup.isShowing()) - mEmojPopup.dismiss(); - } - }); - - //On emoji clicked, add it to edittext - mEmojPopup.setOnEmojiconClickedListener(new EmojiconGridView.OnEmojiconClickedListener() { - - @Override - public void onEmojiconClicked(Emojicon emojicon) { - if (mEditMessage == null || emojicon == null) { - return; - } - - int start = mEditMessage.getSelectionStart(); - int end = mEditMessage.getSelectionEnd(); - if (start < 0) { - mEditMessage.append(emojicon.getEmoji()); - } else { - mEditMessage.getText().replace(Math.min(start, end), - Math.max(start, end), emojicon.getEmoji(), 0, - emojicon.getEmoji().length()); - } - } - }); - - //On backspace clicked, emulate the KEYCODE_DEL key event - mEmojPopup.setOnEmojiconBackspaceClickedListener(new EmojiconsPopup.OnEmojiconBackspaceClickedListener() { - - @Override - public void onEmojiconBackspaceClicked(View v) { - KeyEvent event = new KeyEvent( - 0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0, 0, KeyEvent.KEYCODE_ENDCALL); - mEditMessage.dispatchKeyEvent(event); - } - }); - - // To toggle between text keyboard and emoji keyboard keyboard(Popup) - mEmojButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - - //If popup is not showing => emoji keyboard is not visible, we need to show it - if(!mEmojPopup.isShowing()){ - - //If keyboard is visible, simply show the emoji popup - if(mEmojPopup.isKeyBoardOpen()){ - mEmojPopup.showAtBottom(); - changeEmojiKeyboardIcon(mEmojButton, R.drawable.ic_action_keyboard); - } - - //else, open the text keyboard first and immediately after that show the emoji popup - else{ - mEditMessage.setFocusableInTouchMode(true); - mEditMessage.requestFocus(); - mEmojPopup.showAtBottomPending(); - final InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); - inputMethodManager.showSoftInput(mEditMessage, InputMethodManager.SHOW_IMPLICIT); - changeEmojiKeyboardIcon(mEmojButton, R.drawable.ic_action_keyboard); - } - } - - //If popup is showing, simply dismiss it to show the undelying text keyboard - else{ - mEmojPopup.dismiss(); - } - } - }); - - // End of emojicon - - mSendButton = (ImageButton) view.findViewById(R.id.textSendButton); - mSendButton.setOnClickListener(this.mSendButtonListener); - - snackbar = (RelativeLayout) view.findViewById(R.id.snackbar); - snackbarMessage = (TextView) view.findViewById(R.id.snackbar_message); - snackbarAction = (TextView) view.findViewById(R.id.snackbar_action); - - messagesView = (ListView) view.findViewById(R.id.messages_view); - messagesView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL); - messageListAdapter = new MessageAdapter((ConversationActivity) getActivity(), this.messageList); - messageListAdapter.setOnContactPictureClicked(new OnContactPictureClicked() { - - @Override - public void onContactPictureClicked(Message message) { - if (message.getStatus() <= Message.STATUS_RECEIVED) { - if (message.getConversation().getMode() == Conversation.MODE_MULTI) { - if (message.getCounterpart() != null) { - String user = message.getCounterpart().isBareJid() ? message.getCounterpart().toString() : message.getCounterpart().getResourcepart(); - if (!message.getConversation().getMucOptions().isUserInRoom(user)) { - Toast.makeText(activity,activity.getString(R.string.user_has_left_conference,user),Toast.LENGTH_SHORT).show(); - } - highlightInConference(user); - } - } else { - activity.switchToContactDetails(message.getContact(), message.getFingerprint()); - } - } else { - Account account = message.getConversation().getAccount(); - Intent intent = new Intent(activity, EditAccountActivity.class); - intent.putExtra("jid", account.getJid().toBareJid().toString()); - intent.putExtra("fingerprint", message.getFingerprint()); - startActivity(intent); - } - } - }); - messageListAdapter - .setOnContactPictureLongClicked(new OnContactPictureLongClicked() { - - @Override - public void onContactPictureLongClicked(Message message) { - if (message.getStatus() <= Message.STATUS_RECEIVED) { - if (message.getConversation().getMode() == Conversation.MODE_MULTI) { - if (message.getCounterpart() != null) { - String user = message.getCounterpart().getResourcepart(); - if (user != null) { - if (message.getConversation().getMucOptions().isUserInRoom(user)) { - privateMessageWith(message.getCounterpart()); - } else { - Toast.makeText(activity, activity.getString(R.string.user_has_left_conference, user), Toast.LENGTH_SHORT).show(); - } - } - } - } - } else { - activity.showQrCode(); - } - } - }); - messagesView.setAdapter(messageListAdapter); - - registerForContextMenu(messagesView); - - // Start of swipe refresh - // New Swipe refresh - swipeLayout = (SwipyRefreshLayout) view.findViewById(R.id.swipe_refresh_container); - swipeLayout.setOnRefreshListener(new ConversationSwipeRefreshListener(messageList, swipeLayout, this, messagesView, messageListAdapter)); - // End of swipe refresh - - return view; - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { - synchronized (this.messageList) { - super.onCreateContextMenu(menu, v, menuInfo); - AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo; - this.selectedMessage = this.messageList.get(acmi.position); - populateContextMenu(menu); - } - } - - private void populateContextMenu(ContextMenu menu) { - final Message m = this.selectedMessage; - final Transferable t = m.getTransferable(); - if (m.getType() != Message.TYPE_STATUS) { - final boolean treatAsFile = m.getType() != Message.TYPE_TEXT - && m.getType() != Message.TYPE_PRIVATE - && t == null; - activity.getMenuInflater().inflate(R.menu.message_context, menu); - menu.setHeaderTitle(R.string.message_options); - MenuItem copyText = menu.findItem(R.id.copy_text); - MenuItem retryDecryption = menu.findItem(R.id.retry_decryption); - MenuItem shareWith = menu.findItem(R.id.share_with); - MenuItem sendAgain = menu.findItem(R.id.send_again); - MenuItem copyUrl = menu.findItem(R.id.copy_url); - MenuItem downloadFile = menu.findItem(R.id.download_file); - MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission); - MenuItem deleteFile = menu.findItem(R.id.delete_file); - if (!treatAsFile - && !GeoHelper.isGeoUri(m.getBody()) - && m.treatAsDownloadable() != Message.Decision.MUST) { - copyText.setVisible(true); - } - if (m.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { - retryDecryption.setVisible(true); - } - if (treatAsFile || (GeoHelper.isGeoUri(m.getBody()))) { - shareWith.setVisible(true); - } - if (m.getStatus() == Message.STATUS_SEND_FAILED) { - sendAgain.setVisible(true); - } - if (m.hasFileOnRemoteHost() - || GeoHelper.isGeoUri(m.getBody()) - || m.treatAsDownloadable() == Message.Decision.MUST - || (t != null && t instanceof HttpDownloadConnection)) { - copyUrl.setVisible(true); - } - if ((m.getType() == Message.TYPE_TEXT && t == null && m.treatAsDownloadable() != Message.Decision.NEVER) - || (t instanceof TransferablePlaceholder && m.hasFileOnRemoteHost())){ - downloadFile.setVisible(true); - downloadFile.setTitle(activity.getString(R.string.download_x_file,UIHelper.getFileDescriptionString(activity, m))); - } - if ((t != null && !(t instanceof TransferablePlaceholder)) - || (m.isFileOrImage() && (m.getStatus() == Message.STATUS_WAITING - || m.getStatus() == Message.STATUS_OFFERED))) { - cancelTransmission.setVisible(true); - } - if (treatAsFile) { - deleteFile.setVisible(true); - deleteFile.setTitle(activity.getString(R.string.delete_x_file,UIHelper.getFileDescriptionString(activity, m))); - } - if (m.isHttpUploaded() && MessageUtil.isMessageSent(m) && AccountUtil.isFileTransferHttpAvailable(m.getConversation().getAccount())) { - MenuItem deleteRemoteFile = menu.findItem(R.id.msg_ctx_menu_delete_remote_file); - deleteRemoteFile.setVisible(true); - } - } - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.msg_ctx_menu_delete_remote_file: - new SimpleConfirmDialog(getActivity(), R.string.cplus_are_you_sure, new DeleteRemoteFileService(selectedMessage)).show(); - return true; - case R.id.msg_ctx_mnu_details: - new MessageDetailsDialog(getActivity(), selectedMessage).show(); - return true; - case R.id.share_with: - shareWith(selectedMessage); - return true; - case R.id.copy_text: - copyText(selectedMessage); - return true; - case R.id.send_again: - resendMessage(selectedMessage); - return true; - case R.id.copy_url: - copyUrl(selectedMessage); - return true; - case R.id.download_file: - downloadFile(selectedMessage); - return true; - case R.id.cancel_transmission: - cancelTransmission(selectedMessage); - return true; - case R.id.retry_decryption: - retryDecryption(selectedMessage); - return true; - case R.id.delete_file: - new SimpleConfirmDialog(getActivity(), R.string.cplus_are_you_sure, new DeleteFileCallback(selectedMessage)).show(); - return true; - default: - return super.onContextItemSelected(item); - } - } - - private void shareWith(Message message) { - Intent shareIntent = new Intent(); - shareIntent.setAction(Intent.ACTION_SEND); - if (GeoHelper.isGeoUri(message.getBody())) { - shareIntent.putExtra(Intent.EXTRA_TEXT, message.getBody()); - shareIntent.setType("text/plain"); - } else { - shareIntent.putExtra(Intent.EXTRA_STREAM, - FileBackend.getJingleFileUri(message)); - shareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - String mime = message.getMimeType(); - if (mime == null) { - mime = "*/*"; - } - shareIntent.setType(mime); - } - try { - activity.startActivity(Intent.createChooser(shareIntent, getText(R.string.share_with))); - } catch (ActivityNotFoundException e) { - //This should happen only on faulty androids because normally chooser is always available - Toast.makeText(activity,R.string.no_application_found_to_open_file,Toast.LENGTH_SHORT).show(); - } - } - - private void copyText(Message message) { - if (activity.copyTextToClipboard(message.getBody(), - R.string.message_text)) { - Toast.makeText(activity, R.string.message_copied_to_clipboard, - Toast.LENGTH_SHORT).show(); - } - } - - private void resendMessage(Message message) { - if (message.getType() == Message.TYPE_FILE || message.getType() == Message.TYPE_IMAGE) { - DownloadableFile file = FileBackend.getFile(message); - if (!file.exists()) { - Toast.makeText(activity, R.string.file_deleted, Toast.LENGTH_SHORT).show(); - message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED)); - activity.xmppConnectionService.updateConversationUi(); - return; - } - } - activity.xmppConnectionService.resendFailedMessages(message); - } - - private void copyUrl(Message message) { - final String url; - final int resId; - if (GeoHelper.isGeoUri(message.getBody())) { - resId = R.string.location; - url = message.getBody(); - } else if (message.hasFileOnRemoteHost()) { - resId = R.string.file_url; - url = message.getFileParams().getUrl(); - } else { - url = message.getBody(); - resId = R.string.file_url; - } - if (activity.copyTextToClipboard(url, resId)) { - Toast.makeText(activity, R.string.url_copied_to_clipboard, - Toast.LENGTH_SHORT).show(); - } - } - - private void downloadFile(Message message) { - HttpDownloadConnection downloadConnection = HttpConnectionManager.createNewDownloadConnection(message, true); - if (null == downloadConnection) { - Toast.makeText(activity, R.string.file_not_on_remote_host, Toast.LENGTH_LONG).show(); - } - } - - private void cancelTransmission(Message message) { - Transferable transferable = message.getTransferable(); - if (transferable != null) { - transferable.cancel(); - } else { - MessageUtil.markMessage(message, Message.STATUS_SEND_FAILED); - } - } - - private void retryDecryption(Message message) { - message.setEncryption(Message.ENCRYPTION_PGP); - activity.xmppConnectionService.updateConversationUi(); - conversation.getAccount().getPgpDecryptionService().add(message); - } - - protected void privateMessageWith(final Jid counterpart) { - this.mEditMessage.setText(""); - this.conversation.setNextCounterpart(counterpart); - updateChatMsgHint(); - updateSendButton(); - } - - protected void highlightInConference(String nick) { - String oldString = mEditMessage.getText().toString(); - if (oldString.isEmpty() || mEditMessage.getSelectionStart() == 0) { - mEditMessage.getText().insert(0, nick + ": "); - } else { - if (mEditMessage.getText().charAt( - mEditMessage.getSelectionStart() - 1) != ' ') { - nick = " " + nick; - } - mEditMessage.getText().insert(mEditMessage.getSelectionStart(), - nick + " "); - } - } - - @Override - public void onStop() { - super.onStop(); - if (this.conversation != null) { - final String msg = mEditMessage.getText().toString(); - this.conversation.setNextMessage(msg); - updateChatState(this.conversation, msg); - } - } - - private void updateChatState(final Conversation conversation, final String msg) { - ChatState state = msg.length() == 0 ? Config.DEFAULT_CHATSTATE : ChatState.PAUSED; - Account.State status = conversation.getAccount().getStatus(); - if (status == Account.State.ONLINE && conversation.setOutgoingChatState(state)) { - activity.xmppConnectionService.sendChatState(conversation); - } - } - - public void reInit(Conversation conversation) { - if (conversation == null) { - return; - } - this.activity = (ConversationActivity) getActivity(); - setupIme(); - if (this.conversation != null) { - final String msg = mEditMessage.getText().toString(); - this.conversation.setNextMessage(msg); - if (this.conversation != conversation) { - updateChatState(this.conversation, msg); - } - this.conversation.trim(); - } - - this.keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED; - this.conversation = conversation; - boolean canWrite = this.conversation.getMode() == Conversation.MODE_SINGLE || this.conversation.getMucOptions().participating(); - this.mEditMessage.setEnabled(canWrite); - this.mSendButton.setEnabled(canWrite); - this.mEditMessage.setKeyboardListener(null); - this.mEditMessage.setText(""); - this.mEditMessage.append(this.conversation.getNextMessage()); - this.mEditMessage.setKeyboardListener(this); - this.messagesView.setAdapter(messageListAdapter); - updateMessages(); - this.messagesLoaded = true; - int size = this.messageList.size(); - if (size > 0) { - messagesView.setSelection(size - 1); - } - swipeLayout.setRefreshing(false); - } - - private OnClickListener mEnableAccountListener = new OnClickListener() { - @Override - public void onClick(View v) { - final Account account = conversation == null ? null : conversation.getAccount(); - if (account != null) { - account.setOption(Account.OPTION_DISABLED, false); - activity.xmppConnectionService.updateAccount(account); - } - } - }; - - private OnClickListener mUnblockClickListener = new OnClickListener() { - @Override - public void onClick(final View v) { - v.post(new Runnable() { - @Override - public void run() { - v.setVisibility(View.INVISIBLE); - } - }); - if (conversation.isDomainBlocked()) { - BlockContactDialog.show(activity, activity.xmppConnectionService, conversation); - } else { - activity.unblockConversation(conversation); - } - } - }; - - private OnClickListener mAddBackClickListener = new OnClickListener() { - - @Override - public void onClick(View v) { - final Contact contact = conversation == null ? null : conversation.getContact(); - if (contact != null) { - activity.xmppConnectionService.createContact(contact); - activity.switchToContactDetails(contact); - } - } - }; - - private OnClickListener mAnswerSmpClickListener = new OnClickListener() { - @Override - public void onClick(View view) { - Intent intent = new Intent(activity, VerifyOTRActivity.class); - intent.setAction(VerifyOTRActivity.ACTION_VERIFY_CONTACT); - intent.putExtra("contact", conversation.getContact().getJid().toBareJid().toString()); - intent.putExtra(VerifyOTRActivity.EXTRA_ACCOUNT, conversation.getAccount().getJid().toBareJid().toString()); - intent.putExtra("mode", VerifyOTRActivity.MODE_ANSWER_QUESTION); - startActivity(intent); - } - }; - - private void updateSnackBar(final Conversation conversation) { - final Account account = conversation.getAccount(); - final Contact contact = conversation.getContact(); - final int mode = conversation.getMode(); - if (account.getStatus() == Account.State.DISABLED) { - showSnackbar(R.string.this_account_is_disabled, R.string.enable, this.mEnableAccountListener); - } else if (conversation.isBlocked()) { - showSnackbar(R.string.contact_blocked, R.string.unblock, this.mUnblockClickListener); - } else if (!contact.showInRoster() && contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { - showSnackbar(R.string.contact_added_you, R.string.add_back, this.mAddBackClickListener); - } else if (mode == Conversation.MODE_MULTI - && !conversation.getMucOptions().online() - && account.getStatus() == Account.State.ONLINE) { - switch (conversation.getMucOptions().getError()) { - case NICK_IN_USE: - showSnackbar(R.string.nick_in_use, R.string.edit, clickToMuc); - break; - case NO_RESPONSE: - showSnackbar(R.string.joining_conference, 0, null); - break; - case PASSWORD_REQUIRED: - showSnackbar(R.string.conference_requires_password, R.string.enter_password, enterPassword); - break; - case BANNED: - showSnackbar(R.string.conference_banned, R.string.leave, leaveMuc); - break; - case MEMBERS_ONLY: - showSnackbar(R.string.conference_members_only, R.string.leave, leaveMuc); - break; - case KICKED: - showSnackbar(R.string.conference_kicked, R.string.join, joinMuc); - break; - case UNKNOWN: - showSnackbar(R.string.conference_unknown_error, R.string.join, joinMuc); - break; - case SHUTDOWN: - showSnackbar(R.string.conference_shutdown, R.string.join, joinMuc); - break; - default: - break; - } - } else if (keychainUnlock == KEYCHAIN_UNLOCK_REQUIRED) { - showSnackbar(R.string.openpgp_messages_found, R.string.decrypt, clickToDecryptListener); - } else if (mode == Conversation.MODE_SINGLE - && conversation.smpRequested()) { - showSnackbar(R.string.smp_requested, R.string.verify, this.mAnswerSmpClickListener); - } else if (mode == Conversation.MODE_SINGLE - && conversation.hasValidOtrSession() - && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) - && (!conversation.isOtrFingerprintVerified())) { - showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify, clickToVerify); - } else { - hideSnackbar(); - } - } - - public void updateMessages() { - synchronized (this.messageList) { - if (getView() == null) { - return; - } - final ConversationActivity activity = (ConversationActivity) getActivity(); - if (this.conversation != null) { - conversation.populateWithMessages(ConversationFragment.this.messageList); - updatePgpMessages(); - updateSnackBar(conversation); - updateStatusMessages(); - this.messageListAdapter.notifyDataSetChanged(); - updateChatMsgHint(); - if (!activity.isConversationsOverviewVisable() || !activity.isConversationsOverviewHideable()) { - activity.sendReadMarkerIfNecessary(conversation); - } - this.updateSendButton(); - } - } - } - - public void updatePgpMessages() { - if (keychainUnlock != KEYCHAIN_UNLOCK_PENDING) { - if (getLastPgpDecryptableMessage() != null - && !conversation.getAccount().getPgpDecryptionService().isRunning()) { - keychainUnlock = KEYCHAIN_UNLOCK_REQUIRED; - } else { - keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED; - } - } - } - - @Nullable - private Message getLastPgpDecryptableMessage() { - for (final Message message : this.messageList) { - if (message.getEncryption() == Message.ENCRYPTION_PGP - && (message.getStatus() == Message.STATUS_RECEIVED || message.getStatus() >= Message.STATUS_SEND) - && message.getTransferable() == null) { - return message; - } - } - return null; - } - - private void messageSent() { - int size = this.messageList.size(); - messagesView.setSelection(size - 1); - mEditMessage.setText(""); - updateChatMsgHint(); - } - - public void setFocusOnInputField() { - mEditMessage.requestFocus(); - } - - enum SendButtonAction {TEXT, TAKE_PHOTO, SEND_LOCATION, RECORD_VOICE, CANCEL, CHOOSE_PICTURE} - - private int getSendButtonImageResource(SendButtonAction action, Presence.Status status) { - switch (action) { - case TEXT: - switch (status) { - case CHAT: - case ONLINE: - return R.drawable.ic_send_text_online; - case AWAY: - return R.drawable.ic_send_text_away; - case XA: - case DND: - return R.drawable.ic_send_text_dnd; - default: - return R.drawable.ic_send_text_offline; - } - case TAKE_PHOTO: - switch (status) { - case CHAT: - case ONLINE: - return R.drawable.ic_send_photo_online; - case AWAY: - return R.drawable.ic_send_photo_away; - case XA: - case DND: - return R.drawable.ic_send_photo_dnd; - default: - return R.drawable.ic_send_photo_offline; - } - case RECORD_VOICE: - switch (status) { - case CHAT: - case ONLINE: - return R.drawable.ic_send_voice_online; - case AWAY: - return R.drawable.ic_send_voice_away; - case XA: - case DND: - return R.drawable.ic_send_voice_dnd; - default: - return R.drawable.ic_send_voice_offline; - } - case SEND_LOCATION: - switch (status) { - case CHAT: - case ONLINE: - return R.drawable.ic_send_location_online; - case AWAY: - return R.drawable.ic_send_location_away; - case XA: - case DND: - return R.drawable.ic_send_location_dnd; - default: - return R.drawable.ic_send_location_offline; - } - case CANCEL: - switch (status) { - case CHAT: - case ONLINE: - return R.drawable.ic_send_cancel_online; - case AWAY: - return R.drawable.ic_send_cancel_away; - case XA: - case DND: - return R.drawable.ic_send_cancel_dnd; - default: - return R.drawable.ic_send_cancel_offline; - } - case CHOOSE_PICTURE: - switch (status) { - case CHAT: - case ONLINE: - return R.drawable.ic_send_picture_online; - case AWAY: - return R.drawable.ic_send_picture_away; - case XA: - case DND: - return R.drawable.ic_send_picture_dnd; - default: - return R.drawable.ic_send_picture_offline; - } - } - return R.drawable.ic_send_text_offline; - } - - public void updateSendButton() { - final Conversation c = this.conversation; - final SendButtonAction action; - final Presence.Status status; - final String text = this.mEditMessage == null ? "" : this.mEditMessage.getText().toString(); - final boolean empty = text.length() == 0; - final boolean conference = c.getMode() == Conversation.MODE_MULTI; - if (conference && !AccountUtil.isHttpUploadAvailable(c.getAccount())) { - if (empty && c.getNextCounterpart() != null) { - action = SendButtonAction.CANCEL; - } else { - action = SendButtonAction.TEXT; - } - } else { - if (empty) { - if (conference && c.getNextCounterpart() != null) { - action = SendButtonAction.CANCEL; - } else { - String setting = ConversationsPlusPreferences.quickAction(); - if (!setting.equals("none") && UIHelper.receivedLocationQuestion(conversation.getLatestMessage())) { - setting = "location"; - } else if (setting.equals("recent")) { - setting = ConversationsPlusPreferences.recentlyUsedQuickAction(); - } - switch (setting) { - case "photo": - action = SendButtonAction.TAKE_PHOTO; - break; - case "location": - action = SendButtonAction.SEND_LOCATION; - break; - case "voice": - action = SendButtonAction.RECORD_VOICE; - break; - case "picture": - action = SendButtonAction.CHOOSE_PICTURE; - break; - default: - action = SendButtonAction.TEXT; - break; - } - } - } else { - action = SendButtonAction.TEXT; - } - } - if (ConversationsPlusPreferences.sendButtonStatus() && c != null - && c.getAccount().getStatus() == Account.State.ONLINE) { - if (c.getMode() == Conversation.MODE_SINGLE) { - status = c.getContact().getMostAvailableStatus(); - } else { - status = c.getMucOptions().online() ? Presence.Status.ONLINE : Presence.Status.OFFLINE; - } - } else { - status = Presence.Status.OFFLINE; - } - this.mSendButton.setTag(action); - this.mSendButton.setImageResource(getSendButtonImageResource(action, status)); - } - - public void updateStatusMessages() { - synchronized (this.messageList) { - if (conversation.getMode() == Conversation.MODE_SINGLE) { - ChatState state = conversation.getIncomingChatState(); - if (state == ChatState.COMPOSING) { - this.messageList.add(Message.createStatusMessage(conversation, getString(R.string.contact_is_typing, conversation.getName()))); - } else if (state == ChatState.PAUSED) { - this.messageList.add(Message.createStatusMessage(conversation, getString(R.string.contact_has_stopped_typing, conversation.getName()))); - } else { - for (int i = this.messageList.size() - 1; i >= 0; --i) { - if (this.messageList.get(i).getStatus() == Message.STATUS_RECEIVED) { - return; - } else { - if (this.messageList.get(i).getStatus() == Message.STATUS_SEND_DISPLAYED) { - this.messageList.add(i + 1, - Message.createStatusMessage(conversation, getString(R.string.contact_has_read_up_to_this_point, conversation.getName()))); - return; - } - } - } - } - } - } - } - - protected void showSnackbar(final int message, final int action, final OnClickListener clickListener) { - snackbar.setVisibility(View.VISIBLE); - snackbar.setOnClickListener(null); - snackbarMessage.setText(message); - snackbarMessage.setOnClickListener(null); - snackbarAction.setVisibility(clickListener == null ? View.GONE : View.VISIBLE); - if (action != 0) { - snackbarAction.setText(action); - } - snackbarAction.setOnClickListener(clickListener); - } - - protected void hideSnackbar() { - snackbar.setVisibility(View.GONE); - } - - protected void sendPlainTextMessage(Message message) { - ConversationActivity activity = (ConversationActivity) getActivity(); - activity.xmppConnectionService.sendMessage(message); - messageSent(); - } - - protected void sendPgpMessage(final Message message) { - final ConversationActivity activity = (ConversationActivity) getActivity(); - final XmppConnectionService xmppService = activity.xmppConnectionService; - final Contact contact = message.getConversation().getContact(); - if (!activity.hasPgp()) { - activity.showInstallPgpDialog(); - return; - } - if (conversation.getAccount().getPgpSignature() == null) { - activity.announcePgp(conversation.getAccount(), conversation); - return; - } - if (conversation.getMode() == Conversation.MODE_SINGLE) { - if (contact.getPgpKeyId() != 0) { - xmppService.getPgpEngine().hasKey(contact, - new UiCallback<Contact>() { - - @Override - public void userInputRequried(PendingIntent pi, - Contact contact) { - activity.runIntent( - pi, - ConversationActivity.REQUEST_ENCRYPT_MESSAGE); - } - - @Override - public void success(Contact contact) { - messageSent(); - activity.encryptTextMessage(message); - } - - @Override - public void error(int error, Contact contact) { - System.out.println(); - } - }); - - } else { - showNoPGPKeyDialog(false, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, - int which) { - conversation - .setNextEncryption(Message.ENCRYPTION_NONE); - xmppService.databaseBackend - .updateConversation(conversation); - message.setEncryption(Message.ENCRYPTION_NONE); - xmppService.sendMessage(message); - messageSent(); - } - }); - } - } else { - if (conversation.getMucOptions().pgpKeysInUse()) { - if (!conversation.getMucOptions().everybodyHasKeys()) { - Toast warning = Toast - .makeText(getActivity(), - R.string.missing_public_keys, - Toast.LENGTH_LONG); - warning.setGravity(Gravity.CENTER_VERTICAL, 0, 0); - warning.show(); - } - activity.encryptTextMessage(message); - messageSent(); - } else { - showNoPGPKeyDialog(true, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, - int which) { - conversation - .setNextEncryption(Message.ENCRYPTION_NONE); - message.setEncryption(Message.ENCRYPTION_NONE); - xmppService.databaseBackend - .updateConversation(conversation); - xmppService.sendMessage(message); - messageSent(); - } - }); - } - } - } - - public void showNoPGPKeyDialog(boolean plural, - DialogInterface.OnClickListener listener) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setIconAttribute(android.R.attr.alertDialogIcon); - if (plural) { - builder.setTitle(getString(R.string.no_pgp_keys)); - builder.setMessage(getText(R.string.contacts_have_no_pgp_keys)); - } else { - builder.setTitle(getString(R.string.no_pgp_key)); - builder.setMessage(getText(R.string.contact_has_no_pgp_key)); - } - builder.setNegativeButton(getString(R.string.cancel), null); - builder.setPositiveButton(getString(R.string.send_unencrypted), - listener); - builder.create().show(); - } - - protected void sendAxolotlMessage(final Message message) { - final ConversationActivity activity = (ConversationActivity) getActivity(); - final XmppConnectionService xmppService = activity.xmppConnectionService; - xmppService.sendMessage(message); - messageSent(); - } - - protected void sendOtrMessage(final Message message) { - final ConversationActivity activity = (ConversationActivity) getActivity(); - final XmppConnectionService xmppService = activity.xmppConnectionService; - activity.selectPresence(message.getConversation(), - new OnPresenceSelected() { - - @Override - public void onPresenceSelected() { - message.setCounterpart(conversation.getNextCounterpart()); - xmppService.sendMessage(message); - messageSent(); - } - }); - } - - public void appendText(String text) { - if (text == null) { - return; - } - String previous = this.mEditMessage.getText().toString(); - if (previous.length() != 0 && !previous.endsWith(" ")) { - text = " " + text; - } - this.mEditMessage.append(text); - } - - @Override - public boolean onEnterPressed() { - if (ConversationsPlusPreferences.enterIsSend()) { - sendMessage(); - return true; - } else { - return false; - } - } - - @Override - public void onTypingStarted() { - Account.State status = conversation.getAccount().getStatus(); - if (status == Account.State.ONLINE && conversation.setOutgoingChatState(ChatState.COMPOSING)) { - activity.xmppConnectionService.sendChatState(conversation); - } - activity.hideConversationsOverview(); - updateSendButton(); - } - - @Override - public void onTypingStopped() { - Account.State status = conversation.getAccount().getStatus(); - if (status == Account.State.ONLINE && conversation.setOutgoingChatState(ChatState.PAUSED)) { - activity.xmppConnectionService.sendChatState(conversation); - } - } - - @Override - public void onTextDeleted() { - Account.State status = conversation.getAccount().getStatus(); - if (status == Account.State.ONLINE && conversation.setOutgoingChatState(Config.DEFAULT_CHATSTATE)) { - activity.xmppConnectionService.sendChatState(conversation); - } - updateSendButton(); - } - - private int completionIndex = 0; - private int lastCompletionLength = 0; - private String incomplete; - private int lastCompletionCursor; - private boolean firstWord = false; - - @Override - public boolean onTabPressed(boolean repeated) { - if (conversation == null || conversation.getMode() == Conversation.MODE_SINGLE) { - return false; - } - if (repeated) { - completionIndex++; - } else { - lastCompletionLength = 0; - completionIndex = 0; - final String content = mEditMessage.getText().toString(); - lastCompletionCursor = mEditMessage.getSelectionEnd(); - int start = lastCompletionCursor > 0 ? content.lastIndexOf(" ",lastCompletionCursor-1) + 1 : 0; - firstWord = start == 0; - incomplete = content.substring(start,lastCompletionCursor); - } - List<String> completions = new ArrayList<>(); - for(MucOptions.User user : conversation.getMucOptions().getUsers()) { - if (user.getName().startsWith(incomplete)) { - completions.add(user.getName()+(firstWord ? ": " : " ")); - } - } - Collections.sort(completions); - if (completions.size() > completionIndex) { - String completion = completions.get(completionIndex).substring(incomplete.length()); - mEditMessage.getEditableText().delete(lastCompletionCursor,lastCompletionCursor + lastCompletionLength); - mEditMessage.getEditableText().insert(lastCompletionCursor, completion); - lastCompletionLength = completion.length(); - } else { - completionIndex = -1; - mEditMessage.getEditableText().delete(lastCompletionCursor,lastCompletionCursor + lastCompletionLength); - lastCompletionLength = 0; - } - return true; - } - - @Override - public void onActivityResult(int requestCode, int resultCode, - final Intent data) { - if (resultCode == Activity.RESULT_OK) { - if (requestCode == ConversationActivity.REQUEST_DECRYPT_PGP) { - activity.getSelectedConversation().getAccount().getPgpDecryptionService().onKeychainUnlocked(); - keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED; - updatePgpMessages(); - } else if (requestCode == ConversationActivity.REQUEST_TRUST_KEYS_TEXT) { - final String body = mEditMessage.getText().toString(); - Message message = new Message(conversation, body, conversation.getNextEncryption()); - sendAxolotlMessage(message); - } else if (requestCode == ConversationActivity.REQUEST_TRUST_KEYS_MENU) { - int choice = data.getIntExtra("choice", ConversationActivity.ATTACHMENT_CHOICE_INVALID); - activity.selectPresenceToAttachFile(choice, conversation.getNextEncryption()); - } - } else { - if (requestCode == ConversationActivity.REQUEST_DECRYPT_PGP) { - keychainUnlock = KEYCHAIN_UNLOCK_NOT_REQUIRED; - updatePgpMessages(); - } - } - } - - private void changeEmojiKeyboardIcon(ImageView iconToBeChanged, int drawableResourceId){ - iconToBeChanged.setImageResource(drawableResourceId); - } - -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/EditAccountActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/EditAccountActivity.java deleted file mode 100644 index 1a868949..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/EditAccountActivity.java +++ /dev/null @@ -1,969 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.AlertDialog; -import android.app.AlertDialog.Builder; -import android.app.PendingIntent; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Bundle; -import android.provider.Settings; -import android.security.KeyChain; -import android.security.KeyChainAliasCallback; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.AutoCompleteTextView; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; -import android.widget.EditText; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; -import android.widget.TableLayout; -import android.widget.TableRow; -import android.widget.TextView; -import android.widget.Toast; - -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - -import de.thedevstack.conversationsplus.ConversationsPlusColors; -import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.thedevstack.conversationsplus.ui.listeners.ShowResourcesListDialogListener; -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.crypto.axolotl.AxolotlService; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.services.AvatarService; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.services.XmppConnectionService.OnAccountUpdate; -import de.thedevstack.conversationsplus.services.XmppConnectionService.OnCaptchaRequested; -import de.thedevstack.conversationsplus.ui.adapter.KnownHostsAdapter; -import de.thedevstack.conversationsplus.utils.CryptoHelper; -import de.thedevstack.conversationsplus.utils.UIHelper; -import de.thedevstack.conversationsplus.utils.ui.TextViewUtil; -import de.thedevstack.conversationsplus.xml.Element; -import de.thedevstack.conversationsplus.xmpp.OnKeyStatusUpdated; -import de.thedevstack.conversationsplus.xmpp.XmppConnection; -import de.thedevstack.conversationsplus.xmpp.XmppConnection.Features; -import de.thedevstack.conversationsplus.xmpp.forms.Data; -import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; -import de.thedevstack.conversationsplus.xmpp.pep.Avatar; - -public class EditAccountActivity extends XmppActivity implements OnAccountUpdate, - OnKeyStatusUpdated, OnCaptchaRequested, KeyChainAliasCallback, XmppConnectionService.OnShowErrorToast, XmppConnectionService.OnMamPreferencesFetched { - - private AutoCompleteTextView mAccountJid; - private EditText mPassword; - private EditText mPasswordConfirm; - private CheckBox mRegisterNew; - private Button mCancelButton; - private Button mSaveButton; - private Button mDisableBatterOptimizations; - private TableLayout mMoreTable; - - private LinearLayout mStats; - private RelativeLayout mBatteryOptimizations; - private TextView mServerInfoSm; - private TextView mServerInfoRosterVersion; - private TextView mServerInfoCarbons; - private TextView mServerInfoMam; - private TextView mServerInfoCSI; - private TextView mServerInfoBlocking; - private TextView mServerInfoPep; - private TextView mServerInfoHttpUpload; - private TextView mServerInfoPush; - private TextView mSessionEst; - private TextView mOtrFingerprint; - private TextView mAxolotlFingerprint; - private TextView mAccountJidLabel; - private ImageView mAvatar; - private RelativeLayout mOtrFingerprintBox; - private RelativeLayout mAxolotlFingerprintBox; - private ImageButton mOtrFingerprintToClipboardButton; - private ImageButton mAxolotlFingerprintToClipboardButton; - private ImageButton mRegenerateAxolotlKeyButton; - private LinearLayout keys; - private LinearLayout keysCard; - private LinearLayout mNamePort; - private EditText mHostname; - private EditText mPort; - private AlertDialog mCaptchaDialog = null; - - private Jid jidToEdit; - private boolean mInitMode = false; - private boolean mShowOptions = false; - private Account mAccount; - private String messageFingerprint; - - private boolean mFetchingAvatar = false; - - private final OnClickListener mSaveButtonClickListener = new OnClickListener() { - - @Override - public void onClick(final View v) { - if (mInitMode && mAccount != null) { - mAccount.setOption(Account.OPTION_DISABLED, false); - } - if (mAccount != null && mAccount.getStatus() == Account.State.DISABLED && !accountInfoEdited()) { - mAccount.setOption(Account.OPTION_DISABLED, false); - mAccount.setStatus(Account.State.CONNECTING); - xmppConnectionService.updateAccount(mAccount); - return; - } - final boolean registerNewAccount = mRegisterNew.isChecked() && !Config.DISALLOW_REGISTRATION_IN_UI; - if (Config.DOMAIN_LOCK != null && mAccountJid.getText().toString().contains("@")) { - mAccountJid.setError(getString(R.string.invalid_username)); - mAccountJid.requestFocus(); - return; - } - final Jid jid; - try { - if (Config.DOMAIN_LOCK != null) { - jid = Jid.fromParts(mAccountJid.getText().toString(), Config.DOMAIN_LOCK, null); - } else { - jid = Jid.fromString(mAccountJid.getText().toString()); - } - } catch (final InvalidJidException e) { - if (Config.DOMAIN_LOCK != null) { - mAccountJid.setError(getString(R.string.invalid_username)); - } else { - mAccountJid.setError(getString(R.string.invalid_jid)); - } - mAccountJid.requestFocus(); - return; - } - String hostname = null; - int numericPort = 5222; - if (mShowOptions) { - hostname = mHostname.getText().toString(); - final String port = mPort.getText().toString(); - if (hostname.contains(" ")) { - mHostname.setError(getString(R.string.not_valid_hostname)); - mHostname.requestFocus(); - return; - } - try { - numericPort = Integer.parseInt(port); - if (numericPort < 0 || numericPort > 65535) { - mPort.setError(getString(R.string.not_a_valid_port)); - mPort.requestFocus(); - return; - } - - } catch (NumberFormatException e) { - mPort.setError(getString(R.string.not_a_valid_port)); - mPort.requestFocus(); - return; - } - } - - if (jid.isDomainJid()) { - if (Config.DOMAIN_LOCK != null) { - mAccountJid.setError(getString(R.string.invalid_username)); - } else { - mAccountJid.setError(getString(R.string.invalid_jid)); - } - mAccountJid.requestFocus(); - return; - } - final String password = mPassword.getText().toString(); - final String passwordConfirm = mPasswordConfirm.getText().toString(); - if (registerNewAccount) { - if (!password.equals(passwordConfirm)) { - mPasswordConfirm.setError(getString(R.string.passwords_do_not_match)); - mPasswordConfirm.requestFocus(); - return; - } - } - if (mAccount != null) { - mAccount.setJid(jid); - mAccount.setPort(numericPort); - mAccount.setHostname(hostname); - mAccountJid.setError(null); - mPasswordConfirm.setError(null); - mAccount.setPassword(password); - mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount); - xmppConnectionService.updateAccount(mAccount); - } else { - if (xmppConnectionService.findAccountByJid(jid) != null) { - mAccountJid.setError(getString(R.string.account_already_exists)); - mAccountJid.requestFocus(); - return; - } - mAccount = new Account(jid.toBareJid(), password); - mAccount.setPort(numericPort); - mAccount.setHostname(hostname); - mAccount.setOption(Account.OPTION_USETLS, true); - mAccount.setOption(Account.OPTION_USECOMPRESSION, true); - mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount); - xmppConnectionService.createAccount(mAccount); - } - mHostname.setError(null); - mPort.setError(null); - if (!mAccount.isOptionSet(Account.OPTION_DISABLED) - && !registerNewAccount - && !mInitMode) { - finish(); - } else { - updateSaveButton(); - updateAccountInformation(true); - } - - } - }; - private final OnClickListener mCancelButtonClickListener = new OnClickListener() { - - @Override - public void onClick(final View v) { - finish(); - } - }; - private Toast mFetchingMamPrefsToast; - private TableRow mPushRow; - - public void refreshUiReal() { - invalidateOptionsMenu(); - if (mAccount != null - && mAccount.getStatus() != Account.State.ONLINE - && mFetchingAvatar) { - startActivity(new Intent(getApplicationContext(), - ManageAccountActivity.class)); - finish(); - } else if (mInitMode && mAccount != null && mAccount.getStatus() == Account.State.ONLINE) { - if (!mFetchingAvatar) { - mFetchingAvatar = true; - AvatarService.getInstance().checkForAvatar(mAccount, mAvatarFetchCallback); - } - } - if (mAccount != null) { - updateAccountInformation(false); - } - updateSaveButton(); - } - - @Override - public void onAccountUpdate() { - refreshUi(); - } - - private final UiCallback<Avatar> mAvatarFetchCallback = new UiCallback<Avatar>() { - - @Override - public void userInputRequried(final PendingIntent pi, final Avatar avatar) { - finishInitialSetup(avatar); - } - - @Override - public void success(final Avatar avatar) { - finishInitialSetup(avatar); - } - - @Override - public void error(final int errorCode, final Avatar avatar) { - finishInitialSetup(avatar); - } - }; - private final TextWatcher mTextWatcher = new TextWatcher() { - - @Override - public void onTextChanged(final CharSequence s, final int start, final int before, final int count) { - updateSaveButton(); - } - - @Override - public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) { - } - - @Override - public void afterTextChanged(final Editable s) { - - } - }; - - private final OnClickListener mAvatarClickListener = new OnClickListener() { - @Override - public void onClick(final View view) { - if (mAccount != null) { - final Intent intent = new Intent(getApplicationContext(), PublishProfilePictureActivity.class); - intent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toBareJid().toString()); - startActivity(intent); - } - } - }; - - protected void finishInitialSetup(final Avatar avatar) { - runOnUiThread(new Runnable() { - - @Override - public void run() { - final Intent intent; - final XmppConnection connection = mAccount.getXmppConnection(); - if (avatar != null || (connection != null && !connection.getFeatures().pep())) { - intent = new Intent(getApplicationContext(), StartConversationActivity.class); - if (xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 1) { - intent.putExtra("init", true); - } - } else { - intent = new Intent(getApplicationContext(), PublishProfilePictureActivity.class); - intent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toBareJid().toString()); - intent.putExtra("setup", true); - } - startActivity(intent); - finish(); - } - }); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_BATTERY_OP) { - updateAccountInformation(mAccount == null); - } - } - - protected void updateSaveButton() { - if (accountInfoEdited() && !mInitMode) { - TextViewUtil.enable(mSaveButton, ConversationsPlusColors.primaryText(), R.string.save); - } else if (mAccount != null && (mAccount.getStatus() == Account.State.CONNECTING || mFetchingAvatar)) { - TextViewUtil.disable(mSaveButton, ConversationsPlusColors.secondaryText(), R.string.account_status_connecting); - } else if (mAccount != null && mAccount.getStatus() == Account.State.DISABLED && !mInitMode) { - TextViewUtil.enable(mSaveButton, ConversationsPlusColors.primaryText(), R.string.enable); - } else { - TextViewUtil.enable(mSaveButton, ConversationsPlusColors.primaryText()); - if (!mInitMode) { - if (mAccount != null && mAccount.isOnlineAndConnected()) { - this.mSaveButton.setText(R.string.save); - if (!accountInfoEdited()) { - TextViewUtil.disable(mSaveButton, ConversationsPlusColors.secondaryText()); - } - } else { - this.mSaveButton.setText(R.string.connect); - } - } else { - this.mSaveButton.setText(R.string.next); - } - } - } - - protected boolean accountInfoEdited() { - if (this.mAccount == null) { - return false; - } - final String unmodified; - if (Config.DOMAIN_LOCK != null) { - unmodified = this.mAccount.getJid().getLocalpart(); - } else { - unmodified = this.mAccount.getJid().toBareJid().toString(); - } - return !unmodified.equals(this.mAccountJid.getText().toString()) || - !this.mAccount.getPassword().equals(this.mPassword.getText().toString()) || - !this.mAccount.getHostname().equals(this.mHostname.getText().toString()) || - !String.valueOf(this.mAccount.getPort()).equals(this.mPort.getText().toString()); - } - - @Override - protected String getShareableUri() { - if (mAccount != null) { - return mAccount.getShareableUri(); - } else { - return ""; - } - } - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_edit_account); - this.mAccountJid = (AutoCompleteTextView) findViewById(R.id.account_jid); - this.mAccountJid.addTextChangedListener(this.mTextWatcher); - this.mAccountJidLabel = (TextView) findViewById(R.id.account_jid_label); - if (Config.DOMAIN_LOCK != null) { - this.mAccountJidLabel.setText(R.string.username); - this.mAccountJid.setHint(R.string.username_hint); - } - this.mPassword = (EditText) findViewById(R.id.account_password); - this.mPassword.addTextChangedListener(this.mTextWatcher); - this.mPasswordConfirm = (EditText) findViewById(R.id.account_password_confirm); - this.mAvatar = (ImageView) findViewById(R.id.avater); - this.mAvatar.setOnClickListener(this.mAvatarClickListener); - this.mRegisterNew = (CheckBox) findViewById(R.id.account_register_new); - this.mStats = (LinearLayout) findViewById(R.id.stats); - this.mBatteryOptimizations = (RelativeLayout) findViewById(R.id.battery_optimization); - this.mDisableBatterOptimizations = (Button) findViewById(R.id.batt_op_disable); - this.mDisableBatterOptimizations.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); - Uri uri = Uri.parse("package:"+getPackageName()); - intent.setData(uri); - startActivityForResult(intent,REQUEST_BATTERY_OP); - } - }); - this.mSessionEst = (TextView) findViewById(R.id.session_est); - this.mServerInfoRosterVersion = (TextView) findViewById(R.id.server_info_roster_version); - this.mServerInfoCarbons = (TextView) findViewById(R.id.server_info_carbons); - this.mServerInfoMam = (TextView) findViewById(R.id.server_info_mam); - this.mServerInfoCSI = (TextView) findViewById(R.id.server_info_csi); - this.mServerInfoBlocking = (TextView) findViewById(R.id.server_info_blocking); - this.mServerInfoSm = (TextView) findViewById(R.id.server_info_sm); - this.mServerInfoPep = (TextView) findViewById(R.id.server_info_pep); - this.mServerInfoHttpUpload = (TextView) findViewById(R.id.server_info_http_upload); - this.mPushRow = (TableRow) findViewById(R.id.push_row); - this.mServerInfoPush = (TextView) findViewById(R.id.server_info_push); - this.mOtrFingerprint = (TextView) findViewById(R.id.otr_fingerprint); - this.mOtrFingerprintBox = (RelativeLayout) findViewById(R.id.otr_fingerprint_box); - this.mOtrFingerprintToClipboardButton = (ImageButton) findViewById(R.id.action_copy_to_clipboard); - this.mAxolotlFingerprint = (TextView) findViewById(R.id.axolotl_fingerprint); - this.mAxolotlFingerprintBox = (RelativeLayout) findViewById(R.id.axolotl_fingerprint_box); - this.mAxolotlFingerprintToClipboardButton = (ImageButton) findViewById(R.id.action_copy_axolotl_to_clipboard); - this.mRegenerateAxolotlKeyButton = (ImageButton) findViewById(R.id.action_regenerate_axolotl_key); - this.keysCard = (LinearLayout) findViewById(R.id.other_device_keys_card); - this.keys = (LinearLayout) findViewById(R.id.other_device_keys); - this.mNamePort = (LinearLayout) findViewById(R.id.name_port); - this.mHostname = (EditText) findViewById(R.id.hostname); - this.mHostname.addTextChangedListener(mTextWatcher); - this.mPort = (EditText) findViewById(R.id.port); - this.mPort.setText("5222"); - this.mPort.addTextChangedListener(mTextWatcher); - this.mSaveButton = (Button) findViewById(R.id.save_button); - this.mCancelButton = (Button) findViewById(R.id.cancel_button); - this.mSaveButton.setOnClickListener(this.mSaveButtonClickListener); - this.mCancelButton.setOnClickListener(this.mCancelButtonClickListener); - this.mMoreTable = (TableLayout) findViewById(R.id.server_info_more); - final OnCheckedChangeListener OnCheckedShowConfirmPassword = new OnCheckedChangeListener() { - @Override - public void onCheckedChanged(final CompoundButton buttonView, - final boolean isChecked) { - if (isChecked) { - mPasswordConfirm.setVisibility(View.VISIBLE); - } else { - mPasswordConfirm.setVisibility(View.GONE); - } - updateSaveButton(); - } - }; - this.mRegisterNew.setOnCheckedChangeListener(OnCheckedShowConfirmPassword); - if (Config.DISALLOW_REGISTRATION_IN_UI) { - this.mRegisterNew.setVisibility(View.GONE); - } - } - - @Override - public boolean onCreateOptionsMenu(final Menu menu) { - super.onCreateOptionsMenu(menu); - getMenuInflater().inflate(R.menu.editaccount, menu); - final MenuItem showQrCode = menu.findItem(R.id.action_show_qr_code); - final MenuItem showBlocklist = menu.findItem(R.id.action_show_block_list); - final MenuItem showMoreInfo = menu.findItem(R.id.action_server_info_show_more); - final MenuItem changePassword = menu.findItem(R.id.action_change_password_on_server); - final MenuItem clearDevices = menu.findItem(R.id.action_clear_devices); - final MenuItem renewCertificate = menu.findItem(R.id.action_renew_certificate); - final MenuItem mamPrefs = menu.findItem(R.id.action_mam_prefs); - - renewCertificate.setVisible(mAccount != null && mAccount.getPrivateKeyAlias() != null); - - if (mAccount != null && mAccount.isOnlineAndConnected()) { - if (!mAccount.getXmppConnection().getFeatures().blocking()) { - showBlocklist.setVisible(false); - } - if (!mAccount.getXmppConnection().getFeatures().register()) { - changePassword.setVisible(false); - } - mamPrefs.setVisible(mAccount.getXmppConnection().getFeatures().mam()); - Set<Integer> otherDevices = mAccount.getAxolotlService().getOwnDeviceIds(); - if (otherDevices == null || otherDevices.isEmpty()) { - clearDevices.setVisible(false); - } - } else { - showQrCode.setVisible(false); - showBlocklist.setVisible(false); - showMoreInfo.setVisible(false); - changePassword.setVisible(false); - clearDevices.setVisible(false); - mamPrefs.setVisible(false); - } - return super.onCreateOptionsMenu(menu); - } - - @Override - protected void onStart() { - super.onStart(); - if (getIntent() != null) { - try { - this.jidToEdit = Jid.fromString(getIntent().getStringExtra("jid")); - } catch (final InvalidJidException | NullPointerException ignored) { - this.jidToEdit = null; - } - this.mInitMode = getIntent().getBooleanExtra("init", false) || this.jidToEdit == null; - this.messageFingerprint = getIntent().getStringExtra("fingerprint"); - if (!mInitMode) { - this.mRegisterNew.setVisibility(View.GONE); - if (getActionBar() != null) { - getActionBar().setTitle(getString(R.string.account_details)); - } - } else { - this.mAvatar.setVisibility(View.GONE); - if (getActionBar() != null) { - getActionBar().setTitle(R.string.action_add_account); - } - } - } - this.mShowOptions = ConversationsPlusPreferences.showConnectionOptions(); - this.mNamePort.setVisibility(mShowOptions ? View.VISIBLE : View.GONE); - } - - @Override - protected void onBackendConnected() { - if (this.jidToEdit != null) { - this.mAccount = xmppConnectionService.findAccountByJid(jidToEdit); - this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER); - if (this.mAccount != null) { - if (this.mAccount.getPrivateKeyAlias() != null) { - this.mPassword.setHint(R.string.authenticate_with_certificate); - if (this.mInitMode) { - this.mPassword.requestFocus(); - } - } - updateAccountInformation(true); - } - } else if (this.xmppConnectionService.getAccounts().size() == 0) { - if (getActionBar() != null) { - getActionBar().setDisplayHomeAsUpEnabled(false); - getActionBar().setDisplayShowHomeEnabled(false); - getActionBar().setHomeButtonEnabled(false); - } - TextViewUtil.disable(mCancelButton, ConversationsPlusColors.secondaryText()); - } - if (Config.DOMAIN_LOCK == null) { - final KnownHostsAdapter mKnownHostsAdapter = new KnownHostsAdapter(this, - android.R.layout.simple_list_item_1, - xmppConnectionService.getKnownHosts()); - this.mAccountJid.setAdapter(mKnownHostsAdapter); - } - updateSaveButton(); - invalidateOptionsMenu(); - } - - @Override - public boolean onOptionsItemSelected(final MenuItem item) { - switch (item.getItemId()) { - case R.id.action_show_block_list: - final Intent showBlocklistIntent = new Intent(this, BlocklistActivity.class); - showBlocklistIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString()); - startActivity(showBlocklistIntent); - break; - case R.id.action_server_info_show_more: - mMoreTable.setVisibility(item.isChecked() ? View.GONE : View.VISIBLE); - item.setChecked(!item.isChecked()); - break; - case R.id.action_change_password_on_server: - final Intent changePasswordIntent = new Intent(this, ChangePasswordActivity.class); - changePasswordIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString()); - startActivity(changePasswordIntent); - break; - case R.id.action_mam_prefs: - editMamPrefs(); - break; - case R.id.action_clear_devices: - showWipePepDialog(); - break; - case R.id.action_renew_certificate: - renewCertificate(); - break; - } - return super.onOptionsItemSelected(item); - } - - private void renewCertificate() { - KeyChain.choosePrivateKeyAlias(this, this, null, null, null, -1, null); - } - - @Override - public void alias(String alias) { - if (alias != null) { - xmppConnectionService.updateKeyInAccount(mAccount, alias); - } - } - - private void updateAccountInformation(boolean init) { - if (init) { - this.mAccountJid.getEditableText().clear(); - if (Config.DOMAIN_LOCK != null) { - this.mAccountJid.getEditableText().append(this.mAccount.getJid().getLocalpart()); - } else { - this.mAccountJid.getEditableText().append(this.mAccount.getJid().toBareJid().toString()); - } - this.mPassword.setText(this.mAccount.getPassword()); - this.mHostname.setText(""); - this.mHostname.getEditableText().append(this.mAccount.getHostname()); - this.mPort.setText(""); - this.mPort.getEditableText().append(String.valueOf(this.mAccount.getPort())); - this.mNamePort.setVisibility(mShowOptions ? View.VISIBLE : View.GONE); - - } - mPassword.setEnabled(!Config.LOCK_SETTINGS); - mAccountJid.setEnabled(!Config.LOCK_SETTINGS); - mHostname.setEnabled(!Config.LOCK_SETTINGS); - mPort.setEnabled(!Config.LOCK_SETTINGS); - mPasswordConfirm.setEnabled(!Config.LOCK_SETTINGS); - mRegisterNew.setEnabled(!Config.LOCK_SETTINGS); - - if (!mInitMode) { - this.mAvatar.setVisibility(View.VISIBLE); - this.mAvatar.setImageBitmap(AvatarService.getInstance().get(this.mAccount, getPixel(72))); - } else { - this.mAvatar.setVisibility(View.GONE); - } - if (this.mAccount.isOptionSet(Account.OPTION_REGISTER)) { - this.mRegisterNew.setVisibility(View.VISIBLE); - this.mRegisterNew.setChecked(true); - this.mPasswordConfirm.setText(this.mAccount.getPassword()); - } else { - this.mRegisterNew.setVisibility(View.GONE); - this.mRegisterNew.setChecked(false); - } - if (this.mAccount.isOnlineAndConnected() && !this.mFetchingAvatar) { - this.findViewById(R.id.editAccountBoxes).setVisibility(View.GONE); - this.findViewById(R.id.displayAccountFrame).setVisibility(View.VISIBLE); - TextView detailsAccountJid = (TextView)this.findViewById(R.id.detailsAccountJid); - if (this.mAccount.countPresences() > 0) { - detailsAccountJid.setText(this.mAccount.getJid().toBareJid().toString() + " (" + this.mAccount.countPresences() + ")"); - detailsAccountJid.setOnClickListener(new ShowResourcesListDialogListener(EditAccountActivity.this, this.mAccount.getRoster().getContact(this.mAccount.getJid().toBareJid()))); - } else { - detailsAccountJid.setText(this.mAccount.getJid().toBareJid().toString()); - } - Features features = this.mAccount.getXmppConnection().getFeatures(); - this.mStats.setVisibility(View.VISIBLE); - boolean showOptimizingWarning = !xmppConnectionService.getPushManagementService().available(mAccount) && isOptimizingBattery(); - this.mBatteryOptimizations.setVisibility(showOptimizingWarning ? View.VISIBLE : View.GONE); - this.mSessionEst.setText(UIHelper.readableTimeDifferenceFull(this, this.mAccount.getXmppConnection() - .getLastSessionEstablished())); - if (features.rosterVersioning()) { - this.mServerInfoRosterVersion.setText(R.string.server_info_available); - } else { - this.mServerInfoRosterVersion.setText(R.string.server_info_unavailable); - } - if (features.carbons()) { - this.mServerInfoCarbons.setText(R.string.server_info_available); - } else { - this.mServerInfoCarbons - .setText(R.string.server_info_unavailable); - } - if (features.mam()) { - this.mServerInfoMam.setText(R.string.server_info_available); - } else { - this.mServerInfoMam.setText(R.string.server_info_unavailable); - } - if (features.csi()) { - this.mServerInfoCSI.setText(R.string.server_info_available); - } else { - this.mServerInfoCSI.setText(R.string.server_info_unavailable); - } - if (features.blocking()) { - this.mServerInfoBlocking.setText(R.string.server_info_available); - } else { - this.mServerInfoBlocking.setText(R.string.server_info_unavailable); - } - if (features.sm()) { - this.mServerInfoSm.setText(R.string.server_info_available); - } else { - this.mServerInfoSm.setText(R.string.server_info_unavailable); - } - if (features.pep()) { - AxolotlService axolotlService = this.mAccount.getAxolotlService(); - if (axolotlService != null && axolotlService.isPepBroken()) { - this.mServerInfoPep.setText(R.string.server_info_broken); - } else { - this.mServerInfoPep.setText(R.string.server_info_available); - } - } else { - this.mServerInfoPep.setText(R.string.server_info_unavailable); - } - if (features.httpUpload(0)) { - this.mServerInfoHttpUpload.setText(R.string.server_info_available); - } else { - this.mServerInfoHttpUpload.setText(R.string.server_info_unavailable); - } - - this.mPushRow.setVisibility(xmppConnectionService.getPushManagementService().isStub() ? View.GONE : View.VISIBLE); - - if (xmppConnectionService.getPushManagementService().available(mAccount)) { - this.mServerInfoPush.setText(R.string.server_info_available); - } else { - this.mServerInfoPush.setText(R.string.server_info_unavailable); - } - final String otrFingerprint = this.mAccount.getOtrFingerprint(); - if (otrFingerprint != null) { - this.mOtrFingerprintBox.setVisibility(View.VISIBLE); - this.mOtrFingerprint.setText(CryptoHelper.prettifyFingerprint(otrFingerprint)); - this.mOtrFingerprintToClipboardButton - .setVisibility(View.VISIBLE); - this.mOtrFingerprintToClipboardButton - .setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(final View v) { - - if (copyTextToClipboard(otrFingerprint, R.string.otr_fingerprint)) { - Toast.makeText( - EditAccountActivity.this, - R.string.toast_message_otr_fingerprint, - Toast.LENGTH_SHORT).show(); - } - } - }); - } else { - this.mOtrFingerprintBox.setVisibility(View.GONE); - } - final String axolotlFingerprint = this.mAccount.getAxolotlService().getOwnFingerprint(); - if (axolotlFingerprint != null) { - this.mAxolotlFingerprintBox.setVisibility(View.VISIBLE); - this.mAxolotlFingerprint.setText(CryptoHelper.prettifyFingerprint(axolotlFingerprint.substring(2))); - this.mAxolotlFingerprintToClipboardButton - .setVisibility(View.VISIBLE); - this.mAxolotlFingerprintToClipboardButton - .setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(final View v) { - - if (copyTextToClipboard(axolotlFingerprint.substring(2), R.string.omemo_fingerprint)) { - Toast.makeText( - EditAccountActivity.this, - R.string.toast_message_omemo_fingerprint, - Toast.LENGTH_SHORT).show(); - } - } - }); - if (Config.SHOW_REGENERATE_AXOLOTL_KEYS_BUTTON) { - this.mRegenerateAxolotlKeyButton - .setVisibility(View.VISIBLE); - this.mRegenerateAxolotlKeyButton - .setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(final View v) { - showRegenerateAxolotlKeyDialog(); - } - }); - } - } else { - this.mAxolotlFingerprintBox.setVisibility(View.GONE); - } - final String ownFingerprint = mAccount.getAxolotlService().getOwnFingerprint(); - boolean hasKeys = false; - keys.removeAllViews(); - for (final String fingerprint : mAccount.getAxolotlService().getFingerprintsForOwnSessions()) { - if (ownFingerprint.equals(fingerprint)) { - continue; - } - boolean highlight = fingerprint.equals(messageFingerprint); - hasKeys |= addFingerprintRow(keys, mAccount, fingerprint, highlight, null); - } - if (hasKeys) { - keysCard.setVisibility(View.VISIBLE); - } else { - keysCard.setVisibility(View.GONE); - } - } else { - if (this.mAccount.errorStatus()) { - final EditText errorTextField; - if (this.mAccount.getStatus() == Account.State.UNAUTHORIZED) { - errorTextField = this.mPassword; - } else if (mShowOptions - && this.mAccount.getStatus() == Account.State.SERVER_NOT_FOUND - && this.mHostname.getText().length() > 0) { - errorTextField = this.mHostname; - } else { - errorTextField = this.mAccountJid; - } - errorTextField.setError(getString(this.mAccount.getStatus().getReadableId())); - if (init || !accountInfoEdited()) { - errorTextField.requestFocus(); - } - } else { - this.mAccountJid.setError(null); - this.mPassword.setError(null); - this.mHostname.setError(null); - } - this.mStats.setVisibility(View.GONE); - } - } - - public void showRegenerateAxolotlKeyDialog() { - Builder builder = new Builder(this); - builder.setTitle("Regenerate Key"); - builder.setIconAttribute(android.R.attr.alertDialogIcon); - builder.setMessage("Are you sure you want to regenerate your Identity Key? (This will also wipe all established sessions and contact Identity Keys)"); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.setPositiveButton("Yes", - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mAccount.getAxolotlService().regenerateKeys(false); - } - }); - builder.create().show(); - } - - public void showWipePepDialog() { - Builder builder = new Builder(this); - builder.setTitle(getString(R.string.clear_other_devices)); - builder.setIconAttribute(android.R.attr.alertDialogIcon); - builder.setMessage(getString(R.string.clear_other_devices_desc)); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.setPositiveButton(getString(R.string.accept), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mAccount.getAxolotlService().wipeOtherPepDevices(); - } - }); - builder.create().show(); - } - - private void editMamPrefs() { - this.mFetchingMamPrefsToast = Toast.makeText(this, R.string.fetching_mam_prefs, Toast.LENGTH_LONG); - this.mFetchingMamPrefsToast.show(); - xmppConnectionService.fetchMamPreferences(mAccount, this); - } - - @Override - public void onKeyStatusUpdated(AxolotlService.FetchStatus report) { - refreshUi(); - } - - @Override - public void onCaptchaRequested(final Account account, final String id, final Data data, - final Bitmap captcha) { - final AlertDialog.Builder builder = new AlertDialog.Builder(this); - final ImageView view = new ImageView(this); - final LinearLayout layout = new LinearLayout(this); - final EditText input = new EditText(this); - - view.setImageBitmap(captcha); - view.setScaleType(ImageView.ScaleType.FIT_CENTER); - - input.setHint(getString(R.string.captcha_hint)); - - layout.setOrientation(LinearLayout.VERTICAL); - layout.addView(view); - layout.addView(input); - - builder.setTitle(getString(R.string.captcha_required)); - builder.setView(layout); - - builder.setPositiveButton(getString(R.string.ok), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - String rc = input.getText().toString(); - data.put("username", account.getUsername()); - data.put("password", account.getPassword()); - data.put("ocr", rc); - data.submit(); - - if (xmppConnectionServiceBound) { - xmppConnectionService.sendCreateAccountWithCaptchaPacket( - account, id, data); - } - } - }); - builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (xmppConnectionService != null) { - xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null); - } - } - }); - - builder.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - if (xmppConnectionService != null) { - xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null); - } - } - }); - - runOnUiThread(new Runnable() { - @Override - public void run() { - if ((mCaptchaDialog != null) && mCaptchaDialog.isShowing()) { - mCaptchaDialog.dismiss(); - } - mCaptchaDialog = builder.create(); - mCaptchaDialog.show(); - } - }); - } - - public void onShowErrorToast(final int resId) { - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(EditAccountActivity.this, resId, Toast.LENGTH_SHORT).show(); - } - }); - } - - @Override - public void onPreferencesFetched(final Element prefs) { - runOnUiThread(new Runnable() { - @Override - public void run() { - if (mFetchingMamPrefsToast != null) { - mFetchingMamPrefsToast.cancel(); - } - AlertDialog.Builder builder = new Builder(EditAccountActivity.this); - builder.setTitle(R.string.server_side_mam_prefs); - String defaultAttr = prefs.getAttribute("default"); - final List<String> defaults = Arrays.asList("never", "roster", "always"); - final AtomicInteger choice = new AtomicInteger(Math.max(0,defaults.indexOf(defaultAttr))); - builder.setSingleChoiceItems(R.array.mam_prefs, choice.get(), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - choice.set(which); - } - }); - builder.setNegativeButton(R.string.cancel, null); - builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - prefs.setAttribute("default",defaults.get(choice.get())); - xmppConnectionService.pushMamPreferences(mAccount, prefs); - } - }); - builder.create().show(); - } - }); - } - - @Override - public void onPreferencesFetchFailed() { - runOnUiThread(new Runnable() { - @Override - public void run() { - if (mFetchingMamPrefsToast != null) { - mFetchingMamPrefsToast.cancel(); - } - Toast.makeText(EditAccountActivity.this,R.string.unable_to_fetch_mam_prefs,Toast.LENGTH_LONG).show(); - } - }); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/EditMessage.java b/src/main/java/de/thedevstack/conversationsplus/ui/EditMessage.java deleted file mode 100644 index 5664434f..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/EditMessage.java +++ /dev/null @@ -1,90 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.content.Context; -import android.os.Handler; -import android.util.AttributeSet; -import android.view.KeyEvent; - -import de.thedevstack.conversationsplus.Config; -import github.ankushsachdeva.emojicon.EmojiconEditText; - -public class EditMessage extends EmojiconEditText { - - public EditMessage(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public EditMessage(Context context) { - super(context); - } - - protected Handler mTypingHandler = new Handler(); - - protected Runnable mTypingTimeout = new Runnable() { - @Override - public void run() { - if (isUserTyping && keyboardListener != null) { - keyboardListener.onTypingStopped(); - isUserTyping = false; - } - } - }; - - private boolean isUserTyping = false; - - private boolean lastInputWasTab = false; - - protected KeyboardListener keyboardListener; - - @Override - public boolean onKeyDown(int keyCode, KeyEvent e) { - if (keyCode == KeyEvent.KEYCODE_ENTER && !e.isShiftPressed()) { - lastInputWasTab = false; - if (keyboardListener != null && keyboardListener.onEnterPressed()) { - return true; - } - } else if (keyCode == KeyEvent.KEYCODE_TAB && !e.isAltPressed() && !e.isCtrlPressed()) { - if (keyboardListener != null && keyboardListener.onTabPressed(this.lastInputWasTab)) { - lastInputWasTab = true; - return true; - } - } else { - lastInputWasTab = false; - } - return super.onKeyDown(keyCode, e); - } - - @Override - public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { - super.onTextChanged(text,start,lengthBefore,lengthAfter); - lastInputWasTab = false; - if (this.mTypingHandler != null && this.keyboardListener != null) { - this.mTypingHandler.removeCallbacks(mTypingTimeout); - this.mTypingHandler.postDelayed(mTypingTimeout, Config.TYPING_TIMEOUT * 1000); - final int length = text.length(); - if (!isUserTyping && length > 0) { - this.isUserTyping = true; - this.keyboardListener.onTypingStarted(); - } else if (length == 0) { - this.isUserTyping = false; - this.keyboardListener.onTextDeleted(); - } - } - } - - public void setKeyboardListener(KeyboardListener listener) { - this.keyboardListener = listener; - if (listener != null) { - this.isUserTyping = false; - } - } - - public interface KeyboardListener { - boolean onEnterPressed(); - void onTypingStarted(); - void onTypingStopped(); - void onTextDeleted(); - boolean onTabPressed(boolean repeated); - } - -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/EnterJidDialog.java b/src/main/java/de/thedevstack/conversationsplus/ui/EnterJidDialog.java deleted file mode 100644 index 9e52d390..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/EnterJidDialog.java +++ /dev/null @@ -1,134 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.AlertDialog; -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ArrayAdapter; -import android.widget.AutoCompleteTextView; -import android.widget.Spinner; -import android.widget.TextView; - -import java.util.List; - -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.ui.adapter.KnownHostsAdapter; -import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class EnterJidDialog { - public interface OnEnterJidDialogPositiveListener { - boolean onEnterJidDialogPositive(Jid account, Jid contact) throws EnterJidDialog.JidError; - } - - public static class JidError extends Exception { - final String msg; - - public JidError(final String msg) { - this.msg = msg; - } - - public String toString() { - return msg; - } - } - - protected final AlertDialog dialog; - protected View.OnClickListener dialogOnClick; - protected OnEnterJidDialogPositiveListener listener = null; - - public EnterJidDialog( - final Context context, List<String> knownHosts, final List<String> activatedAccounts, - final String title, final String positiveButton, - final String prefilledJid, final String account, boolean allowEditJid - ) { - final boolean lock = Config.LOCK_DOMAINS_IN_CONVERSATIONS && Config.DOMAIN_LOCK != null; - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(title); - View dialogView = LayoutInflater.from(context).inflate(R.layout.enter_jid_dialog, null); - final TextView jabberIdDesc = (TextView) dialogView.findViewById(R.id.jabber_id); - jabberIdDesc.setText(lock ? R.string.username : R.string.account_settings_jabber_id); - final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account); - final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid); - if (!lock) { - jid.setAdapter(new KnownHostsAdapter(context, android.R.layout.simple_list_item_1, knownHosts)); - } - if (prefilledJid != null) { - jid.append(prefilledJid); - if (!allowEditJid) { - jid.setFocusable(false); - jid.setFocusableInTouchMode(false); - jid.setClickable(false); - jid.setCursorVisible(false); - } - } - - jid.setHint(Config.LOCK_DOMAINS_IN_CONVERSATIONS && Config.DOMAIN_LOCK != null ? R.string.username_hint : R.string.account_settings_example_jabber_id); - - if (account == null) { - StartConversationActivity.populateAccountSpinner(context, activatedAccounts, spinner); - } else { - ArrayAdapter<String> adapter = new ArrayAdapter<>(context, - android.R.layout.simple_spinner_item, - new String[] { account }); - spinner.setEnabled(false); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spinner.setAdapter(adapter); - } - - builder.setView(dialogView); - builder.setNegativeButton(R.string.cancel, null); - builder.setPositiveButton(positiveButton, null); - this.dialog = builder.create(); - - this.dialogOnClick = new View.OnClickListener() { - @Override - public void onClick(final View v) { - final Jid accountJid; - if (!spinner.isEnabled() && account == null) { - return; - } - try { - if (Config.DOMAIN_LOCK != null) { - accountJid = Jid.fromParts((String) spinner.getSelectedItem(), Config.DOMAIN_LOCK, null); - } else { - accountJid = Jid.fromString((String) spinner.getSelectedItem()); - } - } catch (final InvalidJidException e) { - return; - } - final Jid contactJid; - try { - if (lock) { - contactJid = Jid.fromParts(jid.getText().toString(), Config.DOMAIN_LOCK, null); - } else { - contactJid = Jid.fromString(jid.getText().toString()); - } - } catch (final InvalidJidException e) { - jid.setError(context.getString(lock ? R.string.invalid_username : R.string.invalid_jid)); - return; - } - - if(listener != null) { - try { - if(listener.onEnterJidDialogPositive(accountJid, contactJid)) { - dialog.dismiss(); - } - } catch(JidError error) { - jid.setError(error.toString()); - } - } - } - }; - } - - public void setOnEnterJidDialogPositiveListener(OnEnterJidDialogPositiveListener listener) { - this.listener = listener; - } - - public void show() { - this.dialog.show(); - this.dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(this.dialogOnClick); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ExportLogsPreference.java b/src/main/java/de/thedevstack/conversationsplus/ui/ExportLogsPreference.java deleted file mode 100644 index 54fe3910..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ExportLogsPreference.java +++ /dev/null @@ -1,36 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.Manifest; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.Build; -import android.preference.Preference; -import android.util.AttributeSet; - -import de.thedevstack.conversationsplus.services.ExportLogsService; - -public class ExportLogsPreference extends Preference { - - public ExportLogsPreference(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public ExportLogsPreference(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ExportLogsPreference(Context context) { - super(context); - } - - protected void onClick() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M - && getContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - return; - } - final Intent startIntent = new Intent(getContext(), ExportLogsService.class); - getContext().startService(startIntent); - super.onClick(); - } -}
\ No newline at end of file diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/LogCatOutputActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/LogCatOutputActivity.java index fe7968cb..a1f99a48 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/LogCatOutputActivity.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/LogCatOutputActivity.java @@ -11,10 +11,11 @@ import android.widget.ListView; import de.thedevstack.android.logcat.adapters.LogCatArrayAdapter; import de.thedevstack.android.logcat.tasks.ReadLogCatAsyncTask; -import de.thedevstack.conversationsplus.R; import de.thedevstack.conversationsplus.ui.listeners.LogCatOutputCopyOnClickListener; import de.thedevstack.conversationsplus.utils.ClipboardUtil; +import eu.siacs.conversations.R; + /** * Activity to display the logcat output. */ diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ManageAccountActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/ManageAccountActivity.java deleted file mode 100644 index e376b6b3..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ManageAccountActivity.java +++ /dev/null @@ -1,390 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.ActionBar; -import android.app.AlertDialog; -import android.content.ActivityNotFoundException; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.os.Bundle; -import android.security.KeyChain; -import android.security.KeyChainAliasCallback; -import android.util.Pair; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.AdapterView; -import android.widget.AdapterView.AdapterContextMenuInfo; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ListView; -import android.widget.Toast; - -import org.openintents.openpgp.util.OpenPgpApi; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.services.XmppConnectionService.OnAccountUpdate; -import de.thedevstack.conversationsplus.ui.adapter.AccountAdapter; -import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class ManageAccountActivity extends XmppActivity implements OnAccountUpdate, KeyChainAliasCallback, XmppConnectionService.OnAccountCreated { - - private final String STATE_SELECTED_ACCOUNT = "selected_account"; - - protected Account selectedAccount = null; - protected Jid selectedAccountJid = null; - - protected final List<Account> accountList = new ArrayList<>(); - protected ListView accountListView; - protected AccountAdapter mAccountAdapter; - protected AtomicBoolean mInvokedAddAccount = new AtomicBoolean(false); - - protected Pair<Integer, Intent> mPostponedActivityResult = null; - - @Override - public void onAccountUpdate() { - refreshUi(); - } - - @Override - protected void refreshUiReal() { - synchronized (this.accountList) { - accountList.clear(); - accountList.addAll(xmppConnectionService.getAccounts()); - } - ActionBar actionBar = getActionBar(); - if (actionBar != null) { - actionBar.setHomeButtonEnabled(this.accountList.size() > 0); - actionBar.setDisplayHomeAsUpEnabled(this.accountList.size() > 0); - } - invalidateOptionsMenu(); - mAccountAdapter.notifyDataSetChanged(); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - - super.onCreate(savedInstanceState); - - setContentView(R.layout.manage_accounts); - - if (savedInstanceState != null) { - String jid = savedInstanceState.getString(STATE_SELECTED_ACCOUNT); - if (jid != null) { - try { - this.selectedAccountJid = Jid.fromString(jid); - } catch (InvalidJidException e) { - this.selectedAccountJid = null; - } - } - } - - accountListView = (ListView) findViewById(R.id.account_list); - this.mAccountAdapter = new AccountAdapter(this, accountList); - accountListView.setAdapter(this.mAccountAdapter); - accountListView.setOnItemClickListener(new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView<?> arg0, View view, - int position, long arg3) { - switchToAccount(accountList.get(position)); - } - }); - registerForContextMenu(accountListView); - } - - @Override - public void onSaveInstanceState(final Bundle savedInstanceState) { - if (selectedAccount != null) { - savedInstanceState.putString(STATE_SELECTED_ACCOUNT, selectedAccount.getJid().toBareJid().toString()); - } - super.onSaveInstanceState(savedInstanceState); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu, v, menuInfo); - ManageAccountActivity.this.getMenuInflater().inflate( - R.menu.manageaccounts_context, menu); - AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo; - this.selectedAccount = accountList.get(acmi.position); - if (this.selectedAccount.isOptionSet(Account.OPTION_DISABLED)) { - menu.findItem(R.id.mgmt_account_disable).setVisible(false); - menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(false); - menu.findItem(R.id.mgmt_account_publish_avatar).setVisible(false); - } else { - menu.findItem(R.id.mgmt_account_enable).setVisible(false); - menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(Config.supportOpenPgp()); - } - menu.setHeaderTitle(this.selectedAccount.getJid().toBareJid().toString()); - } - - @Override - void onBackendConnected() { - if (selectedAccountJid != null) { - this.selectedAccount = xmppConnectionService.findAccountByJid(selectedAccountJid); - } - refreshUiReal(); - if (this.mPostponedActivityResult != null) { - this.onActivityResult(mPostponedActivityResult.first, RESULT_OK, mPostponedActivityResult.second); - } - if (Config.X509_VERIFICATION && this.accountList.size() == 0) { - if (mInvokedAddAccount.compareAndSet(false, true)) { - addAccountFromKey(); - } - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.manageaccounts, menu); - MenuItem enableAll = menu.findItem(R.id.action_enable_all); - MenuItem addAccount = menu.findItem(R.id.action_add_account); - MenuItem addAccountWithCertificate = menu.findItem(R.id.action_add_account_with_cert); - - if (Config.X509_VERIFICATION) { - addAccount.setVisible(false); - addAccountWithCertificate.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); - } else { - addAccount.setVisible(!Config.LOCK_SETTINGS); - } - addAccountWithCertificate.setVisible(!Config.LOCK_SETTINGS); - - if (!accountsLeftToEnable()) { - enableAll.setVisible(false); - } - MenuItem disableAll = menu.findItem(R.id.action_disable_all); - if (!accountsLeftToDisable()) { - disableAll.setVisible(false); - } - return true; - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.mgmt_account_publish_avatar: - publishAvatar(selectedAccount); - return true; - case R.id.mgmt_account_disable: - disableAccount(selectedAccount); - return true; - case R.id.mgmt_account_enable: - enableAccount(selectedAccount); - return true; - case R.id.mgmt_account_delete: - deleteAccount(selectedAccount); - return true; - case R.id.mgmt_account_announce_pgp: - publishOpenPGPPublicKey(selectedAccount); - return true; - default: - return super.onContextItemSelected(item); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.action_add_account: - startActivity(new Intent(getApplicationContext(), - EditAccountActivity.class)); - break; - case R.id.action_disable_all: - disableAllAccounts(); - break; - case R.id.action_enable_all: - enableAllAccounts(); - break; - case R.id.action_add_account_with_cert: - addAccountFromKey(); - break; - default: - break; - } - return super.onOptionsItemSelected(item); - } - - @Override - public boolean onNavigateUp() { - if (xmppConnectionService.getConversations().size() == 0) { - Intent contactsIntent = new Intent(this, - StartConversationActivity.class); - contactsIntent.setFlags( - // if activity exists in stack, pop the stack and go back to it - Intent.FLAG_ACTIVITY_CLEAR_TOP | - // otherwise, make a new task for it - Intent.FLAG_ACTIVITY_NEW_TASK | - // don't use the new activity animation; finish - // animation runs instead - Intent.FLAG_ACTIVITY_NO_ANIMATION); - startActivity(contactsIntent); - finish(); - return true; - } else { - return super.onNavigateUp(); - } - } - - public void onClickTglAccountState(Account account, boolean enable) { - if (enable) { - enableAccount(account); - } else { - disableAccount(account); - } - } - - private void addAccountFromKey() { - try { - KeyChain.choosePrivateKeyAlias(this, this, null, null, null, -1, null); - } catch (ActivityNotFoundException e) { - Toast.makeText(this, R.string.device_does_not_support_certificates, Toast.LENGTH_LONG).show(); - } - } - - private void publishAvatar(Account account) { - Intent intent = new Intent(getApplicationContext(), - PublishProfilePictureActivity.class); - intent.putExtra(EXTRA_ACCOUNT, account.getJid().toString()); - startActivity(intent); - } - - private void disableAllAccounts() { - List<Account> list = new ArrayList<>(); - synchronized (this.accountList) { - for (Account account : this.accountList) { - if (!account.isOptionSet(Account.OPTION_DISABLED)) { - list.add(account); - } - } - } - for (Account account : list) { - disableAccount(account); - } - } - - private boolean accountsLeftToDisable() { - synchronized (this.accountList) { - for (Account account : this.accountList) { - if (!account.isOptionSet(Account.OPTION_DISABLED)) { - return true; - } - } - return false; - } - } - - private boolean accountsLeftToEnable() { - synchronized (this.accountList) { - for (Account account : this.accountList) { - if (account.isOptionSet(Account.OPTION_DISABLED)) { - return true; - } - } - return false; - } - } - - private void enableAllAccounts() { - List<Account> list = new ArrayList<>(); - synchronized (this.accountList) { - for (Account account : this.accountList) { - if (account.isOptionSet(Account.OPTION_DISABLED)) { - list.add(account); - } - } - } - for (Account account : list) { - enableAccount(account); - } - } - - private void disableAccount(Account account) { - account.setOption(Account.OPTION_DISABLED, true); - xmppConnectionService.updateAccount(account); - } - - private void enableAccount(Account account) { - account.setOption(Account.OPTION_DISABLED, false); - xmppConnectionService.updateAccount(account); - } - - private void publishOpenPGPPublicKey(Account account) { - if (ManageAccountActivity.this.hasPgp()) { - choosePgpSignId(selectedAccount); - } else { - this.showInstallPgpDialog(); - } - } - - private void deleteAccount(final Account account) { - AlertDialog.Builder builder = new AlertDialog.Builder( - ManageAccountActivity.this); - builder.setTitle(getString(R.string.mgmt_account_are_you_sure)); - builder.setIconAttribute(android.R.attr.alertDialogIcon); - builder.setMessage(getString(R.string.mgmt_account_delete_confirm_text)); - builder.setPositiveButton(getString(R.string.delete), - new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - xmppConnectionService.deleteAccount(account); - selectedAccount = null; - } - }); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.create().show(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK) { - if (xmppConnectionServiceBound) { - if (requestCode == REQUEST_CHOOSE_PGP_ID) { - if (data.getExtras().containsKey(OpenPgpApi.EXTRA_SIGN_KEY_ID)) { - selectedAccount.setPgpSignId(data.getExtras().getLong(OpenPgpApi.EXTRA_SIGN_KEY_ID)); - announcePgp(selectedAccount, null); - } else { - choosePgpSignId(selectedAccount); - } - } else if (requestCode == REQUEST_ANNOUNCE_PGP) { - announcePgp(selectedAccount, null); - } - this.mPostponedActivityResult = null; - } else { - this.mPostponedActivityResult = new Pair<>(requestCode, data); - } - } - } - - @Override - public void alias(String alias) { - if (alias != null) { - xmppConnectionService.createAccountFromKey(alias, this); - } - } - - @Override - public void onAccountCreated(Account account) { - switchToAccount(account, true); - } - - @Override - public void informUser(final int r) { - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(ManageAccountActivity.this, r, Toast.LENGTH_LONG).show(); - } - }); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/PublishProfilePictureActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/PublishProfilePictureActivity.java deleted file mode 100644 index 6793d882..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/PublishProfilePictureActivity.java +++ /dev/null @@ -1,319 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.PendingIntent; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnLongClickListener; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; - -import com.soundcloud.android.crop.Crop; - -import java.io.File; -import java.io.FileNotFoundException; - -import de.thedevstack.conversationsplus.ConversationsPlusColors; -import de.thedevstack.conversationsplus.utils.ImageUtil; -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.services.AvatarService; -import de.thedevstack.conversationsplus.utils.ExifHelper; -import de.thedevstack.conversationsplus.utils.FileUtils; -import de.thedevstack.conversationsplus.utils.PhoneHelper; -import de.thedevstack.conversationsplus.utils.ui.TextViewUtil; -import de.thedevstack.conversationsplus.xmpp.pep.Avatar; - -public class PublishProfilePictureActivity extends XmppActivity { - - private static final int REQUEST_CHOOSE_FILE_AND_CROP = 0xac23; - private static final int REQUEST_CHOOSE_FILE = 0xac24; - private ImageView avatar; - private TextView accountTextView; - private TextView hintOrWarning; - private TextView secondaryHint; - private Button cancelButton; - private Button publishButton; - private Uri avatarUri; - private Uri defaultUri; - private Account account; - private boolean support = false; - private OnLongClickListener backToDefaultListener = new OnLongClickListener() { - - @Override - public boolean onLongClick(View v) { - avatarUri = defaultUri; - loadImageIntoPreview(defaultUri); - return true; - } - }; - private boolean mInitialAccountSetup; - private UiCallback<Avatar> avatarPublication = new UiCallback<Avatar>() { - - @Override - public void success(Avatar object) { - runOnUiThread(new Runnable() { - - @Override - public void run() { - if (mInitialAccountSetup) { - Intent intent = new Intent(getApplicationContext(), - StartConversationActivity.class); - intent.putExtra("init", true); - startActivity(intent); - } - Toast.makeText(PublishProfilePictureActivity.this, - R.string.avatar_has_been_published, - Toast.LENGTH_SHORT).show(); - finish(); - } - }); - } - - @Override - public void error(final int errorCode, Avatar object) { - runOnUiThread(new Runnable() { - - @Override - public void run() { - hintOrWarning.setText(errorCode); - hintOrWarning.setTextColor(ConversationsPlusColors.warning()); - TextViewUtil.enable(publishButton, ConversationsPlusColors.primaryText(), R.string.publish); - } - }); - - } - - @Override - public void userInputRequried(PendingIntent pi, Avatar object) { - } - }; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_publish_profile_picture); - this.avatar = (ImageView) findViewById(R.id.account_image); - this.cancelButton = (Button) findViewById(R.id.cancel_button); - this.publishButton = (Button) findViewById(R.id.publish_button); - this.accountTextView = (TextView) findViewById(R.id.account); - this.hintOrWarning = (TextView) findViewById(R.id.hint_or_warning); - this.secondaryHint = (TextView) findViewById(R.id.secondary_hint); - this.publishButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - if (avatarUri != null) { - TextViewUtil.disable(publishButton, ConversationsPlusColors.secondaryText(), R.string.publishing); - AvatarService.getInstance().publishAvatar(account, avatarUri, - avatarPublication); - } - } - }); - this.cancelButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - if (mInitialAccountSetup) { - Intent intent = new Intent(getApplicationContext(), - StartConversationActivity.class); - if (xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 1) { - intent.putExtra("init", true); - } - startActivity(intent); - } - finish(); - } - }); - this.avatar.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - if (hasStoragePermission(REQUEST_CHOOSE_FILE)) { - chooseAvatar(false); - } - - } - }); - this.defaultUri = PhoneHelper.getSefliUri(getApplicationContext()); - } - - private void chooseAvatar(boolean crop) { - Intent attachFileIntent = new Intent(); - attachFileIntent.setType("image/*"); - attachFileIntent.setAction(Intent.ACTION_GET_CONTENT); - Intent chooser = Intent.createChooser(attachFileIntent, getString(R.string.attach_file)); - startActivityForResult(chooser, crop ? REQUEST_CHOOSE_FILE_AND_CROP : REQUEST_CHOOSE_FILE); - } - - @Override - public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { - if (grantResults.length > 0) - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - if (requestCode == REQUEST_CHOOSE_FILE_AND_CROP) { - chooseAvatar(true); - } else if (requestCode == REQUEST_CHOOSE_FILE) { - chooseAvatar(false); - } - } else { - Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show(); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.publish_avatar, menu); - return super.onCreateOptionsMenu(menu); - } - - @Override - public boolean onOptionsItemSelected(final MenuItem item) { - if (item.getItemId() == R.id.action_crop_image) { - if (hasStoragePermission(REQUEST_CHOOSE_FILE_AND_CROP)) { - chooseAvatar(true); - } - return true; - } else { - return super.onOptionsItemSelected(item); - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, final Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK) { - switch (requestCode) { - case REQUEST_CHOOSE_FILE_AND_CROP: - Uri source = data.getData(); - String original = FileUtils.getPath(source); - if (original != null) { - source = Uri.parse("file://"+original); - } - Uri destination = Uri.fromFile(new File(getCacheDir(), "croppedAvatar")); - final int size = getPixel(192); - Crop.of(source, destination).asSquare().withMaxSize(size, size).start(this); - break; - case REQUEST_CHOOSE_FILE: - this.avatarUri = data.getData(); - if (xmppConnectionServiceBound) { - loadImageIntoPreview(this.avatarUri); - } - break; - case Crop.REQUEST_CROP: - this.avatarUri = Uri.fromFile(new File(getCacheDir(), "croppedAvatar")); - if (xmppConnectionServiceBound) { - loadImageIntoPreview(this.avatarUri); - } - break; - } - } else { - if (requestCode == Crop.REQUEST_CROP && data != null) { - Throwable throwable = Crop.getError(data); - if (throwable != null && throwable instanceof OutOfMemoryError) { - Toast.makeText(this,R.string.selection_too_large, Toast.LENGTH_SHORT).show(); - } - } - } - } - - @Override - protected void onBackendConnected() { - this.account = extractAccount(getIntent()); - if (this.account != null) { - if (this.account.getXmppConnection() != null) { - this.support = this.account.getXmppConnection().getFeatures().pep(); - } - if (this.avatarUri == null) { - if (this.account.getAvatar() != null - || this.defaultUri == null) { - this.avatar.setImageBitmap(AvatarService.getInstance().get(account, getPixel(192))); - if (this.defaultUri != null) { - this.avatar - .setOnLongClickListener(this.backToDefaultListener); - } else { - this.secondaryHint.setVisibility(View.INVISIBLE); - } - if (!support) { - this.hintOrWarning - .setTextColor(ConversationsPlusColors.warning()); - this.hintOrWarning - .setText(R.string.error_publish_avatar_no_server_support); - } - } else { - this.avatarUri = this.defaultUri; - loadImageIntoPreview(this.defaultUri); - this.secondaryHint.setVisibility(View.INVISIBLE); - } - } else { - loadImageIntoPreview(avatarUri); - } - String account; - if (Config.DOMAIN_LOCK != null) { - account = this.account.getJid().getLocalpart(); - } else { - account = this.account.getJid().toBareJid().toString(); - } - this.accountTextView.setText(account); - } - } - - @Override - protected void onStart() { - super.onStart(); - if (getIntent() != null) { - this.mInitialAccountSetup = getIntent().getBooleanExtra("setup", false); - } - if (this.mInitialAccountSetup) { - this.cancelButton.setText(R.string.skip); - } - } - - protected void loadImageIntoPreview(Uri uri) { - Bitmap bm = null; - try { - bm = ImageUtil.cropCenterSquare(uri, getPixel(192)); - } catch (Exception e) { - e.printStackTrace(); - } - - if (bm == null) { - TextViewUtil.disable(this.publishButton, ConversationsPlusColors.secondaryText()); - this.hintOrWarning.setTextColor(ConversationsPlusColors.warning()); - this.hintOrWarning - .setText(R.string.error_publish_avatar_converting); - return; - } - this.avatar.setImageBitmap(bm); - if (support) { - TextViewUtil.enable(this.publishButton, ConversationsPlusColors.primaryText(), R.string.publish); - this.hintOrWarning.setText(R.string.publish_avatar_explanation); - this.hintOrWarning.setTextColor(ConversationsPlusColors.primaryText()); - } else { - TextViewUtil.disable(this.publishButton, ConversationsPlusColors.secondaryText()); - this.hintOrWarning.setTextColor(ConversationsPlusColors.warning()); - this.hintOrWarning - .setText(R.string.error_publish_avatar_no_server_support); - } - if (this.defaultUri != null && uri.equals(this.defaultUri)) { - this.secondaryHint.setVisibility(View.INVISIBLE); - this.avatar.setOnLongClickListener(null); - } else if (this.defaultUri != null) { - this.secondaryHint.setVisibility(View.VISIBLE); - this.avatar.setOnLongClickListener(this.backToDefaultListener); - } - } - - public void refreshUiReal() { - //nothing to do. This Activity doesn't implement any listeners - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/SettingsActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/SettingsActivity.java deleted file mode 100644 index 296f8f4f..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/SettingsActivity.java +++ /dev/null @@ -1,227 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.AlertDialog; -import android.app.FragmentManager; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Bundle; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.PreferenceCategory; -import android.preference.PreferenceManager; -import android.widget.Toast; - -import java.security.KeyStoreException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -import de.duenndns.ssl.MemorizingTrustManager; -import de.thedevstack.conversationsplus.ConversationsPlusApplication; -import de.thedevstack.conversationsplus.services.ExportLogsService; -import de.tzur.conversations.Settings; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.persistance.FileBackend; -import de.thedevstack.conversationsplus.xmpp.XmppConnection; -import github.ankushsachdeva.emojicon.EmojiconHandler; - -public class SettingsActivity extends XmppActivity implements - OnSharedPreferenceChangeListener { - - public static final int REQUEST_WRITE_LOGS = 0xbf8701; - private SettingsFragment mSettingsFragment; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - FragmentManager fm = getFragmentManager(); - mSettingsFragment = (SettingsFragment) fm.findFragmentById(android.R.id.content); - if (mSettingsFragment == null || !mSettingsFragment.getClass().equals(SettingsFragment.class)) { - mSettingsFragment = new SettingsFragment(); - fm.beginTransaction().replace(android.R.id.content, mSettingsFragment).commit(); - } - } - - @Override - void onBackendConnected() { - - } - - @Override - public void onStart() { - super.onStart(); - PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); - ListPreference resources = (ListPreference) mSettingsFragment.findPreference("resource"); - if (resources != null) { - ArrayList<CharSequence> entries = new ArrayList<>(Arrays.asList(resources.getEntries())); - if (!entries.contains(Build.MODEL)) { - entries.add(0, Build.MODEL); - resources.setEntries(entries.toArray(new CharSequence[entries.size()])); - resources.setEntryValues(entries.toArray(new CharSequence[entries.size()])); - } - } - - final Preference removeCertsPreference = mSettingsFragment.findPreference("remove_trusted_certificates"); - removeCertsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - final MemorizingTrustManager mtm = ConversationsPlusApplication.getMemorizingTrustManager(); - final ArrayList<String> aliases = Collections.list(mtm.getCertificates()); - if (aliases.size() == 0) { - displayToast(getString(R.string.toast_no_trusted_certs)); - return true; - } - final ArrayList selectedItems = new ArrayList<Integer>(); - final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(SettingsActivity.this); - dialogBuilder.setTitle(getResources().getString(R.string.dialog_manage_certs_title)); - dialogBuilder.setMultiChoiceItems(aliases.toArray(new CharSequence[aliases.size()]), null, - new DialogInterface.OnMultiChoiceClickListener() { - @Override - public void onClick(DialogInterface dialog, int indexSelected, - boolean isChecked) { - if (isChecked) { - selectedItems.add(indexSelected); - } else if (selectedItems.contains(indexSelected)) { - selectedItems.remove(Integer.valueOf(indexSelected)); - } - if (selectedItems.size() > 0) - ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true); - else { - ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false); - } - } - }); - - dialogBuilder.setPositiveButton( - getResources().getString(R.string.dialog_manage_certs_positivebutton), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - int count = selectedItems.size(); - if (count > 0) { - for (int i = 0; i < count; i++) { - try { - Integer item = Integer.valueOf(selectedItems.get(i).toString()); - String alias = aliases.get(item); - mtm.deleteCertificate(alias); - } catch (KeyStoreException e) { - e.printStackTrace(); - displayToast("Error: " + e.getLocalizedMessage()); - } - } - if (xmppConnectionServiceBound) { - reconnectAccounts(); - } - displayToast(getResources().getQuantityString(R.plurals.toast_delete_certificates, count, count)); - } - } - }); - dialogBuilder.setNegativeButton(getResources().getString(R.string.dialog_manage_certs_negativebutton), null); - AlertDialog removeCertsDialog = dialogBuilder.create(); - removeCertsDialog.show(); - removeCertsDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); - return true; - } - }); - // Avoid appearence of setting to enable or disable omemo in screen - Preference omemoEnabledPreference = this.mSettingsFragment.findPreference("omemo_enabled"); - PreferenceCategory otherExpertSettingsGroup = (PreferenceCategory) this.mSettingsFragment.findPreference("other_expert_settings"); - if (null != omemoEnabledPreference && null != otherExpertSettingsGroup) { - otherExpertSettingsGroup.removePreference(omemoEnabledPreference); - } - } - - @Override - public void onStop() { - super.onStop(); - PreferenceManager.getDefaultSharedPreferences(this) - .unregisterOnSharedPreferenceChangeListener(this); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences preferences, String name) { - final List<String> resendPresence = Arrays.asList( - "confirm_messages_list", - "xa_on_silent_mode", - "away_when_screen_off", - "treat_vibrate_as_silent"); - // need to synchronize the settings class first - Settings.synchronizeSettingsClassWithPreferences(preferences, name); - if (name.equals("resource")) { - String resource = preferences.getString("resource", "mobile") - .toLowerCase(Locale.US); - if (xmppConnectionServiceBound) { - for (Account account : xmppConnectionService.getAccounts()) { - if (account.setResource(resource)) { - if (!account.isOptionSet(Account.OPTION_DISABLED)) { - XmppConnection connection = account.getXmppConnection(); - if (connection != null) { - connection.resetStreamId(); - } - xmppConnectionService.reconnectAccountInBackground(account); - } - } - } - } - } else if (name.equals("keep_foreground_service")) { - xmppConnectionService.toggleForegroundService(); - } else if (resendPresence.contains(name)) { - if (xmppConnectionServiceBound) { - if (name.equals("away_when_screen_off")) { - xmppConnectionService.toggleScreenEventReceiver(); - } - xmppConnectionService.refreshAllPresences(); - } - } else if (name.equals("dont_trust_system_cas")) { - ConversationsPlusApplication.updateMemorizingTrustmanager(); - reconnectAccounts(); - } else if ("parse_emoticons".equals(name)) { - EmojiconHandler.setParseEmoticons(Settings.PARSE_EMOTICONS); - } else if ("file_transfer_folder".equals(name)) { - FileBackend.onFileTransferFolderChanged(); - } else if ("img_transfer_folder".equals(name)) { - FileBackend.onImageTransferFolderChanged(); - } - - } - - @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { - if (grantResults.length > 0) - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - if (requestCode == REQUEST_WRITE_LOGS) { - getApplicationContext().startService(new Intent(getApplicationContext(), ExportLogsService.class)); - } - } else { - Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show(); - } - } - - private void displayToast(final String msg) { - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(SettingsActivity.this, msg, Toast.LENGTH_LONG).show(); - } - }); - } - - private void reconnectAccounts() { - for (Account account : xmppConnectionService.getAccounts()) { - if (!account.isOptionSet(Account.OPTION_DISABLED)) { - xmppConnectionService.reconnectAccountInBackground(account); - } - } - } - - public void refreshUiReal() { - //nothing to do. This Activity doesn't implement any listeners - } - -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/SettingsFragment.java b/src/main/java/de/thedevstack/conversationsplus/ui/SettingsFragment.java deleted file mode 100644 index a549ff94..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/SettingsFragment.java +++ /dev/null @@ -1,65 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.Dialog; -import android.os.Bundle; -import android.preference.Preference; -import android.preference.PreferenceFragment; -import android.preference.PreferenceScreen; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.widget.FrameLayout; -import android.widget.LinearLayout; - -import de.thedevstack.conversationsplus.R; - -public class SettingsFragment extends PreferenceFragment { - - //http://stackoverflow.com/questions/16374820/action-bar-home-button-not-functional-with-nested-preferencescreen/16800527#16800527 - private void initializeActionBar(PreferenceScreen preferenceScreen) { - final Dialog dialog = preferenceScreen.getDialog(); - - if (dialog != null) { - View homeBtn = dialog.findViewById(android.R.id.home); - - if (homeBtn != null) { - View.OnClickListener dismissDialogClickListener = new View.OnClickListener() { - @Override - public void onClick(View v) { - dialog.dismiss(); - } - }; - - ViewParent homeBtnContainer = homeBtn.getParent(); - - if (homeBtnContainer instanceof FrameLayout) { - ViewGroup containerParent = (ViewGroup) homeBtnContainer.getParent(); - if (containerParent instanceof LinearLayout) { - ((LinearLayout) containerParent).setOnClickListener(dismissDialogClickListener); - } else { - ((FrameLayout) homeBtnContainer).setOnClickListener(dismissDialogClickListener); - } - } else { - homeBtn.setOnClickListener(dismissDialogClickListener); - } - } - } - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Load the preferences from an XML resource - addPreferencesFromResource(R.xml.preferences); - } - - @Override - public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { - super.onPreferenceTreeClick(preferenceScreen, preference); - if (preference instanceof PreferenceScreen) { - initializeActionBar((PreferenceScreen) preference); - } - return false; - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/ShareWithActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/ShareWithActivity.java deleted file mode 100644 index 8852212b..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/ShareWithActivity.java +++ /dev/null @@ -1,357 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.PendingIntent; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ListView; -import android.widget.Toast; - -import java.net.URLConnection; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.thedevstack.conversationsplus.ui.dialogs.UserDecisionDialog; -import de.thedevstack.conversationsplus.ui.listeners.ResizePictureUserDecisionListener; -import de.thedevstack.conversationsplus.ui.listeners.ShareWithResizePictureUserDecisionListener; -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.entities.Message; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.ui.adapter.ConversationAdapter; -import de.thedevstack.conversationsplus.utils.AccountUtil; -import de.thedevstack.conversationsplus.utils.ConversationUtil; -import de.thedevstack.conversationsplus.utils.FileUtils; -import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class ShareWithActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate { - - private boolean mReturnToPrevious = false; - - @Override - public void onConversationUpdate() { - refreshUi(); - } - - private class Share { - public List<Uri> uris = new ArrayList<>(); - public boolean image; - public String account; - public String contact; - public String text; - public String uuid; - public boolean multiple = false; - } - - private Share share; - - private static final int REQUEST_START_NEW_CONVERSATION = 0x0501; - private ListView mListView; - private ConversationAdapter mAdapter; - private List<Conversation> mConversations = new ArrayList<>(); - private Toast mToast; - private AtomicInteger attachmentCounter = new AtomicInteger(0); - - private UiCallback<Message> attachFileCallback = new UiCallback<Message>() { - - @Override - public void userInputRequried(PendingIntent pi, Message object) { - // TODO Auto-generated method stub - - } - - @Override - public void success(final Message message) { - xmppConnectionService.sendMessage(message); - runOnUiThread(new Runnable() { - @Override - public void run() { - if (attachmentCounter.decrementAndGet() <=0 ) { - int resId; - if (share.image && share.multiple) { - resId = R.string.shared_images_with_x; - } else if (share.image) { - resId = R.string.shared_image_with_x; - } else { - resId = R.string.shared_file_with_x; - } - replaceToast(getString(resId, message.getConversation().getName())); - if (mReturnToPrevious) { - finish(); - } else { - switchToConversation(message.getConversation()); - } - } - } - }); - } - - @Override - public void error(final int errorCode, Message object) { - runOnUiThread(new Runnable() { - @Override - public void run() { - replaceToast(getString(errorCode)); - if (attachmentCounter.decrementAndGet() <=0 ) { - finish(); - } - } - }); - } - }; - - protected void hideToast() { - if (mToast != null) { - mToast.cancel(); - } - } - - protected void replaceToast(String msg) { - hideToast(); - mToast = Toast.makeText(this, msg ,Toast.LENGTH_LONG); - mToast.show(); - } - - protected void onActivityResult(int requestCode, int resultCode, final Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_START_NEW_CONVERSATION - && resultCode == RESULT_OK) { - share.contact = data.getStringExtra("contact"); - share.account = data.getStringExtra(EXTRA_ACCOUNT); - } - if (xmppConnectionServiceBound - && share != null - && share.contact != null - && share.account != null) { - share(); - } - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if (getActionBar() != null) { - getActionBar().setDisplayHomeAsUpEnabled(false); - getActionBar().setHomeButtonEnabled(false); - } - - setContentView(R.layout.share_with); - setTitle(getString(R.string.title_activity_sharewith)); - - mListView = (ListView) findViewById(R.id.choose_conversation_list); - mAdapter = new ConversationAdapter(this, this.mConversations); - mListView.setAdapter(mAdapter); - mListView.setOnItemClickListener(new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { - share(mConversations.get(position)); - } - }); - - this.share = new Share(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.share_with, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(final MenuItem item) { - switch (item.getItemId()) { - case R.id.action_add: - final Intent intent = new Intent(getApplicationContext(), ChooseContactActivity.class); - startActivityForResult(intent, REQUEST_START_NEW_CONVERSATION); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - public void onStart() { - super.onStart(); - Intent intent = getIntent(); - if (intent == null) { - return; - } - this.mReturnToPrevious = ConversationsPlusPreferences.returnToPrevious(); - final String type = intent.getType(); - final String action = intent.getAction(); - Log.d(Config.LOGTAG, "action: "+action+ ", type:"+type); - share.uuid = intent.getStringExtra("uuid"); - if (Intent.ACTION_SEND.equals(action)) { - final String text = intent.getStringExtra(Intent.EXTRA_TEXT); - final Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); - if (type != null && uri != null && (text == null || !type.equals("text/plain"))) { - this.share.uris.clear(); - this.share.uris.add(uri); - this.share.image = type.startsWith("image/") || isImage(uri); - } else { - this.share.text = text; - } - } else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) { - this.share.image = type != null && type.startsWith("image/"); - if (!this.share.image) { - return; - } - this.share.uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); - } - if (xmppConnectionServiceBound) { - if (share.uuid != null) { - share(); - } else { - xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.uris.size() == 0); - } - } - - } - - protected boolean isImage(Uri uri) { - try { - String guess = URLConnection.guessContentTypeFromName(uri.toString()); - return (guess != null && guess.startsWith("image/")); - } catch (final StringIndexOutOfBoundsException ignored) { - return false; - } - } - - @Override - void onBackendConnected() { - if (xmppConnectionServiceBound && share != null - && ((share.contact != null && share.account != null) || share.uuid != null)) { - share(); - return; - } - refreshUiReal(); - } - - private void share() { - final Conversation conversation; - if (share.uuid != null) { - conversation = xmppConnectionService.findConversationByUuid(share.uuid); - if (conversation == null) { - return; - } - }else{ - Account account; - try { - account = xmppConnectionService.findAccountByJid(Jid.fromString(share.account)); - } catch (final InvalidJidException e) { - account = null; - } - if (account == null) { - return; - } - - try { - conversation = xmppConnectionService - .findOrCreateConversation(account, Jid.fromString(share.contact), false); - } catch (final InvalidJidException e) { - return; - } - } - share(conversation); - } - - private void share(final Conversation conversation) { - final Account account = conversation.getAccount(); - mListView.setEnabled(false); - if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP && !hasPgp()) { - if (share.uuid == null) { - showInstallPgpDialog(); - } else { - Toast.makeText(this,R.string.openkeychain_not_installed,Toast.LENGTH_SHORT).show(); - finish(); - } - return; - } - if (share.uris.size() != 0) { - final long max = account.getXmppConnection() - .getFeatures() - .getMaxHttpUploadSize(); - OnPresenceSelected callback; - if (this.share.image) { - // TODO: attachementCounter should be set and decremented correctly - callback = new OnPresenceSelected() { - @Override - public void onPresenceSelected() { - ResizePictureUserDecisionListener userDecisionListener = new ShareWithResizePictureUserDecisionListener(ShareWithActivity.this, conversation, xmppConnectionService, share.uris); - UserDecisionDialog userDecisionDialog = new UserDecisionDialog(ShareWithActivity.this, R.string.userdecision_question_resize_picture, userDecisionListener); - userDecisionDialog.decide(ConversationsPlusPreferences.resizePicture()); - } - }; - } else { - attachmentCounter.set(share.uris.size()); - callback = new OnPresenceSelected() { - @Override - public void onPresenceSelected() { - replaceToast(getString(R.string.preparing_file)); - ConversationUtil.attachFileToConversation(conversation, share.uris.get(0), attachFileCallback); - switchToConversation(conversation, null, true); - finish(); - } - }; - } - if (AccountUtil.isHttpUploadAvailable(account) - && (conversation.getMode() == Conversation.MODE_MULTI - || FileUtils.allFilesUnderSize(this, share.uris, max)) - && conversation.getNextEncryption() != Message.ENCRYPTION_OTR) { - callback.onPresenceSelected(); - } else { - selectPresence(conversation, callback); - } - } else { - if (mReturnToPrevious && this.share.text != null && !this.share.text.isEmpty() ) { - final OnPresenceSelected callback = new OnPresenceSelected() { - @Override - public void onPresenceSelected() { - Message message = new Message(conversation,share.text, conversation.getNextEncryption()); - if (conversation.getNextEncryption() == Message.ENCRYPTION_OTR) { - message.setCounterpart(conversation.getNextCounterpart()); - } - xmppConnectionService.sendMessage(message); - replaceToast(getString(R.string.shared_text_with_x, conversation.getName())); - finish(); - } - }; - if (conversation.getNextEncryption() == Message.ENCRYPTION_OTR) { - selectPresence(conversation, callback); - } else { - callback.onPresenceSelected(); - } - } else { - switchToConversation(conversation, this.share.text, true); - finish(); - } - } - - } - - public void refreshUiReal() { - xmppConnectionService.populateWithOrderedConversations(mConversations, this.share != null && this.share.uris.size() == 0); - mAdapter.notifyDataSetChanged(); - } - - @Override - public void onBackPressed() { - if (attachmentCounter.get() >= 1) { - replaceToast(getString(R.string.sharing_files_please_wait)); - } else { - super.onBackPressed(); - } - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/StartConversationActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/StartConversationActivity.java deleted file mode 100644 index 2dc8d1a5..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/StartConversationActivity.java +++ /dev/null @@ -1,886 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.Manifest; -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.app.ActionBar; -import android.app.ActionBar.Tab; -import android.app.ActionBar.TabListener; -import android.app.AlertDialog; -import android.app.Fragment; -import android.app.FragmentTransaction; -import android.app.ListFragment; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.nfc.NdefMessage; -import android.nfc.NdefRecord; -import android.nfc.NfcAdapter; -import android.os.Build; -import android.os.Bundle; -import android.os.Parcelable; -import android.support.v13.app.FragmentPagerAdapter; -import android.support.v4.view.ViewPager; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import android.widget.AdapterView; -import android.widget.AdapterView.AdapterContextMenuInfo; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ArrayAdapter; -import android.widget.AutoCompleteTextView; -import android.widget.CheckBox; -import android.widget.Checkable; -import android.widget.EditText; -import android.widget.ListView; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -import com.google.zxing.integration.android.IntentIntegrator; -import com.google.zxing.integration.android.IntentResult; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -import de.thedevstack.android.logcat.Logging; -import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Blockable; -import de.thedevstack.conversationsplus.entities.Bookmark; -import de.thedevstack.conversationsplus.entities.Contact; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.entities.ListItem; -import de.thedevstack.conversationsplus.entities.Presence; -import de.thedevstack.conversationsplus.services.XmppConnectionService.OnRosterUpdate; -import de.thedevstack.conversationsplus.ui.adapter.KnownHostsAdapter; -import de.thedevstack.conversationsplus.ui.adapter.ListItemAdapter; -import de.thedevstack.conversationsplus.utils.XmppUri; -import de.thedevstack.conversationsplus.xmpp.OnUpdateBlocklist; -import de.thedevstack.conversationsplus.xmpp.XmppConnection; -import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class StartConversationActivity extends XmppActivity implements OnRosterUpdate, OnUpdateBlocklist { - - public int conference_context_id; - public int contact_context_id; - private Tab mContactsTab; - private Tab mConferencesTab; - private ViewPager mViewPager; - private MyListFragment mContactsListFragment = new MyListFragment(); - private List<ListItem> contacts = new ArrayList<>(); - private ArrayAdapter<ListItem> mContactsAdapter; - private MyListFragment mConferenceListFragment = new MyListFragment(); - private List<ListItem> conferences = new ArrayList<ListItem>(); - private ArrayAdapter<ListItem> mConferenceAdapter; - private List<String> mActivatedAccounts = new ArrayList<String>(); - private List<String> mKnownHosts; - private List<String> mKnownConferenceHosts; - private Invite mPendingInvite = null; - private Menu mOptionsMenu; - private EditText mSearchEditText; - private AtomicBoolean mRequestedContactsPermission = new AtomicBoolean(false); - private final int REQUEST_SYNC_CONTACTS = 0x3b28cf; - - private MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() { - - @Override - public boolean onMenuItemActionExpand(MenuItem item) { - mSearchEditText.post(new Runnable() { - - @Override - public void run() { - mSearchEditText.requestFocus(); - InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(mSearchEditText, - InputMethodManager.SHOW_IMPLICIT); - } - }); - - return true; - } - - @Override - public boolean onMenuItemActionCollapse(MenuItem item) { - InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(), - InputMethodManager.HIDE_IMPLICIT_ONLY); - mSearchEditText.setText(""); - filter(null); - return true; - } - }; - private boolean mHideOfflineContacts = false; - private TabListener mTabListener = new TabListener() { - - @Override - public void onTabUnselected(Tab tab, FragmentTransaction ft) { - return; - } - - @Override - public void onTabSelected(Tab tab, FragmentTransaction ft) { - mViewPager.setCurrentItem(tab.getPosition()); - onTabChanged(); - } - - @Override - public void onTabReselected(Tab tab, FragmentTransaction ft) { - return; - } - }; - private ViewPager.SimpleOnPageChangeListener mOnPageChangeListener = new ViewPager.SimpleOnPageChangeListener() { - @Override - public void onPageSelected(int position) { - if (getActionBar() != null) { - getActionBar().setSelectedNavigationItem(position); - } - onTabChanged(); - } - }; - private TextWatcher mSearchTextWatcher = new TextWatcher() { - - @Override - public void afterTextChanged(Editable editable) { - filter(editable.toString()); - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, - int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, - int count) { - } - }; - private MenuItem mMenuSearchView; - private ListItemAdapter.OnTagClickedListener mOnTagClickedListener = new ListItemAdapter.OnTagClickedListener() { - @Override - public void onTagClicked(String tag) { - if (mMenuSearchView != null) { - mMenuSearchView.expandActionView(); - mSearchEditText.setText(""); - mSearchEditText.append(tag); - filter(tag); - } - } - }; - private String mInitialJid; - - @Override - public void onRosterUpdate() { - this.refreshUi(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_start_conversation); - this.mHideOfflineContacts = ConversationsPlusPreferences.hideOffline(); - mViewPager = (ViewPager) findViewById(R.id.start_conversation_view_pager); - ActionBar actionBar = getActionBar(); - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); - - mContactsTab = actionBar.newTab().setText(R.string.contacts) - .setTabListener(mTabListener); - mConferencesTab = actionBar.newTab().setText(R.string.conferences) - .setTabListener(mTabListener); - actionBar.addTab(mContactsTab); - actionBar.addTab(mConferencesTab); - - mViewPager.setOnPageChangeListener(mOnPageChangeListener); - mViewPager.setAdapter(new FragmentPagerAdapter(getFragmentManager()) { - - @Override - public int getCount() { - return 2; - } - - @Override - public Fragment getItem(int position) { - if (position == 0) { - return mContactsListFragment; - } else { - return mConferenceListFragment; - } - } - }); - - mConferenceAdapter = new ListItemAdapter(this, conferences); - mConferenceListFragment.setListAdapter(mConferenceAdapter); - mConferenceListFragment.setContextMenu(R.menu.conference_context); - mConferenceListFragment - .setOnListItemClickListener(new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView<?> arg0, View arg1, - int position, long arg3) { - openConversationForBookmark(position); - } - }); - - mContactsAdapter = new ListItemAdapter(this, contacts); - ((ListItemAdapter) mContactsAdapter).setOnTagClickedListener(this.mOnTagClickedListener); - mContactsListFragment.setListAdapter(mContactsAdapter); - mContactsListFragment.setContextMenu(R.menu.contact_context); - mContactsListFragment - .setOnListItemClickListener(new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView<?> arg0, View arg1, - int position, long arg3) { - openConversationForContact(position); - } - }); - - - } - - @Override - public void onStart() { - super.onStart(); - askForContactsPermissions(); - } - - protected void openConversationForContact(int position) { - Contact contact = (Contact) contacts.get(position); - Conversation conversation = xmppConnectionService - .findOrCreateConversation(contact.getAccount(), - contact.getJid(), false); - switchToConversation(conversation); - } - - protected void openConversationForContact() { - int position = contact_context_id; - openConversationForContact(position); - } - - protected void openConversationForBookmark() { - openConversationForBookmark(conference_context_id); - } - - protected void openConversationForBookmark(int position) { - Bookmark bookmark = (Bookmark) conferences.get(position); - Jid jid = bookmark.getJid(); - if (jid == null) { - Toast.makeText(this,R.string.invalid_jid,Toast.LENGTH_SHORT).show(); - return; - } - Conversation conversation = xmppConnectionService.findOrCreateConversation(bookmark.getAccount(),jid, true); - conversation.setBookmark(bookmark); - if (!conversation.getMucOptions().online()) { - xmppConnectionService.joinMuc(conversation); - } - if (!bookmark.autojoin() && ConversationsPlusPreferences.autojoin()) { - bookmark.setAutojoin(true); - xmppConnectionService.pushBookmarks(bookmark.getAccount()); - } - switchToConversation(conversation); - } - - protected void openDetailsForContact() { - int position = contact_context_id; - Contact contact = (Contact) contacts.get(position); - switchToContactDetails(contact); - } - - protected void toggleContactBlock() { - final int position = contact_context_id; - BlockContactDialog.show(this, xmppConnectionService, (Contact) contacts.get(position)); - } - - protected void deleteContact() { - final int position = contact_context_id; - final Contact contact = (Contact) contacts.get(position); - final AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setNegativeButton(R.string.cancel, null); - builder.setTitle(R.string.action_delete_contact); - builder.setMessage(getString(R.string.remove_contact_text, - contact.getJid())); - builder.setPositiveButton(R.string.delete, new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - xmppConnectionService.deleteContactOnServer(contact); - filter(mSearchEditText.getText().toString()); - } - }); - builder.create().show(); - } - - protected void deleteConference() { - int position = conference_context_id; - final Bookmark bookmark = (Bookmark) conferences.get(position); - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setNegativeButton(R.string.cancel, null); - builder.setTitle(R.string.delete_bookmark); - builder.setMessage(getString(R.string.remove_bookmark_text, - bookmark.getJid())); - builder.setPositiveButton(R.string.delete, new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - bookmark.unregisterConversation(); - Account account = bookmark.getAccount(); - account.getBookmarks().remove(bookmark); - xmppConnectionService.pushBookmarks(account); - filter(mSearchEditText.getText().toString()); - } - }); - builder.create().show(); - - } - - @SuppressLint("InflateParams") - protected void showCreateContactDialog(final String prefilledJid, final String fingerprint) { - EnterJidDialog dialog = new EnterJidDialog( - this, mKnownHosts, mActivatedAccounts, - getString(R.string.create_contact), getString(R.string.create), - prefilledJid, null, fingerprint == null - ); - - dialog.setOnEnterJidDialogPositiveListener(new EnterJidDialog.OnEnterJidDialogPositiveListener() { - @Override - public boolean onEnterJidDialogPositive(Jid accountJid, Jid contactJid) throws EnterJidDialog.JidError { - if (!xmppConnectionServiceBound) { - return false; - } - - final Account account = xmppConnectionService.findAccountByJid(accountJid); - if (account == null) { - return true; - } - - final Contact contact = account.getRoster().getContact(contactJid); - if (contact.showInRoster()) { - throw new EnterJidDialog.JidError(getString(R.string.contact_already_exists)); - } else { - contact.addOtrFingerprint(fingerprint); - xmppConnectionService.createContact(contact); - switchToConversation(contact); - return true; - } - } - }); - - dialog.show(); - } - - @SuppressLint("InflateParams") - protected void showJoinConferenceDialog(final String prefilledJid) { - final AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.join_conference); - final View dialogView = getLayoutInflater().inflate(R.layout.join_conference_dialog, null); - final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account); - final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid); - final boolean lock = Config.LOCK_DOMAINS_IN_CONVERSATIONS && Config.CONFERENCE_DOMAIN_LOCK != null; - final TextView jabberIdDesc = (TextView) dialogView.findViewById(R.id.jabber_id); - jabberIdDesc.setText(lock ? R.string.conference_name : R.string.conference_address); - jid.setHint(lock ? R.string.conference_name : R.string.conference_address_example); - if (!lock) { - jid.setAdapter(new KnownHostsAdapter(this, android.R.layout.simple_list_item_1, mKnownConferenceHosts)); - } - if (prefilledJid != null) { - jid.append(prefilledJid); - } - populateAccountSpinner(this, mActivatedAccounts, spinner); - final Checkable bookmarkCheckBox = (CheckBox) dialogView - .findViewById(R.id.bookmark); - builder.setView(dialogView); - builder.setNegativeButton(R.string.cancel, null); - builder.setPositiveButton(R.string.join, null); - final AlertDialog dialog = builder.create(); - dialog.show(); - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener( - new View.OnClickListener() { - - @Override - public void onClick(final View v) { - if (!xmppConnectionServiceBound) { - return; - } - final Account account = getSelectedAccount(spinner); - if (account == null) { - return; - } - final Jid conferenceJid; - try { - if (lock) { - conferenceJid = Jid.fromParts(jid.getText().toString(),Config.CONFERENCE_DOMAIN_LOCK, null); - } else { - conferenceJid = Jid.fromString(jid.getText().toString()); - } - } catch (final InvalidJidException e) { - jid.setError(getString(lock ? R.string.invalid_conference_name : R.string.invalid_jid)); - return; - } - - if (bookmarkCheckBox.isChecked()) { - if (account.hasBookmarkFor(conferenceJid)) { - jid.setError(getString(R.string.bookmark_already_exists)); - } else { - final Bookmark bookmark = new Bookmark(account, conferenceJid.toBareJid()); - bookmark.setAutojoin(ConversationsPlusPreferences.autojoin()); - String nick = conferenceJid.getResourcepart(); - if (nick != null && !nick.isEmpty()) { - bookmark.setNick(nick); - } - account.getBookmarks().add(bookmark); - xmppConnectionService.pushBookmarks(account); - final Conversation conversation = xmppConnectionService - .findOrCreateConversation(account, - conferenceJid, true); - conversation.setBookmark(bookmark); - if (!conversation.getMucOptions().online()) { - xmppConnectionService.joinMuc(conversation); - } - dialog.dismiss(); - switchToConversation(conversation); - } - } else { - final Conversation conversation = xmppConnectionService - .findOrCreateConversation(account, - conferenceJid, true); - if (!conversation.getMucOptions().online()) { - xmppConnectionService.joinMuc(conversation); - } - dialog.dismiss(); - switchToConversation(conversation); - } - } - }); - } - - private Account getSelectedAccount(Spinner spinner) { - if (!spinner.isEnabled()) { - return null; - } - Jid jid; - try { - if (Config.DOMAIN_LOCK != null) { - jid = Jid.fromParts((String) spinner.getSelectedItem(), Config.DOMAIN_LOCK, null); - } else { - jid = Jid.fromString((String) spinner.getSelectedItem()); - } - } catch (final InvalidJidException e) { - return null; - } - return xmppConnectionService.findAccountByJid(jid); - } - - protected void switchToConversation(Contact contact) { - Conversation conversation = xmppConnectionService - .findOrCreateConversation(contact.getAccount(), - contact.getJid(), false); - switchToConversation(conversation); - } - - public static void populateAccountSpinner(Context context, List<String> accounts, Spinner spinner) { - if (accounts.size() > 0) { - ArrayAdapter<String> adapter = new ArrayAdapter<>(context, - android.R.layout.simple_spinner_item, accounts); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spinner.setAdapter(adapter); - spinner.setEnabled(true); - } else { - ArrayAdapter<String> adapter = new ArrayAdapter<>(context, - android.R.layout.simple_spinner_item, - Arrays.asList(new String[]{context.getString(R.string.no_accounts)})); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spinner.setAdapter(adapter); - spinner.setEnabled(false); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - this.mOptionsMenu = menu; - getMenuInflater().inflate(R.menu.start_conversation, menu); - MenuItem menuCreateContact = menu.findItem(R.id.action_create_contact); - MenuItem menuCreateConference = menu.findItem(R.id.action_join_conference); - MenuItem menuHideOffline = menu.findItem(R.id.action_hide_offline); - menuHideOffline.setChecked(this.mHideOfflineContacts); - mMenuSearchView = menu.findItem(R.id.action_search); - mMenuSearchView.setOnActionExpandListener(mOnActionExpandListener); - View mSearchView = mMenuSearchView.getActionView(); - mSearchEditText = (EditText) mSearchView - .findViewById(R.id.search_field); - mSearchEditText.addTextChangedListener(mSearchTextWatcher); - if (getActionBar().getSelectedNavigationIndex() == 0) { - menuCreateConference.setVisible(false); - } else { - menuCreateContact.setVisible(false); - } - if (mInitialJid != null) { - mMenuSearchView.expandActionView(); - mSearchEditText.append(mInitialJid); - filter(mInitialJid); - } - return super.onCreateOptionsMenu(menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.action_create_contact: - showCreateContactDialog(null,null); - return true; - case R.id.action_join_conference: - showJoinConferenceDialog(null); - return true; - case R.id.action_scan_qr_code: - new IntentIntegrator(this).initiateScan(); - return true; - case R.id.action_hide_offline: - mHideOfflineContacts = !item.isChecked(); // the item is the menu item which is displayed, the inversion here calculates the new value - ConversationsPlusPreferences.commitHideOffline(mHideOfflineContacts); - if (mSearchEditText != null) { - filter(mSearchEditText.getText().toString()); - } - invalidateOptionsMenu(); // Since the selection of this item changed the checked value, the options menu is now invalid - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_SEARCH && !event.isLongPress()) { - mOptionsMenu.findItem(R.id.action_search).expandActionView(); - return true; - } - return super.onKeyUp(keyCode, event); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent intent) { - if ((requestCode & 0xFFFF) == IntentIntegrator.REQUEST_CODE) { - IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent); - if (scanResult != null && scanResult.getFormatName() != null) { - String data = scanResult.getContents(); - Invite invite = new Invite(data); - if (xmppConnectionServiceBound) { - invite.invite(); - } else if (invite.getJid() != null) { - this.mPendingInvite = invite; - } else { - this.mPendingInvite = null; - } - } - } - super.onActivityResult(requestCode, requestCode, intent); - } - - private void askForContactsPermissions() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { - if (mRequestedContactsPermission.compareAndSet(false, true)) { - if (shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.sync_with_contacts); - builder.setMessage(R.string.sync_with_contacts_long); - builder.setPositiveButton(R.string.next, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_SYNC_CONTACTS); - } - } - }); - builder.create().show(); - } else { - requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, 0); - } - } - } - } - } - - @Override - public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { - if (grantResults.length > 0) - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - if (requestCode == REQUEST_SYNC_CONTACTS && xmppConnectionServiceBound) { - xmppConnectionService.loadPhoneContacts(); - } - } - } - - @Override - protected void onBackendConnected() { - this.mActivatedAccounts.clear(); - for (Account account : xmppConnectionService.getAccounts()) { - if (account.getStatus() != Account.State.DISABLED) { - if (Config.DOMAIN_LOCK != null) { - this.mActivatedAccounts.add(account.getJid().getLocalpart()); - } else { - this.mActivatedAccounts.add(account.getJid().toBareJid().toString()); - } - } - } - final Intent intent = getIntent(); - final ActionBar ab = getActionBar(); - if (intent != null && intent.getBooleanExtra("init",false) && ab != null) { - ab.setDisplayShowHomeEnabled(false); - ab.setDisplayHomeAsUpEnabled(false); - ab.setHomeButtonEnabled(false); - } - this.mKnownHosts = xmppConnectionService.getKnownHosts(); - this.mKnownConferenceHosts = xmppConnectionService.getKnownConferenceHosts(); - if (this.mPendingInvite != null) { - mPendingInvite.invite(); - this.mPendingInvite = null; - } else if (!handleIntent(getIntent())) { - if (mSearchEditText != null) { - filter(mSearchEditText.getText().toString()); - } else { - filter(null); - } - } - setIntent(null); - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - Invite getInviteJellyBean(NdefRecord record) { - return new Invite(record.toUri()); - } - - protected boolean handleIntent(Intent intent) { - if (intent == null || intent.getAction() == null) { - return false; - } - switch (intent.getAction()) { - case Intent.ACTION_SENDTO: - case Intent.ACTION_VIEW: - Logging.d(Config.LOGTAG, "received uri=" + intent.getData()); - return new Invite(intent.getData()).invite(); - case NfcAdapter.ACTION_NDEF_DISCOVERED: - for (Parcelable message : getIntent().getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)) { - if (message instanceof NdefMessage) { - Logging.d(Config.LOGTAG, "received message=" + message); - for (NdefRecord record : ((NdefMessage) message).getRecords()) { - switch (record.getTnf()) { - case NdefRecord.TNF_WELL_KNOWN: - if (Arrays.equals(record.getType(), NdefRecord.RTD_URI)) { - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - return getInviteJellyBean(record).invite(); - } else { - byte[] payload = record.getPayload(); - if (payload[0] == 0) { - return new Invite(Uri.parse(new String(Arrays.copyOfRange( - payload, 1, payload.length)))).invite(); - } - } - } - } - } - } - } - } - return false; - } - - private boolean handleJid(Invite invite) { - List<Contact> contacts = xmppConnectionService.findContacts(invite.getJid()); - if (contacts.size() == 0) { - showCreateContactDialog(invite.getJid().toString(),invite.getFingerprint()); - return false; - } else if (contacts.size() == 1) { - Contact contact = contacts.get(0); - if (invite.getFingerprint() != null) { - if (contact.addOtrFingerprint(invite.getFingerprint())) { - Logging.d(Config.LOGTAG,"added new fingerprint"); - xmppConnectionService.syncRosterToDisk(contact.getAccount()); - } - } - switchToConversation(contact); - return true; - } else { - if (mMenuSearchView != null) { - mMenuSearchView.expandActionView(); - mSearchEditText.setText(""); - mSearchEditText.append(invite.getJid().toString()); - filter(invite.getJid().toString()); - } else { - mInitialJid = invite.getJid().toString(); - } - return true; - } - } - - protected void filter(String needle) { - if (xmppConnectionServiceBound) { - this.filterContacts(needle); - this.filterConferences(needle); - } - } - - protected void filterContacts(String needle) { - this.contacts.clear(); - for (Account account : xmppConnectionService.getAccounts()) { - if (account.getStatus() != Account.State.DISABLED) { - for (Contact contact : account.getRoster().getContacts()) { - Presence p = contact.getPresences().getMostAvailablePresence(); - Presence.Status s = p == null ? Presence.Status.OFFLINE : p.getStatus(); - if (contact.showInRoster() && contact.match(needle) - && (!this.mHideOfflineContacts - || (needle != null && !needle.isEmpty()) - || s.compareTo(Presence.Status.OFFLINE) < 0)) { - this.contacts.add(contact); - } - } - } - } - Collections.sort(this.contacts); - mContactsAdapter.notifyDataSetChanged(); - } - - protected void filterConferences(String needle) { - this.conferences.clear(); - for (Account account : xmppConnectionService.getAccounts()) { - if (account.getStatus() != Account.State.DISABLED) { - for (Bookmark bookmark : account.getBookmarks()) { - if (bookmark.match(needle)) { - this.conferences.add(bookmark); - } - } - } - } - Collections.sort(this.conferences); - mConferenceAdapter.notifyDataSetChanged(); - } - - private void onTabChanged() { - invalidateOptionsMenu(); - } - - @Override - public void OnUpdateBlocklist(final Status status) { - refreshUi(); - } - - @Override - protected void refreshUiReal() { - if (mSearchEditText != null) { - filter(mSearchEditText.getText().toString()); - } - } - - public static class MyListFragment extends ListFragment { - private AdapterView.OnItemClickListener mOnItemClickListener; - private int mResContextMenu; - - public void setContextMenu(final int res) { - this.mResContextMenu = res; - } - - @Override - public void onListItemClick(final ListView l, final View v, final int position, final long id) { - if (mOnItemClickListener != null) { - mOnItemClickListener.onItemClick(l, v, position, id); - } - } - - public void setOnListItemClickListener(AdapterView.OnItemClickListener l) { - this.mOnItemClickListener = l; - } - - @Override - public void onViewCreated(final View view, final Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - registerForContextMenu(getListView()); - getListView().setFastScrollEnabled(true); - } - - @Override - public void onCreateContextMenu(final ContextMenu menu, final View v, - final ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu, v, menuInfo); - final StartConversationActivity activity = (StartConversationActivity) getActivity(); - activity.getMenuInflater().inflate(mResContextMenu, menu); - final AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo; - if (mResContextMenu == R.menu.conference_context) { - activity.conference_context_id = acmi.position; - } else if (mResContextMenu == R.menu.contact_context){ - activity.contact_context_id = acmi.position; - final Blockable contact = (Contact) activity.contacts.get(acmi.position); - final MenuItem blockUnblockItem = menu.findItem(R.id.context_contact_block_unblock); - XmppConnection xmpp = contact.getAccount().getXmppConnection(); - if (xmpp != null && xmpp.getFeatures().blocking()) { - if (contact.isBlocked()) { - blockUnblockItem.setTitle(R.string.unblock_contact); - } else { - blockUnblockItem.setTitle(R.string.block_contact); - } - } else { - blockUnblockItem.setVisible(false); - } - } - } - - @Override - public boolean onContextItemSelected(final MenuItem item) { - StartConversationActivity activity = (StartConversationActivity) getActivity(); - switch (item.getItemId()) { - case R.id.context_start_conversation: - activity.openConversationForContact(); - break; - case R.id.context_contact_details: - activity.openDetailsForContact(); - break; - case R.id.context_contact_block_unblock: - activity.toggleContactBlock(); - break; - case R.id.context_delete_contact: - activity.deleteContact(); - break; - case R.id.context_join_conference: - activity.openConversationForBookmark(); - break; - case R.id.context_delete_conference: - activity.deleteConference(); - } - return true; - } - } - - private class Invite extends XmppUri { - - public Invite(final Uri uri) { - super(uri); - } - - public Invite(final String uri) { - super(uri); - } - - boolean invite() { - if (jid != null) { - if (muc) { - showJoinConferenceDialog(jid); - } else { - return handleJid(this); - } - } - return false; - } - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/TimePreference.java b/src/main/java/de/thedevstack/conversationsplus/ui/TimePreference.java deleted file mode 100644 index bfe7c8f4..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/TimePreference.java +++ /dev/null @@ -1,105 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.content.Context; -import android.content.res.TypedArray; -import android.preference.DialogPreference; -import android.preference.Preference; -import android.util.AttributeSet; -import android.view.View; -import android.widget.TimePicker; - -import java.text.DateFormat; -import java.util.Calendar; -import java.util.Date; - -public class TimePreference extends DialogPreference implements Preference.OnPreferenceChangeListener { - private TimePicker picker = null; - public final static long DEFAULT_VALUE = 0; - - public TimePreference(final Context context, final AttributeSet attrs) { - super(context, attrs, 0); - this.setOnPreferenceChangeListener(this); - } - - protected void setTime(final long time) { - persistLong(time); - notifyDependencyChange(shouldDisableDependents()); - notifyChanged(); - } - - protected void updateSummary(final long time) { - final DateFormat dateFormat = android.text.format.DateFormat.getTimeFormat(getContext()); - final Date date = new Date(time); - setSummary(dateFormat.format(date.getTime())); - } - - @Override - protected View onCreateDialogView() { - picker = new TimePicker(getContext()); - picker.setIs24HourView(android.text.format.DateFormat.is24HourFormat(getContext())); - return picker; - } - - protected Calendar getPersistedTime() { - final Calendar c = Calendar.getInstance(); - c.setTimeInMillis(getPersistedLong(DEFAULT_VALUE)); - - return c; - } - - @SuppressWarnings("NullableProblems") - @Override - protected void onBindDialogView(final View v) { - super.onBindDialogView(v); - final Calendar c = getPersistedTime(); - - picker.setCurrentHour(c.get(Calendar.HOUR_OF_DAY)); - picker.setCurrentMinute(c.get(Calendar.MINUTE)); - } - - @Override - protected void onDialogClosed(final boolean positiveResult) { - super.onDialogClosed(positiveResult); - - if (positiveResult) { - final Calendar c = Calendar.getInstance(); - c.set(Calendar.MINUTE, picker.getCurrentMinute()); - c.set(Calendar.HOUR_OF_DAY, picker.getCurrentHour()); - - - if (!callChangeListener(c.getTimeInMillis())) { - return; - } - - setTime(c.getTimeInMillis()); - } - } - - @Override - protected Object onGetDefaultValue(final TypedArray a, final int index) { - return a.getInteger(index, 0); - } - - @Override - protected void onSetInitialValue(final boolean restorePersistedValue, final Object defaultValue) { - long time; - if (defaultValue == null) { - time = restorePersistedValue ? getPersistedLong(DEFAULT_VALUE) : DEFAULT_VALUE; - } else if (defaultValue instanceof Long) { - time = restorePersistedValue ? getPersistedLong((Long) defaultValue) : (Long) defaultValue; - } else if (defaultValue instanceof Calendar) { - time = restorePersistedValue ? getPersistedLong(((Calendar)defaultValue).getTimeInMillis()) : ((Calendar)defaultValue).getTimeInMillis(); - } else { - time = restorePersistedValue ? getPersistedLong(DEFAULT_VALUE) : DEFAULT_VALUE; - } - - setTime(time); - updateSummary(time); - } - - @Override - public boolean onPreferenceChange(final Preference preference, final Object newValue) { - ((TimePreference) preference).updateSummary((Long)newValue); - return true; - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/TrustKeysActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/TrustKeysActivity.java deleted file mode 100644 index dfddbb78..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/TrustKeysActivity.java +++ /dev/null @@ -1,319 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.CompoundButton; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.Toast; - -import org.whispersystems.libaxolotl.IdentityKey; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import de.thedevstack.conversationsplus.ConversationsPlusColors; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.crypto.axolotl.AxolotlService; -import de.thedevstack.conversationsplus.crypto.axolotl.XmppAxolotlSession; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.utils.ui.TextViewUtil; -import de.thedevstack.conversationsplus.xmpp.OnKeyStatusUpdated; -import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdated { - private List<Jid> contactJids; - - private Account mAccount; - private Conversation mConversation; - private TextView keyErrorMessage; - private LinearLayout keyErrorMessageCard; - private TextView ownKeysTitle; - private LinearLayout ownKeys; - private LinearLayout ownKeysCard; - private LinearLayout foreignKeys; - private Button mSaveButton; - private Button mCancelButton; - - private AxolotlService.FetchStatus lastFetchReport = AxolotlService.FetchStatus.SUCCESS; - - private final Map<String, Boolean> ownKeysToTrust = new HashMap<>(); - private final Map<Jid,Map<String, Boolean>> foreignKeysToTrust = new HashMap<>(); - - private final OnClickListener mSaveButtonListener = new OnClickListener() { - @Override - public void onClick(View v) { - commitTrusts(); - finishOk(); - } - }; - - private final OnClickListener mCancelButtonListener = new OnClickListener() { - @Override - public void onClick(View v) { - setResult(RESULT_CANCELED); - finish(); - } - }; - - @Override - protected void refreshUiReal() { - invalidateOptionsMenu(); - populateView(); - } - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_trust_keys); - this.contactJids = new ArrayList<>(); - for(String jid : getIntent().getStringArrayExtra("contacts")) { - try { - this.contactJids.add(Jid.fromString(jid)); - } catch (InvalidJidException e) { - e.printStackTrace(); - } - } - - keyErrorMessageCard = (LinearLayout) findViewById(R.id.key_error_message_card); - keyErrorMessage = (TextView) findViewById(R.id.key_error_message); - ownKeysTitle = (TextView) findViewById(R.id.own_keys_title); - ownKeys = (LinearLayout) findViewById(R.id.own_keys_details); - ownKeysCard = (LinearLayout) findViewById(R.id.own_keys_card); - foreignKeys = (LinearLayout) findViewById(R.id.foreign_keys); - mCancelButton = (Button) findViewById(R.id.cancel_button); - mCancelButton.setOnClickListener(mCancelButtonListener); - mSaveButton = (Button) findViewById(R.id.save_button); - mSaveButton.setOnClickListener(mSaveButtonListener); - - - if (getActionBar() != null) { - getActionBar().setHomeButtonEnabled(true); - getActionBar().setDisplayHomeAsUpEnabled(true); - } - } - - private void populateView() { - setTitle(getString(R.string.trust_omemo_fingerprints)); - ownKeys.removeAllViews(); - foreignKeys.removeAllViews(); - boolean hasOwnKeys = false; - boolean hasForeignKeys = false; - for(final String fingerprint : ownKeysToTrust.keySet()) { - hasOwnKeys = true; - addFingerprintRowWithListeners(ownKeys, mAccount, fingerprint, false, - XmppAxolotlSession.Trust.fromBoolean(ownKeysToTrust.get(fingerprint)), false, - new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - ownKeysToTrust.put(fingerprint, isChecked); - // own fingerprints have no impact on locked status. - } - }, - null, - null - ); - } - - synchronized (this.foreignKeysToTrust) { - for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) { - hasForeignKeys = true; - final LinearLayout layout = (LinearLayout) getLayoutInflater().inflate(R.layout.keys_card, foreignKeys, false); - final Jid jid = entry.getKey(); - final TextView header = (TextView) layout.findViewById(R.id.foreign_keys_title); - final LinearLayout keysContainer = (LinearLayout) layout.findViewById(R.id.foreign_keys_details); - final TextView informNoKeys = (TextView) layout.findViewById(R.id.no_keys_to_accept); - header.setText(jid.toString()); - final Map<String, Boolean> fingerprints = entry.getValue(); - for (final String fingerprint : fingerprints.keySet()) { - addFingerprintRowWithListeners(keysContainer, mAccount, fingerprint, false, - XmppAxolotlSession.Trust.fromBoolean(fingerprints.get(fingerprint)), false, - new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - fingerprints.put(fingerprint, isChecked); - lockOrUnlockAsNeeded(); - } - }, - null, - null - ); - } - if (fingerprints.size() == 0) { - informNoKeys.setVisibility(View.VISIBLE); - informNoKeys.setText(getString(R.string.no_keys_just_confirm,mAccount.getRoster().getContact(jid).getDisplayName())); - } else { - informNoKeys.setVisibility(View.GONE); - } - foreignKeys.addView(layout); - } - } - - ownKeysTitle.setText(mAccount.getJid().toBareJid().toString()); - ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE); - foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE); - if(hasPendingKeyFetches()) { - TextViewUtil.disable(this.mSaveButton, ConversationsPlusColors.secondaryText(), R.string.fetching_keys); - } else { - if (!hasForeignKeys && hasNoOtherTrustedKeys()) { - keyErrorMessageCard.setVisibility(View.VISIBLE); - if (lastFetchReport == AxolotlService.FetchStatus.ERROR - || mAccount.getAxolotlService().fetchMapHasErrors(contactJids)) { - keyErrorMessage.setText(R.string.error_no_keys_to_trust_server_error); - } else { - keyErrorMessage.setText(R.string.error_no_keys_to_trust); - } - ownKeys.removeAllViews(); - ownKeysCard.setVisibility(View.GONE); - foreignKeys.removeAllViews(); - foreignKeys.setVisibility(View.GONE); - } - lockOrUnlockAsNeeded(); - mSaveButton.setText(R.string.done); - } - } - - private boolean reloadFingerprints() { - List<Jid> acceptedTargets = mConversation == null ? new ArrayList<Jid>() : mConversation.getAcceptedCryptoTargets(); - ownKeysToTrust.clear(); - AxolotlService service = this.mAccount.getAxolotlService(); - Set<IdentityKey> ownKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED); - for(final IdentityKey identityKey : ownKeysSet) { - if(!ownKeysToTrust.containsKey(identityKey)) { - ownKeysToTrust.put(identityKey.getFingerprint().replaceAll("\\s", ""), false); - } - } - synchronized (this.foreignKeysToTrust) { - foreignKeysToTrust.clear(); - for (Jid jid : contactJids) { - Set<IdentityKey> foreignKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, jid); - if (hasNoOtherTrustedKeys(jid) && ownKeysSet.size() == 0) { - foreignKeysSet.addAll(service.getKeysWithTrust(XmppAxolotlSession.Trust.UNTRUSTED, jid)); - } - Map<String, Boolean> foreignFingerprints = new HashMap<>(); - for (final IdentityKey identityKey : foreignKeysSet) { - if (!foreignFingerprints.containsKey(identityKey)) { - foreignFingerprints.put(identityKey.getFingerprint().replaceAll("\\s", ""), false); - } - } - if (foreignFingerprints.size() > 0 || !acceptedTargets.contains(jid)) { - foreignKeysToTrust.put(jid, foreignFingerprints); - } - } - } - return ownKeysSet.size() + foreignKeysToTrust.size() > 0; - } - - @Override - public void onBackendConnected() { - Intent intent = getIntent(); - this.mAccount = extractAccount(intent); - if (this.mAccount != null && intent != null) { - String uuid = intent.getStringExtra("conversation"); - this.mConversation = xmppConnectionService.findConversationByUuid(uuid); - reloadFingerprints(); - populateView(); - } - } - - private boolean hasNoOtherTrustedKeys() { - return mAccount == null || mAccount.getAxolotlService().anyTargetHasNoTrustedKeys(contactJids); - } - - private boolean hasNoOtherTrustedKeys(Jid contact) { - return mAccount == null || mAccount.getAxolotlService().getNumTrustedKeys(contact) == 0; - } - - private boolean hasPendingKeyFetches() { - return mAccount != null && mAccount.getAxolotlService().hasPendingKeyFetches(mAccount, contactJids); - } - - - @Override - public void onKeyStatusUpdated(final AxolotlService.FetchStatus report) { - if (report != null) { - lastFetchReport = report; - runOnUiThread(new Runnable() { - @Override - public void run() { - switch (report) { - case ERROR: - Toast.makeText(TrustKeysActivity.this,R.string.error_fetching_omemo_key,Toast.LENGTH_SHORT).show(); - break; - case SUCCESS_VERIFIED: - Toast.makeText(TrustKeysActivity.this,R.string.verified_omemo_key_with_certificate,Toast.LENGTH_LONG).show(); - break; - } - } - }); - - } - boolean keysToTrust = reloadFingerprints(); - if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) { - refreshUi(); - } else { - runOnUiThread(new Runnable() { - @Override - public void run() { - finishOk(); - } - }); - - } - } - - private void finishOk() { - Intent data = new Intent(); - data.putExtra("choice", getIntent().getIntExtra("choice", ConversationActivity.ATTACHMENT_CHOICE_INVALID)); - setResult(RESULT_OK, data); - finish(); - } - - private void commitTrusts() { - for(final String fingerprint :ownKeysToTrust.keySet()) { - mAccount.getAxolotlService().setFingerprintTrust( - fingerprint, - XmppAxolotlSession.Trust.fromBoolean(ownKeysToTrust.get(fingerprint))); - } - List<Jid> acceptedTargets = mConversation == null ? new ArrayList<Jid>() : mConversation.getAcceptedCryptoTargets(); - synchronized (this.foreignKeysToTrust) { - for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) { - Jid jid = entry.getKey(); - Map<String, Boolean> value = entry.getValue(); - if (!acceptedTargets.contains(jid)) { - acceptedTargets.add(jid); - } - for (final String fingerprint : value.keySet()) { - mAccount.getAxolotlService().setFingerprintTrust( - fingerprint, - XmppAxolotlSession.Trust.fromBoolean(value.get(fingerprint))); - } - } - } - if (mConversation != null && mConversation.getMode() == Conversation.MODE_MULTI) { - mConversation.setAcceptedCryptoTargets(acceptedTargets); - xmppConnectionService.updateConversation(mConversation); - } - } - - private void lockOrUnlockAsNeeded() { - synchronized (this.foreignKeysToTrust) { - for (Jid jid : contactJids) { - Map<String, Boolean> fingerprints = foreignKeysToTrust.get(jid); - if (hasNoOtherTrustedKeys(jid) && (fingerprints == null || !fingerprints.values().contains(true))) { - TextViewUtil.disable(this.mSaveButton, ConversationsPlusColors.secondaryText()); - return; - } - } - } - TextViewUtil.enable(this.mSaveButton, ConversationsPlusColors.primaryText()); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/UiCallback.java b/src/main/java/de/thedevstack/conversationsplus/ui/UiCallback.java deleted file mode 100644 index d5291b80..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/UiCallback.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.PendingIntent; - -public interface UiCallback<T> { - void success(T object); - - void error(int errorCode, T object); - - void userInputRequried(PendingIntent pi, T object); -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/VerifyOTRActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/VerifyOTRActivity.java deleted file mode 100644 index 4f1c9fc7..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/VerifyOTRActivity.java +++ /dev/null @@ -1,443 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.app.ActionBar; -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.view.Menu; -import android.view.View; -import android.widget.Button; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.Toast; - -import com.google.zxing.integration.android.IntentIntegrator; -import com.google.zxing.integration.android.IntentResult; - -import net.java.otr4j.OtrException; -import net.java.otr4j.session.Session; - -import de.thedevstack.conversationsplus.ConversationsPlusColors; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Contact; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.utils.CryptoHelper; -import de.thedevstack.conversationsplus.utils.XmppUri; -import de.thedevstack.conversationsplus.utils.ui.TextViewUtil; -import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class VerifyOTRActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate { - - public static final String ACTION_VERIFY_CONTACT = "verify_contact"; - public static final int MODE_SCAN_FINGERPRINT = - 0x0502; - public static final int MODE_ASK_QUESTION = 0x0503; - public static final int MODE_ANSWER_QUESTION = 0x0504; - public static final int MODE_MANUAL_VERIFICATION = 0x0505; - - private LinearLayout mManualVerificationArea; - private LinearLayout mSmpVerificationArea; - private TextView mRemoteFingerprint; - private TextView mYourFingerprint; - private TextView mVerificationExplain; - private TextView mStatusMessage; - private TextView mSharedSecretHint; - private EditText mSharedSecretHintEditable; - private EditText mSharedSecretSecret; - private Button mLeftButton; - private Button mRightButton; - private Account mAccount; - private Conversation mConversation; - private int mode = MODE_MANUAL_VERIFICATION; - private XmppUri mPendingUri = null; - - private DialogInterface.OnClickListener mVerifyFingerprintListener = new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialogInterface, int click) { - mConversation.verifyOtrFingerprint(); - xmppConnectionService.syncRosterToDisk(mConversation.getAccount()); - Toast.makeText(VerifyOTRActivity.this,R.string.verified,Toast.LENGTH_SHORT).show(); - finish(); - } - }; - - private View.OnClickListener mCreateSharedSecretListener = new View.OnClickListener() { - @Override - public void onClick(final View view) { - if (isAccountOnline()) { - final String question = mSharedSecretHintEditable.getText().toString(); - final String secret = mSharedSecretSecret.getText().toString(); - if (question.trim().isEmpty()) { - mSharedSecretHintEditable.requestFocus(); - mSharedSecretHintEditable.setError(getString(R.string.shared_secret_hint_should_not_be_empty)); - } else if (secret.trim().isEmpty()) { - mSharedSecretSecret.requestFocus(); - mSharedSecretSecret.setError(getString(R.string.shared_secret_can_not_be_empty)); - } else { - mSharedSecretSecret.setError(null); - mSharedSecretHintEditable.setError(null); - initSmp(question, secret); - updateView(); - } - } - } - }; - private View.OnClickListener mCancelSharedSecretListener = new View.OnClickListener() { - @Override - public void onClick(View view) { - if (isAccountOnline()) { - abortSmp(); - updateView(); - } - } - }; - private View.OnClickListener mRespondSharedSecretListener = new View.OnClickListener() { - - @Override - public void onClick(View view) { - if (isAccountOnline()) { - final String question = mSharedSecretHintEditable.getText().toString(); - final String secret = mSharedSecretSecret.getText().toString(); - respondSmp(question, secret); - updateView(); - } - } - }; - private View.OnClickListener mRetrySharedSecretListener = new View.OnClickListener() { - @Override - public void onClick(View view) { - mConversation.smp().status = Conversation.Smp.STATUS_NONE; - mConversation.smp().hint = null; - mConversation.smp().secret = null; - updateView(); - } - }; - private View.OnClickListener mFinishListener = new View.OnClickListener() { - @Override - public void onClick(View view) { - mConversation.smp().status = Conversation.Smp.STATUS_NONE; - finish(); - } - }; - - protected boolean initSmp(final String question, final String secret) { - final Session session = mConversation.getOtrSession(); - if (session!=null) { - try { - session.initSmp(question, secret); - mConversation.smp().status = Conversation.Smp.STATUS_WE_REQUESTED; - mConversation.smp().secret = secret; - mConversation.smp().hint = question; - return true; - } catch (OtrException e) { - return false; - } - } else { - return false; - } - } - - protected boolean abortSmp() { - final Session session = mConversation.getOtrSession(); - if (session!=null) { - try { - session.abortSmp(); - mConversation.smp().status = Conversation.Smp.STATUS_NONE; - mConversation.smp().hint = null; - mConversation.smp().secret = null; - return true; - } catch (OtrException e) { - return false; - } - } else { - return false; - } - } - - protected boolean respondSmp(final String question, final String secret) { - final Session session = mConversation.getOtrSession(); - if (session!=null) { - try { - session.respondSmp(question,secret); - return true; - } catch (OtrException e) { - return false; - } - } else { - return false; - } - } - - protected boolean verifyWithUri(XmppUri uri) { - Contact contact = mConversation.getContact(); - if (this.mConversation.getContact().getJid().equals(uri.getJid()) && uri.getFingerprint() != null) { - contact.addOtrFingerprint(uri.getFingerprint()); - Toast.makeText(this,R.string.verified,Toast.LENGTH_SHORT).show(); - updateView(); - xmppConnectionService.syncRosterToDisk(contact.getAccount()); - return true; - } else { - Toast.makeText(this,R.string.could_not_verify_fingerprint,Toast.LENGTH_SHORT).show(); - return false; - } - } - - protected boolean isAccountOnline() { - if (this.mAccount.getStatus() != Account.State.ONLINE) { - Toast.makeText(this,R.string.not_connected_try_again,Toast.LENGTH_SHORT).show(); - return false; - } else { - return true; - } - } - - protected boolean handleIntent(Intent intent) { - if (intent != null && intent.getAction().equals(ACTION_VERIFY_CONTACT)) { - this.mAccount = extractAccount(intent); - if (this.mAccount == null) { - return false; - } - try { - this.mConversation = this.xmppConnectionService.find(this.mAccount,Jid.fromString(intent.getExtras().getString("contact"))); - if (this.mConversation == null) { - return false; - } - } catch (final InvalidJidException ignored) { - return false; - } - this.mode = intent.getIntExtra("mode", MODE_MANUAL_VERIFICATION); - if (this.mode == MODE_SCAN_FINGERPRINT) { - new IntentIntegrator(this).initiateScan(); - return false; - } - return true; - } else { - return false; - } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent intent) { - if ((requestCode & 0xFFFF) == IntentIntegrator.REQUEST_CODE) { - IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent); - if (scanResult != null && scanResult.getFormatName() != null) { - String data = scanResult.getContents(); - XmppUri uri = new XmppUri(data); - if (xmppConnectionServiceBound) { - verifyWithUri(uri); - finish(); - } else { - this.mPendingUri = uri; - } - } else { - finish(); - } - } - super.onActivityResult(requestCode, requestCode, intent); - } - - @Override - protected void onBackendConnected() { - if (handleIntent(getIntent())) { - updateView(); - } else if (mPendingUri!=null) { - verifyWithUri(mPendingUri); - finish(); - mPendingUri = null; - } - setIntent(null); - } - - protected void updateView() { - if (this.mConversation.hasValidOtrSession()) { - final ActionBar actionBar = getActionBar(); - this.mVerificationExplain.setText(R.string.no_otr_session_found); - invalidateOptionsMenu(); - switch(this.mode) { - case MODE_ASK_QUESTION: - if (actionBar != null ) { - actionBar.setTitle(R.string.ask_question); - } - this.updateViewAskQuestion(); - break; - case MODE_ANSWER_QUESTION: - if (actionBar != null ) { - actionBar.setTitle(R.string.smp_requested); - } - this.updateViewAnswerQuestion(); - break; - case MODE_MANUAL_VERIFICATION: - default: - if (actionBar != null ) { - actionBar.setTitle(R.string.manually_verify); - } - this.updateViewManualVerification(); - break; - } - } else { - this.mManualVerificationArea.setVisibility(View.GONE); - this.mSmpVerificationArea.setVisibility(View.GONE); - } - } - - protected void updateViewManualVerification() { - this.mVerificationExplain.setText(R.string.manual_verification_explanation); - this.mManualVerificationArea.setVisibility(View.VISIBLE); - this.mSmpVerificationArea.setVisibility(View.GONE); - this.mYourFingerprint.setText(CryptoHelper.prettifyFingerprint(this.mAccount.getOtrFingerprint())); - this.mRemoteFingerprint.setText(CryptoHelper.prettifyFingerprint(this.mConversation.getOtrFingerprint())); - if (this.mConversation.isOtrFingerprintVerified()) { - deactivateButton(this.mRightButton,R.string.verified); - activateButton(this.mLeftButton,R.string.cancel,this.mFinishListener); - } else { - activateButton(this.mLeftButton,R.string.cancel,this.mFinishListener); - activateButton(this.mRightButton,R.string.verify, new View.OnClickListener() { - @Override - public void onClick(View view) { - showManuallyVerifyDialog(); - } - }); - } - } - - protected void updateViewAskQuestion() { - this.mManualVerificationArea.setVisibility(View.GONE); - this.mSmpVerificationArea.setVisibility(View.VISIBLE); - this.mVerificationExplain.setText(R.string.smp_explain_question); - final int smpStatus = this.mConversation.smp().status; - switch (smpStatus) { - case Conversation.Smp.STATUS_WE_REQUESTED: - this.mStatusMessage.setVisibility(View.GONE); - this.mSharedSecretHintEditable.setVisibility(View.VISIBLE); - this.mSharedSecretSecret.setVisibility(View.VISIBLE); - this.mSharedSecretHintEditable.setText(this.mConversation.smp().hint); - this.mSharedSecretSecret.setText(this.mConversation.smp().secret); - this.activateButton(this.mLeftButton, R.string.cancel, this.mCancelSharedSecretListener); - this.deactivateButton(this.mRightButton, R.string.in_progress); - break; - case Conversation.Smp.STATUS_FAILED: - this.mStatusMessage.setVisibility(View.GONE); - this.mSharedSecretHintEditable.setVisibility(View.VISIBLE); - this.mSharedSecretSecret.setVisibility(View.VISIBLE); - this.mSharedSecretSecret.requestFocus(); - this.mSharedSecretSecret.setError(getString(R.string.secrets_do_not_match)); - this.deactivateButton(this.mLeftButton, R.string.cancel); - this.activateButton(this.mRightButton, R.string.try_again, this.mRetrySharedSecretListener); - break; - case Conversation.Smp.STATUS_VERIFIED: - this.mSharedSecretHintEditable.setText(""); - this.mSharedSecretHintEditable.setVisibility(View.GONE); - this.mSharedSecretSecret.setText(""); - this.mSharedSecretSecret.setVisibility(View.GONE); - this.mStatusMessage.setVisibility(View.VISIBLE); - this.deactivateButton(this.mLeftButton, R.string.cancel); - this.activateButton(this.mRightButton, R.string.finish, this.mFinishListener); - break; - default: - this.mStatusMessage.setVisibility(View.GONE); - this.mSharedSecretHintEditable.setVisibility(View.VISIBLE); - this.mSharedSecretSecret.setVisibility(View.VISIBLE); - this.activateButton(this.mLeftButton,R.string.cancel,this.mFinishListener); - this.activateButton(this.mRightButton, R.string.ask_question, this.mCreateSharedSecretListener); - break; - } - } - - protected void updateViewAnswerQuestion() { - this.mManualVerificationArea.setVisibility(View.GONE); - this.mSmpVerificationArea.setVisibility(View.VISIBLE); - this.mVerificationExplain.setText(R.string.smp_explain_answer); - this.mSharedSecretHintEditable.setVisibility(View.GONE); - this.mSharedSecretHint.setVisibility(View.VISIBLE); - this.deactivateButton(this.mLeftButton, R.string.cancel); - final int smpStatus = this.mConversation.smp().status; - switch (smpStatus) { - case Conversation.Smp.STATUS_CONTACT_REQUESTED: - this.mStatusMessage.setVisibility(View.GONE); - this.mSharedSecretHint.setText(this.mConversation.smp().hint); - this.activateButton(this.mRightButton,R.string.respond,this.mRespondSharedSecretListener); - break; - case Conversation.Smp.STATUS_VERIFIED: - this.mSharedSecretHintEditable.setText(""); - this.mSharedSecretHintEditable.setVisibility(View.GONE); - this.mSharedSecretHint.setVisibility(View.GONE); - this.mSharedSecretSecret.setText(""); - this.mSharedSecretSecret.setVisibility(View.GONE); - this.mStatusMessage.setVisibility(View.VISIBLE); - this.activateButton(this.mRightButton, R.string.finish, this.mFinishListener); - break; - case Conversation.Smp.STATUS_FAILED: - default: - this.mSharedSecretSecret.requestFocus(); - this.mSharedSecretSecret.setError(getString(R.string.secrets_do_not_match)); - this.activateButton(this.mRightButton,R.string.finish,this.mFinishListener); - break; - } - } - - protected void activateButton(Button button, int text, View.OnClickListener listener) { - TextViewUtil.enable(button, ConversationsPlusColors.primaryText(), text); - button.setOnClickListener(listener); - } - - protected void deactivateButton(Button button, int text) { - TextViewUtil.disable(button, ConversationsPlusColors.secondaryText(), text); - button.setOnClickListener(null); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_verify_otr); - this.mRemoteFingerprint = (TextView) findViewById(R.id.remote_fingerprint); - this.mYourFingerprint = (TextView) findViewById(R.id.your_fingerprint); - this.mLeftButton = (Button) findViewById(R.id.left_button); - this.mRightButton = (Button) findViewById(R.id.right_button); - this.mVerificationExplain = (TextView) findViewById(R.id.verification_explanation); - this.mStatusMessage = (TextView) findViewById(R.id.status_message); - this.mSharedSecretSecret = (EditText) findViewById(R.id.shared_secret_secret); - this.mSharedSecretHintEditable = (EditText) findViewById(R.id.shared_secret_hint_editable); - this.mSharedSecretHint = (TextView) findViewById(R.id.shared_secret_hint); - this.mManualVerificationArea = (LinearLayout) findViewById(R.id.manual_verification_area); - this.mSmpVerificationArea = (LinearLayout) findViewById(R.id.smp_verification_area); - } - - @Override - public boolean onCreateOptionsMenu(final Menu menu) { - super.onCreateOptionsMenu(menu); - getMenuInflater().inflate(R.menu.verify_otr, menu); - return true; - } - - private void showManuallyVerifyDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.manually_verify); - builder.setMessage(R.string.are_you_sure_verify_fingerprint); - builder.setNegativeButton(R.string.cancel, null); - builder.setPositiveButton(R.string.verify, mVerifyFingerprintListener); - builder.create().show(); - } - - @Override - protected String getShareableUri() { - if (mAccount!=null) { - return mAccount.getShareableUri(); - } else { - return ""; - } - } - - public void onConversationUpdate() { - refreshUi(); - } - - @Override - protected void refreshUiReal() { - updateView(); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/XmppActivity.java b/src/main/java/de/thedevstack/conversationsplus/ui/XmppActivity.java deleted file mode 100644 index 726facac..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/XmppActivity.java +++ /dev/null @@ -1,1173 +0,0 @@ -package de.thedevstack.conversationsplus.ui; - -import android.Manifest; -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.app.ActionBar; -import android.app.Activity; -import android.app.AlertDialog; -import android.app.AlertDialog.Builder; -import android.app.PendingIntent; -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.content.IntentSender.SendIntentException; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.graphics.Point; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.nfc.NdefMessage; -import android.nfc.NdefRecord; -import android.nfc.NfcAdapter; -import android.nfc.NfcEvent; -import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.PowerManager; -import android.os.SystemClock; -import android.preference.PreferenceManager; -import android.text.InputType; -import android.util.DisplayMetrics; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import android.widget.CompoundButton; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.Switch; -import android.widget.TextView; -import android.widget.Toast; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.qrcode.QRCodeWriter; -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; - -import net.java.otr4j.session.SessionID; - -import java.io.FileNotFoundException; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.List; -import java.util.concurrent.RejectedExecutionException; - -import de.thedevstack.android.logcat.Logging; -import de.thedevstack.conversationsplus.ConversationsPlusColors; -import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.thedevstack.conversationsplus.utils.ImageUtil; -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.crypto.axolotl.XmppAxolotlSession; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Contact; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.entities.Message; -import de.thedevstack.conversationsplus.entities.MucOptions; -import de.thedevstack.conversationsplus.entities.Presences; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.services.XmppConnectionService.XmppConnectionBinder; -import de.thedevstack.conversationsplus.utils.CryptoHelper; -import de.thedevstack.conversationsplus.utils.ExceptionHelper; -import de.thedevstack.conversationsplus.xmpp.OnKeyStatusUpdated; -import de.thedevstack.conversationsplus.xmpp.OnUpdateBlocklist; -import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public abstract class XmppActivity extends Activity { - - protected static final int REQUEST_ANNOUNCE_PGP = 0x0101; - protected static final int REQUEST_INVITE_TO_CONVERSATION = 0x0102; - protected static final int REQUEST_CHOOSE_PGP_ID = 0x0103; - protected static final int REQUEST_BATTERY_OP = 0x13849ff; - - public static final String EXTRA_ACCOUNT = "account"; - - public XmppConnectionService xmppConnectionService; - public boolean xmppConnectionServiceBound = false; - protected boolean registeredListeners = false; - - private DisplayMetrics metrics; - protected int mTheme; - - private long mLastUiRefresh = 0; - private Handler mRefreshUiHandler = new Handler(); - private Runnable mRefreshUiRunnable = new Runnable() { - @Override - public void run() { - mLastUiRefresh = SystemClock.elapsedRealtime(); - refreshUiReal(); - } - }; - - protected ConferenceInvite mPendingConferenceInvite = null; - - - protected final void refreshUi() { - final long diff = SystemClock.elapsedRealtime() - mLastUiRefresh; - if (diff > Config.REFRESH_UI_INTERVAL) { - mRefreshUiHandler.removeCallbacks(mRefreshUiRunnable); - runOnUiThread(mRefreshUiRunnable); - } else { - final long next = Config.REFRESH_UI_INTERVAL - diff; - mRefreshUiHandler.removeCallbacks(mRefreshUiRunnable); - mRefreshUiHandler.postDelayed(mRefreshUiRunnable,next); - } - } - - abstract protected void refreshUiReal(); - - protected interface OnValueEdited { - public void onValueEdited(String value); - } - - public interface OnPresenceSelected { - public void onPresenceSelected(); - } - - protected ServiceConnection mConnection = new ServiceConnection() { - - @Override - public void onServiceConnected(ComponentName className, IBinder service) { - XmppConnectionBinder binder = (XmppConnectionBinder) service; - xmppConnectionService = binder.getService(); - xmppConnectionServiceBound = true; - if (!registeredListeners && shouldRegisterListeners()) { - registerListeners(); - registeredListeners = true; - } - onBackendConnected(); - } - - @Override - public void onServiceDisconnected(ComponentName arg0) { - xmppConnectionServiceBound = false; - } - }; - - @Override - protected void onStart() { - super.onStart(); - if (!xmppConnectionServiceBound) { - connectToBackend(); - } else { - if (!registeredListeners) { - this.registerListeners(); - this.registeredListeners = true; - } - this.onBackendConnected(); - } - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) - protected boolean shouldRegisterListeners() { - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - return !isDestroyed() && !isFinishing(); - } else { - return !isFinishing(); - } - } - - public void connectToBackend() { - Intent intent = new Intent(this, XmppConnectionService.class); - intent.setAction("ui"); - startService(intent); - bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - } - - @Override - protected void onStop() { - super.onStop(); - if (xmppConnectionServiceBound) { - if (registeredListeners) { - this.unregisterListeners(); - this.registeredListeners = false; - } - unbindService(mConnection); - xmppConnectionServiceBound = false; - } - } - - protected void hideKeyboard() { - InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - - View focus = getCurrentFocus(); - - if (focus != null) { - - inputManager.hideSoftInputFromWindow(focus.getWindowToken(), - InputMethodManager.HIDE_NOT_ALWAYS); - } - } - - public boolean hasPgp() { - return xmppConnectionService.getPgpEngine() != null; - } - - public void showInstallPgpDialog() { - Builder builder = new AlertDialog.Builder(this); - builder.setTitle(getString(R.string.openkeychain_required)); - builder.setIconAttribute(android.R.attr.alertDialogIcon); - builder.setMessage(getText(R.string.openkeychain_required_long)); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.setNeutralButton(getString(R.string.restart), - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - if (xmppConnectionServiceBound) { - unbindService(mConnection); - xmppConnectionServiceBound = false; - } - stopService(new Intent(XmppActivity.this, - XmppConnectionService.class)); - finish(); - } - }); - builder.setPositiveButton(getString(R.string.install), - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - Uri uri = Uri - .parse("market://details?id=org.sufficientlysecure.keychain"); - Intent marketIntent = new Intent(Intent.ACTION_VIEW, - uri); - PackageManager manager = getApplicationContext() - .getPackageManager(); - List<ResolveInfo> infos = manager - .queryIntentActivities(marketIntent, 0); - if (infos.size() > 0) { - startActivity(marketIntent); - } else { - uri = Uri.parse("http://www.openkeychain.org/"); - Intent browserIntent = new Intent( - Intent.ACTION_VIEW, uri); - startActivity(browserIntent); - } - finish(); - } - }); - builder.create().show(); - } - - abstract void onBackendConnected(); - - protected void registerListeners() { - if (this instanceof XmppConnectionService.OnConversationUpdate) { - this.xmppConnectionService.setOnConversationListChangedListener((XmppConnectionService.OnConversationUpdate) this); - } - if (this instanceof XmppConnectionService.OnAccountUpdate) { - this.xmppConnectionService.setOnAccountListChangedListener((XmppConnectionService.OnAccountUpdate) this); - } - if (this instanceof XmppConnectionService.OnCaptchaRequested) { - this.xmppConnectionService.setOnCaptchaRequestedListener((XmppConnectionService.OnCaptchaRequested) this); - } - if (this instanceof XmppConnectionService.OnRosterUpdate) { - this.xmppConnectionService.setOnRosterUpdateListener((XmppConnectionService.OnRosterUpdate) this); - } - if (this instanceof XmppConnectionService.OnMucRosterUpdate) { - this.xmppConnectionService.setOnMucRosterUpdateListener((XmppConnectionService.OnMucRosterUpdate) this); - } - if (this instanceof OnUpdateBlocklist) { - this.xmppConnectionService.setOnUpdateBlocklistListener((OnUpdateBlocklist) this); - } - if (this instanceof XmppConnectionService.OnShowErrorToast) { - this.xmppConnectionService.setOnShowErrorToastListener((XmppConnectionService.OnShowErrorToast) this); - } - if (this instanceof OnKeyStatusUpdated) { - this.xmppConnectionService.setOnKeyStatusUpdatedListener((OnKeyStatusUpdated) this); - } - } - - protected void unregisterListeners() { - if (this instanceof XmppConnectionService.OnConversationUpdate) { - this.xmppConnectionService.removeOnConversationListChangedListener(); - } - if (this instanceof XmppConnectionService.OnAccountUpdate) { - this.xmppConnectionService.removeOnAccountListChangedListener(); - } - if (this instanceof XmppConnectionService.OnCaptchaRequested) { - this.xmppConnectionService.removeOnCaptchaRequestedListener(); - } - if (this instanceof XmppConnectionService.OnRosterUpdate) { - this.xmppConnectionService.removeOnRosterUpdateListener(); - } - if (this instanceof XmppConnectionService.OnMucRosterUpdate) { - this.xmppConnectionService.removeOnMucRosterUpdateListener(); - } - if (this instanceof OnUpdateBlocklist) { - this.xmppConnectionService.removeOnUpdateBlocklistListener(); - } - if (this instanceof XmppConnectionService.OnShowErrorToast) { - this.xmppConnectionService.removeOnShowErrorToastListener(); - } - if (this instanceof OnKeyStatusUpdated) { - this.xmppConnectionService.removeOnNewKeysAvailableListener(); - } - } - - @Override - public boolean onOptionsItemSelected(final MenuItem item) { - switch (item.getItemId()) { - case R.id.action_settings: - startActivity(new Intent(this, SettingsActivity.class)); - break; - case R.id.action_accounts: - startActivity(new Intent(this, ManageAccountActivity.class)); - break; - case android.R.id.home: - finish(); - break; - case R.id.action_show_qr_code: - showQrCode(); - break; - } - return super.onOptionsItemSelected(item); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - metrics = getResources().getDisplayMetrics(); - ExceptionHelper.init(getApplicationContext()); - this.mTheme = findTheme(); - setTheme(this.mTheme); - final ActionBar ab = getActionBar(); - if (ab!=null) { - ab.setDisplayHomeAsUpEnabled(true); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - final MenuItem menuSettings = menu.findItem(R.id.action_settings); - final MenuItem menuManageAccounts = menu.findItem(R.id.action_accounts); - if (menuSettings != null) { - menuSettings.setVisible(!Config.LOCK_SETTINGS); - } - if (menuManageAccounts != null) { - menuManageAccounts.setVisible(!Config.LOCK_SETTINGS); - } - return super.onCreateOptionsMenu(menu); - } - - protected boolean isOptimizingBattery() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); - return !pm.isIgnoringBatteryOptimizations(getPackageName()); - } else { - return false; - } - } - - public void switchToConversation(Conversation conversation) { - switchToConversation(conversation, null, false); - } - - public void switchToConversation(Conversation conversation, String text, - boolean newTask) { - switchToConversation(conversation,text,null,false,newTask); - } - - public void highlightInMuc(Conversation conversation, String nick) { - switchToConversation(conversation, null, nick, false, false); - } - - public void privateMsgInMuc(Conversation conversation, String nick) { - switchToConversation(conversation, null, nick, true, false); - } - - private void switchToConversation(Conversation conversation, String text, String nick, boolean pm, boolean newTask) { - Intent viewConversationIntent = new Intent(this, - ConversationActivity.class); - viewConversationIntent.setAction(Intent.ACTION_VIEW); - viewConversationIntent.putExtra(ConversationActivity.CONVERSATION, - conversation.getUuid()); - if (text != null) { - viewConversationIntent.putExtra(ConversationActivity.TEXT, text); - } - if (nick != null) { - viewConversationIntent.putExtra(ConversationActivity.NICK, nick); - viewConversationIntent.putExtra(ConversationActivity.PRIVATE_MESSAGE,pm); - } - viewConversationIntent.setType(ConversationActivity.VIEW_CONVERSATION); - if (newTask) { - viewConversationIntent.setFlags(viewConversationIntent.getFlags() - | Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_SINGLE_TOP); - } else { - viewConversationIntent.setFlags(viewConversationIntent.getFlags() - | Intent.FLAG_ACTIVITY_CLEAR_TOP); - } - startActivity(viewConversationIntent); - finish(); - } - - public void switchToContactDetails(Contact contact) { - switchToContactDetails(contact, null); - } - - public void switchToContactDetails(Contact contact, String messageFingerprint) { - Intent intent = new Intent(this, ContactDetailsActivity.class); - intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT); - intent.putExtra(EXTRA_ACCOUNT, contact.getAccount().getJid().toBareJid().toString()); - intent.putExtra("contact", contact.getJid().toString()); - intent.putExtra("fingerprint", messageFingerprint); - startActivity(intent); - } - - public void switchToAccount(Account account) { - switchToAccount(account, false); - } - - public void switchToAccount(Account account, boolean init) { - Intent intent = new Intent(this, EditAccountActivity.class); - intent.putExtra("jid", account.getJid().toBareJid().toString()); - intent.putExtra("init", init); - startActivity(intent); - } - - protected void inviteToConversation(Conversation conversation) { - Intent intent = new Intent(getApplicationContext(), - ChooseContactActivity.class); - List<String> contacts = new ArrayList<>(); - if (conversation.getMode() == Conversation.MODE_MULTI) { - for (MucOptions.User user : conversation.getMucOptions().getUsers()) { - Jid jid = user.getJid(); - if (jid != null) { - contacts.add(jid.toBareJid().toString()); - } - } - } else { - contacts.add(conversation.getJid().toBareJid().toString()); - } - intent.putExtra("filter_contacts", contacts.toArray(new String[contacts.size()])); - intent.putExtra("conversation", conversation.getUuid()); - intent.putExtra("multiple", true); - intent.putExtra("show_enter_jid", true); - intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().toBareJid().toString()); - startActivityForResult(intent, REQUEST_INVITE_TO_CONVERSATION); - } - - protected void announcePgp(Account account, final Conversation conversation) { - if (account.getPgpId() == -1) { - choosePgpSignId(account); - } else { - xmppConnectionService.getPgpEngine().generateSignature(account, "", new UiCallback<Account>() { - - @Override - public void userInputRequried(PendingIntent pi, - Account account) { - try { - startIntentSenderForResult(pi.getIntentSender(), - REQUEST_ANNOUNCE_PGP, null, 0, 0, 0); - } catch (final SendIntentException ignored) { - } - } - - @Override - public void success(Account account) { - xmppConnectionService.databaseBackend.updateAccount(account); - xmppConnectionService.sendPresence(account); - if (conversation != null) { - conversation.setNextEncryption(Message.ENCRYPTION_PGP); - xmppConnectionService.databaseBackend.updateConversation(conversation); - } - } - - @Override - public void error(int error, Account account) { - displayErrorDialog(error); - } - }); - } - } - - protected void choosePgpSignId(Account account) { - xmppConnectionService.getPgpEngine().chooseKey(account, new UiCallback<Account>() { - @Override - public void success(Account account1) { - } - - @Override - public void error(int errorCode, Account object) { - - } - - @Override - public void userInputRequried(PendingIntent pi, Account object) { - try { - startIntentSenderForResult(pi.getIntentSender(), - REQUEST_CHOOSE_PGP_ID, null, 0, 0, 0); - } catch (final SendIntentException ignored) { - } - } - }); - } - - public void displayErrorDialog(final int errorCode) { - runOnUiThread(new Runnable() { - - @Override - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder( - XmppActivity.this); - builder.setIconAttribute(android.R.attr.alertDialogIcon); - builder.setTitle(getString(R.string.error)); - builder.setMessage(errorCode); - builder.setNeutralButton(R.string.accept, null); - builder.create().show(); - } - }); - - } - - protected void showAddToRosterDialog(final Conversation conversation) { - showAddToRosterDialog(conversation.getContact()); - } - - protected void showAddToRosterDialog(final Contact contact) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(contact.getJid().toString()); - builder.setMessage(getString(R.string.not_in_roster)); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.setPositiveButton(getString(R.string.add_contact), - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - final Jid jid = contact.getJid(); - Account account = contact.getAccount(); - Contact contact = account.getRoster().getContact(jid); - xmppConnectionService.createContact(contact); - } - }); - builder.create().show(); - } - - private void showAskForPresenceDialog(final Contact contact) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(contact.getJid().toString()); - builder.setMessage(R.string.request_presence_updates); - builder.setNegativeButton(R.string.cancel, null); - builder.setPositiveButton(R.string.request_now, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - if (xmppConnectionServiceBound) { - xmppConnectionService.sendPresencePacket(contact - .getAccount(), xmppConnectionService - .getPresenceGenerator() - .requestPresenceUpdatesFrom(contact)); - } - } - }); - builder.create().show(); - } - - private void warnMutalPresenceSubscription(final Conversation conversation, - final OnPresenceSelected listener) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(conversation.getContact().getJid().toString()); - builder.setMessage(R.string.without_mutual_presence_updates); - builder.setNegativeButton(R.string.cancel, null); - builder.setPositiveButton(R.string.ignore, new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - conversation.setNextCounterpart(null); - if (listener != null) { - listener.onPresenceSelected(); - } - } - }); - builder.create().show(); - } - - protected void quickEdit(String previousValue, OnValueEdited callback) { - quickEdit(previousValue, callback, false); - } - - protected void quickPasswordEdit(String previousValue, - OnValueEdited callback) { - quickEdit(previousValue, callback, true); - } - - @SuppressLint("InflateParams") - private void quickEdit(final String previousValue, - final OnValueEdited callback, boolean password) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - View view = getLayoutInflater().inflate(R.layout.quickedit, null); - final EditText editor = (EditText) view.findViewById(R.id.editor); - OnClickListener mClickListener = new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - String value = editor.getText().toString(); - if (!previousValue.equals(value) && value.trim().length() > 0) { - callback.onValueEdited(value); - } - } - }; - if (password) { - editor.setInputType(InputType.TYPE_CLASS_TEXT - | InputType.TYPE_TEXT_VARIATION_PASSWORD); - editor.setHint(R.string.password); - builder.setPositiveButton(R.string.accept, mClickListener); - } else { - builder.setPositiveButton(R.string.edit, mClickListener); - } - editor.requestFocus(); - editor.setText(previousValue); - builder.setView(view); - builder.setNegativeButton(R.string.cancel, null); - builder.create().show(); - } - - protected boolean addFingerprintRow(LinearLayout keys, final Account account, final String fingerprint, boolean highlight, View.OnClickListener onKeyClickedListener) { - final XmppAxolotlSession.Trust trust = account.getAxolotlService() - .getFingerprintTrust(fingerprint); - if (trust == null) { - return false; - } - return addFingerprintRowWithListeners(keys, account, fingerprint, highlight, trust, true, - new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - account.getAxolotlService().setFingerprintTrust(fingerprint, - (isChecked) ? XmppAxolotlSession.Trust.TRUSTED : - XmppAxolotlSession.Trust.UNTRUSTED); - } - }, - new View.OnClickListener() { - @Override - public void onClick(View v) { - account.getAxolotlService().setFingerprintTrust(fingerprint, - XmppAxolotlSession.Trust.UNTRUSTED); - v.setEnabled(true); - } - }, - onKeyClickedListener - - ); - } - - protected boolean addFingerprintRowWithListeners(LinearLayout keys, final Account account, - final String fingerprint, - boolean highlight, - XmppAxolotlSession.Trust trust, - boolean showTag, - CompoundButton.OnCheckedChangeListener - onCheckedChangeListener, - View.OnClickListener onClickListener, - View.OnClickListener onKeyClickedListener) { - if (trust == XmppAxolotlSession.Trust.COMPROMISED) { - return false; - } - View view = getLayoutInflater().inflate(R.layout.contact_key, keys, false); - TextView key = (TextView) view.findViewById(R.id.key); - key.setOnClickListener(onKeyClickedListener); - TextView keyType = (TextView) view.findViewById(R.id.key_type); - keyType.setOnClickListener(onKeyClickedListener); - Switch trustToggle = (Switch) view.findViewById(R.id.tgl_trust); - trustToggle.setVisibility(View.VISIBLE); - trustToggle.setOnCheckedChangeListener(onCheckedChangeListener); - trustToggle.setOnClickListener(onClickListener); - final View.OnLongClickListener purge = new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - showPurgeKeyDialog(account, fingerprint); - return true; - } - }; - view.setOnLongClickListener(purge); - key.setOnLongClickListener(purge); - keyType.setOnLongClickListener(purge); - boolean x509 = Config.X509_VERIFICATION - && (trust == XmppAxolotlSession.Trust.TRUSTED_X509 || trust == XmppAxolotlSession.Trust.INACTIVE_TRUSTED_X509); - switch (trust) { - case UNTRUSTED: - case TRUSTED: - case TRUSTED_X509: - trustToggle.setChecked(trust.trusted()); - trustToggle.setEnabled(!Config.X509_VERIFICATION || trust != XmppAxolotlSession.Trust.TRUSTED_X509); - if (Config.X509_VERIFICATION && trust == XmppAxolotlSession.Trust.TRUSTED_X509) { - trustToggle.setOnClickListener(null); - } - key.setTextColor(ConversationsPlusColors.primaryText()); - keyType.setTextColor(ConversationsPlusColors.secondaryText()); - break; - case UNDECIDED: - trustToggle.setChecked(false); - trustToggle.setEnabled(false); - key.setTextColor(ConversationsPlusColors.primaryText()); - keyType.setTextColor(ConversationsPlusColors.secondaryText()); - break; - case INACTIVE_UNTRUSTED: - case INACTIVE_UNDECIDED: - trustToggle.setOnClickListener(null); - trustToggle.setChecked(false); - trustToggle.setEnabled(false); - key.setTextColor(ConversationsPlusColors.tertiaryText()); - keyType.setTextColor(ConversationsPlusColors.tertiaryText()); - break; - case INACTIVE_TRUSTED: - case INACTIVE_TRUSTED_X509: - trustToggle.setOnClickListener(null); - trustToggle.setChecked(true); - trustToggle.setEnabled(false); - key.setTextColor(ConversationsPlusColors.tertiaryText()); - keyType.setTextColor(ConversationsPlusColors.tertiaryText()); - break; - } - - if (showTag) { - keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509 : R.string.omemo_fingerprint)); - } else { - keyType.setVisibility(View.GONE); - } - if (highlight) { - keyType.setTextColor(ConversationsPlusColors.accent()); - keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509_selected_message : R.string.omemo_fingerprint_selected_message)); - } else { - keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509 : R.string.omemo_fingerprint)); - } - - key.setText(CryptoHelper.prettifyFingerprint(fingerprint.substring(2))); - keys.addView(view); - return true; - } - - public void showPurgeKeyDialog(final Account account, final String fingerprint) { - Builder builder = new Builder(this); - builder.setTitle(getString(R.string.purge_key)); - builder.setIconAttribute(android.R.attr.alertDialogIcon); - builder.setMessage(getString(R.string.purge_key_desc_part1) - + "\n\n" + CryptoHelper.prettifyFingerprint(fingerprint.substring(2)) - + "\n\n" + getString(R.string.purge_key_desc_part2)); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.setPositiveButton(getString(R.string.purge_key), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - account.getAxolotlService().purgeKey(fingerprint); - refreshUi(); - } - }); - builder.create().show(); - } - - public boolean hasStoragePermission(int requestCode) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode); - return false; - } else { - return true; - } - } else { - return true; - } - } - - public void selectPresence(final Conversation conversation, - final OnPresenceSelected listener) { - final Contact contact = conversation.getContact(); - if (conversation.hasValidOtrSession()) { - SessionID id = conversation.getOtrSession().getSessionID(); - Jid jid; - try { - jid = Jid.fromString(id.getAccountID() + "/" + id.getUserID()); - } catch (InvalidJidException e) { - jid = null; - } - conversation.setNextCounterpart(jid); - listener.onPresenceSelected(); - } else if (!contact.showInRoster()) { - showAddToRosterDialog(conversation); - } else { - Presences presences = contact.getPresences(); - if (presences.size() == 0) { - if (!contact.getOption(Contact.Options.TO) - && !contact.getOption(Contact.Options.ASKING) - && contact.getAccount().getStatus() == Account.State.ONLINE) { - showAskForPresenceDialog(contact); - } else if (!contact.getOption(Contact.Options.TO) - || !contact.getOption(Contact.Options.FROM)) { - warnMutalPresenceSubscription(conversation, listener); - } else { - conversation.setNextCounterpart(null); - listener.onPresenceSelected(); - } - } else if (presences.size() == 1) { - String presence = presences.asStringArray()[0]; - try { - conversation.setNextCounterpart(Jid.fromParts(contact.getJid().getLocalpart(),contact.getJid().getDomainpart(),presence)); - } catch (InvalidJidException e) { - conversation.setNextCounterpart(null); - } - listener.onPresenceSelected(); - } else { - final StringBuilder presence = new StringBuilder(); - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(getString(R.string.choose_presence)); - final String[] presencesArray = presences.asStringArray(); - int preselectedPresence = 0; - for (int i = 0; i < presencesArray.length; ++i) { - if (presencesArray[i].equals(contact.lastseen.presence)) { - preselectedPresence = i; - break; - } - } - presence.append(presencesArray[preselectedPresence]); - builder.setSingleChoiceItems(presencesArray, - preselectedPresence, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, - int which) { - presence.delete(0, presence.length()); - presence.append(presencesArray[which]); - } - }); - builder.setNegativeButton(R.string.cancel, null); - builder.setPositiveButton(R.string.ok, new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - try { - conversation.setNextCounterpart(Jid.fromParts(contact.getJid().getLocalpart(),contact.getJid().getDomainpart(),presence.toString())); - } catch (InvalidJidException e) { - conversation.setNextCounterpart(null); - } - listener.onPresenceSelected(); - } - }); - builder.create().show(); - } - } - } - - protected void onActivityResult(int requestCode, int resultCode, - final Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_INVITE_TO_CONVERSATION && resultCode == RESULT_OK) { - mPendingConferenceInvite = ConferenceInvite.parse(data); - if (xmppConnectionServiceBound && mPendingConferenceInvite != null) { - mPendingConferenceInvite.execute(this); - mPendingConferenceInvite = null; - } - } - } - - private UiCallback<Conversation> adhocCallback = new UiCallback<Conversation>() { - @Override - public void success(final Conversation conversation) { - switchToConversation(conversation); - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(XmppActivity.this,R.string.conference_created,Toast.LENGTH_LONG).show(); - } - }); - } - - @Override - public void error(final int errorCode, Conversation object) { - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(XmppActivity.this,errorCode,Toast.LENGTH_LONG).show(); - } - }); - } - - @Override - public void userInputRequried(PendingIntent pi, Conversation object) { - - } - }; - - public int getPixel(int dp) { - DisplayMetrics metrics = getResources().getDisplayMetrics(); - return ((int) (dp * metrics.density)); - } - - public boolean copyTextToClipboard(String text, int labelResId) { - ClipboardManager mClipBoardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); - String label = getResources().getString(labelResId); - if (mClipBoardManager != null) { - ClipData mClipData = ClipData.newPlainText(label, text); - mClipBoardManager.setPrimaryClip(mClipData); - return true; - } - return false; - } - - protected void registerNdefPushMessageCallback() { - NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); - if (nfcAdapter != null && nfcAdapter.isEnabled()) { - nfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() { - @Override - public NdefMessage createNdefMessage(NfcEvent nfcEvent) { - return new NdefMessage(new NdefRecord[]{ - NdefRecord.createUri(getShareableUri()), - NdefRecord.createApplicationRecord("de.thedevstack.conversationsplus") - }); - } - }, this); - } - } - - protected void unregisterNdefPushMessageCallback() { - NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); - if (nfcAdapter != null && nfcAdapter.isEnabled()) { - nfcAdapter.setNdefPushMessageCallback(null,this); - } - } - - protected String getShareableUri() { - return null; - } - - @Override - public void onResume() { - super.onResume(); - if (this.getShareableUri()!=null) { - this.registerNdefPushMessageCallback(); - } - } - - protected int findTheme() { - if (ConversationsPlusPreferences.useLargerFont()) { - return R.style.ConversationsTheme_LargerText; - } else { - return R.style.ConversationsTheme; - } - } - - @Override - public void onPause() { - super.onPause(); - this.unregisterNdefPushMessageCallback(); - } - - protected void showQrCode() { - String uri = getShareableUri(); - if (uri!=null) { - Point size = new Point(); - getWindowManager().getDefaultDisplay().getSize(size); - final int width = (size.x < size.y ? size.x : size.y); - Bitmap bitmap = createQrCodeBitmap(uri, width); - ImageView view = new ImageView(this); - view.setImageBitmap(bitmap); - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setView(view); - builder.create().show(); - } - } - - protected Bitmap createQrCodeBitmap(String input, int size) { - Logging.d(Config.LOGTAG,"qr code requested size: "+size); - try { - final QRCodeWriter QR_CODE_WRITER = new QRCodeWriter(); - final Hashtable<EncodeHintType, Object> hints = new Hashtable<>(); - hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); - final BitMatrix result = QR_CODE_WRITER.encode(input, BarcodeFormat.QR_CODE, size, size, hints); - final int width = result.getWidth(); - final int height = result.getHeight(); - final int[] pixels = new int[width * height]; - for (int y = 0; y < height; y++) { - final int offset = y * width; - for (int x = 0; x < width; x++) { - pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.TRANSPARENT; - } - } - final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - Logging.d(Config.LOGTAG,"output size: "+width+"x"+height); - bitmap.setPixels(pixels, 0, width, 0, 0, width, height); - return bitmap; - } catch (final WriterException e) { - return null; - } - } - - protected Account extractAccount(Intent intent) { - String jid = intent != null ? intent.getStringExtra(EXTRA_ACCOUNT) : null; - try { - return jid != null ? xmppConnectionService.findAccountByJid(Jid.fromString(jid)) : null; - } catch (InvalidJidException e) { - return null; - } - } - - public static class ConferenceInvite { - private String uuid; - private List<Jid> jids = new ArrayList<>(); - - public static ConferenceInvite parse(Intent data) { - ConferenceInvite invite = new ConferenceInvite(); - invite.uuid = data.getStringExtra("conversation"); - if (invite.uuid == null) { - return null; - } - try { - if (data.getBooleanExtra("multiple", false)) { - String[] toAdd = data.getStringArrayExtra("contacts"); - for (String item : toAdd) { - invite.jids.add(Jid.fromString(item)); - } - } else { - invite.jids.add(Jid.fromString(data.getStringExtra("contact"))); - } - } catch (final InvalidJidException ignored) { - return null; - } - return invite; - } - - public void execute(XmppActivity activity) { - XmppConnectionService service = activity.xmppConnectionService; - Conversation conversation = service.findConversationByUuid(this.uuid); - if (conversation == null) { - return; - } - if (conversation.getMode() == Conversation.MODE_MULTI) { - for (Jid jid : jids) { - service.invite(conversation, jid); - } - } else { - jids.add(conversation.getJid().toBareJid()); - service.createAdhocConference(conversation.getAccount(), jids, activity.adhocCallback); - } - } - } - - class BitmapWorkerTask extends AsyncTask<Message, Void, Bitmap> { - private final WeakReference<ImageView> imageViewReference; - private final boolean setSize; - private Message message = null; - - public BitmapWorkerTask(ImageView imageView, boolean setSize) { - imageViewReference = new WeakReference<>(imageView); - this.setSize = setSize; - } - - @Override - protected Bitmap doInBackground(Message... params) { - message = params[0]; - try { - return ImageUtil.getThumbnail(message, (int) (metrics.density * 288), false); - } catch (FileNotFoundException e) { - return null; - } - } - - @Override - protected void onPostExecute(Bitmap bitmap) { - if (bitmap != null) { - final ImageView imageView = imageViewReference.get(); - if (imageView != null) { - imageView.setImageBitmap(bitmap); - imageView.setBackgroundColor(0x00000000); - if (setSize) { - imageView.setLayoutParams(new LinearLayout.LayoutParams( - bitmap.getWidth(), bitmap.getHeight())); - } - } - } - } - } - - public void loadBitmap(Message message, ImageView imageView, boolean setSize) { - Bitmap bm; - try { - bm = ImageUtil.getThumbnail(message,(int) (metrics.density * 288), true); - } catch (FileNotFoundException e) { - bm = null; - } - - if (bm != null) { - imageView.setImageBitmap(bm); - imageView.setBackgroundColor(0x00000000); - if (setSize) { - imageView.setLayoutParams(new LinearLayout.LayoutParams( - bm.getWidth(), bm.getHeight())); - } - } else { - if (cancelPotentialWork(message, imageView)) { - imageView.setBackgroundColor(0xff333333); - imageView.setImageDrawable(null); - final BitmapWorkerTask task = new BitmapWorkerTask(imageView, setSize); - final AsyncDrawable asyncDrawable = new AsyncDrawable( - getResources(), null, task); - imageView.setImageDrawable(asyncDrawable); - try { - task.execute(message); - } catch (final RejectedExecutionException ignored) { - } - } - } - } - - public static boolean cancelPotentialWork(Message message, - ImageView imageView) { - final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); - - if (bitmapWorkerTask != null) { - final Message oldMessage = bitmapWorkerTask.message; - if (oldMessage == null || message != oldMessage) { - bitmapWorkerTask.cancel(true); - } else { - return false; - } - } - return true; - } - - private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { - if (imageView != null) { - final Drawable drawable = imageView.getDrawable(); - if (drawable instanceof AsyncDrawable) { - final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; - return asyncDrawable.getBitmapWorkerTask(); - } - } - return null; - } - - static class AsyncDrawable extends BitmapDrawable { - private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference; - - public AsyncDrawable(Resources res, Bitmap bitmap, - BitmapWorkerTask bitmapWorkerTask) { - super(res, bitmap); - bitmapWorkerTaskReference = new WeakReference<>( - bitmapWorkerTask); - } - - public BitmapWorkerTask getBitmapWorkerTask() { - return bitmapWorkerTaskReference.get(); - } - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/AccountAdapter.java b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/AccountAdapter.java deleted file mode 100644 index ee209576..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/AccountAdapter.java +++ /dev/null @@ -1,76 +0,0 @@ -package de.thedevstack.conversationsplus.ui.adapter; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.CompoundButton; -import android.widget.ImageView; -import android.widget.Switch; -import android.widget.TextView; - -import java.util.List; - -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.ConversationsPlusColors; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.services.AvatarService; -import de.thedevstack.conversationsplus.ui.ManageAccountActivity; -import de.thedevstack.conversationsplus.ui.XmppActivity; - -public class AccountAdapter extends ArrayAdapter<Account> { - - private XmppActivity activity; - - public AccountAdapter(XmppActivity activity, List<Account> objects) { - super(activity, 0, objects); - this.activity = activity; - } - - @Override - public View getView(int position, View view, ViewGroup parent) { - final Account account = getItem(position); - if (view == null) { - LayoutInflater inflater = (LayoutInflater) getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = inflater.inflate(R.layout.account_row, parent, false); - } - TextView jid = (TextView) view.findViewById(R.id.account_jid); - if (Config.DOMAIN_LOCK != null) { - jid.setText(account.getJid().getLocalpart()); - } else { - jid.setText(account.getJid().toBareJid().toString()); - } - TextView statusView = (TextView) view.findViewById(R.id.account_status); - ImageView imageView = (ImageView) view.findViewById(R.id.account_image); - imageView.setImageBitmap(AvatarService.getInstance().get(account, activity.getPixel(48))); - statusView.setText(getContext().getString(account.getStatus().getReadableId())); - switch (account.getStatus()) { - case ONLINE: - statusView.setTextColor(ConversationsPlusColors.online()); - break; - case DISABLED: - case CONNECTING: - statusView.setTextColor(ConversationsPlusColors.secondaryText()); - break; - default: - statusView.setTextColor(ConversationsPlusColors.warning()); - break; - } - final Switch tglAccountState = (Switch) view.findViewById(R.id.tgl_account_status); - final boolean isDisabled = (account.getStatus() == Account.State.DISABLED); - tglAccountState.setChecked(!isDisabled); - tglAccountState.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton compoundButton, boolean b) { - // Condition compoundButton.isPressed() added because of http://stackoverflow.com/a/28219410 - if (compoundButton.isPressed() && b == isDisabled && activity instanceof ManageAccountActivity) { - ((ManageAccountActivity) activity).onClickTglAccountState(account, b); - } - } - }); - return view; - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ConversationAdapter.java b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ConversationAdapter.java deleted file mode 100644 index e0e672e3..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ConversationAdapter.java +++ /dev/null @@ -1,246 +0,0 @@ -package de.thedevstack.conversationsplus.ui.adapter; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.graphics.Typeface; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.util.Pair; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.TextView; - -import java.lang.ref.WeakReference; -import java.util.List; -import java.util.concurrent.RejectedExecutionException; - -import de.thedevstack.conversationsplus.ConversationsPlusColors; -import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.thedevstack.conversationsplus.ui.listeners.ShowResourcesListDialogListener; -import de.tzur.conversations.Settings; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.entities.Message; -import de.thedevstack.conversationsplus.entities.Transferable; -import de.thedevstack.conversationsplus.services.AvatarService; -import de.thedevstack.conversationsplus.ui.ConversationActivity; -import de.thedevstack.conversationsplus.ui.XmppActivity; -import de.thedevstack.conversationsplus.utils.UIHelper; - -public class ConversationAdapter extends ArrayAdapter<Conversation> { - - private XmppActivity activity; - - public ConversationAdapter(XmppActivity activity, - List<Conversation> conversations) { - super(activity, 0, conversations); - this.activity = activity; - } - - @Override - public View getView(int position, View view, ViewGroup parent) { - if (view == null) { - LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = inflater.inflate(R.layout.conversation_list_row,parent, false); - } - Conversation conversation = getItem(position); - // Highlight the currently selected conversation - if (this.activity instanceof ConversationActivity) { - ConversationActivity a = (ConversationActivity) this.activity; - int c = conversation == a.getSelectedConversation() ? ConversationsPlusColors.secondaryBackground() : ConversationsPlusColors.primaryBackground(); - view.findViewById(R.id.conversationListRowContent).setBackgroundColor(c); - view.findViewById(R.id.conversationListRowFrame).setBackgroundColor(c); - } - TextView convName = (TextView) view.findViewById(R.id.conversation_name); - if (conversation.getMode() == Conversation.MODE_SINGLE || ConversationsPlusPreferences.useSubject()) { - convName.setText(conversation.getName()); - } else { - convName.setText(conversation.getJid().toBareJid().toString()); - } - TextView mLastMessage = (TextView) view.findViewById(R.id.conversation_lastmsg); - TextView mTimestamp = (TextView) view.findViewById(R.id.conversation_lastupdate); - ImageView imagePreview = (ImageView) view.findViewById(R.id.conversation_lastimage); - ImageView notificationStatus = (ImageView) view.findViewById(R.id.notification_status); - TextView txtUnreadCount = (TextView) view.findViewById(R.id.conversation_unreadcount); - - if (Settings.SHOW_ONLINE_STATUS) { - int color = ConversationsPlusColors.offline(); - if (conversation.getAccount().getStatus() == Account.State.ONLINE) { - if (conversation.getMode() == Conversation.MODE_SINGLE) { - color = UIHelper.getStatusColor(conversation.getContact().getMostAvailableStatus()); - } else if (conversation.getMode() == Conversation.MODE_MULTI && conversation.getMucOptions().online()) { - color = ConversationsPlusColors.online(); - } - } - TextView status = (TextView) view.findViewById(R.id.status); - status.setBackgroundColor(color); - } - - Message message = conversation.getLatestMessage(); - - int txtUnreadCountVisibility = View.INVISIBLE; - if (!conversation.isRead()) { - convName.setTypeface(null, Typeface.BOLD); - txtUnreadCountVisibility = View.VISIBLE; - txtUnreadCount.setText(String.valueOf(conversation.unreadCount())); - } else { - convName.setTypeface(null, Typeface.NORMAL); - } - txtUnreadCount.setVisibility(txtUnreadCountVisibility); - - if ((null != message.getFileParams() && message.getFileParams().getWidth() > 0) // TODO: Use FileParams.getMimeType() - && (message.getTransferable() == null - || message.getTransferable().getStatus() != Transferable.STATUS_DELETED)) { - mLastMessage.setVisibility(View.GONE); - imagePreview.setVisibility(View.VISIBLE); - activity.loadBitmap(message, imagePreview, false); - } else { - Pair<String,Boolean> preview = UIHelper.getMessagePreview(activity,message); - mLastMessage.setVisibility(View.VISIBLE); - imagePreview.setVisibility(View.GONE); - CharSequence msgText = preview.first; - String msgPrefix = null; - if (message.getStatus() == Message.STATUS_SEND - || message.getStatus() == Message.STATUS_SEND_DISPLAYED - || message.getStatus() == Message.STATUS_SEND_FAILED - || message.getStatus() == Message.STATUS_SEND_RECEIVED) { - msgPrefix = activity.getString(R.string.cplus_me); - } else if (conversation.getMode() == Conversation.MODE_MULTI) { - msgPrefix = UIHelper.getMessageDisplayName(message); - } - String lastMessagePreview = ((null == msgPrefix || msgPrefix.isEmpty()) ? "" : (msgPrefix + ": ")) + msgText; - mLastMessage.setText(lastMessagePreview); - int lastMessageTypeface = Typeface.NORMAL; - if (conversation.isRead()) { - if (preview.second) { - lastMessageTypeface = Typeface.ITALIC; - } - } else { - if (preview.second) { - lastMessageTypeface = Typeface.BOLD_ITALIC; - } else { - lastMessageTypeface = Typeface.BOLD; - } - } - mLastMessage.setTypeface(null, lastMessageTypeface); - } - - long muted_till = conversation.getLongAttribute(Conversation.ATTRIBUTE_MUTED_TILL,0); - if (muted_till == Long.MAX_VALUE) { - notificationStatus.setVisibility(View.VISIBLE); - notificationStatus.setImageResource(R.drawable.ic_notifications_off_grey600_24dp); - } else if (muted_till >= System.currentTimeMillis()) { - notificationStatus.setVisibility(View.VISIBLE); - notificationStatus.setImageResource(R.drawable.ic_notifications_paused_grey600_24dp); - } else if (conversation.alwaysNotify()) { - notificationStatus.setImageResource(R.drawable.ic_notifications_grey600_24dp); - if (conversation.getMode() == Conversation.MODE_SINGLE) { - notificationStatus.setVisibility(View.GONE); - } else { - notificationStatus.setVisibility(View.VISIBLE); - } - } else { - notificationStatus.setVisibility(View.VISIBLE); - notificationStatus.setImageResource(R.drawable.ic_notifications_none_grey600_24dp); - } - - mTimestamp.setText(UIHelper.readableTimeDifference(activity, message.getTimeSent())); - ImageView profilePicture = (ImageView) view.findViewById(R.id.conversation_image); - if (conversation.getMode() == Conversation.MODE_SINGLE) { - profilePicture.setOnLongClickListener(new ShowResourcesListDialogListener(activity, conversation.getContact())); - } - loadAvatar(conversation, profilePicture); - - return view; - } - - class BitmapWorkerTask extends AsyncTask<Conversation, Void, Bitmap> { - private final WeakReference<ImageView> imageViewReference; - private Conversation conversation = null; - - public BitmapWorkerTask(ImageView imageView) { - imageViewReference = new WeakReference<>(imageView); - } - - @Override - protected Bitmap doInBackground(Conversation... params) { - return AvatarService.getInstance().get(params[0], activity.getPixel(56)); - } - - @Override - protected void onPostExecute(Bitmap bitmap) { - if (bitmap != null) { - final ImageView imageView = imageViewReference.get(); - if (imageView != null) { - imageView.setImageBitmap(bitmap); - imageView.setBackgroundColor(0x00000000); - } - } - } - } - - public void loadAvatar(Conversation conversation, ImageView imageView) { - if (cancelPotentialWork(conversation, imageView)) { - final Bitmap bm = AvatarService.getInstance().get(conversation, activity.getPixel(56), true); - if (bm != null) { - imageView.setImageBitmap(bm); - imageView.setBackgroundColor(0x00000000); - } else { - imageView.setBackgroundColor(UIHelper.getColorForName(conversation.getName())); - imageView.setImageDrawable(null); - final BitmapWorkerTask task = new BitmapWorkerTask(imageView); - final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task); - imageView.setImageDrawable(asyncDrawable); - try { - task.execute(conversation); - } catch (final RejectedExecutionException ignored) { - } - } - } - } - - public static boolean cancelPotentialWork(Conversation conversation, ImageView imageView) { - final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); - - if (bitmapWorkerTask != null) { - final Conversation oldConversation = bitmapWorkerTask.conversation; - if (oldConversation == null || conversation != oldConversation) { - bitmapWorkerTask.cancel(true); - } else { - return false; - } - } - return true; - } - - private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { - if (imageView != null) { - final Drawable drawable = imageView.getDrawable(); - if (drawable instanceof AsyncDrawable) { - final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; - return asyncDrawable.getBitmapWorkerTask(); - } - } - return null; - } - - static class AsyncDrawable extends BitmapDrawable { - private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference; - - public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { - super(res, bitmap); - bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask); - } - - public BitmapWorkerTask getBitmapWorkerTask() { - return bitmapWorkerTaskReference.get(); - } - } -}
\ No newline at end of file diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/KnownHostsAdapter.java b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/KnownHostsAdapter.java deleted file mode 100644 index 41973089..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/KnownHostsAdapter.java +++ /dev/null @@ -1,70 +0,0 @@ -package de.thedevstack.conversationsplus.ui.adapter; - -import android.content.Context; -import android.widget.ArrayAdapter; -import android.widget.Filter; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -public class KnownHostsAdapter extends ArrayAdapter<String> { - private ArrayList<String> domains; - private Filter domainFilter = new Filter() { - - @Override - protected FilterResults performFiltering(CharSequence constraint) { - if (constraint != null) { - ArrayList<String> suggestions = new ArrayList<>(); - final String[] split = constraint.toString().split("@"); - if (split.length == 1) { - for (String domain : domains) { - suggestions.add(split[0].toLowerCase(Locale - .getDefault()) + "@" + domain); - } - } else if (split.length == 2) { - for (String domain : domains) { - if (domain.contentEquals(split[1])) { - suggestions.clear(); - break; - } else if (domain.contains(split[1])) { - suggestions.add(split[0].toLowerCase(Locale - .getDefault()) + "@" + domain); - } - } - } else { - return new FilterResults(); - } - FilterResults filterResults = new FilterResults(); - filterResults.values = suggestions; - filterResults.count = suggestions.size(); - return filterResults; - } else { - return new FilterResults(); - } - } - - @Override - protected void publishResults(CharSequence constraint, - FilterResults results) { - ArrayList filteredList = (ArrayList) results.values; - if (results != null && results.count > 0) { - clear(); - for (Object c : filteredList) { - add((String) c); - } - notifyDataSetChanged(); - } - } - }; - - public KnownHostsAdapter(Context context, int viewResourceId, List<String> mKnownHosts) { - super(context, viewResourceId, new ArrayList<String>()); - domains = new ArrayList<>(mKnownHosts); - } - - @Override - public Filter getFilter() { - return domainFilter; - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ListItemAdapter.java b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ListItemAdapter.java deleted file mode 100644 index a67f5bcd..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/ListItemAdapter.java +++ /dev/null @@ -1,187 +0,0 @@ -package de.thedevstack.conversationsplus.ui.adapter; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.lang.ref.WeakReference; -import java.util.List; -import java.util.concurrent.RejectedExecutionException; - -import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.tzur.conversations.Settings; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.ListItem; -import de.thedevstack.conversationsplus.services.AvatarService; -import de.thedevstack.conversationsplus.ui.XmppActivity; -import de.thedevstack.conversationsplus.utils.UIHelper; - -public class ListItemAdapter extends ArrayAdapter<ListItem> { - - protected XmppActivity activity; - protected boolean showDynamicTags = false; - private View.OnClickListener onTagTvClick = new View.OnClickListener() { - @Override - public void onClick(View view) { - if (view instanceof TextView && mOnTagClickedListener != null) { - TextView tv = (TextView) view; - final String tag = tv.getText().toString(); - mOnTagClickedListener.onTagClicked(tag); - } - } - }; - private OnTagClickedListener mOnTagClickedListener = null; - - public ListItemAdapter(XmppActivity activity, List<ListItem> objects) { - super(activity, 0, objects); - this.activity = activity; - this.showDynamicTags = ConversationsPlusPreferences.showDynamicTags(); - } - - @Override - public View getView(int position, View view, ViewGroup parent) { - LayoutInflater inflater = (LayoutInflater) getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - ListItem item = getItem(position); - if (view == null) { - view = inflater.inflate(R.layout.contact, parent, false); - } - - if (Settings.SHOW_ONLINE_STATUS) { - TextView tvStatus = (TextView) view.findViewById(R.id.contact_status); - tvStatus.setBackgroundColor(item.getStatusColor()); - } - - TextView tvName = (TextView) view.findViewById(R.id.contact_display_name); - TextView tvJid = (TextView) view.findViewById(R.id.contact_jid); - ImageView picture = (ImageView) view.findViewById(R.id.contact_photo); - LinearLayout tagLayout = (LinearLayout) view.findViewById(R.id.tags); - - List<ListItem.Tag> tags = item.getTags(); - if (tags.size() == 0 || !this.showDynamicTags) { - tagLayout.setVisibility(View.GONE); - } else { - tagLayout.setVisibility(View.VISIBLE); - tagLayout.removeAllViewsInLayout(); - for(ListItem.Tag tag : tags) { - TextView tv = (TextView) inflater.inflate(R.layout.list_item_tag,tagLayout,false); - tv.setText(tag.getName()); - tv.setBackgroundColor(tag.getColor()); - tv.setOnClickListener(this.onTagTvClick); - tagLayout.addView(tv); - } - } - final String jid = item.getDisplayJid(); - if (jid != null) { - tvJid.setVisibility(View.VISIBLE); - tvJid.setText(jid); - } else { - tvJid.setVisibility(View.GONE); - } - tvName.setText(item.getDisplayName()); - loadAvatar(item,picture); - return view; - } - - public void setOnTagClickedListener(OnTagClickedListener listener) { - this.mOnTagClickedListener = listener; - } - - public interface OnTagClickedListener { - void onTagClicked(String tag); - } - - class BitmapWorkerTask extends AsyncTask<ListItem, Void, Bitmap> { - private final WeakReference<ImageView> imageViewReference; - private ListItem item = null; - - public BitmapWorkerTask(ImageView imageView) { - imageViewReference = new WeakReference<>(imageView); - } - - @Override - protected Bitmap doInBackground(ListItem... params) { - return AvatarService.getInstance().get(params[0], activity.getPixel(48)); - } - - @Override - protected void onPostExecute(Bitmap bitmap) { - if (bitmap != null) { - final ImageView imageView = imageViewReference.get(); - if (imageView != null) { - imageView.setImageBitmap(bitmap); - imageView.setBackgroundColor(0x00000000); - } - } - } - } - - public void loadAvatar(ListItem item, ImageView imageView) { - if (cancelPotentialWork(item, imageView)) { - final Bitmap bm = AvatarService.getInstance().get(item,activity.getPixel(48),true); - if (bm != null) { - imageView.setImageBitmap(bm); - imageView.setBackgroundColor(0x00000000); - } else { - imageView.setBackgroundColor(UIHelper.getColorForName(item.getDisplayName())); - imageView.setImageDrawable(null); - final BitmapWorkerTask task = new BitmapWorkerTask(imageView); - final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task); - imageView.setImageDrawable(asyncDrawable); - try { - task.execute(item); - } catch (final RejectedExecutionException ignored) { - } - } - } - } - - public static boolean cancelPotentialWork(ListItem item, ImageView imageView) { - final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); - - if (bitmapWorkerTask != null) { - final ListItem oldItem = bitmapWorkerTask.item; - if (oldItem == null || item != oldItem) { - bitmapWorkerTask.cancel(true); - } else { - return false; - } - } - return true; - } - - private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { - if (imageView != null) { - final Drawable drawable = imageView.getDrawable(); - if (drawable instanceof AsyncDrawable) { - final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; - return asyncDrawable.getBitmapWorkerTask(); - } - } - return null; - } - - static class AsyncDrawable extends BitmapDrawable { - private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference; - - public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { - super(res, bitmap); - bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask); - } - - public BitmapWorkerTask getBitmapWorkerTask() { - return bitmapWorkerTaskReference.get(); - } - } - -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java deleted file mode 100644 index 79ab3bc3..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java +++ /dev/null @@ -1,880 +0,0 @@ -package de.thedevstack.conversationsplus.ui.adapter; - -import android.content.ActivityNotFoundException; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Typeface; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.AsyncTask; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.Spanned; -import android.text.style.ForegroundColorSpan; -import android.text.style.RelativeSizeSpan; -import android.text.style.StyleSpan; -import android.text.util.Linkify; -import android.util.Patterns; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnLongClickListener; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.Toast; - -import java.lang.ref.WeakReference; -import java.util.List; -import java.util.concurrent.RejectedExecutionException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import de.thedevstack.conversationsplus.ConversationsPlusApplication; -import de.thedevstack.conversationsplus.ConversationsPlusColors; -import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.crypto.axolotl.XmppAxolotlSession; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.entities.DownloadableFile; -import de.thedevstack.conversationsplus.entities.FileParams; -import de.thedevstack.conversationsplus.entities.Message; -import de.thedevstack.conversationsplus.entities.Transferable; -import de.thedevstack.conversationsplus.enums.FileStatus; -import de.thedevstack.conversationsplus.http.HttpConnectionManager; -import de.thedevstack.conversationsplus.persistance.FileBackend; -import de.thedevstack.conversationsplus.providers.ConversationsPlusFileProvider; -import de.thedevstack.conversationsplus.services.AvatarService; -import de.thedevstack.conversationsplus.ui.ConversationActivity; -import de.thedevstack.conversationsplus.utils.CryptoHelper; -import de.thedevstack.conversationsplus.utils.GeoHelper; -import de.thedevstack.conversationsplus.utils.MessageUtil; -import de.thedevstack.conversationsplus.utils.UIHelper; -import de.thedevstack.conversationsplus.utils.ui.TextViewUtil; -import de.thedevstack.conversationsplus.utils.ui.ViewUtil; - -public class MessageAdapter extends ArrayAdapter<Message> { - - private static final int SENT = 0; - private static final int RECEIVED = 1; - private static final int STATUS = 2; - private static final int NULL = 3; - private static final Pattern XMPP_PATTERN = Pattern - .compile("xmpp\\:(?:(?:[" - + Patterns.GOOD_IRI_CHAR - + "\\;\\/\\?\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])" - + "|(?:\\%[a-fA-F0-9]{2}))+"); - - private ConversationActivity activity; - - private OnContactPictureClicked mOnContactPictureClickedListener; - private OnContactPictureLongClicked mOnContactPictureLongClickedListener; - - public MessageAdapter(ConversationActivity activity, List<Message> messages) { - super(activity, 0, messages); - this.activity = activity; - } - - public void setOnContactPictureClicked(OnContactPictureClicked listener) { - this.mOnContactPictureClickedListener = listener; - } - - public void setOnContactPictureLongClicked( - OnContactPictureLongClicked listener) { - this.mOnContactPictureLongClickedListener = listener; - } - - @Override - public int getViewTypeCount() { - return 3; - } - - public int getItemViewType(Message message) { - if (message.getType() == Message.TYPE_STATUS) { - return STATUS; - } else if (message.getStatus() <= Message.STATUS_RECEIVED) { - return RECEIVED; - } - - return SENT; - } - - @Override - public int getItemViewType(int position) { - return this.getItemViewType(getItem(position)); - } - - private int getMessageTextColor(boolean onDark, boolean primary) { - if (onDark) { - return primary ? ConversationsPlusColors.primaryTextOnDark() : ConversationsPlusColors.secondaryTextOnDark(); - } else { - return primary ? ConversationsPlusColors.primaryText() : ConversationsPlusColors.secondaryText(); - } - } - - private void displayStatus(ViewHolder viewHolder, Message message, int type, boolean darkBackground) { - String filesize = null; - String info = null; - boolean error = false; - if (viewHolder.indicatorReceived != null) { - viewHolder.indicatorReceived.setVisibility(View.GONE); - } - - boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI - && message.getStatus() <= Message.STATUS_RECEIVED; - if (message.hasFileAttached() || message.getTransferable() != null) { - FileParams params = message.getFileParams(); - if (null != params) { - filesize = UIHelper.getHumanReadableFileSize(params.getSize()); - } - - if (message.getTransferable() != null && message.getTransferable().getStatus() == Transferable.STATUS_FAILED) { - error = true; - } - } - switch (message.getStatus()) { - case Message.STATUS_WAITING: - info = getContext().getString(R.string.waiting); - break; - case Message.STATUS_UNSEND: - Transferable d = message.getTransferable(); - if (d!=null) { - info = getContext().getString(R.string.sending_file,d.getProgress()); - } else { - info = getContext().getString(R.string.sending); - } - break; - case Message.STATUS_OFFERED: - info = getContext().getString(R.string.offering); - break; - case Message.STATUS_SEND_RECEIVED: - if (ConversationsPlusPreferences.indicateReceived()) { - viewHolder.indicatorReceived.setVisibility(View.VISIBLE); - } - break; - case Message.STATUS_SEND_DISPLAYED: - if (ConversationsPlusPreferences.indicateReceived()) { - viewHolder.indicatorReceived.setVisibility(View.VISIBLE); - } - break; - case Message.STATUS_SEND_FAILED: - info = getContext().getString(R.string.send_failed); - error = true; - break; - default: - if (multiReceived) { - info = UIHelper.getMessageDisplayName(message); - } - break; - } - if (error && type == SENT) { - viewHolder.time.setTextColor(ConversationsPlusColors.warning()); - } else { - viewHolder.time.setTextColor(this.getMessageTextColor(darkBackground,false)); - } - if (message.getEncryption() == Message.ENCRYPTION_NONE) { - viewHolder.indicator.setVisibility(View.GONE); - } else { - viewHolder.indicator.setImageResource(darkBackground ? R.drawable.ic_lock_white_18dp : R.drawable.ic_lock_black_18dp); - viewHolder.indicator.setVisibility(View.VISIBLE); - if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) { - XmppAxolotlSession.Trust trust = message.getConversation() - .getAccount().getAxolotlService().getFingerprintTrust( - message.getFingerprint()); - - if(trust == null || (!trust.trusted() && !trust.trustedInactive())) { - viewHolder.indicator.setColorFilter(ConversationsPlusColors.warning()); - viewHolder.indicator.setAlpha(1.0f); - } else { - viewHolder.indicator.clearColorFilter(); - if (darkBackground) { - viewHolder.indicator.setAlpha(0.7f); - } else { - viewHolder.indicator.setAlpha(0.57f); - } - } - } else { - viewHolder.indicator.clearColorFilter(); - if (darkBackground) { - viewHolder.indicator.setAlpha(0.7f); - } else { - viewHolder.indicator.setAlpha(0.57f); - } - } - } - - String formatedTime = UIHelper.readableTimeDifferenceFull(getContext(), - message.getTimeSent()); - if (message.getStatus() <= Message.STATUS_RECEIVED) { - StringBuilder timeText = new StringBuilder(); - timeText.append((null != formatedTime) ? formatedTime + ((null != info || null != filesize) ? " \u00B7 " : "") : ""); - timeText.append((null != filesize) ? filesize + ((null != info) ? " \u00B7 " : "") : ""); - timeText.append((null != info) ? info : ""); - viewHolder.time.setText(timeText); - } else { - if ((filesize != null) && (info != null)) { - viewHolder.time.setText(filesize + " \u00B7 " + info); - } else if ((filesize == null) && (info != null)) { - if (error) { - viewHolder.time.setText(info + " \u00B7 " + formatedTime); - } else { - viewHolder.time.setText(info); - } - } else if ((filesize != null) && (info == null)) { - viewHolder.time.setText(filesize + " \u00B7 " + formatedTime); - } else { - viewHolder.time.setText(formatedTime); - } - } - - if (message.hasFileAttached() && null != message.getFileParams() && null != viewHolder.remoteFileStatus) { - FileStatus fileStatus = message.getFileParams().getFileStatus(); - if (fileStatus == FileStatus.DELETE_FAILED || fileStatus == FileStatus.DELETED || fileStatus == FileStatus.DELETING) { - viewHolder.remoteFileStatus.setVisibility(View.VISIBLE); - switch (fileStatus) { - case DELETE_FAILED: - TextViewUtil.setColor(viewHolder.remoteFileStatus, R.color.error); - viewHolder.remoteFileStatus.setText(R.string.remote_filestatus_delete_failed); - break; - case DELETED: - viewHolder.remoteFileStatus.setText(R.string.remote_filestatus_delete_success); - break; - case DELETING: - viewHolder.remoteFileStatus.setText(R.string.remote_filestatus_delete_inprogress); - break; - } - } - } - } - - private void displayInfoMessage(ViewHolder viewHolder, String text, boolean darkBackground) { - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } - viewHolder.image.setVisibility(View.GONE); - viewHolder.messageBody.setVisibility(View.VISIBLE); - viewHolder.messageBody.setText(text); - viewHolder.messageBody.setTextColor(getMessageTextColor(darkBackground, false)); - viewHolder.messageBody.setTypeface(null, Typeface.ITALIC); - viewHolder.messageBody.setTextIsSelectable(false); - } - - private void displayDecryptionFailed(ViewHolder viewHolder, boolean darkBackground) { - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } - viewHolder.image.setVisibility(View.GONE); - viewHolder.messageBody.setVisibility(View.VISIBLE); - viewHolder.messageBody.setText(getContext().getString( - R.string.decryption_failed)); - viewHolder.messageBody.setTextColor(getMessageTextColor(darkBackground, false)); - viewHolder.messageBody.setTypeface(null, Typeface.NORMAL); - viewHolder.messageBody.setTextIsSelectable(false); - } - - private void displayTextMessage(final ViewHolder viewHolder, final Message message, boolean darkBackground) { - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } - viewHolder.image.setVisibility(View.GONE); - viewHolder.messageBody.setVisibility(View.VISIBLE); - viewHolder.messageBody.setIncludeFontPadding(true); - if (message.getBody() != null) { - final String nick = UIHelper.getMessageDisplayName(message); - String body; - if (message.hasMeCommand()) { - body = message.getBodyReplacedMeCommand(nick); - } else { - body = message.getBody(); - } - final SpannableString formattedBody = new SpannableString(body); - int i = body.indexOf(Message.MERGE_SEPARATOR); - while(i >= 0) { - final int end = i + Message.MERGE_SEPARATOR.length(); - formattedBody.setSpan(new RelativeSizeSpan(0.3f),i,end,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - i = body.indexOf(Message.MERGE_SEPARATOR,end); - } - if (message.getType() != Message.TYPE_PRIVATE) { - if (message.hasMeCommand()) { - final Spannable span = new SpannableString(formattedBody); - span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, nick.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - viewHolder.messageBody.setText(span); - } else { - viewHolder.messageBody.setText(formattedBody); - } - } else { - String privateMarker; - if (message.getStatus() <= Message.STATUS_RECEIVED) { - privateMarker = activity - .getString(R.string.private_message); - } else { - final String to; - if (message.getCounterpart() != null) { - to = message.getCounterpart().getResourcepart(); - } else { - to = ""; - } - privateMarker = activity.getString(R.string.private_message_to, to); - } - final Spannable span = new SpannableString(privateMarker + " " - + formattedBody); - span.setSpan(new ForegroundColorSpan(getMessageTextColor(darkBackground,false)), 0, privateMarker - .length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - span.setSpan(new StyleSpan(Typeface.BOLD), 0, - privateMarker.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - if (message.hasMeCommand()) { - span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), privateMarker.length() + 1, - privateMarker.length() + 1 + nick.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - viewHolder.messageBody.setText(span); - } - int patternMatchCount = 0; - int oldAutoLinkMask = viewHolder.messageBody.getAutoLinkMask(); - - // first check if we have a match on XMPP_PATTERN so we do not have to check for EMAIL_ADDRESSES - patternMatchCount += countMatches(XMPP_PATTERN, body); - if ((Linkify.EMAIL_ADDRESSES & oldAutoLinkMask) != 0 && patternMatchCount > 0) { - oldAutoLinkMask -= Linkify.EMAIL_ADDRESSES; - } - - // count matches for all patterns - if ((Linkify.WEB_URLS & oldAutoLinkMask) != 0) { - patternMatchCount += countMatches(Patterns.WEB_URL, body); - } - if ((Linkify.EMAIL_ADDRESSES & oldAutoLinkMask) != 0) { - patternMatchCount += countMatches(Patterns.EMAIL_ADDRESS, body); - } - if ((Linkify.PHONE_NUMBERS & oldAutoLinkMask) != 0) { - patternMatchCount += countMatches(Patterns.PHONE, body); - } - - viewHolder.messageBody.setTextIsSelectable(patternMatchCount <= 1); - viewHolder.messageBody.setAutoLinkMask(0); - Linkify.addLinks(viewHolder.messageBody, XMPP_PATTERN, "xmpp"); - viewHolder.messageBody.setAutoLinkMask(oldAutoLinkMask); - } else { - viewHolder.messageBody.setText(""); - viewHolder.messageBody.setTextIsSelectable(false); - } - viewHolder.messageBody.setTextColor(this.getMessageTextColor(darkBackground, true)); - viewHolder.messageBody.setTypeface(null, Typeface.NORMAL); - } - - /** - * Counts the number of occurrences of the pattern in body. - * @param pattern the pattern to match - * @param body the body to find the pattern - * @return the number of occurrences - */ - private int countMatches(Pattern pattern, String body) { - Matcher matcher = pattern.matcher(body); - int count = 0; - while (matcher.find()) { - count++; - } - return count; - } - - private void displayDownloadButton(ViewHolder viewHolder, String btnText, OnClickListener onClickListener) { - viewHolder.download_button.setVisibility(View.VISIBLE); - viewHolder.download_button.setText(btnText); - viewHolder.download_button.setOnClickListener(onClickListener); - } - - private void displayFileInfoForFileMessage(final Message message, ViewHolder viewHolder) { - viewHolder.messageBody.setVisibility(View.VISIBLE); - StringBuilder fileInfos = new StringBuilder(); - String filename = UIHelper.getDisplayFilename(message); - fileInfos.append((null != filename && !filename.isEmpty()) ? (filename) : ""); - - int oldAutoLinkMask = viewHolder.messageBody.getAutoLinkMask(); - viewHolder.messageBody.setAutoLinkMask(0); - viewHolder.messageBody.setText(fileInfos); - viewHolder.messageBody.setAutoLinkMask(oldAutoLinkMask); - } - - private void displayDownloadableMessage(ViewHolder viewHolder, final Message message, int resId) { - viewHolder.image.setVisibility(View.GONE); - FileParams fileParams = message.getFileParams(); - String btnText; - if (null != fileParams) { - this.displayFileInfoForFileMessage(message, viewHolder); - btnText = activity.getString(resId, ""); - } else { - viewHolder.messageBody.setVisibility(View.GONE); - btnText = activity.getString(resId, UIHelper.getFileDescriptionString(activity, message)); - } - - this.displayDownloadButton(viewHolder, btnText, new OnClickListener() { - - @Override - public void onClick(View v) { - activity.startDownloadable(message); - } - }); - } - - private void displayOpenableMessage(ViewHolder viewHolder,final Message message) { - viewHolder.image.setVisibility(View.GONE); - - FileParams fileParams = message.getFileParams(); - String btnText; - if (null != fileParams) { - this.displayFileInfoForFileMessage(message, viewHolder); - btnText = activity.getString(R.string.cplus_open); - } else { - viewHolder.messageBody.setVisibility(View.GONE); - btnText = activity.getString(R.string.open_x_file, UIHelper.getFileDescriptionString(activity, message)); - } - - this.displayDownloadButton(viewHolder, btnText, new OnClickListener() { - - @Override - public void onClick(View v) { - openDownloadable(message); - } - }); - } - - private void displayLocationMessage(ViewHolder viewHolder, final Message message) { - viewHolder.image.setVisibility(View.GONE); - viewHolder.messageBody.setVisibility(View.GONE); - viewHolder.download_button.setVisibility(View.VISIBLE); - viewHolder.download_button.setText(R.string.show_location); - viewHolder.download_button.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - showLocation(message); - } - }); - } - - private void displayImageMessage(ViewHolder viewHolder, - final Message message) { - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } - viewHolder.messageBody.setVisibility(View.GONE); - viewHolder.image.setVisibility(View.VISIBLE); - //TODO: Check what value add the following lines have (compared with setting height/width in XmppActivity.loadBitmap from thumbnail after thumbnail is created) - /* - FileParams params = message.getFileParams(); - double target = metrics.density * 288; - int scalledW; - int scalledH; - if (params.width <= params.height) { - scalledW = (int) (params.width / ((double) params.height / target)); - scalledH = (int) target; - } else { - scalledW = (int) target; - scalledH = (int) (params.height / ((double) params.width / target)); - } - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(scalledW, scalledH); - layoutParams.setMargins(0, (int) (metrics.density * 4), 0, (int) (metrics.density * 4)); - viewHolder.image.setLayoutParams(layoutParams);*/ - //TODO Why should this be calculated by hand??? - activity.loadBitmap(message, viewHolder.image, true); - viewHolder.image.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - openDownloadable(message); - } - }); - } - - private View displayStatusMessage(final Message message, ViewHolder viewHolder) { - if (null != viewHolder) { - final Conversation conversation = message.getConversation(); - - viewHolder.status_message.setVisibility(View.VISIBLE); - viewHolder.contact_picture.setVisibility(View.VISIBLE); - if (conversation.getMode() == Conversation.MODE_SINGLE) { - viewHolder.contact_picture.setImageBitmap(AvatarService.getInstance().get(conversation.getContact(), - activity.getPixel(32))); - viewHolder.contact_picture.setAlpha(0.5f); - } - viewHolder.status_message.setText(message.getBody()); - } - return viewHolder.view; - } - - private void displayFileMessage(final Message message, ViewHolder viewHolder) { - final FileParams fileParams = message.getFileParams(); - String mimeType = (null != fileParams) ? fileParams.getMimeType() : null; - if ((message.getType() == Message.TYPE_IMAGE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) - || (fileParams != null && fileParams.getWidth() > 0) - || (null != mimeType && mimeType.startsWith("image/"))) { - displayImageMessage(viewHolder, message); - } else if ((message.getType() == Message.TYPE_FILE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) - && null != fileParams && (FileStatus.NEEDS_DOWNLOAD != fileParams.getFileStatus() || 0 == fileParams.getWidth())) { - displayOpenableMessage(viewHolder, message); - } else if (Message.Decision.NEVER == message.treatAsDownloadable()) { - displayTextMessage(viewHolder, message, getItemViewType(message) == RECEIVED && !message.isValidInSession()); - } else { - displayDownloadableMessage(viewHolder, message, R.string.download_x_file); - } - } - - - private void loadAvatar(Message message, ImageView imageView) { - if (cancelPotentialWork(message, imageView)) { - int avatarPixel = imageView.getResources().getDimensionPixelOffset(R.dimen.msg_avatar_size); - final Bitmap bm = AvatarService.getInstance().get(message, avatarPixel, true); - if (bm != null) { - imageView.setImageBitmap(bm); - imageView.setBackgroundColor(0x00000000); - } else { - imageView.setBackgroundColor(UIHelper.getColorForName(UIHelper.getMessageDisplayName(message))); - imageView.setImageDrawable(null); - final BitmapWorkerTask task = new BitmapWorkerTask(imageView); - final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task); - imageView.setImageDrawable(asyncDrawable); - try { - task.execute(message); - } catch (final RejectedExecutionException ignored) { - } - } - } - } - - private void displayAvatar(final Message message, int type, ViewHolder viewHolder) { - if (type == RECEIVED) { - ImageView imageView = viewHolder.contact_picture; - if (null != imageView) { - this.loadAvatar(message, imageView); - imageView.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - if (MessageAdapter.this.mOnContactPictureClickedListener != null) { - MessageAdapter.this.mOnContactPictureClickedListener - .onContactPictureClicked(message); - } - - } - }); - if (message.getConversation().getMode() == Conversation.MODE_MULTI) { - imageView.setOnLongClickListener(new OnLongClickListener() { - - @Override - public boolean onLongClick(View v) { - if (MessageAdapter.this.mOnContactPictureLongClickedListener != null) { - MessageAdapter.this.mOnContactPictureLongClickedListener - .onContactPictureLongClicked(message); - return true; - } else { - return false; - } - } - }); - } - } - } - } - - private View initializeView(int type, ViewGroup parent) { - Integer viewResId = null; - - switch (type) { - case SENT: - viewResId = R.layout.message_sent; - break; - case RECEIVED: - viewResId = R.layout.message_received; - break; - case STATUS: - viewResId = R.layout.message_status; - break; - } - - return activity.getLayoutInflater().inflate(viewResId, parent, false); - } - - private ViewHolder initializeViewHolderAndView(Message message, int type, ViewGroup parent) { - View view = initializeView(type, parent); - ViewHolder viewHolder = new ViewHolder(view); - if (SENT == type - || RECEIVED == type) { - viewHolder.message_box = ViewUtil.visible(view, R.id.message_box); - viewHolder.indicator = (ImageView) view.findViewById(R.id.security_indicator); - viewHolder.messageBody = (TextView) view.findViewById(R.id.message_body); - viewHolder.time = (TextView) view.findViewById(R.id.message_time); - viewHolder.indicatorReceived = (ImageView) view.findViewById(R.id.indicator_received); - } - if ((SENT == type - || RECEIVED == type)) { - viewHolder.download_button = (Button) view.findViewById(R.id.download_button); - viewHolder.image = (ImageView) view.findViewById(R.id.message_image); - } - if (RECEIVED == type) { // Extra block as preparation for new /me representation - viewHolder.contact_picture = ViewUtil.visible(view, R.id.message_photo); - } - if (RECEIVED == type) { - viewHolder.encryption = (TextView) view.findViewById(R.id.message_encryption); - } - if (STATUS == type) { - viewHolder.contact_picture = ViewUtil.visible(view, R.id.message_photo); - viewHolder.status_message = TextViewUtil.visible(view, R.id.status_message); - } - if (SENT == type) { - viewHolder.remoteFileStatus = TextViewUtil.gone(view, R.id.remote_file_status); - } - view.setTag(viewHolder); - - return viewHolder; - } - - @Override - public View getView(int position, View view, ViewGroup parent) { - final Message message = getItem(position); - final boolean isInValidSession = message.isValidInSession(); - final Conversation conversation = message.getConversation(); - final Account account = conversation.getAccount(); - final int type = getItemViewType(position); - ViewHolder viewHolder; - if (null == view) { - viewHolder = initializeViewHolderAndView(message, type, parent); - view = viewHolder.view; - } else { - viewHolder = (ViewHolder) view.getTag(); - if (null == viewHolder) { - return view; - } - } - - if (type == STATUS) { - return displayStatusMessage(message, viewHolder); - } - - this.displayAvatar(message, type, viewHolder); - - boolean darkBackground = (type == RECEIVED && !isInValidSession); - this.displayStatus(viewHolder, message, type, darkBackground); - - final Transferable transferable = message.getTransferable(); - if (null != transferable) { - switch (transferable.getStatus()) { - case Transferable.STATUS_OFFER: - displayDownloadableMessage(viewHolder, message, R.string.download_x_file); - break; - case Transferable.STATUS_OFFER_CHECK_FILESIZE: - displayDownloadableMessage(viewHolder, message, R.string.check_x_filesize); - break; - case Transferable.STATUS_UPLOADING: - displayFileMessage(message, viewHolder); - break; - case Transferable.STATUS_DELETED: - case Transferable.STATUS_CHECKING: - case Transferable.STATUS_FAILED: - case Transferable.STATUS_UNKNOWN: - displayInfoMessage(viewHolder, UIHelper.getMessagePreview(activity, message).first,darkBackground); - break; - } - } else if (message.hasFileAttached()) { - if (message.trusted() - && MessageUtil.needsDownload(message) - && ConversationsPlusPreferences.autoAcceptFileSize() > 0 - && (message.isHttpUploaded() || ConversationsPlusPreferences.autoDownloadFileLink())) { - HttpConnectionManager.createNewDownloadConnection(message); - } else { - displayFileMessage(message, viewHolder); - } - } else if (GeoHelper.isGeoUri(message.getBody())) { - displayLocationMessage(viewHolder, message); - } else if (message.getEncryption() == Message.ENCRYPTION_PGP) { - if (activity.hasPgp()) { - if (account.getPgpDecryptionService().isRunning()) { - displayInfoMessage(viewHolder, activity.getString(R.string.message_decrypting), darkBackground); - } else { - displayInfoMessage(viewHolder, activity.getString(R.string.pgp_message), darkBackground); - } - } else { - displayInfoMessage(viewHolder,activity.getString(R.string.install_openkeychain),darkBackground); - if (viewHolder != null) { - viewHolder.message_box - .setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - activity.showInstallPgpDialog(); - } - }); - } - } - } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { - displayDecryptionFailed(viewHolder,darkBackground); - } else { - displayTextMessage(viewHolder, message, darkBackground); - } - - if (type == RECEIVED) { - if(isInValidSession) { - viewHolder.encryption.setVisibility(View.GONE); - } else { - viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_received_warning); - viewHolder.encryption.setVisibility(View.VISIBLE); - viewHolder.encryption.setText(CryptoHelper.encryptionTypeToText(message.getEncryption())); - } - } - - return view; - } - - public void openDownloadable(Message message) { - DownloadableFile file = FileBackend.getFile(message); - if (!file.exists()) { - Toast.makeText(activity,R.string.file_deleted,Toast.LENGTH_SHORT).show(); - return; - } - boolean bInPrivateStorage = false; - if (file.getAbsolutePath().startsWith(FileBackend.getPrivateFileDirectoryPath())) { - bInPrivateStorage = true; - } - Intent openIntent = new Intent(Intent.ACTION_VIEW); - String mime = file.getMimeType(); - if (mime == null) { - mime = "*/*"; - } - Uri uri; - if (bInPrivateStorage) { - uri = ConversationsPlusFileProvider.createUriForPrivateFile(file); - } else { - uri = Uri.fromFile(file); - } - openIntent.setDataAndType(uri, mime); - PackageManager manager = activity.getPackageManager(); - List<ResolveInfo> infos = manager.queryIntentActivities(openIntent, 0); - if (bInPrivateStorage) { - for (ResolveInfo info : infos) { - ConversationsPlusApplication.getAppContext().grantUriPermission(info.activityInfo.packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - } - if (infos.size() == 0) { - openIntent.setDataAndType(uri,"*/*"); - } - if (bInPrivateStorage) { - openIntent.putExtra(Intent.EXTRA_STREAM, uri); - openIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - try { - getContext().startActivity(openIntent); - return; - } catch (ActivityNotFoundException e) { - //ignored - } - Toast.makeText(activity,R.string.no_application_found_to_open_file,Toast.LENGTH_SHORT).show(); - } - - public void showLocation(Message message) { - for(Intent intent : GeoHelper.createGeoIntentsFromMessage(message)) { - if (intent.resolveActivity(getContext().getPackageManager()) != null) { - getContext().startActivity(intent); - return; - } - } - Toast.makeText(activity,R.string.no_application_found_to_display_location,Toast.LENGTH_SHORT).show(); - } - - public interface OnContactPictureClicked { - void onContactPictureClicked(Message message); - } - - public interface OnContactPictureLongClicked { - void onContactPictureLongClicked(Message message); - } - - private static class ViewHolder { - protected ViewHolder(View view) { - this.view = view; - } - protected View view; - - protected LinearLayout message_box; - protected Button download_button; - protected ImageView image; - protected ImageView indicator; - protected ImageView indicatorReceived; - protected TextView time; - protected TextView messageBody; - protected ImageView contact_picture; - protected TextView status_message; - protected TextView encryption; - public TextView remoteFileStatus; - } - - class BitmapWorkerTask extends AsyncTask<Message, Void, Bitmap> { - private final WeakReference<ImageView> imageViewReference; - private Message message = null; - - public BitmapWorkerTask(ImageView imageView) { - imageViewReference = new WeakReference<>(imageView); - } - - @Override - protected Bitmap doInBackground(Message... params) { - int avatarPixel = activity.getResources().getDimensionPixelOffset(R.dimen.msg_avatar_size); - return AvatarService.getInstance().get(params[0], avatarPixel, isCancelled()); - } - - @Override - protected void onPostExecute(Bitmap bitmap) { - if (bitmap != null) { - final ImageView imageView = imageViewReference.get(); - if (imageView != null) { - imageView.setImageBitmap(bitmap); - imageView.setBackgroundColor(0x00000000); - } - } - } - } - - public static boolean cancelPotentialWork(Message message, ImageView imageView) { - final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); - - if (bitmapWorkerTask != null) { - final Message oldMessage = bitmapWorkerTask.message; - if (oldMessage == null || message != oldMessage) { - bitmapWorkerTask.cancel(true); - } else { - return false; - } - } - return true; - } - - private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { - if (imageView != null) { - final Drawable drawable = imageView.getDrawable(); - if (drawable instanceof AsyncDrawable) { - final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; - return asyncDrawable.getBitmapWorkerTask(); - } - } - return null; - } - - static class AsyncDrawable extends BitmapDrawable { - private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference; - - public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { - super(res, bitmap); - bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask); - } - - public BitmapWorkerTask getBitmapWorkerTask() { - return bitmapWorkerTaskReference.get(); - } - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/PresencesArrayAdapter.java b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/PresencesArrayAdapter.java index 2d777897..d1f1e835 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/PresencesArrayAdapter.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/PresencesArrayAdapter.java @@ -11,9 +11,9 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.Map; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Presences; -import de.thedevstack.conversationsplus.utils.UIHelper; +import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Presences; +import eu.siacs.conversations.utils.UIHelper; /** * Created by tzur on 27.09.2015. @@ -44,7 +44,7 @@ public class PresencesArrayAdapter extends ArrayAdapter<Presence> { private static Presence[] getPresenceArray(Presences presences) { ArrayList<Presence> presenceArrayList = new ArrayList<>(); if (null != presences && null != presences.getPresences() && !presences.getPresences().isEmpty()) { - for (Map.Entry<String, de.thedevstack.conversationsplus.entities.Presence> entry : presences.getPresences().entrySet()) { + for (Map.Entry<String, eu.siacs.conversations.entities.Presence> entry : presences.getPresences().entrySet()) { Presence p = new Presence(); p.resource = entry.getKey(); p.status = entry.getValue().getStatus(); @@ -58,5 +58,5 @@ public class PresencesArrayAdapter extends ArrayAdapter<Presence> { class Presence { String resource; - de.thedevstack.conversationsplus.entities.Presence.Status status; + eu.siacs.conversations.entities.Presence.Status status; } diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/AbstractAlertDialog.java b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/AbstractAlertDialog.java index 10764798..2f394fb3 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/AbstractAlertDialog.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/AbstractAlertDialog.java @@ -9,7 +9,7 @@ import android.view.View; import android.widget.AdapterView; import android.widget.ListAdapter; -import de.thedevstack.conversationsplus.R; +import eu.siacs.conversations.R; /** * Created by tzur on 29.09.2015. diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/MessageDetailsDialog.java b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/MessageDetailsDialog.java index c640ce6d..8a3de18d 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/MessageDetailsDialog.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/MessageDetailsDialog.java @@ -9,13 +9,14 @@ import java.util.Date; import de.thedevstack.android.logcat.Logging; import de.thedevstack.conversationsplus.ConversationsPlusColors; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Conversation; import de.thedevstack.conversationsplus.entities.FileParams; -import de.thedevstack.conversationsplus.entities.Message; -import de.thedevstack.conversationsplus.utils.UIHelper; import de.thedevstack.conversationsplus.utils.ui.TextViewUtil; +import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.utils.UIHelper; + /** * Fills the contents to the message details dialog. * The view definition is done in R.layout.dialog_message_details. diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/SimpleConfirmDialog.java b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/SimpleConfirmDialog.java index 04e60caa..6bf9c563 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/SimpleConfirmDialog.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/SimpleConfirmDialog.java @@ -3,9 +3,10 @@ package de.thedevstack.conversationsplus.ui.dialogs; import android.content.Context; import android.content.DialogInterface; -import de.thedevstack.conversationsplus.R; import de.thedevstack.conversationsplus.ui.listeners.SimpleUserDecisionCallback; +import eu.siacs.conversations.R; + /** * A dialog to give the user the choice to decide whether to do something or not. * A UserDecisionListener is used to provide the functionality to be performed by clicking on yes, or no. diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/UserDecisionDialog.java b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/UserDecisionDialog.java index e0834390..3305e8e1 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/UserDecisionDialog.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/dialogs/UserDecisionDialog.java @@ -8,7 +8,7 @@ import android.widget.TextView; import de.thedevstack.conversationsplus.enums.UserDecision; import de.thedevstack.conversationsplus.ui.listeners.UserDecisionListener; -import de.thedevstack.conversationsplus.R; +import eu.siacs.conversations.R; /** * A dialog to give the user the choice to decide whether to do something or not. diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormBooleanFieldWrapper.java b/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormBooleanFieldWrapper.java deleted file mode 100644 index 04c3fe20..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormBooleanFieldWrapper.java +++ /dev/null @@ -1,80 +0,0 @@ -package de.thedevstack.conversationsplus.ui.forms; - -import android.content.Context; -import android.widget.CheckBox; -import android.widget.CompoundButton; - -import java.util.ArrayList; -import java.util.List; - -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.xmpp.forms.Field; - -public class FormBooleanFieldWrapper extends FormFieldWrapper { - - protected CheckBox checkBox; - - protected FormBooleanFieldWrapper(Context context, Field field) { - super(context, field); - checkBox = (CheckBox) view.findViewById(R.id.field); - checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - checkBox.setError(null); - invokeOnFormFieldValuesEdited(); - } - }); - } - - @Override - protected void setLabel(String label, boolean required) { - CheckBox checkBox = (CheckBox) view.findViewById(R.id.field); - checkBox.setText(createSpannableLabelString(label, required)); - } - - @Override - public List<String> getValues() { - List<String> values = new ArrayList<>(); - values.add(Boolean.toString(checkBox.isChecked())); - return values; - } - - @Override - protected void setValues(List<String> values) { - if (values.size() == 0) { - checkBox.setChecked(false); - } else { - checkBox.setChecked(Boolean.parseBoolean(values.get(0))); - } - } - - @Override - public boolean validates() { - if (checkBox.isChecked() || !field.isRequired()) { - return true; - } else { - checkBox.setError(context.getString(R.string.this_field_is_required)); - checkBox.requestFocus(); - return false; - } - } - - @Override - public boolean edited() { - if (field.getValues().size() == 0) { - return checkBox.isChecked(); - } else { - return super.edited(); - } - } - - @Override - protected int getLayoutResource() { - return R.layout.form_boolean; - } - - @Override - void setReadOnly(boolean readOnly) { - checkBox.setEnabled(!readOnly); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormFieldFactory.java b/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormFieldFactory.java deleted file mode 100644 index e726b6cc..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormFieldFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.thedevstack.conversationsplus.ui.forms; - -import android.content.Context; - -import java.util.Hashtable; - -import de.thedevstack.conversationsplus.xmpp.forms.Field; - - - -public class FormFieldFactory { - - private static final Hashtable<String, Class> typeTable = new Hashtable<>(); - - static { - typeTable.put("text-single", FormTextFieldWrapper.class); - typeTable.put("text-multi", FormTextFieldWrapper.class); - typeTable.put("text-private", FormTextFieldWrapper.class); - typeTable.put("jid-single", FormJidSingleFieldWrapper.class); - typeTable.put("boolean", FormBooleanFieldWrapper.class); - } - - protected static FormFieldWrapper createFromField(Context context, Field field) { - Class clazz = typeTable.get(field.getType()); - if (clazz == null) { - clazz = FormTextFieldWrapper.class; - } - return FormFieldWrapper.createFromField(clazz, context, field); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormFieldWrapper.java b/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormFieldWrapper.java deleted file mode 100644 index 662d5bb5..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormFieldWrapper.java +++ /dev/null @@ -1,94 +0,0 @@ -package de.thedevstack.conversationsplus.ui.forms; - -import android.content.Context; -import android.text.SpannableString; -import android.text.style.ForegroundColorSpan; -import android.text.style.StyleSpan; -import android.view.LayoutInflater; -import android.view.View; - -import java.util.List; - -import de.thedevstack.conversationsplus.ConversationsPlusColors; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.xmpp.forms.Field; - -public abstract class FormFieldWrapper { - - protected final Context context; - protected final Field field; - protected final View view; - protected OnFormFieldValuesEdited onFormFieldValuesEditedListener; - - protected FormFieldWrapper(Context context, Field field) { - this.context = context; - this.field = field; - LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - this.view = inflater.inflate(getLayoutResource(), null); - String label = field.getLabel(); - if (label == null) { - label = field.getFieldName(); - } - setLabel(label, field.isRequired()); - } - - public final void submit() { - this.field.setValues(getValues()); - } - - public final View getView() { - return view; - } - - protected abstract void setLabel(String label, boolean required); - - abstract List<String> getValues(); - - protected abstract void setValues(List<String> values); - - abstract boolean validates(); - - abstract protected int getLayoutResource(); - - abstract void setReadOnly(boolean readOnly); - - protected SpannableString createSpannableLabelString(String label, boolean required) { - SpannableString spannableString = new SpannableString(label + (required ? " *" : "")); - if (required) { - int start = label.length(); - int end = label.length() + 2; - spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), start, end, 0); - spannableString.setSpan(new ForegroundColorSpan(ConversationsPlusColors.accent()), start, end, 0); - } - return spannableString; - } - - protected void invokeOnFormFieldValuesEdited() { - if (this.onFormFieldValuesEditedListener != null) { - this.onFormFieldValuesEditedListener.onFormFieldValuesEdited(); - } - } - - public boolean edited() { - return !field.getValues().equals(getValues()); - } - - public void setOnFormFieldValuesEditedListener(OnFormFieldValuesEdited listener) { - this.onFormFieldValuesEditedListener = listener; - } - - protected static <F extends FormFieldWrapper> FormFieldWrapper createFromField(Class<F> c, Context context, Field field) { - try { - F fieldWrapper = c.getDeclaredConstructor(Context.class, Field.class).newInstance(context,field); - fieldWrapper.setValues(field.getValues()); - return fieldWrapper; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - public interface OnFormFieldValuesEdited { - void onFormFieldValuesEdited(); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormJidSingleFieldWrapper.java b/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormJidSingleFieldWrapper.java deleted file mode 100644 index c86653bf..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormJidSingleFieldWrapper.java +++ /dev/null @@ -1,44 +0,0 @@ -package de.thedevstack.conversationsplus.ui.forms; - -import android.content.Context; -import android.text.InputType; - -import java.util.List; - -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.xmpp.forms.Field; -import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException; -import de.thedevstack.conversationsplus.xmpp.jid.Jid; - -public class FormJidSingleFieldWrapper extends FormTextFieldWrapper { - - protected FormJidSingleFieldWrapper(Context context, Field field) { - super(context, field); - editText.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); - editText.setHint(R.string.account_settings_example_jabber_id); - } - - @Override - public boolean validates() { - String value = getValue(); - if (!value.isEmpty()) { - try { - Jid.fromString(value); - } catch (InvalidJidException e) { - editText.setError(context.getString(R.string.invalid_jid)); - editText.requestFocus(); - return false; - } - } - return super.validates(); - } - - @Override - protected void setValues(List<String> values) { - StringBuilder builder = new StringBuilder(""); - for(String value : values) { - builder.append(value); - } - editText.setText(builder.toString()); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormTextFieldWrapper.java b/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormTextFieldWrapper.java deleted file mode 100644 index f825809c..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormTextFieldWrapper.java +++ /dev/null @@ -1,97 +0,0 @@ -package de.thedevstack.conversationsplus.ui.forms; - -import android.content.Context; -import android.text.Editable; -import android.text.InputType; -import android.text.TextWatcher; -import android.widget.EditText; -import android.widget.TextView; - -import java.util.ArrayList; -import java.util.List; - -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.xmpp.forms.Field; - -public class FormTextFieldWrapper extends FormFieldWrapper { - - protected EditText editText; - - protected FormTextFieldWrapper(Context context, Field field) { - super(context, field); - editText = (EditText) view.findViewById(R.id.field); - editText.setSingleLine(!"text-multi".equals(field.getType())); - if ("text-private".equals(field.getType())) { - editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); - } - editText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - editText.setError(null); - invokeOnFormFieldValuesEdited(); - } - - @Override - public void afterTextChanged(Editable s) { - } - }); - } - - @Override - protected void setLabel(String label, boolean required) { - TextView textView = (TextView) view.findViewById(R.id.label); - textView.setText(createSpannableLabelString(label, required)); - } - - protected String getValue() { - return editText.getText().toString(); - } - - @Override - public List<String> getValues() { - List<String> values = new ArrayList<>(); - for (String line : getValue().split("\\n")) { - if (line.length() > 0) { - values.add(line); - } - } - return values; - } - - @Override - protected void setValues(List<String> values) { - StringBuilder builder = new StringBuilder(""); - for(int i = 0; i < values.size(); ++i) { - builder.append(values.get(i)); - if (i < values.size() - 1 && "text-multi".equals(field.getType())) { - builder.append("\n"); - } - } - editText.setText(builder.toString()); - } - - @Override - public boolean validates() { - if (getValue().trim().length() > 0 || !field.isRequired()) { - return true; - } else { - editText.setError(context.getString(R.string.this_field_is_required)); - editText.requestFocus(); - return false; - } - } - - @Override - protected int getLayoutResource() { - return R.layout.form_text; - } - - @Override - void setReadOnly(boolean readOnly) { - editText.setEnabled(!readOnly); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormWrapper.java b/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormWrapper.java deleted file mode 100644 index 8ff9efae..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/forms/FormWrapper.java +++ /dev/null @@ -1,72 +0,0 @@ -package de.thedevstack.conversationsplus.ui.forms; - -import android.content.Context; -import android.widget.LinearLayout; - -import java.util.ArrayList; -import java.util.List; - -import de.thedevstack.conversationsplus.xmpp.forms.Data; -import de.thedevstack.conversationsplus.xmpp.forms.Field; - -public class FormWrapper { - - private final LinearLayout layout; - - private final Data form; - - private final List<FormFieldWrapper> fieldWrappers = new ArrayList<>(); - - private FormWrapper(Context context, LinearLayout linearLayout, Data form) { - this.form = form; - this.layout = linearLayout; - this.layout.removeAllViews(); - for(Field field : form.getFields()) { - FormFieldWrapper fieldWrapper = FormFieldFactory.createFromField(context,field); - if (fieldWrapper != null) { - layout.addView(fieldWrapper.getView()); - fieldWrappers.add(fieldWrapper); - } - } - } - - public Data submit() { - for(FormFieldWrapper fieldWrapper : fieldWrappers) { - fieldWrapper.submit(); - } - this.form.submit(); - return this.form; - } - - public boolean validates() { - boolean validates = true; - for(FormFieldWrapper fieldWrapper : fieldWrappers) { - validates &= fieldWrapper.validates(); - } - return validates; - } - - public void setOnFormFieldValuesEditedListener(FormFieldWrapper.OnFormFieldValuesEdited listener) { - for(FormFieldWrapper fieldWrapper : fieldWrappers) { - fieldWrapper.setOnFormFieldValuesEditedListener(listener); - } - } - - public void setReadOnly(boolean b) { - for(FormFieldWrapper fieldWrapper : fieldWrappers) { - fieldWrapper.setReadOnly(b); - } - } - - public boolean edited() { - boolean edited = false; - for(FormFieldWrapper fieldWrapper : fieldWrappers) { - edited |= fieldWrapper.edited(); - } - return edited; - } - - public static FormWrapper createInLayout(Context context, LinearLayout layout, Data form) { - return new FormWrapper(context, layout, form); - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ConversationMoreMessagesLoadedListener.java b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ConversationMoreMessagesLoadedListener.java deleted file mode 100644 index 8e2909ad..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ConversationMoreMessagesLoadedListener.java +++ /dev/null @@ -1,143 +0,0 @@ -package de.thedevstack.conversationsplus.ui.listeners; - -import android.view.View; -import android.widget.ListView; -import android.widget.Toast; - -import com.orangegangsters.github.swipyrefreshlayout.library.SwipyRefreshLayout; - -import java.util.List; - -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.entities.Message; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.ui.ConversationActivity; -import de.thedevstack.conversationsplus.ui.ConversationFragment; -import de.thedevstack.conversationsplus.ui.adapter.MessageAdapter; - -/** - * This listener updates the UI when messages are loaded from the server. - */ -public class ConversationMoreMessagesLoadedListener implements XmppConnectionService.OnMoreMessagesLoaded { - private SwipyRefreshLayout swipeLayout; - private List<Message> messageList; - private ConversationFragment fragment; - private ListView messagesView; - private MessageAdapter messageListAdapter; - private Toast messageLoaderToast; - /* - The current loading status - */ - private boolean loadingMessages = false; - /** - * Whether the user is loading only history messages or not. - * History messages are messages which are older than the oldest in the database. - */ - private boolean loadHistory = true; - - public ConversationMoreMessagesLoadedListener(SwipyRefreshLayout swipeLayout, List<Message> messageList, ConversationFragment fragment, ListView messagesView, MessageAdapter messageListAdapter) { - this.swipeLayout = swipeLayout; - this.messageList = messageList; - this.fragment = fragment; - this.messagesView = messagesView; - this.messageListAdapter = messageListAdapter; - } - - public void setLoadHistory(boolean value) { - this.loadHistory = value; - } - - public void setLoadingInProgress() { - this.loadingMessages = true; - } - - public boolean isLoadingInProgress() { - return this.loadingMessages; - } - - @Override - public void onMoreMessagesLoaded(final int c, final Conversation conversation) { - ConversationActivity activity = (ConversationActivity) fragment.getActivity(); - // Current selected conversation is not the same the messages are loaded - skip updating message view and hide loading graphic - if (activity.getSelectedConversation() != conversation) { - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - swipeLayout.setRefreshing(false); - } - }); - return; - } - // No new messages are loaded - if (0 == c) { - if (this.loadHistory) { - conversation.setHasMessagesLeftOnServer(false); - } - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - swipeLayout.setRefreshing(false); - } - }); - } - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - final int oldPosition = messagesView.getFirstVisiblePosition(); // Always 0 - because loading starts always when hitting the top - String uuid = null; - boolean oldMessageListWasEmpty = messageList.isEmpty(); - if (-1 < oldPosition && messageList.size() > oldPosition) { - Message message = messageList.get(oldPosition); - uuid = message != null ? message.getUuid() : null; - } - View v = messagesView.getChildAt(0); - final int pxOffset = (v == null) ? 0 : v.getTop(); - - conversation.populateWithMessages(messageList); // This overrides the old message list - fragment.updateStatusMessages(); // This adds "messages" to the list for the status - messageListAdapter.notifyDataSetChanged(); - loadingMessages = false; // Loading of messages is finished - next query can be loaded - - int pos = getIndexOf(uuid, messageList); - - if (!oldMessageListWasEmpty) { - messagesView.setSelectionFromTop(pos, pxOffset); - } - - if (messageLoaderToast != null) { - messageLoaderToast.cancel(); - } - swipeLayout.setRefreshing(false); - } - }); - } - - @Override - public void informUser(final int resId) { - final ConversationActivity activity = (ConversationActivity) fragment.getActivity(); - - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - if (messageLoaderToast != null) { - messageLoaderToast.cancel(); - } - messageLoaderToast = Toast.makeText(activity, resId, Toast.LENGTH_LONG); - messageLoaderToast.show(); - } - }); - - } - - private int getIndexOf(String uuid, List<Message> messages) { - if (uuid == null) { - return 0; - } - for (int i = 0; i < messages.size(); ++i) { - if (uuid.equals(messages.get(i).getUuid())) { - return i; - } - } - return 0; - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ConversationSwipeRefreshListener.java b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ConversationSwipeRefreshListener.java deleted file mode 100644 index 6dc9f4a4..00000000 --- a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ConversationSwipeRefreshListener.java +++ /dev/null @@ -1,103 +0,0 @@ -package de.thedevstack.conversationsplus.ui.listeners; - -import android.widget.ListView; - -import com.orangegangsters.github.swipyrefreshlayout.library.SwipyRefreshLayout; -import com.orangegangsters.github.swipyrefreshlayout.library.SwipyRefreshLayoutDirection; - -import java.util.List; - -import de.thedevstack.android.logcat.Logging; -import de.thedevstack.conversationsplus.Config; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Account; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.entities.Message; -import de.thedevstack.conversationsplus.services.MessageArchiveService; -import de.thedevstack.conversationsplus.ui.ConversationActivity; -import de.thedevstack.conversationsplus.ui.ConversationFragment; -import de.thedevstack.conversationsplus.ui.adapter.MessageAdapter; - -/** - * This listener starts loading messages from the server. - */ -public class ConversationSwipeRefreshListener implements SwipyRefreshLayout.OnRefreshListener { - private List<Message> messageList; - private ConversationFragment fragment; - private ConversationMoreMessagesLoadedListener listener; - private SwipyRefreshLayout swipeLayout; - - public ConversationSwipeRefreshListener(List<Message> messageList, SwipyRefreshLayout swipeLayout, ConversationFragment fragment, ListView messagesView, MessageAdapter messageListAdapter) { - this.messageList = messageList; - this.fragment = fragment; - this.swipeLayout = swipeLayout; - this.listener = new ConversationMoreMessagesLoadedListener(swipeLayout, messageList, fragment, messagesView, messageListAdapter); - } - - @Override - public void onRefresh(SwipyRefreshLayoutDirection direction) { - Logging.d(Config.LOGTAG, "Refresh swipe container"); - Logging.d(Config.LOGTAG, "Refresh direction " + direction); - final ConversationActivity activity = (ConversationActivity) fragment.getActivity(); - if (activity.getSelectedConversation().getAccount().getStatus() != Account.State.DISABLED) { - synchronized (this.messageList) { - long timestamp; - if (SwipyRefreshLayoutDirection.TOP == direction) { // Load history -> messages sent/received before first message in database - if (messageList.isEmpty()) { - timestamp = System.currentTimeMillis(); - } else { - timestamp = this.messageList.get(0).getTimeSent(); // works only because of the ordering (last msg = first msg in list) - } - this.listener.setLoadHistory(true); - activity.xmppConnectionService.loadMoreMessages(activity.getSelectedConversation(), timestamp, this.listener); - } else if (SwipyRefreshLayoutDirection.BOTTOM == direction) { // load messages sent/received between last received or last session establishment and now - if (activity.getSelectedConversation().getAccount().isOnlineAndConnected()) { - Logging.d("mam", "loading missing messages from mam (last session establishing or last received message)"); - long lastSessionEstablished = this.getTimestampOfLastSessionEstablished(activity.getSelectedConversation()); - long lastReceivedMessage = this.getTimestampOfLastReceivedOrTransmittedMessage(); - long startTimestamp = Math.min(lastSessionEstablished, lastReceivedMessage); - MessageArchiveService.Query query = activity.xmppConnectionService.getMessageArchiveService().query(activity.getSelectedConversation(), startTimestamp, System.currentTimeMillis(), this.listener); - if (query != null) { - this.listener.setLoadHistory(false); - } else { - Logging.d("mam", "no query built - no messages loaded"); - this.listener.onMoreMessagesLoaded(0, activity.getSelectedConversation()); - this.listener.informUser(R.string.no_more_history_on_server); - } - this.listener.informUser(R.string.fetching_history_from_server); - } else { - this.listener.informUser(R.string.not_connected_try_again); - swipeLayout.setRefreshing(false); - } - } - } - } else { - this.listener.informUser(R.string.this_account_is_disabled); - swipeLayout.setRefreshing(false); - } - Logging.d(Config.LOGTAG, "End Refresh swipe container"); - } - - private long getTimestampOfLastReceivedOrTransmittedMessage() { - long lastReceivedOrTransmittedMessage = Long.MAX_VALUE; - if (null != this.messageList - && !this.messageList.isEmpty()) { - int lastMessageIndex = this.messageList.size() - 1; - if (0 <= lastMessageIndex && this.messageList.size() > lastMessageIndex) { - lastReceivedOrTransmittedMessage = this.messageList.get(lastMessageIndex).getTimeSent(); - } - } - - return lastReceivedOrTransmittedMessage; - } - - private long getTimestampOfLastSessionEstablished(Conversation conversation) { - long lastSessionEstablished = Long.MAX_VALUE; - if (null != conversation - && null != conversation.getAccount() - && null != conversation.getAccount().getXmppConnection()) { - lastSessionEstablished = conversation.getAccount().getXmppConnection().getLastSessionEstablished(); - } - return lastSessionEstablished; - } -} diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/DeleteFileCallback.java b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/DeleteFileCallback.java index f855a90d..222e473b 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/DeleteFileCallback.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/DeleteFileCallback.java @@ -1,11 +1,12 @@ package de.thedevstack.conversationsplus.ui.listeners; -import de.thedevstack.conversationsplus.entities.Message; -import de.thedevstack.conversationsplus.entities.Transferable; -import de.thedevstack.conversationsplus.entities.TransferablePlaceholder; -import de.thedevstack.conversationsplus.persistance.FileBackend; import de.thedevstack.conversationsplus.utils.UiUpdateHelper; +import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.entities.Transferable; +import eu.siacs.conversations.entities.TransferablePlaceholder; +import eu.siacs.conversations.persistance.FileBackend; + /** * Callback for the user decision if a file should be deleted or not. */ diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ResizePictureUserDecisionListener.java b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ResizePictureUserDecisionListener.java index 1574bb85..dec6b885 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ResizePictureUserDecisionListener.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ResizePictureUserDecisionListener.java @@ -13,25 +13,25 @@ import java.io.InputStream; import de.thedevstack.android.logcat.Logging; import de.thedevstack.conversationsplus.ConversationsPlusApplication; import de.thedevstack.conversationsplus.ConversationsPlusPreferences; -import de.thedevstack.conversationsplus.crypto.PgpEngine; import de.thedevstack.conversationsplus.entities.FileParams; import de.thedevstack.conversationsplus.enums.FileStatus; import de.thedevstack.conversationsplus.enums.UserDecision; import de.thedevstack.conversationsplus.exceptions.UiException; -import de.thedevstack.conversationsplus.utils.FileUtils; import de.thedevstack.conversationsplus.utils.ImageUtil; import de.thedevstack.conversationsplus.utils.MessageUtil; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.entities.DownloadableFile; -import de.thedevstack.conversationsplus.entities.Message; -import de.thedevstack.conversationsplus.persistance.FileBackend; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.ui.UiCallback; -import de.thedevstack.conversationsplus.ui.XmppActivity; -import de.thedevstack.conversationsplus.utils.MimeUtils; import de.thedevstack.conversationsplus.utils.StreamUtil; +import eu.siacs.conversations.R; +import eu.siacs.conversations.crypto.PgpEngine; +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.DownloadableFile; +import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.persistance.FileBackend; +import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.ui.UiCallback; +import eu.siacs.conversations.ui.XmppActivity; +import eu.siacs.conversations.utils.FileUtils; + /** * Listener to let the user decide whether to resize a picture before sending or not. */ diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ShareWithResizePictureUserDecisionListener.java b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ShareWithResizePictureUserDecisionListener.java index e2678ef7..7455cf97 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ShareWithResizePictureUserDecisionListener.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ShareWithResizePictureUserDecisionListener.java @@ -4,9 +4,9 @@ import android.net.Uri; import java.util.List; -import de.thedevstack.conversationsplus.entities.Conversation; -import de.thedevstack.conversationsplus.services.XmppConnectionService; -import de.thedevstack.conversationsplus.ui.XmppActivity; +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.ui.XmppActivity; /** * Created by tzur on 03.11.2015. diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ShowResourcesListDialogListener.java b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ShowResourcesListDialogListener.java index 791b31a7..1c16095c 100644 --- a/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ShowResourcesListDialogListener.java +++ b/src/main/java/de/thedevstack/conversationsplus/ui/listeners/ShowResourcesListDialogListener.java @@ -5,8 +5,8 @@ import android.view.View; import de.thedevstack.conversationsplus.ui.adapter.PresencesArrayAdapter; import de.thedevstack.conversationsplus.ui.dialogs.AbstractAlertDialog; -import de.thedevstack.conversationsplus.R; -import de.thedevstack.conversationsplus.entities.Contact; +import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Contact; /** * This listener shows the dialog with the resources of a contact. |