diff options
Diffstat (limited to 'src/main/java/eu/siacs/conversations/services')
6 files changed, 441 insertions, 446 deletions
diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java index 276be10d..93eb0889 100644 --- a/src/main/java/eu/siacs/conversations/services/AvatarService.java +++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java @@ -8,9 +8,20 @@ import android.graphics.Typeface; import android.net.Uri; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Locale; +import de.thedevstack.android.logcat.Logging; +import de.thedevstack.conversationsplus.ConversationsPlusApplication; +import de.thedevstack.conversationsplus.utils.AvatarUtil; +import de.thedevstack.conversationsplus.utils.ImageUtil; +import de.thedevstack.conversationsplus.utils.UiUpdateHelper; +import de.thedevstack.conversationsplus.utils.XmppSendUtil; +import de.thedevstack.conversationsplus.xmpp.avatar.AvatarPacketGenerator; +import de.thedevstack.conversationsplus.xmpp.avatar.AvatarPacketParser; +import eu.siacs.conversations.Config; +import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Bookmark; import eu.siacs.conversations.entities.Contact; @@ -18,7 +29,14 @@ import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.ListItem; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; +import eu.siacs.conversations.generator.IqGenerator; +import eu.siacs.conversations.persistance.DatabaseBackend; +import eu.siacs.conversations.ui.UiCallback; import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.OnIqPacketReceived; +import eu.siacs.conversations.xmpp.pep.Avatar; +import eu.siacs.conversations.xmpp.stanzas.IqPacket; public class AvatarService { @@ -30,31 +48,31 @@ public class AvatarService { private static final String PREFIX_CONVERSATION = "conversation"; private static final String PREFIX_ACCOUNT = "account"; private static final String PREFIX_GENERIC = "generic"; + private static final AvatarService INSTANCE = new AvatarService(); - final private ArrayList<Integer> sizes = new ArrayList<>(); - - protected XmppConnectionService mXmppConnectionService = null; - - public AvatarService(XmppConnectionService service) { - this.mXmppConnectionService = service; - } + final private ArrayList<Integer> sizes = new ArrayList<>(); + private final List<String> mInProgressAvatarFetches = new ArrayList<>(); + + public static AvatarService getInstance() { + return INSTANCE; + } private Bitmap get(final Contact contact, final int size, boolean cachedOnly) { final String KEY = key(contact, size); - Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY); + Bitmap avatar = ImageUtil.getBitmapFromCache(KEY); if (avatar != null || cachedOnly) { return avatar; } if (contact.getProfilePhoto() != null) { - avatar = mXmppConnectionService.getFileBackend().cropCenterSquare(Uri.parse(contact.getProfilePhoto()), size); + avatar = ImageUtil.cropCenterSquare(Uri.parse(contact.getProfilePhoto()), size); } if (avatar == null && contact.getAvatar() != null) { - avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatar(), size); + avatar = AvatarUtil.getAvatar(contact.getAvatar(), size); } if (avatar == null) { avatar = get(contact.getDisplayName(), size, cachedOnly); } - this.mXmppConnectionService.getBitmapCache().put(KEY, avatar); + ImageUtil.addBitmapToCache(KEY, avatar); return avatar; } @@ -69,12 +87,12 @@ public class AvatarService { private Bitmap getImpl(final MucOptions.User user, final int size, boolean cachedOnly) { final String KEY = key(user, size); - Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY); + Bitmap avatar = ImageUtil.getBitmapFromCache(KEY); if (avatar != null || cachedOnly) { return avatar; } if (user.getAvatar() != null) { - avatar = mXmppConnectionService.getFileBackend().getAvatar(user.getAvatar(), size); + avatar = AvatarUtil.getAvatar(user.getAvatar(), size); } if (avatar == null) { Contact contact = user.getContact(); @@ -84,15 +102,14 @@ public class AvatarService { avatar = get(user.getName(), size, cachedOnly); } } - this.mXmppConnectionService.getBitmapCache().put(KEY, avatar); + ImageUtil.addBitmapToCache(KEY, avatar); return avatar; } public void clear(Contact contact) { synchronized (this.sizes) { for (Integer size : sizes) { - this.mXmppConnectionService.getBitmapCache().remove( - key(contact, size)); + ImageUtil.removeBitmapFromCache(key(contact, size)); } } } @@ -158,7 +175,7 @@ public class AvatarService { private Bitmap get(MucOptions mucOptions, int size, boolean cachedOnly) { final String KEY = key(mucOptions, size); - Bitmap bitmap = this.mXmppConnectionService.getBitmapCache().get(KEY); + Bitmap bitmap = ImageUtil.getBitmapFromCache(KEY); if (bitmap != null || cachedOnly) { return bitmap; } @@ -195,14 +212,14 @@ public class AvatarService { drawTile(canvas, "\u2026", PLACEHOLDER_COLOR, size / 2 + 1, size / 2 + 1, size, size); } - this.mXmppConnectionService.getBitmapCache().put(KEY, bitmap); + ImageUtil.addBitmapToCache(KEY, bitmap); return bitmap; } public void clear(MucOptions options) { synchronized (this.sizes) { for (Integer size : sizes) { - this.mXmppConnectionService.getBitmapCache().remove(key(options, size)); + ImageUtil.removeBitmapFromCache(key(options, size)); } } } @@ -223,16 +240,15 @@ public class AvatarService { public Bitmap get(Account account, int size, boolean cachedOnly) { final String KEY = key(account, size); - Bitmap avatar = mXmppConnectionService.getBitmapCache().get(KEY); + Bitmap avatar = ImageUtil.getBitmapFromCache(KEY); if (avatar != null || cachedOnly) { return avatar; } - avatar = mXmppConnectionService.getFileBackend().getAvatar( - account.getAvatar(), size); + avatar = AvatarUtil.getAvatar(account.getAvatar(), size); if (avatar == null) { avatar = get(account.getJid().toBareJid().toString(), size,false); } - mXmppConnectionService.getBitmapCache().put(KEY, avatar); + ImageUtil.addBitmapToCache(KEY, avatar); return avatar; } @@ -257,7 +273,7 @@ public class AvatarService { public void clear(Account account) { synchronized (this.sizes) { for (Integer size : sizes) { - this.mXmppConnectionService.getBitmapCache().remove(key(account, size)); + ImageUtil.removeBitmapFromCache(key(account, size)); } } } @@ -265,7 +281,7 @@ public class AvatarService { public void clear(MucOptions.User user) { synchronized (this.sizes) { for (Integer size : sizes) { - this.mXmppConnectionService.getBitmapCache().remove(key(user, size)); + ImageUtil.removeBitmapFromCache(key(user, size)); } } } @@ -286,7 +302,7 @@ public class AvatarService { public Bitmap get(final String name, final int size, boolean cachedOnly) { final String KEY = key(name, size); - Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY); + Bitmap bitmap = ImageUtil.getBitmapFromCache(KEY); if (bitmap != null || cachedOnly) { return bitmap; } @@ -294,7 +310,7 @@ public class AvatarService { Canvas canvas = new Canvas(bitmap); final String trimmedName = name.trim(); drawTile(canvas, trimmedName, 0, 0, size, size); - mXmppConnectionService.getBitmapCache().put(KEY, bitmap); + ImageUtil.addBitmapToCache(KEY, bitmap); return bitmap; } @@ -335,14 +351,13 @@ public class AvatarService { if (contact.getProfilePhoto() != null) { uri = Uri.parse(contact.getProfilePhoto()); } else if (contact.getAvatar() != null) { - uri = mXmppConnectionService.getFileBackend().getAvatarUri( - contact.getAvatar()); + uri = AvatarUtil.getAvatarUri(contact.getAvatar()); } if (drawTile(canvas, uri, left, top, right, bottom)) { return true; } } else if (user.getAvatar() != null) { - Uri uri = mXmppConnectionService.getFileBackend().getAvatarUri(user.getAvatar()); + Uri uri = AvatarUtil.getAvatarUri(user.getAvatar()); if (drawTile(canvas, uri, left, top, right, bottom)) { return true; } @@ -355,7 +370,7 @@ public class AvatarService { private boolean drawTile(Canvas canvas, Account account, int left, int top, int right, int bottom) { String avatar = account.getAvatar(); if (avatar != null) { - Uri uri = mXmppConnectionService.getFileBackend().getAvatarUri(avatar); + Uri uri = AvatarUtil.getAvatarUri(avatar); if (uri != null) { if (drawTile(canvas, uri, left, top, right, bottom)) { return true; @@ -377,8 +392,7 @@ public class AvatarService { private boolean drawTile(Canvas canvas, Uri uri, int left, int top, int right, int bottom) { if (uri != null) { - Bitmap bitmap = mXmppConnectionService.getFileBackend() - .cropCenter(uri, bottom - top, right - left); + Bitmap bitmap = ImageUtil.cropCenter(uri, bottom - top, right - left); if (bitmap != null) { drawTile(canvas, bitmap, left, top, right, bottom); return true; @@ -393,4 +407,221 @@ public class AvatarService { canvas.drawBitmap(bm, null, dst, null); return true; } + + public void publishAvatar(final Account account, + final Uri image, + final UiCallback<Avatar> callback) { + final Bitmap.CompressFormat format = Config.AVATAR_FORMAT; + final int size = Config.AVATAR_SIZE; + final Avatar avatar = AvatarUtil.getPepAvatar(image, size, format); + if (avatar != null) { + avatar.height = size; + avatar.width = size; + if (format.equals(Bitmap.CompressFormat.WEBP)) { + avatar.type = "image/webp"; + } else if (format.equals(Bitmap.CompressFormat.JPEG)) { + avatar.type = "image/jpeg"; + } else if (format.equals(Bitmap.CompressFormat.PNG)) { + avatar.type = "image/png"; + } + if (!AvatarUtil.save(avatar)) { + callback.error(R.string.error_saving_avatar, avatar); + return; + } + final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarPacket(avatar); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + @Override + public void onIqPacketReceived(Account account, IqPacket result) { + if (result.getType() == IqPacket.TYPE.RESULT) { + final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarMetadataPacket(avatar); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + @Override + public void onIqPacketReceived(Account account, + IqPacket result) { + if (result.getType() == IqPacket.TYPE.RESULT) { + if (account.setAvatar(avatar.getFilename())) { + AvatarService.getInstance().clear(account); + DatabaseBackend.getInstance(ConversationsPlusApplication.getAppContext()).updateAccount(account); + } + callback.success(avatar); + } else { + callback.error( + R.string.error_publish_avatar_server_reject, + avatar); + } + } + }); + } else { + callback.error( + R.string.error_publish_avatar_server_reject, + avatar); + } + } + }); + } else { + callback.error(R.string.error_publish_avatar_converting, null); + } + } + + private static String generateFetchKey(Account account, final Avatar avatar) { + return account.getJid().toBareJid()+"_"+avatar.owner+"_"+avatar.sha1sum; + } + + public void fetchAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) { + final String KEY = generateFetchKey(account, avatar); + synchronized(this.mInProgressAvatarFetches) { + if (this.mInProgressAvatarFetches.contains(KEY)) { + return; + } else { + switch (avatar.origin) { + case PEP: + this.mInProgressAvatarFetches.add(KEY); + fetchAvatarPep(account, avatar, callback); + break; + case VCARD: + this.mInProgressAvatarFetches.add(KEY); + fetchAvatarVcard(account, avatar, callback); + break; + } + } + } + } + + private void fetchAvatarPep(final Account account, final Avatar avatar, final UiCallback<Avatar> callback) { + IqPacket packet = AvatarPacketGenerator.generateRetrieveAvatarPacket(avatar); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + @Override + public void onIqPacketReceived(Account account, IqPacket result) { + synchronized (mInProgressAvatarFetches) { + mInProgressAvatarFetches.remove(generateFetchKey(account, avatar)); + } + final String ERROR = account.getJid().toBareJid() + + ": fetching avatar for " + avatar.owner + " failed "; + if (result.getType() == IqPacket.TYPE.RESULT) { + avatar.image = AvatarPacketParser.parseAvatarData(result); + if (avatar.image != null) { + if (AvatarUtil.save(avatar)) { + if (account.getJid().toBareJid().equals(avatar.owner)) { + if (account.setAvatar(avatar.getFilename())) { + DatabaseBackend.getInstance(ConversationsPlusApplication.getAppContext()).updateAccount(account); + } + AvatarService.this.clear(account); + UiUpdateHelper.updateConversationUi(); + UiUpdateHelper.updateAccountUi(); + } else { + Contact contact = account.getRoster() + .getContact(avatar.owner); + contact.setAvatar(avatar); + AvatarService.this.clear(contact); + UiUpdateHelper.updateConversationUi(); + UiUpdateHelper.updateRosterUi(); + } + if (callback != null) { + callback.success(avatar); + } + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + + ": succesfuly fetched pep avatar for " + avatar.owner); + return; + } + } else { + + Logging.d(Config.LOGTAG, ERROR + "(parsing error)"); + } + } else { + Element error = result.findChild("error"); + if (error == null) { + Logging.d(Config.LOGTAG, ERROR + "(server error)"); + } else { + Logging.d(Config.LOGTAG, ERROR + error.toString()); + } + } + if (callback != null) { + callback.error(0, null); + } + + } + }); + } + + private void fetchAvatarVcard(final Account account, final Avatar avatar, final UiCallback<Avatar> callback) { + IqPacket packet = IqGenerator.retrieveVcardAvatar(avatar); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + synchronized (mInProgressAvatarFetches) { + mInProgressAvatarFetches.remove(generateFetchKey(account, avatar)); + } + if (packet.getType() == IqPacket.TYPE.RESULT) { + Element vCard = packet.findChild("vCard", "vcard-temp"); + Element photo = vCard != null ? vCard.findChild("PHOTO") : null; + String image = photo != null ? photo.findChildContent("BINVAL") : null; + if (image != null) { + avatar.image = image; + if (AvatarUtil.save(avatar)) { + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + + ": successfully fetched vCard avatar for " + avatar.owner); + Contact contact = account.getRoster() + .getContact(avatar.owner); + contact.setAvatar(avatar); + AvatarService.this.clear(contact); + UiUpdateHelper.updateConversationUi(); + UiUpdateHelper.updateRosterUi(); + } + } + } + } + }); + } + + public void checkForAvatar(Account account, final UiCallback<Avatar> callback) { + IqPacket packet = AvatarPacketGenerator.generateRetrieveAvatarMetadataPacket(null); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + if (packet.getType() == IqPacket.TYPE.RESULT) { + Element pubsub = packet.findChild("pubsub", + "http://jabber.org/protocol/pubsub"); + if (pubsub != null) { + Element items = pubsub.findChild("items"); + if (items != null) { + Avatar avatar = Avatar.parseMetadata(items); + if (avatar != null) { + avatar.owner = account.getJid().toBareJid(); + if (AvatarUtil.isAvatarCached(avatar)) { + if (account.setAvatar(avatar.getFilename())) { + DatabaseBackend.getInstance(ConversationsPlusApplication.getAppContext()).updateAccount(account); + } + AvatarService.this.clear(account); + callback.success(avatar); + } else { + fetchAvatarPep(account, avatar, callback); + } + return; + } + } + } + } + callback.error(0, null); + } + }); + } + + public void fetchAvatar(Account account, Avatar avatar) { + fetchAvatar(account, avatar, null); + } + + public void clearFetchInProgress(Account account) { + synchronized (this.mInProgressAvatarFetches) { + for(Iterator<String> iterator = this.mInProgressAvatarFetches.iterator(); iterator.hasNext();) { + final String KEY = iterator.next(); + if (KEY.startsWith(account.getJid().toBareJid()+"_")) { + iterator.remove(); + } + } + } + } } diff --git a/src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java b/src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java index c2a45bf2..52894f07 100644 --- a/src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java +++ b/src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java @@ -1,7 +1,6 @@ package eu.siacs.conversations.services; import android.annotation.TargetApi; -import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -11,11 +10,8 @@ import android.graphics.drawable.Icon; import android.os.Build; import android.os.Bundle; import android.os.IBinder; -import android.os.SystemClock; import android.service.chooser.ChooserTarget; import android.service.chooser.ChooserTargetService; -import android.util.DisplayMetrics; -import android.util.Log; import java.util.ArrayList; import java.util.List; @@ -51,7 +47,7 @@ public class ContactChooserTargetService extends ChooserTargetService implements for(int i = 0; i < Math.min(conversations.size(),MAX_TARGETS); ++i) { final Conversation conversation = conversations.get(i); final String name = conversation.getName(); - final Icon icon = Icon.createWithBitmap(mXmppConnectionService.getAvatarService().get(conversation, pixel)); + final Icon icon = Icon.createWithBitmap(AvatarService.getInstance().get(conversation, pixel)); final float score = (1.0f / MAX_TARGETS) * i; final Bundle extras = new Bundle(); extras.putString("uuid", conversation.getUuid()); diff --git a/src/main/java/eu/siacs/conversations/services/ExportLogsService.java b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java index 76983a90..01cc09c3 100644 --- a/src/main/java/eu/siacs/conversations/services/ExportLogsService.java +++ b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java @@ -6,6 +6,7 @@ import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.support.v4.app.NotificationCompat; + import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; diff --git a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java index 59a37fe5..0ca62b97 100644 --- a/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java +++ b/src/main/java/eu/siacs/conversations/services/MessageArchiveService.java @@ -1,6 +1,5 @@ package eu.siacs.conversations.services; -import android.util.Log; import android.util.Pair; import java.math.BigInteger; @@ -9,6 +8,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import de.thedevstack.android.logcat.Logging; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; @@ -30,7 +30,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { public enum PagingOrder { NORMAL, REVERSE - } + }; public MessageArchiveService(final XmppConnectionService service) { this.mXmppConnectionService = service; @@ -128,7 +128,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { private void execute(final Query query) { final Account account= query.getAccount(); if (account.getStatus() == Account.State.ONLINE) { - Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": running mam query " + query.toString()); + Logging.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": running mam query " + query.toString()); IqPacket packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(query); this.mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() { @Override @@ -141,7 +141,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } } } else if (packet.getType() != IqPacket.TYPE.RESULT) { - Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": error executing mam: " + packet.toString()); + Logging.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": error executing mam: " + packet.toString()); finalizeQuery(query, true); } } @@ -171,6 +171,9 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { if (query.hasCallback()) { query.callback(done); } else { + if (null != conversation) { + conversation.setHasMessagesLeftOnServer(query.getMessageCount() > 0); + } this.mXmppConnectionService.updateConversationUi(); } } @@ -213,7 +216,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { if (complete || relevant == null || abort) { final boolean done = (complete || query.getMessageCount() == 0) && query.getStart() == 0; this.finalizeQuery(query, done); - Log.d(Config.LOGTAG,query.getAccount().getJid().toBareJid()+": finished mam after "+query.getTotalCount()+" messages. messages left="+Boolean.toString(!done)); + Logging.d(Config.LOGTAG,query.getAccount().getJid().toBareJid()+": finished mam after "+query.getTotalCount()+" messages. messages left="+Boolean.toString(!done)); if (query.getWith() == null && query.getMessageCount() > 0) { mXmppConnectionService.getNotificationService().finishBacklog(true); } diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index cec9a3ef..3969b9b1 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -5,7 +5,6 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; @@ -26,9 +25,12 @@ import java.util.Calendar; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import de.thedevstack.conversationsplus.ConversationsPlusApplication; +import de.thedevstack.conversationsplus.ConversationsPlusPreferences; +import de.thedevstack.conversationsplus.utils.ImageUtil; +import de.thedevstack.conversationsplus.utils.MessageUtil; +import de.tzur.conversations.Settings; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; @@ -36,7 +38,6 @@ import eu.siacs.conversations.entities.Conversation; 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; @@ -60,10 +61,13 @@ public class NotificationService { public boolean notify(final Message message) { return (message.getStatus() == Message.STATUS_RECEIVED) - && notificationsEnabled() - && !message.getConversation().isMuted() - && (message.getConversation().alwaysNotify() || wasHighlightedOrPrivate(message) - ); + && !message.isRead() + && ConversationsPlusPreferences.showNotification() + && !message.getConversation().isMuted() + && (message.getConversation().getMode() == Conversation.MODE_SINGLE + || ConversationsPlusPreferences.alwaysNotifyInConference() + || wasHighlightedOrPrivate(message) + ); } public void notifyPebble(final Message message) { @@ -77,7 +81,7 @@ public class NotificationService { final String notificationData = new JSONArray().put(jsonData).toString(); i.putExtra("messageType", "PEBBLE_ALERT"); - i.putExtra("sender", "Conversations"); /* XXX: Shouldn't be hardcoded, e.g., AbstractGenerator.APP_NAME); */ + i.putExtra("sender", ConversationsPlusApplication.getName()); i.putExtra("notificationData", notificationData); // notify Pebble App i.setPackage("com.getpebble.android"); @@ -93,11 +97,11 @@ public class NotificationService { } public boolean isQuietHours() { - if (!mXmppConnectionService.getPreferences().getBoolean("enable_quiet_hours", false)) { + if (!ConversationsPlusPreferences.enableQuietHours()) { return false; } - final long startTime = mXmppConnectionService.getPreferences().getLong("quiet_hours_start", TimePreference.DEFAULT_VALUE) % Config.MILLISECONDS_IN_DAY; - final long endTime = mXmppConnectionService.getPreferences().getLong("quiet_hours_end", TimePreference.DEFAULT_VALUE) % Config.MILLISECONDS_IN_DAY; + final long startTime = ConversationsPlusPreferences.quietHoursStart() % Config.MILLISECONDS_IN_DAY; + final long endTime = ConversationsPlusPreferences.quietHoursEnd() % Config.MILLISECONDS_IN_DAY; final long nowTime = Calendar.getInstance().getTimeInMillis() % Config.MILLISECONDS_IN_DAY; if (endTime < startTime) { @@ -134,10 +138,10 @@ public class NotificationService { } public void push(final Message message) { - mXmppConnectionService.updateUnreadCountBadge(); if (!notify(message)) { return; } + mXmppConnectionService.updateUnreadCountBadge(); final boolean isScreenOn = mXmppConnectionService.isInteractive(); if (this.mIsInForeground && isScreenOn && this.mOpenConversation == message.getConversation()) { return; @@ -174,12 +178,10 @@ public class NotificationService { } public void updateNotification(final boolean notify) { - final NotificationManager notificationManager = (NotificationManager) mXmppConnectionService - .getSystemService(Context.NOTIFICATION_SERVICE); - final SharedPreferences preferences = mXmppConnectionService.getPreferences(); + final NotificationManager notificationManager = (NotificationManager) ConversationsPlusApplication.getAppContext().getSystemService(Context.NOTIFICATION_SERVICE); - final String ringtone = preferences.getString("notification_ringtone", null); - final boolean vibrate = preferences.getBoolean("vibrate_on_notification", true); + final String ringtone = ConversationsPlusPreferences.notificationRingtone(); + final boolean vibrate = ConversationsPlusPreferences.vibrateOnNotification(); if (notifications.size() == 0) { notificationManager.cancel(NOTIFICATION_ID); @@ -210,7 +212,7 @@ public class NotificationService { mBuilder.setDefaults(0); mBuilder.setSmallIcon(R.drawable.ic_notification); mBuilder.setDeleteIntent(createDeleteIntent()); - mBuilder.setLights(0xff00FF00, 2000, 3000); + mBuilder.setLights(Settings.LED_COLOR, 2000, 4000); final Notification notification = mBuilder.build(); notificationManager.notify(NOTIFICATION_ID, notification); } @@ -262,8 +264,7 @@ public class NotificationService { final ArrayList<Message> messages = notifications.values().iterator().next(); if (messages.size() >= 1) { final Conversation conversation = messages.get(0).getConversation(); - mBuilder.setLargeIcon(mXmppConnectionService.getAvatarService() - .get(conversation, getPixel(64))); + mBuilder.setLargeIcon(AvatarService.getInstance().get(conversation, getPixel(64))); mBuilder.setContentTitle(conversation.getName()); if (Config.HIDE_MESSAGE_TEXT_IN_NOTIFICATION) { int count = messages.size(); @@ -300,8 +301,7 @@ public class NotificationService { private void modifyForImage(final Builder builder, final Message message, final ArrayList<Message> messages, final boolean notify) { try { - final Bitmap bitmap = mXmppConnectionService.getFileBackend() - .getThumbnail(message, getPixel(288), false); + final Bitmap bitmap = ImageUtil.getThumbnail(message, getPixel(288), false); final ArrayList<Message> tmp = new ArrayList<>(); for (final Message msg : messages) { if (msg.getType() == Message.TYPE_TEXT @@ -361,7 +361,7 @@ public class NotificationService { && message.getEncryption() != Message.ENCRYPTION_PGP && message.getFileParams().height > 0) { return message; - } + } } return null; } @@ -467,23 +467,7 @@ public class NotificationService { } private boolean wasHighlightedOrPrivate(final Message message) { - final String nick = message.getConversation().getMucOptions().getActualNick(); - final Pattern highlight = generateNickHighlightPattern(nick); - if (message.getBody() == null || nick == null) { - return false; - } - final Matcher m = highlight.matcher(message.getBody()); - return (m.find() || message.getType() == Message.TYPE_PRIVATE); - } - - private static Pattern generateNickHighlightPattern(final String nick) { - // We expect a word boundary, i.e. space or start of string, followed by - // the - // nick (matched in case-insensitive manner), followed by optional - // punctuation (for example "bob: i disagree" or "how are you alice?"), - // followed by another word boundary. - return Pattern.compile("\\b" + Pattern.quote(nick) + "\\p{Punct}?\\b", - Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + return MessageUtil.wasHighlightedOrPrivate(message); } public void setOpenConversation(final Conversation conversation) { diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index b836e780..9da9ffb2 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -59,6 +59,15 @@ import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import de.duenndns.ssl.MemorizingTrustManager; +import de.thedevstack.android.logcat.Logging; +import de.thedevstack.conversationsplus.ConversationsPlusApplication; +import de.thedevstack.conversationsplus.ConversationsPlusPreferences; +import de.thedevstack.conversationsplus.exceptions.FileCopyException; +import de.thedevstack.conversationsplus.utils.FileHelper; +import de.thedevstack.conversationsplus.utils.ImageUtil; +import de.thedevstack.conversationsplus.utils.MessageUtil; +import de.thedevstack.conversationsplus.utils.UiUpdateHelper; +import de.tzur.conversations.Settings; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.PgpEngine; @@ -73,6 +82,7 @@ import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.MucOptions.OnRenameListener; import eu.siacs.conversations.entities.Presence; +import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.entities.Roster; import eu.siacs.conversations.entities.ServiceDiscoveryResult; import eu.siacs.conversations.entities.Transferable; @@ -128,11 +138,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts"; public static final String ACTION_GCM_TOKEN_REFRESH = "gcm_token_refresh"; public static final String ACTION_GCM_MESSAGE_RECEIVED = "gcm_message_received"; - private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor(); - private final SerialSingleThreadExecutor mDatabaseExecutor = new SerialSingleThreadExecutor(); private final IBinder mBinder = new XmppConnectionBinder(); private final List<Conversation> conversations = new CopyOnWriteArrayList<>(); - private final IqGenerator mIqGenerator = new IqGenerator(this); + private final IqGenerator mIqGenerator = new IqGenerator(); private final List<String> mInProgressAvatarFetches = new ArrayList<>(); public DatabaseBackend databaseBackend; private ContentObserver contactObserver = new ContentObserver(null) { @@ -145,7 +153,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa startService(intent); } }; - private FileBackend fileBackend = new FileBackend(this); private MemorizingTrustManager mMemorizingTrustManager; private NotificationService mNotificationService = new NotificationService( this); @@ -159,13 +166,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa Element error = packet.findChild("error"); String text = error != null ? error.findChildContent("text") : null; if (text != null) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": received iq error - " + text); + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + ": received iq error - " + text); } } } }; - private MessageGenerator mMessageGenerator = new MessageGenerator(this); - private PresenceGenerator mPresenceGenerator = new PresenceGenerator(this); + private MessageGenerator mMessageGenerator = new MessageGenerator(); + private PresenceGenerator mPresenceGenerator = new PresenceGenerator(); private List<Account> accounts; private JingleConnectionManager mJingleConnectionManager = new JingleConnectionManager( this); @@ -197,7 +204,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa }; private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager( this); - private AvatarService mAvatarService = new AvatarService(this); private MessageArchiveService mMessageArchiveService = new MessageArchiveService(this); private PushManagementService mPushManagementService = new PushManagementService(this); private OnConversationUpdate mOnConversationUpdate = null; @@ -278,10 +284,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (account.getStatus() == Account.State.ONLINE) { if (connection != null && connection.getFeatures().csi()) { if (checkListeners()) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + " sending csi//inactive"); + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + " sending csi//inactive"); connection.sendInactive(); } else { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + " sending csi//active"); + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + " sending csi//active"); connection.sendActive(); } } @@ -290,7 +296,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (conversation.getAccount() == account && !account.pendingConferenceJoins.contains(conversation)) { if (!conversation.startOtrIfNeeded()) { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": couldn't start OTR with "+conversation.getContact().getJid()+" when needed"); + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": couldn't start OTR with "+conversation.getContact().getJid()+" when needed"); } sendUnsentMessages(conversation); } @@ -310,7 +316,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa final boolean pushMode = Config.CLOSE_TCP_WHEN_SWITCHING_TO_BACKGROUND && mPushManagementService.available(account) && checkListeners(); - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": push mode "+Boolean.toString(pushMode)); + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": push mode "+Boolean.toString(pushMode)); if (!disabled && !pushMode) { int timeToReconnect = mRandom.nextInt(20) + 10; scheduleWakeUpCall(timeToReconnect, account.getUuid().hashCode()); @@ -322,7 +328,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa && (account.getStatus() != Account.State.NO_INTERNET)) { if (connection != null) { int next = connection.getTimeToNextAttempt(); - Log.d(Config.LOGTAG, account.getJid().toBareJid() + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + ": error connecting account. try again in " + next + "s for the " + (connection.getAttempt() + 1) + " time"); @@ -342,10 +348,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa private boolean mRestoredFromDatabase = false; - private static String generateFetchKey(Account account, final Avatar avatar) { - return account.getJid().toBareJid() + "_" + avatar.owner + "_" + avatar.sha1sum; - } - public boolean areMessagesInitialized() { return this.mRestoredFromDatabase; } @@ -361,15 +363,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } else { return null; } - - } - - public FileBackend getFileBackend() { - return this.fileBackend; - } - - public AvatarService getAvatarService() { - return this.mAvatarService; } public void attachLocationToConversation(final Conversation conversation, @@ -401,69 +394,35 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } message.setCounterpart(conversation.getNextCounterpart()); message.setType(Message.TYPE_FILE); - String path = getFileBackend().getOriginalPath(uri); + String path = FileHelper.getRealPathFromUri(uri); if (path != null) { message.setRelativeFilePath(path); - getFileBackend().updateFileParams(message); + MessageUtil.updateFileParams(message); if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { getPgpEngine().encrypt(message, callback); } else { callback.success(message); } } else { - mFileAddingExecutor.execute(new Runnable() { - @Override - public void run() { - try { - getFileBackend().copyFileToPrivateStorage(message, uri); - getFileBackend().updateFileParams(message); - if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { - getPgpEngine().encrypt(message, callback); - } else { - callback.success(message); - } - } catch (FileBackend.FileCopyException e) { - callback.error(e.getResId(), message); - } - } - }); + ConversationsPlusApplication.executeFileAdding(new Runnable() { + @Override + public void run() { + try { + FileBackend.copyFileToPrivateStorage(message, uri); + MessageUtil.updateFileParams(message); + if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { + getPgpEngine().encrypt(message, callback); + } else { + callback.success(message); + } + } catch (FileCopyException e) { + callback.error(e.getResId(), message); + } + } + }); } } - public void attachImageToConversation(final Conversation conversation, final Uri uri, final UiCallback<Message> callback) { - final String compressPictures = getCompressPicturesPreference(); - if ("never".equals(compressPictures) - || ("auto".equals(compressPictures) && getFileBackend().useImageAsIs(uri))) { - Log.d(Config.LOGTAG,conversation.getAccount().getJid().toBareJid()+ ": not compressing picture. sending as file"); - attachFileToConversation(conversation, uri, callback); - return; - } - final Message message; - if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) { - message = new Message(conversation, "", Message.ENCRYPTION_DECRYPTED); - } else { - message = new Message(conversation, "", conversation.getNextEncryption()); - } - message.setCounterpart(conversation.getNextCounterpart()); - message.setType(Message.TYPE_IMAGE); - mFileAddingExecutor.execute(new Runnable() { - - @Override - public void run() { - try { - getFileBackend().copyImageToPrivateStorage(message, uri); - if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) { - getPgpEngine().encrypt(message, callback); - } else { - callback.success(message); - } - } catch (final FileBackend.FileCopyException e) { - callback.error(e.getResId(), message); - } - } - }); - } - public Conversation find(Bookmark bookmark) { return find(bookmark.getAccount(), bookmark.getJid()); } @@ -495,7 +454,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa mNotificationService.clear(); break; case ACTION_DISABLE_FOREGROUND: - getPreferences().edit().putBoolean("keep_foreground_service", false).commit(); + ConversationsPlusPreferences.commitKeepForegroundService(false); toggleForegroundService(); break; case ACTION_TRY_AGAIN: @@ -556,7 +515,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa long pingTimeoutIn = (lastSent + Config.PING_TIMEOUT * 1000) - SystemClock.elapsedRealtime(); if (lastSent > lastReceived) { if (pingTimeoutIn < 0) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": ping timeout"); + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + ": ping timeout"); this.reconnectAccount(account, true, interactive); } else { int secs = (int) (pingTimeoutIn / 1000); @@ -564,7 +523,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } else if (msToNextPing <= 0) { account.getXmppConnection().sendPing(); - Log.d(Config.LOGTAG, account.getJid().toBareJid() + " send ping"); + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + " send ping"); this.scheduleWakeUpCall(Config.PING_TIMEOUT, account.getUuid().hashCode()); } else { this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode()); @@ -577,7 +536,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa long discoTimeout = Config.CONNECT_DISCO_TIMEOUT - secondsSinceLastDisco; long timeout = Config.CONNECT_TIMEOUT - secondsSinceLastConnect; if (timeout < 0) { - Log.d(Config.LOGTAG, account.getJid() + ": time out during connect reconnecting"); + Logging.d(Config.LOGTAG, account.getJid() + ": time out during connect reconnecting"); reconnectAccount(account, true, interactive); } else if (discoTimeout < 0) { account.getXmppConnection().sendDiscoTimeout(); @@ -590,6 +549,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa reconnectAccount(account, true, interactive); } } + } if (mOnAccountUpdate != null) { mOnAccountUpdate.onAccountUpdate(); @@ -613,10 +573,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return getPreferences().getBoolean("away_when_screen_off", false); } - private String getCompressPicturesPreference() { - return getPreferences().getString("picture_compression", "auto"); - } - private Presence.Status getTargetPresence() { if (xaOnSilentMode() && isPhoneSilenced()) { return Presence.Status.XA; @@ -647,7 +603,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } private void resetAllAttemptCounts(boolean reallyAll) { - Log.d(Config.LOGTAG, "resetting all attepmt counts"); + Logging.d(Config.LOGTAG, "resetting all attepmt counts"); for (Account account : accounts) { if (account.hasErrorStatus() || reallyAll) { final XmppConnection connection = account.getXmppConnection(); @@ -665,6 +621,25 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return activeNetwork != null && activeNetwork.isConnected(); } + /** + * check whether we are allowed to download at the moment + */ + public boolean isDownloadAllowedInConnection() { + if (ConversationsPlusPreferences.autoDownloadFileWLAN()) { + return isWifiConnected(); + } + return true; + } + + /** + * check whether wifi is connected + */ + public boolean isWifiConnected() { + ConnectivityManager cm = (ConnectivityManager) ConversationsPlusApplication.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo niWifi = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI); + return niWifi.isConnected(); + } + @SuppressLint("TrulyRandom") @Override public void onCreate() { @@ -708,6 +683,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "XmppConnectionService"); toggleForegroundService(); updateUnreadCountBadge(); + UiUpdateHelper.initXmppConnectionService(this); toggleScreenEventReceiver(); } @@ -745,7 +721,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void toggleForegroundService() { - if (getPreferences().getBoolean("keep_foreground_service", false)) { + if (ConversationsPlusPreferences.keepForegroundService()) { startForeground(NotificationService.FOREGROUND_NOTIFICATION_ID, this.mNotificationService.createForegroundNotification()); } else { stopForeground(true); @@ -755,7 +731,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onTaskRemoved(final Intent rootIntent) { super.onTaskRemoved(rootIntent); - if (!getPreferences().getBoolean("keep_foreground_service", false)) { + if (!ConversationsPlusPreferences.keepForegroundService()) { this.logoutAndSave(); } } @@ -773,7 +749,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa cancelWakeUpCall(account.getUuid().hashCode()); } } - Log.d(Config.LOGTAG, "good bye"); + Logging.d(Config.LOGTAG, "good bye"); stopSelf(); } @@ -797,9 +773,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public XmppConnection createConnection(final Account account) { - final SharedPreferences sharedPref = getPreferences(); - account.setResource(sharedPref.getString("resource", "mobile") - .toLowerCase(Locale.getDefault())); + account.setResource(ConversationsPlusPreferences.resource().toLowerCase(Locale.getDefault())); final XmppConnection connection = new XmppConnection(account, this); connection.setOnMessagePacketReceivedListener(this.mMessageParser); connection.setOnStatusChangedListener(this.statusListener); @@ -817,14 +791,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void sendChatState(Conversation conversation) { - if (sendChatStates()) { + if (ConversationsPlusPreferences.chatStates()) { MessagePacket packet = mMessageGenerator.generateChatState(conversation); sendMessagePacket(conversation.getAccount(), packet); } } private void sendFileMessage(final Message message, final boolean delay) { - Log.d(Config.LOGTAG, "send file message"); + Logging.d(Config.LOGTAG, "send file message"); final Account account = message.getConversation().getAccount(); final XmppConnection connection = account.getXmppConnection(); if (connection != null && connection.getFeatures().httpUpload()) { @@ -902,11 +876,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (message.fixCounterpart()) { conversation.startOtrSession(message.getCounterpart().getResourcepart(), true); } else { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not fix counterpart for OTR message to contact "+message.getContact().getJid()); + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": could not fix counterpart for OTR message to contact "+message.getContact().getJid()); break; } } else { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+" OTR session with "+message.getContact()+" is in wrong state: "+otrSession.getSessionStatus().toString()); + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+" OTR session with "+message.getContact()+" is in wrong state: "+otrSession.getSessionStatus().toString()); } break; case Message.ENCRYPTION_AXOLOTL: @@ -951,7 +925,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa break; case Message.ENCRYPTION_OTR: if (!conversation.hasValidOtrSession() && message.getCounterpart() != null) { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": create otr session without starting for "+message.getContact().getJid()); + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": create otr session without starting for "+message.getContact().getJid()); conversation.startOtrSession(message.getCounterpart().getResourcepart(), false); } break; @@ -987,7 +961,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa mMessageGenerator.addDelay(packet, message.getTimeSent()); } if (conversation.setOutgoingChatState(Config.DEFAULT_CHATSTATE)) { - if (this.sendChatStates()) { + if (ConversationsPlusPreferences.chatStates()) { packet.addChild(ChatState.toElement(conversation.getOutgoingChatState())); } } @@ -1012,10 +986,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void fetchRosterFromServer(final Account account) { final IqPacket iqPacket = new IqPacket(IqPacket.TYPE.GET); if (!"".equals(account.getRosterVersion())) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + ": fetching roster version " + account.getRosterVersion()); } else { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": fetching roster"); + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + ": fetching roster"); } iqPacket.query(Xmlns.ROSTER).setAttribute("ver", account.getRosterVersion()); sendIqPacket(account, iqPacket, mIqParser); @@ -1056,7 +1030,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } account.setBookmarks(new ArrayList<>(bookmarks.values())); } else { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not fetch bookmarks"); + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not fetch bookmarks"); } } }; @@ -1064,7 +1038,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void pushBookmarks(Account account) { - Log.d(Config.LOGTAG, account.getJid().toBareJid()+": pushing bookmarks"); + Logging.d(Config.LOGTAG, account.getJid().toBareJid()+": pushing bookmarks"); IqPacket iqPacket = new IqPacket(IqPacket.TYPE.SET); Element query = iqPacket.query("jabber:iq:private"); Element storage = query.addChild("storage", "storage:bookmarks"); @@ -1081,12 +1055,12 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa mPhoneContactMergerThread = new Thread(new Runnable() { @Override public void run() { - Log.d(Config.LOGTAG, "start merging phone contacts with roster"); + Logging.d(Config.LOGTAG, "start merging phone contacts with roster"); for (Account account : accounts) { List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts(); for (Bundle phoneContact : phoneContacts) { if (Thread.interrupted()) { - Log.d(Config.LOGTAG, "interrupted merging phone contacts"); + Logging.d(Config.LOGTAG,"interrupted merging phone contacts"); return; } Jid jid; @@ -1101,7 +1075,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa + phoneContact.getString("lookup"); contact.setSystemAccount(systemAccount); if (contact.setPhotoUri(phoneContact.getString("photouri"))) { - getAvatarService().clear(contact); + AvatarService.getInstance().clear(contact); } contact.setSystemName(phoneContact.getString("displayname")); withSystemAccounts.remove(contact); @@ -1110,11 +1084,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa contact.setSystemAccount(null); contact.setSystemName(null); if (contact.setPhotoUri(null)) { - getAvatarService().clear(contact); + AvatarService.getInstance().clear(contact); } } } - Log.d(Config.LOGTAG, "finished merging phone contacts"); + Logging.d(Config.LOGTAG,"finished merging phone contacts"); updateAccountUi(); } }); @@ -1135,15 +1109,15 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa Runnable runnable = new Runnable() { @Override public void run() { - Log.d(Config.LOGTAG, "restoring roster"); + Logging.d(Config.LOGTAG, "restoring roster"); for (Account account : accounts) { databaseBackend.readRoster(account.getRoster()); account.initAccountServices(XmppConnectionService.this); //roster needs to be loaded at this stage } - getBitmapCache().evictAll(); + ImageUtil.evictBitmapCache(); Looper.prepare(); loadPhoneContacts(); - Log.d(Config.LOGTAG, "restoring messages"); + Logging.d(Config.LOGTAG, "restoring messages"); for (Conversation conversation : conversations) { conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE)); checkDeletedFiles(conversation); @@ -1156,11 +1130,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } mNotificationService.finishBacklog(false); mRestoredFromDatabase = true; - Log.d(Config.LOGTAG, "restored all messages"); + Logging.d(Config.LOGTAG,"restored all messages"); updateConversationUi(); } }; - mDatabaseExecutor.execute(runnable); + ConversationsPlusApplication.executeDatabaseOperation(runnable); } } @@ -1179,7 +1153,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onMessageFound(Message message) { - if (!getFileBackend().isFileAvailable(message)) { + if (!FileBackend.isFileAvailable(message)) { message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED)); final int s = message.getStatus(); if (s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) { @@ -1194,7 +1168,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa for (Conversation conversation : getConversations()) { Message message = conversation.findMessageWithFileAndUuid(uuid); if (message != null) { - if (!getFileBackend().isFileAvailable(message)) { + if (!FileBackend.isFileAvailable(message)) { message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED)); final int s = message.getStatus(); if (s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) { @@ -1242,35 +1216,50 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void loadMoreMessages(final Conversation conversation, final long timestamp, final OnMoreMessagesLoaded callback) { if (XmppConnectionService.this.getMessageArchiveService().queryInProgress(conversation, callback)) { + Logging.d("mam", "Query in progress"); return; } else if (timestamp == 0) { + Logging.d("mam", "Query stopped due to timestamp"); return; } - Log.d(Config.LOGTAG, "load more messages for " + conversation.getName() + " prior to " + MessageGenerator.getTimestamp(timestamp)); + //TODO Create a separate class for this runnable to store if messages are getting loaded or not. Not really a good idea to do this in the callback. + Logging.d(Config.LOGTAG, "load more messages for " + conversation.getName() + " prior to " + MessageGenerator.getTimestamp(timestamp)); Runnable runnable = new Runnable() { @Override public void run() { + if (null == callback || !callback.isLoadingInProgress()) { // if a callback is set, ensure that there is no loading in progress + if (null != callback) { + callback.setLoadingInProgress(); // Tell the callback that the loading is in progress + } final Account account = conversation.getAccount(); List<Message> messages = databaseBackend.getMessages(conversation, 50, timestamp); + Logging.d("mam", "runnable load more messages"); if (messages.size() > 0) { + Logging.d("mam", "At least one message"); conversation.addAll(0, messages); checkDeletedFiles(conversation); callback.onMoreMessagesLoaded(messages.size(), conversation); } else if (conversation.hasMessagesLeftOnServer() && account.isOnlineAndConnected() && conversation.getLastClearHistory() == 0) { + Logging.d("mam", "mam activate, account online and connected and messages left on server"); 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); + MessageArchiveService.Query query = getMessageArchiveService().query(conversation, 0, timestamp - 1); if (query != null) { query.setCallback(callback); } callback.informUser(R.string.fetching_history_from_server); } - } + } else { + Logging.d("mam", ((!conversation.hasMessagesLeftOnServer()) ? "no" : "") + " more messages left on server, mam " + ((account.getXmppConnection().getFeatures().mam()) ? "" : "not") + " activated, account is " + ((account.isOnlineAndConnected()) ? "" : "not") + " online or connected)"); + callback.onMoreMessagesLoaded(0, conversation); + callback.informUser(R.string.no_more_history_on_server); + } } + } }; - mDatabaseExecutor.execute(runnable); + ConversationsPlusApplication.executeDatabaseOperation(runnable); } public List<Account> getAccounts() { @@ -1731,7 +1720,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } } - Log.d(Config.LOGTAG, "app switched into foreground"); + Logging.d(Config.LOGTAG, "app switched into foreground"); } private void switchToBackground() { @@ -1750,7 +1739,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } this.mNotificationService.setIsInForeground(false); - Log.d(Config.LOGTAG, "app switched into background"); + Logging.d(Config.LOGTAG, "app switched into background"); } private void connectMultiModeConversations(Account account) { @@ -1909,7 +1898,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa sendPresencePacket(conversation.getAccount(), packet); conversation.getMucOptions().setOffline(); conversation.deregisterWithBookmark(); - Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + Logging.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": leaving muc " + conversation.getJid()); } else { account.pendingConferenceLeaves.add(conversation); @@ -1936,7 +1925,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void createAdhocConference(final Account account, final Iterable<Jid> jids, final UiCallback<Conversation> callback) { - Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": creating adhoc conference with " + jids.toString()); + Logging.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": creating adhoc conference with " + jids.toString()); if (account.getStatus() == Account.State.ONLINE) { try { String server = findConferenceServer(account); @@ -2111,11 +2100,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void changeRoleInConference(final Conversation conference, final String nick, MucOptions.Role role, final OnRoleChanged callback) { IqPacket request = this.mIqGenerator.changeRole(conference, nick, role.toString()); - Log.d(Config.LOGTAG, request.toString()); + Logging.d(Config.LOGTAG, request.toString()); sendIqPacket(conference.getAccount(), request, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - Log.d(Config.LOGTAG, packet.toString()); + Logging.d(Config.LOGTAG, packet.toString()); if (packet.getType() == IqPacket.TYPE.RESULT) { callback.onRoleChangedSuccessful(nick); } else { @@ -2136,7 +2125,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa leaveMuc(conversation, true); } else { if (conversation.endOtrIfNeeded()) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + ": ended otr session with " + conversation.getJid()); } @@ -2176,8 +2165,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void createContact(Contact contact) { - boolean autoGrant = getPreferences().getBoolean("grant_new_contacts", true); - if (autoGrant) { + if (ConversationsPlusPreferences.grantNewContacts()) { contact.setOption(Contact.Options.PREEMPTIVE_GRANT); contact.setOption(Contact.Options.ASKING); } @@ -2187,10 +2175,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void onOtrSessionEstablished(Conversation conversation) { final Account account = conversation.getAccount(); final Session otrSession = conversation.getOtrSession(); - Log.d(Config.LOGTAG, - account.getJid().toBareJid() + " otr session established with " - + conversation.getJid() + "/" - + otrSession.getSessionID().getUserID()); + Logging.d(Config.LOGTAG, + account.getJid().toBareJid() + " otr session established with " + + conversation.getJid() + "/" + + otrSession.getSessionID().getUserID()); conversation.findUnsentMessagesWithEncryption(Message.ENCRYPTION_OTR, new Conversation.OnMessageFound() { @Override @@ -2266,221 +2254,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } - public void publishAvatar(final Account account, - final Uri image, - final UiCallback<Avatar> callback) { - final Bitmap.CompressFormat format = Config.AVATAR_FORMAT; - final int size = Config.AVATAR_SIZE; - final Avatar avatar = getFileBackend().getPepAvatar(image, size, format); - if (avatar != null) { - avatar.height = size; - avatar.width = size; - if (format.equals(Bitmap.CompressFormat.WEBP)) { - avatar.type = "image/webp"; - } else if (format.equals(Bitmap.CompressFormat.JPEG)) { - avatar.type = "image/jpeg"; - } else if (format.equals(Bitmap.CompressFormat.PNG)) { - avatar.type = "image/png"; - } - if (!getFileBackend().save(avatar)) { - callback.error(R.string.error_saving_avatar, avatar); - return; - } - final IqPacket packet = this.mIqGenerator.publishAvatar(avatar); - this.sendIqPacket(account, packet, new OnIqPacketReceived() { - - @Override - public void onIqPacketReceived(Account account, IqPacket result) { - if (result.getType() == IqPacket.TYPE.RESULT) { - final IqPacket packet = XmppConnectionService.this.mIqGenerator - .publishAvatarMetadata(avatar); - sendIqPacket(account, packet, new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, IqPacket result) { - if (result.getType() == IqPacket.TYPE.RESULT) { - if (account.setAvatar(avatar.getFilename())) { - getAvatarService().clear(account); - databaseBackend.updateAccount(account); - } - callback.success(avatar); - } else { - callback.error( - R.string.error_publish_avatar_server_reject, - avatar); - } - } - }); - } else { - callback.error( - R.string.error_publish_avatar_server_reject, - avatar); - } - } - }); - } else { - callback.error(R.string.error_publish_avatar_converting, null); - } - } - - public void fetchAvatar(Account account, Avatar avatar) { - fetchAvatar(account, avatar, null); - } - - public void fetchAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) { - final String KEY = generateFetchKey(account, avatar); - synchronized (this.mInProgressAvatarFetches) { - if (this.mInProgressAvatarFetches.contains(KEY)) { - return; - } else { - switch (avatar.origin) { - case PEP: - this.mInProgressAvatarFetches.add(KEY); - fetchAvatarPep(account, avatar, callback); - break; - case VCARD: - this.mInProgressAvatarFetches.add(KEY); - fetchAvatarVcard(account, avatar, callback); - break; - } - } - } - } - - private void fetchAvatarPep(Account account, final Avatar avatar, final UiCallback<Avatar> callback) { - IqPacket packet = this.mIqGenerator.retrievePepAvatar(avatar); - sendIqPacket(account, packet, new OnIqPacketReceived() { - - @Override - public void onIqPacketReceived(Account account, IqPacket result) { - synchronized (mInProgressAvatarFetches) { - mInProgressAvatarFetches.remove(generateFetchKey(account, avatar)); - } - final String ERROR = account.getJid().toBareJid() - + ": fetching avatar for " + avatar.owner + " failed "; - if (result.getType() == IqPacket.TYPE.RESULT) { - avatar.image = mIqParser.avatarData(result); - if (avatar.image != null) { - if (getFileBackend().save(avatar)) { - if (account.getJid().toBareJid().equals(avatar.owner)) { - if (account.setAvatar(avatar.getFilename())) { - databaseBackend.updateAccount(account); - } - getAvatarService().clear(account); - updateConversationUi(); - updateAccountUi(); - } else { - Contact contact = account.getRoster() - .getContact(avatar.owner); - contact.setAvatar(avatar); - getAvatarService().clear(contact); - updateConversationUi(); - updateRosterUi(); - } - if (callback != null) { - callback.success(avatar); - } - Log.d(Config.LOGTAG, account.getJid().toBareJid() - + ": succesfuly fetched pep avatar for " + avatar.owner); - return; - } - } else { - - Log.d(Config.LOGTAG, ERROR + "(parsing error)"); - } - } else { - Element error = result.findChild("error"); - if (error == null) { - Log.d(Config.LOGTAG, ERROR + "(server error)"); - } else { - Log.d(Config.LOGTAG, ERROR + error.toString()); - } - } - if (callback != null) { - callback.error(0, null); - } - - } - }); - } - - private void fetchAvatarVcard(final Account account, final Avatar avatar, final UiCallback<Avatar> callback) { - IqPacket packet = this.mIqGenerator.retrieveVcardAvatar(avatar); - this.sendIqPacket(account, packet, new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - synchronized (mInProgressAvatarFetches) { - mInProgressAvatarFetches.remove(generateFetchKey(account, avatar)); - } - if (packet.getType() == IqPacket.TYPE.RESULT) { - Element vCard = packet.findChild("vCard", "vcard-temp"); - Element photo = vCard != null ? vCard.findChild("PHOTO") : null; - String image = photo != null ? photo.findChildContent("BINVAL") : null; - if (image != null) { - avatar.image = image; - if (getFileBackend().save(avatar)) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() - + ": successfully fetched vCard avatar for " + avatar.owner); - if (avatar.owner.isBareJid()) { - Contact contact = account.getRoster() - .getContact(avatar.owner); - contact.setAvatar(avatar); - getAvatarService().clear(contact); - updateConversationUi(); - updateRosterUi(); - } else { - Conversation conversation = find(account, avatar.owner.toBareJid()); - if (conversation != null && conversation.getMode() == Conversation.MODE_MULTI) { - MucOptions.User user = conversation.getMucOptions().findUser(avatar.owner.getResourcepart()); - if (user != null) { - if (user.setAvatar(avatar)) { - getAvatarService().clear(user); - updateConversationUi(); - updateMucRosterUi(); - } - } - } - } - } - } - } - } - }); - } - - public void checkForAvatar(Account account, final UiCallback<Avatar> callback) { - IqPacket packet = this.mIqGenerator.retrieveAvatarMetaData(null); - this.sendIqPacket(account, packet, new OnIqPacketReceived() { - - @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() == IqPacket.TYPE.RESULT) { - Element pubsub = packet.findChild("pubsub", - "http://jabber.org/protocol/pubsub"); - if (pubsub != null) { - Element items = pubsub.findChild("items"); - if (items != null) { - Avatar avatar = Avatar.parseMetadata(items); - if (avatar != null) { - avatar.owner = account.getJid().toBareJid(); - if (fileBackend.isAvatarCached(avatar)) { - if (account.setAvatar(avatar.getFilename())) { - databaseBackend.updateAccount(account); - } - getAvatarService().clear(account); - callback.success(avatar); - } else { - fetchAvatarPep(account, avatar, callback); - } - return; - } - } - } - } - callback.error(0, null); - } - }); - } - public void deleteContactOnServer(Contact contact) { contact.resetOption(Contact.Options.PREEMPTIVE_GRANT); contact.resetOption(Contact.Options.DIRTY_PUSH); @@ -2519,7 +2292,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } if (!force) { try { - Log.d(Config.LOGTAG, "wait for disconnect"); + Logging.d(Config.LOGTAG, "wait for disconnect"); Thread.sleep(500); //sleep wait for disconnect } catch (InterruptedException e) { //ignored @@ -2546,7 +2319,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } public void invite(Conversation conversation, Jid contact) { - Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": inviting " + contact + " to " + conversation.getJid().toBareJid()); + Logging.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": inviting " + contact + " to " + conversation.getJid().toBareJid()); MessagePacket packet = mMessageGenerator.invite(conversation, contact); sendMessagePacket(conversation.getAccount(), packet); } @@ -2743,7 +2516,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } }; - mDatabaseExecutor.execute(runnable); + ConversationsPlusApplication.executeDatabaseOperation(runnable); updateUnreadCountBadge(); return true; } else { @@ -2754,7 +2527,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public synchronized void updateUnreadCountBadge() { int count = unreadCount(); if (unreadCount != count) { - Log.d(Config.LOGTAG, "update unread count to " + count); + Logging.d(Config.LOGTAG, "update unread count to " + count); if (count > 0) { ShortcutBadger.with(getApplicationContext()).count(count); } else { @@ -2769,8 +2542,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (this.markRead(conversation)) { updateConversationUi(); } - if (confirmMessages() && markable != null && markable.getRemoteMsgId() != null) { - Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": sending read marker to " + markable.getCounterpart().toString()); + if (Settings.CONFIRM_MESSAGE_READ && markable != null && markable.getRemoteMsgId() != null) { + Logging.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": sending read marker to " + markable.getCounterpart().toString()); Account account = conversation.getAccount(); final Jid to = markable.getCounterpart(); MessagePacket packet = mMessageGenerator.confirm(account, to, markable.getRemoteMsgId()); @@ -2792,9 +2565,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void updateMemorizingTrustmanager() { final MemorizingTrustManager tm; - final boolean dontTrustSystemCAs = getPreferences().getBoolean("dont_trust_system_cas", false); - if (dontTrustSystemCAs) { - tm = new MemorizingTrustManager(getApplicationContext(), null); + if (ConversationsPlusPreferences.dontTrustSystemCAs()) { + tm = new MemorizingTrustManager(getApplicationContext(), null); } else { tm = new MemorizingTrustManager(getApplicationContext()); } @@ -2817,8 +2589,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa databaseBackend.writeRoster(account.getRoster()); } }; - mDatabaseExecutor.execute(runnable); - + ConversationsPlusApplication.executeDatabaseOperation(runnable); } public List<String> getKnownHosts() { @@ -2969,7 +2740,12 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void clearConversationHistory(final Conversation conversation) { conversation.clearMessages(); - conversation.setHasMessagesLeftOnServer(false); //avoid messages getting loaded through mam + /* + * In case the history was loaded completely before. + * The flag "hasMessagesLeftOnServer" is set to false and no messages will be loaded anymore + * Therefore set this flag to true and try to get messages from server + */ + conversation.setHasMessagesLeftOnServer(true); conversation.setLastClearHistory(System.currentTimeMillis()); Runnable runnable = new Runnable() { @Override @@ -2977,7 +2753,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa databaseBackend.deleteMessagesInConversation(conversation); } }; - mDatabaseExecutor.execute(runnable); + ConversationsPlusApplication.executeDatabaseOperation(runnable); } public void sendBlockRequest(final Blockable blockable) { @@ -3019,7 +2795,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onIqPacketReceived(Account account, IqPacket packet) { if (packet.getType() == IqPacket.TYPE.ERROR) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not publish nick"); + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": could not publish nick"); } } }); @@ -3060,7 +2836,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa databaseBackend.insertDiscoveryResult(disco); injectServiceDiscorveryResult(account.getRoster(), presence.getHash(), presence.getVer(), disco); } else { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": mismatch in caps for contact " + jid + " " + presence.getVer() + " vs " + disco.getVer()); + Logging.d(Config.LOGTAG, account.getJid().toBareJid() + ": mismatch in caps for contact " + jid + " " + presence.getVer() + " vs " + disco.getVer()); } } account.inProgressDiscoFetches.remove(key); @@ -3121,6 +2897,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa void onMoreMessagesLoaded(int count, Conversation conversation); void informUser(int r); + + void setLoadingInProgress(); + + boolean isLoadingInProgress(); } public interface OnAccountPasswordChanged { |