diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index f882b7e1d..08437e87e 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -90,6 +90,11 @@ public class Message extends AbstractEntity { private String axolotlFingerprint = null; private String errorMessage = null; + private Boolean isGeoUri = null; + private Boolean isEmojisOnly = null; + private Boolean treatAsDownloadable = null; + private FileParams fileParams = null; + private Message(Conversation conversation) { this.conversation = conversation; } @@ -195,21 +200,21 @@ public class Message extends AbstractEntity { public static Message createStatusMessage(Conversation conversation, String body) { final Message message = new Message(conversation); message.setType(Message.TYPE_STATUS); - message.setBody(body); + message.body = body; return message; } public static Message createLoadMoreMessage(Conversation conversation) { final Message message = new Message(conversation); message.setType(Message.TYPE_STATUS); - message.setBody("LOAD_MORE"); + message.body = "LOAD_MORE"; return message; } public static Message createDateSeparator(Message message) { final Message separator = new Message(message.getConversation()); separator.setType(Message.TYPE_STATUS); - separator.setBody(MessageAdapter.DATE_SEPARATOR_BODY); + separator.body = MessageAdapter.DATE_SEPARATOR_BODY; separator.setTime(message.getTimeSent()); return separator; } @@ -279,11 +284,15 @@ public class Message extends AbstractEntity { return body; } - public void setBody(String body) { + public synchronized void setBody(String body) { if (body == null) { throw new Error("You should not set the message body to null"); } this.body = body; + this.isGeoUri = null; + this.isEmojisOnly = null; + this.treatAsDownloadable = null; + this.fileParams = null; } public String getErrorMessage() { @@ -401,7 +410,8 @@ public class Message extends AbstractEntity { return this.transferable; } - public void setTransferable(Transferable transferable) { + public synchronized void setTransferable(Transferable transferable) { + this.fileParams = null; this.transferable = transferable; } @@ -496,8 +506,8 @@ public class Message extends AbstractEntity { this.edited() == message.edited() && (message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) && this.getBody().length() + message.getBody().length() <= Config.MAX_DISPLAY_MESSAGE_CHARS && - !GeoHelper.isGeoUri(message.getBody()) && - !GeoHelper.isGeoUri(this.body) && + !message.isGeoUri()&& + !this.isGeoUri() && !message.treatAsDownloadable() && !this.treatAsDownloadable() && !message.getBody().startsWith(ME_COMMAND) && @@ -651,120 +661,92 @@ public class Message extends AbstractEntity { } } - public boolean treatAsDownloadable() { - if (body.trim().contains(" ")) { - return false; - } - try { - final URL url = new URL(body); - final String ref = url.getRef(); - final String protocol = url.getProtocol(); - final boolean encrypted = ref != null && ref.matches("([A-Fa-f0-9]{2}){48}"); - return (AesGcmURLStreamHandler.PROTOCOL_NAME.equalsIgnoreCase(protocol) && encrypted) - || (("http".equalsIgnoreCase(protocol) || "https".equalsIgnoreCase(protocol)) && (oob || encrypted)); + public synchronized boolean treatAsDownloadable() { + if (treatAsDownloadable == null) { + if (body.trim().contains(" ")) { + treatAsDownloadable = false; + } + try { + final URL url = new URL(body); + final String ref = url.getRef(); + final String protocol = url.getProtocol(); + final boolean encrypted = ref != null && ref.matches("([A-Fa-f0-9]{2}){48}"); + treatAsDownloadable = (AesGcmURLStreamHandler.PROTOCOL_NAME.equalsIgnoreCase(protocol) && encrypted) + || (("http".equalsIgnoreCase(protocol) || "https".equalsIgnoreCase(protocol)) && (oob || encrypted)); - } catch (MalformedURLException e) { - return false; + } catch (MalformedURLException e) { + treatAsDownloadable = false; + } } + return treatAsDownloadable; } - public boolean bodyIsOnlyEmojis() { - return EmojiManager.isOnlyEmojis(body.replaceAll("\\s","")); + public synchronized boolean bodyIsOnlyEmojis() { + if (isEmojisOnly == null) { + isEmojisOnly = EmojiManager.isOnlyEmojis(body.replaceAll("\\s", "")); + } + return isEmojisOnly; } - public FileParams getFileParams() { - FileParams params = getLegacyFileParams(); - if (params != null) { - return params; + public synchronized boolean isGeoUri() { + if (isGeoUri == null) { + isGeoUri = GeoHelper.GEO_URI.matcher(body).matches(); } - params = new FileParams(); - if (this.transferable != null) { - params.size = this.transferable.getFileSize(); - } - if (body == null) { - return params; - } - String parts[] = body.split("\\|"); - switch (parts.length) { - case 1: - try { - params.size = Long.parseLong(parts[0]); - } catch (NumberFormatException e) { + return isGeoUri; + } + + public synchronized FileParams getFileParams() { + if (fileParams == null) { + fileParams = new FileParams(); + if (this.transferable != null) { + fileParams.size = this.transferable.getFileSize(); + } + String parts[] = body == null ? new String[0] : body.split("\\|"); + switch (parts.length) { + case 1: try { - params.url = new URL(parts[0]); - } catch (MalformedURLException e1) { - params.url = null; + fileParams.size = Long.parseLong(parts[0]); + } catch (NumberFormatException e) { + fileParams.url = parseUrl(parts[0]); } - } - break; - case 2: - case 4: - try { - params.url = new URL(parts[0]); - } catch (MalformedURLException e1) { - params.url = null; - } - try { - params.size = Long.parseLong(parts[1]); - } catch (NumberFormatException e) { - params.size = 0; - } - try { - params.width = Integer.parseInt(parts[2]); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { - params.width = 0; - } - try { - params.height = Integer.parseInt(parts[3]); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { - params.height = 0; - } - break; - case 3: - try { - params.size = Long.parseLong(parts[0]); - } catch (NumberFormatException e) { - params.size = 0; - } - try { - params.width = Integer.parseInt(parts[1]); - } catch (NumberFormatException e) { - params.width = 0; - } - try { - params.height = Integer.parseInt(parts[2]); - } catch (NumberFormatException e) { - params.height = 0; - } - break; + break; + case 4: + fileParams.width = parseInt(parts[2]); + fileParams.height = parseInt(parts[3]); + case 2: + fileParams.url = parseUrl(parts[0]); + fileParams.size = parseLong(parts[1]); + break; + case 3: + fileParams.size = parseLong(parts[0]); + fileParams.width = parseInt(parts[1]); + fileParams.height = parseInt(parts[2]); + break; + } } - return params; + return fileParams; } - public FileParams getLegacyFileParams() { - FileParams params = new FileParams(); - if (body == null) { - return params; + private static long parseLong(String value) { + try { + return Long.parseLong(value); + } catch (NumberFormatException e) { + return 0; } - String parts[] = body.split(","); - if (parts.length == 3) { - try { - params.size = Long.parseLong(parts[0]); - } catch (NumberFormatException e) { - return null; - } - try { - params.width = Integer.parseInt(parts[1]); - } catch (NumberFormatException e) { - return null; - } - try { - params.height = Integer.parseInt(parts[2]); - } catch (NumberFormatException e) { - return null; - } - return params; - } else { + } + + private static int parseInt(String value) { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + return 0; + } + } + + private static URL parseUrl(String value) { + try { + return new URL(value); + } catch (MalformedURLException e) { return null; } } diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index a50233821..21de6be86 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -531,7 +531,7 @@ public class NotificationService { private Message getFirstLocationMessage(final Iterable messages) { for (final Message message : messages) { - if (GeoHelper.isGeoUri(message.getBody())) { + if (message.isGeoUri()) { return message; } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 635a96274..b03a0a8e6 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -618,7 +618,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission); MenuItem deleteFile = menu.findItem(R.id.delete_file); MenuItem showErrorMessage = menu.findItem(R.id.show_error_message); - if (!treatAsFile && !GeoHelper.isGeoUri(m.getBody()) && !m.treatAsDownloadable()) { + if (!treatAsFile && !m.isGeoUri() && !m.treatAsDownloadable()) { selectText.setVisible(ListSelectionManager.isSupported()); } if (m.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { @@ -636,7 +636,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa sendAgain.setVisible(true); } if (m.hasFileOnRemoteHost() - || GeoHelper.isGeoUri(m.getBody()) + || m.isGeoUri() || m.treatAsDownloadable() || (t != null && t instanceof HttpDownloadConnection)) { copyUrl.setVisible(true); @@ -713,7 +713,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa private void shareWith(Message message) { Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); - if (GeoHelper.isGeoUri(message.getBody())) { + if (message.isGeoUri()) { shareIntent.putExtra(Intent.EXTRA_TEXT, message.getBody()); shareIntent.setType("text/plain"); } else if (!message.isFileOrImage()) { @@ -785,7 +785,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa private void copyUrl(Message message) { final String url; final int resId; - if (GeoHelper.isGeoUri(message.getBody())) { + if (message.isGeoUri()) { resId = R.string.location; url = message.getBody(); } else if (message.hasFileOnRemoteHost()) { diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 2dc8bbbcd..be6204a20 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -790,7 +790,7 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { displayDecryptionFailed(viewHolder,darkBackground); } else { - if (GeoHelper.isGeoUri(message.getBody())) { + if (message.isGeoUri()) { displayLocationMessage(viewHolder,message); } else if (message.bodyIsOnlyEmojis()) { displayEmojiMessage(viewHolder, message.getBody().replaceAll("\\s","")); diff --git a/src/main/java/eu/siacs/conversations/utils/GeoHelper.java b/src/main/java/eu/siacs/conversations/utils/GeoHelper.java index e2e9a212d..a3078bea9 100644 --- a/src/main/java/eu/siacs/conversations/utils/GeoHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/GeoHelper.java @@ -16,9 +16,7 @@ import eu.siacs.conversations.entities.Message; public class GeoHelper { public static Pattern GEO_URI = Pattern.compile("geo:([\\-0-9.]+),([\\-0-9.]+)(?:,([\\-0-9.]+))?(?:\\?(.*))?", Pattern.CASE_INSENSITIVE); - public static boolean isGeoUri(String body) { - return body != null && GEO_URI.matcher(body).matches(); - } + public static ArrayList createGeoIntentsFromMessage(Message message) { final ArrayList intents = new ArrayList<>(); diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index 69eeb58da..3c2ad136a 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -202,7 +202,7 @@ public class UIHelper { if (body.startsWith(Message.ME_COMMAND)) { return new Pair<>(body.replaceAll("^" + Message.ME_COMMAND, UIHelper.getMessageDisplayName(message) + " "), false); - } else if (GeoHelper.isGeoUri(message.getBody())) { + } else if (message.isGeoUri()) { if (message.getStatus() == Message.STATUS_RECEIVED) { return new Pair<>(context.getString(R.string.received_location), true); } else {