aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.gradle1
-rw-r--r--src/main/java/de/pixart/messenger/Config.java4
-rw-r--r--src/main/java/de/pixart/messenger/android/AbstractPhoneContact.java39
-rw-r--r--src/main/java/de/pixart/messenger/android/JabberIdContact.java73
-rw-r--r--src/main/java/de/pixart/messenger/entities/Account.java8
-rw-r--r--src/main/java/de/pixart/messenger/entities/Bookmark.java12
-rw-r--r--src/main/java/de/pixart/messenger/entities/Contact.java61
-rw-r--r--src/main/java/de/pixart/messenger/entities/Conversation.java4
-rw-r--r--src/main/java/de/pixart/messenger/entities/Message.java4
-rw-r--r--src/main/java/de/pixart/messenger/entities/MucOptions.java34
-rw-r--r--src/main/java/de/pixart/messenger/entities/Roster.java14
-rw-r--r--src/main/java/de/pixart/messenger/generator/AbstractGenerator.java2
-rw-r--r--src/main/java/de/pixart/messenger/generator/IqGenerator.java11
-rw-r--r--src/main/java/de/pixart/messenger/parser/MessageParser.java59
-rw-r--r--src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java16
-rw-r--r--src/main/java/de/pixart/messenger/services/AbstractQuickConversationsService.java26
-rw-r--r--src/main/java/de/pixart/messenger/services/AvatarService.java27
-rw-r--r--src/main/java/de/pixart/messenger/services/EventReceiver.java4
-rw-r--r--src/main/java/de/pixart/messenger/services/NotificationService.java34
-rw-r--r--src/main/java/de/pixart/messenger/services/QuickConversationsService.java28
-rw-r--r--src/main/java/de/pixart/messenger/services/ShortcutService.java2
-rw-r--r--src/main/java/de/pixart/messenger/services/XmppConnectionService.java169
-rw-r--r--src/main/java/de/pixart/messenger/ui/ChooseContactActivity.java2
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java15
-rw-r--r--src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java2
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConversationFragment.java53
-rw-r--r--src/main/java/de/pixart/messenger/ui/EditAccountActivity.java56
-rw-r--r--src/main/java/de/pixart/messenger/ui/ShortcutActivity.java2
-rw-r--r--src/main/java/de/pixart/messenger/ui/StartConversationActivity.java34
-rw-r--r--src/main/java/de/pixart/messenger/ui/TimePreference.java45
-rw-r--r--src/main/java/de/pixart/messenger/ui/XmppActivity.java9
-rw-r--r--src/main/java/de/pixart/messenger/ui/widget/TextInputEditText.java47
-rw-r--r--src/main/java/de/pixart/messenger/utils/Compatibility.java2
-rw-r--r--src/main/java/de/pixart/messenger/utils/Namespace.java2
-rw-r--r--src/main/java/de/pixart/messenger/utils/PhoneHelper.java67
-rw-r--r--src/main/java/de/pixart/messenger/utils/ReplacingSerialSingleThreadExecutor.java12
-rw-r--r--src/main/java/de/pixart/messenger/utils/ReplacingTaskManager.java2
-rw-r--r--src/main/java/de/pixart/messenger/utils/Resolver.java7
-rw-r--r--src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java8
-rw-r--r--src/main/res/layout/activity_change_password.xml4
-rw-r--r--src/main/res/layout/activity_edit_account.xml7
-rw-r--r--src/main/res/menu/block.xml3
-rw-r--r--src/main/res/values-de/strings.xml1
-rw-r--r--src/main/res/values-fil/strings.xml2
-rw-r--r--src/main/res/values-ru/strings.xml1
-rw-r--r--src/main/res/values/attrs.xml1
-rw-r--r--src/main/res/values/defaults.xml1
-rw-r--r--src/main/res/values/strings.xml4
-rw-r--r--src/main/res/values/themes.xml2
-rw-r--r--src/standardPush/java/de/pixart/messenger/services/InstanceIdService.java15
-rw-r--r--src/standardPush/java/de/pixart/messenger/services/MaintenanceReceiver.java11
-rw-r--r--src/standardPush/java/de/pixart/messenger/services/PushMessageReceiver.java19
52 files changed, 679 insertions, 389 deletions
diff --git a/build.gradle b/build.gradle
index 1393b25e2..914b8b69d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -81,6 +81,7 @@ dependencies {
implementation 'org.hsluv:hsluv:0.2'
implementation 'org.conscrypt:conscrypt-android:1.3.0'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15'
+ implementation 'me.drakeet.support:toastcompat:1.1.0'
}
ext {
diff --git a/src/main/java/de/pixart/messenger/Config.java b/src/main/java/de/pixart/messenger/Config.java
index 5181b24b1..68ab52590 100644
--- a/src/main/java/de/pixart/messenger/Config.java
+++ b/src/main/java/de/pixart/messenger/Config.java
@@ -18,7 +18,6 @@ public final class Config {
private static final int OMEMO = 8;
private static final int ENCRYPTION_MASK = UNENCRYPTED | OPENPGP | OTR | OMEMO;
-
public static boolean supportUnencrypted() {
return (ENCRYPTION_MASK & UNENCRYPTED) != 0;
}
@@ -39,6 +38,7 @@ public final class Config {
return (ENCRYPTION_MASK & (ENCRYPTION_MASK - 1)) != 0;
}
+
public static final String LOGTAG = "Pix-Art_Messenger";
public static final Jid BUG_REPORTS = Jid.of("bugs@pix-art.de");
@@ -52,6 +52,7 @@ public final class Config {
public static final Integer[] XMPP_Ports = null; //BuildConfig.XMPP_Ports; // set to null means disable
public static final String DOMAIN_LOCK = null; //BuildConfig.DOMAIN_LOCK; //only allow account creation for this domain
public static final String MAGIC_CREATE_DOMAIN = "blabber.im";
+ public static final String QUICKSY_DOMAIN = "quicksy.im";
public static final boolean DISALLOW_REGISTRATION_IN_UI = false; //hide the register checkbox
public static final boolean USE_RANDOM_RESOURCE_ON_EVERY_BIND = false;
@@ -59,6 +60,7 @@ public final class Config {
public static final boolean ALLOW_NON_TLS_CONNECTIONS = false; //very dangerous. you should have a good reason to set this to true
public static final boolean FORCE_ORBOT = false; // always use TOR
+
public static final boolean HIDE_MESSAGE_TEXT_IN_NOTIFICATION = false;
public static final boolean SHOW_CONNECTED_ACCOUNTS = false; //show number of connected accounts in foreground notification
diff --git a/src/main/java/de/pixart/messenger/android/AbstractPhoneContact.java b/src/main/java/de/pixart/messenger/android/AbstractPhoneContact.java
new file mode 100644
index 000000000..32dbfa77e
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/android/AbstractPhoneContact.java
@@ -0,0 +1,39 @@
+package de.pixart.messenger.android;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.text.TextUtils;
+
+public abstract class AbstractPhoneContact {
+
+ private final Uri lookupUri;
+ private final String displayName;
+ private final String photoUri;
+
+
+ AbstractPhoneContact(Cursor cursor) {
+ int phoneId = cursor.getInt(cursor.getColumnIndex(ContactsContract.Data._ID));
+ String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.LOOKUP_KEY));
+ this.lookupUri = ContactsContract.Contacts.getLookupUri(phoneId, lookupKey);
+ this.displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
+ this.photoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.PHOTO_URI));
+ }
+
+ public Uri getLookupUri() {
+ return lookupUri;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public String getPhotoUri() {
+ return photoUri;
+ }
+
+
+ public int rating() {
+ return (TextUtils.isEmpty(displayName) ? 0 : 2) + (TextUtils.isEmpty(photoUri) ? 0 : 1);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/android/JabberIdContact.java b/src/main/java/de/pixart/messenger/android/JabberIdContact.java
new file mode 100644
index 000000000..bfafb54c9
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/android/JabberIdContact.java
@@ -0,0 +1,73 @@
+package de.pixart.messenger.android;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.os.Build;
+import android.provider.ContactsContract;
+import android.util.Log;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import de.pixart.messenger.Config;
+import rocks.xmpp.addr.Jid;
+
+public class JabberIdContact extends AbstractPhoneContact {
+
+ private final Jid jid;
+
+ private JabberIdContact(Cursor cursor) throws IllegalArgumentException {
+ super(cursor);
+ try {
+ this.jid = Jid.of(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)));
+ } catch (IllegalArgumentException | NullPointerException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public Jid getJid() {
+ return jid;
+ }
+
+ public static Map<Jid, JabberIdContact> load(Context context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
+ return Collections.emptyMap();
+ }
+ final String[] PROJECTION = new String[]{ContactsContract.Data._ID,
+ ContactsContract.Data.DISPLAY_NAME,
+ ContactsContract.Data.PHOTO_URI,
+ ContactsContract.Data.LOOKUP_KEY,
+ ContactsContract.CommonDataKinds.Im.DATA};
+
+ final String SELECTION = "(" + ContactsContract.Data.MIMETYPE + "=\""
+ + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE
+ + "\") AND (" + ContactsContract.CommonDataKinds.Im.PROTOCOL
+ + "=\"" + ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER
+ + "\")";
+ final Cursor cursor;
+ try {
+ cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, null, null);
+ } catch (Exception e) {
+ return Collections.emptyMap();
+ }
+ final HashMap<Jid, JabberIdContact> contacts = new HashMap<>();
+ while (cursor != null && cursor.moveToNext()) {
+ try {
+ final JabberIdContact contact = new JabberIdContact(cursor);
+ final JabberIdContact preexisting = contacts.put(contact.getJid(), contact);
+ if (preexisting == null || preexisting.rating() < contact.rating()) {
+ contacts.put(contact.getJid(), contact);
+ }
+ } catch (IllegalArgumentException e) {
+ Log.d(Config.LOGTAG,"unable to create jabber id contact");
+ }
+ }
+ if (cursor != null) {
+ cursor.close();
+ }
+ return contacts;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/entities/Account.java b/src/main/java/de/pixart/messenger/entities/Account.java
index 9e3711535..1bdd130d5 100644
--- a/src/main/java/de/pixart/messenger/entities/Account.java
+++ b/src/main/java/de/pixart/messenger/entities/Account.java
@@ -73,6 +73,7 @@ public class Account extends AbstractEntity {
protected String password;
protected int options = 0;
protected State status = State.OFFLINE;
+ private State lastErrorStatus = State.OFFLINE;
protected String resource;
protected String avatar;
protected String hostname = null;
@@ -271,8 +272,15 @@ public class Account extends AbstractEntity {
}
}
+ public State getLastErrorStatus() {
+ return this.lastErrorStatus;
+ }
+
public void setStatus(final State status) {
this.status = status;
+ if (status.isError || status == State.ONLINE) {
+ this.lastErrorStatus = status;
+ }
}
public State getTrueStatus() {
diff --git a/src/main/java/de/pixart/messenger/entities/Bookmark.java b/src/main/java/de/pixart/messenger/entities/Bookmark.java
index fc7725bb5..e670673dd 100644
--- a/src/main/java/de/pixart/messenger/entities/Bookmark.java
+++ b/src/main/java/de/pixart/messenger/entities/Bookmark.java
@@ -87,6 +87,11 @@ public class Bookmark extends Element implements ListItem {
return this.jid;
}
+ public Jid getFullJid() {
+ final String nick = getNick();
+ return jid == null || nick == null || nick.trim().isEmpty() ? jid : jid.withResource(nick);
+ }
+
@Override
public List<Tag> getTags(Context context) {
ArrayList<Tag> tags = new ArrayList<>();
@@ -160,7 +165,12 @@ public class Bookmark extends Element implements ListItem {
if (this.conversation != null) {
this.conversation.clear();
}
- this.conversation = new WeakReference<>(conversation);
+ if (conversation == null) {
+ this.conversation = null;
+ } else {
+ this.conversation = new WeakReference<>(conversation);
+ conversation.getMucOptions().notifyOfBookmarkNick(getNick());
+ }
}
public String getBookmarkName() {
diff --git a/src/main/java/de/pixart/messenger/entities/Contact.java b/src/main/java/de/pixart/messenger/entities/Contact.java
index a74b09dff..1df6e120a 100644
--- a/src/main/java/de/pixart/messenger/entities/Contact.java
+++ b/src/main/java/de/pixart/messenger/entities/Contact.java
@@ -20,6 +20,7 @@ import java.util.Locale;
import de.pixart.messenger.Config;
import de.pixart.messenger.R;
+import de.pixart.messenger.android.AbstractPhoneContact;
import de.pixart.messenger.utils.JidHelper;
import de.pixart.messenger.utils.UIHelper;
import de.pixart.messenger.xml.Element;
@@ -48,7 +49,7 @@ public class Contact implements ListItem, Blockable {
private String commonName;
protected Jid jid;
private int subscription = 0;
- private String systemAccount;
+ private Uri systemAccount;
private String photoUri;
private final JSONObject keys;
private JSONArray groups = new JSONArray();
@@ -62,7 +63,7 @@ public class Contact implements ListItem, Blockable {
public Contact(final String account, final String systemName, final String serverName,
final Jid jid, final int subscription, final String photoUri,
- final String systemAccount, final String keys, final String avatar, final long lastseen,
+ final Uri systemAccount, final String keys, final String avatar, final long lastseen,
final String presence, final String groups) {
this.accountUuid = account;
this.systemName = systemName;
@@ -105,13 +106,19 @@ public class Contact implements ListItem, Blockable {
// TODO: Borked DB... handle this somehow?
return null;
}
+ Uri systemAccount;
+ try {
+ systemAccount = Uri.parse(cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)));
+ } catch (Exception e) {
+ systemAccount = null;
+ }
return new Contact(cursor.getString(cursor.getColumnIndex(ACCOUNT)),
cursor.getString(cursor.getColumnIndex(SYSTEMNAME)),
cursor.getString(cursor.getColumnIndex(SERVERNAME)),
jid,
cursor.getInt(cursor.getColumnIndex(OPTIONS)),
cursor.getString(cursor.getColumnIndex(PHOTOURI)),
- cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)),
+ systemAccount,
cursor.getString(cursor.getColumnIndex(KEYS)),
cursor.getString(cursor.getColumnIndex(AVATAR)),
cursor.getLong(cursor.getColumnIndex(LAST_TIME)),
@@ -159,9 +166,6 @@ public class Contact implements ListItem, Blockable {
if (isBlocked()) {
tags.add(new Tag(context.getString(R.string.blocked), 0xff2e2f3b, 0));
}
- if (showInPhoneBook()) {
- tags.add(new Tag(context.getString(R.string.phone_book), 0xFF1E88E5, 0));
- }
return tags;
}
@@ -203,7 +207,7 @@ public class Contact implements ListItem, Blockable {
values.put(SERVERNAME, serverName);
values.put(JID, jid.toString());
values.put(OPTIONS, subscription);
- values.put(SYSTEMACCOUNT, systemAccount);
+ values.put(SYSTEMACCOUNT, systemAccount != null ? systemAccount.toString() : null);
values.put(PHOTOURI, photoUri);
values.put(KEYS, keys.toString());
values.put(AVATAR, avatar == null ? null : avatar.getFilename());
@@ -277,21 +281,11 @@ public class Contact implements ListItem, Blockable {
}
public Uri getSystemAccount() {
- if (systemAccount == null) {
- return null;
- } else {
- String[] parts = systemAccount.split("#");
- if (parts.length != 2) {
- return null;
- } else {
- long id = Long.parseLong(parts[0]);
- return ContactsContract.Contacts.getLookupUri(id, parts[1]);
- }
- }
+ return systemAccount;
}
- public void setSystemAccount(String account) {
- this.systemAccount = account;
+ public void setSystemAccount(Uri lookupUri) {
+ this.systemAccount = lookupUri;
}
private Collection<String> getGroups(final boolean unique) {
@@ -390,8 +384,8 @@ public class Contact implements ListItem, Blockable {
|| (this.getOption(Contact.Options.DIRTY_PUSH));
}
- public boolean showInPhoneBook() {
- return systemAccount != null && !systemAccount.trim().isEmpty();
+ public boolean showInContactList() {
+ return showInRoster() || getOption(Options.SYNCED_VIA_OTHER);
}
public void parseSubscriptionFromElement(Element item) {
@@ -583,6 +577,27 @@ public class Contact implements ListItem, Blockable {
return serverName;
}
+ public synchronized boolean setPhoneContact(AbstractPhoneContact phoneContact) {
+ setOption(getOption(phoneContact.getClass()));
+ setSystemAccount(phoneContact.getLookupUri());
+ boolean changed = setSystemName(phoneContact.getDisplayName());
+ changed |= setPhotoUri(phoneContact.getPhotoUri());
+ return changed;
+ }
+ public synchronized boolean unsetPhoneContact(Class<?extends AbstractPhoneContact> clazz) {
+ resetOption(getOption(clazz));
+ boolean changed = false;
+ if (!getOption(Options.SYNCED_VIA_ADDRESSBOOK) && !getOption(Options.SYNCED_VIA_OTHER)) {
+ setSystemAccount(null);
+ changed |= setPhotoUri(null);
+ changed |= setSystemName(null);
+ }
+ return changed;
+ }
+ public static int getOption(Class<? extends AbstractPhoneContact> clazz) {
+ return Options.SYNCED_VIA_OTHER;
+ }
+
public final class Options {
public static final int TO = 0;
public static final int FROM = 1;
@@ -592,5 +607,7 @@ public class Contact implements ListItem, Blockable {
public static final int PENDING_SUBSCRIPTION_REQUEST = 5;
public static final int DIRTY_PUSH = 6;
public static final int DIRTY_DELETE = 7;
+ private static final int SYNCED_VIA_ADDRESSBOOK = 8;
+ public static final int SYNCED_VIA_OTHER = 9;
}
}
diff --git a/src/main/java/de/pixart/messenger/entities/Conversation.java b/src/main/java/de/pixart/messenger/entities/Conversation.java
index db6006ca3..1fa1c7a2d 100644
--- a/src/main/java/de/pixart/messenger/entities/Conversation.java
+++ b/src/main/java/de/pixart/messenger/entities/Conversation.java
@@ -1147,9 +1147,9 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
final Contact contact = getContact();
return mode == MODE_SINGLE
&& !contact.isOwnServer()
- && !contact.showInRoster()
+ && !contact.showInContactList()
&& !contact.isSelf()
- && !contact.showInPhoneBook()
+ && !Config.QUICKSY_DOMAIN.equals(contact.getJid().toEscapedString())
&& sentMessagesCount() == 0;
}
diff --git a/src/main/java/de/pixart/messenger/entities/Message.java b/src/main/java/de/pixart/messenger/entities/Message.java
index 14d235553..6d11d54d3 100644
--- a/src/main/java/de/pixart/messenger/entities/Message.java
+++ b/src/main/java/de/pixart/messenger/entities/Message.java
@@ -295,7 +295,7 @@ public class Message extends AbstractEntity {
return null;
} else {
return this.conversation.getAccount().getRoster()
- .getContactFromRoster(this.trueCounterpart);
+ .getContactFromContactList(this.trueCounterpart);
}
}
}
@@ -673,7 +673,7 @@ public class Message extends AbstractEntity {
public boolean trusted() {
Contact contact = this.getContact();
- return status > STATUS_RECEIVED || (contact != null && (contact.showInRoster() || contact.isSelf()));
+ return status > STATUS_RECEIVED || (contact != null && (contact.showInContactList() || contact.isSelf()));
}
public boolean fixCounterpart() {
diff --git a/src/main/java/de/pixart/messenger/entities/MucOptions.java b/src/main/java/de/pixart/messenger/entities/MucOptions.java
index ec7770d77..01ad8816e 100644
--- a/src/main/java/de/pixart/messenger/entities/MucOptions.java
+++ b/src/main/java/de/pixart/messenger/entities/MucOptions.java
@@ -3,6 +3,7 @@ package de.pixart.messenger.entities;
import android.annotation.SuppressLint;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.text.TextUtils;
import java.util.ArrayList;
import java.util.Collections;
@@ -43,6 +44,7 @@ public class MucOptions {
private Error error = Error.NONE;
private User self;
private String password = null;
+ private boolean tookProposedNickFromBookmark = false;
public MucOptions(Conversation conversation) {
this.account = conversation.getAccount();
this.conversation = conversation;
@@ -95,6 +97,16 @@ public class MucOptions {
}
}
+ public boolean isTookProposedNickFromBookmark() {
+ return tookProposedNickFromBookmark;
+ }
+
+ void notifyOfBookmarkNick(String nick) {
+ if (nick != null && nick.trim().equals(getSelf().getFullJid().getResource())) {
+ this.tookProposedNickFromBookmark = true;
+ }
+ }
+
public boolean mamSupport() {
return MessageArchiveService.Version.has(getFeatures());
}
@@ -374,15 +386,21 @@ public class MucOptions {
}
}
- public String getProposedNick() {
- if (conversation.getBookmark() != null
- && conversation.getBookmark().getNick() != null
- && !conversation.getBookmark().getNick().trim().isEmpty()) {
- return conversation.getBookmark().getNick().trim();
+ private String getProposedNick() {
+ final Bookmark bookmark = this.conversation.getBookmark();
+ final String bookmarkedNick = bookmark == null ? null : bookmark.getNick();
+ if (bookmarkedNick != null && !bookmarkedNick.trim().isEmpty()) {
+ this.tookProposedNickFromBookmark = true;
+ return bookmarkedNick.trim();
} else if (!conversation.getJid().isBareJid()) {
return conversation.getJid().getResource();
} else {
- return JidHelper.localPartOrFallback(account.getJid());
+ final String displayName = account.getDisplayName();
+ if (TextUtils.isEmpty(displayName)) {
+ return JidHelper.localPartOrFallback(account.getJid());
+ } else {
+ return displayName;
+ }
}
}
@@ -563,7 +581,7 @@ public class MucOptions {
ArrayList<Jid> members = new ArrayList<>();
synchronized (users) {
for (User user : users) {
- if (user.affiliation.ranks(Affiliation.MEMBER) && user.realJid != null && (!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);
}
}
@@ -730,7 +748,7 @@ public class MucOptions {
public Contact getContact() {
if (fullJid != null) {
- return getAccount().getRoster().getContactFromRoster(realJid);
+ return getAccount().getRoster().getContactFromContactList(realJid);
} else if (realJid != null) {
return getAccount().getRoster().getContact(realJid);
} else {
diff --git a/src/main/java/de/pixart/messenger/entities/Roster.java b/src/main/java/de/pixart/messenger/entities/Roster.java
index 2db0c796e..13856c068 100644
--- a/src/main/java/de/pixart/messenger/entities/Roster.java
+++ b/src/main/java/de/pixart/messenger/entities/Roster.java
@@ -5,24 +5,25 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import de.pixart.messenger.android.AbstractPhoneContact;
import rocks.xmpp.addr.Jid;
public class Roster {
- final Account account;
- final HashMap<Jid, Contact> contacts = new HashMap<>();
+ private final Account account;
+ private final HashMap<Jid, Contact> contacts = new HashMap<>();
private String version = null;
public Roster(Account account) {
this.account = account;
}
- public Contact getContactFromRoster(Jid jid) {
+ public Contact getContactFromContactList(Jid jid) {
if (jid == null) {
return null;
}
synchronized (this.contacts) {
Contact contact = contacts.get(jid.asBareJid());
- if (contact != null && contact.showInRoster()) {
+ if (contact != null && contact.showInContactList()) {
return contact;
} else {
return null;
@@ -54,11 +55,12 @@ public class Roster {
}
}
- public List<Contact> getWithSystemAccounts() {
+ public List<Contact> getWithSystemAccounts(Class<?extends AbstractPhoneContact> clazz) {
+ int option = Contact.getOption(clazz);
List<Contact> with = getContacts();
for (Iterator<Contact> iterator = with.iterator(); iterator.hasNext(); ) {
Contact contact = iterator.next();
- if (contact.getSystemAccount() == null) {
+ if (!contact.getOption(option)) {
iterator.remove();
}
}
diff --git a/src/main/java/de/pixart/messenger/generator/AbstractGenerator.java b/src/main/java/de/pixart/messenger/generator/AbstractGenerator.java
index ac57c74d1..710a4fb8e 100644
--- a/src/main/java/de/pixart/messenger/generator/AbstractGenerator.java
+++ b/src/main/java/de/pixart/messenger/generator/AbstractGenerator.java
@@ -35,7 +35,7 @@ public abstract class AbstractGenerator {
"http://jabber.org/protocol/caps",
"http://jabber.org/protocol/disco#info",
"urn:xmpp:avatar:metadata+notify",
- "http://jabber.org/protocol/nick+notify",
+ Namespace.NICK + "+notify",
Namespace.BOOKMARKS + "+notify",
"urn:xmpp:ping",
"jabber:iq:version",
diff --git a/src/main/java/de/pixart/messenger/generator/IqGenerator.java b/src/main/java/de/pixart/messenger/generator/IqGenerator.java
index 86f58af69..cb56d66a8 100644
--- a/src/main/java/de/pixart/messenger/generator/IqGenerator.java
+++ b/src/main/java/de/pixart/messenger/generator/IqGenerator.java
@@ -126,8 +126,15 @@ public class IqGenerator extends AbstractGenerator {
public IqPacket publishNick(String nick) {
final Element item = new Element("item");
- item.addChild("nick", "http://jabber.org/protocol/nick").setContent(nick);
- return publish("http://jabber.org/protocol/nick", item);
+ item.addChild("nick", Namespace.NICK).setContent(nick);
+ return publish(Namespace.NICK, item);
+ }
+
+ public IqPacket deleteNode(String node) {
+ IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
+ final Element pubsub = packet.addChild("pubsub", Namespace.PUBSUB_OWNER);
+ pubsub.addChild("delete").setAttribute("node", node);
+ return packet;
}
public IqPacket publishAvatar(Avatar avatar) {
diff --git a/src/main/java/de/pixart/messenger/parser/MessageParser.java b/src/main/java/de/pixart/messenger/parser/MessageParser.java
index dca999069..ed12d6473 100644
--- a/src/main/java/de/pixart/messenger/parser/MessageParser.java
+++ b/src/main/java/de/pixart/messenger/parser/MessageParser.java
@@ -286,16 +286,11 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
mXmppConnectionService.fetchAvatar(account, avatar);
}
}
- } else if ("http://jabber.org/protocol/nick".equals(node)) {
+ } else if (Namespace.NICK.equals(node)) {
final Element i = items.findChild("item");
final String nick = i == null ? null : i.findChildContent("nick", Namespace.NICK);
if (nick != null) {
- Contact contact = account.getRoster().getContact(from);
- if (contact.setPresenceName(nick)) {
- mXmppConnectionService.getAvatarService().clear(contact);
- }
- mXmppConnectionService.updateConversationUi();
- mXmppConnectionService.updateAccountUi();
+ setNick(account, from, nick);
}
} else if (AxolotlService.PEP_DEVICE_LIST.equals(node)) {
Element item = items.findChild("item");
@@ -313,6 +308,31 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
}
}
+ private void parseDeleteEvent(final Element event, final Jid from, final Account account) {
+ final Element delete = event.findChild("delete");
+ if (delete == null) {
+ return;
+ }
+ String node = delete.getAttribute("node");
+ if (Namespace.NICK.equals(node)) {
+ Log.d(Config.LOGTAG, "parsing nick delete event from " + from);
+ setNick(account, from, null);
+ }
+ }
+
+ private void setNick(Account account, Jid user, String nick) {
+ if (user.asBareJid().equals(account.getJid().asBareJid())) {
+ account.setDisplayName(nick);
+ } else {
+ Contact contact = account.getRoster().getContact(user);
+ if (contact.setPresenceName(nick)) {
+ mXmppConnectionService.getAvatarService().clear(contact);
+ }
+ }
+ mXmppConnectionService.updateConversationUi();
+ mXmppConnectionService.updateAccountUi();
+ }
+
private boolean handleErrorMessage(Account account, MessagePacket packet) {
if (packet.getType() == MessagePacket.TYPE_ERROR) {
Jid from = packet.getFrom();
@@ -784,7 +804,9 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
}
} else if ("item".equals(child.getName())) {
MucOptions.User user = AbstractParser.parseItem(conversation, child);
- Log.d(Config.LOGTAG, account.getJid() + ": changing affiliation for " + user.getRealJid() + " to " + user.getAffiliation() + " in " + conversation.getJid().asBareJid());
+ Log.d(Config.LOGTAG, account.getJid() + ": changing affiliation for "
+ + user.getRealJid() + " to " + user.getAffiliation() + " in "
+ + conversation.getJid().asBareJid());
if (!user.realJidMatchesAccount()) {
boolean isNew = conversation.getMucOptions().updateUser(user);
mXmppConnectionService.getAvatarService().clear(conversation);
@@ -850,17 +872,6 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
if (message.addReadByMarker(readByMarker)) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": added read by (" + readByMarker.getRealJid() + ") to message '" + message.getBody() + "'");
mXmppConnectionService.updateMessage(message, false);
- final Message displayedMessage = mXmppConnectionService.markMessage(account, from.asBareJid(), id, Message.STATUS_SEND_DISPLAYED);
- Message m = displayedMessage == null ? null : displayedMessage.prev();
- while (m != null
- && m.getStatus() == Message.STATUS_SEND_RECEIVED
- && m.getTimeSent() < displayedMessage.getTimeSent()) {
- mXmppConnectionService.markMessage(m, Message.STATUS_SEND_DISPLAYED);
- m = m.prev();
- }
- if (displayedMessage != null && selfAddressed) {
- dismissNotification(account, counterpart, query);
- }
}
}
}
@@ -881,9 +892,13 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
}
}
- Element event = original.findChild("event", "http://jabber.org/protocol/pubsub#event");
+ final Element event = original.findChild("event", "http://jabber.org/protocol/pubsub#event");
if (event != null && InvalidJid.hasValidFrom(original)) {
- parseEvent(event, original.getFrom(), account);
+ if (event.hasChild("items")) {
+ parseEvent(event, original.getFrom(), account);
+ } else if (event.hasChild("delete")) {
+ parseDeleteEvent(event, original.getFrom(), account);
+ }
}
final String nick = packet.findChildContent("nick", Namespace.NICK);
@@ -958,4 +973,4 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
return false;
}
}
-}
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java b/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java
index 7b316af70..d148ba0f9 100644
--- a/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java
+++ b/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java
@@ -664,17 +664,23 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.insert(RESOLVER_RESULTS_TABLENAME, null, contentValues);
}
- public Resolver.Result findResolverResult(String domain) {
+ public synchronized Resolver.Result findResolverResult(String domain) {
SQLiteDatabase db = this.getReadableDatabase();
String where = Resolver.Result.DOMAIN + "=?";
String[] whereArgs = {domain};
final Cursor cursor = db.query(RESOLVER_RESULTS_TABLENAME, null, where, whereArgs, null, null, null);
Resolver.Result result = null;
if (cursor != null) {
- if (cursor.moveToFirst()) {
- result = Resolver.Result.fromCursor(cursor);
+ try {
+ if (cursor.moveToFirst()) {
+ result = Resolver.Result.fromCursor(cursor);
+ }
+ } catch (Exception e) {
+ Log.d(Config.LOGTAG, "unable to find cached resolver result in database " + e.getMessage());
+ return null;
+ } finally {
+ cursor.close();
}
- cursor.close();
}
return result;
}
@@ -928,7 +934,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
final SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
for (Contact contact : roster.getContacts()) {
- if (contact.getOption(Contact.Options.IN_ROSTER) || contact.getAvatarFilename() != null) {
+ if (contact.getOption(Contact.Options.IN_ROSTER) || contact.getAvatarFilename() != null || contact.getOption(Contact.Options.SYNCED_VIA_OTHER)) {
db.insert(Contact.TABLENAME, null, contact.getContentValues());
} else {
String where = Contact.ACCOUNT + "=? AND " + Contact.JID + "=?";
diff --git a/src/main/java/de/pixart/messenger/services/AbstractQuickConversationsService.java b/src/main/java/de/pixart/messenger/services/AbstractQuickConversationsService.java
new file mode 100644
index 000000000..f5647bd60
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/services/AbstractQuickConversationsService.java
@@ -0,0 +1,26 @@
+package de.pixart.messenger.services;
+
+public abstract class AbstractQuickConversationsService {
+
+ protected final XmppConnectionService service;
+
+ public AbstractQuickConversationsService(XmppConnectionService service) {
+ this.service = service;
+ }
+
+ public abstract void considerSync();
+
+ public static boolean isQuicksy() {
+ return false;
+ }
+
+ public static boolean isConversations() {
+ return true;
+ }
+
+ public abstract void signalAccountStateChange();
+
+ public abstract boolean isSynchronizing();
+
+ public abstract void considerSyncBackground(boolean force);
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/services/AvatarService.java b/src/main/java/de/pixart/messenger/services/AvatarService.java
index aa861c147..bd157f442 100644
--- a/src/main/java/de/pixart/messenger/services/AvatarService.java
+++ b/src/main/java/de/pixart/messenger/services/AvatarService.java
@@ -12,6 +12,7 @@ import android.graphics.RectF;
import android.graphics.Typeface;
import android.net.Uri;
import android.support.annotation.Nullable;
+import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.LruCache;
@@ -80,7 +81,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
if (avatar != null || cachedOnly) {
return avatar;
}
- if (avatar == null && contact.getAvatarFilename() != null) {
+ if (contact.getAvatarFilename() != null) {
avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatarFilename(), size);
}
if (avatar == null && contact.getProfilePhoto() != null) {
@@ -91,7 +92,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
}
}
if (avatar == null) {
- avatar = get(contact.getDisplayName(), contact.getJid().asBareJid().toString(), size, cachedOnly);
+ avatar = get(contact.getDisplayName(), contact.getJid().asBareJid().toString(), size, false);
}
this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
return avatar;
@@ -165,10 +166,10 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
if (avatar == null) {
Contact contact = user.getContact();
if (contact != null) {
- avatar = get(contact, size, cachedOnly);
+ avatar = get(contact, size, false);
} else {
String seed = user.getRealJid() != null ? user.getRealJid().asBareJid().toString() : null;
- avatar = get(user.getName(), seed, size, cachedOnly);
+ avatar = get(user.getName(), seed, size, false);
}
}
this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
@@ -235,7 +236,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
if (bookmark.getConversation() != null) {
return get(bookmark.getConversation(), size, cachedOnly);
} else {
- Jid jid = bookmark.getJid();
+ final Jid jid = bookmark.getFullJid();
Account account = bookmark.getAccount();
Contact contact = jid == null ? null : account.getRoster().getContact(jid);
if (contact != null && contact.getAvatarFilename() != null) {
@@ -406,7 +407,8 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
}
avatar = mXmppConnectionService.getFileBackend().getAvatar(account.getAvatar(), size);
if (avatar == null) {
- avatar = get(account.getJid().asBareJid().toString(), null, size, false);
+ final String jid = account.getJid().asBareJid().toEscapedString();
+ avatar = get(jid, null, size, false);
}
mXmppConnectionService.getBitmapCache().put(KEY, avatar);
return avatar;
@@ -474,7 +476,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
}
public Bitmap get(final String name, String seed, final int size, boolean cachedOnly) {
- final String KEY = key(seed == null ? name : seed, size);
+ final String KEY = key(seed == null ? name : name + "\0" + seed, size);
Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY);
if (bitmap != null || cachedOnly) {
return bitmap;
@@ -524,11 +526,14 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
Contact contact = user.getContact();
if (contact != null) {
Uri uri = null;
- if (contact.getProfilePhoto() != null) {
+ if (contact.getAvatarFilename() != null) {
+ try {
+ uri = mXmppConnectionService.getFileBackend().getAvatarUri(contact.getAvatarFilename());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else if (contact.getProfilePhoto() != null) {
uri = Uri.parse(contact.getProfilePhoto());
- } else if (contact.getAvatarFilename() != null) {
- uri = mXmppConnectionService.getFileBackend().getAvatarUri(
- contact.getAvatarFilename());
}
if (drawTile(canvas, uri, left, top, right, bottom)) {
return true;
diff --git a/src/main/java/de/pixart/messenger/services/EventReceiver.java b/src/main/java/de/pixart/messenger/services/EventReceiver.java
index a77db569e..03bf68ed9 100644
--- a/src/main/java/de/pixart/messenger/services/EventReceiver.java
+++ b/src/main/java/de/pixart/messenger/services/EventReceiver.java
@@ -13,6 +13,7 @@ import de.pixart.messenger.utils.Compatibility;
public class EventReceiver extends BroadcastReceiver {
public static final String SETTING_ENABLED_ACCOUNTS = "enabled_accounts";
+ public static final String EXTRA_NEEDS_FOREGROUND_SERVICE = "needs_foreground_service";
@Override
public void onReceive(final Context context, final Intent originalIntent) {
@@ -26,6 +27,7 @@ public class EventReceiver extends BroadcastReceiver {
if (action.equals("ui") || hasEnabledAccounts(context)) {
try {
if (Compatibility.runsAndTargetsTwentySix(context)) {
+ intentForService.putExtra(EXTRA_NEEDS_FOREGROUND_SERVICE, true);
ContextCompat.startForegroundService(context, intentForService);
} else {
context.startService(intentForService);
@@ -42,4 +44,4 @@ public class EventReceiver extends BroadcastReceiver {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTING_ENABLED_ACCOUNTS, true);
}
-}
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/services/NotificationService.java b/src/main/java/de/pixart/messenger/services/NotificationService.java
index 053685fc6..6e93145b8 100644
--- a/src/main/java/de/pixart/messenger/services/NotificationService.java
+++ b/src/main/java/de/pixart/messenger/services/NotificationService.java
@@ -209,9 +209,9 @@ public class NotificationService {
return false;
}
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mXmppConnectionService);
- final long startTime = preferences.getLong("quiet_hours_start", TimePreference.DEFAULT_VALUE) % Config.MILLISECONDS_IN_DAY;
- final long endTime = preferences.getLong("quiet_hours_end", TimePreference.DEFAULT_VALUE) % Config.MILLISECONDS_IN_DAY;
- final long nowTime = Calendar.getInstance().getTimeInMillis() % Config.MILLISECONDS_IN_DAY;
+ final long startTime = TimePreference.minutesToTimestamp(preferences.getLong("quiet_hours_start", TimePreference.DEFAULT_VALUE));
+ final long endTime = TimePreference.minutesToTimestamp(preferences.getLong("quiet_hours_end", TimePreference.DEFAULT_VALUE));
+ final long nowTime = Calendar.getInstance().getTimeInMillis();
if (endTime < startTime) {
return nowTime > startTime || nowTime < endTime;
@@ -238,7 +238,7 @@ public class NotificationService {
}
}
- public void pushFromDirectReply(final Message message) {
+ void pushFromDirectReply(final Message message) {
synchronized (notifications) {
pushToStack(message);
updateNotification(false);
@@ -264,8 +264,7 @@ public class NotificationService {
private List<String> getBacklogConversations(Account account) {
final List<String> conversations = new ArrayList<>();
- for (Iterator<Map.Entry<Conversation, AtomicInteger>> it = mBacklogMessageCounter.entrySet().iterator(); it.hasNext(); ) {
- Map.Entry<Conversation, AtomicInteger> entry = it.next();
+ for (Map.Entry<Conversation, AtomicInteger> entry : mBacklogMessageCounter.entrySet()) {
if (entry.getKey().getAccount() == account) {
conversations.add(entry.getKey().getUuid());
}
@@ -286,7 +285,7 @@ public class NotificationService {
return count;
}
- public void finishBacklog(boolean notify) {
+ void finishBacklog(boolean notify) {
finishBacklog(notify, null);
}
@@ -385,7 +384,7 @@ public class NotificationService {
updateNotification(notify, null, false);
}
- public void updateNotification(final boolean notify, final List<String> conversations) {
+ private void updateNotification(final boolean notify, final List<String> conversations) {
updateNotification(notify, conversations, false);
}
@@ -860,7 +859,7 @@ public class NotificationService {
return SystemClock.elapsedRealtime() < (this.mLastNotification + miniGrace);
}
- public Notification createForegroundNotification() {
+ Notification createForegroundNotification() {
final Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService);
mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.conversations_foreground_service));
if (Compatibility.runsAndTargetsTwentySix(mXmppConnectionService) || Config.SHOW_CONNECTED_ACCOUNTS) {
@@ -924,18 +923,19 @@ public class NotificationService {
return PendingIntent.getActivity(mXmppConnectionService, 0, new Intent(mXmppConnectionService, ConversationsActivity.class), 0);
}
- public void updateErrorNotification() {
+ void updateErrorNotification() {
if (Config.SUPPRESS_ERROR_NOTIFICATION) {
cancel(ERROR_NOTIFICATION_ID);
return;
}
+ final boolean showAllErrors = QuickConversationsService.isConversations();
final List<Account> errors = new ArrayList<>();
for (final Account account : mXmppConnectionService.getAccounts()) {
- if (account.hasErrorStatus() && account.showErrorNotification()) {
+ if (account.hasErrorStatus() && account.showErrorNotification() && (showAllErrors || account.getLastErrorStatus() == Account.State.UNAUTHORIZED)) {
errors.add(account);
}
}
- if (Compatibility.keepForegroundService(mXmppConnectionService)) {
+ if (mXmppConnectionService.foregroundNotificationNeedsUpdatingWhenErrorStateChanges()) {
notify(FOREGROUND_NOTIFICATION_ID, createForegroundNotification());
}
final Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService);
@@ -978,7 +978,7 @@ public class NotificationService {
notify(ERROR_NOTIFICATION_ID, mBuilder.build());
}
- public void updateFileAddingNotification(int current, Message message) {
+ void updateFileAddingNotification(int current, Message message) {
Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService);
mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.transcoding_video));
mBuilder.setProgress(100, current, false);
@@ -992,11 +992,11 @@ public class NotificationService {
notify(FOREGROUND_NOTIFICATION_ID, notification);
}
- public void dismissForcedForegroundNotification() {
+ void dismissForcedForegroundNotification() {
cancel(FOREGROUND_NOTIFICATION_ID);
}
- public Notification exportLogsNotification() {
+ Notification exportLogsNotification() {
Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService);
mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.app_name));
mBuilder.setContentText(mXmppConnectionService.getString(R.string.notification_export_logs_title));
@@ -1009,11 +1009,11 @@ public class NotificationService {
return mBuilder.build();
}
- public void exportLogsServiceNotification(Notification notification) {
+ void exportLogsServiceNotification(Notification notification) {
notify(FOREGROUND_NOTIFICATION_ID, notification);
}
- public Notification AppUpdateNotification(PendingIntent intent, String version, String filesize) {
+ Notification AppUpdateNotification(PendingIntent intent, String version, String filesize) {
Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService);
mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.app_name));
mBuilder.setContentText(mXmppConnectionService.getString(R.string.notification_export_logs_title));
diff --git a/src/main/java/de/pixart/messenger/services/QuickConversationsService.java b/src/main/java/de/pixart/messenger/services/QuickConversationsService.java
new file mode 100644
index 000000000..e268ac856
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/services/QuickConversationsService.java
@@ -0,0 +1,28 @@
+package de.pixart.messenger.services;
+
+public class QuickConversationsService extends AbstractQuickConversationsService {
+
+ QuickConversationsService(XmppConnectionService xmppConnectionService) {
+ super(xmppConnectionService);
+ }
+
+ @Override
+ public void considerSync() {
+
+ }
+
+ @Override
+ public void signalAccountStateChange() {
+
+ }
+
+ @Override
+ public boolean isSynchronizing() {
+ return false;
+ }
+
+ @Override
+ public void considerSyncBackground(boolean force) {
+
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/services/ShortcutService.java b/src/main/java/de/pixart/messenger/services/ShortcutService.java
index 0578a8ce5..8051c8849 100644
--- a/src/main/java/de/pixart/messenger/services/ShortcutService.java
+++ b/src/main/java/de/pixart/messenger/services/ShortcutService.java
@@ -24,7 +24,7 @@ import rocks.xmpp.addr.Jid;
public class ShortcutService {
private final XmppConnectionService xmppConnectionService;
- private final ReplacingSerialSingleThreadExecutor replacingSerialSingleThreadExecutor = new ReplacingSerialSingleThreadExecutor(false);
+ private final ReplacingSerialSingleThreadExecutor replacingSerialSingleThreadExecutor = new ReplacingSerialSingleThreadExecutor(ShortcutService.class.getSimpleName());
public ShortcutService(XmppConnectionService xmppConnectionService) {
this.xmppConnectionService = xmppConnectionService;
diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
index bb704c6b6..7c5d2b64d 100644
--- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
+++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
@@ -81,6 +81,7 @@ import java.util.concurrent.atomic.AtomicLong;
import de.pixart.messenger.BuildConfig;
import de.pixart.messenger.Config;
import de.pixart.messenger.R;
+import de.pixart.messenger.android.JabberIdContact;
import de.pixart.messenger.crypto.OmemoSetting;
import de.pixart.messenger.crypto.PgpDecryptionService;
import de.pixart.messenger.crypto.PgpEngine;
@@ -243,7 +244,7 @@ public class XmppConnectionService extends Service {
}
};
public HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager(this);
- private ReplacingSerialSingleThreadExecutor mContactMergerExecutor = new ReplacingSerialSingleThreadExecutor(true);
+ private ReplacingSerialSingleThreadExecutor mContactMergerExecutor = new ReplacingSerialSingleThreadExecutor("ContactMerger");
private long mLastActivity = 0;
private MemorizingTrustManager mMemorizingTrustManager;
private NotificationService mNotificationService = new NotificationService(this);
@@ -286,6 +287,7 @@ public class XmppConnectionService extends Service {
private AvatarService mAvatarService = new AvatarService(this);
private MessageArchiveService mMessageArchiveService = new MessageArchiveService(this);
private PushManagementService mPushManagementService = new PushManagementService(this);
+ private QuickConversationsService mQuickConversationsService = new QuickConversationsService(this);
private final OnBindListener mOnBindListener = new OnBindListener() {
@Override
@@ -298,13 +300,22 @@ public class XmppConnectionService extends Service {
}
}
}
- boolean needsUpdating = account.setOption(Account.OPTION_LOGGED_IN_SUCCESSFULLY, true);
- needsUpdating |= account.setOption(Account.OPTION_HTTP_UPLOAD_AVAILABLE, account.getXmppConnection().getFeatures().httpUpload(0));
- if (needsUpdating) {
+ boolean loggedInSuccessfully = account.setOption(Account.OPTION_LOGGED_IN_SUCCESSFULLY, true);
+ boolean gainedFeature = account.setOption(Account.OPTION_HTTP_UPLOAD_AVAILABLE, account.getXmppConnection().getFeatures().httpUpload(0));
+ if (loggedInSuccessfully || gainedFeature) {
databaseBackend.updateAccount(account);
}
+
+ if (loggedInSuccessfully) {
+ if (!TextUtils.isEmpty(account.getDisplayName())) {
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": display name wasn't empty on first log in. publishing");
+ publishDisplayName(account);
+ }
+ }
+
account.getRoster().clearPresences();
mJingleConnectionManager.cancelInTransmission();
+ mQuickConversationsService.considerSyncBackground(false);
fetchRosterFromServer(account);
if (!account.getXmppConnection().getFeatures().bookmarksConversion()) {
fetchBookmarks(account);
@@ -336,6 +347,9 @@ public class XmppConnectionService extends Service {
public void onStatusChanged(final Account account) {
XmppConnection connection = account.getXmppConnection();
updateAccountUi();
+ if (account.getStatus() == Account.State.ONLINE || account.getStatus().isError()) {
+ mQuickConversationsService.signalAccountStateChange();
+ }
if (account.getStatus() == Account.State.ONLINE) {
synchronized (mLowPingTimeoutMode) {
if (mLowPingTimeoutMode.remove(account.getJid().asBareJid())) {
@@ -567,6 +581,11 @@ public class XmppConnectionService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String action = intent == null ? null : intent.getAction();
+ final boolean needsForegroundService = intent != null && intent.getBooleanExtra(EventReceiver.EXTRA_NEEDS_FOREGROUND_SERVICE, false);
+ if (needsForegroundService) {
+ Log.d(Config.LOGTAG, "toggle forced foreground service after receiving event");
+ toggleForegroundService(true);
+ }
String pushedAccountHash = null;
boolean interactive = false;
if (action != null) {
@@ -938,15 +957,18 @@ public class XmppConnectionService extends Service {
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public boolean isInteractive() {
- final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
-
- final boolean isScreenOn;
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
- isScreenOn = pm.isScreenOn();
- } else {
- isScreenOn = pm.isInteractive();
+ try {
+ final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ final boolean isScreenOn;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ isScreenOn = pm.isScreenOn();
+ } else {
+ isScreenOn = pm.isInteractive();
+ }
+ return isScreenOn;
+ } catch (RuntimeException e) {
+ return false;
}
- return isScreenOn;
}
private boolean isPhoneSilenced() {
@@ -1229,8 +1251,12 @@ public class XmppConnectionService extends Service {
}
public void toggleForegroundService() {
+ toggleForegroundService(false);
+ }
+
+ private void toggleForegroundService(boolean force) {
final boolean status;
- if (mForceForegroundService.get() || (Compatibility.keepForegroundService(this)/* && hasEnabledAccounts()*/)) {
+ if (force || mForceForegroundService.get() || (Compatibility.keepForegroundService(this)/* && hasEnabledAccounts()*/)) {
startForeground(NotificationService.FOREGROUND_NOTIFICATION_ID, this.mNotificationService.createForegroundNotification());
status = true;
} else {
@@ -1241,6 +1267,10 @@ public class XmppConnectionService extends Service {
Log.d(Config.LOGTAG, "ForegroundService: " + (status ? "on" : "off"));
}
+ public boolean foregroundNotificationNeedsUpdatingWhenErrorStateChanges() {
+ return !mForceForegroundService.get() && Compatibility.keepForegroundService(this) && hasEnabledAccounts();
+ }
+
@Override
public void onTaskRemoved(final Intent rootIntent) {
super.onTaskRemoved(rootIntent);
@@ -1351,6 +1381,13 @@ public class XmppConnectionService extends Service {
}
final Conversation conversation = (Conversation) message.getConversation();
account.deactivateGracePeriod();
+ if (QuickConversationsService.isQuicksy() && conversation.getMode() == Conversation.MODE_SINGLE) {
+ final Contact contact = conversation.getContact();
+ if (!contact.showInRoster() && contact.getOption(Contact.Options.SYNCED_VIA_OTHER)) {
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": adding " + contact.getJid() + " on sending message");
+ createContact(contact, true);
+ }
+ }
MessagePacket packet = null;
final boolean addToConversation = (conversation.getMode() != Conversation.MODE_MULTI
|| !Patches.BAD_MUC_REFLECTION.contains(account.getServerIdentity()))
@@ -1585,7 +1622,7 @@ public class XmppConnectionService extends Service {
if (conversation != null) {
bookmark.setConversation(conversation);
} else if (bookmark.autojoin() && bookmark.getJid() != null && autojoin) {
- conversation = findOrCreateConversation(account, bookmark.getJid(), true, true, false);
+ conversation = findOrCreateConversation(account, bookmark.getFullJid(), true, true, false);
bookmark.setConversation(conversation);
}
}
@@ -1720,45 +1757,31 @@ public class XmppConnectionService extends Service {
}
public void loadPhoneContacts() {
- mContactMergerExecutor.execute(() -> PhoneHelper.loadPhoneContacts(XmppConnectionService.this, new OnPhoneContactsLoadedListener() {
- @Override
- public void onPhoneContactsLoaded(List<Bundle> phoneContacts) {
- Log.d(Config.LOGTAG, "start merging phone contacts with roster");
- for (Account account : accounts) {
- List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts();
- for (Bundle phoneContact : phoneContacts) {
- Jid jid;
- try {
- jid = Jid.of(phoneContact.getString("jid"));
- } catch (final IllegalArgumentException e) {
- continue;
- }
- final Contact contact = account.getRoster().getContact(jid);
- String systemAccount = phoneContact.getInt("phoneid")
- + "#"
- + phoneContact.getString("lookup");
- contact.setSystemAccount(systemAccount);
- boolean needsCacheClean = contact.setPhotoUri(phoneContact.getString("photouri"));
- needsCacheClean |= contact.setSystemName(phoneContact.getString("displayname"));
- if (needsCacheClean) {
- getAvatarService().clear(contact);
- }
- withSystemAccounts.remove(contact);
+ mContactMergerExecutor.execute(() -> {
+ Map<Jid, JabberIdContact> contacts = JabberIdContact.load(this);
+ Log.d(Config.LOGTAG, "start merging phone contacts with roster");
+ for (Account account : accounts) {
+ List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts(JabberIdContact.class);
+ for (JabberIdContact jidContact : contacts.values()) {
+ final Contact contact = account.getRoster().getContact(jidContact.getJid());
+ boolean needsCacheClean = contact.setPhoneContact(jidContact);
+ if (needsCacheClean) {
+ getAvatarService().clear(contact);
}
- for (Contact contact : withSystemAccounts) {
- contact.setSystemAccount(null);
- boolean needsCacheClean = contact.setPhotoUri(null);
- needsCacheClean |= contact.setSystemName(null);
- if (needsCacheClean) {
- getAvatarService().clear(contact);
- }
+ withSystemAccounts.remove(contact);
+ }
+ for (Contact contact : withSystemAccounts) {
+ boolean needsCacheClean = contact.unsetPhoneContact(JabberIdContact.class);
+ if (needsCacheClean) {
+ getAvatarService().clear(contact);
}
}
- Log.d(Config.LOGTAG, "finished merging phone contacts");
- mShortcutService.refresh(mInitialAddressbookSyncCompleted.compareAndSet(false, true));
- updateRosterUi();
}
- }));
+ Log.d(Config.LOGTAG, "finished merging phone contacts");
+ mShortcutService.refresh(mInitialAddressbookSyncCompleted.compareAndSet(false, true));
+ updateRosterUi();
+ mQuickConversationsService.considerSync();
+ });
}
public void syncRoster(final Account account) {
@@ -2072,11 +2095,7 @@ public class XmppConnectionService extends Service {
} else {
conversation.endOtrIfNeeded();
if (conversation.getContact().getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
- Log.d(Config.LOGTAG, "Canceling presence request from " + conversation.getJid().toString());
- sendPresencePacket(
- conversation.getAccount(),
- mPresenceGenerator.stopPresenceUpdatesTo(conversation.getContact())
- );
+ stopPresenceUpdatesTo(conversation.getContact());
}
}
updateConversation(conversation);
@@ -2085,6 +2104,12 @@ public class XmppConnectionService extends Service {
}
}
+ public void stopPresenceUpdatesTo(Contact contact) {
+ Log.d(Config.LOGTAG, "Canceling presence request from " + contact.getJid().toString());
+ sendPresencePacket(contact.getAccount(), mPresenceGenerator.stopPresenceUpdatesTo(contact));
+ contact.resetOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST);
+ }
+
public void createAccount(final Account account) {
account.initAccountServices(this);
databaseBackend.createAccount(account);
@@ -2695,15 +2720,17 @@ public class XmppConnectionService extends Service {
public void persistSelfNick(MucOptions.User self) {
final Conversation conversation = self.getConversation();
+ final boolean tookProposedNickFromBookmark = conversation.getMucOptions().isTookProposedNickFromBookmark();
Jid full = self.getFullJid();
if (!full.equals(conversation.getJid())) {
Log.d(Config.LOGTAG, "nick changed. updating");
conversation.setContactJid(full);
databaseBackend.updateConversation(conversation);
}
-
- Bookmark bookmark = conversation.getBookmark();
- if (bookmark != null && !full.getResource().equals(bookmark.getNick())) {
+ final Bookmark bookmark = conversation.getBookmark();
+ final String bookmarkedNick = bookmark == null ? null : bookmark.getNick();
+ if (bookmark != null && (tookProposedNickFromBookmark || TextUtils.isEmpty(bookmarkedNick)) && !full.getResource().equals(bookmarkedNick)) {
+ Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": persist nick '" + full.getResource() + "' into bookmark for " + conversation.getJid().asBareJid());
bookmark.setNick(full.getResource());
pushBookmarks(bookmark.getAccount());
}
@@ -3683,11 +3710,11 @@ public class XmppConnectionService extends Service {
}
public boolean useTorToConnect() {
- return Config.FORCE_ORBOT || getBooleanPreference("use_tor", R.bool.use_tor);
+ return QuickConversationsService.isConversations() && getBooleanPreference("use_tor", R.bool.use_tor);
}
public boolean showExtendedConnectionOptions() {
- return getBooleanPreference("show_connection_options", R.bool.show_connection_options);
+ return QuickConversationsService.isConversations() && getBooleanPreference("show_connection_options", R.bool.show_connection_options);
}
public boolean warnUnecryptedChat() {
@@ -4053,12 +4080,16 @@ public class XmppConnectionService extends Service {
return this.mMessageArchiveService;
}
+ public QuickConversationsService getQuickConversationsService() {
+ return this.mQuickConversationsService;
+ }
+
public List<Contact> findContacts(Jid jid, String accountJid) {
ArrayList<Contact> contacts = new ArrayList<>();
for (Account account : getAccounts()) {
if ((account.isEnabled() || accountJid != null)
&& (accountJid == null || accountJid.equals(account.getJid().asBareJid().toString()))) {
- Contact contact = account.getRoster().getContactFromRoster(jid);
+ Contact contact = account.getRoster().getContactFromContactList(jid);
if (contact != null) {
contacts.add(contact);
}
@@ -4201,14 +4232,18 @@ public class XmppConnectionService extends Service {
public void publishDisplayName(Account account) {
String displayName = account.getDisplayName();
- if (displayName != null && !displayName.isEmpty()) {
- IqPacket publish = mIqGenerator.publishNick(displayName);
- sendIqPacket(account, publish, (account1, packet) -> {
- if (packet.getType() == IqPacket.TYPE.ERROR) {
- Log.d(Config.LOGTAG, account1.getJid().asBareJid() + ": could not publish nick");
- }
- });
+ final IqPacket request;
+ if (TextUtils.isEmpty(displayName)) {
+ request = mIqGenerator.deleteNode(Namespace.NICK);
+ } else {
+ request = mIqGenerator.publishNick(displayName);
}
+ mAvatarService.clear(account);
+ sendIqPacket(account, request, (account1, packet) -> {
+ if (packet.getType() == IqPacket.TYPE.ERROR) {
+ Log.d(Config.LOGTAG, account1.getJid().asBareJid() + ": unable to modify nick name " + packet.toString());
+ }
+ });
}
public ServiceDiscoveryResult getCachedServiceDiscoveryResult(Pair<String, String> key) {
diff --git a/src/main/java/de/pixart/messenger/ui/ChooseContactActivity.java b/src/main/java/de/pixart/messenger/ui/ChooseContactActivity.java
index a760a563b..ac1866fec 100644
--- a/src/main/java/de/pixart/messenger/ui/ChooseContactActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ChooseContactActivity.java
@@ -263,7 +263,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
for (final Account account : xmppConnectionService.getAccounts()) {
if (account.getStatus() != Account.State.DISABLED) {
for (final Contact contact : account.getRoster().getContacts()) {
- if (contact.showInRoster() &&
+ if (contact.showInContactList() &&
!filterContacts.contains(contact.getJid().asBareJid().toString())
&& contact.match(this, needle)) {
getListItems().add(contact);
diff --git a/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java b/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java
index 745ed67c7..7f9e971d3 100644
--- a/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java
@@ -24,6 +24,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.Toast;
@@ -66,6 +67,7 @@ import de.pixart.messenger.utils.StylingHelper;
import de.pixart.messenger.utils.TimeframeUtils;
import de.pixart.messenger.utils.UIHelper;
import de.pixart.messenger.utils.XmppUri;
+import me.drakeet.support.toast.ToastCompat;
import rocks.xmpp.addr.Jid;
import static de.pixart.messenger.entities.Bookmark.printableValue;
@@ -113,8 +115,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
private UiCallback<Conversation> renameCallback = new UiCallback<Conversation>() {
@Override
public void success(Conversation object) {
+ displayToast(getString(R.string.your_nick_has_been_changed));
runOnUiThread(() -> {
- Toast.makeText(ConferenceDetailsActivity.this, getString(R.string.your_nick_has_been_changed), Toast.LENGTH_SHORT).show();
updateView();
});
@@ -122,7 +124,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
@Override
public void error(final int errorCode, Conversation object) {
- runOnUiThread(() -> Toast.makeText(ConferenceDetailsActivity.this, getString(errorCode), Toast.LENGTH_SHORT).show());
+ displayToast(getString(errorCode));
}
@Override
@@ -466,7 +468,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
this.mSelectedUser = user;
String name;
final Contact contact = user.getContact();
- if (contact != null && contact.showInRoster()) {
+ if (contact != null && contact.showInContactList()) {
name = contact.getDisplayName();
} else if (user.getRealJid() != null) {
name = user.getRealJid().asBareJid().toString();
@@ -785,7 +787,12 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
}
private void displayToast(final String msg) {
- runOnUiThread(() -> Toast.makeText(ConferenceDetailsActivity.this, msg, Toast.LENGTH_SHORT).show());
+ runOnUiThread(() -> {
+ if (isFinishing()) {
+ return;
+ }
+ ToastCompat.makeText(this, msg, Toast.LENGTH_SHORT).show();
+ });
}
public void loadAvatar(User user, ImageView imageView) {
diff --git a/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java b/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java
index 619c2b3f2..9db7ce7c9 100644
--- a/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java
@@ -86,7 +86,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
if (contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
- xmppConnectionService.sendPresencePacket(contact.getAccount(), xmppConnectionService.getPresenceGenerator().sendPresenceUpdatesTo(contact));
+ xmppConnectionService.stopPresenceUpdatesTo(contact);
} else {
contact.setOption(Contact.Options.PREEMPTIVE_GRANT);
}
diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
index 69aa51918..949dba90d 100644
--- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
+++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
@@ -1334,10 +1334,11 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
MenuItem downloadFile = menu.findItem(R.id.download_file);
MenuItem deleteFile = menu.findItem(R.id.delete_file);
MenuItem showErrorMessage = menu.findItem(R.id.show_error_message);
+ final boolean showError = m.getStatus() == Message.STATUS_SEND_FAILED && m.getErrorMessage() != null && !Message.ERROR_MESSAGE_CANCELLED.equals(m.getErrorMessage());
deleteMessage.setVisible(true);
if (!m.isFileOrImage() && !encrypted && !m.isGeoUri() && !m.treatAsDownloadable()) {
copyMessage.setVisible(true);
- quoteMessage.setVisible(MessageUtils.prepareQuote(m).length() > 0);
+ quoteMessage.setVisible(!showError && MessageUtils.prepareQuote(m).length() > 0);
String body = m.getMergedBody().toString();
if (ShareUtil.containsXmppUri(body)) {
copyLink.setTitle(R.string.copy_jabber_id);
@@ -1349,7 +1350,8 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
if (m.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
retryDecryption.setVisible(true);
}
- if (relevantForCorrection.getType() == Message.TYPE_TEXT
+ if (!showError
+ && relevantForCorrection.getType() == Message.TYPE_TEXT
&& relevantForCorrection.isLastCorrectableMessage()
&& m.getConversation() instanceof Conversation
&& (((Conversation) m.getConversation()).getMucOptions().nonanonymous() || m.getConversation().getMode() == Conversation.MODE_SINGLE)) {
@@ -1388,7 +1390,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
deleteFile.setTitle(activity.getString(R.string.delete_x_file, UIHelper.getFileDescriptionString(activity, m)));
}
}
- if (m.getStatus() == Message.STATUS_SEND_FAILED && m.getErrorMessage() != null && !Message.ERROR_MESSAGE_CANCELLED.equals(m.getErrorMessage())) {
+ if (showError) {
showErrorMessage.setVisible(true);
}
}
@@ -1883,6 +1885,10 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.error_message);
builder.setMessage(message.getErrorMessage());
+ builder.setNegativeButton(R.string.copy_to_clipboard, (dialog, which) -> {
+ activity.copyTextToClipboard(message.getErrorMessage(), R.string.error_message);
+ Toast.makeText(activity, R.string.error_message_copied_to_clipboard, Toast.LENGTH_SHORT).show();
+ });
builder.setPositiveButton(R.string.ok, null);
builder.create().show();
}
@@ -2332,25 +2338,28 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
private boolean showBlockSubmenu(View view) {
final Jid jid = conversation.getJid();
- if (jid.getLocal() == null) {
- BlockContactDialog.show(activity, conversation);
- } else {
- PopupMenu popupMenu = new PopupMenu(getActivity(), view);
- popupMenu.inflate(R.menu.block);
- popupMenu.setOnMenuItemClickListener(menuItem -> {
- Blockable blockable;
- switch (menuItem.getItemId()) {
- case R.id.block_domain:
- blockable = conversation.getAccount().getRoster().getContact(Jid.ofDomain(jid.getDomain()));
- break;
- default:
- blockable = conversation;
- }
- BlockContactDialog.show(activity, blockable);
- return true;
- });
- popupMenu.show();
- }
+ final boolean showReject = !conversation.isWithStranger() && conversation.getContact().getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST);
+ PopupMenu popupMenu = new PopupMenu(getActivity(), view);
+ popupMenu.inflate(R.menu.block);
+ popupMenu.getMenu().findItem(R.id.block_contact).setVisible(jid.getLocal() != null);
+ popupMenu.getMenu().findItem(R.id.reject).setVisible(showReject);
+ popupMenu.setOnMenuItemClickListener(menuItem -> {
+ Blockable blockable;
+ switch (menuItem.getItemId()) {
+ case R.id.reject:
+ activity.xmppConnectionService.stopPresenceUpdatesTo(conversation.getContact());
+ updateSnackBar(conversation);
+ return true;
+ case R.id.block_domain:
+ blockable = conversation.getAccount().getRoster().getContact(Jid.ofDomain(jid.getDomain()));
+ break;
+ default:
+ blockable = conversation;
+ }
+ BlockContactDialog.show(activity, blockable);
+ return true;
+ });
+ popupMenu.show();
return true;
}
diff --git a/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java b/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java
index 5daaafacd..92962fb45 100644
--- a/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java
@@ -56,6 +56,7 @@ import de.pixart.messenger.entities.Presence;
import de.pixart.messenger.entities.PresenceTemplate;
import de.pixart.messenger.entities.ServiceDiscoveryResult;
import de.pixart.messenger.services.BarcodeProvider;
+import de.pixart.messenger.services.QuickConversationsService;
import de.pixart.messenger.services.XmppConnectionService;
import de.pixart.messenger.services.XmppConnectionService.OnAccountUpdate;
import de.pixart.messenger.services.XmppConnectionService.OnCaptchaRequested;
@@ -66,6 +67,7 @@ import de.pixart.messenger.ui.util.SoftKeyboardUtils;
import de.pixart.messenger.utils.CryptoHelper;
import de.pixart.messenger.utils.MenuDoubleTabUtil;
import de.pixart.messenger.utils.Namespace;
+import de.pixart.messenger.utils.Resolver;
import de.pixart.messenger.utils.SignupUtils;
import de.pixart.messenger.utils.UIHelper;
import de.pixart.messenger.utils.XmppUri;
@@ -106,11 +108,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
final String password = binding.accountPassword.getText().toString();
final boolean wasDisabled = mAccount != null && mAccount.getStatus() == Account.State.DISABLED;
final boolean accountInfoEdited = accountInfoEdited();
-
- if (!mInitMode && passwordChangedInMagicCreateMode()) {
- gotoChangePassword(password);
- return;
- }
if (mInitMode && mAccount != null) {
mAccount.setOption(Account.OPTION_DISABLED, false);
}
@@ -206,7 +203,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
}
}
if (mAccount != null) {
- if (mInitMode && mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)) {
+ if (mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)) {
mAccount.setOption(Account.OPTION_MAGIC_CREATE, mAccount.getPassword().contains(password));
}
mAccount.setJid(jid);
@@ -465,11 +462,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
protected void updateSaveButton() {
boolean accountInfoEdited = accountInfoEdited();
-
- if (!mInitMode && passwordChangedInMagicCreateMode()) {
- this.binding.saveButton.setText(R.string.change_password);
- this.binding.saveButton.setEnabled(true);
- } else if (accountInfoEdited && !mInitMode) {
+ if (accountInfoEdited && !mInitMode) {
this.binding.saveButton.setText(R.string.save);
this.binding.saveButton.setEnabled(true);
} else if (mAccount != null
@@ -528,14 +521,6 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
return !unmodified.equals(this.binding.accountJid.getText().toString());
}
- protected boolean passwordChangedInMagicCreateMode() {
- return mAccount != null
- && mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)
- && !this.mAccount.getPassword().equals(binding.accountPassword.getText().toString())
- && !this.jidEdited()
- && mAccount.isOnlineAndConnected();
- }
-
@Override
protected String getShareableUri(boolean http) {
if (mAccount != null) {
@@ -562,20 +547,17 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
this.binding.hostname.addTextChangedListener(mTextWatcher);
this.binding.hostname.setOnFocusChangeListener(mEditTextFocusListener);
this.binding.clearDevices.setOnClickListener(v -> showWipePepDialog());
- this.binding.port.setText("5222");
+ this.binding.port.setText(String.valueOf(Resolver.DEFAULT_PORT_XMPP));
this.binding.port.addTextChangedListener(mTextWatcher);
this.binding.saveButton.setOnClickListener(this.mSaveButtonClickListener);
this.binding.cancelButton.setOnClickListener(this.mCancelButtonClickListener);
if (savedInstanceState != null && savedInstanceState.getBoolean("showMoreTable")) {
changeMoreTableVisibility(true);
}
- final OnCheckedChangeListener OnCheckedShowConfirmPassword = new OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
- updatePortLayout();
- updateSaveButton();
- updateInfoButtons();
- }
+ final OnCheckedChangeListener OnCheckedShowConfirmPassword = (buttonView, isChecked) -> {
+ updatePortLayout();
+ updateSaveButton();
+ updateInfoButtons();
};
this.binding.accountRegisterNew.setOnCheckedChangeListener(OnCheckedShowConfirmPassword);
if (Config.DISALLOW_REGISTRATION_IN_UI) {
@@ -689,8 +671,8 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
}
}
SharedPreferences preferences = getPreferences();
- mUseTor = Config.FORCE_ORBOT || preferences.getBoolean("use_tor", false);
- this.mShowOptions = mUseTor || preferences.getBoolean("show_connection_options", false);
+ mUseTor = QuickConversationsService.isConversations() && preferences.getBoolean("use_tor", getResources().getBoolean(R.bool.use_tor));
+ this.mShowOptions = mUseTor || (QuickConversationsService.isConversations() && preferences.getBoolean("show_connection_options", getResources().getBoolean(R.bool.show_connection_options)));
this.binding.namePort.setVisibility(mShowOptions ? View.VISIBLE : View.GONE);
}
@@ -976,16 +958,18 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
}
- final boolean editable = !mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY);
+ final boolean editable = !mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY) && QuickConversationsService.isConversations();
this.binding.accountJid.setEnabled(editable);
this.binding.accountJid.setFocusable(editable);
this.binding.accountJid.setFocusableInTouchMode(editable);
- if (mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) || !mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY)) {
- this.binding.accountPasswordLayout.setPasswordVisibilityToggleEnabled(true);
- } else {
- this.binding.accountPasswordLayout.setPasswordVisibilityToggleEnabled(false);
- }
+ final boolean tooglePassword = mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) || !mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY);
+ final boolean editPassword = !mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) || (!mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY) && QuickConversationsService.isConversations()) || mAccount.getLastErrorStatus() == Account.State.UNAUTHORIZED;
+ this.binding.accountPasswordLayout.setPasswordVisibilityToggleEnabled(tooglePassword);
+ this.binding.accountPassword.setFocusable(editPassword);
+ this.binding.accountPassword.setFocusableInTouchMode(editPassword);
+ this.binding.accountPassword.setCursorVisible(editPassword);
+ this.binding.accountPassword.setEnabled(editPassword);
if (!mInitMode) {
binding.avater.setVisibility(View.VISIBLE);
@@ -1062,7 +1046,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
if (getHttpUploadMaxFileSize().equals("0")) {
this.binding.serverInfoHttpUpload.setText(R.string.server_info_available);
} else {
- this.binding.serverInfoHttpUpload.setText(getString(R.string.server_info_available_with, getHttpUploadMaxFileSize()));
+ this.binding.serverInfoHttpUpload.setText(getHttpUploadMaxFileSize());
}
} else if (features.p1S3FileTransfer()) {
this.binding.serverInfoHttpUploadDescription.setText(R.string.p1_s3_filetransfer);
diff --git a/src/main/java/de/pixart/messenger/ui/ShortcutActivity.java b/src/main/java/de/pixart/messenger/ui/ShortcutActivity.java
index 52f87c5a3..ef5c296e0 100644
--- a/src/main/java/de/pixart/messenger/ui/ShortcutActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ShortcutActivity.java
@@ -55,7 +55,7 @@ public class ShortcutActivity extends AbstractSearchableListItemActivity {
for (final Account account : xmppConnectionService.getAccounts()) {
if (account.getStatus() != Account.State.DISABLED) {
for (final Contact contact : account.getRoster().getContacts()) {
- if (contact.showInRoster()
+ if (contact.showInContactList()
&& contact.match(this, needle)) {
getListItems().add(contact);
}
diff --git a/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java b/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java
index 1edbafd67..825494d90 100644
--- a/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java
@@ -395,7 +395,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
}
protected void openConversationsForBookmark(Bookmark bookmark) {
- Jid jid = bookmark.getJid();
+ final Jid jid = bookmark.getFullJid();
if (jid == null) {
Toast.makeText(this, R.string.invalid_jid, Toast.LENGTH_SHORT).show();
return;
@@ -735,6 +735,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
@Override
protected void onBackendConnected() {
+ xmppConnectionService.getQuickConversationsService().considerSyncBackground(false);
if (mPostponedActivityResult != null) {
onActivityResult(mPostponedActivityResult.first, RESULT_OK, mPostponedActivityResult.second);
this.mPostponedActivityResult = null;
@@ -868,12 +869,11 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
protected void filterContacts(String needle) {
this.contacts.clear();
final List<Account> accounts = xmppConnectionService.getAccounts();
- final boolean singleAccountActive = isSingleAccountActive(accounts);
for (Account account : accounts) {
if (account.getStatus() != Account.State.DISABLED) {
for (Contact contact : account.getRoster().getContacts()) {
Presence.Status s = contact.getShownStatus();
- if ((contact.showInRoster() || (singleAccountActive && contact.showInPhoneBook())) && contact.match(this, needle)
+ if (contact.showInContactList() && contact.match(this, needle)
&& (!this.mHideOfflineContacts
|| (needle != null && !needle.trim().isEmpty())
|| s.compareTo(Presence.Status.OFFLINE) < 0)) {
@@ -886,16 +886,6 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
mContactsAdapter.notifyDataSetChanged();
}
- private static boolean isSingleAccountActive(final List<Account> accounts) {
- int i = 0;
- for(Account account : accounts) {
- if (account.getStatus() != Account.State.DISABLED) {
- ++i;
- }
- }
- return i == 1;
- }
-
protected void filterConferences(String needle) {
this.conferences.clear();
for (Account account : xmppConnectionService.getAccounts()) {
@@ -1068,7 +1058,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
if (contact.isSelf()) {
showContactDetailsItem.setVisible(false);
}
- deleteContactMenuItem.setVisible(contact.showInRoster());
+ deleteContactMenuItem.setVisible(contact.showInRoster() && !contact.getOption(Contact.Options.SYNCED_VIA_OTHER));
XmppConnection xmpp = contact.getAccount().getXmppConnection();
if (xmpp != null && xmpp.getFeatures().blocking() && !contact.isSelf()) {
if (contact.isBlocked()) {
@@ -1115,10 +1105,10 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
}
public class ListPagerAdapter extends PagerAdapter {
- FragmentManager fragmentManager;
- MyListFragment[] fragments;
+ private final FragmentManager fragmentManager;
+ private final MyListFragment[] fragments;
- public ListPagerAdapter(FragmentManager fm) {
+ ListPagerAdapter(FragmentManager fm) {
fragmentManager = fm;
fragments = new MyListFragment[2];
}
@@ -1140,10 +1130,14 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
@NonNull
@Override
public Fragment instantiateItem(@NonNull ViewGroup container, int position) {
- Fragment fragment = getItem(position);
- FragmentTransaction trans = fragmentManager.beginTransaction();
+ final Fragment fragment = getItem(position);
+ final FragmentTransaction trans = fragmentManager.beginTransaction();
trans.add(container.getId(), fragment, "fragment:" + position);
- trans.commit();
+ try {
+ trans.commit();
+ } catch (IllegalStateException e) {
+ //ignore
+ }
return fragment;
}
diff --git a/src/main/java/de/pixart/messenger/ui/TimePreference.java b/src/main/java/de/pixart/messenger/ui/TimePreference.java
index 731a3bb50..97750d6e3 100644
--- a/src/main/java/de/pixart/messenger/ui/TimePreference.java
+++ b/src/main/java/de/pixart/messenger/ui/TimePreference.java
@@ -25,11 +25,12 @@ public class TimePreference extends DialogPreference implements Preference.OnPre
persistLong(time);
notifyDependencyChange(shouldDisableDependents());
notifyChanged();
+ updateSummary(time);
}
- protected void updateSummary(final long time) {
+ private void updateSummary(final long time) {
final DateFormat dateFormat = android.text.format.DateFormat.getTimeFormat(getContext());
- final Date date = new Date(time);
+ final Date date = minutesToCalender(time).getTime();
setSummary(dateFormat.format(date.getTime()));
}
@@ -40,21 +41,13 @@ public class TimePreference extends DialogPreference implements Preference.OnPre
return picker;
}
- protected Calendar getPersistedTime() {
- final Calendar c = Calendar.getInstance();
- c.setTimeInMillis(getPersistedLong(DEFAULT_VALUE));
-
- return c;
- }
-
@SuppressWarnings("NullableProblems")
@Override
protected void onBindDialogView(final View v) {
super.onBindDialogView(v);
- final Calendar c = getPersistedTime();
-
- picker.setCurrentHour(c.get(Calendar.HOUR_OF_DAY));
- picker.setCurrentMinute(c.get(Calendar.MINUTE));
+ long time = getPersistedLong(DEFAULT_VALUE);
+ picker.setCurrentHour((int) ((time % (24 * 60)) / 60));
+ picker.setCurrentMinute((int) ((time % (24 * 60)) % 60));
}
@Override
@@ -62,17 +55,19 @@ public class TimePreference extends DialogPreference implements Preference.OnPre
super.onDialogClosed(positiveResult);
if (positiveResult) {
- final Calendar c = Calendar.getInstance();
- c.set(Calendar.MINUTE, picker.getCurrentMinute());
- c.set(Calendar.HOUR_OF_DAY, picker.getCurrentHour());
-
+ setTime(picker.getCurrentHour() * 60 + picker.getCurrentMinute());
+ }
+ }
- if (!callChangeListener(c.getTimeInMillis())) {
- return;
- }
+ private static Calendar minutesToCalender(long time) {
+ final Calendar c = Calendar.getInstance();
+ c.set(Calendar.HOUR_OF_DAY, (int) ((time % (24 * 60)) / 60));
+ c.set(Calendar.MINUTE, (int) ((time % (24 * 60)) % 60));
+ return c;
+ }
- setTime(c.getTimeInMillis());
- }
+ public static long minutesToTimestamp(long time) {
+ return minutesToCalender(time).getTimeInMillis();
}
@Override
@@ -83,12 +78,8 @@ public class TimePreference extends DialogPreference implements Preference.OnPre
@Override
protected void onSetInitialValue(final boolean restorePersistedValue, final Object defaultValue) {
long time;
- if (defaultValue == null) {
- time = restorePersistedValue ? getPersistedLong(DEFAULT_VALUE) : DEFAULT_VALUE;
- } else if (defaultValue instanceof Long) {
+ if (defaultValue instanceof Long) {
time = restorePersistedValue ? getPersistedLong((Long) defaultValue) : (Long) defaultValue;
- } else if (defaultValue instanceof Calendar) {
- time = restorePersistedValue ? getPersistedLong(((Calendar) defaultValue).getTimeInMillis()) : ((Calendar) defaultValue).getTimeInMillis();
} else {
time = restorePersistedValue ? getPersistedLong(DEFAULT_VALUE) : DEFAULT_VALUE;
}
diff --git a/src/main/java/de/pixart/messenger/ui/XmppActivity.java b/src/main/java/de/pixart/messenger/ui/XmppActivity.java
index ef8b753d0..ee606395a 100644
--- a/src/main/java/de/pixart/messenger/ui/XmppActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/XmppActivity.java
@@ -744,6 +744,7 @@ public abstract class XmppActivity extends ActionBarActivity {
SoftKeyboardUtils.hideSoftKeyboard(binding.inputEditText);
dialog.dismiss();
}));
+ dialog.setCanceledOnTouchOutside(false);
dialog.setOnDismissListener(dialog1 -> {
SoftKeyboardUtils.hideSoftKeyboard(binding.inputEditText);
});
@@ -1242,7 +1243,7 @@ public abstract class XmppActivity extends ActionBarActivity {
builder.setTitle(R.string.install_from_unknown_sources_disabled);
builder.setMessage(R.string.install_from_unknown_sources_disabled_dialog);
builder.setPositiveButton(R.string.next, (dialog, which) -> {
- Intent intent = null;
+ Intent intent;
if (android.os.Build.VERSION.SDK_INT >= 26) {
intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
Uri uri = Uri.parse("package:" + getPackageName());
@@ -1254,7 +1255,7 @@ public abstract class XmppActivity extends ActionBarActivity {
try {
startActivityForResult(intent, REQUEST_UNKNOWN_SOURCE_OP);
} catch (ActivityNotFoundException e) {
- Toast.makeText(XmppActivity.this, R.string.device_does_not_support_battery_op, Toast.LENGTH_SHORT).show();
+ Toast.makeText(XmppActivity.this, R.string.device_does_not_support_unknown_source_op, Toast.LENGTH_SHORT).show();
} finally {
UpdateService task = new UpdateService(this, xmppConnectionService.installedFrom(), xmppConnectionService);
task.executeOnExecutor(UpdateService.THREAD_POOL_EXECUTOR, "true");
@@ -1262,6 +1263,10 @@ public abstract class XmppActivity extends ActionBarActivity {
}
});
builder.create().show();
+ } else {
+ UpdateService task = new UpdateService(this, xmppConnectionService.installedFrom(), xmppConnectionService);
+ task.executeOnExecutor(UpdateService.THREAD_POOL_EXECUTOR, "true");
+ Log.d(Config.LOGTAG, "AppUpdater started");
}
}
}
diff --git a/src/main/java/de/pixart/messenger/ui/widget/TextInputEditText.java b/src/main/java/de/pixart/messenger/ui/widget/TextInputEditText.java
new file mode 100644
index 000000000..51ad578df
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/widget/TextInputEditText.java
@@ -0,0 +1,47 @@
+package de.pixart.messenger.ui.widget;
+
+import android.content.Context;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import java.lang.reflect.Field;
+
+/**
+ * A wrapper class to fix some weird fuck ups on Meizu devices
+ * credit goes to the people in this thread https://github.com/android-in-china/Compatibility/issues/11
+ */
+public class TextInputEditText extends android.support.design.widget.TextInputEditText {
+
+ public TextInputEditText(Context context) {
+ super(context);
+ }
+
+ public TextInputEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public TextInputEditText(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public CharSequence getHint() {
+ String manufacturer = Build.MANUFACTURER.toUpperCase();
+ if (!manufacturer.contains("MEIZU") || Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ return super.getHint();
+ } else {
+ try {
+ return getSuperHintHack();
+ } catch (Exception e) {
+ return super.getHint();
+ }
+ }
+ }
+
+ private CharSequence getSuperHintHack() throws NoSuchFieldException, IllegalAccessException {
+ Field hintField = TextView.class.getDeclaredField("mHint");
+ hintField.setAccessible(true);
+ return (CharSequence) hintField.get(this);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/utils/Compatibility.java b/src/main/java/de/pixart/messenger/utils/Compatibility.java
index f178f17c7..38f9db378 100644
--- a/src/main/java/de/pixart/messenger/utils/Compatibility.java
+++ b/src/main/java/de/pixart/messenger/utils/Compatibility.java
@@ -56,6 +56,8 @@ public class Compatibility {
return applicationInfo == null || applicationInfo.targetSdkVersion >= 26;
} catch (PackageManager.NameNotFoundException e) {
return true; //when in doubt…
+ } catch (RuntimeException e) {
+ return true; //when in doubt…
}
}
diff --git a/src/main/java/de/pixart/messenger/utils/Namespace.java b/src/main/java/de/pixart/messenger/utils/Namespace.java
index 146a9784d..83d63cdaa 100644
--- a/src/main/java/de/pixart/messenger/utils/Namespace.java
+++ b/src/main/java/de/pixart/messenger/utils/Namespace.java
@@ -16,10 +16,12 @@ public final class Namespace {
public static final String PUBSUB = "http://jabber.org/protocol/pubsub";
public static final String PUBSUB_PUBLISH_OPTIONS = PUBSUB + "#publish-options";
public static final String PUBSUB_ERROR = PUBSUB + "#errors";
+ public static final String PUBSUB_OWNER = PUBSUB + "#owner";
public static final String NICK = "http://jabber.org/protocol/nick";
public static final String FLEXIBLE_OFFLINE_MESSAGE_RETRIEVAL = "http://jabber.org/protocol/offline";
public static final String BIND = "urn:ietf:params:xml:ns:xmpp-bind";
public static final String P1_S3_FILE_TRANSFER = "p1:s3filetransfer";
public static final String BOOKMARKS_CONVERSION = "urn:xmpp:bookmarks-conversion:0";
public static final String BOOKMARKS = "storage:bookmarks";
+ public static final String SYNCHRONIZATION = "im.quicksy.synchronization:0";
}
diff --git a/src/main/java/de/pixart/messenger/utils/PhoneHelper.java b/src/main/java/de/pixart/messenger/utils/PhoneHelper.java
index f5e2ffde1..327ae1904 100644
--- a/src/main/java/de/pixart/messenger/utils/PhoneHelper.java
+++ b/src/main/java/de/pixart/messenger/utils/PhoneHelper.java
@@ -24,55 +24,6 @@ public class PhoneHelper {
return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
- public static void loadPhoneContacts(Context context, final OnPhoneContactsLoadedListener listener) {
- final List<Bundle> phoneContacts = new ArrayList<>();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
- && context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
- listener.onPhoneContactsLoaded(phoneContacts);
- return;
- }
- final String[] PROJECTION = new String[]{ContactsContract.Data._ID,
- ContactsContract.Data.DISPLAY_NAME,
- ContactsContract.Data.PHOTO_URI,
- ContactsContract.Data.LOOKUP_KEY,
- ContactsContract.CommonDataKinds.Im.DATA};
-
- final String SELECTION = "(" + ContactsContract.Data.MIMETYPE + "=\""
- + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE
- + "\") AND (" + ContactsContract.CommonDataKinds.Im.PROTOCOL
- + "=\"" + ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER
- + "\")";
-
- CursorLoader mCursorLoader = new NotThrowCursorLoader(context,
- ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, null,
- null);
- mCursorLoader.registerListener(0, (arg0, c) -> {
- if (c != null) {
- while (c.moveToNext()) {
- Bundle contact = new Bundle();
- contact.putInt("phoneid", c.getInt(c.getColumnIndex(ContactsContract.Data._ID)));
- contact.putString("displayname", c.getString(c.getColumnIndex(ContactsContract.Data.DISPLAY_NAME)));
- contact.putString("photouri", c.getString(c.getColumnIndex(ContactsContract.Data.PHOTO_URI)));
- contact.putString("lookup", c.getString(c.getColumnIndex(ContactsContract.Data.LOOKUP_KEY)));
- contact.putString("jid", c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)));
- phoneContacts.add(contact);
- }
- c.close();
- }
-
- if (listener != null) {
- listener.onPhoneContactsLoaded(phoneContacts);
- }
- });
- try {
- mCursorLoader.startLoading();
- } catch (RejectedExecutionException e) {
- if (listener != null) {
- listener.onPhoneContactsLoaded(phoneContacts);
- }
- }
- }
-
public static Uri getProfilePictureUri(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
return null;
@@ -106,24 +57,6 @@ public class PhoneHelper {
}
}
- private static class NotThrowCursorLoader extends CursorLoader {
-
- private NotThrowCursorLoader(Context c, Uri u, String[] p, String s, String[] sa, String so) {
- super(c, u, p, s, sa, so);
- }
-
- @Override
- public Cursor loadInBackground() {
-
- try {
- return (super.loadInBackground());
- } catch (Throwable e) {
- return (null);
- }
- }
-
- }
-
public static String getOSVersion(Context context) {
return "Android/" + android.os.Build.MODEL + "/" + android.os.Build.VERSION.RELEASE;
}
diff --git a/src/main/java/de/pixart/messenger/utils/ReplacingSerialSingleThreadExecutor.java b/src/main/java/de/pixart/messenger/utils/ReplacingSerialSingleThreadExecutor.java
index bf4d6e8c2..79e5126b2 100644
--- a/src/main/java/de/pixart/messenger/utils/ReplacingSerialSingleThreadExecutor.java
+++ b/src/main/java/de/pixart/messenger/utils/ReplacingSerialSingleThreadExecutor.java
@@ -3,17 +3,13 @@ package de.pixart.messenger.utils;
public class ReplacingSerialSingleThreadExecutor extends SerialSingleThreadExecutor {
public ReplacingSerialSingleThreadExecutor(String name) {
- super(name, false);
- }
-
- public ReplacingSerialSingleThreadExecutor(boolean prepareLooper) {
- super(ReplacingSerialSingleThreadExecutor.class.getName(), prepareLooper);
+ super(name);
}
@Override
public synchronized void execute(final Runnable r) {
tasks.clear();
- if (active != null && active instanceof Cancellable) {
+ if (active instanceof Cancellable) {
((Cancellable) active).cancel();
}
super.execute(r);
@@ -21,8 +17,8 @@ public class ReplacingSerialSingleThreadExecutor extends SerialSingleThreadExecu
public synchronized void cancelRunningTasks() {
tasks.clear();
- if (active != null && active instanceof Cancellable) {
+ if (active instanceof Cancellable) {
((Cancellable) active).cancel();
}
}
-}
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/utils/ReplacingTaskManager.java b/src/main/java/de/pixart/messenger/utils/ReplacingTaskManager.java
index 3c9f386cd..c25c6fce4 100644
--- a/src/main/java/de/pixart/messenger/utils/ReplacingTaskManager.java
+++ b/src/main/java/de/pixart/messenger/utils/ReplacingTaskManager.java
@@ -41,7 +41,7 @@ public class ReplacingTaskManager {
synchronized (this.executors) {
executor = this.executors.get(account);
if (executor == null) {
- executor = new ReplacingSerialSingleThreadExecutor(false);
+ executor = new ReplacingSerialSingleThreadExecutor(ReplacingTaskManager.class.getSimpleName());
this.executors.put(account, executor);
}
executor.execute(runnable);
diff --git a/src/main/java/de/pixart/messenger/utils/Resolver.java b/src/main/java/de/pixart/messenger/utils/Resolver.java
index f2716a648..2378c429e 100644
--- a/src/main/java/de/pixart/messenger/utils/Resolver.java
+++ b/src/main/java/de/pixart/messenger/utils/Resolver.java
@@ -37,6 +37,7 @@ import de.pixart.messenger.services.XmppConnectionService;
public class Resolver {
+ public static final int DEFAULT_PORT_XMPP = 5222;
private static final String DIRECT_TLS_SERVICE = "_xmpps-client";
private static final String STARTTLS_SERICE = "_xmpp-client";
@@ -150,7 +151,7 @@ public class Resolver {
try {
Result result = new Result();
result.ip = InetAddress.getByName(domain);
- result.port = 5222;
+ result.port = DEFAULT_PORT_XMPP;
return Collections.singletonList(result);
} catch (UnknownHostException e) {
return Collections.emptyList();
@@ -270,7 +271,7 @@ public class Resolver {
public static final String AUTHENTICATED = "authenticated";
private InetAddress ip;
private DNSName hostname;
- private int port = 5222;
+ private int port = DEFAULT_PORT_XMPP;
private boolean directTls = false;
private boolean authenticated = false;
private int priority;
@@ -286,7 +287,7 @@ public class Resolver {
static Result createDefault(DNSName hostname, InetAddress ip) {
Result result = new Result();
- result.port = 5222;
+ result.port = DEFAULT_PORT_XMPP;
result.hostname = hostname;
result.ip = ip;
return result;
diff --git a/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java b/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java
index 500b03c5b..9846146a8 100644
--- a/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java
+++ b/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java
@@ -16,14 +16,8 @@ public class SerialSingleThreadExecutor implements Executor {
private final String name;
protected Runnable active;
- public SerialSingleThreadExecutor(String name) {
- this(name, false);
- }
- SerialSingleThreadExecutor(String name, boolean prepareLooper) {
- if (prepareLooper) {
- execute(Looper::prepare);
- }
+ public SerialSingleThreadExecutor(String name) {
this.name = name;
}
diff --git a/src/main/res/layout/activity_change_password.xml b/src/main/res/layout/activity_change_password.xml
index 6bd7f2d0d..4ff57e22b 100644
--- a/src/main/res/layout/activity_change_password.xml
+++ b/src/main/res/layout/activity_change_password.xml
@@ -39,7 +39,7 @@
app:passwordToggleEnabled="true"
app:passwordToggleTint="?android:textColorSecondary">
- <android.support.design.widget.TextInputEditText
+ <de.pixart.messenger.ui.widget.TextInputEditText.widget.TextInputEditText
android:id="@+id/current_password"
style="@style/Widget.Conversations.EditText"
android:layout_width="match_parent"
@@ -59,7 +59,7 @@
app:passwordToggleEnabled="true"
app:passwordToggleTint="?android:textColorSecondary">
- <android.support.design.widget.TextInputEditText
+ <de.pixart.messenger.ui.widget.TextInputEditText
android:id="@+id/new_password"
style="@style/Widget.Conversations.EditText"
android:layout_width="match_parent"
diff --git a/src/main/res/layout/activity_edit_account.xml b/src/main/res/layout/activity_edit_account.xml
index 0742955d3..011f89e5b 100644
--- a/src/main/res/layout/activity_edit_account.xml
+++ b/src/main/res/layout/activity_edit_account.xml
@@ -78,7 +78,7 @@
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:inputType="textEmailAddress"
- android:textColor="?attr/text_Color_Main" />
+ android:textColor="?attr/edit_text_color" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
@@ -91,13 +91,14 @@
app:passwordToggleEnabled="true"
app:passwordToggleTint="?android:textColorSecondary">
- <android.support.design.widget.TextInputEditText
+ <de.pixart.messenger.ui.widget.TextInputEditText
android:id="@+id/account_password"
style="@style/Widget.Conversations.EditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/password"
- android:inputType="textPassword" />
+ android:inputType="textPassword"
+ android:textColor="?attr/edit_text_color" />
</android.support.design.widget.TextInputLayout>
<LinearLayout
diff --git a/src/main/res/menu/block.xml b/src/main/res/menu/block.xml
index 1256f7142..0a86ef124 100644
--- a/src/main/res/menu/block.xml
+++ b/src/main/res/menu/block.xml
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
+ android:id="@+id/reject"
+ android:title="@string/reject_request" />
+ <item
android:id="@+id/block_domain"
android:title="@string/block_entire_domain" />
<item
diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml
index e871df164..d29077753 100644
--- a/src/main/res/values-de/strings.xml
+++ b/src/main/res/values-de/strings.xml
@@ -836,7 +836,6 @@
<string name="remote_server_timeout">Timeout des Remote-Servers</string>
<string name="already_drafting_message">Du bist bereits dabei, eine Nachricht zu entwerfen.</string>
<string name="bad_key_for_encryption">Ungültiger Schlüssel für die Verschlüsselung.</string>
- <string name="server_info_available_with">ja, %s</string>
<string name="delete_message_dialog">Nachricht löschen</string>
<string name="delete_message_dialog_msg">Bist du sicher, dass du diese Nachricht löschen möchtest?\n\n<b>Achtung:</b> Dies wird keine Kopien dieser Nachricht löschen, die auf anderen Geräten oder Servern gespeichert sind.</string>
<string name="feature_not_implemented">Funktion ist nicht implementiert</string>
diff --git a/src/main/res/values-fil/strings.xml b/src/main/res/values-fil/strings.xml
index 449701f22..691e6fcf2 100644
--- a/src/main/res/values-fil/strings.xml
+++ b/src/main/res/values-fil/strings.xml
@@ -168,7 +168,7 @@
<string name="passwords_do_not_match">Ang password ay hindi magkatugma</string>
<string name="invalid_jid">Hindi ito balido na Jabber-ID</string>
<string name="error_out_of_memory">Wala ng memorya. Ang imahe ay napakalaki</string>
- <string name="add_phone_book_text">Gusto mo bang magdagdag sa iyong address book?</string>
+ <string name="add_phone_book_text">Gusto mo bang magdagdag %s sa iyong address book?</string>
<string name="server_info_show_more">Impormasyon sa server</string>
<string name="server_info_mam">XEP-0313: MAM</string>
<string name="server_info_carbon_messages">XEP-0280: Mensagheng karbon</string>
diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml
index 196ae0d5d..f4703e8bb 100644
--- a/src/main/res/values-ru/strings.xml
+++ b/src/main/res/values-ru/strings.xml
@@ -326,5 +326,4 @@
<string name="delete_file_dialog">Удалить файл</string>
<string name="cancelled">отменён</string>
<string name="bad_key_for_encryption">Неправильный ключ для шифрования.</string>
- <string name="server_info_available_with">да, %s</string>
</resources>
diff --git a/src/main/res/values/attrs.xml b/src/main/res/values/attrs.xml
index c537fd248..8c824c7a6 100644
--- a/src/main/res/values/attrs.xml
+++ b/src/main/res/values/attrs.xml
@@ -20,6 +20,7 @@
<attr name="color_background_tertiary" format="reference|color" />
<attr name="color_background_secondary" format="reference|color" />
<attr name="color_background_primary" format="reference|color" />
+ <attr name="edit_text_color" format="reference|color" />
<attr name="color_warning" format="reference|color" />
<attr name="EmojiColor" format="reference|color" />
diff --git a/src/main/res/values/defaults.xml b/src/main/res/values/defaults.xml
index 7c0072f86..e8ef0805e 100644
--- a/src/main/res/values/defaults.xml
+++ b/src/main/res/values/defaults.xml
@@ -52,6 +52,7 @@
\n\nhttp://leafletjs.com/\n(BSD 2-Clause)
\n\nhttps://www.openstreetmap.org/\n(Open Database License)
\n\nhttp://xmpp.rocks/\n(The MIT License (MIT))
+ \n\nhttps://github.com/drakeet/ToastCompat/\n(Apache License, Version 2.0)
</string>
<string name="default_resource" translatable="false">Phone</string>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 0fd36d8b1..8e8d26713 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -836,9 +836,11 @@
<string name="remote_server_timeout">Remote server timeout</string>
<string name="already_drafting_message">You are already drafting a message.</string>
<string name="bad_key_for_encryption">Bad key for encryption.</string>
- <string name="server_info_available_with">yes, %s</string>
<string name="delete_message_dialog">Delete message</string>
<string name="delete_message_dialog_msg">Are you sure you want to delete this message?\n\n<b>Warning:</b> This will not delete copies of this message that are stored on other devices or servers.</string>
<string name="feature_not_implemented">Feature not implemented</string>
+ <string name="device_does_not_support_unknown_source_op">Your device does not support allowing app installs from unknon sources.</string>
+ <string name="reject_request">Reject request</string>
+ <string name="error_message_copied_to_clipboard">Copied error message to clipboard</string>
</resources>
diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml
index 342ed8aa1..c10f8bffd 100644
--- a/src/main/res/values/themes.xml
+++ b/src/main/res/values/themes.xml
@@ -16,6 +16,7 @@
<item name="color_warning">@color/red700</item>
<item name="TextColorOnline">@color/green500</item>
<item name="TextColorError">@color/red800</item>
+ <item name="edit_text_color">@color/black87</item>
<item name="activity_background_search">@drawable/search_background_light</item>
<item name="activity_background_no_results">@drawable/no_results_background_light</item>
@@ -170,6 +171,7 @@
<item name="color_warning">@color/red700</item>
<item name="TextColorOnline">@color/green500</item>
<item name="TextColorError">@color/red500</item>
+ <item name="edit_text_color">@color/white</item>
<item name="activity_background_search">@drawable/search_background_dark</item>
<item name="activity_background_no_results">@drawable/no_results_background_dark</item>
diff --git a/src/standardPush/java/de/pixart/messenger/services/InstanceIdService.java b/src/standardPush/java/de/pixart/messenger/services/InstanceIdService.java
index d812105aa..9a3309be4 100644
--- a/src/standardPush/java/de/pixart/messenger/services/InstanceIdService.java
+++ b/src/standardPush/java/de/pixart/messenger/services/InstanceIdService.java
@@ -13,12 +13,17 @@ public class InstanceIdService extends FirebaseInstanceIdService {
@Override
public void onTokenRefresh() {
- Intent intent = new Intent(this, XmppConnectionService.class);
+ final Intent intent = new Intent(this, XmppConnectionService.class);
intent.setAction(XmppConnectionService.ACTION_FCM_TOKEN_REFRESH);
try {
- startService(intent);
- } catch (Exception e) {
- Log.e(Config.LOGTAG, "unable to refresh FCM token", e);
+ if (Compatibility.runsAndTargetsTwentySix(this)) {
+ intent.putExtra(EventReceiver.EXTRA_NEEDS_FOREGROUND_SERVICE, true);
+ ContextCompat.startForegroundService(this, intent);
+ } else {
+ startService(intent);
+ }
+ } catch (IllegalStateException e) {
+ Log.e(Config.LOGTAG, "InstanceIdService is not allowed to start service");
}
}
-}
+} \ No newline at end of file
diff --git a/src/standardPush/java/de/pixart/messenger/services/MaintenanceReceiver.java b/src/standardPush/java/de/pixart/messenger/services/MaintenanceReceiver.java
index 9368913bc..5706a487a 100644
--- a/src/standardPush/java/de/pixart/messenger/services/MaintenanceReceiver.java
+++ b/src/standardPush/java/de/pixart/messenger/services/MaintenanceReceiver.java
@@ -3,6 +3,7 @@ package de.pixart.messenger.services;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.support.v4.content.ContextCompat;
import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceId;
@@ -10,6 +11,7 @@ import com.google.firebase.iid.FirebaseInstanceId;
import java.io.IOException;
import de.pixart.messenger.Config;
+import de.pixart.messenger.utils.Compatibility;
public class MaintenanceReceiver extends BroadcastReceiver {
@Override
@@ -25,9 +27,14 @@ public class MaintenanceReceiver extends BroadcastReceiver {
new Thread(() -> {
try {
FirebaseInstanceId.getInstance().deleteInstanceId();
- Intent intent = new Intent(context, XmppConnectionService.class);
+ final Intent intent = new Intent(context, XmppConnectionService.class);
intent.setAction(XmppConnectionService.ACTION_FCM_TOKEN_REFRESH);
- context.startService(intent);
+ if (Compatibility.runsAndTargetsTwentySix(context)) {
+ intent.putExtra(EventReceiver.EXTRA_NEEDS_FOREGROUND_SERVICE, true);
+ ContextCompat.startForegroundService(context, intent);
+ } else {
+ context.startService(intent);
+ }
} catch (IOException e) {
Log.d(Config.LOGTAG, "unable to renew instance token", e);
}
diff --git a/src/standardPush/java/de/pixart/messenger/services/PushMessageReceiver.java b/src/standardPush/java/de/pixart/messenger/services/PushMessageReceiver.java
index 816d11118..f07167f8d 100644
--- a/src/standardPush/java/de/pixart/messenger/services/PushMessageReceiver.java
+++ b/src/standardPush/java/de/pixart/messenger/services/PushMessageReceiver.java
@@ -1,6 +1,7 @@
package de.pixart.messenger.services;
import android.content.Intent;
+import android.support.v4.content.ContextCompat;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
@@ -9,6 +10,7 @@ import com.google.firebase.messaging.RemoteMessage;
import java.util.Map;
import de.pixart.messenger.Config;
+import de.pixart.messenger.utils.Compatibility;
public class PushMessageReceiver extends FirebaseMessagingService {
@@ -18,10 +20,19 @@ public class PushMessageReceiver extends FirebaseMessagingService {
Log.d(Config.LOGTAG, "PushMessageReceiver ignored message because no accounts are enabled");
return;
}
- Map<String, String> data = message.getData();
- Intent intent = new Intent(this, XmppConnectionService.class);
+ final Map<String, String> data = message.getData();
+ final Intent intent = new Intent(this, XmppConnectionService.class);
intent.setAction(XmppConnectionService.ACTION_FCM_MESSAGE_RECEIVED);
intent.putExtra("account", data.get("account"));
- startService(intent);
+ try {
+ if (Compatibility.runsAndTargetsTwentySix(this)) {
+ intent.putExtra(EventReceiver.EXTRA_NEEDS_FOREGROUND_SERVICE, true);
+ ContextCompat.startForegroundService(this, intent);
+ } else {
+ startService(intent);
+ }
+ } catch (IllegalStateException e) {
+ Log.e(Config.LOGTAG, "PushMessageReceiver is not allowed to start service");
+ }
}
-}
+} \ No newline at end of file