diff options
Diffstat (limited to 'src/main/java/de')
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); + } } } |