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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(+) 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(-) 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 d1076588f42aaafbcd75ca36f34b2f53c5765134 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 9 Feb 2015 16:41:29 +0100 Subject: version bump to 1.0.2 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 4b695b0d..f64b5fbf 100644 --- a/build.gradle +++ b/build.gradle @@ -46,8 +46,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 46 - versionName "1.0.1" + versionCode 47 + versionName "1.0.2" } compileOptions { -- 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(-) 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 +++++ .../res/drawable-hdpi/ic_autorenew_white_24dp.png | Bin 0 -> 489 bytes src/main/res/drawable-hdpi/ic_block_white_24dp.png | Bin 0 -> 606 bytes .../res/drawable-mdpi/ic_autorenew_white_24dp.png | Bin 0 -> 353 bytes src/main/res/drawable-mdpi/ic_block_white_24dp.png | Bin 0 -> 428 bytes .../res/drawable-xhdpi/ic_autorenew_white_24dp.png | Bin 0 -> 604 bytes .../res/drawable-xhdpi/ic_block_white_24dp.png | Bin 0 -> 796 bytes .../drawable-xxhdpi/ic_autorenew_white_24dp.png | Bin 0 -> 869 bytes .../res/drawable-xxhdpi/ic_block_white_24dp.png | Bin 0 -> 1194 bytes .../drawable-xxxhdpi/ic_autorenew_white_24dp.png | Bin 0 -> 1114 bytes .../res/drawable-xxxhdpi/ic_block_white_24dp.png | Bin 0 -> 1497 bytes src/main/res/values/strings.xml | 1 + 14 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/main/res/drawable-hdpi/ic_autorenew_white_24dp.png create mode 100644 src/main/res/drawable-hdpi/ic_block_white_24dp.png create mode 100644 src/main/res/drawable-mdpi/ic_autorenew_white_24dp.png create mode 100644 src/main/res/drawable-mdpi/ic_block_white_24dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_autorenew_white_24dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_block_white_24dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_autorenew_white_24dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_block_white_24dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_autorenew_white_24dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_block_white_24dp.png 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; diff --git a/src/main/res/drawable-hdpi/ic_autorenew_white_24dp.png b/src/main/res/drawable-hdpi/ic_autorenew_white_24dp.png new file mode 100644 index 00000000..b1ee2974 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_autorenew_white_24dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_block_white_24dp.png b/src/main/res/drawable-hdpi/ic_block_white_24dp.png new file mode 100644 index 00000000..13f716d7 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_block_white_24dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_autorenew_white_24dp.png b/src/main/res/drawable-mdpi/ic_autorenew_white_24dp.png new file mode 100644 index 00000000..86b71938 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_autorenew_white_24dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_block_white_24dp.png b/src/main/res/drawable-mdpi/ic_block_white_24dp.png new file mode 100644 index 00000000..4e5093f7 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_block_white_24dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_autorenew_white_24dp.png b/src/main/res/drawable-xhdpi/ic_autorenew_white_24dp.png new file mode 100644 index 00000000..e8462223 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_autorenew_white_24dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_block_white_24dp.png b/src/main/res/drawable-xhdpi/ic_block_white_24dp.png new file mode 100644 index 00000000..b86e6c47 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_block_white_24dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_autorenew_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_autorenew_white_24dp.png new file mode 100644 index 00000000..b871381a Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_autorenew_white_24dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_block_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_block_white_24dp.png new file mode 100644 index 00000000..d2be2d61 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_block_white_24dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_autorenew_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_autorenew_white_24dp.png new file mode 100644 index 00000000..569bafe2 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_autorenew_white_24dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_block_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_block_white_24dp.png new file mode 100644 index 00000000..b538af61 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_block_white_24dp.png differ diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 9d3300d8..ebf25604 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -444,4 +444,5 @@ Sending %s Offering %s Hide offline + Disable Account -- 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(-) 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(-) 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 a75042830f219226b3ac4e1ac582d33df368b760 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 12 Feb 2015 23:14:18 +0100 Subject: version bump to 1.0.3 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index f64b5fbf..4c6ce614 100644 --- a/build.gradle +++ b/build.gradle @@ -46,8 +46,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 47 - versionName "1.0.2" + versionCode 48 + versionName "1.0.3" } compileOptions { -- cgit v1.2.3 From 9ff39a1a1ec6429f209861721ec580b5e82a2613 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 13 Feb 2015 10:39:28 +0100 Subject: updated bcprov to 1.51 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4c6ce614..2032e455 100644 --- a/build.gradle +++ b/build.gradle @@ -31,7 +31,7 @@ dependencies { compile project(':libs:openpgp-api-lib') compile project(':libs:MemorizingTrustManager') compile 'com.android.support:support-v13:21.0.3' - compile 'org.bouncycastle:bcprov-jdk15on:1.50' + compile 'org.bouncycastle:bcprov-jdk15on:1.51' compile 'net.java:otr4j:0.22' compile 'org.gnu.inet:libidn:1.15' compile 'com.google.zxing:core:3.1.0' -- 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(-) 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(-) 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(-) 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(-) 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(-) 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 a6e695961404b141948aa5dd2d7822aa164bc581 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 16 Feb 2015 16:56:40 +0100 Subject: pulled translations from transifex --- src/main/res/values-ar-rEG/strings.xml | 90 +++++++ src/main/res/values-ca/strings.xml | 53 +++-- src/main/res/values-de/strings.xml | 3 +- src/main/res/values-el/strings.xml | 420 ++++++++++++++++++++++++++++++++- src/main/res/values-fa/strings.xml | 2 + src/main/res/values-fr/strings.xml | 1 + src/main/res/values-nl/strings.xml | 1 + src/main/res/values-pl/strings.xml | 89 +++++++ src/main/res/values-sr/strings.xml | 15 ++ src/main/res/values-sv/strings.xml | 1 + 10 files changed, 647 insertions(+), 28 deletions(-) create mode 100644 src/main/res/values-fa/strings.xml create mode 100644 src/main/res/values-pl/strings.xml diff --git a/src/main/res/values-ar-rEG/strings.xml b/src/main/res/values-ar-rEG/strings.xml index f81a2ee7..25175243 100644 --- a/src/main/res/values-ar-rEG/strings.xml +++ b/src/main/res/values-ar-rEG/strings.xml @@ -83,6 +83,7 @@ تنزيل الصورة إرسال بدون تشفير فشل فك التشفير. ربما لم يكن لديك المفتاح الخاص الصحيح. + Conversations :: يستخدم تطبيق آخر يسمى OpenKeychain لتشفير وفك تشفير الرسائل وإدارة المفاتيح العامة الخاصة بك \n\nOpenKeychain تحت الرخصة GPLv3 و لتحميل التطبيق من جوجل بلاي \n\n (وأعد تشغيل التطبيق مرة أخرى) اعادة تشغيل تثبيت عرض .. @@ -112,6 +113,95 @@ حسابك مفاتيح ارسال تحديثات الظهور + اختيار صورة + التقاط صورة + الملف غير موجود + غير معروف + متصل + غير متصل + غير مصرح له + لا يمكن الاتصال بالسرفر + تحقق من اتصالك بالانترنت + فشل تسجيل حساب بالسيرفر + اسم المستخدم مستخدم من قبل + تم تسجيل حسابك بنجاح + تسجيل الحسابات غير متاح على هذا السرفر + رساله عادية + OTRرسالة مشفرة عبر + OpenPGPرسالة مشفرة عبر + تعديل الحساب + حذف الحساب + نشر الصورة الرمزية + تفعيل الحساب + هل أنت متأكد ؟ + اذا مسحت حسابك ستفقد جميع الرسائل المحفوظه !! + تسجيل صوت + حساب جابر + كلمة السر + username@example.com + تأكيد كلمة السر + كلمة السر + تأكيد كلمة السر + الكلمتان غير متطابقتان + حساب جابر غير صالح + متصل + متاح للدردشة + بعيد + بعيد جدا + مشغول + غير متصل + الغرف + المشتركين + معلومات السرفر + متاح + غير متاح + آخر ظهور الآن + آخر ظهور منذ 1 دقيقة + آخر ظهور منذ %d دقيقة + آخر ظهور منذ 1 ساعة + آخر ظهور منذ %d ساعة + آخر ظهور منذ 1 يوم + آخر ظهور منذ %d يوم + لم يظهر متصلا حتى الآن + تأكيد + الغرف + بحث + اضافة جهة اتصال + دخول الغرف + حذف جهة اتصال + عرض بيانات جهة الاتصال + حجب جهة اتصال + الغاء حجب جهة اتصال + أضف + جهة الاتصال موجودة لديك مسبقا + دخول + اسم الغرفة كامل + room@conference.example.com + حفظ بالمفضلة + حذف من المفضلة + موجوده بالمفضلة سابقا + انت + تعديل موضوع الغرفة + الغرفة غير متاحه .. تأكد من عنوان الغرفة + غادر + جهة اتصال أضافتك + نشر + نشر ... + الى %s + ارسال رسالة خاصة الى %s + اتصال + الحساب موجود من قبل + التالي + معلومات اضافية + تجاهل + ايقاف التنبيهات + ايقاف التنبيهات لتلك المحادثة + التنبيهات غير فعاله + تفعيل + الغرفة تطلب كلمة مرور + أدخل كلمة المرور + اطلب الآن + تجاهل منع نظام التشغيل من انهاء اتصالك اختيار ملف اكتمل الإستلام %1$s (%2$d%% بنسبة) diff --git a/src/main/res/values-ca/strings.xml b/src/main/res/values-ca/strings.xml index c178283e..e50fa740 100644 --- a/src/main/res/values-ca/strings.xml +++ b/src/main/res/values-ca/strings.xml @@ -17,13 +17,13 @@ Desbloqueja aquest domini Administrar comptes Configuració - Detalls de la conferència o Detalls de la sala + Detalls de la conferència de conversació Detalls del contacte Compartir amb converses Començar una conversa Escollir un contacte LLista bloqueix - ara + Ara 1 min avans %de minuts avans Converses sense llegir o no llegides @@ -112,9 +112,9 @@ Desactiva les notificacions durant un breu termini després de rebre una còpia de missatges carbon Opcions avançades Mai enviïs informes d\'errors - Enviant traces d\'execució ajudes al futur desenvolupament del Conversations. + Enviant traces d\'execució d\'ajudes al futur desenvolupament del Conversations. Confirmant missatges - Deixeu que el seu contacte sápiga quan heu rebut i llegit un missatge + Deixeu que el seu contacte sàpiga quan heu rebut i llegit un missatge Opcions de UI OpenKeychain ha reportat un error I/O Error al desxifrar un arxiu @@ -123,9 +123,9 @@ Concedir actualitzacions Preventivament atorgar i preguntar per les subscripcions als contactes creats Subscripcions - La teva compte + El teu compte Claus - Enviar actualitzacions + Enviar actualitzacions de presència Rebre actualitzacions Preguntar per les actualizacions Escollir una imatge @@ -133,7 +133,7 @@ Preventivament otorgar una petició a la subscripció L\'arxiu que has seleccionat no és una imatge Error mentrés s\'intentaba convertir l\'imatge de l\'arxiu - Arxiu no trobat + L\'arxiu no s\'ha trobat Error general I/O. Potser és troba sense espai d\'emmagatzematge? L\'aplicació què está utilitzan per seleccionar l\'imatge no conté els suficients permissos per llegir l\'arxiu.\n\n Utilitzeu un gestor de fitxers diferent per escollir una imatge. Desconegut @@ -178,7 +178,7 @@ Lluny No molestar Fora de línia - Sala + Conferència de conversació Altres membres Informació del servidor XEP-0313:MAM @@ -203,11 +203,11 @@ Empremta dactilar OTR desconeguda Missatges xifrats OpenPGP trobats Recepció fallida - La teva empremta dactilar - Empremta dactilar OTR + La teva empremta digital + Empremta digital OTR Verificar Desxifrar - Sales + Conferencies de les conversacions Cercar Crear contacte Unir-se a la sala @@ -257,10 +257,10 @@ Perdut les actualitzacions del contacte Si us plau, sol.liciteu les actualitzacions de presència del primer contacte.\n\n.S\'utlitza per determinar quins client(s) ésta utilitzant el vostre contacte. Sol.licita ara - Eliminar l\'empremta dactilar - Estàs segur que t\'agradaria eliminar l\'empremta dactilar? + Eliminar l\'empremta digital + Estàs segur que t\'agradaria eliminar l\'empremta digital? Ignorar - Perill:L\'ennviament d\'aquest sense actualitzacions de presència podria causar problemes inesperats.\n\n Ves als detalls del contacte per verificar les subscripcions de presència. + Perill:L\'enviament d\'aquest sense actualitzacions de presència podria causar problemes inesperats.\n\n Ves als detalls del contacte per verificar les subscripcions de presència. Configuració del xifratge Força d\'extrema extrem del xifrat Enviar sempre missatges xifrat( Excepte per les sales) @@ -275,16 +275,16 @@ Hora de finalització Habilitar hores de silenci Les notificacions seràn silenciades a les hores de silenci - Augmentar el tamany de la lletra + Augmentar el tamany de la font. Utilitzar la mida més gran de les lletres per a tota l\'aplicació Botó d\'indicació de l\'estatus enviar - Rebuts de sol.licituds de missatges + Rebuts de sol.licituds dels missatges Els missatges rebuts seràn marcats amb uns ticks verds si ho admet Pintar el botó d\'enviament per indicar l\'estatus del contacte Altres Nom de la sala Utilitzar el tema de la sala en menys de la identificació de Jabber per identificar les sales - Empremta dactilar OTR copiada al portapapers + Empremta digital OTR copiada al portapapers La teva admissió en aquesta sala ha sigut bloquejada La sala es nomès per membres Estàs expulsat d\'aquesta sala @@ -307,7 +307,7 @@ Mostra la llista de bloqueig Detalls del compte Verificar OTR - Empremta dactilar remota + Empremta digital remota Escanejar ( o toca altres mòbils) Protocol de socialistes millionaris @@ -340,18 +340,18 @@ Cap aplicació trobada a l\'obrir l\'arxiu No s\'ha pogut verificar l\'empremta dactilar Verificat manualment - Estàs segur que vols verificar l\'empremta dactilar OTR dels teus contactes? + Estàs segur que vols verificar l\'empremta digital OTR dels teus contactes? Mostrar etiquetes dinàmiques Mostra etiquetes de nomès lectura per sota dels noms dels contactes Habilitar notificació - Crear una sala amb ... - Servidor de la sala no trobat - Creació de la sala fallat - Sala creada + Crear una conferència de conversació amb ... + Servidor de la conferència de conversació no trobat + la creació de la conferència de conversació ha fallat + Conferència de la conversació creada Aceptació del secret Reset Avatar del compte - Copiar l\'empremta dactilar OTR al portapapers + Copiar l\'empremta digital OTR al portapapers Anar a cercar la història als servidors No hi ha més histories al servidor Actualitzant @@ -386,8 +386,8 @@ Estàs intentant eliminar %s des d\'una sala pùblica. L\'unica manera per fer-ho és eliminar a l\'usuari per sempre Banejat ara No s\'ha pogut canviar les regles de %s - Sala d\'accés pùblica - Privada, únicament membres de la sala + Comferència de la conversació d\'accés pùblic + Privada, únicament els membres de la conferència de conversació Opcions de la sala Privat( Nomès membres) Sense anonimat @@ -416,4 +416,5 @@ L\'avatar ha sigut publicat! Enviant %s Oferint %s + Amaga el fora de línia diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index f1fe86c6..250471de 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -278,7 +278,7 @@ Schrift vergrößern Größere Schrift verwenden Absende-Knopf zeigt Online-Status an - Anfrage für Nachrichten Empfang + Anfrage für Nachrichtenempfang Empfangene Nachrichten werden mit einem grünen Häkchen markiert. Bitte beachte, dass dies nicht in allen Fällen funktioniert. Absende-Knopf einfärben, um den Online-Status des Kontakts zu signalisieren Sonstiges @@ -417,4 +417,5 @@ Sende %s %s angeboten verstecke offline + Konto abschalten diff --git a/src/main/res/values-el/strings.xml b/src/main/res/values-el/strings.xml index c757504a..6028b500 100644 --- a/src/main/res/values-el/strings.xml +++ b/src/main/res/values-el/strings.xml @@ -1,2 +1,420 @@ - + + Ρυθμίσεις + Νέα συζήτηση + Διαχείριση λογαριασμών + Λήξη συζήτησης + Λεπτομέρειες επαφής + Λεπτομέρειες συνδιάσκεψης + Ασφαλής συζήτηση + Προσθήκη λογαριασμού + Επεξεργασία ονόματος + Προσθήκη στον τηλεφωνικό κατάλογο + Διαγραφή από τη λίστα επαφών + Αποκλεισμός επαφής + Άρση αποκλεισμού επαφής + Αποκλεισμός τομέα + Άρση αποκλεισμού τομέα + Διαχείριση Λογαριασμών + Ρυθμίσεις + Λεπτομέρειες Συνδιάσκεψης + Λεπτομέρειες Επαφής + Διαμοιρασμός με Συζήτηση + Έναρξη Συζήτησης + Επιλογή επαφής + Αποκλεισμός λίστας + μόλις τώρα + πριν από 1 λεπτό + πριν από %d λεπτά + μη αναγνωσμένες Συζητήσεις + αποστολή... + Αποκρυπτογράφηση μηνύματος. Παρακαλώ περιμένετε... + Το ψευδώνυμο είναι ήδη σε χρήση + Διαχειριστής + Κάτοχος + Συντονιστής + Συμμετέχων + Επισκέπτης + Θέλετε να αφαιρέσετε την επαφή %s από τη λίστα επαφών; Η συζήτηση που σχετίζεται με αυτή την επαφή δεν θα αφαιρεθεί. + Θέλετε να αποκλείσετε την επαφή %s από το να σας στέλνει μηνύματα; + Θέλετε να επιτρέψετε στην επαφή %s να σας στέλνει μηνύματα; + Αποκλεισμός όλων των επαφών από το %s; + Άρση αποκλεισμού όλων των επαφών από το %s; + Η επαφή αποκλείστηκε + Θέλετε να αφαιρέσετε το %s ως σελιδοδείκτη; Η συζήτηση που σχετίζεται με αυτό τον σελιδοδείκτη δεν θα αφαιρεθεί. + Εγγραφή νέου λογαριασμού στον διακομιστή + Αλλαγή συνθηματικού στον διακομιστή + Διαμοιρασμός με... + Έναρξη Συζήτησης + Πρόσκληση Επαφής + Επαφές + Ακύρωση + Ορισμός + Προσθήκη + Επεξεργασία + Αφαίρεση + Αποκλεισμός + Άρση αποκλεισμού + Αποθήκευση + Εντάξει + Το Conversations έκλεισε απροσδόκητα + Στέλνοντας ίχνη στοίβας προωθείτε την συνεχή ανάπτυξη του Conversations\nΠροειδοποίηση: Για την αποστολή του ίχνους στοίβας θα χρησιμοποιηθεί ο XMPP λογαριασμός σας. + Αποστολή τώρα + Χωρίς ερώτηση την επόμενη φορά + Αδύνατη η σύνδεση στον λογαριασμό + Αδύνατη η σύνδεση σε πολλαπλούς λογαριασμούς + Επιλέξτε εδώ για να διαχειριστείτε τους λογαριασμούς σας + Επισύναψη αρχείου + Η επαφή δεν είναι στη λίστα επαφών σας. Θέλετε να την προσθέσετε; + Προσθήκη επαφής + η αποστολή απέτυχε + απορρίφθηκε + Προετοιμασία εικόνας για μετάδοση + Καθαρισμός ιστορικού + Καθαρισμός ιστορικού Συζήτησης + Θέλετε να σβήσετε όλα τα μηνύματα αυτής της Συζήτησης;\n\nΠροειδοποίηση: Αυτό δεν θα επηρεάσει τα μηνύματα που είναι αποθηκευμένα σε άλλες συσκευές ή άλλους διακομιστές. + Διαγραφή μηνυμάτων + Τερματισμός αυτής της συζήτησης αμέσως μετά + Επιλέξτε παρουσία για επικοινωνία + Αποστολή απλού μηνύματος κειμένου + Αποστολή κρυπτογραφημένου μηνύματος OTR + Αποστολή κρυπτογραφημένου μηνύματος OpenPGP + Το ψευδώνυμό σας έχει αλλάξει + Μεταφόρτωση εικόνας + Αποστολή χωρίς κρυπτογράφηση + Η αποκρυπτογράφηση απέτυχε. Ίσως δεν κατέχετε το σωστό ιδιωτικό κλειδί. + OpenKeychain + Το Conversations χρησιμοποιεί μια τρίτη εφαρμογή που ονομάζεται OpenKeychain για να κρυπτογραφεί και να αποκρυπτογραφεί μηνύματα και να διαχειρίζεται τα δημόσια κλειδιά σας.\n\nΤο OpenKeychain δημοσιεύεται με την άδεια GPLv3 και είναι διαθέσιμο στο F-Droid και το Google Play.\n\n(Παρακαλώ επανεκκινήστε το Conversations αμέσως μετά.) + Επανεκκίνηση + Εγκατάσταση + προσφορά... + αναμονή... + Δεν βρέθηκε κλειδί OpenPGP + Το Conversations αδυνατεί να κρυπτογραφήσει τα μηνύματά σας γιατί η επαφή σας δεν ανακοινώνει το δημόσιο κλειδί της.\n\nΠαρακαλώ ζητήστε από την επαφή σας να εγκαταστήσει το OpenPGP. + Δεν βρέθηκαν κλειδιά OpenPGP + Το Conversations αδυνατεί να κρυπτογραφήσει τα μηνύματά σας γιατί οι επαφές σας δεν ανακοινώνουν το δημόσιο κλειδί τους.\n\nΠαρακαλώ ζητήστε από τις επαφές σας να εγκαταστήσουν το OpenPGP. + Λήψη κρυπτογραφημένου μηνύματος. Επιλέξτε για ανάγνωση και αποκρυπτογράφηση. + Γενικά + πόρος XMPP + Το όνομα με το οποίο ταυτοποιείται αυτό το πρόγραμμα-πελάτης + Αποδοχή αρχείων + Αυτόματη αποδοχή αρχείων μικρότερα από... + Επιλογές ειδοποιήσεων + Ειδοποιήσεις + Ειδοποίηση όταν λαμβάνεται ένα νέο μήνυμα + Δόνηση + Επίσης δόνηση όταν έρχεται ένα νέο μήνυμα + Ήχος + Αναπαραγωγή ήχου κλήσης με την ειδοποίηση + Ειδοποιήσεις συνδιασκέψεων + Ειδοποίηση πάντα όταν ένα νέο μήνυμα συνδιάσκεψης λαμβάνεται αντί για μόνο όταν τονίζεται + Περίοδος χάριτος ειδοποιήσεων + Απενεργοποίηση ειδοποιήσεων για λίγο χρόνο μετά από τη λήψη ακριβούς αντιγράφου + Προχωρημένες επιλογές + Να μην αποστέλλονται αναφορές λαθών + Στέλνοντας ίχνη στοίβας βοηθάτε την συνεχόμενη ανάπτυξη του Conversations + Επιβεβαίωση μηνυμάτων + Επιτρέψτε στην επαφή σας να ειδοποιείται όταν έχετε λάβει και διαβάσει ένα μήνυμα + Επιλογές διεπαφής χρήστη + Το OpenKeychain ανέφερε κάποιο σφάλμα + Σφάλμα εισόδου/εξόδου κατά την αποκρυπτογράφηση αρχείου + Αποδοχή + Έχει συμβεί κάποιο σφάλμα + Χορήγηση ενημερώσεων παρουσίας + Ερήμην χορήγηση και παράκληση για συνδρομή παρουσίας στις επαφές που δημιουργείτε + Συνδρομές + Ο λογαριασμός σας + Κλειδιά + Αποστολή ενημερώσεων παρουσίας + Λήψη ενημερώσεων παρουσίας + Παράκληση για ενημερώσεις παρουσίας + Επιλογή εικόνας + Λήψη εικόνας + Ερήμην χορήγηση αίτησης συνδρομής + Το αρχείο που επιλέξατε δεν είναι εικόνα + Σφάλμα κατά τη μετατροπή του αρχείου εικόνας + Το αρχείο δεν βρέθηκε + Γενικό σφάλμα εισόδου/εξόδου. Ίσως δεν έχετε ελεύθερο χώρο αποθήκευσης; + Η εφαρμογή που χρησιμοποιήσατε για να επιλέξετε αυτή την εικόνα δεν μας παραχώρησε αρκετά δικαιώματα για την ανάγνωση του αρχείου.\n\nΧρησιμοποιήστε διαφορετικό διαχειριστή αρχείων για να επιλέξετε μια εικόνα + Άγνωστο + Προσωρινά απενεργοποιημένο + Συνδεμένος + Σύνδεση\u2026 + Εκτός σύνδεσης + Χωρίς εξουσιοδότηση + Δεν βρέθηκε ο διακομιστής + Χωρίς σύνδεση + Η εγγραφή απέτυχε + Το όνομα χρησιμοποιείται ήδη + Ολοκλήρωση εγγραφής + Ο διακομιστής δεν υποστηρίζει εγγραφή + Σφάλμα ασφάλειας + Μη συμβατός διακομιστής + Απλό κείμενο + OTR + OpenPGP + Επεξεργασία λογαριασμού + Διαγραφή λογαριασμού + Προσωρινά μη διαθέσιμο + Δημοσίευση εικόνας προφίλ + Δημοσίευση του δημόσιου κλειδιού OpenPGP + Ενεργοποίηση λογαριασμού + Είστε βέβαιοι; + Αν διαγράψετε τον λογαριασμό σας, θα χαθεί όλο το ιστορικό συζητήσεών σας + Εγγραφή φωνής + ταυτότητα Jabber + Συνθηματικό + username@example.com + Επιβεβαίωση συνθηματικού + Συνθηματικό + Επιβεβαίωση συνθηματικού + Τα συνθηματικά δεν ταιριάζουν + Αυτή δεν είναι έγκυρη ταυτότητα Jabber + Πλήρης μνήμη. Η εικόνα είναι πολύ μεγάλη + Θέλετε να προσθέσετε την επαφή %s στον τηλεφωνικό κατάλογο του τηλεφώνου σας; + συνδεμένος + ελεύθερος για συνομιλία + λείπω + παρατεταμένη απουσία + μην ενοχλείτε + εκτός σύνδεσης + Συνδιάσκεψη + Άλλα μέλη + Πληροφορίες διακομιστή + XEP-0313: Διαχείριση αρχείου μηνυμάτων + XEP-0280: Αντίγραφα μηνυμάτων + XEP-0352: Ένδειξη κατάστασης πελάτη + XEP-0191: Εντολή αποκλεισμού + XEP-0237: Διατήρηση εκδόσεων λίστας επαφών + XEP-0198: Διαχείριση ροών + XEP-0163: Πρωτόκολλο προσωπικών συμβάντων (εικόνες προφίλ) + διαθέσιμος + μη διαθέσιμος + Ελλειπείς ανακοινώσεις δημοσίων κλειδιών + συνδέθηκε τελευταία φορά μόλις τώρα + τελευταία σύνδεση πριν από 1 λεπτό + τελευταία σύνδεση πριν από %d λεπτά + τελευταία σύνδεση πριν από 1 ώρα + τελευταία σύνδεση πριν από %d ώρες + τελευταία σύνδεσ πριν από 1 μέρα + τελευταία σύνδεση πριν από %d μέρες + δεν έχει συνδεθεί ποτέ + Κρυπτογραφημένο μήνυμα. Παρακαλώ εγκαταστήστε το OpenKeychain για αποκρυπτογράφηση + Άγνωστο αποτύπωμα OTR + Βρέθηκαν μηνύματα κρυπτογραφημένα με OpenPGP + Η λήψη απέτυχε + Το αποτύπωμά σας + Αποτύπωμα OTR + Επαλήθευση + Αποκρυπτογράφηση + Συνδιασκέψεις + Αναζήτηση + Δημιουργία επαφής + Συμμετοχή σε συνδιάσκεψη + Διαγραφή επαφής + Λεπτομέρειες επαφής + Αποκλεισμός επαφής + Άρση αποκλεισμού επαφής + Δημιουργία + Η επαφή υπάρχει ήδη + Συμμετοχή + Διεύθυνση συνδιάσκεψης + room@conference.example.com + Αποθήκευση σαν σελιδοδείκτη + Διαγραφή σελιδοδείκτη + Αυτός ο σελιδοδείκτης υπάρχει ήδη + Εσείς + Επεξεργασία θέματος συνδιάσκεψης + Η συνδιάσκεψη δεν βρέθηκε + Έξοδος + Η επαφή σας πρόσθεσε στην λίστα επαφών + Προσθήκη επίσης + Η επαφή %s έχει διαβάσει μέχρι αυτό το σημείο + Δημοσίευση + Επιλέξτε την εικόνα προφίλ για να διαλέξετε εικόνα από την έκθεση + Παρακαλώ σημειώστε: Όλοι όσοι είναι συνδρομητές στις ενημερώσεις παρουσίας σας θα έχουν την δυνατότητα να δουν αυτή την εικόνα. + Δημοσίευση... + Ο διακομιστής απέρριψε την δημοσίευσή σας + Κάτι πήγε στραβά κατά τη μετατροπή της εικόνας σας + Αδύνατη η αποθήκευση της εικόνας προφίλ στο δίσκο + (Ή πατήστε παρατεταμένα για να επιστρέψετε στο αρχικό) + Ο διακομιστής σας δεν υποστηρίζει την δημοσίευση εικονών προφίλ + ψιθύρισε + στο %s + Αποστολή ιδιωτικού μηνύματος στην επαφή %s + Σύνδεση + Αυτός ο λογαριασμός υπάρχει ήδη + Επόμενος + Σύσταση συνεδρίας + Επιπλέον πληροφορίες + Παράλειψη + Απενεργοποίηση ειδοποιήσεων + Απενεργοποίηση ειδοποιήσεων για αυτή την συζήτηση + Οι ειδοποιήσεις είναι απενεργοποιημένες + Ενεργοποίηση + Η συζήτηση απαιτεί συνθηματικό + Εισαγωγή συνθηματικού + Ελλειπείς ενημερώσεις παρουσίας για την επαφή + Παρακαλώ αιτηθείτε ενημερώσεις παρουσίας από την επαφή σας πρώτα.\n\nΑυτό θα χρησιμοποιηθεί για να ταυτοποιηθεί το πρόγραμμα-πελάτης που χρησιμοποιεί η επαφή σας. + Αίτηση τώρα + Διαγραφή αποτυπώματος + Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το αποτύπωμα; + Αγνόηση + Προειδοποίηση: Η αποστολή αυτού χωρίς αμφίδρομες ενημερώσεις παρουσίας μπορεί να προκαλέσει απροσδόκητα προβλήματα.\n\nΠηγαίνετε στις λεπτομέρειες επαφής για να επαληθεύσετε τις συνδρομές παρουσίας σας. + Ρυθμίσεις κρυπτογράφησης + Επιβολή κρυπτογράφησης από άκρη σε άκρη + Πάντα αποστολή κρυπτογραφημένων μηνυμάτων (εκτός από συνδιασκέψεις) + Χωρίς αποθήκευση κρυπτογραφημένων μηνυμάτων + Προειδοποίηση: Αυτό μπορεί να οδηγήσει σε απώλεια μηνυμάτων + Επιλογές για προχωρημένους + Παρακαλώ να είστε προσεκτικοί με αυτά + Σχετικά με το Conversations + Πληροφορίες δημιουργίας και αδειών + Ώρες ησυχίας + Ώρα έναρξης + Ώρα λήξης + Ενεργοποίηση ωρών ησυχίας + Οι ειδοποιήσεις θα σιγαστούν κατά τις ώρες ησυχίας + Αύξηση μεγέθους γραμματοσειράς + Χρήση μεγαλύτερου μεγέθους γραμματοσειράς για όλη την εφαρμογή + Το κουμπί αποστολής υποδηλώνει την κατάσταση + Αίτηση για αποδείξεις μηνυμάτων + Τα ληφθέντα μηνύματα θα σημειώνονται με ένα πράσινο τικ, αν αυτό υποστηρίζεται + Χρωματισμός του κουμπιού αποστολής ως ένδειξη κατάστασης επαφής + Άλλο + Όνομα συνδιάσκεψης + Χρήση του θέματος δωματίου αντί για την ταυτότητα Jabber για την ταυτοποίηση συνδιασκέψεων + Το αποτύπωμα OTR αντιγράφηκε στο πρόχειρο! + Είστε αποκλεισμένοι από αυτή τη συνδιάσκεψη + Αυτή η συνδιάσκεψη είναι μόνο για μέλη + Έχετε διωχθει από αυτή την συνδιάσκεψη + χρήση λογαριασμού %s + Έλεγχος εικόνας στον διακομιστή HTTP + Το αρχείο εικόνας έχει διαγραφεί + Δεν είστε συνδεμένοι. Δοκιμάστε ξανά αργότερα + Ελέγξτε το μέγεθος του αρχείου εικόνας + Επιλογές μηνυμάτων + Αντιγραφή κειμένου + Αντιγραφή αρχικής διεύθυνσης URL + Αποστολή ξανά + Διεύθυνση URL εικόνας + Κείμενο μηνύματος + Η διεύθυνση URL αντιγράφηκε στο πρόχειρο + Το μήνυμα αντιγράφηκε στο πρόχειρο + Η μετάδοση της εικόνας απέτυχε + Σάρωση κωδικού QR + Εμφάνιση κωδικού QR + Εμφάνιση λίστας αποκλεισμένων + Λεπτομέρειες λογαριασμού + Επαλήθευση OTR + Απομακρυσμένο αποτύπωμα + σάρωση + (ή τηλέφωνα επαφής) + Πρωτόκολλο Socialist Millionaire + Υπαινιγμός ή ερώτηση + Κοινό μυστικό + Επιβεβαίωση + Σε εξέλιξη + Απάντηση + Αποτυχία + Τα μυστικά δεν ταιριάζουν + Επανάληψη + Τέλος + Επαληθέυτηκε! + Η επαφή ζήτησε επαλήθευση SMP + Δεν βρέθηκε έγκυρη συνεδρία OTR! + Συζητήσεις + Διατήρηση της υπηρεσίας στο προσκήνιο + Αποτρέπει τον τερματισμό της σύνδεσης από το λειτουργικό σύστημα + Επιλογή αρχείου + Λήψη %1$s (ολοκληρώθηκε %2$d%%) + Μεταφόρτωση του %s + αρχείο + Άνοιγμα του %s + αποστολή (ολοκλήρωση %1$d%%) + Προετοιμασία του αρχείου για μετάδοση + το %s προσφέρθηκε για μεταφόρτωση + Ακύρωση μετάδοσης + η μετάδοση του αρχείου απέτυχε + Το αρχείο έχει διαγραφεί + Δεν βρέθηκε εφαρμογή για να ανοίξει το αρχείο + Δεν ήταν δυνατή η επαλήθευση του αποτυπώματος + Χειροκίνητη επαλήθευση + Είστε βέβαιοι ότι θέλετε να επαληθεύσετε το αποτύπωμα OTR της επαφής σας; + Εμφάνιση δυναμικών ετικετών + Εμφάνιση ετικετών μόνο για ανάγνωση κάτω από τις επαφές + Ενεργοποίηση ειδοποιήσεων + Δημιουργία συνδιάσκεψης με... + Δεν βρέθηκε διακομιστής συνδιάσκεψης + Η δημιουργία συνδιάσκεψης απέτυχε! + Η συνδιάσκεψη δημιουργήθηκε! + Το μυστικό έγινε δεκτό! + Επαναφορά + Εικόνα προφίλ λογαριασμού + Αντιγραφή αποτυπώματος OTR στο πρόχειρο + Ανάκτηση ιστορικού από τον διακομιστή + Δεν υπάρχει άλλο ιστορικό στον διακομιστή + Ενημέρωση... + Επιτυχής αλλαγή συνθηματικου! + Δεν ήταν δυνατή η αλλαγή του συνθηματικού + Αποστολή μηνύματος για την έναρξη κρυπτογραφημένης συνομιλίας + Ερώτηση + Αν εσείς και η επαφή σας έχετε ένα κοινό μυστικό που κανείς άλλος δεν γνωρίζει (κάτι σαν δικό σας αστείο ή απλώς τι φάγατε την τελευταία φορά που συναντηθήκατε) μπορείτε να χρησιμοποιήσετε αυτό το μυστικό για νε επαληθεύσετε τα αποτυπώματά σας.\n\nΠροσφέρετε έναν υπαινιγμό ή μια ερώτηση για την επαφή σας, που θα απαντήσει με μια φράση στην οποία έχουν διαφοροποίηση τα πεζά από τα κεφαλαία. + Η επαφή σας θα ήθελε να επαληθεύσει το αποτύπωμά σας χρησιμοποιώντας ένα κοινό μυστικό. Η επαφή σας προμήθευση τον παρακάτω υπαινιγμό ή ερώτηση για το μυστικό αυτό. + Ο υπαινιγμός σας δεν μπορεί να είναι κενός + Το κοινό μυστικό σας δεν μπορεί να είναι κενό + Συγκρίνετε προσεκτικά το αποτύπωμα που φαίνεται παρακάτω με το αποτύπωμα της επαφής σας.\nΜπορείτε να χρησιμοποιήσετε οποιαδήποτε μορφή έμπιστης επικοινωνίας, όπως ένα κρυπτογραφημένο e-mail ή μια τηλεφωνική κλήση για να τα ανταλλάξετε. + Αλλαγή συνθηματικού + Τρέχον συνθηματικό + Νέο συνθηματικό + Το συνθηματικό δε μπορεί να είναι κενό + Ενεργοποίηση όλων των λογαριασμών + Απενεργοποίηση όλων των λογαριασμών + Εκτέλεση ενέργειας με + Χωρίς δεσμό + Χωρίς ρόλο + Απόκληρος + Μέλος + Κατάσταση για προχωρημένους + Απόδοση ιδιότητας μέλους + Ανάκληση ιδιότητας μέλους + Απόδοση δικαιωμάτων διαχειριστή + Ανάκληση δικαιωμάτων διαχειριστή + Αφαίρεση από την συνδιάσκεψη + Δεν ήταν δυνατή η αλλαγή του δεσμού της επαφής %s + Αποκλεισμός από συνδιάσκεψη + Προσπαθείτε να αφαιρέσετε την επαφή %s από μια δημόσια συνδιασκεψη. Ο μόνος τρόπος να γίνει αυτό είναι να αποκλείσετε αυτόν τον χρήστη για πάντα. + Αποκλεισμός τώρα + Δεν ήταν δυνατή η αλλαγή ρόλου της επαφής %s + Συνδιάσκεψη δημόσιας πρόσβασης + Ιδιωτική συνδιάσκεψη, μόνο για μέλη + Επιλογές συνδιάσκεψης + Ιδιωτική (μόνο για μέλη) + Μη-ανώνυμα + Μεταβολή των επιλογών συνδιάσκεψης! + Δεν ήταν δυνατή η μεταβολή των επιλογών συνδιάσκεψης + Ποτέ + 30 λεπτά + 1 ώρα + 2 ώρες + 8 ώρες + Μέχρι νεωτέρας + Επιλογές εισόδου + Αποστολή με το πλήκτρο Enter + Χρήση του πλήκτρου Enter για την αποστολή μηνύματος + Εμφάνιση του πλήκτρου Enter + Αλλαγή του πλήκτρου emoticons σε πλήκτρο Enter + ήχος + βίντεο + εικόνα + έγγραφο PDF + Εφαρμογή Android + Επαφή + Λήψη του %s + Απενεργοποίηση της υπηρεσίας στο προσκήνιο + Επιλέξτε για να ανοίξετε το Conversations + Η εικόνα προφίλ έχει δημοσιευτεί! + Αποστολή του %s + Προσφορά του %s + Απόκρυψη των εκτός σύνδεσης + diff --git a/src/main/res/values-fa/strings.xml b/src/main/res/values-fa/strings.xml new file mode 100644 index 00000000..c757504a --- /dev/null +++ b/src/main/res/values-fa/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml index ba2fbcf7..dc3ae4a6 100644 --- a/src/main/res/values-fr/strings.xml +++ b/src/main/res/values-fr/strings.xml @@ -406,4 +406,5 @@ document PDF Contact %s reçu + Désactiver le compte diff --git a/src/main/res/values-nl/strings.xml b/src/main/res/values-nl/strings.xml index 011b018f..39afb426 100644 --- a/src/main/res/values-nl/strings.xml +++ b/src/main/res/values-nl/strings.xml @@ -417,4 +417,5 @@ Bezig met versturen van %s Bezig met aanbieden van %s Offline verbergen + Account uitzetten diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml new file mode 100644 index 00000000..58dea13b --- /dev/null +++ b/src/main/res/values-pl/strings.xml @@ -0,0 +1,89 @@ + + + Ustawienia + Nowa konwersacja + Zarządzaj kontami + Zakończ konwersację + Szczegóły kontaktu + Szczególy konferencji + Dodaj konto + Usuń z rostera + Zablokuj kontakt + Odblokuj kontakt + Zablokuj domenę + Odblokuj domenę + Zarządzaj kontami + Ustawienia + Szczegóły konferencji + Szczegóły kontaktu + Rozpocznij konwersację + Wybierz kontakt + Czarna lista + przed chwilą + minutę temu + %d minut temu + nieprzeczytanych konwersacji + wysyłanie... + Deszyfrowanie wiadomości. Proszę czekać... + Admin + Właściciel + Moderator + Uczestnik + Gość + Czy na pewno chcesz usunąć %s ze swojego rostera? Konwersacja powiązana z tym kontaktem nie zostanie usunięta. + Czy na pewno chcesz zablokować wiadomości od użytkownika %s? + Czy na pewno chcesz odblokować wiadomości przychodzące od użytkownika %s? + Zablokować wszystkie kontakty z %s? + Odblokować wszystkie kontakty z %s? + Kontakt zablokowany + Zarejestruj nowe konto na serwerze + Zmień hasło na serwerze + Rozpocznij konwersację + Zaproś kontakt + Kontakty + Anuluj + Dodaj + Edytuj + Usuń + Zablokuj + Odblokuj + Zapisz + Ok + Conversations uległo awarii + Wyślij teraz + Nie pytaj ponownie + Nie można połączyć się z kontem + Nie można połączyć się z wieloma kontami + Dotknij tutaj aby zarządzać swoimi kontami + Dołącz plik + Kontakt nie jest na twoim rosterze. Czy chcesz go dodać? + Dodaj kontakt + wysyłanie nie powiodło się + odrzucono + Wyczyść historię + Wyczyść historię konwersacji + Usuń wiadomości + Zmień hasło + Obecne hasło + Nowe hasło + Hasło nie może być puste + Aktywuj wszystkie konta + Wyłącz wszystkie konta + Nigdy + 30 minut + 1 godzina + 2 godziny + 8 godzin + Używaj klawisza Enter do wysyłania wiadomości + Pokaż klawisz Enter + Zamień klawisz emotikon na klawisz Enter + plik audio + plik wideo + obraz + Kontakt + Odebrano %s + Avatar został pomyślnie opublikowany! + Wysyłanie %s + Oferowanie %s + Ukryj niedostępnych + diff --git a/src/main/res/values-sr/strings.xml b/src/main/res/values-sr/strings.xml index 874c206d..aef34aef 100644 --- a/src/main/res/values-sr/strings.xml +++ b/src/main/res/values-sr/strings.xml @@ -329,6 +329,7 @@ Изабери фајл Примам %1$s (%2$d%% завршено) Преузми %s + фајл Отвори %s шаљем (%1$d%% завршено) Припремам фајл за пренос @@ -401,6 +402,20 @@ Опције уноса Ентер шаље Користи Ентер тастер за слање порука + Прикажи Ентер тастер + Промени тастер за емотиконе у ентер тастер + звук + видео + слика ПДФ документ + Апликација за Андроид + Контакт Примљено %s + Онемогући сервис у првом плану + Додирните да отворите Конверзацију + Аватар је објављен! + Шаљем %s + Нудим %s + Сакриј неповезане + Онемогући налог diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml index f1eb6acf..ac5e81b6 100644 --- a/src/main/res/values-sv/strings.xml +++ b/src/main/res/values-sv/strings.xml @@ -417,4 +417,5 @@ Skickar %s Erbjuder %s Dölj ej anslutna + Deaktivera konton -- cgit v1.2.3 From 24cd08e55eb18381b5d0c1dd17b21b391a295064 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 16 Feb 2015 16:57:30 +0100 Subject: version bump to 1.0.4 and changelog --- CHANGELOG.md | 14 ++++++++++++++ build.gradle | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98657b21..16b53a3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ ###Changelog +####Version 1.0.4 +* load avatars asynchronously on start up +* support for XEP-0092: Software Version + +####Version 1.0.3 +* load messages asynchronously on start up +* bug fixes + +####Version 1.0.2 +* skipped + +####Version 1.0.1 +* accept more ciphers + ####Version 1.0 * MUC controls (Affiliaton changes) * Added download button to notification diff --git a/build.gradle b/build.gradle index 2032e455..03fafaf9 100644 --- a/build.gradle +++ b/build.gradle @@ -46,8 +46,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 48 - versionName "1.0.3" + versionCode 49 + versionName "1.0.4" } compileOptions { -- 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(-) 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(-) 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(-) 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 f0128fc1e4a263838253d35b16c440692b98bc94 Mon Sep 17 00:00:00 2001 From: "Christian S." Date: Wed, 18 Feb 2015 12:14:25 +0100 Subject: added XEP-0092: Software Version to XEPs.md --- docs/XEPs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/XEPs.md b/docs/XEPs.md index c64f1f57..95282c6d 100644 --- a/docs/XEPs.md +++ b/docs/XEPs.md @@ -2,6 +2,7 @@ * XEP-0030: Service Discovery * XEP-0045: Multi-User Chat * XEP-0048: Bookmarks +* XEP-0092: Software Version * XEP-0115: Entity Capabilities * XEP-0163: Personal Eventing Protocol (avatars and nicks) * XEP-0166: Jingle (only used for file transfer) -- 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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 3f248e0d89af977e7f602102663be9729430f1ed Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 19 Feb 2015 14:38:50 +0100 Subject: version bump to 1.0.5 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 03fafaf9..0a7a4648 100644 --- a/build.gradle +++ b/build.gradle @@ -46,8 +46,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 49 - versionName "1.0.4" + versionCode 50 + versionName "1.0.5" } compileOptions { -- 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 ++++++++ src/main/res/values/strings.xml | 4 + src/main/res/xml/preferences.xml | 7 ++ 14 files changed, 267 insertions(+), 53 deletions(-) create mode 100644 src/main/java/eu/siacs/conversations/xmpp/chatstate/ChatState.java 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; + } +} diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index ebf25604..a17859fc 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -445,4 +445,8 @@ Offering %s Hide offline Disable Account + %s is typing... + %s has stopped typing + Typing notifications + Let your contact know when you are writing a new message diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml index 7c92530f..8bf6eb87 100644 --- a/src/main/res/xml/preferences.xml +++ b/src/main/res/xml/preferences.xml @@ -28,6 +28,13 @@ android:key="confirm_messages" android:summary="@string/pref_confirm_messages_summary" android:title="@string/pref_confirm_messages" /> + + + 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(-) 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(+) 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(-) 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(-) 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 4458750fae9c8378a699fe084c7a7df44c9dce09 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 Feb 2015 17:35:09 +0100 Subject: otr4j has moved to Maven Central --- build.gradle | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 0a7a4648..e19924af 100644 --- a/build.gradle +++ b/build.gradle @@ -20,9 +20,6 @@ allprojects { apply plugin: 'com.android.application' repositories { - maven { - url "http://jitsi.github.com/otr4j/repository/" - } jcenter() mavenCentral() } @@ -32,7 +29,7 @@ dependencies { compile project(':libs:MemorizingTrustManager') compile 'com.android.support:support-v13:21.0.3' compile 'org.bouncycastle:bcprov-jdk15on:1.51' - compile 'net.java:otr4j:0.22' + compile 'org.jitsi:org.otr4j:0.22' compile 'org.gnu.inet:libidn:1.15' compile 'com.google.zxing:core:3.1.0' compile 'com.google.zxing:android-integration:3.1.0' -- cgit v1.2.3 From bf9bf91789c6eb07e1b071abf40a02cce415f54d Mon Sep 17 00:00:00 2001 From: "Christian S." Date: Mon, 23 Feb 2015 10:36:07 +0100 Subject: Update XEPs.md added XEP-0085: Chat State Notifications --- docs/XEPs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/XEPs.md b/docs/XEPs.md index 95282c6d..1b9ea6af 100644 --- a/docs/XEPs.md +++ b/docs/XEPs.md @@ -2,6 +2,7 @@ * XEP-0030: Service Discovery * XEP-0045: Multi-User Chat * XEP-0048: Bookmarks +* XEP-0085: Chat State Notifications * XEP-0092: Software Version * XEP-0115: Entity Capabilities * XEP-0163: Personal Eventing Protocol (avatars and nicks) -- 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(-) 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(+) 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 3e8314459c0b799024eee1413a6ecd794ebce05e Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 23 Feb 2015 21:56:06 +0100 Subject: pulled new translations from transifex --- src/main/res/values-ar-rEG/strings.xml | 26 +++++++++++++++++++ src/main/res/values-de/strings.xml | 46 ++++++++++++++++++---------------- src/main/res/values-es/strings.xml | 5 ++++ src/main/res/values-eu/strings.xml | 6 +++++ src/main/res/values-nl/strings.xml | 4 +++ src/main/res/values-sv/strings.xml | 32 ++++++++++++----------- 6 files changed, 84 insertions(+), 35 deletions(-) diff --git a/src/main/res/values-ar-rEG/strings.xml b/src/main/res/values-ar-rEG/strings.xml index 25175243..3acf8e54 100644 --- a/src/main/res/values-ar-rEG/strings.xml +++ b/src/main/res/values-ar-rEG/strings.xml @@ -83,13 +83,16 @@ تنزيل الصورة إرسال بدون تشفير فشل فك التشفير. ربما لم يكن لديك المفتاح الخاص الصحيح. + OpenKeychain Conversations :: يستخدم تطبيق آخر يسمى OpenKeychain لتشفير وفك تشفير الرسائل وإدارة المفاتيح العامة الخاصة بك \n\nOpenKeychain تحت الرخصة GPLv3 و لتحميل التطبيق من جوجل بلاي \n\n (وأعد تشغيل التطبيق مرة أخرى) اعادة تشغيل تثبيت عرض .. انتظار .. OpenPGP-لايوجد مفتاح + Conversations::لا يستطيع تشفير الرساله\n\nمن فضلك أخبر صديقك بتنصيب تطبيق OpenPGP. OpenPGP-لايوجد مفاتيح + Conversations::لا يستطيع تشفير الرساله\n\nمن فضلك أخبر صديقك بتنصيب تطبيق OpenPGP. تلقيت رساله مشفّرة .. لمسه بأناملك لعرضها. عام الريسورس @@ -106,6 +109,7 @@ اعدادات متقدمّة لا ترسل تقارير أخطاء الغاء ارسال تقارير الأخطاء يقلل من فرص حل المشكلة سريعا فكن متعاون + تأكيد الرسالة قبول حدث خطأ ما منح تحديثات الظهور @@ -202,6 +206,26 @@ أدخل كلمة المرور اطلب الآن تجاهل + أخرى + اسم الغرفة + أنت مفصول في هذه الغرفة + الغرفة للأعضاء فقط + تم طردك من الغرفة + انقطع الإتصال .. حاول مرة أخرى + فحص حجم الصورة + خيارات الرساله + نسخ النص + نص الرسالة + تفاصيل الحساب + سكان + تأكيد + جاري الاتصال + فشل الاتصال + حاول مرة أخرى + انهاء + تأكيد! + Conversations + احتفظ بالتطبيق يعمل في المقدمة منع نظام التشغيل من انهاء اتصالك اختيار ملف اكتمل الإستلام %1$s (%2$d%% بنسبة) @@ -293,4 +317,6 @@ تم نشر الصورة! ارسال %s عرض %s + اخفاء غير المتصلين + ايقاف الحساب diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index 250471de..44c5a525 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -4,7 +4,7 @@ Neue Unterhaltung Konten verwalten Unterhaltung beenden - Kontaktdetails + Kontakt-Details Konferenz-Details Verschlüsselte Unterhaltung Konto hinzufügen @@ -18,7 +18,7 @@ Konten verwalten Einstellungen Konferenz-Details - Kontaktdetails + Kontakt-Details Mit Unterhaltung teilen Beginne Unterhaltung Kontakt auswählen @@ -76,24 +76,24 @@ Nachrichten löschen Diese Unterhaltung danach beenden Ressource des Kontakts auswählen - Unverschlüsselt schreiben - OTR-verschlüsselt schreiben - OpenPGP-verschlüsselt schreiben + Normal schreiben… + OTR-verschlüsselt schreiben… + OpenPGP-verschlüsselt schreiben… Dein Nickname wurde geändert Bild herunterladen - Unverschlüsselt verschicken + Normal verschicken Entschlüsselung fehlgeschlagen. Vielleicht hast du nicht den richtigen privaten Schlüssel. OpenKeychain Conversations benutzt eine Drittanwendung namens OpenKeychain, um Nachrichten zu ver- und entschlüsseln und um deine Schlüssel zu verwalten.\n\nOpenKeychain ist GPLv3-lizenziert und kann über F-Droid oder Google Play bezogen werden.\n\n(Bitte starte Conversations danach neu.) - Neustarten + Neu starten Installieren angeboten… warten… Kein OpenPGP-Schlüssel gefunden Conversations ist nicht in der Lage, deine Nachrichten zu verschlüsseln, weil dein Kontakt seinen oder ihren Schlüssel nicht preisgibt.\n\nBitte sag deinem Kontakt, er oder sie möge OpenPGP einrichten. Keine OpenPGP-Schlüssel gefunden - Conversations ist nicht in der Lage, deine Nachrichten zu verschlüsseln, weil deine Kontakte ihre Schlüssel nicht preisgeben.\n\nBitte sag deinen Kontakten, sie mögen OpenPGP einrichten. - Verschlüsselte Nachricht erhalten. Drücke hier, um sie anzuzeigen und zu entschlüsseln. + Conversations ist nicht in der Lage, deine Nachrichten zu verschlüsseln, weil deine Kontakte ihre Schlüssel nicht preisgeben.\n\nBitte sage deinen Kontakten, sie mögen OpenPGP einrichten. + Verschlüsselte Nachricht erhalten. Drücke hier, um sie zu entschlüsseln und anzuzeigen. Allgemeines XMPP-Ressource Der Name, mit dem sich der Client selbst identifiziert @@ -113,7 +113,7 @@ Erweiterte Optionen Sende niemals Absturzberichte Wenn du Absturzberichte einschickst, hilfst du Conversations stetig zu verbessern - Lesebestätigung senden + Lese- und Empfangsbestätigung senden Informiere deine Kontakte, wenn du eine Nachricht empfangen und gelesen hast Benutzeroberfläche Fehler mit OpenKeychain @@ -139,7 +139,7 @@ Unbekannt Vorübergehend abgeschaltet Online - Verbinde\u2026 + Verbinde… Offline Ungültige Zugangsdaten Server nicht gefunden @@ -212,14 +212,14 @@ Kontakt erstellen Konferenz betreten Kontakt löschen - Kontaktdetails anzeigen + Kontakt-Details anzeigen Kontakt sperren Kontakt entsperren Erstellen Der Kontakt existiert bereits Beitreten Konferenz-Adresse - raum@conference.example.com + raum@conference.domain.de Als Lesezeichen speichern Lesezeichen löschen Das Lesezeichen existiert bereits @@ -239,9 +239,9 @@ Kann Avatar nicht speichern. (Oder klicke lange, um Standard wiederherzustellen) Dein Server unterstützt die Veröffentlichung von Avataren nicht. - private Nachricht - an %s: - Sende private Nachricht an %s + private Nachricht: + privat an %s: + Sende private Nachricht an %s… Verbinden Das Konto existiert bereits Weiter @@ -305,7 +305,7 @@ Scanne QR-Code Zeige QR-Code Zeige Sperrliste - Konto Details + Konto-Details Prüfe OTR Fingerabdruck der Gegenseite Scanne @@ -400,10 +400,10 @@ 8 Stunden Bis auf weiters Eingabeoptionen - Eingabetaste sendet Nachricht - Benutze die Eingabetaste zum Senden einer Nachricht - Zeige Enter-Taste - Zeige die Enter-Taste anstelle der Smiley-Taste + Eingabetaste (Enter) sendet Nachricht + Benutze die Eingabetaste (Enter) zum Senden einer Nachricht + Zeige Eingabe-Taste (Enter) + Zeige die Eingabe-Taste (Enter) anstelle der Smiley-Taste Audio Video Bild @@ -418,4 +418,8 @@ %s angeboten verstecke offline Konto abschalten + %s schreibt… + %s schreibt nicht mehr + Tipp-Benachrichtigung + Informiere deine Kontakte, wenn du eine Nachricht eintippst. diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index 579a226d..2f74fd7a 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -417,4 +417,9 @@ Enviando %s Ofreciendo %s Ocultar desconectados + Deshabilitar Cuenta + %s está escribiendo... + %s ha dejado de escribir + Notificación de escritura + Permite a tus contactos saber cuando estás escribiendo un nuevo mensaje diff --git a/src/main/res/values-eu/strings.xml b/src/main/res/values-eu/strings.xml index a55e3f87..2f19afd0 100644 --- a/src/main/res/values-eu/strings.xml +++ b/src/main/res/values-eu/strings.xml @@ -416,4 +416,10 @@ Profileko argazkia argitaratu da %s bidaltzen %s eskeintzen... + Lineaz kanpokoak ezkutatu + Kontua ezgaitu + %s idazten ari da... + %s idazteari utzi dio + Idazketa jakinarazpenak + Zure kontaktuak mezu berri bat noiz idazten ari zaren jakin dezan baimendu diff --git a/src/main/res/values-nl/strings.xml b/src/main/res/values-nl/strings.xml index 39afb426..ccb14613 100644 --- a/src/main/res/values-nl/strings.xml +++ b/src/main/res/values-nl/strings.xml @@ -418,4 +418,8 @@ Bezig met aanbieden van %s Offline verbergen Account uitzetten + %s is aan het typen... + %s is gestopt met typen + Type-meldingen + Laat je contacten weten wanneer je een nieuw bericht aan het schrijven bent diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml index ac5e81b6..f894bdc7 100644 --- a/src/main/res/values-sv/strings.xml +++ b/src/main/res/values-sv/strings.xml @@ -98,7 +98,7 @@ XMPP resurs Namnet som klienten identifierar sig med Acceptera filer - Acceptera automatistk filer som är mindre än… + Acceptera automatiskt filer som är mindre än… Notifieringsinställningar Notifieringar Notifiera när meddelande tagits emot @@ -107,7 +107,7 @@ Ljud Spela ljud med notifiering Konferensnotifieringar - Notifiera alltid när nytt konferensmeddelande tagits emot istället för endast vid highlight + Notifiera alltid när nytt konferensmeddelande tagits emot i stället för endast vid highlight Notifieringsfrist Inaktivera notifieringar en kort stund efter att en carbon copy tagits emot Avancerade inställningar @@ -156,8 +156,8 @@ Ändra konto Ta bort Inaktivera tillfälligt - Publisera avatarbild - Publisera OpenPGP publik nyckel + Publicera avatarbild + Publicera OpenPGP publik nyckel Aktivera Är du säker? Om du tar bort kontot kommer all konversationshistorik att försvinna @@ -228,17 +228,17 @@ Konferens hittades inte Lämna Kontakten lade till dig i sin kontaktlista - Addera tillbaks + Addera tillbaka %s har läst fram hit Publicera Tryck på avatarbild för att välja en bild från bildgalleriet Notera: Alla som kan se dina tillgänglighetsuppdateringar kommer se denna bild. - Publiserar… - Servern kunde inte publisera + Publicerar… + Servern kunde inte publicera Något gick fel vid konvertering av din bild Kunde inte spara avatarbild till disk (Eller tryck länge för att få tillbaks förvald) - Din server stödjer inte publisering av avatarbilder + Din server stödjer inte publicering av avatarbilder privat meddelande till %s Skicka privat meddelande till %s @@ -300,7 +300,7 @@ Bild-URL Meddelandetext URL kopierad till urklipp - Meddelande kopierad till urklipp + Meddelande kopierat till urklipp Bildöverföring lyckades inte Skanna QR-kod Visa QR-kod @@ -363,7 +363,7 @@ Din kontakt vill verifiera ditt fingeravtryck genom att utmana dig med en delad hemlighet. Din kontakt gav följande ledtråd eller fråga för hemligheten. Din ledtråd ska inte vara tom Din delade hemlighet kan inte vara tom - Jämför noggrant fingeravtrycker nedan med din kontakts fingeravtryck.\nDu kan använda valfri typ av betrodd kommunikation som ett krypterat e-mail eller ett telefonsamtal för att utbyta dessa. + Jämför noggrant fingeravtrycket nedan med din kontakts fingeravtryck.\nDu kan använda valfri typ av betrodd kommunikation som ett krypterat e-mail eller ett telefonsamtal för att utbyta dessa. Byt lösenord Nuvarande lösenord Nytt lösenord @@ -395,14 +395,14 @@ Kunde inte ändra konferensalternativ Aldrig 30 minuter - 1 timma + 1 timme 2 timmar 8 timmar Tills vidare Inmatningsalternativ - Skicka på enter + Skicka med enter Använd enter-knappen för att skicka meddelande - Visa enter-tangent + Visa enter-knappen Byt ut emoticons-tangenten mot en enter-tangent ljud video @@ -413,9 +413,13 @@ Tagit emot %s Deaktivera fögrundstjänst Tryck för att öppna Conversations - Avatarbild har publiserats! + Avatarbild har publicerats! Skickar %s Erbjuder %s Dölj ej anslutna Deaktivera konton + %s är att skriva... + %s har slutat skriva + Skriv-notifieringar + Låter dina kontakter veta när du är att skriva ett nytt meddelande -- cgit v1.2.3 From 0decd8ac287685dc5d82c3b4705cc4f3ba9de10e Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 23 Feb 2015 21:56:30 +0100 Subject: version bump to 1.1.0-beta --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index e19924af..22703437 100644 --- a/build.gradle +++ b/build.gradle @@ -43,8 +43,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 50 - versionName "1.0.5" + versionCode 51 + versionName "1.1.0-beta" } compileOptions { -- 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(-) 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(-) 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(+) 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 1b579f512c129f421517447c9a8bf448daed6b74 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 26 Feb 2015 16:56:46 +0100 Subject: version bump to 1.1.0 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 22703437..0464b3e3 100644 --- a/build.gradle +++ b/build.gradle @@ -43,8 +43,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 51 - versionName "1.1.0-beta" + versionCode 52 + versionName "1.1.0" } compileOptions { -- 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(+) 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(-) 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(-) 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(-) 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(-) 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(-) 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 0d6907f1e093155349c0d3591668bf14e591fb8a Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 27 Feb 2015 17:20:41 +0100 Subject: pulled new translations from transifex --- src/main/res/values-bg/strings.xml | 152 +++++++++++++++++++++++++++++++++++++ src/main/res/values-cs/strings.xml | 8 +- src/main/res/values-de/strings.xml | 44 +++++------ src/main/res/values-el/strings.xml | 5 ++ src/main/res/values-sk/strings.xml | 5 ++ 5 files changed, 191 insertions(+), 23 deletions(-) create mode 100644 src/main/res/values-bg/strings.xml diff --git a/src/main/res/values-bg/strings.xml b/src/main/res/values-bg/strings.xml new file mode 100644 index 00000000..9b2e7012 --- /dev/null +++ b/src/main/res/values-bg/strings.xml @@ -0,0 +1,152 @@ + + + Настройки + Нов разговор + Управление на профилите + Край на този разговор + Подробности за контакта + Подробности за беседата + Защитен разговор + Добавяне на профил + Редактиране на името + Добавяне към списъка с телефонни номера + Изтриване от списъка + Блокиране на контакта + Деблокиране на контакта + Блокиране на домейна + Деблокиране на домейна + Управление на профилите + Настройки + Подробности за беседата + Подробности за контакта + Споделяне в разговора + Започване на разговор + Изберете контакт + Списък с блокирани + току-що + преди 1 минута + преди %d минути + непрочетени разговори + изпращане... + Дешифриране на съобщението. Моля, изчакайте... + Псевдонимът вече се използва + Администратор + Собственик + Модератор + Участник + Посетител + Искате ли да премахнете %s от списъка си? Разговорът с него няма да бъде премахнат. + Искате ли да блокирате %s, така че да не може да Ви праща съобщения? + Искате ли да деблокирате %s, така че отново да може да Ви праща съобщения? + Блокиране на всички контакти от %s? + Деблокиране на всички контакти от %s? + Контактът е блокиран + Искате ли да премахнете отметката за %s? Разговорът, свързан с тази отметка, няма да бъде премахнат. + Регистриране на нов профил на сървъра + Промяна на паролата в сървъра + Споделяне с... + Започване на разговор + Канене на контакт + Контакти + Отказ + Задаване + Добавяне + Редактиране + Изтриване + Блокиране + Деблокиране + Запазване + Добре + Conversations се срина + Изпращайки ни проследявания на стека, Вие помагате за непрекъснатото развитие на Conversations\nВнимание: Това ще използва Вашия XMPP профил, за да изпраща проследяването на стека до разработчика. + Изпращане сега + Не ме питайте повече + Неуспешно свързване с профила + Неуспешно свързване с няколко профила + Докоснете тук за управление на Вашите профили + Прикачане на файл + Този контакт не е в списъка Ви. Искате ли да го добавите? + Добавяне на контакт + доставянето се провали + отказано + Подготовка на изображението за изпращане + Изчистване на историята + Изчистване на историята на разговорите + Искате ли да изтриете всички съобщения от този разговор?\n\nВнимание: Това няма да изтрие съобщенията, съхранявани на други устройства или на сървърите. + Изтриване на съобщенията + Този разговор да приключи след това + Изберете присъствие за контакта + Изпращане на обикновено текстово съобщение + Изпращане на съобщение, шифровано чрез OTP + Изпращане на съобщение, шифровано чрез OpenPGP + Псевдонимът Ви беше променен + Изтегляне на изображението + Изпращане нешифровано + Неуспешно дешифриране. Възможно е да нямате правилния частен ключ. + Conversations не може да шифрира съобщенията Ви, тъй като контактите Ви не обявяват публичния си ключ.\n\nМоля, помолете контактите си да настроят OpenPGP. + Известия за беседите + Изпращайки проследявания на стека, Вие помагате за непрекъснатото развитие на Conversations + Позволяване на актуализации на присъствието + Предварително позволяване и изискване на абониране за актуализации на присъствието за контакти, създадено от Вас + Изпращане на актуализации за присъствието + Получаване на актуализации за присъствието + Питане за актуализации за присъствието + Беседа + XEP-0191: Команда за блокиране + Дешифриране + Беседи + Присъединяване към беседа + Блокиране на контакт + Деблокиране на контакт + Адрес на беседата + room@conference.example.com + Запазване като отметка + Изтриване на отметка + Вече съществува такава отметка + Редактиране на темата на беседата + Беседата не е открита + Забележка: Всеки, абониран за актуализации на присъствието Ви, ще може да вижда тази снимка. + Беседата изисква парола + Липсват актуализации за присъствието на контакта + Моля, първо помолете контакта за актуализации на присъствието му.\n\nТова ще бъде използвано, за да се провери какъв клиент (или клиенти) използва контакта. + Внимание: Изпращането на това без съвместни актуализации на присъствието може да доведе до неочаквани проблеми.\n\nПогледнете подробностите за контакта, за да проверите дали сте абониран за актуализации на присъствието. + Настройки за шифроване + Съобщенията да се изпращат винаги шифровани (освен в беседите) + Шифрованите съобщения да не се запазват + Име на беседата + Достъпът Ви до тази беседа беше забранен + Тази беседа е само за членове + Бяхте изритан от тази конференция + Показване на списъка с блокирани + Започване на беседа с... + Не е открит сървър за беседата + Неуспешно създаване на беседа! + Беседата беше създадена! + Изпратете съобщение, за да започнете нешифрован разговор + Премахване от беседата + Забраняване на достъпа до беседата + Вие се опитвате да премахнете %s от публична беседа. Единственият начин да направите това, е да забраните достъпа на този потребител завинаги. + Забраняване на достъпа сега + Неуспешна промяна на ролята на %s + Публично достъпни беседи + Частни беседи, само за членове + Настройки на беседата + Частна (само за членове) + Не-анонимна + Настройките на беседата бяха променени! + Неуспешна промяна на настройките на беседата + Никога + 30 минути + 1 час + 2 часа + 8 часа + До отмяна + Настройки за въвеждане + Enter изпраща + Натискането на клавиша Enter изпраща съобщението + аудио + видео + изображение + PDF документ + Приложение за Андроид + diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml index a98b00f2..84c7437b 100644 --- a/src/main/res/values-cs/strings.xml +++ b/src/main/res/values-cs/strings.xml @@ -114,7 +114,7 @@ Neodesílat detaily o pádu aplikace Zasláním detailů o důvodu selhání pomůžete dalšímu vývoji aplikace Konverzace Potvrzovat zprávy - Dá vědět kontaktům, že zpráva byla přijata a přečtena + Oznamovat kontaktům, že zpráva byla přijata a přečtena Nastavení UI OpenKeychain nahlásil chybu I/O chyba dešifrování souboru @@ -416,4 +416,10 @@ Avatar byl zveřejněn! Odesílám %s Nabízím %s + Skrýt offline + Vypnout účet + %s píše... + %s přestal(a) psát + Upozornění při psaní + Oznamovat kontaktům že píšete novou zprávu diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index 44c5a525..d266a99d 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -8,7 +8,7 @@ Konferenz-Details Verschlüsselte Unterhaltung Konto hinzufügen - Name bearbeiten + Namen bearbeiten Zum Telefonbuch hinzufügen Aus Kontaktliste entfernen Kontakt sperren @@ -27,7 +27,7 @@ vor einer Minute vor %d Minuten ungelesene Unterhaltungen - Senden… + senden… Entschlüssele Nachricht. Bitte warten… Nickname wird bereits verwendet Administrator @@ -41,7 +41,7 @@ Sperre alle Kontakte von %s? Entsperre alle Kontakte %s? Kontakt gesperrt - Möchtest du das Lesezeichen %s entfernen? Die Unterhaltung mit diesem Lesezeichen wird dabei nicht entfernt. + Möchtest du %s von deiner Kontaktliste entfernen? Die Unterhaltung mit dieser Konferenz wird dabei nicht entfernt. Neues Konto auf dem Server erstellen Passwort ändern Teile mit… @@ -66,12 +66,12 @@ Drücke hier, um das Konto zu verwalten Datei anfügen Der Kontakt ist nicht in deiner Kontaktliste. Möchtest du ihn hinzufügen? - Kontakt hinzufügen + Zur Kontaktliste hinzufügen Zustellung nicht erfolgreich abgelehnt Bereite Bild für die Übertragung vor Verlauf löschen - Unterhaltungsverlauf löschen + Verlauf löschen Möchtest du alle Nachrichten in dieser Unterhaltung löschen?\n\nAchtung: Dies beeinflusst nicht Nachrichten, die auf anderen Geräten oder Servern gespeichert sind. Nachrichten löschen Diese Unterhaltung danach beenden @@ -121,7 +121,7 @@ Annehmen Ein unbekannter Fehler ist aufgetreten Online-Status - Erlaube Kontakten, die von dir erstellt wurden, deinen Status zu sehen und frage um Erlaubnis, ihren sehen zu dürfen + Erlaube neu hinzugefügten Kontakten deinen online-Status zu sehen und frage um Erlaubnis, ihren sehen zu dürfen Abonnements Dein Konto Schlüssel @@ -162,8 +162,8 @@ Bist du dir sicher? Wenn du dein Konto löschst, gehen alle Gesprächsverläufe verloren Sprache aufzeichnen - Jabber-ID: - Passwort: + Jabber-ID + Passwort benutzer@domain.de Passwort bestätigen Passwort @@ -172,7 +172,7 @@ Ungültige Jabber-ID Zu wenig Speicher vorhanden. Das Bild ist zu groß Möchtest du %s zum Telefonbuch hinzufügen? - Online + online Bereit Abwesend Abwesend (erweitert) @@ -220,9 +220,9 @@ Beitreten Konferenz-Adresse raum@conference.domain.de - Als Lesezeichen speichern - Lesezeichen löschen - Das Lesezeichen existiert bereits + Zur Kontaktliste hinzufügen + Von Kontaktliste entfernen + Die Konferenz befindet sich bereits auf deiner Kontaktliste Du Konferenz-Thema anpassen Konferenz nicht gefunden @@ -325,7 +325,7 @@ Keine gültige OTR Sitzung gefunden! Conversations Den Dienst im Vordergrund ausführen. - Verhindert, dass Android die Verbindung unterbricht + Verhindert, dass Android Conversations beendet und die Verbindung unterbricht Datei auswählen Empfange %1$s (%2$d%% abgeschlossen) Lade %s herunter @@ -344,15 +344,15 @@ Dynamische Tags anzeigen Zeige schreibgeschützte Tags unterhalb der Kontakte Aktiviere Benachrichtigungen - Starte Konferenz mit… + Beginne Konferenz mit… Konferenz-Server kann nicht gefunden werden - Starten der Konferenz fehlgeschlagen! + Beginnen der Konferenz fehlgeschlagen! Konferenz erstellt! Schlüssel akzeptiert! Zurücksetzen Konto-Avatar OTR-Fingerabdruck in Zwischenablage kopieren - Lade Chatverlauf + Lade Chatverlauf… Keine weiteren Nachrichten vorhanden Aktualisiere… Passwort geändert. @@ -388,20 +388,20 @@ Rolle von %s konnte nicht geändert werden Öffentlich zugängliche Konferenz Private Konferenz nur für Mitglieder - Konferenzoptionen + Konferenz-Optionen Privat (Nur für Mitglieder) De-anonymisiert - Konferenzoptionen wurden modifiziert! - Konferenzoptionen konnten nicht modifiziert werden + Konferenz-Optionen wurden modifiziert! + Konferenz-Optionen konnten nicht modifiziert werden Niemals 30 Minuten 1 Stunde 2 Stunden 8 Stunden Bis auf weiters - Eingabeoptionen - Eingabetaste (Enter) sendet Nachricht - Benutze die Eingabetaste (Enter) zum Senden einer Nachricht + Eingabe-Optionen + Eingabe-Taste (Enter) sendet Nachricht + Benutze die Eingabe-Taste (Enter) zum Senden einer Nachricht Zeige Eingabe-Taste (Enter) Zeige die Eingabe-Taste (Enter) anstelle der Smiley-Taste Audio diff --git a/src/main/res/values-el/strings.xml b/src/main/res/values-el/strings.xml index 6028b500..06ab989e 100644 --- a/src/main/res/values-el/strings.xml +++ b/src/main/res/values-el/strings.xml @@ -417,4 +417,9 @@ Αποστολή του %s Προσφορά του %s Απόκρυψη των εκτός σύνδεσης + Απενεργοποίηση λογαριασμού + Ο χρήστης %s γράφει... + Ο χρήστης %s σταμάτησε να γράφει + Ειδοποιήσεις πληκτρολόγησης + Επιτρέψτε στην επαφή σας να γνωρίζει πότε γράφετε ένα νέο μήνυμα diff --git a/src/main/res/values-sk/strings.xml b/src/main/res/values-sk/strings.xml index 78622fa5..bca8d3d2 100644 --- a/src/main/res/values-sk/strings.xml +++ b/src/main/res/values-sk/strings.xml @@ -417,4 +417,9 @@ Posielam %s Ponúkam %s Skryť neprihlásených + Vypnúť účet + %s píše... + %s prestal písať + Upozornenia pri písaní + Upozorniť kontakt, keď píšete novú správu -- 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(+) 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 4beb954da5652915dbb0ffb3839d517bfd719b24 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sat, 28 Feb 2015 12:04:32 +0100 Subject: increment version code --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0464b3e3..2c23aad6 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 52 + versionCode 53 versionName "1.1.0" } -- 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(-) 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(-) 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(+) 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(-) 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(+) 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(-) 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(-) 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 a385b6ce0b534bb45a355af514c06153f96e7be0 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 6 Mar 2015 14:25:17 +0100 Subject: added short todo list --- todo.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 todo.md diff --git a/todo.md b/todo.md new file mode 100644 index 00000000..79489fe3 --- /dev/null +++ b/todo.md @@ -0,0 +1,15 @@ +===GSOC teaser tasks=== +====update Contacts last seen for muc messages as well=== +The contact class (entities/Contact) has the ability to save the last time that Conversations + received a message from that contact. Currently this time only gets updated for one-on-one + messages. In non-anonymous mucs messages from a contact should also update the last seen + time. +====Select multiple Contact in Choose Contact Activity==== +Currently the choose Contact activity allows only for one contact to be selected. A long +press on one contact should bring the activity in a mode where the user can select multiple +contacts. +The Activity should then return an array of contacts instead of just one +====Request and respond to message receipts in MUC PNs==== +Private MUC messages either dont request message receipts or dont respond to them. The source +of error should be determined and eliminated. A rather small tasks that just teaches you a bit +about the stanza parser and generator in Conversations -- cgit v1.2.3 From ce9aede11c4deee28df5e5419bef646967f111f4 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 6 Mar 2015 14:27:09 +0100 Subject: fixed markdown syntax in todo list --- todo.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/todo.md b/todo.md index 79489fe3..8ec2cd24 100644 --- a/todo.md +++ b/todo.md @@ -1,15 +1,18 @@ -===GSOC teaser tasks=== -====update Contacts last seen for muc messages as well=== +##GSOC teaser tasks + +####update Contacts last seen for muc messages as well The contact class (entities/Contact) has the ability to save the last time that Conversations received a message from that contact. Currently this time only gets updated for one-on-one messages. In non-anonymous mucs messages from a contact should also update the last seen time. -====Select multiple Contact in Choose Contact Activity==== + +####Select multiple Contact in Choose Contact Activity Currently the choose Contact activity allows only for one contact to be selected. A long press on one contact should bring the activity in a mode where the user can select multiple contacts. The Activity should then return an array of contacts instead of just one -====Request and respond to message receipts in MUC PNs==== + +####Request and respond to message receipts in MUC PNs Private MUC messages either dont request message receipts or dont respond to them. The source of error should be determined and eliminated. A rather small tasks that just teaches you a bit about the stanza parser and generator in Conversations -- cgit v1.2.3 From 16c6f8d2fff851f389c03eab2d3afb8e82547aab Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Fri, 6 Mar 2015 14:39:05 +0100 Subject: another teaser task for gsoc --- todo.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/todo.md b/todo.md index 8ec2cd24..bace5987 100644 --- a/todo.md +++ b/todo.md @@ -16,3 +16,8 @@ The Activity should then return an array of contacts instead of just one Private MUC messages either dont request message receipts or dont respond to them. The source of error should be determined and eliminated. A rather small tasks that just teaches you a bit about the stanza parser and generator in Conversations + +####Edit dynamic tags / groups +The context menu for the contact list (StartConversationActivity) should offer the ability to +edit groups. (Any UI decissions are left to you) Quick suggestion though: Dialog with +checkboxes for existing groups and some way to enter new tags. -- 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(-) 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(-) 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 +++++++++++ src/main/res/menu/attachment_choices.xml | 17 ++- src/main/res/values/strings.xml | 3 + 7 files changed, 230 insertions(+), 53 deletions(-) create mode 100644 src/main/java/eu/siacs/conversations/utils/GeoHelper.java 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; + } +} diff --git a/src/main/res/menu/attachment_choices.xml b/src/main/res/menu/attachment_choices.xml index 5139272c..6e8fc51d 100644 --- a/src/main/res/menu/attachment_choices.xml +++ b/src/main/res/menu/attachment_choices.xml @@ -2,14 +2,21 @@ + android:id="@+id/attach_location" + android:title="@string/send_location"/> + + + - + + + diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index a17859fc..316fbb8c 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -449,4 +449,7 @@ %s has stopped typing Typing notifications Let your contact know when you are writing a new message + Send location + Show location + No application found to display location -- 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(+) 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 +++++++- src/main/res/values/strings.xml | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) 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); } } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 316fbb8c..8ebe58ca 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -452,4 +452,6 @@ Send location Show location No application found to display location + Location + Received location -- 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 +++++++++++++++++++++ src/main/res/drawable-hdpi/ic_room_white_24dp.png | Bin 0 -> 494 bytes src/main/res/drawable-mdpi/ic_room_white_24dp.png | Bin 0 -> 362 bytes src/main/res/drawable-xhdpi/ic_room_white_24dp.png | Bin 0 -> 587 bytes .../res/drawable-xxhdpi/ic_room_white_24dp.png | Bin 0 -> 861 bytes .../res/drawable-xxxhdpi/ic_room_white_24dp.png | Bin 0 -> 1093 bytes 6 files changed, 25 insertions(+) create mode 100644 src/main/res/drawable-hdpi/ic_room_white_24dp.png create mode 100644 src/main/res/drawable-mdpi/ic_room_white_24dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_room_white_24dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_room_white_24dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_room_white_24dp.png 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); diff --git a/src/main/res/drawable-hdpi/ic_room_white_24dp.png b/src/main/res/drawable-hdpi/ic_room_white_24dp.png new file mode 100644 index 00000000..c2ccd510 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_room_white_24dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_room_white_24dp.png b/src/main/res/drawable-mdpi/ic_room_white_24dp.png new file mode 100644 index 00000000..a4fcd770 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_room_white_24dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_room_white_24dp.png b/src/main/res/drawable-xhdpi/ic_room_white_24dp.png new file mode 100644 index 00000000..e1e60a5c Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_room_white_24dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_room_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_room_white_24dp.png new file mode 100644 index 00000000..00b15508 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_room_white_24dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_room_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_room_white_24dp.png new file mode 100644 index 00000000..a5dde3b9 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_room_white_24dp.png differ -- 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(-) 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(-) 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 3d570f4a08ea417f6119d7c0e9a8e5e12287ae29 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Wed, 11 Mar 2015 18:18:07 +0100 Subject: updated changelong --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16b53a3e..77a49e47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ ###Changelog +####Version 1.2.0 +* Send current location (requires plugin) +* bug fixes + +####Version 1.1.0 +* Typing notifications (must be turned on in settings) +* Various UI performance improvements +* bug fixes + ####Version 1.0.4 * load avatars asynchronously on start up * support for XEP-0092: Software Version -- cgit v1.2.3 From 4aab45533ac8a32be2fe66b266b845aed02acf1b Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Mon, 16 Mar 2015 11:52:42 +0100 Subject: pulled new translations from transifex --- src/main/res/values-bg/strings.xml | 286 ++++++++++++++++++++++++++++++++++++- src/main/res/values-cs/strings.xml | 5 + src/main/res/values-de/strings.xml | 5 + src/main/res/values-el/strings.xml | 5 + src/main/res/values-es/strings.xml | 5 + src/main/res/values-eu/strings.xml | 2 +- src/main/res/values-fr/strings.xml | 22 ++- src/main/res/values-nl/strings.xml | 5 + src/main/res/values-sr/strings.xml | 9 ++ src/main/res/values-sv/strings.xml | 15 +- 10 files changed, 348 insertions(+), 11 deletions(-) diff --git a/src/main/res/values-bg/strings.xml b/src/main/res/values-bg/strings.xml index 9b2e7012..3715e820 100644 --- a/src/main/res/values-bg/strings.xml +++ b/src/main/res/values-bg/strings.xml @@ -28,7 +28,7 @@ преди %d минути непрочетени разговори изпращане... - Дешифриране на съобщението. Моля, изчакайте... + Дешифроване на съобщението. Моля, изчакайте... Псевдонимът вече се използва Администратор Собственик @@ -82,48 +82,306 @@ Псевдонимът Ви беше променен Изтегляне на изображението Изпращане нешифровано - Неуспешно дешифриране. Възможно е да нямате правилния частен ключ. - Conversations не може да шифрира съобщенията Ви, тъй като контактите Ви не обявяват публичния си ключ.\n\nМоля, помолете контактите си да настроят OpenPGP. + Неуспешно дешифроване. Възможно е да нямате правилния частен ключ. + OpenKeychain + Conversations използва външно приложение с име OpenKeychain, за да шифрова и дешифрова съобщенията и да управлява публичните Ви ключове.\n\nOpenKeychain е лицензирано под условията на GPLv3 и е налично в F-Droid и Google Play.\n\n(Моля, рестартирайте Conversations след това.) + Рестартиране + Инсталиране + предлагане... + изчакване... + Не е открит OpenPGP ключ + Conversations не може да шифрова съобщенията Ви, тъй като Вашият контакт не обявява публичния си ключ.\n\nМоля, помолете го/я да инсталира и настрои OpenPGP. + Не са открити OpenPGP ключове + Conversations не може да шифрова съобщенията Ви, тъй като Вашите контакти не обявяват публичните си ключове.\n\nМоля, помолете го да инсталират и настроят OpenPGP. + Получено е шифровано съобщение. Докоснете, за да го прегледате и дешифровате. + Общи + XMPP ресурс + Името, с което се определя този клиент + Приемане на файлове + Автоматично приемане на файлове с размер, по-малък от... + Настройки за известията + Известия + Известяване при получаване на ново съобщение + Вибрация + Също така да има и вибрация при получаване на ново съобщение + Звук + Изпълнение на звук с известието Известия за беседите + Известяване винаги, когато пристигне ново съобщение в беседа, а не само когато тя е отбелязана + Продължителност на отсрочване на известията + Изключва известията за кратко, след като бъде получено копие на съобщение + Разширени настройки + Никога да не се изпращат доклади за сривове Изпращайки проследявания на стека, Вие помагате за непрекъснатото развитие на Conversations + Потвърждаване на съобщенията + Уведомява контакта Ви, че сте приели и прочели съобщението му + Настройки на интерфейса + OpenKeychain докладва за грешка + В/И грешка при дешифроването на файла + Приемане + Възникна грешка Позволяване на актуализации на присъствието Предварително позволяване и изискване на абониране за актуализации на присъствието за контакти, създадено от Вас + Абонаменти + Вашият профил + Ключове Изпращане на актуализации за присъствието Получаване на актуализации за присъствието Питане за актуализации за присъствието + Изберете снимка + Заснемане + Предварително позволяване на абониране при заявка + Избраният файл не е изображение + Грешка при преобразуването на изображението + Файлът не е открит + Обща В/И грешка. Може би нямате достатъчно свободно място? + Приложението, което използвахте, за да изберете това изображение, не ни осигури нужните права за прочитането му.\n\nИзползвайте друг диспечер на файлове, за да изберете изображение. + Непознат + Временно деактивиран + На линия + Свързване\u2026 + Извън линия + Неупълномощен + Сървърът не е открит + Няма връзка + Неуспешна регистрация + Потребителското име е заето + Регистрацията е завършена + Сървърът не поддържа регистриране + Грешка в сигурността + Несъвместим сървър + Обикновен текст + OTR + OpenPGP + Редактиране на профила + Изтриване на профила + Временно деактивиране + Публикуване на аватар + Публикуване на публичния OpenPGP ключ + Активиране на профила + Сигурни ли сте? + Ако изтриете профила, цялата история на разговорите Ви ще бъде изтрита. + Запис на глас + Jabber идентификатор + Парола + username@example.com + Потвърдете паролата + Парола + Потвърдете паролата + Паролите са различни + Това не е правилен Jabber идентификатор + Няма достатъчно памет. Изображението е твърде голямо. + Искате ли да добавите %s в списъка си от телефонни контакти? + на линия + свободен за разговор + отсъстващ + разширено отсъстващ + отпочиващ + извън линия Беседа + Други членове + Инф. за сървъра + XEP-0313: Управление на архива на съобщенията + XEP-0280: Копия на съобщенията + XEP-0352: Показания за състоянието на клиента XEP-0191: Команда за блокиране - Дешифриране + XEP-0237: Поддържане на версия на списъка + XEP-0198: Управление на потоците + XEP-0163: PEP (Аватари) + налично + не е налично + Липсват обявления за публичен ключ + последно видян току-що + последно видян преди 1 минута + последно видян преди %d минути + последно видян преди 1 час + последно видян преди %d часа + последно видян преди 1 ден + последно видян преди %d дни + не е виждан никога + Шифровано съобщение. Моля, инсталирайте OpenKeychain, за да го дешифровате. + Непознат OTR отпечатък + Открити са съобщения, шифровани чрез OpenPGP + Неуспешно получаване + Вашият отпечатък + OTR отпечатък + Потвърждаване + Дешифроване Беседи + Търсене + Създаване на контакт Присъединяване към беседа + Изтриване на контакт + Преглед на подр. за контакта Блокиране на контакт Деблокиране на контакт + Създаване + Контактът вече съществува + Присъединяване Адрес на беседата room@conference.example.com Запазване като отметка Изтриване на отметка Вече съществува такава отметка + Вие Редактиране на темата на беседата Беседата не е открита + Напускане + Контактът е добавен във Вашия списък от контакти + Добавяне обратно + %s е прочел до тук + Публикуване + Докоснете аватара, за да изберете изображение от галерията Забележка: Всеки, абониран за актуализации на присъствието Ви, ще може да вижда тази снимка. + Публикуване... + Сървърът отказа Вашето публикуване + Нещо се обърка при преобразуването на снимката Ви + Неуспешно запазване на аватара на диска + (Или задръжте, за да върнете началното) + Сървърът Ви не поддържа публикуване на аватари + прошепна + на %s + Изпращане на лично съобщение до %s + Свързване + Този профил вече съществува + Следващо + Установена е текуща сесия + Допълнителна информация + Пропускане + Изключване на известията + Изключване на известията за този разговор + Известията са изключени + Включване Беседата изисква парола + Въведете парола Липсват актуализации за присъствието на контакта Моля, първо помолете контакта за актуализации на присъствието му.\n\nТова ще бъде използвано, за да се провери какъв клиент (или клиенти) използва контакта. + Поискване сега + Изтриване на отпечатъка + Сигурни ли сте, че искате да изтриете този отпечатък? + Пренебрегване Внимание: Изпращането на това без съвместни актуализации на присъствието може да доведе до неочаквани проблеми.\n\nПогледнете подробностите за контакта, за да проверите дали сте абониран за актуализации на присъствието. Настройки за шифроване + Налагане на шифроване в двете посоки Съобщенията да се изпращат винаги шифровани (освен в беседите) Шифрованите съобщения да не се запазват + Внимание: Това може да доведе до загуба на съобщения + Настройки за напреднали + Моля, бъдете внимателни с тези + Относно Conversations + Информация за версията и лицензите + Тихи часове + Начало + Край + Включване на тихите часове + Известията ще бъдат заглушени по време на тихите часове + Голям размер на шрифта + Използване на по-голям размер на шрифтовете в цялото приложение + Бутонът за изпращане показва състоянието + Изискване на отчет за съобщенията + Получените съобщения ще бъдат отбелязани със зелена отметка, ако това се поддържа + Оцветяване на бутона за изпращане в зависимост от състоянието на контакта + Други Име на беседата + Използване на темата на стаята вместо JID идентификатора за беседите + OTR отпечатъкът е копиран! Достъпът Ви до тази беседа беше забранен Тази беседа е само за членове Бяхте изритан от тази конференция + използвайки профила %s + Проверяване на изображението на HTTP сървъра + Изображението е изтрито + Не сте свързани. Опитайте отново по-късно + Проверка на размера на файла с изображението + Настройки за съобщенята + Копиране на текста + Копиране на оригиналния адрес + Повторно изпращане + Адрес на изображението + Текст на съобщението + Адресът е копиран + Съобщението е копирано + Неуспешно прехвърляне на изображението + Сканиране на QR кода + Показване на QR кода Показване на списъка с блокирани + Подробности за профила + Проверка на OTR + Отдалечен отпечатък + сканиране + (или докоснете телефоните) + Протокол „Socialist Millionaire“ + Подсказка или въпрос + Обща тайна + Потвърждаване + В процес + Отговаряне + Неуспешно + Тайната информация не съвпада + Повторен опит + Край + Проверено! + Контактът изиска SMP проверка + Няма открита OTR сесия! + Conversations + Услугата да е на преден план + Предотвратява прекъсването на връзката Ви от операционната система + Изберете файл + Получаване на %1$s (%2$d%% завършено) + Изтегляне на %s + файл + Отваряне на %s + изпращане (%1$d%% завършено) + Подготовка на файла за прехвърляне + %s е предложен за сваляне + Отказ на прехвърлянето + неуспешно прехвърляне на файл + Файлът беше изтрит + Няма намерено приложение за отваряне на файла + Неуспешна проверка на отпечатъка + Ръчна проверка + Сигурни ли сте, че искате да проверите OTR отпечатъка на контактите си? + Динамични етикети + Показване на етикети, предназначени само за четене под контактите + Включване на известията Започване на беседа с... Не е открит сървър за беседата Неуспешно създаване на беседа! Беседата беше създадена! + Тайната е приета! + Възстановяване + Аватар на профила + Копиране на OTR отпечатъка + Получаване на историята от сървъра + Няма повече история на сървъра + Актуализиране... + Паролата е променена! + Неуспешна промяна на паролата Изпратете съобщение, за да започнете нешифрован разговор + Задаване на въпрос + Ако Вие и контакта Ви имате някаква тайна информация, която никой друг не знае (като някаква шега или пък просто какво сте обядвали, когато сте се срещнали за последно), можете да я използвате, за да проверите отпечатъците си един на друг.\n\nМожете да подсигурите подсказка или въпрос, на който контакта Ви да отговори, като има предвид, че главните и малките букви се броят за различни. + Вашият контакт би искал да провери отпечатъка Ви, като Ви попита за обща тайна информация. Контактът Ви предостави следната подсказка или въпрос, който да Ви насочи към тази тайна. + Подсказката Ви не трябва да е празна + Общата Ви тайна не може да е празна + Внимателно сравнете отпечатъка по-долу с този на Вашия контакт.\nМожете да използвате всякакъв начин на сигурна комуникация, като шифрована е-поща или телефонен разговор, за да размените отпечатъците. + Промяна на паролата + Текуща парола + Нова парола + Паролата не трябва да е празна + Активиране на всички профили + Деактивиране на всички профили + Изпълнение на действието с + Няма принадлежност + Няма роля + Отхвърлен + Член + Разширен режим + Даване на членство + Отмяна на членството + Даване на администраторски права + Отмяна на администраторските права Премахване от беседата + Неуспешна промяна на принадлежността на %s Забраняване на достъпа до беседата Вие се опитвате да премахнете %s от публична беседа. Единственият начин да направите това, е да забраните достъпа на този потребител завинаги. Забраняване на достъпа сега @@ -144,9 +402,29 @@ Настройки за въвеждане Enter изпраща Натискането на клавиша Enter изпраща съобщението + Показване на клавиша Enter + Смяна на клавиша за емотикони с клавиша Enter аудио видео изображение PDF документ Приложение за Андроид + Контакт + Получи %s + Изключване на услугата на преден план + Докоснете, за да отворите Conversations + Аватарът беше публикуван! + Изпращане на %s + Предлагане на %s + Скриване на тези извън линия + Деактивиране на профила + %s пише... + %s спря да пише + Известия за писането + Позволяване на контакта Ви да вижда, когато пишете ново съобщение + Изпращане на местоположението + Показване на местоположението + Няма намерено приложение за показване на местоположението + Местоположение + Получено местоположение diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml index 84c7437b..55311aee 100644 --- a/src/main/res/values-cs/strings.xml +++ b/src/main/res/values-cs/strings.xml @@ -422,4 +422,9 @@ %s přestal(a) psát Upozornění při psaní Oznamovat kontaktům že píšete novou zprávu + Poslat pozici + Zobrazit pozici + Nebyla nalezena aplikace pro zobrazení pozice + Pozice + Přijmout pozici diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index d266a99d..2e2f4fe7 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -422,4 +422,9 @@ %s schreibt nicht mehr Tipp-Benachrichtigung Informiere deine Kontakte, wenn du eine Nachricht eintippst. + Standort senden + Standort anzeigen + Keine App für die Standort-Anzeige gefunden + Standort + Standort empfangen diff --git a/src/main/res/values-el/strings.xml b/src/main/res/values-el/strings.xml index 06ab989e..48dc4034 100644 --- a/src/main/res/values-el/strings.xml +++ b/src/main/res/values-el/strings.xml @@ -422,4 +422,9 @@ Ο χρήστης %s σταμάτησε να γράφει Ειδοποιήσεις πληκτρολόγησης Επιτρέψτε στην επαφή σας να γνωρίζει πότε γράφετε ένα νέο μήνυμα + Αποστολή τοποθεσίας + Εμφάνιση τοποθεσίας + Δεν βρέθηκε εφαρμογή για την απεικόνιση τοποθεσίας + Τοποθεσία + Ελήφθη τοποθεσία diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index 2f74fd7a..639eddfa 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -422,4 +422,9 @@ %s ha dejado de escribir Notificación de escritura Permite a tus contactos saber cuando estás escribiendo un nuevo mensaje + Enviar ubicación + Mostrar ubicación + No se ha encontrado ninguna aplicación para mostrar la ubicación + Ubicación + Ubicación recibida diff --git a/src/main/res/values-eu/strings.xml b/src/main/res/values-eu/strings.xml index 2f19afd0..a7a5b871 100644 --- a/src/main/res/values-eu/strings.xml +++ b/src/main/res/values-eu/strings.xml @@ -419,7 +419,7 @@ Lineaz kanpokoak ezkutatu Kontua ezgaitu %s idazten ari da... - %s idazteari utzi dio + %s(e)k idazteari utzi dio Idazketa jakinarazpenak Zure kontaktuak mezu berri bat noiz idazten ari zaren jakin dezan baimendu diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml index dc3ae4a6..69440362 100644 --- a/src/main/res/values-fr/strings.xml +++ b/src/main/res/values-fr/strings.xml @@ -325,7 +325,7 @@ Aucune session valide d\'OTR n\'a été trouvée! Conversations Garder le service au premier-plan - Evite que le système ferme votre connexion + Évite que le système ferme votre connexion Choix d\'un fichier Réception %1$s (%2$d%% complété) Télecharger %s @@ -400,11 +400,31 @@ 8 heures Jusqu\'à nouvel ordre Options de saisie + Entrée permet d\'envoyer + Utiliser la touche Entrée pour envoyer un message + Afficher la touche Entrée + Remplacer le bouton Émoticônes par un bouton Entrée audio video image document PDF + Application Android Contact %s reçu + Cesser de garder le service au premier plan + Cliquez pour ouvrir Conversations + L\'avatar a été envoyé ! + Envoi de %s + Proposition pour %s + Cacher hors-ligne Désactiver le compte + %s écrit un message... + %s a arrêté d\'écrire + Notifications d\'écriture + Permettre à votre contact de savoir que vous écrivez un message + Envoyer la position + Afficher la position + Aucune application trouvée pour afficher la position + Position + Position reçue diff --git a/src/main/res/values-nl/strings.xml b/src/main/res/values-nl/strings.xml index ccb14613..7d6f31e5 100644 --- a/src/main/res/values-nl/strings.xml +++ b/src/main/res/values-nl/strings.xml @@ -422,4 +422,9 @@ %s is gestopt met typen Type-meldingen Laat je contacten weten wanneer je een nieuw bericht aan het schrijven bent + Locatie versturen + Locatie weergeven + Geen applicatie gevonden om locatie weer te geven + Locatie + Locatie ontvangen diff --git a/src/main/res/values-sr/strings.xml b/src/main/res/values-sr/strings.xml index aef34aef..479889b7 100644 --- a/src/main/res/values-sr/strings.xml +++ b/src/main/res/values-sr/strings.xml @@ -418,4 +418,13 @@ Нудим %s Сакриј неповезане Онемогући налог + %s куца... + %s престаде да куца + Обавештења о куцању + Обзнаните контакту кад куцате нову поруку + Пошаљи локацију + Прикажи локацију + Нема апликације за приказ локације + Локација + Примљена локација diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml index f894bdc7..03485920 100644 --- a/src/main/res/values-sv/strings.xml +++ b/src/main/res/values-sv/strings.xml @@ -247,7 +247,7 @@ Nästa Nuvarande session upprättad Ytterligare information - skippa + Hoppa över Inaktivera notifieringar Inaktivera notifieringar för denna konversation Notifieringar är inaktiverade @@ -264,7 +264,7 @@ Krypteringsinställningar Tvinga kryptering Sänd alltid krypterade meddelanden (utom för konferenser) - Spara in krypterade meddelanden + Spara inte krypterade meddelanden Varning: Detta kan leda till att meddelanden förloras Expertinställningar Var försiktig med dem @@ -411,15 +411,20 @@ Android App Kontakt Tagit emot %s - Deaktivera fögrundstjänst + Deaktivera förgrundstjänst Tryck för att öppna Conversations Avatarbild har publicerats! Skickar %s Erbjuder %s Dölj ej anslutna Deaktivera konton - %s är att skriva... + %s skriver... %s har slutat skriva Skriv-notifieringar - Låter dina kontakter veta när du är att skriva ett nytt meddelande + Låter dina kontakter veta när du skriver ett nytt meddelande + Skicka position + Visa position + Kunde inte hitta applikation för att visa position + Position + Mottog position -- 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(-) 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 ++++++-- src/main/res/menu/select_multiple.xml | 9 +++ src/main/res/values/strings.xml | 4 + 4 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 src/main/res/menu/select_multiple.xml 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() { diff --git a/src/main/res/menu/select_multiple.xml b/src/main/res/menu/select_multiple.xml new file mode 100644 index 00000000..4240849f --- /dev/null +++ b/src/main/res/menu/select_multiple.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 8ebe58ca..af56c014 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -454,4 +454,8 @@ No application found to display location Location Received location + + Select %d contact + Select %d contacts + -- 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(-) 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 0d6475d0d930b637ccdabac78fc9acd159d6ef5c Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 19 Mar 2015 19:32:24 +0100 Subject: pulled more translations --- src/main/res/values-eu/strings.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/res/values-eu/strings.xml b/src/main/res/values-eu/strings.xml index a7a5b871..4d81c1bf 100644 --- a/src/main/res/values-eu/strings.xml +++ b/src/main/res/values-eu/strings.xml @@ -422,4 +422,9 @@ %s(e)k idazteari utzi dio Idazketa jakinarazpenak Zure kontaktuak mezu berri bat noiz idazten ari zaren jakin dezan baimendu + Kokapena partekatu + Kokapena erakutsi + Kokapena erakutsi dezakeen aplikaziorik ez da aurkitu + Kokapena + Kokapena jaso da -- 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(-) 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 5793fb680f1d318b6f5fdb3962ab1c884a9259ce Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Thu, 19 Mar 2015 19:40:42 +0100 Subject: version bump to 1.2.0-beta --- CHANGELOG.md | 4 +++- build.gradle | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77a49e47..dc62ffde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,9 @@ ###Changelog ####Version 1.2.0 -* Send current location (requires plugin) +* Send current location (requires [plugin]https://play.google.com/store/apps/details?id=eu.siacs.conversations.sharelocation()) +* Invite multiple contacts at once +* performance improvements * bug fixes ####Version 1.1.0 diff --git a/build.gradle b/build.gradle index 2c23aad6..7feadf23 100644 --- a/build.gradle +++ b/build.gradle @@ -43,8 +43,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 53 - versionName "1.1.0" + versionCode 54 + versionName "1.2.0-beta" } compileOptions { -- cgit v1.2.3 From 30e2dee456081a7355e411762ef8aa6a19c8f113 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 Mar 2015 19:45:47 +0100 Subject: Update CHANGELOG.md fixed plugin link --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc62ffde..28bf2765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ###Changelog ####Version 1.2.0 -* Send current location (requires [plugin]https://play.google.com/store/apps/details?id=eu.siacs.conversations.sharelocation()) +* Send current location. (requires [plugin](https://play.google.com/store/apps/details?id=eu.siacs.conversations.sharelocation)) * Invite multiple contacts at once * performance improvements * bug fixes -- 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(-) 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(-) 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(-) 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 From ad8f1902d1c43ce84ee4c1b2ecd6590aa959879c Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 22 Mar 2015 18:56:28 +0100 Subject: pulled translations --- src/main/res/values-bg/strings.xml | 4 ++++ src/main/res/values-cs/strings.xml | 5 +++++ src/main/res/values-de/strings.xml | 4 ++++ src/main/res/values-nl/strings.xml | 4 ++++ src/main/res/values-sv/strings.xml | 4 ++++ 5 files changed, 21 insertions(+) diff --git a/src/main/res/values-bg/strings.xml b/src/main/res/values-bg/strings.xml index 3715e820..2f89f3ae 100644 --- a/src/main/res/values-bg/strings.xml +++ b/src/main/res/values-bg/strings.xml @@ -427,4 +427,8 @@ Няма намерено приложение за показване на местоположението Местоположение Получено местоположение + + Изберете %d контакт + Изберете %d контакта + diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml index 55311aee..0c08fa7a 100644 --- a/src/main/res/values-cs/strings.xml +++ b/src/main/res/values-cs/strings.xml @@ -427,4 +427,9 @@ Nebyla nalezena aplikace pro zobrazení pozice Pozice Přijmout pozici + + Vybrat %d kontakt + Vybrat %d kontakty + Vybrat %d kontaktů + diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index 2e2f4fe7..0dd9f401 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -427,4 +427,8 @@ Keine App für die Standort-Anzeige gefunden Standort Standort empfangen + + %d Kontakt ausgewählt + %d Kontakte ausgewählt + diff --git a/src/main/res/values-nl/strings.xml b/src/main/res/values-nl/strings.xml index 7d6f31e5..2b8c5501 100644 --- a/src/main/res/values-nl/strings.xml +++ b/src/main/res/values-nl/strings.xml @@ -427,4 +427,8 @@ Geen applicatie gevonden om locatie weer te geven Locatie Locatie ontvangen + + Selecteer %d contact + Selecteer %d contacten + diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml index 03485920..69a66808 100644 --- a/src/main/res/values-sv/strings.xml +++ b/src/main/res/values-sv/strings.xml @@ -427,4 +427,8 @@ Kunde inte hitta applikation för att visa position Position Mottog position + + Välj %d kontakt + Välj %d kontakter + -- cgit v1.2.3 From 7eabdfd80f50634282307f45c5f99ab46181805d Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 22 Mar 2015 19:42:40 +0100 Subject: bump version code --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 7feadf23..8f7bb914 100644 --- a/build.gradle +++ b/build.gradle @@ -43,8 +43,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 54 - versionName "1.2.0-beta" + versionCode 56 + versionName "1.2.0" } compileOptions { -- cgit v1.2.3