aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/eu/siacs/conversations/entities/MucOptions.java5
-rw-r--r--src/main/java/eu/siacs/conversations/generator/MessageGenerator.java20
-rw-r--r--src/main/java/eu/siacs/conversations/parser/MessageParser.java6
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/FileBackend.java50
-rw-r--r--src/main/java/eu/siacs/conversations/services/ExportLogsService.java208
-rw-r--r--src/main/java/eu/siacs/conversations/services/MessageArchiveService.java12
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java98
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java13
-rw-r--r--src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java7
9 files changed, 254 insertions, 165 deletions
diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java
index cf078ee52..dc0701645 100644
--- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java
+++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java
@@ -247,6 +247,11 @@ public class MucOptions {
return hasFeature("muc_membersonly");
}
+ public boolean mamSupport() {
+ // Update with "urn:xmpp:mam:1" once we support it
+ return hasFeature("urn:xmpp:mam:0");
+ }
+
public boolean nonanonymous() {
return hasFeature("muc_nonanonymous");
}
diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
index 11aa96068..5ae41a0fd 100644
--- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
+++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java
@@ -68,6 +68,15 @@ public class MessageGenerator extends AbstractGenerator {
return packet;
}
+ public static void addXhtmlImImage(MessagePacket packet, Message.FileParams params) {
+ Element html = packet.addChild("html","http://jabber.org/protocol/xhtml-im");
+ Element body = html.addChild("body","http://www.w3.org/1999/xhtml");
+ Element img = body.addChild("img");
+ img.setAttribute("src",params.url.toString());
+ img.setAttribute("height",params.height);
+ img.setAttribute("width",params.width);
+ }
+
public static void addMessageHints(MessagePacket packet) {
packet.addChild("private", "urn:xmpp:carbons:2");
packet.addChild("no-copy", "urn:xmpp:hints");
@@ -98,11 +107,18 @@ public class MessageGenerator extends AbstractGenerator {
public MessagePacket generateChat(Message message) {
MessagePacket packet = preparePacket(message);
+ String content;
if (message.hasFileOnRemoteHost()) {
- packet.setBody(message.getFileParams().url.toString());
+ Message.FileParams fileParams = message.getFileParams();
+ content = fileParams.url.toString();
+ if (fileParams.width > 0 && fileParams.height > 0) {
+ addXhtmlImImage(packet,fileParams);
+ }
+ packet.addChild("x","jabber:x:oob").addChild("url").setContent(fileParams.url.toString());
} else {
- packet.setBody(message.getBody());
+ content = message.getBody();
}
+ packet.setBody(content);
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 ec900de4d..4d0577566 100644
--- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
@@ -40,6 +40,10 @@ public class MessageParser extends AbstractParser implements
Jid from = packet.getFrom();
if (from.toBareJid().equals(account.getJid().toBareJid())) {
conversation.setOutgoingChatState(state);
+ if (state == ChatState.ACTIVE || state == ChatState.COMPOSING) {
+ mXmppConnectionService.markRead(conversation);
+ account.activateGracePeriod();
+ }
return false;
} else {
return conversation.setIncomingChatState(state);
@@ -300,7 +304,7 @@ public class MessageParser extends AbstractParser implements
return;
}
- if (extractChatState(mXmppConnectionService.find(account, from), packet)) {
+ if (extractChatState(mXmppConnectionService.find(account, counterpart.toBareJid()), packet)) {
mXmppConnectionService.updateConversationUi();
}
diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
index 66682ee2d..edbcd26ee 100644
--- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
@@ -58,33 +58,23 @@ public class FileBackend {
}
public DownloadableFile getFile(Message message, boolean decrypted) {
- String path = message.getRelativeFilePath();
- String extension;
- if (path != null && !path.isEmpty()) {
- String[] parts = path.split("\\.");
- extension = "."+parts[parts.length - 1];
- } else {
- if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_TEXT) {
- extension = ".jpg";
- } else {
- extension = "";
- }
- path = message.getUuid()+extension;
- }
final boolean encrypted = !decrypted
&& (message.getEncryption() == Message.ENCRYPTION_PGP
|| message.getEncryption() == Message.ENCRYPTION_DECRYPTED);
if (encrypted) {
- return new DownloadableFile(getConversationsFileDirectory()+message.getUuid()+extension+".pgp");
+ return new DownloadableFile(getConversationsFileDirectory()+message.getUuid()+".pgp");
} else {
- if (path.startsWith("/")) {
+ String path = message.getRelativeFilePath();
+ if (path == null) {
+ path = message.getUuid();
+ } else if (path.startsWith("/")) {
return new DownloadableFile(path);
+ }
+ String mime = message.getMimeType();
+ if (mime != null && mime.startsWith("image")) {
+ return new DownloadableFile(getConversationsImageDirectory() + path);
} else {
- if (Arrays.asList(Transferable.VALID_IMAGE_EXTENSIONS).contains(extension)) {
- return new DownloadableFile(getConversationsFileDirectory() + path);
- } else {
- return new DownloadableFile(getConversationsImageDirectory() + path);
- }
+ return new DownloadableFile(getConversationsFileDirectory() + path);
}
}
}
@@ -112,7 +102,11 @@ public class FileBackend {
scalledW = size;
scalledH = (int) (h / ((double) w / size));
}
- return Bitmap.createScaledBitmap(originalBitmap, scalledW, scalledH, true);
+ Bitmap result = Bitmap.createScaledBitmap(originalBitmap, scalledW, scalledH, true);
+ if (originalBitmap != null && !originalBitmap.isRecycled()) {
+ originalBitmap.recycle();
+ }
+ return result;
} else {
return originalBitmap;
}
@@ -123,7 +117,11 @@ public class FileBackend {
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
mtx.postRotate(degree);
- return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
+ Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
+ if (bitmap != null && !bitmap.isRecycled()) {
+ bitmap.recycle();
+ }
+ return result;
}
public boolean useImageAsIs(Uri uri) {
@@ -227,7 +225,6 @@ public class FileBackend {
if (rotation > 0) {
scaledBitmap = rotate(scaledBitmap, rotation);
}
-
boolean success = scaledBitmap.compress(Config.IMAGE_FORMAT, Config.IMAGE_QUALITY, os);
if (!success) {
throw new FileCopyException(R.string.error_compressing_image);
@@ -288,7 +285,6 @@ public class FileBackend {
throw new FileNotFoundException();
}
thumbnail = resize(fullsize, size);
- fullsize.recycle();
int rotation = getRotation(file);
if (rotation > 0) {
thumbnail = rotate(thumbnail, rotation);
@@ -447,6 +443,9 @@ public class FileBackend {
Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(dest);
canvas.drawBitmap(source, null, targetRect, null);
+ if (source != null && !source.isRecycled()) {
+ source.recycle();
+ }
return dest;
} catch (FileNotFoundException e) {
return null;
@@ -470,6 +469,9 @@ public class FileBackend {
Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
canvas.drawBitmap(input, null, target, null);
+ if (input != null && !input.isRecycled()) {
+ input.recycle();
+ }
return output;
}
diff --git a/src/main/java/eu/siacs/conversations/services/ExportLogsService.java b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java
index 8501c04ad..76983a905 100644
--- a/src/main/java/eu/siacs/conversations/services/ExportLogsService.java
+++ b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java
@@ -4,18 +4,8 @@ import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
-import android.os.Build;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
-
-import eu.siacs.conversations.R;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.Conversation;
-import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.persistance.DatabaseBackend;
-import eu.siacs.conversations.persistance.FileBackend;
-import eu.siacs.conversations.xmpp.jid.Jid;
-
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
@@ -25,6 +15,14 @@ import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.persistance.DatabaseBackend;
+import eu.siacs.conversations.persistance.FileBackend;
+import eu.siacs.conversations.xmpp.jid.Jid;
+
public class ExportLogsService extends Service {
private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
@@ -32,107 +30,113 @@ public class ExportLogsService extends Service {
private static final String MESSAGE_STRING_FORMAT = "(%s) %s: %s\n";
private static final int NOTIFICATION_ID = 1;
private static AtomicBoolean running = new AtomicBoolean(false);
+ private DatabaseBackend mDatabaseBackend;
+ private List<Account> mAccounts;
+
+ @Override
+ public void onCreate() {
+ mDatabaseBackend = DatabaseBackend.getInstance(getBaseContext());
+ mAccounts = mDatabaseBackend.getAccounts();
+ }
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (running.compareAndSet(false, true)) {
- new Thread(
- new Runnable() {
- DatabaseBackend databaseBackend = DatabaseBackend.getInstance(getBaseContext());
- List<Account> accounts = databaseBackend.getAccounts();
-
- @Override
- public void run() {
- List<Conversation> conversations = databaseBackend.getConversations(Conversation.STATUS_AVAILABLE);
- conversations.addAll(databaseBackend.getConversations(Conversation.STATUS_ARCHIVED));
-
- NotificationManager mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext());
- mBuilder.setContentTitle(getString(R.string.notification_export_logs_title))
- .setSmallIcon(R.drawable.ic_import_export_white_24dp)
- .setProgress(conversations.size(), 0, false);
- startForeground(NOTIFICATION_ID, mBuilder.build());
-
- int progress = 0;
- for (Conversation conversation : conversations) {
- writeToFile(conversation);
- progress++;
- mBuilder.setProgress(conversations.size(), progress, false);
- mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
- }
-
- running.set(false);
- stopForeground(true);
- }
-
- private void writeToFile(Conversation conversation) {
- Jid accountJid = resolveAccountUuid(conversation.getAccountUuid());
- Jid contactJid = conversation.getJid();
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ running.set(false);
+ export();
+ stopForeground(true);
+ stopSelf();
+ }
+ }).start();
+ }
+ return START_NOT_STICKY;
+ }
- File dir = new File(String.format(DIRECTORY_STRING_FORMAT,
- accountJid.toBareJid().toString()));
- dir.mkdirs();
+ private void export() {
+ List<Conversation> conversations = mDatabaseBackend.getConversations(Conversation.STATUS_AVAILABLE);
+ conversations.addAll(mDatabaseBackend.getConversations(Conversation.STATUS_ARCHIVED));
+ NotificationManager mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext());
+ mBuilder.setContentTitle(getString(R.string.notification_export_logs_title))
+ .setSmallIcon(R.drawable.ic_import_export_white_24dp)
+ .setProgress(conversations.size(), 0, false);
+ startForeground(NOTIFICATION_ID, mBuilder.build());
+
+ int progress = 0;
+ for (Conversation conversation : conversations) {
+ writeToFile(conversation);
+ progress++;
+ mBuilder.setProgress(conversations.size(), progress, false);
+ mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
+ }
+ }
- BufferedWriter bw = null;
- try {
- for (Message message : databaseBackend.getMessagesIterable(conversation)) {
- if (message.getType() == Message.TYPE_TEXT || message.hasFileOnRemoteHost()) {
- String date = simpleDateFormat.format(new Date(message.getTimeSent()));
- if (bw == null) {
- bw = new BufferedWriter(new FileWriter(
- new File(dir, contactJid.toBareJid().toString() + ".txt")));
- }
- String jid = null;
- switch (message.getStatus()) {
- case Message.STATUS_RECEIVED:
- jid = getMessageCounterpart(message);
- break;
- case Message.STATUS_SEND:
- case Message.STATUS_SEND_RECEIVED:
- case Message.STATUS_SEND_DISPLAYED:
- jid = accountJid.toBareJid().toString();
- break;
- }
- if (jid != null) {
- String body = message.hasFileOnRemoteHost() ? message.getFileParams().url.toString() : message.getBody();
- bw.write(String.format(MESSAGE_STRING_FORMAT, date, jid,
- body.replace("\\\n", "\\ \n").replace("\n", "\\ \n")));
- }
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if (bw != null) {
- bw.close();
- }
- } catch (IOException e1) {
- e1.printStackTrace();
- }
- }
- }
+ private void writeToFile(Conversation conversation) {
+ Jid accountJid = resolveAccountUuid(conversation.getAccountUuid());
+ Jid contactJid = conversation.getJid();
+
+ File dir = new File(String.format(DIRECTORY_STRING_FORMAT,accountJid.toBareJid().toString()));
+ dir.mkdirs();
+
+ BufferedWriter bw = null;
+ try {
+ for (Message message : mDatabaseBackend.getMessagesIterable(conversation)) {
+ if (message.getType() == Message.TYPE_TEXT || message.hasFileOnRemoteHost()) {
+ String date = simpleDateFormat.format(new Date(message.getTimeSent()));
+ if (bw == null) {
+ bw = new BufferedWriter(new FileWriter(
+ new File(dir, contactJid.toBareJid().toString() + ".txt")));
+ }
+ String jid = null;
+ switch (message.getStatus()) {
+ case Message.STATUS_RECEIVED:
+ jid = getMessageCounterpart(message);
+ break;
+ case Message.STATUS_SEND:
+ case Message.STATUS_SEND_RECEIVED:
+ case Message.STATUS_SEND_DISPLAYED:
+ jid = accountJid.toBareJid().toString();
+ break;
+ }
+ if (jid != null) {
+ String body = message.hasFileOnRemoteHost() ? message.getFileParams().url.toString() : message.getBody();
+ bw.write(String.format(MESSAGE_STRING_FORMAT, date, jid,
+ body.replace("\\\n", "\\ \n").replace("\n", "\\ \n")));
+ }
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (bw != null) {
+ bw.close();
+ }
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
- private Jid resolveAccountUuid(String accountUuid) {
- for (Account account : accounts) {
- if (account.getUuid().equals(accountUuid)) {
- return account.getJid();
- }
- }
- return null;
- }
+ private Jid resolveAccountUuid(String accountUuid) {
+ for (Account account : mAccounts) {
+ if (account.getUuid().equals(accountUuid)) {
+ return account.getJid();
+ }
+ }
+ return null;
+ }
- private String getMessageCounterpart(Message message) {
- String trueCounterpart = (String) message.getContentValues().get(Message.TRUE_COUNTERPART);
- if (trueCounterpart != null) {
- return trueCounterpart;
- } else {
- return message.getCounterpart().toString();
- }
- }
- }).start();
+ private String getMessageCounterpart(Message message) {
+ String trueCounterpart = (String) message.getContentValues().get(Message.TRUE_COUNTERPART);
+ if (trueCounterpart != null) {
+ return trueCounterpart;
+ } else {
+ return message.getCounterpart().toString();
}
- return START_STICKY;
}
@Override
diff --git a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java
index 351ded0b8..ae81cc17f 100644
--- a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java
+++ b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java
@@ -54,6 +54,18 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
this.execute(query);
}
+ public void catchupMUC(final Conversation conversation) {
+ if (conversation.getLastMessageTransmitted() < 0 && conversation.countMessages() == 0) {
+ query(conversation,
+ 0,
+ System.currentTimeMillis());
+ } else {
+ query(conversation,
+ conversation.getLastMessageTransmitted(),
+ System.currentTimeMillis());
+ }
+ }
+
private long getLastMessageTransmitted(final Account account) {
long timestamp = 0;
for(final Conversation conversation : mXmppConnectionService.getConversations()) {
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index 2f00083f8..8326766e5 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -1064,10 +1064,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
public void loadMoreMessages(final Conversation conversation, final long timestamp, final OnMoreMessagesLoaded callback) {
- Log.d(Config.LOGTAG, "load more messages for " + conversation.getName() + " prior to " + MessageGenerator.getTimestamp(timestamp));
if (XmppConnectionService.this.getMessageArchiveService().queryInProgress(conversation,callback)) {
return;
}
+ Log.d(Config.LOGTAG, "load more messages for " + conversation.getName() + " prior to " + MessageGenerator.getTimestamp(timestamp));
Runnable runnable = new Runnable() {
@Override
public void run() {
@@ -1078,13 +1078,15 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
checkDeletedFiles(conversation);
callback.onMoreMessagesLoaded(messages.size(), conversation);
} else if (conversation.hasMessagesLeftOnServer()
- && account.isOnlineAndConnected()
- && account.getXmppConnection().getFeatures().mam()) {
- MessageArchiveService.Query query = getMessageArchiveService().query(conversation,0,timestamp - 1);
- if (query != null) {
- query.setCallback(callback);
+ && account.isOnlineAndConnected()) {
+ if ((conversation.getMode() == Conversation.MODE_SINGLE && account.getXmppConnection().getFeatures().mam())
+ || (conversation.getMode() == Conversation.MODE_MULTI && conversation.getMucOptions().mamSupport())) {
+ MessageArchiveService.Query query = getMessageArchiveService().query(conversation,0,timestamp - 1);
+ if (query != null) {
+ query.setCallback(callback);
+ }
+ callback.informUser(R.string.fetching_history_from_server);
}
- callback.informUser(R.string.fetching_history_from_server);
}
}
};
@@ -1478,7 +1480,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
public void joinMuc(Conversation conversation) {
- joinMuc(conversation,false);
+ joinMuc(conversation, false);
}
private void joinMuc(Conversation conversation, boolean now) {
@@ -1487,32 +1489,49 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
account.pendingConferenceLeaves.remove(conversation);
if (account.getStatus() == Account.State.ONLINE || now) {
conversation.resetMucOptions();
- final String nick = conversation.getMucOptions().getProposedNick();
- final Jid joinJid = conversation.getMucOptions().createJoinJid(nick);
- if (joinJid == null) {
- return; //safety net
- }
- Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": joining conversation " + joinJid.toString());
- PresencePacket packet = new PresencePacket();
- packet.setFrom(conversation.getAccount().getJid());
- packet.setTo(joinJid);
- Element x = packet.addChild("x", "http://jabber.org/protocol/muc");
- if (conversation.getMucOptions().getPassword() != null) {
- x.addChild("password").setContent(conversation.getMucOptions().getPassword());
- }
- x.addChild("history").setAttribute("since", PresenceGenerator.getTimestamp(conversation.getLastMessageTransmitted()));
- String sig = account.getPgpSignature();
- if (sig != null) {
- packet.addChild("status").setContent("online");
- packet.addChild("x", "jabber:x:signed").setContent(sig);
- }
- sendPresencePacket(account, packet);
- fetchConferenceConfiguration(conversation);
- if (!joinJid.equals(conversation.getJid())) {
- conversation.setContactJid(joinJid);
- databaseBackend.updateConversation(conversation);
- }
- conversation.setHasMessagesLeftOnServer(false);
+ fetchConferenceConfiguration(conversation, new OnConferenceConfigurationFetched() {
+ @Override
+ public void onConferenceConfigurationFetched(Conversation conversation) {
+ Account account = conversation.getAccount();
+ final String nick = conversation.getMucOptions().getProposedNick();
+ final Jid joinJid = conversation.getMucOptions().createJoinJid(nick);
+ if (joinJid == null) {
+ return; //safety net
+ }
+ Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": joining conversation " + joinJid.toString());
+ PresencePacket packet = new PresencePacket();
+ packet.setFrom(conversation.getAccount().getJid());
+ packet.setTo(joinJid);
+ Element x = packet.addChild("x", "http://jabber.org/protocol/muc");
+ if (conversation.getMucOptions().getPassword() != null) {
+ x.addChild("password").setContent(conversation.getMucOptions().getPassword());
+ }
+
+ if (conversation.getMucOptions().mamSupport()) {
+ // Use MAM instead of the limited muc history to get history
+ x.addChild("history").setAttribute("maxchars", "0");
+ } else {
+ // Fallback to muc history
+ x.addChild("history").setAttribute("since", PresenceGenerator.getTimestamp(conversation.getLastMessageTransmitted()));
+ }
+ String sig = account.getPgpSignature();
+ if (sig != null) {
+ packet.addChild("status").setContent("online");
+ packet.addChild("x", "jabber:x:signed").setContent(sig);
+ }
+ sendPresencePacket(account, packet);
+ fetchConferenceConfiguration(conversation);
+ if (!joinJid.equals(conversation.getJid())) {
+ conversation.setContactJid(joinJid);
+ databaseBackend.updateConversation(conversation);
+ }
+ conversation.setHasMessagesLeftOnServer(false);
+ if (conversation.getMucOptions().mamSupport()) {
+ getMessageArchiveService().catchupMUC(conversation);
+ }
+ }
+ });
+
} else {
account.pendingConferenceJoins.add(conversation);
}
@@ -1672,6 +1691,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
public void fetchConferenceConfiguration(final Conversation conversation) {
+ fetchConferenceConfiguration(conversation, null);
+ }
+
+ public void fetchConferenceConfiguration(final Conversation conversation, final OnConferenceConfigurationFetched callback) {
IqPacket request = new IqPacket(IqPacket.TYPE.GET);
request.setTo(conversation.getJid().toBareJid());
request.query("http://jabber.org/protocol/disco#info");
@@ -1689,6 +1712,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
}
conversation.getMucOptions().updateFeatures(features);
+ if (callback != null) {
+ callback.onConferenceConfigurationFetched(conversation);
+ }
updateConversationUi();
}
}
@@ -2629,6 +2655,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public void onMucRosterUpdate();
}
+ public interface OnConferenceConfigurationFetched {
+ public void onConferenceConfigurationFetched(Conversation conversation);
+ }
+
public interface OnConferenceOptionsPushed {
public void onPushSucceeded();
diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
index 95c39d25c..0dfeea985 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
@@ -19,6 +19,7 @@ import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -61,6 +62,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
private LinearLayout membersView;
private LinearLayout mMoreDetails;
private TextView mConferenceType;
+ private TableLayout mConferenceInfoTable;
+ private TextView mConferenceInfoMam;
private ImageButton mChangeConferenceSettingsButton;
private Button mInviteButton;
private String uuid = null;
@@ -194,7 +197,6 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
mMoreDetails.setVisibility(View.GONE);
mChangeConferenceSettingsButton = (ImageButton) findViewById(R.id.change_conference_button);
mChangeConferenceSettingsButton.setOnClickListener(this.mChangeConferenceSettings);
- mConferenceType = (TextView) findViewById(R.id.muc_conference_type);
mInviteButton = (Button) findViewById(R.id.invite);
mInviteButton.setOnClickListener(inviteListener);
mConferenceType = (TextView) findViewById(R.id.muc_conference_type);
@@ -217,6 +219,9 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
}
});
this.mAdvancedMode = getPreferences().getBoolean("advanced_muc_mode", false);
+ this.mConferenceInfoTable = (TableLayout) findViewById(R.id.muc_info_more);
+ mConferenceInfoTable.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE);
+ this.mConferenceInfoMam = (TextView) findViewById(R.id.muc_info_mam);
}
@Override
@@ -240,6 +245,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
this.mAdvancedMode = !menuItem.isChecked();
menuItem.setChecked(this.mAdvancedMode);
getPreferences().edit().putBoolean("advanced_muc_mode", mAdvancedMode).commit();
+ mConferenceInfoTable.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE);
invalidateOptionsMenu();
updateView();
break;
@@ -473,6 +479,11 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
} else {
mConferenceType.setText(R.string.public_conference);
}
+ if (mucOptions.mamSupport()) {
+ mConferenceInfoMam.setText(R.string.server_info_available);
+ } else {
+ mConferenceInfoMam.setText(R.string.server_info_unavailable);
+ }
if (self.getAffiliation().ranks(MucOptions.Affiliation.OWNER)) {
mChangeConferenceSettingsButton.setVisibility(View.VISIBLE);
} else {
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 3bcbda439..99af14cd8 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
@@ -276,7 +276,12 @@ public class MessageAdapter extends ArrayAdapter<Message> {
viewHolder.messageBody.setIncludeFontPadding(true);
if (message.getBody() != null) {
final String nick = UIHelper.getMessageDisplayName(message);
- final String body = message.getMergedBody().replaceAll("^" + Message.ME_COMMAND,nick + " ");
+ String body;
+ try {
+ body = message.getMergedBody().replaceAll("^" + Message.ME_COMMAND, nick + " ");
+ } catch (ArrayIndexOutOfBoundsException e) {
+ body = message.getMergedBody();
+ }
final SpannableString formattedBody = new SpannableString(body);
int i = body.indexOf(Message.MERGE_SEPARATOR);
while(i >= 0) {