diff options
Diffstat (limited to 'src/main')
106 files changed, 2262 insertions, 1139 deletions
diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 779cbbe86..99a94a8fb 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -16,7 +16,7 @@ public final class Config { public static final int CARBON_GRACE_PERIOD = 60; public static final int MINI_GRACE_PERIOD = 750; - public static final int AVATAR_SIZE = 192; + public static final int AVATAR_SIZE = 384; public static final Bitmap.CompressFormat AVATAR_FORMAT = Bitmap.CompressFormat.WEBP; public static final int MESSAGE_MERGE_WINDOW = 20; @@ -32,6 +32,8 @@ public final class Config { public static final boolean EXTENDED_SM_LOGGING = true; // log stanza counts public static final boolean RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE = true; //setting to true might increase power consumption + public static final boolean ENCRYPT_ON_HTTP_UPLOADED = false; + public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000; public static final long MAM_MAX_CATCHUP = MILLISECONDS_IN_DAY / 2; public static final int MAM_MAX_MESSAGES = 500; diff --git a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java index ad5a41323..505c4b0f1 100644 --- a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java @@ -59,9 +59,9 @@ public class PgpEngine { message.setEncryption(Message.ENCRYPTION_DECRYPTED); final HttpConnectionManager manager = mXmppConnectionService.getHttpConnectionManager(); if (message.trusted() - && message.bodyContainsDownloadable() + && message.treatAsDownloadable() != Message.Decision.NEVER && manager.getAutoAcceptFileSize() > 0) { - manager.createNewConnection(message); + manager.createNewDownloadConnection(message); } callback.success(message); } @@ -98,7 +98,7 @@ public class PgpEngine { switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { case OpenPgpApi.RESULT_CODE_SUCCESS: - URL url = message.getImageParams().url; + URL url = message.getFileParams().url; mXmppConnectionService.getFileBackend().updateFileParams(message,url); message.setEncryption(Message.ENCRYPTION_DECRYPTED); PgpEngine.this.mXmppConnectionService @@ -143,11 +143,15 @@ public class PgpEngine { params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message .getConversation().getAccount().getJid().toBareJid().toString()); - if (message.getType() == Message.TYPE_TEXT) { + if (!message.needsUploading()) { params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); - - InputStream is = new ByteArrayInputStream(message.getBody() - .getBytes()); + String body; + if (message.hasFileOnRemoteHost()) { + body = message.getFileParams().url.toString(); + } else { + body = message.getBody(); + } + InputStream is = new ByteArrayInputStream(body.getBytes()); final OutputStream os = new ByteArrayOutputStream(); api.executeApiAsync(params, is, os, new IOpenPgpCallback() { @@ -184,7 +188,7 @@ public class PgpEngine { } } }); - } else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) { + } else { try { DownloadableFile inputFile = this.mXmppConnectionService .getFileBackend().getFile(message, true); diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1.java index 10cd3167e..c95a62df3 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1.java @@ -185,7 +185,7 @@ public class ScramSha1 extends SaslMechanism { case RESPONSE_SENT: final String clientCalculatedServerFinalMessage = "v=" + Base64.encodeToString(serverSignature, Base64.NO_WRAP); - if (!clientCalculatedServerFinalMessage.equals(new String(Base64.decode(challenge, Base64.DEFAULT)))) { + if (challenge == null || !clientCalculatedServerFinalMessage.equals(new String(Base64.decode(challenge, Base64.DEFAULT)))) { throw new AuthenticationException("Server final message does not match calculated final message"); } state = State.VALID_SERVER_RESPONSE; diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 6e6dcb6a0..f472361f2 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -44,6 +44,10 @@ public class Account extends AbstractEntity { public static final int OPTION_REGISTER = 2; public static final int OPTION_USECOMPRESSION = 3; + public boolean httpUploadAvailable() { + return xmppConnection != null && xmppConnection.getFeatures().httpUpload(); + } + public static enum State { DISABLED, OFFLINE, diff --git a/src/main/java/eu/siacs/conversations/entities/Downloadable.java b/src/main/java/eu/siacs/conversations/entities/Downloadable.java deleted file mode 100644 index d25bf93a8..000000000 --- a/src/main/java/eu/siacs/conversations/entities/Downloadable.java +++ /dev/null @@ -1,28 +0,0 @@ -package eu.siacs.conversations.entities; - -public interface Downloadable { - - public final String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; - public final String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; - - public static final int STATUS_UNKNOWN = 0x200; - public static final int STATUS_CHECKING = 0x201; - public static final int STATUS_FAILED = 0x202; - public static final int STATUS_OFFER = 0x203; - public static final int STATUS_DOWNLOADING = 0x204; - public static final int STATUS_DELETED = 0x205; - public static final int STATUS_OFFER_CHECK_FILESIZE = 0x206; - public static final int STATUS_UPLOADING = 0x207; - - public boolean start(); - - public int getStatus(); - - public long getFileSize(); - - public int getProgress(); - - public String getMimeType(); - - public void cancel(); -} diff --git a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java index 7c8f95d14..ae9ba1f1d 100644 --- a/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java +++ b/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java @@ -20,6 +20,8 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import eu.siacs.conversations.Config; +import eu.siacs.conversations.utils.MimeUtils; + import android.util.Log; public class DownloadableFile extends File { @@ -56,16 +58,11 @@ public class DownloadableFile extends File { public String getMimeType() { String path = this.getAbsolutePath(); - try { - String mime = URLConnection.guessContentTypeFromName(path.replace("#","")); - if (mime != null) { - return mime; - } else if (mime == null && path.endsWith(".webp")) { - return "image/webp"; - } else { - return ""; - } - } catch (final StringIndexOutOfBoundsException e) { + int start = path.lastIndexOf('.') + 1; + if (start < path.length()) { + String mime = MimeUtils.guessMimeTypeFromExtension(path.substring(start)); + return mime == null ? "" : mime; + } else { return ""; } } diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index a63d033d2..957c2a6d7 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -9,6 +9,7 @@ import java.util.Arrays; import eu.siacs.conversations.Config; import eu.siacs.conversations.utils.GeoHelper; +import eu.siacs.conversations.utils.MimeUtils; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; @@ -69,7 +70,7 @@ public class Message extends AbstractEntity { protected String remoteMsgId = null; protected String serverMsgId = null; protected Conversation conversation = null; - protected Downloadable downloadable = null; + protected Transferable transferable = null; private Message mNextMessage = null; private Message mPreviousMessage = null; @@ -307,12 +308,12 @@ public class Message extends AbstractEntity { this.trueCounterpart = trueCounterpart; } - public Downloadable getDownloadable() { - return this.downloadable; + public Transferable getTransferable() { + return this.transferable; } - public void setDownloadable(Downloadable downloadable) { - this.downloadable = downloadable; + public void setTransferable(Transferable transferable) { + this.transferable = transferable; } public boolean equals(Message message) { @@ -320,15 +321,25 @@ public class Message extends AbstractEntity { return this.serverMsgId.equals(message.getServerMsgId()); } else if (this.body == null || this.counterpart == null) { return false; - } else if (message.getRemoteMsgId() != null) { - return (message.getRemoteMsgId().equals(this.remoteMsgId) || message.getRemoteMsgId().equals(this.uuid)) - && this.counterpart.equals(message.getCounterpart()) - && this.body.equals(message.getBody()); } else { - return this.remoteMsgId == null - && this.counterpart.equals(message.getCounterpart()) - && this.body.equals(message.getBody()) - && Math.abs(this.getTimeSent() - message.getTimeSent()) < Config.MESSAGE_MERGE_WINDOW * 1000; + String body, otherBody; + if (this.hasFileOnRemoteHost()) { + body = getFileParams().url.toString(); + otherBody = message.body == null ? null : message.body.trim(); + } else { + body = this.body; + otherBody = message.body; + } + if (message.getRemoteMsgId() != null) { + return (message.getRemoteMsgId().equals(this.remoteMsgId) || message.getRemoteMsgId().equals(this.uuid)) + && this.counterpart.equals(message.getCounterpart()) + && body.equals(otherBody); + } else { + return this.remoteMsgId == null + && this.counterpart.equals(message.getCounterpart()) + && body.equals(otherBody) + && Math.abs(this.getTimeSent() - message.getTimeSent()) < Config.MESSAGE_MERGE_WINDOW * 1000; + } } } @@ -363,8 +374,8 @@ public class Message extends AbstractEntity { public boolean mergeable(final Message message) { return message != null && (message.getType() == Message.TYPE_TEXT && - this.getDownloadable() == null && - message.getDownloadable() == null && + this.getTransferable() == null && + message.getTransferable() == null && message.getEncryption() != Message.ENCRYPTION_PGP && this.getType() == message.getType() && //this.getStatus() == message.getStatus() && @@ -375,8 +386,8 @@ public class Message extends AbstractEntity { (message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) && !GeoHelper.isGeoUri(message.getBody()) && !GeoHelper.isGeoUri(this.body) && - !message.bodyContainsDownloadable() && - !this.bodyContainsDownloadable() && + message.treatAsDownloadable() == Decision.NEVER && + this.treatAsDownloadable() == Decision.NEVER && !message.getBody().startsWith(ME_COMMAND) && !this.getBody().startsWith(ME_COMMAND) && !this.bodyIsHeart() && @@ -434,48 +445,97 @@ public class Message extends AbstractEntity { return (status > STATUS_RECEIVED || (contact != null && contact.trusted())); } - public boolean bodyContainsDownloadable() { - /** - * there are a few cases where spaces result in an unwanted behavior, e.g. - * "http://example.com/image.jpg text that will not be shown /abc.png" - * or more than one image link in one message. - */ - if (body.trim().contains(" ")) { + public boolean fixCounterpart() { + Presences presences = conversation.getContact().getPresences(); + if (counterpart != null && presences.has(counterpart.getResourcepart())) { + return true; + } else if (presences.size() >= 1) { + try { + counterpart = Jid.fromParts(conversation.getJid().getLocalpart(), + conversation.getJid().getDomainpart(), + presences.asStringArray()[0]); + return true; + } catch (InvalidJidException e) { + counterpart = null; + return false; + } + } else { + counterpart = null; return false; } + } + + public enum Decision { + MUST, + SHOULD, + NEVER, + } + + private static String extractRelevantExtension(URL url) { + String path = url.getPath(); + if (path == null || path.isEmpty()) { + return null; + } + String filename = path.substring(path.lastIndexOf('/') + 1).toLowerCase(); + String[] extensionParts = filename.split("\\."); + if (extensionParts.length == 2) { + return extensionParts[extensionParts.length - 1]; + } else if (extensionParts.length == 3 && Arrays + .asList(Transferable.VALID_CRYPTO_EXTENSIONS) + .contains(extensionParts[extensionParts.length - 1])) { + return extensionParts[extensionParts.length -2]; + } + return null; + } + + public String getMimeType() { + if (relativeFilePath != null) { + int start = relativeFilePath.lastIndexOf('.') + 1; + if (start < relativeFilePath.length()) { + return MimeUtils.guessMimeTypeFromExtension(relativeFilePath.substring(start)); + } else { + return null; + } + } else { + try { + return MimeUtils.guessMimeTypeFromExtension(extractRelevantExtension(new URL(body.trim()))); + } catch (MalformedURLException e) { + return null; + } + } + } + + public Decision treatAsDownloadable() { + if (body.trim().contains(" ")) { + return Decision.NEVER; + } try { URL url = new URL(body); - if (!url.getProtocol().equalsIgnoreCase("http") - && !url.getProtocol().equalsIgnoreCase("https")) { - return false; + if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { + return Decision.NEVER; } - - String sUrlPath = url.getPath(); - if (sUrlPath == null || sUrlPath.isEmpty()) { - return false; + String extension = extractRelevantExtension(url); + if (extension == null) { + return Decision.NEVER; } + String ref = url.getRef(); + boolean encrypted = ref != null && ref.matches("([A-Fa-f0-9]{2}){48}"); - int iSlashIndex = sUrlPath.lastIndexOf('/') + 1; - - String sLastUrlPath = sUrlPath.substring(iSlashIndex).toLowerCase(); - - String[] extensionParts = sLastUrlPath.split("\\."); - if (extensionParts.length == 2 - && Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains( - extensionParts[extensionParts.length - 1])) { - return true; - } else if (extensionParts.length == 3 - && Arrays - .asList(Downloadable.VALID_CRYPTO_EXTENSIONS) - .contains(extensionParts[extensionParts.length - 1]) - && Arrays.asList(Downloadable.VALID_IMAGE_EXTENSIONS).contains( - extensionParts[extensionParts.length - 2])) { - return true; + if (encrypted) { + if (MimeUtils.guessMimeTypeFromExtension(extension) != null) { + return Decision.MUST; + } else { + return Decision.NEVER; + } + } else if (Arrays.asList(Transferable.VALID_IMAGE_EXTENSIONS).contains(extension) + || Arrays.asList(Transferable.WELL_KNOWN_EXTENSIONS).contains(extension)) { + return Decision.SHOULD; } else { - return false; + return Decision.NEVER; } + } catch (MalformedURLException e) { - return false; + return Decision.NEVER; } } @@ -483,74 +543,77 @@ public class Message extends AbstractEntity { return body != null && UIHelper.HEARTS.contains(body.trim()); } - public ImageParams getImageParams() { - ImageParams params = getLegacyImageParams(); + public FileParams getFileParams() { + FileParams params = getLegacyFileParams(); if (params != null) { return params; } - params = new ImageParams(); - if (this.downloadable != null) { - params.size = this.downloadable.getFileSize(); + params = new FileParams(); + if (this.transferable != null) { + params.size = this.transferable.getFileSize(); } if (body == null) { return params; } String parts[] = body.split("\\|"); - if (parts.length == 1) { - try { - params.size = Long.parseLong(parts[0]); - } catch (NumberFormatException e) { - params.origin = parts[0]; + switch (parts.length) { + case 1: + try { + params.size = Long.parseLong(parts[0]); + } catch (NumberFormatException e) { + try { + params.url = new URL(parts[0]); + } catch (MalformedURLException e1) { + params.url = null; + } + } + break; + case 2: + case 4: try { params.url = new URL(parts[0]); } catch (MalformedURLException e1) { params.url = null; } - } - } else if (parts.length == 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; - } - } else if (parts.length == 4) { - params.origin = parts[0]; - 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 e) { - params.width = 0; - } - try { - params.height = Integer.parseInt(parts[3]); - } catch (NumberFormatException e) { - params.height = 0; - } + 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; } return params; } - public ImageParams getLegacyImageParams() { - ImageParams params = new ImageParams(); + public FileParams getLegacyFileParams() { + FileParams params = new FileParams(); if (body == null) { return params; } @@ -586,11 +649,18 @@ public class Message extends AbstractEntity { return type == TYPE_FILE || type == TYPE_IMAGE; } - public class ImageParams { + public boolean hasFileOnRemoteHost() { + return isFileOrImage() && getFileParams().url != null; + } + + public boolean needsUploading() { + return isFileOrImage() && getFileParams().url == null; + } + + public class FileParams { public URL url; public long size = 0; public int width = 0; public int height = 0; - public String origin; } } diff --git a/src/main/java/eu/siacs/conversations/entities/Roster.java b/src/main/java/eu/siacs/conversations/entities/Roster.java index d6777ef63..628a31d1c 100644 --- a/src/main/java/eu/siacs/conversations/entities/Roster.java +++ b/src/main/java/eu/siacs/conversations/entities/Roster.java @@ -74,6 +74,9 @@ public class Roster { } public void initContact(final Contact contact) { + if (contact == null) { + return; + } contact.setAccount(account); contact.setOption(Contact.Options.IN_ROSTER); synchronized (this.contacts) { diff --git a/src/main/java/eu/siacs/conversations/entities/Transferable.java b/src/main/java/eu/siacs/conversations/entities/Transferable.java new file mode 100644 index 000000000..56489774b --- /dev/null +++ b/src/main/java/eu/siacs/conversations/entities/Transferable.java @@ -0,0 +1,28 @@ +package eu.siacs.conversations.entities; + +public interface Transferable { + + String[] VALID_IMAGE_EXTENSIONS = {"webp", "jpeg", "jpg", "png", "jpe"}; + String[] VALID_CRYPTO_EXTENSIONS = {"pgp", "gpg", "otr"}; + String[] WELL_KNOWN_EXTENSIONS = {"pdf","m4a","mp3","avi","mp4","apk","vcf"}; + + int STATUS_UNKNOWN = 0x200; + int STATUS_CHECKING = 0x201; + int STATUS_FAILED = 0x202; + int STATUS_OFFER = 0x203; + int STATUS_DOWNLOADING = 0x204; + int STATUS_DELETED = 0x205; + int STATUS_OFFER_CHECK_FILESIZE = 0x206; + int STATUS_UPLOADING = 0x207; + + + boolean start(); + + int getStatus(); + + long getFileSize(); + + int getProgress(); + + void cancel(); +} diff --git a/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java b/src/main/java/eu/siacs/conversations/entities/TransferablePlaceholder.java index 03fceceb7..e065953ef 100644 --- a/src/main/java/eu/siacs/conversations/entities/DownloadablePlaceholder.java +++ b/src/main/java/eu/siacs/conversations/entities/TransferablePlaceholder.java @@ -1,10 +1,10 @@ package eu.siacs.conversations.entities; -public class DownloadablePlaceholder implements Downloadable { +public class TransferablePlaceholder implements Transferable { private int status; - public DownloadablePlaceholder(int status) { + public TransferablePlaceholder(int status) { this.status = status; } @Override @@ -28,11 +28,6 @@ public class DownloadablePlaceholder implements Downloadable { } @Override - public String getMimeType() { - return ""; - } - - @Override public void cancel() { } diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java index d7366daa8..47915e3fb 100644 --- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java @@ -6,6 +6,7 @@ import java.util.List; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.services.MessageArchiveService; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.PhoneHelper; @@ -102,7 +103,7 @@ public class IqGenerator extends AbstractGenerator { public IqPacket retrieveVcardAvatar(final Avatar avatar) { final IqPacket packet = new IqPacket(IqPacket.TYPE.GET); packet.setTo(avatar.owner); - packet.addChild("vCard","vcard-temp"); + packet.addChild("vCard", "vcard-temp"); return packet; } @@ -194,4 +195,13 @@ public class IqGenerator extends AbstractGenerator { item.setAttribute("role", role); return packet; } + + public IqPacket requestHttpUploadSlot(Jid host, DownloadableFile file) { + IqPacket packet = new IqPacket(IqPacket.TYPE.GET); + packet.setTo(host); + Element request = packet.addChild("request",Xmlns.HTTP_UPLOAD); + request.addChild("filename").setContent(file.getName()); + request.addChild("size").setContent(String.valueOf(file.getExpectedSize())); + return packet; + } } diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index 474a3e1dc..bc1148d9a 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -73,7 +73,13 @@ public class MessageGenerator extends AbstractGenerator { packet.addChild("no-copy", "urn:xmpp:hints"); packet.addChild("no-permanent-store", "urn:xmpp:hints"); try { - packet.setBody(otrSession.transformSending(message.getBody())[0]); + String content; + if (message.hasFileOnRemoteHost()) { + content = message.getFileParams().url.toString(); + } else { + content = message.getBody(); + } + packet.setBody(otrSession.transformSending(content)[0]); return packet; } catch (OtrException e) { return null; @@ -86,7 +92,11 @@ public class MessageGenerator extends AbstractGenerator { public MessagePacket generateChat(Message message, boolean addDelay) { MessagePacket packet = preparePacket(message, addDelay); - packet.setBody(message.getBody()); + if (message.hasFileOnRemoteHost()) { + packet.setBody(message.getFileParams().url.toString()); + } else { + packet.setBody(message.getBody()); + } return packet; } @@ -96,13 +106,11 @@ public class MessageGenerator extends AbstractGenerator { public MessagePacket generatePgpChat(Message message, boolean addDelay) { MessagePacket packet = preparePacket(message, addDelay); - packet.setBody("This is an XEP-0027 encryted message"); + packet.setBody("This is an XEP-0027 encrypted message"); if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { - packet.addChild("x", "jabber:x:encrypted").setContent( - message.getEncryptedBody()); + packet.addChild("x", "jabber:x:encrypted").setContent(message.getEncryptedBody()); } else if (message.getEncryption() == Message.ENCRYPTION_PGP) { - packet.addChild("x", "jabber:x:encrypted").setContent( - message.getBody()); + packet.addChild("x", "jabber:x:encrypted").setContent(message.getBody()); } return packet; } diff --git a/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java b/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java index 9a2a24052..58a6d1e37 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java @@ -1,11 +1,22 @@ package eu.siacs.conversations.http; +import org.apache.http.conn.ssl.StrictHostnameVerifier; + +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; + import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.utils.CryptoHelper; public class HttpConnectionManager extends AbstractConnectionManager { @@ -13,16 +24,67 @@ public class HttpConnectionManager extends AbstractConnectionManager { super(service); } - private List<HttpConnection> connections = new CopyOnWriteArrayList<HttpConnection>(); + private List<HttpDownloadConnection> downloadConnections = new CopyOnWriteArrayList<>(); + private List<HttpUploadConnection> uploadConnections = new CopyOnWriteArrayList<>(); + + public HttpDownloadConnection createNewDownloadConnection(Message message) { + return this.createNewDownloadConnection(message, false); + } + + public HttpDownloadConnection createNewDownloadConnection(Message message, boolean interactive) { + HttpDownloadConnection connection = new HttpDownloadConnection(this); + connection.init(message,interactive); + this.downloadConnections.add(connection); + return connection; + } - public HttpConnection createNewConnection(Message message) { - HttpConnection connection = new HttpConnection(this); + public HttpUploadConnection createNewUploadConnection(Message message) { + HttpUploadConnection connection = new HttpUploadConnection(this); connection.init(message); - this.connections.add(connection); + this.uploadConnections.add(connection); return connection; } - public void finishConnection(HttpConnection connection) { - this.connections.remove(connection); + public void finishConnection(HttpDownloadConnection connection) { + this.downloadConnections.remove(connection); + } + + public void finishUploadConnection(HttpUploadConnection httpUploadConnection) { + this.uploadConnections.remove(httpUploadConnection); + } + + public void setupTrustManager(final HttpsURLConnection connection, final boolean interactive) { + final X509TrustManager trustManager; + final HostnameVerifier hostnameVerifier; + if (interactive) { + trustManager = mXmppConnectionService.getMemorizingTrustManager(); + hostnameVerifier = mXmppConnectionService + .getMemorizingTrustManager().wrapHostnameVerifier( + new StrictHostnameVerifier()); + } else { + trustManager = mXmppConnectionService.getMemorizingTrustManager() + .getNonInteractive(); + hostnameVerifier = mXmppConnectionService + .getMemorizingTrustManager() + .wrapHostnameVerifierNonInteractive( + new StrictHostnameVerifier()); + } + try { + final SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, new X509TrustManager[]{trustManager}, + mXmppConnectionService.getRNG()); + + final SSLSocketFactory sf = sc.getSocketFactory(); + final String[] cipherSuites = CryptoHelper.getOrderedCipherSuites( + sf.getSupportedCipherSuites()); + if (cipherSuites.length > 0) { + sc.getDefaultSSLParameters().setCipherSuites(cipherSuites); + + } + + connection.setSSLSocketFactory(sf); + connection.setHostnameVerifier(hostnameVerifier); + } catch (final KeyManagementException | NoSuchAlgorithmException ignored) { + } } } diff --git a/src/main/java/eu/siacs/conversations/http/HttpConnection.java b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java index e7d309190..62fe4191d 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpConnection.java +++ b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java @@ -3,8 +3,7 @@ package eu.siacs.conversations.http; import android.content.Intent; import android.net.Uri; import android.os.SystemClock; - -import org.apache.http.conn.ssl.StrictHostnameVerifier; +import android.util.Log; import java.io.BufferedInputStream; import java.io.IOException; @@ -12,25 +11,20 @@ import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; import java.util.Arrays; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.X509TrustManager; import eu.siacs.conversations.Config; -import eu.siacs.conversations.entities.Downloadable; +import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.CryptoHelper; -public class HttpConnection implements Downloadable { +public class HttpDownloadConnection implements Transferable { private HttpConnectionManager mHttpConnectionManager; private XmppConnectionService mXmppConnectionService; @@ -38,12 +32,12 @@ public class HttpConnection implements Downloadable { private URL mUrl; private Message message; private DownloadableFile file; - private int mStatus = Downloadable.STATUS_UNKNOWN; + private int mStatus = Transferable.STATUS_UNKNOWN; private boolean acceptedAutomatically = false; private int mProgress = 0; private long mLastGuiRefresh = 0; - public HttpConnection(HttpConnectionManager manager) { + public HttpDownloadConnection(HttpConnectionManager manager) { this.mHttpConnectionManager = manager; this.mXmppConnectionService = manager.getXmppConnectionService(); } @@ -63,8 +57,12 @@ public class HttpConnection implements Downloadable { } public void init(Message message) { + init(message, false); + } + + public void init(Message message, boolean interactive) { this.message = message; - this.message.setDownloadable(this); + this.message.setTransferable(this); try { mUrl = new URL(message.getBody()); String[] parts = mUrl.getPath().toLowerCase().split("\\."); @@ -92,7 +90,7 @@ public class HttpConnection implements Downloadable { && this.file.getKey() == null) { this.message.setEncryption(Message.ENCRYPTION_NONE); } - checkFileSize(false); + checkFileSize(interactive); } catch (MalformedURLException e) { this.cancel(); } @@ -104,7 +102,7 @@ public class HttpConnection implements Downloadable { public void cancel() { mHttpConnectionManager.finishConnection(this); - message.setDownloadable(null); + message.setTransferable(null); mXmppConnectionService.updateConversationUi(); } @@ -112,7 +110,7 @@ public class HttpConnection implements Downloadable { Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(Uri.fromFile(file)); mXmppConnectionService.sendBroadcast(intent); - message.setDownloadable(null); + message.setTransferable(null); mHttpConnectionManager.finishConnection(this); mXmppConnectionService.updateConversationUi(); if (acceptedAutomatically) { @@ -125,42 +123,6 @@ public class HttpConnection implements Downloadable { mXmppConnectionService.updateConversationUi(); } - private void setupTrustManager(final HttpsURLConnection connection, - final boolean interactive) { - final X509TrustManager trustManager; - final HostnameVerifier hostnameVerifier; - if (interactive) { - trustManager = mXmppConnectionService.getMemorizingTrustManager(); - hostnameVerifier = mXmppConnectionService - .getMemorizingTrustManager().wrapHostnameVerifier( - new StrictHostnameVerifier()); - } else { - trustManager = mXmppConnectionService.getMemorizingTrustManager() - .getNonInteractive(); - hostnameVerifier = mXmppConnectionService - .getMemorizingTrustManager() - .wrapHostnameVerifierNonInteractive( - new StrictHostnameVerifier()); - } - try { - final SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(null, new X509TrustManager[]{trustManager}, - mXmppConnectionService.getRNG()); - - final SSLSocketFactory sf = sc.getSocketFactory(); - final String[] cipherSuites = CryptoHelper.getOrderedCipherSuites( - sf.getSupportedCipherSuites()); - if (cipherSuites.length > 0) { - sc.getDefaultSSLParameters().setCipherSuites(cipherSuites); - - } - - connection.setSSLSocketFactory(sf); - connection.setHostnameVerifier(hostnameVerifier); - } catch (final KeyManagementException | NoSuchAlgorithmException ignored) { - } - } - private class FileSizeChecker implements Runnable { private boolean interactive = false; @@ -176,43 +138,46 @@ public class HttpConnection implements Downloadable { size = retrieveFileSize(); } catch (SSLHandshakeException e) { changeStatus(STATUS_OFFER_CHECK_FILESIZE); - HttpConnection.this.acceptedAutomatically = false; - HttpConnection.this.mXmppConnectionService.getNotificationService().push(message); + HttpDownloadConnection.this.acceptedAutomatically = false; + HttpDownloadConnection.this.mXmppConnectionService.getNotificationService().push(message); return; } catch (IOException e) { + Log.d(Config.LOGTAG, "io exception in http file size checker: " + e.getMessage()); + if (interactive) { + mXmppConnectionService.showErrorToastInUi(R.string.file_not_found_on_remote_host); + } cancel(); return; } file.setExpectedSize(size); if (size <= mHttpConnectionManager.getAutoAcceptFileSize()) { - HttpConnection.this.acceptedAutomatically = true; + HttpDownloadConnection.this.acceptedAutomatically = true; new Thread(new FileDownloader(interactive)).start(); } else { changeStatus(STATUS_OFFER); - HttpConnection.this.acceptedAutomatically = false; - HttpConnection.this.mXmppConnectionService.getNotificationService().push(message); + HttpDownloadConnection.this.acceptedAutomatically = false; + HttpDownloadConnection.this.mXmppConnectionService.getNotificationService().push(message); } } - private long retrieveFileSize() throws IOException, - SSLHandshakeException { - changeStatus(STATUS_CHECKING); - HttpURLConnection connection = (HttpURLConnection) mUrl - .openConnection(); - connection.setRequestMethod("HEAD"); - if (connection instanceof HttpsURLConnection) { - setupTrustManager((HttpsURLConnection) connection, interactive); - } - connection.connect(); - String contentLength = connection.getHeaderField("Content-Length"); - if (contentLength == null) { - throw new IOException(); - } - try { - return Long.parseLong(contentLength, 10); - } catch (NumberFormatException e) { - throw new IOException(); - } + private long retrieveFileSize() throws IOException { + Log.d(Config.LOGTAG,"retrieve file size. interactive:"+String.valueOf(interactive)); + changeStatus(STATUS_CHECKING); + HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection(); + connection.setRequestMethod("HEAD"); + if (connection instanceof HttpsURLConnection) { + mHttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, interactive); + } + connection.connect(); + String contentLength = connection.getHeaderField("Content-Length"); + if (contentLength == null) { + throw new IOException(); + } + try { + return Long.parseLong(contentLength, 10); + } catch (NumberFormatException e) { + throw new IOException(); + } } } @@ -235,19 +200,18 @@ public class HttpConnection implements Downloadable { } catch (SSLHandshakeException e) { changeStatus(STATUS_OFFER); } catch (IOException e) { + mXmppConnectionService.showErrorToastInUi(R.string.file_not_found_on_remote_host); cancel(); } } private void download() throws SSLHandshakeException, IOException { - HttpURLConnection connection = (HttpURLConnection) mUrl - .openConnection(); + HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection(); if (connection instanceof HttpsURLConnection) { - setupTrustManager((HttpsURLConnection) connection, interactive); + mHttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, interactive); } connection.connect(); - BufferedInputStream is = new BufferedInputStream( - connection.getInputStream()); + BufferedInputStream is = new BufferedInputStream(connection.getInputStream()); file.getParentFile().mkdirs(); file.createNewFile(); OutputStream os = file.createOutputStream(); @@ -269,8 +233,8 @@ public class HttpConnection implements Downloadable { } private void updateImageBounds() { - message.setType(Message.TYPE_IMAGE); - mXmppConnectionService.getFileBackend().updateFileParams(message,mUrl); + message.setType(Message.TYPE_FILE); + mXmppConnectionService.getFileBackend().updateFileParams(message, mUrl); mXmppConnectionService.updateMessage(message); } @@ -302,9 +266,4 @@ public class HttpConnection implements Downloadable { public int getProgress() { return this.mProgress; } - - @Override - public String getMimeType() { - return ""; - } } diff --git a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java new file mode 100644 index 000000000..dd8427541 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java @@ -0,0 +1,204 @@ +package eu.siacs.conversations.http; + +import android.app.PendingIntent; +import android.util.Log; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +import javax.net.ssl.HttpsURLConnection; + +import eu.siacs.conversations.Config; +import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Transferable; +import eu.siacs.conversations.entities.DownloadableFile; +import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.persistance.FileBackend; +import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.ui.UiCallback; +import eu.siacs.conversations.utils.CryptoHelper; +import eu.siacs.conversations.utils.Xmlns; +import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.OnIqPacketReceived; +import eu.siacs.conversations.xmpp.jid.Jid; +import eu.siacs.conversations.xmpp.stanzas.IqPacket; + +public class HttpUploadConnection implements Transferable { + + private HttpConnectionManager mHttpConnectionManager; + private XmppConnectionService mXmppConnectionService; + + private boolean canceled = false; + private Account account; + private DownloadableFile file; + private Message message; + private URL mGetUrl; + private URL mPutUrl; + + private byte[] key = null; + + private long transmitted = 0; + private long expected = 1; + + public HttpUploadConnection(HttpConnectionManager httpConnectionManager) { + this.mHttpConnectionManager = httpConnectionManager; + this.mXmppConnectionService = httpConnectionManager.getXmppConnectionService(); + } + + @Override + public boolean start() { + return false; + } + + @Override + public int getStatus() { + return STATUS_UPLOADING; + } + + @Override + public long getFileSize() { + return this.file.getExpectedSize(); + } + + @Override + public int getProgress() { + return (int) ((((double) transmitted) / expected) * 100); + } + + @Override + public void cancel() { + this.canceled = true; + } + + private void fail() { + mHttpConnectionManager.finishUploadConnection(this); + message.setTransferable(null); + mXmppConnectionService.markMessage(message,Message.STATUS_SEND_FAILED); + } + + public void init(Message message) { + this.message = message; + message.setTransferable(this); + mXmppConnectionService.markMessage(message,Message.STATUS_UNSEND); + this.account = message.getConversation().getAccount(); + this.file = mXmppConnectionService.getFileBackend().getFile(message, false); + this.file.setExpectedSize(this.file.getSize()); + + if (Config.ENCRYPT_ON_HTTP_UPLOADED) { + this.key = new byte[48]; + mXmppConnectionService.getRNG().nextBytes(this.key); + this.file.setKey(this.key); + } + + Jid host = account.getXmppConnection().findDiscoItemByFeature(Xmlns.HTTP_UPLOAD); + IqPacket request = mXmppConnectionService.getIqGenerator().requestHttpUploadSlot(host,file); + mXmppConnectionService.sendIqPacket(account, request, new OnIqPacketReceived() { + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + if (packet.getType() == IqPacket.TYPE.RESULT) { + Element slot = packet.findChild("slot",Xmlns.HTTP_UPLOAD); + if (slot != null) { + try { + mGetUrl = new URL(slot.findChildContent("get")); + mPutUrl = new URL(slot.findChildContent("put")); + if (!canceled) { + new Thread(new FileUploader()).start(); + } + } catch (MalformedURLException e) { + fail(); + } + } else { + fail(); + } + } else { + fail(); + } + } + }); + } + + private class FileUploader implements Runnable { + + @Override + public void run() { + this.upload(); + } + + private void upload() { + OutputStream os = null; + InputStream is = null; + HttpURLConnection connection = null; + try { + Log.d(Config.LOGTAG, "uploading to " + mPutUrl.toString()); + connection = (HttpURLConnection) mPutUrl.openConnection(); + if (connection instanceof HttpsURLConnection) { + mHttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, true); + } + connection.setRequestMethod("PUT"); + connection.setFixedLengthStreamingMode((int) file.getExpectedSize()); + connection.setDoOutput(true); + connection.connect(); + os = connection.getOutputStream(); + is = file.createInputStream(); + transmitted = 0; + expected = file.getExpectedSize(); + int count = -1; + byte[] buffer = new byte[4096]; + while (((count = is.read(buffer)) != -1) && !canceled) { + transmitted += count; + os.write(buffer, 0, count); + mXmppConnectionService.updateConversationUi(); + } + os.flush(); + os.close(); + is.close(); + int code = connection.getResponseCode(); + if (code == 200) { + Log.d(Config.LOGTAG, "finished uploading file"); + Message.FileParams params = message.getFileParams(); + if (key != null) { + mGetUrl = new URL(mGetUrl.toString() + "#" + CryptoHelper.bytesToHex(key)); + } + mXmppConnectionService.getFileBackend().updateFileParams(message, mGetUrl); + message.setTransferable(null); + message.setCounterpart(message.getConversation().getJid().toBareJid()); + if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { + mXmppConnectionService.getPgpEngine().encrypt(message, new UiCallback<Message>() { + @Override + public void success(Message message) { + mXmppConnectionService.resendMessage(message); + } + + @Override + public void error(int errorCode, Message object) { + fail(); + } + + @Override + public void userInputRequried(PendingIntent pi, Message object) { + fail(); + } + }); + } else { + mXmppConnectionService.resendMessage(message); + } + } else { + fail(); + } + } catch (IOException e) { + Log.d(Config.LOGTAG, e.getMessage()); + fail(); + } finally { + FileBackend.close(is); + FileBackend.close(os); + if (connection != null) { + connection.disconnect(); + } + } + } + } +} diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 5a40b1708..d46ff1950 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -239,6 +239,12 @@ public class MessageParser extends AbstractParser implements final Jid to = packet.getTo(); final Jid from = packet.getFrom(); final String remoteMsgId = packet.getId(); + + if (from == null || to == null) { + Log.d(Config.LOGTAG,"no to or from in: "+packet.toString()); + return; + } + boolean isTypeGroupChat = packet.getType() == MessagePacket.TYPE_GROUPCHAT; boolean isProperlyAddressed = !to.isBareJid() || account.countPresences() == 1; boolean isMucStatusMessage = from.isBareJid() && mucUserElement != null && mucUserElement.hasChild("status"); @@ -250,11 +256,6 @@ public class MessageParser extends AbstractParser implements counterpart = from; } - if (from == null || to == null) { - Log.d(Config.LOGTAG,"no to or from in: "+packet.toString()); - return; - } - Invite invite = extractInvite(packet); if (invite != null && invite.execute(account)) { return; @@ -360,8 +361,8 @@ public class MessageParser extends AbstractParser implements mXmppConnectionService.databaseBackend.createMessage(message); } final HttpConnectionManager manager = this.mXmppConnectionService.getHttpConnectionManager(); - if (message.trusted() && message.bodyContainsDownloadable() && manager.getAutoAcceptFileSize() > 0) { - manager.createNewConnection(message); + if (message.trusted() && message.treatAsDownloadable() != Message.Decision.NEVER && manager.getAutoAcceptFileSize() > 0) { + manager.createNewDownloadConnection(message); } else if (!message.isRead()) { mXmppConnectionService.getNotificationService().push(message); } diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index ed88e434e..d11b02fa4 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -386,8 +386,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor; String args[] = { roster.getAccount().getUuid() }; - cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT + "=?", - args, null, null, null); + cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT + "=?", args, null, null, null); while (cursor.moveToNext()) { roster.initContact(Contact.fromCursor(cursor)); } diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java index e120adbd1..fb61691c2 100644 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -13,6 +13,7 @@ import java.security.DigestOutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Date; import java.util.Locale; @@ -32,6 +33,7 @@ import android.webkit.MimeTypeMap; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; @@ -63,7 +65,7 @@ public class FileBackend { extension = "."+parts[parts.length - 1]; } else { if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_TEXT) { - extension = ".webp"; + extension = ".jpg"; } else { extension = ""; } @@ -78,10 +80,10 @@ public class FileBackend { if (path.startsWith("/")) { return new DownloadableFile(path); } else { - if (message.getType() == Message.TYPE_FILE) { + if (Arrays.asList(Transferable.VALID_IMAGE_EXTENSIONS).contains(extension)) { return new DownloadableFile(getConversationsFileDirectory() + path); } else { - return new DownloadableFile(getConversationsImageDirectory()+path); + return new DownloadableFile(getConversationsImageDirectory() + path); } } } @@ -209,7 +211,7 @@ public class FileBackend { scaledBitmap = rotate(scaledBitmap, rotation); } - boolean success = scaledBitmap.compress(Bitmap.CompressFormat.WEBP, 75, os); + boolean success = scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 75, os); if (!success) { throw new FileCopyException(R.string.error_compressing_image); } @@ -217,7 +219,7 @@ public class FileBackend { long size = file.getSize(); int width = scaledBitmap.getWidth(); int height = scaledBitmap.getHeight(); - message.setBody(Long.toString(size) + ',' + width + ',' + height); + message.setBody(Long.toString(size) + '|' + width + '|' + height); return file; } catch (FileNotFoundException e) { throw new FileCopyException(R.string.error_file_not_found); @@ -233,6 +235,8 @@ public class FileBackend { } else { throw new FileCopyException(R.string.error_out_of_memory); } + } catch (NullPointerException e) { + throw new FileCopyException(R.string.error_io_exception); } finally { close(os); close(is); @@ -497,7 +501,11 @@ public class FileBackend { message.setBody(url.toString()+"|"+Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight); } } else { - message.setBody(Long.toString(file.getSize())); + if (url != null) { + message.setBody(url.toString()+"|"+Long.toString(file.getSize())); + } else { + message.setBody(Long.toString(file.getSize())); + } } } diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java index 7412eb933..e88047f67 100644 --- a/src/main/java/eu/siacs/conversations/services/AvatarService.java +++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java @@ -44,12 +44,12 @@ public class AvatarService { if (avatar != null || cachedOnly) { return avatar; } - if (contact.getProfilePhoto() != null) { - avatar = mXmppConnectionService.getFileBackend().cropCenterSquare(Uri.parse(contact.getProfilePhoto()), size); - } if (avatar == null && contact.getAvatar() != null) { avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatar(), size); } + if (avatar == null && contact.getProfilePhoto() != null) { + avatar = mXmppConnectionService.getFileBackend().cropCenterSquare(Uri.parse(contact.getProfilePhoto()), size); + } if (avatar == null) { avatar = get(contact.getDisplayName(), size, cachedOnly); } @@ -265,11 +265,11 @@ public class AvatarService { Contact contact = user.getContact(); if (contact != null) { Uri uri = null; - if (contact.getProfilePhoto() != null) { - uri = Uri.parse(contact.getProfilePhoto()); - } else if (contact.getAvatar() != null) { + if (contact.getAvatar() != null) { uri = mXmppConnectionService.getFileBackend().getAvatarUri( contact.getAvatar()); + } else if (contact.getProfilePhoto() != null) { + uri = Uri.parse(contact.getProfilePhoto()); } if (uri != null) { Bitmap bitmap = mXmppConnectionService.getFileBackend() diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index 49543eebc..ec68c07a6 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -18,7 +18,6 @@ import android.support.v4.app.NotificationCompat.Builder; import android.support.v4.app.TaskStackBuilder; import android.text.Html; import android.util.DisplayMetrics; -import android.util.Log; import org.json.JSONArray; import org.json.JSONObject; @@ -42,7 +41,6 @@ import eu.siacs.conversations.ui.ManageAccountActivity; import eu.siacs.conversations.ui.TimePreference; import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.utils.UIHelper; -import eu.siacs.conversations.xmpp.XmppConnection; public class NotificationService { @@ -64,12 +62,12 @@ public class NotificationService { public boolean notify(final Message message) { return (message.getStatus() == Message.STATUS_RECEIVED) - && notificationsEnabled() - && !message.getConversation().isMuted() - && (message.getConversation().getMode() == Conversation.MODE_SINGLE - || conferenceNotificationsEnabled() - || wasHighlightedOrPrivate(message) - ); + && notificationsEnabled() + && !message.getConversation().isMuted() + && (message.getConversation().getMode() == Conversation.MODE_SINGLE + || conferenceNotificationsEnabled() + || wasHighlightedOrPrivate(message) + ); } public void notifyPebble(final Message message) { @@ -121,7 +119,7 @@ public class NotificationService { @SuppressWarnings("deprecation") private boolean isInteractive() { final PowerManager pm = (PowerManager) mXmppConnectionService - .getSystemService(Context.POWER_SERVICE); + .getSystemService(Context.POWER_SERVICE); final boolean isScreenOn; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { @@ -155,9 +153,7 @@ public class NotificationService { notifications.put(conversationUuid, mList); } final Account account = message.getConversation().getAccount(); - final boolean doNotify = (!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn) - && !account.inGracePeriod() - && !this.inMiniGracePeriod(account); + final boolean doNotify = !account.inGracePeriod() && !this.inMiniGracePeriod(account); updateNotification(doNotify); if (doNotify) { notifyPebble(message); @@ -180,12 +176,12 @@ public class NotificationService { } private void setNotificationColor(final Builder mBuilder) { - mBuilder.setColor(mXmppConnectionService.getResources().getColor(R.color.primary)); + mBuilder.setColor(mXmppConnectionService.getResources().getColor(R.color.green500)); } private void updateNotification(final boolean notify) { final NotificationManager notificationManager = (NotificationManager) mXmppConnectionService - .getSystemService(Context.NOTIFICATION_SERVICE); + .getSystemService(Context.NOTIFICATION_SERVICE); final SharedPreferences preferences = mXmppConnectionService.getPreferences(); final String ringtone = preferences.getString("notification_ringtone", null); @@ -241,7 +237,7 @@ public class NotificationService { conversation = messages.get(0).getConversation(); final String name = conversation.getName(); style.addLine(Html.fromHtml("<b>" + name + "</b> " - + UIHelper.getMessagePreview(mXmppConnectionService,messages.get(0)).first)); + + UIHelper.getMessagePreview(mXmppConnectionService,messages.get(0)).first)); names.append(name); names.append(", "); } @@ -281,9 +277,9 @@ public class NotificationService { Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? R.drawable.ic_file_download_white_24dp : R.drawable.ic_action_download, mXmppConnectionService.getResources().getString(R.string.download_x_file, - UIHelper.getFileDescriptionString(mXmppConnectionService, message)), + UIHelper.getFileDescriptionString(mXmppConnectionService, message)), createDownloadIntent(message) - ); + ); } if ((message = getFirstLocationMessage(messages)) != null) { mBuilder.addAction(R.drawable.ic_room_white_24dp, @@ -296,16 +292,16 @@ public class NotificationService { } private void modifyForImage(final Builder builder, final Message message, - final ArrayList<Message> messages, final boolean notify) { + final ArrayList<Message> messages, final boolean notify) { try { final Bitmap bitmap = mXmppConnectionService.getFileBackend() - .getThumbnail(message, getPixel(288), false); + .getThumbnail(message, getPixel(288), false); final ArrayList<Message> tmp = new ArrayList<>(); for (final Message msg : messages) { if (msg.getType() == Message.TYPE_TEXT - && msg.getDownloadable() == null) { + && msg.getTransferable() == null) { tmp.add(msg); - } + } } final BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(); bigPictureStyle.bigPicture(bitmap); @@ -324,7 +320,7 @@ public class NotificationService { } private void modifyForTextOnly(final Builder builder, - final ArrayList<Message> messages, final boolean notify) { + final ArrayList<Message> messages, final boolean notify) { builder.setStyle(new NotificationCompat.BigTextStyle().bigText(getMergedBodies(messages))); builder.setContentText(UIHelper.getMessagePreview(mXmppConnectionService,messages.get(0)).first); if (notify) { @@ -335,10 +331,10 @@ public class NotificationService { private Message getImage(final Iterable<Message> messages) { for (final Message message : messages) { if (message.getType() == Message.TYPE_IMAGE - && message.getDownloadable() == null + && message.getTransferable() == null && message.getEncryption() != Message.ENCRYPTION_PGP) { return message; - } + } } return null; } @@ -346,7 +342,7 @@ public class NotificationService { private Message getFirstDownloadableMessage(final Iterable<Message> messages) { for (final Message message : messages) { if ((message.getType() == Message.TYPE_FILE || message.getType() == Message.TYPE_IMAGE) && - message.getDownloadable() != null) { + message.getTransferable() != null) { return message; } } @@ -385,7 +381,7 @@ public class NotificationService { private PendingIntent createContentIntent(final String conversationUuid, final String downloadMessageUuid) { final TaskStackBuilder stackBuilder = TaskStackBuilder - .create(mXmppConnectionService); + .create(mXmppConnectionService); stackBuilder.addParentStack(ConversationActivity.class); final Intent viewConversationIntent = new Intent(mXmppConnectionService, @@ -439,7 +435,7 @@ public class NotificationService { private PendingIntent createDisableAccountIntent(final Account account) { final Intent intent = new Intent(mXmppConnectionService,XmppConnectionService.class); intent.setAction(XmppConnectionService.ACTION_DISABLE_ACCOUNT); - intent.putExtra("account",account.getJid().toBareJid().toString()); + intent.putExtra("account", account.getJid().toBareJid().toString()); return PendingIntent.getService(mXmppConnectionService,0,intent,PendingIntent.FLAG_UPDATE_CURRENT); } @@ -473,7 +469,7 @@ public class NotificationService { private int getPixel(final int dp) { final DisplayMetrics metrics = mXmppConnectionService.getResources() - .getDisplayMetrics(); + .getDisplayMetrics(); return ((int) (dp * metrics.density)); } @@ -483,7 +479,7 @@ public class NotificationService { private boolean inMiniGracePeriod(final Account account) { final int miniGrace = account.getStatus() == Account.State.ONLINE ? Config.MINI_GRACE_PERIOD - : Config.MINI_GRACE_PERIOD * 2; + : Config.MINI_GRACE_PERIOD * 2; return SystemClock.elapsedRealtime() < (this.mLastNotification + miniGrace); } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 0a264dd13..ee212aed0 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -28,6 +28,7 @@ import android.util.LruCache; import net.java.otr4j.OtrException; import net.java.otr4j.session.Session; import net.java.otr4j.session.SessionID; +import net.java.otr4j.session.SessionImpl; import net.java.otr4j.session.SessionStatus; import org.openintents.openpgp.util.OpenPgpApi; @@ -56,12 +57,11 @@ import eu.siacs.conversations.entities.Blockable; import eu.siacs.conversations.entities.Bookmark; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Downloadable; -import eu.siacs.conversations.entities.DownloadablePlaceholder; +import eu.siacs.conversations.entities.Transferable; +import eu.siacs.conversations.entities.TransferablePlaceholder; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.MucOptions.OnRenameListener; -import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.generator.IqGenerator; import eu.siacs.conversations.generator.MessageGenerator; import eu.siacs.conversations.generator.PresenceGenerator; @@ -233,7 +233,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa private MessageArchiveService mMessageArchiveService = new MessageArchiveService(this); private OnConversationUpdate mOnConversationUpdate = null; private int convChangedListenerCount = 0; - private int unreadCount = 0; + private OnShowErrorToast mOnShowErrorToast = null; + private int showErrorToastListenerCount = 0; + private int unreadCount = -1; private OnAccountUpdate mOnAccountUpdate = null; private OnStatusChanged statusListener = new OnStatusChanged() { @@ -390,7 +392,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa callback.success(message); } } catch (FileBackend.FileCopyException e) { - callback.error(e.getResId(),message); + callback.error(e.getResId(), message); } } }); @@ -602,6 +604,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa this.pm = (PowerManager) getSystemService(Context.POWER_SERVICE); this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"XmppConnectionService"); toggleForegroundService(); + updateUnreadCountBadge(); } public void toggleForegroundService() { @@ -629,7 +632,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } Context context = getApplicationContext(); AlarmManager alarmManager = (AlarmManager) context - .getSystemService(Context.ALARM_SERVICE); + .getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, EventReceiver.class); alarmManager.cancel(PendingIntent.getBroadcast(context, 0, intent, 0)); Log.d(Config.LOGTAG, "good bye"); @@ -671,114 +674,138 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } + private void sendFileMessage(final Message message) { + Log.d(Config.LOGTAG, "send file message"); + final Account account = message.getConversation().getAccount(); + final XmppConnection connection = account.getXmppConnection(); + if (connection != null && connection.getFeatures().httpUpload()) { + mHttpConnectionManager.createNewUploadConnection(message); + } else { + mJingleConnectionManager.createNewConnection(message); + } + } + public void sendMessage(final Message message) { + sendMessage(message, false); + } + + private void sendMessage(final Message message, final boolean resend) { final Account account = message.getConversation().getAccount(); + final Conversation conversation = message.getConversation(); account.deactivateGracePeriod(); - final Conversation conv = message.getConversation(); MessagePacket packet = null; boolean saveInDb = true; - boolean send = false; - if (account.getStatus() == Account.State.ONLINE - && account.getXmppConnection() != null) { - if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) { - if (message.getCounterpart() != null) { - if (message.getEncryption() == Message.ENCRYPTION_OTR) { - if (!conv.hasValidOtrSession()) { - conv.startOtrSession(message.getCounterpart().getResourcepart(),true); - message.setStatus(Message.STATUS_WAITING); - } else if (conv.hasValidOtrSession() - && conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) { - mJingleConnectionManager - .createNewConnection(message); - } + message.setStatus(Message.STATUS_WAITING); + + if (!resend && message.getEncryption() != Message.ENCRYPTION_OTR) { + message.getConversation().endOtrIfNeeded(); + message.getConversation().findUnsentMessagesWithOtrEncryption(new Conversation.OnMessageFound() { + @Override + public void onMessageFound(Message message) { + markMessage(message,Message.STATUS_SEND_FAILED); + } + }); + } + + if (account.isOnlineAndConnected()) { + switch (message.getEncryption()) { + case Message.ENCRYPTION_NONE: + if (message.needsUploading()) { + if (account.httpUploadAvailable() || message.fixCounterpart()) { + this.sendFileMessage(message); + } else { + break; + } } else { - mJingleConnectionManager.createNewConnection(message); + packet = mMessageGenerator.generateChat(message,resend); } - } else { - if (message.getEncryption() == Message.ENCRYPTION_OTR) { - conv.startOtrIfNeeded(); - } - message.setStatus(Message.STATUS_WAITING); - } - } else { - if (message.getEncryption() == Message.ENCRYPTION_OTR) { - if (!conv.hasValidOtrSession() && (message.getCounterpart() != null)) { - conv.startOtrSession(message.getCounterpart().getResourcepart(), true); - message.setStatus(Message.STATUS_WAITING); - } else if (conv.hasValidOtrSession()) { - if (conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) { - packet = mMessageGenerator.generateOtrChat(message); - send = true; + break; + case Message.ENCRYPTION_PGP: + case Message.ENCRYPTION_DECRYPTED: + if (message.needsUploading()) { + if (account.httpUploadAvailable() || message.fixCounterpart()) { + this.sendFileMessage(message); } else { - message.setStatus(Message.STATUS_WAITING); - conv.startOtrIfNeeded(); + break; } } else { - message.setStatus(Message.STATUS_WAITING); + packet = mMessageGenerator.generatePgpChat(message,resend); } - } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { - message.getConversation().endOtrIfNeeded(); - message.getConversation().findUnsentMessagesWithOtrEncryption(new Conversation.OnMessageFound() { - @Override - public void onMessageFound(Message message) { - markMessage(message,Message.STATUS_SEND_FAILED); + break; + case Message.ENCRYPTION_OTR: + SessionImpl otrSession = conversation.getOtrSession(); + if (otrSession != null && otrSession.getSessionStatus() == SessionStatus.ENCRYPTED) { + try { + message.setCounterpart(Jid.fromSessionID(otrSession.getSessionID())); + } catch (InvalidJidException e) { + break; } - }); - packet = mMessageGenerator.generatePgpChat(message); - send = true; - } else { - message.getConversation().endOtrIfNeeded(); - message.getConversation().findUnsentMessagesWithOtrEncryption(new Conversation.OnMessageFound() { - @Override - public void onMessageFound(Message message) { - markMessage(message,Message.STATUS_SEND_FAILED); + if (message.needsUploading()) { + mJingleConnectionManager.createNewConnection(message); + } else { + packet = mMessageGenerator.generateOtrChat(message,resend); } - }); - packet = mMessageGenerator.generateChat(message); - send = true; + } else if (otrSession == null) { + if (message.fixCounterpart()) { + conversation.startOtrSession(message.getCounterpart().getResourcepart(), true); + } else { + break; + } + } + break; + } + if (packet != null) { + if (account.getXmppConnection().getFeatures().sm() || conversation.getMode() == Conversation.MODE_MULTI) { + message.setStatus(Message.STATUS_UNSEND); + } else { + message.setStatus(Message.STATUS_SEND); } } - if (!account.getXmppConnection().getFeatures().sm() - && conv.getMode() != Conversation.MODE_MULTI) { - message.setStatus(Message.STATUS_SEND); - } } else { - message.setStatus(Message.STATUS_WAITING); - if (message.getType() == Message.TYPE_TEXT) { - if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { - String pgpBody = message.getEncryptedBody(); - String decryptedBody = message.getBody(); - message.setBody(pgpBody); - message.setEncryption(Message.ENCRYPTION_PGP); - databaseBackend.createMessage(message); - saveInDb = false; - message.setBody(decryptedBody); - message.setEncryption(Message.ENCRYPTION_DECRYPTED); - } else if (message.getEncryption() == Message.ENCRYPTION_OTR) { - if (!conv.hasValidOtrSession() - && message.getCounterpart() != null) { - conv.startOtrSession(message.getCounterpart().getResourcepart(), false); - } - } + switch(message.getEncryption()) { + case Message.ENCRYPTION_DECRYPTED: + if (!message.needsUploading()) { + String pgpBody = message.getEncryptedBody(); + String decryptedBody = message.getBody(); + message.setBody(pgpBody); + message.setEncryption(Message.ENCRYPTION_PGP); + databaseBackend.createMessage(message); + saveInDb = false; + message.setBody(decryptedBody); + message.setEncryption(Message.ENCRYPTION_DECRYPTED); + } + break; + case Message.ENCRYPTION_OTR: + if (!conversation.hasValidOtrSession() && message.getCounterpart() != null) { + conversation.startOtrSession(message.getCounterpart().getResourcepart(), false); + } + break; } - } - conv.add(message); - if (saveInDb) { - if (message.getEncryption() == Message.ENCRYPTION_NONE - || saveEncryptedMessages()) { + + if (resend) { + if (packet != null) { + if (account.getXmppConnection().getFeatures().sm() || conversation.getMode() == Conversation.MODE_MULTI) { + markMessage(message,Message.STATUS_UNSEND); + } else { + markMessage(message,Message.STATUS_SEND); + } + } + } else { + conversation.add(message); + if (saveInDb && (message.getEncryption() == Message.ENCRYPTION_NONE || saveEncryptedMessages())) { databaseBackend.createMessage(message); - } + } + updateConversationUi(); } - if ((send) && (packet != null)) { - if (conv.setOutgoingChatState(Config.DEFAULT_CHATSTATE)) { + if (packet != null) { + if (conversation.setOutgoingChatState(Config.DEFAULT_CHATSTATE)) { if (this.sendChatStates()) { - packet.addChild(ChatState.toElement(conv.getOutgoingChatState())); + packet.addChild(ChatState.toElement(conversation.getOutgoingChatState())); } } sendMessagePacket(account, packet); } - updateConversationUi(); } private void sendUnsentMessages(final Conversation conversation) { @@ -791,77 +818,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa }); } - private void resendMessage(final Message message) { - Account account = message.getConversation().getAccount(); - MessagePacket packet = null; - if (message.getEncryption() == Message.ENCRYPTION_OTR) { - Presences presences = message.getConversation().getContact() - .getPresences(); - if (!message.getConversation().hasValidOtrSession()) { - if ((message.getCounterpart() != null) - && (presences.has(message.getCounterpart().getResourcepart()))) { - message.getConversation().startOtrSession(message.getCounterpart().getResourcepart(), true); - } else { - if (presences.size() == 1) { - String presence = presences.asStringArray()[0]; - message.getConversation().startOtrSession(presence, true); - } - } - } else { - if (message.getConversation().getOtrSession() - .getSessionStatus() == SessionStatus.ENCRYPTED) { - try { - message.setCounterpart(Jid.fromSessionID(message.getConversation().getOtrSession().getSessionID())); - if (message.getType() == Message.TYPE_TEXT) { - packet = mMessageGenerator.generateOtrChat(message, - true); - } else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) { - mJingleConnectionManager.createNewConnection(message); - } - } catch (final InvalidJidException ignored) { - - } - } - } - } else if (message.getType() == Message.TYPE_TEXT) { - if (message.getEncryption() == Message.ENCRYPTION_NONE) { - packet = mMessageGenerator.generateChat(message, true); - } else if ((message.getEncryption() == Message.ENCRYPTION_DECRYPTED) - || (message.getEncryption() == Message.ENCRYPTION_PGP)) { - packet = mMessageGenerator.generatePgpChat(message, true); - } - } else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) { - Contact contact = message.getConversation().getContact(); - Presences presences = contact.getPresences(); - if ((message.getCounterpart() != null) - && (presences.has(message.getCounterpart().getResourcepart()))) { - mJingleConnectionManager.createNewConnection(message); - } else { - if (presences.size() == 1) { - String presence = presences.asStringArray()[0]; - try { - message.setCounterpart(Jid.fromParts(contact.getJid().getLocalpart(), contact.getJid().getDomainpart(), presence)); - } catch (InvalidJidException e) { - return; - } - mJingleConnectionManager.createNewConnection(message); - } - } - } - if (packet != null) { - if (!account.getXmppConnection().getFeatures().sm() - && message.getConversation().getMode() != Conversation.MODE_MULTI) { - markMessage(message, Message.STATUS_SEND); - } else { - markMessage(message, Message.STATUS_UNSEND); - } - if (message.getConversation().setOutgoingChatState(Config.DEFAULT_CHATSTATE)) { - if (this.sendChatStates()) { - packet.addChild(ChatState.toElement(message.getConversation().getOutgoingChatState())); - } - } - sendMessagePacket(account, packet); - } + public void resendMessage(final Message message) { + sendMessage(message, true); } public void fetchRosterFromServer(final Account account) { @@ -1016,7 +974,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa @Override public void onMessageFound(Message message) { if (!getFileBackend().isFileAvailable(message)) { - message.setDownloadable(new DownloadablePlaceholder(Downloadable.STATUS_DELETED)); + message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED)); } } }); @@ -1027,7 +985,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa Message message = conversation.findMessageWithFileAndUuid(uuid); if (message != null) { if (!getFileBackend().isFileAvailable(message)) { - message.setDownloadable(new DownloadablePlaceholder(Downloadable.STATUS_DELETED)); + message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED)); updateConversationUi(); } return; @@ -1039,13 +997,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa populateWithOrderedConversations(list, true); } - public void populateWithOrderedConversations(final List<Conversation> list, boolean includeConferences) { + public void populateWithOrderedConversations(final List<Conversation> list, boolean includeNoFileUpload) { list.clear(); - if (includeConferences) { + if (includeNoFileUpload) { list.addAll(getConversations()); } else { for (Conversation conversation : getConversations()) { - if (conversation.getMode() == Conversation.MODE_SINGLE) { + if (conversation.getMode() == Conversation.MODE_SINGLE + || conversation.getAccount().httpUploadAvailable()) { list.add(conversation); } } @@ -1283,6 +1242,32 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } } + public void setOnShowErrorToastListener(OnShowErrorToast onShowErrorToast) { + synchronized (this) { + if (checkListeners()) { + switchToForeground(); + } + this.mOnShowErrorToast = onShowErrorToast; + if (this.showErrorToastListenerCount < 2) { + this.showErrorToastListenerCount++; + } + } + this.mOnShowErrorToast = onShowErrorToast; + } + + public void removeOnShowErrorToastListener() { + synchronized (this) { + this.showErrorToastListenerCount--; + if (this.showErrorToastListenerCount <= 0) { + this.showErrorToastListenerCount = 0; + this.mOnShowErrorToast = null; + if (checkListeners()) { + switchToBackground(); + } + } + } + } + public void setOnAccountListChangedListener(OnAccountUpdate listener) { synchronized (this) { if (checkListeners()) { @@ -1387,7 +1372,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return (this.mOnAccountUpdate == null && this.mOnConversationUpdate == null && this.mOnRosterUpdate == null - && this.mOnUpdateBlocklist == null); + && this.mOnUpdateBlocklist == null + && this.mOnShowErrorToast == null); } private void switchToForeground() { @@ -1713,7 +1699,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void changeAffiliationsInConference(final Conversation conference, MucOptions.Affiliation before, MucOptions.Affiliation after) { List<Jid> jids = new ArrayList<>(); for (MucOptions.User user : conference.getMucOptions().getUsers()) { - if (user.getAffiliation() == before) { + if (user.getAffiliation() == before && user.getJid() != null) { jids.add(user.getJid()); } } @@ -1809,15 +1795,15 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } catch (InvalidJidException e) { return; } - if (message.getType() == Message.TYPE_TEXT) { + if (message.needsUploading()) { + mJingleConnectionManager.createNewConnection(message); + } else { MessagePacket outPacket = mMessageGenerator.generateOtrChat(message, true); if (outPacket != null) { message.setStatus(Message.STATUS_SEND); databaseBackend.updateMessage(message); sendMessagePacket(account, outPacket); } - } else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) { - mJingleConnectionManager.createNewConnection(message); } updateConversationUi(); } @@ -2238,6 +2224,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa return count; } + + public void showErrorToastInUi(int resId) { + if (mOnShowErrorToast != null) { + mOnShowErrorToast.onShowErrorToast(resId); + } + } + public void updateConversationUi() { if (mOnConversationUpdate != null) { mOnConversationUpdate.onConversationUpdate(); @@ -2571,6 +2564,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void onPushFailed(); } + public interface OnShowErrorToast { + void onShowErrorToast(int resId); + } + public class XmppConnectionBinder extends Binder { public XmppConnectionService getService() { return XmppConnectionService.this; diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index 07b8819d9..b76689ad3 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -406,7 +406,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers final User self = mucOptions.getSelf(); mAccountJid.setText(getString(R.string.using_account, mConversation .getAccount().getJid().toBareJid())); - mYourPhoto.setImageBitmap(avatarService().get(mConversation.getAccount(), getPixel(48))); + mYourPhoto.setImageBitmap(avatarService().get(mConversation.getAccount(), getPixel(56))); setTitle(mConversation.getName()); mFullJid.setText(mConversation.getJid().toBareJid().toString()); mYourNick.setText(mucOptions.getActualNick()); @@ -469,11 +469,11 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers Bitmap bm; Contact contact = user.getContact(); if (contact != null) { - bm = avatarService().get(contact, getPixel(48)); + bm = avatarService().get(contact, getPixel(56)); tvDisplayName.setText(contact.getDisplayName()); tvStatus.setText(user.getName() + " \u2022 " + getStatus(user)); } else { - bm = avatarService().get(user.getName(), getPixel(48)); + bm = avatarService().get(user.getName(), getPixel(56)); tvDisplayName.setText(user.getName()); tvStatus.setText(getStatus(user)); @@ -567,4 +567,4 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } }); } -} +}
\ No newline at end of file diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index c190caede..e897716a6 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -32,6 +32,7 @@ import org.openintents.openpgp.util.OpenPgpUtils; import java.util.List; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.entities.Account; @@ -351,7 +352,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd contactJidTv.setText(contact.getJid().toString()); } accountJidTv.setText(getString(R.string.using_account, contact.getAccount().getJid().toBareJid())); - badge.setImageBitmap(avatarService().get(contact, getPixel(72))); + badge.setImageBitmap(avatarService().get(contact, getPixel(Config.AVATAR_SIZE))); badge.setOnClickListener(this.onBadgeClick); keys.removeAllViews(); diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index c48b5865c..6b0f89b1c 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -35,10 +35,12 @@ import java.util.Iterator; import java.util.List; import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Blockable; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate; @@ -47,7 +49,7 @@ import eu.siacs.conversations.utils.ExceptionHelper; import eu.siacs.conversations.xmpp.OnUpdateBlocklist; public class ConversationActivity extends XmppActivity - implements OnAccountUpdate, OnConversationUpdate, OnRosterUpdate, OnUpdateBlocklist { + implements OnAccountUpdate, OnConversationUpdate, OnRosterUpdate, OnUpdateBlocklist, XmppConnectionService.OnShowErrorToast { public static final String ACTION_DOWNLOAD = "eu.siacs.conversations.action.DOWNLOAD"; @@ -171,83 +173,84 @@ public class ConversationActivity extends XmppActivity listView.setOnItemClickListener(new OnItemClickListener() { - @Override - public void onItemClick(AdapterView<?> arg0, View clickedView, - int position, long arg3) { - if (getSelectedConversation() != conversationList.get(position)) { - setSelectedConversation(conversationList.get(position)); - ConversationActivity.this.mConversationFragment.reInit(getSelectedConversation()); - } - hideConversationsOverview(); - openConversation(); - } - }); + @Override + public void onItemClick(AdapterView<?> arg0, View clickedView, + int position, long arg3) { + if (getSelectedConversation() != conversationList.get(position)) { + setSelectedConversation(conversationList.get(position)); + ConversationActivity.this.mConversationFragment.reInit(getSelectedConversation()); + } + hideConversationsOverview(); + openConversation(); + } + }); listView.setDismissCallback(new EnhancedListView.OnDismissCallback() { - @Override - public EnhancedListView.Undoable onDismiss(final EnhancedListView enhancedListView, final int position) { - - final int index = listView.getFirstVisiblePosition(); - View v = listView.getChildAt(0); - final int top = (v == null) ? 0 : (v.getTop() - listView.getPaddingTop()); - - swipedConversation = listAdapter.getItem(position); - listAdapter.remove(swipedConversation); - swipedConversation.markRead(); - xmppConnectionService.getNotificationService().clear(swipedConversation); - - final boolean formerlySelected = (getSelectedConversation() == swipedConversation); - if (position == 0 && listAdapter.getCount() == 0) { - endConversation(swipedConversation, false, true); - return null; - } else if (formerlySelected) { - setSelectedConversation(listAdapter.getItem(0)); - ConversationActivity.this.mConversationFragment - .reInit(getSelectedConversation()); - } - - return new EnhancedListView.Undoable() { - - @Override - public void undo() { - listAdapter.insert(swipedConversation, position); - if (formerlySelected) { - setSelectedConversation(swipedConversation); - ConversationActivity.this.mConversationFragment - .reInit(getSelectedConversation()); - } - swipedConversation = null; - listView.setSelectionFromTop(index + (listView.getChildCount() < position ? 1 : 0), top); - } - - @Override - public void discard() { - if (!swipedConversation.isRead() - && swipedConversation.getMode() == Conversation.MODE_SINGLE) { - swipedConversation = null; - return; - } - endConversation(swipedConversation, false, false); - swipedConversation = null; - } - - @Override - public String getTitle() { - if (swipedConversation.getMode() == Conversation.MODE_MULTI) { - return getResources().getString(R.string.title_undo_swipe_out_muc); - } else { - return getResources().getString(R.string.title_undo_swipe_out_conversation); - } - } - }; - } - }); + @Override + public EnhancedListView.Undoable onDismiss(final EnhancedListView enhancedListView, final int position) { + + final int index = listView.getFirstVisiblePosition(); + View v = listView.getChildAt(0); + final int top = (v == null) ? 0 : (v.getTop() - listView.getPaddingTop()); + + swipedConversation = listAdapter.getItem(position); + listAdapter.remove(swipedConversation); + swipedConversation.markRead(); + xmppConnectionService.getNotificationService().clear(swipedConversation); + + final boolean formerlySelected = (getSelectedConversation() == swipedConversation); + if (position == 0 && listAdapter.getCount() == 0) { + endConversation(swipedConversation, false, true); + return null; + } else if (formerlySelected) { + setSelectedConversation(listAdapter.getItem(0)); + ConversationActivity.this.mConversationFragment + .reInit(getSelectedConversation()); + } + + return new EnhancedListView.Undoable() { + + @Override + public void undo() { + listAdapter.insert(swipedConversation, position); + if (formerlySelected) { + setSelectedConversation(swipedConversation); + ConversationActivity.this.mConversationFragment + .reInit(getSelectedConversation()); + } + swipedConversation = null; + listView.setSelectionFromTop(index + (listView.getChildCount() < position ? 1 : 0), top); + } + + @Override + public void discard() { + if (!swipedConversation.isRead() + && swipedConversation.getMode() == Conversation.MODE_SINGLE) { + swipedConversation = null; + return; + } + endConversation(swipedConversation, false, false); + swipedConversation = null; + } + + @Override + public String getTitle() { + if (swipedConversation.getMode() == Conversation.MODE_MULTI) { + return getResources().getString(R.string.title_undo_swipe_out_muc); + } else { + return getResources().getString(R.string.title_undo_swipe_out_conversation); + } + } + }; + } + }); listView.enableSwipeToDismiss(); listView.setSwipingLayout(R.id.swipeable_item); listView.setUndoStyle(EnhancedListView.UndoStyle.SINGLE_POPUP); - listView.setUndoHideDelay(5000); + listView.setUndoHideDelay(10000); listView.setRequireTouchBeforeDismiss(false); + listView.setSwipeDirection(EnhancedListView.SwipeDirection.START); // swipe to left to close conversation mContentView = findViewById(R.id.content_view_spl); if (mContentView == null) { @@ -372,8 +375,7 @@ public class ConversationActivity extends XmppActivity } else { menuAdd.setVisible(!isConversationsOverviewHideable()); if (this.getSelectedConversation() != null) { - if (this.getSelectedConversation().getLatestMessage() - .getEncryption() != Message.ENCRYPTION_NONE) { + if (this.getSelectedConversation().getNextEncryption(forceEncryption()) != Message.ENCRYPTION_NONE) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { menuSecure.setIcon(R.drawable.ic_lock_white_24dp); } else { @@ -382,7 +384,7 @@ public class ConversationActivity extends XmppActivity } if (this.getSelectedConversation().getMode() == Conversation.MODE_MULTI) { menuContactDetails.setVisible(false); - menuAttach.setVisible(false); + menuAttach.setVisible(getSelectedConversation().getAccount().httpUploadAvailable()); menuInviteContact.setVisible(getSelectedConversation().getMucOptions().canInvite()); } else { menuMucDetails.setVisible(false); @@ -398,6 +400,8 @@ public class ConversationActivity extends XmppActivity } private void selectPresenceToAttachFile(final int attachmentChoice, final int encryption) { + final Conversation conversation = getSelectedConversation(); + final Account account = conversation.getAccount(); final OnPresenceSelected callback = new OnPresenceSelected() { @Override @@ -449,11 +453,11 @@ public class ConversationActivity extends XmppActivity } } }; - if (attachmentChoice == ATTACHMENT_CHOICE_LOCATION && encryption != Message.ENCRYPTION_OTR) { - getSelectedConversation().setNextCounterpart(null); + if ((account.httpUploadAvailable() || attachmentChoice == ATTACHMENT_CHOICE_LOCATION) && encryption != Message.ENCRYPTION_OTR) { + conversation.setNextCounterpart(null); callback.onPresenceSelected(); } else { - selectPresence(getSelectedConversation(),callback); + selectPresence(conversation,callback); } } @@ -736,14 +740,11 @@ public class ConversationActivity extends XmppActivity break; case R.id.encryption_choice_pgp: if (hasPgp()) { - if (conversation.getAccount().getKeys() - .has("pgp_signature")) { - conversation - .setNextEncryption(Message.ENCRYPTION_PGP); + if (conversation.getAccount().getKeys().has("pgp_signature")) { + conversation.setNextEncryption(Message.ENCRYPTION_PGP); item.setChecked(true); } else { - announcePgp(conversation.getAccount(), - conversation); + announcePgp(conversation.getAccount(),conversation); } } else { showInstallPgpDialog(); @@ -753,16 +754,16 @@ public class ConversationActivity extends XmppActivity conversation.setNextEncryption(Message.ENCRYPTION_NONE); break; } - xmppConnectionService.databaseBackend - .updateConversation(conversation); + xmppConnectionService.databaseBackend.updateConversation(conversation); fragment.updateChatMsgHint(); + invalidateOptionsMenu(); return true; } }); popup.inflate(R.menu.encryption_choices); MenuItem otr = popup.getMenu().findItem(R.id.encryption_choice_otr); - MenuItem none = popup.getMenu().findItem( - R.id.encryption_choice_none); + MenuItem none = popup.getMenu().findItem(R.id.encryption_choice_none); + MenuItem pgp = popup.getMenu().findItem(R.id.encryption_choice_pgp); if (conversation.getMode() == Conversation.MODE_MULTI) { otr.setEnabled(false); } else { @@ -778,12 +779,10 @@ public class ConversationActivity extends XmppActivity otr.setChecked(true); break; case Message.ENCRYPTION_PGP: - popup.getMenu().findItem(R.id.encryption_choice_pgp) - .setChecked(true); + pgp.setChecked(true); break; default: - popup.getMenu().findItem(R.id.encryption_choice_none) - .setChecked(true); + none.setChecked(true); break; } popup.show(); @@ -1075,6 +1074,9 @@ public class ConversationActivity extends XmppActivity } private void attachLocationToConversation(Conversation conversation, Uri uri) { + if (conversation == null) { + return; + } xmppConnectionService.attachLocationToConversation(conversation,uri, new UiCallback<Message>() { @Override @@ -1095,8 +1097,10 @@ public class ConversationActivity extends XmppActivity } private void attachFileToConversation(Conversation conversation, Uri uri) { - prepareFileToast = Toast.makeText(getApplicationContext(), - getText(R.string.preparing_file), Toast.LENGTH_LONG); + if (conversation == null) { + return; + } + prepareFileToast = Toast.makeText(getApplicationContext(),getText(R.string.preparing_file), Toast.LENGTH_LONG); prepareFileToast.show(); xmppConnectionService.attachFileToConversation(conversation,uri, new UiCallback<Message>() { @Override @@ -1118,8 +1122,10 @@ public class ConversationActivity extends XmppActivity } private void attachImageToConversation(Conversation conversation, Uri uri) { - prepareFileToast = Toast.makeText(getApplicationContext(), - getText(R.string.preparing_image), Toast.LENGTH_LONG); + if (conversation == null) { + return; + } + prepareFileToast = Toast.makeText(getApplicationContext(),getText(R.string.preparing_image), Toast.LENGTH_LONG); prepareFileToast.show(); xmppConnectionService.attachImageToConversation(conversation, uri, new UiCallback<Message>() { @@ -1268,4 +1274,14 @@ public class ConversationActivity extends XmppActivity public boolean enterIsSend() { return getPreferences().getBoolean("enter_is_send",false); } + + @Override + public void onShowErrorToast(final int resId) { + runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(ConversationActivity.this,resId,Toast.LENGTH_SHORT).show(); + } + }); + } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index a817b27bf..587e923aa 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -3,6 +3,7 @@ package eu.siacs.conversations.ui; import android.app.AlertDialog; import android.app.Fragment; import android.app.PendingIntent; +import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -34,7 +35,6 @@ import android.widget.Toast; import net.java.otr4j.session.SessionStatus; -import java.net.URLConnection; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; @@ -46,9 +46,9 @@ import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Downloadable; +import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.DownloadableFile; -import eu.siacs.conversations.entities.DownloadablePlaceholder; +import eu.siacs.conversations.entities.TransferablePlaceholder; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.Presences; @@ -437,34 +437,36 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa MenuItem shareWith = menu.findItem(R.id.share_with); MenuItem sendAgain = menu.findItem(R.id.send_again); MenuItem copyUrl = menu.findItem(R.id.copy_url); - MenuItem downloadImage = menu.findItem(R.id.download_image); + 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.getDownloadable() != null || GeoHelper.isGeoUri(m.getBody())) { - copyText.setVisible(false); + if ((m.getType() == Message.TYPE_TEXT || m.getType() == Message.TYPE_PRIVATE) + && m.getTransferable() == null + && !GeoHelper.isGeoUri(m.getBody()) + && m.treatAsDownloadable() != Message.Decision.MUST) { + copyText.setVisible(true); } - if ((m.getType() == Message.TYPE_TEXT - || m.getType() == Message.TYPE_PRIVATE - || m.getDownloadable() != null) - && (!GeoHelper.isGeoUri(m.getBody()))) { - shareWith.setVisible(false); + if ((m.getType() != Message.TYPE_TEXT + && m.getType() != Message.TYPE_PRIVATE + && m.getTransferable() == null) + || (GeoHelper.isGeoUri(m.getBody()))) { + shareWith.setVisible(true); } - if (m.getStatus() != Message.STATUS_SEND_FAILED) { - sendAgain.setVisible(false); + if (m.getStatus() == Message.STATUS_SEND_FAILED) { + sendAgain.setVisible(true); } - if (((m.getType() != Message.TYPE_IMAGE && m.getDownloadable() == null) - || m.getImageParams().url == null) && !GeoHelper.isGeoUri(m.getBody())) { - copyUrl.setVisible(false); + if (m.hasFileOnRemoteHost() + || GeoHelper.isGeoUri(m.getBody()) + || m.treatAsDownloadable() == Message.Decision.MUST) { + copyUrl.setVisible(true); } - if (m.getType() != Message.TYPE_TEXT - || m.getDownloadable() != null - || !m.bodyContainsDownloadable()) { - downloadImage.setVisible(false); + if (m.getType() == Message.TYPE_TEXT && m.getTransferable() == null && m.treatAsDownloadable() != Message.Decision.NEVER) { + downloadFile.setVisible(true); + downloadFile.setTitle(activity.getString(R.string.download_x_file,UIHelper.getFileDescriptionString(activity, m))); } - if (!((m.getDownloadable() != null && !(m.getDownloadable() instanceof DownloadablePlaceholder)) + if ((m.getTransferable() != null && !(m.getTransferable() instanceof TransferablePlaceholder)) || (m.isFileOrImage() && (m.getStatus() == Message.STATUS_WAITING - || m.getStatus() == Message.STATUS_OFFERED)))) { - cancelTransmission.setVisible(false); + || m.getStatus() == Message.STATUS_OFFERED))) { + cancelTransmission.setVisible(true); } } } @@ -484,8 +486,8 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa case R.id.copy_url: copyUrl(selectedMessage); return true; - case R.id.download_image: - downloadImage(selectedMessage); + case R.id.download_file: + downloadFile(selectedMessage); return true; case R.id.cancel_transmission: cancelTransmission(selectedMessage); @@ -506,14 +508,18 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa activity.xmppConnectionService.getFileBackend() .getJingleFileUri(message)); shareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - String path = message.getRelativeFilePath(); - String mime = path == null ? null : URLConnection.guessContentTypeFromName(path); + String mime = message.getMimeType(); if (mime == null) { - mime = "image/webp"; + mime = "image/jpeg"; } shareIntent.setType(mime); } - activity.startActivity(Intent.createChooser(shareIntent, getText(R.string.share_with))); + try { + activity.startActivity(Intent.createChooser(shareIntent, getText(R.string.share_with))); + } catch (ActivityNotFoundException e) { + //This should happen only on faulty androids because normally chooser is always available + Toast.makeText(activity,R.string.no_application_found_to_open_file,Toast.LENGTH_SHORT).show(); + } } private void copyText(Message message) { @@ -529,7 +535,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa DownloadableFile file = activity.xmppConnectionService.getFileBackend().getFile(message); if (!file.exists()) { Toast.makeText(activity, R.string.file_deleted, Toast.LENGTH_SHORT).show(); - message.setDownloadable(new DownloadablePlaceholder(Downloadable.STATUS_DELETED)); + message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED)); return; } } @@ -542,9 +548,12 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa if (GeoHelper.isGeoUri(message.getBody())) { resId = R.string.location; url = message.getBody(); + } else if (message.hasFileOnRemoteHost()) { + resId = R.string.file_url; + url = message.getFileParams().url.toString(); } else { - resId = R.string.image_url; - url = message.getImageParams().url.toString(); + url = message.getBody().trim(); + resId = R.string.file_url; } if (activity.copyTextToClipboard(url, resId)) { Toast.makeText(activity, R.string.url_copied_to_clipboard, @@ -552,15 +561,15 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } } - private void downloadImage(Message message) { + private void downloadFile(Message message) { activity.xmppConnectionService.getHttpConnectionManager() - .createNewConnection(message); + .createNewDownloadConnection(message); } private void cancelTransmission(Message message) { - Downloadable downloadable = message.getDownloadable(); - if (downloadable != null) { - downloadable.cancel(); + Transferable transferable = message.getTransferable(); + if (transferable != null) { + transferable.cancel(); } else { activity.xmppConnectionService.markMessage(message, Message.STATUS_SEND_FAILED); } @@ -754,7 +763,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa if (message.getEncryption() == Message.ENCRYPTION_PGP && (message.getStatus() == Message.STATUS_RECEIVED || message .getStatus() >= Message.STATUS_SEND) - && message.getDownloadable() == null) { + && message.getTransferable() == null) { if (!mEncryptedMessages.contains(message)) { mEncryptedMessages.add(message); } @@ -912,7 +921,8 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa final SendButtonAction action; final int status; final boolean empty = this.mEditMessage == null || this.mEditMessage.getText().length() == 0; - if (c.getMode() == Conversation.MODE_MULTI) { + final boolean conference = c.getMode() == Conversation.MODE_MULTI; + if (conference && !c.getAccount().httpUploadAvailable()) { if (empty && c.getNextCounterpart() != null) { action = SendButtonAction.CANCEL; } else { @@ -920,28 +930,32 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } } else { if (empty) { - String setting = activity.getPreferences().getString("quick_action","recent"); - if (!setting.equals("none") && UIHelper.receivedLocationQuestion(conversation.getLatestMessage())) { - setting = "location"; - } else if (setting.equals("recent")) { - setting = activity.getPreferences().getString("recently_used_quick_action","text"); - } - switch (setting) { - case "photo": - action = SendButtonAction.TAKE_PHOTO; - break; - case "location": - action = SendButtonAction.SEND_LOCATION; - break; - case "voice": - action = SendButtonAction.RECORD_VOICE; - break; - case "picture": - action = SendButtonAction.CHOOSE_PICTURE; - break; - default: - action = SendButtonAction.TEXT; - break; + if (conference && c.getNextCounterpart() != null) { + action = SendButtonAction.CANCEL; + } else { + String setting = activity.getPreferences().getString("quick_action", "recent"); + if (!setting.equals("none") && UIHelper.receivedLocationQuestion(conversation.getLatestMessage())) { + setting = "location"; + } else if (setting.equals("recent")) { + setting = activity.getPreferences().getString("recently_used_quick_action", "text"); + } + switch (setting) { + case "photo": + action = SendButtonAction.TAKE_PHOTO; + break; + case "location": + action = SendButtonAction.SEND_LOCATION; + break; + case "voice": + action = SendButtonAction.RECORD_VOICE; + break; + case "picture": + action = SendButtonAction.CHOOSE_PICTURE; + break; + default: + action = SendButtonAction.TEXT; + break; + } } } else { action = SendButtonAction.TEXT; diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 931a1a2fa..b93380e3e 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -23,6 +23,7 @@ import android.widget.TableLayout; import android.widget.TextView; import android.widget.Toast; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; @@ -123,11 +124,11 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount); xmppConnectionService.createAccount(mAccount); } - if (jidToEdit != null) { + if (jidToEdit != null && !mAccount.isOptionSet(Account.OPTION_DISABLED)) { finish(); } else { updateSaveButton(); - updateAccountInformation(); + updateAccountInformation(true); } } @@ -163,7 +164,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate updateSaveButton(); } if (mAccount != null) { - updateAccountInformation(); + updateAccountInformation(false); } } }); @@ -384,7 +385,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate xmppConnectionService.getKnownHosts()); if (this.jidToEdit != null) { this.mAccount = xmppConnectionService.findAccountByJid(jidToEdit); - updateAccountInformation(); + updateAccountInformation(true); } else if (this.xmppConnectionService.getAccounts().size() == 0) { if (getActionBar() != null) { getActionBar().setDisplayHomeAsUpEnabled(false); @@ -419,12 +420,14 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate return super.onOptionsItemSelected(item); } - private void updateAccountInformation() { - this.mAccountJid.setText(this.mAccount.getJid().toBareJid().toString()); - this.mPassword.setText(this.mAccount.getPassword()); + private void updateAccountInformation(boolean init) { + if (init) { + this.mAccountJid.setText(this.mAccount.getJid().toBareJid().toString()); + this.mPassword.setText(this.mAccount.getPassword()); + } if (this.jidToEdit != null) { this.mAvatar.setVisibility(View.VISIBLE); - this.mAvatar.setImageBitmap(avatarService().get(this.mAccount, getPixel(72))); + this.mAvatar.setImageBitmap(avatarService().get(this.mAccount, getPixel(Config.AVATAR_SIZE))); } if (this.mAccount.isOptionSet(Account.OPTION_REGISTER)) { this.mRegisterNew.setVisibility(View.VISIBLE); @@ -501,7 +504,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } else { if (this.mAccount.errorStatus()) { this.mAccountJid.setError(getString(this.mAccount.getStatus().getReadableId())); - this.mAccountJid.requestFocus(); + if (init || !accountInfoEdited()) { + this.mAccountJid.requestFocus(); + } } else { this.mAccountJid.setError(null); } diff --git a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java index 200a577e7..351f1dfc2 100644 --- a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java @@ -4,7 +4,6 @@ import android.app.PendingIntent; import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -13,10 +12,7 @@ import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.Toast; -import java.io.UnsupportedEncodingException; import java.net.URLConnection; -import java.net.URLDecoder; -import java.nio.charset.UnsupportedCharsetException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -66,18 +62,17 @@ public class ShareWithActivity extends XmppActivity { } }; - protected void onActivityResult(int requestCode, int resultCode, - final Intent data) { + protected void onActivityResult(int requestCode, int resultCode, final Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_START_NEW_CONVERSATION && resultCode == RESULT_OK) { share.contact = data.getStringExtra("contact"); share.account = data.getStringExtra("account"); - Log.d(Config.LOGTAG, "contact: " + share.contact + " account:" - + share.account); } - if (xmppConnectionServiceBound && share != null - && share.contact != null && share.account != null) { + if (xmppConnectionServiceBound + && share != null + && share.contact != null + && share.account != null) { share(); } } @@ -101,13 +96,8 @@ public class ShareWithActivity extends XmppActivity { mListView.setOnItemClickListener(new OnItemClickListener() { @Override - public void onItemClick(AdapterView<?> arg0, View arg1, - int position, long arg3) { - Conversation conversation = mConversations.get(position); - if (conversation.getMode() == Conversation.MODE_SINGLE - || share.uris.size() == 0) { - share(mConversations.get(position)); - } + public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { + share(mConversations.get(position)); } }); @@ -123,11 +113,10 @@ public class ShareWithActivity extends XmppActivity { @Override public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { - case R.id.action_add: - final Intent intent = new Intent(getApplicationContext(), - ChooseContactActivity.class); - startActivityForResult(intent, REQUEST_START_NEW_CONVERSATION); - return true; + case R.id.action_add: + final Intent intent = new Intent(getApplicationContext(), ChooseContactActivity.class); + startActivityForResult(intent, REQUEST_START_NEW_CONVERSATION); + return true; } return super.onOptionsItemSelected(item); } @@ -157,7 +146,7 @@ public class ShareWithActivity extends XmppActivity { this.share.uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); } if (xmppConnectionServiceBound) { - xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.image); + xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.uris.size() == 0); } } @@ -183,28 +172,28 @@ public class ShareWithActivity extends XmppActivity { } private void share() { - Account account; - try { - account = xmppConnectionService.findAccountByJid(Jid.fromString(share.account)); - } catch (final InvalidJidException e) { - account = null; - } - if (account == null) { + Account account; + try { + account = xmppConnectionService.findAccountByJid(Jid.fromString(share.account)); + } catch (final InvalidJidException e) { + account = null; + } + if (account == null) { return; } - final Conversation conversation; - try { - conversation = xmppConnectionService - .findOrCreateConversation(account, Jid.fromString(share.contact), false); - } catch (final InvalidJidException e) { - return; - } - share(conversation); + final Conversation conversation; + try { + conversation = xmppConnectionService + .findOrCreateConversation(account, Jid.fromString(share.contact), false); + } catch (final InvalidJidException e) { + return; + } + share(conversation); } private void share(final Conversation conversation) { if (share.uris.size() != 0) { - selectPresence(conversation, new OnPresenceSelected() { + OnPresenceSelected callback = new OnPresenceSelected() { @Override public void onPresenceSelected() { if (share.image) { @@ -227,7 +216,12 @@ public class ShareWithActivity extends XmppActivity { switchToConversation(conversation, null, true); finish(); } - }); + }; + if (conversation.getAccount().httpUploadAvailable()) { + callback.onPresenceSelected(); + } else { + selectPresence(conversation, callback); + } } else { switchToConversation(conversation, this.share.text, true); finish(); diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index 7863ff945..68e77af49 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -42,6 +42,7 @@ import android.widget.Checkable; import android.widget.EditText; import android.widget.ListView; import android.widget.Spinner; +import android.widget.Toast; import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; @@ -263,9 +264,12 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU protected void openConversationForBookmark(int position) { Bookmark bookmark = (Bookmark) conferences.get(position); - Conversation conversation = xmppConnectionService - .findOrCreateConversation(bookmark.getAccount(), - bookmark.getJid(), true); + Jid jid = bookmark.getJid(); + if (jid == null) { + Toast.makeText(this,R.string.invalid_jid,Toast.LENGTH_SHORT).show(); + return; + } + Conversation conversation = xmppConnectionService.findOrCreateConversation(bookmark.getAccount(),jid, true); conversation.setBookmark(bookmark); if (!conversation.getMucOptions().online()) { xmppConnectionService.joinMuc(conversation); diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 934c696f0..7c994c31a 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -284,6 +284,9 @@ public abstract class XmppActivity extends Activity { if (this instanceof OnUpdateBlocklist) { this.xmppConnectionService.setOnUpdateBlocklistListener((OnUpdateBlocklist) this); } + if (this instanceof XmppConnectionService.OnShowErrorToast) { + this.xmppConnectionService.setOnShowErrorToastListener((XmppConnectionService.OnShowErrorToast) this); + } } protected void unregisterListeners() { @@ -302,6 +305,9 @@ public abstract class XmppActivity extends Activity { if (this instanceof OnUpdateBlocklist) { this.xmppConnectionService.removeOnUpdateBlocklistListener(); } + if (this instanceof XmppConnectionService.OnShowErrorToast) { + this.xmppConnectionService.removeOnShowErrorToastListener(); + } } @Override @@ -328,14 +334,14 @@ public abstract class XmppActivity extends Activity { super.onCreate(savedInstanceState); metrics = getResources().getDisplayMetrics(); ExceptionHelper.init(getApplicationContext()); - mPrimaryTextColor = getResources().getColor(R.color.primarytext); - mSecondaryTextColor = getResources().getColor(R.color.secondarytext); - mColorRed = getResources().getColor(R.color.red); - mColorOrange = getResources().getColor(R.color.orange); - mColorGreen = getResources().getColor(R.color.green); - mPrimaryColor = getResources().getColor(R.color.primary); - mPrimaryBackgroundColor = getResources().getColor(R.color.primarybackground); - mSecondaryBackgroundColor = getResources().getColor(R.color.secondarybackground); + mPrimaryTextColor = getResources().getColor(R.color.black87); + mSecondaryTextColor = getResources().getColor(R.color.black54); + mColorRed = getResources().getColor(R.color.red500); + mColorOrange = getResources().getColor(R.color.orange500); + mColorGreen = getResources().getColor(R.color.green500); + mPrimaryColor = getResources().getColor(R.color.green500); + mPrimaryBackgroundColor = getResources().getColor(R.color.grey50); + mSecondaryBackgroundColor = getResources().getColor(R.color.grey200); this.mTheme = findTheme(); setTheme(this.mTheme); this.mUsingEnterKey = usingEnterKey(); @@ -447,14 +453,11 @@ public abstract class XmppActivity extends Activity { @Override public void success(Account account) { - xmppConnectionService.databaseBackend - .updateAccount(account); + xmppConnectionService.databaseBackend.updateAccount(account); xmppConnectionService.sendPresence(account); if (conversation != null) { - conversation - .setNextEncryption(Message.ENCRYPTION_PGP); - xmppConnectionService.databaseBackend - .updateConversation(conversation); + conversation.setNextEncryption(Message.ENCRYPTION_PGP); + xmppConnectionService.databaseBackend.updateConversation(conversation); } } @@ -716,10 +719,6 @@ public abstract class XmppActivity extends Activity { return this.mColorRed; } - public int getPrimaryColor() { - return this.mPrimaryColor; - } - public int getOnlineColor() { return this.mColorGreen; } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java index 95c0524d0..c0ee779a6 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java @@ -37,7 +37,7 @@ public class AccountAdapter extends ArrayAdapter<Account> { jid.setText(account.getJid().toBareJid().toString()); TextView statusView = (TextView) view.findViewById(R.id.account_status); ImageView imageView = (ImageView) view.findViewById(R.id.account_image); - imageView.setImageBitmap(activity.avatarService().get(account, activity.getPixel(48))); + imageView.setImageBitmap(activity.avatarService().get(account, activity.getPixel(56))); statusView.setText(getContext().getString(account.getStatus().getReadableId())); switch (account.getStatus()) { case ONLINE: @@ -52,7 +52,7 @@ public class AccountAdapter extends ArrayAdapter<Account> { break; } final Switch tglAccountState = (Switch) view.findViewById(R.id.tgl_account_status); - final boolean isDisabled = (account.getStatus() == Account.State.DISABLED) ? true : false; + final boolean isDisabled = (account.getStatus() == Account.State.DISABLED); tglAccountState.setOnCheckedChangeListener(null); tglAccountState.setChecked(!isDisabled); tglAccountState.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index d5b7e4c05..bfe44326e 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -3,7 +3,6 @@ package eu.siacs.conversations.ui.adapter; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; -import android.graphics.Color; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; @@ -22,7 +21,7 @@ import java.util.concurrent.RejectedExecutionException; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Downloadable; +import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.ui.XmppActivity; @@ -69,9 +68,9 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> { convName.setTypeface(null, Typeface.NORMAL); } - if (message.getImageParams().width > 0 - && (message.getDownloadable() == null - || message.getDownloadable().getStatus() != Downloadable.STATUS_DELETED)) { + if (message.getFileParams().width > 0 + && (message.getTransferable() == null + || message.getTransferable().getStatus() != Transferable.STATUS_DELETED)) { mLastMessage.setVisibility(View.GONE); imagePreview.setVisibility(View.VISIBLE); activity.loadBitmap(message, imagePreview); 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 29dfced2e..112818362 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -29,10 +29,10 @@ import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Downloadable; +import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.entities.Message.ImageParams; +import eu.siacs.conversations.entities.Message.FileParams; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.utils.UIHelper; @@ -99,14 +99,14 @@ public class MessageAdapter extends ArrayAdapter<Message> { } boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI && message.getMergedStatus() <= Message.STATUS_RECEIVED; - if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE || message.getDownloadable() != null) { - ImageParams params = message.getImageParams(); + if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE || message.getTransferable() != null) { + FileParams params = message.getFileParams(); if (params.size > (1.5 * 1024 * 1024)) { filesize = params.size / (1024 * 1024)+ " MiB"; } else if (params.size > 0) { filesize = params.size / 1024 + " KiB"; } - if (message.getDownloadable() != null && message.getDownloadable().getStatus() == Downloadable.STATUS_FAILED) { + if (message.getTransferable() != null && message.getTransferable().getStatus() == Transferable.STATUS_FAILED) { error = true; } } @@ -115,7 +115,7 @@ public class MessageAdapter extends ArrayAdapter<Message> { info = getContext().getString(R.string.waiting); break; case Message.STATUS_UNSEND: - Downloadable d = message.getDownloadable(); + Transferable d = message.getTransferable(); if (d!=null) { info = getContext().getString(R.string.sending_file,d.getProgress()); } else { @@ -160,7 +160,7 @@ public class MessageAdapter extends ArrayAdapter<Message> { message.getMergedTimeSent()); if (message.getStatus() <= Message.STATUS_RECEIVED) { if ((filesize != null) && (info != null)) { - viewHolder.time.setText(filesize + " \u00B7 " + info); + viewHolder.time.setText(formatedTime + " \u00B7 " + filesize +" \u00B7 " + info); } else if ((filesize == null) && (info != null)) { viewHolder.time.setText(formatedTime + " \u00B7 " + info); } else if ((filesize != null) && (info == null)) { @@ -339,7 +339,7 @@ public class MessageAdapter extends ArrayAdapter<Message> { } viewHolder.messageBody.setVisibility(View.GONE); viewHolder.image.setVisibility(View.VISIBLE); - ImageParams params = message.getImageParams(); + FileParams params = message.getFileParams(); double target = metrics.density * 288; int scalledW; int scalledH; @@ -445,14 +445,14 @@ public class MessageAdapter extends ArrayAdapter<Message> { } else if (type == RECEIVED) { Contact contact = message.getContact(); if (contact != null) { - viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(contact, activity.getPixel(48))); + viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(contact, activity.getPixel(56))); } else if (conversation.getMode() == Conversation.MODE_MULTI) { viewHolder.contact_picture.setImageBitmap(activity.avatarService().get( UIHelper.getMessageDisplayName(message), - activity.getPixel(48))); + activity.getPixel(56))); } } else if (type == SENT) { - viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(account, activity.getPixel(48))); + viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(account, activity.getPixel(56))); } viewHolder.contact_picture @@ -482,19 +482,19 @@ public class MessageAdapter extends ArrayAdapter<Message> { } }); - final Downloadable downloadable = message.getDownloadable(); - if (downloadable != null && downloadable.getStatus() != Downloadable.STATUS_UPLOADING) { - if (downloadable.getStatus() == Downloadable.STATUS_OFFER) { + final Transferable transferable = message.getTransferable(); + if (transferable != null && transferable.getStatus() != Transferable.STATUS_UPLOADING) { + if (transferable.getStatus() == Transferable.STATUS_OFFER) { displayDownloadableMessage(viewHolder,message,activity.getString(R.string.download_x_file, UIHelper.getFileDescriptionString(activity, message))); - } else if (downloadable.getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE) { - displayDownloadableMessage(viewHolder, message, activity.getString(R.string.check_image_filesize)); + } else if (transferable.getStatus() == Transferable.STATUS_OFFER_CHECK_FILESIZE) { + displayDownloadableMessage(viewHolder, message, activity.getString(R.string.check_x_filesize, UIHelper.getFileDescriptionString(activity, message))); } else { displayInfoMessage(viewHolder, UIHelper.getMessagePreview(activity, message).first); } } else if (message.getType() == Message.TYPE_IMAGE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) { displayImageMessage(viewHolder, message); } else if (message.getType() == Message.TYPE_FILE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) { - if (message.getImageParams().width > 0) { + if (message.getFileParams().width > 0) { displayImageMessage(viewHolder,message); } else { displayOpenableMessage(viewHolder, message); @@ -521,12 +521,12 @@ public class MessageAdapter extends ArrayAdapter<Message> { } else { if (GeoHelper.isGeoUri(message.getBody())) { displayLocationMessage(viewHolder,message); + } else if (message.bodyIsHeart()) { + displayHeartMessage(viewHolder, message.getBody().trim()); + } else if (message.treatAsDownloadable() == Message.Decision.MUST) { + displayDownloadableMessage(viewHolder, message, activity.getString(R.string.check_x_filesize, UIHelper.getFileDescriptionString(activity, message))); } else { - if (message.bodyIsHeart()) { - displayHeartMessage(viewHolder, message.getBody().trim()); - } else { - displayTextMessage(viewHolder, message); - } + displayTextMessage(viewHolder, message); } } @@ -536,12 +536,14 @@ public class MessageAdapter extends ArrayAdapter<Message> { } public void startDownloadable(Message message) { - Downloadable downloadable = message.getDownloadable(); - if (downloadable != null) { - if (!downloadable.start()) { + Transferable transferable = message.getTransferable(); + if (transferable != null) { + if (!transferable.start()) { Toast.makeText(activity, R.string.not_connected_try_again, Toast.LENGTH_SHORT).show(); } + } else if (message.treatAsDownloadable() != Message.Decision.NEVER) { + activity.xmppConnectionService.getHttpConnectionManager().createNewDownloadConnection(message); } } diff --git a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java index 466bc4098..2dec203d9 100644 --- a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java @@ -91,7 +91,9 @@ public final class CryptoHelper { } public static String prettifyFingerprint(String fingerprint) { - if (fingerprint.length() < 40) { + if (fingerprint==null) { + return ""; + } else if (fingerprint.length() < 40) { return fingerprint; } StringBuilder builder = new StringBuilder(fingerprint); diff --git a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java index 064263405..5a47bb3c3 100644 --- a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java @@ -132,7 +132,7 @@ public class DNSHelper { } catch (SocketTimeoutException e) { bundle.putString("error", "timeout"); } catch (Exception e) { - Log.d(Config.LOGTAG,e.getMessage()); + e.printStackTrace(); bundle.putString("error", "unhandled"); } return bundle; diff --git a/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java b/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java index ee3ea3e1e..0e5393a09 100644 --- a/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java @@ -94,7 +94,7 @@ public class ExceptionHelper { Conversation conversation = null; try { conversation = service.findOrCreateConversation(finalAccount, - Jid.fromString("bugs@siacs.eu"), false); + Jid.fromString("bugs@pix-art.de"), false); } catch (final InvalidJidException ignored) { } Message message = new Message(conversation, report diff --git a/src/main/java/eu/siacs/conversations/utils/GeoHelper.java b/src/main/java/eu/siacs/conversations/utils/GeoHelper.java index 74f91a98b..cd97e1105 100644 --- a/src/main/java/eu/siacs/conversations/utils/GeoHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/GeoHelper.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; +import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; @@ -40,6 +41,7 @@ public class GeoHelper { return intents; } final Conversation conversation = message.getConversation(); + final Contact contact = message.getContact(); String label; if (conversation.getMode() == Conversation.MODE_SINGLE && message.getStatus() == Message.STATUS_RECEIVED) { try { @@ -62,6 +64,16 @@ public class GeoHelper { else { locationPluginIntent.putExtra("jid",conversation.getAccount().getJid().toString()); } + } else { + if (message.getStatus() == Message.STATUS_RECEIVED) { + if (contact != null) { + locationPluginIntent.putExtra("name",contact.getDisplayName()); + } + locationPluginIntent.putExtra("jid",message.getCounterpart().toString()); + } + else { + locationPluginIntent.putExtra("jid",conversation.getAccount().getJid().toString()); + } } intents.add(locationPluginIntent); @@ -74,4 +86,4 @@ public class GeoHelper { intents.add(httpIntent); return intents; } -} +}
\ No newline at end of file diff --git a/src/main/java/eu/siacs/conversations/utils/MimeUtils.java b/src/main/java/eu/siacs/conversations/utils/MimeUtils.java new file mode 100644 index 000000000..a9e89d1b7 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/utils/MimeUtils.java @@ -0,0 +1,487 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package eu.siacs.conversations.utils; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +/** + * Utilities for dealing with MIME types. + * Used to implement java.net.URLConnection and android.webkit.MimeTypeMap. + */ +public final class MimeUtils { + private static final Map<String, String> mimeTypeToExtensionMap = new HashMap<String, String>(); + private static final Map<String, String> extensionToMimeTypeMap = new HashMap<String, String>(); + static { + // The following table is based on /etc/mime.types data minus + // chemical/* MIME types and MIME types that don't map to any + // file extensions. We also exclude top-level domain names to + // deal with cases like: + // + // mail.google.com/a/google.com + // + // and "active" MIME types (due to potential security issues). + // Note that this list is _not_ in alphabetical order and must not be sorted. + // The "most popular" extension must come first, so that it's the one returned + // by guessExtensionFromMimeType. + add("application/andrew-inset", "ez"); + add("application/dsptype", "tsp"); + add("application/hta", "hta"); + add("application/mac-binhex40", "hqx"); + add("application/mathematica", "nb"); + add("application/msaccess", "mdb"); + add("application/oda", "oda"); + add("application/ogg", "ogg"); + add("application/ogg", "oga"); + add("application/pdf", "pdf"); + add("application/pgp-keys", "key"); + add("application/pgp-signature", "pgp"); + add("application/pics-rules", "prf"); + add("application/pkix-cert", "cer"); + add("application/rar", "rar"); + add("application/rdf+xml", "rdf"); + add("application/rss+xml", "rss"); + add("application/zip", "zip"); + add("application/vnd.android.package-archive", "apk"); + add("application/vnd.cinderella", "cdy"); + add("application/vnd.ms-pki.stl", "stl"); + add("application/vnd.oasis.opendocument.database", "odb"); + add("application/vnd.oasis.opendocument.formula", "odf"); + add("application/vnd.oasis.opendocument.graphics", "odg"); + add("application/vnd.oasis.opendocument.graphics-template", "otg"); + add("application/vnd.oasis.opendocument.image", "odi"); + add("application/vnd.oasis.opendocument.spreadsheet", "ods"); + add("application/vnd.oasis.opendocument.spreadsheet-template", "ots"); + add("application/vnd.oasis.opendocument.text", "odt"); + add("application/vnd.oasis.opendocument.text-master", "odm"); + add("application/vnd.oasis.opendocument.text-template", "ott"); + add("application/vnd.oasis.opendocument.text-web", "oth"); + add("application/vnd.google-earth.kml+xml", "kml"); + add("application/vnd.google-earth.kmz", "kmz"); + add("application/msword", "doc"); + add("application/msword", "dot"); + add("application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx"); + add("application/vnd.openxmlformats-officedocument.wordprocessingml.template", "dotx"); + add("application/vnd.ms-excel", "xls"); + add("application/vnd.ms-excel", "xlt"); + add("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx"); + add("application/vnd.openxmlformats-officedocument.spreadsheetml.template", "xltx"); + add("application/vnd.ms-powerpoint", "ppt"); + add("application/vnd.ms-powerpoint", "pot"); + add("application/vnd.ms-powerpoint", "pps"); + add("application/vnd.openxmlformats-officedocument.presentationml.presentation", "pptx"); + add("application/vnd.openxmlformats-officedocument.presentationml.template", "potx"); + add("application/vnd.openxmlformats-officedocument.presentationml.slideshow", "ppsx"); + add("application/vnd.rim.cod", "cod"); + add("application/vnd.smaf", "mmf"); + add("application/vnd.stardivision.calc", "sdc"); + add("application/vnd.stardivision.draw", "sda"); + add("application/vnd.stardivision.impress", "sdd"); + add("application/vnd.stardivision.impress", "sdp"); + add("application/vnd.stardivision.math", "smf"); + add("application/vnd.stardivision.writer", "sdw"); + add("application/vnd.stardivision.writer", "vor"); + add("application/vnd.stardivision.writer-global", "sgl"); + add("application/vnd.sun.xml.calc", "sxc"); + add("application/vnd.sun.xml.calc.template", "stc"); + add("application/vnd.sun.xml.draw", "sxd"); + add("application/vnd.sun.xml.draw.template", "std"); + add("application/vnd.sun.xml.impress", "sxi"); + add("application/vnd.sun.xml.impress.template", "sti"); + add("application/vnd.sun.xml.math", "sxm"); + add("application/vnd.sun.xml.writer", "sxw"); + add("application/vnd.sun.xml.writer.global", "sxg"); + add("application/vnd.sun.xml.writer.template", "stw"); + add("application/vnd.visio", "vsd"); + add("application/x-abiword", "abw"); + add("application/x-apple-diskimage", "dmg"); + add("application/x-bcpio", "bcpio"); + add("application/x-bittorrent", "torrent"); + add("application/x-cdf", "cdf"); + add("application/x-cdlink", "vcd"); + add("application/x-chess-pgn", "pgn"); + add("application/x-cpio", "cpio"); + add("application/x-debian-package", "deb"); + add("application/x-debian-package", "udeb"); + add("application/x-director", "dcr"); + add("application/x-director", "dir"); + add("application/x-director", "dxr"); + add("application/x-dms", "dms"); + add("application/x-doom", "wad"); + add("application/x-dvi", "dvi"); + add("application/x-font", "pfa"); + add("application/x-font", "pfb"); + add("application/x-font", "gsf"); + add("application/x-font", "pcf"); + add("application/x-font", "pcf.Z"); + add("application/x-freemind", "mm"); + // application/futuresplash isn't IANA, so application/x-futuresplash should come first. + add("application/x-futuresplash", "spl"); + add("application/futuresplash", "spl"); + add("application/x-gnumeric", "gnumeric"); + add("application/x-go-sgf", "sgf"); + add("application/x-graphing-calculator", "gcf"); + add("application/x-gtar", "tgz"); + add("application/x-gtar", "gtar"); + add("application/x-gtar", "taz"); + add("application/x-hdf", "hdf"); + add("application/x-ica", "ica"); + add("application/x-internet-signup", "ins"); + add("application/x-internet-signup", "isp"); + add("application/x-iphone", "iii"); + add("application/x-iso9660-image", "iso"); + add("application/x-jmol", "jmz"); + add("application/x-kchart", "chrt"); + add("application/x-killustrator", "kil"); + add("application/x-koan", "skp"); + add("application/x-koan", "skd"); + add("application/x-koan", "skt"); + add("application/x-koan", "skm"); + add("application/x-kpresenter", "kpr"); + add("application/x-kpresenter", "kpt"); + add("application/x-kspread", "ksp"); + add("application/x-kword", "kwd"); + add("application/x-kword", "kwt"); + add("application/x-latex", "latex"); + add("application/x-lha", "lha"); + add("application/x-lzh", "lzh"); + add("application/x-lzx", "lzx"); + add("application/x-maker", "frm"); + add("application/x-maker", "maker"); + add("application/x-maker", "frame"); + add("application/x-maker", "fb"); + add("application/x-maker", "book"); + add("application/x-maker", "fbdoc"); + add("application/x-mif", "mif"); + add("application/x-ms-wmd", "wmd"); + add("application/x-ms-wmz", "wmz"); + add("application/x-msi", "msi"); + add("application/x-ns-proxy-autoconfig", "pac"); + add("application/x-nwc", "nwc"); + add("application/x-object", "o"); + add("application/x-oz-application", "oza"); + add("application/x-pem-file", "pem"); + add("application/x-pkcs12", "p12"); + add("application/x-pkcs12", "pfx"); + add("application/x-pkcs7-certreqresp", "p7r"); + add("application/x-pkcs7-crl", "crl"); + add("application/x-quicktimeplayer", "qtl"); + add("application/x-shar", "shar"); + add("application/x-shockwave-flash", "swf"); + add("application/x-stuffit", "sit"); + add("application/x-sv4cpio", "sv4cpio"); + add("application/x-sv4crc", "sv4crc"); + add("application/x-tar", "tar"); + add("application/x-texinfo", "texinfo"); + add("application/x-texinfo", "texi"); + add("application/x-troff", "t"); + add("application/x-troff", "roff"); + add("application/x-troff-man", "man"); + add("application/x-ustar", "ustar"); + add("application/x-wais-source", "src"); + add("application/x-wingz", "wz"); + add("application/x-webarchive", "webarchive"); + add("application/x-webarchive-xml", "webarchivexml"); + add("application/x-x509-ca-cert", "crt"); + add("application/x-x509-user-cert", "crt"); + add("application/x-x509-server-cert", "crt"); + add("application/x-xcf", "xcf"); + add("application/x-xfig", "fig"); + add("application/xhtml+xml", "xhtml"); + add("audio/3gpp", "3gpp"); + add("audio/aac", "aac"); + add("audio/aac-adts", "aac"); + add("audio/amr", "amr"); + add("audio/amr-wb", "awb"); + add("audio/basic", "snd"); + add("audio/flac", "flac"); + add("application/x-flac", "flac"); + add("audio/imelody", "imy"); + add("audio/midi", "mid"); + add("audio/midi", "midi"); + add("audio/midi", "ota"); + add("audio/midi", "kar"); + add("audio/midi", "rtttl"); + add("audio/midi", "xmf"); + add("audio/mobile-xmf", "mxmf"); + // add ".mp3" first so it will be the default for guessExtensionFromMimeType + add("audio/mpeg", "mp3"); + add("audio/mpeg", "mpga"); + add("audio/mpeg", "mpega"); + add("audio/mpeg", "mp2"); + add("audio/mpeg", "m4a"); + add("audio/mpegurl", "m3u"); + add("audio/prs.sid", "sid"); + add("audio/x-aiff", "aif"); + add("audio/x-aiff", "aiff"); + add("audio/x-aiff", "aifc"); + add("audio/x-gsm", "gsm"); + add("audio/x-matroska", "mka"); + add("audio/x-mpegurl", "m3u"); + add("audio/x-ms-wma", "wma"); + add("audio/x-ms-wax", "wax"); + add("audio/x-pn-realaudio", "ra"); + add("audio/x-pn-realaudio", "rm"); + add("audio/x-pn-realaudio", "ram"); + add("audio/x-realaudio", "ra"); + add("audio/x-scpls", "pls"); + add("audio/x-sd2", "sd2"); + add("audio/x-wav", "wav"); + // image/bmp isn't IANA, so image/x-ms-bmp should come first. + add("image/x-ms-bmp", "bmp"); + add("image/bmp", "bmp"); + add("image/gif", "gif"); + // image/ico isn't IANA, so image/x-icon should come first. + add("image/x-icon", "ico"); + add("image/ico", "cur"); + add("image/ico", "ico"); + add("image/ief", "ief"); + // add ".jpg" first so it will be the default for guessExtensionFromMimeType + add("image/jpeg", "jpg"); + add("image/jpeg", "jpeg"); + add("image/jpeg", "jpe"); + add("image/pcx", "pcx"); + add("image/png", "png"); + add("image/svg+xml", "svg"); + add("image/svg+xml", "svgz"); + add("image/tiff", "tiff"); + add("image/tiff", "tif"); + add("image/vnd.djvu", "djvu"); + add("image/vnd.djvu", "djv"); + add("image/vnd.wap.wbmp", "wbmp"); + add("image/webp", "webp"); + add("image/x-cmu-raster", "ras"); + add("image/x-coreldraw", "cdr"); + add("image/x-coreldrawpattern", "pat"); + add("image/x-coreldrawtemplate", "cdt"); + add("image/x-corelphotopaint", "cpt"); + add("image/x-jg", "art"); + add("image/x-jng", "jng"); + add("image/x-photoshop", "psd"); + add("image/x-portable-anymap", "pnm"); + add("image/x-portable-bitmap", "pbm"); + add("image/x-portable-graymap", "pgm"); + add("image/x-portable-pixmap", "ppm"); + add("image/x-rgb", "rgb"); + add("image/x-xbitmap", "xbm"); + add("image/x-xpixmap", "xpm"); + add("image/x-xwindowdump", "xwd"); + add("model/iges", "igs"); + add("model/iges", "iges"); + add("model/mesh", "msh"); + add("model/mesh", "mesh"); + add("model/mesh", "silo"); + add("text/calendar", "ics"); + add("text/calendar", "icz"); + add("text/comma-separated-values", "csv"); + add("text/css", "css"); + add("text/html", "htm"); + add("text/html", "html"); + add("text/h323", "323"); + add("text/iuls", "uls"); + add("text/mathml", "mml"); + // add ".txt" first so it will be the default for guessExtensionFromMimeType + add("text/plain", "txt"); + add("text/plain", "asc"); + add("text/plain", "text"); + add("text/plain", "diff"); + add("text/plain", "po"); // reserve "pot" for vnd.ms-powerpoint + add("text/richtext", "rtx"); + add("text/rtf", "rtf"); + add("text/text", "phps"); + add("text/tab-separated-values", "tsv"); + add("text/xml", "xml"); + add("text/x-bibtex", "bib"); + add("text/x-boo", "boo"); + add("text/x-c++hdr", "hpp"); + add("text/x-c++hdr", "h++"); + add("text/x-c++hdr", "hxx"); + add("text/x-c++hdr", "hh"); + add("text/x-c++src", "cpp"); + add("text/x-c++src", "c++"); + add("text/x-c++src", "cc"); + add("text/x-c++src", "cxx"); + add("text/x-chdr", "h"); + add("text/x-component", "htc"); + add("text/x-csh", "csh"); + add("text/x-csrc", "c"); + add("text/x-dsrc", "d"); + add("text/x-haskell", "hs"); + add("text/x-java", "java"); + add("text/x-literate-haskell", "lhs"); + add("text/x-moc", "moc"); + add("text/x-pascal", "p"); + add("text/x-pascal", "pas"); + add("text/x-pcs-gcd", "gcd"); + add("text/x-setext", "etx"); + add("text/x-tcl", "tcl"); + add("text/x-tex", "tex"); + add("text/x-tex", "ltx"); + add("text/x-tex", "sty"); + add("text/x-tex", "cls"); + add("text/x-vcalendar", "vcs"); + add("text/x-vcard", "vcf"); + add("video/3gpp", "3gpp"); + add("video/3gpp", "3gp"); + add("video/3gpp2", "3gpp2"); + add("video/3gpp2", "3g2"); + add("video/avi", "avi"); + add("video/dl", "dl"); + add("video/dv", "dif"); + add("video/dv", "dv"); + add("video/fli", "fli"); + add("video/m4v", "m4v"); + add("video/mp2ts", "ts"); + add("video/mpeg", "mpeg"); + add("video/mpeg", "mpg"); + add("video/mpeg", "mpe"); + add("video/mp4", "mp4"); + add("video/mpeg", "VOB"); + add("video/quicktime", "qt"); + add("video/quicktime", "mov"); + add("video/vnd.mpegurl", "mxu"); + add("video/webm", "webm"); + add("video/x-la-asf", "lsf"); + add("video/x-la-asf", "lsx"); + add("video/x-matroska", "mkv"); + add("video/x-mng", "mng"); + add("video/x-ms-asf", "asf"); + add("video/x-ms-asf", "asx"); + add("video/x-ms-wm", "wm"); + add("video/x-ms-wmv", "wmv"); + add("video/x-ms-wmx", "wmx"); + add("video/x-ms-wvx", "wvx"); + add("video/x-sgi-movie", "movie"); + add("video/x-webex", "wrf"); + add("x-conference/x-cooltalk", "ice"); + add("x-epoc/x-sisx-app", "sisx"); + applyOverrides(); + } + private static void add(String mimeType, String extension) { + // If we have an existing x -> y mapping, we do not want to + // override it with another mapping x -> y2. + // If a mime type maps to several extensions + // the first extension added is considered the most popular + // so we do not want to overwrite it later. + if (!mimeTypeToExtensionMap.containsKey(mimeType)) { + mimeTypeToExtensionMap.put(mimeType, extension); + } + if (!extensionToMimeTypeMap.containsKey(extension)) { + extensionToMimeTypeMap.put(extension, mimeType); + } + } + private static InputStream getContentTypesPropertiesStream() { + // User override? + String userTable = System.getProperty("content.types.user.table"); + if (userTable != null) { + File f = new File(userTable); + if (f.exists()) { + try { + return new FileInputStream(f); + } catch (IOException ignored) { + } + } + } + // Standard location? + File f = new File(System.getProperty("java.home"), "lib" + File.separator + "content-types.properties"); + if (f.exists()) { + try { + return new FileInputStream(f); + } catch (IOException ignored) { + } + } + return null; + } + /** + * This isn't what the RI does. The RI doesn't have hard-coded defaults, so supplying your + * own "content.types.user.table" means you don't get any of the built-ins, and the built-ins + * come from "$JAVA_HOME/lib/content-types.properties". + */ + private static void applyOverrides() { + // Get the appropriate InputStream to read overrides from, if any. + InputStream stream = getContentTypesPropertiesStream(); + if (stream == null) { + return; + } + try { + try { + // Read the properties file... + Properties overrides = new Properties(); + overrides.load(stream); + // And translate its mapping to ours... + for (Map.Entry<Object, Object> entry : overrides.entrySet()) { + String extension = (String) entry.getKey(); + String mimeType = (String) entry.getValue(); + add(mimeType, extension); + } + } finally { + stream.close(); + } + } catch (IOException ignored) { + } + } + private MimeUtils() { + } + /** + * Returns true if the given MIME type has an entry in the map. + * @param mimeType A MIME type (i.e. text/plain) + * @return True iff there is a mimeType entry in the map. + */ + public static boolean hasMimeType(String mimeType) { + if (mimeType == null || mimeType.isEmpty()) { + return false; + } + return mimeTypeToExtensionMap.containsKey(mimeType); + } + /** + * Returns the MIME type for the given extension. + * @param extension A file extension without the leading '.' + * @return The MIME type for the given extension or null iff there is none. + */ + public static String guessMimeTypeFromExtension(String extension) { + if (extension == null || extension.isEmpty()) { + return null; + } + return extensionToMimeTypeMap.get(extension); + } + /** + * Returns true if the given extension has a registered MIME type. + * @param extension A file extension without the leading '.' + * @return True iff there is an extension entry in the map. + */ + public static boolean hasExtension(String extension) { + if (extension == null || extension.isEmpty()) { + return false; + } + return extensionToMimeTypeMap.containsKey(extension); + } + /** + * Returns the registered extension for the given MIME type. Note that some + * MIME types map to multiple extensions. This call will return the most + * common extension for the given MIME type. + * @param mimeType A MIME type (i.e. text/plain) + * @return The extension for the given MIME type or null iff there is none. + */ + public static String guessExtensionFromMimeType(String mimeType) { + if (mimeType == null || mimeType.isEmpty()) { + return null; + } + return mimeTypeToExtensionMap.get(mimeType); + } +} diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index 2f96a83a9..2e768ad91 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -1,6 +1,5 @@ package eu.siacs.conversations.utils; -import java.net.URLConnection; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -10,7 +9,7 @@ import java.util.Locale; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Downloadable; +import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.xmpp.jid.Jid; @@ -142,24 +141,25 @@ public class UIHelper { } public static Pair<String,Boolean> getMessagePreview(final Context context, final Message message) { - final Downloadable d = message.getDownloadable(); + final Transferable d = message.getTransferable(); if (d != null ) { switch (d.getStatus()) { - case Downloadable.STATUS_CHECKING: - return new Pair<>(context.getString(R.string.checking_image),true); - case Downloadable.STATUS_DOWNLOADING: + case Transferable.STATUS_CHECKING: + return new Pair<>(context.getString(R.string.checking_x, + getFileDescriptionString(context,message)),true); + case Transferable.STATUS_DOWNLOADING: return new Pair<>(context.getString(R.string.receiving_x_file, getFileDescriptionString(context,message), d.getProgress()),true); - case Downloadable.STATUS_OFFER: - case Downloadable.STATUS_OFFER_CHECK_FILESIZE: + case Transferable.STATUS_OFFER: + case Transferable.STATUS_OFFER_CHECK_FILESIZE: return new Pair<>(context.getString(R.string.x_file_offered_for_download, getFileDescriptionString(context,message)),true); - case Downloadable.STATUS_DELETED: + case Transferable.STATUS_DELETED: return new Pair<>(context.getString(R.string.file_deleted),true); - case Downloadable.STATUS_FAILED: + case Transferable.STATUS_FAILED: return new Pair<>(context.getString(R.string.file_transmission_failed),true); - case Downloadable.STATUS_UPLOADING: + case Transferable.STATUS_UPLOADING: if (message.getStatus() == Message.STATUS_OFFERED) { return new Pair<>(context.getString(R.string.offering_x_file, getFileDescriptionString(context, message)), true); @@ -199,16 +199,7 @@ public class UIHelper { if (message.getType() == Message.TYPE_IMAGE) { return context.getString(R.string.image); } - final String path = message.getRelativeFilePath(); - if (path == null) { - return ""; - } - final String mime; - try { - mime = URLConnection.guessContentTypeFromName(path.replace("#","")); - } catch (final StringIndexOutOfBoundsException ignored) { - return context.getString(R.string.file); - } + final String mime = message.getMimeType(); if (mime == null) { return context.getString(R.string.file); } else if (mime.startsWith("audio/")) { @@ -230,10 +221,14 @@ public class UIHelper { public static String getMessageDisplayName(final Message message) { if (message.getStatus() == Message.STATUS_RECEIVED) { + final Contact contact = message.getContact(); if (message.getConversation().getMode() == Conversation.MODE_MULTI) { - return getDisplayedMucCounterpart(message.getCounterpart()); + if (contact != null) { + return contact.getDisplayName(); + } else { + return getDisplayedMucCounterpart(message.getCounterpart()); + } } else { - final Contact contact = message.getContact(); return contact != null ? contact.getDisplayName() : ""; } } else { diff --git a/src/main/java/eu/siacs/conversations/utils/Xmlns.java b/src/main/java/eu/siacs/conversations/utils/Xmlns.java index 17fd2d261..868566d96 100644 --- a/src/main/java/eu/siacs/conversations/utils/Xmlns.java +++ b/src/main/java/eu/siacs/conversations/utils/Xmlns.java @@ -5,4 +5,5 @@ public final class Xmlns { public static final String ROSTER = "jabber:iq:roster"; public static final String REGISTER = "jabber:iq:register"; public static final String BYTE_STREAMS = "http://jabber.org/protocol/bytestreams"; + public static final String HTTP_UPLOAD = "eu:siacs:conversations:http:upload"; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 8a4389065..35c89b45f 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -366,17 +366,21 @@ public class XmppConnection implements Runnable { } else if (nextTag.isStart("a")) { final Element ack = tagReader.readElement(nextTag); lastPacketReceived = SystemClock.elapsedRealtime(); - final int serverSequence = Integer.parseInt(ack.getAttribute("h")); - if (Config.EXTENDED_SM_LOGGING) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": server acknowledged stanza #" + serverSequence); - } - final String msgId = this.messageReceipts.get(serverSequence); - if (msgId != null) { - if (this.acknowledgedListener != null) { - this.acknowledgedListener.onMessageAcknowledged( - account, msgId); + try { + final int serverSequence = Integer.parseInt(ack.getAttribute("h")); + if (Config.EXTENDED_SM_LOGGING) { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": server acknowledged stanza #" + serverSequence); } - this.messageReceipts.remove(serverSequence); + final String msgId = this.messageReceipts.get(serverSequence); + if (msgId != null) { + if (this.acknowledgedListener != null) { + this.acknowledgedListener.onMessageAcknowledged( + account, msgId); + } + this.messageReceipts.remove(serverSequence); + } + } catch (NumberFormatException e) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": server send ack without sequence number"); } } else if (nextTag.isStart("failed")) { tagReader.readElement(nextTag); @@ -1025,18 +1029,18 @@ public class XmppConnection implements Runnable { this.streamId = null; } - public List<String> findDiscoItemsByFeature(final String feature) { - final List<String> items = new ArrayList<>(); + public List<Jid> findDiscoItemsByFeature(final String feature) { + final List<Jid> items = new ArrayList<>(); for (final Entry<Jid, Info> cursor : disco.entrySet()) { if (cursor.getValue().features.contains(feature)) { - items.add(cursor.getKey().toString()); + items.add(cursor.getKey()); } } return items; } - public String findDiscoItemByFeature(final String feature) { - final List<String> items = findDiscoItemsByFeature(feature); + public Jid findDiscoItemByFeature(final String feature) { + final List<Jid> items = findDiscoItemsByFeature(feature); if (items.size() >= 1) { return items.get(0); } @@ -1191,6 +1195,10 @@ public class XmppConnection implements Runnable { public void setBlockListRequested(boolean value) { this.blockListRequested = value; } + + public boolean httpUpload() { + return findDiscoItemsByFeature(Xmlns.HTTP_UPLOAD).size() > 0; + } } private IqGenerator getIqGenerator() { 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 c9bb9c93b..3c355b577 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -1,6 +1,5 @@ package eu.siacs.conversations.xmpp.jingle; -import java.net.URLConnection; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; @@ -16,9 +15,9 @@ import android.util.Log; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Downloadable; +import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.DownloadableFile; -import eu.siacs.conversations.entities.DownloadablePlaceholder; +import eu.siacs.conversations.entities.TransferablePlaceholder; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; @@ -29,7 +28,7 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.jingle.stanzas.Reason; import eu.siacs.conversations.xmpp.stanzas.IqPacket; -public class JingleConnection implements Downloadable { +public class JingleConnection implements Transferable { private JingleConnectionManager mJingleConnectionManager; private XmppConnectionService mXmppConnectionService; @@ -40,10 +39,10 @@ public class JingleConnection implements Downloadable { protected static final int JINGLE_STATUS_TRANSMITTING = 5; protected static final int JINGLE_STATUS_FAILED = 99; - private int ibbBlockSize = 4096; + private int ibbBlockSize = 8192; private int mJingleStatus = -1; - private int mStatus = Downloadable.STATUS_UNKNOWN; + private int mStatus = Transferable.STATUS_UNKNOWN; private Message message; private String sessionId; private Account account; @@ -199,8 +198,8 @@ public class JingleConnection implements Downloadable { this.contentCreator = "initiator"; this.contentName = this.mJingleConnectionManager.nextRandomId(); this.message = message; - this.message.setDownloadable(this); - this.mStatus = Downloadable.STATUS_UPLOADING; + this.message.setTransferable(this); + this.mStatus = Transferable.STATUS_UPLOADING; this.account = message.getConversation().getAccount(); this.initiator = this.account.getJid(); this.responder = this.message.getCounterpart(); @@ -256,8 +255,8 @@ public class JingleConnection implements Downloadable { packet.getFrom().toBareJid(), false); this.message = new Message(conversation, "", Message.ENCRYPTION_NONE); this.message.setStatus(Message.STATUS_RECEIVED); - this.mStatus = Downloadable.STATUS_OFFER; - this.message.setDownloadable(this); + this.mStatus = Transferable.STATUS_OFFER; + this.message.setTransferable(this); final Jid from = packet.getFrom(); this.message.setCounterpart(from); this.account = account; @@ -408,7 +407,7 @@ public class JingleConnection implements Downloadable { private void sendAccept() { mJingleStatus = JINGLE_STATUS_ACCEPTED; - this.mStatus = Downloadable.STATUS_DOWNLOADING; + this.mStatus = Transferable.STATUS_DOWNLOADING; mXmppConnectionService.updateConversationUi(); this.mJingleConnectionManager.getPrimaryCandidate(this.account, new OnPrimaryCandidateFound() { @Override @@ -639,7 +638,7 @@ public class JingleConnection implements Downloadable { this.disconnectSocks5Connections(); this.mJingleStatus = JINGLE_STATUS_FINISHED; this.message.setStatus(Message.STATUS_RECEIVED); - this.message.setDownloadable(null); + this.message.setTransferable(null); this.mXmppConnectionService.updateMessage(message); this.mJingleConnectionManager.finishConnection(this); } @@ -716,7 +715,7 @@ public class JingleConnection implements Downloadable { if (this.transport != null && this.transport instanceof JingleInbandTransport) { this.transport.disconnect(); } - this.message.setDownloadable(null); + this.message.setTransferable(null); this.mJingleConnectionManager.finishConnection(this); } @@ -728,7 +727,7 @@ public class JingleConnection implements Downloadable { this.sendCancel(); this.mJingleConnectionManager.finishConnection(this); if (this.responder.equals(account.getJid())) { - this.message.setDownloadable(new DownloadablePlaceholder(Downloadable.STATUS_FAILED)); + this.message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_FAILED)); if (this.file!=null) { file.delete(); } @@ -736,7 +735,7 @@ public class JingleConnection implements Downloadable { } else { this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_FAILED); - this.message.setDownloadable(null); + this.message.setTransferable(null); } } @@ -748,7 +747,7 @@ public class JingleConnection implements Downloadable { } if (this.message != null) { if (this.responder.equals(account.getJid())) { - this.message.setDownloadable(new DownloadablePlaceholder(Downloadable.STATUS_FAILED)); + this.message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_FAILED)); if (this.file!=null) { file.delete(); } @@ -756,7 +755,7 @@ public class JingleConnection implements Downloadable { } else { this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_FAILED); - this.message.setDownloadable(null); + this.message.setTransferable(null); } } this.mJingleConnectionManager.finishConnection(this); @@ -954,24 +953,4 @@ public class JingleConnection implements Downloadable { public int getProgress() { return this.mProgress; } - - @Override - public String getMimeType() { - if (this.message.getType() == Message.TYPE_FILE) { - String mime = null; - String path = this.message.getRelativeFilePath(); - if (path != null && !this.message.getRelativeFilePath().isEmpty()) { - mime = URLConnection.guessContentTypeFromName(this.message.getRelativeFilePath()); - if (mime!=null) { - return mime; - } else { - return ""; - } - } else { - return ""; - } - } else { - return "image/webp"; - } - } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index c19dd04c7..cadf9df39 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -9,14 +9,13 @@ import android.annotation.SuppressLint; import android.util.Log; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; -import eu.siacs.conversations.entities.Downloadable; +import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.Xmlns; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnIqPacketReceived; -import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket; @@ -59,7 +58,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { } public JingleConnection createNewConnection(Message message) { - Downloadable old = message.getDownloadable(); + Transferable old = message.getTransferable(); if (old != null) { old.cancel(); } @@ -87,10 +86,10 @@ public class JingleConnectionManager extends AbstractConnectionManager { return; } if (!this.primaryCandidates.containsKey(account.getJid().toBareJid())) { - final String proxy = account.getXmppConnection().findDiscoItemByFeature(Xmlns.BYTE_STREAMS); + final Jid proxy = account.getXmppConnection().findDiscoItemByFeature(Xmlns.BYTE_STREAMS); if (proxy != null) { IqPacket iq = new IqPacket(IqPacket.TYPE.GET); - iq.setAttribute("to", proxy); + iq.setTo(proxy); iq.query(Xmlns.BYTE_STREAMS); account.getXmppConnection().sendIqPacket(iq,new OnIqPacketReceived() { @@ -105,11 +104,11 @@ public class JingleConnectionManager extends AbstractConnectionManager { candidate.setHost(host); candidate.setPort(Integer.parseInt(port)); candidate.setType(JingleCandidate.TYPE_PROXY); - candidate.setJid(Jid.fromString(proxy)); + candidate.setJid(proxy); candidate.setPriority(655360 + 65535); primaryCandidates.put(account.getJid().toBareJid(),candidate); listener.onPrimaryCandidateFound(true,candidate); - } catch (final NumberFormatException | InvalidJidException e) { + } catch (final NumberFormatException e) { listener.onPrimaryCandidateFound(false,null); return; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java index 8da53c1bb..9a02ee7aa 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java @@ -25,7 +25,6 @@ public class JingleInbandTransport extends JingleTransport { private Account account; private Jid counterpart; private int blockSize; - private int bufferSize; private int seq = 0; private String sessionId; @@ -58,7 +57,6 @@ public class JingleInbandTransport extends JingleTransport { this.account = connection.getAccount(); this.counterpart = connection.getCounterPart(); this.blockSize = blocksize; - this.bufferSize = blocksize / 4; this.sessionId = sid; } @@ -157,7 +155,7 @@ public class JingleInbandTransport extends JingleTransport { } private void sendNextBlock() { - byte[] buffer = new byte[this.bufferSize]; + byte[] buffer = new byte[this.blockSize]; try { int count = fileInputStream.read(buffer); if (count == -1) { diff --git a/src/main/res/drawable/es_slidingpane_shadow.xml b/src/main/res/drawable/es_slidingpane_shadow.xml index 44ffd4ea6..de96e08f4 100644 --- a/src/main/res/drawable/es_slidingpane_shadow.xml +++ b/src/main/res/drawable/es_slidingpane_shadow.xml @@ -2,7 +2,7 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android" > <gradient - android:endColor="@color/divider" + android:endColor="@color/black12" android:startColor="@android:color/transparent" /> <size diff --git a/src/main/res/drawable/grey.xml b/src/main/res/drawable/grey.xml index 96e03d2d9..26986dbe2 100644 --- a/src/main/res/drawable/grey.xml +++ b/src/main/res/drawable/grey.xml @@ -2,6 +2,6 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > - <solid android:color="@color/divider" /> + <solid android:color="@color/black12" /> </shape>
\ No newline at end of file diff --git a/src/main/res/drawable/infocard_border.xml b/src/main/res/drawable/infocard_border.xml index 7c7ded571..e01e1442a 100644 --- a/src/main/res/drawable/infocard_border.xml +++ b/src/main/res/drawable/infocard_border.xml @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > - <solid android:color="@color/primarybackground" /> + <solid android:color="@color/grey50" /> <corners android:radius="2dp" /> <stroke android:width="0.5dp" - android:color="@color/divider" > + android:color="@color/black12" > </stroke> <padding diff --git a/src/main/res/drawable/message_border.xml b/src/main/res/drawable/message_border.xml index b463d788e..990d02886 100644 --- a/src/main/res/drawable/message_border.xml +++ b/src/main/res/drawable/message_border.xml @@ -10,6 +10,6 @@ android:right="1.5dp" android:top="1.5dp" /> - <solid android:color="@color/divider" /> + <solid android:color="@color/black12" /> </shape>
\ No newline at end of file diff --git a/src/main/res/drawable/snackbar.xml b/src/main/res/drawable/snackbar.xml index 951d7aee8..2645b1362 100644 --- a/src/main/res/drawable/snackbar.xml +++ b/src/main/res/drawable/snackbar.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > - <solid android:color="@color/darkbackground" /> + <solid android:color="@color/grey800" /> <corners android:radius="8dip" /> diff --git a/src/main/res/layout-w945dp/fragment_conversations_overview.xml b/src/main/res/layout-w945dp/fragment_conversations_overview.xml index 50039c03a..7ae1788d7 100644 --- a/src/main/res/layout-w945dp/fragment_conversations_overview.xml +++ b/src/main/res/layout-w945dp/fragment_conversations_overview.xml @@ -9,15 +9,15 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" - android:background="@color/primarybackground" + android:background="@color/grey50" android:orientation="vertical" > <de.timroes.android.listview.EnhancedListView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:background="@color/primarybackground" - android:divider="@color/divider" + android:background="@color/grey50" + android:divider="@color/black12" android:dividerHeight="1dp" /> </LinearLayout> diff --git a/src/main/res/layout/account_row.xml b/src/main/res/layout/account_row.xml index 0e73dd643..1d94586ec 100644 --- a/src/main/res/layout/account_row.xml +++ b/src/main/res/layout/account_row.xml @@ -13,7 +13,9 @@ android:layout_height="48dp" android:layout_alignParentLeft="true" android:src="@drawable/ic_profile" - android:contentDescription="@string/account_image_description"> + android:contentDescription="@string/account_image_description" + android:background="@drawable/message_border" + android:padding="1dp"> </ImageView> <LinearLayout @@ -32,7 +34,7 @@ android:layout_height="wrap_content" android:scrollHorizontally="false" android:singleLine="true" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeHeadline" /> <TextView @@ -40,7 +42,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/account_status_unknown" - android:textColor="@color/secondarytext" + android:textColor="@color/black54" android:textSize="?attr/TextSizeBody" android:textStyle="bold" /> </LinearLayout> diff --git a/src/main/res/layout/actionview_search.xml b/src/main/res/layout/actionview_search.xml index cc5fc9d7a..8b657f4a1 100644 --- a/src/main/res/layout/actionview_search.xml +++ b/src/main/res/layout/actionview_search.xml @@ -14,6 +14,8 @@ android:layout_height="wrap_content" android:focusable="true" android:inputType="textEmailAddress|textNoSuggestions" - android:textColor="@color/ondarktext" /> + android:textColor="@color/white" + android:textColorHint="@color/white70" + android:hint="@string/search_for_contacts_or_groups"/> </RelativeLayout>
\ No newline at end of file diff --git a/src/main/res/layout/activity_about.xml b/src/main/res/layout/activity_about.xml index ab0e34eb6..d7d23f0f9 100644 --- a/src/main/res/layout/activity_about.xml +++ b/src/main/res/layout/activity_about.xml @@ -1,7 +1,7 @@ <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:context="eu.siacs.conversations.ui.AboutActivity" - android:background="@color/primarybackground" + android:background="@color/grey50" android:layout_width="fill_parent" android:layout_height="fill_parent"> @@ -15,7 +15,7 @@ android:layout_marginRight="@dimen/activity_horizontal_margin" android:layout_marginTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" android:typeface="monospace"/> </ScrollView> diff --git a/src/main/res/layout/activity_change_password.xml b/src/main/res/layout/activity_change_password.xml index 28d531c22..1a4d00d81 100644 --- a/src/main/res/layout/activity_change_password.xml +++ b/src/main/res/layout/activity_change_password.xml @@ -2,7 +2,7 @@ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/primarybackground"> + android:background="@color/grey50"> <ScrollView android:layout_width="fill_parent" @@ -22,7 +22,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/current_password" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody"/> <EditText @@ -32,15 +32,15 @@ android:layout_marginBottom="8dp" android:hint="@string/password" android:inputType="textPassword" - android:textColor="@color/primarytext" - android:textColorHint="@color/secondarytext" + android:textColor="@color/black87" + android:textColorHint="@color/black54" android:textSize="?attr/TextSizeBody"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/new_password" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody"/> <EditText @@ -50,15 +50,15 @@ android:layout_marginBottom="8dp" android:hint="@string/password" android:inputType="textPassword" - android:textColor="@color/primarytext" - android:textColorHint="@color/secondarytext" + android:textColor="@color/black87" + android:textColorHint="@color/black54" android:textSize="?attr/TextSizeBody"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/account_settings_confirm_password" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody"/> <EditText @@ -67,8 +67,8 @@ android:layout_height="wrap_content" android:hint="@string/password" android:inputType="textPassword" - android:textColor="@color/primarytext" - android:textColorHint="@color/secondarytext" + android:textColor="@color/black87" + android:textColorHint="@color/black54" android:textSize="?attr/TextSizeBody"/> </LinearLayout> </ScrollView> @@ -94,7 +94,7 @@ android:layout_height="fill_parent" android:layout_marginBottom="7dp" android:layout_marginTop="7dp" - android:background="@color/divider"/> + android:background="@color/black12"/> <Button android:id="@+id/right_button" diff --git a/src/main/res/layout/activity_contact_details.xml b/src/main/res/layout/activity_contact_details.xml index 1254a3ab7..e1a967c07 100644 --- a/src/main/res/layout/activity_contact_details.xml +++ b/src/main/res/layout/activity_contact_details.xml @@ -2,7 +2,7 @@ <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:background="@color/secondarybackground" > + android:background="@color/grey200" > <LinearLayout android:layout_width="fill_parent" @@ -21,32 +21,41 @@ <QuickContactBadge android:id="@+id/details_contact_badge" - android:layout_width="72dp" - android:layout_height="72dp" + android:layout_width="300dp" + android:layout_height="300dp" + android:scaleType="centerCrop" android:layout_alignParentTop="true" - android:scaleType="centerCrop" /> + android:layout_centerHorizontal="true" + android:background="@drawable/message_border" + android:padding="1dp" /> <LinearLayout android:id="@+id/details_jidbox" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginLeft="16dp" - android:layout_toRightOf="@+id/details_contact_badge" - android:orientation="vertical" > + android:orientation="vertical" + android:layout_below="@+id/details_contact_badge" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" + android:layout_marginTop="16dp" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true"> <TextView android:id="@+id/details_contactjid" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/account_settings_example_jabber_id" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeHeadline" - android:textStyle="bold" /> + android:textStyle="bold" + android:layout_gravity="center_horizontal" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:orientation="vertical" > + android:orientation="vertical" + android:layout_gravity="center_horizontal"> <LinearLayout android:id="@+id/tags" @@ -54,15 +63,17 @@ android:layout_height="wrap_content" android:layout_marginTop="4dp" android:layout_marginBottom="4dp" - android:orientation="horizontal"> + android:orientation="horizontal" + android:layout_gravity="center_horizontal"> </LinearLayout> <TextView android:id="@+id/details_lastseen" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/secondarytext" - android:textSize="?attr/TextSizeBody" /> + android:textColor="@color/black54" + android:textSize="?attr/TextSizeBody" + android:layout_gravity="center_horizontal" /> </LinearLayout> <Button @@ -70,7 +81,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:text="@string/add_contact"/> + android:text="@string/add_contact" + android:layout_gravity="center_horizontal" /> <CheckBox android:id="@+id/details_send_presence" @@ -78,7 +90,7 @@ android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/send_presence_updates" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <CheckBox @@ -86,7 +98,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/receive_presence_updates" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> </LinearLayout> @@ -98,7 +110,7 @@ android:layout_below="@+id/details_jidbox" android:layout_marginTop="32dp" android:text="@string/using_account" - android:textColor="@color/secondarytext" + android:textColor="@color/black54" android:textSize="?attr/TextSizeInfo" /> </RelativeLayout> diff --git a/src/main/res/layout/activity_edit_account.xml b/src/main/res/layout/activity_edit_account.xml index 7d84a4af3..05954f043 100644 --- a/src/main/res/layout/activity_edit_account.xml +++ b/src/main/res/layout/activity_edit_account.xml @@ -3,7 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/secondarybackground" > + android:background="@color/grey200" > <ScrollView android:layout_width="fill_parent" @@ -28,21 +28,26 @@ android:orientation="vertical" android:padding="@dimen/infocard_padding"> <ImageView android:id="@+id/avater" - android:layout_width="72dp" - android:layout_height="72dp" + android:layout_width="300dp" + android:layout_height="300dp" + android:contentDescription="@string/account_image_description" + android:background="@drawable/message_border" + android:padding="1dp" android:layout_alignParentTop="true" - android:layout_marginRight="16dp" - android:contentDescription="@string/account_image_description"/> + android:layout_centerHorizontal="true" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" - android:layout_toRightOf="@+id/avater"> + android:layout_below="@+id/avater" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_marginTop="16dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/account_settings_jabber_id" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <AutoCompleteTextView @@ -51,8 +56,8 @@ android:layout_height="wrap_content" android:hint="@string/account_settings_example_jabber_id" android:inputType="textEmailAddress" - android:textColor="@color/primarytext" - android:textColorHint="@color/secondarytext" + android:textColor="@color/black87" + android:textColorHint="@color/black54" android:textSize="?attr/TextSizeBody" /> <TextView @@ -60,7 +65,7 @@ android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/account_settings_password" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <EditText @@ -69,8 +74,8 @@ android:layout_height="wrap_content" android:hint="@string/password" android:inputType="textPassword" - android:textColor="@color/primarytext" - android:textColorHint="@color/secondarytext" + android:textColor="@color/black87" + android:textColorHint="@color/black54" android:textSize="?attr/TextSizeBody" /> <CheckBox @@ -79,7 +84,7 @@ android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/register_account" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <TextView @@ -87,7 +92,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/account_settings_confirm_password" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" android:visibility="gone" /> @@ -99,8 +104,8 @@ android:hint="@string/confirm_password" android:inputType="textPassword" android:visibility="gone" - android:textColor="@color/primarytext" - android:textColorHint="@color/secondarytext" + android:textColor="@color/black87" + android:textColorHint="@color/black54" android:textSize="?attr/TextSizeBody" /> </LinearLayout> </RelativeLayout> @@ -132,7 +137,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/server_info_session_established" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <TextView @@ -140,7 +145,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" tools:ignore="RtlHardcoded"/> </TableRow> @@ -161,7 +166,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/server_info_pep" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <TextView @@ -169,7 +174,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" tools:ignore="RtlHardcoded"/> </TableRow> @@ -182,7 +187,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/server_info_blocking" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <TextView @@ -190,7 +195,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" tools:ignore="RtlHardcoded"/> </TableRow> @@ -203,7 +208,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/server_info_stream_management" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <TextView @@ -211,7 +216,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" tools:ignore="RtlHardcoded"/> </TableRow> @@ -224,7 +229,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/server_info_roster_version" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <TextView @@ -232,7 +237,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" tools:ignore="RtlHardcoded"/> </TableRow> @@ -245,7 +250,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/server_info_carbon_messages" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <TextView @@ -253,7 +258,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" tools:ignore="RtlHardcoded"/> </TableRow> @@ -266,7 +271,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/server_info_mam" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <TextView @@ -274,7 +279,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" tools:ignore="RtlHardcoded"/> </TableRow> @@ -287,7 +292,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/server_info_csi" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <TextView @@ -295,7 +300,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" tools:ignore="RtlHardcoded"/> </TableRow> @@ -318,14 +323,14 @@ android:id="@+id/otr_fingerprint" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" android:typeface="monospace" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/secondarytext" + android:textColor="@color/black54" android:textSize="?attr/TextSizeInfo" android:text="@string/otr_fingerprint"/> </LinearLayout> @@ -363,14 +368,14 @@ android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/cancel" - android:textColor="@color/primarytext" /> + android:textColor="@color/black87" /> <View android:layout_width="1dp" android:layout_height="fill_parent" android:layout_marginBottom="7dp" android:layout_marginTop="7dp" - android:background="@color/divider" /> + android:background="@color/black12" /> <Button android:id="@+id/save_button" @@ -380,7 +385,7 @@ android:layout_weight="1" android:enabled="false" android:text="@string/save" - android:textColor="@color/secondarytext" /> + android:textColor="@color/black54" /> </LinearLayout> </RelativeLayout> diff --git a/src/main/res/layout/activity_muc_details.xml b/src/main/res/layout/activity_muc_details.xml index 116026512..671215eaa 100644 --- a/src/main/res/layout/activity_muc_details.xml +++ b/src/main/res/layout/activity_muc_details.xml @@ -2,7 +2,7 @@ <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:background="@color/secondarybackground"> + android:background="@color/grey200"> <LinearLayout android:layout_width="fill_parent" @@ -26,7 +26,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="16dp" android:text="@string/account_settings_example_jabber_id" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeHeadline" android:textStyle="bold"/> @@ -37,10 +37,13 @@ <ImageView android:id="@+id/your_photo" - android:layout_width="48dp" - android:layout_height="48dp" + android:layout_width="72dp" + android:layout_height="72dp" android:layout_alignParentLeft="true" - android:src="@drawable/ic_profile"> + android:src="@drawable/ic_profile" + android:background="@drawable/message_border" + android:padding="1dp" + android:layout_alignParentEnd="false"> </ImageView> <LinearLayout @@ -56,7 +59,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeHeadline"/> <TextView @@ -64,7 +67,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody"/> </LinearLayout> @@ -88,7 +91,7 @@ android:layout_height="wrap_content" android:text="@string/private_conference" android:layout_centerVertical="true" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" android:layout_alignParentLeft="true" android:layout_toLeftOf="@+id/change_conference_button" @@ -113,7 +116,7 @@ android:layout_gravity="right" android:layout_marginTop="32dp" android:text="@string/using_account" - android:textColor="@color/secondarytext" + android:textColor="@color/black54" android:textSize="?attr/TextSizeInfo"/> </LinearLayout> diff --git a/src/main/res/layout/activity_publish_profile_picture.xml b/src/main/res/layout/activity_publish_profile_picture.xml index fac499bce..6bb28a1ec 100644 --- a/src/main/res/layout/activity_publish_profile_picture.xml +++ b/src/main/res/layout/activity_publish_profile_picture.xml @@ -2,7 +2,7 @@ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/primarybackground" > + android:background="@color/grey50" > <LinearLayout android:id="@+id/account_image_wrapper" @@ -16,8 +16,8 @@ <ImageView android:id="@+id/account_image" - android:layout_width="194dp" - android:layout_height="194dp" /> + android:layout_width="300dp" + android:layout_height="300dp" /> </LinearLayout> <TextView @@ -27,7 +27,7 @@ android:layout_below="@id/account_image_wrapper" android:layout_centerHorizontal="true" android:text="@string/touch_to_choose_picture" - android:textColor="@color/secondarytext" /> + android:textColor="@color/black54" /> <TextView android:id="@+id/secondary_hint" @@ -36,7 +36,7 @@ android:layout_below="@id/hint" android:layout_centerHorizontal="true" android:text="@string/or_long_press_for_default" - android:textColor="@color/secondarytext" /> + android:textColor="@color/black54" /> <LinearLayout android:id="@+id/button_bar" @@ -53,14 +53,14 @@ android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/cancel" - android:textColor="@color/primarytext" /> + android:textColor="@color/black87" /> <View android:layout_width="1dp" android:layout_height="fill_parent" android:layout_marginBottom="7dp" android:layout_marginTop="7dp" - android:background="@color/divider" /> + android:background="@color/black12" /> <Button android:id="@+id/publish_button" @@ -70,7 +70,7 @@ android:layout_weight="1" android:enabled="false" android:text="@string/publish" - android:textColor="@color/secondarytext" /> + android:textColor="@color/black54" /> </LinearLayout> <LinearLayout @@ -89,7 +89,7 @@ android:id="@+id/account" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeHeadline" /> <TextView @@ -99,8 +99,8 @@ android:layout_marginTop="8dp" android:minLines="3" android:text="@string/publish_avatar_explanation" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> </LinearLayout> -</RelativeLayout>
\ No newline at end of file +</RelativeLayout> diff --git a/src/main/res/layout/activity_start_conversation.xml b/src/main/res/layout/activity_start_conversation.xml index f9c985292..d55ec196f 100644 --- a/src/main/res/layout/activity_start_conversation.xml +++ b/src/main/res/layout/activity_start_conversation.xml @@ -3,6 +3,6 @@ android:id="@+id/start_conversation_view_pager" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/primarybackground" > + android:background="@color/grey50" > </android.support.v4.view.ViewPager>
\ No newline at end of file diff --git a/src/main/res/layout/activity_verify_otr.xml b/src/main/res/layout/activity_verify_otr.xml index 54f9a542b..ab21c693d 100644 --- a/src/main/res/layout/activity_verify_otr.xml +++ b/src/main/res/layout/activity_verify_otr.xml @@ -2,7 +2,7 @@ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/primarybackground"> + android:background="@color/grey50"> <ScrollView android:layout_width="fill_parent" @@ -34,7 +34,7 @@ android:id="@+id/your_fingerprint" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" android:typeface="monospace"/> @@ -42,7 +42,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/your_fingerprint" - android:textColor="@color/secondarytext" + android:textColor="@color/black54" android:textSize="?attr/TextSizeInfo"/> <TextView @@ -50,7 +50,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" android:typeface="monospace"/> @@ -59,7 +59,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="20dp" android:text="@string/remote_fingerprint" - android:textColor="@color/secondarytext" + android:textColor="@color/black54" android:textSize="?attr/TextSizeInfo"/> </LinearLayout> @@ -77,7 +77,7 @@ android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="@string/verified" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeHeadline" android:textStyle="bold" android:visibility="gone"/> @@ -87,7 +87,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" android:textStyle="bold" android:visibility="gone"/> @@ -99,8 +99,8 @@ android:layout_marginBottom="8dp" android:hint="@string/shared_secret_hint" android:inputType="textAutoComplete" - android:textColor="@color/primarytext" - android:textColorHint="@color/secondarytext" + android:textColor="@color/black87" + android:textColorHint="@color/black54" android:textSize="?attr/TextSizeBody"/> <EditText @@ -110,8 +110,8 @@ android:layout_marginTop="8dp" android:hint="@string/shared_secret_secret" android:inputType="textPassword" - android:textColor="@color/primarytext" - android:textColorHint="@color/secondarytext" + android:textColor="@color/black87" + android:textColorHint="@color/black54" android:textSize="?attr/TextSizeBody"/> </LinearLayout> </LinearLayout> @@ -137,7 +137,7 @@ android:layout_height="fill_parent" android:layout_marginBottom="7dp" android:layout_marginTop="7dp" - android:background="@color/divider"/> + android:background="@color/black12"/> <Button android:id="@+id/right_button" diff --git a/src/main/res/layout/contact.xml b/src/main/res/layout/contact.xml index 69545c250..d42782dd8 100644 --- a/src/main/res/layout/contact.xml +++ b/src/main/res/layout/contact.xml @@ -7,11 +7,13 @@ <ImageView android:id="@+id/contact_photo" - android:layout_width="48dp" - android:layout_height="48dp" + android:layout_width="56dp" + android:layout_height="56dp" android:layout_alignParentLeft="true" android:scaleType="centerCrop" - android:src="@drawable/ic_profile" > + android:src="@drawable/ic_profile" + android:background="@drawable/message_border" + android:padding="1dp"> </ImageView> <LinearLayout @@ -27,7 +29,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeHeadline" /> <TextView @@ -35,7 +37,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <LinearLayout android:id="@+id/tags" @@ -48,7 +50,7 @@ android:id="@+id/key" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeHeadline" android:typeface="monospace" android:visibility="gone" /> diff --git a/src/main/res/layout/contact_key.xml b/src/main/res/layout/contact_key.xml index b7817b383..933b72b45 100644 --- a/src/main/res/layout/contact_key.xml +++ b/src/main/res/layout/contact_key.xml @@ -15,7 +15,7 @@ android:id="@+id/key" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" android:typeface="monospace" /> @@ -23,7 +23,7 @@ android:id="@+id/key_type" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/secondarytext" + android:textColor="@color/black54" android:textSize="?attr/TextSizeInfo"/> </LinearLayout> diff --git a/src/main/res/layout/conversation_list_row.xml b/src/main/res/layout/conversation_list_row.xml index 69abb2256..5f1c5047d 100644 --- a/src/main/res/layout/conversation_list_row.xml +++ b/src/main/res/layout/conversation_list_row.xml @@ -6,13 +6,13 @@ <View android:layout_width="fill_parent" android:layout_height="fill_parent" - android:background="@color/primary"/> + android:background="@color/green500"/> <FrameLayout android:id="@+id/swipeable_item" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:background="@color/primarybackground"> + android:background="@color/grey50"> <RelativeLayout android:layout_width="fill_parent" @@ -26,7 +26,9 @@ android:layout_width="56dp" android:layout_height="56dp" android:layout_alignParentLeft="true" - android:scaleType="centerCrop" /> + android:scaleType="centerCrop" + android:background="@drawable/message_border" + android:padding="1dp" /> <RelativeLayout android:layout_width="fill_parent" @@ -42,7 +44,7 @@ android:layout_alignLeft="@+id/conversation_lastwrapper" android:layout_toLeftOf="@+id/conversation_lastupdate" android:singleLine="true" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeHeadline" android:typeface="sans" /> @@ -60,14 +62,14 @@ android:layout_height="wrap_content" android:scrollHorizontally="false" android:singleLine="true" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <ImageView android:id="@+id/conversation_lastimage" android:layout_width="fill_parent" android:layout_height="36dp" - android:background="@color/primarytext" + android:background="@color/black87" android:scaleType="centerCrop" /> </LinearLayout> @@ -78,7 +80,7 @@ android:layout_alignBaseline="@+id/conversation_name" android:layout_alignParentRight="true" android:gravity="right" - android:textColor="@color/secondarytext" + android:textColor="@color/black54" android:textSize="?attr/TextSizeInfo" /> </RelativeLayout> </RelativeLayout> diff --git a/src/main/res/layout/create_contact_dialog.xml b/src/main/res/layout/create_contact_dialog.xml index 1ab4b6862..6333e340a 100644 --- a/src/main/res/layout/create_contact_dialog.xml +++ b/src/main/res/layout/create_contact_dialog.xml @@ -10,7 +10,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/your_account" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <Spinner @@ -24,7 +24,7 @@ android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/account_settings_jabber_id" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <AutoCompleteTextView @@ -33,7 +33,7 @@ android:layout_height="wrap_content" android:hint="@string/account_settings_example_jabber_id" android:inputType="textEmailAddress" - android:textColor="@color/primarytext" - android:textColorHint="@color/secondarytext" /> + android:textColor="@color/black87" + android:textColorHint="@color/black54" /> </LinearLayout>
\ No newline at end of file diff --git a/src/main/res/layout/fragment_conversation.xml b/src/main/res/layout/fragment_conversation.xml index 5aa7dffab..d0ac6ba7c 100644 --- a/src/main/res/layout/fragment_conversation.xml +++ b/src/main/res/layout/fragment_conversation.xml @@ -3,7 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/secondarybackground" > + android:background="@color/grey200" > <ListView android:id="@+id/messages_view" @@ -12,7 +12,7 @@ android:layout_above="@+id/snackbar" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" - android:background="@color/secondarybackground" + android:background="@color/grey200" android:divider="@null" android:dividerHeight="0dp" android:listSelector="@android:color/transparent" @@ -27,7 +27,7 @@ android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" - android:background="@color/primarybackground" > + android:background="@color/grey50" > <eu.siacs.conversations.ui.EditMessage android:id="@+id/textinput" @@ -35,7 +35,7 @@ android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_toLeftOf="@+id/textSendButton" - android:background="@color/primarybackground" + android:background="@color/grey50" android:ems="10" android:imeOptions="flagNoExtractUi|actionSend" android:inputType="textShortMessage|textMultiLine|textCapSentences" @@ -45,7 +45,7 @@ android:paddingLeft="8dp" android:paddingRight="8dp" android:paddingTop="12dp" - android:textColor="@color/primarytext" > + android:textColor="@color/black87" > <requestFocus /> </eu.siacs.conversations.ui.EditMessage> @@ -80,7 +80,7 @@ android:layout_centerVertical="true" android:layout_toLeftOf="@+id/snackbar_action" android:paddingLeft="24dp" - android:textColor="@color/ondarktext" + android:textColor="@color/white" android:textSize="?attr/TextSizeBody" /> <TextView @@ -94,7 +94,7 @@ android:paddingRight="24dp" android:paddingTop="16dp" android:textAllCaps="true" - android:textColor="@color/ondarktext" + android:textColor="@color/white" android:textSize="?attr/TextSizeBody" android:textStyle="bold" /> </RelativeLayout> diff --git a/src/main/res/layout/fragment_conversations_overview.xml b/src/main/res/layout/fragment_conversations_overview.xml index 24c653ae6..2223219a4 100644 --- a/src/main/res/layout/fragment_conversations_overview.xml +++ b/src/main/res/layout/fragment_conversations_overview.xml @@ -7,15 +7,15 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="@dimen/conversations_overview_width" android:layout_height="match_parent" - android:background="@color/primarybackground" + android:background="@color/grey50" android:orientation="vertical" > <de.timroes.android.listview.EnhancedListView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:background="@color/primarybackground" - android:divider="@color/divider" + android:background="@color/grey50" + android:divider="@color/black12" android:dividerHeight="1dp" /> </LinearLayout> diff --git a/src/main/res/layout/join_conference_dialog.xml b/src/main/res/layout/join_conference_dialog.xml index 95c9d24cb..7609dd0d5 100644 --- a/src/main/res/layout/join_conference_dialog.xml +++ b/src/main/res/layout/join_conference_dialog.xml @@ -10,7 +10,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/your_account" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <Spinner @@ -24,7 +24,7 @@ android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/conference_address" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <AutoCompleteTextView @@ -33,8 +33,8 @@ android:layout_height="wrap_content" android:hint="@string/conference_address_example" android:inputType="textEmailAddress" - android:textColor="@color/primarytext" - android:textColorHint="@color/secondarytext" /> + android:textColor="@color/black87" + android:textColorHint="@color/black54" /> <CheckBox android:id="@+id/bookmark" diff --git a/src/main/res/layout/list_item_tag.xml b/src/main/res/layout/list_item_tag.xml index 7a77f710f..1a6a5576f 100644 --- a/src/main/res/layout/list_item_tag.xml +++ b/src/main/res/layout/list_item_tag.xml @@ -7,7 +7,7 @@ android:paddingLeft="4dp" android:paddingRight="4dp" android:textSize="?attr/TextSizeInfo" - android:textColor="@color/ondarktext" + android:textColor="@color/white" android:textAllCaps="true" android:layout_marginRight="8dp" />
\ No newline at end of file diff --git a/src/main/res/layout/manage_accounts.xml b/src/main/res/layout/manage_accounts.xml index 11ce35b2f..90ca7de04 100644 --- a/src/main/res/layout/manage_accounts.xml +++ b/src/main/res/layout/manage_accounts.xml @@ -3,13 +3,13 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:background="@color/primarybackground" > + android:background="@color/grey50" > <ListView android:id="@+id/account_list" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:divider="@color/divider" + android:divider="@color/black12" android:dividerHeight="1dp" > </ListView> diff --git a/src/main/res/layout/message_received.xml b/src/main/res/layout/message_received.xml index 39bb842ac..1de744d13 100644 --- a/src/main/res/layout/message_received.xml +++ b/src/main/res/layout/message_received.xml @@ -21,7 +21,7 @@ <LinearLayout android:layout_width="wrap_content" android:layout_height="fill_parent" - android:background="@color/primarybackground" + android:background="@color/grey50" android:gravity="center_vertical" android:orientation="vertical" android:paddingBottom="4dp" @@ -34,7 +34,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:adjustViewBounds="true" - android:background="@color/primarytext" + android:background="@color/black87" android:paddingBottom="2dp" android:scaleType="centerCrop" /> @@ -43,7 +43,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:autoLink="web" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <Button @@ -51,7 +51,6 @@ style="?android:attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/download_image" android:visibility="gone" /> <LinearLayout @@ -77,7 +76,7 @@ android:layout_gravity="center_vertical" android:gravity="center_vertical" android:text="@string/sending" - android:textColor="@color/secondarytext" + android:textColor="@color/black54" android:textSize="?attr/TextSizeInfo" /> </LinearLayout> </LinearLayout> @@ -90,8 +89,12 @@ android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginRight="-1.5dp" - android:padding="0dp" android:scaleType="fitXY" - android:src="@drawable/ic_profile" /> + android:src="@drawable/ic_profile" + android:background="@drawable/message_border" + android:paddingLeft="1dp" + android:paddingTop="1dp" + android:paddingBottom="1dp" + android:paddingRight="0dp" /> </RelativeLayout>
\ No newline at end of file diff --git a/src/main/res/layout/message_sent.xml b/src/main/res/layout/message_sent.xml index 3e8546432..7048de952 100644 --- a/src/main/res/layout/message_sent.xml +++ b/src/main/res/layout/message_sent.xml @@ -21,7 +21,7 @@ <LinearLayout android:layout_width="wrap_content" android:layout_height="fill_parent" - android:background="@color/primarybackground" + android:background="@color/grey50" android:gravity="center_vertical" android:orientation="vertical" android:paddingBottom="4dp" @@ -34,7 +34,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:adjustViewBounds="true" - android:background="@color/primarytext" + android:background="@color/black87" android:paddingBottom="2dp" android:scaleType="centerCrop" /> @@ -43,7 +43,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:autoLink="web" - android:textColor="@color/primarytext" + android:textColor="@color/black87" android:textSize="?attr/TextSizeBody" /> <Button @@ -51,7 +51,6 @@ style="?android:attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/download_image" android:visibility="gone" /> <LinearLayout @@ -68,7 +67,7 @@ android:layout_gravity="center_vertical" android:gravity="center_vertical" android:text="@string/sending" - android:textColor="@color/secondarytext" + android:textColor="@color/black54" android:textSize="?attr/TextSizeInfo" /> <ImageView @@ -101,8 +100,12 @@ android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginLeft="-1.5dp" - android:padding="0dp" android:scaleType="fitXY" - android:src="@drawable/ic_profile" /> + android:src="@drawable/ic_profile" + android:background="@drawable/message_border" + android:paddingTop="1dp" + android:paddingRight="1dp" + android:paddingBottom="1dp" + android:paddingLeft="0dp" /> </RelativeLayout>
\ No newline at end of file diff --git a/src/main/res/layout/message_status.xml b/src/main/res/layout/message_status.xml index 20544cd5e..393b672fb 100644 --- a/src/main/res/layout/message_status.xml +++ b/src/main/res/layout/message_status.xml @@ -15,9 +15,10 @@ android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginRight="-1.5dp" - android:padding="0dp" + android:padding="1dp" android:scaleType="fitXY" - android:src="@drawable/ic_profile" /> + android:src="@drawable/ic_profile" + android:background="@drawable/message_border" /> <TextView android:id="@+id/status_message" @@ -28,7 +29,7 @@ android:layout_toEndOf="@+id/message_photo" android:layout_toRightOf="@+id/message_photo" android:text="@string/contact_has_read_up_to_this_point" - android:textColor="@color/secondarytext" + android:textColor="@color/black54" android:textSize="?attr/TextSizeInfo" android:textStyle="italic"/> diff --git a/src/main/res/layout/quickedit.xml b/src/main/res/layout/quickedit.xml index 20a2868ac..ff6b0413a 100644 --- a/src/main/res/layout/quickedit.xml +++ b/src/main/res/layout/quickedit.xml @@ -11,7 +11,7 @@ android:layout_height="wrap_content" android:ems="10" android:inputType="textPersonName" - android:textColor="@color/primarytext" > + android:textColor="@color/black87" > <requestFocus /> </EditText> diff --git a/src/main/res/menu/conversations.xml b/src/main/res/menu/conversations.xml index 4c724d27d..fe2ff834d 100644 --- a/src/main/res/menu/conversations.xml +++ b/src/main/res/menu/conversations.xml @@ -10,7 +10,7 @@ android:id="@+id/action_security" android:icon="?attr/icon_not_secure" android:orderInCategory="20" - android:showAsAction="always" + android:showAsAction="never" android:title="@string/action_secure"/> <item android:id="@+id/action_attach_file" @@ -20,14 +20,15 @@ android:title="@string/attach_file"/> <item android:id="@+id/action_contact_details" + android:icon="?attr/icon_group" android:orderInCategory="40" - android:showAsAction="never" + android:showAsAction="always" android:title="@string/action_contact_details"/> <item android:id="@+id/action_muc_details" android:icon="?attr/icon_group" android:orderInCategory="40" - android:showAsAction="ifRoom" + android:showAsAction="always" android:title="@string/action_muc_details"/> <item android:id="@+id/action_invite" diff --git a/src/main/res/menu/message_context.xml b/src/main/res/menu/message_context.xml index 21659266f..4e1316d39 100644 --- a/src/main/res/menu/message_context.xml +++ b/src/main/res/menu/message_context.xml @@ -3,21 +3,27 @@ <item android:id="@+id/copy_text" - android:title="@string/copy_text"/> + android:title="@string/copy_text" + android:visible="false"/> <item android:id="@+id/share_with" - android:title="@string/share_with"/> + android:title="@string/share_with" + android:visible="false"/> <item android:id="@+id/copy_url" - android:title="@string/copy_original_url"/> + android:title="@string/copy_original_url" + android:visible="false"/> <item android:id="@+id/send_again" - android:title="@string/send_again"/> + android:title="@string/send_again" + android:visible="false"/> <item - android:id="@+id/download_image" - android:title="@string/download_image"/> + android:id="@+id/download_file" + android:title="@string/download_x_file" + android:visible="false"/> <item android:id="@+id/cancel_transmission" - android:title="@string/cancel_transmission" /> + android:title="@string/cancel_transmission" + android:visible="false"/> </menu>
\ No newline at end of file diff --git a/src/main/res/values-ar-rEG/strings.xml b/src/main/res/values-ar-rEG/strings.xml index 35eff49fd..c5a43674a 100644 --- a/src/main/res/values-ar-rEG/strings.xml +++ b/src/main/res/values-ar-rEG/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">OTRارساله رساله مشفره عبر</string> <string name="send_pgp_message">OpenPGPارساله رساله مشفره عبر</string> <string name="your_nick_has_been_changed">تم تغيير لقبك بنجاح</string> - <string name="download_image">تنزيل الصورة</string> <string name="send_unencrypted">إرسال بدون تشفير</string> <string name="decryption_failed">فشل فك التشفير. ربما لم يكن لديك المفتاح الخاص الصحيح.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -212,7 +211,6 @@ <string name="conference_members_only">الغرفة للأعضاء فقط</string> <string name="conference_kicked">تم طردك من الغرفة</string> <string name="not_connected_try_again">انقطع الإتصال .. حاول مرة أخرى</string> - <string name="check_image_filesize">فحص حجم الصورة</string> <string name="message_options">خيارات الرساله</string> <string name="copy_text">نسخ النص</string> <string name="message_text">نص الرسالة</string> diff --git a/src/main/res/values-bg/strings.xml b/src/main/res/values-bg/strings.xml index 52bb00549..cff228f7a 100644 --- a/src/main/res/values-bg/strings.xml +++ b/src/main/res/values-bg/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Изпращане на съобщение, шифровано чрез OTP</string> <string name="send_pgp_message">Изпращане на съобщение, шифровано чрез OpenPGP</string> <string name="your_nick_has_been_changed">Псевдонимът Ви беше променен</string> - <string name="download_image">Изтегляне на изображението</string> <string name="send_unencrypted">Изпращане нешифровано</string> <string name="decryption_failed">Неуспешно дешифроване. Възможно е да нямате правилния частен ключ.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,14 @@ <string name="conference_members_only">Тази беседа е само за членове</string> <string name="conference_kicked">Бяхте изритан от тази конференция</string> <string name="using_account">използвайки профила %s</string> - <string name="checking_image">Проверяване на изображението на HTTP сървъра</string> - <string name="image_file_deleted">Изображението е изтрито</string> + <string name="checking_x">Проверяване на %s на HTTP сървъра</string> <string name="not_connected_try_again">Не сте свързани. Опитайте отново по-късно</string> - <string name="check_image_filesize">Проверка на размера на файла с изображението</string> + <string name="check_x_filesize">Проверете размера на %s</string> <string name="message_options">Настройки за съобщенята</string> <string name="copy_text">Копиране на текста</string> <string name="copy_original_url">Копиране на оригиналния адрес</string> <string name="send_again">Повторно изпращане</string> - <string name="image_url">Адрес на изображението</string> + <string name="file_url">Адрес на файла</string> <string name="message_text">Текст на съобщението</string> <string name="url_copied_to_clipboard">Адресът е копиран</string> <string name="message_copied_to_clipboard">Съобщението е копирано</string> @@ -451,4 +449,6 @@ <string name="none">Нищо</string> <string name="recently_used">Използвани наскоро</string> <string name="choose_quick_action">Изберете бързо действие</string> + <string name="file_not_found_on_remote_host">Файлът не е открит на отдалечения сървър</string> + <string name="search_for_contacts_or_groups">Търсене на контакти или групи</string> </resources> diff --git a/src/main/res/values-ca/strings.xml b/src/main/res/values-ca/strings.xml index 9583932bb..b10fb617f 100644 --- a/src/main/res/values-ca/strings.xml +++ b/src/main/res/values-ca/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Enviar missatge xifrat amb OTR</string> <string name="send_pgp_message">Enviar missatge xifrat amb OpenPGP</string> <string name="your_nick_has_been_changed">El teu sobrenom s\'ha modificat</string> - <string name="download_image">Descarregar imatge</string> <string name="send_unencrypted">Enviar sense xifrar</string> <string name="decryption_failed">Ha fallat el desxiframent. Potser no tinguis la clau privada apropiada.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,11 @@ <string name="conference_members_only">La sala es nomès per membres</string> <string name="conference_kicked">Estàs expulsat d\'aquesta sala</string> <string name="using_account">Utlitzant el compte %s</string> - <string name="checking_image">Comprovant l\'imatge en el client HTTP</string> - <string name="image_file_deleted">L\'arxiu de l\'imatge ha sigut eliminada</string> <string name="not_connected_try_again">No estàs connectat. Intenta-ho més tard</string> - <string name="check_image_filesize">Comprobant el tamany de l\'imatge</string> <string name="message_options">Opcions del missatge</string> <string name="copy_text">Copiar el text</string> <string name="copy_original_url">Copiar la URL original</string> <string name="send_again">Envia una altra vegada</string> - <string name="image_url">Imatge URL</string> <string name="message_text">Missatge de text</string> <string name="url_copied_to_clipboard">URL copiada al portapapers</string> <string name="message_copied_to_clipboard">Missatge copiat al portapapers</string> diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml index c199ec768..190fd575c 100644 --- a/src/main/res/values-cs/strings.xml +++ b/src/main/res/values-cs/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Poslat OTR šifrovanou zprávu</string> <string name="send_pgp_message">Poslat OpenPGP šifrovanou zprávu</string> <string name="your_nick_has_been_changed">Přezdívka byla změněna</string> - <string name="download_image">Stáhnout obrázek</string> <string name="send_unencrypted">Poslat nešifrované</string> <string name="decryption_failed">Zašifrování se nezdařilo. Možná nemáte správný privátní klíč.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,14 @@ <string name="conference_members_only">Tato konference je pouze pro členy</string> <string name="conference_kicked">Vykopli tě z této konference</string> <string name="using_account">za použití účtu %s</string> - <string name="checking_image">Ověřuji obrázek na HTTP hostiteli</string> - <string name="image_file_deleted">Obrázek byl smazán</string> + <string name="checking_x">Ověřuji %s na HTTP hostiteli</string> <string name="not_connected_try_again">Bez připojení. Zkus znovu později</string> - <string name="check_image_filesize">Ověřit velikost obrázku</string> + <string name="check_x_filesize">Ověřit %s velikost</string> <string name="message_options">Možnosti zpráv</string> <string name="copy_text">Zkopírovat text</string> <string name="copy_original_url">Kopírovat originální URL</string> <string name="send_again">Poslat znovu</string> - <string name="image_url">URL obrázku</string> + <string name="file_url">URL souboru</string> <string name="message_text">Text zprávy</string> <string name="url_copied_to_clipboard">URL zkopírováno do schránky</string> <string name="message_copied_to_clipboard">Zpráva zkopírována do schránky</string> @@ -453,4 +451,6 @@ <string name="none">Žádná</string> <string name="recently_used">Naposledy použitá</string> <string name="choose_quick_action">Vybrat rychlou akci</string> + <string name="file_not_found_on_remote_host">Soubor nenalezen na vzdáleném serveru</string> + <string name="search_for_contacts_or_groups">Hledat kontakty či skupiny</string> </resources> diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index 000c253b2..0bd4afaaa 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">OTR-verschlüsselt schreiben…</string> <string name="send_pgp_message">OpenPGP-verschlüsselt schreiben…</string> <string name="your_nick_has_been_changed">Dein Nickname wurde geändert</string> - <string name="download_image">Bild herunterladen</string> <string name="send_unencrypted">Normal verschicken</string> <string name="decryption_failed">Entschlüsselung fehlgeschlagen. Vielleicht hast du nicht den richtigen privaten Schlüssel.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,14 @@ <string name="conference_members_only">Die Konferenz ist nur für Mitglieder</string> <string name="conference_kicked">Du wurdest aus der Konferenz geworfen</string> <string name="using_account">Verwende Konto %s</string> - <string name="checking_image">Prüfe Bild auf HTTP-Host</string> - <string name="image_file_deleted">Bild wurde gelöscht</string> + <string name="checking_x">%s auf HTTP-Host prüfen</string> <string name="not_connected_try_again">Nicht verbunden, bitte später versuchen</string> - <string name="check_image_filesize">Bildgröße prüfen</string> + <string name="check_x_filesize">%s-Größe prüfen</string> <string name="message_options">Nachrichtenoptionen</string> <string name="copy_text">Text kopieren</string> <string name="copy_original_url">Original-URL kopieren</string> <string name="send_again">Erneut senden</string> - <string name="image_url">Bild-URL</string> + <string name="file_url">Datei-URL</string> <string name="message_text">Nachrichtentext</string> <string name="url_copied_to_clipboard">URL in Zwischenablage kopiert</string> <string name="message_copied_to_clipboard">Nachricht in Zwischenablage kopiert</string> @@ -451,4 +449,6 @@ <string name="none">keine</string> <string name="recently_used">zuletzt verwendet</string> <string name="choose_quick_action">wähle Schnell-Taste</string> + <string name="file_not_found_on_remote_host">Datei auf Server nicht gefunden</string> + <string name="search_for_contacts_or_groups">Nach Kontakten oder Konferenzen suchen</string> </resources> diff --git a/src/main/res/values-el/strings.xml b/src/main/res/values-el/strings.xml index 01b33908d..d796cd6da 100644 --- a/src/main/res/values-el/strings.xml +++ b/src/main/res/values-el/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Αποστολή κρυπτογραφημένου μηνύματος OTR</string> <string name="send_pgp_message">Αποστολή κρυπτογραφημένου μηνύματος OpenPGP</string> <string name="your_nick_has_been_changed">Το ψευδώνυμό σας έχει αλλάξει</string> - <string name="download_image">Μεταφόρτωση εικόνας</string> <string name="send_unencrypted">Αποστολή χωρίς κρυπτογράφηση</string> <string name="decryption_failed">Η αποκρυπτογράφηση απέτυχε. Ίσως δεν κατέχετε το σωστό ιδιωτικό κλειδί.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,11 @@ <string name="conference_members_only">Αυτή η συνδιάσκεψη είναι μόνο για μέλη</string> <string name="conference_kicked">Έχετε διωχθει από αυτή την συνδιάσκεψη</string> <string name="using_account">χρήση λογαριασμού %s</string> - <string name="checking_image">Έλεγχος εικόνας στον διακομιστή HTTP</string> - <string name="image_file_deleted">Το αρχείο εικόνας έχει διαγραφεί</string> <string name="not_connected_try_again">Δεν είστε συνδεμένοι. Δοκιμάστε ξανά αργότερα</string> - <string name="check_image_filesize">Ελέγξτε το μέγεθος του αρχείου εικόνας</string> <string name="message_options">Επιλογές μηνυμάτων</string> <string name="copy_text">Αντιγραφή κειμένου</string> <string name="copy_original_url">Αντιγραφή αρχικής διεύθυνσης URL</string> <string name="send_again">Αποστολή ξανά</string> - <string name="image_url">Διεύθυνση URL εικόνας</string> <string name="message_text">Κείμενο μηνύματος</string> <string name="url_copied_to_clipboard">Η διεύθυνση URL αντιγράφηκε στο πρόχειρο</string> <string name="message_copied_to_clipboard">Το μήνυμα αντιγράφηκε στο πρόχειρο</string> diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index 880ee66b3..29938612f 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Enviar mensaje cifrado con OTR</string> <string name="send_pgp_message">Enviar mensaje cifrado con OpenPGP</string> <string name="your_nick_has_been_changed">Tu apodo se ha modificado</string> - <string name="download_image">Descargar imagen</string> <string name="send_unencrypted">Enviar sin cifrar</string> <string name="decryption_failed">Falló el descifrado. Tal vez no tengas la clave privada apropiada.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,14 @@ <string name="conference_members_only">Esta conversación es solo para miembros</string> <string name="conference_kicked">Has sido expulsado de esta conversación</string> <string name="using_account">Usando cuenta %s</string> - <string name="checking_image">Comprobando imagen en servidor HTTP</string> - <string name="image_file_deleted">El archivo de imagen ha sido eliminado</string> + <string name="checking_x">Comprobando %s en servidor HTTP</string> <string name="not_connected_try_again">No estás conectado. Inténtalo más tarde</string> - <string name="check_image_filesize">Comprobar el tamaño del archivo de imagen</string> + <string name="check_x_filesize">Comprobar tamaño de %s</string> <string name="message_options">Opciones de mensaje</string> <string name="copy_text">Copiar texto</string> <string name="copy_original_url">Copiar URL original</string> <string name="send_again">Volver a enviar</string> - <string name="image_url">URL Imagen</string> + <string name="file_url">URL de archivo</string> <string name="message_text">Mensaje de texto</string> <string name="url_copied_to_clipboard">URL copiada al portapapeles</string> <string name="message_copied_to_clipboard">Mensaje copiado al portapapeles</string> @@ -451,4 +449,6 @@ <string name="none">Ninguna</string> <string name="recently_used">Usada más recientemente</string> <string name="choose_quick_action">Elegir acción rápida</string> + <string name="file_not_found_on_remote_host">Archivo no encontrado en servidor remoto</string> + <string name="search_for_contacts_or_groups">Buscar contactos o grupos</string> </resources> diff --git a/src/main/res/values-eu/strings.xml b/src/main/res/values-eu/strings.xml index b594c069c..028acc532 100644 --- a/src/main/res/values-eu/strings.xml +++ b/src/main/res/values-eu/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">OTRz enkriptatutako mezua bidali</string> <string name="send_pgp_message">OpenPGPz enkriptatutako mezua bidali</string> <string name="your_nick_has_been_changed">Zure ezizena aldatu da</string> - <string name="download_image">Irudia deskargatu</string> <string name="send_unencrypted">Enkriptatu gabe bidali</string> <string name="decryption_failed">Desenkriptazioak huts egin du. Agian ez duzu gako pribatu egokia.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,14 @@ <string name="conference_members_only">Konferentzia hau kideentzat da soilik</string> <string name="conference_kicked">Konferentzia honetatik kanporatua izan zara</string> <string name="using_account">%s kontua erabiltzen</string> - <string name="checking_image">Irudia egiaztatzen HTTP ostalarian</string> - <string name="image_file_deleted">Irudia ezabatu egin da</string> + <string name="checking_x">%s egiaztatzen HTTP ostalarian</string> <string name="not_connected_try_again">Ez zaude konektatuta. Saiatu beranduago berriz</string> - <string name="check_image_filesize">Irudiaren tamaina egiaztatu</string> + <string name="check_x_filesize">Egiaztatu %sren neurria</string> <string name="message_options">Mezuaren aukerak</string> <string name="copy_text">Testua kopiatu</string> <string name="copy_original_url">Jatorrizko URLa kopiatu</string> <string name="send_again">Berriro bidali</string> - <string name="image_url">Irudiaren URLa</string> + <string name="file_url">Fitxategiaren URLa</string> <string name="message_text">Testu mezua</string> <string name="url_copied_to_clipboard">URLa arbelera kopiatu da</string> <string name="message_copied_to_clipboard">Mezua arbelera kopiatu da</string> @@ -451,4 +449,6 @@ <string name="none">Bat ere ez</string> <string name="recently_used">Azkenengo aldiz erabilitakoa</string> <string name="choose_quick_action">Ekintza azkarra aukeratu</string> + <string name="file_not_found_on_remote_host">Fitxategia ez da aurkitu urruneko zerbitzarian</string> + <string name="search_for_contacts_or_groups">Kontaktuak edo taldeak bilatu</string> </resources> diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml index 4baef67f6..05ac82ace 100644 --- a/src/main/res/values-fr/strings.xml +++ b/src/main/res/values-fr/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Envoyer un message sécurisé par OTR</string> <string name="send_pgp_message">Envoyer un message sécurisé par OpenPGP</string> <string name="your_nick_has_been_changed">Votre identifiant a été changé</string> - <string name="download_image">Télécharger l\'image</string> <string name="send_unencrypted">Envoyer en clair</string> <string name="decryption_failed">Echec du déchiffrement. Merci de vérifier la clef privée utilisée.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,11 @@ <string name="conference_members_only">Cette conférence est réservée aux membres</string> <string name="conference_kicked">Vous avez été éjecté de cette conférence</string> <string name="using_account">utiliser le compte %s</string> - <string name="checking_image">Vérification de l\'image</string> - <string name="image_file_deleted">L\'image a été suprimée</string> <string name="not_connected_try_again">Vous n\'êtes pas connecté. Merci de retenter plus tard.</string> - <string name="check_image_filesize">Vérifier la taille de l\'image</string> <string name="message_options">Options du message</string> <string name="copy_text">Copier le texte</string> <string name="copy_original_url">Copier l\'URL</string> <string name="send_again">Envoyer de nouveau</string> - <string name="image_url">URL de l\'image</string> <string name="message_text">Message texte</string> <string name="url_copied_to_clipboard">URL copiée dans le presse-papier</string> <string name="message_copied_to_clipboard">Message copié dans le presse-papier</string> diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml index 70a8f351e..477b75806 100644 --- a/src/main/res/values-gl/strings.xml +++ b/src/main/res/values-gl/strings.xml @@ -48,7 +48,6 @@ <string name="send_otr_message">Enviar mensaxe cifrado con OTR</string> <string name="send_pgp_message">Enviar mensaxe cifrado con OpenPGP</string> <string name="your_nick_has_been_changed">Modificouse o teu apodo</string> - <string name="download_image">Descargar imaxe</string> <string name="send_unencrypted">Enviar sen cifrar</string> <string name="decryption_failed">Fallou o descifrado. Quizábeis non teñas a clave privada apropiada.</string> <string name="openkeychain_required">OpenKeychain</string> diff --git a/src/main/res/values-id/strings.xml b/src/main/res/values-id/strings.xml index 3ce9cc821..6f2d967fd 100644 --- a/src/main/res/values-id/strings.xml +++ b/src/main/res/values-id/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Kirim pesan terenskripsi OTR</string> <string name="send_pgp_message">Kirim pesan terenskripsi OpenPGP</string> <string name="your_nick_has_been_changed">Nick kamu telah dirubah</string> - <string name="download_image">Unduh Gambar</string> <string name="send_unencrypted">Kirim tidak terenkripsi</string> <string name="decryption_failed">Dekripsi gagal. Mungkin Anda tidak memiliki kunci pribadi yang tepat.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,11 @@ <string name="conference_members_only">Conference ini hanya untuk member terdaftar</string> <string name="conference_kicked">Anda telah ditendang dari conference ini</string> <string name="using_account">menggunakan akun %s</string> - <string name="checking_image">Mengecek gambar di host HTTP</string> - <string name="image_file_deleted">Berkas gambar telah dihapus</string> <string name="not_connected_try_again">Anda tidak terhubung. Coba lagi nanti</string> - <string name="check_image_filesize">Cek ukuran berkas gambar</string> <string name="message_options">Opsi pesan</string> <string name="copy_text">Salin teks</string> <string name="copy_original_url">Salin URL asli</string> <string name="send_again">Kirim lagi</string> - <string name="image_url">URL gambar</string> <string name="message_text">Pesan teks</string> <string name="url_copied_to_clipboard">URL disalin ke clipboard</string> <string name="message_copied_to_clipboard">Pesan disalin ke clipboard</string> diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml index 8960f60b5..01299530f 100644 --- a/src/main/res/values-it/strings.xml +++ b/src/main/res/values-it/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Messaggio OTR</string> <string name="send_pgp_message">Messaggio OpenPGP</string> <string name="your_nick_has_been_changed">Il tuo nome utente è stato cambiato</string> - <string name="download_image">Scarica Immagine</string> <string name="send_unencrypted">Invia non cifrato</string> <string name="decryption_failed">Decifrazione fallita. Forse non disponi della chiave privata corretta.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,11 @@ <string name="conference_members_only">Questa conferenza è solo per membri</string> <string name="conference_kicked">Sei stato buttato fuori dalla conferenza</string> <string name="using_account">usando l’utente %s</string> - <string name="checking_image">Controlla immagine su HTTP</string> - <string name="image_file_deleted">Il file dell’immagine è stato cancellato</string> <string name="not_connected_try_again">Non sei connesso. Riprova più tardi</string> - <string name="check_image_filesize">Controlla le dimensioni dell’immagine</string> <string name="message_options">Opzioni del messaggio</string> <string name="copy_text">Copia testo</string> <string name="copy_original_url">Copia URL originale</string> <string name="send_again">Invia di nuovo</string> - <string name="image_url">URL immagine</string> <string name="message_text">Messaggio di testo</string> <string name="url_copied_to_clipboard">URL copiato</string> <string name="message_copied_to_clipboard">Messaggio copiato</string> diff --git a/src/main/res/values-iw/strings.xml b/src/main/res/values-iw/strings.xml index 010da80e0..545ba1c88 100644 --- a/src/main/res/values-iw/strings.xml +++ b/src/main/res/values-iw/strings.xml @@ -66,7 +66,6 @@ <string name="send_otr_message">שלח הודעה מוצפנת OTR</string> <string name="send_pgp_message">שלח הודעה מוצפנת OpenPGP</string> <string name="your_nick_has_been_changed">שם כינוי שלך השתנה</string> - <string name="download_image">הורד תצלום</string> <string name="send_unencrypted">שלח לא מוצפנת</string> <string name="decryption_failed">פענוח נכשל. אולי אין לך את המפתח הפרטי המתאים.</string> <string name="openkeychain_required">OpenKeychain</string> diff --git a/src/main/res/values-ja/strings.xml b/src/main/res/values-ja/strings.xml index 38735f393..f6edfaaec 100644 --- a/src/main/res/values-ja/strings.xml +++ b/src/main/res/values-ja/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">OTR 暗号化メッセージを送信</string> <string name="send_pgp_message">OpenPGP 暗号化メッセージを送信</string> <string name="your_nick_has_been_changed">あなたのニックネームが変更されました</string> - <string name="download_image">画像のダウンロード</string> <string name="send_unencrypted">暗号化されていない送信</string> <string name="decryption_failed">復号化に失敗しました。おそらく秘密鍵が正しくないようです。</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,11 @@ <string name="conference_members_only">この会議はメンバーのみです</string> <string name="conference_kicked">あなたはこの会議からキックされました</string> <string name="using_account">アカウント %s を使用</string> - <string name="checking_image">HTTP ホストの画像を確認中</string> - <string name="image_file_deleted">画像ファイルは削除されました</string> <string name="not_connected_try_again">接続されていません。後でもう一度お試しください</string> - <string name="check_image_filesize">画像ファイルのサイズを確認</string> <string name="message_options">メッセージオプション</string> <string name="copy_text">テキストをコピー</string> <string name="copy_original_url">元の URL をコピー</string> <string name="send_again">再送</string> - <string name="image_url">画像 URL</string> <string name="message_text">メッセージテキスト</string> <string name="url_copied_to_clipboard">URL をクリップボードにコピーしました</string> <string name="message_copied_to_clipboard">メッセージをクリップボードにコピーしました</string> diff --git a/src/main/res/values-ko/strings.xml b/src/main/res/values-ko/strings.xml index 9354c432e..cdc3737ad 100644 --- a/src/main/res/values-ko/strings.xml +++ b/src/main/res/values-ko/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">OTR 암호화된 메세지 전송 </string> <string name="send_pgp_message">OpenPGP 암호화된 메세지 전송 </string> <string name="your_nick_has_been_changed">닉네임이 변경되었습니다 </string> - <string name="download_image">이미지 다운로드 </string> <string name="send_unencrypted">암호화하지 않고 전송 </string> <string name="decryption_failed">복호화 실패. 올바른 개인 키를 가지고 있지 않은 것 같습니다. </string> <string name="openkeychain_required">OpenKeychain </string> @@ -289,15 +288,11 @@ <string name="conference_members_only">이 회의는 멤버 전용입니다 </string> <string name="conference_kicked">당신은 이 회의에서 추방되었습니다 </string> <string name="using_account">using account %s</string> - <string name="checking_image">HTTP 호스트에서 이미지 확인중 </string> - <string name="image_file_deleted">이미지 파일이 삭제되었습니다 </string> <string name="not_connected_try_again">접속중이 아닙니다. 다시 시도하세요. </string> - <string name="check_image_filesize">이미지 파일 크기 확인 </string> <string name="message_options">메세지 설정 </string> <string name="copy_text">텍스트 복사 </string> <string name="copy_original_url">원본 URL 복사 </string> <string name="send_again">다시 보내기 </string> - <string name="image_url">이미지 URL </string> <string name="message_text">메세지 텍스트 </string> <string name="url_copied_to_clipboard">URL이 클립보드에 복사되었습니다 </string> <string name="message_copied_to_clipboard">메세지가 클립보드에 복사되었습니다 </string> diff --git a/src/main/res/values-ms/strings.xml b/src/main/res/values-ms/strings.xml new file mode 100644 index 000000000..c757504ac --- /dev/null +++ b/src/main/res/values-ms/strings.xml @@ -0,0 +1,2 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources/> diff --git a/src/main/res/values-nl/strings.xml b/src/main/res/values-nl/strings.xml index e3f0e69bc..80b6934bc 100644 --- a/src/main/res/values-nl/strings.xml +++ b/src/main/res/values-nl/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Verstuur OTR versleuteld bericht</string> <string name="send_pgp_message">Verstuur OpenPGP versleuteld bericht</string> <string name="your_nick_has_been_changed">Je naam is veranderd</string> - <string name="download_image">Download afbeelding</string> <string name="send_unencrypted">Verstuur onversleuteld</string> <string name="decryption_failed">Ontsleutelen mislukt. Misschien heb je niet de juiste private sleutel.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,13 @@ <string name="conference_members_only">Dit groepsgesprek is enkel voor leden</string> <string name="conference_kicked">Je bent uit dit groepsgesprek geschopt</string> <string name="using_account">account %s gebruiken</string> - <string name="checking_image">Afbeelding op HTTP host nakijken</string> - <string name="image_file_deleted">De afbeelding is verwijderd</string> <string name="not_connected_try_again">Je bent niet verbonden. Probeer later opnieuw</string> - <string name="check_image_filesize">Bekijk bestandsgrootte van afbeelding</string> + <string name="check_x_filesize">Bekijk bestandsgrootte van %s</string> <string name="message_options">Berichtopties</string> <string name="copy_text">Kopieer tekst</string> <string name="copy_original_url">Kopieer oorspronkelijke URL</string> <string name="send_again">Verstuur opnieuw</string> - <string name="image_url">AfbeeldingsURL</string> + <string name="file_url">Bestands-URL</string> <string name="message_text">Berichttekst</string> <string name="url_copied_to_clipboard">URL gekopieerd naar klembord</string> <string name="message_copied_to_clipboard">Bericht gekopieerd naar klembord</string> @@ -451,4 +448,5 @@ <string name="none">Geen</string> <string name="recently_used">Recent gebruikt</string> <string name="choose_quick_action">Kies snelle actie</string> + <string name="file_not_found_on_remote_host">Bestand niet gevonden op externe server</string> </resources> diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml index 6a983f508..ea2ecc525 100644 --- a/src/main/res/values-pl/strings.xml +++ b/src/main/res/values-pl/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Wyślij zaszyfrowaną wiadomość (OTR)</string> <string name="send_pgp_message">Wyślij zaszyfrowaną wiadomość (OpenPGP)</string> <string name="your_nick_has_been_changed">Twoja nazwa została zmieniona</string> - <string name="download_image">Pobierz obraz</string> <string name="send_unencrypted">Wyślij bez szyfrowania</string> <string name="decryption_failed">Nie można odszyfrować. Sprawdź poprawność klucza prywatnego.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,11 @@ <string name="conference_members_only">To jest zamknięty pokój</string> <string name="conference_kicked">Wyrzucono cię z konferencji</string> <string name="using_account">używając konta %s</string> - <string name="checking_image">Sprawdzanie obrazka na hoście HTTP</string> - <string name="image_file_deleted">Obraz został usunięty</string> <string name="not_connected_try_again">Brak połączenia. Spróbuj ponownie później</string> - <string name="check_image_filesize">Sprawdź rozmiar pliku</string> <string name="message_options">Opcje wiadomości</string> <string name="copy_text">Skopiuj tekst</string> <string name="copy_original_url">Skopiuj oryginalny URL</string> <string name="send_again">Wyślij ponownie</string> - <string name="image_url">URL obrazu</string> <string name="message_text">Treść wiadomości</string> <string name="url_copied_to_clipboard">URL obrazu został skopiowany do schowka</string> <string name="message_copied_to_clipboard">Wiadomość została skopiowana do schowka</string> diff --git a/src/main/res/values-pt/strings.xml b/src/main/res/values-pt/strings.xml new file mode 100644 index 000000000..559ae6cfa --- /dev/null +++ b/src/main/res/values-pt/strings.xml @@ -0,0 +1,297 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources> + <string name="action_settings">Configurações</string> + <string name="action_add">Nova conversa</string> + <string name="action_accounts">Gerenciar contas</string> + <string name="action_end_conversation">Finalizar essa conversa</string> + <string name="action_contact_details">Detalhes do contato</string> + <string name="action_muc_details">Detalhes da conferência</string> + <string name="action_secure">Conversa segura</string> + <string name="action_add_account">Adicionar conta</string> + <string name="action_edit_contact">Editar nome</string> + <string name="action_add_phone_book">Adicionar aos contatos</string> + <string name="action_block_contact">Bloquear contato</string> + <string name="action_unblock_contact">Desbloquear contato</string> + <string name="action_block_domain">Bloquear domínio</string> + <string name="action_unblock_domain">Desbloquear domínio</string> + <string name="title_activity_manage_accounts">Gerenciar contas</string> + <string name="title_activity_settings">Configurações</string> + <string name="title_activity_conference_details">Detalhes da conferência</string> + <string name="title_activity_contact_details">Detalhes do contato</string> + <string name="title_activity_sharewith">Compartilhar conversa</string> + <string name="title_activity_start_conversation">Iniciar conversa</string> + <string name="title_activity_choose_contact">Escolher contato</string> + <string name="title_activity_block_list">Bloquear lista</string> + <string name="just_now">agora há pouco</string> + <string name="minute_ago">1 minuto atrás</string> + <string name="minutes_ago">%d minutos atrás</string> + <string name="unread_conversations">Conversas não lidas</string> + <string name="sending">enviando...</string> + <string name="encrypted_message">Descriptografando mensagem. Por favor aguarde...</string> + <string name="nick_in_use">O apelido já está em uso</string> + <string name="admin">Administrador</string> + <string name="owner">Dono</string> + <string name="moderator">Moderador</string> + <string name="participant">Participante</string> + <string name="visitor">Visitante</string> + <string name="block_contact_text">Deseja bloquear o o recebimento de mensagens de %s?</string> + <string name="unblock_contact_text">Deseja desbloquear o recebimento de mensagens de %s?</string> + <string name="block_domain_text">Bloquear todos os contatos de %s?</string> + <string name="unblock_domain_text">Desbloquear todos os contatos de %s?</string> + <string name="contact_blocked">Contato bloqueado</string> + <string name="remove_bookmark_text">Você deseja remover %s dos favoritos? A conversa associada a esse favorito não será removida.</string> + <string name="register_account">Registre uma nova conta no servidor</string> + <string name="change_password_on_server">Altere a senha no servidor</string> + <string name="share_with">Compartilhar com...</string> + <string name="start_conversation">Iniciar conversa</string> + <string name="invite_contact">Convidar contato</string> + <string name="contacts">Contatos</string> + <string name="cancel">Cancelar</string> + <string name="set">Definir</string> + <string name="add">Adicionar</string> + <string name="edit">Editar</string> + <string name="delete">Remover</string> + <string name="block">Bloquear</string> + <string name="unblock">Desbloquear</string> + <string name="save">Salvar</string> + <string name="ok">OK</string> + <string name="crash_report_title">A conversa foi interrompida</string> + <string name="crash_report_message">Ao enviar os stack traces você ajudará o desenvolvimento do aplicativo\n<b>Atenção:</b> Isso usará a sua conta XMPP para enviar o stack trace para o desenvolvedor.</string> + <string name="send_now">Enviar agora</string> + <string name="send_never">Não pergunte novamente</string> + <string name="problem_connecting_to_account">Não foi possível se conectar à conta</string> + <string name="problem_connecting_to_accounts">Não foi possível conectar a múltiplas contas</string> + <string name="touch_to_fix">Toque aqui para gerenciar suas contas</string> + <string name="attach_file">Anexar arquivo</string> + <string name="not_in_roster">O contato não está no seu rol</string> + <string name="add_contact">Adicionar contato</string> + <string name="send_failed">a entrega falhou</string> + <string name="send_rejected">rejeitado</string> + <string name="preparing_image">Preparando a imagem para transmissão</string> + <string name="action_clear_history">Limpar histórico</string> + <string name="clear_conversation_history">Limpar o histórico de conversas</string> + <string name="clear_histor_msg">Você deseja remover todas as mensagens nessa conversa?\n\n<b>Atenção:<b> Isso não irá influenciar mensagens salvas em outros dispositivos ou servidores.</string> + <string name="delete_messages">Remover mensagens</string> + <string name="also_end_conversation">Finalizar essa conversa ao final</string> + <string name="choose_presence">Escolha a presença do contato</string> + <string name="send_plain_text_message">Enviar mensagem de texto puro</string> + <string name="send_otr_message">Enviar mensagem criptografada com OTR</string> + <string name="send_pgp_message">Enviar mensagem criptografada com OpenPGP</string> + <string name="your_nick_has_been_changed">Seu apelido foi alterado</string> + <string name="send_unencrypted">Enviar sem criptografia</string> + <string name="decryption_failed">A desencriptação falhou. Talvez você não tenha a chave privada correta.</string> + <string name="openkeychain_required">OpenKeychain</string> + <string name="openkeychain_required_long">Conversas utiliza um aplicativo de terceiro chamado <b>OpenKeychain</b> para criptografar e descriptografar mensagens e gerenciar suas chaves públicas.\n\nOpenKeychain é licenciado sob a licença GPLv3 e está disponível no F-Droid e Google Play.\n\n<small>(Por favor reinicie Coversas em seguida)</small></string> + <string name="restart">Reiniciar</string> + <string name="install">Instalar</string> + <string name="offering">oferecendo...</string> + <string name="waiting">aguardando...</string> + <string name="no_pgp_key">Nenhuma chave OpenPGP encontrado</string> + <string name="pref_general">Geral</string> + <string name="pref_xmpp_resource">Recurso XMPP</string> + <string name="pref_xmpp_resource_summary">O nome pelo qual esse cliente se identifica</string> + <string name="pref_accept_files">Aceitar arquivos</string> + <string name="pref_accept_files_summary">Automaticamente aceita arquivos menores que...</string> + <string name="pref_notification_settings">Configurações de notificação</string> + <string name="pref_notifications">Notificações</string> + <string name="pref_notifications_summary">Notificar quando uma nova mensagem for recebida</string> + <string name="pref_vibrate">Vibrar</string> + <string name="pref_vibrate_summary">Vibrar também quando uma nova mensagem for recebida</string> + <string name="pref_sound">Som</string> + <string name="pref_sound_summary">Tocar um som com a notificação</string> + <string name="pref_conference_notifications">Notificações de conferência</string> + <string name="pref_conference_notifications_summary">Sempre notificar quando uma nova mensagem de conferencia for recebida ao invés de apenas quando a mesma for ressaltada</string> + <string name="pref_notification_grace_period">Período de carência da notificação</string> + <string name="pref_notification_grace_period_summary">Desativar notificações por um curto período após a copia oculta ser recebida</string> + <string name="pref_advanced_options">Opções avançadas</string> + <string name="pref_never_send_crash">Nunca enviar relatórios de quebra</string> + <string name="pref_never_send_crash_summary">Ao enviar os stack traces você ajuda o desenvolvimento do aplicativo</string> + <string name="pref_confirm_messages">Confirmar mensanges</string> + <string name="pref_confirm_messages_summary">Permitir que um contato saiba quando você recebeu e leu uma mensagem</string> + <string name="pref_ui_options">Opções de UI</string> + <string name="openpgp_error">O OpenKeychain informou um erro</string> + <string name="error_decrypting_file">Erro de I/O de critpografia</string> + <string name="accept">Aceitar</string> + <string name="error">Ocorreu um erro</string> + <string name="pref_grant_presence_updates">Permitir atualizações de presença</string> + <string name="subscriptions">Inscrições</string> + <string name="your_account">Sua conta</string> + <string name="keys">Chaves</string> + <string name="send_presence_updates">Enviar atualizações de presença</string> + <string name="receive_presence_updates">Receber atualizações de presença</string> + <string name="ask_for_presence_updates">Pedir atualizações de presença</string> + <string name="attach_choose_picture">Escolher imagem</string> + <string name="attach_take_picture">Tirar foto</string> + <string name="error_not_an_image_file">O arquivo selecionado não é uma imagem</string> + <string name="error_compressing_image">Erro ao converter o arquivo de imagem</string> + <string name="error_file_not_found">Arquivo não encontrado</string> + <string name="account_status_unknown">Desconhecido</string> + <string name="account_status_disabled">Temporariamente desabilitado</string> + <string name="account_status_online">Online</string> + <string name="account_status_connecting">Conectando\u2026</string> + <string name="account_status_offline">Offline</string> + <string name="account_status_unauthorized">Não autorizado</string> + <string name="account_status_not_found">Servidor não encontrado</string> + <string name="account_status_no_internet">Sem conectividade</string> + <string name="account_status_regis_fail">O registro falhou</string> + <string name="account_status_regis_conflict">O nome de usuário já está em uso</string> + <string name="account_status_regis_success">Registro efetuado com sucesso</string> + <string name="account_status_regis_not_sup">O servidor não aceita o registro</string> + <string name="account_status_security_error">Erro de segurança</string> + <string name="account_status_incompatible_server">Servidor incompatível</string> + <string name="encryption_choice_none">Texto puro</string> + <string name="encryption_choice_otr">OTR</string> + <string name="encryption_choice_pgp">OpenPGP</string> + <string name="mgmt_account_edit">Editar conta</string> + <string name="mgmt_account_delete">Remover conta</string> + <string name="mgmt_account_disable">Desabilitar temporariamente</string> + <string name="mgmt_account_publish_avatar">Publicar o avatar</string> + <string name="mgmt_account_publish_pgp">Publicar chave pública OpenPGP</string> + <string name="mgmt_account_enable">Ativar conta</string> + <string name="mgmt_account_are_you_sure">Tem certeza?</string> + <string name="attach_record_voice">Gravar voz</string> + <string name="account_settings_jabber_id">ID Jabber</string> + <string name="account_settings_password">Senha</string> + <string name="account_settings_example_jabber_id">nomedeusuario@exemplo.com</string> + <string name="account_settings_confirm_password">Confirmar senha</string> + <string name="password">Senha</string> + <string name="confirm_password">Confirmar senha</string> + <string name="passwords_do_not_match">As senhas não combina</string> + <string name="invalid_jid">Esse não é um ID Jabber válido</string> + <string name="error_out_of_memory">Memória insuficiente. A imagem é muito grande</string> + <string name="add_phone_book_text">Você tem certeza que deseja adicionar %s à sua lista de contato do telefone?</string> + <string name="contact_status_online">online</string> + <string name="contact_status_free_to_chat">disponível para conversa</string> + <string name="contact_status_away">fora</string> + <string name="contact_status_extended_away">fora extendido</string> + <string name="contact_status_do_not_disturb">não pertube</string> + <string name="contact_status_offline">offline</string> + <string name="muc_details_conference">Conferência</string> + <string name="muc_details_other_members">Outros Membros</string> + <string name="server_info_show_more">Informações do servior</string> + <string name="server_info_available">disponível</string> + <string name="server_info_unavailable">indisponível</string> + <string name="missing_public_keys">Anúncios de ausência de chave pública</string> + <string name="last_seen_now">visto agora há pouco</string> + <string name="last_seen_min">visto há 1 minuto atrás</string> + <string name="last_seen_mins">visto %d minutos atrás</string> + <string name="last_seen_hour">visto há 1 hora atrás</string> + <string name="last_seen_hours">visto %d horas atrás</string> + <string name="last_seen_day">visto há 1 dia atrás</string> + <string name="last_seen_days">visto %d dias atrás</string> + <string name="never_seen">nunca visto</string> + <string name="install_openkeychain">Mensagem criptografada. Por favor instale o OpenKeychain para desencriptar</string> + <string name="unknown_otr_fingerprint">Impressão OTR inválida</string> + <string name="openpgp_messages_found">Mensagens encriptadas com OpenPGP não encontrada</string> + <string name="reception_failed">A recepção falhou</string> + <string name="your_fingerprint">Sua impressão</string> + <string name="otr_fingerprint">Impressão OTR</string> + <string name="verify">Verificar</string> + <string name="decrypt">Desencriptar</string> + <string name="conferences">Conferências</string> + <string name="search">Buscar</string> + <string name="create_contact">Criar contato</string> + <string name="join_conference">Se juntar à conferência</string> + <string name="delete_contact">Remover contato</string> + <string name="view_contact_details">Ver os detalhes dos contatos</string> + <string name="block_contact">Bloquear contato</string> + <string name="unblock_contact">Desbloquear contato</string> + <string name="create">Criar</string> + <string name="contact_already_exists">O contato já existe</string> + <string name="join">Juntar</string> + <string name="conference_address">Endereço da conferência</string> + <string name="conference_address_example">sala@conferencia.example.com</string> + <string name="save_as_bookmark">Salvar como favorito</string> + <string name="delete_bookmark">Salvar favorito</string> + <string name="bookmark_already_exists">O favorito já existe</string> + <string name="you">Você</string> + <string name="action_edit_subject">Editar o assunto da conferência</string> + <string name="conference_not_found">Conferência não encontrada</string> + <string name="leave">Sair</string> + <string name="contact_added_you">Contato adicionado à sua lista de contato</string> + <string name="add_back">Adicionar novamente</string> + <string name="contact_has_read_up_to_this_point">%s leu até esse ponto</string> + <string name="publish">Publicar</string> + <string name="touch_to_choose_picture">Toque o avatar para escolher uma imagem da sua galeria</string> + <string name="publish_avatar_explanation">Por favor observe: Todos inscritos na sua atualização de presença poderá ver essa imagem</string> + <string name="publishing">Publicando...</string> + <string name="error_publish_avatar_server_reject">O servidor rejeitou sua publicação</string> + <string name="error_publish_avatar_converting">Algo deu errado ao converter sua imagem</string> + <string name="error_saving_avatar">Não foi possível salvar o avatar no disco</string> + <string name="or_long_press_for_default">(Ou mantenha pressionado por um tempo para voltar para o padrão)</string> + <string name="error_publish_avatar_no_server_support">O seu servidor não suporta a publicação de avatares</string> + <string name="private_message">sussurado</string> + <string name="private_message_to">para %s</string> + <string name="send_private_message_to">Enviar mensagem privada para %s</string> + <string name="connect">Conectar</string> + <string name="account_already_exists">Essa conta já existe</string> + <string name="next">Próximo</string> + <string name="server_info_session_established">Sessão atual estebelecida</string> + <string name="additional_information">Informação adicional</string> + <string name="skip">Pular</string> + <string name="disable_notifications">Desativar notificações</string> + <string name="disable_notifications_for_this_conversation">Desativar notificações para essa conversa</string> + <string name="notifications_disabled">As notificações foram desativadas</string> + <string name="enable">Ativar</string> + <string name="conference_requires_password">Essa conferencia requer uma senha</string> + <string name="enter_password">Informar a senha</string> + <string name="missing_presence_updates">Atualizações de presença inexistente para o contato</string> + <string name="request_now">Solicitar agora</string> + <string name="delete_fingerprint">Remover impressão</string> + <string name="sure_delete_fingerprint">Tem certeza que deseja remover essa assinatura?</string> + <string name="pref_encryption_settings">Configurações de criptografia</string> + <string name="pref_force_encryption">Forçar criptografia ponto-a-ponto</string> + <string name="pref_force_encryption_summary">Sempre envie mensagem criptografada (exceto para conferências)</string> + <string name="pref_dont_save_encrypted">Não salve mensagens criptografadas</string> + <string name="pref_dont_save_encrypted_summary">Atenção: Isso pode levar a perda de mensagens</string> + <string name="pref_expert_options">Opções de expert</string> + <string name="pref_expert_options_summary">Por favor tenha cuidado com essas</string> + <string name="title_activity_about">Sobre Conversas</string> + <string name="pref_about_conversations_summary">Informação de licença e construção</string> + <string name="title_pref_quiet_hours">Horas de tranquilidade</string> + <string name="title_pref_quiet_hours_start_time">Hora de início</string> + <string name="title_pref_quiet_hours_end_time">Hora de fim</string> + <string name="title_pref_enable_quiet_hours">Habilitar hora de tranquilidade</string> + <string name="pref_quiet_hours_summary">Notificações serão silenciadas nas horas de tranquilidade</string> + <string name="pref_use_larger_font">Aumentar o tamanho da fonte</string> + <string name="pref_use_larger_font_summary">Usar fontes maiores por todo aplicativo</string> + <string name="pref_use_send_button_to_indicate_status">O botão de enviar indica o estado</string> + <string name="pref_use_indicate_received">Solicitar recibo de mensagem</string> + <string name="pref_use_indicate_received_summary">Mensagens recebidas serão marcadas com um check verde se suportado</string> + <string name="pref_use_send_button_to_indicate_status_summary">Colorir o botão de enviar para indicar o estado do contato</string> + <string name="pref_expert_options_other">Outros</string> + <string name="pref_conference_name">Nome da conferência</string> + <string name="pref_conference_name_summary">Use o assunto da sala ao invés do JID para identificar as conferências</string> + <string name="toast_message_otr_fingerprint">Impressão OTR copiada para a área de transferência!</string> + <string name="try_again">Tentar novamente</string> + <string name="finish">Finalizar</string> + <string name="perform_action_with">Realizar a ação com</string> + <string name="no_affiliation">Sem afiliação</string> + <string name="no_role">Sem papel</string> + <string name="member">Membro</string> + <string name="advanced_mode">Modo avançado</string> + <string name="one_hour">1 hora</string> + <string name="two_hours">2 horas</string> + <string name="eight_hours">8 horas</string> + <string name="until_further_notice">Até segunda ordem</string> + <string name="pref_input_options">Opções de entrada</string> + <string name="pref_enter_is_send">O enter envia</string> + <string name="pref_enter_is_send_summary">Use o enter para enviar a mensagem</string> + <string name="pref_display_enter_key">Exibir tecla enter</string> + <string name="audio">áudio</string> + <string name="video">vídeo</string> + <string name="image">imagem</string> + <string name="pdf_document">Documento PDF</string> + <string name="apk">Aplicativo Android</string> + <string name="vcard">Contato</string> + <string name="sending_x_file">Enviando %s</string> + <string name="offering_x_file">Oferecendo %s</string> + <string name="contact_is_typing">%s está digitando...</string> + <string name="contact_has_stopped_typing">%s parou de digitar</string> + <string name="pref_chat_states">Notificações de digitação</string> + <string name="send_location">Enviar localização</string> + <string name="show_location">Exibir localização</string> + <string name="dialog_manage_certs_negativebutton">Cancelar</string> + <string name="pref_quick_action">Ação rápida</string> + <string name="none">Nada</string> +</resources> diff --git a/src/main/res/values-ro-rRO/strings.xml b/src/main/res/values-ro-rRO/strings.xml index 9572b3db5..9cbfcdbf3 100644 --- a/src/main/res/values-ro-rRO/strings.xml +++ b/src/main/res/values-ro-rRO/strings.xml @@ -79,7 +79,6 @@ <string name="send_otr_message">Trimite mesaj criptat cu OTR</string> <string name="send_pgp_message">Trimite mesaj criptat cu OpenPGP</string> <string name="your_nick_has_been_changed">Numele tau a fost schimbat</string> - <string name="download_image">Copiaza imagine</string> <string name="send_unencrypted">Trimite necriptat</string> <string name="decryption_failed">Decriptia a esuat. Poate nu ai cheia privata corecta.</string> <string name="openkeychain_required">OpenKeychain</string> diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml index 7a57777b6..56a87ffca 100644 --- a/src/main/res/values-ru/strings.xml +++ b/src/main/res/values-ru/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Отправить OTR защифрованное сообщение</string> <string name="send_pgp_message">Отправить OpenPGP защифрованное сообщение</string> <string name="your_nick_has_been_changed">Ваш псевдоним был изменен</string> - <string name="download_image">Загрузить изображение</string> <string name="send_unencrypted">Отправить в незашифрованном виде</string> <string name="decryption_failed">Расшифровка не удалась. Вероятно, что у вас нет надлежащего ключа.</string> <string name="openkeychain_required">Установите OpenKeychain</string> @@ -289,15 +288,11 @@ <string name="conference_members_only">Эта конференция требует членства</string> <string name="conference_kicked">Вы были удалены из конференции</string> <string name="using_account">использовать учётную запись %s</string> - <string name="checking_image">Проверка изображения на узле HTTP</string> - <string name="image_file_deleted">Файл изображения был удалён</string> <string name="not_connected_try_again">Вы неподключены. Попробуйте позже</string> - <string name="check_image_filesize">Проверить размер файла изображения</string> <string name="message_options">Опции сообщения</string> <string name="copy_text">Копировать текст</string> <string name="copy_original_url">Копировать адрес ссылки</string> <string name="send_again">Отправить ещё раз</string> - <string name="image_url">Адрес изображения</string> <string name="message_text">Текст сообщения</string> <string name="url_copied_to_clipboard">Ссылка скопирована в буфер обмена</string> <string name="message_copied_to_clipboard">Сообщение скопировано в буфер обмена</string> diff --git a/src/main/res/values-sk/strings.xml b/src/main/res/values-sk/strings.xml index 561f9824f..d62387949 100644 --- a/src/main/res/values-sk/strings.xml +++ b/src/main/res/values-sk/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Poslať OTR šifrovanú správu</string> <string name="send_pgp_message">Poslať OpenPGP šifrovanú správu</string> <string name="your_nick_has_been_changed">Prezývka sa zmenila</string> - <string name="download_image">Stiahnuť obrázok</string> <string name="send_unencrypted">Poslať nešifrované</string> <string name="decryption_failed">Zašifrovanie zlyhalo. Možno nemáte správny privátny kľúč.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,13 @@ <string name="conference_members_only">Táto konverzácia je iba pre členov</string> <string name="conference_kicked">Vyčlenili vás z tejto konverzácie</string> <string name="using_account">Používa sa účet %s</string> - <string name="checking_image">Overuje sa obrázok na serveri HTTP</string> - <string name="image_file_deleted">Súbor s obrázkom bol vymazaný</string> <string name="not_connected_try_again">Nie ste pripojený. Skúste to neskôr</string> - <string name="check_image_filesize">Overiť veľkosť obrázku</string> + <string name="check_x_filesize">Overiť %s veľkosť</string> <string name="message_options">Možnosti správy</string> <string name="copy_text">Skopírovať text</string> <string name="copy_original_url">Skopírovať originálny URL</string> <string name="send_again">Poslať znova</string> - <string name="image_url">Obrázok URL</string> + <string name="file_url">URL súbor</string> <string name="message_text">Textová správa</string> <string name="url_copied_to_clipboard">URL skopírovaný do schránky</string> <string name="message_copied_to_clipboard">Správa skopírovaná do schránky</string> @@ -438,6 +435,11 @@ <string name="dialog_manage_certs_title">Odstrániť certifikáty</string> <string name="dialog_manage_certs_positivebutton">Vymazať výber</string> <string name="dialog_manage_certs_negativebutton">Zrušiť</string> + <plurals name="toast_delete_certificates"> + <item quantity="one">%d certifikátu vymazaných</item> + <item quantity="few">%d certifikátu vymazaných</item> + <item quantity="other">%d certifikátov vymazaných</item> + </plurals> <plurals name="select_contact"> <item quantity="one">Vybrať %d kontaktu</item> <item quantity="few">Vybrať %d kontaktu</item> @@ -448,4 +450,5 @@ <string name="none">Žiadny</string> <string name="recently_used">Naposledy použitý</string> <string name="choose_quick_action">Vybrať rýchlu voľbu</string> + <string name="file_not_found_on_remote_host">Súbor sa na vzdialenom serveri nenašiel</string> </resources> diff --git a/src/main/res/values-sr/strings.xml b/src/main/res/values-sr/strings.xml index 60f2e586d..082cfa465 100644 --- a/src/main/res/values-sr/strings.xml +++ b/src/main/res/values-sr/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Пошаљи ОТР шифровану поруку</string> <string name="send_pgp_message">Пошаљи ОпенПГП шифровану поруку</string> <string name="your_nick_has_been_changed">Ваш надимак је промењен</string> - <string name="download_image">Преузми слику</string> <string name="send_unencrypted">Пошаљи нешифровано</string> <string name="decryption_failed">Шифровање није успело. Можда немате одговарајући лични кључ.</string> <string name="openkeychain_required">Отворени кључарник</string> @@ -289,15 +288,14 @@ <string name="conference_members_only">Ова конференција је само за чланове</string> <string name="conference_kicked">Шутнути сте из ове конференције</string> <string name="using_account">преко налога %s</string> - <string name="checking_image">Проверавам слику на ХТТП домаћину</string> - <string name="image_file_deleted">Ова слика је обрисана</string> + <string name="checking_x">Проверавам %s на ХТТП домаћину</string> <string name="not_connected_try_again">Нисте повезани. Покушајте поново касније</string> - <string name="check_image_filesize">Провери величину слике</string> + <string name="check_x_filesize">Провери величину %s</string> <string name="message_options">Опције поруке</string> <string name="copy_text">Копирај текст</string> <string name="copy_original_url">Копирај изворни УРЛ</string> <string name="send_again">Пошаљи поново</string> - <string name="image_url">УРЛ слике</string> + <string name="file_url">УРЛ фајла</string> <string name="message_text">Текст поруке</string> <string name="url_copied_to_clipboard">УРЛ је копиран на клипборд</string> <string name="message_copied_to_clipboard">Порука је копирана на клипборд</string> @@ -453,4 +451,6 @@ <string name="none">Ниједна</string> <string name="recently_used">Недавно коришћена</string> <string name="choose_quick_action">Изаберите брзу радњу</string> + <string name="file_not_found_on_remote_host">Фајл није нађен на удаљеном серверу</string> + <string name="search_for_contacts_or_groups">Тражите контакте или групе</string> </resources> diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml index 9c60db531..98ab71105 100644 --- a/src/main/res/values-sv/strings.xml +++ b/src/main/res/values-sv/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">Skicka OTR-krypterat meddelande</string> <string name="send_pgp_message">Skicka OpenPGP-krypterat meddelande</string> <string name="your_nick_has_been_changed">Ditt nick har ändrats</string> - <string name="download_image">Ladda ner bild</string> <string name="send_unencrypted">Skicka okrypterat</string> <string name="decryption_failed">Avkryptering misslyckades. Du har kanske kanske inte rätt privat nyckel.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,14 @@ <string name="conference_members_only">Medlemsskap krävs för denna konferens</string> <string name="conference_kicked">Du har blivit utsparkad från denna konferens</string> <string name="using_account">använder konto %s</string> - <string name="checking_image">Kontrollerar bild på HTTP host</string> - <string name="image_file_deleted">Bildfilen har blivit borttagen</string> + <string name="checking_x">Kontrollerar %s på webbserver</string> <string name="not_connected_try_again">Du är inte ansluten. Försök igen senare</string> - <string name="check_image_filesize">Kontrollera bildens filstorlek</string> + <string name="check_x_filesize">Kontrollera storleken på %s</string> <string name="message_options">Meddelandealternativ</string> <string name="copy_text">Kopiera text</string> <string name="copy_original_url">Kopiera orginal-URL</string> <string name="send_again">Skicka igen</string> - <string name="image_url">Bild-URL</string> + <string name="file_url">Fil URL</string> <string name="message_text">Meddelandetext</string> <string name="url_copied_to_clipboard">URL kopierad till urklipp</string> <string name="message_copied_to_clipboard">Meddelande kopierat till urklipp</string> @@ -451,4 +449,6 @@ <string name="none">Ingen</string> <string name="recently_used">Senast använd</string> <string name="choose_quick_action">Välj snabbfunktion</string> + <string name="file_not_found_on_remote_host">Filen hittas ej på servern</string> + <string name="search_for_contacts_or_groups">Sök efter kontakter eller grupper</string> </resources> diff --git a/src/main/res/values-v21/themes.xml b/src/main/res/values-v21/themes.xml index a1f3d0c57..d1679f928 100644 --- a/src/main/res/values-v21/themes.xml +++ b/src/main/res/values-v21/themes.xml @@ -2,8 +2,8 @@ <resources> <style name="ConversationsTheme" parent="@android:style/Theme.Material.Light.DarkActionBar"> - <item name="android:colorPrimary">@color/primary</item> - <item name="android:colorPrimaryDark">@color/primarydark</item> + <item name="android:colorPrimary">@color/green500</item> + <item name="android:colorPrimaryDark">@color/green700</item> <item name="android:colorAccent">@color/accent</item> <item name="TextSizeInfo">12sp</item> diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index e194bffd2..528afed72 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -80,7 +80,6 @@ <string name="send_otr_message">发送 OTR 加密信息</string> <string name="send_pgp_message">发送 OpenPGP 加密信息</string> <string name="your_nick_has_been_changed">昵称修改成功</string> - <string name="download_image">下载图片</string> <string name="send_unencrypted">不加密发送</string> <string name="decryption_failed">解密失败,可能是私钥不正确。</string> <string name="openkeychain_required">OpenKeychain</string> @@ -289,15 +288,16 @@ <string name="conference_members_only">此讨论组只允许成员加入</string> <string name="conference_kicked">你被从此讨论组踢出</string> <string name="using_account">用账户 %s</string> - <string name="checking_image">正在 HTTP 托管中检查图片</string> +<<<<<<< HEAD + <string name="checking_file">正在 HTTP 托管中检查图片</string> <string name="image_file_deleted">此图片已经被删除</string> +======= +>>>>>>> 4f62793a67415e91f589924b70fdd5bdd35c284d <string name="not_connected_try_again">你没有连接。请稍后重试</string> - <string name="check_image_filesize">检查图片文件尺寸</string> <string name="message_options">消息选项</string> <string name="copy_text">拷贝文本</string> <string name="copy_original_url">拷贝原始URL</string> <string name="send_again">再次发送</string> - <string name="image_url">图片 URL</string> <string name="message_text">消息文本</string> <string name="url_copied_to_clipboard">已经拷贝 URL 到剪贴板</string> <string name="message_copied_to_clipboard">消息已经拷贝到剪贴板</string> diff --git a/src/main/res/values-zh-rTW/strings.xml b/src/main/res/values-zh-rTW/strings.xml index 8aed12d6f..1fd7c4bf2 100644 --- a/src/main/res/values-zh-rTW/strings.xml +++ b/src/main/res/values-zh-rTW/strings.xml @@ -64,7 +64,6 @@ <string name="send_otr_message">發送 OTR 加密訊息</string> <string name="send_pgp_message">發送 OpenPGP 加密訊息</string> <string name="your_nick_has_been_changed">用戶名稱修改成功</string> - <string name="download_image">下載圖片</string> <string name="send_unencrypted">不加密發送</string> <string name="decryption_failed">解密失敗,可能是私鑰不正確。</string> <string name="openkeychain_required">OpenKeychain</string> diff --git a/src/main/res/values/colors.xml b/src/main/res/values/colors.xml index 753a56df9..3a778a210 100644 --- a/src/main/res/values/colors.xml +++ b/src/main/res/values/colors.xml @@ -1,18 +1,16 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - - <color name="primary" type="color">#ff259b24</color> - <color name="primarydark" type="color">#ff0a7e07</color> - <color name="accent">#ff0091ea</color> - <color name="primarytext" type="color">#de000000</color> - <color name="secondarytext" type="color">#8a000000</color> - <color name="ondarktext" type="color">#fffafafa</color> - <color name="primarybackground" type="color">#fffafafa</color> - <color name="secondarybackground" type="color">#ffeeeeee</color> - <color name="darkbackground" type="color">#ff323232</color> - <color name="divider">#1f000000</color> - <color name="red">#fff44336</color> - <color name="orange">#ffff9800</color> - <color name="green">#ff259b24</color> - + <color name="green500">#ff259b24</color> + <color name="green700">#ff0a7e07</color> + <color name="accent">#ff0091ea</color> + <color name="black87">#de000000</color> + <color name="black54">#8a000000</color> + <color name="black12">#1f000000</color> + <color name="white">#ffffffff</color> + <color name="white70">#b2ffffff</color> + <color name="grey50">#fffafafa</color> + <color name="grey200">#ffeeeeee</color> + <color name="grey800">#ff424242</color> + <color name="red500">#fff44336</color> + <color name="orange500">#ffff9800</color> </resources>
\ No newline at end of file diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 4631bd60c..ff05b5b43 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -82,7 +82,6 @@ <string name="send_otr_message">Send OTR encrypted message</string> <string name="send_pgp_message">Send OpenPGP encrypted message</string> <string name="your_nick_has_been_changed">Your nickname has been changed</string> - <string name="download_image">Download Image</string> <string name="send_unencrypted">Send unencrypted</string> <string name="decryption_failed">Decryption failed. Maybe you don’t have the proper private key.</string> <string name="openkeychain_required">OpenKeychain</string> @@ -317,15 +316,14 @@ <string name="conference_members_only">This conference is members only</string> <string name="conference_kicked">You have been kicked from this conference</string> <string name="using_account">using account %s</string> - <string name="checking_image">Checking image on HTTP host</string> - <string name="image_file_deleted">The image file has been deleted</string> + <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_image_filesize">Check image file size</string> + <string name="check_x_filesize">Check %s size</string> <string name="message_options">Message options</string> <string name="copy_text">Copy text</string> <string name="copy_original_url">Copy original URL</string> <string name="send_again">Send again</string> - <string name="image_url">Image URL</string> + <string name="file_url">File URL</string> <string name="message_text">Message text</string> <string name="url_copied_to_clipboard">URL copied to clipboard</string> <string name="message_copied_to_clipboard">Message copied to clipboard</string> @@ -479,4 +477,6 @@ <string name="none">None</string> <string name="recently_used">Most recently used</string> <string name="choose_quick_action">Choose quick action</string> + <string name="file_not_found_on_remote_host">File not found on remote server</string> + <string name="search_for_contacts_or_groups">Search for contacts or groups</string> </resources> diff --git a/src/main/res/values/styles.xml b/src/main/res/values/styles.xml index b329eee44..b98a37fcb 100644 --- a/src/main/res/values/styles.xml +++ b/src/main/res/values/styles.xml @@ -2,7 +2,7 @@ <style name="Divider"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">1.5dp</item> - <item name="android:background">@color/divider</item> + <item name="android:background">@color/black12</item> </style> <style name="Tag"> diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml index 80f2bfe65..5c67203be 100644 --- a/src/main/res/values/themes.xml +++ b/src/main/res/values/themes.xml @@ -38,8 +38,8 @@ </style> <style name="ConversationsActionBar" parent="@android:style/Widget.Holo.Light.ActionBar.Solid.Inverse"> - <item name="android:background">@color/primary</item> - <item name="android:backgroundStacked">@color/primarydark</item> + <item name="android:background">@color/green500</item> + <item name="android:backgroundStacked">@color/green700</item> <item name="android:displayOptions">showHome|homeAsUp|showTitle</item> <item name="android:icon">@android:color/transparent</item> </style> diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml index 5b7d69040..388f5089b 100644 --- a/src/main/res/xml/preferences.xml +++ b/src/main/res/xml/preferences.xml @@ -16,7 +16,7 @@ android:summary="@string/pref_xmpp_resource_summary" android:title="@string/pref_xmpp_resource" /> <ListPreference - android:defaultValue="524288" + android:defaultValue="1048576" android:entries="@array/filesizes" android:entryValues="@array/filesizes_values" android:key="auto_accept_file_size" @@ -101,7 +101,7 @@ android:summary="@string/pref_use_larger_font_summary" android:title="@string/pref_use_larger_font" /> <CheckBoxPreference - android:defaultValue="false" + android:defaultValue="true" android:key="send_button_status" android:summary="@string/pref_use_send_button_to_indicate_status_summary" android:title="@string/pref_use_send_button_to_indicate_status" /> @@ -163,12 +163,12 @@ </PreferenceCategory> <PreferenceCategory android:title="@string/pref_expert_options_other" > <CheckBoxPreference - android:defaultValue="false" + android:defaultValue="true" android:key="indicate_received" android:summary="@string/pref_use_indicate_received_summary" android:title="@string/pref_use_indicate_received" /> <CheckBoxPreference - android:defaultValue="false" + android:defaultValue="true" android:key="keep_foreground_service" android:title="@string/pref_keep_foreground_service" android:summary="@string/pref_keep_foreground_service_summary" /> @@ -176,7 +176,7 @@ </PreferenceScreen> <CheckBoxPreference - android:defaultValue="false" + android:defaultValue="true" android:key="never_send" android:summary="@string/pref_never_send_crash_summary" android:title="@string/pref_never_send_crash" /> |