aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--build.gradle5
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/PgpEngine.java13
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Contact.java8
-rw-r--r--src/main/java/eu/siacs/conversations/entities/MucOptions.java38
-rw-r--r--src/main/java/eu/siacs/conversations/parser/MessageParser.java1
-rw-r--r--src/main/java/eu/siacs/conversations/parser/PresenceParser.java22
-rw-r--r--src/main/java/eu/siacs/conversations/services/MessageArchiveService.java5
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java7
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java1
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java54
-rw-r--r--src/main/res/values/strings.xml5
12 files changed, 97 insertions, 64 deletions
diff --git a/.travis.yml b/.travis.yml
index 0b3dd195b..e26ccaa42 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,3 +15,5 @@ android:
- extra-google-google_play_services
licenses:
- '.+'
+script:
+ - ./gradlew assembleFreeRelease
diff --git a/build.gradle b/build.gradle
index f99ad1cfb..1f1f47d7c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -62,10 +62,11 @@ android {
minSdkVersion 14
targetSdkVersion 23
- versionCode 124
- versionName "1.10.0-beta"
+ versionCode 127
+ versionName "1.10.0"
archivesBaseName += "-$versionName"
+ applicationId "eu.siacs.conversations"
}
compileOptions {
diff --git a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java
index 624d1b139..0afcb9e10 100644
--- a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java
+++ b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java
@@ -37,25 +37,24 @@ public class PgpEngine {
this.mXmppConnectionService = service;
}
- public void decrypt(final Message message,
- final UiCallback<Message> callback) {
+ public void decrypt(final Message message, final UiCallback<Message> callback) {
Intent params = new Intent();
params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
+ final String uuid = message.getUuid();
if (message.getType() == Message.TYPE_TEXT) {
- InputStream is = new ByteArrayInputStream(message.getBody()
- .getBytes());
+ InputStream is = new ByteArrayInputStream(message.getBody().getBytes());
final OutputStream os = new ByteArrayOutputStream();
api.executeApiAsync(params, is, os, new IOpenPgpCallback() {
@Override
public void onReturn(Intent result) {
notifyPgpDecryptionService(message.getConversation().getAccount(), OpenPgpApi.ACTION_DECRYPT_VERIFY, result);
- switch (result.getIntExtra(OpenPgpApi.RESULT_CODE,
- OpenPgpApi.RESULT_CODE_ERROR)) {
+ switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
case OpenPgpApi.RESULT_CODE_SUCCESS:
try {
os.flush();
- if (message.getEncryption() == Message.ENCRYPTION_PGP) {
+ if (message.getEncryption() == Message.ENCRYPTION_PGP
+ && message.getUuid().equals(uuid)) {
message.setBody(os.toString());
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
final HttpConnectionManager manager = mXmppConnectionService.getHttpConnectionManager();
diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java
index aba9a8091..9887d3ef1 100644
--- a/src/main/java/eu/siacs/conversations/entities/Contact.java
+++ b/src/main/java/eu/siacs/conversations/entities/Contact.java
@@ -45,7 +45,7 @@ public class Contact implements ListItem, Blockable {
protected String photoUri;
protected JSONObject keys = new JSONObject();
protected JSONArray groups = new JSONArray();
- protected Presences presences = new Presences();
+ protected final Presences presences = new Presences();
protected Account account;
protected Avatar avatar;
@@ -222,10 +222,6 @@ public class Contact implements ListItem, Blockable {
return this.presences;
}
- public void setPresences(Presences pres) {
- this.presences = pres;
- }
-
public void updatePresence(final String resource, final Presence presence) {
this.presences.updatePresence(resource, presence);
}
@@ -386,11 +382,13 @@ public class Contact implements ListItem, Blockable {
this.resetOption(Options.TO);
this.setOption(Options.FROM);
this.resetOption(Options.PREEMPTIVE_GRANT);
+ this.resetOption(Options.PENDING_SUBSCRIPTION_REQUEST);
break;
case "both":
this.setOption(Options.TO);
this.setOption(Options.FROM);
this.resetOption(Options.PREEMPTIVE_GRANT);
+ this.resetOption(Options.PENDING_SUBSCRIPTION_REQUEST);
break;
case "none":
this.resetOption(Options.FROM);
diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java
index 00d7ae592..d23041416 100644
--- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java
+++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java
@@ -91,22 +91,26 @@ public class MucOptions {
}
}
- public static final int ERROR_NO_ERROR = 0;
- public static final int ERROR_NICK_IN_USE = 1;
- public static final int ERROR_UNKNOWN = 2;
- public static final int ERROR_PASSWORD_REQUIRED = 3;
- public static final int ERROR_BANNED = 4;
- public static final int ERROR_MEMBERS_ONLY = 5;
- public static final int ERROR_NO_RESPONSE = 6;
-
- public static final int KICKED_FROM_ROOM = 9;
+ public enum Error {
+ NO_RESPONSE,
+ NONE,
+ NICK_IN_USE,
+ PASSWORD_REQUIRED,
+ BANNED,
+ MEMBERS_ONLY,
+ KICKED,
+ SHUTDOWN,
+ UNKNOWN
+ }
public static final String STATUS_CODE_ROOM_CONFIG_CHANGED = "104";
public static final String STATUS_CODE_SELF_PRESENCE = "110";
public static final String STATUS_CODE_BANNED = "301";
public static final String STATUS_CODE_CHANGED_NICK = "303";
public static final String STATUS_CODE_KICKED = "307";
- public static final String STATUS_CODE_LOST_MEMBERSHIP = "321";
+ public static final String STATUS_CODE_AFFILIATION_CHANGE = "321";
+ public static final String STATUS_CODE_LOST_MEMBERSHIP = "322";
+ public static final String STATUS_CODE_SHUTDOWN = "332";
private interface OnEventListener {
void onSuccess();
@@ -245,7 +249,7 @@ public class MucOptions {
private Data form = new Data();
private Conversation conversation;
private boolean isOnline = false;
- private int error = ERROR_NO_RESPONSE;
+ private Error error = Error.NONE;
public OnRenameListener onRenameListener = null;
private User self;
private String subject = null;
@@ -282,7 +286,9 @@ public class MucOptions {
}
public boolean participating() {
- return !online() || self.getRole().ranks(Role.PARTICIPANT);
+ return !online()
+ || self.getRole().ranks(Role.PARTICIPANT)
+ || hasFeature("muc_unmoderated");
}
public boolean membersOnly() {
@@ -322,8 +328,8 @@ public class MucOptions {
return findUser(name) != null;
}
- public void setError(int error) {
- this.isOnline = isOnline && error == ERROR_NO_ERROR;
+ public void setError(Error error) {
+ this.isOnline = isOnline && error == Error.NONE;
this.error = error;
}
@@ -377,7 +383,7 @@ public class MucOptions {
return this.isOnline;
}
- public int getError() {
+ public Error getError() {
return this.error;
}
@@ -387,7 +393,7 @@ public class MucOptions {
public void setOffline() {
this.users.clear();
- this.error = ERROR_NO_RESPONSE;
+ this.error = Error.NO_RESPONSE;
this.isOnline = false;
}
diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
index f01e7ce1f..43edb2c38 100644
--- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
@@ -411,6 +411,7 @@ public class MessageParser extends AbstractParser implements
replacedMessage.markUnread();
}
mXmppConnectionService.updateMessage(replacedMessage, uuid);
+ mXmppConnectionService.getNotificationService().updateNotification(false);
if (mXmppConnectionService.confirmMessages() && remoteMsgId != null && !isForwarded && !isTypeGroupChat) {
sendMessageReceipts(account, packet);
}
diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java
index dc02eda8f..63d28c97b 100644
--- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java
@@ -63,7 +63,7 @@ public class PresenceParser extends AbstractParser implements
if (x != null) {
Element item = x.findChild("item");
if (item != null && !from.isBareJid()) {
- mucOptions.setError(MucOptions.ERROR_NO_ERROR);
+ mucOptions.setError(MucOptions.Error.NONE);
MucOptions.User user = new MucOptions.User(mucOptions,from);
user.setAffiliation(item.getAttribute("affiliation"));
user.setRole(item.getAttribute("role"));
@@ -109,13 +109,17 @@ public class PresenceParser extends AbstractParser implements
if (codes.contains(MucOptions.STATUS_CODE_CHANGED_NICK)) {
mucOptions.mNickChangingInProgress = true;
} else if (codes.contains(MucOptions.STATUS_CODE_KICKED)) {
- mucOptions.setError(MucOptions.KICKED_FROM_ROOM);
+ mucOptions.setError(MucOptions.Error.KICKED);
} else if (codes.contains(MucOptions.STATUS_CODE_BANNED)) {
- mucOptions.setError(MucOptions.ERROR_BANNED);
+ mucOptions.setError(MucOptions.Error.BANNED);
} else if (codes.contains(MucOptions.STATUS_CODE_LOST_MEMBERSHIP)) {
- mucOptions.setError(MucOptions.ERROR_MEMBERS_ONLY);
+ mucOptions.setError(MucOptions.Error.MEMBERS_ONLY);
+ } else if (codes.contains(MucOptions.STATUS_CODE_AFFILIATION_CHANGE)) {
+ mucOptions.setError(MucOptions.Error.MEMBERS_ONLY);
+ } else if (codes.contains(MucOptions.STATUS_CODE_SHUTDOWN)) {
+ mucOptions.setError(MucOptions.Error.SHUTDOWN);
} else {
- mucOptions.setError(MucOptions.ERROR_UNKNOWN);
+ mucOptions.setError(MucOptions.Error.UNKNOWN);
Log.d(Config.LOGTAG, "unknown error in conference: " + packet);
}
} else if (!from.isBareJid()){
@@ -132,14 +136,14 @@ public class PresenceParser extends AbstractParser implements
mucOptions.onRenameListener.onFailure();
}
} else {
- mucOptions.setError(MucOptions.ERROR_NICK_IN_USE);
+ mucOptions.setError(MucOptions.Error.NICK_IN_USE);
}
} else if (error != null && error.hasChild("not-authorized")) {
- mucOptions.setError(MucOptions.ERROR_PASSWORD_REQUIRED);
+ mucOptions.setError(MucOptions.Error.PASSWORD_REQUIRED);
} else if (error != null && error.hasChild("forbidden")) {
- mucOptions.setError(MucOptions.ERROR_BANNED);
+ mucOptions.setError(MucOptions.Error.BANNED);
} else if (error != null && error.hasChild("registration-required")) {
- mucOptions.setError(MucOptions.ERROR_MEMBERS_ONLY);
+ mucOptions.setError(MucOptions.Error.BANNED);
}
}
}
diff --git a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java
index 165c7c2a8..e8616bd8f 100644
--- a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java
+++ b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java
@@ -189,6 +189,10 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
}
}
+ public boolean queryInProgress(Conversation conversation) {
+ return queryInProgress(conversation, null);
+ }
+
public void processFin(Element fin, Jid from) {
if (fin == null) {
return;
@@ -223,7 +227,6 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
this.execute(nextQuery);
this.finalizeQuery(query, false);
synchronized (this.queries) {
- this.queries.remove(query);
this.queries.add(nextQuery);
}
}
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index b836e780a..ec13d6dc2 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -1772,6 +1772,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
account.pendingConferenceLeaves.remove(conversation);
if (account.getStatus() == Account.State.ONLINE) {
conversation.resetMucOptions();
+ conversation.setHasMessagesLeftOnServer(false);
fetchConferenceConfiguration(conversation, new OnConferenceConfigurationFetched() {
private void join(Conversation conversation) {
@@ -1806,7 +1807,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
conversation.setContactJid(joinJid);
databaseBackend.updateConversation(conversation);
}
- conversation.setHasMessagesLeftOnServer(false);
if (conversation.getMucOptions().mamSupport()) {
getMessageArchiveService().catchupMUC(conversation);
}
@@ -1824,9 +1824,12 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
fetchConferenceConfiguration(conversation);
}
});
-
+ updateConversationUi();
} else {
account.pendingConferenceJoins.add(conversation);
+ conversation.resetMucOptions();
+ conversation.setHasMessagesLeftOnServer(false);
+ updateConversationUi();
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
index 7d49aa114..9769295e2 100644
--- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
@@ -14,7 +14,6 @@ import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index a16f8c8df..22e0e5c3c 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -53,6 +53,7 @@ import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.Presence;
import eu.siacs.conversations.entities.Transferable;
import eu.siacs.conversations.entities.TransferablePlaceholder;
+import eu.siacs.conversations.services.MessageArchiveService;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.XmppActivity.OnPresenceSelected;
import eu.siacs.conversations.ui.XmppActivity.OnValueEdited;
@@ -808,27 +809,29 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
&& !conversation.getMucOptions().online()
&& account.getStatus() == Account.State.ONLINE) {
switch (conversation.getMucOptions().getError()) {
- case MucOptions.ERROR_NICK_IN_USE:
+ case NICK_IN_USE:
showSnackbar(R.string.nick_in_use, R.string.edit, clickToMuc);
break;
- case MucOptions.ERROR_NO_RESPONSE:
- showSnackbar(R.string.conference_not_found, R.string.leave, leaveMuc);
+ case NO_RESPONSE:
+ showSnackbar(R.string.joining_conference, 0, null);
break;
- case MucOptions.ERROR_PASSWORD_REQUIRED:
+ case PASSWORD_REQUIRED:
showSnackbar(R.string.conference_requires_password, R.string.enter_password, enterPassword);
break;
- case MucOptions.ERROR_BANNED:
+ case BANNED:
showSnackbar(R.string.conference_banned, R.string.leave, leaveMuc);
break;
- case MucOptions.ERROR_MEMBERS_ONLY:
+ case 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);
- activity.xmppConnectionService.joinMuc(conversation);
+ case KICKED:
+ showSnackbar(R.string.conference_kicked, R.string.join, joinMuc);
break;
- case MucOptions.ERROR_UNKNOWN:
- showSnackbar(R.string.conference_unknown_error, R.string.try_again, joinMuc);
+ case UNKNOWN:
+ showSnackbar(R.string.conference_unknown_error, R.string.join, joinMuc);
+ break;
+ case SHUTDOWN:
+ showSnackbar(R.string.conference_shutdown, R.string.join, joinMuc);
break;
default:
break;
@@ -1053,10 +1056,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
protected void updateStatusMessages() {
synchronized (this.messageList) {
- final XmppConnection connection = conversation.getAccount().getXmppConnection();
- if (conversation.getLastClearHistory() != 0
- && connection != null
- && connection.getFeatures().mam()) {
+ if (showLoadMoreMessages(conversation)) {
this.messageList.add(0, Message.createLoadMoreMessage(conversation));
}
if (conversation.getMode() == Conversation.MODE_SINGLE) {
@@ -1082,14 +1082,30 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
}
- protected void showSnackbar(final int message, final int action,
- final OnClickListener clickListener) {
+ private boolean showLoadMoreMessages(final Conversation c) {
+ final boolean mam = hasMamSupport(c);
+ final MessageArchiveService service = activity.xmppConnectionService.getMessageArchiveService();
+ return mam && (c.getLastClearHistory() != 0 || (c.countMessages() == 0 && c.hasMessagesLeftOnServer() && !service.queryInProgress(c)));
+ }
+
+ private boolean hasMamSupport(final Conversation c) {
+ if (c.getMode() == Conversation.MODE_SINGLE) {
+ final XmppConnection connection = c.getAccount().getXmppConnection();
+ return connection != null && connection.getFeatures().mam();
+ } else {
+ return c.getMucOptions().mamSupport();
+ }
+ }
+
+ protected void showSnackbar(final int message, final int action, final OnClickListener clickListener) {
snackbar.setVisibility(View.VISIBLE);
snackbar.setOnClickListener(null);
snackbarMessage.setText(message);
snackbarMessage.setOnClickListener(null);
- snackbarAction.setVisibility(View.VISIBLE);
- snackbarAction.setText(action);
+ snackbarAction.setVisibility(clickListener == null ? View.GONE : View.VISIBLE);
+ if (action != 0) {
+ snackbarAction.setText(action);
+ }
snackbarAction.setOnClickListener(clickListener);
}
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 982c3ab84..f97e59bd3 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -241,8 +241,7 @@
<string name="bookmark_already_exists">This bookmark already exists</string>
<string name="you">You</string>
<string name="action_edit_subject">Edit conference subject</string>
- <string name="conference_not_found">Conference not found</string>
- <string name="conference_unknown_error">Unknown error received</string>2
+ <string name="joining_conference">Joining conferenceā€¦</string>
<string name="leave">Leave</string>
<string name="contact_added_you">Contact added you to contact list</string>
<string name="add_back">Add back</string>
@@ -341,6 +340,8 @@
<string name="conference_banned">You are banned from this conference</string>
<string name="conference_members_only">This conference is members only</string>
<string name="conference_kicked">You have been kicked from this conference</string>
+ <string name="conference_shutdown">The conference was shut down</string>
+ <string name="conference_unknown_error">You are no longer in this conference</string>
<string name="using_account">using account %s</string>
<string name="checking_x">Checking %s on HTTP host</string>
<string name="not_connected_try_again">You are not connected. Try again later</string>