aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian S <christian@pix-art.de>2016-03-05 10:42:44 +0100
committerChristian S <christian@pix-art.de>2016-03-05 10:42:44 +0100
commit7412b0634fb62d9cf045c9e6d70c25cffaae57d0 (patch)
treefacedfe6508757ee0cce561f1eea140bab3567dc
parent251c27328b7812f6f01a4c8f7215fdd51af84b7e (diff)
parent8339ebf3dc0c0f27e6fc1bfdc1af574ec6cd82c9 (diff)
Merge branch 'siacs/master' into development
-rw-r--r--build.gradle4
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Message.java24
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Transferable.java107
-rw-r--r--src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java2
-rw-r--r--src/main/java/eu/siacs/conversations/parser/MessageParser.java6
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java7
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java15
-rw-r--r--src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java62
-rw-r--r--src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java27
-rw-r--r--src/main/java/eu/siacs/conversations/utils/UIHelper.java5
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java6
-rw-r--r--src/main/res/drawable-hdpi/ic_crop_white_24dp.pngbin0 -> 302 bytes
-rw-r--r--src/main/res/drawable-mdpi/ic_crop_white_24dp.pngbin0 -> 214 bytes
-rw-r--r--src/main/res/drawable-xhdpi/ic_crop_white_24dp.pngbin0 -> 272 bytes
-rw-r--r--src/main/res/drawable-xxhdpi/ic_crop_white_24dp.pngbin0 -> 326 bytes
-rw-r--r--src/main/res/drawable-xxxhdpi/ic_crop_white_24dp.pngbin0 -> 394 bytes
-rw-r--r--src/main/res/menu/publish_avatar.xml8
-rw-r--r--src/main/res/values/strings.xml2
18 files changed, 177 insertions, 98 deletions
diff --git a/build.gradle b/build.gradle
index f676b5f2e..b600e2418 100644
--- a/build.gradle
+++ b/build.gradle
@@ -61,8 +61,8 @@ android {
defaultConfig {
minSdkVersion 14
targetSdkVersion 23
- versionCode 130
- versionName "1.11.0-beta.2"
+ versionCode 131
+ versionName "1.11.0-beta.3"
archivesBaseName += "-$versionName"
applicationId "eu.siacs.conversations"
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java
index 3dfbd787c..be9d3d924 100644
--- a/src/main/java/eu/siacs/conversations/entities/Message.java
+++ b/src/main/java/eu/siacs/conversations/entities/Message.java
@@ -52,6 +52,7 @@ public class Message extends AbstractEntity {
public static final String STATUS = "status";
public static final String TYPE = "type";
public static final String CARBON = "carbon";
+ public static final String OOB = "oob";
public static final String EDITED = "edited";
public static final String REMOTE_MSG_ID = "remoteMsgId";
public static final String SERVER_MSG_ID = "serverMsgId";
@@ -72,6 +73,7 @@ public class Message extends AbstractEntity {
protected int status;
protected int type;
protected boolean carbon = false;
+ protected boolean oob = false;
protected String edited = null;
protected String relativeFilePath;
protected boolean read = true;
@@ -107,7 +109,8 @@ public class Message extends AbstractEntity {
null,
null,
true,
- null);
+ null,
+ false);
this.conversation = conversation;
}
@@ -116,7 +119,7 @@ public class Message extends AbstractEntity {
final int encryption, final int status, final int type, final boolean carbon,
final String remoteMsgId, final String relativeFilePath,
final String serverMsgId, final String fingerprint, final boolean read,
- final String edited) {
+ final String edited, final boolean oob) {
this.uuid = uuid;
this.conversationUuid = conversationUUid;
this.counterpart = counterpart;
@@ -133,6 +136,7 @@ public class Message extends AbstractEntity {
this.axolotlFingerprint = fingerprint;
this.read = read;
this.edited = edited;
+ this.oob = oob;
}
public static Message fromCursor(Cursor cursor) {
@@ -173,7 +177,8 @@ public class Message extends AbstractEntity {
cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)),
cursor.getString(cursor.getColumnIndex(FINGERPRINT)),
cursor.getInt(cursor.getColumnIndex(READ)) > 0,
- cursor.getString(cursor.getColumnIndex(EDITED)));
+ cursor.getString(cursor.getColumnIndex(EDITED)),
+ cursor.getInt(cursor.getColumnIndex(OOB)) > 0);
}
public static Message createStatusMessage(Conversation conversation, String body) {
@@ -219,6 +224,7 @@ public class Message extends AbstractEntity {
values.put(FINGERPRINT, axolotlFingerprint);
values.put(READ,read ? 1 : 0);
values.put(EDITED, edited);
+ values.put(OOB, oob ? 1 : 0);
return values;
}
@@ -554,6 +560,10 @@ public class Message extends AbstractEntity {
return edited;
}
+ public void setOob(boolean isOob) {
+ this.oob = isOob;
+ }
+
public enum Decision {
MUST,
SHOULD,
@@ -576,7 +586,7 @@ public class Message extends AbstractEntity {
if (dotPosition != -1) {
String extension = filename.substring(dotPosition + 1);
// we want the real file extension, not the crypto one
- if (Arrays.asList(Transferable.VALID_CRYPTO_EXTENSIONS).contains(extension)) {
+ if (Transferable.VALID_CRYPTO_EXTENSIONS.contains(extension)) {
return extractRelevantExtension(filename.substring(0,dotPosition));
} else {
return extension;
@@ -610,6 +620,8 @@ public class Message extends AbstractEntity {
URL url = new URL(body);
if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) {
return Decision.NEVER;
+ } else if (oob) {
+ return Decision.MUST;
}
String extension = extractRelevantExtension(url);
if (extension == null) {
@@ -624,8 +636,8 @@ public class Message extends AbstractEntity {
} else {
return Decision.NEVER;
}
- } else if (Arrays.asList(Transferable.VALID_IMAGE_EXTENSIONS).contains(extension)
- || Arrays.asList(Transferable.WELL_KNOWN_EXTENSIONS).contains(extension)) {
+ } else if (Transferable.VALID_IMAGE_EXTENSIONS.contains(extension)
+ || Transferable.WELL_KNOWN_EXTENSIONS.contains(extension)) {
return Decision.SHOULD;
} else {
return Decision.NEVER;
diff --git a/src/main/java/eu/siacs/conversations/entities/Transferable.java b/src/main/java/eu/siacs/conversations/entities/Transferable.java
index 859cda658..383db7b6a 100644
--- a/src/main/java/eu/siacs/conversations/entities/Transferable.java
+++ b/src/main/java/eu/siacs/conversations/entities/Transferable.java
@@ -1,59 +1,60 @@
package eu.siacs.conversations.entities;
-public interface Transferable {
-
- String[] VALID_IMAGE_EXTENSIONS = {
- "webp",
- "jpeg",
- "jpg",
- "png",
- "jpe",
- "gif",
- "tif"
- };
- String[] VALID_CRYPTO_EXTENSIONS = {
- "pgp",
- "gpg",
- "otr"
- };
- String[] WELL_KNOWN_EXTENSIONS = {
- //documents
- "pdf",
- "doc",
- "docx",
- "txt",
- //audio
- "m4a",
- "m4b",
- "mp3",
- "mp2",
- "wav",
- "aac",
- "aif",
- "aiff",
- "aifc",
- "mid",
- "midi",
- "3gpp",
- //video
- "avi",
- "mp4",
- "mpeg",
- "mpg",
- "mpe",
- "mov",
- "3gp",
- //applications
- "apk",
- //contact
- "vcf",
- //calendar
- "ics",
- //compressed
- "zip",
- "rar",
+import java.util.Arrays;
+import java.util.List;
- };
+public interface Transferable {
+ List<String> VALID_IMAGE_EXTENSIONS = Arrays.asList(
+ "webp",
+ "jpeg",
+ "jpg",
+ "png",
+ "jpe",
+ "gif",
+ "tif"
+ );
+ List<String> VALID_CRYPTO_EXTENSIONS = Arrays.asList(
+ "pgp",
+ "gpg",
+ "otr"
+ );
+ List<String> WELL_KNOWN_EXTENSIONS = Arrays.asList(
+ //documents
+ "pdf",
+ "doc",
+ "docx",
+ "txt",
+ //audio
+ "m4a",
+ "m4b",
+ "mp3",
+ "mp2",
+ "wav",
+ "aac",
+ "aif",
+ "aiff",
+ "aifc",
+ "mid",
+ "midi",
+ "3gpp",
+ //video
+ "avi",
+ "mp4",
+ "mpeg",
+ "mpg",
+ "mpe",
+ "mov",
+ "3gp",
+ //applications
+ "apk",
+ //contact
+ "vcf",
+ //calendar
+ "ics",
+ //compressed
+ "zip",
+ "rar",
+ );
int STATUS_UNKNOWN = 0x200;
int STATUS_CHECKING = 0x201;
diff --git a/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java
index 455a0b14b..84a44715b 100644
--- a/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java
+++ b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java
@@ -89,7 +89,7 @@ public class HttpDownloadConnection implements Transferable {
this.message.setEncryption(Message.ENCRYPTION_NONE);
}
String extension;
- if (Arrays.asList(VALID_CRYPTO_EXTENSIONS).contains(lastPart)) {
+ if (VALID_CRYPTO_EXTENSIONS.contains(lastPart)) {
extension = secondToLast;
} else {
extension = lastPart;
diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
index fd2d070ce..9470dab88 100644
--- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
@@ -6,6 +6,7 @@ import android.util.Pair;
import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionStatus;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;
@@ -290,7 +291,9 @@ public class MessageParser extends AbstractParser implements
final String body = packet.getBody();
final Element mucUserElement = packet.findChild("x", "http://jabber.org/protocol/muc#user");
final String pgpEncrypted = packet.findChildContent("x", "jabber:x:encrypted");
- final Element replaceElement = packet.findChild("replace","urn:xmpp:message-correct:0");
+ final Element replaceElement = packet.findChild("replace", "urn:xmpp:message-correct:0");
+ final Element oob = packet.findChild("x", "jabber:x:oob");
+ final boolean isOob = oob!= null && body != null && body.equals(oob.findChildContent("url"));
final String replacementId = replaceElement == null ? null : replaceElement.getAttribute("id");
final Element axolotlEncrypted = packet.findChild(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX);
int status;
@@ -384,6 +387,7 @@ public class MessageParser extends AbstractParser implements
message.setServerMsgId(serverMsgId);
message.setCarbon(isCarbon);
message.setTime(timestamp);
+ message.setOob(isOob);
message.markable = packet.hasChild("markable", "urn:xmpp:chat-markers:0");
if (conversation.getMode() == Conversation.MODE_MULTI) {
Jid trueCounterpart = conversation.getMucOptions().getTrueCounterpart(counterpart.getResourcepart());
diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
index dcba4f748..b975a0017 100644
--- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
@@ -51,7 +51,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
private static DatabaseBackend instance = null;
private static final String DATABASE_NAME = "history";
- private static final int DATABASE_VERSION = 24;
+ private static final int DATABASE_VERSION = 25;
private static String CREATE_CONTATCS_STATEMENT = "create table "
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@@ -163,6 +163,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ Message.CARBON + " INTEGER, "
+ Message.EDITED + " TEXT, "
+ Message.READ + " NUMBER DEFAULT 1, "
+ + Message.OOB + " INTEGER, "
+ Message.REMOTE_MSG_ID + " TEXT, FOREIGN KEY("
+ Message.CONVERSATION + ") REFERENCES "
+ Conversation.TABLENAME + "(" + Conversation.UUID
@@ -375,6 +376,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
if (oldVersion < 24 && newVersion >= 24) {
db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " + Message.EDITED + " TEXT");
}
+
+ if (oldVersion < 25 && newVersion >= 25) {
+ db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " + Message.OOB + " INTEGER");
+ }
}
public static synchronized DatabaseBackend getInstance(Context context) {
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index 15e75d7f5..02c09a5f2 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -53,6 +53,7 @@ import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.Presence;
import eu.siacs.conversations.entities.Transferable;
import eu.siacs.conversations.entities.TransferablePlaceholder;
+import eu.siacs.conversations.http.HttpDownloadConnection;
import eu.siacs.conversations.services.MessageArchiveService;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.XmppActivity.OnPresenceSelected;
@@ -520,6 +521,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
private void populateContextMenu(ContextMenu menu) {
final Message m = this.selectedMessage;
+ final Transferable t = m.getTransferable();
Message relevantForCorrection = m;
while(relevantForCorrection.mergeable(relevantForCorrection.next())) {
relevantForCorrection = relevantForCorrection.next();
@@ -536,7 +538,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
MenuItem downloadFile = menu.findItem(R.id.download_file);
MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission);
if ((m.getType() == Message.TYPE_TEXT || m.getType() == Message.TYPE_PRIVATE)
- && m.getTransferable() == null
+ && t == null
&& !GeoHelper.isGeoUri(m.getBody())
&& m.treatAsDownloadable() != Message.Decision.MUST) {
copyText.setVisible(true);
@@ -550,7 +552,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
if ((m.getType() != Message.TYPE_TEXT
&& m.getType() != Message.TYPE_PRIVATE
- && m.getTransferable() == null)
+ && t == null)
|| (GeoHelper.isGeoUri(m.getBody()))) {
shareWith.setVisible(true);
}
@@ -559,15 +561,16 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
if (m.hasFileOnRemoteHost()
|| GeoHelper.isGeoUri(m.getBody())
- || m.treatAsDownloadable() == Message.Decision.MUST) {
+ || m.treatAsDownloadable() == Message.Decision.MUST
+ || (t != null && t instanceof HttpDownloadConnection)) {
copyUrl.setVisible(true);
}
- if ((m.getType() == Message.TYPE_TEXT && m.getTransferable() == null && m.treatAsDownloadable() != Message.Decision.NEVER)
- || (m.isFileOrImage() && m.getTransferable() instanceof TransferablePlaceholder && m.hasFileOnRemoteHost())){
+ if ((m.getType() == Message.TYPE_TEXT && t == null && m.treatAsDownloadable() != Message.Decision.NEVER)
+ || (m.isFileOrImage() && t instanceof TransferablePlaceholder && m.hasFileOnRemoteHost())){
downloadFile.setVisible(true);
downloadFile.setTitle(activity.getString(R.string.download_x_file,UIHelper.getFileDescriptionString(activity, m)));
}
- if ((m.getTransferable() != null && !(m.getTransferable() instanceof TransferablePlaceholder))
+ if ((t != null && !(t instanceof TransferablePlaceholder))
|| (m.isFileOrImage() && (m.getStatus() == Message.STATUS_WAITING
|| m.getStatus() == Message.STATUS_OFFERED))) {
cancelTransmission.setVisible(true);
diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
index 411407a19..828f39d84 100644
--- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
@@ -8,6 +8,8 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
@@ -28,13 +30,12 @@ import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.utils.ExifHelper;
import eu.siacs.conversations.utils.FileUtils;
import eu.siacs.conversations.utils.PhoneHelper;
-import eu.siacs.conversations.xmpp.jid.InvalidJidException;
-import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar;
public class PublishProfilePictureActivity extends XmppActivity {
- private static final int REQUEST_CHOOSE_FILE = 0xac23;
+ private static final int REQUEST_CHOOSE_FILE_AND_CROP = 0xac23;
+ private static final int REQUEST_CHOOSE_FILE = 0xac24;
private ImageView avatar;
private TextView accountTextView;
private TextView hintOrWarning;
@@ -139,7 +140,7 @@ public class PublishProfilePictureActivity extends XmppActivity {
@Override
public void onClick(View v) {
if (hasStoragePermission(REQUEST_CHOOSE_FILE)) {
- chooseAvatar();
+ chooseAvatar(false);
}
}
@@ -147,20 +148,22 @@ public class PublishProfilePictureActivity extends XmppActivity {
this.defaultUri = PhoneHelper.getSefliUri(getApplicationContext());
}
- private void chooseAvatar() {
+ private void chooseAvatar(boolean crop) {
Intent attachFileIntent = new Intent();
attachFileIntent.setType("image/*");
attachFileIntent.setAction(Intent.ACTION_GET_CONTENT);
Intent chooser = Intent.createChooser(attachFileIntent, getString(R.string.attach_file));
- startActivityForResult(chooser, REQUEST_CHOOSE_FILE);
+ startActivityForResult(chooser, crop ? REQUEST_CHOOSE_FILE_AND_CROP : REQUEST_CHOOSE_FILE);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (grantResults.length > 0)
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- if (requestCode == REQUEST_CHOOSE_FILE) {
- chooseAvatar();
+ if (requestCode == REQUEST_CHOOSE_FILE_AND_CROP) {
+ chooseAvatar(true);
+ } else if (requestCode == REQUEST_CHOOSE_FILE) {
+ chooseAvatar(false);
}
} else {
Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show();
@@ -168,11 +171,29 @@ public class PublishProfilePictureActivity extends XmppActivity {
}
@Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.publish_avatar, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (item.getItemId() == R.id.action_crop_image) {
+ if (hasStoragePermission(REQUEST_CHOOSE_FILE_AND_CROP)) {
+ chooseAvatar(true);
+ }
+ return true;
+ } else {
+ return onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
- case REQUEST_CHOOSE_FILE:
+ case REQUEST_CHOOSE_FILE_AND_CROP:
Uri source = data.getData();
String original = FileUtils.getPath(this, source);
if (original != null) {
@@ -182,9 +203,17 @@ public class PublishProfilePictureActivity extends XmppActivity {
final int size = getPixel(Config.AVATAR_SIZE);
Crop.of(source, destination).asSquare().withMaxSize(size, size).start(this);
break;
+ case REQUEST_CHOOSE_FILE:
+ this.avatarUri = data.getData();
+ if (xmppConnectionServiceBound) {
+ loadImageIntoPreview(this.avatarUri);
+ }
+ break;
case Crop.REQUEST_CROP:
this.avatarUri = Uri.fromFile(new File(getCacheDir(), "croppedAvatar"));
- loadImageIntoPreview(this.avatarUri);
+ if (xmppConnectionServiceBound) {
+ loadImageIntoPreview(this.avatarUri);
+ }
break;
}
} else {
@@ -249,21 +278,10 @@ public class PublishProfilePictureActivity extends XmppActivity {
}
}
- private Bitmap loadScaledBitmap(Uri uri, int reqSize) throws FileNotFoundException {
- final BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
- int rotation = ExifHelper.getOrientation(getContentResolver().openInputStream(uri));
- options.inSampleSize = FileBackend.calcSampleSize(options, reqSize);
- options.inJustDecodeBounds = false;
- Bitmap bm = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
- return FileBackend.rotate(bm,rotation);
- }
-
protected void loadImageIntoPreview(Uri uri) {
Bitmap bm = null;
try {
- bm = loadScaledBitmap(uri, getPixel(Config.AVATAR_SIZE));
+ bm = xmppConnectionService.getFileBackend().cropCenterSquare(uri, getPixel(Config.AVATAR_SIZE));
} catch (Exception e) {
e.printStackTrace();
}
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 45e54ded5..16bde282d 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
@@ -17,6 +17,7 @@ import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
+import android.text.util.Linkify;
import android.util.DisplayMetrics;
import android.util.Patterns;
import android.view.View;
@@ -31,9 +32,11 @@ import android.widget.TextView;
import android.widget.Toast;
import java.lang.ref.WeakReference;
+import java.net.URL;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
@@ -53,6 +56,11 @@ public class MessageAdapter extends ArrayAdapter<Message> {
private static final int SENT = 0;
private static final int RECEIVED = 1;
private static final int STATUS = 2;
+ private static final Pattern XMPP_PATTERN = Pattern
+ .compile("xmpp\\:(?:(?:["
+ + Patterns.GOOD_IRI_CHAR
+ + "\\;\\/\\?\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])"
+ + "|(?:\\%[a-fA-F0-9]{2}))+");
private ConversationActivity activity;
@@ -351,6 +359,9 @@ public class MessageAdapter extends ArrayAdapter<Message> {
urlCount++;
}
viewHolder.messageBody.setTextIsSelectable(urlCount <= 1);
+ viewHolder.messageBody.setAutoLinkMask(0);
+ Linkify.addLinks(viewHolder.messageBody, Linkify.WEB_URLS);
+ Linkify.addLinks(viewHolder.messageBody, XMPP_PATTERN, "xmpp");
} else {
viewHolder.messageBody.setText("");
viewHolder.messageBody.setTextIsSelectable(false);
@@ -628,8 +639,20 @@ public class MessageAdapter extends ArrayAdapter<Message> {
displayLocationMessage(viewHolder,message);
} else if (message.bodyIsHeart()) {
displayHeartMessage(viewHolder, message.getBody().trim());
- } else if (message.treatAsDownloadable() == Message.Decision.MUST || message.treatAsDownloadable() == Message.Decision.SHOULD) {
- displayDownloadableMessage(viewHolder, message, activity.getString(R.string.check_x_filesize, UIHelper.getFileDescriptionString(activity, message)));
+ } else if (message.treatAsDownloadable() == Message.Decision.MUST) {
+ try {
+ URL url = new URL(message.getBody());
+ displayDownloadableMessage(viewHolder,
+ message,
+ activity.getString(R.string.check_x_filesize_on_host,
+ UIHelper.getFileDescriptionString(activity, message),
+ url.getHost()));
+ } catch (Exception e) {
+ displayDownloadableMessage(viewHolder,
+ message,
+ activity.getString(R.string.check_x_filesize,
+ UIHelper.getFileDescriptionString(activity, message)));
+ }
} else {
displayTextMessage(viewHolder, message, darkBackground);
}
diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java
index 5e8af085c..8cae81171 100644
--- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java
+++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java
@@ -187,10 +187,13 @@ public class UIHelper {
UIHelper.getMessageDisplayName(message) + " "), false);
} else if (GeoHelper.isGeoUri(message.getBody())) {
if (message.getStatus() == Message.STATUS_RECEIVED) {
- return new Pair<>(context.getString(R.string.received_location),true);
+ return new Pair<>(context.getString(R.string.received_location), true);
} else {
return new Pair<>(context.getString(R.string.location), true);
}
+ } else if (message.treatAsDownloadable() == Message.Decision.MUST) {
+ return new Pair<>(context.getString(R.string.x_file_offered_for_download,
+ getFileDescriptionString(context,message)),true);
} else{
return new Pair<>(message.getBody().trim(), false);
}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
index a8e081a72..dcb13c233 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
@@ -322,14 +322,14 @@ public class JingleConnection implements Transferable {
String[] filename = fileNameElement.getContent()
.toLowerCase(Locale.US).toLowerCase().split("\\.");
String extension = filename[filename.length - 1];
- if (Arrays.asList(VALID_IMAGE_EXTENSIONS).contains(extension)) {
+ if (VALID_IMAGE_EXTENSIONS.contains(extension)) {
message.setType(Message.TYPE_IMAGE);
message.setRelativeFilePath(message.getUuid()+"."+extension);
- } else if (Arrays.asList(VALID_CRYPTO_EXTENSIONS).contains(
+ } else if (VALID_CRYPTO_EXTENSIONS.contains(
filename[filename.length - 1])) {
if (filename.length == 3) {
extension = filename[filename.length - 2];
- if (Arrays.asList(VALID_IMAGE_EXTENSIONS).contains(extension)) {
+ if (VALID_IMAGE_EXTENSIONS.contains(extension)) {
message.setType(Message.TYPE_IMAGE);
message.setRelativeFilePath(message.getUuid()+"."+extension);
} else {
diff --git a/src/main/res/drawable-hdpi/ic_crop_white_24dp.png b/src/main/res/drawable-hdpi/ic_crop_white_24dp.png
new file mode 100644
index 000000000..6cbb87ce8
--- /dev/null
+++ b/src/main/res/drawable-hdpi/ic_crop_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-mdpi/ic_crop_white_24dp.png b/src/main/res/drawable-mdpi/ic_crop_white_24dp.png
new file mode 100644
index 000000000..d606c0725
--- /dev/null
+++ b/src/main/res/drawable-mdpi/ic_crop_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xhdpi/ic_crop_white_24dp.png b/src/main/res/drawable-xhdpi/ic_crop_white_24dp.png
new file mode 100644
index 000000000..983af77f1
--- /dev/null
+++ b/src/main/res/drawable-xhdpi/ic_crop_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xxhdpi/ic_crop_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_crop_white_24dp.png
new file mode 100644
index 000000000..8c9eecb9c
--- /dev/null
+++ b/src/main/res/drawable-xxhdpi/ic_crop_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xxxhdpi/ic_crop_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_crop_white_24dp.png
new file mode 100644
index 000000000..35d5434af
--- /dev/null
+++ b/src/main/res/drawable-xxxhdpi/ic_crop_white_24dp.png
Binary files differ
diff --git a/src/main/res/menu/publish_avatar.xml b/src/main/res/menu/publish_avatar.xml
new file mode 100644
index 000000000..1bffb2961
--- /dev/null
+++ b/src/main/res/menu/publish_avatar.xml
@@ -0,0 +1,8 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/action_crop_image"
+ android:showAsAction="always"
+ android:icon="@drawable/ic_crop_white_24dp"
+ android:title="@string/select_image_and_crop"/>
+</menu> \ No newline at end of file
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 9247ba075..6f7190ec7 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -345,6 +345,7 @@
<string name="checking_x">Checking %s on HTTP host</string>
<string name="not_connected_try_again">You are not connected. Try again later</string>
<string name="check_x_filesize">Check %s size</string>
+ <string name="check_x_filesize_on_host">Check %1$s size on %2$s</string>
<string name="message_options">Message options</string>
<string name="copy_text">Copy text</string>
<string name="copy_original_url">Copy original URL</string>
@@ -625,4 +626,5 @@
<string name="correct_message">Correct message</string>
<string name="send_corrected_message">Send corrected message</string>
<string name="no_keys_just_confirm">You already trust this contact. By selecting \'done\' you are just confirming that %s is part of this conference.</string>
+ <string name="select_image_and_crop">Select image and crop</string>
</resources>