From 03d30e4fdb0b60c4c4531703495a385c97cfbe10 Mon Sep 17 00:00:00 2001 From: Sam Whited Date: Mon, 2 Feb 2015 08:33:55 -0500 Subject: Use platform ciphers as well, just prefer ours --- src/main/java/eu/siacs/conversations/Config.java | 4 ++-- .../java/eu/siacs/conversations/http/HttpConnection.java | 2 +- src/main/java/eu/siacs/conversations/utils/CryptoHelper.java | 12 +++++++----- .../java/eu/siacs/conversations/xmpp/XmppConnection.java | 3 ++- 4 files changed, 12 insertions(+), 9 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 7a50c47f..d8b3139e 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -34,8 +34,8 @@ public final class Config { "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDHE_RSA_AES_128_SHA", - "TLS_ECDHE_RSA_AES_256_SHA", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA384", diff --git a/src/main/java/eu/siacs/conversations/http/HttpConnection.java b/src/main/java/eu/siacs/conversations/http/HttpConnection.java index 4bff5251..e7d30919 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpConnection.java +++ b/src/main/java/eu/siacs/conversations/http/HttpConnection.java @@ -148,7 +148,7 @@ public class HttpConnection implements Downloadable { mXmppConnectionService.getRNG()); final SSLSocketFactory sf = sc.getSocketFactory(); - final String[] cipherSuites = CryptoHelper.getSupportedCipherSuites( + final String[] cipherSuites = CryptoHelper.getOrderedCipherSuites( sf.getSupportedCipherSuites()); if (cipherSuites.length > 0) { sc.getDefaultSSLParameters().setCipherSuites(cipherSuites); diff --git a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java index fc21acbc..31fe2c11 100644 --- a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java @@ -5,6 +5,7 @@ import java.text.Normalizer; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; +import java.util.List; import eu.siacs.conversations.Config; @@ -97,10 +98,11 @@ public final class CryptoHelper { return builder.toString(); } - public static String[] getSupportedCipherSuites(final String[] platformSupportedCipherSuites) { - //final Collection cipherSuites = new LinkedHashSet<>(Arrays.asList(Config.ENABLED_CIPHERS)); - //cipherSuites.retainAll(Arrays.asList(platformSupportedCipherSuites)); - //return cipherSuites.toArray(new String[cipherSuites.size()]); - return platformSupportedCipherSuites; + public static String[] getOrderedCipherSuites(final String[] platformSupportedCipherSuites) { + final Collection cipherSuites = new LinkedHashSet<>(Arrays.asList(Config.ENABLED_CIPHERS)); + final List platformCiphers = Arrays.asList(platformSupportedCipherSuites); + cipherSuites.retainAll(platformCiphers); + cipherSuites.addAll(platformCiphers); + return cipherSuites.toArray(new String[cipherSuites.size()]); } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 19e271b2..121d8a54 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -515,8 +515,9 @@ public class XmppConnection implements Runnable { sslSocket.setEnabledProtocols(supportProtocols); - final String[] cipherSuites = CryptoHelper.getSupportedCipherSuites( + final String[] cipherSuites = CryptoHelper.getOrderedCipherSuites( sslSocket.getSupportedCipherSuites()); + Log.d(Config.LOGTAG, "Using ciphers: " + Arrays.toString(cipherSuites)); if (cipherSuites.length > 0) { sslSocket.setEnabledCipherSuites(cipherSuites); } -- cgit v1.2.3 From e1e09d5cba9374935d8c872ead21131f5dd61625 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 7 Feb 2015 12:17:03 +0100 Subject: refactored how snackbar is displayed --- .../conversations/ui/ConversationFragment.java | 187 ++++++++++++--------- 1 file changed, 105 insertions(+), 82 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 80ac9da1..35f5fdac 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -99,7 +99,6 @@ public class ConversationFragment extends Fragment { protected ListView messagesView; final protected List messageList = new ArrayList<>(); protected MessageAdapter messageListAdapter; - protected Contact contact; private EditMessage mEditMessage; private ImageButton mSendButton; private RelativeLayout snackbar; @@ -196,6 +195,7 @@ public class ConversationFragment extends Fragment { askForPassphraseIntent, ConversationActivity.REQUEST_DECRYPT_PGP, null, 0, 0, 0); + askForPassphraseIntent = null; } catch (SendIntentException e) { // } @@ -585,88 +585,127 @@ public class ConversationFragment extends Fragment { } } + 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 mUnmuteClickListener = new OnClickListener() { + + @Override + public void onClick(final View v) { + activity.unmuteConversation(conversation); + } + }; + + 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("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 (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 MucOptions.ERROR_NICK_IN_USE: + showSnackbar(R.string.nick_in_use, R.string.edit, clickToMuc); + break; + case MucOptions.ERROR_UNKNOWN: + showSnackbar(R.string.conference_not_found, R.string.leave, leaveMuc); + break; + case MucOptions.ERROR_PASSWORD_REQUIRED: + showSnackbar(R.string.conference_requires_password, R.string.enter_password, enterPassword); + break; + case MucOptions.ERROR_BANNED: + showSnackbar(R.string.conference_banned, R.string.leave, leaveMuc); + break; + case MucOptions.ERROR_MEMBERS_ONLY: + showSnackbar(R.string.conference_members_only, R.string.leave, leaveMuc); + break; + case MucOptions.KICKED_FROM_ROOM: + showSnackbar(R.string.conference_kicked, R.string.join, joinMuc); + break; + default: + break; + } + } else if (askForPassphraseIntent != null ) { + 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 if (conversation.isMuted()) { + showSnackbar(R.string.notifications_disabled, R.string.enable,this.mUnmuteClickListener); + } else { + hideSnackbar(); + } + } + public void updateMessages() { synchronized (this.messageList) { if (getView() == null) { return; } - hideSnackbar(); final ConversationActivity activity = (ConversationActivity) getActivity(); if (this.conversation != null) { + updateSnackBar(this.conversation); final Contact contact = this.conversation.getContact(); if (this.conversation.isBlocked()) { - showSnackbar(R.string.contact_blocked, R.string.unblock, - 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(getActivity(), ((ConversationActivity) getActivity()).xmppConnectionService, conversation); - } else { - ((ConversationActivity) getActivity()).unblockConversation(conversation); - } - } - }); + } else if (!contact.showInRoster() && contact .getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { - showSnackbar(R.string.contact_added_you, R.string.add_back, - new OnClickListener() { - @Override - public void onClick(View v) { - activity.xmppConnectionService - .createContact(contact); - activity.switchToContactDetails(contact); - } - }); } else if (conversation.getMode() == Conversation.MODE_SINGLE) { makeFingerprintWarning(); } else if (!conversation.getMucOptions().online() && conversation.getAccount().getStatus() == Account.State.ONLINE) { - int error = conversation.getMucOptions().getError(); - switch (error) { - case MucOptions.ERROR_NICK_IN_USE: - showSnackbar(R.string.nick_in_use, R.string.edit, - clickToMuc); - break; - case MucOptions.ERROR_UNKNOWN: - showSnackbar(R.string.conference_not_found, - R.string.leave, leaveMuc); - break; - case MucOptions.ERROR_PASSWORD_REQUIRED: - showSnackbar(R.string.conference_requires_password, - R.string.enter_password, enterPassword); - break; - case MucOptions.ERROR_BANNED: - showSnackbar(R.string.conference_banned, - R.string.leave, leaveMuc); - break; - case MucOptions.ERROR_MEMBERS_ONLY: - showSnackbar(R.string.conference_members_only, - R.string.leave, leaveMuc); - break; - case MucOptions.KICKED_FROM_ROOM: - showSnackbar(R.string.conference_kicked, R.string.join, - joinMuc); - break; - default: - break; - } + } else if (this.conversation.isMuted()) { - showSnackbar(R.string.notifications_disabled, R.string.enable, - new OnClickListener() { - @Override - public void onClick(final View v) { - activity.unmuteConversation(conversation); - } - }); } conversation.populateWithMessages(ConversationFragment.this.messageList); for (final Message message : this.messageList) { @@ -703,8 +742,7 @@ public class ConversationFragment extends Fragment { public void userInputRequried(PendingIntent pi, Message message) { mDecryptJobRunning = false; askForPassphraseIntent = pi.getIntentSender(); - showSnackbar(R.string.openpgp_messages_found, - R.string.decrypt, clickToDecryptListener); + updateSnackBar(conversation); } @Override @@ -807,22 +845,7 @@ public class ConversationFragment extends Fragment { } protected void makeFingerprintWarning() { - if (conversation.smpRequested()) { - showSnackbar(R.string.smp_requested, R.string.verify, 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("account", conversation.getAccount().getJid().toBareJid().toString()); - intent.putExtra("mode",VerifyOTRActivity.MODE_ANSWER_QUESTION); - startActivity(intent); - } - }); - } else if (conversation.hasValidOtrSession() && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) - && (!conversation.isOtrFingerprintVerified())) { - showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify, clickToVerify); - } + } protected void showSnackbar(final int message, final int action, -- cgit v1.2.3 From 00b2e30938a2a185e4c786fc683b60cf47774019 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 7 Feb 2015 12:29:17 +0100 Subject: trim message bodys on display --- src/main/java/eu/siacs/conversations/entities/Message.java | 4 ++-- src/main/java/eu/siacs/conversations/utils/UIHelper.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 8112f5de..ce421ceb 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -376,9 +376,9 @@ public class Message extends AbstractEntity { public String getMergedBody() { final Message next = this.next(); if (this.mergeable(next)) { - return getBody() + '\n' + next.getMergedBody(); + return getBody().trim() + '\n' + next.getMergedBody(); } - return getBody(); + return getBody().trim(); } public boolean hasMeCommand() { diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index 235ef84c..e36c169b 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -154,7 +154,7 @@ public class UIHelper { return new Pair<>(message.getBody().replaceAll("^" + Message.ME_COMMAND, UIHelper.getMessageDisplayName(message) + " "), false); } else { - return new Pair<>(message.getBody(), false); + return new Pair<>(message.getBody().trim(), false); } } } -- cgit v1.2.3 From ae8c021c16b1b2dca20f4fb385d9afc517f4b935 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 7 Feb 2015 12:29:32 +0100 Subject: sort users in muc --- .../siacs/conversations/ui/ConferenceDetailsActivity.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index 399d9fdf..6a8ee024 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -25,6 +25,8 @@ 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.List; import eu.siacs.conversations.R; @@ -431,9 +433,16 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); membersView.removeAllViews(); - for (final User user : mConversation.getMucOptions().getUsers()) { - View view = inflater.inflate(R.layout.contact, membersView, - false); + final ArrayList users = new ArrayList<>(); + users.addAll(mConversation.getMucOptions().getUsers()); + Collections.sort(users,new Comparator() { + @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 -- cgit v1.2.3 From ac309efcc8a19b23a79283a07a93054b6ebf3356 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 9 Feb 2015 11:53:35 +0100 Subject: made delay timestamp parser accept nano seconds --- src/main/java/eu/siacs/conversations/parser/AbstractParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java index 08070c08..391a2d0d 100644 --- a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java +++ b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java @@ -41,7 +41,7 @@ public abstract class AbstractParser { timestamp = timestamp.replace("Z", "+0000"); SimpleDateFormat dateFormat; if (timestamp.contains(".")) { - dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US); + dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ", Locale.US); } else { dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",Locale.US); } -- cgit v1.2.3 From 16dc13e4dfd2995da3213f7197de63ac97d74d56 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 9 Feb 2015 11:54:20 +0100 Subject: always add a non resolved SRV record to the list --- src/main/java/eu/siacs/conversations/utils/DNSHelper.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java index a09b4d0f..bcb2ca44 100644 --- a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java @@ -140,18 +140,13 @@ public class DNSHelper { } ArrayList values = new ArrayList<>(); for (SRV srv : result) { - boolean added = false; if (ips6.containsKey(srv.getName())) { values.add(createNamePortBundle(srv.getName(),srv.getPort(),ips6)); - added = true; } if (ips4.containsKey(srv.getName())) { values.add(createNamePortBundle(srv.getName(),srv.getPort(),ips4)); - added = true; - } - if (!added) { - values.add(createNamePortBundle(srv.getName(),srv.getPort(),null)); } + values.add(createNamePortBundle(srv.getName(),srv.getPort(),null)); } bundle.putParcelableArrayList("values", values); } catch (SocketTimeoutException e) { -- cgit v1.2.3 From 026be61b7290829899a685c119f8924550386494 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 9 Feb 2015 16:01:30 +0100 Subject: don't show 'enter pgp key' in non encrypted chats --- src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 35f5fdac..f4093ef2 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -568,6 +568,7 @@ public class ConversationFragment extends Fragment { this.conversation.trim(); } this.activity = (ConversationActivity) getActivity(); + this.askForPassphraseIntent = null; this.conversation = conversation; this.mDecryptJobRunning = false; this.mEncryptedMessages.clear(); -- cgit v1.2.3 From af0c979f458995532fa71be9e912d873e14ce54f Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 9 Feb 2015 16:41:13 +0100 Subject: disabled cipher logging --- src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 121d8a54..5c252097 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -517,7 +517,7 @@ public class XmppConnection implements Runnable { final String[] cipherSuites = CryptoHelper.getOrderedCipherSuites( sslSocket.getSupportedCipherSuites()); - Log.d(Config.LOGTAG, "Using ciphers: " + Arrays.toString(cipherSuites)); + //Log.d(Config.LOGTAG, "Using ciphers: " + Arrays.toString(cipherSuites)); if (cipherSuites.length > 0) { sslSocket.setEnabledCipherSuites(cipherSuites); } -- cgit v1.2.3 From 6c8b82dd663b3183b1769891daf11edfa46ded5d Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 10 Feb 2015 11:11:01 +0100 Subject: strip fractional seconds from timestamp before parsing --- .../java/eu/siacs/conversations/generator/AbstractGenerator.java | 2 +- src/main/java/eu/siacs/conversations/parser/AbstractParser.java | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java index 526e5b19..7e745443 100644 --- a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java @@ -33,7 +33,7 @@ public abstract class AbstractGenerator { public final String IDENTITY_NAME = "Conversations 1.0"; public final String IDENTITY_TYPE = "phone"; - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); protected XmppConnectionService mXmppConnectionService; diff --git a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java index 391a2d0d..3f7f1548 100644 --- a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java +++ b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java @@ -1,5 +1,6 @@ package eu.siacs.conversations.parser; + import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @@ -40,11 +41,8 @@ public abstract class AbstractParser { public static Date parseTimestamp(String timestamp) throws ParseException { timestamp = timestamp.replace("Z", "+0000"); SimpleDateFormat dateFormat; - if (timestamp.contains(".")) { - dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ", Locale.US); - } else { - dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",Locale.US); - } + timestamp = timestamp.substring(0,19)+timestamp.substring(timestamp.length() -5,timestamp.length()); + dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",Locale.US); return dateFormat.parse(timestamp); } -- cgit v1.2.3 From 44ee7466816378eb4fc6b2bff2e4fa001c3b08a0 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 10 Feb 2015 17:13:34 +0100 Subject: added actions to error notification --- .../services/NotificationService.java | 24 +++++++++++++++++++++- .../services/XmppConnectionService.java | 24 ++++++++++++++++++++++ .../siacs/conversations/xmpp/XmppConnection.java | 5 +++++ 3 files changed, 52 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index 2ea0904f..203cda49 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -41,6 +41,7 @@ import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.ui.ManageAccountActivity; import eu.siacs.conversations.ui.TimePreference; import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.xmpp.XmppConnection; public class NotificationService { @@ -395,7 +396,20 @@ public class NotificationService { final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class); intent.setAction(XmppConnectionService.ACTION_DISABLE_FOREGROUND); - return PendingIntent.getService(mXmppConnectionService, 0, intent, 0); + return PendingIntent.getService(mXmppConnectionService, 34, intent, 0); + } + + private PendingIntent createTryAgainIntent() { + final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class); + intent.setAction(XmppConnectionService.ACTION_TRY_AGAIN); + return PendingIntent.getService(mXmppConnectionService, 45, intent, 0); + } + + private PendingIntent createDisableAccountIntent(final Account account) { + final Intent intent = new Intent(mXmppConnectionService,XmppConnectionService.class); + intent.setAction(XmppConnectionService.ACTION_DISABLE_ACCOUNT); + intent.putExtra("account",account.getJid().toBareJid().toString()); + return PendingIntent.getService(mXmppConnectionService,0,intent,PendingIntent.FLAG_UPDATE_CURRENT); } private boolean wasHighlightedOrPrivate(final Message message) { @@ -492,6 +506,14 @@ public class NotificationService { mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.problem_connecting_to_accounts)); mBuilder.setContentText(mXmppConnectionService.getString(R.string.touch_to_fix)); } + mBuilder.addAction(R.drawable.ic_autorenew_white_24dp, + mXmppConnectionService.getString(R.string.try_again), + createTryAgainIntent()); + if (errors.size() == 1) { + mBuilder.addAction(R.drawable.ic_block_white_24dp, + mXmppConnectionService.getString(R.string.disable_account), + createDisableAccountIntent(errors.get(0))); + } mBuilder.setOngoing(true); //mBuilder.setLights(0xffffffff, 2000, 4000); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index e34f9bd7..c08e2c02 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -102,6 +102,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public static final String ACTION_CLEAR_NOTIFICATION = "clear_notification"; public static final String ACTION_DISABLE_FOREGROUND = "disable_foreground"; private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts"; + public static final String ACTION_TRY_AGAIN = "try_again"; + public static final String ACTION_DISABLE_ACCOUNT = "disable_account"; private ContentObserver contactObserver = new ContentObserver(null) { @Override public void onChange(boolean selfChange) { @@ -398,6 +400,28 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa getPreferences().edit().putBoolean("keep_foreground_service",false).commit(); toggleForegroundService(); break; + case ACTION_TRY_AGAIN: + for(Account account : accounts) { + if (account.hasErrorStatus()) { + final XmppConnection connection = account.getXmppConnection(); + if (connection != null) { + connection.resetAttemptCount(); + } + } + } + break; + case ACTION_DISABLE_ACCOUNT: + try { + String jid = intent.getStringExtra("account"); + Account account = jid == null ? null : findAccountByJid(Jid.fromString(jid)); + if (account != null) { + account.setOption(Account.OPTION_DISABLED,true); + updateAccount(account); + } + } catch (final InvalidJidException ignored) { + break; + } + break; } } this.wakeLock.acquire(); diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 5c252097..4d6695a5 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -1028,6 +1028,11 @@ public class XmppConnection implements Runnable { this.sendPacket(new InactivePacket()); } + public void resetAttemptCount() { + this.attempt = 0; + this.lastConnect = 0; + } + public class Features { XmppConnection connection; private boolean carbonsEnabled = false; -- cgit v1.2.3 From 45de788773ffc62bd936fa9b4a5ca81a5a5c6010 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 12 Feb 2015 18:52:10 +0100 Subject: use time instead of uptime for unmute --- src/main/java/eu/siacs/conversations/entities/Conversation.java | 3 +-- src/main/java/eu/siacs/conversations/ui/ConversationActivity.java | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 036acf63..71c2523e 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -626,8 +626,7 @@ public class Conversation extends AbstractEntity implements Blockable { } public boolean isMuted() { - return SystemClock.elapsedRealtime() < this.getLongAttribute( - ATTRIBUTE_MUTED_TILL, 0); + return System.currentTimeMillis() < this.getLongAttribute(ATTRIBUTE_MUTED_TILL, 0); } public boolean setAttribute(String key, String value) { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 0a55c6b5..d9e6ffb8 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -12,7 +12,6 @@ import android.content.IntentSender.SendIntentException; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.os.SystemClock; import android.provider.MediaStore; import android.support.v4.widget.SlidingPaneLayout; import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener; @@ -677,8 +676,7 @@ public class ConversationActivity extends XmppActivity if (durations[which] == -1) { till = Long.MAX_VALUE; } else { - till = SystemClock.elapsedRealtime() - + (durations[which] * 1000); + till = System.currentTimeMillis() + (durations[which] * 1000); } conversation.setMutedTill(till); ConversationActivity.this.xmppConnectionService.databaseBackend -- cgit v1.2.3 From e68c6a1b740928116cdb5cafa23a202302eefce3 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 12 Feb 2015 18:53:00 +0100 Subject: load messages asynchronously --- .../services/XmppConnectionService.java | 20 ++++++++++++++++++-- .../eu/siacs/conversations/xmpp/XmppConnection.java | 6 ++++++ 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index c08e2c02..53abd575 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -277,6 +277,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa private LruCache mBitmapCache; private Thread mPhoneContactMergerThread; + private boolean mMessagesInitialized = false; + public boolean areMessagesInitialized() { + return this.mMessagesInitialized; + } + public PgpEngine getPgpEngine() { if (pgpServiceConnection.isBound()) { if (this.mPgpEngine == null) { @@ -889,9 +894,20 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa for (Conversation conversation : this.conversations) { Account account = accountLookupTable.get(conversation.getAccountUuid()); conversation.setAccount(account); - conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE)); - checkDeletedFiles(conversation); } + new Thread(new Runnable() { + @Override + public void run() { + Log.d(Config.LOGTAG,"start initilizing messages"); + for (Conversation conversation : conversations) { + conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE)); + checkDeletedFiles(conversation); + } + mMessagesInitialized = true; + Log.d(Config.LOGTAG,"done intilizing old messages"); + updateConversationUi(); + } + }).start(); } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 4d6695a5..44c367a6 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -659,6 +659,12 @@ public class XmppConnection implements Runnable { } private void sendBindRequest() { + while(!mXmppConnectionService.areMessagesInitialized()) { + try { + Thread.sleep(500); + } catch (final InterruptedException ignored) { + } + } final IqPacket iq = new IqPacket(IqPacket.TYPE.SET); iq.addChild("bind", "urn:ietf:params:xml:ns:xmpp-bind") .addChild("resource").setContent(account.getResource()); -- cgit v1.2.3 From 0485da8488c2e1a671bac3e80b990b9003c1cb91 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 15 Feb 2015 18:48:05 +0100 Subject: loading avatars in seperate tasks --- .../conversations/services/AvatarService.java | 40 ++++++---- .../ui/adapter/ConversationAdapter.java | 90 ++++++++++++++++++++- .../conversations/ui/adapter/ListItemAdapter.java | 91 +++++++++++++++++++++- 3 files changed, 203 insertions(+), 18 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java index f28dc24e..7412eb93 100644 --- a/src/main/java/eu/siacs/conversations/services/AvatarService.java +++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java @@ -38,10 +38,10 @@ public class AvatarService { this.mXmppConnectionService = service; } - public Bitmap get(final Contact contact, final int size) { + private Bitmap get(final Contact contact, final int size, boolean cachedOnly) { final String KEY = key(contact, size); Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY); - if (avatar != null) { + if (avatar != null || cachedOnly) { return avatar; } if (contact.getProfilePhoto() != null) { @@ -51,7 +51,7 @@ public class AvatarService { avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatar(), size); } if (avatar == null) { - avatar = get(contact.getDisplayName(), size); + avatar = get(contact.getDisplayName(), size, cachedOnly); } this.mXmppConnectionService.getBitmapCache().put(KEY, avatar); return avatar; @@ -77,25 +77,33 @@ public class AvatarService { } public Bitmap get(ListItem item, int size) { + return get(item,size,false); + } + + public Bitmap get(ListItem item, int size, boolean cachedOnly) { if (item instanceof Contact) { - return get((Contact) item, size); + return get((Contact) item, size,cachedOnly); } else if (item instanceof Bookmark) { Bookmark bookmark = (Bookmark) item; if (bookmark.getConversation() != null) { - return get(bookmark.getConversation(), size); + return get(bookmark.getConversation(), size, cachedOnly); } else { - return get(bookmark.getDisplayName(), size); + return get(bookmark.getDisplayName(), size, cachedOnly); } } else { - return get(item.getDisplayName(), size); + return get(item.getDisplayName(), size, cachedOnly); } } public Bitmap get(Conversation conversation, int size) { + return get(conversation,size,false); + } + + public Bitmap get(Conversation conversation, int size, boolean cachedOnly) { if (conversation.getMode() == Conversation.MODE_SINGLE) { - return get(conversation.getContact(), size); + return get(conversation.getContact(), size, cachedOnly); } else { - return get(conversation.getMucOptions(), size); + return get(conversation.getMucOptions(), size, cachedOnly); } } @@ -107,10 +115,10 @@ public class AvatarService { } } - public Bitmap get(MucOptions mucOptions, int size) { + private Bitmap get(MucOptions mucOptions, int size, boolean cachedOnly) { final String KEY = key(mucOptions, size); Bitmap bitmap = this.mXmppConnectionService.getBitmapCache().get(KEY); - if (bitmap != null) { + if (bitmap != null || cachedOnly) { return bitmap; } final List users = new ArrayList<>(mucOptions.getUsers()); @@ -179,7 +187,7 @@ public class AvatarService { avatar = mXmppConnectionService.getFileBackend().getAvatar( account.getAvatar(), size); if (avatar == null) { - avatar = get(account.getJid().toBareJid().toString(), size); + avatar = get(account.getJid().toBareJid().toString(), size,false); } mXmppConnectionService.getBitmapCache().put(KEY, avatar); return avatar; @@ -204,10 +212,14 @@ public class AvatarService { + String.valueOf(size); } - public Bitmap get(final String name, final int size) { + public Bitmap get(String name, int size) { + return get(name,size,false); + } + + public Bitmap get(final String name, final int size, boolean cachedOnly) { final String KEY = key(name, size); Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY); - if (bitmap != null) { + if (bitmap != null || cachedOnly) { return bitmap; } bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 38c321d0..02a3dfef 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -1,8 +1,13 @@ package eu.siacs.conversations.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; @@ -11,12 +16,13 @@ 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 eu.siacs.conversations.R; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Downloadable; -import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.ui.XmppActivity; @@ -98,8 +104,88 @@ public class ConversationAdapter extends ArrayAdapter { mTimestamp.setText(UIHelper.readableTimeDifference(activity,conversation.getLatestMessage().getTimeSent())); ImageView profilePicture = (ImageView) view.findViewById(R.id.conversation_image); - profilePicture.setImageBitmap(activity.avatarService().get(conversation, activity.getPixel(56))); + loadAvatar(conversation,profilePicture); return view; } + + class BitmapWorkerTask extends AsyncTask { + private final WeakReference imageViewReference; + private Conversation conversation = null; + + public BitmapWorkerTask(ImageView imageView) { + imageViewReference = new WeakReference<>(imageView); + } + + @Override + protected Bitmap doInBackground(Conversation... params) { + return activity.avatarService().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) { + Bitmap bm = activity.avatarService().get(conversation,activity.getPixel(56),true); + if (bm != null) { + imageView.setImageBitmap(bm); + imageView.setBackgroundColor(0x00000000); + } else if (cancelPotentialWork(conversation, imageView)) { + imageView.setBackgroundColor(0xff333333); + 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 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/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index 91fb021c..37865aca 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -1,15 +1,23 @@ package eu.siacs.conversations.ui.adapter; +import java.lang.ref.WeakReference; import java.util.List; +import java.util.concurrent.RejectedExecutionException; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.ListItem; import eu.siacs.conversations.ui.XmppActivity; import eu.siacs.conversations.xmpp.jid.Jid; import android.content.Context; import android.content.SharedPreferences; +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.preference.PreferenceManager; import android.util.Log; import android.view.LayoutInflater; @@ -77,8 +85,7 @@ public class ListItemAdapter extends ArrayAdapter { tvJid.setText(""); } tvName.setText(item.getDisplayName()); - picture.setImageBitmap(activity.avatarService().get(item, - activity.getPixel(48))); + loadAvatar(item,picture); return view; } @@ -90,4 +97,84 @@ public class ListItemAdapter extends ArrayAdapter { public void onTagClicked(String tag); } + class BitmapWorkerTask extends AsyncTask { + private final WeakReference imageViewReference; + private ListItem item = null; + + public BitmapWorkerTask(ImageView imageView) { + imageViewReference = new WeakReference<>(imageView); + } + + @Override + protected Bitmap doInBackground(ListItem... params) { + return activity.avatarService().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) { + Bitmap bm = activity.avatarService().get(item,activity.getPixel(56),true); + if (bm != null) { + imageView.setImageBitmap(bm); + imageView.setBackgroundColor(0x00000000); + } else if (cancelPotentialWork(item, imageView)) { + imageView.setBackgroundColor(0xff333333); + 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 bitmapWorkerTaskReference; + + public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { + super(res, bitmap); + bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask); + } + + public BitmapWorkerTask getBitmapWorkerTask() { + return bitmapWorkerTaskReference.get(); + } + } + } -- cgit v1.2.3 From 00fa6f89d6203430309d678898d3f91b04674d33 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Sun, 15 Feb 2015 14:18:41 -0500 Subject: Vitelity's s.ms service requires first If the tag is not first, their bot just silently drops the stanza. I know we shouldn't have to care about order, and I'm trying to get them to fix it, but it's not high-priority for them since "most" clients seem to work, so I'd like this workaround in. --- src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java index 4e7b532b..61465ae0 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java +++ b/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java @@ -26,7 +26,7 @@ public class MessagePacket extends AbstractStanza { this.children.remove(findChild("body")); Element body = new Element("body"); body.setContent(text); - this.children.add(body); + this.children.add(0, body); } public void setType(int type) { -- cgit v1.2.3 From 146edb8c81821ec40c61519ee5911a7c0335ca4a Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 15 Feb 2015 23:25:35 +0100 Subject: made image view background more colorful while waiting on actual avatar to load --- .../java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java | 2 +- src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 02a3dfef..00f90382 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -140,7 +140,7 @@ public class ConversationAdapter extends ArrayAdapter { imageView.setImageBitmap(bm); imageView.setBackgroundColor(0x00000000); } else if (cancelPotentialWork(conversation, imageView)) { - imageView.setBackgroundColor(0xff333333); + imageView.setBackgroundColor(UIHelper.getColorForName(conversation.getName())); final BitmapWorkerTask task = new BitmapWorkerTask(imageView); final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task); imageView.setImageDrawable(asyncDrawable); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index 37865aca..cd5dfeb4 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -9,6 +9,7 @@ import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.ListItem; import eu.siacs.conversations.ui.XmppActivity; +import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.jid.Jid; import android.content.Context; @@ -128,7 +129,7 @@ public class ListItemAdapter extends ArrayAdapter { imageView.setImageBitmap(bm); imageView.setBackgroundColor(0x00000000); } else if (cancelPotentialWork(item, imageView)) { - imageView.setBackgroundColor(0xff333333); + imageView.setBackgroundColor(UIHelper.getColorForName(item.getDisplayName())); final BitmapWorkerTask task = new BitmapWorkerTask(imageView); final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task); imageView.setImageDrawable(asyncDrawable); -- cgit v1.2.3 From 5aa600c63895dea110653192ae19c610228c2600 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 16 Feb 2015 00:58:31 +0100 Subject: fixed avatar cache lookup in ListItemAdapter --- src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index cd5dfeb4..254721e5 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -4,9 +4,7 @@ import java.lang.ref.WeakReference; import java.util.List; import java.util.concurrent.RejectedExecutionException; -import eu.siacs.conversations.Config; import eu.siacs.conversations.R; -import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.ListItem; import eu.siacs.conversations.ui.XmppActivity; import eu.siacs.conversations.utils.UIHelper; @@ -20,7 +18,6 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.preference.PreferenceManager; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -124,7 +121,7 @@ public class ListItemAdapter extends ArrayAdapter { } public void loadAvatar(ListItem item, ImageView imageView) { - Bitmap bm = activity.avatarService().get(item,activity.getPixel(56),true); + Bitmap bm = activity.avatarService().get(item,activity.getPixel(48),true); if (bm != null) { imageView.setImageBitmap(bm); imageView.setBackgroundColor(0x00000000); -- cgit v1.2.3 From 4e14c89ff8d5d791b5dcbd4361356c86c7a4b475 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 16 Feb 2015 10:06:09 +0100 Subject: support for XEP-0092: Software Version --- .../conversations/generator/AbstractGenerator.java | 22 ++++++++++++++++++---- .../siacs/conversations/generator/IqGenerator.java | 13 +++++++++++-- .../eu/siacs/conversations/parser/IqParser.java | 8 +++++--- .../eu/siacs/conversations/ui/AboutPreference.java | 14 +++----------- .../eu/siacs/conversations/utils/PhoneHelper.java | 14 ++++++++++++++ 5 files changed, 51 insertions(+), 20 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java index 7e745443..ef1eda3f 100644 --- a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java @@ -13,6 +13,7 @@ import java.util.Locale; import java.util.TimeZone; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.utils.PhoneHelper; public abstract class AbstractGenerator { private final String[] FEATURES = { @@ -25,12 +26,14 @@ public abstract class AbstractGenerator { "http://jabber.org/protocol/caps", "http://jabber.org/protocol/disco#info", "urn:xmpp:avatar:metadata+notify", - "urn:xmpp:ping"}; + "urn:xmpp:ping", + "jabber:iq:version"}; private final String[] MESSAGE_CONFIRMATION_FEATURES = { "urn:xmpp:chat-markers:0", "urn:xmpp:receipts" }; - public final String IDENTITY_NAME = "Conversations 1.0"; + private String mVersion = null; + public final String IDENTITY_NAME = "Conversations"; public final String IDENTITY_TYPE = "phone"; private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); @@ -41,10 +44,21 @@ public abstract class AbstractGenerator { this.mXmppConnectionService = service; } + protected String getIdentityVersion() { + if (mVersion == null) { + this.mVersion = PhoneHelper.getVersionName(mXmppConnectionService); + } + return this.mVersion; + } + + protected String getIdentityName() { + return IDENTITY_NAME + " " + getIdentityVersion(); + } + public String getCapHash() { StringBuilder s = new StringBuilder(); - s.append("client/" + IDENTITY_TYPE + "//" + IDENTITY_NAME + "<"); - MessageDigest md = null; + s.append("client/" + IDENTITY_TYPE + "//" + getIdentityName() + "<"); + MessageDigest md; try { md = MessageDigest.getInstance("SHA-1"); } catch (NoSuchAlgorithmException e) { diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java index 161e6f89..6bc629b5 100644 --- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java @@ -8,6 +8,7 @@ import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.services.MessageArchiveService; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.utils.PhoneHelper; import eu.siacs.conversations.utils.Xmlns; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.forms.Data; @@ -30,14 +31,22 @@ public class IqGenerator extends AbstractGenerator { query.setAttribute("node", request.query().getAttribute("node")); final Element identity = query.addChild("identity"); identity.setAttribute("category", "client"); - identity.setAttribute("type", this.IDENTITY_TYPE); - identity.setAttribute("name", IDENTITY_NAME); + identity.setAttribute("type", IDENTITY_TYPE); + identity.setAttribute("name", getIdentityName()); for (final String feature : getFeatures()) { query.addChild("feature").setAttribute("var", feature); } return packet; } + public IqPacket versionResponse(final IqPacket request) { + final IqPacket packet = request.generateResponse(IqPacket.TYPE.RESULT); + Element query = packet.query("jabber:iq:version"); + query.addChild("name").setContent(IDENTITY_NAME); + query.addChild("version").setContent(getIdentityVersion()); + return packet; + } + protected IqPacket publish(final String node, final Element item) { final IqPacket packet = new IqPacket(IqPacket.TYPE.SET); final Element pubsub = packet.addChild("pubsub", diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index 6430c296..6039d395 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -134,9 +134,11 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { mXmppConnectionService.getJingleConnectionManager() .deliverIbbPacket(account, packet); } else if (packet.hasChild("query", "http://jabber.org/protocol/disco#info")) { - final IqPacket response = mXmppConnectionService.getIqGenerator() - .discoResponse(packet); - account.getXmppConnection().sendIqPacket(response, null); + final IqPacket response = mXmppConnectionService.getIqGenerator().discoResponse(packet); + mXmppConnectionService.sendIqPacket(account, response, null); + } else if (packet.hasChild("query","jabber:iq:version")) { + final IqPacket response = mXmppConnectionService.getIqGenerator().versionResponse(packet); + mXmppConnectionService.sendIqPacket(account,response,null); } else if (packet.hasChild("ping", "urn:xmpp:ping")) { final IqPacket response = packet.generateResponse(IqPacket.TYPE.RESULT); mXmppConnectionService.sendIqPacket(account, response, null); diff --git a/src/main/java/eu/siacs/conversations/ui/AboutPreference.java b/src/main/java/eu/siacs/conversations/ui/AboutPreference.java index 804b4e23..a57e1b89 100644 --- a/src/main/java/eu/siacs/conversations/ui/AboutPreference.java +++ b/src/main/java/eu/siacs/conversations/ui/AboutPreference.java @@ -6,6 +6,8 @@ import android.content.pm.PackageManager; import android.preference.Preference; import android.util.AttributeSet; +import eu.siacs.conversations.utils.PhoneHelper; + public class AboutPreference extends Preference { public AboutPreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); @@ -25,17 +27,7 @@ public class AboutPreference extends Preference { } private void setSummary() { - if (getContext() != null && getContext().getPackageManager() != null) { - final String packageName = getContext().getPackageName(); - final String versionName; - try { - versionName = getContext().getPackageManager().getPackageInfo(packageName, 0).versionName; - setSummary("Conversations " + versionName); - } catch (final PackageManager.NameNotFoundException e) { - // Using try/catch as part of the logic is sort of like this: - // https://xkcd.com/292/ - } - } + setSummary("Conversations " + PhoneHelper.getVersionName(getContext())); } } diff --git a/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java b/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java index 9a5cbaaf..99e8ebb8 100644 --- a/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java @@ -8,6 +8,7 @@ import android.content.Context; import android.content.CursorLoader; import android.content.Loader; import android.content.Loader.OnLoadCompleteListener; +import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -91,4 +92,17 @@ public class PhoneHelper { } } } + + public static String getVersionName(Context context) { + final String packageName = context == null ? null : context.getPackageName(); + if (packageName != null) { + try { + return context.getPackageManager().getPackageInfo(packageName, 0).versionName; + } catch (final PackageManager.NameNotFoundException e) { + return "unknown"; + } + } else { + return "unknown"; + } + } } -- cgit v1.2.3 From 62b15a5d26fe5dc52a16b86c1c2658d1b7b5aa1b Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 17 Feb 2015 09:53:16 +0100 Subject: refresh list view more often --- src/main/java/eu/siacs/conversations/ui/ConversationActivity.java | 2 +- src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index d9e6ffb8..1b5f76f0 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -793,7 +793,7 @@ public class ConversationActivity extends XmppActivity this.mConversationFragment.reInit(getSelectedConversation()); mOpenConverstaion = null; } else if (getSelectedConversation() != null) { - this.mConversationFragment.updateMessages(); + this.mConversationFragment.reInit(getSelectedConversation()); } else { showConversationsOverview(); mPendingImageUri = null; diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index f4093ef2..d9f386d3 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -577,7 +577,7 @@ public class ConversationFragment extends Fragment { } this.mEditMessage.setText(""); this.mEditMessage.append(this.conversation.getNextMessage()); - this.messagesView.invalidateViews(); + this.messagesView.setAdapter(messageListAdapter); updateMessages(); this.messagesLoaded = true; int size = this.messageList.size(); -- cgit v1.2.3 From 67d5ee6b71d036206df03ec09f6188f2fe2f5918 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 17 Feb 2015 11:51:11 +0100 Subject: moved roster loading to async task as well --- .../services/XmppConnectionService.java | 32 +++++++++++++++------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 53abd575..44d77b45 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -16,6 +16,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.FileObserver; import android.os.IBinder; +import android.os.Looper; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemClock; @@ -277,9 +278,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa private LruCache mBitmapCache; private Thread mPhoneContactMergerThread; - private boolean mMessagesInitialized = false; + private boolean mRestoredFromDatabase = false; public boolean areMessagesInitialized() { - return this.mMessagesInitialized; + return this.mRestoredFromDatabase; } public PgpEngine getPgpEngine() { @@ -393,7 +394,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (action != null) { switch (action) { case ACTION_MERGE_PHONE_CONTACTS: - PhoneHelper.loadPhoneContacts(getApplicationContext(), new CopyOnWriteArrayList(), this); + if (mRestoredFromDatabase) { + PhoneHelper.loadPhoneContacts(getApplicationContext(), + new CopyOnWriteArrayList(), + this); + } return START_STICKY; case Intent.ACTION_SHUTDOWN: logoutAndSave(); @@ -528,10 +533,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa for (final Account account : this.accounts) { account.initOtrEngine(this); - this.databaseBackend.readRoster(account.getRoster()); } - initConversations(); - PhoneHelper.loadPhoneContacts(getApplicationContext(),new CopyOnWriteArrayList(), this); + restoreFromDatabase(); getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, contactObserver); this.fileObserver.startWatching(); @@ -884,7 +887,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa mPhoneContactMergerThread.start(); } - private void initConversations() { + private void restoreFromDatabase() { synchronized (this.conversations) { final Map accountLookupTable = new Hashtable<>(); for (Account account : this.accounts) { @@ -898,13 +901,22 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa new Thread(new Runnable() { @Override public void run() { - Log.d(Config.LOGTAG,"start initilizing messages"); + Log.d(Config.LOGTAG,"restoring roster"); + for(Account account : accounts) { + databaseBackend.readRoster(account.getRoster()); + } + getBitmapCache().evictAll(); + Looper.prepare(); + PhoneHelper.loadPhoneContacts(getApplicationContext(), + new CopyOnWriteArrayList(), + XmppConnectionService.this); + Log.d(Config.LOGTAG,"restoring messages"); for (Conversation conversation : conversations) { conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE)); checkDeletedFiles(conversation); } - mMessagesInitialized = true; - Log.d(Config.LOGTAG,"done intilizing old messages"); + mRestoredFromDatabase = true; + Log.d(Config.LOGTAG,"restored all messages"); updateConversationUi(); } }).start(); -- cgit v1.2.3 From a8ec36cda816e37fae5abf4a5947872cbe834fdc Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 17 Feb 2015 14:18:35 +0100 Subject: limit ui refresh rate --- src/main/java/eu/siacs/conversations/Config.java | 3 +- .../ui/ConferenceDetailsActivity.java | 19 +++------ .../conversations/ui/ContactDetailsActivity.java | 22 ++++------ .../conversations/ui/ConversationActivity.java | 49 +++++++--------------- .../conversations/ui/ManageAccountActivity.java | 15 ++++--- .../ui/StartConversationActivity.java | 25 ++++------- .../siacs/conversations/ui/VerifyOTRActivity.java | 12 +++--- .../eu/siacs/conversations/ui/XmppActivity.java | 29 +++++++++++++ 8 files changed, 81 insertions(+), 93 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index d8b3139e..5dc7c207 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -21,7 +21,8 @@ public final class Config { public static final int PAGE_SIZE = 50; public static final int MAX_NUM_PAGES = 3; - public static final int PROGRESS_UI_UPDATE_INTERVAL = 750; + public static final int PROGRESS_UI_UPDATE_INTERVAL = 750; + public static final int REFRESH_UI_INTERVAL = 500; public static final boolean NO_PROXY_LOOKUP = false; //useful to debug ibb diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index 6a8ee024..e4bfd6ff 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -144,24 +144,17 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers @Override public void onConversationUpdate() { - runOnUiThread(new Runnable() { - - @Override - public void run() { - updateView(); - } - }); + refreshUi(); } @Override public void onMucRosterUpdate() { - runOnUiThread(new Runnable() { + refreshUi(); + } - @Override - public void run() { - updateView(); - } - }); + @Override + protected void refreshUiReal() { + updateView(); } @Override diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index fda0c617..40a4587c 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -139,26 +139,18 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd @Override public void onRosterUpdate() { - runOnUiThread(new Runnable() { - - @Override - public void run() { - invalidateOptionsMenu(); - populateView(); - } - }); + refreshUi(); } @Override public void onAccountUpdate() { - runOnUiThread(new Runnable() { + refreshUi(); + } - @Override - public void run() { - invalidateOptionsMenu(); - populateView(); - } - }); + @Override + protected void refreshUiReal() { + invalidateOptionsMenu(); + populateView(); } @Override diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 1b5f76f0..118f6dd2 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -1006,56 +1006,39 @@ public class ConversationActivity extends XmppActivity } @Override - public void onAccountUpdate() { - runOnUiThread(new Runnable() { + protected void refreshUiReal() { + updateConversationList(); + if (conversationList.size() == 0) { + startActivity(new Intent(getApplicationContext(), + StartConversationActivity.class)); + finish(); + } + ConversationActivity.this.mConversationFragment.updateMessages(); + updateActionBarTitle(); + } - @Override - public void run() { - updateConversationList(); - ConversationActivity.this.mConversationFragment.updateMessages(); - updateActionBarTitle(); - } - }); + @Override + public void onAccountUpdate() { + this.refreshUi(); } @Override public void onConversationUpdate() { - runOnUiThread(new Runnable() { - - @Override - public void run() { - updateConversationList(); - if (conversationList.size() == 0) { - startActivity(new Intent(getApplicationContext(), - StartConversationActivity.class)); - finish(); - } - ConversationActivity.this.mConversationFragment.updateMessages(); - updateActionBarTitle(); - } - }); + this.refreshUi(); } @Override public void onRosterUpdate() { - runOnUiThread(new Runnable() { - - @Override - public void run() { - updateConversationList(); - ConversationActivity.this.mConversationFragment.updateMessages(); - updateActionBarTitle(); - } - }); + this.refreshUi(); } @Override public void OnUpdateBlocklist(Status status) { + this.refreshUi(); runOnUiThread(new Runnable() { @Override public void run() { invalidateOptionsMenu(); - ConversationActivity.this.mConversationFragment.updateMessages(); } }); } diff --git a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java index b3ab5ee6..b2d5ddfd 100644 --- a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java @@ -32,18 +32,17 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda @Override public void onAccountUpdate() { + refreshUi(); + } + + @Override + protected void refreshUiReal() { synchronized (this.accountList) { accountList.clear(); accountList.addAll(xmppConnectionService.getAccounts()); } - runOnUiThread(new Runnable() { - - @Override - public void run() { - invalidateOptionsMenu(); - mAccountAdapter.notifyDataSetChanged(); - } - }); + invalidateOptionsMenu(); + mAccountAdapter.notifyDataSetChanged(); } @Override diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index ff46ffd8..2e16d8e7 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -176,15 +176,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU @Override public void onRosterUpdate() { - runOnUiThread(new Runnable() { - - @Override - public void run() { - if (mSearchEditText != null) { - filter(mSearchEditText.getText().toString()); - } - } - }); + this.refreshUi(); } @Override @@ -711,15 +703,14 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU @Override public void OnUpdateBlocklist(final Status status) { - runOnUiThread(new Runnable() { + refreshUi(); + } - @Override - public void run() { - if (mSearchEditText != null) { - filter(mSearchEditText.getText().toString()); - } - } - }); + @Override + protected void refreshUiReal() { + if (mSearchEditText != null) { + filter(mSearchEditText.getText().toString()); + } } public static class MyListFragment extends ListFragment { diff --git a/src/main/java/eu/siacs/conversations/ui/VerifyOTRActivity.java b/src/main/java/eu/siacs/conversations/ui/VerifyOTRActivity.java index c33decd8..ec9d59e1 100644 --- a/src/main/java/eu/siacs/conversations/ui/VerifyOTRActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/VerifyOTRActivity.java @@ -436,11 +436,11 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer } public void onConversationUpdate() { - runOnUiThread(new Runnable() { - @Override - public void run() { - updateView(); - } - }); + refreshUi(); + } + + @Override + protected void refreshUiReal() { + updateView(); } } diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index bf247787..ac7fcf9d 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -33,7 +33,9 @@ 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.SystemClock; import android.preference.PreferenceManager; import android.text.InputType; import android.util.DisplayMetrics; @@ -99,6 +101,33 @@ public abstract class XmppActivity extends Activity { protected int mTheme; protected boolean mUsingEnterKey = false; + private long mLastUiRefresh = 0; + private Handler mRefreshUiHandler = new Handler(); + private Runnable mRefreshUiRunnable = new Runnable() { + @Override + public void run() { + mLastUiRefresh = SystemClock.elapsedRealtime(); + refreshUiReal(); + } + }; + + + protected 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); + } + } + + protected void refreshUiReal() { + + }; + protected interface OnValueEdited { public void onValueEdited(String value); } -- cgit v1.2.3 From da2bc6db232d15420d8dde6ca9d8890ef8af5c6a Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 18 Feb 2015 13:11:41 +0100 Subject: avoid weird npe. fixed #991 --- src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index d9f386d3..91aaab00 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -321,7 +321,9 @@ public class ConversationFragment extends Fragment { @Override public void onClick(View v) { - activity.hideConversationsOverview(); + if (activity != null) { + activity.hideConversationsOverview(); + } } }); mEditMessage.setOnEditorActionListener(mEditorActionListener); -- cgit v1.2.3 From b128b33e56d56920d3d5c1327eb15610e5b536f2 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 18 Feb 2015 13:37:26 +0100 Subject: always go through reconnect method instead of just starting XmppConnection threads --- .../java/eu/siacs/conversations/services/XmppConnectionService.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 44d77b45..948e78d4 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -466,10 +466,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode()); } } else if (account.getStatus() == Account.State.OFFLINE) { - if (account.getXmppConnection() == null) { - account.setXmppConnection(this.createConnection(account)); - } - new Thread(account.getXmppConnection()).start(); + reconnectAccount(account,true); } else if (account.getStatus() == Account.State.CONNECTING) { long timeout = Config.CONNECT_TIMEOUT - ((SystemClock.elapsedRealtime() - account.getXmppConnection().getLastConnect()) / 1000); if (timeout < 0) { -- cgit v1.2.3 From 9c2e6392ec0920e6c594aae7b784397d94cf5ba2 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 18 Feb 2015 18:12:43 +0100 Subject: always call to cancel before loading new avatars --- .../ui/adapter/ConversationAdapter.java | 26 ++++++++++++---------- .../conversations/ui/adapter/ListItemAdapter.java | 26 ++++++++++++---------- 2 files changed, 28 insertions(+), 24 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 00f90382..3e747b0a 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -135,18 +135,20 @@ public class ConversationAdapter extends ArrayAdapter { } public void loadAvatar(Conversation conversation, ImageView imageView) { - Bitmap bm = activity.avatarService().get(conversation,activity.getPixel(56),true); - if (bm != null) { - imageView.setImageBitmap(bm); - imageView.setBackgroundColor(0x00000000); - } else if (cancelPotentialWork(conversation, imageView)) { - imageView.setBackgroundColor(UIHelper.getColorForName(conversation.getName())); - 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) { + if (cancelPotentialWork(conversation, imageView)) { + final Bitmap bm = activity.avatarService().get(conversation, activity.getPixel(56), true); + if (bm != null) { + imageView.setImageBitmap(bm); + imageView.setBackgroundColor(0x00000000); + } else { + imageView.setBackgroundColor(UIHelper.getColorForName(conversation.getName())); + 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) { + } } } } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index 254721e5..60e47019 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -121,18 +121,20 @@ public class ListItemAdapter extends ArrayAdapter { } public void loadAvatar(ListItem item, ImageView imageView) { - Bitmap bm = activity.avatarService().get(item,activity.getPixel(48),true); - if (bm != null) { - imageView.setImageBitmap(bm); - imageView.setBackgroundColor(0x00000000); - } else if (cancelPotentialWork(item, imageView)) { - imageView.setBackgroundColor(UIHelper.getColorForName(item.getDisplayName())); - 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) { + if (cancelPotentialWork(item, imageView)) { + final Bitmap bm = activity.avatarService().get(item,activity.getPixel(48),true); + if (bm != null) { + imageView.setImageBitmap(bm); + imageView.setBackgroundColor(0x00000000); + } else { + imageView.setBackgroundColor(UIHelper.getColorForName(item.getDisplayName())); + 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) { + } } } } -- cgit v1.2.3 From 5003d1f549e799b56421ffb2078d682921e97bc5 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 18 Feb 2015 18:23:13 +0100 Subject: made xmpp uris case insensitive --- src/main/java/eu/siacs/conversations/utils/XmppUri.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/utils/XmppUri.java b/src/main/java/eu/siacs/conversations/utils/XmppUri.java index 0f1b18c3..92c0241e 100644 --- a/src/main/java/eu/siacs/conversations/utils/XmppUri.java +++ b/src/main/java/eu/siacs/conversations/utils/XmppUri.java @@ -32,7 +32,7 @@ public class XmppUri { protected void parse(Uri uri) { String scheme = uri.getScheme(); - if ("xmpp".equals(scheme)) { + if ("xmpp".equalsIgnoreCase(scheme)) { // sample: xmpp:jid@foo.com muc = "join".equalsIgnoreCase(uri.getQuery()); if (uri.getAuthority() != null) { @@ -41,7 +41,7 @@ public class XmppUri { jid = uri.getSchemeSpecificPart().split("\\?")[0]; } fingerprint = parseFingerprint(uri.getQuery()); - } else if ("imto".equals(scheme)) { + } else if ("imto".equalsIgnoreCase(scheme)) { // sample: imto://xmpp/jid@foo.com try { jid = URLDecoder.decode(uri.getEncodedPath(), "UTF-8").split("/")[1]; @@ -73,7 +73,7 @@ public class XmppUri { public Jid getJid() { try { - return this.jid == null ? null :Jid.fromString(this.jid); + return this.jid == null ? null :Jid.fromString(this.jid.toLowerCase()); } catch (InvalidJidException e) { return null; } -- cgit v1.2.3 From 2e596c0bd4608feae238ece9edbb3ad5e7c436f4 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 19 Feb 2015 13:48:40 +0100 Subject: launch edit account activity when starting Conversations for the first time (fixed regression) --- .../eu/siacs/conversations/ui/ConversationActivity.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 118f6dd2..9f997c86 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -777,6 +777,7 @@ public class ConversationActivity extends XmppActivity updateConversationList(); if (xmppConnectionService.getAccounts().size() == 0) { startActivity(new Intent(this, EditAccountActivity.class)); + finish(); } else if (conversationList.size() <= 0) { startActivity(new Intent(this, StartConversationActivity.class)); finish(); @@ -1008,13 +1009,16 @@ public class ConversationActivity extends XmppActivity @Override protected void refreshUiReal() { updateConversationList(); - if (conversationList.size() == 0) { - startActivity(new Intent(getApplicationContext(), - StartConversationActivity.class)); + if (xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 0) { + startActivity(new Intent(this, EditAccountActivity.class)); + finish(); + } else if (conversationList.size() == 0) { + startActivity(new Intent(this, StartConversationActivity.class)); finish(); + } else { + ConversationActivity.this.mConversationFragment.updateMessages(); + updateActionBarTitle(); } - ConversationActivity.this.mConversationFragment.updateMessages(); - updateActionBarTitle(); } @Override -- cgit v1.2.3 From f26f6e9a00c740a7cfc8895f30d406c4409fb662 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 19 Feb 2015 14:36:52 +0100 Subject: fixed #993 --- src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 91aaab00..35599946 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -420,7 +420,8 @@ public class ConversationFragment extends Fragment { MenuItem copyUrl = menu.findItem(R.id.copy_url); MenuItem downloadImage = menu.findItem(R.id.download_image); MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission); - if (m.getType() != Message.TYPE_TEXT || m.getDownloadable() != null) { + if ((m.getType() != Message.TYPE_TEXT && m.getType() != Message.TYPE_PRIVATE) + || m.getDownloadable() != null) { copyText.setVisible(false); } if (m.getType() == Message.TYPE_TEXT -- cgit v1.2.3 From 7ee5e959597cfded524c7179b663138aca781ad8 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sat, 21 Feb 2015 11:06:52 +0100 Subject: added typing notifications through XEP-0085. fixed #210 --- src/main/java/eu/siacs/conversations/Config.java | 5 ++ .../eu/siacs/conversations/crypto/OtrEngine.java | 14 ++++ .../siacs/conversations/entities/Conversation.java | 31 ++++++++ .../eu/siacs/conversations/entities/Message.java | 3 +- .../conversations/generator/AbstractGenerator.java | 3 +- .../conversations/generator/MessageGenerator.java | 20 ++--- .../siacs/conversations/parser/MessageParser.java | 25 ++++++ .../services/XmppConnectionService.java | 22 ++++++ .../conversations/ui/ConversationFragment.java | 91 ++++++++++++++++------ .../eu/siacs/conversations/ui/EditMessage.java | 59 +++++++++++--- .../conversations/ui/adapter/MessageAdapter.java | 4 +- .../conversations/xmpp/chatstate/ChatState.java | 32 ++++++++ 12 files changed, 256 insertions(+), 53 deletions(-) create mode 100644 src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 5dc7c207..41e8971f 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -2,6 +2,8 @@ package eu.siacs.conversations; import android.graphics.Bitmap; +import eu.siacs.conversations.xmpp.chatstate.ChatState; + public final class Config { public static final String LOGTAG = "conversations"; @@ -30,6 +32,9 @@ public final class Config { public static final long MAM_MAX_CATCHUP = MILLISECONDS_IN_DAY / 2; public static final int MAM_MAX_MESSAGES = 500; + public static final ChatState DEFAULT_CHATSTATE = ChatState.ACTIVE; + public static final int TYPING_TIMEOUT = 8; + public static final String ENABLED_CIPHERS[] = { "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384", diff --git a/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java b/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java index d5c45465..c85864d0 100644 --- a/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java +++ b/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java @@ -21,6 +21,7 @@ import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.CryptoHelper; +import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; @@ -182,6 +183,19 @@ public class OtrEngine extends OtrCryptoEngineImpl implements OtrEngineHost { packet.addChild("private", "urn:xmpp:carbons:2"); packet.addChild("no-copy", "urn:xmpp:hints"); packet.addChild("no-store", "urn:xmpp:hints"); + + try { + Jid jid = Jid.fromSessionID(session); + Conversation conversation = mXmppConnectionService.find(account,jid); + if (conversation != null && conversation.setOutgoingChatState(Config.DEFAULT_CHATSTATE)) { + if (mXmppConnectionService.sendChatStates()) { + packet.addChild(ChatState.toElement(conversation.getOutgoingChatState())); + } + } + } catch (final InvalidJidException ignored) { + + } + packet.setType(MessagePacket.TYPE_CHAT); account.getXmppConnection().sendMessagePacket(packet); } diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 71c2523e..1feb04c7 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -21,6 +21,7 @@ import java.util.Comparator; import java.util.List; import eu.siacs.conversations.Config; +import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; @@ -77,6 +78,8 @@ public class Conversation extends AbstractEntity implements Blockable { private Bookmark bookmark; private boolean messagesLeftOnServer = true; + private ChatState mOutgoingChatState = Config.DEFAULT_CHATSTATE; + private ChatState mIncomingChatState = Config.DEFAULT_CHATSTATE; public boolean hasMessagesLeftOnServer() { return messagesLeftOnServer; @@ -138,6 +141,34 @@ public class Conversation extends AbstractEntity implements Blockable { } } + public boolean setIncomingChatState(ChatState state) { + if (this.mIncomingChatState == state) { + return false; + } + this.mIncomingChatState = state; + return true; + } + + public ChatState getIncomingChatState() { + return this.mIncomingChatState; + } + + public boolean setOutgoingChatState(ChatState state) { + if (mode == MODE_MULTI) { + return false; + } + if (this.mOutgoingChatState != state) { + this.mOutgoingChatState = state; + return true; + } else { + return false; + } + } + + public ChatState getOutgoingChatState() { + return this.mOutgoingChatState; + } + public void trim() { synchronized (this.messages) { final int size = messages.size(); diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index ce421ceb..ccf274b7 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -147,10 +147,11 @@ public class Message extends AbstractEntity { cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID))); } - public static Message createStatusMessage(Conversation conversation) { + public static Message createStatusMessage(Conversation conversation, String body) { Message message = new Message(); message.setType(Message.TYPE_STATUS); message.setConversation(conversation); + message.setBody(body); return message; } diff --git a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java index ef1eda3f..79626511 100644 --- a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java @@ -27,7 +27,8 @@ public abstract class AbstractGenerator { "http://jabber.org/protocol/disco#info", "urn:xmpp:avatar:metadata+notify", "urn:xmpp:ping", - "jabber:iq:version"}; + "jabber:iq:version", + "http://jabber.org/protocol/chatstates"}; private final String[] MESSAGE_CONFIRMATION_FEATURES = { "urn:xmpp:chat-markers:0", "urn:xmpp:receipts" diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index 2ee636b5..e274d2bc 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -12,6 +12,7 @@ import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; @@ -102,21 +103,12 @@ public class MessageGenerator extends AbstractGenerator { return packet; } - public MessagePacket generateNotAcceptable(MessagePacket origin) { - MessagePacket packet = generateError(origin); - Element error = packet.addChild("error"); - error.setAttribute("type", "modify"); - error.setAttribute("code", "406"); - error.addChild("not-acceptable"); - return packet; - } - - private MessagePacket generateError(MessagePacket origin) { + public MessagePacket generateChatState(Conversation conversation) { + final Account account = conversation.getAccount(); MessagePacket packet = new MessagePacket(); - packet.setId(origin.getId()); - packet.setTo(origin.getFrom()); - packet.setBody(origin.getBody()); - packet.setType(MessagePacket.TYPE_ERROR); + packet.setTo(conversation.getJid().toBareJid()); + packet.setFrom(account.getJid()); + packet.addChild(ChatState.toElement(conversation.getOutgoingChatState())); return packet; } diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 49efb004..3f3cf8cb 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -1,8 +1,11 @@ package eu.siacs.conversations.parser; +import android.util.Log; + import net.java.otr4j.session.Session; import net.java.otr4j.session.SessionStatus; +import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; @@ -14,6 +17,7 @@ import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnMessagePacketReceived; +import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.pep.Avatar; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; @@ -24,6 +28,21 @@ public class MessageParser extends AbstractParser implements super(service); } + private boolean extractChatState(Conversation conversation, final Element element) { + ChatState state = ChatState.parse(element); + if (state != null && conversation != null) { + final Account account = conversation.getAccount(); + Jid from = element.getAttributeAsJid("from"); + if (from != null && from.toBareJid().equals(account.getJid().toBareJid())) { + conversation.setOutgoingChatState(state); + return false; + } else { + return conversation.setIncomingChatState(state); + } + } + return false; + } + private Message parseChat(MessagePacket packet, Account account) { final Jid jid = packet.getFrom(); if (jid == null) { @@ -55,6 +74,7 @@ public class MessageParser extends AbstractParser implements } finishedMessage.setCounterpart(jid); finishedMessage.setTime(getTimestamp(packet)); + extractChatState(conversation,packet); return finishedMessage; } @@ -123,6 +143,7 @@ public class MessageParser extends AbstractParser implements finishedMessage.setRemoteMsgId(packet.getId()); finishedMessage.markable = isMarkable(packet); finishedMessage.setCounterpart(from); + extractChatState(conversation,packet); return finishedMessage; } catch (Exception e) { conversation.resetOtrSession(); @@ -275,6 +296,7 @@ public class MessageParser extends AbstractParser implements finishedMessage = new Message(conversation, body, Message.ENCRYPTION_NONE, status); } + extractChatState(conversation,message); finishedMessage.setTime(getTimestamp(message)); finishedMessage.setRemoteMsgId(message.getAttribute("id")); finishedMessage.markable = isMarkable(message); @@ -362,6 +384,9 @@ public class MessageParser extends AbstractParser implements private void parseNonMessage(Element packet, Account account) { final Jid from = packet.getAttributeAsJid("from"); + if (extractChatState(from == null ? null : mXmppConnectionService.find(account,from), packet)) { + mXmppConnectionService.updateConversationUi(); + } Element invite = extractInvite(packet); if (invite != null) { Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, from, true); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 948e78d4..1d2def93 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -86,6 +86,7 @@ import eu.siacs.conversations.xmpp.OnPresencePacketReceived; import eu.siacs.conversations.xmpp.OnStatusChanged; import eu.siacs.conversations.xmpp.OnUpdateBlocklist; import eu.siacs.conversations.xmpp.XmppConnection; +import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.forms.Data; import eu.siacs.conversations.xmpp.forms.Field; import eu.siacs.conversations.xmpp.jid.InvalidJidException; @@ -603,6 +604,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return connection; } + public void sendChatState(Conversation conversation) { + if (sendChatStates()) { + MessagePacket packet = mMessageGenerator.generateChatState(conversation); + sendMessagePacket(conversation.getAccount(), packet); + } + } + public void sendMessage(final Message message) { final Account account = message.getConversation().getAccount(); account.deactivateGracePeriod(); @@ -703,6 +711,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } if ((send) && (packet != null)) { + if (conv.setOutgoingChatState(Config.DEFAULT_CHATSTATE)) { + if (this.sendChatStates()) { + packet.addChild(ChatState.toElement(conv.getOutgoingChatState())); + } + } sendMessagePacket(account, packet); } updateConversationUi(); @@ -784,6 +797,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } else { markMessage(message, Message.STATUS_UNSEND); } + if (message.getConversation().setOutgoingChatState(Config.DEFAULT_CHATSTATE)) { + if (this.sendChatStates()) { + packet.addChild(ChatState.toElement(message.getConversation().getOutgoingChatState())); + } + } sendMessagePacket(account, packet); } } @@ -2046,6 +2064,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return getPreferences().getBoolean("confirm_messages", true); } + public boolean sendChatStates() { + return getPreferences().getBoolean("chat_states", false); + } + public boolean saveEncryptedMessages() { return !getPreferences().getBoolean("dont_save_encrypted", false); } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 35599946..3e0668be 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -40,6 +40,7 @@ import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.ConcurrentLinkedQueue; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.entities.Account; @@ -52,15 +53,15 @@ import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.services.XmppConnectionService; -import eu.siacs.conversations.ui.EditMessage.OnEnterPressed; import eu.siacs.conversations.ui.XmppActivity.OnPresenceSelected; import eu.siacs.conversations.ui.XmppActivity.OnValueEdited; import eu.siacs.conversations.ui.adapter.MessageAdapter; import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureClicked; import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureLongClicked; +import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.jid.Jid; -public class ConversationFragment extends Fragment { +public class ConversationFragment extends Fragment implements EditMessage.KeyboardListener { protected Conversation conversation; private OnClickListener leaveMuc = new OnClickListener() { @@ -327,18 +328,6 @@ public class ConversationFragment extends Fragment { } }); mEditMessage.setOnEditorActionListener(mEditorActionListener); - mEditMessage.setOnEnterPressedListener(new OnEnterPressed() { - - @Override - public boolean onEnterPressed() { - if (activity.enterIsSend()) { - sendMessage(); - return true; - } else { - return false; - } - } - }); mSendButton = (ImageButton) view.findViewById(R.id.textSendButton); mSendButton.setOnClickListener(this.mSendButtonListener); @@ -558,7 +547,17 @@ public class ConversationFragment extends Fragment { mDecryptJobRunning = false; super.onStop(); if (this.conversation != null) { - this.conversation.setNextMessage(mEditMessage.getText().toString()); + 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); } } @@ -566,11 +565,18 @@ public class ConversationFragment extends Fragment { if (conversation == null) { return; } + + this.activity = (ConversationActivity) getActivity(); + if (this.conversation != null) { - this.conversation.setNextMessage(mEditMessage.getText().toString()); + final String msg = mEditMessage.getText().toString(); + this.conversation.setNextMessage(msg); + if (this.conversation != conversation) { + updateChatState(this.conversation,msg); + } this.conversation.trim(); } - this.activity = (ConversationActivity) getActivity(); + this.askForPassphraseIntent = null; this.conversation = conversation; this.mDecryptJobRunning = false; @@ -578,8 +584,10 @@ public class ConversationFragment extends Fragment { if (this.conversation.getMode() == Conversation.MODE_MULTI) { this.conversation.setNextCounterpart(null); } + 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; @@ -834,13 +842,21 @@ public class ConversationFragment extends Fragment { protected void updateStatusMessages() { synchronized (this.messageList) { if (conversation.getMode() == Conversation.MODE_SINGLE) { - 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)); + 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; + } } } } @@ -995,4 +1011,33 @@ public class ConversationFragment extends Fragment { this.mEditMessage.append(text); } + @Override + public void onEnterPressed() { + sendMessage(); + } + + @Override + public void onTypingStarted() { + Account.State status = conversation.getAccount().getStatus(); + if (status == Account.State.ONLINE && conversation.setOutgoingChatState(ChatState.COMPOSING)) { + activity.xmppConnectionService.sendChatState(conversation); + } + } + + @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); + } + } + } diff --git a/src/main/java/eu/siacs/conversations/ui/EditMessage.java b/src/main/java/eu/siacs/conversations/ui/EditMessage.java index 5090bbf5..57fa7285 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditMessage.java +++ b/src/main/java/eu/siacs/conversations/ui/EditMessage.java @@ -1,10 +1,13 @@ package eu.siacs.conversations.ui; import android.content.Context; +import android.os.Handler; import android.util.AttributeSet; import android.view.KeyEvent; import android.widget.EditText; +import eu.siacs.conversations.Config; + public class EditMessage extends EditText { public EditMessage(Context context, AttributeSet attrs) { @@ -15,28 +18,62 @@ public class EditMessage extends EditText { super(context); } - protected OnEnterPressed mOnEnterPressed; + 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; + + protected KeyboardListener keyboardListener; @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_ENTER) { - if (mOnEnterPressed != null) { - if (mOnEnterPressed.onEnterPressed()) { - return true; - } else { - return super.onKeyDown(keyCode, event); - } + if (keyboardListener != null) { + keyboardListener.onEnterPressed(); } + return true; } return super.onKeyDown(keyCode, event); } - public void setOnEnterPressedListener(OnEnterPressed listener) { - this.mOnEnterPressed = listener; + @Override + public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { + super.onTextChanged(text,start,lengthBefore,lengthAfter); + 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 OnEnterPressed { - public boolean onEnterPressed(); + public interface KeyboardListener { + public void onEnterPressed(); + public void onTypingStarted(); + public void onTypingStopped(); + public void onTextDeleted(); } } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 442c6ecf..58713534 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -410,9 +410,7 @@ public class MessageAdapter extends ArrayAdapter { .avatarService().get(conversation.getContact(), activity.getPixel(32))); viewHolder.contact_picture.setAlpha(0.5f); - viewHolder.status_message.setText( - activity.getString(R.string.contact_has_read_up_to_this_point, conversation.getName())); - + viewHolder.status_message.setText(message.getBody()); } return view; } else if (type == NULL) { diff --git a/src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java b/src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java new file mode 100644 index 00000000..f85efbdb --- /dev/null +++ b/src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java @@ -0,0 +1,32 @@ +package eu.siacs.conversations.xmpp.chatstate; + +import eu.siacs.conversations.xml.Element; + +public enum ChatState { + + ACTIVE, INACTIVE, GONE, COMPOSING, PAUSED, mIncomingChatState; + + public static ChatState parse(Element element) { + final String NAMESPACE = "http://jabber.org/protocol/chatstates"; + if (element.hasChild("active",NAMESPACE)) { + return ACTIVE; + } else if (element.hasChild("inactive",NAMESPACE)) { + return INACTIVE; + } else if (element.hasChild("composing",NAMESPACE)) { + return COMPOSING; + } else if (element.hasChild("gone",NAMESPACE)) { + return GONE; + } else if (element.hasChild("paused",NAMESPACE)) { + return PAUSED; + } else { + return null; + } + } + + public static Element toElement(ChatState state) { + final String NAMESPACE = "http://jabber.org/protocol/chatstates"; + final Element element = new Element(state.toString().toLowerCase()); + element.setAttribute("xmlns",NAMESPACE); + return element; + } +} -- cgit v1.2.3 From 3db5a48529949b2219b036495f412ea383707524 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sat, 21 Feb 2015 22:19:10 +0100 Subject: clear muc tiles cache only when necessary --- .../java/eu/siacs/conversations/entities/MucOptions.java | 15 +++++++++++++++ .../eu/siacs/conversations/parser/PresenceParser.java | 8 +++++++- 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 27821c65..2fd4db74 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -150,6 +150,21 @@ public class MucOptions { } } + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } else if (!(other instanceof User)) { + return false; + } else { + User o = (User) other; + return name != null && name.equals(o.name) + && jid != null && jid.equals(o.jid) + && affiliation == o.affiliation + && role == o.role; + } + } + public Affiliation getAffiliation() { return this.affiliation; } diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index accb56ea..a7752842 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.parser; +import java.util.ArrayList; + import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; @@ -27,8 +29,12 @@ public class PresenceParser extends AbstractParser implements final MucOptions mucOptions = conversation.getMucOptions(); boolean before = mucOptions.online(); int count = mucOptions.getUsers().size(); + final ArrayList tileUserBefore = new ArrayList<>(mucOptions.getUsers().subList(0,Math.min(mucOptions.getUsers().size(),4))); mucOptions.processPacket(packet, mPgpEngine); - mXmppConnectionService.getAvatarService().clear(conversation); + final ArrayList tileUserAfter = new ArrayList<>(mucOptions.getUsers().subList(0,Math.min(mucOptions.getUsers().size(),4))); + if (!tileUserAfter.equals(tileUserBefore)) { + mXmppConnectionService.getAvatarService().clear(conversation); + } if (before != mucOptions.online() || (mucOptions.online() && count != mucOptions.getUsers().size())) { mXmppConnectionService.updateConversationUi(); } else if (mucOptions.online()) { -- cgit v1.2.3 From f52bc4f0beff94a5a70477b64038073f1534c043 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 22 Feb 2015 13:15:27 +0100 Subject: properly remove invalid avatar --- src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java | 1 + src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java | 1 + 2 files changed, 2 insertions(+) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 3e747b0a..a48f6ae4 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -142,6 +142,7 @@ public class ConversationAdapter extends ArrayAdapter { 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); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index 60e47019..7b20b55f 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -128,6 +128,7 @@ public class ListItemAdapter extends ArrayAdapter { 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); -- cgit v1.2.3 From 7259e666ea5ee8ecc63e3657565c474684e8f4e8 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 22 Feb 2015 13:16:07 +0100 Subject: look at 5 muc users instead of 4 for tile cache clearing --- src/main/java/eu/siacs/conversations/parser/PresenceParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index a7752842..7505b091 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -29,9 +29,9 @@ public class PresenceParser extends AbstractParser implements final MucOptions mucOptions = conversation.getMucOptions(); boolean before = mucOptions.online(); int count = mucOptions.getUsers().size(); - final ArrayList tileUserBefore = new ArrayList<>(mucOptions.getUsers().subList(0,Math.min(mucOptions.getUsers().size(),4))); + final ArrayList tileUserBefore = new ArrayList<>(mucOptions.getUsers().subList(0,Math.min(mucOptions.getUsers().size(),5))); mucOptions.processPacket(packet, mPgpEngine); - final ArrayList tileUserAfter = new ArrayList<>(mucOptions.getUsers().subList(0,Math.min(mucOptions.getUsers().size(),4))); + final ArrayList tileUserAfter = new ArrayList<>(mucOptions.getUsers().subList(0,Math.min(mucOptions.getUsers().size(),5))); if (!tileUserAfter.equals(tileUserBefore)) { mXmppConnectionService.getAvatarService().clear(conversation); } -- cgit v1.2.3 From da2da75756f835d6ce299c8c08860317fe747a5d Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 22 Feb 2015 13:24:29 +0100 Subject: init mode (first start) for StartConversationActivity (no up button) and avoid being started multiple times. fixed #995 --- .../conversations/ui/ConversationActivity.java | 34 +++++++++++++++++----- .../conversations/ui/EditAccountActivity.java | 2 ++ .../ui/PublishProfilePictureActivity.java | 12 +++++--- .../ui/StartConversationActivity.java | 10 +++++-- 4 files changed, 44 insertions(+), 14 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 9f997c86..ad2aab56 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -84,6 +84,7 @@ public class ConversationActivity extends XmppActivity private Toast prepareFileToast; private boolean mActivityPaused = false; + private boolean mRedirected = true; public Conversation getSelectedConversation() { return this.mSelectedConversation; @@ -720,6 +721,7 @@ public class ConversationActivity extends XmppActivity @Override public void onStart() { super.onStart(); + this.mRedirected = false; if (this.xmppConnectionServiceBound) { this.onBackendConnected(); } @@ -776,11 +778,19 @@ public class ConversationActivity extends XmppActivity this.xmppConnectionService.getNotificationService().setIsInForeground(true); updateConversationList(); if (xmppConnectionService.getAccounts().size() == 0) { - startActivity(new Intent(this, EditAccountActivity.class)); - finish(); + if (!mRedirected) { + this.mRedirected = true; + startActivity(new Intent(this, EditAccountActivity.class)); + finish(); + } } else if (conversationList.size() <= 0) { - startActivity(new Intent(this, StartConversationActivity.class)); - finish(); + if (!mRedirected) { + this.mRedirected = true; + Intent intent = new Intent(this, StartConversationActivity.class); + intent.putExtra("init",true); + startActivity(intent); + finish(); + } } else if (getIntent() != null && VIEW_CONVERSATION.equals(getIntent().getType())) { handleViewConversationIntent(getIntent()); } else if (selectConversationByUuid(mOpenConverstaion)) { @@ -1010,11 +1020,19 @@ public class ConversationActivity extends XmppActivity protected void refreshUiReal() { updateConversationList(); if (xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 0) { - startActivity(new Intent(this, EditAccountActivity.class)); - finish(); + if (!mRedirected) { + this.mRedirected = true; + startActivity(new Intent(this, EditAccountActivity.class)); + finish(); + } } else if (conversationList.size() == 0) { - startActivity(new Intent(this, StartConversationActivity.class)); - finish(); + if (!mRedirected) { + this.mRedirected = true; + Intent intent = new Intent(this, StartConversationActivity.class); + intent.putExtra("init",true); + startActivity(intent); + finish(); + } } else { ConversationActivity.this.mConversationFragment.updateMessages(); updateActionBarTitle(); diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index ea45b75e..12326136 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -221,6 +221,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate if (avatar != null) { intent = new Intent(getApplicationContext(), StartConversationActivity.class); + intent.putExtra("init",true); } else { intent = new Intent(getApplicationContext(), PublishProfilePictureActivity.class); @@ -379,6 +380,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate if (getActionBar() != null) { getActionBar().setDisplayHomeAsUpEnabled(false); getActionBar().setDisplayShowHomeEnabled(false); + getActionBar().setHomeButtonEnabled(false); } this.mCancelButton.setEnabled(false); this.mCancelButton.setTextColor(getSecondaryTextColor()); diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java index 2ba0b090..3f72b723 100644 --- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java @@ -54,8 +54,10 @@ public class PublishProfilePictureActivity extends XmppActivity { @Override public void run() { if (mInitialAccountSetup) { - startActivity(new Intent(getApplicationContext(), - StartConversationActivity.class)); + Intent intent = new Intent(getApplicationContext(), + StartConversationActivity.class); + intent.putExtra("init",true); + startActivity(intent); } Toast.makeText(PublishProfilePictureActivity.this, R.string.avatar_has_been_published, @@ -112,8 +114,10 @@ public class PublishProfilePictureActivity extends XmppActivity { @Override public void onClick(View v) { if (mInitialAccountSetup) { - startActivity(new Intent(getApplicationContext(), - StartConversationActivity.class)); + Intent intent = new Intent(getApplicationContext(), + StartConversationActivity.class); + intent.putExtra("init",true); + startActivity(intent); } finish(); } diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index 2e16d8e7..a556b8b7 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -574,9 +574,15 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU 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(); + this.mKnownConferenceHosts = xmppConnectionService.getKnownConferenceHosts(); if (this.mPendingInvite != null) { mPendingInvite.invite(); this.mPendingInvite = null; -- cgit v1.2.3 From 7a62fbbeae99e3ee3b5a2516e8f08e3a2c37c718 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 23 Feb 2015 12:05:18 +0100 Subject: get rid of some useless debugging --- src/main/java/eu/siacs/conversations/services/NotificationService.java | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index 203cda49..6bfe3268 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -437,9 +437,6 @@ public class NotificationService { } public void setIsInForeground(final boolean foreground) { - if (foreground != this.mIsInForeground) { - Log.d(Config.LOGTAG,"setIsInForeground("+Boolean.toString(foreground)+")"); - } this.mIsInForeground = foreground; } -- cgit v1.2.3 From 8319446c03ad4586150ae4d38cb1861aba2decf9 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 23 Feb 2015 21:47:35 +0100 Subject: reset incoming chat state when going into background --- .../java/eu/siacs/conversations/services/XmppConnectionService.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 1d2def93..90f69338 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1341,6 +1341,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } } + for(Conversation conversation : getConversations()) { + conversation.setIncomingChatState(ChatState.ACTIVE); + } this.mNotificationService.setIsInForeground(false); Log.d(Config.LOGTAG, "app switched into background"); } -- cgit v1.2.3 From b8bc70aaa0bd3228dff1848bedeaf19568f4abf8 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 25 Feb 2015 23:48:45 +0100 Subject: prevent next button from showing up too early on account setup --- src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 12326136..c3e8e174 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -235,7 +235,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } protected void updateSaveButton() { - if (mAccount != null && mAccount.getStatus() == Account.State.CONNECTING) { + if (mAccount != null && (mAccount.getStatus() == Account.State.CONNECTING || mFetchingAvatar)) { this.mSaveButton.setEnabled(false); this.mSaveButton.setTextColor(getSecondaryTextColor()); this.mSaveButton.setText(R.string.account_status_connecting); -- cgit v1.2.3 From fa45ceabc97cee3ec48fc1a726a4806884aeb747 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 26 Feb 2015 16:55:49 +0100 Subject: initilize keys with jsonobject value on parse error --- src/main/java/eu/siacs/conversations/entities/Account.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index b0cde62c..2bc2c954 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -148,7 +148,7 @@ public class Account extends AbstractEntity { try { this.keys = new JSONObject(keys); } catch (final JSONException ignored) { - + this.keys = new JSONObject(); } this.avatar = avatar; } -- cgit v1.2.3 From 9e10c3841e21e49db11a01e838753409ee01d5de Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 26 Feb 2015 16:56:07 +0100 Subject: check for null in jid parser --- src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java | 1 + src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java | 2 ++ 2 files changed, 3 insertions(+) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java b/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java index f1855263..164e8849 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/InvalidJidException.java @@ -8,6 +8,7 @@ public class InvalidJidException extends Exception { public final static String INVALID_PART_LENGTH = "JID part must be between 0 and 1023 characters"; public final static String INVALID_CHARACTER = "JID contains an invalid character"; public final static String STRINGPREP_FAIL = "The STRINGPREP operation has failed for the given JID"; + public final static String IS_NULL = "JID can not be NULL"; /** * Constructs a new {@code Exception} that includes the current stack trace. diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index a35ea37c..b8be527b 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -60,6 +60,8 @@ public final class Jid { } private Jid(final String jid) throws InvalidJidException { + if (jid == null) throw new InvalidJidException(InvalidJidException.IS_NULL); + // Hackish Android way to count the number of chars in a string... should work everywhere. final int atCount = jid.length() - jid.replace("@", "").length(); final int slashCount = jid.length() - jid.replace("/", "").length(); -- cgit v1.2.3 From a022e4b41aa9973e2e208633380c7c82b4b1a4a6 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 26 Feb 2015 17:17:40 +0100 Subject: reset error status in edit account when reconnecting --- src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index c3e8e174..d001d9d9 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -102,6 +102,8 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } catch (final InvalidJidException ignored) { return; } + mAccountJid.setError(null); + mPasswordConfirm.setError(null); mAccount.setPassword(password); mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount); xmppConnectionService.updateAccount(mAccount); @@ -493,6 +495,8 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate if (this.mAccount.errorStatus()) { this.mAccountJid.setError(getString(this.mAccount.getStatus().getReadableId())); this.mAccountJid.requestFocus(); + } else { + this.mAccountJid.setError(null); } this.mStats.setVisibility(View.GONE); } -- cgit v1.2.3 From 71ce73a2711f5ca31ac5f3b8300f99ad1b250d39 Mon Sep 17 00:00:00 2001 From: Quentin Date: Fri, 27 Feb 2015 00:33:49 +0100 Subject: - Update mBuilder in NotificationService.java to ensure that the led is displayed at the right color. CF: http://stackoverflow.com/questions/14953793/android-notification-led-doesnt-use-my-color#comment20991762_14953793 - Changed led Color to green to remember the icon color and led times --- src/main/java/eu/siacs/conversations/services/NotificationService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index 6bfe3268..cffde6a5 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -211,9 +211,10 @@ public class NotificationService { mBuilder.setCategory(Notification.CATEGORY_MESSAGE); } setNotificationColor(mBuilder); + mBuilder.setDefaults(0); mBuilder.setSmallIcon(R.drawable.ic_notification); mBuilder.setDeleteIntent(createDeleteIntent()); - mBuilder.setLights(0xffffffff, 2000, 4000); + mBuilder.setLights(0xff00ff00, 500, 1500); final Notification notification = mBuilder.build(); notificationManager.notify(NOTIFICATION_ID, notification); } -- cgit v1.2.3 From c67a481e4be753faaef76fd1c97338818996073b Mon Sep 17 00:00:00 2001 From: QuentinC Date: Fri, 27 Feb 2015 11:18:15 +0100 Subject: Update NotificationService.java Revert led light color --- src/main/java/eu/siacs/conversations/services/NotificationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index cffde6a5..c6eee2fa 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -214,7 +214,7 @@ public class NotificationService { mBuilder.setDefaults(0); mBuilder.setSmallIcon(R.drawable.ic_notification); mBuilder.setDeleteIntent(createDeleteIntent()); - mBuilder.setLights(0xff00ff00, 500, 1500); + mBuilder.setLights(0xffffffff, 2000, 4000); final Notification notification = mBuilder.build(); notificationManager.notify(NOTIFICATION_ID, notification); } -- cgit v1.2.3 From 6ad4865d961e187c9fa96f91a5ffeac68b756b51 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 27 Feb 2015 17:03:13 +0100 Subject: hide change password menu item if server feature is unavailable --- .../eu/siacs/conversations/ui/EditAccountActivity.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index d001d9d9..27dfc492 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -332,17 +332,18 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate 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); - if (mAccount == null) { + if (mAccount != null && mAccount.isOnlineAndConnected()) { + if (!mAccount.getXmppConnection().getFeatures().blocking()) { + showBlocklist.setVisible(false); + } + if (!mAccount.getXmppConnection().getFeatures().register()) { + changePassword.setVisible(false); + } + } else { showQrCode.setVisible(false); showBlocklist.setVisible(false); showMoreInfo.setVisible(false); changePassword.setVisible(false); - } else if (mAccount.getStatus() != Account.State.ONLINE) { - showBlocklist.setVisible(false); - showMoreInfo.setVisible(false); - changePassword.setVisible(false); - } else if (!mAccount.getXmppConnection().getFeatures().blocking()) { - showBlocklist.setVisible(false); } return true; } -- cgit v1.2.3 From f3be0d99cc4e59b784d6bebedd58c58829d94327 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 27 Feb 2015 17:04:13 +0100 Subject: don't add users with null nicks to muc user list --- src/main/java/eu/siacs/conversations/entities/MucOptions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 2fd4db74..addee8db 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -275,7 +275,7 @@ public class MucOptions { User user = new User(); if (x != null) { Element item = x.findChild("item"); - if (item != null) { + if (item != null && name != null) { user.setName(name); user.setAffiliation(item.getAttribute("affiliation")); user.setRole(item.getAttribute("role")); -- cgit v1.2.3 From 98df008bce04a5d70e7388871196d06c287c31af Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 27 Feb 2015 17:16:28 +0100 Subject: use conversations green in notification led --- src/main/java/eu/siacs/conversations/services/NotificationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index c6eee2fa..a260d6e2 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -214,7 +214,7 @@ public class NotificationService { mBuilder.setDefaults(0); mBuilder.setSmallIcon(R.drawable.ic_notification); mBuilder.setDeleteIntent(createDeleteIntent()); - mBuilder.setLights(0xffffffff, 2000, 4000); + mBuilder.setLights(0xff259b24, 2000, 3000); final Notification notification = mBuilder.build(); notificationManager.notify(NOTIFICATION_ID, notification); } -- cgit v1.2.3 From 864c709c96110c8a4f7c16a3d27bb88818230f50 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sat, 28 Feb 2015 12:03:53 +0100 Subject: catching out of memory run time exception in hasEnabledAccounts() --- src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index 3ae3356d..28e1c47e 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -278,6 +278,8 @@ public class DatabaseBackend extends SQLiteOpenHelper { return (count > 0); } catch (SQLiteCantOpenDatabaseException e) { return true; // better safe than sorry + } catch (RuntimeException e) { + return true; // better safe than sorry } } -- cgit v1.2.3 From d318af098d28b6685219f852558087eee5c8c3ae Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 1 Mar 2015 12:05:54 +0100 Subject: merge messages with related status (unsend, send, send_received) --- .../java/eu/siacs/conversations/entities/Message.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index ccf274b7..7ad43d53 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -362,7 +362,8 @@ public class Message extends AbstractEntity { message.getDownloadable() == null && message.getEncryption() != Message.ENCRYPTION_PGP && this.getType() == message.getType() && - this.getStatus() == message.getStatus() && + //this.getStatus() == message.getStatus() && + isStatusMergeable(this.getStatus(),message.getStatus()) && this.getEncryption() == message.getEncryption() && this.getCounterpart() != null && this.getCounterpart().equals(message.getCounterpart()) && @@ -374,6 +375,17 @@ public class Message extends AbstractEntity { ); } + private static boolean isStatusMergeable(int a, int b) { + return a == b || ( + ( a == Message.STATUS_SEND_RECEIVED && b == Message.STATUS_UNSEND) + || (a == Message.STATUS_SEND_RECEIVED && b == Message.STATUS_SEND) + || (a == Message.STATUS_UNSEND && b == Message.STATUS_SEND) + || (a == Message.STATUS_UNSEND && b == Message.STATUS_SEND_RECEIVED) + || (a == Message.STATUS_SEND && b == Message.STATUS_UNSEND) + || (a == Message.STATUS_SEND && b == Message.STATUS_SEND_RECEIVED) + ); + } + public String getMergedBody() { final Message next = this.next(); if (this.mergeable(next)) { @@ -387,6 +399,10 @@ public class Message extends AbstractEntity { } public int getMergedStatus() { + final Message next = this.next(); + if (this.mergeable(next)) { + return next.getStatus(); + } return getStatus(); } -- cgit v1.2.3 From ff86fa604903cd77fe26860be0cc256b5d1e04eb Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 1 Mar 2015 14:15:40 +0100 Subject: mark all sent messages up to a marker as displayed --- .../eu/siacs/conversations/parser/MessageParser.java | 13 +++++++++---- .../conversations/services/XmppConnectionService.java | 19 ++++++++++--------- 2 files changed, 19 insertions(+), 13 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 3f3cf8cb..ced81520 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -402,14 +402,19 @@ public class MessageParser extends AbstractParser implements Element event = packet.findChild("event", "http://jabber.org/protocol/pubsub#event"); parseEvent(event, from, account); - } else if (from != null - && packet.hasChild("displayed", "urn:xmpp:chat-markers:0")) { + } else if (from != null && packet.hasChild("displayed", "urn:xmpp:chat-markers:0")) { String id = packet .findChild("displayed", "urn:xmpp:chat-markers:0") .getAttribute("id"); updateLastseen(packet, account, true); - mXmppConnectionService.markMessage(account, from.toBareJid(), - id, Message.STATUS_SEND_DISPLAYED); + final Message displayedMessage = mXmppConnectionService.markMessage(account, from.toBareJid(), id, Message.STATUS_SEND_DISPLAYED); + Message message = displayedMessage.prev(); + while(message != null + && message.getStatus() == Message.STATUS_SEND_RECEIVED + && message.getTimeSent() < displayedMessage.getTimeSent()) { + mXmppConnectionService.markMessage(message,Message.STATUS_SEND_DISPLAYED); + message = message.prev(); + } } else if (from != null && packet.hasChild("received", "urn:xmpp:chat-markers:0")) { String id = packet.findChild("received", "urn:xmpp:chat-markers:0") diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 90f69338..a67378de 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -2013,19 +2013,20 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } - public boolean markMessage(final Account account, final Jid recipient, final String uuid, - final int status) { + public Message markMessage(final Account account, final Jid recipient, final String uuid, final int status) { if (uuid == null) { - return false; - } else { - for (Conversation conversation : getConversations()) { - if (conversation.getJid().equals(recipient) - && conversation.getAccount().equals(account)) { - return markMessage(conversation, uuid, status); + return null; + } + for (Conversation conversation : getConversations()) { + if (conversation.getJid().equals(recipient) && conversation.getAccount() == account) { + final Message message = conversation.findSentMessageWithUuid(uuid); + if (message != null) { + markMessage(message, status); } + return message; } - return false; } + return null; } public boolean markMessage(Conversation conversation, String uuid, -- cgit v1.2.3 From ac577fe4fd36e56ff492d588af5bb427b98d915e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 2 Mar 2015 11:53:15 +0100 Subject: added methods to count number of unread messages --- .../java/eu/siacs/conversations/entities/Conversation.java | 13 +++++++++++++ .../siacs/conversations/services/XmppConnectionService.java | 8 ++++++++ 2 files changed, 21 insertions(+) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 1feb04c7..99823e4e 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -736,6 +736,19 @@ public class Conversation extends AbstractEntity implements Blockable { } } + public int unreadCount() { + synchronized (this.messages) { + int count = 0; + for(int i = this.messages.size() - 1; i >= 0; --i) { + if (this.messages.get(i).isRead()) { + return count; + } + ++count; + } + return count; + } + } + public class Smp { public static final int STATUS_NONE = 0; public static final int STATUS_CONTACT_REQUESTED = 1; diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index a67378de..f6e479c7 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -2080,6 +2080,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return getPreferences().getBoolean("indicate_received", false); } + public int unreadCount() { + int count = 0; + for(Conversation conversation : getConversations()) { + count += conversation.unreadCount(); + } + return count; + } + public void updateConversationUi() { if (mOnConversationUpdate != null) { mOnConversationUpdate.onConversationUpdate(); -- cgit v1.2.3 From fb3740f07bc75a9b22ef767d995490941a083895 Mon Sep 17 00:00:00 2001 From: Quentin Date: Wed, 4 Mar 2015 00:57:34 +0100 Subject: Green led color is better with "full-green" --- src/main/java/eu/siacs/conversations/services/NotificationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index a260d6e2..6e4f9981 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -214,7 +214,7 @@ public class NotificationService { mBuilder.setDefaults(0); mBuilder.setSmallIcon(R.drawable.ic_notification); mBuilder.setDeleteIntent(createDeleteIntent()); - mBuilder.setLights(0xff259b24, 2000, 3000); + mBuilder.setLights(0xff00FF00, 2000, 3000); final Notification notification = mBuilder.build(); notificationManager.notify(NOTIFICATION_ID, notification); } -- cgit v1.2.3 From e10c4e78f17dd7f428c139f1f4c29feb97b64099 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 4 Mar 2015 19:56:24 +0100 Subject: experimantal in memory jid caching --- src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index b8be527b..f6ab73bf 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.xmpp.jid; +import android.util.LruCache; + import net.java.otr4j.session.SessionID; import java.net.IDN; @@ -12,6 +14,8 @@ import gnu.inet.encoding.StringprepException; */ public final class Jid { + private static LruCache cache = new LruCache<>(1024); + private final String localpart; private final String domainpart; private final String resourcepart; @@ -62,6 +66,15 @@ public final class Jid { private Jid(final String jid) throws InvalidJidException { if (jid == null) throw new InvalidJidException(InvalidJidException.IS_NULL); + Jid fromCache = Jid.cache.get(jid); + if (fromCache != null) { + displayjid = fromCache.displayjid; + localpart = fromCache.localpart; + domainpart = fromCache.domainpart; + resourcepart = fromCache.resourcepart; + return; + } + // Hackish Android way to count the number of chars in a string... should work everywhere. final int atCount = jid.length() - jid.replace("@", "").length(); final int slashCount = jid.length() - jid.replace("/", "").length(); @@ -141,6 +154,8 @@ public final class Jid { throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH); } + Jid.cache.put(jid,this); + this.displayjid = finaljid; } -- cgit v1.2.3 From c5230e081cd2c9a1c5b5bd0459e339668ff4cb6d Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 5 Mar 2015 10:15:04 +0100 Subject: added config option to disable string prep in jids --- src/main/java/eu/siacs/conversations/Config.java | 1 + src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 41e8971f..2b9cee9f 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -27,6 +27,7 @@ public final class Config { public static final int REFRESH_UI_INTERVAL = 500; public static final boolean NO_PROXY_LOOKUP = false; //useful to debug ibb + public static final boolean DISABLE_STRING_PREP = false; // setting to true might increase startup performance public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000; public static final long MAM_MAX_CATCHUP = MILLISECONDS_IN_DAY / 2; diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index f6ab73bf..c95e45f9 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -6,6 +6,7 @@ import net.java.otr4j.session.SessionID; import java.net.IDN; +import eu.siacs.conversations.Config; import gnu.inet.encoding.Stringprep; import gnu.inet.encoding.StringprepException; @@ -103,7 +104,7 @@ public final class Jid { } else { final String lp = jid.substring(0, atLoc); try { - localpart = Stringprep.nodeprep(lp); + localpart = Config.DISABLE_STRING_PREP ? lp : Stringprep.nodeprep(lp); } catch (final StringprepException e) { throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e); } @@ -118,7 +119,7 @@ public final class Jid { if (slashCount > 0) { final String rp = jid.substring(slashLoc + 1, jid.length()); try { - resourcepart = Stringprep.resourceprep(rp); + resourcepart = Config.DISABLE_STRING_PREP ? rp : Stringprep.resourceprep(rp); } catch (final StringprepException e) { throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e); } @@ -154,7 +155,7 @@ public final class Jid { throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH); } - Jid.cache.put(jid,this); + Jid.cache.put(jid, this); this.displayjid = finaljid; } -- cgit v1.2.3 From f25a82461007f43c23960720d6d94d2db5c8c7f7 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 5 Mar 2015 15:46:33 +0100 Subject: avoid unnecessary thread creation --- .../services/XmppConnectionService.java | 37 ++++++++++++---------- .../siacs/conversations/ui/SettingsActivity.java | 2 +- .../siacs/conversations/xmpp/XmppConnection.java | 7 ++++ 3 files changed, 29 insertions(+), 17 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index f6e479c7..ea93308f 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1136,7 +1136,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa account.initOtrEngine(this); databaseBackend.createAccount(account); this.accounts.add(account); - this.reconnectAccount(account, false); + this.reconnectAccountInBackground(account); updateAccountUi(); } @@ -1972,24 +1972,29 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void reconnectAccount(final Account account, final boolean force) { - new Thread(new Runnable() { + synchronized (account) { + if (account.getXmppConnection() != null) { + disconnect(account, force); + } + if (!account.isOptionSet(Account.OPTION_DISABLED)) { + if (account.getXmppConnection() == null) { + account.setXmppConnection(createConnection(account)); + } + Thread thread = new Thread(account.getXmppConnection()); + thread.start(); + scheduleWakeUpCall(Config.CONNECT_TIMEOUT, account.getUuid().hashCode()); + } else { + account.getRoster().clearPresences(); + account.setXmppConnection(null); + } + } + } + public void reconnectAccountInBackground(final Account account) { + new Thread(new Runnable() { @Override public void run() { - if (account.getXmppConnection() != null) { - disconnect(account, force); - } - if (!account.isOptionSet(Account.OPTION_DISABLED)) { - if (account.getXmppConnection() == null) { - account.setXmppConnection(createConnection(account)); - } - Thread thread = new Thread(account.getXmppConnection()); - thread.start(); - scheduleWakeUpCall(Config.CONNECT_TIMEOUT, account.getUuid().hashCode()); - } else { - account.getRoster().clearPresences(); - account.setXmppConnection(null); - } + reconnectAccount(account,false); } }).start(); } diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java index 5bf3cdab..39e215f2 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java @@ -65,7 +65,7 @@ public class SettingsActivity extends XmppActivity implements for (Account account : xmppConnectionService.getAccounts()) { account.setResource(resource); if (!account.isOptionSet(Account.OPTION_DISABLED)) { - xmppConnectionService.reconnectAccount(account, false); + xmppConnectionService.reconnectAccountInBackground(account); } } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 44c367a6..57a64513 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -242,6 +242,13 @@ public class XmppConnection implements Runnable { @Override public void run() { + try { + if (socket != null) { + socket.close(); + } + } catch (final IOException ignored) { + + } connect(); } -- cgit v1.2.3 From 44028a547f23306cb8e88b0cb5b950e3c543fd34 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 6 Mar 2015 21:14:55 +0100 Subject: fixed npe in message parser --- src/main/java/eu/siacs/conversations/parser/MessageParser.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index ced81520..6652842d 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -143,7 +143,7 @@ public class MessageParser extends AbstractParser implements finishedMessage.setRemoteMsgId(packet.getId()); finishedMessage.markable = isMarkable(packet); finishedMessage.setCounterpart(from); - extractChatState(conversation,packet); + extractChatState(conversation, packet); return finishedMessage; } catch (Exception e) { conversation.resetOtrSession(); @@ -408,11 +408,11 @@ public class MessageParser extends AbstractParser implements .getAttribute("id"); updateLastseen(packet, account, true); final Message displayedMessage = mXmppConnectionService.markMessage(account, from.toBareJid(), id, Message.STATUS_SEND_DISPLAYED); - Message message = displayedMessage.prev(); - while(message != null + Message message = displayedMessage == null ? null :displayedMessage.prev(); + while (message != null && message.getStatus() == Message.STATUS_SEND_RECEIVED && message.getTimeSent() < displayedMessage.getTimeSent()) { - mXmppConnectionService.markMessage(message,Message.STATUS_SEND_DISPLAYED); + mXmppConnectionService.markMessage(message, Message.STATUS_SEND_DISPLAYED); message = message.prev(); } } else if (from != null -- cgit v1.2.3 From cbca92d2099a9b3096b7ed6fbe0e5e8758f746fc Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 6 Mar 2015 22:22:50 +0100 Subject: fixed enter is send option --- .../java/eu/siacs/conversations/ui/ConversationFragment.java | 9 +++++++-- src/main/java/eu/siacs/conversations/ui/EditMessage.java | 7 +++---- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 3e0668be..0bc4c1ef 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -1012,8 +1012,13 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } @Override - public void onEnterPressed() { - sendMessage(); + public boolean onEnterPressed() { + if (activity.enterIsSend()) { + sendMessage(); + return true; + } else { + return false; + } } @Override diff --git a/src/main/java/eu/siacs/conversations/ui/EditMessage.java b/src/main/java/eu/siacs/conversations/ui/EditMessage.java index 57fa7285..a58cf2b8 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditMessage.java +++ b/src/main/java/eu/siacs/conversations/ui/EditMessage.java @@ -37,10 +37,9 @@ public class EditMessage extends EditText { @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_ENTER) { - if (keyboardListener != null) { - keyboardListener.onEnterPressed(); + if (keyboardListener != null && keyboardListener.onEnterPressed()) { + return true; } - return true; } return super.onKeyDown(keyCode, event); } @@ -70,7 +69,7 @@ public class EditMessage extends EditText { } public interface KeyboardListener { - public void onEnterPressed(); + public boolean onEnterPressed(); public void onTypingStarted(); public void onTypingStopped(); public void onTextDeleted(); -- cgit v1.2.3 From 87a048fe6f88739a381cecab973e1af12325ce16 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sat, 7 Mar 2015 14:15:38 +0100 Subject: display geo uris as location. show 'send loction' in share menu if request location intent can be resolved --- .../eu/siacs/conversations/entities/Message.java | 4 + .../services/XmppConnectionService.java | 18 +++ .../conversations/ui/ConversationActivity.java | 138 ++++++++++++++------- .../conversations/ui/adapter/MessageAdapter.java | 32 ++++- .../eu/siacs/conversations/utils/GeoHelper.java | 71 +++++++++++ 5 files changed, 215 insertions(+), 48 deletions(-) create mode 100644 src/main/java/eu/siacs/conversations/utils/GeoHelper.java (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 7ad43d53..d9710289 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -8,6 +8,7 @@ import java.net.URL; import java.util.Arrays; import eu.siacs.conversations.Config; +import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; @@ -49,6 +50,7 @@ public class Message extends AbstractEntity { public static final String RELATIVE_FILE_PATH = "relativeFilePath"; public static final String ME_COMMAND = "/me "; + public boolean markable = false; protected String conversationUuid; protected Jid counterpart; @@ -368,6 +370,8 @@ public class Message extends AbstractEntity { this.getCounterpart() != null && this.getCounterpart().equals(message.getCounterpart()) && (message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) && + !GeoHelper.isGeoUri(message.getBody()) && + !GeoHelper.isGeoUri(this.body) && !message.bodyContainsDownloadable() && !this.bodyContainsDownloadable() && !message.getBody().startsWith(ME_COMMAND) && diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index ea93308f..188f1eb9 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -306,6 +306,24 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return this.mAvatarService; } + public void attachLocationToConversation(final Conversation conversation, + final Uri uri, + final UiCallback callback) { + int encryption = conversation.getNextEncryption(forceEncryption()); + if (encryption == Message.ENCRYPTION_PGP) { + encryption = Message.ENCRYPTION_DECRYPTED; + } + Message message = new Message(conversation,uri.toString(),encryption); + if (conversation.getNextCounterpart() != null) { + message.setCounterpart(conversation.getNextCounterpart()); + } + if (encryption == Message.ENCRYPTION_DECRYPTED) { + getPgpEngine().encrypt(message,callback); + } else { + callback.success(message); + } + } + public void attachFileToConversation(final Conversation conversation, final Uri uri, final UiCallback callback) { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index ad2aab56..82afda07 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -33,7 +33,6 @@ import java.util.ArrayList; import java.util.List; import eu.siacs.conversations.R; -import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Blockable; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; @@ -63,6 +62,7 @@ public class ConversationActivity extends XmppActivity private static final int ATTACHMENT_CHOICE_TAKE_PHOTO = 0x0302; private static final int ATTACHMENT_CHOICE_CHOOSE_FILE = 0x0303; private static final int ATTACHMENT_CHOICE_RECORD_VOICE = 0x0304; + private static final int ATTACHMENT_CHOICE_LOCATION = 0x0305; 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"; @@ -71,6 +71,7 @@ public class ConversationActivity extends XmppActivity private boolean mPanelOpen = true; private Uri mPendingImageUri = null; private Uri mPendingFileUri = null; + private Uri mPendingGeoUri = null; private View mContentView; @@ -313,7 +314,6 @@ public class ConversationActivity extends XmppActivity menuInviteContact.setVisible(getSelectedConversation().getMucOptions().canInvite()); } else { menuMucDetails.setVisible(false); - final Account account = this.getSelectedConversation().getAccount(); } if (this.getSelectedConversation().isMuted()) { menuMute.setVisible(false); @@ -325,50 +325,60 @@ public class ConversationActivity extends XmppActivity return true; } - private void selectPresenceToAttachFile(final int attachmentChoice) { - selectPresence(getSelectedConversation(), new OnPresenceSelected() { + private void selectPresenceToAttachFile(final int attachmentChoice, final int encryption) { + if (attachmentChoice == ATTACHMENT_CHOICE_LOCATION && encryption != Message.ENCRYPTION_OTR) { + getSelectedConversation().setNextCounterpart(null); + Intent intent = new Intent("eu.siacs.conversations.location.request"); + startActivityForResult(intent,attachmentChoice); + } else { + selectPresence(getSelectedConversation(), new OnPresenceSelected() { - @Override - public void onPresenceSelected() { - Intent intent = new Intent(); - boolean chooser = false; - switch (attachmentChoice) { - case ATTACHMENT_CHOICE_CHOOSE_IMAGE: - intent.setAction(Intent.ACTION_GET_CONTENT); - intent.setType("image/*"); - chooser = true; - break; - case ATTACHMENT_CHOICE_TAKE_PHOTO: - mPendingImageUri = xmppConnectionService.getFileBackend().getTakePhotoUri(); - intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); - intent.putExtra(MediaStore.EXTRA_OUTPUT,mPendingImageUri); - 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); - break; - } - if (intent.resolveActivity(getPackageManager()) != null) { - if (chooser) { - startActivityForResult( - Intent.createChooser(intent,getString(R.string.perform_action_with)), - attachmentChoice); - } else { - startActivityForResult(intent, attachmentChoice); + @Override + public void onPresenceSelected() { + Intent intent = new Intent(); + boolean chooser = false; + switch (attachmentChoice) { + case ATTACHMENT_CHOICE_CHOOSE_IMAGE: + intent.setAction(Intent.ACTION_GET_CONTENT); + intent.setType("image/*"); + chooser = true; + break; + case ATTACHMENT_CHOICE_TAKE_PHOTO: + mPendingImageUri = xmppConnectionService.getFileBackend().getTakePhotoUri(); + intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); + intent.putExtra(MediaStore.EXTRA_OUTPUT, mPendingImageUri); + 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); + break; + case ATTACHMENT_CHOICE_LOCATION: + intent.setAction("eu.siacs.conversations.location.request"); + break; + } + if (intent.resolveActivity(getPackageManager()) != null) { + if (chooser) { + startActivityForResult( + Intent.createChooser(intent, getString(R.string.perform_action_with)), + attachmentChoice); + } else { + startActivityForResult(intent, attachmentChoice); + } } } - } - }); + }); + } } private void attachFile(final int attachmentChoice) { final Conversation conversation = getSelectedConversation(); - if (conversation.getNextEncryption(forceEncryption()) == Message.ENCRYPTION_PGP) { + final int encryption = conversation.getNextEncryption(forceEncryption()); + if (encryption == Message.ENCRYPTION_PGP) { if (hasPgp()) { if (conversation.getContact().getPgpKeyId() != 0) { xmppConnectionService.getPgpEngine().hasKey( @@ -378,13 +388,12 @@ public class ConversationActivity extends XmppActivity @Override public void userInputRequried(PendingIntent pi, Contact contact) { - ConversationActivity.this.runIntent(pi, - attachmentChoice); + ConversationActivity.this.runIntent(pi,attachmentChoice); } @Override public void success(Contact contact) { - selectPresenceToAttachFile(attachmentChoice); + selectPresenceToAttachFile(attachmentChoice,encryption); } @Override @@ -406,7 +415,7 @@ public class ConversationActivity extends XmppActivity .setNextEncryption(Message.ENCRYPTION_NONE); xmppConnectionService.databaseBackend .updateConversation(conversation); - selectPresenceToAttachFile(attachmentChoice); + selectPresenceToAttachFile(attachmentChoice,Message.ENCRYPTION_NONE); } }); } @@ -414,11 +423,8 @@ public class ConversationActivity extends XmppActivity } else { showInstallPgpDialog(); } - } else if (getSelectedConversation().getNextEncryption( - forceEncryption()) == Message.ENCRYPTION_NONE) { - selectPresenceToAttachFile(attachmentChoice); } else { - selectPresenceToAttachFile(attachmentChoice); + selectPresenceToAttachFile(attachmentChoice,encryption); } } @@ -526,6 +532,9 @@ public class ConversationActivity extends XmppActivity 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 @@ -543,6 +552,9 @@ public class ConversationActivity extends XmppActivity case R.id.attach_record_voice: attachFile(ATTACHMENT_CHOICE_RECORD_VOICE); break; + case R.id.attach_location: + attachFile(ATTACHMENT_CHOICE_LOCATION); + break; } return false; } @@ -809,6 +821,7 @@ public class ConversationActivity extends XmppActivity showConversationsOverview(); mPendingImageUri = null; mPendingFileUri = null; + mPendingGeoUri = null; setSelectedConversation(conversationList.get(0)); this.mConversationFragment.reInit(getSelectedConversation()); } @@ -819,6 +832,9 @@ public class ConversationActivity extends XmppActivity } else if (mPendingFileUri != null) { attachFileToConversation(getSelectedConversation(),mPendingFileUri); mPendingFileUri = null; + } else if (mPendingGeoUri != null) { + attachLocationToConversation(getSelectedConversation(),mPendingGeoUri); + mPendingGeoUri = null; } ExceptionHelper.checkForCrash(this, this.xmppConnectionService); setIntent(new Intent()); @@ -897,6 +913,14 @@ public class ConversationActivity extends XmppActivity Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(mPendingImageUri); sendBroadcast(intent); + } 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 == ATTACHMENT_CHOICE_TAKE_PHOTO) { @@ -905,6 +929,26 @@ public class ConversationActivity extends XmppActivity } } + private void attachLocationToConversation(Conversation conversation, Uri uri) { + xmppConnectionService.attachLocationToConversation(conversation,uri, new UiCallback() { + + @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) { prepareFileToast = Toast.makeText(getApplicationContext(), getText(R.string.preparing_file), Toast.LENGTH_LONG); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 58713534..da92fb18 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -34,6 +34,7 @@ import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message.ImageParams; import eu.siacs.conversations.ui.ConversationActivity; +import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.utils.UIHelper; public class MessageAdapter extends ArrayAdapter { @@ -299,6 +300,21 @@ public class MessageAdapter extends ArrayAdapter { viewHolder.download_button.setOnLongClickListener(openContextMenu); } + 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); + } + }); + viewHolder.download_button.setOnLongClickListener(openContextMenu); + } + private void displayImageMessage(ViewHolder viewHolder, final Message message) { if (viewHolder.download_button != null) { @@ -509,7 +525,11 @@ public class MessageAdapter extends ArrayAdapter { } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { displayDecryptionFailed(viewHolder); } else { - displayTextMessage(viewHolder, message); + if (GeoHelper.isGeoUri(message.getBody())) { + displayLocationMessage(viewHolder,message); + } else { + displayTextMessage(viewHolder, message); + } } displayStatus(viewHolder, message); @@ -544,6 +564,16 @@ public class MessageAdapter extends ArrayAdapter { } } + 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 { public void onContactPictureClicked(Message message); } diff --git a/src/main/java/eu/siacs/conversations/utils/GeoHelper.java b/src/main/java/eu/siacs/conversations/utils/GeoHelper.java new file mode 100644 index 00000000..f7dda936 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/utils/GeoHelper.java @@ -0,0 +1,71 @@ +package eu.siacs.conversations.utils; + +import android.content.Intent; +import android.net.Uri; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Message; + +public class GeoHelper { + private static Pattern GEO_URI = Pattern.compile("geo:([\\-0-9.]+),([\\-0-9.]+)(?:,([\\-0-9.]+))?(?:\\?(.*))?", Pattern.CASE_INSENSITIVE); + + public static boolean isGeoUri(String body) { + return body != null && GEO_URI.matcher(body).matches(); + } + + public static ArrayList createGeoIntentsFromMessage(Message message) { + final ArrayList intents = new ArrayList(); + Matcher matcher = GEO_URI.matcher(message.getBody()); + if (!matcher.matches()) { + return intents; + } + double latitude; + double longitude; + try { + latitude = Double.parseDouble(matcher.group(1)); + if (latitude > 90.0 || latitude < -90.0) { + return intents; + } + longitude = Double.parseDouble(matcher.group(2)); + if (longitude > 180.0 || longitude < -180.0) { + return intents; + } + } catch (NumberFormatException nfe) { + return intents; + } + final Conversation conversation = message.getConversation(); + String label; + if (conversation.getMode() == Conversation.MODE_SINGLE && message.getStatus() == Message.STATUS_RECEIVED) { + try { + label = "(" + URLEncoder.encode(message.getConversation().getName(), "UTF-8") + ")"; + } catch (UnsupportedEncodingException e) { + label = ""; + } + } else { + label = ""; + } + + Intent locationPluginIntent = new Intent("eu.siacs.conversations.location.show"); + locationPluginIntent.putExtra("latitude",latitude); + locationPluginIntent.putExtra("longitude",longitude); + if (conversation.getMode() == Conversation.MODE_SINGLE && message.getStatus() == Message.STATUS_RECEIVED) { + locationPluginIntent.putExtra("name",conversation.getName()); + } + intents.add(locationPluginIntent); + + Intent geoIntent = new Intent(Intent.ACTION_VIEW); + geoIntent.setData(Uri.parse("geo:" + String.valueOf(latitude) + "," + String.valueOf(longitude) + "?q=" + String.valueOf(latitude) + "," + String.valueOf(longitude) + label)); + intents.add(geoIntent); + + Intent httpIntent = new Intent(Intent.ACTION_VIEW); + httpIntent.setData(Uri.parse("https://maps.google.com/maps?q=loc:"+String.valueOf(latitude) + "," + String.valueOf(longitude) +label)); + intents.add(httpIntent); + return intents; + } +} -- cgit v1.2.3 From 67f8ed44bd7241556a7cb1eb2aee2dda4cbbbf4e Mon Sep 17 00:00:00 2001 From: Boris Wachtmeister Date: Sat, 7 Mar 2015 15:36:31 +0100 Subject: disable all really weak cipher suites With #959 all ciphers of the platform were enabled, but this also includes several suites that are considered as very weak, even down to NULL- and anon-ciphers which disable completely disable encryption and/or authentication. Especially the anon-ciphers could be easily used for a mitm-attack. To remove all weak ciphers a blacklist with patterns of cipher-names was added to Config.java. The blacklist is based on the "mandatory discards" that Mozilla suggests to not use for TLS-servers because they are weak or known to be broken. https://wiki.mozilla.org/Security/Server_Side_TLS#Mandatory_discards --- src/main/java/eu/siacs/conversations/Config.java | 9 +++++++++ .../java/eu/siacs/conversations/utils/CryptoHelper.java | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 2b9cee9f..f38bcbfc 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -64,6 +64,15 @@ public final class Config { "TLS_RSA_WITH_AES_256_CBC_SHA", }; + public static final String WEAK_CIPHER_PATTERNS[] = { + "_NULL_", + "_EXPORT_", + "_anon_", + "_RC4_", + "_DES_", + "_MD5", + }; + private Config() { } diff --git a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java index 31fe2c11..eb7e2c3c 100644 --- a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java @@ -4,6 +4,7 @@ import java.security.SecureRandom; import java.text.Normalizer; import java.util.Arrays; import java.util.Collection; +import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; @@ -103,6 +104,21 @@ public final class CryptoHelper { final List platformCiphers = Arrays.asList(platformSupportedCipherSuites); cipherSuites.retainAll(platformCiphers); cipherSuites.addAll(platformCiphers); + filterWeakCipherSuites(cipherSuites); return cipherSuites.toArray(new String[cipherSuites.size()]); } + + private static void filterWeakCipherSuites(final Collection cipherSuites) { + final Iterator it = cipherSuites.iterator(); + while (it.hasNext()) { + String cipherName = it.next(); + // remove all ciphers with no or very weak encryption or no authentication + for (String weakCipherPattern : Config.WEAK_CIPHER_PATTERNS) { + if (cipherName.contains(weakCipherPattern)) { + it.remove(); + break; + } + } + } + } } -- cgit v1.2.3 From 5132cd723476b6f612cf103b927e1fcf869cb039 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 10 Mar 2015 17:20:50 +0100 Subject: show geo uris as 'location' in overview --- src/main/java/eu/siacs/conversations/utils/UIHelper.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index e36c169b..c3195d86 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -153,7 +153,13 @@ public class UIHelper { if (message.getBody().startsWith(Message.ME_COMMAND)) { return new Pair<>(message.getBody().replaceAll("^" + Message.ME_COMMAND, UIHelper.getMessageDisplayName(message) + " "), false); - } else { + } else if (GeoHelper.isGeoUri(message.getBody())) { + if (message.getStatus() == Message.STATUS_RECEIVED) { + return new Pair<>(context.getString(R.string.received_location),true); + } else { + return new Pair<>(context.getString(R.string.location), true); + } + } else{ return new Pair<>(message.getBody().trim(), false); } } -- cgit v1.2.3 From db6a63bcf6c100f24b90778c3d69e8b6cec31b16 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Tue, 10 Mar 2015 21:46:13 +0100 Subject: open location directly from notification --- .../services/NotificationService.java | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index a260d6e2..f5d733b3 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -40,6 +40,7 @@ import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.ui.ManageAccountActivity; import eu.siacs.conversations.ui.TimePreference; +import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.XmppConnection; @@ -279,6 +280,11 @@ public class NotificationService { createDownloadIntent(message) ); } + if ((message = getFirstLocationMessage(messages)) != null) { + mBuilder.addAction(R.drawable.ic_room_white_24dp, + mXmppConnectionService.getString(R.string.show_location), + createShowLocationIntent(message)); + } mBuilder.setContentIntent(createContentIntent(conversation)); } return mBuilder; @@ -342,6 +348,15 @@ public class NotificationService { return null; } + private Message getFirstLocationMessage(final Iterable messages) { + for(final Message message : messages) { + if (GeoHelper.isGeoUri(message.getBody())) { + return message; + } + } + return null; + } + private CharSequence getMergedBodies(final ArrayList messages) { final StringBuilder text = new StringBuilder(); for (int i = 0; i < messages.size(); ++i) { @@ -353,6 +368,16 @@ public class NotificationService { return text.toString(); } + private PendingIntent createShowLocationIntent(final Message message) { + Iterable intents = GeoHelper.createGeoIntentsFromMessage(message); + for(Intent intent : intents) { + if (intent.resolveActivity(mXmppConnectionService.getPackageManager()) != null) { + return PendingIntent.getActivity(mXmppConnectionService,18,intent,PendingIntent.FLAG_UPDATE_CURRENT); + } + } + return createOpenConversationsIntent(); + } + private PendingIntent createContentIntent(final String conversationUuid, final String downloadMessageUuid) { final TaskStackBuilder stackBuilder = TaskStackBuilder .create(mXmppConnectionService); -- cgit v1.2.3 From 4ee4eeb5e7d87001f1da83951f67609384bca853 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 11 Mar 2015 15:48:43 +0100 Subject: add context menu entries for geo uris --- .../conversations/ui/ConversationFragment.java | 50 ++++++++++++++-------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 0bc4c1ef..d5f20e41 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -8,6 +8,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender; import android.content.IntentSender.SendIntentException; +import android.net.Uri; import android.os.Bundle; import android.text.InputType; import android.view.ContextMenu; @@ -58,6 +59,7 @@ import eu.siacs.conversations.ui.XmppActivity.OnValueEdited; import eu.siacs.conversations.ui.adapter.MessageAdapter; import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureClicked; import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureLongClicked; +import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.jid.Jid; @@ -410,19 +412,20 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa MenuItem downloadImage = menu.findItem(R.id.download_image); MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission); if ((m.getType() != Message.TYPE_TEXT && m.getType() != Message.TYPE_PRIVATE) - || m.getDownloadable() != null) { + || m.getDownloadable() != null || GeoHelper.isGeoUri(m.getBody())) { copyText.setVisible(false); } - if (m.getType() == Message.TYPE_TEXT + if ((m.getType() == Message.TYPE_TEXT || m.getType() == Message.TYPE_PRIVATE - || m.getDownloadable() != null) { + || m.getDownloadable() != null) + && (!GeoHelper.isGeoUri(m.getBody()))) { shareWith.setVisible(false); - } + } if (m.getStatus() != Message.STATUS_SEND_FAILED) { sendAgain.setVisible(false); } - if ((m.getType() != Message.TYPE_IMAGE && m.getDownloadable() == null) - || m.getImageParams().url == null) { + if (((m.getType() != Message.TYPE_IMAGE && m.getDownloadable() == null) + || m.getImageParams().url == null) && !GeoHelper.isGeoUri(m.getBody())) { copyUrl.setVisible(false); } if (m.getType() != Message.TYPE_TEXT @@ -467,16 +470,21 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa private void shareWith(Message message) { Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); - shareIntent.putExtra(Intent.EXTRA_STREAM, - activity.xmppConnectionService.getFileBackend() - .getJingleFileUri(message)); - shareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - String path = message.getRelativeFilePath(); - String mime = path == null ? null :URLConnection.guessContentTypeFromName(path); - if (mime == null) { - mime = "image/webp"; + if (GeoHelper.isGeoUri(message.getBody())) { + shareIntent.putExtra(Intent.EXTRA_TEXT, message.getBody()); + shareIntent.setType("text/plain"); + } else { + shareIntent.putExtra(Intent.EXTRA_STREAM, + activity.xmppConnectionService.getFileBackend() + .getJingleFileUri(message)); + shareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + String path = message.getRelativeFilePath(); + String mime = path == null ? null : URLConnection.guessContentTypeFromName(path); + if (mime == null) { + mime = "image/webp"; + } + shareIntent.setType(mime); } - shareIntent.setType(mime); activity.startActivity(Intent.createChooser(shareIntent,getText(R.string.share_with))); } @@ -501,8 +509,16 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } private void copyUrl(Message message) { - if (activity.copyTextToClipboard( - message.getImageParams().url.toString(), R.string.image_url)) { + final String url; + final int resId; + if (GeoHelper.isGeoUri(message.getBody())) { + resId = R.string.location; + url = message.getBody(); + } else { + resId = R.string.image_url; + url = message.getImageParams().url.toString(); + } + if (activity.copyTextToClipboard(url, resId)) { Toast.makeText(activity, R.string.url_copied_to_clipboard, Toast.LENGTH_SHORT).show(); } -- cgit v1.2.3 From 74e5317095f19b16f99251ba25177d84aaf21a8a Mon Sep 17 00:00:00 2001 From: "Mateusz \"maxmati\" Nowoty?ski" Date: Thu, 5 Mar 2015 22:11:59 +0100 Subject: Do not Strigprep JIDs from database --- src/main/java/eu/siacs/conversations/entities/Contact.java | 2 +- .../java/eu/siacs/conversations/entities/Conversation.java | 4 +--- src/main/java/eu/siacs/conversations/entities/Message.java | 4 ++-- src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java | 14 +++++++++----- 4 files changed, 13 insertions(+), 11 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 698e0322..cef03ebe 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -80,7 +80,7 @@ public class Contact implements ListItem, Blockable { cursor.getLong(cursor.getColumnIndex(LAST_TIME))); final Jid jid; try { - jid = Jid.fromString(cursor.getString(cursor.getColumnIndex(JID))); + jid = Jid.fromString(cursor.getString(cursor.getColumnIndex(JID)), true); } catch (final InvalidJidException e) { // TODO: Borked DB... handle this somehow? return null; diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 99823e4e..c150fb91 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -2,10 +2,8 @@ package eu.siacs.conversations.entities; import android.content.ContentValues; import android.database.Cursor; -import android.os.SystemClock; import net.java.otr4j.OtrException; -import net.java.otr4j.crypto.OtrCryptoEngineImpl; import net.java.otr4j.crypto.OtrCryptoException; import net.java.otr4j.session.SessionID; import net.java.otr4j.session.SessionImpl; @@ -371,7 +369,7 @@ public class Conversation extends AbstractEntity implements Blockable { public static Conversation fromCursor(Cursor cursor) { Jid jid; try { - jid = Jid.fromString(cursor.getString(cursor.getColumnIndex(CONTACTJID))); + jid = Jid.fromString(cursor.getString(cursor.getColumnIndex(CONTACTJID)), true); } catch (final InvalidJidException e) { // Borked DB.. jid = null; diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index d9710289..8015eead 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -117,7 +117,7 @@ public class Message extends AbstractEntity { try { String value = cursor.getString(cursor.getColumnIndex(COUNTERPART)); if (value != null) { - jid = Jid.fromString(value); + jid = Jid.fromString(value, true); } else { jid = null; } @@ -128,7 +128,7 @@ public class Message extends AbstractEntity { try { String value = cursor.getString(cursor.getColumnIndex(TRUE_COUNTERPART)); if (value != null) { - trueCounterpart = Jid.fromString(value); + trueCounterpart = Jid.fromString(value, true); } else { trueCounterpart = null; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index c95e45f9..295e067a 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -46,7 +46,11 @@ public final class Jid { } public static Jid fromString(final String jid) throws InvalidJidException { - return new Jid(jid); + return Jid.fromString(jid, false); + } + + public static Jid fromString(final String jid, final boolean safe) throws InvalidJidException { + return new Jid(jid, safe); } public static Jid fromParts(final String localpart, @@ -61,10 +65,10 @@ public final class Jid { if (resourcepart != null && !resourcepart.isEmpty()) { out = out + "/" + resourcepart; } - return new Jid(out); + return new Jid(out, false); } - private Jid(final String jid) throws InvalidJidException { + private Jid(final String jid, final boolean safe) throws InvalidJidException { if (jid == null) throw new InvalidJidException(InvalidJidException.IS_NULL); Jid fromCache = Jid.cache.get(jid); @@ -104,7 +108,7 @@ public final class Jid { } else { final String lp = jid.substring(0, atLoc); try { - localpart = Config.DISABLE_STRING_PREP ? lp : Stringprep.nodeprep(lp); + localpart = Config.DISABLE_STRING_PREP || safe ? lp : Stringprep.nodeprep(lp); } catch (final StringprepException e) { throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e); } @@ -119,7 +123,7 @@ public final class Jid { if (slashCount > 0) { final String rp = jid.substring(slashLoc + 1, jid.length()); try { - resourcepart = Config.DISABLE_STRING_PREP ? rp : Stringprep.resourceprep(rp); + resourcepart = Config.DISABLE_STRING_PREP || safe ? rp : Stringprep.resourceprep(rp); } catch (final StringprepException e) { throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e); } -- cgit v1.2.3 From 52af62d298da5780fc1f4a931b3007124b4760eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Wei=C3=9F?= Date: Tue, 17 Mar 2015 17:36:17 +0100 Subject: Set file size also for cached avatars --- .../conversations/persistance/FileBackend.java | 60 +++++++++++----------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java index 62987aaa..c499d499 100644 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -318,39 +318,41 @@ public class FileBackend { } public boolean save(Avatar avatar) { + File file; if (isAvatarCached(avatar)) { - return true; - } - String filename = getAvatarPath(avatar.getFilename()); - File file = new File(filename + ".tmp"); - file.getParentFile().mkdirs(); - try { - file.createNewFile(); - FileOutputStream mFileOutputStream = new FileOutputStream(file); - MessageDigest digest = MessageDigest.getInstance("SHA-1"); - digest.reset(); - DigestOutputStream mDigestOutputStream = new DigestOutputStream( - mFileOutputStream, digest); - mDigestOutputStream.write(avatar.getImageAsBytes()); - mDigestOutputStream.flush(); - mDigestOutputStream.close(); - avatar.size = file.length(); - String sha1sum = CryptoHelper.bytesToHex(digest.digest()); - if (sha1sum.equals(avatar.sha1sum)) { - file.renameTo(new File(filename)); - return true; - } else { - Log.d(Config.LOGTAG, "sha1sum mismatch for " + avatar.owner); - file.delete(); + file = new File(getAvatarPath(avatar.getFilename())); + } else { + String filename = getAvatarPath(avatar.getFilename()); + file = new File(filename + ".tmp"); + file.getParentFile().mkdirs(); + try { + file.createNewFile(); + FileOutputStream mFileOutputStream = new FileOutputStream(file); + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + digest.reset(); + DigestOutputStream mDigestOutputStream = new DigestOutputStream( + mFileOutputStream, digest); + mDigestOutputStream.write(avatar.getImageAsBytes()); + mDigestOutputStream.flush(); + mDigestOutputStream.close(); + String sha1sum = CryptoHelper.bytesToHex(digest.digest()); + if (sha1sum.equals(avatar.sha1sum)) { + file.renameTo(new File(filename)); + } else { + Log.d(Config.LOGTAG, "sha1sum mismatch for " + avatar.owner); + file.delete(); + return false; + } + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + return false; + } catch (NoSuchAlgorithmException e) { return false; } - } catch (FileNotFoundException e) { - return false; - } catch (IOException e) { - return false; - } catch (NoSuchAlgorithmException e) { - return false; } + avatar.size = file.length(); + return true; } public String getAvatarPath(String avatar) { -- cgit v1.2.3 From f76baa5658df9b08c7cdc7b3b85560842cb4d7f9 Mon Sep 17 00:00:00 2001 From: Andreas Straub Date: Tue, 17 Mar 2015 15:00:50 +0100 Subject: Added multiple select to Choose Contact Activity When passing the Choose Contact Activity a boolean called "multiple" set to true, it now allows the user to select multiple contacts. Long pressing a contact enters multiple selection mode and the selection is confirmed using a button in the CAB. The Activity returns whether or not multiple contacts were selected using the same boolean. If multiple contacts were selected, an array of JID strings called "contacts" is returned. The Choose Contact Activity now also honors "filter_contacts", an array of strings containing JIDs that should not be displayed in the picker. The invite to conference dialog now uses this feature to enable inviting multiple contacts at once. Additionally, Invite Contact uses "filter_contacts" to only display contacts that are not yet participating in the conversation --- .../conversations/ui/ChooseContactActivity.java | 94 +++++++++++++++++++++- .../eu/siacs/conversations/ui/XmppActivity.java | 33 ++++++-- 2 files changed, 121 insertions(+), 6 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java index 70b353c6..c9e99ce5 100644 --- a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java @@ -3,20 +3,100 @@ package eu.siacs.conversations.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.Set; +import java.util.HashSet; import java.util.Collections; +import java.util.List; +import java.util.ArrayList; +import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.ListItem; public class ChooseContactActivity extends AbstractSearchableListItemActivity { + + private Set selected; + private Set 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(); + 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 @@ -36,6 +116,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity { data.putExtra("account", account); data.putExtra("conversation", request.getStringExtra("conversation")); + data.putExtra("multiple", false); setResult(RESULT_OK, data); finish(); } @@ -48,7 +129,9 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity { for (final Account account : xmppConnectionService.getAccounts()) { if (account.getStatus() != Account.State.DISABLED) { for (final Contact contact : account.getRoster().getContacts()) { - if (contact.showInRoster() && contact.match(needle)) { + if (contact.showInRoster() && + !filterContacts.contains(contact.getJid().toBareJid().toString()) + && contact.match(needle)) { getListItems().add(contact); } } @@ -57,4 +140,13 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity { Collections.sort(getListItems()); getListItemAdapter().notifyDataSetChanged(); } + + private String[] getSelectedContactJids() { + List result = new ArrayList<>(); + for (Contact contact : selected) { + result.add(contact.getJid().toString()); + } + return result.toArray(new String[result.size()]); + } + } diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index ac7fcf9d..7eaec10c 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -69,6 +69,7 @@ import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.services.AvatarService; import eu.siacs.conversations.services.XmppConnectionService; @@ -409,7 +410,20 @@ public abstract class XmppActivity extends Activity { protected void inviteToConversation(Conversation conversation) { Intent intent = new Intent(getApplicationContext(), ChooseContactActivity.class); + List 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); startActivityForResult(intent, REQUEST_INVITE_TO_CONVERSATION); } @@ -652,22 +666,31 @@ public abstract class XmppActivity extends Activity { if (requestCode == REQUEST_INVITE_TO_CONVERSATION && resultCode == RESULT_OK) { try { - Jid jid = Jid.fromString(data.getStringExtra("contact")); String conversationUuid = data.getStringExtra("conversation"); Conversation conversation = xmppConnectionService .findConversationByUuid(conversationUuid); + List jids = new ArrayList(); + if (data.getBooleanExtra("multiple", false)) { + String[] toAdd = data.getStringArrayExtra("contacts"); + for (String item : toAdd) { + jids.add(Jid.fromString(item)); + } + } else { + jids.add(Jid.fromString(data.getStringExtra("contact"))); + } + if (conversation.getMode() == Conversation.MODE_MULTI) { - xmppConnectionService.invite(conversation, jid); + for (Jid jid : jids) { + xmppConnectionService.invite(conversation, jid); + } } else { - List jids = new ArrayList(); jids.add(conversation.getJid().toBareJid()); - jids.add(jid); xmppConnectionService.createAdhocConference(conversation.getAccount(), jids, adhocCallback); } } catch (final InvalidJidException ignored) { } - } + } } private UiCallback adhocCallback = new UiCallback() { -- cgit v1.2.3 From 1c600fefcf9cba751bc8bc0f151cc03e28d9c4b9 Mon Sep 17 00:00:00 2001 From: BrianBlade Date: Mon, 16 Mar 2015 23:23:51 +0100 Subject: # add delivery receipts for private muc msgs # enable update last-seen for muc-msgs --- .../conversations/generator/MessageGenerator.java | 3 +++ .../siacs/conversations/parser/AbstractParser.java | 5 +++++ .../siacs/conversations/parser/MessageParser.java | 22 +++++++++++++++------- .../services/XmppConnectionService.java | 2 +- 4 files changed, 24 insertions(+), 8 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index e274d2bc..7f2f10a1 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -35,6 +35,9 @@ public class MessageGenerator extends AbstractGenerator { } else if (message.getType() == Message.TYPE_PRIVATE) { packet.setTo(message.getCounterpart()); packet.setType(MessagePacket.TYPE_CHAT); + if (this.mXmppConnectionService.indicateReceived()) { + packet.addChild("request", "urn:xmpp:receipts"); + } } else { packet.setTo(message.getCounterpart().toBareJid()); packet.setType(MessagePacket.TYPE_GROUPCHAT); diff --git a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java index 3f7f1548..bfe84440 100644 --- a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java +++ b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java @@ -49,6 +49,11 @@ public abstract class AbstractParser { protected void updateLastseen(final Element packet, final Account account, final boolean presenceOverwrite) { final Jid from = packet.getAttributeAsJid("from"); + updateLastseen(packet, account, from, presenceOverwrite); + } + + protected void updateLastseen(final Element packet, final Account account, final Jid from, + final boolean presenceOverwrite) { final String presence = from == null || from.isBareJid() ? "" : from.getResourcepart(); final Contact contact = account.getRoster().getContact(from); final long timestamp = getTimestamp(packet); diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 6652842d..88d9daae 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -44,12 +44,11 @@ public class MessageParser extends AbstractParser implements } private Message parseChat(MessagePacket packet, Account account) { - final Jid jid = packet.getFrom(); + final Jid jid = packet.getFrom(); if (jid == null) { return null; } Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, jid.toBareJid(), false); - updateLastseen(packet, account, true); String pgpBody = getPgpBody(packet); Message finishedMessage; if (pgpBody != null) { @@ -64,13 +63,18 @@ public class MessageParser extends AbstractParser implements finishedMessage.markable = isMarkable(packet); if (conversation.getMode() == Conversation.MODE_MULTI && !jid.isBareJid()) { + final Jid trueCounterpart = conversation.getMucOptions() + .getTrueCounterpart(jid.getResourcepart()); + if (trueCounterpart != null) { + updateLastseen(packet, account, trueCounterpart, true); + } finishedMessage.setType(Message.TYPE_PRIVATE); - finishedMessage.setTrueCounterpart(conversation.getMucOptions() - .getTrueCounterpart(jid.getResourcepart())); + finishedMessage.setTrueCounterpart(trueCounterpart); if (conversation.hasDuplicateMessage(finishedMessage)) { return null; } - + } else { + updateLastseen(packet, account, true); } finishedMessage.setCounterpart(jid); finishedMessage.setTime(getTimestamp(packet)); @@ -89,7 +93,7 @@ public class MessageParser extends AbstractParser implements .findOrCreateConversation(account, from.toBareJid(), false); String presence; if (from.isBareJid()) { - presence = ""; + presence = ""; } else { presence = from.getResourcepart(); } @@ -153,7 +157,7 @@ public class MessageParser extends AbstractParser implements private Message parseGroupchat(MessagePacket packet, Account account) { int status; - final Jid from = packet.getFrom(); + final Jid from = packet.getFrom(); if (from == null) { return null; } @@ -163,6 +167,10 @@ public class MessageParser extends AbstractParser implements } Conversation conversation = mXmppConnectionService .findOrCreateConversation(account, from.toBareJid(), true); + final Jid trueCounterpart = conversation.getMucOptions().getTrueCounterpart(from.getResourcepart()); + if (trueCounterpart != null) { + updateLastseen(packet, account, trueCounterpart.toBareJid(), true); + } if (packet.hasChild("subject")) { conversation.setHasMessagesLeftOnServer(true); conversation.getMucOptions().setSubject(packet.findChild("subject").getContent()); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 188f1eb9..ca182867 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -2041,7 +2041,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return null; } for (Conversation conversation : getConversations()) { - if (conversation.getJid().equals(recipient) && conversation.getAccount() == account) { + if (conversation.getJid().toBareJid().equals(recipient) && conversation.getAccount() == account) { final Message message = conversation.findSentMessageWithUuid(uuid); if (message != null) { markMessage(message, status); -- cgit v1.2.3 From 442ae12ee5f979043e9ad248cdca0f2890b39654 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 19 Mar 2015 19:40:24 +0100 Subject: don't update presence for muc messages --- src/main/java/eu/siacs/conversations/parser/MessageParser.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 88d9daae..aa6aa4dc 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -1,11 +1,8 @@ package eu.siacs.conversations.parser; -import android.util.Log; - import net.java.otr4j.session.Session; import net.java.otr4j.session.SessionStatus; -import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; @@ -66,7 +63,7 @@ public class MessageParser extends AbstractParser implements final Jid trueCounterpart = conversation.getMucOptions() .getTrueCounterpart(jid.getResourcepart()); if (trueCounterpart != null) { - updateLastseen(packet, account, trueCounterpart, true); + updateLastseen(packet, account, trueCounterpart, false); } finishedMessage.setType(Message.TYPE_PRIVATE); finishedMessage.setTrueCounterpart(trueCounterpart); @@ -169,7 +166,7 @@ public class MessageParser extends AbstractParser implements .findOrCreateConversation(account, from.toBareJid(), true); final Jid trueCounterpart = conversation.getMucOptions().getTrueCounterpart(from.getResourcepart()); if (trueCounterpart != null) { - updateLastseen(packet, account, trueCounterpart.toBareJid(), true); + updateLastseen(packet, account, trueCounterpart, false); } if (packet.hasChild("subject")) { conversation.setHasMessagesLeftOnServer(true); -- cgit v1.2.3 From da099e5fa451587a0dba92179a4462c91c02c12d Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 20 Mar 2015 21:48:45 +0100 Subject: wait for session iq to return sucessfully before sending other stanzas. fixed #1017 --- .../siacs/conversations/xmpp/XmppConnection.java | 68 +++++++++++++--------- 1 file changed, 42 insertions(+), 26 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 57a64513..48dc2150 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -687,28 +687,11 @@ public class XmppConnection implements Runnable { } catch (final InvalidJidException e) { // TODO: Handle the case where an external JID is technically invalid? } - if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) { - smVersion = 3; - final EnablePacket enable = new EnablePacket(smVersion); - tagWriter.writeStanzaAsync(enable); - stanzasSent = 0; - messageReceipts.clear(); - } else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) { - smVersion = 2; - final EnablePacket enable = new EnablePacket(smVersion); - tagWriter.writeStanzaAsync(enable); - stanzasSent = 0; - messageReceipts.clear(); - } - features.carbonsEnabled = false; - features.blockListRequested = false; - disco.clear(); - sendServiceDiscoveryInfo(account.getServer()); - sendServiceDiscoveryItems(account.getServer()); - if (bindListener != null) { - bindListener.onBind(account); + if (streamFeatures.hasChild("session")) { + sendStartSession(); + } else { + sendPostBindInitialization(); } - sendInitialPing(); } else { disconnect(true); } @@ -717,12 +700,45 @@ public class XmppConnection implements Runnable { } } }); - if (this.streamFeatures.hasChild("session")) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": sending deprecated session"); - final IqPacket startSession = new IqPacket(IqPacket.TYPE.SET); - startSession.addChild("session","urn:ietf:params:xml:ns:xmpp-session"); - this.sendUnmodifiedIqPacket(startSession, null); + } + + private void sendStartSession() { + final IqPacket startSession = new IqPacket(IqPacket.TYPE.SET); + startSession.addChild("session","urn:ietf:params:xml:ns:xmpp-session"); + this.sendUnmodifiedIqPacket(startSession, new OnIqPacketReceived() { + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + if (packet.getType() == IqPacket.TYPE.RESULT) { + sendPostBindInitialization(); + } else { + disconnect(true); + } + } + }); + } + + private void sendPostBindInitialization() { + smVersion = 0; + if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) { + smVersion = 3; + } else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) { + smVersion = 2; + } + if (smVersion != 0) { + final EnablePacket enable = new EnablePacket(smVersion); + tagWriter.writeStanzaAsync(enable); + stanzasSent = 0; + messageReceipts.clear(); + } + features.carbonsEnabled = false; + features.blockListRequested = false; + disco.clear(); + sendServiceDiscoveryInfo(account.getServer()); + sendServiceDiscoveryItems(account.getServer()); + if (bindListener != null) { + bindListener.onBind(account); } + sendInitialPing(); } private void sendServiceDiscoveryInfo(final Jid server) { -- cgit v1.2.3 From 99b2ef7e9d571dcfa386df4d0190ce626e657232 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sat, 21 Mar 2015 16:07:17 +0100 Subject: respond to unreadable OTR messages with error message. fixed #1021 --- .../java/eu/siacs/conversations/crypto/OtrEngine.java | 18 +++++++++++++++--- .../eu/siacs/conversations/entities/Conversation.java | 9 +++++++++ .../conversations/generator/MessageGenerator.java | 13 +++++++++++++ .../eu/siacs/conversations/parser/MessageParser.java | 2 ++ .../conversations/xmpp/stanzas/MessagePacket.java | 3 +++ 5 files changed, 42 insertions(+), 3 deletions(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java b/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java index c85864d0..20427d7b 100644 --- a/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java +++ b/src/main/java/eu/siacs/conversations/crypto/OtrEngine.java @@ -201,9 +201,21 @@ public class OtrEngine extends OtrCryptoEngineImpl implements OtrEngineHost { } @Override - public void messageFromAnotherInstanceReceived(SessionID id) { - Log.d(Config.LOGTAG, - "unreadable message received from " + id.getAccountID()); + public void messageFromAnotherInstanceReceived(SessionID session) { + try { + Jid jid = Jid.fromSessionID(session); + Conversation conversation = mXmppConnectionService.find(account, jid); + String id = conversation == null ? null : conversation.getLastReceivedOtrMessageId(); + if (id != null) { + MessagePacket packet = mXmppConnectionService.getMessageGenerator().generateOtrError(jid,id); + packet.setFrom(account.getJid()); + mXmppConnectionService.sendMessagePacket(account,packet); + Log.d(Config.LOGTAG,packet.toString()); + Log.d(Config.LOGTAG,account.getJid().toBareJid().toString()+": unreadable OTR message in "+conversation.getName()); + } + } catch (InvalidJidException e) { + return; + } } @Override diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index c150fb91..bfee5007 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -78,6 +78,7 @@ public class Conversation extends AbstractEntity implements Blockable { private boolean messagesLeftOnServer = true; private ChatState mOutgoingChatState = Config.DEFAULT_CHATSTATE; private ChatState mIncomingChatState = Config.DEFAULT_CHATSTATE; + private String mLastReceivedOtrMessageId = null; public boolean hasMessagesLeftOnServer() { return messagesLeftOnServer; @@ -234,6 +235,14 @@ public class Conversation extends AbstractEntity implements Blockable { return getContact().getBlockedJid(); } + public String getLastReceivedOtrMessageId() { + return this.mLastReceivedOtrMessageId; + } + + public void setLastReceivedOtrMessageId(String id) { + this.mLastReceivedOtrMessageId = id; + } + public interface OnMessageFound { public void onMessageFound(final Message message); diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index 7f2f10a1..8f6a90b9 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -171,4 +171,17 @@ public class MessageGenerator extends AbstractGenerator { received.setAttribute("id", originalMessage.getId()); return receivedPacket; } + + public MessagePacket generateOtrError(Jid to, String id) { + MessagePacket packet = new MessagePacket(); + packet.setType(MessagePacket.TYPE_ERROR); + packet.setAttribute("id",id); + packet.setTo(to); + Element error = packet.addChild("error"); + error.setAttribute("code","406"); + error.setAttribute("type","modify"); + error.addChild("not-acceptable","urn:ietf:params:xml:ns:xmpp-stanzas"); + error.addChild("text").setContent("unreadable OTR message received"); + return packet; + } } diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index aa6aa4dc..72ece046 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -118,6 +118,7 @@ public class MessageParser extends AbstractParser implements } } try { + conversation.setLastReceivedOtrMessageId(packet.getId()); Session otrSession = conversation.getOtrSession(); SessionStatus before = otrSession.getSessionStatus(); body = otrSession.transformReceiving(body); @@ -145,6 +146,7 @@ public class MessageParser extends AbstractParser implements finishedMessage.markable = isMarkable(packet); finishedMessage.setCounterpart(from); extractChatState(conversation, packet); + conversation.setLastReceivedOtrMessageId(null); return finishedMessage; } catch (Exception e) { conversation.resetOtrSession(); diff --git a/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java b/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java index 61465ae0..93aaa68c 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java +++ b/src/main/java/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java @@ -39,6 +39,9 @@ public class MessagePacket extends AbstractStanza { break; case TYPE_NORMAL: break; + case TYPE_ERROR: + this.setAttribute("type","error"); + break; default: this.setAttribute("type", "chat"); break; -- cgit v1.2.3 From c47d1e83c1a5ee11f6924dd4e8ac95f123802824 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sat, 21 Mar 2015 16:43:03 +0100 Subject: properly set chat states when receiving otr status messages --- src/main/java/eu/siacs/conversations/parser/MessageParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu') diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 72ece046..8ae9b642 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -94,6 +94,7 @@ public class MessageParser extends AbstractParser implements } else { presence = from.getResourcepart(); } + extractChatState(conversation, packet); updateLastseen(packet, account, true); String body = packet.getBody(); if (body.matches("^\\?OTRv\\d{1,2}\\?.*")) { @@ -145,7 +146,6 @@ public class MessageParser extends AbstractParser implements finishedMessage.setRemoteMsgId(packet.getId()); finishedMessage.markable = isMarkable(packet); finishedMessage.setCounterpart(from); - extractChatState(conversation, packet); conversation.setLastReceivedOtrMessageId(null); return finishedMessage; } catch (Exception e) { -- cgit v1.2.3