diff options
Diffstat (limited to '')
7 files changed, 798 insertions, 0 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/utils/AvatarUtil.java b/src/main/java/de/thedevstack/conversationsplus/utils/AvatarUtil.java new file mode 100644 index 00000000..63dc320e --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/utils/AvatarUtil.java @@ -0,0 +1,163 @@ +package de.thedevstack.conversationsplus.utils; + +import android.graphics.Bitmap; +import android.net.Uri; +import android.util.Base64; +import android.util.Base64OutputStream; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.security.DigestOutputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import de.thedevstack.android.logcat.Logging; +import de.thedevstack.conversationsplus.ConversationsPlusApplication; +import eu.siacs.conversations.Config; +import eu.siacs.conversations.utils.CryptoHelper; +import eu.siacs.conversations.xmpp.pep.Avatar; + +/** + * This util provides access to saved avatars, creating avatars. + */ +public final class AvatarUtil { + + /** + * Get the PEP Avatar. + * TODO: Why PEP Avatar? + * @param image the uri to the avatar's image + * @param size the image width/height to resize to + * @param format the format for the avatar + * @return the avatar + */ + public static Avatar getPepAvatar(Uri image, int size, Bitmap.CompressFormat format) { + try { + Avatar avatar = new Avatar(); + Bitmap bm = ImageUtil.cropCenterSquare(image, size); + if (bm == null) { + return null; + } + ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream(); + Base64OutputStream mBase64OutputSttream = new Base64OutputStream( + mByteArrayOutputStream, Base64.DEFAULT); + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + DigestOutputStream mDigestOutputStream = new DigestOutputStream( + mBase64OutputSttream, digest); + if (!bm.compress(format, 75, mDigestOutputStream)) { + return null; + } + mDigestOutputStream.flush(); + mDigestOutputStream.close(); + avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest()); + avatar.image = new String(mByteArrayOutputStream.toByteArray()); + return avatar; + } catch (NoSuchAlgorithmException e) { + return null; + } catch (IOException e) { + return null; + } + } + + /** + * Returns whether the avatar is cached or not. + * @param avatar the avatar to check the existance + * @return <code>true</code> if the file of the avatar exists, <code>false</code> otherwise + */ + public static boolean isAvatarCached(Avatar avatar) { + File file = new File(getAvatarPath(avatar.getFilename())); + return file.exists(); + } + + /** + * Saves an avatar to the file system. + * All exceptions are silently ignored. + * TODO: Move real saving operation to FileBackend + * @param avatar the avatar to save + * @return <code>true</code> if the avatar was saved successfully, <code>false</code> otherwise. + */ + public static boolean save(Avatar avatar) { + File file; + if (isAvatarCached(avatar)) { + file = new File(getAvatarPath(avatar.getFilename())); + } else { + String filename = getAvatarPath(avatar.getFilename()); + file = new File(filename + ".tmp"); + file.getParentFile().mkdirs(); + OutputStream os = null; + try { + file.createNewFile(); + os = new FileOutputStream(file); + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + digest.reset(); + DigestOutputStream mDigestOutputStream = new DigestOutputStream(os, digest); + mDigestOutputStream.write(avatar.getImageAsBytes()); + mDigestOutputStream.flush(); + mDigestOutputStream.close(); + String sha1sum = CryptoHelper.bytesToHex(digest.digest()); + if (sha1sum.equals(avatar.sha1sum)) { + file.renameTo(new File(filename)); + } else { + Logging.d(Config.LOGTAG, "sha1sum mismatch for " + avatar.owner); + file.delete(); + return false; + } + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + return false; + } catch (NoSuchAlgorithmException e) { + return false; + } finally { + StreamUtil.close(os); + } + } + avatar.size = file.length(); + return true; + } + + /** + * Returns the avatar for an uri. + * @param avatar the avatar's uri + * @param size the height/width the avatar should have + * @return the bitmap of the uri + */ + public static Bitmap getAvatar(String avatar, int size) { + if (avatar == null) { + return null; + } + Bitmap bm = ImageUtil.cropCenter(getAvatarUri(avatar), size, size); + if (bm == null) { + return null; + } + return bm; + } + + /** + * Returns the path to an avatar + * @param avatar the name of the avatar. + * @return the path as string + */ + public static String getAvatarPath(String avatar) { + return ConversationsPlusApplication.getInstance().getFilesDir().getAbsolutePath()+ "/avatars/" + avatar; + } + + /** + * Returns the path to an avatar as an uri. + * @param avatar the name of the avatar + * @return the path as uri + */ + public static Uri getAvatarUri(String avatar) { + return Uri.parse("file:" + getAvatarPath(avatar)); + } + + /** + * Avoid instantiation it's an helper class. + */ + private AvatarUtil() { + // Static helper class + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/utils/FileHelper.java b/src/main/java/de/thedevstack/conversationsplus/utils/FileHelper.java new file mode 100644 index 00000000..3384b54e --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/utils/FileHelper.java @@ -0,0 +1,43 @@ +package de.thedevstack.conversationsplus.utils; + +import android.database.Cursor; +import android.net.Uri; +import android.provider.MediaStore; + +import de.thedevstack.conversationsplus.ConversationsPlusApplication; + +/** + * Created by tzur on 30.10.2015. + */ +public final class FileHelper { + + /** + * Get the real path from an Uri. + * @param uri the uri to convert to the real path + * @return the real path or <code>null</code> + */ + public static String getRealPathFromUri(Uri uri) { + String path = null; + if (uri.getScheme().equals("file")) { + return uri.getPath(); + } else if (uri.toString().startsWith("content://media/")) { + String[] projection = {MediaStore.MediaColumns.DATA}; + Cursor metaCursor = ConversationsPlusApplication.getInstance().getContentResolver().query(uri, + projection, null, null, null); + if (metaCursor != null) { + try { + if (metaCursor.moveToFirst()) { + path = metaCursor.getString(0); + } + } finally { + metaCursor.close(); + } + } + } + return path; + } + + private FileHelper() { + // Utility class - do not instantiate + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/utils/ImageUtil.java b/src/main/java/de/thedevstack/conversationsplus/utils/ImageUtil.java new file mode 100644 index 00000000..b28e6f1c --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/utils/ImageUtil.java @@ -0,0 +1,372 @@ +package de.thedevstack.conversationsplus.utils; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.RectF; +import android.media.ExifInterface; +import android.net.Uri; +import android.util.LruCache; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import de.thedevstack.android.logcat.Logging; +import de.thedevstack.conversationsplus.exceptions.ImageResizeException; +import eu.siacs.conversations.Config; +import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.persistance.FileBackend; +import eu.siacs.conversations.utils.ExifHelper; + +/** + * This util provides + */ +public final class ImageUtil { + + private static int IMAGE_SIZE = 1920; + private static LruCache<String, Bitmap> BITMAP_CACHE; + + /** + * Returns a bitmap from the cache. + * @see LruCache#get(Object) for details + * @param key the key of the bitmap to get + * @return the bitmap + */ + public static Bitmap getBitmapFromCache(String key) { + return BITMAP_CACHE.get(key); + } + + /** + * Adds a bitmap with the given key to the cache. + * @see LruCache#put(Object, Object) for details + * @param key the key to identify this bitmap + * @param bitmap the bitmap to cache + */ + public static void addBitmapToCache(String key, Bitmap bitmap) { + BITMAP_CACHE.put(key, bitmap); + } + + /** + * Removes the bitmap with given key from the cache. + * @param key the key of the bitmap to remove + */ + public static void removeBitmapFromCache(String key) { + BITMAP_CACHE.remove(key); + } + + /** + * Clears the cache. + * @see LruCache#evictAll() for more details. + */ + public static void evictBitmapCache() { + BITMAP_CACHE.evictAll(); + } + + /** + * Initializes the bitmap cache. + * This has to be executed once on application start. + * @see LruCache#LruCache(int) for details + */ + public static void initBitmapCache() { + Logging.i("Conversations+ImageUtil", "Initializing BitmapCache"); + final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); + final int cacheSize = maxMemory / 8; + BITMAP_CACHE = new LruCache<String, Bitmap>(cacheSize) { + @Override + protected int sizeOf(final String key, final Bitmap bitmap) { + return bitmap.getByteCount() / 1024; + } + }; + } + + /** + * Resizes a given bitmap and return a new and resized bitmap. + * The bitmap is only resized if either the width or the height of the original bitmap is smaller than the given size. + * @param originalBitmap the bitmap to resize + * @param size the size to scale to + * @return new and resized bitmap or the original bitmap if width and height are smaller than size + */ + public static Bitmap resize(Bitmap originalBitmap, int size) { + int w = originalBitmap.getWidth(); + int h = originalBitmap.getHeight(); + if (Math.max(w, h) > size) { + int scalledW; + int scalledH; + if (w <= h) { + scalledW = (int) (w / ((double) h / size)); + scalledH = size; + } else { + scalledW = size; + scalledH = (int) (h / ((double) w / size)); + } + return Bitmap.createScaledBitmap(originalBitmap, scalledW, scalledH, true); + } else { + return originalBitmap; + } + } + + /** + * Resizes and rotates an image given by uri and returns the bitmap. + * @param image the uri of the image to be resized and rotated + * @return resized and rotated bitmap + * @throws ImageResizeException + */ + public static Bitmap resizeAndRotateImage(Uri image) throws ImageResizeException { + return ImageUtil.resizeAndRotateImage(image, 0); + } + + /** + * Resizes and rotates an image given by uri and returns the bitmap. + * @param image the uri of the image to be resized and rotated + * @return resized and rotated bitmap + * @throws ImageResizeException + */ + private static Bitmap resizeAndRotateImage(Uri image, int sampleSize) throws ImageResizeException { + InputStream imageInputStream = null; + try { + imageInputStream = StreamUtil.openInputStreamFromContentResolver(image); + Bitmap originalBitmap; + BitmapFactory.Options options = new BitmapFactory.Options(); + int inSampleSize = (int) Math.pow(2, sampleSize); + Logging.d(Config.LOGTAG, "reading bitmap with sample size " + inSampleSize); + options.inSampleSize = inSampleSize; + originalBitmap = BitmapFactory.decodeStream(imageInputStream, null, options); + imageInputStream.close(); + if (originalBitmap == null) { + throw new ImageResizeException(R.string.error_not_an_image_file); + } + Bitmap scaledBitmap = ImageUtil.resize(originalBitmap, IMAGE_SIZE); + int rotation = ImageUtil.getRotation(image); + if (rotation > 0) { + scaledBitmap = ImageUtil.rotate(scaledBitmap, rotation); + } + + return scaledBitmap; + } catch (FileNotFoundException e) { + throw new ImageResizeException(R.string.error_file_not_found); + } catch (IOException e) { + throw new ImageResizeException(R.string.error_io_exception); + } catch (OutOfMemoryError e) { + ++sampleSize; + if (sampleSize <= 3) { + return resizeAndRotateImage(image, sampleSize); + } else { + throw new ImageResizeException(R.string.error_out_of_memory); + } + } finally { + StreamUtil.close(imageInputStream); + } + } + + /** + * Returns the rotation from the exif information of an image identified with the given uri. + * The orientation is retrieved by parsing the stream of the image. + * FileNotFoundException is silently ignored. + * @param image the uri of the image to get the rotation + * @return the rotation value for the image, <code>0</code> if the file cannot be found. + */ + public static int getRotation(Uri image) { + InputStream is = null; + try { + is = StreamUtil.openInputStreamFromContentResolver(image); + return ExifHelper.getOrientation(is); + } catch (FileNotFoundException e) { + return 0; + } finally { + StreamUtil.close(is); + } + } + + /** + * Returns a thumbnail for a bitmap in a message. + * @param message the message to get the thumbnail for + * @param size the size to resize the original image to + * @param cacheOnly whether only cached images should be returned or not + * @return the resized thumbail + * @throws FileNotFoundException if the original image does not exist anymore or an IOException occurs. + */ + public static Bitmap getThumbnail(Message message, int size, boolean cacheOnly) + throws FileNotFoundException { + Bitmap thumbnail = ImageUtil.getBitmapFromCache(message.getUuid()); + if ((thumbnail == null) && (!cacheOnly)) { + File file = FileBackend.getFile(message); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inSampleSize = calcSampleSize(file, size); + Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(),options); + if (fullsize == null) { + throw new FileNotFoundException(); + } + thumbnail = resize(fullsize, size); + thumbnail = rotate(thumbnail, file.getAbsolutePath()); + + ImageUtil.addBitmapToCache(message.getUuid(), thumbnail); + } + return thumbnail; + } + + /** + * Rotates an bitmap. Only the values 90°, 180° and 270° are considered to rotate the image. + * The orientation information is read using the ExifInterface. + * @param original the original bitmap + * @param srcPath the path to the original bitmap (used to read the exif information) + * @return rotated bitmap, or original bitmap if criteria are not met + * @throws IOException + */ + public static Bitmap rotate(Bitmap original, String srcPath) { + try { + ExifInterface exif = new ExifInterface(srcPath); + int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); + int rotation = 0; + switch (orientation) { + case ExifInterface.ORIENTATION_ROTATE_90: + rotation = 90; + break; + case ExifInterface.ORIENTATION_ROTATE_180: + rotation = 180; + break; + case ExifInterface.ORIENTATION_ROTATE_270: + rotation = 270; + break; + } + if (rotation > 0) { + return rotate(original, rotation); + } + } catch (IOException e) { + Logging.w("filebackend", "Error while rotating image, returning original (" + e.getMessage() + ")"); + } + return original; + } + + /** + * Rotates a bitmap with given degrees. + * @param bitmap the bitmap to be rotated + * @param degree the degrees to rotate the bitmap + * @return a newly created bitmap + */ + public static Bitmap rotate(Bitmap bitmap, int degree) { + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + Matrix mtx = new Matrix(); + mtx.postRotate(degree); + return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true); + } + + + public static Bitmap cropCenterSquare(Uri image, int size) { + if (image == null) { + return null; + } + InputStream is = null; + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inSampleSize = calcSampleSize(image, size); + is = StreamUtil.openInputStreamFromContentResolver(image); + Bitmap input = BitmapFactory.decodeStream(is, null, options); + if (input == null) { + return null; + } else { + int rotation = getRotation(image); + if (rotation > 0) { + input = rotate(input, rotation); + } + return cropCenterSquare(input, size); + } + } catch (FileNotFoundException e) { + return null; + } finally { + StreamUtil.close(is); + } + } + + public static Bitmap cropCenter(Uri image, int newHeight, int newWidth) { + if (image == null) { + return null; + } + InputStream is = null; + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inSampleSize = calcSampleSize(image,Math.max(newHeight, newWidth)); + is = StreamUtil.openInputStreamFromContentResolver(image); + Bitmap source = BitmapFactory.decodeStream(is, null, options); + if (source == null) { + return null; + } + int sourceWidth = source.getWidth(); + int sourceHeight = source.getHeight(); + float xScale = (float) newWidth / sourceWidth; + float yScale = (float) newHeight / sourceHeight; + float scale = Math.max(xScale, yScale); + float scaledWidth = scale * sourceWidth; + float scaledHeight = scale * sourceHeight; + float left = (newWidth - scaledWidth) / 2; + float top = (newHeight - scaledHeight) / 2; + + RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight); + Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(dest); + canvas.drawBitmap(source, null, targetRect, null); + return dest; + } catch (FileNotFoundException e) { + return null; + } finally { + StreamUtil.close(is); + } + } + + public static Bitmap cropCenterSquare(Bitmap input, int size) { + int w = input.getWidth(); + int h = input.getHeight(); + + float scale = Math.max((float) size / h, (float) size / w); + + float outWidth = scale * w; + float outHeight = scale * h; + float left = (size - outWidth) / 2; + float top = (size - outHeight) / 2; + RectF target = new RectF(left, top, left + outWidth, top + outHeight); + + Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(output); + canvas.drawBitmap(input, null, target, null); + return output; + } + + public static int calcSampleSize(Uri image, int size) throws FileNotFoundException { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeStream(StreamUtil.openInputStreamFromContentResolver(image), null, options); + return calcSampleSize(options, size); + } + + public static int calcSampleSize(File image, int size) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(image.getAbsolutePath(), options); + return calcSampleSize(options, size); + } + + public static int calcSampleSize(BitmapFactory.Options options, int size) { + int height = options.outHeight; + int width = options.outWidth; + int inSampleSize = 1; + + if (height > size || width > size) { + int halfHeight = height / 2; + int halfWidth = width / 2; + + while ((halfHeight / inSampleSize) > size + && (halfWidth / inSampleSize) > size) { + inSampleSize *= 2; + } + } + return inSampleSize; + } + + private ImageUtil() { + // Static helper class + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/utils/MessageUtil.java b/src/main/java/de/thedevstack/conversationsplus/utils/MessageUtil.java new file mode 100644 index 00000000..81f5b843 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/utils/MessageUtil.java @@ -0,0 +1,94 @@ +package de.thedevstack.conversationsplus.utils; + +import android.graphics.BitmapFactory; + +import java.net.URL; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import eu.siacs.conversations.entities.DownloadableFile; +import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.persistance.FileBackend; + +/** + * Created by tzur on 15.12.2015. + */ +public final class MessageUtil { + public static 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); + } + + public static void updateMessageWithImageDetails(Message message, String filePath, long size, int imageWidth, int imageHeight) { + message.setRelativeFilePath(filePath); + MessageUtil.updateMessageBodyWithImageParams(message, size, imageWidth, imageHeight); + } + + public static void updateFileParams(Message message) { + updateFileParams(message, null); + } + + public static void updateFileParams(Message message, URL url) { + DownloadableFile file = FileBackend.getFile(message); + int imageWidth = -1; + int imageHeight = -1; + if (message.getType() == Message.TYPE_IMAGE || file.getMimeType().startsWith("image/")) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(file.getAbsolutePath(), options); + imageHeight = options.outHeight; + imageWidth = options.outWidth; + } + + MessageUtil.updateMessageBodyWithFileParams(message, url, file.getSize(), imageWidth, imageHeight); + } + + private static void updateMessageBodyWithFileParams(Message message, URL url, long fileSize, int imageWidth, int imageHeight) { + message.setBody(MessageUtil.getMessageBodyWithImageParams(url, fileSize, imageWidth, imageHeight)); + } + + private static void updateMessageBodyWithImageParams(Message message, long size, int imageWidth, int imageHeight) { + MessageUtil.updateMessageBodyWithImageParams(message, null, size, imageWidth, imageHeight); + } + + private static void updateMessageBodyWithImageParams(Message message, URL url, long size, int imageWidth, int imageHeight) { + message.setBody(MessageUtil.getMessageBodyWithImageParams(url, size, imageWidth, imageHeight)); + } + + private static String getMessageBodyWithImageParams(URL url, long size, int imageWidth, int imageHeight) { + StringBuilder sb = new StringBuilder(); + if (null != url) { + sb.append(url.toString()); + sb.append('|'); + } + sb.append(size); + if (-1 < imageWidth) { + sb.append('|'); + sb.append(imageWidth); + } + if (-1 < imageHeight) { + sb.append('|'); + sb.append(imageHeight); + } + return sb.toString(); + } + + private MessageUtil() { + // Static helper class + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/utils/StreamUtil.java b/src/main/java/de/thedevstack/conversationsplus/utils/StreamUtil.java new file mode 100644 index 00000000..64f46314 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/utils/StreamUtil.java @@ -0,0 +1,48 @@ +package de.thedevstack.conversationsplus.utils; + +import android.net.Uri; + +import java.io.Closeable; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import de.thedevstack.conversationsplus.ConversationsPlusApplication; + +/** + * Util to handle streams. + */ +public final class StreamUtil { + + /** + * Opens an InputStream from Uri using the ContentResolver from application. + * @see android.content.ContentResolver#openInputStream(Uri) + * @param uri the uri to open + * @return the InputStream for given uri + * @throws FileNotFoundException if the provided URI could not be opened. + */ + public static InputStream openInputStreamFromContentResolver(Uri uri) throws FileNotFoundException { + return ConversationsPlusApplication.getInstance().getContentResolver().openInputStream(uri); + } + + /** + * Closes a stream. + * IOException is silently ignored. + * @param stream the stream to close + */ + public static void close(Closeable stream) { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + } + } + } + + /** + * Avoid instantiation of util class. + */ + private StreamUtil() { + // Static helper class + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/utils/UiUpdateHelper.java b/src/main/java/de/thedevstack/conversationsplus/utils/UiUpdateHelper.java new file mode 100644 index 00000000..84ce200a --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/utils/UiUpdateHelper.java @@ -0,0 +1,52 @@ +package de.thedevstack.conversationsplus.utils; + +import de.thedevstack.android.logcat.Logging; +import eu.siacs.conversations.services.XmppConnectionService; + +/** + * Helper class to avoid passing the xmppConnectionService to everywhere just to update the UI. + * TODO: Make even this helper class work without XmppConnectionService + */ +public class UiUpdateHelper { + private static XmppConnectionService xmppConnectionService; + + public static void initXmppConnectionService(XmppConnectionService xmppConnectionService) { + if (null == UiUpdateHelper.xmppConnectionService) { + UiUpdateHelper.xmppConnectionService = xmppConnectionService; + } else { + Logging.e("UiUpdateHelper", "XMPP Connection Service already instantiated."); + } + } + + public static void updateConversationUi() { + if (null != UiUpdateHelper.xmppConnectionService) { + UiUpdateHelper.xmppConnectionService.updateConversationUi(); + } else { + Logging.e("UiUpdateHelper", "XMPP Connection Service not initialized. Conversation Ui not updated."); + } + } + + public static void updateAccountUi() { + if (null != UiUpdateHelper.xmppConnectionService) { + UiUpdateHelper.xmppConnectionService.updateAccountUi(); + } else { + Logging.e("UiUpdateHelper", "XMPP Connection Service not initialized. Account Ui not updated."); + } + } + + public static void updateRosterUi() { + if (null != UiUpdateHelper.xmppConnectionService) { + UiUpdateHelper.xmppConnectionService.updateRosterUi(); + } else { + Logging.e("UiUpdateHelper", "XMPP Connection Service not initialized. Roster Ui not updated."); + } + } + + public static void updateMucRosterUi() { + if (null != UiUpdateHelper.xmppConnectionService) { + UiUpdateHelper.xmppConnectionService.updateMucRosterUi(); + } else { + Logging.e("UiUpdateHelper", "XMPP Connection Service not initialized. MUC Roster Ui not updated."); + } + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/utils/XmppSendUtil.java b/src/main/java/de/thedevstack/conversationsplus/utils/XmppSendUtil.java new file mode 100644 index 00000000..74e65857 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/utils/XmppSendUtil.java @@ -0,0 +1,26 @@ +package de.thedevstack.conversationsplus.utils; + +import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.xmpp.OnIqPacketReceived; +import eu.siacs.conversations.xmpp.XmppConnection; +import eu.siacs.conversations.xmpp.stanzas.IqPacket; +import eu.siacs.conversations.xmpp.stanzas.PresencePacket; + +/** + * Created by tzur on 09.01.2016. + */ +public class XmppSendUtil { + public static void sendIqPacket(Account account, IqPacket packet, OnIqPacketReceived callback) { + final XmppConnection connection = account.getXmppConnection(); + if (connection != null) { + connection.sendIqPacket(packet, callback); + } + } + + public static void sendPresencePacket(Account account, PresencePacket packet) { + XmppConnection connection = account.getXmppConnection(); + if (connection != null) { + connection.sendPresencePacket(packet); + } + } +} |