diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9516c25bd2476b23b1f137e4a72d75e20ac5ea61..5a991842efe4354883a8e783147f3926f687c810 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
# Changelog
+### Version 2.17.10
+
+* Allow audio recording to be pause by tapping the timer
+* Fix reactions in MUC PMs
+* Stop accepting 'fallback messages' for reactions, receipts and display markers
+* Add some more media preview icons
+
+### Version 2.17.9
+
+* Make use of SASL SCRAM Downgrade Protection (XEP-0474)
+* Send reactions to MUC PMs to correct JID
+
### Version 2.17.8
* Fix some minor UI bugs
diff --git a/fastlane/metadata/android/de-DE/changelogs/4213104.txt b/fastlane/metadata/android/de-DE/changelogs/4213104.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fabfac695af6a4173e7af34c49715beac984534b
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/4213104.txt
@@ -0,0 +1,2 @@
+* Verwendung von SASL SCRAM Downgrade Protection (XEP-0474)
+* Reaktionen an MUC PMs senden, damit die XMPP-Adresse korrekt ist
diff --git a/fastlane/metadata/android/de-DE/changelogs/4213204.txt b/fastlane/metadata/android/de-DE/changelogs/4213204.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c5ea7dbb555bf730494cb25a88b369f3493b43e5
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/4213204.txt
@@ -0,0 +1,4 @@
+* Audioaufnahme kann durch Antippen des Timers angehalten werden
+* Reaktionen in MUC PMs korrigiert
+* Annahme von 'Fallback-Nachrichten' für Reaktionen, Bestätigungen und Anzeigemarkierungen beendet
+* Weitere Medienvorschau-Symbole hinzugefügt
diff --git a/fastlane/metadata/android/en-US/changelogs/4213104.txt b/fastlane/metadata/android/en-US/changelogs/4213104.txt
new file mode 100644
index 0000000000000000000000000000000000000000..886e2fc13126f2cea2102fdb48b3cfe9ecb2f9ae
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/4213104.txt
@@ -0,0 +1,2 @@
+* Make use of SASL SCRAM Downgrade Protection (XEP-0474)
+* Send reactions to MUC PMs to correct JID
diff --git a/fastlane/metadata/android/en-US/changelogs/4213204.txt b/fastlane/metadata/android/en-US/changelogs/4213204.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ae676ad87b4111770e798951049eeadea3864ac4
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/4213204.txt
@@ -0,0 +1,4 @@
+* Allow audio recording to be pause by tapping the timer
+* Fix reactions in MUC PMs
+* Stop accepting 'fallback messages' for reactions, receipts and display markers
+* Add some more media preview icons
diff --git a/fastlane/metadata/android/es-ES/changelogs/4213104.txt b/fastlane/metadata/android/es-ES/changelogs/4213104.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d029b2c27c85805e9a3f3e021a3e4de06aaad0a7
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/4213104.txt
@@ -0,0 +1,2 @@
+* Hicimos uso de la protección contra degradación de SCRAM SASL (XEP-0474)
+* Envíe reacciones a los mensajes privados de MUC para corregir el JID
diff --git a/fastlane/metadata/android/et/changelogs/42043.txt b/fastlane/metadata/android/et/changelogs/42043.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5ce423f963fb158a8098804345ffa19489d64038
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/42043.txt
@@ -0,0 +1 @@
+* Parandasime regressiooni, mis tekkis failide teisaldamisel P2P-ühenduse kaudu
diff --git a/fastlane/metadata/android/et/changelogs/42044.txt b/fastlane/metadata/android/et/changelogs/42044.txt
new file mode 100644
index 0000000000000000000000000000000000000000..916dd4e19767dddd24d1f161ee8e775467ac50a2
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/42044.txt
@@ -0,0 +1,3 @@
+* Parandasime sõnumite kordussaatmise SASL2 kasutamisel
+* Parandasime musta videovaate tekkimise mõnede seadmete puhul
+* Parandasime rakenduse kokkujooksmise tühja salasõna puhul
diff --git a/fastlane/metadata/android/et/changelogs/42046.txt b/fastlane/metadata/android/et/changelogs/42046.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a9aa11eadd8566dd1df58a12dee1911d5dacd5b1
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/42046.txt
@@ -0,0 +1 @@
+* Lõimisime UnifiedPushi tõuketeenuste levitajana teistele UnifiedPushi kasutajatele nagu Tusky ja Fedilab
diff --git a/fastlane/metadata/android/et/changelogs/42047.txt b/fastlane/metadata/android/et/changelogs/42047.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d65bd1e5f7a847b6e161263aa1414eaaa41c81d3
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/42047.txt
@@ -0,0 +1 @@
+* Parandasime kokkujooksmise, mis ilmnes UnifiedPushi kasutamisel tõuketeenuste levitajana
diff --git a/fastlane/metadata/android/et/changelogs/42050.txt b/fastlane/metadata/android/et/changelogs/42050.txt
new file mode 100644
index 0000000000000000000000000000000000000000..cc51ce1f3292e2e2403030f92a2f98d9f9e34a9f
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/42050.txt
@@ -0,0 +1 @@
+* Suurendasime profiilipiltide nurkade raadiust
diff --git a/fastlane/metadata/android/et/changelogs/42059.txt b/fastlane/metadata/android/et/changelogs/42059.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1d47a1cf89d9109cb39cf389d7e915ebc9880918
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/42059.txt
@@ -0,0 +1,2 @@
+* Kompileerime jälle arvestades Androidi SDK versiooni 33
+* Parandasime vead serveritega, mis ilmnesid SASL2 kasutamisel ilma lõimitud meediavoo halduseta (inline Stream Management)
diff --git a/fastlane/metadata/android/et/changelogs/42060.txt b/fastlane/metadata/android/et/changelogs/42060.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c19cd31ece12079fc84435ca2b500b5e96e42e67
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/42060.txt
@@ -0,0 +1 @@
+* Parandasime olukorra, kus „q“ tuvastus kirillitsana
diff --git a/fastlane/metadata/android/et/changelogs/4213104.txt b/fastlane/metadata/android/et/changelogs/4213104.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3631b51f5702af963c7b212620ffd6a5d3b45048
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/4213104.txt
@@ -0,0 +1,2 @@
+* Võtsime kasutusele SASL SCRAM madaldusründe kaitse (SASL SCRAM Downgrade Protection XEP-0474)
+* saadame jututoa sõnumite reakstioonid õigetele kasutajatele
diff --git a/fastlane/metadata/android/et/changelogs/4213204.txt b/fastlane/metadata/android/et/changelogs/4213204.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a879dc812c17864b030587e1dada751d95f2d351
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/4213204.txt
@@ -0,0 +1,4 @@
+* Nüüd saab heliklipi salvestust peatada taimeril klõpsides
+* Parandasime reageerimise jututubade otsesõnumitele
+* Enam me ei võta vastu reageerimiste, lugemisteatiste ja lugemismarkerite asendussõnumeid
+* Lisasime veel mõned meedia eelvaate ikoonid
diff --git a/fastlane/metadata/android/gl-ES/changelogs/4213104.txt b/fastlane/metadata/android/gl-ES/changelogs/4213104.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3eae5234324d4a1e80ad4db963f7e65e36661129
--- /dev/null
+++ b/fastlane/metadata/android/gl-ES/changelogs/4213104.txt
@@ -0,0 +1,2 @@
+* Uso de SASL SCRAM Downgrade Protection (XEP-0474)
+* Envío de reaccións en MUC PMs ao JID correcto
diff --git a/fastlane/metadata/android/pl-PL/changelogs/4213104.txt b/fastlane/metadata/android/pl-PL/changelogs/4213104.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7946673f6abee73e4090c1b760b2fb7151e2ad8d
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/4213104.txt
@@ -0,0 +1,2 @@
+* Implementacja ochrony przed obniżeniem poziomu bezpieczeństwa SASL SCRAM (XEP-0474)
+* Wysyłanie reakcji w prywatnych wiadomościach w rozmowie grupowej do właściwego JID
diff --git a/fastlane/metadata/android/pl-PL/changelogs/4213204.txt b/fastlane/metadata/android/pl-PL/changelogs/4213204.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ff73979e3e854126aca483077d95048e99e32196
--- /dev/null
+++ b/fastlane/metadata/android/pl-PL/changelogs/4213204.txt
@@ -0,0 +1,4 @@
+* Umożliwienie wstrzymania nagrywania dźwięku poprzez kliknięcie czasomierza
+* Naprawienie reakcji w prywatnych wiadomościach w rozmowie grupowej
+* Koniec akceptowania „zastępczych wiadomości”, dla reakcji, potwierdzeń i wskaźników przeczytania
+* Dodanie paru więcej ikonek załączników
diff --git a/fastlane/metadata/android/ru-RU/changelogs/4213104.txt b/fastlane/metadata/android/ru-RU/changelogs/4213104.txt
new file mode 100644
index 0000000000000000000000000000000000000000..73bc95031fde7804462c2893fc8c9f69a1ea4c5e
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/changelogs/4213104.txt
@@ -0,0 +1,2 @@
+* Используется защита от понижения SASL SCRAM (XEP-0474)
+* Реакции отправляются в MUC PM для корректировки JID
diff --git a/fastlane/metadata/android/ru-RU/changelogs/4213204.txt b/fastlane/metadata/android/ru-RU/changelogs/4213204.txt
new file mode 100644
index 0000000000000000000000000000000000000000..14f4c0400134be6289f4623cf0b17a9dbe8513f2
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/changelogs/4213204.txt
@@ -0,0 +1,4 @@
+* Добавлена возможность приостановить запись звука нажатием на таймер
+* Исправлены реакции в MUC PM
+* Прекращён приём "резервных сообщений" для реакций, уведомлений о доставке и маркеров отображения
+* Добавлено ещё несколько значков для просмотра медиа
diff --git a/fastlane/metadata/android/sq/changelogs/4213204.txt b/fastlane/metadata/android/sq/changelogs/4213204.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c44d9a8f9422a0e2d566590929af0cc65a8e2c2e
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/4213204.txt
@@ -0,0 +1,4 @@
+* Lejim ndaljeje regjistrimi audio duke shtypur matësin e kohës
+* Ndreqje reagimesh në MP-ra MUC
+* Reshtje pranimi 'fallback messages' për reagime, dëftesa dhe shenja në ekrani
+* Shtim i disa ikonash paraparjeje media më tepër
diff --git a/fastlane/metadata/android/uk/changelogs/4213104.txt b/fastlane/metadata/android/uk/changelogs/4213104.txt
new file mode 100644
index 0000000000000000000000000000000000000000..151ac4a042c33796d760e0bf9ffbda92d50b7046
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/4213104.txt
@@ -0,0 +1,2 @@
+* Використання SASL SCRAM Downgrade Protection (XEP-0474)
+* Надсилання реакцій у приватні повідомлення MUC на правильний JID
diff --git a/fastlane/metadata/android/zh-CN/changelogs/4213104.txt b/fastlane/metadata/android/zh-CN/changelogs/4213104.txt
new file mode 100644
index 0000000000000000000000000000000000000000..69a28dd68019fff1b5084304a3fbfaa6381d540c
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/4213104.txt
@@ -0,0 +1,2 @@
+* 使用 SASL SCRAM 降级保护(XEP-0474)
+* 将 MUC 私信中的回应发送至正确的 JID
diff --git a/fastlane/metadata/android/zh-CN/changelogs/4213204.txt b/fastlane/metadata/android/zh-CN/changelogs/4213204.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d81e465d52d704a11390e9a38e3ba61846d89df9
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/4213204.txt
@@ -0,0 +1,4 @@
+* 允许通过点按计时器暂停录制音频
+* 修复 MUC 私信中的回应
+* 停止接收回应,回执和显示标记的“回退消息”
+* 添加更多媒体预览图标
diff --git a/src/cheogram/java/com/cheogram/ExportBackupService.java b/src/cheogram/java/com/cheogram/ExportBackupService.java
index 9a121f29bca5978f23926d9d31d1c1e2aeca6d1b..f0157868d0782f21526934a50fb39e496d1bf466 100644
--- a/src/cheogram/java/com/cheogram/ExportBackupService.java
+++ b/src/cheogram/java/com/cheogram/ExportBackupService.java
@@ -308,7 +308,7 @@ public class ExportBackupService extends Worker {
}
Log.d(Config.LOGTAG, String.format("exporting data for account %s (%s)", account.getJid().asBareJid(), account.getUuid()));
final Progress progress = new Progress(notification, max, count);
- final File file = new File(FileBackend.getBackupDirectory(context), account.getJid().asBareJid().toEscapedString() + ".xml.pgp");
+ final File file = new File(FileBackend.getBackupDirectory(context), account.getJid().asBareJid().toString() + ".xml.pgp");
files.add(file);
final File directory = file.getParentFile();
if (directory != null && directory.mkdirs()) {
@@ -333,7 +333,7 @@ public class ExportBackupService extends Worker {
new byte[4096]
),
PGPLiteralDataGenerator.UTF8,
- account.getJid().asBareJid().toEscapedString() + ".xml",
+ account.getJid().asBareJid().toString() + ".xml",
PGPLiteralDataGenerator.NOW,
new byte[4096]
));
diff --git a/src/cheogram/java/com/cheogram/android/FinishOnboarding.java b/src/cheogram/java/com/cheogram/android/FinishOnboarding.java
index 86debf794f39d049568644534b92d9d5cd2e934b..fabcd644b0cf89becb8c0e9ed211576ed500729f 100644
--- a/src/cheogram/java/com/cheogram/android/FinishOnboarding.java
+++ b/src/cheogram/java/com/cheogram/android/FinishOnboarding.java
@@ -56,7 +56,7 @@ public class FinishOnboarding {
return;
}
- dataForm.put("new-jid", newAccount.getJid().toEscapedString());
+ dataForm.put("new-jid", newAccount.getJid().toString());
dataForm.submit();
command.setAttribute("action", "execute");
iq.setTo(iq.getFrom());
diff --git a/src/cheogram/java/com/cheogram/android/WebxdcPage.java b/src/cheogram/java/com/cheogram/android/WebxdcPage.java
index 9499619c0857efe2e69c822afaf8a4cfab217415..f1df4728b2e758ffa3b004dc1fa9fe3ad54f52a4 100644
--- a/src/cheogram/java/com/cheogram/android/WebxdcPage.java
+++ b/src/cheogram/java/com/cheogram/android/WebxdcPage.java
@@ -395,7 +395,7 @@ public class WebxdcPage implements ConversationPage {
final var occupantId = conversation.getMucOptions().getSelf().getOccupantId();
if (occupantId != null) return occupantId;
}
- return "xmpp:" + Uri.encode(selfJid().toEscapedString(), "@/+");
+ return "xmpp:" + Uri.encode(selfJid().toString(), "@/+");
}
@JavascriptInterface
diff --git a/src/cheogram/java/com/cheogram/android/WebxdcUpdate.java b/src/cheogram/java/com/cheogram/android/WebxdcUpdate.java
index 570b3a180cfa5b2c8aeea17efdfafdc6add671a9..da37fc0a1cb754eb212fc463dd4cc6dd23c8d8d3 100644
--- a/src/cheogram/java/com/cheogram/android/WebxdcUpdate.java
+++ b/src/cheogram/java/com/cheogram/android/WebxdcUpdate.java
@@ -63,7 +63,7 @@ public class WebxdcUpdate {
ContentValues cv = new ContentValues();
cv.put(Message.CONVERSATION, conversationId);
cv.put("message_id", messageId);
- cv.put("sender", sender.toEscapedString());
+ cv.put("sender", sender.toString());
cv.put("thread", thread);
cv.put("threadParent", threadParent);
if (info != null) cv.put("info", info);
@@ -75,7 +75,7 @@ public class WebxdcUpdate {
public String toString() {
StringBuilder body = new StringBuilder("{\"sender\":");
- body.append(JSONObject.quote(sender.toEscapedString()));
+ body.append(JSONObject.quote(sender.toString()));
if (serial != null) {
body.append(",\"serial\":");
body.append(serial.toString());
diff --git a/src/cheogram/java/eu/siacs/conversations/entities/AccountConfiguration.java b/src/cheogram/java/eu/siacs/conversations/entities/AccountConfiguration.java
index 65b6804f9b6e7bb4abac560824bf5958a38dbd0b..8fdf6aa817b2e049b2078b3a7b48aee5f509cb8a 100644
--- a/src/cheogram/java/eu/siacs/conversations/entities/AccountConfiguration.java
+++ b/src/cheogram/java/eu/siacs/conversations/entities/AccountConfiguration.java
@@ -17,7 +17,7 @@ public class AccountConfiguration {
public String password;
public Jid getJid() {
- return Jid.ofEscaped(address);
+ return Jid.of(address);
}
public static AccountConfiguration parse(final String input) {
diff --git a/src/cheogram/java/eu/siacs/conversations/services/ImportBackupService.java b/src/cheogram/java/eu/siacs/conversations/services/ImportBackupService.java
index 1718e4c4652d610207efc6acc32b1f1463fbe5aa..3ba1c15a0c9bad89fed9d3ae2a7f482b90f3a20b 100644
--- a/src/cheogram/java/eu/siacs/conversations/services/ImportBackupService.java
+++ b/src/cheogram/java/eu/siacs/conversations/services/ImportBackupService.java
@@ -277,7 +277,7 @@ public class ImportBackupService extends Service {
db.setTransactionSuccessful();
db.endTransaction();
final Jid jid = backupFileHeader.getJid();
- final Cursor countCursor = db.rawQuery("select count(messages.uuid) from messages join conversations on conversations.uuid=messages.conversationUuid join accounts on conversations.accountUuid=accounts.uuid where accounts.username=? and accounts.server=?", new String[]{jid.getEscapedLocal(), jid.getDomain().toEscapedString()});
+ final Cursor countCursor = db.rawQuery("select count(messages.uuid) from messages join conversations on conversations.uuid=messages.conversationUuid join accounts on conversations.accountUuid=accounts.uuid where accounts.username=? and accounts.server=?", new String[]{jid.getLocal(), jid.getDomain().toString()});
countCursor.moveToFirst();
final int count = countCursor.getInt(0);
Log.d(Config.LOGTAG, String.format("restored %d messages in %s", count, stopwatch.stop().toString()));
diff --git a/src/cheogram/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java b/src/cheogram/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java
index 0d0f126c7cc7efebe52af23ec75d1af06885880a..1871db6d1a47d7e96d521de8fd94fa121f909efe 100644
--- a/src/cheogram/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java
+++ b/src/cheogram/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java
@@ -133,7 +133,7 @@ public class EasyOnboardingInviteActivity extends XmppActivity implements EasyOn
}
final Intent launchIntent = getIntent();
final String accountExtra = launchIntent.getStringExtra(EXTRA_ACCOUNT);
- final Jid jid = accountExtra == null ? null : Jid.ofEscaped(accountExtra);
+ final Jid jid = accountExtra == null ? null : Jid.of(accountExtra);
if (jid == null) {
return;
}
@@ -143,7 +143,7 @@ public class EasyOnboardingInviteActivity extends XmppActivity implements EasyOn
public static void launch(final Account account, final Activity context) {
final Intent intent = new Intent(context, EasyOnboardingInviteActivity.class);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
context.startActivity(intent);
}
diff --git a/src/cheogram/java/eu/siacs/conversations/ui/MagicCreateActivity.java b/src/cheogram/java/eu/siacs/conversations/ui/MagicCreateActivity.java
index 53b362b5c22c045a4b013a566fe355ba3f1ff22c..8d47a2dd95ffede4e49685ab225e1c365bc7b6f0 100644
--- a/src/cheogram/java/eu/siacs/conversations/ui/MagicCreateActivity.java
+++ b/src/cheogram/java/eu/siacs/conversations/ui/MagicCreateActivity.java
@@ -70,15 +70,15 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher {
final boolean fixedUsername;
if (this.domain != null && this.username != null) {
fixedUsername = true;
- jid = Jid.ofLocalAndDomainEscaped(this.username, this.domain);
+ jid = Jid.ofLocalAndDomain(this.username, this.domain);
} else if (this.domain != null) {
fixedUsername = false;
- jid = Jid.ofLocalAndDomainEscaped(username, this.domain);
+ jid = Jid.ofLocalAndDomain(username, this.domain);
} else {
fixedUsername = false;
- jid = Jid.ofLocalAndDomainEscaped(username, Config.MAGIC_CREATE_DOMAIN);
+ jid = Jid.ofLocalAndDomain(username, Config.MAGIC_CREATE_DOMAIN);
}
- if (!jid.getEscapedLocal().equals(jid.getLocal())) {
+ if (!jid.getLocal().equals(jid.getLocal())) {
binding.username.setError(getString(R.string.invalid_username));
binding.username.requestFocus();
} else {
@@ -140,11 +140,11 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher {
binding.fullJid.setVisibility(View.VISIBLE);
final Jid jid;
if (this.domain == null) {
- jid = Jid.ofLocalAndDomainEscaped(username, Config.MAGIC_CREATE_DOMAIN);
+ jid = Jid.ofLocalAndDomain(username, Config.MAGIC_CREATE_DOMAIN);
} else {
- jid = Jid.ofLocalAndDomainEscaped(username, this.domain);
+ jid = Jid.ofLocalAndDomain(username, this.domain);
}
- binding.fullJid.setText(getString(R.string.your_full_jid_will_be, jid.toEscapedString()));
+ binding.fullJid.setText(getString(R.string.your_full_jid_will_be, jid.toString()));
} catch (IllegalArgumentException e) {
binding.fullJid.setVisibility(View.INVISIBLE);
}
diff --git a/src/cheogram/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/cheogram/java/eu/siacs/conversations/ui/ManageAccountActivity.java
index 7176d22546ddb2dfe5bfc1bd356a34f8fb42bbaa..4783d3720b0918bcaed15c3ee45d5903ec1ec4e6 100644
--- a/src/cheogram/java/eu/siacs/conversations/ui/ManageAccountActivity.java
+++ b/src/cheogram/java/eu/siacs/conversations/ui/ManageAccountActivity.java
@@ -119,7 +119,7 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
String jid = savedInstanceState.getString(STATE_SELECTED_ACCOUNT);
if (jid != null) {
try {
- this.selectedAccountJid = Jid.ofEscaped(jid);
+ this.selectedAccountJid = Jid.of(jid);
} catch (IllegalArgumentException e) {
this.selectedAccountJid = null;
}
@@ -136,7 +136,7 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
@Override
public void onSaveInstanceState(final Bundle savedInstanceState) {
if (selectedAccount != null) {
- savedInstanceState.putString(STATE_SELECTED_ACCOUNT, selectedAccount.getJid().asBareJid().toEscapedString());
+ savedInstanceState.putString(STATE_SELECTED_ACCOUNT, selectedAccount.getJid().asBareJid().toString());
}
super.onSaveInstanceState(savedInstanceState);
}
@@ -156,7 +156,7 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(false);
menu.findItem(R.id.mgmt_account_publish_avatar).setVisible(false);
}
- menu.setHeaderTitle(this.selectedAccount.getJid().asBareJid().toEscapedString());
+ menu.setHeaderTitle(this.selectedAccount.getJid().asBareJid().toString());
}
@Override
@@ -347,7 +347,7 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
private void publishAvatar(Account account) {
Intent intent = new Intent(getApplicationContext(),
PublishProfilePictureActivity.class);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
startActivity(intent);
}
diff --git a/src/cheogram/java/eu/siacs/conversations/ui/WelcomeActivity.java b/src/cheogram/java/eu/siacs/conversations/ui/WelcomeActivity.java
index 8e9199b2cb4fb3b63c2e5c791a13c1b1e98c406f..fad6a203952c886f3cb05b616a90006b0e69d986 100644
--- a/src/cheogram/java/eu/siacs/conversations/ui/WelcomeActivity.java
+++ b/src/cheogram/java/eu/siacs/conversations/ui/WelcomeActivity.java
@@ -97,7 +97,7 @@ public class WelcomeActivity extends XmppActivity implements XmppConnectionServi
Intent intent = new Intent(this, StartConversationActivity.class);
intent.putExtra("init", true);
- intent.putExtra(EXTRA_ACCOUNT, onboardingAccount.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, onboardingAccount.getJid().asBareJid().toString());
onboardingAccount = null;
startActivity(intent);
finish();
@@ -172,7 +172,7 @@ public class WelcomeActivity extends XmppActivity implements XmppConnectionServi
} else {
binding.registerNewAccount.setText("Working...");
binding.registerNewAccount.setEnabled(false);
- onboardingAccount = new Account(Jid.ofLocalAndDomain(UUID.randomUUID().toString(), Config.ONBOARDING_DOMAIN.toEscapedString()), CryptoHelper.createPassword(new SecureRandom()));
+ onboardingAccount = new Account(Jid.ofLocalAndDomain(UUID.randomUUID().toString(), Config.ONBOARDING_DOMAIN.toString()), CryptoHelper.createPassword(new SecureRandom()));
onboardingAccount.setOption(Account.OPTION_REGISTER, true);
onboardingAccount.setOption(Account.OPTION_FIXED_USERNAME, true);
xmppConnectionService.createAccount(onboardingAccount);
@@ -259,7 +259,7 @@ public class WelcomeActivity extends XmppActivity implements XmppConnectionServi
@Override
public void onAccountCreated(final Account account) {
final Intent intent = new Intent(this, EditAccountActivity.class);
- intent.putExtra("jid", account.getJid().asBareJid().toEscapedString());
+ intent.putExtra("jid", account.getJid().asBareJid().toString());
intent.putExtra("init", true);
addInviteUri(intent);
startActivity(intent);
diff --git a/src/cheogram/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java b/src/cheogram/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java
index f0a3fa87d5a8d59395b4bf22a80e7e86ff2ae293..2948a613ed140b4ae2434f029451167a5b435660 100644
--- a/src/cheogram/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java
+++ b/src/cheogram/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java
@@ -26,12 +26,12 @@ public class PhoneNumberUtilWrapper {
try {
return getInstance(context).format(toPhoneNumber(context, jid), PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL).replace(' ','\u202F');
} catch (Exception e) {
- return jid.getEscapedLocal();
+ return jid.getLocal();
}
}
public static Phonenumber.PhoneNumber toPhoneNumber(Context context, Jid jid) throws NumberParseException {
- return getInstance(context).parse(jid.getEscapedLocal(), "de");
+ return getInstance(context).parse(jid.getLocal(), "de");
}
public static String normalize(Context context, String input) throws IllegalArgumentException, NumberParseException {
diff --git a/src/cheogram/java/eu/siacs/conversations/utils/ProvisioningUtils.java b/src/cheogram/java/eu/siacs/conversations/utils/ProvisioningUtils.java
index 593291d95374f4be2f1722b8c46a03fe34ed28dc..7c4d2a29e078071211a923702dc8cd71c1b6bd6d 100644
--- a/src/cheogram/java/eu/siacs/conversations/utils/ProvisioningUtils.java
+++ b/src/cheogram/java/eu/siacs/conversations/utils/ProvisioningUtils.java
@@ -31,11 +31,11 @@ public class ProvisioningUtils {
}
final Intent serviceIntent = new Intent(activity, XmppConnectionService.class);
serviceIntent.setAction(XmppConnectionService.ACTION_PROVISION_ACCOUNT);
- serviceIntent.putExtra("address", jid.asBareJid().toEscapedString());
+ serviceIntent.putExtra("address", jid.asBareJid().toString());
serviceIntent.putExtra("password", accountConfiguration.password);
Compatibility.startService(activity, serviceIntent);
final Intent intent = new Intent(activity, EditAccountActivity.class);
- intent.putExtra("jid", jid.asBareJid().toEscapedString());
+ intent.putExtra("jid", jid.asBareJid().toString());
intent.putExtra("init", true);
activity.startActivity(intent);
}
diff --git a/src/cheogram/java/eu/siacs/conversations/utils/SignupUtils.java b/src/cheogram/java/eu/siacs/conversations/utils/SignupUtils.java
index fbb294e9b1fde88384c465f11edce933d7f33429..bfe265466d08387d68b3e84cd35fce1ad8c4e303 100644
--- a/src/cheogram/java/eu/siacs/conversations/utils/SignupUtils.java
+++ b/src/cheogram/java/eu/siacs/conversations/utils/SignupUtils.java
@@ -24,10 +24,10 @@ public class SignupUtils {
public static Intent getTokenRegistrationIntent(final Activity activity, Jid jid, String preAuth) {
final Intent intent = new Intent(activity, MagicCreateActivity.class);
if (jid.isDomainJid()) {
- intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toEscapedString());
+ intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toString());
} else {
- intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toEscapedString());
- intent.putExtra(MagicCreateActivity.EXTRA_USERNAME, jid.getEscapedLocal());
+ intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toString());
+ intent.putExtra(MagicCreateActivity.EXTRA_USERNAME, jid.getLocal());
}
intent.putExtra(MagicCreateActivity.EXTRA_PRE_AUTH, preAuth);
return intent;
diff --git a/src/conversations/java/eu/siacs/conversations/entities/AccountConfiguration.java b/src/conversations/java/eu/siacs/conversations/entities/AccountConfiguration.java
index 65b6804f9b6e7bb4abac560824bf5958a38dbd0b..c3326d8ee81761121fcba634d788242b6811f373 100644
--- a/src/conversations/java/eu/siacs/conversations/entities/AccountConfiguration.java
+++ b/src/conversations/java/eu/siacs/conversations/entities/AccountConfiguration.java
@@ -5,7 +5,6 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName;
-
import eu.siacs.conversations.xmpp.Jid;
public class AccountConfiguration {
@@ -17,7 +16,7 @@ public class AccountConfiguration {
public String password;
public Jid getJid() {
- return Jid.ofEscaped(address);
+ return Jid.of(address);
}
public static AccountConfiguration parse(final String input) {
@@ -27,24 +26,17 @@ public class AccountConfiguration {
} catch (JsonSyntaxException e) {
throw new IllegalArgumentException("Not a valid JSON string", e);
}
- Preconditions.checkArgument(
- c.protocol == Protocol.XMPP,
- "Protocol must be XMPP"
- );
+ Preconditions.checkArgument(c.protocol == Protocol.XMPP, "Protocol must be XMPP");
Preconditions.checkArgument(
c.address != null && c.getJid().isBareJid() && !c.getJid().isDomainJid(),
- "Invalid XMPP address"
- );
+ "Invalid XMPP address");
Preconditions.checkArgument(
- c.password != null && c.password.length() > 0,
- "No password specified"
- );
+ c.password != null && !c.password.isEmpty(), "No password specified");
return c;
}
public enum Protocol {
- @SerializedName("xmpp") XMPP,
+ @SerializedName("xmpp")
+ XMPP,
}
-
}
-
diff --git a/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java b/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java
index dd96468ee87427a2fb4a1ef319650c5ab9ff1abb..c15208bfa1b8c0fc383dadbcce3d92ff95292aed 100644
--- a/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java
+++ b/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java
@@ -16,10 +16,8 @@ import android.os.Binder;
import android.os.IBinder;
import android.provider.OpenableColumns;
import android.util.Log;
-
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
-
import com.google.common.base.Charsets;
import com.google.common.base.Stopwatch;
import com.google.common.io.CountingInputStream;
@@ -27,7 +25,6 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore;
@@ -41,14 +38,6 @@ import eu.siacs.conversations.utils.BackupFileHeader;
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
import eu.siacs.conversations.worker.ExportBackupWorker;
import eu.siacs.conversations.xmpp.Jid;
-
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.io.CipherInputStream;
-import org.bouncycastle.crypto.modes.AEADBlockCipher;
-import org.bouncycastle.crypto.modes.GCMBlockCipher;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
@@ -72,8 +61,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipException;
-
import javax.crypto.BadPaddingException;
+import org.bouncycastle.crypto.engines.AESEngine;
+import org.bouncycastle.crypto.io.CipherInputStream;
+import org.bouncycastle.crypto.modes.AEADBlockCipher;
+import org.bouncycastle.crypto.modes.GCMBlockCipher;
+import org.bouncycastle.crypto.params.AEADParameters;
+import org.bouncycastle.crypto.params.KeyParameter;
public class ImportBackupService extends Service {
@@ -314,10 +308,11 @@ public class ImportBackupService extends Service {
final Jid jid = backupFileHeader.getJid();
final Cursor countCursor =
db.rawQuery(
- "select count(messages.uuid) from messages join conversations on conversations.uuid=messages.conversationUuid join accounts on conversations.accountUuid=accounts.uuid where accounts.username=? and accounts.server=?",
- new String[] {
- jid.getEscapedLocal(), jid.getDomain().toEscapedString()
- });
+ "select count(messages.uuid) from messages join conversations on"
+ + " conversations.uuid=messages.conversationUuid join accounts on"
+ + " conversations.accountUuid=accounts.uuid where"
+ + " accounts.username=? and accounts.server=?",
+ new String[] {jid.getLocal(), jid.getDomain().toString()});
countCursor.moveToFirst();
final int count = countCursor.getInt(0);
Log.d(
diff --git a/src/conversations/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java b/src/conversations/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java
index 9228a5170a8c053f005c9b9a33517fd043dab5e2..874557198c196712980ed227863e736da9f8cb4f 100644
--- a/src/conversations/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java
+++ b/src/conversations/java/eu/siacs/conversations/ui/EasyOnboardingInviteActivity.java
@@ -11,13 +11,10 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
-
import com.google.android.material.color.MaterialColors;
import com.google.common.base.Strings;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityEasyInviteBinding;
@@ -153,7 +150,7 @@ public class EasyOnboardingInviteActivity extends XmppActivity
}
final Intent launchIntent = getIntent();
final String accountExtra = launchIntent.getStringExtra(EXTRA_ACCOUNT);
- final Jid jid = accountExtra == null ? null : Jid.ofEscaped(accountExtra);
+ final Jid jid = accountExtra == null ? null : Jid.of(accountExtra);
if (jid == null) {
return;
}
@@ -163,7 +160,7 @@ public class EasyOnboardingInviteActivity extends XmppActivity
public static void launch(final Account account, final Activity context) {
final Intent intent = new Intent(context, EasyOnboardingInviteActivity.class);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
context.startActivity(intent);
}
diff --git a/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java b/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java
index b6d4d452ee6fa28bfa281f12058d5e87d490bf78..bebf9bab67ba4de49b5bfc39cabb8962bff3e451 100644
--- a/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java
+++ b/src/conversations/java/eu/siacs/conversations/ui/MagicCreateActivity.java
@@ -7,9 +7,7 @@ import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.Toast;
-
import androidx.databinding.DataBindingUtil;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityMagicCreateBinding;
@@ -17,7 +15,6 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.InstallReferrerUtils;
import eu.siacs.conversations.xmpp.Jid;
-
import java.security.SecureRandom;
public class MagicCreateActivity extends XmppActivity implements TextWatcher {
@@ -68,15 +65,15 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher {
final boolean fixedUsername;
if (this.domain != null && this.username != null) {
fixedUsername = true;
- jid = Jid.ofLocalAndDomainEscaped(this.username, this.domain);
+ jid = Jid.ofLocalAndDomain(this.username, this.domain);
} else if (this.domain != null) {
fixedUsername = false;
- jid = Jid.ofLocalAndDomainEscaped(username, this.domain);
+ jid = Jid.ofLocalAndDomain(username, this.domain);
} else {
fixedUsername = false;
- jid = Jid.ofLocalAndDomainEscaped(username, Config.MAGIC_CREATE_DOMAIN);
+ jid = Jid.ofLocalAndDomain(username, Config.MAGIC_CREATE_DOMAIN);
}
- if (!jid.getEscapedLocal().equals(jid.getLocal())
+ if (!jid.getLocal().equals(jid.getLocal())
|| (this.username == null && username.length() < 3)) {
binding.usernameLayout.setError(getString(R.string.invalid_username));
binding.username.requestFocus();
@@ -146,12 +143,11 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher {
binding.fullJid.setVisibility(View.VISIBLE);
final Jid jid;
if (this.domain == null) {
- jid = Jid.ofLocalAndDomainEscaped(username, Config.MAGIC_CREATE_DOMAIN);
+ jid = Jid.ofLocalAndDomain(username, Config.MAGIC_CREATE_DOMAIN);
} else {
- jid = Jid.ofLocalAndDomainEscaped(username, this.domain);
+ jid = Jid.ofLocalAndDomain(username, this.domain);
}
- binding.fullJid.setText(
- getString(R.string.your_full_jid_will_be, jid.toEscapedString()));
+ binding.fullJid.setText(getString(R.string.your_full_jid_will_be, jid.toString()));
binding.usernameLayout.setError(null);
} catch (final IllegalArgumentException e) {
binding.fullJid.setVisibility(View.INVISIBLE);
diff --git a/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java
index 6ab32682fd866ac7d906d058220fdbe2ea7598a4..c2a82f8d5cddfa39f08ce263b2afa4e5cc34495a 100644
--- a/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java
+++ b/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java
@@ -17,13 +17,10 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.databinding.DataBindingUtil;
-
import com.google.common.base.Strings;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityManageAccountsBinding;
@@ -34,12 +31,10 @@ import eu.siacs.conversations.ui.adapter.AccountAdapter;
import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.XmppConnection;
-
-import org.openintents.openpgp.util.OpenPgpApi;
-
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.openintents.openpgp.util.OpenPgpApi;
public class ManageAccountActivity extends XmppActivity
implements OnAccountUpdate,
@@ -95,7 +90,7 @@ public class ManageAccountActivity extends XmppActivity
String jid = savedInstanceState.getString(STATE_SELECTED_ACCOUNT);
if (jid != null) {
try {
- this.selectedAccountJid = Jid.ofEscaped(jid);
+ this.selectedAccountJid = Jid.of(jid);
} catch (IllegalArgumentException e) {
this.selectedAccountJid = null;
}
@@ -113,7 +108,7 @@ public class ManageAccountActivity extends XmppActivity
public void onSaveInstanceState(@NonNull final Bundle savedInstanceState) {
if (selectedAccount != null) {
savedInstanceState.putString(
- STATE_SELECTED_ACCOUNT, selectedAccount.getJid().asBareJid().toEscapedString());
+ STATE_SELECTED_ACCOUNT, selectedAccount.getJid().asBareJid().toString());
}
super.onSaveInstanceState(savedInstanceState);
}
@@ -132,7 +127,7 @@ public class ManageAccountActivity extends XmppActivity
menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(false);
menu.findItem(R.id.mgmt_account_publish_avatar).setVisible(false);
}
- menu.setHeaderTitle(this.selectedAccount.getJid().asBareJid().toEscapedString());
+ menu.setHeaderTitle(this.selectedAccount.getJid().asBareJid().toString());
}
@Override
@@ -297,7 +292,7 @@ public class ManageAccountActivity extends XmppActivity
private void publishAvatar(Account account) {
Intent intent = new Intent(getApplicationContext(), PublishProfilePictureActivity.class);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
startActivity(intent);
}
@@ -357,7 +352,8 @@ public class ManageAccountActivity extends XmppActivity
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
- + ": quick start disabled. account will regain this capability on the next connect");
+ + ": quick start disabled. account will regain this capability on the"
+ + " next connect");
}
if (!xmppConnectionService.updateAccount(account)) {
Toast.makeText(this, R.string.unable_to_update_account, Toast.LENGTH_SHORT).show();
diff --git a/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java b/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java
index b2a40976c503c4b744f83e0562092bf85dbb2f62..514d0ccfdfd8afb106d965cc6385fecab84e71a3 100644
--- a/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java
+++ b/src/conversations/java/eu/siacs/conversations/ui/WelcomeActivity.java
@@ -1,5 +1,8 @@
package eu.siacs.conversations.ui;
+import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
+import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
+
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Intent;
@@ -12,14 +15,10 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
-
-import java.util.Arrays;
-import java.util.List;
-
+import com.google.common.base.Strings;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityWelcomeBinding;
@@ -30,11 +29,8 @@ import eu.siacs.conversations.utils.InstallReferrerUtils;
import eu.siacs.conversations.utils.SignupUtils;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xmpp.Jid;
-
-import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
-import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
-
-import com.google.common.base.Strings;
+import java.util.Arrays;
+import java.util.List;
public class WelcomeActivity extends XmppActivity
implements XmppConnectionService.OnAccountCreated, KeyChainAliasCallback {
@@ -196,7 +192,7 @@ public class WelcomeActivity extends XmppActivity
@Override
public void onAccountCreated(final Account account) {
final Intent intent = new Intent(this, EditAccountActivity.class);
- intent.putExtra("jid", account.getJid().asBareJid().toEscapedString());
+ intent.putExtra("jid", account.getJid().asBareJid().toString());
intent.putExtra("init", true);
addInviteUri(intent);
startActivity(intent);
diff --git a/src/conversations/java/eu/siacs/conversations/utils/ProvisioningUtils.java b/src/conversations/java/eu/siacs/conversations/utils/ProvisioningUtils.java
index 593291d95374f4be2f1722b8c46a03fe34ed28dc..fdfe28dbb784ad05a6465c3bcea989192ea83495 100644
--- a/src/conversations/java/eu/siacs/conversations/utils/ProvisioningUtils.java
+++ b/src/conversations/java/eu/siacs/conversations/utils/ProvisioningUtils.java
@@ -3,15 +3,13 @@ package eu.siacs.conversations.utils;
import android.app.Activity;
import android.content.Intent;
import android.widget.Toast;
-
-import java.util.List;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.AccountConfiguration;
import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.EditAccountActivity;
import eu.siacs.conversations.xmpp.Jid;
+import java.util.List;
public class ProvisioningUtils {
@@ -20,7 +18,8 @@ public class ProvisioningUtils {
try {
accountConfiguration = AccountConfiguration.parse(json);
} catch (final IllegalArgumentException e) {
- Toast.makeText(activity, R.string.improperly_formatted_provisioning, Toast.LENGTH_LONG).show();
+ Toast.makeText(activity, R.string.improperly_formatted_provisioning, Toast.LENGTH_LONG)
+ .show();
return;
}
final Jid jid = accountConfiguration.getJid();
@@ -31,13 +30,12 @@ public class ProvisioningUtils {
}
final Intent serviceIntent = new Intent(activity, XmppConnectionService.class);
serviceIntent.setAction(XmppConnectionService.ACTION_PROVISION_ACCOUNT);
- serviceIntent.putExtra("address", jid.asBareJid().toEscapedString());
+ serviceIntent.putExtra("address", jid.asBareJid().toString());
serviceIntent.putExtra("password", accountConfiguration.password);
Compatibility.startService(activity, serviceIntent);
final Intent intent = new Intent(activity, EditAccountActivity.class);
- intent.putExtra("jid", jid.asBareJid().toEscapedString());
+ intent.putExtra("jid", jid.asBareJid().toString());
intent.putExtra("init", true);
activity.startActivity(intent);
}
-
}
diff --git a/src/conversations/java/eu/siacs/conversations/utils/SignupUtils.java b/src/conversations/java/eu/siacs/conversations/utils/SignupUtils.java
index fb088234a24e10ea315bafebd910e28df9caa270..b8123947f98b90e73ef230b50785f28eceefa369 100644
--- a/src/conversations/java/eu/siacs/conversations/utils/SignupUtils.java
+++ b/src/conversations/java/eu/siacs/conversations/utils/SignupUtils.java
@@ -2,7 +2,6 @@ package eu.siacs.conversations.utils;
import android.app.Activity;
import android.content.Intent;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.XmppConnectionService;
@@ -21,13 +20,14 @@ public class SignupUtils {
return true;
}
- public static Intent getTokenRegistrationIntent(final Activity activity, Jid jid, String preAuth) {
+ public static Intent getTokenRegistrationIntent(
+ final Activity activity, Jid jid, String preAuth) {
final Intent intent = new Intent(activity, MagicCreateActivity.class);
if (jid.isDomainJid()) {
- intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toEscapedString());
+ intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toString());
} else {
- intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toEscapedString());
- intent.putExtra(MagicCreateActivity.EXTRA_USERNAME, jid.getEscapedLocal());
+ intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, jid.getDomain().toString());
+ intent.putExtra(MagicCreateActivity.EXTRA_USERNAME, jid.getLocal());
}
intent.putExtra(MagicCreateActivity.EXTRA_PRE_AUTH, preAuth);
return intent;
@@ -55,7 +55,9 @@ public class SignupUtils {
intent = new Intent(activity, EditAccountActivity.class);
intent.putExtra("jid", pendingAccount.getJid().asBareJid().toString());
if (!pendingAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)) {
- intent.putExtra(EditAccountActivity.EXTRA_FORCE_REGISTER, pendingAccount.isOptionSet(Account.OPTION_REGISTER));
+ intent.putExtra(
+ EditAccountActivity.EXTRA_FORCE_REGISTER,
+ pendingAccount.isOptionSet(Account.OPTION_REGISTER));
}
} else {
if (service.getAccounts().size() == 0) {
@@ -74,4 +76,4 @@ public class SignupUtils {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return intent;
}
-}
\ No newline at end of file
+}
diff --git a/src/conversations/res/values-be/strings.xml b/src/conversations/res/values-be/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a6b3daec9354f9ae75cdf8d94a67446c6227dd96
--- /dev/null
+++ b/src/conversations/res/values-be/strings.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/DowngradeProtection.java b/src/main/java/eu/siacs/conversations/crypto/sasl/DowngradeProtection.java
index 6daaa8809398e6f4aa2c7d311ed894fc0ae05299..a1934c9e0d3a791aa73f4afb06bff2f0bd4df657 100644
--- a/src/main/java/eu/siacs/conversations/crypto/sasl/DowngradeProtection.java
+++ b/src/main/java/eu/siacs/conversations/crypto/sasl/DowngradeProtection.java
@@ -9,8 +9,8 @@ import java.util.Collection;
public class DowngradeProtection {
- private static final char SEPARATOR = ',';
- private static final char SEPARATOR_MECHANISM_AND_BINDING = '|';
+ private static final char SEPARATOR = 0x1E;
+ private static final char SEPARATOR_MECHANISM_AND_BINDING = 0x1F;
public final ImmutableList mechanisms;
public final ImmutableList channelBindings;
@@ -26,7 +26,7 @@ public class DowngradeProtection {
this.channelBindings = null;
}
- public String asDString() {
+ public String asHString() {
ensureSaslMechanismFormat(this.mechanisms);
ensureNoSeparators(this.mechanisms);
if (this.channelBindings != null) {
diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/External.java b/src/main/java/eu/siacs/conversations/crypto/sasl/External.java
index 6aba413a5682c9a544797aac797bec6ee6fa35e3..2e8adf1892d5332340e2a9fb28872223807f34df 100644
--- a/src/main/java/eu/siacs/conversations/crypto/sasl/External.java
+++ b/src/main/java/eu/siacs/conversations/crypto/sasl/External.java
@@ -1,10 +1,8 @@
package eu.siacs.conversations.crypto.sasl;
import android.util.Base64;
-
-import javax.net.ssl.SSLSocket;
-
import eu.siacs.conversations.entities.Account;
+import javax.net.ssl.SSLSocket;
public class External extends SaslMechanism {
@@ -27,6 +25,6 @@ public class External extends SaslMechanism {
@Override
public String getClientFirstMessage(final SSLSocket sslSocket) {
return Base64.encodeToString(
- account.getJid().asBareJid().toEscapedString().getBytes(), Base64.NO_WRAP);
+ account.getJid().asBareJid().toString().getBytes(), Base64.NO_WRAP);
}
}
diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java
index 97ae1600ecfe8a95d4d34b7fc8253174110f3b84..0ee9b879c40fce893ab391d1182e727c8e9a86f7 100644
--- a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java
+++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java
@@ -183,7 +183,7 @@ public abstract class ScramMechanism extends SaslMechanism {
final String i = attributes.get("i");
final String s = attributes.get("s");
final String nonce = attributes.get("r");
- final String d = attributes.get("d");
+ final String h = attributes.get("h");
if (Strings.isNullOrEmpty(s) || Strings.isNullOrEmpty(nonce) || Strings.isNullOrEmpty(i)) {
throw new AuthenticationException("Missing attributes from server first message");
}
@@ -205,15 +205,15 @@ public abstract class ScramMechanism extends SaslMechanism {
throw new AuthenticationException("Invalid salt in server first message");
}
- if (d != null && this.downgradeProtection != null) {
+ if (h != null && this.downgradeProtection != null) {
final String asSeenInFeatures;
try {
- asSeenInFeatures = downgradeProtection.asDString();
+ asSeenInFeatures = downgradeProtection.asHString();
} catch (final SecurityException e) {
throw new AuthenticationException(e);
}
final var hashed = BaseEncoding.base64().encode(digest(asSeenInFeatures.getBytes()));
- if (!hashed.equals(d)) {
+ if (!hashed.equals(h)) {
throw new AuthenticationException("Mismatch in SSDP");
}
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java
index 0cd880c85c7c82e4211a49a400216aa9988dc165..07974dab3af466f77c5dce788ce8e152ac0d58c1 100644
--- a/src/main/java/eu/siacs/conversations/entities/Account.java
+++ b/src/main/java/eu/siacs/conversations/entities/Account.java
@@ -306,7 +306,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
}
public String getUsername() {
- return jid.getEscapedLocal();
+ return jid.getLocal();
}
public boolean setJid(final Jid next) {
@@ -330,7 +330,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
}
public String getServer() {
- return jid.getDomain().toEscapedString();
+ return jid.getDomain().toString();
}
public String getPassword() {
@@ -546,7 +546,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
final ContentValues values = new ContentValues();
values.put(UUID, uuid);
values.put(USERNAME, jid.getLocal());
- values.put(SERVER, jid.getDomain().toEscapedString());
+ values.put(SERVER, jid.getDomain().toString());
values.put(PASSWORD, password);
values.put(OPTIONS, options);
synchronized (this.keys) {
@@ -768,11 +768,11 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
public String getShareableUri() {
List fingerprints = this.getFingerprints();
- String uri = "xmpp:" + Uri.encode(getJid().asBareJid().toEscapedString(), "@/+");
- if (fingerprints.size() > 0) {
- return XmppUri.getFingerprintUri(uri, fingerprints, ';');
- } else {
+ final String uri = "xmpp:" + Uri.encode(this.getJid().asBareJid().toString(), "@/+");
+ if (fingerprints.isEmpty()) {
return uri;
+ } else {
+ return XmppUri.getFingerprintUri(uri, fingerprints, ';');
}
}
@@ -780,11 +780,11 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
List fingerprints = this.getFingerprints();
String uri =
"https://conversations.im/i/"
- + XmppUri.lameUrlEncode(this.getJid().asBareJid().toEscapedString());
- if (fingerprints.size() > 0) {
- return XmppUri.getFingerprintUri(uri, fingerprints, '&');
- } else {
+ + XmppUri.lameUrlEncode(this.getJid().asBareJid().toString());
+ if (fingerprints.isEmpty()) {
return uri;
+ } else {
+ return XmppUri.getFingerprintUri(uri, fingerprints, '&');
}
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Bookmark.java b/src/main/java/eu/siacs/conversations/entities/Bookmark.java
index 37467abcd04abeddb0eae00dc16652cc9c707c29..cef2b653eefc9f99dbb97bb6d2988835585c80eb 100644
--- a/src/main/java/eu/siacs/conversations/entities/Bookmark.java
+++ b/src/main/java/eu/siacs/conversations/entities/Bookmark.java
@@ -1,13 +1,15 @@
package eu.siacs.conversations.entities;
import android.content.Context;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
-
+import eu.siacs.conversations.utils.StringUtils;
+import eu.siacs.conversations.utils.UIHelper;
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xml.Namespace;
+import eu.siacs.conversations.xmpp.Jid;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
@@ -16,81 +18,76 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
-import eu.siacs.conversations.utils.StringUtils;
-import eu.siacs.conversations.utils.UIHelper;
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xml.Namespace;
-import eu.siacs.conversations.xmpp.InvalidJid;
-import eu.siacs.conversations.xmpp.Jid;
-
public class Bookmark extends Element implements ListItem {
- private final Account account;
- private WeakReference conversation;
- private Jid jid;
- protected Element extensions = new Element("extensions", Namespace.BOOKMARKS2);
-
- public Bookmark(final Account account, final Jid jid) {
- super("conference");
- this.jid = jid;
- this.setAttribute("jid", jid);
- this.account = account;
- }
-
- private Bookmark(Account account) {
- super("conference");
- this.account = account;
- }
-
- public static Map parseFromStorage(Element storage, Account account) {
- if (storage == null) {
- return Collections.emptyMap();
- }
- final HashMap bookmarks = new HashMap<>();
- for (final Element item : storage.getChildren()) {
- if (item.getName().equals("conference")) {
- final Bookmark bookmark = Bookmark.parse(item, account);
- if (bookmark != null) {
- final Bookmark old = bookmarks.put(bookmark.jid, bookmark);
- if (old != null && old.getBookmarkName() != null && bookmark.getBookmarkName() == null) {
- bookmark.setBookmarkName(old.getBookmarkName());
- }
- }
- }
- }
- return bookmarks;
- }
-
- public static Map parseFromPubSub(final Element pubSub, final Account account) {
- if (pubSub == null) {
- return Collections.emptyMap();
- }
- final Element items = pubSub.findChild("items");
- if (items != null && Namespace.BOOKMARKS2.equals(items.getAttribute("node"))) {
- final Map bookmarks = new HashMap<>();
- for(Element item : items.getChildren()) {
- if (item.getName().equals("item")) {
- final Bookmark bookmark = Bookmark.parseFromItem(item, account);
- if (bookmark != null) {
- bookmarks.put(bookmark.jid, bookmark);
- }
- }
- }
- return bookmarks;
- }
- return Collections.emptyMap();
- }
-
- public static Bookmark parse(Element element, Account account) {
- Bookmark bookmark = new Bookmark(account);
- bookmark.setAttributes(element.getAttributes());
- bookmark.setChildren(element.getChildren());
- bookmark.jid = InvalidJid.getNullForInvalid(bookmark.getAttributeAsJid("jid"));
- if (bookmark.jid == null) {
- return null;
- }
- return bookmark;
- }
+ private final Account account;
+ private WeakReference conversation;
+ private Jid jid;
+ protected Element extensions = new Element("extensions", Namespace.BOOKMARKS2);
+
+ public Bookmark(final Account account, final Jid jid) {
+ super("conference");
+ this.jid = jid;
+ this.setAttribute("jid", jid);
+ this.account = account;
+ }
+
+ private Bookmark(Account account) {
+ super("conference");
+ this.account = account;
+ }
+
+ public static Map parseFromStorage(Element storage, Account account) {
+ if (storage == null) {
+ return Collections.emptyMap();
+ }
+ final HashMap bookmarks = new HashMap<>();
+ for (final Element item : storage.getChildren()) {
+ if (item.getName().equals("conference")) {
+ final Bookmark bookmark = Bookmark.parse(item, account);
+ if (bookmark != null) {
+ final Bookmark old = bookmarks.put(bookmark.jid, bookmark);
+ if (old != null
+ && old.getBookmarkName() != null
+ && bookmark.getBookmarkName() == null) {
+ bookmark.setBookmarkName(old.getBookmarkName());
+ }
+ }
+ }
+ }
+ return bookmarks;
+ }
+
+ public static Map parseFromPubSub(final Element pubSub, final Account account) {
+ if (pubSub == null) {
+ return Collections.emptyMap();
+ }
+ final Element items = pubSub.findChild("items");
+ if (items != null && Namespace.BOOKMARKS2.equals(items.getAttribute("node"))) {
+ final Map bookmarks = new HashMap<>();
+ for (Element item : items.getChildren()) {
+ if (item.getName().equals("item")) {
+ final Bookmark bookmark = Bookmark.parseFromItem(item, account);
+ if (bookmark != null) {
+ bookmarks.put(bookmark.jid, bookmark);
+ }
+ }
+ }
+ return bookmarks;
+ }
+ return Collections.emptyMap();
+ }
+
+ public static Bookmark parse(Element element, Account account) {
+ Bookmark bookmark = new Bookmark(account);
+ bookmark.setAttributes(element.getAttributes());
+ bookmark.setChildren(element.getChildren());
+ bookmark.jid = Jid.Invalid.getNullForInvalid(bookmark.getAttributeAsJid("jid"));
+ if (bookmark.jid == null) {
+ return null;
+ }
+ return bookmark;
+ }
public static Bookmark parseFromItem(Element item, Account account) {
final Element conference = item.findChild("conference", Namespace.BOOKMARKS2);
@@ -98,7 +95,7 @@ public class Bookmark extends Element implements ListItem {
return null;
}
final Bookmark bookmark = new Bookmark(account);
- bookmark.jid = InvalidJid.getNullForInvalid(item.getAttributeAsJid("id"));
+ bookmark.jid = Jid.Invalid.getNullForInvalid(item.getAttributeAsJid("id"));
// TODO verify that we only use bare jids and ignore full jids
if (bookmark.jid == null) {
return null;
@@ -119,9 +116,9 @@ public class Bookmark extends Element implements ListItem {
return bookmark;
}
- public Element getExtensions() {
- return extensions;
- }
+ public Element getExtensions() {
+ return extensions;
+ }
public void addGroup(final String group) {
addChild("group", "jabber:iq:roster").setContent(group);
@@ -172,32 +169,32 @@ public class Bookmark extends Element implements ListItem {
another.getDisplayName());
}
- @Override
- public String getDisplayName() {
- final Conversation c = getConversation();
- final String name = getBookmarkName();
- if (c != null) {
- return c.getName().toString();
- } else if (printableValue(name, false)) {
- return name.trim();
- } else {
- Jid jid = this.getJid();
- return jid != null && jid.getLocal() != null ? jid.getLocal() : "";
- }
- }
-
- public static boolean printableValue(@Nullable String value, boolean permitNone) {
- return value != null && !value.trim().isEmpty() && (permitNone || !"None".equals(value));
- }
-
- public static boolean printableValue(@Nullable String value) {
- return printableValue(value, true);
- }
-
- @Override
- public Jid getJid() {
- return this.jid;
- }
+ @Override
+ public String getDisplayName() {
+ final Conversation c = getConversation();
+ final String name = getBookmarkName();
+ if (c != null) {
+ return c.getName().toString();
+ } else if (printableValue(name, false)) {
+ return name.trim();
+ } else {
+ Jid jid = this.getJid();
+ return jid != null && jid.getLocal() != null ? jid.getLocal() : "";
+ }
+ }
+
+ public static boolean printableValue(@Nullable String value, boolean permitNone) {
+ return value != null && !value.trim().isEmpty() && (permitNone || !"None".equals(value));
+ }
+
+ public static boolean printableValue(@Nullable String value) {
+ return printableValue(value, true);
+ }
+
+ @Override
+ public Jid getJid() {
+ return this.jid;
+ }
public Jid getFullJid() {
return getFullJid(getNick(), true);
@@ -236,32 +233,32 @@ public class Bookmark extends Element implements ListItem {
return tags;
}
- public String getNick() {
- return Strings.emptyToNull(this.findChildContent("nick"));
- }
+ public String getNick() {
+ return Strings.emptyToNull(this.findChildContent("nick"));
+ }
- public void setNick(String nick) {
- Element element = this.findChild("nick");
- if (element == null) {
- element = this.addChild("nick");
- }
- element.setContent(nick);
- }
+ public void setNick(String nick) {
+ Element element = this.findChild("nick");
+ if (element == null) {
+ element = this.addChild("nick");
+ }
+ element.setContent(nick);
+ }
- public boolean autojoin() {
- return this.getAttributeAsBoolean("autojoin");
- }
+ public boolean autojoin() {
+ return this.getAttributeAsBoolean("autojoin");
+ }
- public String getPassword() {
- return this.findChildContent("password");
- }
+ public String getPassword() {
+ return this.findChildContent("password");
+ }
- public void setPassword(String password) {
- Element element = this.findChild("password");
- if (element != null) {
- element.setContent(password);
- }
- }
+ public void setPassword(String password) {
+ Element element = this.findChild("password");
+ if (element != null) {
+ element.setContent(password);
+ }
+ }
@Override
public boolean match(Context context, String needle) {
@@ -289,56 +286,57 @@ public class Bookmark extends Element implements ListItem {
}
}
- private boolean matchInTag(Context context, String needle) {
- needle = needle.toLowerCase(Locale.US);
- for (Tag tag : getTags(context)) {
- if (tag.getName().toLowerCase(Locale.US).contains(needle)) {
- return true;
- }
- }
- return false;
- }
-
- public Account getAccount() {
- return this.account;
- }
-
- public synchronized Conversation getConversation() {
- return this.conversation != null ? this.conversation.get() : null;
- }
-
- public synchronized void setConversation(Conversation conversation) {
- if (this.conversation != null) {
- this.conversation.clear();
- }
- if (conversation == null) {
- this.conversation = null;
- } else {
- this.conversation = new WeakReference<>(conversation);
- }
- }
-
- public String getBookmarkName() {
- return this.getAttribute("name");
- }
-
- public boolean setBookmarkName(String name) {
- String before = getBookmarkName();
- if (name != null) {
- this.setAttribute("name", name);
- } else {
- this.removeAttribute("name");
- }
- return StringUtils.changed(before, name);
- }
-
- @Override
- public int getAvatarBackgroundColor() {
- return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName());
- }
-
- @Override
- public String getAvatarName() {
- return getDisplayName();
- }
+ private boolean matchInTag(Context context, String needle) {
+ needle = needle.toLowerCase(Locale.US);
+ for (Tag tag : getTags(context)) {
+ if (tag.getName().toLowerCase(Locale.US).contains(needle)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Account getAccount() {
+ return this.account;
+ }
+
+ public synchronized Conversation getConversation() {
+ return this.conversation != null ? this.conversation.get() : null;
+ }
+
+ public synchronized void setConversation(Conversation conversation) {
+ if (this.conversation != null) {
+ this.conversation.clear();
+ }
+ if (conversation == null) {
+ this.conversation = null;
+ } else {
+ this.conversation = new WeakReference<>(conversation);
+ }
+ }
+
+ public String getBookmarkName() {
+ return this.getAttribute("name");
+ }
+
+ public boolean setBookmarkName(String name) {
+ String before = getBookmarkName();
+ if (name != null) {
+ this.setAttribute("name", name);
+ } else {
+ this.removeAttribute("name");
+ }
+ return StringUtils.changed(before, name);
+ }
+
+ @Override
+ public int getAvatarBackgroundColor() {
+ return UIHelper.getColorForName(
+ jid != null ? jid.asBareJid().toString() : getDisplayName());
+ }
+
+ @Override
+ public String getAvatarName() {
+ return getDisplayName();
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java
index 7c6f9ec9d5609c65022e1d94d3f7d8ce2b31fa8c..7520ed2b5ae341bcaf4919a801d579d0c8ac5d7a 100644
--- a/src/main/java/eu/siacs/conversations/entities/Contact.java
+++ b/src/main/java/eu/siacs/conversations/entities/Contact.java
@@ -16,7 +16,6 @@ import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
-
import com.google.common.base.Strings;
import org.json.JSONArray;
@@ -88,10 +87,21 @@ public class Contact implements ListItem, Blockable {
setAccount(other.getAccount());
}
- 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, final RtpCapability.Capability rtpCapability) {
+ 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,
+ final RtpCapability.Capability rtpCapability) {
this.accountUuid = account;
this.systemName = systemName;
this.serverName = serverName;
@@ -110,7 +120,7 @@ public class Contact implements ListItem, Blockable {
if (avatar != null) {
this.avatar = new Avatar();
this.avatar.sha1sum = avatar;
- this.avatar.origin = Avatar.Origin.VCARD; //always assume worst
+ this.avatar.origin = Avatar.Origin.VCARD; // always assume worst
}
try {
this.groups = (groups == null ? new JSONArray() : new JSONArray(groups));
@@ -141,7 +151,8 @@ public class Contact implements ListItem, Blockable {
} catch (Exception e) {
systemAccount = null;
}
- return new Contact(cursor.getString(cursor.getColumnIndex(ACCOUNT)),
+ return new Contact(
+ cursor.getString(cursor.getColumnIndex(ACCOUNT)),
cursor.getString(cursor.getColumnIndex(SYSTEMNAME)),
cursor.getString(cursor.getColumnIndex(SERVERNAME)),
cursor.getString(cursor.getColumnIndex(PRESENCE_NAME)),
@@ -154,7 +165,8 @@ public class Contact implements ListItem, Blockable {
cursor.getLong(cursor.getColumnIndex(LAST_TIME)),
cursor.getString(cursor.getColumnIndex(LAST_PRESENCE)),
cursor.getString(cursor.getColumnIndex(GROUPS)),
- RtpCapability.Capability.of(cursor.getString(cursor.getColumnIndex(RTP_CAPABILITY))));
+ RtpCapability.Capability.of(
+ cursor.getString(cursor.getColumnIndex(RTP_CAPABILITY))));
}
public String getDisplayName() {
@@ -175,12 +187,14 @@ public class Contact implements ListItem, Blockable {
ListItem bookmark = account.getBookmark(jid);
if (bookmark != null) {
return bookmark.getDisplayName();
+ } else if (!TextUtils.isEmpty(this.presenceName) && mutualPresenceSubscription()) {
+ return this.presenceName;
} else if (!TextUtils.isEmpty(this.presenceName)) {
return this.presenceName + (mutualPresenceSubscription() ? "" : " (" + jid + ")");
} else if (jid.getLocal() != null) {
return JidHelper.localPartOrFallback(jid);
} else {
- return jid.getDomain().toEscapedString();
+ return jid.getDomain().toString();
}
}
@@ -190,7 +204,7 @@ public class Contact implements ListItem, Blockable {
} else if (jid.getLocal() != null) {
return JidHelper.localPartOrFallback(jid);
} else {
- return jid.getDomain().toEscapedString();
+ return jid.getDomain().toString();
}
}
@@ -242,8 +256,9 @@ public class Contact implements ListItem, Blockable {
getDisplayName().toLowerCase(Locale.US).contains(parts[0]) ||
matchInTag(context, parts[0]);
} else {
- return jid.toString().contains(needle) ||
- getDisplayName().toLowerCase(Locale.US).contains(needle);
+ return jid.toString().contains(needle)
+ || getDisplayName().toLowerCase(Locale.US).contains(needle)
+ || matchInTag(context, needle);
}
}
@@ -437,8 +452,8 @@ public class Contact implements ListItem, Blockable {
}
public boolean showInRoster() {
- return (this.getOption(Contact.Options.IN_ROSTER) && (!this
- .getOption(Contact.Options.DIRTY_DELETE)))
+ return (this.getOption(Contact.Options.IN_ROSTER)
+ && (!this.getOption(Contact.Options.DIRTY_DELETE)))
|| (this.getOption(Contact.Options.DIRTY_PUSH));
}
@@ -530,21 +545,25 @@ public class Contact implements ListItem, Blockable {
}
public String getServer() {
- return getJid().getDomain().toEscapedString();
+ return getJid().getDomain().toString();
}
- public void setAvatar(Avatar avatar) {
- setAvatar(avatar, false);
+ public boolean setAvatar(final Avatar avatar) {
+ return setAvatar(avatar, false);
}
- public void setAvatar(Avatar avatar, boolean previouslyOmittedPepFetch) {
+ public boolean setAvatar(final Avatar avatar, final boolean previouslyOmittedPepFetch) {
if (this.avatar != null && this.avatar.equals(avatar)) {
- return;
+ return false;
}
- if (!previouslyOmittedPepFetch && this.avatar != null && this.avatar.origin == Avatar.Origin.PEP && avatar.origin == Avatar.Origin.VCARD) {
- return;
+ if (!previouslyOmittedPepFetch
+ && this.avatar != null
+ && this.avatar.origin == Avatar.Origin.PEP
+ && avatar.origin == Avatar.Origin.VCARD) {
+ return false;
}
this.avatar = avatar;
+ return true;
}
public String getAvatarFilename() {
@@ -720,7 +739,8 @@ public class Contact implements ListItem, Blockable {
@Override
public int getAvatarBackgroundColor() {
- return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName());
+ return UIHelper.getColorForName(
+ jid != null ? jid.asBareJid().toString() : getDisplayName());
}
@Override
diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java
index 1e790acad03f1b9ee38dffa1b18d465fbf205f6d..c920481fca33b01246be5176060d80df3fa587a3 100644
--- a/src/main/java/eu/siacs/conversations/entities/Conversation.java
+++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java
@@ -287,8 +287,7 @@ public class Conversation extends AbstractEntity
cursor.getString(cursor.getColumnIndexOrThrow(NAME)),
cursor.getString(cursor.getColumnIndexOrThrow(CONTACT)),
cursor.getString(cursor.getColumnIndexOrThrow(ACCOUNT)),
- JidHelper.parseOrFallbackToInvalid(
- cursor.getString(cursor.getColumnIndexOrThrow(CONTACTJID))),
+ Jid.ofOrInvalid(cursor.getString(cursor.getColumnIndexOrThrow(CONTACTJID))),
cursor.getLong(cursor.getColumnIndexOrThrow(CREATED)),
cursor.getInt(cursor.getColumnIndexOrThrow(STATUS)),
cursor.getInt(cursor.getColumnIndexOrThrow(MODE)),
@@ -315,7 +314,7 @@ public class Conversation extends AbstractEntity
if (conversation.getContact().isOwnServer()) {
return false;
}
- final String contact = conversation.getJid().getDomain().toEscapedString();
+ final String contact = conversation.getJid().getDomain().toString();
final String account = conversation.getAccount().getServer();
if (Config.OMEMO_EXCEPTIONS.matchesContactDomain(contact)
|| Config.OMEMO_EXCEPTIONS.ACCOUNT_DOMAINS.contains(account)) {
@@ -2206,7 +2205,7 @@ public class Conversation extends AbstractEntity
if (field.getType().equals(Optional.of("jid-single")) || field.getType().equals(Optional.of("jid-multi"))) {
binding.values.setOnItemClickListener((arg0, arg1, pos, id) -> {
- new FixedURLSpan("xmpp:" + Uri.encode(Jid.ofEscaped(values.getItem(pos).getValue()).toEscapedString(), "@/+"), account).onClick(binding.values);
+ new FixedURLSpan("xmpp:" + Uri.encode(Jid.of(values.getItem(pos).getValue()).toString(), "@/+"), account).onClick(binding.values);
});
} else if ("xs:anyURI".equals(datatype)) {
binding.values.setOnItemClickListener((arg0, arg1, pos, id) -> {
@@ -2245,7 +2244,7 @@ public class Conversation extends AbstractEntity
String value = formatValue(datatype, cell.el.findChildContent("value", "jabber:x:data"), true);
SpannableStringBuilder text = new SpannableStringBuilder(value == null ? "" : value);
if (cell.reported.getType().equals(Optional.of("jid-single"))) {
- text.setSpan(new FixedURLSpan("xmpp:" + Jid.ofEscaped(text.toString()).toEscapedString(), account), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(new FixedURLSpan("xmpp:" + Jid.of(text.toString()).toString(), account), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if ("xs:anyURI".equals(datatype)) {
text.setSpan(new FixedURLSpan(text.toString(), account), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if ("html:tel".equals(datatype)) {
diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java
index 31db0cb06d55643d755cf31283d72680fc19a9bb..112f3c40fab9c80f97d63d0a741c296ecfa4f2c8 100644
--- a/src/main/java/eu/siacs/conversations/entities/Message.java
+++ b/src/main/java/eu/siacs/conversations/entities/Message.java
@@ -1813,8 +1813,8 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
return encryption;
}
- public static boolean configurePrivateMessage(final Message message) {
- return configurePrivateMessage(message, false);
+ public static void configurePrivateMessage(final Message message) {
+ configurePrivateMessage(message, false);
}
public static boolean configurePrivateFileMessage(final Message message) {
@@ -1822,27 +1822,19 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
}
private static boolean configurePrivateMessage(final Message message, final boolean isFile) {
- final Conversation conversation;
- if (message.conversation instanceof Conversation) {
- conversation = (Conversation) message.conversation;
- } else {
- return false;
- }
- if (conversation.getMode() == Conversation.MODE_MULTI) {
- final Jid nextCounterpart = conversation.getNextCounterpart();
- return configurePrivateMessage(conversation, message, nextCounterpart, isFile);
+ if (message.conversation instanceof Conversation conversation) {
+ if (conversation.getMode() == Conversation.MODE_MULTI) {
+ final Jid nextCounterpart = conversation.getNextCounterpart();
+ return configurePrivateMessage(conversation, message, nextCounterpart, isFile);
+ }
}
return false;
}
- public static boolean configurePrivateMessage(final Message message, final Jid counterpart) {
- final Conversation conversation;
- if (message.conversation instanceof Conversation) {
- conversation = (Conversation) message.conversation;
- } else {
- return false;
+ public static void configurePrivateMessage(final Message message, final Jid counterpart) {
+ if (message.conversation instanceof Conversation conversation) {
+ configurePrivateMessage(conversation, message, counterpart, false);
}
- return configurePrivateMessage(conversation, message, counterpart, false);
}
private static boolean configurePrivateMessage(
@@ -1854,7 +1846,16 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
return false;
}
message.setCounterpart(counterpart);
- message.setTrueCounterpart(conversation.getMucOptions().getTrueCounterpart(counterpart));
+ final var mucOptions = conversation.getMucOptions();
+ if (counterpart.equals(mucOptions.getSelf().getFullJid())) {
+ message.setTrueCounterpart(conversation.getAccount().getJid().asBareJid());
+ } else {
+ final var user = mucOptions.findUserByFullJid(counterpart);
+ if (user != null) {
+ message.setTrueCounterpart(user.getRealJid());
+ message.setOccupantId(user.getOccupantId());
+ }
+ }
message.setType(isFile ? Message.TYPE_PRIVATE_FILE : Message.TYPE_PRIVATE);
return true;
}
diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java
index 24b0d0e7642ab42adb356204cefc60dc4ba7ee2e..2643b8d8dcb5a32ce93b443fbdbbfe2d6ab7ce33 100644
--- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java
+++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java
@@ -12,7 +12,6 @@ import io.ipfs.cid.Cid;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.services.AvatarService;
@@ -71,16 +70,17 @@ public class MucOptions {
return this.conversation.getAccount();
}
- public boolean setSelf(User user) {
+ public boolean setSelf(final User user) {
this.self = user;
final boolean roleChanged = this.conversation.setAttribute("role", user.role.toString());
- final boolean affiliationChanged = this.conversation.setAttribute("affiliation", user.affiliation.toString());
+ final boolean affiliationChanged =
+ this.conversation.setAttribute("affiliation", user.affiliation.toString());
this.conversation.setAttribute("mucNick", user.getNick());
return roleChanged || affiliationChanged;
}
- public void changeAffiliation(Jid jid, Affiliation affiliation) {
- User user = findUserByRealJid(jid);
+ public void changeAffiliation(final Jid jid, final Affiliation affiliation) {
+ var user = findUserByRealJid(jid);
synchronized (users) {
if (user == null) {
user = new User(this, null, null, null, new HashSet<>());
@@ -130,21 +130,30 @@ public class MucOptions {
final var identities = serviceDiscoveryResult.getIdentities();
final String identityName = !identities.isEmpty() ? identities.get(0).getName() : null;
final Jid jid = conversation.getJid();
- if (identityName != null && !identityName.equals(jid == null ? null : jid.getEscapedLocal())) {
+ if (identityName != null && !identityName.equals(jid == null ? null : jid.getLocal())) {
name = identityName;
} else {
name = null;
}
}
boolean changed = conversation.setAttribute("muc_name", name);
- changed |= conversation.setAttribute(Conversation.ATTRIBUTE_MEMBERS_ONLY, this.hasFeature("muc_membersonly"));
- changed |= conversation.setAttribute(Conversation.ATTRIBUTE_MODERATED, this.hasFeature("muc_moderated"));
- changed |= conversation.setAttribute(Conversation.ATTRIBUTE_NON_ANONYMOUS, this.hasFeature("muc_nonanonymous"));
+ changed |=
+ conversation.setAttribute(
+ Conversation.ATTRIBUTE_MEMBERS_ONLY, this.hasFeature("muc_membersonly"));
+ changed |=
+ conversation.setAttribute(
+ Conversation.ATTRIBUTE_MODERATED, this.hasFeature("muc_moderated"));
+ changed |=
+ conversation.setAttribute(
+ Conversation.ATTRIBUTE_NON_ANONYMOUS, this.hasFeature("muc_nonanonymous"));
return changed;
}
private Data getRoomInfoForm() {
- final List forms = serviceDiscoveryResult == null ? Collections.emptyList() : serviceDiscoveryResult.forms;
+ final List forms =
+ serviceDiscoveryResult == null
+ ? Collections.emptyList()
+ : serviceDiscoveryResult.forms;
return forms.isEmpty() ? new Data() : forms.get(0);
}
@@ -153,7 +162,8 @@ public class MucOptions {
}
public boolean hasFeature(String feature) {
- return this.serviceDiscoveryResult != null && this.serviceDiscoveryResult.features.contains(feature);
+ return this.serviceDiscoveryResult != null
+ && this.serviceDiscoveryResult.features.contains(feature);
}
public boolean hasVCards() {
@@ -161,7 +171,8 @@ public class MucOptions {
}
public boolean canInvite() {
- final boolean hasPermission = !membersOnly() || self.getRole().ranks(Role.MODERATOR) || allowInvites();
+ final boolean hasPermission =
+ !membersOnly() || self.getRole().ranks(Role.MODERATOR) || allowInvites();
return hasPermission && online();
}
@@ -184,7 +195,7 @@ public class MucOptions {
public boolean allowPm() {
final Field field = getRoomInfoForm().getFieldByName("muc#roomconfig_allowpm");
if (field == null) {
- return true; //fall back if field does not exists
+ return true; // fall back if field does not exists
}
if ("anyone".equals(field.getValue())) {
return true;
@@ -199,7 +210,7 @@ public class MucOptions {
public boolean allowPmRaw() {
final Field field = getRoomInfoForm().getFieldByName("muc#roomconfig_allowpm");
- return field == null || Arrays.asList("anyone","participants").contains(field.getValue());
+ return field == null || Arrays.asList("anyone", "participants").contains(field.getValue());
}
public boolean participating() {
@@ -211,7 +222,9 @@ public class MucOptions {
}
public List getFeatures() {
- return this.serviceDiscoveryResult != null ? this.serviceDiscoveryResult.features : Collections.emptyList();
+ return this.serviceDiscoveryResult != null
+ ? this.serviceDiscoveryResult.features
+ : Collections.emptyList();
}
public boolean nonanonymous() {
@@ -247,7 +260,8 @@ public class MucOptions {
break;
}
}
- boolean self = user.realJid != null && user.realJid.equals(account.getJid().asBareJid());
+ boolean self =
+ user.realJid != null && user.realJid.equals(account.getJid().asBareJid());
if (membersOnly()
&& nonanonymous()
&& user.affiliation.ranks(Affiliation.MEMBER)
@@ -264,7 +278,7 @@ public class MucOptions {
return user;
}
- //returns true if real jid was new;
+ // returns true if real jid was new;
public boolean updateUser(User user) {
User old;
boolean realJidFound = false;
@@ -273,7 +287,7 @@ public class MucOptions {
realJidFound = old != null;
if (old != null) {
if (old.fullJid != null) {
- return false; //don't add. user already exists
+ return false; // don't add. user already exists
} else {
synchronized (users) {
users.remove(old);
@@ -298,7 +312,10 @@ public class MucOptions {
if (old.hats != null && user.hats == null) user.hats = old.hats;
if (old.avatar != null && user.avatar == null) user.avatar = old.avatar;
}
- boolean fullJidIsSelf = isOnline && user.getFullJid() != null && user.getFullJid().equals(self.getFullJid());
+ boolean fullJidIsSelf =
+ isOnline
+ && user.getFullJid() != null
+ && user.getFullJid().equals(self.getFullJid());
if (!fullJidIsSelf) {
this.users.add(user);
return !realJidFound && user.realJid != null;
@@ -351,7 +368,9 @@ public class MucOptions {
public User findUserByOccupantId(final String occupantId, final Jid counterpart) {
synchronized (this.users) {
- final var found = Strings.isNullOrEmpty(occupantId) ? null : Iterables.find(this.users, u -> occupantId.equals(u.occupantId),null);
+ final var found = Strings.isNullOrEmpty(occupantId)
+ ? null
+ : Iterables.find(this.users, u -> occupantId.equals(u.occupantId), null);
if (Strings.isNullOrEmpty(occupantId) || found != null) return found;
final var user = new User(this, counterpart, occupantId, null, new HashSet<>());
user.setOnline(false);
@@ -372,7 +391,8 @@ public class MucOptions {
public User findUser(ReadByMarker readByMarker) {
if (readByMarker.getRealJid() != null) {
- return findOrCreateUserByRealJid(readByMarker.getRealJid().asBareJid(), readByMarker.getFullJid(), null);
+ return findOrCreateUserByRealJid(
+ readByMarker.getRealJid().asBareJid(), readByMarker.getFullJid(), null);
} else if (readByMarker.getFullJid() != null) {
return findUserByFullJid(readByMarker.getFullJid());
} else {
@@ -396,7 +416,7 @@ public class MucOptions {
public List findUsers(final Collection reactions) {
final ImmutableList.Builder builder = new ImmutableList.Builder<>();
- for(final Reaction reaction : reactions) {
+ for (final Reaction reaction : reactions) {
final var user = findUser(reaction);
if (user != null) {
builder.add(user);
@@ -470,13 +490,15 @@ public class MucOptions {
}
}
- public List getUsers(int max) {
- ArrayList subset = new ArrayList<>();
- HashSet jids = new HashSet<>();
- jids.add(account.getJid().asBareJid());
+ public List getUsers(final int max) {
+ final ArrayList subset = new ArrayList<>();
+ final HashSet addresses = new HashSet<>();
+ addresses.add(account.getJid().asBareJid());
synchronized (users) {
for (User user : users) {
- if (user.getRealJid() == null || (user.getRealJid().getLocal() != null && jids.add(user.getRealJid()))) {
+ if (user.getRealJid() == null
+ || (user.getRealJid().getLocal() != null
+ && addresses.add(user.getRealJid()))) {
subset.add(user);
}
if (subset.size() >= max) {
@@ -492,7 +514,8 @@ public class MucOptions {
HashSet jids = new HashSet<>();
for (User user : users) {
jids.add(user.getAccount().getJid().asBareJid());
- if (user.getRealJid() == null || (user.getRealJid().getLocal() != null && jids.add(user.getRealJid()))) {
+ if (user.getRealJid() == null
+ || (user.getRealJid().getLocal() != null && jids.add(user.getRealJid()))) {
subset.add(user);
}
if (subset.size() >= max) {
@@ -530,7 +553,8 @@ public class MucOptions {
public String getProposedNickPure() {
final Bookmark bookmark = this.conversation.getBookmark();
- final String bookmarkedNick = normalize(account.getJid(), bookmark == null ? null : bookmark.getNick());
+ final String bookmarkedNick =
+ normalize(account.getJid(), bookmark == null ? null : bookmark.getNick());
if (bookmarkedNick != null) {
return bookmarkedNick;
} else {
@@ -718,7 +742,8 @@ public class MucOptions {
public String getPassword() {
this.password = conversation.getAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD);
- if (this.password == null && conversation.getBookmark() != null
+ if (this.password == null
+ && conversation.getBookmark() != null
&& conversation.getBookmark().getPassword() != null) {
return conversation.getBookmark().getPassword();
} else {
@@ -743,7 +768,12 @@ public class MucOptions {
ArrayList members = new ArrayList<>();
synchronized (users) {
for (User user : users) {
- if (user.affiliation.ranks(Affiliation.MEMBER) && user.realJid != null && !user.realJid.asBareJid().equals(conversation.account.getJid().asBareJid()) && (!user.isDomain() || includeDomains)) {
+ if (user.affiliation.ranks(Affiliation.MEMBER)
+ && user.realJid != null
+ && !user.realJid
+ .asBareJid()
+ .equals(conversation.account.getJid().asBareJid())
+ && (!user.isDomain() || includeDomains)) {
members.add(user.realJid);
}
}
@@ -859,9 +889,7 @@ public class MucOptions {
void onFailure();
}
- public interface OnRenameListener extends OnEventListener {
-
- }
+ public interface OnRenameListener extends OnEventListener {}
public static class Hat implements Comparable {
private final Uri uri;
@@ -1014,7 +1042,7 @@ public class MucOptions {
}
}
- public boolean setAvatar(Avatar avatar) {
+ public boolean setAvatar(final Avatar avatar) {
if (occupantId != null) {
options.getConversation().setAttribute("occupantAvatar/" + occupantId, getContact() == null && avatar != null ? avatar.sha1sum : null);
}
@@ -1030,7 +1058,10 @@ public class MucOptions {
if (avatar != null) {
return avatar.getFilename();
}
- Avatar avatar = realJid != null ? getAccount().getRoster().getContact(realJid).getAvatar() : null;
+ Avatar avatar =
+ realJid != null
+ ? getAccount().getRoster().getContact(realJid).getAvatar()
+ : null;
return avatar == null ? null : avatar.getFilename();
}
@@ -1066,7 +1097,6 @@ public class MucOptions {
if (realJid != null ? !realJid.equals(user.realJid) : user.realJid != null)
return false;
return fullJid != null ? fullJid.equals(user.fullJid) : user.fullJid == null;
-
}
public boolean isDomain() {
@@ -1084,7 +1114,13 @@ public class MucOptions {
@Override
public String toString() {
- return "[fulljid:" + fullJid + ",realjid:" + realJid + ",nick:" + nick + ",affiliation" + affiliation.toString() + "]";
+ return "[fulljid:"
+ + fullJid
+ + ",realjid:"
+ + realJid
+ + ",affiliation"
+ + affiliation.toString()
+ + "]";
}
public boolean realJidMatchesAccount() {
diff --git a/src/main/java/eu/siacs/conversations/entities/RawBlockable.java b/src/main/java/eu/siacs/conversations/entities/RawBlockable.java
index 664a6a1c938a705509f5ade4b927141dc5b83e6c..97f63d99cfe6eb4a13bb224687a28f0b3309dda4 100644
--- a/src/main/java/eu/siacs/conversations/entities/RawBlockable.java
+++ b/src/main/java/eu/siacs/conversations/entities/RawBlockable.java
@@ -2,14 +2,12 @@ package eu.siacs.conversations.entities;
import android.content.Context;
import android.text.TextUtils;
-
+import eu.siacs.conversations.utils.UIHelper;
+import eu.siacs.conversations.xmpp.Jid;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
-import eu.siacs.conversations.utils.UIHelper;
-import eu.siacs.conversations.xmpp.Jid;
-
public class RawBlockable implements ListItem, Blockable {
private final Account account;
@@ -40,7 +38,7 @@ public class RawBlockable implements ListItem, Blockable {
if (jid.isFullJid()) {
return jid.getResource();
} else {
- return jid.toEscapedString();
+ return jid.toString();
}
}
@@ -62,7 +60,7 @@ public class RawBlockable implements ListItem, Blockable {
needle = needle.toLowerCase(Locale.US).trim();
String[] parts = needle.split("\\s+");
for (String part : parts) {
- if (!jid.toEscapedString().contains(part)) {
+ if (!jid.toString().contains(part)) {
return false;
}
}
@@ -76,7 +74,7 @@ public class RawBlockable implements ListItem, Blockable {
@Override
public int getAvatarBackgroundColor() {
- return UIHelper.getColorForName(jid.toEscapedString());
+ return UIHelper.getColorForName(jid.toString());
}
@Override
@@ -86,7 +84,6 @@ public class RawBlockable implements ListItem, Blockable {
@Override
public int compareTo(ListItem o) {
- return this.getDisplayName().compareToIgnoreCase(
- o.getDisplayName());
+ return this.getDisplayName().compareToIgnoreCase(o.getDisplayName());
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/eu/siacs/conversations/entities/Reaction.java b/src/main/java/eu/siacs/conversations/entities/Reaction.java
index ce8ac5044163cdf8c842b723b95d8e7b31fa651c..84dda0bdaedd5fcb5efb05c46381faaa08482f2b 100644
--- a/src/main/java/eu/siacs/conversations/entities/Reaction.java
+++ b/src/main/java/eu/siacs/conversations/entities/Reaction.java
@@ -1,7 +1,6 @@
package eu.siacs.conversations.entities;
import android.util.Log;
-
import androidx.annotation.NonNull;
import com.cheogram.android.EmojiSearch;
@@ -29,7 +28,6 @@ import io.ipfs.cid.Cid;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.utils.Emoticons;
import eu.siacs.conversations.xmpp.Jid;
-
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
@@ -178,7 +176,7 @@ public class Reaction {
if (value == null) {
out.nullValue();
} else {
- out.value(value.toEscapedString());
+ out.value(value.toString());
}
}
@@ -189,7 +187,7 @@ public class Reaction {
return null;
} else if (in.peek() == JsonToken.STRING) {
final String value = in.nextString();
- return Jid.ofEscaped(value);
+ return Jid.of(value);
}
throw new IOException("Unexpected token");
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Room.java b/src/main/java/eu/siacs/conversations/entities/Room.java
index 9e1d61fc3dc904ebeef044edd4552c59cb5dc3eb..c702c3189bfde4306b067b8448b718d6ab173731 100644
--- a/src/main/java/eu/siacs/conversations/entities/Room.java
+++ b/src/main/java/eu/siacs/conversations/entities/Room.java
@@ -3,7 +3,6 @@ package eu.siacs.conversations.entities;
import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.common.collect.ComparisonChain;
-
import eu.siacs.conversations.services.AvatarService;
import eu.siacs.conversations.utils.LanguageUtils;
import eu.siacs.conversations.utils.UIHelper;
@@ -25,9 +24,7 @@ public class Room implements AvatarService.Avatarable, Comparable {
this.nusers = nusers;
}
- public Room() {
-
- }
+ public Room() {}
public String getName() {
return name;
@@ -52,7 +49,7 @@ public class Room implements AvatarService.Avatarable, Comparable {
@Override
public int getAvatarBackgroundColor() {
Jid room = getRoom();
- return UIHelper.getColorForName(room != null ? room.asBareJid().toEscapedString() : name);
+ return UIHelper.getColorForName(room != null ? room.asBareJid().toString() : name);
}
@Override
@@ -65,9 +62,9 @@ public class Room implements AvatarService.Avatarable, Comparable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Room room = (Room) o;
- return Objects.equal(address, room.address) &&
- Objects.equal(name, room.name) &&
- Objects.equal(description, room.description);
+ return Objects.equal(address, room.address)
+ && Objects.equal(name, room.name)
+ && Objects.equal(description, room.description);
}
@Override
@@ -75,7 +72,6 @@ public class Room implements AvatarService.Avatarable, Comparable {
return Objects.hashCode(address, name, description);
}
-
public boolean contains(String needle) {
return Strings.nullToEmpty(name).contains(needle)
|| Strings.nullToEmpty(description).contains(needle)
@@ -90,4 +86,4 @@ public class Room implements AvatarService.Avatarable, Comparable {
.compare(Strings.nullToEmpty(address), Strings.nullToEmpty(o.address))
.result();
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java
index e851d247ef7e16dc09c8df564cab6ad0adb21c4f..d041ce577edc4a8595b95b0bfef75373174c1d0c 100644
--- a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java
+++ b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java
@@ -1,7 +1,6 @@
package eu.siacs.conversations.generator;
import android.util.Base64;
-
import eu.siacs.conversations.BuildConfig;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
@@ -10,7 +9,6 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.XmppConnection;
-
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
@@ -40,7 +38,8 @@ public abstract class AbstractGenerator {
Namespace.NICK + "+notify",
"urn:xmpp:ping",
"jabber:iq:version",
- "http://jabber.org/protocol/chatstates"
+ "http://jabber.org/protocol/chatstates",
+ Namespace.REACTIONS
};
private final String[] MESSAGE_CONFIRMATION_FEATURES = {
"urn:xmpp:chat-markers:0", "urn:xmpp:receipts"
diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
index 219547eee4ec565be71edc21a14c38ca00d1f84e..d648536699267bdfa7b68d10b719b1c777ef1cdb 100644
--- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
+++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
@@ -181,7 +181,7 @@ public class IqGenerator extends AbstractGenerator {
final Element pubsub = packet.addChild("pubsub", Namespace.PUBSUB);
final Element retract = pubsub.addChild("retract");
retract.setAttribute("node", node);
- retract.setAttribute("notify","true");
+ retract.setAttribute("notify", "true");
retract.addChild("item").setAttribute("id", id);
return packet;
}
@@ -194,7 +194,8 @@ public class IqGenerator extends AbstractGenerator {
return publish(Namespace.AVATAR_DATA, item, options);
}
- public Iq publishElement(final String namespace, final Element element, String id, final Bundle options) {
+ public Iq publishElement(
+ final String namespace, final Element element, String id, final Bundle options) {
final Element item = new Element("item");
item.setAttribute("id", id);
item.addChild(element);
@@ -204,8 +205,7 @@ public class IqGenerator extends AbstractGenerator {
public Iq publishAvatarMetadata(final Avatar avatar, final Bundle options) {
final Element item = new Element("item");
item.setAttribute("id", avatar.sha1sum);
- final Element metadata = item
- .addChild("metadata", Namespace.AVATAR_METADATA);
+ final Element metadata = item.addChild("metadata", Namespace.AVATAR_METADATA);
final Element info = metadata.addChild("info");
info.setAttribute("bytes", avatar.size);
info.setAttribute("id", avatar.sha1sum);
@@ -292,7 +292,7 @@ public class IqGenerator extends AbstractGenerator {
if (password != null) {
conference.addChild("password").setContent(password);
}
- conference.setAttribute("autojoin",String.valueOf(autojoin));
+ conference.setAttribute("autojoin", String.valueOf(autojoin));
conference.addChild(bookmark.getExtensions());
return conference;
}
@@ -315,8 +315,12 @@ public class IqGenerator extends AbstractGenerator {
return displayed;
}
- public Iq publishBundles(final SignedPreKeyRecord signedPreKeyRecord, final IdentityKey identityKey,
- final Set preKeyRecords, final int deviceId, Bundle publishOptions) {
+ public Iq publishBundles(
+ final SignedPreKeyRecord signedPreKeyRecord,
+ final IdentityKey identityKey,
+ final Set preKeyRecords,
+ final int deviceId,
+ Bundle publishOptions) {
final Element item = new Element("item");
item.setAttribute("id", "current");
final Element bundle = item.addChild("bundle", AxolotlService.PEP_PREFIX);
@@ -325,21 +329,26 @@ public class IqGenerator extends AbstractGenerator {
ECPublicKey publicKey = signedPreKeyRecord.getKeyPair().getPublicKey();
signedPreKeyPublic.setContent(Base64.encodeToString(publicKey.serialize(), Base64.NO_WRAP));
final Element signedPreKeySignature = bundle.addChild("signedPreKeySignature");
- signedPreKeySignature.setContent(Base64.encodeToString(signedPreKeyRecord.getSignature(), Base64.NO_WRAP));
+ signedPreKeySignature.setContent(
+ Base64.encodeToString(signedPreKeyRecord.getSignature(), Base64.NO_WRAP));
final Element identityKeyElement = bundle.addChild("identityKey");
- identityKeyElement.setContent(Base64.encodeToString(identityKey.serialize(), Base64.NO_WRAP));
+ identityKeyElement.setContent(
+ Base64.encodeToString(identityKey.serialize(), Base64.NO_WRAP));
final Element prekeys = bundle.addChild("prekeys", AxolotlService.PEP_PREFIX);
for (PreKeyRecord preKeyRecord : preKeyRecords) {
final Element prekey = prekeys.addChild("preKeyPublic");
prekey.setAttribute("preKeyId", preKeyRecord.getId());
- prekey.setContent(Base64.encodeToString(preKeyRecord.getKeyPair().getPublicKey().serialize(), Base64.NO_WRAP));
+ prekey.setContent(
+ Base64.encodeToString(
+ preKeyRecord.getKeyPair().getPublicKey().serialize(), Base64.NO_WRAP));
}
return publish(AxolotlService.PEP_BUNDLES + ":" + deviceId, item, publishOptions);
}
- public Iq publishVerification(byte[] signature, X509Certificate[] certificates, final int deviceId) {
+ public Iq publishVerification(
+ byte[] signature, X509Certificate[] certificates, final int deviceId) {
final Element item = new Element("item");
item.setAttribute("id", "current");
final Element verification = item.addChild("verification", AxolotlService.PEP_PREFIX);
@@ -347,13 +356,16 @@ public class IqGenerator extends AbstractGenerator {
for (int i = 0; i < certificates.length; ++i) {
try {
Element certificate = chain.addChild("certificate");
- certificate.setContent(Base64.encodeToString(certificates[i].getEncoded(), Base64.NO_WRAP));
+ certificate.setContent(
+ Base64.encodeToString(certificates[i].getEncoded(), Base64.NO_WRAP));
certificate.setAttribute("index", i);
} catch (CertificateEncodingException e) {
Log.d(Config.LOGTAG, "could not encode certificate");
}
}
- verification.addChild("signature").setContent(Base64.encodeToString(signature, Base64.NO_WRAP));
+ verification
+ .addChild("signature")
+ .setContent(Base64.encodeToString(signature, Base64.NO_WRAP));
return publish(AxolotlService.PEP_VERIFICATION + ":" + deviceId, item);
}
@@ -366,7 +378,7 @@ public class IqGenerator extends AbstractGenerator {
if (mam.muc()) {
packet.setTo(mam.getWith());
} else if (mam.getWith() != null) {
- data.put("with", mam.getWith().toEscapedString());
+ data.put("with", mam.getWith().toString());
}
final long start = mam.getStart();
final long end = mam.getEnd();
@@ -395,7 +407,8 @@ public class IqGenerator extends AbstractGenerator {
return iq;
}
- public Iq generateSetBlockRequest(final Jid jid, final boolean reportSpam, final String serverMsgId) {
+ public Iq generateSetBlockRequest(
+ final Jid jid, final boolean reportSpam, final String serverMsgId) {
final Iq iq = new Iq(Iq.Type.SET);
final Element block = iq.addChild("block", Namespace.BLOCKING);
final Element item = block.addChild("item").setAttribute("jid", jid);
@@ -499,7 +512,9 @@ public class IqGenerator extends AbstractGenerator {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
- return Base64.encodeToString(bb.array(), Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP) + name.substring(pos);
+ return Base64.encodeToString(
+ bb.array(), Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP)
+ + name.substring(pos);
} catch (Exception e) {
return name;
}
@@ -508,7 +523,8 @@ public class IqGenerator extends AbstractGenerator {
}
}
- public static Iq generateCreateAccountWithCaptcha(final Account account, final String id, final Data data) {
+ public static Iq generateCreateAccountWithCaptcha(
+ final Account account, final String id, final Data data) {
final Iq register = new Iq(Iq.Type.SET);
register.setFrom(account.getJid().asBareJid());
register.setTo(account.getDomain());
@@ -534,7 +550,7 @@ public class IqGenerator extends AbstractGenerator {
data.put("token", token);
data.put("android-id", deviceId);
if (muc != null) {
- data.put("muc", muc.toEscapedString());
+ data.put("muc", muc.toString());
}
data.submit();
command.addChild(data);
@@ -581,7 +597,9 @@ public class IqGenerator extends AbstractGenerator {
public Iq queryAffiliation(Conversation conversation, String affiliation) {
final Iq packet = new Iq(Iq.Type.GET);
packet.setTo(conversation.getJid().asBareJid());
- packet.query("http://jabber.org/protocol/muc#admin").addChild("item").setAttribute("affiliation", affiliation);
+ packet.query("http://jabber.org/protocol/muc#admin")
+ .addChild("item")
+ .setAttribute("affiliation", affiliation);
return packet;
}
@@ -593,9 +611,9 @@ public class IqGenerator extends AbstractGenerator {
options.putString("muc#roomconfig_whois", "anyone");
options.putString("muc#roomconfig_changesubject", "0");
options.putString("muc#roomconfig_allowinvites", "0");
- options.putString("muc#roomconfig_enablearchiving", "1"); //prosody
- options.putString("mam", "1"); //ejabberd community
- options.putString("muc#roomconfig_mam", "1"); //ejabberd saas
+ options.putString("muc#roomconfig_enablearchiving", "1"); // prosody
+ options.putString("mam", "1"); // ejabberd community
+ options.putString("muc#roomconfig_mam", "1"); // ejabberd saas
return options;
}
@@ -606,9 +624,9 @@ public class IqGenerator extends AbstractGenerator {
options.putString("muc#roomconfig_publicroom", "1");
options.putString("muc#roomconfig_whois", "moderators");
options.putString("muc#roomconfig_changesubject", "0");
- options.putString("muc#roomconfig_enablearchiving", "1"); //prosody
- options.putString("mam", "1"); //ejabberd community
- options.putString("muc#roomconfig_mam", "1"); //ejabberd saas
+ options.putString("muc#roomconfig_enablearchiving", "1"); // prosody
+ options.putString("mam", "1"); // ejabberd community
+ options.putString("muc#roomconfig_mam", "1"); // ejabberd saas
return options;
}
@@ -648,7 +666,7 @@ public class IqGenerator extends AbstractGenerator {
public Iq queryDiscoInfo(final Jid jid) {
final Iq packet = new Iq(Iq.Type.GET);
packet.setTo(jid);
- packet.addChild("query",Namespace.DISCO_INFO);
+ packet.addChild("query", Namespace.DISCO_INFO);
return packet;
}
diff --git a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java
index 3530097886f485c99a553082de826917abe8a6e0..3b40c82b19a9392dff925b9659706ddcc6bf54c8 100644
--- a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java
@@ -15,80 +15,82 @@ import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.xmpp.model.stanza.Stanza;
public abstract class AbstractParser {
- protected final XmppConnectionService mXmppConnectionService;
- protected final Account account;
-
- protected AbstractParser(final XmppConnectionService service, final Account account) {
- this.mXmppConnectionService = service;
- this.account = account;
- }
-
- public static Long parseTimestamp(Element element, Long d) {
- return parseTimestamp(element,d,false);
- }
-
- public static Long parseTimestamp(Element element, Long d, boolean ignoreCsiAndSm) {
- long min = Long.MAX_VALUE;
- boolean returnDefault = true;
- final Jid to;
- if (ignoreCsiAndSm && element instanceof Stanza stanza) {
- to = stanza.getTo();
- } else {
- to = null;
- }
- for(Element child : element.getChildren()) {
- if ("delay".equals(child.getName()) && "urn:xmpp:delay".equals(child.getNamespace())) {
- final Jid f = to == null ? null : InvalidJid.getNullForInvalid(child.getAttributeAsJid("from"));
- if (f != null && (to.asBareJid().equals(f) || to.getDomain().equals(f))) {
- continue;
- }
- final String stamp = child.getAttribute("stamp");
- if (stamp != null) {
- try {
- min = Math.min(min,AbstractParser.parseTimestamp(stamp));
- returnDefault = false;
- } catch (Throwable t) {
- //ignore
- }
- }
- }
- }
- if (returnDefault) {
- return d;
- } else {
- return min;
- }
- }
-
- public static long parseTimestamp(Element element) {
- return parseTimestamp(element, System.currentTimeMillis());
- }
-
- public static long parseTimestamp(String timestamp) throws ParseException {
- timestamp = timestamp.replace("Z", "+0000");
- SimpleDateFormat dateFormat;
- long ms;
- if (timestamp.length() >= 25 && timestamp.charAt(19) == '.') {
- String millis = timestamp.substring(19,timestamp.length() - 5);
- try {
- double fractions = Double.parseDouble("0" + millis);
- ms = Math.round(1000 * fractions);
- } catch (NumberFormatException e) {
- ms = 0;
- }
- } else {
- ms = 0;
- }
- timestamp = timestamp.substring(0,19)+timestamp.substring(timestamp.length() -5);
- dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",Locale.US);
- return Math.min(dateFormat.parse(timestamp).getTime()+ms, System.currentTimeMillis());
- }
+ protected final XmppConnectionService mXmppConnectionService;
+ protected final Account account;
+
+ protected AbstractParser(final XmppConnectionService service, final Account account) {
+ this.mXmppConnectionService = service;
+ this.account = account;
+ }
+
+ public static Long parseTimestamp(Element element, Long d) {
+ return parseTimestamp(element, d, false);
+ }
+
+ public static Long parseTimestamp(Element element, Long d, boolean ignoreCsiAndSm) {
+ long min = Long.MAX_VALUE;
+ boolean returnDefault = true;
+ final Jid to;
+ if (ignoreCsiAndSm && element instanceof Stanza stanza) {
+ to = stanza.getTo();
+ } else {
+ to = null;
+ }
+ for (Element child : element.getChildren()) {
+ if ("delay".equals(child.getName()) && "urn:xmpp:delay".equals(child.getNamespace())) {
+ final Jid f =
+ to == null
+ ? null
+ : Jid.Invalid.getNullForInvalid(child.getAttributeAsJid("from"));
+ if (f != null && (to.asBareJid().equals(f) || to.getDomain().equals(f))) {
+ continue;
+ }
+ final String stamp = child.getAttribute("stamp");
+ if (stamp != null) {
+ try {
+ min = Math.min(min, AbstractParser.parseTimestamp(stamp));
+ returnDefault = false;
+ } catch (Throwable t) {
+ // ignore
+ }
+ }
+ }
+ }
+ if (returnDefault) {
+ return d;
+ } else {
+ return min;
+ }
+ }
+
+ public static long parseTimestamp(Element element) {
+ return parseTimestamp(element, System.currentTimeMillis());
+ }
+
+ public static long parseTimestamp(String timestamp) throws ParseException {
+ timestamp = timestamp.replace("Z", "+0000");
+ SimpleDateFormat dateFormat;
+ long ms;
+ if (timestamp.length() >= 25 && timestamp.charAt(19) == '.') {
+ String millis = timestamp.substring(19, timestamp.length() - 5);
+ try {
+ double fractions = Double.parseDouble("0" + millis);
+ ms = Math.round(1000 * fractions);
+ } catch (NumberFormatException e) {
+ ms = 0;
+ }
+ } else {
+ ms = 0;
+ }
+ timestamp = timestamp.substring(0, 19) + timestamp.substring(timestamp.length() - 5);
+ dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
+ return Math.min(dateFormat.parse(timestamp).getTime() + ms, System.currentTimeMillis());
+ }
public static long getTimestamp(final String input) throws ParseException {
if (input == null) {
@@ -121,107 +123,107 @@ public abstract class AbstractParser {
}
}
- protected void updateLastseen(final Account account, final Jid from) {
- final Contact contact = account.getRoster().getContact(from);
- contact.setLastResource(from.isBareJid() ? "" : from.getResource());
- }
-
- protected static String avatarData(Element items) {
- Element item = items.findChild("item");
- if (item == null) {
- return null;
- }
- return item.findChildContent("data", "urn:xmpp:avatar:data");
- }
-
- public static MucOptions.User parseItem(Conversation conference, Element item) {
- return parseItem(conference,item,null,null,null,new Element("hats", "urn:xmpp:hats:0"));
- }
-
- public static MucOptions.User parseItem(final Conversation conference, Element item, Jid fullJid, final Element occupantId, final String nicknameIn, final Element hatsEl) {
- final String local = conference.getJid().getLocal();
- final String domain = conference.getJid().getDomain().toEscapedString();
- String affiliation = item.getAttribute("affiliation");
- String role = item.getAttribute("role");
- String nick = item.getAttribute("nick");
- if (nick != null && fullJid == null) {
- try {
- fullJid = Jid.of(local, domain, nick);
- } catch (IllegalArgumentException e) {
- fullJid = null;
- }
- }
- Jid realJid = item.getAttributeAsJid("jid");
- if (fullJid != null) nick = fullJid.getResource();
- String nickname = null;
- if (nick != null && nicknameIn != null) nickname = nick.equals(nicknameIn) ? nick : null;
- try {
- if (nickname == null && nicknameIn != null && nick != null && gnu.inet.encoding.Punycode.decode(nick).equals(nicknameIn)) {
- nickname = nicknameIn;
- }
- } catch (final Exception e) { }
- Set hats = new TreeSet<>();
- for (Element hat : hatsEl.getChildren()) {
- if ("hat".equals(hat.getName()) && ("urn:xmpp:hats:0".equals(hat.getNamespace()) || "xmpp:prosody.im/protocol/hats:1".equals(hat.getNamespace()))) {
- hats.add(new MucOptions.Hat(hat));
- }
- }
- MucOptions.User user = new MucOptions.User(conference.getMucOptions(), fullJid, occupantId == null ? null : occupantId.getAttribute("id"), nickname, hatsEl == null ? null : hats);
- if (InvalidJid.isValid(realJid)) {
- user.setRealJid(realJid);
- }
- user.setAffiliation(affiliation);
- user.setRole(role);
- return user;
- }
-
- public static String extractErrorMessage(final Element packet) {
- final Element error = packet.findChild("error");
- if (error != null && error.getChildren().size() > 0) {
- final List errorNames = orderedElementNames(error.getChildren());
- final String text = error.findChildContent("text");
- if (text != null && !text.trim().isEmpty()) {
- return prefixError(errorNames)+text;
- } else if (errorNames.size() > 0){
- return prefixError(errorNames)+errorNames.get(0).replace("-"," ");
- }
- }
- return null;
- }
-
- public static String errorMessage(Element packet) {
- final Element error = packet.findChild("error");
- if (error != null && error.getChildren().size() > 0) {
- final List errorNames = orderedElementNames(error.getChildren());
- final String text = error.findChildContent("text");
- if (text != null && !text.trim().isEmpty()) {
- return text;
- } else if (errorNames.size() > 0){
- return errorNames.get(0).replace("-"," ");
- }
- }
- return null;
- }
-
- private static String prefixError(List errorNames) {
- if (errorNames.size() > 0) {
- return errorNames.get(0)+'\u001f';
- }
- return "";
- }
-
- private static List orderedElementNames(List children) {
- List names = new ArrayList<>();
- for(Element child : children) {
- final String name = child.getName();
- if (name != null && !name.equals("text")) {
- if ("urn:ietf:params:xml:ns:xmpp-stanzas".equals(child.getNamespace())) {
- names.add(name);
- } else {
- names.add(0, name);
- }
- }
- }
- return names;
- }
+ protected void updateLastseen(final Account account, final Jid from) {
+ final Contact contact = account.getRoster().getContact(from);
+ contact.setLastResource(from.isBareJid() ? "" : from.getResource());
+ }
+
+ protected static String avatarData(Element items) {
+ Element item = items.findChild("item");
+ if (item == null) {
+ return null;
+ }
+ return item.findChildContent("data", "urn:xmpp:avatar:data");
+ }
+
+ public static MucOptions.User parseItem(Conversation conference, Element item) {
+ return parseItem(conference,item,null,null,null,new Element("hats", "urn:xmpp:hats:0"));
+ }
+
+ public static MucOptions.User parseItem(final Conversation conference, Element item, Jid fullJid, final Element occupantId, final String nicknameIn, final Element hatsEl) {
+ final String local = conference.getJid().getLocal();
+ final String domain = conference.getJid().getDomain().toString();
+ String affiliation = item.getAttribute("affiliation");
+ String role = item.getAttribute("role");
+ String nick = item.getAttribute("nick");
+ if (nick != null && fullJid == null) {
+ try {
+ fullJid = Jid.of(local, domain, nick);
+ } catch (IllegalArgumentException e) {
+ fullJid = null;
+ }
+ }
+ Jid realJid = item.getAttributeAsJid("jid");
+ if (fullJid != null) nick = fullJid.getResource();
+ String nickname = null;
+ if (nick != null && nicknameIn != null) nickname = nick.equals(nicknameIn) ? nick : null;
+ try {
+ if (nickname == null && nicknameIn != null && nick != null && gnu.inet.encoding.Punycode.decode(nick).equals(nicknameIn)) {
+ nickname = nicknameIn;
+ }
+ } catch (final Exception e) { }
+ Set hats = new TreeSet<>();
+ for (Element hat : hatsEl.getChildren()) {
+ if ("hat".equals(hat.getName()) && ("urn:xmpp:hats:0".equals(hat.getNamespace()) || "xmpp:prosody.im/protocol/hats:1".equals(hat.getNamespace()))) {
+ hats.add(new MucOptions.Hat(hat));
+ }
+ }
+ MucOptions.User user = new MucOptions.User(conference.getMucOptions(), fullJid, occupantId == null ? null : occupantId.getAttribute("id"), nickname, hatsEl == null ? null : hats);
+ if (Jid.Invalid.isValid(realJid)) {
+ user.setRealJid(realJid);
+ }
+ user.setAffiliation(affiliation);
+ user.setRole(role);
+ return user;
+ }
+
+ public static String extractErrorMessage(final Element packet) {
+ final Element error = packet.findChild("error");
+ if (error != null && error.getChildren().size() > 0) {
+ final List errorNames = orderedElementNames(error.getChildren());
+ final String text = error.findChildContent("text");
+ if (text != null && !text.trim().isEmpty()) {
+ return prefixError(errorNames) + text;
+ } else if (errorNames.size() > 0) {
+ return prefixError(errorNames) + errorNames.get(0).replace("-", " ");
+ }
+ }
+ return null;
+ }
+
+ public static String errorMessage(Element packet) {
+ final Element error = packet.findChild("error");
+ if (error != null && error.getChildren().size() > 0) {
+ final List errorNames = orderedElementNames(error.getChildren());
+ final String text = error.findChildContent("text");
+ if (text != null && !text.trim().isEmpty()) {
+ return text;
+ } else if (errorNames.size() > 0) {
+ return errorNames.get(0).replace("-", " ");
+ }
+ }
+ return null;
+ }
+
+ private static String prefixError(List errorNames) {
+ if (errorNames.size() > 0) {
+ return errorNames.get(0) + '\u001f';
+ }
+ return "";
+ }
+
+ private static List orderedElementNames(List children) {
+ List names = new ArrayList<>();
+ for (Element child : children) {
+ final String name = child.getName();
+ if (name != null && !name.equals("text")) {
+ if ("urn:ietf:params:xml:ns:xmpp-stanzas".equals(child.getNamespace())) {
+ names.add(name);
+ } else {
+ names.add(0, name);
+ }
+ }
+ }
+ return names;
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java
index 95b239802f50b767fe0c3fb23a71f21ea234095a..c562da2ebc601ffa1a9c2dac393bb58c1846263a 100644
--- a/src/main/java/eu/siacs/conversations/parser/IqParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java
@@ -3,18 +3,21 @@ package eu.siacs.conversations.parser;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
-
import androidx.annotation.NonNull;
-
import com.google.common.base.CharMatcher;
import com.google.common.io.BaseEncoding;
-
-import org.whispersystems.libsignal.IdentityKey;
-import org.whispersystems.libsignal.InvalidKeyException;
-import org.whispersystems.libsignal.ecc.Curve;
-import org.whispersystems.libsignal.ecc.ECPublicKey;
-import org.whispersystems.libsignal.state.PreKeyBundle;
-
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.crypto.axolotl.AxolotlService;
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Contact;
+import eu.siacs.conversations.entities.Room;
+import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xml.Namespace;
+import eu.siacs.conversations.xmpp.Jid;
+import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
+import eu.siacs.conversations.xmpp.forms.Data;
+import im.conversations.android.xmpp.model.stanza.Iq;
import java.io.ByteArrayInputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
@@ -37,12 +40,17 @@ import eu.siacs.conversations.entities.Room;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
import eu.siacs.conversations.xmpp.forms.Data;
import im.conversations.android.xmpp.model.stanza.Iq;
+import org.whispersystems.libsignal.IdentityKey;
+import org.whispersystems.libsignal.InvalidKeyException;
+import org.whispersystems.libsignal.ecc.Curve;
+import org.whispersystems.libsignal.ecc.ECPublicKey;
+import org.whispersystems.libsignal.state.PreKeyBundle;
+
public class IqParser extends AbstractParser implements Consumer {
public IqParser(final XmppConnectionService service, final Account account) {
@@ -95,8 +103,7 @@ public class IqParser extends AbstractParser implements Consumer {
TextUtils.isEmpty(roomName) ? name : roomName,
description,
language,
- nusers
- );
+ nusers);
}
private void rosterItems(final Account account, final Element query) {
@@ -106,14 +113,16 @@ public class IqParser extends AbstractParser implements Consumer {
}
for (final Element item : query.getChildren()) {
if (item.getName().equals("item")) {
- final Jid jid = InvalidJid.getNullForInvalid(item.getAttributeAsJid("jid"));
+ final Jid jid = Jid.Invalid.getNullForInvalid(item.getAttributeAsJid("jid"));
if (jid == null) {
continue;
}
final String name = item.getAttribute("name");
final String subscription = item.getAttribute("subscription");
final Contact contact = account.getRoster().getContact(jid);
- boolean bothPre = contact.getOption(Contact.Options.TO) && contact.getOption(Contact.Options.FROM);
+ boolean bothPre =
+ contact.getOption(Contact.Options.TO)
+ && contact.getOption(Contact.Options.FROM);
if (!contact.getOption(Contact.Options.DIRTY_PUSH)) {
contact.setServerName(name);
contact.parseGroupsFromElement(item);
@@ -127,9 +136,15 @@ public class IqParser extends AbstractParser implements Consumer {
contact.resetOption(Contact.Options.DIRTY_PUSH);
contact.parseSubscriptionFromElement(item);
}
- boolean both = contact.getOption(Contact.Options.TO) && contact.getOption(Contact.Options.FROM);
+ boolean both =
+ contact.getOption(Contact.Options.TO)
+ && contact.getOption(Contact.Options.FROM);
if ((both != bothPre) && both) {
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": gained mutual presence subscription with " + contact.getJid());
+ Log.d(
+ Config.LOGTAG,
+ account.getJid().asBareJid()
+ + ": gained mutual presence subscription with "
+ + contact.getJid());
AxolotlService axolotlService = account.getAxolotlService();
if (axolotlService != null) {
axolotlService.clearErrorsInFetchStatusMap(contact.getJid());
@@ -182,7 +197,15 @@ public class IqParser extends AbstractParser implements Consumer {
Integer id = Integer.valueOf(device.getAttribute("id"));
deviceIds.add(id);
} catch (NumberFormatException e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Encountered invalid node in PEP (" + e.getMessage() + "):" + device.toString() + ", skipping...");
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Encountered invalid node in PEP ("
+ + e.getMessage()
+ + "):"
+ + device.toString()
+ + ", skipping...");
}
}
}
@@ -211,7 +234,12 @@ public class IqParser extends AbstractParser implements Consumer {
try {
publicKey = Curve.decodePoint(base64decode(signedPreKeyPublic), 0);
} catch (final IllegalArgumentException | InvalidKeyException e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Invalid signedPreKeyPublic in PEP: " + e.getMessage());
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Invalid signedPreKeyPublic in PEP: "
+ + e.getMessage());
}
return publicKey;
}
@@ -224,7 +252,9 @@ public class IqParser extends AbstractParser implements Consumer {
try {
return base64decode(signedPreKeySignature);
} catch (final IllegalArgumentException e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : Invalid base64 in signedPreKeySignature");
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX + " : Invalid base64 in signedPreKeySignature");
return null;
}
}
@@ -237,7 +267,12 @@ public class IqParser extends AbstractParser implements Consumer {
try {
return new IdentityKey(base64decode(identityKey), 0);
} catch (final IllegalArgumentException | InvalidKeyException e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Invalid identityKey in PEP: " + e.getMessage());
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Invalid identityKey in PEP: "
+ + e.getMessage());
return null;
}
}
@@ -246,7 +281,12 @@ public class IqParser extends AbstractParser implements Consumer {
Map preKeyRecords = new HashMap<>();
Element item = getItem(packet);
if (item == null) {
- Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Couldn't find - in bundle IQ packet: " + packet);
+ Log.d(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Couldn't find
- in bundle IQ packet: "
+ + packet);
return null;
}
final Element bundleElement = item.findChild("bundle");
@@ -255,12 +295,22 @@ public class IqParser extends AbstractParser implements Consumer {
}
final Element prekeysElement = bundleElement.findChild("prekeys");
if (prekeysElement == null) {
- Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Couldn't find in bundle IQ packet: " + packet);
+ Log.d(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Couldn't find in bundle IQ packet: "
+ + packet);
return null;
}
for (Element preKeyPublicElement : prekeysElement.getChildren()) {
if (!preKeyPublicElement.getName().equals("preKeyPublic")) {
- Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Encountered unexpected tag in prekeys list: " + preKeyPublicElement);
+ Log.d(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Encountered unexpected tag in prekeys list: "
+ + preKeyPublicElement);
continue;
}
final String preKey = preKeyPublicElement.getContent();
@@ -273,9 +323,22 @@ public class IqParser extends AbstractParser implements Consumer {
final ECPublicKey preKeyPublic = Curve.decodePoint(base64decode(preKey), 0);
preKeyRecords.put(preKeyId, preKeyPublic);
} catch (NumberFormatException e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "could not parse preKeyId from preKey " + preKeyPublicElement.toString());
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "could not parse preKeyId from preKey "
+ + preKeyPublicElement.toString());
} catch (Throwable e) {
- Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX + " : " + "Invalid preKeyPublic (ID=" + preKeyId + ") in PEP: " + e.getMessage() + ", skipping...");
+ Log.e(
+ Config.LOGTAG,
+ AxolotlService.LOGPREFIX
+ + " : "
+ + "Invalid preKeyPublic (ID="
+ + preKeyId
+ + ") in PEP: "
+ + e.getMessage()
+ + ", skipping...");
}
}
return preKeyRecords;
@@ -287,7 +350,8 @@ public class IqParser extends AbstractParser implements Consumer {
public static Pair verification(final Iq packet) {
Element item = getItem(packet);
- Element verification = item != null ? item.findChild("verification", AxolotlService.PEP_PREFIX) : null;
+ Element verification =
+ item != null ? item.findChild("verification", AxolotlService.PEP_PREFIX) : null;
Element chain = verification != null ? verification.findChild("chain") : null;
String signature = verification != null ? verification.findChildContent("signature") : null;
if (chain != null && signature != null) {
@@ -301,7 +365,11 @@ public class IqParser extends AbstractParser implements Consumer {
if (cert == null) {
continue;
}
- certificates[i] = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(BaseEncoding.base64().decode(cert)));
+ certificates[i] =
+ (X509Certificate)
+ certificateFactory.generateCertificate(
+ new ByteArrayInputStream(
+ BaseEncoding.base64().decode(cert)));
++i;
}
return new Pair<>(certificates, BaseEncoding.base64().decode(signature));
@@ -333,8 +401,15 @@ public class IqParser extends AbstractParser implements Consumer {
|| signedPreKeySignature.length == 0) {
return null;
}
- return new PreKeyBundle(0, 0, 0, null,
- signedPreKeyId, signedPreKeyPublic, signedPreKeySignature, identityKey);
+ return new PreKeyBundle(
+ 0,
+ 0,
+ 0,
+ null,
+ signedPreKeyId,
+ signedPreKeyPublic,
+ signedPreKeySignature,
+ identityKey);
}
public static List preKeys(final Iq preKeys) {
@@ -343,8 +418,7 @@ public class IqParser extends AbstractParser implements Consumer {
if (preKeyPublics != null) {
for (Integer preKeyId : preKeyPublics.keySet()) {
ECPublicKey preKeyPublic = preKeyPublics.get(preKeyId);
- bundles.add(new PreKeyBundle(0, 0, preKeyId, preKeyPublic,
- 0, null, null, null));
+ bundles.add(new PreKeyBundle(0, 0, preKeyId, preKeyPublic, 0, null, null, null));
}
}
@@ -364,15 +438,19 @@ public class IqParser extends AbstractParser implements Consumer {
account.getRoster().markAllAsNotInRoster();
}
this.rosterItems(account, query);
- } else if ((packet.hasChild("block", Namespace.BLOCKING) || packet.hasChild("blocklist", Namespace.BLOCKING)) &&
- packet.fromServer(account)) {
+ } else if ((packet.hasChild("block", Namespace.BLOCKING)
+ || packet.hasChild("blocklist", Namespace.BLOCKING))
+ && packet.fromServer(account)) {
// Block list or block push.
Log.d(Config.LOGTAG, "Received blocklist update from server");
final Element blocklist = packet.findChild("blocklist", Namespace.BLOCKING);
final Element block = packet.findChild("block", Namespace.BLOCKING);
- final Collection items = blocklist != null ? blocklist.getChildren() :
- (block != null ? block.getChildren() : null);
- // If this is a response to a blocklist query, clear the block list and replace with the new one.
+ final Collection items =
+ blocklist != null
+ ? blocklist.getChildren()
+ : (block != null ? block.getChildren() : null);
+ // If this is a response to a blocklist query, clear the block list and replace with the
+ // new one.
// Otherwise, just update the existing blocklist.
if (packet.getType() == Iq.Type.RESULT) {
account.clearBlocklist();
@@ -383,7 +461,8 @@ public class IqParser extends AbstractParser implements Consumer {
// Create a collection of Jids from the packet
for (final Element item : items) {
if (item.getName().equals("item")) {
- final Jid jid = InvalidJid.getNullForInvalid(item.getAttributeAsJid("jid"));
+ final Jid jid =
+ Jid.Invalid.getNullForInvalid(item.getAttributeAsJid("jid"));
if (jid != null) {
jids.add(jid);
}
@@ -406,10 +485,12 @@ public class IqParser extends AbstractParser implements Consumer {
final Iq response = packet.generateResponse(Iq.Type.RESULT);
mXmppConnectionService.sendIqPacket(account, response, null);
}
- } else if (packet.hasChild("unblock", Namespace.BLOCKING) &&
- packet.fromServer(account) && packet.getType() == Iq.Type.SET) {
+ } else if (packet.hasChild("unblock", Namespace.BLOCKING)
+ && packet.fromServer(account)
+ && packet.getType() == Iq.Type.SET) {
Log.d(Config.LOGTAG, "Received unblock update from server");
- final Collection items = packet.findChild("unblock", Namespace.BLOCKING).getChildren();
+ final Collection items =
+ packet.findChild("unblock", Namespace.BLOCKING).getChildren();
if (items.isEmpty()) {
// No children to unblock == unblock all
account.getBlocklist().clear();
@@ -417,7 +498,8 @@ public class IqParser extends AbstractParser implements Consumer {
final Collection jids = new ArrayList<>(items.size());
for (final Element item : items) {
if (item.getName().equals("item")) {
- final Jid jid = InvalidJid.getNullForInvalid(item.getAttributeAsJid("jid"));
+ final Jid jid =
+ Jid.Invalid.getNullForInvalid(item.getAttributeAsJid("jid"));
if (jid != null) {
jids.add(jid);
}
@@ -431,10 +513,10 @@ public class IqParser extends AbstractParser implements Consumer {
} else if (packet.hasChild("open", "http://jabber.org/protocol/ibb")
|| packet.hasChild("data", "http://jabber.org/protocol/ibb")
|| packet.hasChild("close", "http://jabber.org/protocol/ibb")) {
- mXmppConnectionService.getJingleConnectionManager()
- .deliverIbbPacket(account, packet);
+ mXmppConnectionService.getJingleConnectionManager().deliverIbbPacket(account, packet);
} else if (packet.hasChild("query", "http://jabber.org/protocol/disco#info")) {
- final Iq response = mXmppConnectionService.getIqGenerator().discoResponse(account, packet);
+ final Iq response =
+ mXmppConnectionService.getIqGenerator().discoResponse(account, packet);
mXmppConnectionService.sendIqPacket(account, response, null);
} else if (packet.hasChild("query", "jabber:iq:version") && isGet) {
final Iq response = mXmppConnectionService.getIqGenerator().versionResponse(packet);
@@ -453,7 +535,8 @@ public class IqParser extends AbstractParser implements Consumer {
response = mXmppConnectionService.getIqGenerator().entityTimeResponse(packet);
}
mXmppConnectionService.sendIqPacket(account, response, null);
- } else if (packet.hasChild("push", Namespace.UNIFIED_PUSH) && packet.getType() == Iq.Type.SET) {
+ } else if (packet.hasChild("push", Namespace.UNIFIED_PUSH)
+ && packet.getType() == Iq.Type.SET) {
final Jid transport = packet.getFrom();
final Element push = packet.findChild("push", Namespace.UNIFIED_PUSH);
final boolean success =
@@ -485,5 +568,4 @@ public class IqParser extends AbstractParser implements Consumer {
}
}
}
-
}
diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
index cc2dc8bd975d5eb90fd9f3c75a80f0123057c496..7c19680cc75242b9ccd6139d2e301a6f07714b8a 100644
--- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
@@ -59,25 +59,27 @@ import eu.siacs.conversations.utils.Emoticons;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.LocalizedContent;
import eu.siacs.conversations.xml.Namespace;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
-import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.forms.Data;
import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
import eu.siacs.conversations.xmpp.pep.Avatar;
import im.conversations.android.xmpp.model.Extension;
+import im.conversations.android.xmpp.model.axolotl.Encrypted;
import im.conversations.android.xmpp.model.carbons.Received;
import im.conversations.android.xmpp.model.carbons.Sent;
import im.conversations.android.xmpp.model.correction.Replace;
import im.conversations.android.xmpp.model.forward.Forwarded;
+import im.conversations.android.xmpp.model.markers.Displayed;
import im.conversations.android.xmpp.model.occupant.OccupantId;
import im.conversations.android.xmpp.model.reactions.Reactions;
-public class MessageParser extends AbstractParser implements Consumer {
+public class MessageParser extends AbstractParser
+ implements Consumer {
- private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss", Locale.ENGLISH);
+ private static final SimpleDateFormat TIME_FORMAT =
+ new SimpleDateFormat("HH:mm:ss", Locale.ENGLISH);
private static final List JINGLE_MESSAGE_ELEMENT_NAMES =
Arrays.asList("accept", "propose", "proceed", "reject", "retract", "ringing", "finish");
@@ -86,7 +88,8 @@ public class MessageParser extends AbstractParser implements Consumer deviceIds = IqParser.deviceIds(item);
- Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received PEP device list " + deviceIds + " update from " + from + ", processing... ");
+ Log.d(
+ Config.LOGTAG,
+ AxolotlService.getLogprefix(account)
+ + "Received PEP device list "
+ + deviceIds
+ + " update from "
+ + from
+ + ", processing... ");
final AxolotlService axolotlService = account.getAxolotlService();
axolotlService.registerDevices(from, deviceIds);
} else if (Namespace.BOOKMARKS.equals(node) && account.getJid().asBareJid().equals(from)) {
@@ -275,7 +321,8 @@ public class MessageParser extends AbstractParser implements Consumer f;
f = getForwardedMessagePacket(original, Received.class);
f = f == null ? getForwardedMessagePacket(original, Sent.class) : f;
@@ -471,10 +562,14 @@ public class MessageParser extends AbstractParser implements Consumer fallbacksBySourceId = Collections.emptySet();
if (conversationMultiMode) {
- final Jid fallback = conversation.getMucOptions().getTrueCounterpart(counterpart);
+ final Jid fallback =
+ conversation.getMucOptions().getTrueCounterpart(counterpart);
origin = getTrueCounterpart(query != null ? mucUserElement : null, fallback);
if (origin == null) {
try {
- fallbacksBySourceId = account.getAxolotlService().findCounterpartsBySourceId(XmppAxolotlMessage.parseSourceId(axolotlEncrypted));
+ fallbacksBySourceId =
+ account.getAxolotlService()
+ .findCounterpartsBySourceId(
+ XmppAxolotlMessage.parseSourceId(
+ axolotlEncrypted));
} catch (IllegalArgumentException e) {
- //ignoring
+ // ignoring
}
}
- if (origin == null && fallbacksBySourceId.size() == 0) {
- Log.d(Config.LOGTAG, "axolotl message in anonymous conference received and no possible fallbacks");
+ if (origin == null && fallbacksBySourceId.isEmpty()) {
+ Log.d(
+ Config.LOGTAG,
+ "axolotl message in anonymous conference received and no possible"
+ + " fallbacks");
return;
}
} else {
@@ -716,17 +867,40 @@ public class MessageParser extends AbstractParser implements Consumer 0);
- final LocalizedContent subject = packet.findInternationalizedChildContentInDefaultNamespace("subject");
- if (subject != null && conversation.getMucOptions().setSubject(subject.content)) {
+ final LocalizedContent subject =
+ packet.findInternationalizedChildContentInDefaultNamespace(
+ "subject");
+ if (subject != null
+ && conversation.getMucOptions().setSubject(subject.content)) {
mXmppConnectionService.updateConversation(conversation);
}
mXmppConnectionService.updateConversationUi();
@@ -1088,7 +1343,10 @@ public class MessageParser extends AbstractParser implements Consumer cryptoTargets = conversation.getAcceptedCryptoTargets();
if (cryptoTargets.remove(user.getRealJid())) {
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": removed " + jid + " from crypto targets of " + conversation.getName());
+ Log.d(
+ Config.LOGTAG,
+ account.getJid().asBareJid()
+ + ": removed "
+ + jid
+ + " from crypto targets of "
+ + conversation.getName());
conversation.setAcceptedCryptoTargets(cryptoTargets);
mXmppConnectionService.updateConversation(conversation);
}
@@ -1123,7 +1398,8 @@ public class MessageParser extends AbstractParser implements Consumer(reactions.getReactions());
- newReactions.removeAll(message.getReactions().stream().filter(r -> occupantId.equals(r.occupantId)).map(r -> r.reaction).collect(Collectors.toList()));
- final var combinedReactions =
- Reaction.withOccupantId(
- message.getReactions(),
- reactions.getReactions(),
- isReceived,
- counterpart,
- null,
- occupantId,
- message.getRemoteMsgId());
- message.setReactions(combinedReactions);
- mXmppConnectionService.updateMessage(message, false);
- if (isReceived) mXmppConnectionService.getNotificationService().push(message, counterpart, occupantId, newReactions);
- } else {
- Log.d(Config.LOGTAG, "message with id " + reactingTo + " not found");
- }
- } else {
- Log.d(
- Config.LOGTAG,
- "received reaction in channel w/o occupant ids. ignoring");
- }
- } else if (conversation.getMode() == Conversational.MODE_SINGLE) {
+ private void processReactions(
+ final Reactions reactions,
+ final Conversation conversation,
+ final boolean isTypeGroupChat,
+ final OccupantId occupant,
+ final Jid counterpart,
+ final Jid mucTrueCounterPart,
+ final int status,
+ final im.conversations.android.xmpp.model.stanza.Message packet) {
+ final String reactingTo = reactions.getId();
+ if (conversation != null && reactingTo != null) {
+ if (isTypeGroupChat && conversation.getMode() == Conversational.MODE_MULTI) {
+ final var mucOptions = conversation.getMucOptions();
+ final var occupantId = occupant == null ? null : occupant.getId();
+ if (occupantId != null) {
+ final boolean isReceived = !mucOptions.isSelf(occupantId);
final Message message;
- final var inMemoryMessage =
- conversation.findMessageWithUuidOrRemoteId(reactingTo);
+ final var inMemoryMessage = conversation.findMessageWithServerMsgId(reactingTo);
if (inMemoryMessage != null) {
message = inMemoryMessage;
} else {
message =
- mXmppConnectionService.databaseBackend.getMessageWithUuidOrRemoteId(
+ mXmppConnectionService.databaseBackend.getMessageWithServerMsgId(
conversation, reactingTo);
}
- final boolean isReceived;
- final Jid reactionFrom;
- if (packet.fromAccount(account)) {
- isReceived = false;
- reactionFrom = account.getJid().asBareJid();
- } else {
- isReceived = true;
- reactionFrom = counterpart;
- }
- packet.fromAccount(account);
if (message != null) {
final var newReactions = new HashSet<>(reactions.getReactions());
- newReactions.removeAll(message.getReactions().stream().filter(r -> reactionFrom.equals(r.from)).map(r -> r.reaction).collect(Collectors.toList()));
+ newReactions.removeAll(message.getReactions().stream().filter(r -> occupantId.equals(r.occupantId)).map(r -> r.reaction).collect(Collectors.toList()));
final var combinedReactions =
- Reaction.withFrom(
+ Reaction.withOccupantId(
message.getReactions(),
reactions.getReactions(),
isReceived,
- reactionFrom,
+ counterpart,
+ mucTrueCounterPart,
+ occupantId,
message.getRemoteMsgId());
message.setReactions(combinedReactions);
mXmppConnectionService.updateMessage(message, false);
- if (status < Message.STATUS_SEND) mXmppConnectionService.getNotificationService().push(message, counterpart, null, newReactions);
+ if (isReceived) mXmppConnectionService.getNotificationService().push(message, counterpart, occupantId, newReactions);
} else {
Log.d(Config.LOGTAG, "message with id " + reactingTo + " not found");
}
+ } else {
+ Log.d(Config.LOGTAG, "received reaction in channel w/o occupant ids. ignoring");
}
- }
- }
-
- final Element event = original.findChild("event", "http://jabber.org/protocol/pubsub#event");
- if (event != null && InvalidJid.hasValidFrom(original) && original.getFrom().isBareJid()) {
- if (event.hasChild("items")) {
- parseEvent(event, original.getFrom(), account);
- } else if (event.hasChild("delete")) {
- parseDeleteEvent(event, original.getFrom(), account);
- } else if (event.hasChild("purge")) {
- parsePurgeEvent(event, original.getFrom(), account);
- }
- }
-
- final String nick = packet.findChildContent("nick", Namespace.NICK);
- if (nick != null && InvalidJid.hasValidFrom(original)) {
- if (mXmppConnectionService.isMuc(account, from)) {
- return;
- }
- final Contact contact = account.getRoster().getContact(from);
- if (contact.setPresenceName(nick)) {
- mXmppConnectionService.syncRoster(account);
- mXmppConnectionService.getAvatarService().clear(contact);
+ } else {
+ final Message message;
+ final var inMemoryMessage = conversation.findMessageWithUuidOrRemoteId(reactingTo);
+ if (inMemoryMessage != null) {
+ message = inMemoryMessage;
+ } else {
+ message =
+ mXmppConnectionService.databaseBackend.getMessageWithUuidOrRemoteId(
+ conversation, reactingTo);
+ }
+ if (message == null) {
+ Log.d(Config.LOGTAG, "message with id " + reactingTo + " not found");
+ return;
+ }
+ final boolean isReceived;
+ final Jid reactionFrom;
+ if (conversation.getMode() == Conversational.MODE_MULTI) {
+ Log.d(Config.LOGTAG, "received reaction as MUC PM. triggering validation");
+ final var mucOptions = conversation.getMucOptions();
+ final var occupantId = occupant == null ? null : occupant.getId();
+ if (occupantId == null) {
+ Log.d(
+ Config.LOGTAG,
+ "received reaction via PM channel w/o occupant ids. ignoring");
+ return;
+ }
+ isReceived = !mucOptions.isSelf(occupantId);
+ if (isReceived) {
+ reactionFrom = counterpart;
+ } else {
+ if (!occupantId.equals(message.getOccupantId())) {
+ Log.d(
+ Config.LOGTAG,
+ "reaction received via MUC PM did not pass validation");
+ return;
+ }
+ reactionFrom = account.getJid().asBareJid();
+ }
+ } else {
+ if (packet.fromAccount(account)) {
+ isReceived = false;
+ reactionFrom = account.getJid().asBareJid();
+ } else {
+ isReceived = true;
+ reactionFrom = counterpart;
+ }
+ }
+ final var newReactions = new HashSet<>(reactions.getReactions());
+ newReactions.removeAll(message.getReactions().stream().filter(r -> reactionFrom.equals(r.from)).map(r -> r.reaction).collect(Collectors.toList()));
+ final var combinedReactions =
+ Reaction.withFrom(
+ message.getReactions(),
+ reactions.getReactions(),
+ isReceived,
+ reactionFrom,
+ message.getRemoteMsgId());
+ message.setReactions(combinedReactions);
+ mXmppConnectionService.updateMessage(message, false);
+ if (status < Message.STATUS_SEND) mXmppConnectionService.getNotificationService().push(message, counterpart, null, newReactions);
}
}
}
- private static Pair getForwardedMessagePacket(final im.conversations.android.xmpp.model.stanza.Message original, Class extends Extension> clazz) {
+ private static Pair
+ getForwardedMessagePacket(
+ final im.conversations.android.xmpp.model.stanza.Message original,
+ Class extends Extension> clazz) {
final var extension = original.getExtension(clazz);
final var forwarded = extension == null ? null : extension.getExtension(Forwarded.class);
if (forwarded == null) {
@@ -1469,36 +1840,51 @@ public class MessageParser extends AbstractParser implements Consumer(forwardedMessage,timestamp);
+ return new Pair<>(forwardedMessage, timestamp);
}
- private static Pair getForwardedMessagePacket(final im.conversations.android.xmpp.model.stanza.Message original, final String name, final String namespace) {
+ private static Pair
+ getForwardedMessagePacket(
+ final im.conversations.android.xmpp.model.stanza.Message original,
+ final String name,
+ final String namespace) {
final Element wrapper = original.findChild(name, namespace);
- final var forwardedElement = wrapper == null ? null : wrapper.findChild("forwarded",Namespace.FORWARD);
+ final var forwardedElement =
+ wrapper == null ? null : wrapper.findChild("forwarded", Namespace.FORWARD);
if (forwardedElement instanceof Forwarded forwarded) {
final Long timestamp = AbstractParser.parseTimestamp(forwarded, null);
final var forwardedMessage = forwarded.getMessage();
if (forwardedMessage == null) {
return null;
}
- return new Pair<>(forwardedMessage,timestamp);
+ return new Pair<>(forwardedMessage, timestamp);
}
return null;
}
- private void dismissNotification(Account account, Jid counterpart, MessageArchiveService.Query query, final String id) {
- final Conversation conversation = mXmppConnectionService.find(account, counterpart.asBareJid());
+ private void dismissNotification(
+ Account account, Jid counterpart, MessageArchiveService.Query query, final String id) {
+ final Conversation conversation =
+ mXmppConnectionService.find(account, counterpart.asBareJid());
if (conversation != null && (query == null || query.isCatchup())) {
final String displayableId = conversation.findMostRecentRemoteDisplayableId();
if (displayableId != null && displayableId.equals(id)) {
mXmppConnectionService.markRead(conversation);
} else {
- Log.w(Config.LOGTAG, account.getJid().asBareJid() + ": received dismissing display marker that did not match our last id in that conversation");
+ Log.w(
+ Config.LOGTAG,
+ account.getJid().asBareJid()
+ + ": received dismissing display marker that did not match our last"
+ + " id in that conversation");
}
}
}
- private void processMessageReceipts(final Account account, final im.conversations.android.xmpp.model.stanza.Message packet, final String remoteMsgId, MessageArchiveService.Query query) {
+ private void processMessageReceipts(
+ final Account account,
+ final im.conversations.android.xmpp.model.stanza.Message packet,
+ final String remoteMsgId,
+ MessageArchiveService.Query query) {
final boolean markable = packet.hasChild("markable", "urn:xmpp:chat-markers:0");
final boolean request = packet.hasChild("request", "urn:xmpp:receipts");
if (query == null) {
@@ -1510,11 +1896,15 @@ public class MessageParser extends AbstractParser implements Consumer 0) {
- final var receipt = mXmppConnectionService.getMessageGenerator().received(account,
- packet.getFrom(),
- remoteMsgId,
- receiptsNamespaces,
- packet.getType());
+ final var receipt =
+ mXmppConnectionService
+ .getMessageGenerator()
+ .received(
+ account,
+ packet.getFrom(),
+ remoteMsgId,
+ receiptsNamespaces,
+ packet.getType());
mXmppConnectionService.sendMessagePacket(account, receipt);
}
} else if (query.isCatchup()) {
@@ -1525,8 +1915,15 @@ public class MessageParser extends AbstractParser implements Consumer {
+public class PresenceParser extends AbstractParser
+ implements Consumer {
public PresenceParser(final XmppConnectionService service, final Account account) {
super(service, account);
}
- public void parseConferencePresence(final im.conversations.android.xmpp.model.stanza.Presence packet, Account account) {
+ public void parseConferencePresence(
+ final im.conversations.android.xmpp.model.stanza.Presence packet, Account account) {
final Conversation conversation =
packet.getFrom() == null
? null
: mXmppConnectionService.find(account, packet.getFrom().asBareJid());
- if (conversation != null) {
- final MucOptions mucOptions = conversation.getMucOptions();
- boolean before = mucOptions.online();
- int count = mucOptions.getUserCount();
- final List tileUserBefore = mucOptions.getUsers(5);
- processConferencePresence(packet, conversation);
- final List tileUserAfter = mucOptions.getUsers(5);
- if (!tileUserAfter.equals(tileUserBefore)) {
- mXmppConnectionService.getAvatarService().clear(mucOptions);
- }
- if (before != mucOptions.online()
- || (mucOptions.online() && count != mucOptions.getUserCount())) {
- mXmppConnectionService.updateConversationUi();
- } else if (mucOptions.online()) {
- mXmppConnectionService.updateMucRosterUi();
- }
+ if (conversation == null) {
+ return;
+ }
+ final MucOptions mucOptions = conversation.getMucOptions();
+ boolean before = mucOptions.online();
+ int count = mucOptions.getUserCount();
+ final List tileUserBefore = mucOptions.getUsers(5);
+ processConferencePresence(packet, conversation);
+ final List tileUserAfter = mucOptions.getUsers(5);
+ if (Strings.isNullOrEmpty(mucOptions.getAvatar())
+ && !tileUserAfter.equals(tileUserBefore)) {
+ mXmppConnectionService.getAvatarService().clear(mucOptions);
+ }
+ if (before != mucOptions.online()
+ || (mucOptions.online() && count != mucOptions.getUserCount())) {
+ mXmppConnectionService.updateConversationUi();
+ } else if (mucOptions.online()) {
+ mXmppConnectionService.updateMucRosterUi();
}
}
- private void processConferencePresence(final im.conversations.android.xmpp.model.stanza.Presence packet, Conversation conversation) {
+ private void processConferencePresence(
+ final im.conversations.android.xmpp.model.stanza.Presence packet,
+ Conversation conversation) {
final Account account = conversation.getAccount();
final MucOptions mucOptions = conversation.getMucOptions();
final Jid jid = conversation.getAccount().getJid();
@@ -82,12 +85,15 @@ public class PresenceParser extends AbstractParser implements Consumer= "
+ "account = ? AND transport = ? AND instance = ? AND endpoint IS NOT NULL"
+ + " AND expiration >= "
+ expiration,
new String[] {account, transport, instance},
null,
@@ -131,17 +130,26 @@ public class UnifiedPushDatabase extends SQLiteOpenHelper {
public List deletePushTargets() {
final SQLiteDatabase sqLiteDatabase = getReadableDatabase();
final ImmutableList.Builder builder = new ImmutableList.Builder<>();
- try (final Cursor cursor = sqLiteDatabase.query("push",new String[]{"application","instance"},null,null,null,null,null)) {
+ try (final Cursor cursor =
+ sqLiteDatabase.query(
+ "push",
+ new String[] {"application", "instance"},
+ null,
+ null,
+ null,
+ null,
+ null)) {
if (cursor != null && cursor.moveToFirst()) {
- builder.add(new PushTarget(
- cursor.getString(cursor.getColumnIndexOrThrow("application")),
- cursor.getString(cursor.getColumnIndexOrThrow("instance"))));
+ builder.add(
+ new PushTarget(
+ cursor.getString(cursor.getColumnIndexOrThrow("application")),
+ cursor.getString(cursor.getColumnIndexOrThrow("instance"))));
}
} catch (final Exception e) {
- Log.d(Config.LOGTAG,"unable to retrieve push targets",e);
+ Log.d(Config.LOGTAG, "unable to retrieve push targets", e);
return builder.build();
}
- sqLiteDatabase.delete("push",null,null);
+ sqLiteDatabase.delete("push", null, null);
return builder.build();
}
@@ -149,9 +157,10 @@ public class UnifiedPushDatabase extends SQLiteOpenHelper {
final SQLiteDatabase sqLiteDatabase = getReadableDatabase();
try (final Cursor cursor =
sqLiteDatabase.rawQuery(
- "SELECT EXISTS(SELECT endpoint FROM push WHERE account = ? AND transport = ?)",
+ "SELECT EXISTS(SELECT endpoint FROM push WHERE account = ? AND transport ="
+ + " ?)",
new String[] {
- transport.account.getUuid(), transport.transport.toEscapedString()
+ transport.account.getUuid(), transport.transport.toString()
})) {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getInt(0) > 0;
diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java
index 3b4d87aebfd41bff970c9b05d8435ac544592e54..8f9662e6a19ba5cff4946182c461a7919971c56b 100644
--- a/src/main/java/eu/siacs/conversations/services/AvatarService.java
+++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java
@@ -18,17 +18,10 @@ import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.LruCache;
-
import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-
+import com.google.common.base.Strings;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
@@ -46,6 +39,11 @@ import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
import eu.siacs.conversations.xmpp.XmppConnection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
@@ -99,7 +97,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
if (conversation != null) {
return get(conversation,size,cacheOnly);
}
- return get(CHANNEL_SYMBOL, room != null ? room.asBareJid().toEscapedString() : result.getName(), size, cacheOnly);
+ return get(CHANNEL_SYMBOL, room != null ? room.asBareJid().toString() : result.getName(), size, cacheOnly);
}
private Drawable get(final Contact contact, final int size, boolean cachedOnly) {
@@ -287,7 +285,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
public Drawable get(ListItem item, int size, boolean cachedOnly) {
if (item instanceof RawBlockable) {
- return get(item.getDisplayName(), item.getJid().toEscapedString(), size, cachedOnly);
+ return get(item.getDisplayName(), item.getJid().toString(), size, cachedOnly);
} else if (item instanceof Contact) {
return get((Contact) item, size, cachedOnly);
} else if (item instanceof Bookmark) {
@@ -472,7 +470,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
avatar = mXmppConnectionService.getFileBackend().getAvatar(account.getAvatar(), size);
if (avatar == null) {
final String displayName = account.getDisplayName();
- final String jid = account.getJid().asBareJid().toEscapedString();
+ final String jid = account.getJid().asBareJid().toString();
if (QuickConversationsService.isQuicksy() && !TextUtils.isEmpty(displayName)) {
avatar = get(displayName, jid, size, false);
} else {
@@ -551,7 +549,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
}
public static Drawable get(final Jid jid, final int size) {
- return getImpl(jid.asBareJid().toEscapedString(), null, size);
+ return getImpl(jid.asBareJid().toString(), null, size);
}
private static Drawable getImpl(final String name, final String seed, final int size) {
diff --git a/src/main/java/eu/siacs/conversations/services/CallIntegration.java b/src/main/java/eu/siacs/conversations/services/CallIntegration.java
index b6efdd85185d6ee53a7ac08b1ee444c025b83256..01534fb08ce3d9b78401d0673af555def1182629 100644
--- a/src/main/java/eu/siacs/conversations/services/CallIntegration.java
+++ b/src/main/java/eu/siacs/conversations/services/CallIntegration.java
@@ -460,7 +460,7 @@ public class CallIntegration extends Connection {
}
public static Uri address(final Jid contact) {
- return Uri.parse(String.format("xmpp:%s", contact.toEscapedString()));
+ return Uri.parse(String.format("xmpp:%s", contact.toString()));
}
public void verifyDisconnected() {
diff --git a/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java b/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java
index facc616b098ffefe342adfa66a1685bab6624a98..fd849c0174d02f4f3ddc7f2da396991cbbf90faf 100644
--- a/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java
@@ -21,14 +21,11 @@ import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.util.Log;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
-
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
@@ -41,7 +38,6 @@ import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
import eu.siacs.conversations.xmpp.jingle.Media;
import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
import eu.siacs.conversations.xmpp.jingle.stanzas.Reason;
-
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
@@ -93,7 +89,8 @@ public class CallIntegrationConnectionService extends ConnectionService {
if (service == null) {
Log.d(
Config.LOGTAG,
- "CallIntegrationConnection service was unable to bind to XmppConnectionService");
+ "CallIntegrationConnection service was unable to bind to"
+ + " XmppConnectionService");
return Connection.createFailedConnection(
new DisconnectCause(DisconnectCause.ERROR, "service connection not found"));
}
@@ -109,8 +106,8 @@ public class CallIntegrationConnectionService extends ConnectionService {
Log.d(Config.LOGTAG, "create outgoing rtp connection!");
final Intent intent = new Intent(service, RtpSessionActivity.class);
intent.setAction(Intent.ACTION_VIEW);
- intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, account.getJid().toEscapedString());
- intent.putExtra(RtpSessionActivity.EXTRA_WITH, with.toEscapedString());
+ intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, account.getJid().toString());
+ intent.putExtra(RtpSessionActivity.EXTRA_WITH, with.toString());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
final Connection callIntegration;
@@ -137,7 +134,8 @@ public class CallIntegrationConnectionService extends ConnectionService {
return Connection.createFailedConnection(
new DisconnectCause(
DisconnectCause.ERROR,
- "Phone is busy. Probably race condition. Try again in a moment"));
+ "Phone is busy. Probably race condition. Try again in a"
+ + " moment"));
}
if (proposal == null) {
// TODO instead of just null checking try to get the sessionID
@@ -189,9 +187,9 @@ public class CallIntegrationConnectionService extends ConnectionService {
}
final Jid jid;
if ("tel".equals(uri.getScheme())) {
- jid = Jid.ofEscaped(extras.getString(EXTRA_ADDRESS));
+ jid = Jid.of(extras.getString(EXTRA_ADDRESS));
} else {
- jid = Jid.ofEscaped(uri.getSchemeSpecificPart());
+ jid = Jid.of(uri.getSchemeSpecificPart());
}
final int videoState = extras.getInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE);
final Set media =
@@ -228,7 +226,7 @@ public class CallIntegrationConnectionService extends ConnectionService {
return Connection.createFailedConnection(
new DisconnectCause(DisconnectCause.ERROR, "service connection not found"));
}
- final var jid = Jid.ofEscaped(uri.getSchemeSpecificPart());
+ final var jid = Jid.of(uri.getSchemeSpecificPart());
final Account account = service.findAccountByUuid(phoneAccountHandle.getId());
final var weakReference =
service.getJingleConnectionManager().findJingleRtpConnection(account, jid, sid);
@@ -367,7 +365,7 @@ public class CallIntegrationConnectionService extends ConnectionService {
} else {
// for Android 8 we need to put in a fake tel uri
final var outgoingCallExtras = new Bundle();
- outgoingCallExtras.putString(EXTRA_ADDRESS, with.toEscapedString());
+ outgoingCallExtras.putString(EXTRA_ADDRESS, with.toString());
extras.putBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, outgoingCallExtras);
address = Uri.parse("tel:0");
}
diff --git a/src/main/java/eu/siacs/conversations/services/ChannelDiscoveryService.java b/src/main/java/eu/siacs/conversations/services/ChannelDiscoveryService.java
index e2a828ac63209592dabcce2b9c85c0096bc4e6c5..ccc02d36b476c50ecc24e3a982ec80fc6f9666ee 100644
--- a/src/main/java/eu/siacs/conversations/services/ChannelDiscoveryService.java
+++ b/src/main/java/eu/siacs/conversations/services/ChannelDiscoveryService.java
@@ -1,14 +1,10 @@
package eu.siacs.conversations.services;
-
import android.util.Log;
-
import androidx.annotation.NonNull;
-
import com.google.common.base.Strings;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Room;
@@ -17,18 +13,7 @@ import eu.siacs.conversations.http.services.MuclumbusService;
import eu.siacs.conversations.parser.IqParser;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.XmppConnection;
-
import im.conversations.android.xmpp.model.stanza.Iq;
-
-import okhttp3.OkHttpClient;
-import okhttp3.ResponseBody;
-
-import retrofit2.Call;
-import retrofit2.Callback;
-import retrofit2.Response;
-import retrofit2.Retrofit;
-import retrofit2.converter.gson.GsonConverterFactory;
-
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@@ -38,6 +23,13 @@ import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import okhttp3.OkHttpClient;
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
public class ChannelDiscoveryService {
@@ -57,7 +49,8 @@ public class ChannelDiscoveryService {
this.muclumbusService = null;
return;
}
- final OkHttpClient.Builder builder = HttpConnectionManager.okHttpClient(service).newBuilder();
+ final OkHttpClient.Builder builder =
+ HttpConnectionManager.okHttpClient(service).newBuilder();
if (service.useTorToConnect()) {
builder.proxy(HttpConnectionManager.getProxy());
}
@@ -207,10 +200,8 @@ public class ChannelDiscoveryService {
account,
infoRequest,
infoResponse -> {
- if (infoResponse.getType()
- == Iq.Type.RESULT) {
- final Room room =
- IqParser.parseRoom(infoResponse);
+ if (infoResponse.getType() == Iq.Type.RESULT) {
+ final Room room = IqParser.parseRoom(infoResponse);
if (room != null) {
rooms.add(room);
}
@@ -262,7 +253,7 @@ public class ChannelDiscoveryService {
continue;
}
for (final String mucService : xmppConnection.getMucServers()) {
- Jid jid = Jid.ofEscaped(mucService);
+ final Jid jid = Jid.of(mucService);
if (!localMucServices.containsKey(jid)) {
localMucServices.put(jid, account);
}
diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java
index 09b19a4a370e9ebb52544515b4c83ec3a2e0a113..f50a25ae02e889d39881bdccd973cd12ec609d75 100644
--- a/src/main/java/eu/siacs/conversations/services/NotificationService.java
+++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java
@@ -639,9 +639,8 @@ public class NotificationService {
final Intent fullScreenIntent =
new Intent(mXmppConnectionService, RtpSessionActivity.class);
fullScreenIntent.putExtra(
- RtpSessionActivity.EXTRA_ACCOUNT,
- id.account.getJid().asBareJid().toEscapedString());
- fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toEscapedString());
+ RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().asBareJid().toString());
+ fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toString());
fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.sessionId);
fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -797,9 +796,8 @@ public class NotificationService {
new Intent(mXmppConnectionService, RtpSessionActivity.class);
fullScreenIntent.setAction(action);
fullScreenIntent.putExtra(
- RtpSessionActivity.EXTRA_ACCOUNT,
- id.account.getJid().asBareJid().toEscapedString());
- fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toEscapedString());
+ RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().asBareJid().toString());
+ fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toString());
fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.sessionId);
return PendingIntent.getActivity(
mXmppConnectionService,
@@ -2081,7 +2079,7 @@ public class NotificationService {
} else if (errors.size() == 1) {
mBuilder.setContentTitle(
mXmppConnectionService.getString(R.string.problem_connecting_to_account));
- mBuilder.setContentText(errors.get(0).getJid().asBareJid().toEscapedString());
+ mBuilder.setContentText(errors.get(0).getJid().asBareJid().toString());
} else {
mBuilder.setContentTitle(
mXmppConnectionService.getString(R.string.problem_connecting_to_accounts));
@@ -2140,7 +2138,7 @@ public class NotificationService {
intent = new Intent(mXmppConnectionService, AccountUtils.MANAGE_ACCOUNT_ACTIVITY);
} else {
intent = new Intent(mXmppConnectionService, EditAccountActivity.class);
- intent.putExtra("jid", errors.get(0).getJid().asBareJid().toEscapedString());
+ intent.putExtra("jid", errors.get(0).getJid().asBareJid().toString());
intent.putExtra(EditAccountActivity.EXTRA_OPENED_FROM_NOTIFICATION, true);
}
mBuilder.setContentIntent(
diff --git a/src/main/java/eu/siacs/conversations/services/ShortcutService.java b/src/main/java/eu/siacs/conversations/services/ShortcutService.java
index 547f8019a285ca88a9642cc0abfa9831132a94e3..1f286529cfd77f13afae0d2e5c2c13c1c89d21b3 100644
--- a/src/main/java/eu/siacs/conversations/services/ShortcutService.java
+++ b/src/main/java/eu/siacs/conversations/services/ShortcutService.java
@@ -14,10 +14,12 @@ import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
+import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -32,11 +34,11 @@ import eu.siacs.conversations.ui.StartConversationActivity;
import eu.siacs.conversations.ui.ConversationsActivity;
import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
import eu.siacs.conversations.xmpp.Jid;
-import java.util.Collection;
-import java.util.List;
public class ShortcutService {
+ public static final char ID_SEPARATOR = '#';
+
private final XmppConnectionService xmppConnectionService;
private final ReplacingSerialSingleThreadExecutor replacingSerialSingleThreadExecutor =
new ReplacingSerialSingleThreadExecutor(ShortcutService.class.getSimpleName());
@@ -167,17 +169,17 @@ public class ShortcutService {
}
private static String getShortcutId(final Contact contact) {
- return contact.getAccount().getJid().asBareJid().toEscapedString()
- + "#"
- + contact.getJid().asBareJid().toEscapedString();
+ return Joiner.on(ID_SEPARATOR)
+ .join(
+ contact.getAccount().getJid().asBareJid().toString(),
+ contact.getJid().asBareJid().toString());
}
private static String getShortcutId(final MucOptions mucOptions) {
final Account account = mucOptions.getAccount();
final Jid jid = mucOptions.getConversation().getJid();
- return account.getJid().asBareJid().toEscapedString()
- + "#"
- + jid.asBareJid().toEscapedString();
+ return Joiner.on(ID_SEPARATOR)
+ .join(account.getJid().asBareJid().toString(), jid.asBareJid().toString());
}
private Intent getShortcutIntent(final MucOptions mucOptions) {
@@ -187,17 +189,12 @@ public class ShortcutService {
Uri.parse(
String.format(
"xmpp:%s?join",
- mucOptions
- .getConversation()
- .getJid()
- .asBareJid()
- .toEscapedString())));
+ mucOptions.getConversation().getJid().asBareJid().toString())));
}
private Intent getShortcutIntent(final Contact contact) {
return getShortcutIntent(
- contact.getAccount(),
- Uri.parse("xmpp:" + contact.getJid().asBareJid().toEscapedString()));
+ contact.getAccount(), Uri.parse("xmpp:" + contact.getJid().asBareJid().toString()));
}
private Intent getShortcutIntent(final Account account, final Uri uri) {
diff --git a/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java b/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java
index 92ae9d9ec668533d097680e333ac58bb4bc33248..24aaf1f4279b04abd32fbf3da615283c0dda3a32 100644
--- a/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java
+++ b/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java
@@ -10,10 +10,8 @@ import android.os.Messenger;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
@@ -22,7 +20,6 @@ import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
@@ -34,7 +31,6 @@ import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.xmpp.model.stanza.Iq;
import im.conversations.android.xmpp.model.stanza.Presence;
-
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.List;
@@ -92,7 +88,8 @@ public class UnifiedPushBroker {
renewUnifiedPushEndpoints(null);
}
- public Optional renewUnifiedPushEndpoints(@Nullable final PushTargetMessenger pushTargetMessenger) {
+ public Optional renewUnifiedPushEndpoints(
+ @Nullable final PushTargetMessenger pushTargetMessenger) {
final Optional transportOptional = getTransport();
if (transportOptional.isPresent()) {
final Transport transport = transportOptional.get();
@@ -100,13 +97,13 @@ public class UnifiedPushBroker {
renewUnifiedEndpoint(transportOptional.get(), pushTargetMessenger);
} else {
if (pushTargetMessenger != null && pushTargetMessenger.messenger != null) {
- sendRegistrationDelayed(pushTargetMessenger.messenger,"account is disabled");
+ sendRegistrationDelayed(pushTargetMessenger.messenger, "account is disabled");
}
Log.d(Config.LOGTAG, "skipping UnifiedPush endpoint renewal. Account is disabled");
}
} else {
if (pushTargetMessenger != null && pushTargetMessenger.messenger != null) {
- sendRegistrationDelayed(pushTargetMessenger.messenger,"no transport selected");
+ sendRegistrationDelayed(pushTargetMessenger.messenger, "no transport selected");
}
Log.d(Config.LOGTAG, "skipping UnifiedPush endpoint renewal. No transport selected");
}
@@ -121,16 +118,16 @@ public class UnifiedPushBroker {
try {
messenger.send(message);
} catch (final RemoteException e) {
- Log.d(Config.LOGTAG,"unable to tell messenger of delayed registration",e);
+ Log.d(Config.LOGTAG, "unable to tell messenger of delayed registration", e);
}
}
- private void renewUnifiedEndpoint(final Transport transport, final PushTargetMessenger pushTargetMessenger) {
+ private void renewUnifiedEndpoint(
+ final Transport transport, final PushTargetMessenger pushTargetMessenger) {
final Account account = transport.account;
final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service);
final List renewals =
- unifiedPushDatabase.getRenewals(
- account.getUuid(), transport.transport.toEscapedString());
+ unifiedPushDatabase.getRenewals(account.getUuid(), transport.transport.toString());
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
@@ -142,7 +139,11 @@ public class UnifiedPushBroker {
Log.d(
Config.LOGTAG,
account.getJid().asBareJid() + ": try to renew UnifiedPush " + renewal);
- UnifiedPushDistributor.quickLog(service,String.format("%s: try to renew UnifiedPush %s", account.getJid(), renewal.toString()));
+ UnifiedPushDistributor.quickLog(
+ service,
+ String.format(
+ "%s: try to renew UnifiedPush %s",
+ account.getJid(), renewal.toString()));
final String hashedApplication =
UnifiedPushDistributor.hash(account.getUuid(), renewal.application);
final String hashedInstance =
@@ -205,7 +206,7 @@ public class UnifiedPushBroker {
unifiedPushDatabase.updateEndpoint(
renewal.instance,
transport.account.getUuid(),
- transport.transport.toEscapedString(),
+ transport.transport.toString(),
endpoint,
expiration);
if (modified) {
@@ -231,15 +232,21 @@ public class UnifiedPushBroker {
}
}
- private void sendEndpoint(final Messenger messenger, String instance, final UnifiedPushDatabase.ApplicationEndpoint applicationEndpoint) {
+ private void sendEndpoint(
+ final Messenger messenger,
+ String instance,
+ final UnifiedPushDatabase.ApplicationEndpoint applicationEndpoint) {
if (messenger != null) {
- Log.d(Config.LOGTAG,"using messenger instead of broadcast to communicate endpoint to "+applicationEndpoint.application);
+ Log.d(
+ Config.LOGTAG,
+ "using messenger instead of broadcast to communicate endpoint to "
+ + applicationEndpoint.application);
final Message message = new Message();
message.obj = endpointIntent(instance, applicationEndpoint);
try {
messenger.send(message);
} catch (final RemoteException e) {
- Log.d(Config.LOGTAG,"messenger failed. falling back to broadcast");
+ Log.d(Config.LOGTAG, "messenger failed. falling back to broadcast");
broadcastEndpoint(instance, applicationEndpoint);
}
} else {
@@ -281,8 +288,7 @@ public class UnifiedPushBroker {
future,
new FutureCallback<>() {
@Override
- public void onSuccess(
- final List pushTargets) {
+ public void onSuccess(final List pushTargets) {
broadcastUnregistered(pushTargets);
}
@@ -290,19 +296,21 @@ public class UnifiedPushBroker {
public void onFailure(@NonNull Throwable throwable) {
Log.d(
Config.LOGTAG,
- "could not delete endpoints after UnifiedPushDistributor was disabled");
+ "could not delete endpoints after UnifiedPushDistributor was"
+ + " disabled");
}
},
MoreExecutors.directExecutor());
}
private ListenableFuture
> deletePushTargets() {
- return Futures.submit(() -> UnifiedPushDatabase.getInstance(service).deletePushTargets(),SCHEDULER);
+ return Futures.submit(
+ () -> UnifiedPushDatabase.getInstance(service).deletePushTargets(), SCHEDULER);
}
private void broadcastUnregistered(final List pushTargets) {
- for(final UnifiedPushDatabase.PushTarget pushTarget : pushTargets) {
- Log.d(Config.LOGTAG,"sending unregistered to "+pushTarget);
+ for (final UnifiedPushDatabase.PushTarget pushTarget : pushTargets) {
+ Log.d(Config.LOGTAG, "sending unregistered to " + pushTarget);
broadcastUnregistered(pushTarget);
}
}
@@ -368,8 +376,8 @@ public class UnifiedPushBroker {
final Jid transport;
final Jid jid;
try {
- transport = Jid.ofEscaped(Strings.nullToEmpty(pushServerPreference).trim());
- jid = Jid.ofEscaped(Strings.nullToEmpty(accountPreference).trim());
+ transport = Jid.of(Strings.nullToEmpty(pushServerPreference).trim());
+ jid = Jid.of(Strings.nullToEmpty(accountPreference).trim());
} catch (final IllegalArgumentException e) {
return Optional.absent();
}
@@ -390,8 +398,7 @@ public class UnifiedPushBroker {
}
final String uuid = account.getUuid();
final List pushTargets =
- UnifiedPushDatabase.getInstance(service)
- .getPushTargets(uuid, transport.toEscapedString());
+ UnifiedPushDatabase.getInstance(service).getPushTargets(uuid, transport.toString());
return Iterables.tryFind(
pushTargets,
pt ->
@@ -422,7 +429,8 @@ public class UnifiedPushBroker {
service.sendBroadcast(updateIntent);
}
- private Intent endpointIntent(final String instance, final UnifiedPushDatabase.ApplicationEndpoint endpoint) {
+ private Intent endpointIntent(
+ final String instance, final UnifiedPushDatabase.ApplicationEndpoint endpoint) {
final Intent intent = new Intent(UnifiedPushDistributor.ACTION_NEW_ENDPOINT);
intent.setPackage(endpoint.application);
intent.putExtra("token", instance);
@@ -449,13 +457,12 @@ public class UnifiedPushBroker {
return intent;
}
- public void rebroadcastEndpoint(final Messenger messenger, final String instance, final Transport transport) {
+ public void rebroadcastEndpoint(
+ final Messenger messenger, final String instance, final Transport transport) {
final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service);
final UnifiedPushDatabase.ApplicationEndpoint endpoint =
unifiedPushDatabase.getEndpoint(
- transport.account.getUuid(),
- transport.transport.toEscapedString(),
- instance);
+ transport.account.getUuid(), transport.transport.toString(), instance);
if (endpoint != null) {
sendEndpoint(messenger, instance, endpoint);
}
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index 6bd5f2ca28483e7932b87fb8968153fbdc218cb1..a5b51bb43b4be6833d33710c9781b75d04dc66f6 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -184,7 +184,6 @@ import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.LocalizedContent;
import eu.siacs.conversations.xml.Namespace;
-import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnContactStatusChanged;
import eu.siacs.conversations.xmpp.OnGatewayResult;
@@ -2554,7 +2553,7 @@ public class XmppConnectionService extends Service {
if (uri != null) {
final EasyOnboardingInvite invite =
new EasyOnboardingInvite(
- jid.getDomain().toEscapedString(), uri, landingUrl);
+ jid.getDomain().toString(), uri, landingUrl);
callback.inviteRequested(invite);
return;
}
@@ -2630,7 +2629,7 @@ public class XmppConnectionService extends Service {
public void processMdsItem(final Account account, final Element item) {
final Jid jid =
- item == null ? null : InvalidJid.getNullForInvalid(item.getAttributeAsJid("id"));
+ item == null ? null : Jid.Invalid.getNullForInvalid(item.getAttributeAsJid("id"));
if (jid == null) {
return;
}
@@ -2791,7 +2790,7 @@ public class XmppConnectionService extends Service {
account,
Namespace.BOOKMARKS2,
item,
- bookmark.getJid().asBareJid().toEscapedString(),
+ bookmark.getJid().asBareJid().toString(),
PublishOptions.persistentWhitelistAccessMaxItems());
} else if (connection.getFeatures().bookmarksConversion()) {
pushBookmarksPep(account);
@@ -2811,7 +2810,7 @@ public class XmppConnectionService extends Service {
if (connection.getFeatures().bookmarks2()) {
final Iq request =
mIqGenerator.deleteItem(
- Namespace.BOOKMARKS2, bookmark.getJid().asBareJid().toEscapedString());
+ Namespace.BOOKMARKS2, bookmark.getJid().asBareJid().toString());
Log.d(
Config.LOGTAG,
account.getJid().asBareJid() + ": removing bookmark via Bookmarks 2");
@@ -3577,10 +3576,10 @@ public class XmppConnectionService extends Service {
}
private void provisionAccount(final String address, final String password) {
- final Jid jid = Jid.ofEscaped(address);
+ final Jid jid = Jid.of(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().toString() + ": provisioning account");
createAccount(account);
}
@@ -4018,15 +4017,15 @@ public class XmppConnectionService extends Service {
}
public boolean checkListeners() {
- return (this.mOnAccountUpdates.size() == 0
- && this.mOnConversationUpdates.size() == 0
- && this.mOnRosterUpdates.size() == 0
- && this.mOnCaptchaRequested.size() == 0
- && this.mOnMucRosterUpdate.size() == 0
- && this.mOnUpdateBlocklist.size() == 0
- && this.mOnShowErrorToasts.size() == 0
- && this.onJingleRtpConnectionUpdate.size() == 0
- && this.mOnKeyStatusUpdated.size() == 0);
+ return (this.mOnAccountUpdates.isEmpty()
+ && this.mOnConversationUpdates.isEmpty()
+ && this.mOnRosterUpdates.isEmpty()
+ && this.mOnCaptchaRequested.isEmpty()
+ && this.mOnMucRosterUpdate.isEmpty()
+ && this.mOnUpdateBlocklist.isEmpty()
+ && this.mOnShowErrorToasts.isEmpty()
+ && this.onJingleRtpConnectionUpdate.isEmpty()
+ && this.mOnKeyStatusUpdated.isEmpty());
}
private void switchToForeground() {
@@ -4383,7 +4382,8 @@ public class XmppConnectionService extends Service {
}
++i;
if (i >= affiliations.size()) {
- List members = conversation.getMucOptions().getMembers(true);
+ final var mucOptions = conversation.getMucOptions();
+ List members = mucOptions.getMembers(true);
if (success) {
List cryptoTargets = conversation.getAcceptedCryptoTargets();
boolean changed = false;
@@ -4408,7 +4408,7 @@ public class XmppConnectionService extends Service {
updateConversation(conversation);
}
}
- getAvatarService().clear(conversation);
+ getAvatarService().clear(mucOptions);
updateMucRosterUi();
updateConversationUi();
}
@@ -5093,8 +5093,9 @@ public class XmppConnectionService extends Service {
request,
(response) -> {
if (response.getType() == Iq.Type.RESULT) {
- conference.getMucOptions().changeAffiliation(jid, affiliation);
- getAvatarService().clear(conference);
+ final var mucOptions = conference.getMucOptions();
+ mucOptions.changeAffiliation(jid, affiliation);
+ getAvatarService().clear(mucOptions);
if (callback != null) {
callback.onAffiliationChangedSuccessful(jid);
} else {
@@ -6373,7 +6374,7 @@ public class XmppConnectionService extends Service {
account,
Namespace.MDS_DISPLAYED,
item,
- itemId.toEscapedString(),
+ itemId.toString(),
PublishOptions.persistentWhitelistAccessMaxItems());
}
@@ -6526,7 +6527,7 @@ public class XmppConnectionService extends Service {
if (Config.QUICKSY_DOMAIN != null) {
hosts.remove(
Config.QUICKSY_DOMAIN
- .toEscapedString()); // we only want to show this when we type a e164
+ .toString()); // we only want to show this when we type a e164
// number
}
if (Config.MAGIC_CREATE_DOMAIN != null) {
@@ -6543,7 +6544,7 @@ public class XmppConnectionService extends Service {
mucServers.addAll(account.getXmppConnection().getMucServers());
for (final Bookmark bookmark : account.getBookmarks()) {
final Jid jid = bookmark.getJid();
- final String s = jid == null ? null : jid.getDomain().toEscapedString();
+ final String s = jid == null ? null : jid.getDomain().toString();
if (s != null) {
mucServers.add(s);
}
diff --git a/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java b/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java
index 73f6420a09bc45f9273297f7eda2aa947dd29687..8978fe0da61d3a8399b80e5f834ac756891598ea 100644
--- a/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java
+++ b/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java
@@ -2,13 +2,9 @@ package eu.siacs.conversations.ui;
import android.view.View;
import android.widget.Toast;
-
import androidx.annotation.StringRes;
-import androidx.appcompat.app.AlertDialog;
import androidx.databinding.DataBindingUtil;
-
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.DialogBlockContactBinding;
import eu.siacs.conversations.entities.Blockable;
@@ -17,43 +13,56 @@ import eu.siacs.conversations.ui.util.JidDialog;
public final class BlockContactDialog {
- public static void show(final XmppActivity xmppActivity, final Blockable blockable) {
- show(xmppActivity, blockable, null);
- }
- public static void show(final XmppActivity xmppActivity, final Blockable blockable, final String serverMsgId) {
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(xmppActivity);
- final boolean isBlocked = blockable.isBlocked();
- builder.setNegativeButton(R.string.cancel, null);
- DialogBlockContactBinding binding = DataBindingUtil.inflate(xmppActivity.getLayoutInflater(), R.layout.dialog_block_contact, null, false);
- final boolean reporting = blockable.getAccount().getXmppConnection().getFeatures().spamReporting();
- if (reporting && !isBlocked) {
- binding.reportSpam.setVisibility(View.VISIBLE);
- if (serverMsgId != null) {
- binding.reportSpam.setChecked(true);
- binding.reportSpam.setEnabled(false);
- } else {
- binding.reportSpam.setEnabled(true);
- }
- } else {
- binding.reportSpam.setVisibility(View.GONE);
- }
- builder.setView(binding.getRoot());
+ public static void show(final XmppActivity xmppActivity, final Blockable blockable) {
+ show(xmppActivity, blockable, null);
+ }
- final String value;
- @StringRes int res;
- if (blockable.getJid().isFullJid()) {
- builder.setTitle(isBlocked ? R.string.action_unblock_participant : R.string.action_block_participant);
- value = blockable.getJid().toEscapedString();
- res = isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text;
- } else if (blockable.getJid().getLocal() == null || blockable.getAccount().isBlocked(blockable.getJid().getDomain())) {
- builder.setTitle(isBlocked ? R.string.action_unblock_domain : R.string.action_block_domain);
- value =blockable.getJid().getDomain().toEscapedString();
- res = isBlocked ? R.string.unblock_domain_text : R.string.block_domain_text;
- } else {
- if (isBlocked) {
- builder.setTitle(R.string.action_unblock_contact);
- } else if (serverMsgId != null) {
- builder.setTitle(R.string.report_spam_and_block);
+ public static void show(
+ final XmppActivity xmppActivity, final Blockable blockable, final String serverMsgId) {
+ final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(xmppActivity);
+ final boolean isBlocked = blockable.isBlocked();
+ builder.setNegativeButton(R.string.cancel, null);
+ DialogBlockContactBinding binding =
+ DataBindingUtil.inflate(
+ xmppActivity.getLayoutInflater(),
+ R.layout.dialog_block_contact,
+ null,
+ false);
+ final boolean reporting =
+ blockable.getAccount().getXmppConnection().getFeatures().spamReporting();
+ if (reporting && !isBlocked) {
+ binding.reportSpam.setVisibility(View.VISIBLE);
+ if (serverMsgId != null) {
+ binding.reportSpam.setChecked(true);
+ binding.reportSpam.setEnabled(false);
+ } else {
+ binding.reportSpam.setEnabled(true);
+ }
+ } else {
+ binding.reportSpam.setVisibility(View.GONE);
+ }
+ builder.setView(binding.getRoot());
+
+ final String value;
+ @StringRes int res;
+ if (blockable.getJid().isFullJid()) {
+ builder.setTitle(
+ isBlocked
+ ? R.string.action_unblock_participant
+ : R.string.action_block_participant);
+ value = blockable.getJid().toString();
+ res = isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text;
+ } else if (blockable.getJid().getLocal() == null
+ || blockable.getAccount().isBlocked(blockable.getJid().getDomain())) {
+ builder.setTitle(
+ isBlocked ? R.string.action_unblock_domain : R.string.action_block_domain);
+ value = blockable.getJid().getDomain().toString();
+ res = isBlocked ? R.string.unblock_domain_text : R.string.block_domain_text;
+ } else {
+ if (isBlocked) {
+ builder.setTitle(R.string.action_unblock_contact);
+ } else if (serverMsgId != null) {
+ builder.setTitle(R.string.report_spam_and_block);
} else {
final int resBlockAction =
blockable instanceof Conversation
@@ -61,34 +70,44 @@ public final class BlockContactDialog {
? R.string.block_stranger
: R.string.action_block_contact;
builder.setTitle(resBlockAction);
- }
- value = blockable.getJid().asBareJid().toEscapedString();
- res = isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text;
- }
- binding.text.setText(JidDialog.style(xmppActivity, res, value));
- builder.setPositiveButton(isBlocked ? R.string.unblock : R.string.block, (dialog, which) -> {
- if (isBlocked) {
- xmppActivity.xmppConnectionService.sendUnblockRequest(blockable);
- } else {
- boolean toastShown = false;
- var finalServerId = serverMsgId;
- if (serverMsgId == null && binding.reportSpam.isChecked() && blockable instanceof Conversation) {
- final var lastM = ((Conversation) blockable).getLatestMessage();
- if (lastM != null) finalServerId = lastM.getServerMsgId();
- }
-
- if (xmppActivity.xmppConnectionService.sendBlockRequest(blockable, binding.reportSpam.isChecked(), finalServerId)) {
- Toast.makeText(xmppActivity, R.string.corresponding_chats_closed, Toast.LENGTH_SHORT).show();
- toastShown = true;
- }
- if (xmppActivity instanceof ContactDetailsActivity) {
- if (!toastShown) {
- Toast.makeText(xmppActivity, R.string.contact_blocked_past_tense, Toast.LENGTH_SHORT).show();
- }
- xmppActivity.finish();
- }
- }
- });
- builder.create().show();
- }
+ }
+ value = blockable.getJid().asBareJid().toString();
+ res = isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text;
+ }
+ binding.text.setText(JidDialog.style(xmppActivity, res, value));
+ builder.setPositiveButton(
+ isBlocked ? R.string.unblock : R.string.block,
+ (dialog, which) -> {
+ if (isBlocked) {
+ xmppActivity.xmppConnectionService.sendUnblockRequest(blockable);
+ } else {
+ boolean toastShown = false;
+ var finalServerId = serverMsgId;
+ if (serverMsgId == null && binding.reportSpam.isChecked() && blockable instanceof Conversation) {
+ final var lastM = ((Conversation) blockable).getLatestMessage();
+ if (lastM != null) finalServerId = lastM.getServerMsgId();
+ }
+ if (xmppActivity.xmppConnectionService.sendBlockRequest(
+ blockable, binding.reportSpam.isChecked(), finalServerId)) {
+ Toast.makeText(
+ xmppActivity,
+ R.string.corresponding_chats_closed,
+ Toast.LENGTH_SHORT)
+ .show();
+ toastShown = true;
+ }
+ if (xmppActivity instanceof ContactDetailsActivity) {
+ if (!toastShown) {
+ Toast.makeText(
+ xmppActivity,
+ R.string.contact_blocked_past_tense,
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ xmppActivity.finish();
+ }
+ }
+ });
+ builder.create().show();
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java b/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java
index 20eac8bc302ff21ff47742eaaa4427d132549d86..7d55e33a67ff3bf44c96a0806b9451b7dcb68f7c 100644
--- a/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java
@@ -3,12 +3,8 @@ package eu.siacs.conversations.ui;
import android.os.Bundle;
import android.text.Editable;
import android.widget.Toast;
-
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
-
-import java.util.Collections;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Blockable;
@@ -17,99 +13,109 @@ import eu.siacs.conversations.entities.RawBlockable;
import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
+import java.util.Collections;
-public class BlocklistActivity extends AbstractSearchableListItemActivity implements OnUpdateBlocklist {
-
- private Account account = null;
+public class BlocklistActivity extends AbstractSearchableListItemActivity
+ implements OnUpdateBlocklist {
- @Override
- public void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- getListView().setOnItemLongClickListener((parent, view, position, id) -> {
- BlockContactDialog.show(BlocklistActivity.this, (Blockable) getListItems().get(position));
- return true;
- });
- this.binding.fab.show();
- this.binding.fab.setOnClickListener((v)->showEnterJidDialog());
- }
+ private Account account = null;
- @Override
- public void onBackendConnected() {
- for (final Account account : xmppConnectionService.getAccounts()) {
- if (account.getJid().toEscapedString().equals(getIntent().getStringExtra(EXTRA_ACCOUNT))) {
- this.account = account;
- break;
- }
- }
- filterContacts();
- Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_DIALOG);
- if (fragment instanceof OnBackendConnected) {
- ((OnBackendConnected) fragment).onBackendConnected();
- }
- }
+ @Override
+ public void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getListView()
+ .setOnItemLongClickListener(
+ (parent, view, position, id) -> {
+ BlockContactDialog.show(
+ BlocklistActivity.this,
+ (Blockable) getListItems().get(position));
+ return true;
+ });
+ this.binding.fab.show();
+ this.binding.fab.setOnClickListener((v) -> showEnterJidDialog());
+ }
- @Override
- protected void filterContacts(final String needle) {
- getListItems().clear();
- if (account != null) {
- for (final Jid jid : account.getBlocklist()) {
- ListItem item;
- if (jid.isFullJid()) {
- item = new RawBlockable(account, jid);
- } else {
- item = account.getRoster().getContact(jid);
- }
- if (item.match(this, needle)) {
- getListItems().add(item);
- }
- }
- Collections.sort(getListItems());
- }
- getListItemAdapter().notifyDataSetChanged();
- }
+ @Override
+ public void onBackendConnected() {
+ for (final Account account : xmppConnectionService.getAccounts()) {
+ if (account.getJid().toString().equals(getIntent().getStringExtra(EXTRA_ACCOUNT))) {
+ this.account = account;
+ break;
+ }
+ }
+ filterContacts();
+ Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_DIALOG);
+ if (fragment instanceof OnBackendConnected) {
+ ((OnBackendConnected) fragment).onBackendConnected();
+ }
+ }
- protected void showEnterJidDialog() {
- FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
- Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
- if (prev != null) {
- ft.remove(prev);
- }
- ft.addToBackStack(null);
- EnterJidDialog dialog = EnterJidDialog.newInstance(
- null,
- getString(R.string.block_jabber_id),
- getString(R.string.block),
- null,
- null,
- account.getJid().asBareJid().toEscapedString(),
- true,
- false,
- EnterJidDialog.SanityCheck.NO
- );
+ @Override
+ protected void filterContacts(final String needle) {
+ getListItems().clear();
+ if (account != null) {
+ for (final Jid jid : account.getBlocklist()) {
+ ListItem item;
+ if (jid.isFullJid()) {
+ item = new RawBlockable(account, jid);
+ } else {
+ item = account.getRoster().getContact(jid);
+ }
+ if (item.match(this, needle)) {
+ getListItems().add(item);
+ }
+ }
+ Collections.sort(getListItems());
+ }
+ getListItemAdapter().notifyDataSetChanged();
+ }
- dialog.setOnEnterJidDialogPositiveListener((accountJid, contactJid, x, y) -> {
- Blockable blockable = new RawBlockable(account, contactJid);
- if (xmppConnectionService.sendBlockRequest(blockable, false, null)) {
- Toast.makeText(BlocklistActivity.this, R.string.corresponding_chats_closed, Toast.LENGTH_SHORT).show();
- }
- return true;
- });
+ protected void showEnterJidDialog() {
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+ Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
+ if (prev != null) {
+ ft.remove(prev);
+ }
+ ft.addToBackStack(null);
+ EnterJidDialog dialog =
+ EnterJidDialog.newInstance(
+ null,
+ getString(R.string.block_jabber_id),
+ getString(R.string.block),
+ null,
+ null,
+ account.getJid().asBareJid().toString(),
+ true,
+ false,
+ EnterJidDialog.SanityCheck.NO);
- dialog.show(ft, "dialog");
- }
+ dialog.setOnEnterJidDialogPositiveListener(
+ (accountJid, contactJid, x, y) -> {
+ Blockable blockable = new RawBlockable(account, contactJid);
+ if (xmppConnectionService.sendBlockRequest(blockable, false, null)) {
+ Toast.makeText(
+ BlocklistActivity.this,
+ R.string.corresponding_chats_closed,
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ return true;
+ });
- protected void refreshUiReal() {
- final Editable editable = getSearchEditText().getText();
- if (editable != null) {
- filterContacts(editable.toString());
- } else {
- filterContacts();
- }
- }
+ dialog.show(ft, "dialog");
+ }
- @Override
- public void OnUpdateBlocklist(final OnUpdateBlocklist.Status status) {
- refreshUi();
- }
+ protected void refreshUiReal() {
+ final Editable editable = getSearchEditText().getText();
+ if (editable != null) {
+ filterContacts(editable.toString());
+ } else {
+ filterContacts();
+ }
+ }
+ @Override
+ public void OnUpdateBlocklist(final OnUpdateBlocklist.Status status) {
+ refreshUi();
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/ui/ChannelDiscoveryActivity.java b/src/main/java/eu/siacs/conversations/ui/ChannelDiscoveryActivity.java
index b5a7e6d4ceadfaaabc958e00c80aed7a92825889..f4bea10d84deae9db682b0435c803264e4f4fe41 100644
--- a/src/main/java/eu/siacs/conversations/ui/ChannelDiscoveryActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ChannelDiscoveryActivity.java
@@ -311,7 +311,7 @@ public class ChannelDiscoveryActivity extends XmppActivity
}
public void joinChannelSearchResult(final String selectedAccount, final Room result) {
- final Jid jid = Jid.ofEscaped(selectedAccount);
+ final Jid jid = Jid.of(selectedAccount);
final Account account = xmppConnectionService.findAccountByJid(jid);
final Conversation conversation =
xmppConnectionService.findOrCreateConversation(
diff --git a/src/main/java/eu/siacs/conversations/ui/ChooseAccountForProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/ChooseAccountForProfilePictureActivity.java
index 71662589ca3739f9a6a86ad83cefb828488fc6d5..ff60e6419b2abde89bbc53b6fce4417bb90bef7b 100644
--- a/src/main/java/eu/siacs/conversations/ui/ChooseAccountForProfilePictureActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ChooseAccountForProfilePictureActivity.java
@@ -4,14 +4,11 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Toast;
-
import androidx.databinding.DataBindingUtil;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityManageAccountsBinding;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.ui.adapter.AccountAdapter;
-
import java.util.ArrayList;
import java.util.List;
@@ -29,16 +26,18 @@ public class ChooseAccountForProfilePictureActivity extends XmppActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final ActivityManageAccountsBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_manage_accounts);
+ final ActivityManageAccountsBinding binding =
+ DataBindingUtil.setContentView(this, R.layout.activity_manage_accounts);
Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
setSupportActionBar(binding.toolbar);
configureActionBar(getSupportActionBar(), false);
this.mAccountAdapter = new AccountAdapter(this, accountList, false);
binding.accountList.setAdapter(this.mAccountAdapter);
- binding.accountList.setOnItemClickListener((arg0, view, position, arg3) -> {
- final Account account = accountList.get(position);
- goToProfilePictureActivity(account);
- });
+ binding.accountList.setOnItemClickListener(
+ (arg0, view, position, arg3) -> {
+ final Account account = accountList.get(position);
+ goToProfilePictureActivity(account);
+ });
}
@Override
@@ -58,7 +57,7 @@ public class ChooseAccountForProfilePictureActivity extends XmppActivity {
private void loadEnabledAccounts() {
accountList.clear();
- for(Account account : xmppConnectionService.getAccounts()) {
+ for (Account account : xmppConnectionService.getAccounts()) {
if (account.isEnabled()) {
accountList.add(account);
}
@@ -70,13 +69,17 @@ public class ChooseAccountForProfilePictureActivity extends XmppActivity {
final Uri uri = startIntent == null ? null : startIntent.getData();
if (uri != null) {
Intent intent = new Intent(this, PublishProfilePictureActivity.class);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
intent.setData(uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
startActivity(intent);
} catch (SecurityException e) {
- Toast.makeText(this, R.string.sharing_application_not_grant_permission, Toast.LENGTH_SHORT).show();
+ Toast.makeText(
+ this,
+ R.string.sharing_application_not_grant_permission,
+ Toast.LENGTH_SHORT)
+ .show();
return;
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java
index 1198d86dd7ae5ef648da2b4c6ac4e3a769799535..1344e40d6c8b6290d63b2f4c3555482709416c16 100644
--- a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java
@@ -16,23 +16,12 @@ import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
-
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.appcompat.app.ActionBar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
-
import com.google.common.base.Strings;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
@@ -44,8 +33,15 @@ import eu.siacs.conversations.ui.util.ActivityResult;
import eu.siacs.conversations.ui.util.PendingItem;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xmpp.Jid;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
-public class ChooseContactActivity extends AbstractSearchableListItemActivity implements MultiChoiceModeListener, AdapterView.OnItemClickListener {
+public class ChooseContactActivity extends AbstractSearchableListItemActivity
+ implements MultiChoiceModeListener, AdapterView.OnItemClickListener {
public static final String EXTRA_TITLE_RES_ID = "extra_title_res_id";
public static final String EXTRA_GROUP_CHAT_NAME = "extra_group_chat_name";
public static final String EXTRA_SELECT_MULTIPLE = "extra_select_multiple";
@@ -76,11 +72,11 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
} else {
contacts.add(conversation.getJid().asBareJid().toString());
}
- intent.putExtra(EXTRA_FILTERED_CONTACTS, contacts.toArray(new String[contacts.size()]));
+ intent.putExtra(EXTRA_FILTERED_CONTACTS, contacts.toArray(new String[0]));
intent.putExtra(EXTRA_CONVERSATION, conversation.getUuid());
intent.putExtra(EXTRA_SELECT_MULTIPLE, true);
intent.putExtra(EXTRA_SHOW_ENTER_JID, true);
- intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().asBareJid().toString());
return intent;
}
@@ -136,7 +132,11 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
final SharedPreferences preferences = getPreferences();
- this.startSearching = intent.getBooleanExtra("direct_search", false) && preferences.getBoolean("start_searching", getResources().getBoolean(R.bool.start_searching));
+ this.startSearching =
+ intent.getBooleanExtra("direct_search", false)
+ && preferences.getBoolean(
+ "start_searching",
+ getResources().getBoolean(R.bool.start_searching));
getListItemAdapter().refreshSettings();
getListItemAdapter().setOnTagClickedListener((tag) -> {
@@ -174,9 +174,11 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
binding.fab.setImageResource(R.drawable.ic_navigate_next_24dp);
binding.fab.show();
final View view = getSearchEditText();
- final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ final InputMethodManager imm =
+ (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (view != null && imm != null) {
- imm.hideSoftInputFromWindow(getSearchEditText().getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
+ imm.hideSoftInputFromWindow(
+ getSearchEditText().getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
}
return true;
}
@@ -241,11 +243,14 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
}
- public @StringRes
- int getTitleFromIntent() {
+ public @StringRes int getTitleFromIntent() {
final Intent intent = getIntent();
boolean multiple = intent != null && intent.getBooleanExtra(EXTRA_SELECT_MULTIPLE, false);
- @StringRes int fallback = multiple ? R.string.title_activity_choose_contacts : R.string.title_activity_choose_contact;
+ @StringRes
+ int fallback =
+ multiple
+ ? R.string.title_activity_choose_contacts
+ : R.string.title_activity_choose_contact;
return intent != null ? intent.getIntExtra(EXTRA_TITLE_RES_ID, fallback) : fallback;
}
@@ -254,7 +259,8 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
super.onCreateOptionsMenu(menu);
final Intent i = getIntent();
boolean showEnterJid = i != null && i.getBooleanExtra(EXTRA_SHOW_ENTER_JID, false);
- menu.findItem(R.id.action_scan_qr_code).setVisible(isCameraFeatureAvailable() && showEnterJid);
+ menu.findItem(R.id.action_scan_qr_code)
+ .setVisible(isCameraFeatureAvailable() && showEnterJid);
MenuItem mMenuSearchView = menu.findItem(R.id.action_search);
if (startSearching) {
mMenuSearchView.expandActionView();
@@ -290,7 +296,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
final var accounts = new ArrayList();
for (final var account : xmppConnectionService.getAccounts()) {
- if (mActivatedAccounts.contains(account.getJid().asBareJid().toEscapedString())) accounts.add(account);
+ if (mActivatedAccounts.contains(account.getJid().asBareJid().toString())) accounts.add(account);
}
for (final var contact : extraContacts) {
if (!filterContacts.contains(contact.getJid().asBareJid().toString())
@@ -325,7 +331,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
public void refreshUiReal() {
- //nothing to do. This Activity doesn't implement any listeners
+ // nothing to do. This Activity doesn't implement any listeners
}
@Override
@@ -380,8 +386,8 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
}
- return true;
- });
+ return true;
+ });
dialog.show(ft, "dialog");
}
@@ -398,7 +404,8 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
}
private void handleActivityResult(ActivityResult activityResult) {
- if (activityResult.resultCode == RESULT_OK && activityResult.requestCode == ScanActivity.REQUEST_SCAN_QR_CODE) {
+ if (activityResult.resultCode == RESULT_OK
+ && activityResult.requestCode == ScanActivity.REQUEST_SCAN_QR_CODE) {
String result = activityResult.data.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT);
XmppUri uri = new XmppUri(Strings.nullToEmpty(result));
if (uri.isValidJid()) {
@@ -412,8 +419,8 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
this.mActivatedAccounts.clear();
final var selected = getIntent().getStringExtra(EXTRA_ACCOUNT);
for (final Account account : xmppConnectionService.getAccounts()) {
- if (account.isEnabled() && (selected == null || selected.equals(account.getJid().asBareJid().toEscapedString()))) {
- this.mActivatedAccounts.add(account.getJid().asBareJid().toEscapedString());
+ if (account.isEnabled() && (selected == null || selected.equals(account.getJid().asBareJid().toString()))) {
+ this.mActivatedAccounts.add(account.getJid().asBareJid().toString());
}
}
filterContacts();
@@ -421,14 +428,16 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
if (activityResult != null) {
handleActivityResult(activityResult);
}
- final Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_DIALOG);
+ final Fragment fragment =
+ getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_DIALOG);
if (fragment instanceof OnBackendConnected) {
((OnBackendConnected) fragment).onBackendConnected();
}
}
@Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ public void onRequestPermissionsResult(
+ int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
ScanActivity.onRequestPermissionResult(this, requestCode, grantResults);
}
@@ -456,8 +465,10 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
return;
}
- final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(getSearchEditText().getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
+ final InputMethodManager imm =
+ (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(
+ getSearchEditText().getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
final ListItem mListItem = getListItems().get(position);
onListItemClicked(mListItem);
}
@@ -468,7 +479,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
data.putExtra("contact", item.getJid().toString());
String account = request.getStringExtra(EXTRA_ACCOUNT);
if (account == null && item instanceof Contact) {
- account = ((Contact) item).getAccount().getJid().asBareJid().toEscapedString();
+ account = ((Contact) item).getAccount().getJid().asBareJid().toString();
}
data.putExtra(EXTRA_ACCOUNT, account);
data.putExtra(EXTRA_SELECT_MULTIPLE, false);
diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
index 8843c3cb2670ed8125dad6cb39a01c50ac21035a..4c731d9d97b832b977bdbc812316a5eae8a01f84 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
@@ -328,7 +328,7 @@ public class ConferenceDetailsActivity extends XmppActivity
});
this.binding.relatedMucs.setOnClickListener(v -> {
final Intent intent = new Intent(this, ChannelDiscoveryActivity.class);
- intent.putExtra("services", new String[]{ mConversation.getJid().getDomain().toEscapedString(), mConversation.getAccount().getJid().toEscapedString() });
+ intent.putExtra("services", new String[]{ mConversation.getJid().getDomain().toString(), mConversation.getAccount().getJid().toString() });
startActivity(intent);
});
}
@@ -518,10 +518,9 @@ public class ConferenceDetailsActivity extends XmppActivity
if (mConversation != null) {
if (http) {
return "https://conversations.im/j/"
- + XmppUri.lameUrlEncode(
- mConversation.getJid().asBareJid().toEscapedString());
+ + XmppUri.lameUrlEncode(mConversation.getJid().asBareJid().toString());
} else {
- return "xmpp:" + Uri.encode(mConversation.getJid().asBareJid().toEscapedString(), "@/+") + "?join";
+ return "xmpp:" + Uri.encode(mConversation.getJid().asBareJid().toString(), "@/+") + "?join";
}
} else {
return null;
@@ -642,7 +641,7 @@ public class ConferenceDetailsActivity extends XmppActivity
}
final MucOptions mucOptions = mConversation.getMucOptions();
final User self = mucOptions.getSelf();
- final String account = mConversation.getAccount().getJid().asBareJid().toEscapedString();
+ final String account = mConversation.getAccount().getJid().asBareJid().toString();
setTitle(
mucOptions.isPrivateAndNonAnonymous()
? R.string.action_muc_details
@@ -655,10 +654,10 @@ public class ConferenceDetailsActivity extends XmppActivity
if (mConversation.isPrivateAndNonAnonymous()) {
this.binding.jid.setText(
getString(R.string.hosted_on, mConversation.getJid().getDomain()));
- this.binding.truejid.setText(mConversation.getJid().asBareJid().toEscapedString());
+ this.binding.truejid.setText(mConversation.getJid().asBareJid().toString());
if (mAdvancedMode) this.binding.truejid.setVisibility(View.VISIBLE);
} else {
- this.binding.jid.setText(mConversation.getJid().asBareJid().toEscapedString());
+ this.binding.jid.setText(mConversation.getJid().asBareJid().toString());
}
AvatarWorkerTask.loadAvatar(
mConversation, binding.yourPhoto, R.dimen.avatar_on_details_screen_size);
@@ -843,7 +842,7 @@ public class ConferenceDetailsActivity extends XmppActivity
@Override
public void onAffiliationChangeFailed(Jid jid, int resId) {
- displayToast(getString(resId, jid.asBareJid().toEscapedString()));
+ displayToast(getString(resId, jid.asBareJid().toString()));
}
@Override
diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
index 8f66f34038330b3c199128a2bef2609bc7ea7e73..e81ceba0a6b1bbef777829fcd593ac6f9fd0cc19 100644
--- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
@@ -202,7 +202,7 @@ public class ContactDetailsActivity extends OmemoActivity
if (quicksyContact) {
value = PhoneNumberUtilWrapper.toFormattedPhoneNumber(this, jid);
} else {
- value = jid.toEscapedString();
+ value = jid.toString();
}
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
builder.setTitle(getString(R.string.action_add_phone_book));
@@ -262,9 +262,9 @@ public class ContactDetailsActivity extends OmemoActivity
protected String getShareableUri(boolean http) {
if (http) {
return "https://conversations.im/i/"
- + XmppUri.lameUrlEncode(contact.getJid().asBareJid().toEscapedString());
+ + XmppUri.lameUrlEncode(contact.getJid().asBareJid().toString());
} else {
- return "xmpp:" + Uri.encode(contact.getJid().asBareJid().toEscapedString(), "@/+");
+ return "xmpp:" + Uri.encode(contact.getJid().asBareJid().toString(), "@/+");
}
}
@@ -276,11 +276,11 @@ public class ContactDetailsActivity extends OmemoActivity
&& savedInstanceState.getBoolean("show_inactive_omemo", false);
if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) {
try {
- this.accountJid = Jid.ofEscaped(getIntent().getExtras().getString(EXTRA_ACCOUNT));
+ this.accountJid = Jid.of(getIntent().getExtras().getString(EXTRA_ACCOUNT));
} catch (final IllegalArgumentException ignored) {
}
try {
- this.contactJid = Jid.ofEscaped(getIntent().getExtras().getString("contact"));
+ this.contactJid = Jid.of(getIntent().getExtras().getString("contact"));
} catch (final IllegalArgumentException ignored) {
}
}
@@ -370,7 +370,7 @@ public class ContactDetailsActivity extends OmemoActivity
JidDialog.style(
this,
R.string.remove_contact_text,
- contact.getJid().toEscapedString()))
+ contact.getJid().toString()))
.setPositiveButton(getString(R.string.delete), removeFromRoster)
.create()
.show();
@@ -598,7 +598,7 @@ public class ContactDetailsActivity extends OmemoActivity
}
binding.detailsContactjid.setText(IrregularUnicodeDetector.style(this, contact.getJid()));
- final String account = contact.getAccount().getJid().asBareJid().toEscapedString();
+ final String account = contact.getAccount().getJid().asBareJid().toString();
binding.detailsAccount.setText(getString(R.string.using_account, account));
AvatarWorkerTask.loadAvatar(
contact, binding.detailsContactBadge, R.dimen.avatar_on_details_screen_size);
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index 1867735579571a3b5fbdfda5a4af0081398e5e2c..8226c6e81e72261d856e851960b0282ef5c708ae 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -1099,8 +1099,7 @@ public class ConversationFragment extends XmppFragment
}
intent.putExtra("contacts", contacts);
intent.putExtra(
- EXTRA_ACCOUNT,
- conversation.getAccount().getJid().asBareJid().toEscapedString());
+ EXTRA_ACCOUNT, conversation.getAccount().getJid().asBareJid().toString());
intent.putExtra("conversation", conversation.getUuid());
startActivityForResult(intent, requestCode);
return true;
@@ -2298,8 +2297,8 @@ public class ConversationFragment extends XmppFragment
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(
RtpSessionActivity.EXTRA_ACCOUNT,
- id.getAccount().getJid().asBareJid().toEscapedString());
- intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.getWith().toEscapedString());
+ id.getAccount().getJid().asBareJid().toString());
+ intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.getWith().toString());
if (id instanceof AbstractJingleConnection) {
intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.getSessionId());
startActivity(intent);
@@ -4742,7 +4741,7 @@ public class ConversationFragment extends XmppFragment
+ message.getContact()
.getJid()
.asBareJid()
- .toEscapedString());
+ .toString());
break;
}
return true;
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationsOverviewFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationsOverviewFragment.java
index 7546aaf41d617f96cb919224d7c869dc2f1e3b7c..23ebc7bd7684ece2fd5640ec2d7b23592ae59942 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationsOverviewFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationsOverviewFragment.java
@@ -29,12 +29,13 @@
package eu.siacs.conversations.ui;
+import static androidx.recyclerview.widget.ItemTouchHelper.LEFT;
+import static androidx.recyclerview.widget.ItemTouchHelper.RIGHT;
+
import android.app.Activity;
-import android.app.AlertDialog;
import android.app.Fragment;
import android.content.Intent;
import android.graphics.Canvas;
-import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
@@ -47,23 +48,15 @@ import android.view.ViewGroup;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.PopupMenu;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-
-import com.google.android.material.color.MaterialColors;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
import com.google.common.base.Optional;
import com.google.common.collect.Collections2;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
import eu.siacs.conversations.BuildConfig;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
@@ -88,471 +81,543 @@ import eu.siacs.conversations.xmpp.jingle.OngoingRtpSession;
import static androidx.recyclerview.widget.ItemTouchHelper.LEFT;
import static androidx.recyclerview.widget.ItemTouchHelper.RIGHT;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
public class ConversationsOverviewFragment extends XmppFragment {
- private static final String STATE_SCROLL_POSITION = ConversationsOverviewFragment.class.getName()+".scroll_state";
-
- private final List conversations = new ArrayList<>();
- private final PendingItem swipedConversation = new PendingItem<>();
- private final PendingItem pendingScrollState = new PendingItem<>();
- private FragmentConversationsOverviewBinding binding;
- private ConversationAdapter conversationsAdapter;
- private XmppActivity activity;
- private final PendingActionHelper pendingActionHelper = new PendingActionHelper();
-
- private final ItemTouchHelper.SimpleCallback callback = new ItemTouchHelper.SimpleCallback(0,LEFT|RIGHT) {
- @Override
- public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
- return false;
- }
-
- @Override
- public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder,
- float dX, float dY, int actionState, boolean isCurrentlyActive) {
- if (viewHolder instanceof ConversationAdapter.ConversationViewHolder conversationViewHolder) {
- getDefaultUIUtil().onDraw(c,recyclerView,conversationViewHolder.binding.frame,dX,dY,actionState,isCurrentlyActive);
- }
- }
-
- @Override
- public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
- if (viewHolder instanceof ConversationAdapter.ConversationViewHolder conversationViewHolder) {
- getDefaultUIUtil().clearView(conversationViewHolder.binding.frame);
- }
- }
-
- @Override
- public float getSwipeEscapeVelocity(final float defaultEscapeVelocity) {
- return 32 * defaultEscapeVelocity;
- }
-
- @Override
- public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int direction) {
- pendingActionHelper.execute();
- int position = viewHolder.getLayoutPosition();
- try {
- swipedConversation.push(conversations.get(position));
- } catch (IndexOutOfBoundsException e) {
- return;
- }
- conversationsAdapter.remove(swipedConversation.peek(), position);
- activity.xmppConnectionService.markRead(swipedConversation.peek());
-
- if (position == 0 && conversationsAdapter.getItemCount() == 0) {
- final Conversation c = swipedConversation.pop();
- activity.xmppConnectionService.archiveConversation(c);
- return;
- }
- final boolean formerlySelected = ConversationFragment.getConversation(getActivity()) == swipedConversation.peek();
- if (activity instanceof OnConversationArchived) {
- ((OnConversationArchived) activity).onConversationArchived(swipedConversation.peek());
- }
- final Conversation c = swipedConversation.peek();
- final int title;
- if (c.getMode() == Conversational.MODE_MULTI) {
- if (c.getMucOptions().isPrivateAndNonAnonymous()) {
- title = R.string.title_undo_swipe_out_group_chat;
- } else {
- title = R.string.title_undo_swipe_out_channel;
- }
- } else {
- title = R.string.title_undo_swipe_out_chat;
- }
-
- final Snackbar snackbar = Snackbar.make(binding.list, title, 5000)
- .setAction(R.string.undo, v -> {
- pendingActionHelper.undo();
- Conversation conversation = swipedConversation.pop();
- conversationsAdapter.insert(conversation, position);
- if (formerlySelected) {
- if (activity instanceof OnConversationSelected) {
- ((OnConversationSelected) activity).onConversationSelected(c);
- }
- }
- LinearLayoutManager layoutManager = (LinearLayoutManager) binding.list.getLayoutManager();
- if (position > layoutManager.findLastVisibleItemPosition()) {
- binding.list.smoothScrollToPosition(position);
- }
- })
- .addCallback(new Snackbar.Callback() {
- @Override
- public void onDismissed(Snackbar transientBottomBar, int event) {
- switch (event) {
- case DISMISS_EVENT_SWIPE:
- case DISMISS_EVENT_TIMEOUT:
- pendingActionHelper.execute();
- break;
- }
- }
- });
-
- pendingActionHelper.push(() -> {
- if (snackbar.isShownOrQueued()) {
- snackbar.dismiss();
- }
- final Conversation conversation = swipedConversation.pop();
- if(conversation != null){
- if (!conversation.isRead(activity.xmppConnectionService) && conversation.getMode() == Conversation.MODE_SINGLE) {
- return;
- }
- activity.xmppConnectionService.archiveConversation(c);
- }
- });
- snackbar.show();
- }
- };
-
- private ItemTouchHelper touchHelper = null;
-
- public static Conversation getSuggestion(Activity activity) {
- final Conversation exception;
- Fragment fragment = activity.getFragmentManager().findFragmentById(R.id.main_fragment);
- if (fragment instanceof ConversationsOverviewFragment) {
- exception = ((ConversationsOverviewFragment) fragment).swipedConversation.peek();
- } else {
- exception = null;
- }
- return getSuggestion(activity, exception);
- }
-
- public static Conversation getSuggestion(Activity activity, Conversation exception) {
- Fragment fragment = activity.getFragmentManager().findFragmentById(R.id.main_fragment);
- if (fragment instanceof ConversationsOverviewFragment) {
- List conversations = ((ConversationsOverviewFragment) fragment).conversations;
- if (conversations.size() > 0) {
- Conversation suggestion = conversations.get(0);
- if (suggestion == exception) {
- if (conversations.size() > 1) {
- return conversations.get(1);
- }
- } else {
- return suggestion;
- }
- }
- }
- return null;
-
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- if (savedInstanceState == null) {
- return;
- }
- pendingScrollState.push(savedInstanceState.getParcelable(STATE_SCROLL_POSITION));
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- if (activity instanceof XmppActivity) {
- this.activity = (XmppActivity) activity;
- } else {
- throw new IllegalStateException("Trying to attach fragment to activity that is not an XmppActivity");
- }
- }
- @Override
- public void onDestroyView() {
- Log.d(Config.LOGTAG,"ConversationsOverviewFragment.onDestroyView()");
- super.onDestroyView();
- this.binding = null;
- this.conversationsAdapter = null;
- this.touchHelper = null;
- }
- @Override
- public void onDestroy() {
- Log.d(Config.LOGTAG,"ConversationsOverviewFragment.onDestroy()");
- super.onDestroy();
-
- }
- @Override
- public void onPause() {
- Log.d(Config.LOGTAG,"ConversationsOverviewFragment.onPause()");
- pendingActionHelper.execute();
- super.onPause();
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- this.activity = null;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
- }
-
- @Override
- public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- this.binding = DataBindingUtil.inflate(inflater, R.layout.fragment_conversations_overview, container, false);
- this.binding.fab.setOnClickListener((view) -> activity.launchStartConversation());
-
- this.conversationsAdapter = new ConversationAdapter(this.activity, this.conversations);
- this.conversationsAdapter.setConversationClickListener((view, conversation) -> {
- if (activity instanceof OnConversationSelected) {
- ((OnConversationSelected) activity).onConversationSelected(conversation);
- } else {
- Log.w(ConversationsOverviewFragment.class.getCanonicalName(), "Activity does not implement OnConversationSelected");
- }
- });
- this.binding.list.setAdapter(this.conversationsAdapter);
- this.binding.list.setLayoutManager(new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false));
- registerForContextMenu(this.binding.list);
- this.binding.list.addOnScrollListener(ExtendedFabSizeChanger.of(binding.fab));
- this.touchHelper = new ItemTouchHelper(this.callback);
- this.touchHelper.attachToRecyclerView(this.binding.list);
- return binding.getRoot();
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
- menuInflater.inflate(R.menu.fragment_conversations_overview, menu);
- AccountUtils.showHideMenuItems(menu);
- final MenuItem easyOnboardInvite = menu.findItem(R.id.action_easy_invite);
- easyOnboardInvite.setVisible(EasyOnboardingInvite.anyHasSupport(activity == null ? null : activity.xmppConnectionService));
- if (activity != null && activity.xmppConnectionService != null && activity.xmppConnectionService.isOnboarding()) {
- final MenuItem manageAccounts = menu.findItem(R.id.action_accounts);
- if (manageAccounts != null) manageAccounts.setVisible(false);
-
- final MenuItem settings = menu.findItem(R.id.action_settings);
- if (settings != null) settings.setVisible(false);
- }
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
- activity.getMenuInflater().inflate(R.menu.conversations, menu);
-
- final MenuItem menuMucDetails = menu.findItem(R.id.action_muc_details);
- final MenuItem menuContactDetails = menu.findItem(R.id.action_contact_details);
- final MenuItem menuMute = menu.findItem(R.id.action_mute);
- final MenuItem menuUnmute = menu.findItem(R.id.action_unmute);
- final MenuItem menuOngoingCall = menu.findItem(R.id.action_ongoing_call);
- final MenuItem menuTogglePinned = menu.findItem(R.id.action_toggle_pinned);
- final MenuItem menuArchiveChat = menu.findItem(R.id.action_archive);
-
- if (menuInfo == null) return;
- int pos = ((AdapterContextMenuInfo) menuInfo).position;
- if (pos < 0) return;
- Conversation conversation = conversations.get(pos);
- if (conversation != null) {
- if (conversation.getMode() == Conversation.MODE_MULTI) {
- menuContactDetails.setVisible(false);
- menuMucDetails.setTitle(conversation.getMucOptions().isPrivateAndNonAnonymous() ? R.string.action_muc_details : R.string.channel_details);
- menuOngoingCall.setVisible(false);
- menuArchiveChat.setTitle("Leave " + (conversation.getMucOptions().isPrivateAndNonAnonymous() ? "group chat" : "Channel"));
- } else {
- final XmppConnectionService service = activity == null ? null : activity.xmppConnectionService;
- final Optional ongoingRtpSession = service == null ? Optional.absent() : service.getJingleConnectionManager().getOngoingRtpConnection(conversation.getContact());
- if (ongoingRtpSession.isPresent()) {
- menuOngoingCall.setVisible(true);
- } else {
- menuOngoingCall.setVisible(false);
- }
- menuContactDetails.setVisible(!conversation.withSelf());
- menuMucDetails.setVisible(false);
- menuArchiveChat.setTitle(R.string.action_archive_chat);
- }
- if (conversation.isMuted()) {
- menuMute.setVisible(false);
- } else {
- menuUnmute.setVisible(false);
- }
- if (conversation.getBooleanAttribute(Conversation.ATTRIBUTE_PINNED_ON_TOP, false)) {
- menuTogglePinned.setTitle(R.string.remove_from_favorites);
- } else {
- menuTogglePinned.setTitle(R.string.add_to_favorites);
- }
- }
- super.onCreateContextMenu(menu, view, menuInfo);
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- final var info = ((AdapterContextMenuInfo) item.getMenuInfo());
- if (info == null) return false;
-
- int pos = info.position;
- if (conversations == null || conversations.size() <= pos || pos < 0) return false;
-
- Conversation conversation = conversations.get(pos);
- ConversationFragment fragment = new ConversationFragment();
- fragment.setHasOptionsMenu(false);
- fragment.onAttach(activity);
- fragment.reInit(conversation, null);
- boolean r = fragment.onOptionsItemSelected(item);
- refresh();
- return r;
- }
-
- @Override
- public void onBackendConnected() {
- refresh();
- }
-
- private void setupSwipe() {
- if (this.touchHelper == null && (activity.xmppConnectionService == null || !activity.xmppConnectionService.isOnboarding())) {
- this.touchHelper = new ItemTouchHelper(this.callback);
- this.touchHelper.attachToRecyclerView(this.binding.list);
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle bundle) {
- super.onSaveInstanceState(bundle);
- ScrollState scrollState = getScrollState();
- if (scrollState != null) {
- bundle.putParcelable(STATE_SCROLL_POSITION, scrollState);
- }
- }
-
- private ScrollState getScrollState() {
- if (this.binding == null) {
- return null;
- }
- LinearLayoutManager layoutManager = (LinearLayoutManager) this.binding.list.getLayoutManager();
- int position = layoutManager.findFirstVisibleItemPosition();
- final View view = this.binding.list.getChildAt(0);
- if (view != null) {
- return new ScrollState(position,view.getTop());
- } else {
- return new ScrollState(position, 0);
- }
- }
-
- @Override
- public void onStart() {
- super.onStart();
- Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onStart()");
- if (activity.xmppConnectionService != null) {
- refresh();
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onResume()");
- }
-
- @Override
- public boolean onOptionsItemSelected(final MenuItem item) {
- if (MenuDoubleTabUtil.shouldIgnoreTap()) {
- return false;
- }
- switch (item.getItemId()) {
- case R.id.action_search:
- startActivity(new Intent(getActivity(), SearchActivity.class));
- return true;
- case R.id.action_easy_invite:
- selectAccountToStartEasyInvite();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- private void selectAccountToStartEasyInvite() {
- final List accounts = EasyOnboardingInvite.getSupportingAccounts(activity.xmppConnectionService);
- if (accounts.isEmpty()) {
- //This can technically happen if opening the menu item races with accounts reconnecting or something
- Toast.makeText(getActivity(),R.string.no_active_accounts_support_this, Toast.LENGTH_LONG).show();
- } else if (accounts.size() == 1) {
- openEasyInviteScreen(accounts.get(0));
- } else {
- final AtomicReference selectedAccount = new AtomicReference<>(accounts.get(0));
- final MaterialAlertDialogBuilder alertDialogBuilder = new MaterialAlertDialogBuilder(activity);
- alertDialogBuilder.setTitle(R.string.choose_account);
- final String[] asStrings = Collections2.transform(accounts, a -> a.getJid().asBareJid().toEscapedString()).toArray(new String[0]);
- alertDialogBuilder.setSingleChoiceItems(asStrings, 0, (dialog, which) -> selectedAccount.set(accounts.get(which)));
- alertDialogBuilder.setNegativeButton(R.string.cancel, null);
- alertDialogBuilder.setPositiveButton(R.string.ok, (dialog, which) -> openEasyInviteScreen(selectedAccount.get()));
- alertDialogBuilder.create().show();
- }
- }
-
- private void openEasyInviteScreen(final Account account) {
- EasyOnboardingInviteActivity.launch(account, activity);
- }
-
- @Override
- protected void refresh() {
- if (binding == null || this.activity == null) {
- Log.d(Config.LOGTAG,"ConversationsOverviewFragment.refresh() skipped updated because view binding or activity was null");
- return;
- }
- this.activity.populateWithOrderedConversations(this.conversations);
- Conversation removed = this.swipedConversation.peek();
- if (removed != null) {
- if (removed.isRead(activity == null ? null : activity.xmppConnectionService)) {
- this.conversations.remove(removed);
- } else {
- pendingActionHelper.execute();
- }
- }
- this.conversationsAdapter.notifyDataSetChanged();
- ScrollState scrollState = pendingScrollState.pop();
- if (scrollState != null) {
- setScrollPosition(scrollState);
- }
-
- if (activity.xmppConnectionService != null && activity.xmppConnectionService.isOnboarding()) {
- binding.fab.setVisibility(View.GONE);
-
- if (this.conversations.size() == 1) {
- if (activity instanceof OnConversationSelected) {
- ((OnConversationSelected) activity).onConversationSelected(this.conversations.get(0));
- } else {
- Log.w(ConversationsOverviewFragment.class.getCanonicalName(), "Activity does not implement OnConversationSelected");
- }
- }
- } else {
- binding.fab.setVisibility(View.VISIBLE);
- }
- setupSwipe();
-
- if (activity.xmppConnectionService == null || binding == null || binding.overviewSnackbar == null) return;
- binding.overviewSnackbar.setVisibility(View.GONE);
- for (final var account : activity.xmppConnectionService.getAccounts()) {
- if (activity.getPreferences().getBoolean("no_mam_pref_warn:" + account.getUuid(), false)) continue;
- if (account.mamPrefs() != null && !"always".equals(account.mamPrefs().getAttribute("default"))) {
- binding.overviewSnackbar.setVisibility(View.VISIBLE);
- binding.overviewSnackbarMessage.setText("Your account " + account.getJid().asBareJid().toEscapedString() + " does not have archiving fully enabled. This may result in missed messages if you use multiple devices or apps.");
- binding.overviewSnackbarAction.setOnClickListener((v) -> {
- final var prefs = account.mamPrefs();
- prefs.setAttribute("default", "always");
- activity.xmppConnectionService.pushMamPreferences(account, prefs);
- refresh();
- });
-
- binding.overviewSnackbarAction.setOnLongClickListener((v) -> {
- PopupMenu popupMenu = new PopupMenu(getActivity(), v);
- popupMenu.inflate(R.menu.mam_pref_fix);
- popupMenu.setOnMenuItemClickListener(menuItem -> {
- switch (menuItem.getItemId()) {
- case R.id.ignore:
- final var editor = activity.getPreferences().edit();
- editor.putBoolean("no_mam_pref_warn:" + account.getUuid(), true).apply();
- editor.apply();
- refresh();
- return true;
- }
- return true;
- });
- popupMenu.show();
- return true;
- });
- break;
- }
- }
- }
-
- private void setScrollPosition(ScrollState scrollPosition) {
- if (scrollPosition != null) {
- LinearLayoutManager layoutManager = (LinearLayoutManager) binding.list.getLayoutManager();
- layoutManager.scrollToPositionWithOffset(scrollPosition.position, scrollPosition.offset);
- }
- }
+ private static final String STATE_SCROLL_POSITION =
+ ConversationsOverviewFragment.class.getName() + ".scroll_state";
+
+ private final List conversations = new ArrayList<>();
+ private final PendingItem swipedConversation = new PendingItem<>();
+ private final PendingItem pendingScrollState = new PendingItem<>();
+ private FragmentConversationsOverviewBinding binding;
+ private ConversationAdapter conversationsAdapter;
+ private XmppActivity activity;
+ private final PendingActionHelper pendingActionHelper = new PendingActionHelper();
+
+ private final ItemTouchHelper.SimpleCallback callback =
+ new ItemTouchHelper.SimpleCallback(0, LEFT | RIGHT) {
+ @Override
+ public boolean onMove(
+ @NonNull RecyclerView recyclerView,
+ @NonNull RecyclerView.ViewHolder viewHolder,
+ @NonNull RecyclerView.ViewHolder target) {
+ return false;
+ }
+
+ @Override
+ public void onChildDraw(
+ @NonNull Canvas c,
+ @NonNull RecyclerView recyclerView,
+ @NonNull RecyclerView.ViewHolder viewHolder,
+ float dX,
+ float dY,
+ int actionState,
+ boolean isCurrentlyActive) {
+ if (viewHolder
+ instanceof
+ ConversationAdapter.ConversationViewHolder conversationViewHolder) {
+ getDefaultUIUtil()
+ .onDraw(
+ c,
+ recyclerView,
+ conversationViewHolder.binding.frame,
+ dX,
+ dY,
+ actionState,
+ isCurrentlyActive);
+ }
+ }
+
+ @Override
+ public void clearView(
+ @NonNull RecyclerView recyclerView,
+ @NonNull RecyclerView.ViewHolder viewHolder) {
+ if (viewHolder
+ instanceof
+ ConversationAdapter.ConversationViewHolder conversationViewHolder) {
+ getDefaultUIUtil().clearView(conversationViewHolder.binding.frame);
+ }
+ }
+
+ @Override
+ public float getSwipeEscapeVelocity(final float defaultEscapeVelocity) {
+ return 32 * defaultEscapeVelocity;
+ }
+
+ @Override
+ public void onSwiped(
+ final RecyclerView.ViewHolder viewHolder, final int direction) {
+ pendingActionHelper.execute();
+ int position = viewHolder.getLayoutPosition();
+ try {
+ swipedConversation.push(conversations.get(position));
+ } catch (IndexOutOfBoundsException e) {
+ return;
+ }
+ conversationsAdapter.remove(swipedConversation.peek(), position);
+ activity.xmppConnectionService.markRead(swipedConversation.peek());
+
+ if (position == 0 && conversationsAdapter.getItemCount() == 0) {
+ final Conversation c = swipedConversation.pop();
+ activity.xmppConnectionService.archiveConversation(c);
+ return;
+ }
+ final boolean formerlySelected =
+ ConversationFragment.getConversation(getActivity())
+ == swipedConversation.peek();
+ if (activity instanceof OnConversationArchived) {
+ ((OnConversationArchived) activity)
+ .onConversationArchived(swipedConversation.peek());
+ }
+ final Conversation c = swipedConversation.peek();
+ final int title;
+ if (c.getMode() == Conversational.MODE_MULTI) {
+ if (c.getMucOptions().isPrivateAndNonAnonymous()) {
+ title = R.string.title_undo_swipe_out_group_chat;
+ } else {
+ title = R.string.title_undo_swipe_out_channel;
+ }
+ } else {
+ title = R.string.title_undo_swipe_out_chat;
+ }
+
+ final Snackbar snackbar =
+ Snackbar.make(binding.list, title, 5000)
+ .setAction(
+ R.string.undo,
+ v -> {
+ pendingActionHelper.undo();
+ Conversation conversation =
+ swipedConversation.pop();
+ conversationsAdapter.insert(conversation, position);
+ if (formerlySelected) {
+ if (activity
+ instanceof OnConversationSelected) {
+ ((OnConversationSelected) activity)
+ .onConversationSelected(c);
+ }
+ }
+ LinearLayoutManager layoutManager =
+ (LinearLayoutManager)
+ binding.list.getLayoutManager();
+ if (position
+ > layoutManager
+ .findLastVisibleItemPosition()) {
+ binding.list.smoothScrollToPosition(position);
+ }
+ })
+ .addCallback(
+ new Snackbar.Callback() {
+ @Override
+ public void onDismissed(
+ Snackbar transientBottomBar, int event) {
+ switch (event) {
+ case DISMISS_EVENT_SWIPE:
+ case DISMISS_EVENT_TIMEOUT:
+ pendingActionHelper.execute();
+ break;
+ }
+ }
+ });
+
+ pendingActionHelper.push(
+ () -> {
+ if (snackbar.isShownOrQueued()) {
+ snackbar.dismiss();
+ }
+ final Conversation conversation = swipedConversation.pop();
+ if (conversation != null) {
+ if (!conversation.isRead(activity.xmppConnectionService)
+ && conversation.getMode() == Conversation.MODE_SINGLE) {
+ return;
+ }
+ activity.xmppConnectionService.archiveConversation(c);
+ }
+ });
+ snackbar.show();
+ }
+ };
+
+ private ItemTouchHelper touchHelper;
+
+ public static Conversation getSuggestion(Activity activity) {
+ final Conversation exception;
+ Fragment fragment = activity.getFragmentManager().findFragmentById(R.id.main_fragment);
+ if (fragment instanceof ConversationsOverviewFragment) {
+ exception = ((ConversationsOverviewFragment) fragment).swipedConversation.peek();
+ } else {
+ exception = null;
+ }
+ return getSuggestion(activity, exception);
+ }
+
+ public static Conversation getSuggestion(Activity activity, Conversation exception) {
+ Fragment fragment = activity.getFragmentManager().findFragmentById(R.id.main_fragment);
+ if (fragment instanceof ConversationsOverviewFragment) {
+ List conversations =
+ ((ConversationsOverviewFragment) fragment).conversations;
+ if (conversations.size() > 0) {
+ Conversation suggestion = conversations.get(0);
+ if (suggestion == exception) {
+ if (conversations.size() > 1) {
+ return conversations.get(1);
+ }
+ } else {
+ return suggestion;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ if (savedInstanceState == null) {
+ return;
+ }
+ pendingScrollState.push(savedInstanceState.getParcelable(STATE_SCROLL_POSITION));
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ if (activity instanceof XmppActivity) {
+ this.activity = (XmppActivity) activity;
+ } else {
+ throw new IllegalStateException(
+ "Trying to attach fragment to activity that is not an XmppActivity");
+ }
+ }
+
+ @Override
+ public void onDestroyView() {
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onDestroyView()");
+ super.onDestroyView();
+ this.binding = null;
+ this.conversationsAdapter = null;
+ this.touchHelper = null;
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onDestroy()");
+ super.onDestroy();
+ }
+
+ @Override
+ public void onPause() {
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onPause()");
+ pendingActionHelper.execute();
+ super.onPause();
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ this.activity = null;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public View onCreateView(
+ final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ this.binding =
+ DataBindingUtil.inflate(
+ inflater, R.layout.fragment_conversations_overview, container, false);
+ this.binding.fab.setOnClickListener(
+ (view) -> StartConversationActivity.launch(getActivity()));
+
+ this.conversationsAdapter = new ConversationAdapter(this.activity, this.conversations);
+ this.conversationsAdapter.setConversationClickListener(
+ (view, conversation) -> {
+ if (activity instanceof OnConversationSelected) {
+ ((OnConversationSelected) activity).onConversationSelected(conversation);
+ } else {
+ Log.w(
+ ConversationsOverviewFragment.class.getCanonicalName(),
+ "Activity does not implement OnConversationSelected");
+ }
+ });
+ this.binding.list.setAdapter(this.conversationsAdapter);
+ this.binding.list.setLayoutManager(
+ new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
+ registerForContextMenu(this.binding.list);
+ this.binding.list.addOnScrollListener(ExtendedFabSizeChanger.of(binding.fab));
+ this.touchHelper = new ItemTouchHelper(this.callback);
+ this.touchHelper.attachToRecyclerView(this.binding.list);
+ return binding.getRoot();
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
+ menuInflater.inflate(R.menu.fragment_conversations_overview, menu);
+ AccountUtils.showHideMenuItems(menu);
+ final MenuItem easyOnboardInvite = menu.findItem(R.id.action_easy_invite);
+ easyOnboardInvite.setVisible(EasyOnboardingInvite.anyHasSupport(activity == null ? null : activity.xmppConnectionService));
+ if (activity != null && activity.xmppConnectionService != null && activity.xmppConnectionService.isOnboarding()) {
+ final MenuItem manageAccounts = menu.findItem(R.id.action_accounts);
+ if (manageAccounts != null) manageAccounts.setVisible(false);
+
+ final MenuItem settings = menu.findItem(R.id.action_settings);
+ if (settings != null) settings.setVisible(false);
+ }
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
+ activity.getMenuInflater().inflate(R.menu.conversations, menu);
+
+ final MenuItem menuMucDetails = menu.findItem(R.id.action_muc_details);
+ final MenuItem menuContactDetails = menu.findItem(R.id.action_contact_details);
+ final MenuItem menuMute = menu.findItem(R.id.action_mute);
+ final MenuItem menuUnmute = menu.findItem(R.id.action_unmute);
+ final MenuItem menuOngoingCall = menu.findItem(R.id.action_ongoing_call);
+ final MenuItem menuTogglePinned = menu.findItem(R.id.action_toggle_pinned);
+ final MenuItem menuArchiveChat = menu.findItem(R.id.action_archive);
+
+ if (menuInfo == null) return;
+ int pos = ((AdapterContextMenuInfo) menuInfo).position;
+ if (pos < 0) return;
+ Conversation conversation = conversations.get(pos);
+ if (conversation != null) {
+ if (conversation.getMode() == Conversation.MODE_MULTI) {
+ menuContactDetails.setVisible(false);
+ menuMucDetails.setTitle(conversation.getMucOptions().isPrivateAndNonAnonymous() ? R.string.action_muc_details : R.string.channel_details);
+ menuOngoingCall.setVisible(false);
+ menuArchiveChat.setTitle("Leave " + (conversation.getMucOptions().isPrivateAndNonAnonymous() ? "group chat" : "Channel"));
+ } else {
+ final XmppConnectionService service = activity == null ? null : activity.xmppConnectionService;
+ final Optional ongoingRtpSession = service == null ? Optional.absent() : service.getJingleConnectionManager().getOngoingRtpConnection(conversation.getContact());
+ if (ongoingRtpSession.isPresent()) {
+ menuOngoingCall.setVisible(true);
+ } else {
+ menuOngoingCall.setVisible(false);
+ }
+ menuContactDetails.setVisible(!conversation.withSelf());
+ menuMucDetails.setVisible(false);
+ menuArchiveChat.setTitle(R.string.action_archive_chat);
+ }
+ if (conversation.isMuted()) {
+ menuMute.setVisible(false);
+ } else {
+ menuUnmute.setVisible(false);
+ }
+ if (conversation.getBooleanAttribute(Conversation.ATTRIBUTE_PINNED_ON_TOP, false)) {
+ menuTogglePinned.setTitle(R.string.remove_from_favorites);
+ } else {
+ menuTogglePinned.setTitle(R.string.add_to_favorites);
+ }
+ }
+ super.onCreateContextMenu(menu, view, menuInfo);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ final var info = ((AdapterContextMenuInfo) item.getMenuInfo());
+ if (info == null) return false;
+
+ int pos = info.position;
+ if (conversations == null || conversations.size() <= pos || pos < 0) return false;
+
+ Conversation conversation = conversations.get(pos);
+ ConversationFragment fragment = new ConversationFragment();
+ fragment.setHasOptionsMenu(false);
+ fragment.onAttach(activity);
+ fragment.reInit(conversation, null);
+ boolean r = fragment.onOptionsItemSelected(item);
+ refresh();
+ return r;
+ }
+
+ @Override
+ public void onBackendConnected() {
+ refresh();
+ }
+
+ private void setupSwipe() {
+ if (this.touchHelper == null && (activity.xmppConnectionService == null || !activity.xmppConnectionService.isOnboarding())) {
+ this.touchHelper = new ItemTouchHelper(this.callback);
+ this.touchHelper.attachToRecyclerView(this.binding.list);
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle bundle) {
+ super.onSaveInstanceState(bundle);
+ ScrollState scrollState = getScrollState();
+ if (scrollState != null) {
+ bundle.putParcelable(STATE_SCROLL_POSITION, scrollState);
+ }
+ }
+
+ private ScrollState getScrollState() {
+ if (this.binding == null) {
+ return null;
+ }
+ LinearLayoutManager layoutManager =
+ (LinearLayoutManager) this.binding.list.getLayoutManager();
+ int position = layoutManager.findFirstVisibleItemPosition();
+ final View view = this.binding.list.getChildAt(0);
+ if (view != null) {
+ return new ScrollState(position, view.getTop());
+ } else {
+ return new ScrollState(position, 0);
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onStart()");
+ if (activity.xmppConnectionService != null) {
+ refresh();
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onResume()");
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (MenuDoubleTabUtil.shouldIgnoreTap()) {
+ return false;
+ }
+ switch (item.getItemId()) {
+ case R.id.action_search:
+ startActivity(new Intent(getActivity(), SearchActivity.class));
+ return true;
+ case R.id.action_easy_invite:
+ selectAccountToStartEasyInvite();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void selectAccountToStartEasyInvite() {
+ final List accounts =
+ EasyOnboardingInvite.getSupportingAccounts(activity.xmppConnectionService);
+ if (accounts.isEmpty()) {
+ // This can technically happen if opening the menu item races with accounts reconnecting
+ // or something
+ Toast.makeText(
+ getActivity(),
+ R.string.no_active_accounts_support_this,
+ Toast.LENGTH_LONG)
+ .show();
+ } else if (accounts.size() == 1) {
+ openEasyInviteScreen(accounts.get(0));
+ } else {
+ final AtomicReference selectedAccount = new AtomicReference<>(accounts.get(0));
+ final MaterialAlertDialogBuilder alertDialogBuilder =
+ new MaterialAlertDialogBuilder(activity);
+ alertDialogBuilder.setTitle(R.string.choose_account);
+ final String[] asStrings =
+ Collections2.transform(accounts, a -> a.getJid().asBareJid().toString())
+ .toArray(new String[0]);
+ alertDialogBuilder.setSingleChoiceItems(
+ asStrings, 0, (dialog, which) -> selectedAccount.set(accounts.get(which)));
+ alertDialogBuilder.setNegativeButton(R.string.cancel, null);
+ alertDialogBuilder.setPositiveButton(
+ R.string.ok, (dialog, which) -> openEasyInviteScreen(selectedAccount.get()));
+ alertDialogBuilder.create().show();
+ }
+ }
+
+ private void openEasyInviteScreen(final Account account) {
+ EasyOnboardingInviteActivity.launch(account, activity);
+ }
+
+ @Override
+ protected void refresh() {
+ if (binding == null || this.activity == null) {
+ Log.d(Config.LOGTAG,"ConversationsOverviewFragment.refresh() skipped updated because view binding or activity was null");
+ return;
+ }
+ this.activity.populateWithOrderedConversations(this.conversations);
+ Conversation removed = this.swipedConversation.peek();
+ if (removed != null) {
+ if (removed.isRead(activity == null ? null : activity.xmppConnectionService)) {
+ this.conversations.remove(removed);
+ } else {
+ pendingActionHelper.execute();
+ }
+ }
+ this.conversationsAdapter.notifyDataSetChanged();
+ ScrollState scrollState = pendingScrollState.pop();
+ if (scrollState != null) {
+ setScrollPosition(scrollState);
+ }
+
+ if (activity.xmppConnectionService != null && activity.xmppConnectionService.isOnboarding()) {
+ binding.fab.setVisibility(View.GONE);
+
+ if (this.conversations.size() == 1) {
+ if (activity instanceof OnConversationSelected) {
+ ((OnConversationSelected) activity).onConversationSelected(this.conversations.get(0));
+ } else {
+ Log.w(ConversationsOverviewFragment.class.getCanonicalName(), "Activity does not implement OnConversationSelected");
+ }
+ }
+ } else {
+ binding.fab.setVisibility(View.VISIBLE);
+ }
+ setupSwipe();
+
+ if (activity.xmppConnectionService == null || binding == null || binding.overviewSnackbar == null) return;
+ binding.overviewSnackbar.setVisibility(View.GONE);
+ for (final var account : activity.xmppConnectionService.getAccounts()) {
+ if (activity.getPreferences().getBoolean("no_mam_pref_warn:" + account.getUuid(), false)) continue;
+ if (account.mamPrefs() != null && !"always".equals(account.mamPrefs().getAttribute("default"))) {
+ binding.overviewSnackbar.setVisibility(View.VISIBLE);
+ binding.overviewSnackbarMessage.setText("Your account " + account.getJid().asBareJid().toString() + " does not have archiving fully enabled. This may result in missed messages if you use multiple devices or apps.");
+ binding.overviewSnackbarAction.setOnClickListener((v) -> {
+ final var prefs = account.mamPrefs();
+ prefs.setAttribute("default", "always");
+ activity.xmppConnectionService.pushMamPreferences(account, prefs);
+ refresh();
+ });
+
+ binding.overviewSnackbarAction.setOnLongClickListener((v) -> {
+ PopupMenu popupMenu = new PopupMenu(getActivity(), v);
+ popupMenu.inflate(R.menu.mam_pref_fix);
+ popupMenu.setOnMenuItemClickListener(menuItem -> {
+ switch (menuItem.getItemId()) {
+ case R.id.ignore:
+ final var editor = activity.getPreferences().edit();
+ editor.putBoolean("no_mam_pref_warn:" + account.getUuid(), true).apply();
+ editor.apply();
+ refresh();
+ return true;
+ }
+ return true;
+ });
+ popupMenu.show();
+ return true;
+ });
+ break;
+ }
+ }
+ }
+
+ private void setScrollPosition(ScrollState scrollPosition) {
+ if (scrollPosition != null) {
+ LinearLayoutManager layoutManager =
+ (LinearLayoutManager) binding.list.getLayoutManager();
+ layoutManager.scrollToPositionWithOffset(
+ scrollPosition.position, scrollPosition.offset);
+ }
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/ui/CreatePublicChannelDialog.java b/src/main/java/eu/siacs/conversations/ui/CreatePublicChannelDialog.java
index b20db451d74501c0cfc5c4fac6895b17fc356029..b12aba750cb0accb3a0ace23dccf6000425ba759 100644
--- a/src/main/java/eu/siacs/conversations/ui/CreatePublicChannelDialog.java
+++ b/src/main/java/eu/siacs/conversations/ui/CreatePublicChannelDialog.java
@@ -11,18 +11,11 @@ import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
-
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.DialogFragment;
-
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.DialogCreatePublicChannelBinding;
import eu.siacs.conversations.entities.Account;
@@ -33,10 +26,14 @@ import eu.siacs.conversations.ui.util.DelayedHintHelper;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.XmppConnection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
public class CreatePublicChannelDialog extends DialogFragment implements OnBackendConnected {
- private static final char[] FORBIDDEN = new char[]{'\u0022','&','\'','/',':','<','>','@'};
+ private static final char[] FORBIDDEN =
+ new char[] {'\u0022', '&', '\'', '/', ':', '<', '>', '@'};
private static final String ACCOUNTS_LIST_KEY = "activated_accounts_list";
private CreatePublicChannelDialogListener mListener;
@@ -62,48 +59,56 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- jidWasModified = savedInstanceState != null && savedInstanceState.getBoolean("jid_was_modified_false", false);
- nameEntered = savedInstanceState != null && savedInstanceState.getBoolean("name_entered", false);
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity());
+ jidWasModified =
+ savedInstanceState != null
+ && savedInstanceState.getBoolean("jid_was_modified_false", false);
+ nameEntered =
+ savedInstanceState != null && savedInstanceState.getBoolean("name_entered", false);
+ final MaterialAlertDialogBuilder builder =
+ new MaterialAlertDialogBuilder(requireActivity());
builder.setTitle(R.string.create_public_channel);
- final DialogCreatePublicChannelBinding binding = DataBindingUtil.inflate(getActivity().getLayoutInflater(), R.layout.dialog_create_public_channel, null, false);
- binding.account.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- updateJidSuggestion(binding);
- }
-
- @Override
- public void onNothingSelected(AdapterView> parent) {
-
- }
- });
- binding.jid.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
-
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- if (skipTetxWatcher) {
- return;
- }
- if (jidWasModified) {
- jidWasModified = !TextUtils.isEmpty(s);
- } else {
- jidWasModified = !s.toString().equals(getJidSuggestion(binding));
- }
- }
- });
- updateInputs(binding,false);
+ final DialogCreatePublicChannelBinding binding =
+ DataBindingUtil.inflate(
+ getActivity().getLayoutInflater(),
+ R.layout.dialog_create_public_channel,
+ null,
+ false);
+ binding.account.setOnItemSelectedListener(
+ new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(
+ AdapterView> parent, View view, int position, long id) {
+ updateJidSuggestion(binding);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {}
+ });
+ binding.jid.addTextChangedListener(
+ new TextWatcher() {
+ @Override
+ public void beforeTextChanged(
+ CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (skipTetxWatcher) {
+ return;
+ }
+ if (jidWasModified) {
+ jidWasModified = !TextUtils.isEmpty(s);
+ } else {
+ jidWasModified = !s.toString().equals(getJidSuggestion(binding));
+ }
+ }
+ });
+ updateInputs(binding, false);
ArrayList mActivatedAccounts = getArguments().getStringArrayList(ACCOUNTS_LIST_KEY);
- StartConversationActivity.populateAccountSpinner(getActivity(), mActivatedAccounts, binding.account);
+ StartConversationActivity.populateAccountSpinner(
+ getActivity(), mActivatedAccounts, binding.account);
builder.setView(binding.getRoot());
builder.setPositiveButton(nameEntered ? R.string.create : R.string.next, null);
builder.setNegativeButton(nameEntered ? R.string.back : R.string.cancel, null);
@@ -111,14 +116,18 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
this.knownHostsAdapter = new KnownHostsAdapter(getActivity(), R.layout.item_autocomplete);
binding.jid.setAdapter(knownHostsAdapter);
final AlertDialog dialog = builder.create();
- binding.groupChatName.setOnEditorActionListener((v, actionId, event) -> {
- submit(dialog, binding);
- return true;
- });
- dialog.setOnShowListener(dialogInterface -> {
- dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(v -> goBack(dialog, binding));
- dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> submit(dialog, binding));
- });
+ binding.groupChatName.setOnEditorActionListener(
+ (v, actionId, event) -> {
+ submit(dialog, binding);
+ return true;
+ });
+ dialog.setOnShowListener(
+ dialogInterface -> {
+ dialog.getButton(DialogInterface.BUTTON_NEGATIVE)
+ .setOnClickListener(v -> goBack(dialog, binding));
+ dialog.getButton(DialogInterface.BUTTON_POSITIVE)
+ .setOnClickListener(v -> submit(dialog, binding));
+ });
return dialog;
}
@@ -134,13 +143,15 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
@Override
public void onSaveInstanceState(Bundle outState) {
- outState.putBoolean("jid_was_modified",jidWasModified);
+ outState.putBoolean("jid_was_modified", jidWasModified);
outState.putBoolean("name_entered", nameEntered);
super.onSaveInstanceState(outState);
}
private static String getJidSuggestion(final DialogCreatePublicChannelBinding binding) {
- final Account account = StartConversationActivity.getSelectedAccount(binding.getRoot().getContext(), binding.account);
+ final Account account =
+ StartConversationActivity.getSelectedAccount(
+ binding.getRoot().getContext(), binding.account);
final XmppConnection connection = account == null ? null : account.getXmppConnection();
if (connection == null) {
return "";
@@ -156,18 +167,18 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
return "";
} else {
try {
- return Jid.of(localpart, domain, null).toEscapedString();
+ return Jid.of(localpart, domain, null).toString();
} catch (IllegalArgumentException e) {
- return Jid.of(CryptoHelper.pronounceable(), domain, null).toEscapedString();
+ return Jid.of(CryptoHelper.pronounceable(), domain, null).toString();
}
}
}
private static String clean(String name) {
- for(char c : FORBIDDEN) {
- name = name.replace(String.valueOf(c),"");
+ for (char c : FORBIDDEN) {
+ name = name.replace(String.valueOf(c), "");
}
- return name.replaceAll("\\s+","-");
+ return name.replaceAll("\\s+", "-");
}
private void goBack(AlertDialog dialog, DialogCreatePublicChannelBinding binding) {
@@ -189,22 +200,26 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
if (nameEntered) {
binding.nameLayout.setError(null);
if (address.isEmpty()) {
- binding.xmppAddressLayout.setError(context.getText(R.string.please_enter_xmpp_address));
+ binding.xmppAddressLayout.setError(
+ context.getText(R.string.please_enter_xmpp_address));
} else {
final Jid jid;
try {
- jid = Jid.ofEscaped(address);
- } catch (IllegalArgumentException e) {
+ jid = Jid.ofUserInput(address);
+ } catch (final IllegalArgumentException e) {
binding.xmppAddressLayout.setError(context.getText(R.string.invalid_jid));
return;
}
- final Account account = StartConversationActivity.getSelectedAccount(context, binding.account);
+ final Account account =
+ StartConversationActivity.getSelectedAccount(context, binding.account);
if (account == null) {
return;
}
- final XmppConnectionService service = ((XmppActivity )context).xmppConnectionService;
+ final XmppConnectionService service =
+ ((XmppActivity) context).xmppConnectionService;
if (service != null && service.findFirstMuc(jid) != null) {
- binding.xmppAddressLayout.setError(context.getString(R.string.channel_already_exists));
+ binding.xmppAddressLayout.setError(
+ context.getString(R.string.channel_already_exists));
return;
}
mListener.onCreatePublicChannel(account, name, jid);
@@ -214,7 +229,7 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
binding.xmppAddressLayout.setError(null);
if (name.isEmpty()) {
binding.nameLayout.setError(context.getText(R.string.please_enter_name));
- } else if (StartConversationActivity.isValidJid(name)){
+ } else if (StartConversationActivity.isValidJid(name)) {
binding.nameLayout.setError(context.getText(R.string.this_is_an_xmpp_address));
} else {
binding.nameLayout.setError(null);
@@ -227,8 +242,8 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
}
}
-
- private void updateInputs(final DialogCreatePublicChannelBinding binding, final boolean requestFocus) {
+ private void updateInputs(
+ final DialogCreatePublicChannelBinding binding, final boolean requestFocus) {
binding.xmppAddressLayout.setVisibility(nameEntered ? View.VISIBLE : View.GONE);
binding.nameLayout.setVisibility(nameEntered ? View.GONE : View.VISIBLE);
if (!requestFocus) {
@@ -256,7 +271,8 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
private void refreshKnownHosts() {
Activity activity = getActivity();
if (activity instanceof XmppActivity) {
- Collection hosts = ((XmppActivity) activity).xmppConnectionService.getKnownConferenceHosts();
+ Collection hosts =
+ ((XmppActivity) activity).xmppConnectionService.getKnownConferenceHosts();
this.knownHostsAdapter.refresh(hosts);
}
}
@@ -271,8 +287,8 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
try {
mListener = (CreatePublicChannelDialogListener) context;
} catch (ClassCastException e) {
- throw new ClassCastException(context.toString()
- + " must implement CreateConferenceDialogListener");
+ throw new ClassCastException(
+ context.toString() + " must implement CreateConferenceDialogListener");
}
}
@@ -280,7 +296,8 @@ public class CreatePublicChannelDialog extends DialogFragment implements OnBacke
public void onStart() {
super.onStart();
final Activity activity = getActivity();
- if (activity instanceof XmppActivity && ((XmppActivity) activity).xmppConnectionService != null) {
+ if (activity instanceof XmppActivity
+ && ((XmppActivity) activity).xmppConnectionService != null) {
refreshKnownHosts();
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
index 25149a7979d56d77192d05fa48564154275d9aa8..e4d529c71d6e45ee4799ea101f954ddc5fe54325 100644
--- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
@@ -32,13 +32,11 @@ import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.Lifecycle;
-
import com.google.android.material.color.MaterialColors;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputLayout;
@@ -100,13 +98,9 @@ import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
import okhttp3.HttpUrl;
-
+import okhttp3.HttpUrl;
+import org.openintents.openpgp.util.OpenPgpUtils;
import org.openintents.openpgp.util.OpenPgpUtils;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
public class EditAccountActivity extends OmemoActivity
implements OnAccountUpdate,
@@ -165,8 +159,7 @@ public class EditAccountActivity extends OmemoActivity
new Intent(
getApplicationContext(),
PublishProfilePictureActivity.class);
- intent.putExtra(
- EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toString());
startActivity(intent);
}
}
@@ -285,12 +278,12 @@ public class EditAccountActivity extends OmemoActivity
try {
if (mUsernameMode) {
jid =
- Jid.ofEscaped(
+ Jid.of(
binding.accountJid.getText().toString(),
getUserModeDomain(),
null);
} else {
- jid = Jid.ofEscaped(binding.accountJid.getText().toString());
+ jid = Jid.ofUserInput(binding.accountJid.getText().toString());
Resolver.checkDomain(jid);
}
} catch (final NullPointerException | IllegalArgumentException e) {
@@ -564,14 +557,13 @@ public class EditAccountActivity extends OmemoActivity
getApplicationContext(), StartConversationActivity.class);
intent.putExtra("init", true);
intent.putExtra(
- EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toEscapedString());
+ EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toString());
} else {
intent =
new Intent(
getApplicationContext(),
PublishProfilePictureActivity.class);
- intent.putExtra(
- EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().asBareJid().toString());
intent.putExtra("setup", true);
}
if (wasFirstAccount) {
@@ -731,9 +723,9 @@ public class EditAccountActivity extends OmemoActivity
protected boolean jidEdited() {
final String unmodified;
if (mUsernameMode) {
- unmodified = this.mAccount.getJid().getEscapedLocal();
+ unmodified = this.mAccount.getJid().getLocal();
} else {
- unmodified = this.mAccount.getJid().asBareJid().toEscapedString();
+ unmodified = this.mAccount.getJid().asBareJid().toString();
}
return !unmodified.equals(this.binding.accountJid.getText().toString());
}
@@ -890,7 +882,7 @@ public class EditAccountActivity extends OmemoActivity
final Intent intent = getIntent();
if (intent != null) {
try {
- this.jidToEdit = Jid.ofEscaped(intent.getStringExtra("jid"));
+ this.jidToEdit = Jid.of(intent.getStringExtra("jid"));
} catch (final IllegalArgumentException | NullPointerException ignored) {
this.jidToEdit = null;
}
@@ -990,8 +982,7 @@ public class EditAccountActivity extends OmemoActivity
@Override
public void onSaveInstanceState(@NonNull final Bundle savedInstanceState) {
if (mAccount != null) {
- savedInstanceState.putString(
- "account", mAccount.getJid().asBareJid().toEscapedString());
+ savedInstanceState.putString("account", mAccount.getJid().asBareJid().toString());
savedInstanceState.putBoolean("initMode", mInitMode);
savedInstanceState.putBoolean(
"showMoreTable", binding.serverInfoMore.getVisibility() == View.VISIBLE);
@@ -1004,8 +995,7 @@ public class EditAccountActivity extends OmemoActivity
if (mSavedInstanceAccount != null) {
try {
this.mAccount =
- xmppConnectionService.findAccountByJid(
- Jid.ofEscaped(mSavedInstanceAccount));
+ xmppConnectionService.findAccountByJid(Jid.of(mSavedInstanceAccount));
this.mInitMode = mSavedInstanceInit;
init = false;
} catch (IllegalArgumentException e) {
@@ -1071,7 +1061,7 @@ public class EditAccountActivity extends OmemoActivity
break;
case R.id.action_show_block_list:
final Intent showBlocklistIntent = new Intent(this, BlocklistActivity.class);
- showBlocklistIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toEscapedString());
+ showBlocklistIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString());
startActivity(showBlocklistIntent);
break;
case R.id.action_server_info_show_more:
@@ -1146,7 +1136,7 @@ public class EditAccountActivity extends OmemoActivity
private void openChangePassword(boolean didUnlock) {
final Intent changePasswordIntent = new Intent(this, ChangePasswordActivity.class);
- changePasswordIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toEscapedString());
+ changePasswordIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString());
changePasswordIntent.putExtra("did_unlock", didUnlock);
startActivity(changePasswordIntent);
}
@@ -1264,15 +1254,12 @@ public class EditAccountActivity extends OmemoActivity
if (init) {
this.binding.accountJid.getEditableText().clear();
if (mUsernameMode) {
- this.binding
- .accountJid
- .getEditableText()
- .append(this.mAccount.getJid().getEscapedLocal());
+ this.binding.accountJid.getEditableText().append(this.mAccount.getJid().getLocal());
} else {
this.binding
.accountJid
.getEditableText()
- .append(this.mAccount.getJid().asBareJid().toEscapedString());
+ .append(this.mAccount.getJid().asBareJid().toString());
}
this.binding.accountPassword.getEditableText().clear();
this.binding.accountPassword.getEditableText().append(this.mAccount.getPassword());
diff --git a/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java b/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java
index 873147880cadaa4e1b965ac300699086b2fa87fd..7b8cbc26b52d400ffb24d80833c9fb1d6ebf2c1d 100644
--- a/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java
+++ b/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java
@@ -129,10 +129,15 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final var arguments = getArguments();
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity());
+ final MaterialAlertDialogBuilder builder =
+ new MaterialAlertDialogBuilder(requireActivity());
builder.setTitle(arguments.getString(TITLE_KEY));
binding =
- DataBindingUtil.inflate(requireActivity().getLayoutInflater(), R.layout.dialog_enter_jid, null, false);
+ DataBindingUtil.inflate(
+ requireActivity().getLayoutInflater(),
+ R.layout.dialog_enter_jid,
+ null,
+ false);
this.knownHostsAdapter = new KnownHostsAdapter(getActivity(), R.layout.item_autocomplete);
binding.jid.setAdapter(this.knownHostsAdapter);
binding.jid.addTextChangedListener(this);
@@ -162,7 +167,8 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
binding.account);
} else {
final ArrayAdapter adapter =
- new ArrayAdapter<>(requireActivity(), R.layout.item_autocomplete, new String[] {account});
+ new ArrayAdapter<>(
+ requireActivity(), R.layout.item_autocomplete, new String[] {account});
binding.account.setText(account);
binding.account.setEnabled(false);
adapter.setDropDownViewResource(R.layout.item_autocomplete);
@@ -229,7 +235,7 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
protected Jid accountJid() {
try {
- return Jid.ofEscaped((String) binding.account.getEditableText().toString());
+ return Jid.of((String) binding.account.getEditableText().toString());
} catch (final IllegalArgumentException e) {
return null;
}
@@ -256,7 +262,7 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
Jid contactJid = null;
try {
- contactJid = Jid.ofEscaped(jidString);
+ contactJid = Jid.of(jidString);
} catch (final IllegalArgumentException e) {
binding.jidLayout.setError(getActivity().getString(R.string.invalid_jid));
return;
@@ -269,7 +275,7 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
issuedWarning = true;
return;
}
- if (sanityCheckJid != SanityCheck.ALLOW_MUC && suspiciousSubDomain(contactJid.getDomain().toEscapedString())) {
+ if (sanityCheckJid != SanityCheck.ALLOW_MUC && suspiciousSubDomain(contactJid.getDomain().toString())) {
binding.jidLayout.setError(getActivity().getString(R.string.this_looks_like_channel));
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add_anway);
issuedWarning = true;
diff --git a/src/main/java/eu/siacs/conversations/ui/MediaBrowserActivity.java b/src/main/java/eu/siacs/conversations/ui/MediaBrowserActivity.java
index ac5b07e77dcb543a5a511de2b81c3605834dd280..58d46fd76712840aa5d3537423e5aa5259ea4a2a 100644
--- a/src/main/java/eu/siacs/conversations/ui/MediaBrowserActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/MediaBrowserActivity.java
@@ -3,11 +3,7 @@ package eu.siacs.conversations.ui;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-
import androidx.databinding.DataBindingUtil;
-
-import java.util.List;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityMediaBrowserBinding;
import eu.siacs.conversations.entities.Account;
@@ -18,6 +14,7 @@ import eu.siacs.conversations.ui.interfaces.OnMediaLoaded;
import eu.siacs.conversations.ui.util.Attachment;
import eu.siacs.conversations.ui.util.GridManager;
import eu.siacs.conversations.xmpp.Jid;
+import java.util.List;
public class MediaBrowserActivity extends XmppActivity implements OnMediaLoaded {
@@ -28,20 +25,17 @@ public class MediaBrowserActivity extends XmppActivity implements OnMediaLoaded
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- this.binding = DataBindingUtil.setContentView(this,R.layout.activity_media_browser);
+ this.binding = DataBindingUtil.setContentView(this, R.layout.activity_media_browser);
Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
setSupportActionBar(binding.toolbar);
configureActionBar(getSupportActionBar());
mMediaAdapter = new MediaAdapter(this, R.dimen.media_size);
this.binding.media.setAdapter(mMediaAdapter);
GridManager.setupLayoutManager(this, this.binding.media, R.dimen.browser_media_size);
-
}
@Override
- protected void refreshUiReal() {
-
- }
+ protected void refreshUiReal() {}
@Override
protected void onBackendConnected() {
@@ -49,29 +43,30 @@ public class MediaBrowserActivity extends XmppActivity implements OnMediaLoaded
String account = intent == null ? null : intent.getStringExtra("account");
String jid = intent == null ? null : intent.getStringExtra("jid");
if (account != null && jid != null) {
- xmppConnectionService.getAttachments(account, Jid.ofEscaped(jid), 0, this);
+ xmppConnectionService.getAttachments(account, Jid.of(jid), 0, this);
}
}
public static void launch(Context context, Contact contact) {
- launch(context, contact.getAccount(), contact.getJid().asBareJid().toEscapedString());
+ launch(context, contact.getAccount(), contact.getJid().asBareJid().toString());
}
public static void launch(Context context, Conversation conversation) {
- launch(context, conversation.getAccount(), conversation.getJid().asBareJid().toEscapedString());
+ launch(context, conversation.getAccount(), conversation.getJid().asBareJid().toString());
}
private static void launch(Context context, Account account, String jid) {
final Intent intent = new Intent(context, MediaBrowserActivity.class);
- intent.putExtra("account",account.getUuid());
- intent.putExtra("jid",jid);
+ intent.putExtra("account", account.getUuid());
+ intent.putExtra("jid", jid);
context.startActivity(intent);
}
@Override
public void onMediaLoaded(List attachments) {
- runOnUiThread(()->{
- mMediaAdapter.setAttachments(attachments);
- });
+ runOnUiThread(
+ () -> {
+ mMediaAdapter.setAttachments(attachments);
+ });
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
index 7677e1e7510f5546302af6c96791015ab75fe206..1c3a33ab2ff11890efc868ab4e0e52463f423a81 100644
--- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
@@ -64,8 +64,7 @@ public class PublishProfilePictureActivity extends XmppActivity
getApplicationContext(), StartConversationActivity.class);
StartConversationActivity.addInviteUri(intent, getIntent());
intent.putExtra("init", true);
- intent.putExtra(
- EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
startActivity(intent);
}
Toast.makeText(
@@ -119,8 +118,7 @@ public class PublishProfilePictureActivity extends XmppActivity
intent.putExtra("init", true);
StartConversationActivity.addInviteUri(intent, getIntent());
if (account != null) {
- intent.putExtra(
- EXTRA_ACCOUNT, account.getJid().asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
}
startActivity(intent);
}
diff --git a/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java b/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java
index 8795c92d95040f4a9dcaab050bd8ea8949bbc85a..b1656cb5bb5b870942e6c3c3f8e51b0806ef9262 100644
--- a/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java
@@ -16,34 +16,29 @@ import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
-
-import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
-
+import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableSet;
-
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.databinding.ActivityRecordingBinding;
+import eu.siacs.conversations.utils.TimeFrameUtils;
import java.io.File;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import java.util.Set;
-
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.R;
-import eu.siacs.conversations.databinding.ActivityRecordingBinding;
-import eu.siacs.conversations.ui.util.SettingsUtils;
-import eu.siacs.conversations.utils.TimeFrameUtils;
public class RecordingActivity extends BaseActivity implements View.OnClickListener {
private ActivityRecordingBinding binding;
private MediaRecorder mRecorder;
- private long mStartTime = 0;
+ private Stopwatch stopwatch;
private final CountDownLatch outputFileWrittenLatch = new CountDownLatch(1);
@@ -65,17 +60,48 @@ public class RecordingActivity extends BaseActivity implements View.OnClickListe
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.binding = DataBindingUtil.setContentView(this, R.layout.activity_recording);
+ this.binding.timer.setOnClickListener(
+ v -> {
+ onPauseContinue();
+ });
this.binding.cancelButton.setOnClickListener(this);
this.binding.shareButton.setOnClickListener(this);
this.setFinishOnTouchOutside(false);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
+
+ private void onPauseContinue() {
+ final var recorder = this.mRecorder;
+ final var stopwatch = this.stopwatch;
+ if (recorder == null
+ || stopwatch == null
+ || Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+ return;
+ }
+ if (stopwatch.isRunning()) {
+ try {
+ recorder.pause();
+ stopwatch.stop();
+ } catch (final IllegalStateException e) {
+ Log.d(Config.LOGTAG, "could not pause recording", e);
+ }
+ } else {
+ try {
+ recorder.resume();
+ stopwatch.start();
+ } catch (final IllegalStateException e) {
+ Log.d(Config.LOGTAG, "could not resume recording", e);
+ }
+ }
+ }
+
@Override
public void onStart() {
super.onStart();
if (!startRecording()) {
this.binding.shareButton.setEnabled(false);
- this.binding.timer.setTextAppearance(com.google.android.material.R.style.TextAppearance_Material3_BodyMedium);
+ this.binding.timer.setTextAppearance(
+ com.google.android.material.R.style.TextAppearance_Material3_BodyMedium);
// TODO reset font family. make red?
this.binding.timer.setText(R.string.unable_to_start_recording);
}
@@ -99,23 +125,32 @@ public class RecordingActivity extends BaseActivity implements View.OnClickListe
private static final Set AAC_SENSITIVE_DEVICES =
new ImmutableSet.Builder()
- .add("FP4") // Fairphone 4 https://codeberg.org/monocles/monocles_chat/issues/133
- .add("ONEPLUS A6000") // OnePlus 6 https://github.com/iNPUTmice/Conversations/issues/4329
- .add("ONEPLUS A6003") // OnePlus 6 https://github.com/iNPUTmice/Conversations/issues/4329
- .add("ONEPLUS A6010") // OnePlus 6T https://codeberg.org/monocles/monocles_chat/issues/133
- .add("ONEPLUS A6013") // OnePlus 6T https://codeberg.org/monocles/monocles_chat/issues/133
- .add("Pixel 4a") // Pixel 4a https://github.com/iNPUTmice/Conversations/issues/4223
- .add("WP12 Pro") // Oukitel WP 12 Pro https://github.com/iNPUTmice/Conversations/issues/4223
- .add("Volla Phone X") // Volla Phone X https://github.com/iNPUTmice/Conversations/issues/4223
+ .add("FP4") // Fairphone 4
+ // https://codeberg.org/monocles/monocles_chat/issues/133
+ .add("ONEPLUS A6000") // OnePlus 6
+ // https://github.com/iNPUTmice/Conversations/issues/4329
+ .add("ONEPLUS A6003") // OnePlus 6
+ // https://github.com/iNPUTmice/Conversations/issues/4329
+ .add("ONEPLUS A6010") // OnePlus 6T
+ // https://codeberg.org/monocles/monocles_chat/issues/133
+ .add("ONEPLUS A6013") // OnePlus 6T
+ // https://codeberg.org/monocles/monocles_chat/issues/133
+ .add("Pixel 4a") // Pixel 4a
+ // https://github.com/iNPUTmice/Conversations/issues/4223
+ .add("WP12 Pro") // Oukitel WP 12 Pro
+ // https://github.com/iNPUTmice/Conversations/issues/4223
+ .add("Volla Phone X") // Volla Phone X
+ // https://github.com/iNPUTmice/Conversations/issues/4223
.build();
private boolean startRecording() {
mRecorder = new MediaRecorder();
final String userChosenCodec = getPreferences().getString("voice_message_codec", "");
+ stopwatch = Stopwatch.createUnstarted();
try {
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
} catch (final RuntimeException e) {
- Log.e(Config.LOGTAG,"could not set audio source", e);
+ Log.e(Config.LOGTAG, "could not set audio source", e);
return false;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
@@ -131,8 +166,10 @@ public class RecordingActivity extends BaseActivity implements View.OnClickListe
} else if ("mpeg4".equals(userChosenCodec) || !Config.USE_OPUS_VOICE_MESSAGES) {
outputFormat = MediaRecorder.OutputFormat.MPEG_4;
mRecorder.setOutputFormat(outputFormat);
- if (AAC_SENSITIVE_DEVICES.contains(Build.MODEL) && Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
- // Changing these three settings for AAC sensitive devices for Android<=13 might lead to sporadically truncated (cut-off) voice messages.
+ if (AAC_SENSITIVE_DEVICES.contains(Build.MODEL)
+ && Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
+ // Changing these three settings for AAC sensitive devices for Android<=13 might
+ // lead to sporadically truncated (cut-off) voice messages.
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.HE_AAC);
mRecorder.setAudioSamplingRate(24_000);
mRecorder.setAudioEncodingBitRate(28_000);
@@ -154,7 +191,7 @@ public class RecordingActivity extends BaseActivity implements View.OnClickListe
try {
mRecorder.prepare();
mRecorder.start();
- mStartTime = SystemClock.elapsedRealtime();
+ stopwatch.start();
mHandler.postDelayed(mTickExecutor, 100);
Log.d(Config.LOGTAG, "started recording to " + mOutputFile.getAbsolutePath());
return true;
@@ -168,14 +205,17 @@ public class RecordingActivity extends BaseActivity implements View.OnClickListe
try {
mRecorder.stop();
mRecorder.release();
- } catch (Exception e) {
+ if (stopwatch.isRunning()) {
+ stopwatch.stop();
+ }
+ } catch (final Exception e) {
+ Log.d(Config.LOGTAG, "could not save recording", e);
if (saveFile) {
Toast.makeText(this, R.string.unable_to_save_recording, Toast.LENGTH_SHORT).show();
return;
}
} finally {
mRecorder = null;
- mStartTime = 0;
}
if (!saveFile && mOutputFile != null) {
if (mOutputFile.delete()) {
@@ -272,24 +312,23 @@ public class RecordingActivity extends BaseActivity implements View.OnClickListe
}
private void tick() {
- this.binding.timer.setText(TimeFrameUtils.formatTimePassed(mStartTime, true));
+ this.binding.timer.setText(
+ TimeFrameUtils.formatElapsedTime(stopwatch.elapsed(TimeUnit.MILLISECONDS), true));
}
@Override
public void onClick(final View view) {
- switch (view.getId()) {
- case R.id.cancel_button:
- mHandler.removeCallbacks(mTickExecutor);
- stopRecording(false);
- setResult(RESULT_CANCELED);
- finish();
- break;
- case R.id.share_button:
- this.binding.shareButton.setEnabled(false);
- this.binding.shareButton.setText(R.string.please_wait);
- mHandler.removeCallbacks(mTickExecutor);
- mHandler.postDelayed(() -> stopRecording(true), 500);
- break;
+ if (view.getId() == R.id.cancel_button) {
+ mHandler.removeCallbacks(mTickExecutor);
+ stopRecording(false);
+ setResult(RESULT_CANCELED);
+ finish();
+ } else if (view.getId() == R.id.share_button) {
+ this.binding.timer.setOnClickListener(null);
+ this.binding.shareButton.setEnabled(false);
+ this.binding.shareButton.setText(R.string.please_wait);
+ mHandler.removeCallbacks(mTickExecutor);
+ mHandler.postDelayed(() -> stopRecording(true), 500);
}
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java
index 80b4537c16edb89fdcf1a201414695347934f8e8..f0545f8ed567d025a01bba4d37c3458cce06a0c4 100644
--- a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java
@@ -1,7 +1,6 @@
package eu.siacs.conversations.ui;
import static eu.siacs.conversations.utils.PermissionUtils.getFirstDenied;
-
import static java.util.Arrays.asList;
import android.Manifest;
@@ -25,13 +24,11 @@ import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import androidx.databinding.DataBindingUtil;
-
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
@@ -78,16 +75,6 @@ import eu.siacs.conversations.xmpp.jingle.OngoingRtpSession;
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
-import org.webrtc.RendererCommon;
-import org.webrtc.SurfaceViewRenderer;
-import org.webrtc.VideoTrack;
-
-import java.lang.ref.WeakReference;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
public class RtpSessionActivity extends XmppActivity
implements XmppConnectionService.OnJingleRtpConnectionUpdate,
eu.siacs.conversations.ui.widget.SurfaceViewRenderer.OnAspectRatioChanged {
@@ -350,7 +337,7 @@ public class RtpSessionActivity extends XmppActivity
final String action = intent.getAction();
final String lastAction = intent.getStringExtra(EXTRA_LAST_ACTION);
final Account account = extractAccount(intent);
- final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
+ final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
final String state = intent.getStringExtra(EXTRA_LAST_REPORTED_STATE);
if (!Intent.ACTION_VIEW.equals(action)
|| state == null
@@ -554,7 +541,7 @@ public class RtpSessionActivity extends XmppActivity
Log.d(Config.LOGTAG, "initializeWithIntent(" + event + "," + action + ")");
final Account account = extractAccount(intent);
final var extraWith = intent.getStringExtra(EXTRA_WITH);
- final Jid with = Strings.isNullOrEmpty(extraWith) ? null : Jid.ofEscaped(extraWith);
+ final Jid with = Strings.isNullOrEmpty(extraWith) ? null : Jid.of(extraWith);
if (with == null || account == null) {
Log.e(Config.LOGTAG, "intent is missing extras (account or with)");
return;
@@ -623,7 +610,7 @@ public class RtpSessionActivity extends XmppActivity
binding.with.setText(contact.getDisplayName());
if (Arrays.asList(RtpEndUserState.INCOMING_CALL, RtpEndUserState.ACCEPTING_CALL)
.contains(state)) {
- binding.withJid.setText(contact.getJid().asBareJid().toEscapedString());
+ binding.withJid.setText(contact.getJid().asBareJid().toString());
binding.withJid.setVisibility(View.VISIBLE);
} else {
binding.withJid.setVisibility(View.GONE);
@@ -825,9 +812,9 @@ public class RtpSessionActivity extends XmppActivity
.getJingleConnectionManager()
.getTerminalSessionState(with, sessionId);
if (terminatedRtpSession == null) {
- Log.e(Config.LOGTAG, "failed to initialize activity with running rtp session. session not found");
- finish();
- return true;
+ throw new IllegalStateException(
+ "failed to initialize activity with running rtp session. session not"
+ + " found");
}
initializeWithTerminatedSessionState(account, with, terminatedRtpSession);
return true;
@@ -888,8 +875,8 @@ public class RtpSessionActivity extends XmppActivity
private void resetIntent(final Account account, final Jid with, final String sessionId) {
final Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString());
- intent.putExtra(EXTRA_WITH, with.toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().toString());
+ intent.putExtra(EXTRA_WITH, with.toString());
intent.putExtra(EXTRA_SESSION_ID, sessionId);
setIntent(intent);
}
@@ -946,10 +933,12 @@ public class RtpSessionActivity extends XmppActivity
case RETRACTED -> setTitle(R.string.rtp_state_retracted);
case APPLICATION_ERROR -> setTitle(R.string.rtp_state_application_failure);
case SECURITY_ERROR -> setTitle(R.string.rtp_state_security_error);
- case ENDED -> throw new IllegalStateException(
- "Activity should have called finishAndReleaseWakeLock();");
- default -> throw new IllegalStateException(
- String.format("State %s has not been handled in UI", state));
+ case ENDED ->
+ throw new IllegalStateException(
+ "Activity should have called finishAndReleaseWakeLock();");
+ default ->
+ throw new IllegalStateException(
+ String.format("State %s has not been handled in UI", state));
}
}
@@ -983,9 +972,7 @@ public class RtpSessionActivity extends XmppActivity
final Account account = contact == null ? getWith().getAccount() : contact.getAccount();
binding.usingAccount.setVisibility(View.VISIBLE);
binding.usingAccount.setText(
- getString(
- R.string.using_account,
- account.getJid().asBareJid().toEscapedString()));
+ getString(R.string.using_account, account.getJid().asBareJid().toString()));
} else {
binding.usingAccount.setVisibility(View.GONE);
binding.contactPhoto.setVisibility(View.GONE);
@@ -1481,12 +1468,12 @@ public class RtpSessionActivity extends XmppActivity
private void retry(final View view) {
final Intent intent = getIntent();
final Account account = extractAccount(intent);
- final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
+ final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
final String lastAction = intent.getStringExtra(EXTRA_LAST_ACTION);
final String action = intent.getAction();
final Set media = actionToMedia(lastAction == null ? action : lastAction);
this.rtpConnectionReference = null;
- Log.d(Config.LOGTAG, "attempting retry with " + with.toEscapedString());
+ Log.d(Config.LOGTAG, "attempting retry with " + with.toString());
CallIntegrationConnectionService.placeCall(xmppConnectionService, account, with, media);
}
@@ -1497,7 +1484,7 @@ public class RtpSessionActivity extends XmppActivity
private void recordVoiceMail(final View view) {
final Intent intent = getIntent();
final Account account = extractAccount(intent);
- final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
+ final Jid with = Jid.of(intent.getStringExtra(EXTRA_WITH));
final Conversation conversation =
xmppConnectionService.findOrCreateConversation(account, with, false, true);
final Intent launchIntent = new Intent(this, ConversationsActivity.class);
@@ -1668,7 +1655,7 @@ public class RtpSessionActivity extends XmppActivity
return;
}
final Set media = actionToMedia(currentIntent.getStringExtra(EXTRA_LAST_ACTION));
- if (Jid.ofEscaped(withExtra).asBareJid().equals(with)) {
+ if (Jid.of(withExtra).asBareJid().equals(with)) {
runOnUiThread(
() -> {
updateVerifiedShield(false);
@@ -1691,11 +1678,11 @@ public class RtpSessionActivity extends XmppActivity
private void resetIntent(
final Account account, Jid with, final RtpEndUserState state, final Set media) {
final Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, account.getJid().toString());
if (RtpCapability.jmiSupport(account.getRoster().getContact(with))) {
- intent.putExtra(EXTRA_WITH, with.asBareJid().toEscapedString());
+ intent.putExtra(EXTRA_WITH, with.asBareJid().toString());
} else {
- intent.putExtra(EXTRA_WITH, with.toEscapedString());
+ intent.putExtra(EXTRA_WITH, with.toString());
}
intent.putExtra(EXTRA_LAST_REPORTED_STATE, state.toString());
intent.putExtra(
diff --git a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
index ddc6e253ccbb71717786c2d91f77f2d4c249e98f..02c9b3b25bb47a4892df187b54321d93a3b77e12 100644
--- a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
@@ -12,12 +12,16 @@ import androidx.annotation.NonNull;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.LinearLayoutManager;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityShareWithBinding;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.persistance.DatabaseBackend;
+import eu.siacs.conversations.services.ShortcutService;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.adapter.ConversationAdapter;
import eu.siacs.conversations.xmpp.Jid;
@@ -132,10 +136,28 @@ public class ShareWithActivity extends XmppActivity
if (shortcut.isPresent()) {
final var extras = shortcut.get().getExtras();
if (extras == null) {
- return null;
+ return shortcutIdToConversationFallback(shortcutId);
} else {
- return extras.getString(ConversationsActivity.EXTRA_CONVERSATION);
+ final var conversation = extras.getString(ConversationsActivity.EXTRA_CONVERSATION);
+ if (Strings.isNullOrEmpty(conversation)) {
+ return shortcutIdToConversationFallback(shortcutId);
+ } else {
+ return conversation;
+ }
}
+ } else {
+ return shortcutIdToConversationFallback(shortcutId);
+ }
+ }
+
+ private String shortcutIdToConversationFallback(final String shortcutId) {
+ final var parts =
+ Splitter.on(ShortcutService.ID_SEPARATOR).limit(2).splitToList(shortcutId);
+ if (parts.size() == 2) {
+ final var account = Jid.of(parts.get(0));
+ final var jid = Jid.of(parts.get(1));
+ final var database = DatabaseBackend.getInstance(getApplicationContext());
+ return database.findConversationUuid(account, jid);
} else {
return null;
}
@@ -228,7 +250,7 @@ public class ShareWithActivity extends XmppActivity
final Conversation conversation;
Account account;
try {
- account = xmppConnectionService.findAccountByJid(Jid.ofEscaped(share.account));
+ account = xmppConnectionService.findAccountByJid(Jid.of(share.account));
} catch (final IllegalArgumentException e) {
account = null;
}
diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
index b2329093c26418588c9b7936c925fd360e95757a..27053beca7af66904670eeee48d90e2ec438ff06 100644
--- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
@@ -38,7 +38,6 @@ import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
-
import androidx.annotation.MenuRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -66,7 +65,6 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.leinardi.android.speeddial.SpeedDialActionItem;
import com.leinardi.android.speeddial.SpeedDialView;
-
import eu.siacs.conversations.BuildConfig;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
@@ -289,7 +287,7 @@ public class StartConversationActivity extends XmppActivity
if (account != null) {
intent.putExtra(
EXTRA_ACCOUNT_FILTER,
- account.getJid().asBareJid().toEscapedString());
+ account.getJid().asBareJid().toString());
}
if (q != null) {
intent.putExtra(EXTRA_TEXT_FILTER, q);
@@ -410,7 +408,7 @@ public class StartConversationActivity extends XmppActivity
mSearchEditText != null ? mSearchEditText.getText().toString() : null;
final String prefilled;
if (isValidJid(searchString)) {
- prefilled = Jid.ofEscaped(searchString).toEscapedString();
+ prefilled = Jid.of(searchString).toString();
} else {
prefilled = null;
}
@@ -466,14 +464,15 @@ public class StartConversationActivity extends XmppActivity
.create();
speedDialView.addActionItem(actionItem);
}
- speedDialView.setContentDescription(getString(R.string.add_contact_or_create_or_join_group_chat));
+ speedDialView.setContentDescription(
+ getString(R.string.add_contact_or_create_or_join_group_chat));
}
- public static boolean isValidJid(String input) {
+ public static boolean isValidJid(final String input) {
try {
- Jid jid = Jid.ofEscaped(input);
+ final Jid jid = Jid.ofUserInput(input);
return !jid.isDomainJid();
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
return false;
}
}
@@ -555,12 +554,12 @@ public class StartConversationActivity extends XmppActivity
}
protected void shareBookmarkUri() {
- shareAsChannel(this, contextItem.getJid().asBareJid().toEscapedString());
+ shareAsChannel(this, contextItem.getJid().asBareJid().toString());
}
protected void shareBookmarkUri(int position) {
Bookmark bookmark = (Bookmark) conferences.get(position);
- shareAsChannel(this, bookmark.getJid().asBareJid().toEscapedString());
+ shareAsChannel(this, bookmark.getJid().asBareJid().toString());
}
public static void shareAsChannel(final Context context, final String address) {
@@ -600,7 +599,7 @@ public class StartConversationActivity extends XmppActivity
}
protected void showQrForContact() {
- showQrCode("xmpp:" + contextItem.getJid().asBareJid().toEscapedString());
+ showQrCode("xmpp:" + contextItem.getJid().asBareJid().toString());
}
protected void toggleContactBlock() {
@@ -613,8 +612,7 @@ public class StartConversationActivity extends XmppActivity
builder.setNegativeButton(R.string.cancel, null);
builder.setTitle(R.string.action_delete_contact);
builder.setMessage(
- JidDialog.style(
- this, R.string.remove_contact_text, contact.getJid().toEscapedString()));
+ JidDialog.style(this, R.string.remove_contact_text, contact.getJid().toString()));
builder.setPositiveButton(
R.string.delete,
(dialog, which) -> {
@@ -636,11 +634,10 @@ public class StartConversationActivity extends XmppActivity
JidDialog.style(
this,
R.string.remove_bookmark_and_close,
- bookmark.getJid().toEscapedString()));
+ bookmark.getJid().toString()));
} else {
builder.setMessage(
- JidDialog.style(
- this, R.string.remove_bookmark, bookmark.getJid().toEscapedString()));
+ JidDialog.style(this, R.string.remove_bookmark, bookmark.getJid().toString()));
}
builder.setPositiveButton(
hasConversation ? R.string.delete_and_close : R.string.delete,
@@ -787,7 +784,7 @@ public class StartConversationActivity extends XmppActivity
if (context instanceof XmppActivity) {
final Jid jid;
try {
- jid = Jid.ofEscaped(spinner.getText().toString());
+ jid = Jid.of(spinner.getText().toString());
} catch (final IllegalArgumentException e) {
return null;
}
@@ -1160,7 +1157,7 @@ public class StartConversationActivity extends XmppActivity
if (onboardingAccount == null && account.getJid().getDomain().equals(Config.ONBOARDING_DOMAIN)) onboardingAccount = account;
if (accountJid != null) {
- if(account.getJid().asBareJid().toEscapedString().equals(accountJid)) {
+ if(account.getJid().asBareJid().toString().equals(accountJid)) {
selectedAccount = account;
} else {
continue;
@@ -1251,11 +1248,11 @@ public class StartConversationActivity extends XmppActivity
switchToConversationDoNotAppend(muc, invite.getBody());
return true;
} else {
- showJoinConferenceDialog(invite.getJid().asBareJid().toEscapedString(), invite);
+ showJoinConferenceDialog(invite.getJid().asBareJid().toString(), invite);
return false;
}
- } else if (contacts.size() == 0) {
- showCreateContactDialog(invite.getJid().toEscapedString(), invite);
+ } else if (contacts.isEmpty()) {
+ showCreateContactDialog(invite.getJid().toString(), invite);
return false;
} else if (contacts.size() == 1) {
Contact contact = contacts.get(0);
@@ -1279,10 +1276,10 @@ public class StartConversationActivity extends XmppActivity
if (mMenuSearchView != null) {
mMenuSearchView.expandActionView();
mSearchEditText.setText("");
- mSearchEditText.append(invite.getJid().toEscapedString());
- filter(invite.getJid().toEscapedString());
+ mSearchEditText.append(invite.getJid().toString());
+ filter(invite.getJid().toString());
} else {
- mInitialSearchValue.push(invite.getJid().toEscapedString());
+ mInitialSearchValue.push(invite.getJid().toString());
}
return true;
}
@@ -1298,7 +1295,7 @@ public class StartConversationActivity extends XmppActivity
JidDialog.style(
this,
R.string.verifying_omemo_keys_trusted_source,
- contact.getJid().asBareJid().toEscapedString(),
+ contact.getJid().asBareJid().toString(),
contact.getDisplayName()));
builder.setView(view);
builder.setPositiveButton(
@@ -1329,7 +1326,7 @@ public class StartConversationActivity extends XmppActivity
ArrayList tags = new ArrayList<>();
final var accounts = new ArrayList();
for (final var account : xmppConnectionService.getAccounts()) {
- if (mActivatedAccounts.contains(account.getJid().asBareJid().toEscapedString())) accounts.add(account);
+ if (mActivatedAccounts.contains(account.getJid().asBareJid().toString())) accounts.add(account);
}
boolean foundSopranica = false;
for (final Account account : accounts) {
@@ -1454,8 +1451,7 @@ public class StartConversationActivity extends XmppActivity
intent.putExtra(ChooseContactActivity.EXTRA_SELECT_MULTIPLE, true);
intent.putExtra(ChooseContactActivity.EXTRA_GROUP_CHAT_NAME, name.trim());
intent.putExtra(
- ChooseContactActivity.EXTRA_ACCOUNT,
- account.getJid().asBareJid().toEscapedString());
+ ChooseContactActivity.EXTRA_ACCOUNT, account.getJid().asBareJid().toString());
intent.putExtra(ChooseContactActivity.EXTRA_TITLE_RES_ID, R.string.choose_participants);
startActivityForResult(intent, REQUEST_CREATE_CONFERENCE);
}
@@ -1477,13 +1473,13 @@ public class StartConversationActivity extends XmppActivity
final String input = jid.getText().toString().trim();
Jid conferenceJid;
try {
- conferenceJid = Jid.ofEscaped(input);
+ conferenceJid = Jid.ofUserInput(input);
} catch (final IllegalArgumentException e) {
final XmppUri xmppUri = new XmppUri(input);
if (xmppUri.isValidJid() && xmppUri.isAction(XmppUri.ACTION_JOIN)) {
final Editable editable = jid.getEditableText();
editable.clear();
- editable.append(xmppUri.getJid().toEscapedString());
+ editable.append(xmppUri.getJid().toString());
conferenceJid = xmppUri.getJid();
} else {
layout.setError(getString(R.string.invalid_jid));
diff --git a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java
index 689030c796ab07c98aa5f8fef767f45a4e07da2e..c1a5ef08c9649c23acd2e35b301783e2675e4924 100644
--- a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java
@@ -1,6 +1,5 @@
package eu.siacs.conversations.ui;
-import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
@@ -10,12 +9,9 @@ import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
-
import androidx.appcompat.app.ActionBar;
import androidx.databinding.DataBindingUtil;
-
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.OmemoSetting;
@@ -32,433 +28,515 @@ import eu.siacs.conversations.utils.IrregularUnicodeDetector;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
-
-import org.whispersystems.libsignal.IdentityKey;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.whispersystems.libsignal.IdentityKey;
public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdated {
- private final Map ownKeysToTrust = new HashMap<>();
- private final Map> foreignKeysToTrust = new HashMap<>();
- private final OnClickListener mCancelButtonListener = v -> {
- setResult(RESULT_CANCELED);
- finish();
- };
- private List contactJids;
- private Account mAccount;
- private Conversation mConversation;
- private final OnClickListener mSaveButtonListener = v -> {
- commitTrusts();
- finishOk(false);
- };
- private final AtomicBoolean mUseCameraHintShown = new AtomicBoolean(false);
- private AxolotlService.FetchStatus lastFetchReport = AxolotlService.FetchStatus.SUCCESS;
- private Toast mUseCameraHintToast = null;
- private ActivityTrustKeysBinding binding;
-
- @Override
- protected void refreshUiReal() {
- invalidateOptionsMenu();
- populateView();
- }
-
- @Override
- protected void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- this.binding = DataBindingUtil.setContentView(this, R.layout.activity_trust_keys);
- Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
- this.contactJids = new ArrayList<>();
- final var intent = getIntent();
- final String[] contacts = intent == null ? null : intent.getStringArrayExtra("contacts");
- for (final String jid : (contacts == null ? new String[0] : contacts)) {
- try {
- this.contactJids.add(Jid.of(jid));
- } catch (final IllegalArgumentException ignored) {
- }
- }
-
- binding.cancelButton.setOnClickListener(mCancelButtonListener);
- binding.saveButton.setOnClickListener(mSaveButtonListener);
-
- setSupportActionBar(binding.toolbar);
- configureActionBar(getSupportActionBar());
-
- if (savedInstanceState != null) {
- mUseCameraHintShown.set(savedInstanceState.getBoolean("camera_hint_shown", false));
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle savedInstanceState) {
- savedInstanceState.putBoolean("camera_hint_shown", mUseCameraHintShown.get());
- super.onSaveInstanceState(savedInstanceState);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.trust_keys, menu);
- MenuItem scanQrCode = menu.findItem(R.id.action_scan_qr_code);
- scanQrCode.setVisible((!ownKeysToTrust.isEmpty() || foreignActuallyHasKeys()) && isCameraFeatureAvailable());
- return super.onCreateOptionsMenu(menu);
- }
-
- private void showCameraToast() {
- mUseCameraHintToast = Toast.makeText(this, R.string.use_camera_icon_to_scan_barcode, Toast.LENGTH_LONG);
- ActionBar actionBar = getSupportActionBar();
- mUseCameraHintToast.setGravity(Gravity.TOP | Gravity.END, 0, actionBar == null ? 0 : actionBar.getHeight());
- mUseCameraHintToast.show();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_scan_qr_code:
- if (hasPendingKeyFetches()) {
- Toast.makeText(this, R.string.please_wait_for_keys_to_be_fetched, Toast.LENGTH_SHORT).show();
- } else {
- ScanActivity.scan(this);
- //new IntentIntegrator(this).initiateScan(Arrays.asList("AZTEC","QR_CODE"));
- return true;
- }
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- if (mUseCameraHintToast != null) {
- mUseCameraHintToast.cancel();
- }
- }
-
- @Override
- protected void processFingerprintVerification(XmppUri uri) {
- if (mConversation != null
- && mAccount != null
- && uri.hasFingerprints()
- && mAccount.getAxolotlService().getCryptoTargets(mConversation).contains(uri.getJid())) {
- boolean performedVerification = xmppConnectionService.verifyFingerprints(mAccount.getRoster().getContact(uri.getJid()), uri.getFingerprints());
- boolean keys = reloadFingerprints();
- if (performedVerification && !keys && !hasNoOtherTrustedKeys() && !hasPendingKeyFetches()) {
- Toast.makeText(this, R.string.all_omemo_keys_have_been_verified, Toast.LENGTH_SHORT).show();
- finishOk(false);
- return;
- } else if (performedVerification) {
- Toast.makeText(this, R.string.verified_fingerprints, Toast.LENGTH_SHORT).show();
- }
- } else {
- reloadFingerprints();
- Log.d(Config.LOGTAG, "xmpp uri was: " + uri.getJid() + " has Fingerprints: " + uri.hasFingerprints());
- Toast.makeText(this, R.string.barcode_does_not_contain_fingerprints_for_this_chat, Toast.LENGTH_SHORT).show();
- }
- populateView();
- }
-
- private void populateView() {
- if (this.mAccount == null) {
- return;
- }
-
- setTitle(getString(R.string.trust_omemo_fingerprints));
- binding.ownKeysDetails.removeAllViews();
- binding.foreignKeys.removeAllViews();
- boolean hasOwnKeys = false;
- boolean hasForeignKeys = false;
- for (final String fingerprint : ownKeysToTrust.keySet()) {
- hasOwnKeys = true;
- addFingerprintRowWithListeners(binding.ownKeysDetails, mAccount, fingerprint, false,
- FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)), false, false,
- (buttonView, isChecked) -> {
- ownKeysToTrust.put(fingerprint, isChecked);
- // own fingerprints have no impact on locked status.
- }
- );
- }
-
- synchronized (this.foreignKeysToTrust) {
- for (Map.Entry> entry : foreignKeysToTrust.entrySet()) {
- hasForeignKeys = true;
- KeysCardBinding keysCardBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.keys_card, binding.foreignKeys, false);
- final Jid jid = entry.getKey();
- keysCardBinding.foreignKeysTitle.setText(IrregularUnicodeDetector.style(this, jid));
- keysCardBinding.foreignKeysTitle.setOnClickListener(v -> switchToContactDetails(mAccount.getRoster().getContact(jid)));
- final Map fingerprints = entry.getValue();
- for (final String fingerprint : fingerprints.keySet()) {
- addFingerprintRowWithListeners(keysCardBinding.foreignKeysDetails, mAccount, fingerprint, false,
- FingerprintStatus.createActive(fingerprints.get(fingerprint)), false, false,
- (buttonView, isChecked) -> {
- fingerprints.put(fingerprint, isChecked);
- lockOrUnlockAsNeeded();
- }
- );
- }
- if (fingerprints.isEmpty()) {
- keysCardBinding.noKeysToAccept.setVisibility(View.VISIBLE);
- if (hasNoOtherTrustedKeys(jid)) {
- if (!mAccount.getRoster().getContact(jid).mutualPresenceSubscription()) {
- keysCardBinding.noKeysToAccept.setText(R.string.error_no_keys_to_trust_presence);
- } else {
- keysCardBinding.noKeysToAccept.setText(R.string.error_no_keys_to_trust_server_error);
- }
- } else {
- keysCardBinding.noKeysToAccept.setText(getString(R.string.no_keys_just_confirm, mAccount.getRoster().getContact(jid).getDisplayName()));
- }
- } else {
- keysCardBinding.noKeysToAccept.setVisibility(View.GONE);
- }
- binding.foreignKeys.addView(keysCardBinding.foreignKeysCard);
- }
- }
-
- if ((hasOwnKeys || foreignActuallyHasKeys()) && isCameraFeatureAvailable() && mUseCameraHintShown.compareAndSet(false, true)) {
- showCameraToast();
- }
-
- binding.ownKeysTitle.setText(mAccount.getJid().asBareJid().toEscapedString());
- binding.ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE);
- binding.foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE);
- if (hasPendingKeyFetches()) {
- setFetching();
- lock();
- } else {
- if (!hasForeignKeys && hasNoOtherTrustedKeys()) {
- binding.keyErrorMessageCard.setVisibility(View.VISIBLE);
- boolean lastReportWasError = lastFetchReport == AxolotlService.FetchStatus.ERROR;
- boolean errorFetchingBundle = mAccount.getAxolotlService().fetchMapHasErrors(contactJids);
- boolean errorFetchingDeviceList = mAccount.getAxolotlService().hasErrorFetchingDeviceList(contactJids);
- boolean anyWithoutMutualPresenceSubscription = anyWithoutMutualPresenceSubscription(contactJids);
- if (errorFetchingDeviceList) {
- binding.keyErrorMessage.setVisibility(View.VISIBLE);
- binding.keyErrorMessage.setText(R.string.error_trustkey_device_list);
- } else if (errorFetchingBundle || lastReportWasError) {
- binding.keyErrorMessage.setVisibility(View.VISIBLE);
- binding.keyErrorMessage.setText(R.string.error_trustkey_bundle);
- } else {
- binding.keyErrorMessage.setVisibility(View.GONE);
- }
- this.binding.keyErrorHintMutual.setVisibility(anyWithoutMutualPresenceSubscription ? View.VISIBLE : View.GONE);
- Contact contact = mAccount.getRoster().getContact(contactJids.get(0));
- binding.keyErrorGeneral.setText(getString(R.string.error_trustkey_general, getString(R.string.app_name), contact.getDisplayName()));
- binding.ownKeysDetails.removeAllViews();
- if (OmemoSetting.isAlways()) {
- binding.disableButton.setVisibility(View.GONE);
- } else {
- binding.disableButton.setVisibility(View.VISIBLE);
- binding.disableButton.setOnClickListener(this::disableEncryptionDialog);
- }
- binding.ownKeysCard.setVisibility(View.GONE);
- binding.foreignKeys.removeAllViews();
- binding.foreignKeys.setVisibility(View.GONE);
- }
- lockOrUnlockAsNeeded();
- setDone();
- }
- }
-
- private void disableEncryptionDialog(final View view) {
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
- builder.setTitle(R.string.disable_encryption);
- builder.setMessage(R.string.disable_encryption_message);
- builder.setPositiveButton(R.string.disable_now, (dialog, which) -> {
- mConversation.setNextEncryption(Message.ENCRYPTION_NONE);
- xmppConnectionService.updateConversation(mConversation);
- finishOk(true);
- });
- builder.setNegativeButton(R.string.cancel, null);
- builder.create().show();
- }
-
- private boolean anyWithoutMutualPresenceSubscription(List contactJids) {
- for (Jid jid : contactJids) {
- if (!mAccount.getRoster().getContact(jid).mutualPresenceSubscription()) {
- return true;
- }
- }
- return false;
- }
-
- private boolean foreignActuallyHasKeys() {
- synchronized (this.foreignKeysToTrust) {
- for (Map.Entry> entry : foreignKeysToTrust.entrySet()) {
- if (!entry.getValue().isEmpty()) {
- return true;
- }
- }
- }
- return false;
- }
-
- private boolean reloadFingerprints() {
- List acceptedTargets = mConversation == null ? new ArrayList<>() : mConversation.getAcceptedCryptoTargets();
- ownKeysToTrust.clear();
- if (this.mAccount == null) {
- return false;
- }
- AxolotlService service = this.mAccount.getAxolotlService();
- Set ownKeysSet = service.getKeysWithTrust(FingerprintStatus.createActiveUndecided());
- for (final IdentityKey identityKey : ownKeysSet) {
- final String fingerprint = CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize());
- if (!ownKeysToTrust.containsKey(fingerprint)) {
- ownKeysToTrust.put(fingerprint, false);
- }
- }
- synchronized (this.foreignKeysToTrust) {
- foreignKeysToTrust.clear();
- for (Jid jid : contactJids) {
- Set foreignKeysSet = service.getKeysWithTrust(FingerprintStatus.createActiveUndecided(), jid);
- if (hasNoOtherTrustedKeys(jid) && ownKeysSet.isEmpty()) {
- foreignKeysSet.addAll(service.getKeysWithTrust(FingerprintStatus.createActive(false), jid));
- }
- Map foreignFingerprints = new HashMap<>();
- for (final IdentityKey identityKey : foreignKeysSet) {
- final String fingerprint = CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize());
- if (!foreignFingerprints.containsKey(fingerprint)) {
- foreignFingerprints.put(fingerprint, false);
- }
- }
- if (!foreignFingerprints.isEmpty() || !acceptedTargets.contains(jid)) {
- foreignKeysToTrust.put(jid, foreignFingerprints);
- }
- }
- }
- return ownKeysSet.size() + foreignKeysToTrust.size() > 0;
- }
-
- public void onBackendConnected() {
- Intent intent = getIntent();
- this.mAccount = extractAccount(intent);
- if (this.mAccount != null && intent != null) {
- String uuid = intent.getStringExtra("conversation");
- this.mConversation = xmppConnectionService.findConversationByUuid(uuid);
- if (this.mPendingFingerprintVerificationUri != null) {
- processFingerprintVerification(this.mPendingFingerprintVerificationUri);
- this.mPendingFingerprintVerificationUri = null;
- } else {
- final boolean keysToTrust = reloadFingerprints();
- if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) {
- populateView();
- invalidateOptionsMenu();
- } else {
- finishOk(false);
- }
- }
- }
- }
-
- private boolean hasNoOtherTrustedKeys() {
- return mAccount == null || mAccount.getAxolotlService().anyTargetHasNoTrustedKeys(contactJids);
- }
-
- private boolean hasNoOtherTrustedKeys(Jid contact) {
- return mAccount == null || mAccount.getAxolotlService().getNumTrustedKeys(contact) == 0;
- }
-
- private boolean hasPendingKeyFetches() {
- return mAccount != null && mAccount.getAxolotlService().hasPendingKeyFetches(contactJids);
- }
-
-
- @Override
- public void onKeyStatusUpdated(final AxolotlService.FetchStatus report) {
- final boolean keysToTrust = reloadFingerprints();
- if (report != null) {
- lastFetchReport = report;
- runOnUiThread(() -> {
- if (mUseCameraHintToast != null && !keysToTrust) {
- mUseCameraHintToast.cancel();
- }
- switch (report) {
- case ERROR:
- Toast.makeText(TrustKeysActivity.this, R.string.error_fetching_omemo_key, Toast.LENGTH_SHORT).show();
- break;
- case SUCCESS_TRUSTED:
- Toast.makeText(TrustKeysActivity.this, R.string.blindly_trusted_omemo_keys, Toast.LENGTH_LONG).show();
- break;
- case SUCCESS_VERIFIED:
- Toast.makeText(TrustKeysActivity.this,
- Config.X509_VERIFICATION ? R.string.verified_omemo_key_with_certificate : R.string.all_omemo_keys_have_been_verified,
- Toast.LENGTH_LONG).show();
- break;
- }
- });
-
- }
- if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) {
- refreshUi();
- } else {
- runOnUiThread(() -> finishOk(false));
-
- }
- }
-
- private void finishOk(boolean disabled) {
- Intent data = new Intent();
- data.putExtra("choice", getIntent().getIntExtra("choice", ConversationFragment.ATTACHMENT_CHOICE_INVALID));
- data.putExtra("disabled", disabled);
- setResult(RESULT_OK, data);
- finish();
- }
-
- private void commitTrusts() {
- for (final String fingerprint : ownKeysToTrust.keySet()) {
- mAccount.getAxolotlService().setFingerprintTrust(
- fingerprint,
- FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)));
- }
- List acceptedTargets = mConversation == null ? new ArrayList<>() : mConversation.getAcceptedCryptoTargets();
- synchronized (this.foreignKeysToTrust) {
- for (Map.Entry> entry : foreignKeysToTrust.entrySet()) {
- Jid jid = entry.getKey();
- Map value = entry.getValue();
- if (!acceptedTargets.contains(jid)) {
- acceptedTargets.add(jid);
- }
- for (final String fingerprint : value.keySet()) {
- mAccount.getAxolotlService().setFingerprintTrust(
- fingerprint,
- FingerprintStatus.createActive(value.get(fingerprint)));
- }
- }
- }
- if (mConversation != null && mConversation.getMode() == Conversation.MODE_MULTI) {
- mConversation.setAcceptedCryptoTargets(acceptedTargets);
- xmppConnectionService.updateConversation(mConversation);
- }
- }
-
- private void unlock() {
- binding.saveButton.setEnabled(true);
- }
-
- private void lock() {
- binding.saveButton.setEnabled(false);
- }
-
- private void lockOrUnlockAsNeeded() {
- synchronized (this.foreignKeysToTrust) {
- for (Jid jid : contactJids) {
- Map fingerprints = foreignKeysToTrust.get(jid);
- if (hasNoOtherTrustedKeys(jid) && (fingerprints == null || !fingerprints.containsValue(true))) {
- lock();
- return;
- }
- }
- }
- unlock();
-
- }
-
- private void setDone() {
- binding.saveButton.setText(getString(R.string.done));
- }
-
- private void setFetching() {
- binding.saveButton.setText(getString(R.string.fetching_keys));
- }
+ private final Map ownKeysToTrust = new HashMap<>();
+ private final Map> foreignKeysToTrust = new HashMap<>();
+ private final OnClickListener mCancelButtonListener =
+ v -> {
+ setResult(RESULT_CANCELED);
+ finish();
+ };
+ private List contactJids;
+ private Account mAccount;
+ private Conversation mConversation;
+ private final OnClickListener mSaveButtonListener =
+ v -> {
+ commitTrusts();
+ finishOk(false);
+ };
+ private final AtomicBoolean mUseCameraHintShown = new AtomicBoolean(false);
+ private AxolotlService.FetchStatus lastFetchReport = AxolotlService.FetchStatus.SUCCESS;
+ private Toast mUseCameraHintToast = null;
+ private ActivityTrustKeysBinding binding;
+
+ @Override
+ protected void refreshUiReal() {
+ invalidateOptionsMenu();
+ populateView();
+ }
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.binding = DataBindingUtil.setContentView(this, R.layout.activity_trust_keys);
+ Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
+ this.contactJids = new ArrayList<>();
+ final var intent = getIntent();
+ final String[] contacts = intent == null ? null : intent.getStringArrayExtra("contacts");
+ for (final String jid : (contacts == null ? new String[0] : contacts)) {
+ try {
+ this.contactJids.add(Jid.of(jid));
+ } catch (final IllegalArgumentException ignored) {
+ }
+ }
+
+ binding.cancelButton.setOnClickListener(mCancelButtonListener);
+ binding.saveButton.setOnClickListener(mSaveButtonListener);
+
+ setSupportActionBar(binding.toolbar);
+ configureActionBar(getSupportActionBar());
+
+ if (savedInstanceState != null) {
+ mUseCameraHintShown.set(savedInstanceState.getBoolean("camera_hint_shown", false));
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle savedInstanceState) {
+ savedInstanceState.putBoolean("camera_hint_shown", mUseCameraHintShown.get());
+ super.onSaveInstanceState(savedInstanceState);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.trust_keys, menu);
+ MenuItem scanQrCode = menu.findItem(R.id.action_scan_qr_code);
+ scanQrCode.setVisible(
+ (!ownKeysToTrust.isEmpty() || foreignActuallyHasKeys())
+ && isCameraFeatureAvailable());
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ private void showCameraToast() {
+ mUseCameraHintToast =
+ Toast.makeText(this, R.string.use_camera_icon_to_scan_barcode, Toast.LENGTH_LONG);
+ ActionBar actionBar = getSupportActionBar();
+ mUseCameraHintToast.setGravity(
+ Gravity.TOP | Gravity.END, 0, actionBar == null ? 0 : actionBar.getHeight());
+ mUseCameraHintToast.show();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_scan_qr_code:
+ if (hasPendingKeyFetches()) {
+ Toast.makeText(
+ this,
+ R.string.please_wait_for_keys_to_be_fetched,
+ Toast.LENGTH_SHORT)
+ .show();
+ } else {
+ ScanActivity.scan(this);
+ // new IntentIntegrator(this).initiateScan(Arrays.asList("AZTEC","QR_CODE"));
+ return true;
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (mUseCameraHintToast != null) {
+ mUseCameraHintToast.cancel();
+ }
+ }
+
+ @Override
+ protected void processFingerprintVerification(XmppUri uri) {
+ if (mConversation != null
+ && mAccount != null
+ && uri.hasFingerprints()
+ && mAccount.getAxolotlService()
+ .getCryptoTargets(mConversation)
+ .contains(uri.getJid())) {
+ boolean performedVerification =
+ xmppConnectionService.verifyFingerprints(
+ mAccount.getRoster().getContact(uri.getJid()), uri.getFingerprints());
+ boolean keys = reloadFingerprints();
+ if (performedVerification
+ && !keys
+ && !hasNoOtherTrustedKeys()
+ && !hasPendingKeyFetches()) {
+ Toast.makeText(this, R.string.all_omemo_keys_have_been_verified, Toast.LENGTH_SHORT)
+ .show();
+ finishOk(false);
+ return;
+ } else if (performedVerification) {
+ Toast.makeText(this, R.string.verified_fingerprints, Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ reloadFingerprints();
+ Log.d(
+ Config.LOGTAG,
+ "xmpp uri was: "
+ + uri.getJid()
+ + " has Fingerprints: "
+ + uri.hasFingerprints());
+ Toast.makeText(
+ this,
+ R.string.barcode_does_not_contain_fingerprints_for_this_chat,
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ populateView();
+ }
+
+ private void populateView() {
+ setTitle(getString(R.string.trust_omemo_fingerprints));
+ binding.ownKeysDetails.removeAllViews();
+ binding.foreignKeys.removeAllViews();
+ boolean hasOwnKeys = false;
+ boolean hasForeignKeys = false;
+ for (final String fingerprint : ownKeysToTrust.keySet()) {
+ hasOwnKeys = true;
+ addFingerprintRowWithListeners(
+ binding.ownKeysDetails,
+ mAccount,
+ fingerprint,
+ false,
+ FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)),
+ false,
+ false,
+ (buttonView, isChecked) -> {
+ ownKeysToTrust.put(fingerprint, isChecked);
+ // own fingerprints have no impact on locked status.
+ });
+ }
+
+ synchronized (this.foreignKeysToTrust) {
+ for (Map.Entry> entry : foreignKeysToTrust.entrySet()) {
+ hasForeignKeys = true;
+ KeysCardBinding keysCardBinding =
+ DataBindingUtil.inflate(
+ getLayoutInflater(),
+ R.layout.keys_card,
+ binding.foreignKeys,
+ false);
+ final Jid jid = entry.getKey();
+ keysCardBinding.foreignKeysTitle.setText(IrregularUnicodeDetector.style(this, jid));
+ keysCardBinding.foreignKeysTitle.setOnClickListener(
+ v -> switchToContactDetails(mAccount.getRoster().getContact(jid)));
+ final Map fingerprints = entry.getValue();
+ for (final String fingerprint : fingerprints.keySet()) {
+ addFingerprintRowWithListeners(
+ keysCardBinding.foreignKeysDetails,
+ mAccount,
+ fingerprint,
+ false,
+ FingerprintStatus.createActive(fingerprints.get(fingerprint)),
+ false,
+ false,
+ (buttonView, isChecked) -> {
+ fingerprints.put(fingerprint, isChecked);
+ lockOrUnlockAsNeeded();
+ });
+ }
+ if (fingerprints.isEmpty()) {
+ keysCardBinding.noKeysToAccept.setVisibility(View.VISIBLE);
+ if (hasNoOtherTrustedKeys(jid)) {
+ if (!mAccount.getRoster().getContact(jid).mutualPresenceSubscription()) {
+ keysCardBinding.noKeysToAccept.setText(
+ R.string.error_no_keys_to_trust_presence);
+ } else {
+ keysCardBinding.noKeysToAccept.setText(
+ R.string.error_no_keys_to_trust_server_error);
+ }
+ } else {
+ keysCardBinding.noKeysToAccept.setText(
+ getString(
+ R.string.no_keys_just_confirm,
+ mAccount.getRoster().getContact(jid).getDisplayName()));
+ }
+ } else {
+ keysCardBinding.noKeysToAccept.setVisibility(View.GONE);
+ }
+ binding.foreignKeys.addView(keysCardBinding.foreignKeysCard);
+ }
+ }
+
+ if ((hasOwnKeys || foreignActuallyHasKeys())
+ && isCameraFeatureAvailable()
+ && mUseCameraHintShown.compareAndSet(false, true)) {
+ showCameraToast();
+ }
+
+ binding.ownKeysTitle.setText(mAccount.getJid().asBareJid().toString());
+ binding.ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE);
+ binding.foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE);
+ if (hasPendingKeyFetches()) {
+ setFetching();
+ lock();
+ } else {
+ if (!hasForeignKeys && hasNoOtherTrustedKeys()) {
+ binding.keyErrorMessageCard.setVisibility(View.VISIBLE);
+ boolean lastReportWasError = lastFetchReport == AxolotlService.FetchStatus.ERROR;
+ boolean errorFetchingBundle =
+ mAccount.getAxolotlService().fetchMapHasErrors(contactJids);
+ boolean errorFetchingDeviceList =
+ mAccount.getAxolotlService().hasErrorFetchingDeviceList(contactJids);
+ boolean anyWithoutMutualPresenceSubscription =
+ anyWithoutMutualPresenceSubscription(contactJids);
+ if (errorFetchingDeviceList) {
+ binding.keyErrorMessage.setVisibility(View.VISIBLE);
+ binding.keyErrorMessage.setText(R.string.error_trustkey_device_list);
+ } else if (errorFetchingBundle || lastReportWasError) {
+ binding.keyErrorMessage.setVisibility(View.VISIBLE);
+ binding.keyErrorMessage.setText(R.string.error_trustkey_bundle);
+ } else {
+ binding.keyErrorMessage.setVisibility(View.GONE);
+ }
+ this.binding.keyErrorHintMutual.setVisibility(
+ anyWithoutMutualPresenceSubscription ? View.VISIBLE : View.GONE);
+ Contact contact = mAccount.getRoster().getContact(contactJids.get(0));
+ binding.keyErrorGeneral.setText(
+ getString(
+ R.string.error_trustkey_general,
+ getString(R.string.app_name),
+ contact.getDisplayName()));
+ binding.ownKeysDetails.removeAllViews();
+ if (OmemoSetting.isAlways()) {
+ binding.disableButton.setVisibility(View.GONE);
+ } else {
+ binding.disableButton.setVisibility(View.VISIBLE);
+ binding.disableButton.setOnClickListener(this::disableEncryptionDialog);
+ }
+ binding.ownKeysCard.setVisibility(View.GONE);
+ binding.foreignKeys.removeAllViews();
+ binding.foreignKeys.setVisibility(View.GONE);
+ }
+ lockOrUnlockAsNeeded();
+ setDone();
+ }
+ }
+
+ private void disableEncryptionDialog(final View view) {
+ final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
+ builder.setTitle(R.string.disable_encryption);
+ builder.setMessage(R.string.disable_encryption_message);
+ builder.setPositiveButton(
+ R.string.disable_now,
+ (dialog, which) -> {
+ mConversation.setNextEncryption(Message.ENCRYPTION_NONE);
+ xmppConnectionService.updateConversation(mConversation);
+ finishOk(true);
+ });
+ builder.setNegativeButton(R.string.cancel, null);
+ builder.create().show();
+ }
+
+ private boolean anyWithoutMutualPresenceSubscription(List contactJids) {
+ for (Jid jid : contactJids) {
+ if (!mAccount.getRoster().getContact(jid).mutualPresenceSubscription()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean foreignActuallyHasKeys() {
+ synchronized (this.foreignKeysToTrust) {
+ for (Map.Entry> entry : foreignKeysToTrust.entrySet()) {
+ if (!entry.getValue().isEmpty()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean reloadFingerprints() {
+ List acceptedTargets =
+ mConversation == null
+ ? new ArrayList<>()
+ : mConversation.getAcceptedCryptoTargets();
+ ownKeysToTrust.clear();
+ if (this.mAccount == null) {
+ return false;
+ }
+ AxolotlService service = this.mAccount.getAxolotlService();
+ Set ownKeysSet =
+ service.getKeysWithTrust(FingerprintStatus.createActiveUndecided());
+ for (final IdentityKey identityKey : ownKeysSet) {
+ final String fingerprint =
+ CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize());
+ if (!ownKeysToTrust.containsKey(fingerprint)) {
+ ownKeysToTrust.put(fingerprint, false);
+ }
+ }
+ synchronized (this.foreignKeysToTrust) {
+ foreignKeysToTrust.clear();
+ for (Jid jid : contactJids) {
+ Set foreignKeysSet =
+ service.getKeysWithTrust(FingerprintStatus.createActiveUndecided(), jid);
+ if (hasNoOtherTrustedKeys(jid) && ownKeysSet.isEmpty()) {
+ foreignKeysSet.addAll(
+ service.getKeysWithTrust(FingerprintStatus.createActive(false), jid));
+ }
+ Map foreignFingerprints = new HashMap<>();
+ for (final IdentityKey identityKey : foreignKeysSet) {
+ final String fingerprint =
+ CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize());
+ if (!foreignFingerprints.containsKey(fingerprint)) {
+ foreignFingerprints.put(fingerprint, false);
+ }
+ }
+ if (!foreignFingerprints.isEmpty() || !acceptedTargets.contains(jid)) {
+ foreignKeysToTrust.put(jid, foreignFingerprints);
+ }
+ }
+ }
+ return ownKeysSet.size() + foreignKeysToTrust.size() > 0;
+ }
+
+ public void onBackendConnected() {
+ Intent intent = getIntent();
+ this.mAccount = extractAccount(intent);
+ if (this.mAccount != null && intent != null) {
+ String uuid = intent.getStringExtra("conversation");
+ this.mConversation = xmppConnectionService.findConversationByUuid(uuid);
+ if (this.mPendingFingerprintVerificationUri != null) {
+ processFingerprintVerification(this.mPendingFingerprintVerificationUri);
+ this.mPendingFingerprintVerificationUri = null;
+ } else {
+ final boolean keysToTrust = reloadFingerprints();
+ if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) {
+ populateView();
+ invalidateOptionsMenu();
+ } else {
+ finishOk(false);
+ }
+ }
+ }
+ }
+
+ private boolean hasNoOtherTrustedKeys() {
+ return mAccount == null
+ || mAccount.getAxolotlService().anyTargetHasNoTrustedKeys(contactJids);
+ }
+
+ private boolean hasNoOtherTrustedKeys(Jid contact) {
+ return mAccount == null || mAccount.getAxolotlService().getNumTrustedKeys(contact) == 0;
+ }
+
+ private boolean hasPendingKeyFetches() {
+ return mAccount != null && mAccount.getAxolotlService().hasPendingKeyFetches(contactJids);
+ }
+
+ @Override
+ public void onKeyStatusUpdated(final AxolotlService.FetchStatus report) {
+ final boolean keysToTrust = reloadFingerprints();
+ if (report != null) {
+ lastFetchReport = report;
+ runOnUiThread(
+ () -> {
+ if (mUseCameraHintToast != null && !keysToTrust) {
+ mUseCameraHintToast.cancel();
+ }
+ switch (report) {
+ case ERROR:
+ Toast.makeText(
+ TrustKeysActivity.this,
+ R.string.error_fetching_omemo_key,
+ Toast.LENGTH_SHORT)
+ .show();
+ break;
+ case SUCCESS_TRUSTED:
+ Toast.makeText(
+ TrustKeysActivity.this,
+ R.string.blindly_trusted_omemo_keys,
+ Toast.LENGTH_LONG)
+ .show();
+ break;
+ case SUCCESS_VERIFIED:
+ Toast.makeText(
+ TrustKeysActivity.this,
+ Config.X509_VERIFICATION
+ ? R.string
+ .verified_omemo_key_with_certificate
+ : R.string
+ .all_omemo_keys_have_been_verified,
+ Toast.LENGTH_LONG)
+ .show();
+ break;
+ }
+ });
+ }
+ if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) {
+ refreshUi();
+ } else {
+ runOnUiThread(() -> finishOk(false));
+ }
+ }
+
+ private void finishOk(boolean disabled) {
+ Intent data = new Intent();
+ data.putExtra(
+ "choice",
+ getIntent().getIntExtra("choice", ConversationFragment.ATTACHMENT_CHOICE_INVALID));
+ data.putExtra("disabled", disabled);
+ setResult(RESULT_OK, data);
+ finish();
+ }
+
+ private void commitTrusts() {
+ for (final String fingerprint : ownKeysToTrust.keySet()) {
+ mAccount.getAxolotlService()
+ .setFingerprintTrust(
+ fingerprint,
+ FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)));
+ }
+ List acceptedTargets =
+ mConversation == null
+ ? new ArrayList<>()
+ : mConversation.getAcceptedCryptoTargets();
+ synchronized (this.foreignKeysToTrust) {
+ for (Map.Entry> entry : foreignKeysToTrust.entrySet()) {
+ Jid jid = entry.getKey();
+ Map value = entry.getValue();
+ if (!acceptedTargets.contains(jid)) {
+ acceptedTargets.add(jid);
+ }
+ for (final String fingerprint : value.keySet()) {
+ mAccount.getAxolotlService()
+ .setFingerprintTrust(
+ fingerprint,
+ FingerprintStatus.createActive(value.get(fingerprint)));
+ }
+ }
+ }
+ if (mConversation != null && mConversation.getMode() == Conversation.MODE_MULTI) {
+ mConversation.setAcceptedCryptoTargets(acceptedTargets);
+ xmppConnectionService.updateConversation(mConversation);
+ }
+ }
+
+ private void unlock() {
+ binding.saveButton.setEnabled(true);
+ }
+
+ private void lock() {
+ binding.saveButton.setEnabled(false);
+ }
+
+ private void lockOrUnlockAsNeeded() {
+ synchronized (this.foreignKeysToTrust) {
+ for (Jid jid : contactJids) {
+ Map fingerprints = foreignKeysToTrust.get(jid);
+ if (hasNoOtherTrustedKeys(jid)
+ && (fingerprints == null || !fingerprints.containsValue(true))) {
+ lock();
+ return;
+ }
+ }
+ }
+ unlock();
+ }
+
+ private void setDone() {
+ binding.saveButton.setText(getString(R.string.done));
+ }
+
+ private void setFetching() {
+ binding.saveButton.setText(getString(R.string.fetching_keys));
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java b/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java
index fbe42e3b33928fc43847ac5a54ed7107b776415c..c2878041b1453d356d44818803e5876265c58af5 100644
--- a/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java
@@ -11,12 +11,10 @@ import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
-
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
-
import com.google.common.base.Strings;
import com.cheogram.android.DownloadDefaultStickers;
@@ -38,18 +36,12 @@ import eu.siacs.conversations.utils.ProvisioningUtils;
import eu.siacs.conversations.utils.SignupUtils;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xmpp.Jid;
-
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.Request;
import okhttp3.Response;
-import java.io.IOException;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
public class UriHandlerActivity extends BaseActivity {
public static final String ACTION_SCAN_QR_CODE = "scan_qr_code";
@@ -68,7 +60,8 @@ public class UriHandlerActivity extends BaseActivity {
}
public static void scan(final Activity activity, final boolean provisioning) {
- if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
+ if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA)
+ == PackageManager.PERMISSION_GRANTED) {
final Intent intent = new Intent(activity, UriHandlerActivity.class);
intent.setAction(UriHandlerActivity.ACTION_SCAN_QR_CODE);
if (provisioning) {
@@ -178,7 +171,7 @@ public class UriHandlerActivity extends BaseActivity {
final String preAuth = xmppUri.getParameter(XmppUri.PARAMETER_PRE_AUTH);
final Jid jid = xmppUri.getJid();
if (xmppUri.isAction(XmppUri.ACTION_REGISTER)) {
- if (jid.getEscapedLocal() != null && accounts.contains(jid.asBareJid())) {
+ if (jid.getLocal() != null && accounts.contains(jid.asBareJid())) {
showError(R.string.account_already_exists);
return false;
}
@@ -227,7 +220,7 @@ public class UriHandlerActivity extends BaseActivity {
intent = new Intent(this, StartConversationActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri);
- intent.putExtra("account", accounts.get(0).toEscapedString());
+ intent.putExtra("account", accounts.get(0).toString());
}
} else {
intent = new Intent(this, ShareWithActivity.class);
@@ -258,8 +251,8 @@ public class UriHandlerActivity extends BaseActivity {
private void checkForLinkHeader(final HttpUrl url) {
Log.d(Config.LOGTAG, "checking for link header on " + url);
this.call =
- HttpConnectionManager.okHttpClient(this).newCall(
- new Request.Builder().url(url).head().build());
+ HttpConnectionManager.okHttpClient(this)
+ .newCall(new Request.Builder().url(url).head().build());
this.call.enqueue(
new Callback() {
@Override
@@ -301,7 +294,7 @@ public class UriHandlerActivity extends BaseActivity {
}
private void showErrorOnUiThread(@StringRes int error) {
- runOnUiThread(()-> showError(error));
+ runOnUiThread(() -> showError(error));
}
private static Class> findShareViaAccountClass() {
diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
index bee7d2f8ca4f65126214de2d06f58797eafbd664..f86a45c8252ee1a2a566430c05da1795dc8125ea 100644
--- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
@@ -838,8 +838,8 @@ public abstract class XmppActivity extends ActionBarActivity {
public void switchToContactDetails(Contact contact, String messageFingerprint) {
Intent intent = new Intent(this, ContactDetailsActivity.class);
intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
- intent.putExtra(EXTRA_ACCOUNT, contact.getAccount().getJid().asBareJid().toEscapedString());
- intent.putExtra("contact", contact.getJid().toEscapedString());
+ intent.putExtra(EXTRA_ACCOUNT, contact.getAccount().getJid().asBareJid().toString());
+ intent.putExtra("contact", contact.getJid().toString());
intent.putExtra("fingerprint", messageFingerprint);
startActivity(intent);
}
@@ -854,7 +854,7 @@ public abstract class XmppActivity extends ActionBarActivity {
public void switchToAccount(Account account, boolean init, String fingerprint) {
Intent intent = new Intent(this, EditAccountActivity.class);
- intent.putExtra("jid", account.getJid().asBareJid().toEscapedString());
+ intent.putExtra("jid", account.getJid().asBareJid().toString());
intent.putExtra("init", init);
if (init) {
intent.setFlags(
@@ -1251,7 +1251,7 @@ public abstract class XmppActivity extends ActionBarActivity {
final AtomicReference selectedAccount = new AtomicReference<>(accounts.get(0));
final MaterialAlertDialogBuilder alertDialogBuilder = new MaterialAlertDialogBuilder(this);
alertDialogBuilder.setTitle(R.string.choose_account);
- final String[] asStrings = Collections2.transform(accounts, a -> a.getJid().asBareJid().toEscapedString()).toArray(new String[0]);
+ final String[] asStrings = Collections2.transform(accounts, a -> a.getJid().asBareJid().toString()).toArray(new String[0]);
alertDialogBuilder.setSingleChoiceItems(asStrings, 0, (dialog, which) -> selectedAccount.set(accounts.get(which)));
alertDialogBuilder.setNegativeButton(R.string.cancel, null);
alertDialogBuilder.setPositiveButton(R.string.ok, (dialog, which) -> showQrCode(selectedAccount.get().getShareableUri()));
@@ -1302,7 +1302,7 @@ public abstract class XmppActivity extends ActionBarActivity {
protected Account extractAccount(Intent intent) {
final String jid = intent != null ? intent.getStringExtra(EXTRA_ACCOUNT) : null;
try {
- return jid != null ? xmppConnectionService.findAccountByJid(Jid.ofEscaped(jid)) : null;
+ return jid != null ? xmppConnectionService.findAccountByJid(Jid.of(jid)) : null;
} catch (IllegalArgumentException e) {
return null;
}
diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java
index f913bd86b6efa484de74b9bf2063a0e60bb6e61d..ac31e248f0c987fe7e4a7d561de80480594bae43 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java
@@ -4,14 +4,10 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
-
import androidx.annotation.NonNull;
import androidx.core.graphics.ColorUtils;
import androidx.databinding.DataBindingUtil;
-
import com.google.android.material.color.MaterialColors;
-
-import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ItemAccountBinding;
import eu.siacs.conversations.entities.Account;
@@ -44,27 +40,42 @@ public class AccountAdapter extends ArrayAdapter {
final Account account = getItem(position);
final ViewHolder viewHolder;
if (view == null) {
- ItemAccountBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item_account, parent, false);
+ ItemAccountBinding binding =
+ DataBindingUtil.inflate(
+ LayoutInflater.from(parent.getContext()),
+ R.layout.item_account,
+ parent,
+ false);
view = binding.getRoot();
viewHolder = new ViewHolder(binding);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
- viewHolder.binding.accountJid.setText(account.getJid().asBareJid().toEscapedString());
+ viewHolder.binding.accountJid.setText(account.getJid().asBareJid().toString());
AvatarWorkerTask.loadAvatar(account, viewHolder.binding.accountImage, R.dimen.avatar);
- viewHolder.binding.accountStatus.setText(getContext().getString(account.getStatus().getReadableId()));
+ viewHolder.binding.accountStatus.setText(
+ getContext().getString(account.getStatus().getReadableId()));
switch (account.getStatus()) {
case ONLINE:
- viewHolder.binding.accountStatus.setTextColor(MaterialColors.getColor(viewHolder.binding.accountStatus, com.google.android.material.R.attr.colorPrimary));
+ viewHolder.binding.accountStatus.setTextColor(
+ MaterialColors.getColor(
+ viewHolder.binding.accountStatus,
+ com.google.android.material.R.attr.colorPrimary));
break;
case DISABLED:
case LOGGED_OUT:
case CONNECTING:
- viewHolder.binding.accountStatus.setTextColor(MaterialColors.getColor(viewHolder.binding.accountStatus, com.google.android.material.R.attr.colorOnSurfaceVariant));
+ viewHolder.binding.accountStatus.setTextColor(
+ MaterialColors.getColor(
+ viewHolder.binding.accountStatus,
+ com.google.android.material.R.attr.colorOnSurfaceVariant));
break;
default:
- viewHolder.binding.accountStatus.setTextColor(MaterialColors.getColor(viewHolder.binding.accountStatus, com.google.android.material.R.attr.colorError));
+ viewHolder.binding.accountStatus.setTextColor(
+ MaterialColors.getColor(
+ viewHolder.binding.accountStatus,
+ com.google.android.material.R.attr.colorError));
break;
}
if (account.isOnlineAndConnected()) {
@@ -89,11 +100,12 @@ public class AccountAdapter extends ArrayAdapter {
} else {
viewHolder.binding.tglAccountStatus.setVisibility(View.GONE);
}
- viewHolder.binding.tglAccountStatus.setOnCheckedChangeListener((compoundButton, b) -> {
- if (b == isDisabled && activity instanceof OnTglAccountState) {
- ((OnTglAccountState) activity).onClickTglAccountState(account, b);
- }
- });
+ viewHolder.binding.tglAccountStatus.setOnCheckedChangeListener(
+ (compoundButton, b) -> {
+ if (b == isDisabled && activity instanceof OnTglAccountState) {
+ ((OnTglAccountState) activity).onClickTglAccountState(account, b);
+ }
+ });
if (activity.xmppConnectionService != null && activity.xmppConnectionService.getAccounts().size() > 1) {
viewHolder.binding.frame.setBackgroundColor(account.getColor(activity.isDark()));
}
@@ -108,10 +120,7 @@ public class AccountAdapter extends ArrayAdapter {
}
}
-
-
public interface OnTglAccountState {
void onClickTglAccountState(Account account, boolean state);
}
-
}
diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java
index b085cb964430dcb3c2a6b86231dbc02a7d3e096a..88f7636bfa612fecfe44661104fd717af37896e6 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/KnownHostsAdapter.java
@@ -3,14 +3,10 @@ package eu.siacs.conversations.ui.adapter;
import android.content.Context;
import android.widget.ArrayAdapter;
import android.widget.Filter;
-
import androidx.annotation.NonNull;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
-
import eu.siacs.conversations.Config;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -22,61 +18,66 @@ public class KnownHostsAdapter extends ArrayAdapter {
private static final Pattern E164_PATTERN = Pattern.compile("^\\+[1-9]\\d{1,14}$");
private List domains;
- private final Filter domainFilter = new Filter() {
+ private final Filter domainFilter =
+ new Filter() {
- @Override
- protected FilterResults performFiltering(final CharSequence constraint) {
- final ImmutableList.Builder builder = new ImmutableList.Builder<>();
- final String[] split = constraint == null ? new String[0] : constraint.toString().split("@");
- if (split.length == 1) {
- final String local = split[0].toLowerCase(Locale.ENGLISH);
- if (Config.QUICKSY_DOMAIN != null && E164_PATTERN.matcher(local).matches()) {
- builder.add(local + '@' + Config.QUICKSY_DOMAIN.toEscapedString());
- } else {
- for (String domain : domains) {
- builder.add(local + '@' + domain);
- }
- }
- } else if (split.length == 2) {
- final String localPart = split[0].toLowerCase(Locale.ENGLISH);
- final String domainPart = split[1].toLowerCase(Locale.ENGLISH);
- if (domains.contains(domainPart)) {
- return new FilterResults();
- }
- for (final String domain : domains) {
- if (domain.contains(domainPart)) {
- builder.add(localPart + "@" + domain);
+ @Override
+ protected FilterResults performFiltering(final CharSequence constraint) {
+ final ImmutableList.Builder builder = new ImmutableList.Builder<>();
+ final String[] split =
+ constraint == null ? new String[0] : constraint.toString().split("@");
+ if (split.length == 1) {
+ final String local = split[0].toLowerCase(Locale.ENGLISH);
+ if (Config.QUICKSY_DOMAIN != null
+ && E164_PATTERN.matcher(local).matches()) {
+ builder.add(local + '@' + Config.QUICKSY_DOMAIN.toString());
+ } else {
+ for (String domain : domains) {
+ builder.add(local + '@' + domain);
+ }
+ }
+ } else if (split.length == 2) {
+ final String localPart = split[0].toLowerCase(Locale.ENGLISH);
+ final String domainPart = split[1].toLowerCase(Locale.ENGLISH);
+ if (domains.contains(domainPart)) {
+ return new FilterResults();
+ }
+ for (final String domain : domains) {
+ if (domain.contains(domainPart)) {
+ builder.add(localPart + "@" + domain);
+ }
+ }
+ } else {
+ return new FilterResults();
}
+ final var suggestions = builder.build();
+ final FilterResults filterResults = new FilterResults();
+ filterResults.values = suggestions;
+ filterResults.count = suggestions.size();
+ return filterResults;
}
- } else {
- return new FilterResults();
- }
- final var suggestions = builder.build();
- final FilterResults filterResults = new FilterResults();
- filterResults.values = suggestions;
- filterResults.count = suggestions.size();
- return filterResults;
- }
- @Override
- protected void publishResults(final CharSequence constraint, final FilterResults results) {
- final ImmutableList.Builder suggestions = new ImmutableList.Builder<>();
- if (results.values instanceof Collection> collection) {
- for(final Object item : collection) {
- if (item instanceof String string) {
- suggestions.add(string);
+ @Override
+ protected void publishResults(
+ final CharSequence constraint, final FilterResults results) {
+ final ImmutableList.Builder suggestions = new ImmutableList.Builder<>();
+ if (results.values instanceof Collection> collection) {
+ for (final Object item : collection) {
+ if (item instanceof String string) {
+ suggestions.add(string);
+ }
+ }
}
+ clear();
+ addAll(suggestions.build());
+ notifyDataSetChanged();
}
- }
- clear();
- addAll(suggestions.build());
- notifyDataSetChanged();
- }
- };
+ };
- public KnownHostsAdapter(final Context context, final int viewResourceId, final Collection knownHosts) {
+ public KnownHostsAdapter(
+ final Context context, final int viewResourceId, final Collection knownHosts) {
super(context, viewResourceId, new ArrayList<>());
- domains = Ordering.natural().sortedCopy(knownHosts);
+ domains = Ordering.natural().sortedCopy(knownHosts);
}
public KnownHostsAdapter(final Context context, final int viewResourceId) {
diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java
index 79cf215b56f85744a4ed918f1551bb607dbd83e3..e88ba5d3da16de7d4ef65334135d531295d39278 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java
@@ -10,17 +10,14 @@ import android.os.AsyncTask;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.ImageView;
-
import androidx.annotation.DimenRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.core.widget.ImageViewCompat;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
-
import com.google.android.material.color.MaterialColors;
import com.google.common.base.Strings;
-
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ItemMediaBinding;
import eu.siacs.conversations.ui.XmppActivity;
@@ -45,6 +42,21 @@ public class MediaAdapter extends RecyclerView.Adapter SPREAD_SHEET_MIMES =
+ Arrays.asList(
+ "text/comma-separated-values",
+ "application/vnd.ms-excel",
+ "application/vnd.stardivision.calc",
+ "application/vnd.oasis.opendocument.spreadsheet",
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+
+ public static final List SLIDE_SHOW_MIMES =
+ Arrays.asList(
+ "application/vnd.ms-powerpoint",
+ "application/vnd.stardivision.impress",
+ "application/vnd.oasis.opendocument.presentation",
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+ "application/vnd.openxmlformats-officedocument.presentationml.slideshow");
private static final List ARCHIVE_MIMES =
Arrays.asList(
@@ -112,6 +124,10 @@ public class MediaAdapter extends RecyclerView.Adapter {
- if (newValue instanceof String string) {
- if (Strings.isNullOrEmpty(string) || isJidInvalid(string) || isHttpUri(string)) {
- Toast.makeText(requireActivity(),R.string.invalid_jid,Toast.LENGTH_LONG).show();
- return false;
- } else {
- return true;
- }
- } else {
- Toast.makeText(requireActivity(),R.string.invalid_jid,Toast.LENGTH_LONG).show();
- return false;
- }
- });
+ pushServer.setOnPreferenceChangeListener(
+ (preference, newValue) -> {
+ if (newValue instanceof String string) {
+ if (Strings.isNullOrEmpty(string)
+ || isJidInvalid(string)
+ || isHttpUri(string)) {
+ Toast.makeText(
+ requireActivity(),
+ R.string.invalid_jid,
+ Toast.LENGTH_LONG)
+ .show();
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ Toast.makeText(requireActivity(), R.string.invalid_jid, Toast.LENGTH_LONG)
+ .show();
+ return false;
+ }
+ });
reconfigureUpAccountPreference(upAccounts);
}
private static boolean isJidInvalid(final String input) {
try {
- final var jid = Jid.ofEscaped(input);
+ final var jid = Jid.ofUserInput(input);
return !jid.isBareJid();
} catch (final IllegalArgumentException e) {
return true;
@@ -67,16 +72,15 @@ public class UpSettingsFragment extends XmppPreferenceFragment {
} catch (final URISyntaxException e) {
return false;
}
- return Arrays.asList("http","https").contains(uri.getScheme());
+ return Arrays.asList("http", "https").contains(uri.getScheme());
}
-
private void reconfigureUpAccountPreference(final ListPreference listPreference) {
final List accounts =
ImmutableList.copyOf(
Lists.transform(
requireService().getAccounts(),
- a -> a.getJid().asBareJid().toEscapedString()));
+ a -> a.getJid().asBareJid().toString()));
final ImmutableList.Builder entries = new ImmutableList.Builder<>();
final ImmutableList.Builder entryValues = new ImmutableList.Builder<>();
entries.add(getString(R.string.no_account_deactivated));
diff --git a/src/main/java/eu/siacs/conversations/ui/service/AudioPlayer.java b/src/main/java/eu/siacs/conversations/ui/service/AudioPlayer.java
index 95f4a54eeeebf325fac4776e1e3f35fb7ba1e11f..2be7ccfba01f80206146caf6b94c0436dde92c72 100644
--- a/src/main/java/eu/siacs/conversations/ui/service/AudioPlayer.java
+++ b/src/main/java/eu/siacs/conversations/ui/service/AudioPlayer.java
@@ -14,16 +14,13 @@ import android.os.Handler;
import android.os.PowerManager;
import android.util.Log;
import android.view.View;
-import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
-
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
-
+import com.google.android.material.button.MaterialButton;
import com.google.common.primitives.Ints;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Message;
@@ -33,7 +30,6 @@ import eu.siacs.conversations.ui.adapter.MessageAdapter;
import eu.siacs.conversations.ui.util.PendingItem;
import eu.siacs.conversations.utils.TimeFrameUtils;
import eu.siacs.conversations.utils.WeakReferenceSet;
-
import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -54,7 +50,8 @@ public class AudioPlayer
private final WeakReferenceSet audioPlayerLayouts = new WeakReferenceSet<>();
private final SensorManager sensorManager;
private final Sensor proximitySensor;
- private final PendingItem> pendingOnClickView = new PendingItem<>();
+ private final PendingItem> pendingOnClickView =
+ new PendingItem<>();
private final ExecutorService executor = Executors.newSingleThreadExecutor();
@@ -81,7 +78,7 @@ public class AudioPlayer
}
private static String formatTime(final int ms) {
- return TimeFrameUtils.formatElapsedTime(ms,false);
+ return TimeFrameUtils.formatElapsedTime(ms, false);
}
private void initializeProximityWakeLock(Context context) {
@@ -124,20 +121,17 @@ public class AudioPlayer
final Context context = viewHolder.playPause.getContext();
if (message == currentlyPlayingMessage) {
if (AudioPlayer.player != null && AudioPlayer.player.isPlaying()) {
- viewHolder.playPause.setImageResource(R.drawable.ic_pause_24dp);
- MessageAdapter.setImageTint(viewHolder.playPause, viewHolder.bubbleColor);
+ viewHolder.playPause.setIconResource(R.drawable.ic_pause_24dp);
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(R.drawable.ic_play_arrow_24dp);
- MessageAdapter.setImageTint(viewHolder.playPause, viewHolder.bubbleColor);
+ viewHolder.playPause.setIconResource(R.drawable.ic_play_arrow_24dp);
viewHolder.progress.setEnabled(false);
}
return true;
} else {
- viewHolder.playPause.setImageResource(R.drawable.ic_play_arrow_24dp);
- MessageAdapter.setImageTint(viewHolder.playPause, viewHolder.bubbleColor);
+ viewHolder.playPause.setIconResource(R.drawable.ic_play_arrow_24dp);
viewHolder.playPause.setContentDescription(context.getString(R.string.play_audio));
viewHolder.runtime.setText(formatTime(message.getFileParams().runtime));
viewHolder.progress.setProgress(0);
@@ -150,12 +144,12 @@ public class AudioPlayer
public synchronized void onClick(View v) {
if (v.getId() == R.id.play_pause) {
synchronized (LOCK) {
- startStop((ImageButton) v);
+ startStop((MaterialButton) v);
}
}
}
- private void startStop(ImageButton playPause) {
+ private void startStop(final MaterialButton playPause) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
&& ContextCompat.checkSelfPermission(
messageAdapter.getActivity(),
@@ -186,8 +180,7 @@ public class AudioPlayer
player.pause();
messageAdapter.flagScreenOff();
releaseProximityWakeLock();
- viewHolder.playPause.setImageResource(R.drawable.ic_play_arrow_24dp);
- MessageAdapter.setImageTint(viewHolder.playPause, viewHolder.bubbleColor);
+ viewHolder.playPause.setIconResource(R.drawable.ic_play_arrow_24dp);
viewHolder.playPause.setContentDescription(context.getString(R.string.play_audio));
} else {
viewHolder.progress.setEnabled(true);
@@ -195,8 +188,7 @@ public class AudioPlayer
messageAdapter.flagScreenOn();
acquireProximityWakeLock();
this.stopRefresher(true);
- viewHolder.playPause.setImageResource(R.drawable.ic_pause_24dp);
- MessageAdapter.setImageTint(viewHolder.playPause, viewHolder.bubbleColor);
+ viewHolder.playPause.setIconResource(R.drawable.ic_pause_24dp);
viewHolder.playPause.setContentDescription(context.getString(R.string.pause_audio));
}
return false;
@@ -222,8 +214,7 @@ public class AudioPlayer
messageAdapter.flagScreenOn();
acquireProximityWakeLock();
viewHolder.progress.setEnabled(true);
- viewHolder.playPause.setImageResource(R.drawable.ic_pause_24dp);
- MessageAdapter.setImageTint(viewHolder.playPause, viewHolder.bubbleColor);
+ viewHolder.playPause.setIconResource(R.drawable.ic_pause_24dp);
viewHolder.playPause.setContentDescription(
viewHolder.playPause.getContext().getString(R.string.pause_audio));
sensorManager.registerListener(
@@ -239,9 +230,9 @@ public class AudioPlayer
}
public void startStopPending() {
- WeakReference reference = pendingOnClickView.pop();
+ final var reference = pendingOnClickView.pop();
if (reference != null) {
- ImageButton imageButton = reference.get();
+ var imageButton = reference.get();
if (imageButton != null) {
startStop(imageButton);
}
@@ -283,8 +274,7 @@ public class AudioPlayer
final Message message = (Message) audioPlayer.getTag();
viewHolder.playPause.setContentDescription(
viewHolder.playPause.getContext().getString(R.string.play_audio));
- viewHolder.playPause.setImageResource(R.drawable.ic_play_arrow_24dp);
- MessageAdapter.setImageTint(viewHolder.playPause, viewHolder.bubbleColor);
+ viewHolder.playPause.setIconResource(R.drawable.ic_play_arrow_24dp);
if (message != null) {
viewHolder.runtime.setText(formatTime(message.getFileParams().runtime));
}
@@ -309,7 +299,8 @@ public class AudioPlayer
}
@Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ public void onProgressChanged(
+ final SeekBar seekBar, final int progress, final boolean fromUser) {
synchronized (AudioPlayer.LOCK) {
final RelativeLayout audioPlayer = (RelativeLayout) seekBar.getParent();
final Message message = (Message) audioPlayer.getTag();
@@ -462,7 +453,7 @@ public class AudioPlayer
public static class ViewHolder {
private TextView runtime;
private SeekBar progress;
- private ImageButton playPause;
+ private MaterialButton playPause;
private MessageAdapter.BubbleColor bubbleColor = MessageAdapter.BubbleColor.SURFACE;
public static ViewHolder get(final RelativeLayout audioPlayer) {
diff --git a/src/main/java/eu/siacs/conversations/utils/AccountUtils.java b/src/main/java/eu/siacs/conversations/utils/AccountUtils.java
index 4b2c2957f62aaa1e1a2e6e814312a4bb7b136843..bcfffe8c18b294cd03725e98452c584e85e1d45c 100644
--- a/src/main/java/eu/siacs/conversations/utils/AccountUtils.java
+++ b/src/main/java/eu/siacs/conversations/utils/AccountUtils.java
@@ -5,20 +5,16 @@ import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
-
import com.google.common.primitives.Bytes;
import com.google.common.primitives.Longs;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.XmppActivity;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
public class AccountUtils {
@@ -50,9 +46,7 @@ public class AccountUtils {
public static UUID createUuid4(long mostSigBits, long leastSigBits) {
final byte[] bytes =
- Bytes.concat(
- Longs.toByteArray(mostSigBits),
- Longs.toByteArray(leastSigBits));
+ Bytes.concat(Longs.toByteArray(mostSigBits), Longs.toByteArray(leastSigBits));
bytes[6] &= 0x0f; /* clear version */
bytes[6] |= 0x40; /* set to version 4 */
bytes[8] &= 0x3f; /* clear variant */
@@ -65,7 +59,7 @@ public class AccountUtils {
final ArrayList accounts = new ArrayList<>();
for (final Account account : service.getAccounts()) {
if (account.isEnabled()) {
- accounts.add(account.getJid().asBareJid().toEscapedString());
+ accounts.add(account.getJid().asBareJid().toString());
}
}
return accounts;
diff --git a/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java b/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java
index 404140084136a7c265d1cdb045e639234314ce55..c134a470e4d5116db3ed5629ff77419d7538abd7 100644
--- a/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java
+++ b/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java
@@ -1,13 +1,11 @@
package eu.siacs.conversations.utils;
import androidx.annotation.NonNull;
-
+import eu.siacs.conversations.xmpp.Jid;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
-import eu.siacs.conversations.xmpp.Jid;
-
public class BackupFileHeader {
private static final int VERSION = 1;
@@ -18,17 +16,22 @@ public class BackupFileHeader {
private final byte[] iv;
private final byte[] salt;
-
@NonNull
@Override
public String toString() {
- return "BackupFileHeader{" +
- "app='" + app + '\'' +
- ", jid=" + jid +
- ", timestamp=" + timestamp +
- ", iv=" + CryptoHelper.bytesToHex(iv) +
- ", salt=" + CryptoHelper.bytesToHex(salt) +
- '}';
+ return "BackupFileHeader{"
+ + "app='"
+ + app
+ + '\''
+ + ", jid="
+ + jid
+ + ", timestamp="
+ + timestamp
+ + ", iv="
+ + CryptoHelper.bytesToHex(iv)
+ + ", salt="
+ + CryptoHelper.bytesToHex(salt)
+ + '}';
}
public BackupFileHeader(String app, Jid jid, long timestamp, byte[] iv, byte[] salt) {
@@ -42,7 +45,7 @@ public class BackupFileHeader {
public void write(DataOutputStream dataOutputStream) throws IOException {
dataOutputStream.writeInt(VERSION);
dataOutputStream.writeUTF(app);
- dataOutputStream.writeUTF(jid.asBareJid().toEscapedString());
+ dataOutputStream.writeUTF(jid.asBareJid().toString());
dataOutputStream.writeLong(timestamp);
dataOutputStream.write(iv);
dataOutputStream.write(salt);
@@ -61,10 +64,13 @@ public class BackupFileHeader {
throw new OutdatedBackupFileVersion();
}
if (version != VERSION) {
- throw new IllegalArgumentException("Backup File version was " + version + " but app only supports version " + VERSION);
+ throw new IllegalArgumentException(
+ "Backup File version was "
+ + version
+ + " but app only supports version "
+ + VERSION);
}
return new BackupFileHeader(app, Jid.of(jid), timestamp, iv, salt);
-
}
public byte[] getSalt() {
@@ -87,7 +93,5 @@ public class BackupFileHeader {
return timestamp;
}
- public static class OutdatedBackupFileVersion extends RuntimeException {
-
- }
+ public static class OutdatedBackupFileVersion extends RuntimeException {}
}
diff --git a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java
index 2a02d0ddfd77ada76b615f29f7c4b61cd7e4579c..91376ba0efccb2f74a92b4404c71d5ab8c0e48ee 100644
--- a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java
+++ b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java
@@ -5,7 +5,6 @@ import static eu.siacs.conversations.utils.Random.SECURE_RANDOM;
import android.os.Bundle;
import android.util.Base64;
import android.util.Pair;
-
import androidx.annotation.StringRes;
import org.bouncycastle.asn1.x500.X500Name;
@@ -15,6 +14,11 @@ import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import java.io.InputStream;
import java.io.IOException;
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.xmpp.Jid;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -42,13 +46,15 @@ import eu.siacs.conversations.xmpp.Jid;
public final class CryptoHelper {
- public static final Pattern UUID_PATTERN = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}");
- final public static byte[] ONE = new byte[]{0, 0, 0, 1};
- private static final char[] CHARS = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789+-/#$!?".toCharArray();
+ public static final Pattern UUID_PATTERN =
+ Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}");
+ public static final byte[] ONE = new byte[] {0, 0, 0, 1};
+ private static final char[] CHARS =
+ "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789+-/#$!?".toCharArray();
private static final int PW_LENGTH = 25;
private static final char[] VOWELS = "aeiou".toCharArray();
private static final char[] CONSONANTS = "bcfghjklmnpqrstvwxyz".toCharArray();
- private final static char[] hexArray = "0123456789abcdef".toCharArray();
+ private static final char[] hexArray = "0123456789abcdef".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
@@ -73,7 +79,10 @@ public final class CryptoHelper {
char[] output = new char[rand * 2 + (5 - rand)];
boolean vowel = SECURE_RANDOM.nextBoolean();
for (int i = 0; i < output.length; ++i) {
- output[i] = vowel ? VOWELS[SECURE_RANDOM.nextInt(VOWELS.length)] : CONSONANTS[SECURE_RANDOM.nextInt(CONSONANTS.length)];
+ output[i] =
+ vowel
+ ? VOWELS[SECURE_RANDOM.nextInt(VOWELS.length)]
+ : CONSONANTS[SECURE_RANDOM.nextInt(CONSONANTS.length)];
vowel = !vowel;
}
return String.valueOf(output);
@@ -83,8 +92,10 @@ public final class CryptoHelper {
int len = hexString.length();
byte[] array = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
- array[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
- .digit(hexString.charAt(i + 1), 16));
+ array[i / 2] =
+ (byte)
+ ((Character.digit(hexString.charAt(i), 16) << 4)
+ + Character.digit(hexString.charAt(i + 1), 16));
}
return array;
}
@@ -100,9 +111,7 @@ public final class CryptoHelper {
return result;
}
- /**
- * Escapes usernames or passwords for SASL.
- */
+ /** Escapes usernames or passwords for SASL. */
public static String saslEscape(final String s) {
final StringBuilder sb = new StringBuilder((int) (s.length() * 1.1));
for (int i = 0; i < s.length(); i++) {
@@ -154,7 +163,8 @@ public final class CryptoHelper {
}
public static String[] getOrderedCipherSuites(final String[] platformSupportedCipherSuites) {
- final Collection cipherSuites = new LinkedHashSet<>(Arrays.asList(Config.ENABLED_CIPHERS));
+ final Collection cipherSuites =
+ new LinkedHashSet<>(Arrays.asList(Config.ENABLED_CIPHERS));
final List platformCiphers = Arrays.asList(platformSupportedCipherSuites);
cipherSuites.retainAll(platformCiphers);
cipherSuites.addAll(platformCiphers);
@@ -177,7 +187,10 @@ public final class CryptoHelper {
}
}
- public static Pair extractJidAndName(X509Certificate certificate) throws CertificateEncodingException, IllegalArgumentException, CertificateParsingException {
+ public static Pair extractJidAndName(X509Certificate certificate)
+ throws CertificateEncodingException,
+ IllegalArgumentException,
+ CertificateParsingException {
Collection> alternativeNames = certificate.getSubjectAlternativeNames();
List emails = new ArrayList<>();
if (alternativeNames != null) {
@@ -190,9 +203,15 @@ public final class CryptoHelper {
}
X500Name x500name = new JcaX509CertificateHolder(certificate).getSubject();
if (emails.size() == 0 && x500name.getRDNs(BCStyle.EmailAddress).length > 0) {
- emails.add(IETFUtils.valueToString(x500name.getRDNs(BCStyle.EmailAddress)[0].getFirst().getValue()));
+ emails.add(
+ IETFUtils.valueToString(
+ x500name.getRDNs(BCStyle.EmailAddress)[0].getFirst().getValue()));
}
- String name = x500name.getRDNs(BCStyle.CN).length > 0 ? IETFUtils.valueToString(x500name.getRDNs(BCStyle.CN)[0].getFirst().getValue()) : null;
+ String name =
+ x500name.getRDNs(BCStyle.CN).length > 0
+ ? IETFUtils.valueToString(
+ x500name.getRDNs(BCStyle.CN)[0].getFirst().getValue())
+ : null;
if (emails.size() >= 1) {
return new Pair<>(Jid.of(emails.get(0)), name);
} else if (name != null) {
@@ -214,26 +233,33 @@ public final class CryptoHelper {
JcaX509CertificateHolder holder = new JcaX509CertificateHolder(certificate);
X500Name subject = holder.getSubject();
try {
- information.putString("subject_cn", subject.getRDNs(BCStyle.CN)[0].getFirst().getValue().toString());
+ information.putString(
+ "subject_cn",
+ subject.getRDNs(BCStyle.CN)[0].getFirst().getValue().toString());
} catch (Exception e) {
- //ignored
+ // ignored
}
try {
- information.putString("subject_o", subject.getRDNs(BCStyle.O)[0].getFirst().getValue().toString());
+ information.putString(
+ "subject_o",
+ subject.getRDNs(BCStyle.O)[0].getFirst().getValue().toString());
} catch (Exception e) {
- //ignored
+ // ignored
}
X500Name issuer = holder.getIssuer();
try {
- information.putString("issuer_cn", issuer.getRDNs(BCStyle.CN)[0].getFirst().getValue().toString());
+ information.putString(
+ "issuer_cn",
+ issuer.getRDNs(BCStyle.CN)[0].getFirst().getValue().toString());
} catch (Exception e) {
- //ignored
+ // ignored
}
try {
- information.putString("issuer_o", issuer.getRDNs(BCStyle.O)[0].getFirst().getValue().toString());
+ information.putString(
+ "issuer_o", issuer.getRDNs(BCStyle.O)[0].getFirst().getValue().toString());
} catch (Exception e) {
- //ignored
+ // ignored
}
try {
information.putString("sha1", getFingerprintCert(certificate.getEncoded()));
@@ -253,7 +279,7 @@ public final class CryptoHelper {
}
public static String getFingerprint(Jid jid, String androidId) {
- return getFingerprint(jid.toEscapedString() + "\00" + androidId);
+ return getFingerprint(jid.toString() + "\00" + androidId);
}
public static String getAccountFingerprint(Account account, String androidId) {
@@ -273,8 +299,9 @@ public final class CryptoHelper {
return switch (encryption) {
case Message.ENCRYPTION_OTR -> R.string.encryption_choice_otr;
case Message.ENCRYPTION_AXOLOTL,
- Message.ENCRYPTION_AXOLOTL_NOT_FOR_THIS_DEVICE,
- Message.ENCRYPTION_AXOLOTL_FAILED -> R.string.encryption_choice_omemo;
+ Message.ENCRYPTION_AXOLOTL_NOT_FOR_THIS_DEVICE,
+ Message.ENCRYPTION_AXOLOTL_FAILED ->
+ R.string.encryption_choice_omemo;
case Message.ENCRYPTION_PGP -> R.string.encryption_choice_pgp;
default -> R.string.encryption_choice_unencrypted;
};
@@ -285,7 +312,9 @@ public final class CryptoHelper {
return false;
}
final String u = url.toLowerCase();
- return !u.contains(" ") && (u.startsWith("https://") || u.startsWith("http://") || u.startsWith("p1s3://")) && u.endsWith(".pgp");
+ return !u.contains(" ")
+ && (u.startsWith("https://") || u.startsWith("http://") || u.startsWith("p1s3://"))
+ && u.endsWith(".pgp");
}
public static String multihashAlgo(Multihash.Type type) throws NoSuchAlgorithmException {
diff --git a/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java b/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java
index 970ae046d99da128c23da424c9b3f1278d7f5b17..9dcdbb15e11cfb90154392a20409d814d61de376 100644
--- a/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java
+++ b/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java
@@ -37,11 +37,9 @@ import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.util.LruCache;
-
import androidx.annotation.ColorInt;
-
import com.google.android.material.color.MaterialColors;
-
+import eu.siacs.conversations.xmpp.Jid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -54,226 +52,234 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import eu.siacs.conversations.R;
-import eu.siacs.conversations.xmpp.Jid;
-
public class IrregularUnicodeDetector {
- private static final Map NORMALIZATION_MAP;
- private static final LruCache CACHE = new LruCache<>(4096);
- private static final List AMBIGUOUS_CYRILLIC = Arrays.asList("а","г","е","ѕ","і","ј","ķ","ԛ","о","р","с","у","х");
-
- static {
- Map temp = new HashMap<>();
- temp.put(Character.UnicodeBlock.LATIN_1_SUPPLEMENT, Character.UnicodeBlock.BASIC_LATIN);
- NORMALIZATION_MAP = Collections.unmodifiableMap(temp);
- }
+ private static final Map NORMALIZATION_MAP;
+ private static final LruCache CACHE = new LruCache<>(4096);
+ private static final List AMBIGUOUS_CYRILLIC =
+ Arrays.asList("а", "г", "е", "ѕ", "і", "ј", "ķ", "ԛ", "о", "р", "с", "у", "х");
- private static Character.UnicodeBlock normalize(Character.UnicodeBlock in) {
- if (NORMALIZATION_MAP.containsKey(in)) {
- return NORMALIZATION_MAP.get(in);
- } else {
- return in;
- }
- }
+ static {
+ Map temp = new HashMap<>();
+ temp.put(Character.UnicodeBlock.LATIN_1_SUPPLEMENT, Character.UnicodeBlock.BASIC_LATIN);
+ NORMALIZATION_MAP = Collections.unmodifiableMap(temp);
+ }
- public static Spannable style(final Context context, Jid jid) {
- return style(jid, MaterialColors.getColor(context, com.google.android.material.R.attr.colorError,"colorError not found"));
- }
+ private static Character.UnicodeBlock normalize(Character.UnicodeBlock in) {
+ if (NORMALIZATION_MAP.containsKey(in)) {
+ return NORMALIZATION_MAP.get(in);
+ } else {
+ return in;
+ }
+ }
- private static Spannable style(Jid jid, @ColorInt int color) {
- PatternTuple patternTuple = find(jid);
- SpannableStringBuilder builder = new SpannableStringBuilder();
- if (jid.getEscapedLocal() != null && patternTuple.local != null) {
- SpannableString local = new SpannableString(jid.getEscapedLocal());
- colorize(local, patternTuple.local, color);
- builder.append(local);
- builder.append('@');
- }
- if (jid.getDomain() != null) {
- String[] labels = jid.getDomain().toEscapedString().split("\\.");
- for (int i = 0; i < labels.length; ++i) {
- SpannableString spannableString = new SpannableString(labels[i]);
- if (patternTuple.domain.size() > i) {
- colorize(spannableString, patternTuple.domain.get(i), color);
- }
- if (i != 0) {
- builder.append('.');
- }
- builder.append(spannableString);
- }
- }
- if (builder.length() != 0 && jid.getResource() != null) {
- builder.append('/');
- builder.append(jid.getResource());
- }
- return builder;
- }
+ public static Spannable style(final Context context, Jid jid) {
+ return style(
+ jid,
+ MaterialColors.getColor(
+ context,
+ com.google.android.material.R.attr.colorError,
+ "colorError not found"));
+ }
- private static void colorize(SpannableString spannableString, Pattern pattern, @ColorInt int color) {
- Matcher matcher = pattern.matcher(spannableString);
- while (matcher.find()) {
- if (matcher.start() < matcher.end()) {
- spannableString.setSpan(new ForegroundColorSpan(color), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
+ private static Spannable style(Jid jid, @ColorInt int color) {
+ PatternTuple patternTuple = find(jid);
+ SpannableStringBuilder builder = new SpannableStringBuilder();
+ if (jid.getLocal() != null && patternTuple.local != null) {
+ SpannableString local = new SpannableString(jid.getLocal());
+ colorize(local, patternTuple.local, color);
+ builder.append(local);
+ builder.append('@');
+ }
+ if (jid.getDomain() != null) {
+ String[] labels = jid.getDomain().toString().split("\\.");
+ for (int i = 0; i < labels.length; ++i) {
+ SpannableString spannableString = new SpannableString(labels[i]);
+ colorize(spannableString, patternTuple.domain.get(i), color);
+ if (i != 0) {
+ builder.append('.');
+ }
+ builder.append(spannableString);
+ }
+ }
+ if (builder.length() != 0 && jid.getResource() != null) {
+ builder.append('/');
+ builder.append(jid.getResource());
+ }
+ return builder;
+ }
- private static Map> mapCompat(String word) {
- Map> map = new HashMap<>();
- final int length = word.length();
- for (int offset = 0; offset < length; ) {
- final int codePoint = word.codePointAt(offset);
- offset += Character.charCount(codePoint);
- if (!Character.isLetter(codePoint)) {
- continue;
- }
- Character.UnicodeBlock block = normalize(Character.UnicodeBlock.of(codePoint));
- List codePoints;
- if (map.containsKey(block)) {
- codePoints = map.get(block);
- } else {
- codePoints = new ArrayList<>();
- map.put(block, codePoints);
- }
- codePoints.add(String.copyValueOf(Character.toChars(codePoint)));
- }
- return map;
- }
+ private static void colorize(
+ SpannableString spannableString, Pattern pattern, @ColorInt int color) {
+ Matcher matcher = pattern.matcher(spannableString);
+ while (matcher.find()) {
+ if (matcher.start() < matcher.end()) {
+ spannableString.setSpan(
+ new ForegroundColorSpan(color),
+ matcher.start(),
+ matcher.end(),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+ }
- @TargetApi(Build.VERSION_CODES.N)
- private static Map> map(String word) {
- Map> map = new HashMap<>();
- final int length = word.length();
- for (int offset = 0; offset < length; ) {
- final int codePoint = word.codePointAt(offset);
- Character.UnicodeScript script = Character.UnicodeScript.of(codePoint);
- if (script != Character.UnicodeScript.COMMON) {
- List codePoints;
- if (map.containsKey(script)) {
- codePoints = map.get(script);
- } else {
- codePoints = new ArrayList<>();
- map.put(script, codePoints);
- }
- codePoints.add(String.copyValueOf(Character.toChars(codePoint)));
- }
- offset += Character.charCount(codePoint);
- }
- return map;
- }
+ private static Map> mapCompat(String word) {
+ Map> map = new HashMap<>();
+ final int length = word.length();
+ for (int offset = 0; offset < length; ) {
+ final int codePoint = word.codePointAt(offset);
+ offset += Character.charCount(codePoint);
+ if (!Character.isLetter(codePoint)) {
+ continue;
+ }
+ Character.UnicodeBlock block = normalize(Character.UnicodeBlock.of(codePoint));
+ List codePoints;
+ if (map.containsKey(block)) {
+ codePoints = map.get(block);
+ } else {
+ codePoints = new ArrayList<>();
+ map.put(block, codePoints);
+ }
+ codePoints.add(String.copyValueOf(Character.toChars(codePoint)));
+ }
+ return map;
+ }
- private static Set eliminateFirstAndGetCodePointsCompat(Map> map) {
- return eliminateFirstAndGetCodePoints(map, Character.UnicodeBlock.BASIC_LATIN);
- }
+ @TargetApi(Build.VERSION_CODES.N)
+ private static Map> map(String word) {
+ Map> map = new HashMap<>();
+ final int length = word.length();
+ for (int offset = 0; offset < length; ) {
+ final int codePoint = word.codePointAt(offset);
+ Character.UnicodeScript script = Character.UnicodeScript.of(codePoint);
+ if (script != Character.UnicodeScript.COMMON) {
+ List codePoints;
+ if (map.containsKey(script)) {
+ codePoints = map.get(script);
+ } else {
+ codePoints = new ArrayList<>();
+ map.put(script, codePoints);
+ }
+ codePoints.add(String.copyValueOf(Character.toChars(codePoint)));
+ }
+ offset += Character.charCount(codePoint);
+ }
+ return map;
+ }
- @TargetApi(Build.VERSION_CODES.N)
- private static Set eliminateFirstAndGetCodePoints(Map> map) {
- return eliminateFirstAndGetCodePoints(map, Character.UnicodeScript.COMMON);
- }
+ private static Set eliminateFirstAndGetCodePointsCompat(
+ Map> map) {
+ return eliminateFirstAndGetCodePoints(map, Character.UnicodeBlock.BASIC_LATIN);
+ }
- private static Set eliminateFirstAndGetCodePoints(Map> map, T defaultPick) {
- T pick = defaultPick;
- int size = 0;
- for (Map.Entry> entry : map.entrySet()) {
- if (entry.getValue().size() > size) {
- size = entry.getValue().size();
- pick = entry.getKey();
- }
- }
- map.remove(pick);
- Set all = new HashSet<>();
- for (List codePoints : map.values()) {
- all.addAll(codePoints);
- }
- return all;
- }
+ @TargetApi(Build.VERSION_CODES.N)
+ private static Set eliminateFirstAndGetCodePoints(
+ Map> map) {
+ return eliminateFirstAndGetCodePoints(map, Character.UnicodeScript.COMMON);
+ }
- private static Set findIrregularCodePoints(String word) {
- Set codePoints;
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
- final Map> map = mapCompat(word);
- final Set set = asSet(map);
- if (containsOnlyAmbiguousCyrillic(set)) {
- return set;
- }
- codePoints = eliminateFirstAndGetCodePointsCompat(map);
- } else {
- final Map> map = map(word);
- final Set set = asSet(map);
- if (containsOnlyAmbiguousCyrillic(set)) {
- return set;
- }
- codePoints = eliminateFirstAndGetCodePoints(map);
- }
- return codePoints;
- }
+ private static Set eliminateFirstAndGetCodePoints(
+ Map> map, T defaultPick) {
+ T pick = defaultPick;
+ int size = 0;
+ for (Map.Entry