aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de')
-rw-r--r--src/main/java/de/pixart/messenger/Config.java1
-rw-r--r--src/main/java/de/pixart/messenger/entities/Contact.java6
-rw-r--r--src/main/java/de/pixart/messenger/entities/MucOptions.java624
-rw-r--r--src/main/java/de/pixart/messenger/parser/PresenceParser.java8
-rw-r--r--src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java2
-rw-r--r--src/main/java/de/pixart/messenger/persistance/FileBackend.java12
-rw-r--r--src/main/java/de/pixart/messenger/services/AudioPlayer.java67
-rw-r--r--src/main/java/de/pixart/messenger/services/AvatarService.java24
-rw-r--r--src/main/java/de/pixart/messenger/services/EventReceiver.java7
-rw-r--r--src/main/java/de/pixart/messenger/services/NotificationService.java16
-rw-r--r--src/main/java/de/pixart/messenger/services/XmppConnectionService.java15
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConversationFragment.java4
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConversationsActivity.java1
-rw-r--r--src/main/java/de/pixart/messenger/ui/ShareWithActivity.java2
-rw-r--r--src/main/java/de/pixart/messenger/ui/XmppActivity.java4
-rw-r--r--src/main/java/de/pixart/messenger/ui/text/FixedURLSpan.java6
-rw-r--r--src/main/java/de/pixart/messenger/ui/util/EditMessageActionModeCallback.java11
-rw-r--r--src/main/java/de/pixart/messenger/utils/Compatibility.java35
-rw-r--r--src/main/java/de/pixart/messenger/utils/Resolver.java23
19 files changed, 461 insertions, 407 deletions
diff --git a/src/main/java/de/pixart/messenger/Config.java b/src/main/java/de/pixart/messenger/Config.java
index e2914f9d3..147bb6873 100644
--- a/src/main/java/de/pixart/messenger/Config.java
+++ b/src/main/java/de/pixart/messenger/Config.java
@@ -45,6 +45,7 @@ public final class Config {
public static final String inviteUserURL = "https://jabber.pix-art.de/i/";
public static final String inviteMUCURL = "https://jabber.pix-art.de/j/";
+ public static final String inviteHostURL = "jabber.pix-art.de"; // without http(s)
public static final String CHANGELOG_URL = "https://github.com/kriztan/Pix-Art-Messenger/blob/master/CHANGELOG.md";
public static final String XMPP_IP = null; //BuildConfig.XMPP_IP; // set to null means disable
diff --git a/src/main/java/de/pixart/messenger/entities/Contact.java b/src/main/java/de/pixart/messenger/entities/Contact.java
index 6edb14ada..a74b09dff 100644
--- a/src/main/java/de/pixart/messenger/entities/Contact.java
+++ b/src/main/java/de/pixart/messenger/entities/Contact.java
@@ -479,10 +479,14 @@ public class Contact implements ListItem, Blockable {
}
}
- public String getAvatar() {
+ public String getAvatarFilename() {
return avatar == null ? null : avatar.getFilename();
}
+ public Avatar getAvatar() {
+ return avatar;
+ }
+
public boolean deleteOtrFingerprint(String fingerprint) {
synchronized (this.keys) {
boolean success = false;
diff --git a/src/main/java/de/pixart/messenger/entities/MucOptions.java b/src/main/java/de/pixart/messenger/entities/MucOptions.java
index 258ded842..cf09e73a7 100644
--- a/src/main/java/de/pixart/messenger/entities/MucOptions.java
+++ b/src/main/java/de/pixart/messenger/entities/MucOptions.java
@@ -25,7 +25,31 @@ import rocks.xmpp.addr.Jid;
@SuppressLint("DefaultLocale")
public class MucOptions {
+ public static final String STATUS_CODE_SELF_PRESENCE = "110";
+ public static final String STATUS_CODE_ROOM_CREATED = "201";
+ public static final String STATUS_CODE_BANNED = "301";
+ public static final String STATUS_CODE_CHANGED_NICK = "303";
+ public static final String STATUS_CODE_KICKED = "307";
+ public static final String STATUS_CODE_AFFILIATION_CHANGE = "321";
+ public static final String STATUS_CODE_LOST_MEMBERSHIP = "322";
+ public static final String STATUS_CODE_SHUTDOWN = "332";
+ private final Set<User> users = new HashSet<>();
+ private final Conversation conversation;
+ public OnRenameListener onRenameListener = null;
private boolean mAutoPushConfiguration = true;
+ private Account account;
+ private ServiceDiscoveryResult serviceDiscoveryResult;
+ private boolean isOnline = false;
+ private Error error = Error.NONE;
+ private User self;
+ private String password = null;
+ public MucOptions(Conversation conversation) {
+ this.account = conversation.getAccount();
+ this.conversation = conversation;
+ this.self = new User(this, createJoinJid(getProposedNick()));
+ this.self.affiliation = Affiliation.of(conversation.getAttribute("affiliation"));
+ this.self.role = Role.of(conversation.getAttribute("role"));
+ }
public Account getAccount() {
return this.conversation.getAccount();
@@ -75,302 +99,6 @@ public class MucOptions {
return MessageArchiveService.Version.has(getFeatures());
}
- public enum Affiliation {
- OWNER(4, R.string.owner),
- ADMIN(3, R.string.admin),
- MEMBER(2, R.string.member),
- OUTCAST(0, R.string.outcast),
- NONE(1, R.string.no_affiliation);
-
- Affiliation(int rank, int resId) {
- this.resId = resId;
- this.rank = rank;
- }
-
- private int resId;
- private int rank;
-
- public int getResId() {
- return resId;
- }
-
- @Override
- public String toString() {
- return name().toLowerCase(Locale.US);
- }
-
- public boolean outranks(Affiliation affiliation) {
- return rank > affiliation.rank;
- }
-
- public boolean ranks(Affiliation affiliation) {
- return rank >= affiliation.rank;
- }
-
- public static Affiliation of(@Nullable String value) {
- if (value == null) {
- return NONE;
- }
- try {
- return Affiliation.valueOf(value.toUpperCase(Locale.US));
- } catch (IllegalArgumentException e) {
- return NONE;
- }
- }
- }
-
- public enum Role {
- MODERATOR(R.string.moderator, 3),
- VISITOR(R.string.visitor, 1),
- PARTICIPANT(R.string.participant, 2),
- NONE(R.string.no_role, 0);
-
- Role(int resId, int rank) {
- this.resId = resId;
- this.rank = rank;
- }
-
- private int resId;
- private int rank;
-
- public int getResId() {
- return resId;
- }
-
- @Override
- public String toString() {
- return name().toLowerCase(Locale.US);
- }
-
- public boolean ranks(Role role) {
- return rank >= role.rank;
- }
-
- public static Role of(@Nullable String value) {
- if (value == null) {
- return NONE;
- }
- try {
- return Role.valueOf(value.toUpperCase(Locale.US));
- } catch (IllegalArgumentException e) {
- return NONE;
- }
- }
- }
-
- public enum Error {
- NO_RESPONSE,
- SERVER_NOT_FOUND,
- NONE,
- NICK_IN_USE,
- PASSWORD_REQUIRED,
- BANNED,
- MEMBERS_ONLY,
- RESOURCE_CONSTRAINT,
- KICKED,
- SHUTDOWN,
- DESTROYED,
- INVALID_NICK,
- UNKNOWN
- }
-
- public static final String STATUS_CODE_SELF_PRESENCE = "110";
- public static final String STATUS_CODE_ROOM_CREATED = "201";
- public static final String STATUS_CODE_BANNED = "301";
- public static final String STATUS_CODE_CHANGED_NICK = "303";
- public static final String STATUS_CODE_KICKED = "307";
- public static final String STATUS_CODE_AFFILIATION_CHANGE = "321";
- public static final String STATUS_CODE_LOST_MEMBERSHIP = "322";
- public static final String STATUS_CODE_SHUTDOWN = "332";
-
- private interface OnEventListener {
- void onSuccess();
-
- void onFailure();
- }
-
- public interface OnRenameListener extends OnEventListener {
-
- }
-
- public static class User implements Comparable<User> {
- private Role role = Role.NONE;
- private Affiliation affiliation = Affiliation.NONE;
- private Jid realJid;
- private Jid fullJid;
- private long pgpKeyId = 0;
- private Avatar avatar;
- private MucOptions options;
- private ChatState chatState = Config.DEFAULT_CHATSTATE;
-
- public User(MucOptions options, Jid from) {
- this.options = options;
- this.fullJid = from;
- }
-
- public String getName() {
- return fullJid == null ? null : fullJid.getResource();
- }
-
- public void setRealJid(Jid jid) {
- this.realJid = jid != null ? jid.asBareJid() : null;
- }
-
- public Role getRole() {
- return this.role;
- }
-
- public void setRole(String role) {
- this.role = Role.of(role);
- }
-
- public Affiliation getAffiliation() {
- return this.affiliation;
- }
-
- public void setAffiliation(String affiliation) {
- this.affiliation = Affiliation.of(affiliation);
- }
-
- public void setPgpKeyId(long id) {
- this.pgpKeyId = id;
- }
-
- public long getPgpKeyId() {
- if (this.pgpKeyId != 0) {
- return this.pgpKeyId;
- } else if (realJid != null) {
- return getAccount().getRoster().getContact(realJid).getPgpKeyId();
- } else {
- return 0;
- }
- }
-
- public Contact getContact() {
- if (fullJid != null) {
- return getAccount().getRoster().getContactFromRoster(realJid);
- } else if (realJid != null) {
- return getAccount().getRoster().getContact(realJid);
- } else {
- return null;
- }
- }
-
- public boolean setAvatar(Avatar avatar) {
- if (this.avatar != null && this.avatar.equals(avatar)) {
- return false;
- } else {
- this.avatar = avatar;
- return true;
- }
- }
-
- public String getAvatar() {
- return avatar == null ? null : avatar.getFilename();
- }
-
- public Account getAccount() {
- return options.getAccount();
- }
-
- public Conversation getConversation() {
- return options.getConversation();
- }
-
- public Jid getFullJid() {
- return fullJid;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- User user = (User) o;
-
- if (role != user.role) return false;
- if (affiliation != user.affiliation) return false;
- if (realJid != null ? !realJid.equals(user.realJid) : user.realJid != null)
- return false;
- return fullJid != null ? fullJid.equals(user.fullJid) : user.fullJid == null;
-
- }
-
- public boolean isDomain() {
- return realJid != null && realJid.getLocal() == null && role == Role.NONE;
- }
-
- @Override
- public int hashCode() {
- int result = role != null ? role.hashCode() : 0;
- result = 31 * result + (affiliation != null ? affiliation.hashCode() : 0);
- result = 31 * result + (realJid != null ? realJid.hashCode() : 0);
- result = 31 * result + (fullJid != null ? fullJid.hashCode() : 0);
- return result;
- }
-
- @Override
- public String toString() {
- return "[fulljid:" + String.valueOf(fullJid) + ",realjid:" + String.valueOf(realJid) + ",affiliation" + affiliation.toString() + "]";
- }
-
- public boolean realJidMatchesAccount() {
- return realJid != null && realJid.equals(options.account.getJid().asBareJid());
- }
-
- @Override
- public int compareTo(@NonNull User another) {
- if (another.getAffiliation().outranks(getAffiliation())) {
- return 1;
- } else if (getAffiliation().outranks(another.getAffiliation())) {
- return -1;
- } else {
- return getComparableName().compareToIgnoreCase(another.getComparableName());
- }
- }
-
-
- private String getComparableName() {
- Contact contact = getContact();
- if (contact != null) {
- return contact.getDisplayName();
- } else {
- String name = getName();
- return name == null ? "" : name;
- }
- }
-
- public Jid getRealJid() {
- return realJid;
- }
-
- public boolean setChatState(ChatState chatState) {
- if (this.chatState == chatState) {
- return false;
- }
- this.chatState = chatState;
- return true;
- }
- }
-
- private Account account;
- private final Set<User> users = new HashSet<>();
- private ServiceDiscoveryResult serviceDiscoveryResult;
- private final Conversation conversation;
- private boolean isOnline = false;
- private Error error = Error.NONE;
- public OnRenameListener onRenameListener = null;
- private User self;
- private String password = null;
-
- public MucOptions(Conversation conversation) {
- this.account = conversation.getAccount();
- this.conversation = conversation;
- this.self = new User(this, createJoinJid(getProposedNick()));
- this.self.affiliation = Affiliation.of(conversation.getAttribute("affiliation"));
- this.self.role = Role.of(conversation.getAttribute("role"));
- }
-
public boolean updateConfiguration(ServiceDiscoveryResult serviceDiscoveryResult) {
this.serviceDiscoveryResult = serviceDiscoveryResult;
String name;
@@ -400,7 +128,7 @@ public class MucOptions {
}
public String getAvatar() {
- return account.getRoster().getContact(conversation.getJid()).getAvatar();
+ return account.getRoster().getContact(conversation.getJid()).getAvatarFilename();
}
public boolean hasFeature(String feature) {
@@ -559,10 +287,10 @@ public class MucOptions {
return null;
}
- public User findOrCreateUserByRealJid(Jid jid) {
+ public User findOrCreateUserByRealJid(Jid jid, Jid fullJid) {
User user = findUserByRealJid(jid);
if (user == null) {
- user = new User(this, null);
+ user = new User(this, fullJid);
user.setRealJid(jid);
}
return user;
@@ -570,12 +298,7 @@ public class MucOptions {
public User findUser(ReadByMarker readByMarker) {
if (readByMarker.getRealJid() != null) {
- User user = findUserByRealJid(readByMarker.getRealJid().asBareJid());
- if (user == null) {
- user = new User(this, readByMarker.getFullJid());
- user.setRealJid(readByMarker.getRealJid());
- }
- return user;
+ return findOrCreateUserByRealJid(readByMarker.getRealJid().asBareJid(), readByMarker.getFullJid());
} else if (readByMarker.getFullJid() != null) {
return findUserByFullJid(readByMarker.getFullJid());
} else {
@@ -591,11 +314,6 @@ public class MucOptions {
return findUserByFullJid(jid) != null;
}
- public void setError(Error error) {
- this.isOnline = isOnline && error == Error.NONE;
- this.error = error;
- }
-
public boolean setOnline() {
boolean before = this.isOnline;
this.isOnline = true;
@@ -638,7 +356,7 @@ public class MucOptions {
HashSet<Jid> jids = new HashSet<>();
jids.add(account.getJid().asBareJid());
synchronized (users) {
- for(User user : users) {
+ for (User user : users) {
if (user.getRealJid() == null || (user.getRealJid().getLocal() != null && jids.add(user.getRealJid()))) {
subset.add(user);
}
@@ -684,6 +402,11 @@ public class MucOptions {
return this.error;
}
+ public void setError(Error error) {
+ this.isOnline = isOnline && error == Error.NONE;
+ this.error = error;
+ }
+
public void setOnRenameListener(OnRenameListener listener) {
this.onRenameListener = listener;
}
@@ -732,21 +455,18 @@ public class MucOptions {
return users;
}
-
public int NumberOfUsers() {
List<User> users = getUsersRelevantForNameAndAvatar();
if (users.size() >= 1) {
- return users.size();
+ return users.size() + 1; // add 1 for yourself
} else {
- return 0;
+ return 1;
}
}
-
-
public String createNameFromParticipants() {
List<User> users = getUsersRelevantForNameAndAvatar();
- if (users.size() >= 1) {
+ if (users.size() >= 2) {
StringBuilder builder = new StringBuilder();
for (User user : users) {
if (builder.length() != 0) {
@@ -850,4 +570,274 @@ public class MucOptions {
}
return members;
}
+
+ public enum Affiliation {
+ OWNER(4, R.string.owner),
+ ADMIN(3, R.string.admin),
+ MEMBER(2, R.string.member),
+ OUTCAST(0, R.string.outcast),
+ NONE(1, R.string.no_affiliation);
+
+ private int resId;
+ private int rank;
+ Affiliation(int rank, int resId) {
+ this.resId = resId;
+ this.rank = rank;
+ }
+
+ public static Affiliation of(@Nullable String value) {
+ if (value == null) {
+ return NONE;
+ }
+ try {
+ return Affiliation.valueOf(value.toUpperCase(Locale.US));
+ } catch (IllegalArgumentException e) {
+ return NONE;
+ }
+ }
+
+ public int getResId() {
+ return resId;
+ }
+
+ @Override
+ public String toString() {
+ return name().toLowerCase(Locale.US);
+ }
+
+ public boolean outranks(Affiliation affiliation) {
+ return rank > affiliation.rank;
+ }
+
+ public boolean ranks(Affiliation affiliation) {
+ return rank >= affiliation.rank;
+ }
+ }
+
+ public enum Role {
+ MODERATOR(R.string.moderator, 3),
+ VISITOR(R.string.visitor, 1),
+ PARTICIPANT(R.string.participant, 2),
+ NONE(R.string.no_role, 0);
+
+ private int resId;
+ private int rank;
+ Role(int resId, int rank) {
+ this.resId = resId;
+ this.rank = rank;
+ }
+
+ public static Role of(@Nullable String value) {
+ if (value == null) {
+ return NONE;
+ }
+ try {
+ return Role.valueOf(value.toUpperCase(Locale.US));
+ } catch (IllegalArgumentException e) {
+ return NONE;
+ }
+ }
+
+ public int getResId() {
+ return resId;
+ }
+
+ @Override
+ public String toString() {
+ return name().toLowerCase(Locale.US);
+ }
+
+ public boolean ranks(Role role) {
+ return rank >= role.rank;
+ }
+ }
+
+ public enum Error {
+ NO_RESPONSE,
+ SERVER_NOT_FOUND,
+ NONE,
+ NICK_IN_USE,
+ PASSWORD_REQUIRED,
+ BANNED,
+ MEMBERS_ONLY,
+ RESOURCE_CONSTRAINT,
+ KICKED,
+ SHUTDOWN,
+ DESTROYED,
+ INVALID_NICK,
+ UNKNOWN
+ }
+
+ private interface OnEventListener {
+ void onSuccess();
+
+ void onFailure();
+ }
+
+ public interface OnRenameListener extends OnEventListener {
+
+ }
+
+ public static class User implements Comparable<User> {
+ private Role role = Role.NONE;
+ private Affiliation affiliation = Affiliation.NONE;
+ private Jid realJid;
+ private Jid fullJid;
+ private long pgpKeyId = 0;
+ private Avatar avatar;
+ private MucOptions options;
+ private ChatState chatState = Config.DEFAULT_CHATSTATE;
+
+ public User(MucOptions options, Jid from) {
+ this.options = options;
+ this.fullJid = from;
+ }
+
+ public String getName() {
+ return fullJid == null ? null : fullJid.getResource();
+ }
+
+ public Role getRole() {
+ return this.role;
+ }
+
+ public void setRole(String role) {
+ this.role = Role.of(role);
+ }
+
+ public Affiliation getAffiliation() {
+ return this.affiliation;
+ }
+
+ public void setAffiliation(String affiliation) {
+ this.affiliation = Affiliation.of(affiliation);
+ }
+
+ public long getPgpKeyId() {
+ if (this.pgpKeyId != 0) {
+ return this.pgpKeyId;
+ } else if (realJid != null) {
+ return getAccount().getRoster().getContact(realJid).getPgpKeyId();
+ } else {
+ return 0;
+ }
+ }
+
+ public void setPgpKeyId(long id) {
+ this.pgpKeyId = id;
+ }
+
+ public Contact getContact() {
+ if (fullJid != null) {
+ return getAccount().getRoster().getContactFromRoster(realJid);
+ } else if (realJid != null) {
+ return getAccount().getRoster().getContact(realJid);
+ } else {
+ return null;
+ }
+ }
+
+ public boolean setAvatar(Avatar avatar) {
+ if (this.avatar != null && this.avatar.equals(avatar)) {
+ return false;
+ } else {
+ this.avatar = avatar;
+ return true;
+ }
+ }
+
+ public String getAvatar() {
+ if (avatar != null) {
+ return avatar.getFilename();
+ }
+ Avatar avatar = realJid != null ? getAccount().getRoster().getContact(realJid).getAvatar() : null;
+ return avatar == null ? null : avatar.getFilename();
+ }
+
+ public Account getAccount() {
+ return options.getAccount();
+ }
+
+ public Conversation getConversation() {
+ return options.getConversation();
+ }
+
+ public Jid getFullJid() {
+ return fullJid;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ User user = (User) o;
+
+ if (role != user.role) return false;
+ if (affiliation != user.affiliation) return false;
+ if (realJid != null ? !realJid.equals(user.realJid) : user.realJid != null)
+ return false;
+ return fullJid != null ? fullJid.equals(user.fullJid) : user.fullJid == null;
+
+ }
+
+ public boolean isDomain() {
+ return realJid != null && realJid.getLocal() == null && role == Role.NONE;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = role != null ? role.hashCode() : 0;
+ result = 31 * result + (affiliation != null ? affiliation.hashCode() : 0);
+ result = 31 * result + (realJid != null ? realJid.hashCode() : 0);
+ result = 31 * result + (fullJid != null ? fullJid.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "[fulljid:" + String.valueOf(fullJid) + ",realjid:" + String.valueOf(realJid) + ",affiliation" + affiliation.toString() + "]";
+ }
+
+ public boolean realJidMatchesAccount() {
+ return realJid != null && realJid.equals(options.account.getJid().asBareJid());
+ }
+
+ @Override
+ public int compareTo(@NonNull User another) {
+ if (another.getAffiliation().outranks(getAffiliation())) {
+ return 1;
+ } else if (getAffiliation().outranks(another.getAffiliation())) {
+ return -1;
+ } else {
+ return getComparableName().compareToIgnoreCase(another.getComparableName());
+ }
+ }
+
+ private String getComparableName() {
+ Contact contact = getContact();
+ if (contact != null) {
+ return contact.getDisplayName();
+ } else {
+ String name = getName();
+ return name == null ? "" : name;
+ }
+ }
+
+ public Jid getRealJid() {
+ return realJid;
+ }
+
+ public void setRealJid(Jid jid) {
+ this.realJid = jid != null ? jid.asBareJid() : null;
+ }
+
+ public boolean setChatState(ChatState chatState) {
+ if (this.chatState == chatState) {
+ return false;
+ }
+ this.chatState = chatState;
+ return true;
+ }
+ }
}
diff --git a/src/main/java/de/pixart/messenger/parser/PresenceParser.java b/src/main/java/de/pixart/messenger/parser/PresenceParser.java
index 39a3cfeba..6a878d27f 100644
--- a/src/main/java/de/pixart/messenger/parser/PresenceParser.java
+++ b/src/main/java/de/pixart/messenger/parser/PresenceParser.java
@@ -115,6 +115,14 @@ public class PresenceParser extends AbstractParser implements
if (user.setAvatar(avatar)) {
mXmppConnectionService.getAvatarService().clear(user);
}
+ if (user.getRealJid() != null) {
+ Contact c = conversation.getAccount().getRoster().getContact(user.getRealJid());
+ if (c.setAvatar(avatar)) {
+ mXmppConnectionService.syncRoster(conversation.getAccount());
+ mXmppConnectionService.getAvatarService().clear(c);
+ mXmppConnectionService.updateRosterUi();
+ }
+ }
} else if (mXmppConnectionService.isDataSaverDisabled()) {
mXmppConnectionService.fetchAvatar(mucOptions.getAccount(), avatar);
}
diff --git a/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java b/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java
index 365f8fa87..4cc5b7955 100644
--- a/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java
+++ b/src/main/java/de/pixart/messenger/persistance/DatabaseBackend.java
@@ -925,7 +925,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.getAvatar() != null) {
+ if (contact.getOption(Contact.Options.IN_ROSTER) || contact.getAvatarFilename() != null) {
db.insert(Contact.TABLENAME, null, contact.getContentValues());
} else {
String where = Contact.ACCOUNT + "=? AND " + Contact.JID + "=?";
diff --git a/src/main/java/de/pixart/messenger/persistance/FileBackend.java b/src/main/java/de/pixart/messenger/persistance/FileBackend.java
index 822fa6318..8397a7bb8 100644
--- a/src/main/java/de/pixart/messenger/persistance/FileBackend.java
+++ b/src/main/java/de/pixart/messenger/persistance/FileBackend.java
@@ -491,6 +491,18 @@ public class FileBackend {
updateFileParams(message);
}
+ public boolean unusualBounds(Uri image) {
+ try {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeStream(mXmppConnectionService.getContentResolver().openInputStream(image), null, options);
+ float ratio = (float) options.outHeight / options.outWidth;
+ return ratio > (21.0f / 9.0f) || ratio < (9.0f / 21.0f);
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
private int getRotation(File file) {
return getRotation(Uri.parse("file://" + file.getAbsolutePath()));
}
diff --git a/src/main/java/de/pixart/messenger/services/AudioPlayer.java b/src/main/java/de/pixart/messenger/services/AudioPlayer.java
index e3e17fdb0..ca6e7c3fa 100644
--- a/src/main/java/de/pixart/messenger/services/AudioPlayer.java
+++ b/src/main/java/de/pixart/messenger/services/AudioPlayer.java
@@ -9,7 +9,6 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioManager;
-import android.media.MediaPlayer;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
@@ -37,14 +36,13 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
private static final int REFRESH_INTERVAL = 250;
private static final Object LOCK = new Object();
- private static MediaPlayerWrapper player = null;
+ private static MediaPlayer player = null;
private static Message currentlyPlayingMessage = null;
+ private static PowerManager.WakeLock wakeLock;
private final MessageAdapter messageAdapter;
private final WeakReferenceSet<RelativeLayout> audioPlayerLayouts = new WeakReferenceSet<>();
private final SensorManager sensorManager;
private final Sensor proximitySensor;
- private static PowerManager.WakeLock wakeLock;
-
private final PendingItem<WeakReference<ImageButton>> pendingOnClickView = new PendingItem<>();
private final Handler handler = new Handler();
@@ -54,17 +52,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
this.messageAdapter = adapter;
this.sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
this.proximitySensor = this.sensorManager == null ? null : this.sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
- if (Build.VERSION.SDK_INT >= 21) {
- synchronized (AudioPlayer.LOCK) {
- if (AudioPlayer.wakeLock == null) {
- final PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- AudioPlayer.wakeLock = powerManager == null ? null : powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, AudioPlayer.class.getSimpleName());
- AudioPlayer.wakeLock.setReferenceCounted(false);
- }
- }
- } else {
- AudioPlayer.wakeLock = null;
- }
+ initializeProximityWakeLock(context);
synchronized (AudioPlayer.LOCK) {
if (AudioPlayer.player != null) {
AudioPlayer.player.setOnCompletionListener(this);
@@ -79,6 +67,20 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
return String.format(Locale.ENGLISH, "%d:%02d", ms / 60000, Math.min(Math.round((ms % 60000) / 1000f), 59));
}
+ private void initializeProximityWakeLock(Context context) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ synchronized (AudioPlayer.LOCK) {
+ if (AudioPlayer.wakeLock == null) {
+ final PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ AudioPlayer.wakeLock = powerManager == null ? null : powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, AudioPlayer.class.getSimpleName());
+ AudioPlayer.wakeLock.setReferenceCounted(false);
+ }
+ }
+ } else {
+ AudioPlayer.wakeLock = null;
+ }
+ }
+
public void init(RelativeLayout audioPlayer, Message message) {
synchronized (AudioPlayer.LOCK) {
audioPlayer.setTag(message);
@@ -119,9 +121,6 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
viewHolder.runtime.setText(formatTime(message.getFileParams().runtime));
viewHolder.progress.setProgress(0);
viewHolder.progress.setEnabled(false);
- messageAdapter.flagScreenOff();
- releaseProximityWakeLock();
- messageAdapter.flagEnableInputs();
return false;
}
}
@@ -141,6 +140,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
ActivityCompat.requestPermissions(messageAdapter.getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, ConversationsActivity.REQUEST_PLAY_PAUSE);
return;
}
+ initializeProximityWakeLock(playPause.getContext());
final RelativeLayout audioPlayer = (RelativeLayout) playPause.getParent();
final ViewHolder viewHolder = ViewHolder.get(audioPlayer);
final Message message = (Message) audioPlayer.getTag();
@@ -158,7 +158,6 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
player.pause();
messageAdapter.flagScreenOff();
releaseProximityWakeLock();
- messageAdapter.flagEnableInputs();
viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp);
} else {
viewHolder.progress.setEnabled(true);
@@ -178,7 +177,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
}
private boolean play(ViewHolder viewHolder, Message message, boolean earpiece) {
- AudioPlayer.player = new MediaPlayerWrapper();
+ AudioPlayer.player = new MediaPlayer();
try {
AudioPlayer.currentlyPlayingMessage = message;
AudioPlayer.player.setAudioStreamType(earpiece ? AudioManager.STREAM_VOICE_CALL : AudioManager.STREAM_MUSIC);
@@ -188,11 +187,6 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
AudioPlayer.player.start();
messageAdapter.flagScreenOn();
acquireProximityWakeLock();
- if (earpiece) {
- messageAdapter.flagDisableInputs();
- } else {
- messageAdapter.flagEnableInputs();
- }
viewHolder.progress.setEnabled(true);
viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp);
sensorManager.registerListener(this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
@@ -200,7 +194,6 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
} catch (Exception e) {
messageAdapter.flagScreenOff();
releaseProximityWakeLock();
- messageAdapter.flagEnableInputs();
AudioPlayer.currentlyPlayingMessage = null;
sensorManager.unregisterListener(this);
return false;
@@ -234,10 +227,8 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
AudioPlayer.player.release();
messageAdapter.flagScreenOff();
releaseProximityWakeLock();
- messageAdapter.flagEnableInputs();
AudioPlayer.player = null;
resetPlayerUi();
- sensorManager.unregisterListener(this);
}
private void resetPlayerUi() {
@@ -271,7 +262,6 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
mediaPlayer.release();
messageAdapter.flagScreenOff();
releaseProximityWakeLock();
- messageAdapter.flagEnableInputs();
resetPlayerUi();
sensorManager.unregisterListener(this);
}
@@ -293,12 +283,10 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
-
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
-
}
public void stop() {
@@ -393,6 +381,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
+
private void acquireProximityWakeLock() {
synchronized (AudioPlayer.LOCK) {
if (wakeLock != null) {
@@ -400,6 +389,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
}
}
}
+
private void releaseProximityWakeLock() {
synchronized (AudioPlayer.LOCK) {
if (wakeLock != null && wakeLock.isHeld()) {
@@ -407,6 +397,7 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
}
}
}
+
private ViewHolder getCurrentViewHolder() {
for (WeakReference<RelativeLayout> audioPlayer : audioPlayerLayouts) {
final Message message = (Message) audioPlayer.get().getTag();
@@ -439,18 +430,4 @@ public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompleti
this.darkBackground = darkBackground;
}
}
-
- private static class MediaPlayerWrapper extends MediaPlayer {
- private int streamType;
-
- private int getAudioStreamType() {
- return streamType;
- }
-
- @Override
- public void setAudioStreamType(int streamType) {
- this.streamType = streamType;
- super.setAudioStreamType(streamType);
- }
- }
} \ 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 bf415515b..aa861c147 100644
--- a/src/main/java/de/pixart/messenger/services/AvatarService.java
+++ b/src/main/java/de/pixart/messenger/services/AvatarService.java
@@ -80,8 +80,8 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
if (avatar != null || cachedOnly) {
return avatar;
}
- if (avatar == null && contact.getAvatar() != null) {
- avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatar(), size);
+ if (avatar == null && contact.getAvatarFilename() != null) {
+ avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatarFilename(), size);
}
if (avatar == null && contact.getProfilePhoto() != null) {
try {
@@ -146,7 +146,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
public Bitmap get(final MucOptions.User user, final int size, boolean cachedOnly) {
Contact c = user.getContact();
- if (c != null && (c.getProfilePhoto() != null || c.getAvatar() != null || user.getAvatar() == null)) {
+ if (c != null && (c.getProfilePhoto() != null || c.getAvatarFilename() != null || user.getAvatar() == null)) {
return get(c, size, cachedOnly);
} else {
return getImpl(user, size, cachedOnly);
@@ -183,6 +183,10 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
}
}
for (Conversation conversation : mXmppConnectionService.findAllConferencesWith(contact)) {
+ MucOptions.User user = conversation.getMucOptions().findUserByRealJid(contact.getJid().asBareJid());
+ if (user != null) {
+ clear(user);
+ }
clear(conversation);
}
}
@@ -234,7 +238,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
Jid jid = bookmark.getJid();
Account account = bookmark.getAccount();
Contact contact = jid == null ? null : account.getRoster().getContact(jid);
- if (contact != null && contact.getAvatar() != null) {
+ if (contact != null && contact.getAvatarFilename() != null) {
return get(contact, size, cachedOnly);
}
String seed = jid != null ? jid.asBareJid().toString() : null;
@@ -414,14 +418,14 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
return get(message.getCounterparts(), size, cachedOnly);
} else if (message.getStatus() == Message.STATUS_RECEIVED) {
Contact c = message.getContact();
- if (c != null && (c.getProfilePhoto() != null || c.getAvatar() != null)) {
+ if (c != null && (c.getProfilePhoto() != null || c.getAvatarFilename() != null)) {
return get(c, size, cachedOnly);
} else if (conversation instanceof Conversation && message.getConversation().getMode() == Conversation.MODE_MULTI) {
final Jid trueCounterpart = message.getTrueCounterpart();
final MucOptions mucOptions = ((Conversation) conversation).getMucOptions();
MucOptions.User user;
if (trueCounterpart != null) {
- user = mucOptions.findUserByRealJid(trueCounterpart);
+ user = mucOptions.findOrCreateUserByRealJid(trueCounterpart, message.getCounterpart());
} else {
user = mucOptions.findUserByFullJid(message.getCounterpart());
}
@@ -520,11 +524,11 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
Contact contact = user.getContact();
if (contact != null) {
Uri uri = null;
- if (contact.getAvatar() != null) {
- uri = mXmppConnectionService.getFileBackend().getAvatarUri(
- contact.getAvatar());
- } else if (contact.getProfilePhoto() != null) {
+ 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 529741ead..a77db569e 100644
--- a/src/main/java/de/pixart/messenger/services/EventReceiver.java
+++ b/src/main/java/de/pixart/messenger/services/EventReceiver.java
@@ -8,6 +8,7 @@ import android.support.v4.content.ContextCompat;
import android.util.Log;
import de.pixart.messenger.Config;
+import de.pixart.messenger.utils.Compatibility;
public class EventReceiver extends BroadcastReceiver {
@@ -24,7 +25,11 @@ public class EventReceiver extends BroadcastReceiver {
final String action = originalIntent.getAction();
if (action.equals("ui") || hasEnabledAccounts(context)) {
try {
- ContextCompat.startForegroundService(context, intentForService);
+ if (Compatibility.runsAndTargetsTwentySix(context)) {
+ ContextCompat.startForegroundService(context, intentForService);
+ } else {
+ context.startService(intentForService);
+ }
} catch (RuntimeException e) {
Log.d(Config.LOGTAG, "EventReceiver was unable to start service");
}
diff --git a/src/main/java/de/pixart/messenger/services/NotificationService.java b/src/main/java/de/pixart/messenger/services/NotificationService.java
index 8f82207ac..4982e9fe2 100644
--- a/src/main/java/de/pixart/messenger/services/NotificationService.java
+++ b/src/main/java/de/pixart/messenger/services/NotificationService.java
@@ -397,10 +397,12 @@ public class NotificationService {
if (!summaryOnly) {
for (Map.Entry<String, ArrayList<Message>> entry : notifications.entrySet()) {
String uuid = entry.getKey();
- Builder singleBuilder = buildSingleConversations(entry.getValue(), notifyOnlyOneChild ? conversations.contains(uuid) : notify);
+ final boolean notifyThis = notifyOnlyOneChild ? conversations.contains(uuid) : notify;
+ Builder singleBuilder = buildSingleConversations(entry.getValue(), notifyThis);
if (!notifyOnlyOneChild) {
singleBuilder.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY);
}
+ modifyForSoundVibrationAndLight(singleBuilder, notifyThis, preferences);
singleBuilder.setGroup(CONVERSATIONS_GROUP);
setNotificationColor(singleBuilder);
notify(entry.getKey(), NOTIFICATION_ID, singleBuilder.build());
@@ -845,7 +847,7 @@ public class NotificationService {
public Notification createForegroundNotification() {
final Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService);
mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.conversations_foreground_service));
- if (Compatibility.twentySix() || Config.SHOW_CONNECTED_ACCOUNTS) {
+ if (Compatibility.runsAndTargetsTwentySix(mXmppConnectionService) || Config.SHOW_CONNECTED_ACCOUNTS) {
List<Account> accounts = mXmppConnectionService.getAccounts();
int enabled = 0;
int connected = 0;
@@ -896,7 +898,7 @@ public class NotificationService {
mBuilder.setWhen(0);
mBuilder.setPriority(Notification.PRIORITY_LOW);
mBuilder.setSmallIcon(R.drawable.ic_link_white_24dp);
- if (Compatibility.twentySix()) {
+ if (Compatibility.runsTwentySix()) {
mBuilder.setChannelId(FOREGROUND_CHANNEL_ID);
}
return mBuilder.build();
@@ -949,7 +951,7 @@ public class NotificationService {
145,
new Intent(mXmppConnectionService, ManageAccountActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT));
- if (Compatibility.twentySix()) {
+ if (Compatibility.runsTwentySix()) {
mBuilder.setChannelId(ERROR_CHANNEL_ID);
}
notify(ERROR_NOTIFICATION_ID, mBuilder.build());
@@ -962,7 +964,7 @@ public class NotificationService {
mBuilder.setSmallIcon(R.drawable.ic_hourglass_empty_white_24dp);
mBuilder.setContentIntent(createContentIntent(message.getConversation()));
mBuilder.setOngoing(true);
- if (Compatibility.twentySix()) {
+ if (Compatibility.runsTwentySix()) {
mBuilder.setChannelId(VIDEOCOMPRESSION_CHANNEL_ID);
}
Notification notification = mBuilder.build();
@@ -980,7 +982,7 @@ public class NotificationService {
mBuilder.setProgress(0, 0, true);
mBuilder.setSmallIcon(R.drawable.ic_import_export_white_24dp);
mBuilder.setOngoing(true);
- if (Compatibility.twentySix()) {
+ if (Compatibility.runsTwentySix()) {
mBuilder.setChannelId(BACKUP_CHANNEL_ID);
}
return mBuilder.build();
@@ -998,7 +1000,7 @@ public class NotificationService {
mBuilder.setSmallIcon(R.drawable.ic_update_notification);
mBuilder.setContentIntent(intent);
mBuilder.setOngoing(true);
- if (Compatibility.twentySix()) {
+ if (Compatibility.runsTwentySix()) {
mBuilder.setChannelId(UPDATE_CHANNEL_ID);
}
return mBuilder.build();
diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
index 525354957..132ede7b6 100644
--- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
+++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
@@ -522,7 +522,8 @@ public class XmppConnectionService extends Service {
if ("never".equals(compressPictures)
|| ("auto".equals(compressPictures) && getFileBackend().useImageAsIs(uri))
- || (mimeType != null && mimeType.endsWith("/gif"))) {
+ || (mimeType != null && mimeType.endsWith("/gif"))
+ || getFileBackend().unusualBounds(uri)) {
Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": not compressing picture. sending as file");
attachFileToConversation(conversation, uri, mimeType, callback);
return;
@@ -1103,7 +1104,7 @@ public class XmppConnectionService extends Service {
Resolver.init(this);
this.mRandom = new SecureRandom();
updateMemorizingTrustmanager();
- if (Compatibility.twentySix()) {
+ if (Compatibility.runsTwentySix()) {
mNotificationService.initializeChannels();
}
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
@@ -3460,6 +3461,14 @@ public class XmppConnectionService extends Service {
updateConversationUi();
updateMucRosterUi();
}
+ if (user.getRealJid() != null) {
+ Contact contact = account.getRoster().getContact(user.getRealJid());
+ if (contact.setAvatar(avatar)) {
+ syncRoster(account);
+ getAvatarService().clear(contact);
+ updateRosterUi();
+ }
+ }
}
}
}
@@ -3800,7 +3809,7 @@ public class XmppConnectionService extends Service {
public Conversation findUniqueConversationByJid(XmppUri xmppUri) {
List<Conversation> findings = new ArrayList<>();
for (Conversation c : getConversations()) {
- if (c.getJid().asBareJid().equals(xmppUri.getJid()) && ((c.getMode() == Conversational.MODE_MULTI) == xmppUri.isAction(XmppUri.ACTION_JOIN))) {
+ if (c.getAccount().isEnabled() && c.getJid().asBareJid().equals(xmppUri.getJid()) && ((c.getMode() == Conversational.MODE_MULTI) == xmppUri.isAction(XmppUri.ACTION_JOIN))) {
findings.add(c);
}
}
diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
index d326058e7..a0f4bf894 100644
--- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
+++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
@@ -1221,7 +1221,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
Jid tcp = message.getTrueCounterpart();
Jid cp = message.getCounterpart();
if (cp != null && !cp.isBareJid()) {
- User userByRealJid = tcp != null ? conversation.getMucOptions().findOrCreateUserByRealJid(tcp) : null;
+ User userByRealJid = tcp != null ? conversation.getMucOptions().findOrCreateUserByRealJid(tcp, cp) : null;
final User user = userByRealJid != null ? userByRealJid : conversation.getMucOptions().findUserByFullJid(cp);
final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
popupMenu.inflate(R.menu.muc_details_context);
@@ -2278,7 +2278,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
private void processExtras(Bundle extras) {
final String downloadUuid = extras.getString(ConversationsActivity.EXTRA_DOWNLOAD_UUID);
- final String text = extras.getString(ConversationsActivity.EXTRA_TEXT);
+ final String text = extras.getString(Intent.EXTRA_TEXT);
final String nick = extras.getString(ConversationsActivity.EXTRA_NICK);
final boolean asQuote = extras.getBoolean(ConversationsActivity.EXTRA_AS_QUOTE);
final boolean pm = extras.getBoolean(ConversationsActivity.EXTRA_IS_PRIVATE_MESSAGE, false);
diff --git a/src/main/java/de/pixart/messenger/ui/ConversationsActivity.java b/src/main/java/de/pixart/messenger/ui/ConversationsActivity.java
index 8d8e5386a..2d07be344 100644
--- a/src/main/java/de/pixart/messenger/ui/ConversationsActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ConversationsActivity.java
@@ -105,7 +105,6 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
public static final String ACTION_VIEW_CONVERSATION = "de.pixart.messenger.VIEW";
public static final String EXTRA_CONVERSATION = "conversationUuid";
public static final String EXTRA_DOWNLOAD_UUID = "de.pixart.messenger.download_uuid";
- public static final String EXTRA_TEXT = "text";
public static final String EXTRA_AS_QUOTE = "as_quote";
public static final String EXTRA_NICK = "nick";
public static final String EXTRA_IS_PRIVATE_MESSAGE = "pm";
diff --git a/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java b/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java
index da3d2ff8f..a5d64c820 100644
--- a/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java
@@ -174,7 +174,7 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else if (share.text != null) {
intent.setAction(ConversationsActivity.ACTION_VIEW_CONVERSATION);
- intent.putExtra(ConversationsActivity.EXTRA_TEXT, share.text);
+ intent.putExtra(Intent.EXTRA_TEXT, share.text);
}
startActivity(intent);
finish();
diff --git a/src/main/java/de/pixart/messenger/ui/XmppActivity.java b/src/main/java/de/pixart/messenger/ui/XmppActivity.java
index acb970e82..d01f29ac5 100644
--- a/src/main/java/de/pixart/messenger/ui/XmppActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/XmppActivity.java
@@ -471,9 +471,9 @@ public abstract class XmppActivity extends ActionBarActivity {
intent.setAction(ConversationsActivity.ACTION_VIEW_CONVERSATION);
intent.putExtra(ConversationsActivity.EXTRA_CONVERSATION, conversation.getUuid());
if (text != null) {
- intent.putExtra(ConversationsActivity.EXTRA_TEXT, text);
+ intent.putExtra(Intent.EXTRA_TEXT, text);
if (asQuote) {
- intent.putExtra(ConversationsActivity.EXTRA_AS_QUOTE, asQuote);
+ intent.putExtra(ConversationsActivity.EXTRA_AS_QUOTE, true);
}
}
if (nick != null) {
diff --git a/src/main/java/de/pixart/messenger/ui/text/FixedURLSpan.java b/src/main/java/de/pixart/messenger/ui/text/FixedURLSpan.java
index 353887054..67232462c 100644
--- a/src/main/java/de/pixart/messenger/ui/text/FixedURLSpan.java
+++ b/src/main/java/de/pixart/messenger/ui/text/FixedURLSpan.java
@@ -41,6 +41,9 @@ import android.text.style.URLSpan;
import android.view.View;
import android.widget.Toast;
+import java.util.Arrays;
+
+import de.pixart.messenger.Config;
import de.pixart.messenger.R;
import de.pixart.messenger.ui.ConversationsActivity;
@@ -64,7 +67,8 @@ public class FixedURLSpan extends URLSpan {
public void onClick(View widget) {
final Uri uri = Uri.parse(getURL());
final Context context = widget.getContext();
- if (uri.getScheme().equals("xmpp") && context instanceof ConversationsActivity) {
+ final boolean candidateToProcessDirecty = "xmpp".equals(uri.getScheme()) || ("https".equals(uri.getScheme()) && Config.inviteHostURL.equals(uri.getHost()) && uri.getPathSegments().size() > 1 && Arrays.asList("j", "i").contains(uri.getPathSegments().get(0)));
+ if (candidateToProcessDirecty && context instanceof ConversationsActivity) {
if (((ConversationsActivity) context).onXmppUriClicked(uri)) {
widget.playSoundEffect(0);
return;
diff --git a/src/main/java/de/pixart/messenger/ui/util/EditMessageActionModeCallback.java b/src/main/java/de/pixart/messenger/ui/util/EditMessageActionModeCallback.java
index cb50e4164..79914001a 100644
--- a/src/main/java/de/pixart/messenger/ui/util/EditMessageActionModeCallback.java
+++ b/src/main/java/de/pixart/messenger/ui/util/EditMessageActionModeCallback.java
@@ -32,6 +32,7 @@ package de.pixart.messenger.ui.util;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
+import android.text.TextUtils;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
@@ -52,12 +53,14 @@ public class EditMessageActionModeCallback implements ActionMode.Callback {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- MenuInflater inflater = mode.getMenuInflater();
+ final MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.edit_message_actions, menu);
- MenuItem pasteAsQuote = menu.findItem(R.id.paste_as_quote);
- ClipData primaryClip = clipboardManager.getPrimaryClip();
+ final MenuItem pasteAsQuote = menu.findItem(R.id.paste_as_quote);
+ final ClipData primaryClip = clipboardManager.getPrimaryClip();
if (primaryClip != null && primaryClip.getItemCount() >= 0) {
- pasteAsQuote.setVisible(primaryClip.getDescription().getMimeType(0).startsWith("text/") && primaryClip.getItemAt(0).getText() != null);
+ pasteAsQuote.setVisible(primaryClip.getDescription().getMimeType(0).startsWith("text/") && !TextUtils.isEmpty(primaryClip.getItemAt(0).getText()));
+ } else {
+ pasteAsQuote.setVisible(false);
}
return true;
}
diff --git a/src/main/java/de/pixart/messenger/utils/Compatibility.java b/src/main/java/de/pixart/messenger/utils/Compatibility.java
index 3ebc7c4f6..6d5f35bc4 100644
--- a/src/main/java/de/pixart/messenger/utils/Compatibility.java
+++ b/src/main/java/de/pixart/messenger/utils/Compatibility.java
@@ -2,6 +2,7 @@ package de.pixart.messenger.utils;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.preference.Preference;
@@ -26,13 +27,13 @@ public class Compatibility {
"notification_ringtone",
"notification_headsup",
"vibrate_on_notification");
- private static final List<String> UNUESD_SETTINGS_PRE_TWENTYSIX = Collections.singletonList("more_notification_settings");
+ private static final List<String> UNUSED_SETTINGS_PRE_TWENTYSIX = Collections.singletonList("more_notification_settings");
public static boolean hasStoragePermission(Context context) {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
- public static boolean twentySix() {
+ public static boolean runsTwentySix() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
}
@@ -48,8 +49,22 @@ public class Compatibility {
return PreferenceManager.getDefaultSharedPreferences(context);
}
+ private static boolean targetsTwentySix(Context context) {
+ try {
+ final PackageManager packageManager = context.getPackageManager();
+ final ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
+ return applicationInfo == null || applicationInfo.targetSdkVersion >= 26;
+ } catch (PackageManager.NameNotFoundException e) {
+ return true; //when in doubt…
+ }
+ }
+
+ public static boolean runsAndTargetsTwentySix(Context context) {
+ return runsTwentySix() && targetsTwentySix(context);
+ }
+
public static boolean keepForegroundService(Context context) {
- return twentySix() || getBooleanPreference(context, SettingsActivity.SHOW_FOREGROUND_SERVICE, R.bool.show_foreground_service);
+ return runsTwentySix() || getBooleanPreference(context, SettingsActivity.SHOW_FOREGROUND_SERVICE, R.bool.show_foreground_service);
}
public static void removeUnusedPreferences(SettingsFragment settingsFragment) {
@@ -57,7 +72,7 @@ public class Compatibility {
(PreferenceScreen) settingsFragment.findPreference("notifications"));
List<PreferenceCategory> categories = Arrays.asList(
(PreferenceCategory) settingsFragment.findPreference("general"));
- for (String key : (twentySix() ? UNUSED_SETTINGS_POST_TWENTYSIX : UNUESD_SETTINGS_PRE_TWENTYSIX)) {
+ for (String key : (runsTwentySix() ? UNUSED_SETTINGS_POST_TWENTYSIX : UNUSED_SETTINGS_PRE_TWENTYSIX)) {
Preference preference = settingsFragment.findPreference(key);
if (preference != null) {
for (PreferenceScreen screen : screens) {
@@ -72,5 +87,17 @@ public class Compatibility {
}
}
}
+ if (Compatibility.runsTwentySix()) {
+ if (targetsTwentySix(settingsFragment.getContext())) {
+ Preference preference = settingsFragment.findPreference(SettingsActivity.SHOW_FOREGROUND_SERVICE);
+ if (preference != null) {
+ for (PreferenceCategory category : categories) {
+ if (category != null) {
+ category.removePreference(preference);
+ }
+ }
+ }
+ }
+ }
}
} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/utils/Resolver.java b/src/main/java/de/pixart/messenger/utils/Resolver.java
index 4bae6fae7..e159c3dd0 100644
--- a/src/main/java/de/pixart/messenger/utils/Resolver.java
+++ b/src/main/java/de/pixart/messenger/utils/Resolver.java
@@ -108,17 +108,26 @@ public class Resolver {
threads[1].join();
if (results.size() > 0) {
threads[2].interrupt();
- Collections.sort(results);
- Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": " + results.toString());
- return results;
+ synchronized (results) {
+ Collections.sort(results);
+ Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": " + results.toString());
+ return new ArrayList<>(results);
+ }
} else {
threads[2].join();
- Collections.sort(fallbackResults);
- Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": " + fallbackResults.toString());
- return fallbackResults;
+ synchronized (fallbackResults) {
+ Collections.sort(fallbackResults);
+ Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": " + fallbackResults.toString());
+ return new ArrayList<>(fallbackResults);
+ }
}
} catch (InterruptedException e) {
- return results;
+ for (Thread thread : threads) {
+ thread.interrupt();
+ }
+ synchronized (results) {
+ return new ArrayList<>(results);
+ }
}
}