Merge commit 'v2.9.0' into develop

This commit is contained in:
genofire 2020-09-11 16:53:56 +02:00
commit 06b2043b24
91 changed files with 664 additions and 281 deletions

View File

@ -11,7 +11,7 @@ android:
- '.+'
before_script:
- mkdir libs
- wget -O libs/libwebrtc-m84.aar http://gultsch.de/files/libwebrtc-m84.aar
- wget -O libs/libwebrtc-m85.aar https://gultsch.de/files/libwebrtc-m85.aar
script:
- ./gradlew assembleConversationsFreeSystemRelease
- ./gradlew assembleQuicksyFreeCompatRelease

View File

@ -1,5 +1,12 @@
# Changelog
### Version 2.9.0
* Search individual conversations
* Notify user if message delivery fails
* Remember display names (nicks) from Quicksy users across restarts
* Add button to start Orbot (Tor) from notification if necessary
### Version 2.8.10
* Handle GPX files

View File

@ -80,7 +80,7 @@ dependencies {
implementation 'com.squareup.okhttp3:okhttp:3.12.12'
implementation 'com.google.guava:guava:27.1-android'
quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.11.1'
//implementation fileTree(include: ['libwebrtc-m83.aar'], dir: 'libs')
//implementation fileTree(include: ['libwebrtc-m85.aar'], dir: 'libs')
implementation 'org.webrtc:google-webrtc:1.0.32006'
}
@ -96,8 +96,8 @@ android {
defaultConfig {
minSdkVersion 21
targetSdkVersion 28
versionCode 398
versionName "2.8.10.1"
versionCode 399
versionName "2.9.0"
archivesBaseName += "-$versionName"
applicationId "eu.sum7.conversations"
resValue "string", "applicationId", applicationId

View File

@ -8,4 +8,5 @@
<string name="magic_create_text_on_x">Zostałeś zaproszony do %1$s. Poprowadzimy ciebie przez proces tworzenia konta.\nWybierając %1$s jako dostawcę będziesz mógł komunikować się z innymi użytkownikami podając swój pełny adres XMPP.</string>
<string name="magic_create_text_fixed">Zostałeś zaproszony do %1$s. Nazwa użytkownika została już dla ciebie wybrana. Poprowadzimy ciebie przez proces tworzenia konta.\nBęziesz mógł komunikować się z innymi użytkownikami podając swój adres XMPP.</string>
<string name="your_server_invitation">Zaproszenie twojego serwera</string>
</resources>
<string name="improperly_formatted_provisioning">Niepoprawnie sformatowany kod zaopatrywania</string>
</resources>

View File

@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" android:maxSdkVersion="22" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
@ -36,10 +37,6 @@
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission
android:name="android.permission.READ_PHONE_STATE"
tools:node="remove" />
<uses-sdk tools:overrideLibrary="net.ypresto.androidtranscoder" />
<uses-feature

View File

@ -118,7 +118,7 @@ public final class Config {
public static final boolean ONLY_INTERNAL_STORAGE = false; //use internal storage instead of sdcard to save attachments
public static final boolean IGNORE_ID_REWRITE_IN_MUC = true;
public static final boolean MUC_LEAVE_BEFORE_JOIN = true;
public static final boolean MUC_LEAVE_BEFORE_JOIN = false;
public static final boolean USE_LMC_VERSION_1_1 = true;

View File

@ -615,6 +615,11 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
return UIHelper.getColorForName(jid.asBareJid().toString());
}
@Override
public String getAvatarName() {
throw new IllegalStateException("This method should not be called");
}
public enum State {
DISABLED(false, false),
OFFLINE(false),

View File

@ -248,4 +248,9 @@ public class Bookmark extends Element implements ListItem {
public int getAvatarBackgroundColor() {
return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName());
}
@Override
public String getAvatarName() {
return getDisplayName();
}
}

View File

@ -33,6 +33,7 @@ public class Contact implements ListItem, Blockable {
public static final String SYSTEMNAME = "systemname";
public static final String SERVERNAME = "servername";
public static final String PRESENCE_NAME = "presence_name";
public static final String JID = "jid";
public static final String OPTIONS = "options";
public static final String SYSTEMACCOUNT = "systemaccount";
@ -62,13 +63,14 @@ public class Contact implements ListItem, Blockable {
private long mLastseen = 0;
private String mLastPresence = null;
public Contact(final String account, final String systemName, final String serverName,
public Contact(final String account, final String systemName, final String serverName, final String presenceName,
final Jid jid, final int subscription, final String photoUri,
final Uri systemAccount, final String keys, final String avatar, final long lastseen,
final String presence, final String groups) {
this.accountUuid = account;
this.systemName = systemName;
this.serverName = serverName;
this.presenceName = presenceName;
this.jid = jid;
this.subscription = subscription;
this.photoUri = photoUri;
@ -116,6 +118,7 @@ public class Contact implements ListItem, Blockable {
return new Contact(cursor.getString(cursor.getColumnIndex(ACCOUNT)),
cursor.getString(cursor.getColumnIndex(SYSTEMNAME)),
cursor.getString(cursor.getColumnIndex(SERVERNAME)),
cursor.getString(cursor.getColumnIndex(PRESENCE_NAME)),
jid,
cursor.getInt(cursor.getColumnIndex(OPTIONS)),
cursor.getString(cursor.getColumnIndex(PHOTOURI)),
@ -213,6 +216,7 @@ public class Contact implements ListItem, Blockable {
values.put(ACCOUNT, accountUuid);
values.put(SYSTEMNAME, systemName);
values.put(SERVERNAME, serverName);
values.put(PRESENCE_NAME, presenceName);
values.put(JID, jid.toString());
values.put(OPTIONS, subscription);
values.put(SYSTEMACCOUNT, systemAccount != null ? systemAccount.toString() : null);
@ -554,6 +558,15 @@ public class Contact implements ListItem, Blockable {
return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName());
}
@Override
public String getAvatarName() {
return getDisplayName();
}
public boolean hasAvatarOrPresenceName() {
return (avatar != null && avatar.getFilename() != null) || presenceName != null;
}
public final class Options {
public static final int TO = 0;
public static final int FROM = 1;

View File

@ -186,6 +186,18 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
return null;
}
public int countFailedDeliveries() {
int count = 0;
synchronized (this.messages) {
for(final Message message : this.messages) {
if (message.getStatus() == Message.STATUS_SEND_FAILED) {
++count;
}
}
}
return count;
}
public Message getLastEditableMessage() {
synchronized (this.messages) {
for (final Message message : Lists.reverse(this.messages)) {
@ -1066,6 +1078,11 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
return UIHelper.getColorForName(getName().toString());
}
@Override
public String getAvatarName() {
return getName().toString();
}
public interface OnMessageFound {
void onMessageFound(final Message message);
}

View File

@ -684,6 +684,11 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
}
}
@Override
public String getAvatarName() {
return UIHelper.getMessageDisplayName(this);
}
public boolean isOOb() {
return oob;
}

View File

@ -900,5 +900,10 @@ public class MucOptions {
final String seed = realJid != null ? realJid.asBareJid().toString() : null;
return UIHelper.getColorForName(seed == null ? getName() : seed);
}
@Override
public String getAvatarName() {
return getConversation().getName().toString();
}
}
}

View File

@ -79,6 +79,11 @@ public class RawBlockable implements ListItem, Blockable {
return UIHelper.getColorForName(jid.toEscapedString());
}
@Override
public String getAvatarName() {
return getDisplayName();
}
@Override
public int compareTo(ListItem o) {
return this.getDisplayName().compareToIgnoreCase(

View File

@ -55,6 +55,11 @@ public class Room implements AvatarService.Avatarable, Comparable<Room> {
return UIHelper.getColorForName(room != null ? room.asBareJid().toEscapedString() : name);
}
@Override
public String getAvatarName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View File

@ -13,81 +13,81 @@ import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
public class PresenceGenerator extends AbstractGenerator {
public PresenceGenerator(XmppConnectionService service) {
super(service);
}
public PresenceGenerator(XmppConnectionService service) {
super(service);
}
private PresencePacket subscription(String type, Contact contact) {
PresencePacket packet = new PresencePacket();
packet.setAttribute("type", type);
packet.setTo(contact.getJid());
packet.setFrom(contact.getAccount().getJid().asBareJid());
return packet;
}
private PresencePacket subscription(String type, Contact contact) {
PresencePacket packet = new PresencePacket();
packet.setAttribute("type", type);
packet.setTo(contact.getJid());
packet.setFrom(contact.getAccount().getJid().asBareJid());
return packet;
}
public PresencePacket requestPresenceUpdatesFrom(Contact contact) {
PresencePacket packet = subscription("subscribe", contact);
String displayName = contact.getAccount().getDisplayName();
if (!TextUtils.isEmpty(displayName)) {
packet.addChild("nick",Namespace.NICK).setContent(displayName);
}
return packet;
}
public PresencePacket requestPresenceUpdatesFrom(Contact contact) {
PresencePacket packet = subscription("subscribe", contact);
String displayName = contact.getAccount().getDisplayName();
if (!TextUtils.isEmpty(displayName)) {
packet.addChild("nick", Namespace.NICK).setContent(displayName);
}
return packet;
}
public PresencePacket stopPresenceUpdatesFrom(Contact contact) {
return subscription("unsubscribe", contact);
}
public PresencePacket stopPresenceUpdatesFrom(Contact contact) {
return subscription("unsubscribe", contact);
}
public PresencePacket stopPresenceUpdatesTo(Contact contact) {
return subscription("unsubscribed", contact);
}
public PresencePacket stopPresenceUpdatesTo(Contact contact) {
return subscription("unsubscribed", contact);
}
public PresencePacket sendPresenceUpdatesTo(Contact contact) {
return subscription("subscribed", contact);
}
public PresencePacket sendPresenceUpdatesTo(Contact contact) {
return subscription("subscribed", contact);
}
public PresencePacket selfPresence(Account account, Presence.Status status) {
return selfPresence(account, status, true);
}
public PresencePacket selfPresence(Account account, Presence.Status status) {
return selfPresence(account, status, true);
}
public PresencePacket selfPresence(final Account account, final Presence.Status status, final boolean personal) {
final PresencePacket packet = new PresencePacket();
if (personal) {
final String sig = account.getPgpSignature();
final String message = account.getPresenceStatusMessage();
if(status.toShowString() != null) {
packet.addChild("show").setContent(status.toShowString());
}
if (!TextUtils.isEmpty(message)) {
packet.addChild(new Element("status").setContent(message));
}
if (sig != null && mXmppConnectionService.getPgpEngine() != null) {
packet.addChild("x", "jabber:x:signed").setContent(sig);
}
}
final String capHash = getCapHash(account);
if (capHash != null) {
Element cap = packet.addChild("c",
"http://jabber.org/protocol/caps");
cap.setAttribute("hash", "sha-1");
cap.setAttribute("node", "https://sum7.eu");
cap.setAttribute("ver", capHash);
}
return packet;
}
public PresencePacket selfPresence(final Account account, final Presence.Status status, final boolean personal) {
final PresencePacket packet = new PresencePacket();
if (personal) {
final String sig = account.getPgpSignature();
final String message = account.getPresenceStatusMessage();
if (status.toShowString() != null) {
packet.addChild("show").setContent(status.toShowString());
}
if (!TextUtils.isEmpty(message)) {
packet.addChild(new Element("status").setContent(message));
}
if (sig != null && mXmppConnectionService.getPgpEngine() != null) {
packet.addChild("x", "jabber:x:signed").setContent(sig);
}
}
final String capHash = getCapHash(account);
if (capHash != null) {
Element cap = packet.addChild("c",
"http://jabber.org/protocol/caps");
cap.setAttribute("hash", "sha-1");
cap.setAttribute("node", "http://conversations.im");
cap.setAttribute("ver", capHash);
}
return packet;
}
public PresencePacket leave(final MucOptions mucOptions) {
PresencePacket presencePacket = new PresencePacket();
presencePacket.setTo(mucOptions.getSelf().getFullJid());
presencePacket.setFrom(mucOptions.getAccount().getJid());
presencePacket.setAttribute("type", "unavailable");
return presencePacket;
}
public PresencePacket leave(final MucOptions mucOptions) {
PresencePacket presencePacket = new PresencePacket();
presencePacket.setTo(mucOptions.getSelf().getFullJid());
presencePacket.setFrom(mucOptions.getAccount().getJid());
presencePacket.setAttribute("type", "unavailable");
return presencePacket;
}
public PresencePacket sendOfflinePresence(Account account) {
PresencePacket packet = new PresencePacket();
packet.setFrom(account.getJid());
packet.setAttribute("type","unavailable");
return packet;
}
public PresencePacket sendOfflinePresence(Account account) {
PresencePacket packet = new PresencePacket();
packet.setFrom(account.getJid());
packet.setAttribute("type", "unavailable");
return packet;
}
}

View File

@ -300,6 +300,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
} else {
Contact contact = account.getRoster().getContact(user);
if (contact.setPresenceName(nick)) {
mXmppConnectionService.syncRoster(account);
mXmppConnectionService.getAvatarService().clear(contact);
}
}
@ -307,8 +308,14 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
mXmppConnectionService.updateAccountUi();
}
private boolean handleErrorMessage(Account account, MessagePacket packet) {
private boolean handleErrorMessage(final Account account, final MessagePacket packet) {
if (packet.getType() == MessagePacket.TYPE_ERROR) {
if (packet.fromServer(account)) {
final Pair<MessagePacket, Long> forwarded = packet.getForwardedMessagePacket("received", "urn:xmpp:carbons:2");
if (forwarded != null) {
return handleErrorMessage(account, forwarded.first);
}
}
final Jid from = packet.getFrom();
final String id = packet.getId();
if (from != null && id != null) {
@ -362,7 +369,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
final Element result = MessageArchiveService.Version.findResult(original);
final MessageArchiveService.Query query = result == null ? null : mXmppConnectionService.getMessageArchiveService().findQuery(result.getAttribute("queryid"));
if (query != null && query.validFrom(original.getFrom())) {
Pair<MessagePacket, Long> f = original.getForwardedMessagePacket("result", query.version.namespace);
final Pair<MessagePacket, Long> f = original.getForwardedMessagePacket("result", query.version.namespace);
if (f == null) {
return;
}
@ -370,6 +377,9 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
packet = f.first;
serverMsgId = result.getAttribute("id");
query.incrementMessageCount();
if (handleErrorMessage(account, packet)) {
return;
}
} else if (query != null) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received mam result from invalid sender");
return;
@ -1011,8 +1021,9 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
final String nick = packet.findChildContent("nick", Namespace.NICK);
if (nick != null && InvalidJid.hasValidFrom(original)) {
Contact contact = account.getRoster().getContact(from);
final Contact contact = account.getRoster().getContact(from);
if (contact.setPresenceName(nick)) {
mXmppConnectionService.syncRoster(account);
mXmppConnectionService.getAvatarService().clear(contact);
}
}

View File

@ -337,6 +337,7 @@ public class PresenceParser extends AbstractParser implements
mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, false);
} else if (type.equals("subscribe")) {
if (contact.setPresenceName(packet.findChildContent("nick", Namespace.NICK))) {
mXmppConnectionService.syncRoster(account);
mXmppConnectionService.getAvatarService().clear(contact);
}
if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) {

View File

@ -63,11 +63,12 @@ import eu.siacs.conversations.xmpp.Jid;
public class DatabaseBackend extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "history";
private static final int DATABASE_VERSION = 47;
private static final int DATABASE_VERSION = 48;
private static DatabaseBackend instance = null;
private static String CREATE_CONTATCS_STATEMENT = "create table "
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
+ Contact.SERVERNAME + " TEXT, " + Contact.SYSTEMNAME + " TEXT,"
+ Contact.PRESENCE_NAME + " TEXT,"
+ Contact.JID + " TEXT," + Contact.KEYS + " TEXT,"
+ Contact.PHOTOURI + " TEXT," + Contact.OPTIONS + " NUMBER,"
+ Contact.SYSTEMACCOUNT + " NUMBER, " + Contact.AVATAR + " TEXT, "
@ -559,6 +560,9 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.execSQL(CREATE_RESOLVER_RESULTS_TABLE);
}
if (oldVersion < 48 && newVersion >= 48) {
db.execSQL("ALTER TABLE " + Contact.TABLENAME + " ADD COLUMN " + Contact.PRESENCE_NAME + " TEXT");
}
}
private void canonicalizeJids(SQLiteDatabase db) {
@ -577,7 +581,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
continue;
}
String updateArgs[] = {
final String[] updateArgs = {
newJid,
cursor.getString(cursor.getColumnIndex(Conversation.UUID)),
};
@ -780,11 +784,20 @@ public class DatabaseBackend extends SQLiteOpenHelper {
return list;
}
public Cursor getMessageSearchCursor(List<String> term) {
SQLiteDatabase db = this.getReadableDatabase();
String SQL = "SELECT " + Message.TABLENAME + ".*," + Conversation.TABLENAME + '.' + Conversation.CONTACTJID + ',' + Conversation.TABLENAME + '.' + Conversation.ACCOUNT + ',' + Conversation.TABLENAME + '.' + Conversation.MODE + " FROM " + Message.TABLENAME + " join " + Conversation.TABLENAME + " on " + Message.TABLENAME + '.' + Message.CONVERSATION + '=' + Conversation.TABLENAME + '.' + Conversation.UUID + " join messages_index ON messages_index.uuid=messages.uuid where " + Message.ENCRYPTION + " NOT IN(" + Message.ENCRYPTION_AXOLOTL_NOT_FOR_THIS_DEVICE + ',' + Message.ENCRYPTION_PGP + ',' + Message.ENCRYPTION_DECRYPTION_FAILED + ',' + Message.ENCRYPTION_AXOLOTL_FAILED + ") AND " + Message.TYPE + " IN(" + Message.TYPE_TEXT + ',' + Message.TYPE_PRIVATE + ") AND messages_index.body MATCH ? ORDER BY " + Message.TIME_SENT + " DESC limit " + Config.MAX_SEARCH_RESULTS;
public Cursor getMessageSearchCursor(final List<String> term, final String uuid) {
final SQLiteDatabase db = this.getReadableDatabase();
final StringBuilder SQL = new StringBuilder();
final String[] selectionArgs;
SQL.append("SELECT " + Message.TABLENAME + ".*," + Conversation.TABLENAME + '.' + Conversation.CONTACTJID + ',' + Conversation.TABLENAME + '.' + Conversation.ACCOUNT + ',' + Conversation.TABLENAME + '.' + Conversation.MODE + " FROM " + Message.TABLENAME + " join " + Conversation.TABLENAME + " on " + Message.TABLENAME + '.' + Message.CONVERSATION + '=' + Conversation.TABLENAME + '.' + Conversation.UUID + " join messages_index ON messages_index.uuid=messages.uuid where " + Message.ENCRYPTION + " NOT IN(" + Message.ENCRYPTION_AXOLOTL_NOT_FOR_THIS_DEVICE + ',' + Message.ENCRYPTION_PGP + ',' + Message.ENCRYPTION_DECRYPTION_FAILED + ',' + Message.ENCRYPTION_AXOLOTL_FAILED + ") AND " + Message.TYPE + " IN(" + Message.TYPE_TEXT + ',' + Message.TYPE_PRIVATE + ") AND messages_index.body MATCH ?");
if (uuid == null) {
selectionArgs = new String[]{FtsUtils.toMatchString(term)};
} else {
selectionArgs = new String[]{FtsUtils.toMatchString(term), uuid};
SQL.append(" AND "+Conversation.TABLENAME+'.'+Conversation.UUID+"=?");
}
SQL.append(" ORDER BY " + Message.TIME_SENT + " DESC limit " + Config.MAX_SEARCH_RESULTS);
Log.d(Config.LOGTAG, "search term: " + FtsUtils.toMatchString(term));
return db.rawQuery(SQL, new String[]{FtsUtils.toMatchString(term)});
return db.rawQuery(SQL.toString(), selectionArgs);
}
public List<String> markFileAsDeleted(final File file, final boolean internal) {
@ -1006,7 +1019,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
final SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
for (Contact contact : roster.getContacts()) {
if (contact.getOption(Contact.Options.IN_ROSTER) || contact.getAvatarFilename() != null || contact.getOption(Contact.Options.SYNCED_VIA_OTHER)) {
if (contact.getOption(Contact.Options.IN_ROSTER) || contact.hasAvatarOrPresenceName() || contact.getOption(Contact.Options.SYNCED_VIA_OTHER)) {
db.insert(Contact.TABLENAME, null, contact.getContentValues());
} else {
String where = Contact.ACCOUNT + "=? AND " + Contact.JID + "=?";

View File

@ -685,5 +685,6 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
public interface Avatarable {
@ColorInt int getAvatarBackgroundColor();
String getAvatarName();
}
}

View File

@ -8,6 +8,8 @@ import android.preference.PreferenceManager;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import com.google.common.base.Strings;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.utils.Compatibility;
@ -19,17 +21,13 @@ public class EventReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent originalIntent) {
final Intent intentForService = new Intent(context, XmppConnectionService.class);
if (originalIntent.getAction() != null) {
intentForService.setAction(originalIntent.getAction());
final Bundle extras = originalIntent.getExtras();
if (extras != null) {
intentForService.putExtras(extras);
}
} else {
intentForService.setAction("other");
}
final String action = originalIntent.getAction();
if (action.equals("ui") || hasEnabledAccounts(context)) {
intentForService.setAction(Strings.isNullOrEmpty(action) ? "other" : action);
final Bundle extras = originalIntent.getExtras();
if (extras != null) {
intentForService.putExtras(extras);
}
if ("ui".equals(action) || hasEnabledAccounts(context)) {
Compatibility.startService(context, intentForService);
} else {
Log.d(Config.LOGTAG, "EventReceiver ignored action " + intentForService.getAction());

View File

@ -56,18 +56,20 @@ public class MessageSearchTask implements Runnable, Cancellable {
private final XmppConnectionService xmppConnectionService;
private final List<String> term;
private final String uuid;
private final OnSearchResultsAvailable onSearchResultsAvailable;
private boolean isCancelled = false;
private MessageSearchTask(XmppConnectionService xmppConnectionService, List<String> term, OnSearchResultsAvailable onSearchResultsAvailable) {
private MessageSearchTask(XmppConnectionService xmppConnectionService, List<String> term, final String uuid, OnSearchResultsAvailable onSearchResultsAvailable) {
this.xmppConnectionService = xmppConnectionService;
this.term = term;
this.uuid = uuid;
this.onSearchResultsAvailable = onSearchResultsAvailable;
}
public static void search(XmppConnectionService xmppConnectionService, List<String> term, OnSearchResultsAvailable onSearchResultsAvailable) {
new MessageSearchTask(xmppConnectionService, term, onSearchResultsAvailable).executeInBackground();
public static void search(XmppConnectionService xmppConnectionService, List<String> term, final String uuid, OnSearchResultsAvailable onSearchResultsAvailable) {
new MessageSearchTask(xmppConnectionService, term, uuid, onSearchResultsAvailable).executeInBackground();
}
public static void cancelRunningTasks() {
@ -86,7 +88,7 @@ public class MessageSearchTask implements Runnable, Cancellable {
try {
final HashMap<String, Conversational> conversationCache = new HashMap<>();
final List<Message> result = new ArrayList<>();
cursor = xmppConnectionService.databaseBackend.getMessageSearchCursor(term);
cursor = xmppConnectionService.databaseBackend.getMessageSearchCursor(term, uuid);
long dbTimer = SystemClock.elapsedRealtime();
if (isCancelled) {
Log.d(Config.LOGTAG, "canceled search task");

View File

@ -61,6 +61,7 @@ import eu.siacs.conversations.ui.TimePreference;
import eu.siacs.conversations.utils.AccountUtils;
import eu.siacs.conversations.utils.Compatibility;
import eu.siacs.conversations.utils.GeoHelper;
import eu.siacs.conversations.utils.TorServiceUtils;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
@ -82,6 +83,7 @@ public class NotificationService {
private static final int ERROR_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 6;
private static final int INCOMING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 8;
public static final int ONGOING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 10;
private static final int DELIVERY_FAILED_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 12;
private final XmppConnectionService mXmppConnectionService;
private final LinkedHashMap<String, ArrayList<Message>> notifications = new LinkedHashMap<>();
private final HashMap<Conversation, AtomicInteger> mBacklogMessageCounter = new HashMap<>();
@ -220,9 +222,20 @@ public class NotificationService {
quietHoursChannel.setSound(null, null);
notificationManager.createNotificationChannel(quietHoursChannel);
final NotificationChannel deliveryFailedChannel = new NotificationChannel("delivery_failed",
c.getString(R.string.delivery_failed_channel_name),
NotificationManager.IMPORTANCE_DEFAULT);
deliveryFailedChannel.setShowBadge(false);
deliveryFailedChannel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT)
.build());
deliveryFailedChannel.setGroup("chats");
notificationManager.createNotificationChannel(deliveryFailedChannel);
}
public boolean notify(final Message message) {
private boolean notify(final Message message) {
final Conversation conversation = (Conversation) message.getConversation();
return message.getStatus() == Message.STATUS_RECEIVED
&& !conversation.isMuted()
@ -342,6 +355,37 @@ public class NotificationService {
}
}
public void pushFailedDelivery(final Message message) {
final Conversation conversation = (Conversation) message.getConversation();
final boolean isScreenOn = mXmppConnectionService.isInteractive();
if (this.mIsInForeground && isScreenOn && this.mOpenConversation == message.getConversation()) {
Log.d(Config.LOGTAG, message.getConversation().getAccount().getJid().asBareJid() + ": suppressing failed delivery notification because conversation is open");
return;
}
final PendingIntent pendingIntent = createContentIntent(conversation);
final int notificationId = generateRequestCode(conversation, 0) + DELIVERY_FAILED_NOTIFICATION_ID;
final int failedDeliveries = conversation.countFailedDeliveries();
final Notification notification =
new Builder(mXmppConnectionService, "delivery_failed")
.setContentTitle(conversation.getName())
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_error_white_24dp)
.setContentText(mXmppConnectionService.getResources().getQuantityText(R.plurals.some_messages_could_not_be_delivered, failedDeliveries))
.setGroup("delivery_failed")
.setContentIntent(pendingIntent).build();
final Notification summaryNotification =
new Builder(mXmppConnectionService, "delivery_failed")
.setContentTitle(mXmppConnectionService.getString(R.string.failed_deliveries))
.setContentText(mXmppConnectionService.getResources().getQuantityText(R.plurals.some_messages_could_not_be_delivered, 1024))
.setSmallIcon(R.drawable.ic_error_white_24dp)
.setGroup("delivery_failed")
.setGroupSummary(true)
.setAutoCancel(true)
.build();
notify(notificationId, notification);
notify(DELIVERY_FAILED_NOTIFICATION_ID, summaryNotification);
}
public void showIncomingCallNotification(final AbstractJingleConnection.Id id, final Set<Media> media) {
final Intent fullScreenIntent = new Intent(mXmppConnectionService, RtpSessionActivity.class);
fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().asBareJid().toEscapedString());
@ -1092,9 +1136,11 @@ public class NotificationService {
}
final boolean showAllErrors = QuickConversationsService.isConversations();
final List<Account> errors = new ArrayList<>();
boolean torNotAvailable = false;
for (final Account account : mXmppConnectionService.getAccounts()) {
if (account.hasErrorStatus() && account.showErrorNotification() && (showAllErrors || account.getLastErrorStatus() == Account.State.UNAUTHORIZED)) {
errors.add(account);
torNotAvailable |= account.getStatus() == Account.State.TOR_NOT_AVAILABLE;
}
}
if (mXmppConnectionService.foregroundNotificationNeedsUpdatingWhenErrorStateChanges()) {
@ -1113,7 +1159,23 @@ public class NotificationService {
}
mBuilder.addAction(R.drawable.ic_autorenew_white_24dp,
mXmppConnectionService.getString(R.string.try_again),
createTryAgainIntent());
createTryAgainIntent()
);
if (torNotAvailable) {
if (TorServiceUtils.isOrbotInstalled(mXmppConnectionService)) {
mBuilder.addAction(
R.drawable.ic_play_circle_filled_white_48dp,
mXmppConnectionService.getString(R.string.start_orbot),
PendingIntent.getActivity(mXmppConnectionService, 147, TorServiceUtils.LAUNCH_INTENT, 0)
);
} else {
mBuilder.addAction(
R.drawable.ic_file_download_white_24dp,
mXmppConnectionService.getString(R.string.install_orbot),
PendingIntent.getActivity(mXmppConnectionService, 146, TorServiceUtils.INSTALL_INTENT, 0)
);
}
}
mBuilder.setDeleteIntent(createDismissErrorIntent());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mBuilder.setVisibility(Notification.VISIBILITY_PRIVATE);

View File

@ -36,6 +36,8 @@ import android.support.annotation.BoolRes;
import android.support.annotation.IntegerRes;
import android.support.v4.app.RemoteInput;
import android.support.v4.content.ContextCompat;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
@ -127,6 +129,7 @@ import eu.siacs.conversations.utils.ReplacingTaskManager;
import eu.siacs.conversations.utils.Resolver;
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
import eu.siacs.conversations.utils.StringUtils;
import eu.siacs.conversations.utils.TorServiceUtils;
import eu.siacs.conversations.utils.WakeLockHelper;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xml.Element;
@ -261,6 +264,16 @@ public class XmppConnectionService extends Service {
return false;
}
};
private final AtomicBoolean isPhoneInCall = new AtomicBoolean(false);
private final PhoneStateListener phoneStateListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(final int state, final String phoneNumber) {
isPhoneInCall.set(state != TelephonyManager.CALL_STATE_IDLE);
if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
mJingleConnectionManager.notifyPhoneCallStarted();
}
}
};
private boolean destroyed = false;
@ -602,8 +615,8 @@ public class XmppConnectionService extends Service {
return c != null && c.getMode() == Conversational.MODE_MULTI;
}
public void search(List<String> term, OnSearchResultsAvailable onSearchResultsAvailable) {
MessageSearchTask.search(this, term, onSearchResultsAvailable);
public void search(final List<String> term, final String uuid, final OnSearchResultsAvailable onSearchResultsAvailable) {
MessageSearchTask.search(this, term, uuid, onSearchResultsAvailable);
}
@Override
@ -652,8 +665,15 @@ public class XmppConnectionService extends Service {
final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID);
Log.d(Config.LOGTAG, "received intent to dismiss call with session id " + sessionId);
mJingleConnectionManager.rejectRtpSession(sessionId);
break;
}
break;
case TorServiceUtils.ACTION_STATUS:
final String status = intent.getStringExtra(TorServiceUtils.EXTRA_STATUS);
if ("ON".equals(status)) {
handleOrbotStartedEvent();
return START_STICKY;
}
break;
case ACTION_END_CALL: {
final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID);
Log.d(Config.LOGTAG, "received intent to end call with session id " + sessionId);
@ -787,6 +807,14 @@ public class XmppConnectionService extends Service {
return START_STICKY;
}
private void handleOrbotStartedEvent() {
for (final Account account : accounts) {
if (account.getStatus() == Account.State.TOR_NOT_AVAILABLE) {
reconnectAccount(account, true, false);
}
}
}
private boolean processAccountState(Account account, boolean interactive, boolean isUiAction, boolean isAccountPushed, HashSet<Account> pingCandidates) {
boolean pingNow = false;
if (account.getStatus().isAttemptReconnect()) {
@ -1128,17 +1156,31 @@ public class XmppConnectionService extends Service {
toggleForegroundService();
updateUnreadCountBadge();
toggleScreenEventReceiver();
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TorServiceUtils.ACTION_STATUS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
scheduleNextIdlePing();
IntentFilter intentFilter = new IntentFilter();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
}
intentFilter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
registerReceiver(this.mInternalEventReceiver, intentFilter);
}
registerReceiver(this.mInternalEventReceiver, intentFilter);
mForceDuringOnCreate.set(false);
toggleForegroundService();
setupPhoneStateListener();
}
private void setupPhoneStateListener() {
final TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager != null) {
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
public boolean isPhoneInCall() {
return isPhoneInCall.get();
}
private void checkForDeletedFiles() {
@ -1192,7 +1234,7 @@ public class XmppConnectionService extends Service {
public void onDestroy() {
try {
unregisterReceiver(this.mInternalEventReceiver);
} catch (IllegalArgumentException e) {
} catch (final IllegalArgumentException e) {
//ignored
}
destroyed = false;
@ -2193,7 +2235,7 @@ public class XmppConnectionService extends Service {
final Jid jid = Jid.ofEscaped(address);
final Account account = new Account(jid, password);
account.setOption(Account.OPTION_DISABLED, true);
Log.d(Config.LOGTAG,jid.asBareJid().toEscapedString()+": provisioning account");
Log.d(Config.LOGTAG, jid.asBareJid().toEscapedString() + ": provisioning account");
createAccount(account);
}
@ -3880,7 +3922,7 @@ public class XmppConnectionService extends Service {
}
public void markMessage(Message message, int status, String errorMessage) {
public void markMessage(final Message message, final int status, final String errorMessage) {
final int oldStatus = message.getStatus();
if (status == Message.STATUS_SEND_FAILED && (oldStatus == Message.STATUS_SEND_RECEIVED || oldStatus == Message.STATUS_SEND_DISPLAYED)) {
return;
@ -3892,6 +3934,9 @@ public class XmppConnectionService extends Service {
message.setStatus(status);
databaseBackend.updateMessage(message, false);
updateConversationUi();
if (oldStatus != status && status == Message.STATUS_SEND_FAILED) {
mNotificationService.pushFailedDelivery(message);
}
}
private SharedPreferences getPreferences() {

View File

@ -1240,6 +1240,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
case R.id.attach_location:
handleAttachmentSelection(item);
break;
case R.id.action_search:
startSearch();
break;
case R.id.action_archive:
activity.xmppConnectionService.archiveConversation(conversation);
break;
@ -1289,6 +1292,12 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
return super.onOptionsItemSelected(item);
}
private void startSearch() {
final Intent intent = new Intent(getActivity(), SearchActivity.class);
intent.putExtra(SearchActivity.EXTRA_CONVERSATION_UUID, conversation.getUuid());
startActivity(intent);
}
private void returnToOngoingCall() {
final Optional<OngoingRtpSession> ongoingRtpSession = activity.xmppConnectionService.getJingleConnectionManager().getOngoingRtpConnection(conversation.getContact());
if (ongoingRtpSession.isPresent()) {
@ -2034,9 +2043,12 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
toggleInputMethod();
}
public void reInit(Conversation conversation, Bundle extras) {
public void reInit(final Conversation conversation, final Bundle extras) {
QuickLoader.set(conversation.getUuid());
this.saveMessageDraftStopAudioPlayer();
final boolean changedConversation = this.conversation != conversation;
if (changedConversation) {
this.saveMessageDraftStopAudioPlayer();
}
this.clearPending();
if (this.reInit(conversation, extras != null)) {
if (extras != null) {
@ -2753,7 +2765,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
correctMessage(lastEditableMessage);
return true;
} else {
Toast.makeText(getActivity(),R.string.could_not_correct_message, Toast.LENGTH_LONG).show();
Toast.makeText(getActivity(), R.string.could_not_correct_message, Toast.LENGTH_LONG).show();
return false;
}
}

View File

@ -266,8 +266,8 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
}
private boolean processViewIntent(Intent intent) {
String uuid = intent.getStringExtra(EXTRA_CONVERSATION);
Conversation conversation = uuid != null ? xmppConnectionService.findConversationByUuid(uuid) : null;
final String uuid = intent.getStringExtra(EXTRA_CONVERSATION);
final Conversation conversation = uuid != null ? xmppConnectionService.findConversationByUuid(uuid) : null;
if (conversation == null) {
Log.d(Config.LOGTAG, "unable to view conversation with uuid:" + uuid);
return false;
@ -380,8 +380,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_conversations, menu);
AccountUtils.showHideMenuItems(menu);
MenuItem qrCodeScanMenuItem = menu.findItem(R.id.action_scan_qr_code);
final MenuItem qrCodeScanMenuItem = menu.findItem(R.id.action_scan_qr_code);
if (qrCodeScanMenuItem != null) {
if (isCameraFeatureAvailable()) {
Fragment fragment = getFragmentManager().findFragmentById(R.id.main_fragment);
@ -489,6 +488,18 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
case R.id.action_scan_qr_code:
UriHandlerActivity.scan(this);
return true;
case R.id.action_search_all_conversations:
startActivity(new Intent(this, SearchActivity.class));
return true;
case R.id.action_search_this_conversation:
final Conversation conversation = ConversationFragment.getConversation(this);
if (conversation == null) {
return true;
}
final Intent intent = new Intent(this, SearchActivity.class);
intent.putExtra(SearchActivity.EXTRA_CONVERSATION_UUID, conversation.getUuid());
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}

View File

@ -64,6 +64,7 @@ import eu.siacs.conversations.ui.util.PendingActionHelper;
import eu.siacs.conversations.ui.util.PendingItem;
import eu.siacs.conversations.ui.util.ScrollState;
import eu.siacs.conversations.ui.util.StyledAttributes;
import eu.siacs.conversations.utils.AccountUtils;
import eu.siacs.conversations.utils.ThemeHelper;
import static android.support.v7.widget.helper.ItemTouchHelper.LEFT;
@ -284,6 +285,7 @@ public class ConversationsOverviewFragment extends XmppFragment {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
menuInflater.inflate(R.menu.fragment_conversations_overview, menu);
AccountUtils.showHideMenuItems(menu);
}
@Override

View File

@ -89,7 +89,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
private static final int REQUEST_CHANGE_STATUS = 0xee11;
private static final int REQUEST_ORBOT = 0xff22;
private final PendingItem<PresenceTemplate> mPendingPresenceTemplate = new PendingItem<>();
private final AtomicBoolean mPendingReconnect = new AtomicBoolean(false);
private AlertDialog mCaptchaDialog = null;
private Jid jidToEdit;
private boolean mInitMode = false;
@ -475,13 +474,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
Log.d(Config.LOGTAG, "pgp result not ok");
}
}
if (requestCode == REQUEST_ORBOT) {
if (xmppConnectionService != null && mAccount != null) {
xmppConnectionService.reconnectAccountInBackground(mAccount);
} else {
mPendingReconnect.set(true);
}
}
}
@Override
@ -781,11 +773,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
}
if (mAccount != null) {
if (mPendingReconnect.compareAndSet(true, false)) {
xmppConnectionService.reconnectAccountInBackground(mAccount);
}
this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER);
this.mUsernameMode |= mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) && mAccount.isOptionSet(Account.OPTION_REGISTER);
if (mPendingFingerprintVerificationUri != null) {

View File

@ -677,18 +677,22 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
this.binding.endCall.setVisibility(View.INVISIBLE);
this.binding.acceptCall.setVisibility(View.INVISIBLE);
} else if (state == RtpEndUserState.INCOMING_CALL) {
this.binding.rejectCall.setContentDescription(getString(R.string.dismiss_call));
this.binding.rejectCall.setOnClickListener(this::rejectCall);
this.binding.rejectCall.setImageResource(R.drawable.ic_call_end_white_48dp);
this.binding.rejectCall.setVisibility(View.VISIBLE);
this.binding.endCall.setVisibility(View.INVISIBLE);
this.binding.acceptCall.setContentDescription(getString(R.string.answer_call));
this.binding.acceptCall.setOnClickListener(this::acceptCall);
this.binding.acceptCall.setImageResource(R.drawable.ic_call_white_48dp);
this.binding.acceptCall.setVisibility(View.VISIBLE);
} else if (state == RtpEndUserState.DECLINED_OR_BUSY) {
this.binding.rejectCall.setContentDescription(getString(R.string.exit));
this.binding.rejectCall.setOnClickListener(this::exit);
this.binding.rejectCall.setImageResource(R.drawable.ic_clear_white_48dp);
this.binding.rejectCall.setVisibility(View.VISIBLE);
this.binding.endCall.setVisibility(View.INVISIBLE);
this.binding.acceptCall.setContentDescription(getString(R.string.record_voice_mail));
this.binding.acceptCall.setOnClickListener(this::recordVoiceMail);
this.binding.acceptCall.setImageResource(R.drawable.ic_voicemail_white_24dp);
this.binding.acceptCall.setVisibility(View.VISIBLE);
@ -698,15 +702,18 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
RtpEndUserState.APPLICATION_ERROR,
RtpEndUserState.RETRACTED
).contains(state)) {
this.binding.rejectCall.setContentDescription(getString(R.string.exit));
this.binding.rejectCall.setOnClickListener(this::exit);
this.binding.rejectCall.setImageResource(R.drawable.ic_clear_white_48dp);
this.binding.rejectCall.setVisibility(View.VISIBLE);
this.binding.endCall.setVisibility(View.INVISIBLE);
this.binding.acceptCall.setContentDescription(getString(R.string.try_again));
this.binding.acceptCall.setOnClickListener(this::retry);
this.binding.acceptCall.setImageResource(R.drawable.ic_replay_white_48dp);
this.binding.acceptCall.setVisibility(View.VISIBLE);
} else {
this.binding.rejectCall.setVisibility(View.INVISIBLE);
this.binding.endCall.setContentDescription(getString(R.string.hang_up));
this.binding.endCall.setOnClickListener(this::endCall);
this.binding.endCall.setImageResource(R.drawable.ic_call_end_white_48dp);
this.binding.endCall.setVisibility(View.VISIBLE);

View File

@ -29,6 +29,7 @@
package eu.siacs.conversations.ui;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
@ -42,6 +43,8 @@ import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import com.google.common.base.Strings;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@ -70,17 +73,21 @@ import static eu.siacs.conversations.ui.util.SoftKeyboardUtils.showKeyboard;
public class SearchActivity extends XmppActivity implements TextWatcher, OnSearchResultsAvailable, MessageAdapter.OnContactPictureClicked {
private static final String EXTRA_SEARCH_TERM = "search-term";
public static final String EXTRA_CONVERSATION_UUID = "uuid";
private ActivitySearchBinding binding;
private MessageAdapter messageListAdapter;
private final List<Message> messages = new ArrayList<>();
private WeakReference<Message> selectedMessageReference = new WeakReference<>(null);
private String uuid;
private final ChangeWatcher<List<String>> currentSearch = new ChangeWatcher<>();
private final PendingItem<String> pendingSearchTerm = new PendingItem<>();
private final PendingItem<List<String>> pendingSearch = new PendingItem<>();
@Override
public void onCreate(final Bundle bundle) {
final Intent intent = getIntent();
this.uuid = intent == null ? null : Strings.emptyToNull(intent.getStringExtra(EXTRA_CONVERSATION_UUID));
final String searchTerm = bundle == null ? null : bundle.getString(EXTRA_SEARCH_TERM);
if (searchTerm != null) {
pendingSearchTerm.push(searchTerm);
@ -103,10 +110,10 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc
final String term = pendingSearchTerm.pop();
if (term != null) {
searchField.append(term);
List<String> searchTerm = FtsUtils.parse(term);
final List<String> searchTerm = FtsUtils.parse(term);
if (xmppConnectionService != null) {
if (currentSearch.watch(searchTerm)) {
xmppConnectionService.search(searchTerm, this);
xmppConnectionService.search(searchTerm, uuid, this);
}
} else {
pendingSearch.push(searchTerm);
@ -114,6 +121,7 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc
}
searchField.addTextChangedListener(this);
searchField.setHint(R.string.search_messages);
searchField.setContentDescription(getString(R.string.search_messages));
searchField.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
if (term == null) {
showKeyboard(searchField);
@ -206,7 +214,7 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc
void onBackendConnected() {
final List<String> searchTerm = pendingSearch.pop();
if (searchTerm != null && currentSearch.watch(searchTerm)) {
xmppConnectionService.search(searchTerm, this);
xmppConnectionService.search(searchTerm, uuid,this);
}
}
@ -239,7 +247,7 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc
return;
}
if (term.size() > 0) {
xmppConnectionService.search(term, this);
xmppConnectionService.search(term, uuid,this);
} else {
MessageSearchTask.cancelRunningTasks();
this.messages.clear();

View File

@ -621,8 +621,10 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
}
if (binding.startConversationViewPager.getCurrentItem() == 0) {
mSearchEditText.setHint(R.string.search_contacts);
mSearchEditText.setContentDescription(getString(R.string.search_contacts));
} else {
mSearchEditText.setHint(R.string.search_bookmarks);
mSearchEditText.setContentDescription(getString(R.string.search_bookmarks));
}
}

View File

@ -112,17 +112,21 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
}
viewHolder.playPause.setAlpha(viewHolder.darkBackground ? 0.7f : 0.57f);
viewHolder.playPause.setOnClickListener(this);
final Context context = viewHolder.playPause.getContext();
if (message == currentlyPlayingMessage) {
if (AudioPlayer.player != null && AudioPlayer.player.isPlaying()) {
viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp);
viewHolder.playPause.setContentDescription(context.getString(R.string.pause_audio));
viewHolder.progress.setEnabled(true);
} else {
viewHolder.playPause.setContentDescription(context.getString(R.string.play_audio));
viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp);
viewHolder.progress.setEnabled(false);
}
return true;
} else {
viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp);
viewHolder.playPause.setContentDescription(context.getString(R.string.play_audio));
viewHolder.runtime.setText(formatTime(message.getFileParams().runtime));
viewHolder.progress.setProgress(0);
viewHolder.progress.setEnabled(false);
@ -156,7 +160,8 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
}
}
private boolean playPauseCurrent(ViewHolder viewHolder) {
private boolean playPauseCurrent(final ViewHolder viewHolder) {
final Context context = viewHolder.playPause.getContext();
viewHolder.playPause.setAlpha(viewHolder.darkBackground ? 0.7f : 0.57f);
if (player.isPlaying()) {
viewHolder.progress.setEnabled(false);
@ -164,6 +169,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
messageAdapter.flagScreenOff();
releaseProximityWakeLock();
viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp);
viewHolder.playPause.setContentDescription(context.getString(R.string.play_audio));
} else {
viewHolder.progress.setEnabled(true);
player.start();
@ -171,6 +177,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
acquireProximityWakeLock();
this.stopRefresher(true);
viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp);
viewHolder.playPause.setContentDescription(context.getString(R.string.pause_audio));
}
return false;
}
@ -194,6 +201,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
acquireProximityWakeLock();
viewHolder.progress.setEnabled(true);
viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp);
viewHolder.playPause.setContentDescription(viewHolder.playPause.getContext().getString(R.string.pause_audio));
sensorManager.registerListener(this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
return true;
} catch (Exception e) {
@ -248,6 +256,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
}
final ViewHolder viewHolder = ViewHolder.get(audioPlayer);
final Message message = (Message) audioPlayer.getTag();
viewHolder.playPause.setContentDescription(viewHolder.playPause.getContext().getString(R.string.play_audio));
viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp);
if (message != null) {
viewHolder.runtime.setText(formatTime(message.getFileParams().runtime));

View File

@ -1,5 +1,6 @@
package eu.siacs.conversations.ui.util;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
@ -11,11 +12,10 @@ import android.widget.ImageView;
import java.lang.ref.WeakReference;
import java.util.concurrent.RejectedExecutionException;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.AvatarService;
import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.ui.adapter.AccountAdapter;
import eu.siacs.conversations.utils.UIHelper;
public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
@ -80,6 +80,7 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void,
return;
}
final Bitmap bm = activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), true);
setContentDescription(avatarable, imageView);
if (bm != null) {
cancelPotentialWork(avatarable, imageView);
imageView.setImageBitmap(bm);
@ -98,6 +99,15 @@ public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void,
}
}
private static void setContentDescription(final AvatarService.Avatarable avatarable, final ImageView imageView) {
final Context context = imageView.getContext();
if (avatarable instanceof Account) {
imageView.setContentDescription(context.getString(R.string.your_avatar));
} else {
imageView.setContentDescription(context.getString(R.string.avatar_for_x, avatarable.getAvatarName()));
}
}
static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<AvatarWorkerTask> avatarWorkerTaskReference;

View File

@ -112,16 +112,16 @@ public class ConversationMenuConfigurator {
none.setVisible(Config.supportUnencrypted() || conversation.getMode() == Conversation.MODE_MULTI);
axolotl.setVisible(Config.supportOmemo());
switch (conversation.getNextEncryption()) {
case Message.ENCRYPTION_NONE:
none.setChecked(true);
break;
case Message.ENCRYPTION_PGP:
menuSecure.setTitle(R.string.encrypted_with_openpgp);
pgp.setChecked(true);
break;
case Message.ENCRYPTION_AXOLOTL:
menuSecure.setTitle(R.string.encrypted_with_omemo);
axolotl.setChecked(true);
break;
default:
menuSecure.setTitle(R.string.not_encrypted);
none.setChecked(true);
break;
}

View File

@ -129,7 +129,7 @@ public class StylingHelper {
int start = indexOfIgnoreCase(string, needle, 0);
while (start != -1) {
int end = start + length;
editable.setSpan(new BackgroundColorSpan(ContextCompat.getColor(context, dark ? R.color.blue_a100 : R.color.blue_a200)), start, end, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
editable.setSpan(new BackgroundColorSpan(ContextCompat.getColor(context, dark ? R.color.blue_a100 : R.color.blue_a400)), start, end, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
editable.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, dark ? R.color.black87 : R.color.white)), start, end, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
start = indexOfIgnoreCase(string, needle, start + length);
}

View File

@ -16,6 +16,12 @@ public class TorServiceUtils {
private static final Uri ORBOT_PLAYSTORE_URI = Uri.parse("market://details?id=" + URI_ORBOT);
private final static String ACTION_START_TOR = "org.torproject.android.START_TOR";
public static final Intent INSTALL_INTENT = new Intent(Intent.ACTION_VIEW, ORBOT_PLAYSTORE_URI);
public static final Intent LAUNCH_INTENT = new Intent(ACTION_START_TOR);
public final static String ACTION_STATUS = "org.torproject.android.intent.action.STATUS";
public final static String EXTRA_STATUS = "org.torproject.android.intent.extra.STATUS";
public static boolean isOrbotInstalled(Context context) {
try {
context.getPackageManager().getPackageInfo(URI_ORBOT, PackageManager.GET_ACTIVITIES);
@ -27,17 +33,14 @@ public class TorServiceUtils {
public static void downloadOrbot(Activity activity, int requestCode) {
final Intent intent = new Intent(Intent.ACTION_VIEW, ORBOT_PLAYSTORE_URI);
try {
activity.startActivityForResult(intent, requestCode);
activity.startActivityForResult(INSTALL_INTENT, requestCode);
} catch (ActivityNotFoundException e) {
ToastCompat.makeText(activity, R.string.no_market_app_installed, ToastCompat.LENGTH_SHORT).show();
}
}
public static void startOrbot(Activity activity, int requestCode) {
final Intent launchIntent = new Intent(URI_ORBOT);
launchIntent.setAction(ACTION_START_TOR);
activity.startActivityForResult(launchIntent, requestCode);
activity.startActivityForResult(LAUNCH_INTENT, requestCode);
}
}

View File

@ -14,6 +14,7 @@ import com.google.common.collect.ImmutableSet;
import java.lang.ref.WeakReference;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -90,7 +91,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
final AbstractJingleConnection connection;
if (FileTransferDescription.NAMESPACES.contains(descriptionNamespace)) {
connection = new JingleFileTransferConnection(this, id, from);
} else if (Namespace.JINGLE_APPS_RTP.equals(descriptionNamespace) && !usesTor(account)) {
} else if (Namespace.JINGLE_APPS_RTP.equals(descriptionNamespace) && isUsingClearNet(account)) {
final boolean sessionEnded = this.terminatedSessions.asMap().containsKey(PersistableSessionId.of(id));
final boolean stranger = isWithStrangerAndStrangerNotificationsAreOff(account, id.with);
if (isBusy() || sessionEnded || stranger) {
@ -116,11 +117,14 @@ public class JingleConnectionManager extends AbstractConnectionManager {
}
}
private boolean usesTor(final Account account) {
return account.isOnion() || mXmppConnectionService.useTorToConnect();
private boolean isUsingClearNet(final Account account) {
return !account.isOnion() && !mXmppConnectionService.useTorToConnect();
}
public boolean isBusy() {
if (mXmppConnectionService.isPhoneInCall()) {
return true;
}
for (AbstractJingleConnection connection : this.connections.values()) {
if (connection instanceof JingleRtpConnection) {
if (((JingleRtpConnection) connection).isTerminated()) {
@ -134,6 +138,18 @@ public class JingleConnectionManager extends AbstractConnectionManager {
}
}
public void notifyPhoneCallStarted() {
for (AbstractJingleConnection connection : connections.values()) {
if (connection instanceof JingleRtpConnection) {
final JingleRtpConnection rtpConnection = (JingleRtpConnection) connection;
if (rtpConnection.isTerminated()) {
continue;
}
rtpConnection.notifyPhoneCall();
}
}
}
private Optional<RtpSessionProposal> findMatchingSessionProposal(final Account account, final Jid with, final Set<Media> media) {
synchronized (this.rtpSessionProposals) {
for (Map.Entry<RtpSessionProposal, DeviceDiscoveryState> entry : this.rtpSessionProposals.entrySet()) {
@ -257,7 +273,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
Collections2.filter(descriptions, d -> d instanceof RtpDescription),
input -> (RtpDescription) input
);
if (rtpDescriptions.size() > 0 && rtpDescriptions.size() == descriptions.size() && !usesTor(account)) {
if (rtpDescriptions.size() > 0 && rtpDescriptions.size() == descriptions.size() && isUsingClearNet(account)) {
final Collection<Media> media = Collections2.transform(rtpDescriptions, RtpDescription::getMedia);
if (media.contains(Media.UNKNOWN)) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": encountered unknown media in session proposal. " + propose);

View File

@ -371,8 +371,6 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
if (transition(State.SESSION_ACCEPTED)) {
respondOk(jinglePacket);
receiveSessionAccept(contentMap);
final List<String> identificationTags = contentMap.group == null ? contentMap.getNames() : contentMap.group.getIdentificationTags();
processCandidates(identificationTags, contentMap.contents.entrySet());
} else {
Log.d(Config.LOGTAG, String.format("%s: received session-accept while in state %s", id.account.getJid().asBareJid(), state));
respondOk(jinglePacket);
@ -390,7 +388,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
sendSessionTerminate(Reason.FAILED_APPLICATION, e.getMessage());
return;
}
org.webrtc.SessionDescription answer = new org.webrtc.SessionDescription(
final org.webrtc.SessionDescription answer = new org.webrtc.SessionDescription(
org.webrtc.SessionDescription.Type.ANSWER,
sessionDescription.toString()
);
@ -400,7 +398,10 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": unable to set remote description after receiving session-accept", Throwables.getRootCause(e));
webRTCWrapper.close();
sendSessionTerminate(Reason.FAILED_APPLICATION);
return;
}
final List<String> identificationTags = contentMap.group == null ? contentMap.getNames() : contentMap.group.getIdentificationTags();
processCandidates(identificationTags, contentMap.contents.entrySet());
}
private void sendSessionAccept() {
@ -900,6 +901,16 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
}
}
public void notifyPhoneCall() {
Log.d(Config.LOGTAG, "a phone call has just been started. killing jingle rtp connections");
if (Arrays.asList(State.PROPOSED, State.SESSION_INITIALIZED).contains(this.state)) {
rejectCall();
} else {
endCall();
}
}
public synchronized void rejectCall() {
if (isTerminated()) {
Log.w(Config.LOGTAG, id.account.getJid().asBareJid() + ": received rejectCall() when session has already been terminated. nothing to do");

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 814 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -50,6 +50,7 @@
app:sdMainFabClosedBackgroundColor="?colorPrimary"
app:sdMainFabOpenedBackgroundColor="?colorPrimaryDark"
app:sdUseReverseAnimationOnClose="true"
android:contentDescription="@string/add_contact_or_create_or_join_group_chat"
app:sdOverlayLayout="@id/overlay"/>
</RelativeLayout>
</layout>

View File

@ -37,7 +37,9 @@
android:orientation="vertical"
android:padding="2dp">
<include layout="@layout/message_content"/>
<include
android:id="@+id/message_content"
layout="@layout/message_content"/>
<LinearLayout
android:layout_width="wrap_content"
@ -82,6 +84,8 @@
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:text="@string/sending"
android:accessibilityTraversalAfter="@id/message_photo"
android:accessibilityTraversalBefore="@id/message_content"
android:textAppearance="@style/TextAppearance.Conversations.Caption"/>
</LinearLayout>
</LinearLayout>

View File

@ -51,7 +51,9 @@
android:orientation="vertical"
android:padding="2dp">
<include layout="@layout/message_content" />
<include
android:id="@+id/message_content"
layout="@layout/message_content" />
<LinearLayout
android:layout_width="wrap_content"
@ -67,6 +69,8 @@
android:layout_gravity="center_vertical"
android:layout_marginEnd="4sp"
android:layout_marginRight="4sp"
android:accessibilityTraversalAfter="@id/message_photo"
android:accessibilityTraversalBefore="@id/message_content"
android:gravity="center_vertical"
android:text="@string/sending"
android:textAppearance="@style/TextAppearance.Conversations.Caption" />

View File

@ -1,26 +1,25 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:icon="?attr/icon_search"
android:orderInCategory="5"
android:title="@string/search_messages"
android:visible="@bool/show_combined_search_options"
app:showAsAction="always">
<menu>
<item
android:id="@+id/action_search_all_conversations"
android:title="@string/search_all_conversations" />
<item
android:id="@+id/action_search_this_conversation"
android:title="@string/search_this_conversation" />
</menu>
</item>
<item
android:id="@+id/action_scan_qr_code"
android:title="@string/scan_qr_code"
app:showAsAction="always"
android:icon="?attr/icon_scan_qr_code"
android:orderInCategory="10"
android:title="@string/scan_qr_code"
android:visible="@bool/show_qr_code_scan"
android:icon="?attr/icon_scan_qr_code"/>
<item
android:id="@+id/action_accounts"
android:orderInCategory="90"
android:title="@string/action_accounts"
app:showAsAction="never"/>
<item
android:id="@+id/action_account"
android:orderInCategory="90"
android:title="@string/action_account"
app:showAsAction="never"/>
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never"/>
app:showAsAction="always" />
</menu>

View File

@ -28,7 +28,7 @@
android:id="@+id/action_security"
android:icon="?attr/icon_not_secure"
android:orderInCategory="20"
android:title="@string/action_secure"
android:title="@string/encrypted_with_omemo"
app:showAsAction="always">
<menu>
<group android:checkableBehavior="single">
@ -99,6 +99,12 @@
android:orderInCategory="45"
android:title="@string/invite_contact"
app:showAsAction="never" />
<item
android:id="@+id/action_search"
android:orderInCategory="48"
android:title="@string/search_messages"
android:visible="@bool/show_individual_search_options"
app:showAsAction="never" />
<item
android:id="@+id/action_clear_history"
android:orderInCategory="50"
@ -110,20 +116,27 @@
android:title="@string/action_end_conversation"
app:showAsAction="never" />
<item
android:id="@+id/action_mute"
android:orderInCategory="70"
android:title="@string/disable_notifications"
app:showAsAction="never" />
android:title="@string/more_options">
<menu>
<item
android:id="@+id/action_mute"
android:orderInCategory="71"
android:title="@string/disable_notifications"
app:showAsAction="never" />
<item
android:id="@+id/action_unmute"
android:orderInCategory="72"
android:title="@string/enable_notifications"
app:showAsAction="never" />
<item
android:id="@+id/action_toggle_pinned"
android:orderInCategory="73"
android:title="@string/add_to_favorites"
app:showAsAction="never" />
</menu>
</item>
<item
android:id="@+id/action_unmute"
android:orderInCategory="71"
android:title="@string/enable_notifications"
app:showAsAction="never" />
<item
android:id="@+id/action_toggle_pinned"
android:orderInCategory="72"
android:title="@string/add_to_favorites"
app:showAsAction="never"/>
</menu>

View File

@ -28,10 +28,26 @@
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_search"
android:orderInCategory="10"
android:title="@string/search_messages"
android:orderInCategory="50"
app:showAsAction="never"/>
android:visible="@bool/show_individual_search_options"
app:showAsAction="never" />
<item
android:id="@+id/action_accounts"
android:orderInCategory="90"
android:title="@string/action_accounts"
app:showAsAction="never" />
<item
android:id="@+id/action_account"
android:orderInCategory="90"
android:title="@string/action_account"
app:showAsAction="never" />
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>

View File

@ -4,11 +4,9 @@
<string name="action_add">محادثة جديدة</string>
<string name="action_accounts">إدارة الحسابات</string>
<string name="action_account">إدارة الحساب</string>
<string name="action_end_conversation">أغلق هذه المحادثة</string>
<string name="action_contact_details">بيانات جهة الإتصال</string>
<string name="action_muc_details">تفاصيل مجموعة المحادثة</string>
<string name="channel_details">تفاصيل القناة</string>
<string name="action_secure">تشفير المحادثة</string>
<string name="action_add_account">إضافة حساب</string>
<string name="action_edit_contact">تعديل الإسم</string>
<string name="action_add_phone_book">أضف إلى دفتر العناوين</string>

View File

@ -4,11 +4,9 @@
<string name="action_add">Нов разговор</string>
<string name="action_accounts">Управление на профилите</string>
<string name="action_account">Управление на профила</string>
<string name="action_end_conversation">Затваряне на този разговор</string>
<string name="action_contact_details">Подробности за контакта</string>
<string name="action_muc_details">Подробности за груповия разговор</string>
<string name="channel_details">Подробности за канала</string>
<string name="action_secure">Защитен разговор</string>
<string name="action_add_account">Добавяне на профил</string>
<string name="action_edit_contact">Редактиране на името</string>
<string name="action_add_phone_book">Добавяне към адресния указател</string>

View File

@ -4,10 +4,8 @@
<string name="action_add">Nova conversa</string>
<string name="action_accounts">Gestiona els comptes</string>
<string name="action_account">Administrar compte</string>
<string name="action_end_conversation">Tancar aquesta conversa</string>
<string name="action_contact_details">Detalls del contacte</string>
<string name="action_muc_details">Detalls del xat de grup</string>
<string name="action_secure">Conversa segura</string>
<string name="action_add_account">Afegeix un compte</string>
<string name="action_edit_contact">Edita el nom</string>
<string name="action_add_phone_book">Afegeix a la llibreta d\'adreces</string>

View File

@ -4,9 +4,7 @@
<string name="action_add">Nová konverzace</string>
<string name="action_accounts">Nastavení účtů</string>
<string name="action_account">Nastavení účtu</string>
<string name="action_end_conversation">Zavřít tuto konverzaci</string>
<string name="action_contact_details">Detaily kontaktu</string>
<string name="action_secure">Zabezpečená konverzace</string>
<string name="action_add_account">Přidat účet</string>
<string name="action_edit_contact">Upravit jméno</string>
<string name="action_add_phone_book">Přidat do adresáře</string>

View File

@ -4,11 +4,10 @@
<string name="action_add">Neue Unterhaltung</string>
<string name="action_accounts">Konten verwalten</string>
<string name="action_account">Konto verwalten</string>
<string name="action_end_conversation">Diese Unterhaltung beenden</string>
<string name="action_end_conversation">Unterhaltung beenden</string>
<string name="action_contact_details">Kontaktdetails</string>
<string name="action_muc_details">Gruppenchatdetails</string>
<string name="channel_details">Channeldetails</string>
<string name="action_secure">Verschlüsselte Unterhaltung</string>
<string name="action_add_account">Konto hinzufügen</string>
<string name="action_edit_contact">Namen bearbeiten</string>
<string name="action_add_phone_book">Zum Telefonbuch hinzufügen</string>
@ -754,6 +753,7 @@
<string name="ongoing_calls_channel_name">Laufende Anrufe</string>
<string name="silent_messages_channel_name">Lautlose Nachrichten</string>
<string name="silent_messages_channel_description">Diese Benachrichtigungsart wird verwendet, um Benachrichtigungen anzuzeigen, die keinen Ton auslösen sollen. Zum Beispiel, wenn du auf einem anderen Gerät aktiv bist (Schonfrist).</string>
<string name="delivery_failed_channel_name">Fehlgeschlagene Zustellungen</string>
<string name="pref_message_notification_settings">Benachrichtigungseinstellungen</string>
<string name="pref_incoming_call_notification_settings">Anrufeinstellungen</string>
<string name="pref_more_notification_settings_summary">Wichtigkeit, Klang, Vibrationen</string>
@ -921,12 +921,30 @@
<string name="only_one_call_at_a_time">Du kannst immer nur einen Anruf zur gleichen Zeit machen.</string>
<string name="return_to_ongoing_call">Zurück zum laufenden Aufruf</string>
<string name="could_not_switch_camera">Kamera konnte nicht gewechselt werden</string>
<string name="add_to_favorites">Zu Favoriten hinzufügen</string>
<string name="remove_from_favorites">Von Favoriten entfernen</string>
<string name="add_to_favorites">Oben anheften</string>
<string name="remove_from_favorites">Von oben ablösen</string>
<string name="gpx_track">GPX-Strecke</string>
<string name="could_not_correct_message">Nachricht konnte nicht korrigiert werden</string>
<string name="search_all_conversations">Alle Unterhaltungen</string>
<string name="search_this_conversation">Diese Unterhaltung</string>
<string name="your_avatar">Dein Avatar</string>
<string name="avatar_for_x">Avatar für %s</string>
<string name="encrypted_with_omemo">Verschlüsselt mit OMEMO</string>
<string name="encrypted_with_openpgp">Verschlüsselt mit OpenPGP</string>
<string name="not_encrypted">Nicht verschlüsselt</string>
<string name="exit">Beenden</string>
<string name="record_voice_mail">Sprachnachricht aufzeichnen</string>
<string name="play_audio">Audio abspielen</string>
<string name="pause_audio">Audio anhalten</string>
<string name="add_contact_or_create_or_join_group_chat">Kontakt hinzufügen, Gruppenchat erstellen oder beitreten oder Channels entdecken</string>
<plurals name="view_users">
<item quantity="one">%1$d Teilnehmer anzeigen</item>
<item quantity="other">%1$d Teilnehmer anzeigen</item>
</plurals>
<plurals name="some_messages_could_not_be_delivered">
<item quantity="one">Eine Nachricht konnte nicht zugestellt werden</item>
<item quantity="other">Einige Nachrichten konnten nicht zugestellt werden</item>
</plurals>
<string name="failed_deliveries">Fehlgeschlagene Zustellungen</string>
<string name="more_options">Weitere Optionen</string>
</resources>

View File

@ -4,11 +4,9 @@
<string name="action_add">Νέα συζήτηση</string>
<string name="action_accounts">Διαχείριση λογαριασμών</string>
<string name="action_account">Διαχείριση λογαριασμού</string>
<string name="action_end_conversation">Κλείσιμο συζήτησης</string>
<string name="action_contact_details">Λεπτομέρειες επαφής</string>
<string name="action_muc_details">Λεπτομέρειες ομαδικής συζήτησης</string>
<string name="channel_details">Λεπτομέρειες καναλιού</string>
<string name="action_secure">Ασφαλής συζήτηση</string>
<string name="action_add_account">Προσθήκη λογαριασμού</string>
<string name="action_edit_contact">Επεξεργασία ονόματος</string>
<string name="action_add_phone_book">Προσθήκη στην ατζέντα</string>

View File

@ -4,11 +4,10 @@
<string name="action_add">Nueva conversación</string>
<string name="action_accounts">Gestionar cuentas</string>
<string name="action_account">Gestionar cuenta</string>
<string name="action_end_conversation">Cerrar esta conversación</string>
<string name="action_end_conversation">Cerrar conversación</string>
<string name="action_contact_details">Detalles del contacto</string>
<string name="action_muc_details">Detalles de conversación</string>
<string name="channel_details">Detalles del canal</string>
<string name="action_secure">Conversación segura</string>
<string name="action_add_account">Añadir cuenta</string>
<string name="action_edit_contact">Editar contacto</string>
<string name="action_add_phone_book">Añadir a contactos</string>
@ -921,10 +920,20 @@
<string name="only_one_call_at_a_time">Solo puedes hacer una llamada a la vez</string>
<string name="return_to_ongoing_call">Volver a la llamada en curso</string>
<string name="could_not_switch_camera">No se ha podido cambiar de cámara</string>
<string name="add_to_favorites">Añadir a los favoritos</string>
<string name="remove_from_favorites">Eliminar de favoritos</string>
<string name="gpx_track">Recorrido GPX</string>
<string name="could_not_correct_message">No se pudo corregir el mensaje</string>
<string name="search_all_conversations">Todas las conversaciones</string>
<string name="search_this_conversation">Esta conversación</string>
<string name="your_avatar">Tu imagen de perfil</string>
<string name="avatar_for_x">Imagen de perfil de %s</string>
<string name="encrypted_with_omemo">Encriptado con OMEMO</string>
<string name="encrypted_with_openpgp">Encriptado con OpenPGP</string>
<string name="not_encrypted">Sin encriptar</string>
<string name="exit">Salir</string>
<string name="record_voice_mail">Grabar mensaje de voz</string>
<string name="play_audio">Reproducir audio</string>
<string name="pause_audio">Pausar audio</string>
<string name="add_contact_or_create_or_join_group_chat">Añadir contacto, crear o unirse a un grupo de chat, o descubrir canales</string>
<plurals name="view_users">
<item quantity="one">Ver %1$d Participante</item>
<item quantity="other">Ver %1$d Participantes</item>

View File

@ -4,11 +4,9 @@
<string name="action_add">Elkarrizketa berria</string>
<string name="action_accounts">Kontuak kudeatu</string>
<string name="action_account">Kontua kudeatu</string>
<string name="action_end_conversation">Elkarrizketa hau itxi</string>
<string name="action_contact_details">Kontaktuaren xehetasunak</string>
<string name="action_muc_details">Taldearen xehetasunak</string>
<string name="channel_details">Kanalaren xehetasunak</string>
<string name="action_secure">Elkarrizketa segurua</string>
<string name="action_add_account">Kontua gehitu</string>
<string name="action_edit_contact">Izena editatu</string>
<string name="action_add_phone_book">Helbideen liburura gehitu</string>

View File

@ -5,7 +5,6 @@
<string name="action_accounts">مدیریت حساب های کاربری</string>
<string name="action_contact_details">جزییات مخاطب</string>
<string name="action_muc_details">جزئیات چت گروهی</string>
<string name="action_secure">مکالمه امن</string>
<string name="action_add_account">اضافه کردن حساب کاربری</string>
<string name="action_edit_contact">تغییر نام</string>
<string name="action_add_phone_book">اضافه کردن به لیست ادرس ها</string>

View File

@ -4,11 +4,9 @@
<string name="action_add">Nouvelle conversation</string>
<string name="action_accounts">Gérer les comptes</string>
<string name="action_account">Gérer le compte</string>
<string name="action_end_conversation">Fermer cette conversation</string>
<string name="action_contact_details">Détails du contact</string>
<string name="action_muc_details">Détails du groupe</string>
<string name="channel_details">Détails du canal</string>
<string name="action_secure">Conversation sécurisée</string>
<string name="action_add_account">Ajouter un compte</string>
<string name="action_edit_contact">Modifier le nom</string>
<string name="action_add_phone_book">Ajouter au carnet d\'adresses</string>
@ -913,8 +911,6 @@
<string name="only_one_call_at_a_time">Vous ne pouvez prendre qu\'un appel à la fois.</string>
<string name="return_to_ongoing_call">Reprendre l\'appel en cours</string>
<string name="could_not_switch_camera">Impossible de changer de caméra</string>
<string name="add_to_favorites">Ajouter aux favoris</string>
<string name="remove_from_favorites">Enlever des favoris</string>
<plurals name="view_users">
<item quantity="one">Voir %1$d participant</item>
<item quantity="other">Voir %1$d participants</item>

View File

@ -4,11 +4,10 @@
<string name="action_add">Nova conversa</string>
<string name="action_accounts">Xestionar contas</string>
<string name="action_account">Xestionar conta</string>
<string name="action_end_conversation">Pechar esta conversa</string>
<string name="action_end_conversation">Pechar conversa</string>
<string name="action_contact_details">Detalles do contacto</string>
<string name="action_muc_details">Detalles da conversa de grupo</string>
<string name="channel_details">Detalles do canal</string>
<string name="action_secure">Conversa segura</string>
<string name="action_add_account">Engadir conta</string>
<string name="action_edit_contact">Editar contacto</string>
<string name="action_add_phone_book">Engadir a libreta de enderezos</string>
@ -754,6 +753,7 @@
<string name="ongoing_calls_channel_name">Chamadas realizadas</string>
<string name="silent_messages_channel_name">Mensaxes acalados</string>
<string name="silent_messages_channel_description">Este grupo de notificacións é utilizado para mostrar notificacións que non debería activar ningún son. Por exemplo, cando está activo en outro dispositivo (Período de Graza).</string>
<string name="delivery_failed_channel_name">Entregas fallidas</string>
<string name="pref_message_notification_settings">Axustes de notificación das mensaxes</string>
<string name="pref_incoming_call_notification_settings">Axustes da notificación de chamadas</string>
<string name="pref_more_notification_settings_summary">Importancia, Son, Vibrar</string>
@ -921,12 +921,30 @@
<string name="only_one_call_at_a_time">Só podes manter unha chamada en cada momento.</string>
<string name="return_to_ongoing_call">Voltar á chamada activa</string>
<string name="could_not_switch_camera">Non se puido activar a cámara</string>
<string name="add_to_favorites">Engadir a favoritas</string>
<string name="remove_from_favorites">Eliminar das favoritas</string>
<string name="add_to_favorites">Fixar enriba</string>
<string name="remove_from_favorites">Desafixar de enriba</string>
<string name="gpx_track">Ruta GPX</string>
<string name="could_not_correct_message">No se pode correxir a mensaxe</string>
<string name="search_all_conversations">Todas as conversas</string>
<string name="search_this_conversation">Esta conversa</string>
<string name="your_avatar">O teu avatar</string>
<string name="avatar_for_x">Avatar para %s</string>
<string name="encrypted_with_omemo">Cifrado con OMEMO</string>
<string name="encrypted_with_openpgp">Cifrado con OpenPGP</string>
<string name="not_encrypted">Sen cifrar</string>
<string name="exit">Saír</string>
<string name="record_voice_mail">Gravar correo de voz</string>
<string name="play_audio">Reproducir audio</string>
<string name="pause_audio">Pausar audio</string>
<string name="add_contact_or_create_or_join_group_chat">Engade un contacto, crea o únete a unha conversa en grupo ou descubre canles.</string>
<plurals name="view_users">
<item quantity="one">Ver %1$d Participante</item>
<item quantity="other">Ver %1$d Participantes</item>
</plurals>
<plurals name="some_messages_could_not_be_delivered">
<item quantity="one">Unha mensaxe non se entregou</item>
<item quantity="other">Algunhas mensaxes non se entregaron</item>
</plurals>
<string name="failed_deliveries">Entregas fallidas</string>
<string name="more_options">Máis opcións</string>
</resources>

View File

@ -4,11 +4,9 @@
<string name="action_add">Új beszélgetés</string>
<string name="action_accounts">Fiókok kezelése</string>
<string name="action_account">Fiók kezelése</string>
<string name="action_end_conversation">Beszélgetés bezárása</string>
<string name="action_contact_details">Partner részletei</string>
<string name="action_muc_details">Csoportos csevegés részletei</string>
<string name="channel_details">Csatorna részletei</string>
<string name="action_secure">Biztonságos beszélgetés</string>
<string name="action_add_account">Fiók hozzáadása</string>
<string name="action_edit_contact">Név szerkesztése</string>
<string name="action_add_phone_book">Hozzáadás a címjegyzékhez</string>
@ -883,8 +881,6 @@
<string name="only_one_call_at_a_time">Egyszerre csak egy hívásban vehet részt.</string>
<string name="return_to_ongoing_call">Visszatérés a kimenő híváshoz</string>
<string name="could_not_switch_camera">Nem sikerült átváltani a kamerát</string>
<string name="add_to_favorites">Hozzáadás a kedvencekhez</string>
<string name="remove_from_favorites">Eltávolítás a kedvencekből</string>
<plurals name="view_users">
<item quantity="one">%1$d résztvevő megtekintése</item>
<item quantity="other">%1$d résztvevő megtekintése</item>

View File

@ -4,7 +4,6 @@
<string name="action_add">Percakapan Baru</string>
<string name="action_accounts">Pengaturan Akun</string>
<string name="action_contact_details">Detil Kontak</string>
<string name="action_secure">Amankan Percakapan</string>
<string name="action_add_account">Tambah Akun</string>
<string name="action_edit_contact">Ubah Nama</string>
<string name="action_add_phone_book">Tambahkan ke daftar kontak</string>

View File

@ -4,11 +4,9 @@
<string name="action_add">Nuova conversazione</string>
<string name="action_accounts">Gestisci account</string>
<string name="action_account">Gestisci account</string>
<string name="action_end_conversation">Chiudi questa conversazione</string>
<string name="action_contact_details">Dettagli del contatto</string>
<string name="action_muc_details">Dettagli chat di gruppo</string>
<string name="channel_details">Dettagli canale</string>
<string name="action_secure">Conversazione sicura</string>
<string name="action_add_account">Aggiungi account</string>
<string name="action_edit_contact">Modifica il nome</string>
<string name="action_add_phone_book">Aggiungi alla rubrica</string>
@ -461,7 +459,11 @@
<string name="server_info_broken">Rotto</string>
<string name="pref_presence_settings">Disponibilità</string>
<string name="pref_away_when_screen_off">\"Non disponibile\" a schermo spento</string>
<string name="pref_away_when_screen_off_summary">Imposta come non disponibile quando lo schermo è spento</string>
<string name="pref_dnd_on_silent_mode">\"Occupato\" in modalità silenziosa</string>
<string name="pref_dnd_on_silent_mode_summary">Imposta come occupato quando il dispositivo è in modalità silenziosa</string>
<string name="pref_treat_vibrate_as_silent">Tratta vibrazione come modalità silenziosa</string>
<string name="pref_treat_vibrate_as_dnd_summary">Imposta come occupato quando il dispositivo è in modalità vibrazione</string>
<string name="pref_show_connection_options">Impostazioni estese di connessione</string>
<string name="pref_show_connection_options_summary">Mostra nome host e impostazioni della porta quando configuri un account</string>
<string name="hostname_example">xmpp.esempio.it</string>
@ -917,8 +919,8 @@
<string name="only_one_call_at_a_time">Puoi fare solo una chiamata alla volta.</string>
<string name="return_to_ongoing_call">Torna alla chiamata in corso</string>
<string name="could_not_switch_camera">Impossibile cambiare fotocamera</string>
<string name="add_to_favorites">Aggiungi ai preferiti</string>
<string name="remove_from_favorites">Rimuovi dai preferiti</string>
<string name="gpx_track">Traccia GPX</string>
<string name="could_not_correct_message">Impossibile correggere il messaggio</string>
<plurals name="view_users">
<item quantity="one">Vedi %1$d partecipante</item>
<item quantity="other">Vedi %1$d partecipanti</item>

View File

@ -4,7 +4,6 @@
<string name="action_add">שיחה חדשה</string>
<string name="action_accounts">נהל חשבונות</string>
<string name="action_contact_details">פרטי איש קשר</string>
<string name="action_secure">דיון מאובטח</string>
<string name="action_add_account">הוסף חשבון</string>
<string name="action_edit_contact">ערוך שם</string>
<string name="action_delete_contact">מחק מרשימת אנשי הקשר</string>

View File

@ -4,11 +4,9 @@
<string name="action_add">新しい会話</string>
<string name="action_accounts">アカウントの管理</string>
<string name="action_account">アカウントの管理</string>
<string name="action_end_conversation">この会話を閉じる</string>
<string name="action_contact_details">連絡先の詳細</string>
<string name="action_muc_details">談話室の詳細</string>
<string name="channel_details">チャンネルの詳細</string>
<string name="action_secure">安全に会話</string>
<string name="action_add_account">アカウントを追加</string>
<string name="action_edit_contact">名前の編集</string>
<string name="action_add_phone_book">アドレス帳に追加</string>

View File

@ -4,7 +4,6 @@
<string name="action_add">새 대화</string>
<string name="action_accounts">계정 </string>
<string name="action_contact_details">연락처 정보</string>
<string name="action_secure">안전한 대화 </string>
<string name="action_add_account">계정 추가 </string>
<string name="action_edit_contact">이름 편집 </string>
<string name="action_add_phone_book">주소록에 추가</string>

View File

@ -5,7 +5,6 @@
<string name="action_accounts">Kontobehandling</string>
<string name="action_contact_details">Kontaktdetaljer</string>
<string name="action_muc_details">Gruppesludringsdetaljer</string>
<string name="action_secure">Sikret samtale</string>
<string name="action_add_account">Legg til samtale</string>
<string name="action_edit_contact">Rediger navn</string>
<string name="action_add_phone_book">Legg til i kontaktliste</string>

View File

@ -4,11 +4,9 @@
<string name="action_add">Nieuw gesprek</string>
<string name="action_accounts">Accounts beheren</string>
<string name="action_account">Account beheren</string>
<string name="action_end_conversation">Dit gesprek sluiten</string>
<string name="action_contact_details">Contactgegevens</string>
<string name="action_muc_details">Gespreksgegevens</string>
<string name="channel_details">Kanaalinformatie</string>
<string name="action_secure">Beveiligd gesprek</string>
<string name="action_add_account">Account toevoegen</string>
<string name="action_edit_contact">Naam veranderen</string>
<string name="action_add_phone_book">Toevoegen aan adresboek</string>

View File

@ -4,11 +4,10 @@
<string name="action_add">Nowa konwersacja</string>
<string name="action_accounts">Zarządzaj kontami</string>
<string name="action_account">Zarządzaj kontem</string>
<string name="action_end_conversation">Zamknij konwersację</string>
<string name="action_end_conversation">Zamknij rozmowę</string>
<string name="action_contact_details">Szczegóły kontaktu</string>
<string name="action_muc_details">Szczegóły konferencji</string>
<string name="channel_details">Szczegóły kanału</string>
<string name="action_secure">Konwersacja szyfrowana</string>
<string name="action_add_account">Dodaj konto</string>
<string name="action_edit_contact">Edytuj nazwę</string>
<string name="action_add_phone_book">Dodaj do kontaktów</string>
@ -401,6 +400,7 @@
<string name="mark_as_read">Oznacz jako przeczytane</string>
<string name="pref_input_options">Ustawienia wprowadzania</string>
<string name="pref_enter_is_send">Enter wysyła</string>
<string name="pref_enter_is_send_summary">Użyj klawisza Enter aby wysłać wiadomość. Możesz zawsze użyć Ctrl+Enter do wysyłania wiadomości, nawet jeśli ta opcja jest wyłączona.</string>
<string name="pref_display_enter_key">Pokaż klawisz Enter</string>
<string name="pref_display_enter_key_summary">Zamień klawisz emotikon na klawisz Enter</string>
<string name="audio">plik audio</string>
@ -424,8 +424,8 @@
<string name="no_application_found_to_display_location">Nie odnaleziono aplikacji do wyświetlenia lokalizacji</string>
<string name="location">Lokalizacja</string>
<string name="title_undo_swipe_out_conversation">Zamknięto konwersację</string>
<string name="title_undo_swipe_out_group_chat">Opuść prywatną rozmowę grupową</string>
<string name="title_undo_swipe_out_channel">Opuść publiczny kanał</string>
<string name="title_undo_swipe_out_group_chat">Opuszczono prywatną rozmowę grupową</string>
<string name="title_undo_swipe_out_channel">Opuszczono publiczny kanał</string>
<string name="pref_dont_trust_system_cas_title">Nie ufaj certyfikatom systemowym</string>
<string name="pref_dont_trust_system_cas_summary">Wymagaj ręcznego potwierdzania certyfikatów</string>
<string name="pref_remove_trusted_certificates_title">Usuń certyfikaty</string>
@ -462,7 +462,11 @@
<string name="server_info_broken">Zepsute</string>
<string name="pref_presence_settings">Dostępność</string>
<string name="pref_away_when_screen_off">Status \"Oddalony\" gdy wyświetlacz jest wyłączony</string>
<string name="pref_away_when_screen_off_summary">Pokaż jako Oddalony kiedy ekran jest wyłączony.</string>
<string name="pref_dnd_on_silent_mode">Zajęty w trybie cichym</string>
<string name="pref_dnd_on_silent_mode_summary">Pokaż jako Zajęty jeśli urządzenie jest w trybie cichym</string>
<string name="pref_treat_vibrate_as_silent">Traktuj tryb wibracji jak tryb cichy</string>
<string name="pref_treat_vibrate_as_dnd_summary">Pokaż jako Zajęty kiedy urządzenie jest w trybie wibracji</string>
<string name="pref_show_connection_options">Rozszerzone ustawienia połączenia</string>
<string name="pref_show_connection_options_summary">Pokaż nazwę hosta i ustawienia portu przy dodawaniu konta</string>
<string name="hostname_example">xmpp.example.com</string>
@ -767,6 +771,7 @@ Administrator twojego serwera będzie mógł czytać twoje wiadomości, ale moż
<string name="ongoing_calls_channel_name">Połączenia wychodzące</string>
<string name="silent_messages_channel_name">Ciche wiadomości</string>
<string name="silent_messages_channel_description">Ta kategoria powiadomień jest używana aby wyświetlać powiadomienia które nie powodują żadnych dźwięków. Na przykład w ciągu aktywności na innym urządzeniu (okres karencji).</string>
<string name="delivery_failed_channel_name">Nie dostarczone wiadomości</string>
<string name="pref_message_notification_settings">Ustawienia powiadomień wiadomości</string>
<string name="pref_incoming_call_notification_settings">Ustawienia powiadomień dla przychodzących połączeń</string>
<string name="pref_more_notification_settings_summary">Ważność, Dźwięk, Wibracja</string>
@ -929,16 +934,39 @@ Administrator twojego serwera będzie mógł czytać twoje wiadomości, ale moż
<string name="audio_call">Połączenie audio</string>
<string name="video_call">Połączenie wideo</string>
<string name="help">Pomoc</string>
<string name="switch_to_conversation">Przełącz do rozmowy</string>
<string name="microphone_unavailable">Twój mikrofon jest niedostępny</string>
<string name="only_one_call_at_a_time">Możesz mieć tylko jedno połączenie na raz.</string>
<string name="return_to_ongoing_call">Powróć do trwającego połączenia</string>
<string name="could_not_switch_camera">Nie można zmienić aparatu</string>
<string name="add_to_favorites">Dodaj do ulubionych</string>
<string name="remove_from_favorites">Usuń z ulubionych</string>
<string name="add_to_favorites">Przypnij</string>
<string name="remove_from_favorites">Odepnij</string>
<string name="gpx_track">Ścieżka GPX</string>
<string name="could_not_correct_message">Nie można poprawić wiadomości</string>
<string name="search_all_conversations">Wszystkie rozmowy</string>
<string name="search_this_conversation">Ta rozmowa</string>
<string name="your_avatar">Twój awatar</string>
<string name="avatar_for_x">Awatar dla %s</string>
<string name="encrypted_with_omemo">Zaszyfrowane OMEMO</string>
<string name="encrypted_with_openpgp">Zaszyfrowane OpenPGP</string>
<string name="not_encrypted">Niezaszyfrowane</string>
<string name="exit">Wyjście</string>
<string name="record_voice_mail">Zapisz pocztę głosową</string>
<string name="play_audio">Odtwórz audio</string>
<string name="pause_audio">Spauzuj audio</string>
<string name="add_contact_or_create_or_join_group_chat">Dodaj kontakt, stwórz lub dołącz do rozmowy grupowej lub odkryj kanały</string>
<plurals name="view_users">
<item quantity="one">Pokaż %1$d uczestnika</item>
<item quantity="few">Pokaż %1$d uczestników</item>
<item quantity="many">Pokaż %1$d uczestników</item>
<item quantity="other">Pokaż %1$d uczestników</item>
</plurals>
<plurals name="some_messages_could_not_be_delivered">
<item quantity="one">Wiadomość nie mogła zostać dostarczona</item>
<item quantity="few">Niektóre wiadomości nie mogły być dostarczone</item>
<item quantity="many">Niektóre wiadomości nie mogły być dostarczone</item>
<item quantity="other">Niektóre wiadomości nie mogły być dostarczone</item>
</plurals>
<string name="failed_deliveries">Nie dostarczone wiadomości</string>
<string name="more_options">Więcej ustawień</string>
</resources>

View File

@ -4,11 +4,9 @@
<string name="action_add">Nova conversa</string>
<string name="action_accounts">Gerenciar contas</string>
<string name="action_account">Gerenciar conta</string>
<string name="action_end_conversation">Encerrar essa conversa</string>
<string name="action_contact_details">Detalhes do contato</string>
<string name="action_muc_details">Detalhes da conversa em grupo</string>
<string name="channel_details">Detalhes do canal</string>
<string name="action_secure">Conversa segura</string>
<string name="action_add_account">Adicionar conta</string>
<string name="action_edit_contact">Editar o nome</string>
<string name="action_add_phone_book">Adicionar ao livro de endereços</string>
@ -921,8 +919,6 @@
<string name="only_one_call_at_a_time">Você só pode ter uma chamada de cada vez</string>
<string name="return_to_ongoing_call">Retornar para a chamada em andamento</string>
<string name="could_not_switch_camera">Não foi possível trocar a câmera</string>
<string name="add_to_favorites">Adicionar aos favoritos</string>
<string name="remove_from_favorites">Remover dos favoritos</string>
<string name="gpx_track">Trilha GPX</string>
<string name="could_not_correct_message">Não foi possível corrigir a mensagem</string>
<plurals name="view_users">

View File

@ -4,7 +4,6 @@
<string name="action_add">Nova conversa</string>
<string name="action_accounts">Gerir contas</string>
<string name="action_contact_details">Detalhes do contacto</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 ao livro de endereços</string>

View File

@ -8,7 +8,6 @@
<string name="action_contact_details">Detalii contact</string>
<string name="action_muc_details">Detalii discuție de grup</string>
<string name="channel_details">Detalii canal</string>
<string name="action_secure">Securizează conferința</string>
<string name="action_add_account">Adaugă cont</string>
<string name="action_edit_contact">Editează nume</string>
<string name="action_add_phone_book">Adaugă la lista de contacte</string>
@ -762,6 +761,7 @@
<string name="ongoing_calls_channel_name">Apeluri în curs</string>
<string name="silent_messages_channel_name">Mesaje silențioase</string>
<string name="silent_messages_channel_description">Acest grup de notificări este folosit pentru a arăta notificări care nu emit sunete. De exemplu atunci când sunteți activi pe un alt dispozitiv (Perioada de grație).</string>
<string name="delivery_failed_channel_name">Trimiteri eșuate</string>
<string name="pref_message_notification_settings">Setări de notificare ale mesajelor</string>
<string name="pref_incoming_call_notification_settings">Setări de notificare ale apelurilor primite</string>
<string name="pref_more_notification_settings_summary">Importanță, sunete, vibrații</string>
@ -929,13 +929,32 @@
<string name="only_one_call_at_a_time">Puteți avea un singur apel simultan.</string>
<string name="return_to_ongoing_call">Reveniți la apelul în curs</string>
<string name="could_not_switch_camera">Nu s-a putut face comutarea camerei foto</string>
<string name="add_to_favorites">Adaugă la favorite</string>
<string name="remove_from_favorites">Înlătură din favorite</string>
<string name="add_to_favorites">Fixează sus</string>
<string name="remove_from_favorites">Anulează fixarea</string>
<string name="gpx_track">Traseu GPX</string>
<string name="could_not_correct_message">Nu s-a putut corecta mesajul</string>
<string name="search_all_conversations">Toate conversațiile</string>
<string name="search_this_conversation">Această conversație</string>
<string name="your_avatar">Avatarul dumneavoastră</string>
<string name="avatar_for_x">Avatar pentru %s</string>
<string name="encrypted_with_omemo">Criptare OMEMO</string>
<string name="encrypted_with_openpgp">Criptare OpenPGP</string>
<string name="not_encrypted">Fără criptare</string>
<string name="exit">Ieșire</string>
<string name="record_voice_mail">Înregistrare mesaj vocal</string>
<string name="play_audio">Redare audio</string>
<string name="pause_audio">Pauză audio</string>
<string name="add_contact_or_create_or_join_group_chat">Adaugă contact, creează sau alătură-te discuției de grup, sau descoperă canale</string>
<plurals name="view_users">
<item quantity="one">Arată %1$d participant</item>
<item quantity="few">Arată %1$d participanți</item>
<item quantity="other">Arată %1$d de participanți</item>
</plurals>
<plurals name="some_messages_could_not_be_delivered">
<item quantity="one">Un mesaj nu a putut fi livrat</item>
<item quantity="few">Niște mesaje nu au putut fi livrate</item>
<item quantity="other">Niște mesaje nu au putut fi livrate</item>
</plurals>
<string name="failed_deliveries">Trimiteri eșuate</string>
<string name="more_options">Mai multe</string>
</resources>

View File

@ -4,11 +4,9 @@
<string name="action_add">Новая беседа</string>
<string name="action_accounts">Управление аккаунтами</string>
<string name="action_account">Управление аккаунтом</string>
<string name="action_end_conversation">Закрыть текущую беседу</string>
<string name="action_contact_details">Сведения о контакте</string>
<string name="action_muc_details">Подробности конференции</string>
<string name="channel_details">Сведения о канале</string>
<string name="action_secure">Защищённая беседа</string>
<string name="action_add_account">Добавить аккаунт</string>
<string name="action_edit_contact">Редактировать контакт</string>
<string name="action_add_phone_book">Добавить в адресную книгу</string>
@ -933,8 +931,6 @@
<string name="only_one_call_at_a_time">Нельзя одновременно совершать больше одного звонка.</string>
<string name="return_to_ongoing_call">Вернуться к текущему звонку</string>
<string name="could_not_switch_camera">Не удалось переключить камеру</string>
<string name="add_to_favorites">Добавить в избранные</string>
<string name="remove_from_favorites">Убрать из избранных</string>
<plurals name="view_users">
<item quantity="one">Просмотр %1$d участника</item>
<item quantity="few">Просмотр %1$d участников</item>

View File

@ -4,7 +4,6 @@
<string name="action_add">Nová konverzácia</string>
<string name="action_accounts">Nastavenie účtov</string>
<string name="action_contact_details">Detaily kontaktu</string>
<string name="action_secure">Zabezpečená konverzácia</string>
<string name="action_add_account">Pridať účet</string>
<string name="action_edit_contact">Upraviť meno</string>
<string name="action_delete_contact">Vymazať zo zoznamu</string>

View File

@ -5,7 +5,6 @@
<string name="action_accounts">Управљај налозима</string>
<string name="action_contact_details">Детаљи контакта</string>
<string name="action_muc_details">Детаљи групног ћаскања</string>
<string name="action_secure">Безбедна преписка</string>
<string name="action_add_account">Додај налог</string>
<string name="action_edit_contact">Уреди име</string>
<string name="action_add_phone_book">Додај у именик</string>

View File

@ -4,11 +4,9 @@
<string name="action_add">Ny konversation</string>
<string name="action_accounts">Kontoinställningar</string>
<string name="action_account">Hantera konto</string>
<string name="action_end_conversation">Stäng denna konversation</string>
<string name="action_contact_details">Kontaktdetaljer</string>
<string name="action_muc_details">Gruppchattdetaljer</string>
<string name="channel_details">Kanaldetaljer</string>
<string name="action_secure">Säker konversation</string>
<string name="action_add_account">Lägg till konto</string>
<string name="action_edit_contact">Ändra namn</string>
<string name="action_add_phone_book">Lägg till i kontakter</string>

View File

@ -4,11 +4,9 @@
<string name="action_add">Yeni konuşma</string>
<string name="action_accounts">Hesapları yönet</string>
<string name="action_account">Hesabı yönet</string>
<string name="action_end_conversation">Bu konuşmayı kapat</string>
<string name="action_contact_details">Kişi bilgileri</string>
<string name="action_muc_details">Küme konuşması ayrıntıları</string>
<string name="channel_details">Kanal ayrıntıları</string>
<string name="action_secure">Güvenli konuşma</string>
<string name="action_add_account">Hesap ekle</string>
<string name="action_edit_contact">İsmi düzenle</string>
<string name="action_add_phone_book">Telefon rehberine ekle</string>

View File

@ -4,11 +4,9 @@
<string name="action_add">Нова розмова</string>
<string name="action_accounts">Мої облікові записи</string>
<string name="action_account">Мій обліковий запис</string>
<string name="action_end_conversation">Завершити розмову</string>
<string name="action_contact_details">Деталі контакту</string>
<string name="action_muc_details">Деталі групи</string>
<string name="channel_details">Деталі каналу</string>
<string name="action_secure">Захищена розмова</string>
<string name="action_add_account">Додати обліковий запис</string>
<string name="action_edit_contact">Редагувати ім\'я</string>
<string name="action_add_phone_book">Додати до контактів</string>
@ -933,8 +931,6 @@
<string name="only_one_call_at_a_time">Водночас можливо здійснювати лише один виклик.</string>
<string name="return_to_ongoing_call">Назад до активного виклику</string>
<string name="could_not_switch_camera">Неможливо перемкнути камеру</string>
<string name="add_to_favorites">Додати до обраного</string>
<string name="remove_from_favorites">Вилучити з обраного</string>
<plurals name="view_users">
<item quantity="one">Перегляд %1$d учасника</item>
<item quantity="few">Перегляд %1$d учасників</item>

View File

@ -4,7 +4,6 @@
<string name="action_add">Hội thoại mới</string>
<string name="action_accounts">Quản lý tài khoản</string>
<string name="action_contact_details">Thông tin liên hệ</string>
<string name="action_secure">Bảo mật hội thoại</string>
<string name="action_add_account">Thêm tài khoản</string>
<string name="action_edit_contact">Chỉnh sửa tên</string>
<string name="action_add_phone_book">Thêm vào danh bạ</string>

View File

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="show_qr_code_scan">false</bool>
<bool name="show_individual_search_options">false</bool>
<bool name="show_combined_search_options">true</bool>
</resources>

View File

@ -4,11 +4,9 @@
<string name="action_add">新对话</string>
<string name="action_accounts">管理账户</string>
<string name="action_account">管理账户</string>
<string name="action_end_conversation">关闭对话</string>
<string name="action_contact_details">联系人详情</string>
<string name="action_muc_details">群聊详情</string>
<string name="channel_details">频道详情</string>
<string name="action_secure">加密对话</string>
<string name="action_add_account">添加账户</string>
<string name="action_edit_contact">编辑名称</string>
<string name="action_add_phone_book">添加到通讯录</string>
@ -460,7 +458,11 @@
<string name="server_info_broken">损坏</string>
<string name="pref_presence_settings">可用性</string>
<string name="pref_away_when_screen_off">锁屏时显示离开</string>
<string name="pref_away_when_screen_off_summary">屏幕关闭时显示为“离开”</string>
<string name="pref_dnd_on_silent_mode">在静音模式显示为忙碌</string>
<string name="pref_dnd_on_silent_mode_summary">设备处于静音模式时显示为忙碌</string>
<string name="pref_treat_vibrate_as_silent">将振动看作静音</string>
<string name="pref_treat_vibrate_as_dnd_summary">设备振动时显示为忙碌</string>
<string name="pref_show_connection_options">高级连接设置</string>
<string name="pref_show_connection_options_summary">注册账户时显示主机名和端口</string>
<string name="hostname_example">xmpp.example.com</string>
@ -909,8 +911,8 @@
<string name="only_one_call_at_a_time">只能同时打一通电话</string>
<string name="return_to_ongoing_call">返回正在进行的通话</string>
<string name="could_not_switch_camera">无法切换摄像头</string>
<string name="add_to_favorites">添加到收藏夹</string>
<string name="remove_from_favorites">从收藏夹删除</string>
<string name="gpx_track">GPX轨迹</string>
<string name="could_not_correct_message">无法更正消息</string>
<plurals name="view_users">
<item quantity="other">查看%1$d成员</item>
</plurals>

View File

@ -4,7 +4,6 @@
<string name="action_add">新對話</string>
<string name="action_accounts">管理帳戶</string>
<string name="action_contact_details">聯絡人詳情</string>
<string name="action_secure">安全對話</string>
<string name="action_add_account">新增帳戶</string>
<string name="action_edit_contact">編輯姓名</string>
<string name="action_add_phone_book">添加到地址薄</string>

View File

@ -26,6 +26,8 @@
<color name="green500">#ff4CAF50</color>
<color name="blue_a100">#ff82B1FF</color>
<color name="blue_a200">#ff448AFF</color>
<color name="blue_a400">#ff2979FF</color>
<color name="blue_a700">#ff2962FF</color>
<color name="orange500">#ffff9800</color>
<color name="orange600">#fffb8c00</color>
<color name="orange700">#ffF57C00</color>

View File

@ -34,6 +34,8 @@
<bool name="never_send">false</bool>
<bool name="validate_hostname">false</bool>
<bool name="show_qr_code_scan">true</bool>
<bool name="show_individual_search_options">true</bool>
<bool name="show_combined_search_options">false</bool>
<bool name="scroll_to_bottom">true</bool>
<string name="omemo_setting_default">default_on</string>
<string name="default_font_size">small</string>

View File

@ -4,11 +4,10 @@
<string name="action_add">New conversation</string>
<string name="action_accounts">Manage accounts</string>
<string name="action_account">Manage account</string>
<string name="action_end_conversation">Close this conversation</string>
<string name="action_end_conversation">Close conversation</string>
<string name="action_contact_details">Contact details</string>
<string name="action_muc_details">Group chat details</string>
<string name="channel_details">Channel details</string>
<string name="action_secure">Secure conversation</string>
<string name="action_add_account">Add account</string>
<string name="action_edit_contact">Edit name</string>
<string name="action_add_phone_book">Add to address book</string>
@ -756,6 +755,7 @@
<string name="ongoing_calls_channel_name">Ongoing calls</string>
<string name="silent_messages_channel_name">Silent messages</string>
<string name="silent_messages_channel_description">This notification group is used to display notifications that should not trigger any sound. For example when being active on another device (Grace Period).</string>
<string name="delivery_failed_channel_name">Failed deliveries</string>
<string name="pref_message_notification_settings">Message notification settings</string>
<string name="pref_incoming_call_notification_settings">Incoming calls notification settings</string>
<string name="pref_more_notification_settings_summary">Importance, Sound, Vibrate</string>
@ -923,12 +923,30 @@
<string name="only_one_call_at_a_time">You can only have one call at a time.</string>
<string name="return_to_ongoing_call">Return to ongoing call</string>
<string name="could_not_switch_camera">Could not switch camera</string>
<string name="add_to_favorites">Add to favorites</string>
<string name="remove_from_favorites">Remove from favorites</string>
<string name="add_to_favorites">Pin to top</string>
<string name="remove_from_favorites">Unpin from top</string>
<string name="gpx_track">GPX track</string>
<string name="could_not_correct_message">Could not correct message</string>
<string name="search_all_conversations">All conversations</string>
<string name="search_this_conversation">This conversation</string>
<string name="your_avatar">Your avatar</string>
<string name="avatar_for_x">Avatar for %s</string>
<string name="encrypted_with_omemo">Encrypted with OMEMO</string>
<string name="encrypted_with_openpgp">Encrypted with OpenPGP</string>
<string name="not_encrypted">Not encrypted</string>
<string name="exit">Exit</string>
<string name="record_voice_mail">Record voice mail</string>
<string name="play_audio">Play audio</string>
<string name="pause_audio">Pause audio</string>
<string name="add_contact_or_create_or_join_group_chat">Add contact, create or join group chat, or discover channels</string>
<plurals name="view_users">
<item quantity="one">View %1$d Participant</item>
<item quantity="other">View %1$d Participants</item>
</plurals>
<plurals name="some_messages_could_not_be_delivered">
<item quantity="one">A message could not be delivered</item>
<item quantity="other">Some messages could not be delivered</item>
</plurals>
<string name="failed_deliveries">Failed deliveries</string>
<string name="more_options">More options</string>
</resources>

View File

@ -4,7 +4,7 @@
<style name="ConversationsTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/orange600</item>
<item name="colorPrimaryDark">@color/orange800</item>
<item name="colorAccent">@color/blue_a200</item>
<item name="colorAccent">@color/blue_a400</item>
<item name="popupOverlayStyle">@style/ThemeOverlay.AppCompat.Light</item>
<item name="color_background_primary">@color/grey50</item>
@ -371,7 +371,7 @@
<style name="ConversationsTheme.Dialog" parent="@style/Theme.AppCompat.Light.Dialog">
<item name="colorPrimary">@color/orange600</item>
<item name="colorPrimaryDark">@color/orange700</item>
<item name="colorAccent">@color/blue_a200</item>
<item name="colorAccent">@color/blue_a400</item>
<item name="color_background_primary">@color/grey50</item>
<item name="divider">@color/black12</item>
<item name="TextSizeTitle">18sp</item>

View File

@ -55,7 +55,7 @@ public class PushManagementService {
e.printStackTrace();
}
} else {
Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": invalid response from app server");
Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": failed to enable push. invalid response from app server "+response);
}
});
});