diff --git a/CHANGELOG.md b/CHANGELOG.md index 49e2bf17..ca875727 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# Build 255 (3.3) +2024-11-14 + +- Improved global search layout and performance (tabs, search in group member names, search in personal notes, etc.) +- Support for incoming call notification during a call +- Improved RTL language support + # Build 254 (3.2.2) 2024-10-18 diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/Logger.java b/obv_engine/engine/src/main/java/io/olvid/engine/Logger.java index 404d2bae..e57546d3 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/Logger.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/Logger.java @@ -78,9 +78,13 @@ public static void e(String message) { } public static void e(String message, Exception e) { log(ERROR, message + "( " + e.toString() + ")"); - e.printStackTrace(); + x(e); + } + public static void x(Throwable throwable) { + if (WARNING >= outputLogLevel) { + outputter.x("Logger", throwable); + } } - private static final char[] hexArray = "0123456789ABCDEF".toCharArray(); public static String toHexString(byte[] bytes) { @@ -121,5 +125,6 @@ public interface LogOutputter { void i(String tag, String message); void w(String tag, String message); void e(String tag, String message); + void x(String tag, Throwable throwable); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/backup/BackupManager.java b/obv_engine/engine/src/main/java/io/olvid/engine/backup/BackupManager.java index 2ac8ca5e..50304ae8 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/backup/BackupManager.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/backup/BackupManager.java @@ -124,7 +124,7 @@ public void initialisationComplete() { } backupManagerSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -136,7 +136,7 @@ public void setDelegate(CreateSessionDelegate createSessionDelegate) { BackupKey.createTable(backupManagerSession.session); backupManagerSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); throw new RuntimeException("Unable to create backup databases"); } } @@ -202,11 +202,11 @@ public void generateNewBackupKey() { userInfo.put(BackupNotifications.NOTIFICATION_NEW_BACKUP_SEED_GENERATED_SEED_KEY, backupSeed.toString()); notificationPostingDelegate.postNotification(BackupNotifications.NOTIFICATION_NEW_BACKUP_SEED_GENERATED, userInfo); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); throw new Exception("Failed to save new BackupKey to database"); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); notificationPostingDelegate.postNotification(BackupNotifications.NOTIFICATION_BACKUP_SEED_GENERATION_FAILED, new HashMap<>()); } } @@ -265,7 +265,7 @@ public void setAutoBackupEnabled(boolean enabled, boolean initiateBackupNowIfNee } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -319,7 +319,7 @@ public void initiateBackup(boolean forExpert) { userInfo.put(BackupNotifications.NOTIFICATION_APP_BACKUP_INITIATION_REQUEST_VERSION_KEY, newVersion); notificationPostingDelegate.postNotification(BackupNotifications.NOTIFICATION_APP_BACKUP_INITIATION_REQUEST, userInfo); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); // nothing to do... } }); @@ -445,7 +445,7 @@ public void backupSuccess(String tag, UID backupKeyUid, int version, String back notificationPostingDelegate.postNotification(BackupNotifications.NOTIFICATION_BACKUP_FINISHED, userInfo); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); backupFailed(tag, backupKeyUid, version); } }); @@ -494,7 +494,7 @@ public void markBackupExported(UID backupKeyUid, int version) { } backupManagerSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -516,7 +516,7 @@ public void markBackupUploaded(UID backupKeyUid, int version) { } backupManagerSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -534,7 +534,7 @@ public void discardBackup(UID backupKeyUid, int version) { backup.setFailed(); Logger.d("Backup discarded."); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -636,7 +636,7 @@ public ObvIdentity[] restoreOwnedIdentitiesFromBackup(String seedString, byte[] return identityDelegate.restoreOwnedIdentitiesFromBackup(backupContentAndDerivedKeys.pojo.engine.identity_manager, deviceDisplayName, prng); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -660,7 +660,7 @@ public void restoreContactsAndGroupsFromBackup(String seedString, byte[] backupC notificationPostingDelegate.postNotification(BackupNotifications.NOTIFICATION_BACKUP_RESTORATION_FINISHED, new HashMap<>()); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/channel/ChannelManager.java b/obv_engine/engine/src/main/java/io/olvid/engine/channel/ChannelManager.java index e0e4aad5..e1715354 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/channel/ChannelManager.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/channel/ChannelManager.java @@ -101,7 +101,7 @@ public void initialisationComplete() { ObliviousChannel.clean(channelManagerSession); channelManagerSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } try (ChannelManagerSession channelManagerSession = getSession()) { @@ -115,7 +115,7 @@ public void initialisationComplete() { } channelManagerSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } try (ChannelManagerSession channelManagerSession = getSession()) { @@ -215,7 +215,7 @@ public void initialisationComplete() { channelManagerSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -228,7 +228,7 @@ public void setDelegate(CreateSessionDelegate createSessionDelegate) { ProvisionedKeyMaterial.createTable(channelManagerSession.session); channelManagerSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); throw new RuntimeException("Unable to create channel databases"); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/channel/coordinators/ChannelCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/channel/coordinators/ChannelCoordinator.java index c3435170..6a6d502c 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/channel/coordinators/ChannelCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/channel/coordinators/ChannelCoordinator.java @@ -132,7 +132,7 @@ private void decryptAndProcess(ChannelManagerSession channelManagerSession, Netw } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } @@ -171,7 +171,7 @@ private void decryptAndProcess(ChannelManagerSession channelManagerSession, Netw channelReceivedMessage.getExtendedPayloadKey() ); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); Logger.i("Error while processing a ChannelReceivedApplicationMessage."); channelManagerSession.networkFetchDelegate.deleteMessageAndAttachments(channelManagerSession.session, networkReceivedMessage.getOwnedIdentity(), networkReceivedMessage.getMessageUid()); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/ObliviousChannel.java b/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/ObliviousChannel.java index 46206eaa..5ee8989d 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/ObliviousChannel.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/ObliviousChannel.java @@ -310,7 +310,7 @@ private RatchetingOutput selfRatchet() { statement.executeUpdate(); this.seedForNextSendKey = ratchetingOutput.getRatchetedSeed(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } return ratchetingOutput; @@ -338,7 +338,7 @@ public static ObliviousChannel create(ChannelManagerSession channelManagerSessio } return obliviousChannel; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -498,7 +498,7 @@ public static ObliviousChannel get(ChannelManagerSession channelManagerSession, } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } return null; } @@ -600,7 +600,7 @@ public static void deleteMany(final ChannelManagerSession channelManagerSession, channelManagerSession.notificationPostingDelegate.postNotification(ChannelNotifications.NOTIFICATION_OBLIVIOUS_CHANNEL_DELETED, userInfo); }); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -641,7 +641,7 @@ public void wasCommitted() { channelManagerSession.fullRatchetProtocolStarterDelegate.startFullRatchetProtocolForObliviousChannel(currentDeviceUid, remoteDeviceUid, remoteIdentity); } catch (Exception e) { // no need to do anything, the next message will try to restart the full ratchet - e.printStackTrace(); + Logger.x(e); } } else { Logger.w("Full ratchet required, but no FullRatchetProtocolStarterDelegate is set."); @@ -848,7 +848,7 @@ public MessageToSend.Header wrapMessageKey(AuthEncKey messageKey, PRNGService pr try { encryptedMessageKey = authEnc.encrypt(ratchetingOutput.getAuthEncKey(), Encoded.of(messageKey).getBytes(), prng); } catch (InvalidKeyException e) { - e.printStackTrace(); + Logger.x(e); return null; } byte[] headerBytes = new byte[KeyId.KEYID_LENGTH + encryptedMessageKey.length]; @@ -873,7 +873,7 @@ public MessageToSend.Header wrapMessageKey(AuthEncKey messageKey, PRNGService pr channelManagerSession.session.addSessionCommitListener(this); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } return header; @@ -891,7 +891,7 @@ public static AuthEncKeyAndChannelInfo unwrapMessageKey(ChannelManagerSession ch deviceUid = channelManagerSession.identityDelegate.getCurrentDeviceUidOfOwnedIdentity(channelManagerSession.session, header.getOwnedIdentity()); } catch (SQLException e) { Logger.e("Error retrieving a currentDeviceUid -> a received message might have been lost..."); - e.printStackTrace(); + Logger.x(e); return null; } ProvisionedKeyMaterial[] provisionedKeys = ProvisionedKeyMaterial.getAll(channelManagerSession, keyId, deviceUid); @@ -934,7 +934,7 @@ public static AuthEncKeyAndChannelInfo unwrapMessageKey(ChannelManagerSession ch obliviousChannel.commitHookBits |= HOOK_BIT_MIGHT_NEED_FULL_RATCHET; channelManagerSession.session.addSessionCommitListener(obliviousChannel); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } try { @@ -943,7 +943,7 @@ public static AuthEncKeyAndChannelInfo unwrapMessageKey(ChannelManagerSession ch obliviousChannel.confirm(); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } ReceptionChannelInfo receptionChannelInfo = obliviousChannel.getReceptionChannelInfo(); // add information about GKMV2 in receptionChannelInfo diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/Provision.java b/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/Provision.java index 86819567..b160f82f 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/Provision.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/Provision.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.List; +import io.olvid.engine.Logger; import io.olvid.engine.channel.datatypes.ChannelManagerSession; import io.olvid.engine.channel.datatypes.RatchetingOutput; import io.olvid.engine.datatypes.Constants; @@ -112,7 +113,7 @@ private void selfRatchet(int count) { statement.setBytes(6, obliviousChannelRemoteIdentity.getBytes()); statement.executeUpdate(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -135,7 +136,7 @@ public static void deleteAllEmpty(ChannelManagerSession channelManagerSession) { ")")) { statement.executeUpdate(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -156,7 +157,7 @@ public static Provision createOrReplace(ChannelManagerSession channelManagerSess provision.selfRatchet(2*Constants.REPROVISIONING_THRESHOLD); return provision; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/ProvisionedKeyMaterial.java b/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/ProvisionedKeyMaterial.java index 1adbe485..2e9e55bf 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/ProvisionedKeyMaterial.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/channel/databases/ProvisionedKeyMaterial.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.List; +import io.olvid.engine.Logger; import io.olvid.engine.channel.datatypes.ChannelManagerSession; import io.olvid.engine.datatypes.Constants; import io.olvid.engine.datatypes.Identity; @@ -144,7 +145,7 @@ public static ProvisionedKeyMaterial create(ChannelManagerSession channelManager provisionedKeyMaterial.insert(); return provisionedKeyMaterial; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -171,7 +172,7 @@ private ProvisionedKeyMaterial(ChannelManagerSession channelManagerSession, Resu try { this.authEncKey = (AuthEncKey) new Encoded(res.getBytes(AUTH_ENC_KEY)).decodeSymmetricKey(); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } this.expirationTimestamp = res.getLong(EXPIRATION_TIMESTAMP); this.selfRatchetingCount = res.getInt(SELF_RATCHETING_COUNT); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/crypto/Signature.java b/obv_engine/engine/src/main/java/io/olvid/engine/crypto/Signature.java index 9a51a818..88460014 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/crypto/Signature.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/crypto/Signature.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.HashMap; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Constants; import io.olvid.engine.datatypes.DictionaryKey; import io.olvid.engine.datatypes.EdwardCurvePoint; @@ -65,7 +66,7 @@ public static boolean verify(Constants.SignatureContext signatureContext, Identi Signature signatureAlgo = Suite.getSignature(signaturePublicKey); return signatureAlgo.verify(signaturePublicKey, challenge, Arrays.copyOfRange(signature, Constants.SIGNATURE_PADDING_LENGTH, signature.length)); } catch (InvalidKeyException e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -88,7 +89,7 @@ public static boolean verify(Constants.SignatureContext signatureContext, UID de Signature signatureAlgo = Suite.getSignature(signaturePublicKey); return signatureAlgo.verify(signaturePublicKey, challenge, Arrays.copyOfRange(signature, Constants.SIGNATURE_PADDING_LENGTH, signature.length)); } catch (InvalidKeyException e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -108,7 +109,7 @@ public static boolean verify(Constants.SignatureContext signatureContext, byte[] Signature signatureAlgo = Suite.getSignature(signaturePublicKey); return signatureAlgo.verify(signaturePublicKey, challenge, Arrays.copyOfRange(signature, Constants.SIGNATURE_PADDING_LENGTH, signature.length)); } catch (InvalidKeyException e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -132,7 +133,7 @@ public static boolean verify(Constants.SignatureContext signatureContext, GroupV Signature signatureAlgo = Suite.getSignature(signaturePublicKey); return signatureAlgo.verify(signaturePublicKey, challenge, Arrays.copyOfRange(signature, Constants.SIGNATURE_PADDING_LENGTH, signature.length)); } catch (InvalidKeyException e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -152,7 +153,7 @@ public static byte[] sign(Constants.SignatureContext signatureContext, Signature System.arraycopy(signatureBytes, 0, output, Constants.SIGNATURE_PADDING_LENGTH, signatureBytes.length); return output; } catch (InvalidKeyException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -173,7 +174,7 @@ public static byte[] sign(Constants.SignatureContext signatureContext, byte[] da System.arraycopy(signatureBytes, 0, output, Constants.SIGNATURE_PADDING_LENGTH, signatureBytes.length); return output; } catch (InvalidKeyException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/crypto/SymEnc.java b/obv_engine/engine/src/main/java/io/olvid/engine/crypto/SymEnc.java index 731b3a76..ce4b260e 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/crypto/SymEnc.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/crypto/SymEnc.java @@ -26,6 +26,7 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.EncryptedBytes; import io.olvid.engine.datatypes.key.symmetric.SymEncCTRAES256Key; import io.olvid.engine.datatypes.key.symmetric.SymmetricKey; @@ -109,7 +110,7 @@ public void encrypt(byte[] iv, byte[] plaintext, byte[] ciphertext) throws Inval outOffset += aes.update(plaintext, offsetIn, len, ciphertext, outOffset); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -127,7 +128,7 @@ public byte[] decrypt(EncryptedBytes ciphertext) { aes.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getKeyBytes(), "AES"), new IvParameterSpec(fullIV)); plaintext = aes.doFinal(ciphertextEnd); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } return plaintext; } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/BackupSeed.java b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/BackupSeed.java index e809b17a..a58f620b 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/BackupSeed.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/BackupSeed.java @@ -21,6 +21,7 @@ import java.util.Arrays; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.MAC; import io.olvid.engine.crypto.PRNG; import io.olvid.engine.crypto.Suite; @@ -94,7 +95,7 @@ public static BackupSeed generate(PRNG prng) { try { return new BackupSeed(prng.bytes(BACKUP_SEED_LENGTH)); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/Constants.java b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/Constants.java index c1e1c01e..c7647ce6 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/Constants.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/Constants.java @@ -55,9 +55,9 @@ public abstract class Constants { // full ratcheting thresholds public static final int THRESHOLD_NUMBER_OF_DECRYPTED_MESSAGES_SINCE_LAST_FULL_RATCHET_SENT_MESSAGE = 20; - public static final long THRESHOLD_TIME_INTERVAL_SINCE_LAST_FULL_RATCHET_SENT_MESSAGE = 7_200_000L; // restart the full ratchet after 2 hours without response - public static final int THRESHOLD_NUMBER_OF_ENCRYPTED_MESSAGES_PER_FULL_RATCHET = 100; // do a full ratchet after 100 messages - public static final long FULL_RATCHET_TIME_INTERVAL_VALIDITY = 86_400_000L * 7; // do a full ratchet every week + public static final long THRESHOLD_TIME_INTERVAL_SINCE_LAST_FULL_RATCHET_SENT_MESSAGE = 86_400_000L; // restart the full ratchet after 24 hours without response + public static final int THRESHOLD_NUMBER_OF_ENCRYPTED_MESSAGES_PER_FULL_RATCHET = 500; // do a full ratchet after 500 messages + public static final long FULL_RATCHET_TIME_INTERVAL_VALIDITY = 86_400_000L * 30; // do a full ratchet every month public static final int REPROVISIONING_THRESHOLD = 50; public static final long PROVISIONED_KEY_MATERIAL_EXPIRATION_DELAY = 86_400_000L * 2; // expire old ProvisionedKeyMaterial after 2 days diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/NoDuplicateOperationQueue.java b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/NoDuplicateOperationQueue.java index 925bc453..5b2aa374 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/NoDuplicateOperationQueue.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/NoDuplicateOperationQueue.java @@ -124,7 +124,7 @@ public void run() { op.execute(); } catch (Exception e) { Logger.e("Exception in operation that could have killed a queue!"); - e.printStackTrace(); + Logger.x(e); } } else { operations.add(op); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/NoExceptionSingleThreadExecutor.java b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/NoExceptionSingleThreadExecutor.java index 8de11dc3..36bbf202 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/NoExceptionSingleThreadExecutor.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/NoExceptionSingleThreadExecutor.java @@ -23,6 +23,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import io.olvid.engine.Logger; + public class NoExceptionSingleThreadExecutor implements Executor { private final String name; private final ExecutorService executor; @@ -46,7 +48,7 @@ public void shutdownNow() { try { executor.shutdownNow(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/OperationQueue.java b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/OperationQueue.java index 29eab347..9db20c59 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/OperationQueue.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/OperationQueue.java @@ -78,7 +78,7 @@ public void join() { try { notifier.wait(500); } catch (InterruptedException e) { - e.printStackTrace(); + Logger.x(e); } } lockOnCount.lock(); @@ -126,7 +126,7 @@ public void run() { try { notifier.wait(30000); } catch (InterruptedException e) { - e.printStackTrace(); + Logger.x(e); } } continue; @@ -157,7 +157,7 @@ public void run() { op.execute(); } catch (Exception e) { Logger.e("Exception in operation that could have killed a queue!"); - e.printStackTrace(); + Logger.x(e); } } else { addOperation(op); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/PreKeyBlobOnServer.java b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/PreKeyBlobOnServer.java index a6dbf3ae..e5cd8e0d 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/PreKeyBlobOnServer.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/PreKeyBlobOnServer.java @@ -50,7 +50,7 @@ public static PreKeyBlobOnServer verifySignatureAndDecode(Encoded encodedSignedP Logger.i("PreKey signature verification failed."); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } if (verifiedEncodedPreKey != null) { @@ -88,7 +88,7 @@ public static PreKeyBlobOnServer verifySignatureAndDecode(Encoded encodedSignedP } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } return null; } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/PriorityOperationQueue.java b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/PriorityOperationQueue.java index 26f4cbea..628612e1 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/PriorityOperationQueue.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/PriorityOperationQueue.java @@ -137,7 +137,7 @@ public void run() { op.execute(); } catch (Exception e) { Logger.e("Exception in operation that could have killed a queue!"); - e.printStackTrace(); + Logger.x(e); } lockOnExecutingOperations.lock(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/ServerMethod.java b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/ServerMethod.java index 630a0ac5..d0501a64 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/ServerMethod.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/ServerMethod.java @@ -180,13 +180,13 @@ public byte execute(boolean ownedIdentityIsActive) { connection.disconnect(); } } catch (MalformedURLException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = MALFORMED_URL; } catch (IOException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = SERVER_CONNECTION_ERROR; } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = MALFORMED_SERVER_RESPONSE; } return returnStatus; diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/ServerMethodForS3.java b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/ServerMethodForS3.java index 55c73552..d5448ae9 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/ServerMethodForS3.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/ServerMethodForS3.java @@ -174,10 +174,10 @@ public byte execute(boolean ownedIdentityIsActive) { connection.disconnect(); } } catch (MalformedURLException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = MALFORMED_URL; } catch (IOException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = SERVER_CONNECTION_ERROR; } return returnStatus; diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/Session.java b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/Session.java index cfde6679..bce6008c 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/Session.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/datatypes/Session.java @@ -75,7 +75,7 @@ public class Session implements Connection { try { DriverManager.registerDriver((Driver) Class.forName("org.sqlite.JDBC").getDeclaredConstructor().newInstance()); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -200,7 +200,7 @@ public void close() throws SQLException { Logger.e(" - Un-committed entity: " + sessionCommitListener.getClass()); } sessionCommitListeners.clear(); - new Exception("Trace").printStackTrace(); + Logger.x(new Exception("Trace")); } if (!getAutoCommit()) { rollback(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/engine/Engine.java b/obv_engine/engine/src/main/java/io/olvid/engine/engine/Engine.java index ea77e2dd..36d21c55 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/engine/Engine.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/engine/Engine.java @@ -266,7 +266,7 @@ public Engine(File baseDirectory, ObvBackupAndSyncDelegate appBackupAndSyncDeleg } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); throw new RuntimeException("Unable to check for tables upgrade", e); } @@ -281,7 +281,7 @@ public Engine(File baseDirectory, ObvBackupAndSyncDelegate appBackupAndSyncDeleg UserInterfaceDialog.createTable(engineSession.session); engineSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); throw new RuntimeException("Unable to create engine databases"); } @@ -312,7 +312,7 @@ private void initializationComplete() { userInterfaceDialog.delete(); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); try { userInterfaceDialog.delete(); } catch (Exception ignored) { } @@ -321,7 +321,7 @@ private void initializationComplete() { engineSession.session.commit(); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -398,7 +398,7 @@ void postEngineNotification(String notificationName, HashMap use try { notificationQueue.put(new EngineNotification(notificationName, userInfo)); } catch (InterruptedException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -417,7 +417,7 @@ public synchronized void start() { try { engineNotification = notificationQueue.take(); } catch (InterruptedException e) { - e.printStackTrace(); + Logger.x(e); } if (engineNotification == null) { continue; @@ -439,7 +439,7 @@ public synchronized void start() { try { listener.callback(engineNotification.notificationName, engineNotification.userInfo); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } @@ -455,7 +455,7 @@ public synchronized void start() { try { listener.callback(engineNotification.notificationName, engineNotification.userInfo); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } @@ -798,7 +798,7 @@ public RegisterApiKeyResult registerOwnedIdentityApiKeyOnServer(byte[] bytesOwne return RegisterApiKeyResult.FAILED; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return RegisterApiKeyResult.FAILED; } } @@ -814,7 +814,7 @@ public void updateKeycloakPushTopicsIfNeeded(byte[] bytesOwnedIdentity, String s fetchManager.forceRegisterPushNotification(ownedIdentity, false); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -830,7 +830,7 @@ public void updateKeycloakRevocationList(byte[] bytesOwnedIdentity, long latestR identityManager.unCertifyExpiredSignedContactDetails(engineSession.session, ownedIdentity, latestRevocationListTimestamp); engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -841,7 +841,7 @@ public void setOwnedIdentityKeycloakSelfRevocationTestNonce(byte[] bytesOwnedIde identityManager.setOwnedIdentityKeycloakSelfRevocationTestNonce(engineSession.session, ownedIdentity, serverUrl, nonce); engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -851,7 +851,7 @@ public String getOwnedIdentityKeycloakSelfRevocationTestNonce(byte[] bytesOwnedI Identity ownedIdentity = Identity.of(bytesOwnedIdentity); return identityManager.getOwnedIdentityKeycloakSelfRevocationTestNonce(engineSession.session, ownedIdentity, serverUrl); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } return null; } @@ -867,7 +867,7 @@ public boolean updateKeycloakGroups(byte[] bytesOwnedIdentity, List sign identityManager.updateKeycloakGroups(engineSession.session, ownedIdentity, signedGroupBlobs, signedGroupDeletions, signedGroupKicks, keycloakCurrentTimestamp); success = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (success) { engineSession.session.commit(); @@ -877,7 +877,7 @@ public boolean updateKeycloakGroups(byte[] bytesOwnedIdentity, List sign } return success; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -889,7 +889,7 @@ public void recreateServerSession(byte[] bytesOwnedIdentity) { fetchManager.deleteExistingServerSession(engineSession.session, ownedIdentity, true); engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1006,7 +1006,7 @@ public ObvIdentity bindOwnedIdentityToKeycloak(byte[] bytesOwnedIdentity, ObvKey engineSession.session.commit(); return obvIdentity; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } return null; } @@ -1017,7 +1017,7 @@ public void unbindOwnedIdentityFromKeycloak(byte[] bytesOwnedIdentity) { Identity ownedIdentity = Identity.of(bytesOwnedIdentity); protocolManager.startProtocolForUnbindingOwnedIdentityFromKeycloak(ownedIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1106,7 +1106,7 @@ public void discardLatestIdentityDetails(byte[] bytesOwnedIdentity) { identityManager.discardLatestIdentityDetails(engineSession.session, ownedIdentity); engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1121,7 +1121,7 @@ public void publishLatestIdentityDetails(byte[] bytesOwnedIdentity) { } engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1141,7 +1141,7 @@ public byte[] getServerAuthenticationToken(byte[] bytesOwnedIdentity) { Identity ownedIdentity = Identity.of(bytesOwnedIdentity); return fetchManager.getServerAuthenticationToken(ownedIdentity); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -1153,7 +1153,7 @@ public List getOwnCapabilities(byte[] bytesOwnedIdentity) { Identity ownedIdentity = Identity.of(bytesOwnedIdentity); return identityManager.getOwnCapabilities(ownedIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -1164,7 +1164,7 @@ public List getOwnedDevices(byte[] bytesOwnedIdentity) { Identity ownedIdentity = Identity.of(bytesOwnedIdentity); return identityManager.getDevicesOfOwnedIdentity(engineSession.session, ownedIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -1229,7 +1229,7 @@ public ObvDeviceList queryRegisteredOwnedDevicesFromServer(byte[] bytesOwnedIden return new ObvDeviceList(multiDevice, deviceUidsAndServerInfo); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } return null; } @@ -1240,7 +1240,7 @@ public void refreshOwnedDeviceList(byte[] bytesOwnedIdentity) { Identity ownedIdentity = Identity.of(bytesOwnedIdentity); protocolManager.startOwnedDeviceDiscoveryProtocol(ownedIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1252,7 +1252,7 @@ public void recreateOwnedDeviceChannel(byte[] bytesOwnedIdentity, byte[] bytesDe // simply start the channel creation protocol: this deletes any channel and aborts any ongoing instance protocolManager.startChannelCreationWithOwnedDeviceProtocol(ownedIdentity, deviceUid); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1263,7 +1263,7 @@ public void recreateOwnedDeviceChannel(byte[] bytesOwnedIdentity, byte[] bytesDe // protocolManager.triggerOwnedDevicesSync(engineSession.session, ownedIdentity); // engineSession.session.commit(); // } catch (Exception e) { -// e.printStackTrace(); +// Logger.x(e); // } // } @@ -1301,7 +1301,7 @@ public EnumSet getContactActiveOrInactiveReaso Identity contactIdentity = Identity.of(bytesContactIdentity); return identityManager.getContactActiveOrInactiveReasons(engineSession.session, ownedIdentity, contactIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -1315,7 +1315,7 @@ public boolean forcefullyUnblockContact(byte[] bytesOwnedIdentity, byte[] bytesC engineSession.session.commit(); return success; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -1329,7 +1329,7 @@ public boolean reBlockForcefullyUnblockedContact(byte[] bytesOwnedIdentity, byte engineSession.session.commit(); return success; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -1379,7 +1379,7 @@ public void trustPublishedContactDetails(byte[] bytesOwnedIdentity, byte[] bytes } engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1421,7 +1421,7 @@ public List getContactCapabilities(byte[] bytesOwnedIdentity, byt Identity contactIdentity = Identity.of(bytesContactIdentity); return identityManager.getContactCapabilities(ownedIdentity, contactIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -1508,7 +1508,7 @@ public void trustPublishedGroupDetails(byte[] bytesOwnedIdentity, byte[] bytesGr } engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1530,7 +1530,7 @@ public void discardLatestGroupDetails(byte[] bytesOwnedIdentity, byte[] bytesGro identityManager.discardLatestGroupDetails(engineSession.session, ownedIdentity, bytesGroupOwnerAndUid); engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1545,7 +1545,7 @@ public void publishLatestGroupDetails(byte[] bytesOwnedIdentity, byte[] bytesGro } engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1598,7 +1598,7 @@ public String getGroupV2JsonType(byte[] bytesOwnedIdentity, byte[] bytesGroupIde return identityManager.getGroupV2JsonGroupType(engineSession.session, ownedIdentity, groupIdentifier); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -1617,7 +1617,7 @@ public ObvGroupV2.ObvGroupV2DetailsAndPhotos getGroupV2DetailsAndPhotos(byte[] b return identityManager.getGroupV2DetailsAndPhotos(engineSession.session, ownedIdentity, groupIdentifier); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } @@ -2008,7 +2008,7 @@ public void deleteReturnReceipt(byte[] bytesOwnedIdentity, byte[] serverUid) { fetchManager.deleteReturnReceipt(ownedIdentity, serverUid); } catch (DecodingException e) { Logger.w("DecodingException while reconstructing the ownedIdentity in deleteReturnReceipt"); - e.printStackTrace(); + Logger.x(e); } } @@ -2038,7 +2038,7 @@ public ObvReturnReceipt decryptReturnReceipt(byte[] returnReceiptKey, byte[] enc } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } return null; } @@ -2057,7 +2057,7 @@ public ObvPostMessageOutput post(byte[] messagePayload, byte[] extendedMessagePa } list.add(contactIdentity); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); Logger.w("Error decoding a bytesContactIdentity while posting a message!"); } } @@ -2124,7 +2124,7 @@ public ObvPostMessageOutput post(byte[] messagePayload, byte[] extendedMessagePa for (Identity contactIdentity : contactIdentities) { messageIdentifierByContactIdentity.put(new ObvBytesKey(contactIdentity.getBytes()), null); } - e.printStackTrace(); + Logger.x(e); } } @@ -2150,7 +2150,7 @@ public void sendReturnReceipt(byte[] bytesOwnedIdentity, byte[] bytesContactIden } engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2159,7 +2159,7 @@ public boolean isOutboxAttachmentSent(byte[] bytesOwnedIdentity, byte[] engineMe try (EngineSession engineSession = getSession()) { return sendManager.isOutboxAttachmentSent(engineSession.session, Identity.of(bytesOwnedIdentity), new UID(engineMessageIdentifier), engineNumber); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -2169,7 +2169,7 @@ public boolean isOutboxMessageSent(byte[] bytesOwnedIdentity, byte[] engineMessa try (EngineSession engineSession = getSession()) { return sendManager.isOutboxMessageSent(engineSession.session, Identity.of(bytesOwnedIdentity), new UID(engineMessageIdentifier)); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -2181,7 +2181,7 @@ public void cancelMessageSending(byte[] bytesOwnedIdentity, byte[] engineMessage sendManager.cancelMessageSending(engineSession.session, Identity.of(bytesOwnedIdentity), new UID(engineMessageIdentifier)); engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2190,7 +2190,7 @@ public boolean isInboxAttachmentReceived(byte[] bytesOwnedIdentity, byte[] engin try (EngineSession engineSession = getSession()) { return fetchManager.isInboxAttachmentReceived(engineSession.session, Identity.of(bytesOwnedIdentity), new UID(engineMessageIdentifier), attachmentNumber); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -2202,7 +2202,7 @@ public void downloadMessages(byte[] bytesOwnedIdentity) { UID currentDeviceUid = identityManager.getCurrentDeviceUidOfOwnedIdentity(engineSession.session, ownedIdentity); fetchManager.downloadMessages(ownedIdentity, currentDeviceUid); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2212,7 +2212,7 @@ public void downloadSmallAttachment(byte[] bytesOwnedIdentity, byte[] messageIde fetchManager.downloadAttachment(Identity.of(bytesOwnedIdentity), new UID(messageIdentifier), attachmentNumber, DownloadAttachmentPriorityCategory.WEIGHT); } catch (DecodingException e) { Logger.e("Error parsing bytesOwnedIdentity in Engine.downloadSmallAttachment"); - e.printStackTrace(); + Logger.x(e); } } @@ -2222,7 +2222,7 @@ public void downloadLargeAttachment(byte[] bytesOwnedIdentity, byte[] messageIde fetchManager.downloadAttachment(Identity.of(bytesOwnedIdentity), new UID(messageIdentifier), attachmentNumber, DownloadAttachmentPriorityCategory.TIMESTAMP); } catch (DecodingException e) { Logger.e("Error parsing bytesOwnedIdentity in Engine.downloadLargeAttachment"); - e.printStackTrace(); + Logger.x(e); } } @@ -2232,7 +2232,7 @@ public void pauseAttachmentDownload(byte[] bytesOwnedIdentity, byte[] messageIde fetchManager.pauseDownloadAttachment(Identity.of(bytesOwnedIdentity), new UID(messageIdentifier), attachmentNumber); } catch (DecodingException e) { Logger.e("Error parsing bytesOwnedIdentity in Engine.pauseAttachmentDownload"); - e.printStackTrace(); + Logger.x(e); } } @@ -2247,7 +2247,7 @@ public void markAttachmentForDeletion(byte[] bytesOwnedIdentity, byte[] messageI markAttachmentForDeletion(Identity.of(bytesOwnedIdentity), new UID(messageIdentifier), attachmentNumber); } catch (DecodingException e) { Logger.e("Error parsing bytesOwnedIdentity in Engine.deleteAttachment"); - e.printStackTrace(); + Logger.x(e); } } @@ -2259,14 +2259,14 @@ public void deleteMessageAndAttachments(byte[] bytesOwnedIdentity, byte[] messag ownedIdentity = Identity.of(bytesOwnedIdentity); } catch (DecodingException e) { Logger.e("Error parsing bytesOwnedIdentity in Engine.deleteMessage"); - e.printStackTrace(); + Logger.x(e); return; } try (EngineSession engineSession = getSession()) { fetchManager.deleteMessageAndAttachments(engineSession.session, ownedIdentity, messageUid); engineSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2278,14 +2278,14 @@ public void markMessageForDeletion(byte[] bytesOwnedIdentity, byte[] messageIden ownedIdentity = Identity.of(bytesOwnedIdentity); } catch (DecodingException e) { Logger.e("Error parsing bytesOwnedIdentity in Engine.deleteMessage"); - e.printStackTrace(); + Logger.x(e); return; } try (EngineSession engineSession = getSession()) { fetchManager.deleteMessage(engineSession.session, ownedIdentity, messageUid); engineSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2297,7 +2297,7 @@ private void markAttachmentForDeletion(Identity ownedIdentity, UID messageUid, i fetchManager.deleteAttachment(engineSession.session, ownedIdentity, messageUid, attachmentNumber); engineSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2310,7 +2310,7 @@ public void cancelAttachmentUpload(byte[] bytesOwnedIdentity, byte[] messageIden sendManager.cancelAttachmentUpload(engineSession.session, Identity.of(bytesOwnedIdentity), new UID(messageIdentifier), attachmentNumber); engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2449,7 +2449,7 @@ public void getTurnCredentials(byte[] bytesOwnedIdentity, UUID callUuid, String Identity ownedIdentity = Identity.of(bytesOwnedIdentity); fetchManager.getTurnCredentials(ownedIdentity, callUuid, callerUsername, recipientUsername); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2459,7 +2459,7 @@ public void queryApiKeyStatus(byte[] bytesOwnedIdentity, UUID apiKey) { Identity ownedIdentity = Identity.of(bytesOwnedIdentity); fetchManager.queryApiKeyStatus(ownedIdentity, apiKey); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2480,7 +2480,7 @@ public void queryFreeTrial(byte[] bytesOwnedIdentity) { Identity ownedIdentity = Identity.of(bytesOwnedIdentity); fetchManager.queryFreeTrial(ownedIdentity); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2493,7 +2493,7 @@ public void startFreeTrial(byte[] bytesOwnedIdentity) { fetchManager.startFreeTrial(ownedIdentity); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2506,7 +2506,7 @@ public void verifyReceipt(byte[] bytesOwnedIdentity, String storeToken) { fetchManager.verifyReceipt(ownedIdentity, storeToken); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2606,7 +2606,7 @@ public void setAllOwnedDeviceNames(String deviceName) { } engineSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerChannelsAndProtocols.java b/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerChannelsAndProtocols.java index 98b0a953..bc055244 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerChannelsAndProtocols.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerChannelsAndProtocols.java @@ -80,7 +80,7 @@ public void callback(String notificationName, HashMap userInfo) UserInterfaceDialog.createOrReplace(engine.wrapSession(session), engine.createDialog(channelDialogMessageToSend)); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -99,7 +99,7 @@ public void callback(String notificationName, HashMap userInfo) engine.postEngineNotification(EngineNotifications.CHANNEL_CONFIRMED_OR_DELETED, engineInfo); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -121,7 +121,7 @@ public void callback(String notificationName, HashMap userInfo) engine.postEngineNotification(EngineNotifications.CHANNEL_CONFIRMED_OR_DELETED, engineInfo); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerGroups.java b/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerGroups.java index b6668b7a..b5542a3f 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerGroups.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerGroups.java @@ -126,7 +126,7 @@ public void callback(String notificationName, HashMap userInfo) engineInfo.put(EngineNotifications.GROUP_CREATED_ON_OTHER_DEVICE_KEY, createdOnOtherDevice); engine.postEngineNotification(EngineNotifications.GROUP_CREATED, engineInfo); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; case IdentityNotifications.NOTIFICATION_GROUP_DELETED: { diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerGroupsV2.java b/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerGroupsV2.java index f6f7ce25..87b10c97 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerGroupsV2.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerGroupsV2.java @@ -77,7 +77,7 @@ public void callback(String notificationName, HashMap userInfo) engineInfo.put(EngineNotifications.GROUP_V2_CREATED_OR_UPDATED_CREATED_ON_OTHER_DEVICE, createdOnOtherDevice); engine.postEngineNotification(EngineNotifications.GROUP_V2_CREATED_OR_UPDATED, engineInfo); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -102,7 +102,7 @@ public void callback(String notificationName, HashMap userInfo) engineInfo.put(EngineNotifications.GROUP_V2_CREATED_OR_UPDATED_CREATED_ON_OTHER_DEVICE, false); engine.postEngineNotification(EngineNotifications.GROUP_V2_CREATED_OR_UPDATED, engineInfo); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerIdentity.java b/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerIdentity.java index 8413eca7..7d30490b 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerIdentity.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/engine/NotificationListenerIdentity.java @@ -96,7 +96,7 @@ public void callback(String notificationName, HashMap userInfo) engineInfo.put(EngineNotifications.NEW_CONTACT_HAS_UNTRUSTED_PUBLISHED_DETAILS_KEY, engine.identityManager.contactHasUntrustedPublishedDetails(engineSession.session, ownedIdentity, contactIdentity)); engine.postEngineNotification(EngineNotifications.NEW_CONTACT, engineInfo); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -318,7 +318,7 @@ public void callback(String notificationName, HashMap userInfo) engine.postEngineNotification(EngineNotifications.CONTACT_CAPABILITIES_UPDATED, engineInfo); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -336,7 +336,7 @@ public void callback(String notificationName, HashMap userInfo) engine.postEngineNotification(EngineNotifications.OWN_CAPABILITIES_UPDATED, engineInfo); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/engine/databases/UserInterfaceDialog.java b/obv_engine/engine/src/main/java/io/olvid/engine/engine/databases/UserInterfaceDialog.java index 28bd8803..b99de978 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/engine/databases/UserInterfaceDialog.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/engine/databases/UserInterfaceDialog.java @@ -55,7 +55,7 @@ public void resend() { try { sendNotification(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -74,7 +74,7 @@ public void update(Encoded encodedDialog) { this.commitHookBits |= HOOK_BIT_SHOULD_SEND_NOTIFICATION; engineSession.session.addSessionCommitListener(this); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -96,7 +96,7 @@ public static UserInterfaceDialog createOrReplace(EngineSession engineSession, O return userInterfaceDialog; } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -216,7 +216,7 @@ public static UserInterfaceDialog[] getAll(EngineSession engineSession) { return list.toArray(new UserInterfaceDialog[0]); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return new UserInterfaceDialog[0]; } } @@ -242,7 +242,7 @@ public void wasCommitted() { try { sendNotification(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } @@ -251,7 +251,7 @@ public void wasCommitted() { try { engineSession.userInterfaceDialogListener.sendUserInterfaceDialogDeletionNotification(uuid); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/ObvDialog.java b/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/ObvDialog.java index 7a98ed5f..dea20e8e 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/ObvDialog.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/ObvDialog.java @@ -23,6 +23,7 @@ import java.util.UUID; +import io.olvid.engine.Logger; import io.olvid.engine.encoder.DecodingException; import io.olvid.engine.encoder.Encoded; import io.olvid.engine.engine.types.identities.ObvGroupV2; @@ -482,7 +483,7 @@ private Encoded encode(ObjectMapper jsonObjectMapper) { try { pendingEncodeds[i] = pendingGroupMemberIdentities[i].encode(jsonObjectMapper); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); break; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/identities/ObvMutualScanUrl.java b/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/identities/ObvMutualScanUrl.java index 0e32cf66..a927a1ce 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/identities/ObvMutualScanUrl.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/identities/ObvMutualScanUrl.java @@ -23,6 +23,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.ObvBase64; import io.olvid.engine.encoder.Encoded; @@ -69,7 +70,7 @@ public static ObvMutualScanUrl fromUrlRepresentation(String urlRepresentation) { byte[] signature = list[2].decodeBytes(); return new ObvMutualScanUrl(identity, displayName, signature); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/identities/ObvUrlIdentity.java b/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/identities/ObvUrlIdentity.java index d0bc5b56..ec8178e6 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/identities/ObvUrlIdentity.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/identities/ObvUrlIdentity.java @@ -22,6 +22,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.ObvBase64; import io.olvid.engine.encoder.DecodingException; @@ -73,7 +74,7 @@ public static ObvUrlIdentity fromUrlRepresentation(String urlRepresentation) { String displayName = list[1].decodeString(); return new ObvUrlIdentity(identity, displayName); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/sync/ObvSyncSnapshot.java b/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/sync/ObvSyncSnapshot.java index bac2eda3..eb207b4e 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/sync/ObvSyncSnapshot.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/engine/types/sync/ObvSyncSnapshot.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Objects; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.DictionaryKey; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.encoder.Encoded; @@ -108,7 +109,7 @@ public HashMap toEncodedDictionary(ObvBackupAndSyncDeleg } return map; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -126,7 +127,7 @@ public static ObvSyncSnapshot fromEncodedDictionary(HashMap ignore it - e.printStackTrace(); + Logger.x(e); } } } @@ -1216,7 +1216,7 @@ public void updateKeycloakGroups(Session session, Identity ownedIdentity, List ignore it - e.printStackTrace(); + Logger.x(e); } } } @@ -1244,7 +1244,7 @@ public void updateKeycloakGroups(Session session, Identity ownedIdentity, List ignore it - e.printStackTrace(); + Logger.x(e); } } } @@ -1268,7 +1268,7 @@ public void reactivateOwnedIdentityIfNeeded(Session session, Identity ownedIdent protocolStarterDelegate.startChannelCreationProtocolWithOwnedDevice(session, ownedIdentity, ownedDeviceUid); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } ContactIdentity[] contactIdentities = ContactIdentity.getAll(wrapSession(session), ownedIdentity); @@ -1276,13 +1276,13 @@ public void reactivateOwnedIdentityIfNeeded(Session session, Identity ownedIdent try { protocolStarterDelegate.startDeviceDiscoveryProtocolWithinTransaction(session, ownedIdentity, contactIdentity.getContactIdentity()); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } try { protocolStarterDelegate.startOwnedDeviceDiscoveryProtocolWithinTransaction(session, ownedIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1544,7 +1544,7 @@ public void addContactIdentity(Session session, Identity contactIdentity, String } session.addSessionCommitListener(backupNeededSessionCommitListener); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); throw new Exception(); } } @@ -1576,7 +1576,7 @@ public Identity[] getContactsOfOwnedIdentity(Session session, Identity ownedIden return identities; } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } return null; } @@ -1730,7 +1730,7 @@ public void reCheckAllCertifiedByOwnKeycloakContacts(Session session, Identity o continue; } catch (Exception e) { // error parsing signed details --> do nothing - e.printStackTrace(); + Logger.x(e); } } } @@ -1866,7 +1866,7 @@ public boolean reBlockForcefullyUnblockedContact(Session session, Identity owned contactIdentityObject.setForcefullyTrustedByUser(false); return true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -1935,7 +1935,7 @@ public UID[] getDeviceUidsOfContactIdentity(Session session, Identity ownedIdent } return uids; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } return new UID[0]; } @@ -1950,7 +1950,7 @@ public List getDeviceUidsAndPreKeysOfContactIdentity(Session sessi } return uids; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } return Collections.emptyList(); } @@ -2156,7 +2156,7 @@ public byte[] signIdentities(Session session, Constants.SignatureContext signatu System.arraycopy(signatureBytes, 0, output, Constants.SIGNATURE_PADDING_LENGTH, signatureBytes.length); return output; } catch (InvalidKeyException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -2192,7 +2192,7 @@ public byte[] signChannel(Session session, Constants.SignatureContext signatureC System.arraycopy(signatureBytes, 0, output, Constants.SIGNATURE_PADDING_LENGTH, signatureBytes.length); return output; } catch (InvalidKeyException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -2224,7 +2224,7 @@ public byte[] signBlock(Session session, Constants.SignatureContext signatureCon System.arraycopy(signatureBytes, 0, output, Constants.SIGNATURE_PADDING_LENGTH, signatureBytes.length); return output; } catch (InvalidKeyException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -2261,7 +2261,7 @@ public byte[] signGroupInvitationNonce(Session session, Constants.SignatureConte System.arraycopy(signatureBytes, 0, output, Constants.SIGNATURE_PADDING_LENGTH, signatureBytes.length); return output; } catch (InvalidKeyException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -2876,11 +2876,11 @@ public void refreshMembersOfGroupsOwnedByGroupOwner(UID currentDeviceUid, Identi try { protocolStarterDelegate.queryGroupMembers(groupOwnerAndUid, ownedIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -2898,7 +2898,7 @@ public void pushMembersOfOwnedGroupsToContact(UID currentDeviceUid, Identity con try { protocolStarterDelegate.reinviteAndPushMembersToContact(groupOwnerAndUid, ownedIdentity, contactIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } @@ -2908,12 +2908,12 @@ public void pushMembersOfOwnedGroupsToContact(UID currentDeviceUid, Identity con try { protocolStarterDelegate.reinvitePendingToGroup(groupOwnerAndUid, ownedIdentity, contactIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -3352,7 +3352,7 @@ public GroupV2.ServerPhotoInfo getGroupV2PublishedServerPhotoInfo(Session sessio } return ContactGroupV2.getServerPhotoInfo(wrapSession(session), ownedIdentity, groupIdentifier); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } return null; } @@ -3398,7 +3398,7 @@ public ObvGroupV2.ObvGroupV2DetailsAndPhotos getGroupV2DetailsAndPhotos(Session return new ObvGroupV2.ObvGroupV2DetailsAndPhotos(serializedGroupDetails, photoUrl, serializedPublishedDetails, publishedPhotoUrl); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -3510,10 +3510,10 @@ public void initiateGroupV2BatchKeysResend(UID currentDeviceUid, Identity contac protocolStarterDelegate.initiateGroupV2BatchKeysResend(identityManagerSession.session, ownedIdentity, contactIdentity, contactDeviceUid); identityManagerSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -3576,7 +3576,7 @@ public byte[] createKeycloakGroupV2(Session session, Identity ownedIdentity, Gro AuthEncKey photoKey = (AuthEncKey) new Encoded(keycloakGroupBlob.encodedPhotoKey).decodeSymmetricKey(); serverPhotoInfo = new GroupV2.ServerPhotoInfo(null, photoUid, photoKey); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -3628,7 +3628,7 @@ public byte[] createKeycloakGroupV2(Session session, Identity ownedIdentity, Gro } } catch (InvalidJwtException | JsonProcessingException e) { Logger.w("Unable to process one keycloak group member --> skipping them"); - e.printStackTrace(); + Logger.x(e); } } @@ -3646,7 +3646,7 @@ public byte[] createKeycloakGroupV2(Session session, Identity ownedIdentity, Gro session.addSessionCommitListener(backupNeededSessionCommitListener); return ownInvitationNonce; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -3684,7 +3684,7 @@ public void rePingOrDemoteContactFromAllKeycloakGroups(Session session, Identity try { protocolStarterDelegate.initiateKeycloakGroupV2TargetedPing(session, ownedIdentity, groupIdentifier, contactIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } @@ -3695,7 +3695,7 @@ public void rePingOrDemoteContactFromAllKeycloakGroups(Session session, Identity try { moveKeycloakMemberToPendingMember(identityManagerSession, groupIdentifier, ownedIdentity, contactIdentity, lastKnownSerializedCertifiedDetails); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } @@ -3766,7 +3766,7 @@ public void initiateBackup(final BackupDelegate backupDelegate, final String tag String jsonString = jsonObjectMapper.writeValueAsString(ownedIdentityPojos); backupDelegate.backupSuccess(tag, backupKeyUid, version, jsonString); } catch (SQLException | JsonProcessingException e) { - e.printStackTrace(); + Logger.x(e); backupDelegate.backupFailed(tag, backupKeyUid, version); } }, "Identity Backup").start(); @@ -3796,7 +3796,7 @@ public ObvIdentity[] restoreOwnedIdentitiesFromBackup(String serializedJsonPojo, return restoredIdentities.toArray(new ObvIdentity[0]); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -3829,7 +3829,7 @@ public void restoreContactsAndGroupsFromBackup(String serializedJsonPojo, ObvIde } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } // endregion @@ -3893,7 +3893,7 @@ public void processSyncItem(Session session, Identity ownedIdentity, ObvSyncAtom } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -3912,7 +3912,7 @@ public void processSyncItem(Session session, Identity ownedIdentity, ObvSyncAtom } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -3926,7 +3926,7 @@ public void processSyncItem(Session session, Identity ownedIdentity, ObvSyncAtom trustGroupV2PublishedDetails(session, ownedIdentity, groupIdentifier); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -4062,7 +4062,7 @@ public EncryptedBytes wrapWithPreKey(Session session, AuthEncKey messageKey, Ide return new EncryptedBytes(outputBytes); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -4108,7 +4108,7 @@ public AuthEncKeyAndChannelInfo unwrapWithPreKey(Session session, EncryptedBytes } return new AuthEncKeyAndChannelInfo(messageKey, ReceptionChannelInfo.createPreKeyChannelInfo(remoteDeviceUid, remoteIdentity)); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -4133,14 +4133,14 @@ public ObvSyncSnapshotNode getSyncSnapshot(Identity ownedIdentity) { identityManagerSession.session.startTransaction(); return getSyncSnapshotWithinTransaction(identityManagerSession, ownedIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } finally { // always rollback as the snapshot creation should never modify the DB. identityManagerSession.session.rollback(); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -4171,7 +4171,7 @@ public RestoreFinishedCallback restoreSyncSnapshot(ObvSyncSnapshotNode node) thr transactionSuccessful = true; return callback; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (transactionSuccessful) { identityManagerSession.session.commit(); @@ -4180,7 +4180,7 @@ public RestoreFinishedCallback restoreSyncSnapshot(ObvSyncSnapshotNode node) thr } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } return null; } @@ -4220,7 +4220,7 @@ public ObvSyncSnapshotNode getSyncSnapshot(Identity ownedIdentity) { try { return IdentityManager.this.getSyncSnapshotWithinTransaction(identityManagerSession, ownedIdentity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroup.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroup.java index b5d4ca92..61b1b7e9 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroup.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroup.java @@ -512,7 +512,7 @@ public static ContactGroup create(IdentityManagerSession identityManagerSession, try { jsonGroupDetailsWithVersionAndPhoto = identityManagerSession.jsonObjectMapper.readValue(serializedGroupDetailsWithVersionAndPhoto, JsonGroupDetailsWithVersionAndPhoto.class); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } @@ -533,7 +533,7 @@ public static ContactGroup create(IdentityManagerSession identityManagerSession, } return contactGroup; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupDetails.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupDetails.java index 55722052..7f974c60 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupDetails.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupDetails.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.List; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.ObvDatabase; import io.olvid.engine.datatypes.Session; @@ -217,7 +218,7 @@ public static ContactGroupDetails create(IdentityManagerSession identityManagerS contactGroupDetails.insert(); return contactGroupDetails; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -250,7 +251,7 @@ public static ContactGroupDetails copy(IdentityManagerSession identityManagerSes contactGroupDetails.insert(); return contactGroupDetails; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -291,7 +292,7 @@ private ContactGroupDetails(IdentityManagerSession identityManagerSession, Resul try { this.photoServerKey = (AuthEncKey) new Encoded(bytes).decodeSymmetricKey(); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); this.photoServerKey = null; } } @@ -432,7 +433,7 @@ public static ContactGroupDetails restore(IdentityManagerSession identityManager photoServerKey = (AuthEncKey) new Encoded(pojo.photo_server_key).decodeSymmetricKey(); } } catch (DecodingException | ClassCastException e) { - e.printStackTrace(); + Logger.x(e); } ContactGroupDetails contactGroupDetails = new ContactGroupDetails(identityManagerSession, groupOwnerAndUid, ownedIdentity, pojo.version, pojo.serialized_details, null, photoServerLabel, photoServerKey); contactGroupDetails.insert(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupMembersJoin.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupMembersJoin.java index 81b545ea..7de20c79 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupMembersJoin.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupMembersJoin.java @@ -212,13 +212,13 @@ public static Identity[] getContactIdentitiesInGroup(IdentityManagerSession iden try { list.add(Identity.of(res.getBytes(1))); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } } return list.toArray(new Identity[0]); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return new Identity[0]; } } @@ -291,7 +291,7 @@ static void restoreAll(IdentityManagerSession identityManagerSession, Identity o create(identityManagerSession, groupOwnerAndUid, ownedIdentity, Identity.of(pojo.contact_identity)); } } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2.java index 69e39b77..3cc52f6e 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2.java @@ -192,7 +192,7 @@ public static ContactGroupV2 createNew(IdentityManagerSession identityManagerSes contactGroup.commitHookBits |= HOOK_BIT_INSERTED_AS_NEW | HOOK_BIT_FROZEN_CHANGED; // this way the app also receives a frozen notification to mark the group as updating return contactGroup; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -220,7 +220,7 @@ public static ContactGroupV2 createJoined(IdentityManagerSession identityManager } return contactGroup; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -249,7 +249,7 @@ public static ContactGroupV2 createKeycloak(IdentityManagerSession identityManag } return contactGroup; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -402,7 +402,7 @@ public static GroupV2.ServerBlob getServerBlob(IdentityManagerSession identityMa )); } } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -434,7 +434,7 @@ public static GroupV2.ServerBlob getServerBlob(IdentityManagerSession identityMa )); } } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -849,7 +849,7 @@ public List updateWithNewBlob(GroupV2.ServerBlob serverBlob, GroupV2.B return null; } } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); return null; } @@ -968,7 +968,7 @@ public List updateWithNewBlob(GroupV2.ServerBlob serverBlob, GroupV2.B } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); Logger.w("Error while updating group members from new serverBlob"); return null; } @@ -1362,7 +1362,7 @@ public KeycloakGroupV2UpdateOutput updateWithNewKeycloakBlob(KeycloakGroupBlob k } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); Logger.w("Error while updating group members from new serverBlob"); return null; } @@ -1737,7 +1737,7 @@ static void restore(IdentityManagerSession identityManagerSession, ProtocolStart try { serverAuthenticationPrivateKey = (ServerAuthenticationPrivateKey) new Encoded(pojo.encoded_admin_key).decodePrivateKey(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } GroupV2.BlobKeys blobKeys = ((pojo.main_seed == null) || (pojo.version_seed == null)) ? null : new GroupV2.BlobKeys(new Seed(pojo.main_seed), new Seed(pojo.version_seed), serverAuthenticationPrivateKey); @@ -1767,7 +1767,7 @@ static void restore(IdentityManagerSession identityManagerSession, ProtocolStart try { protocolStarterDelegate.initiateGroupV2ReDownloadWithinTransaction(identityManagerSession.session, ownedIdentity, groupIdentifier); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } identityManagerSession.session.commit(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2Details.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2Details.java index fd6dc4cf..041f8501 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2Details.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2Details.java @@ -159,7 +159,7 @@ public static ContactGroupV2Details createNew(IdentityManagerSession identityMan photoUrl = randFileName; } catch (IOException e) { - e.printStackTrace(); + Logger.x(e); Logger.w("Error copying the photo for the groupV2 --> creating a group without photo"); } } @@ -174,7 +174,7 @@ public static ContactGroupV2Details createNew(IdentityManagerSession identityMan contactGroupDetails.insert(); return contactGroupDetails; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -201,7 +201,7 @@ public static ContactGroupV2Details createJoined(IdentityManagerSession identity contactGroupDetails.insert(); return contactGroupDetails; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -222,7 +222,7 @@ public static ContactGroupV2Details create(IdentityManagerSession identityManage contactGroupDetails.insert(); return contactGroupDetails; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -263,7 +263,7 @@ public static ContactGroupV2Details createOrUpdateKeycloak(IdentityManagerSessio return contactGroupDetails; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -683,7 +683,7 @@ static void restore(IdentityManagerSession identityManagerSession, Identity owne contactGroupV2Details = new ContactGroupV2Details(identityManagerSession, groupIdentifier.groupUid, groupIdentifier.serverUrl, groupIdentifier.category, ownedIdentity, version, pojo.serialized_details, null, photoServerIdentity, photoServerLabel, photoServerKey); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2Member.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2Member.java index e26ea069..b554d93a 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2Member.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2Member.java @@ -89,7 +89,7 @@ public static ContactGroupV2Member create(IdentityManagerSession identityManager contactGroupMember.insert(); return contactGroupMember; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -215,7 +215,7 @@ public static List getKeycloakGroupV2IdentifiersWhereContact GroupV2.Identifier.CATEGORY_KEYCLOAK )); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } return list; @@ -376,7 +376,7 @@ static void restoreAll(IdentityManagerSession identityManagerSession, Identity o try { create(identityManagerSession, ownedIdentity, groupIdentifier, Identity.of(pojo.contact_identity), Arrays.asList(pojo.permissions), pojo.invitation_nonce); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2PendingMember.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2PendingMember.java index 5b3ebcfd..37c99bca 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2PendingMember.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactGroupV2PendingMember.java @@ -96,7 +96,7 @@ public static ContactGroupV2PendingMember create(IdentityManagerSession identity contactGroupPendingMember.insert(); return contactGroupPendingMember; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -266,7 +266,7 @@ public static List getKeycloakGroupV2IdentifiersWhereContact GroupV2.Identifier.CATEGORY_KEYCLOAK )); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } return list; @@ -404,7 +404,7 @@ static void restoreAll(IdentityManagerSession identityManagerSession, Identity o create(identityManagerSession, ownedIdentity, groupIdentifier, Identity.of(pojo.contact_identity), sanitizedSerializedDetails, Arrays.asList(pojo.permissions), pojo.invitation_nonce); } } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactIdentity.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactIdentity.java index 0ed5e148..8120b04d 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactIdentity.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactIdentity.java @@ -616,7 +616,7 @@ public static ContactIdentity create(IdentityManagerSession identityManagerSessi JsonIdentityDetails certifiedJsonIdentityDetails = jsonKeycloakUserDetails.getIdentityDetails(jsonIdentityDetailsWithVersionAndPhoto.getIdentityDetails().getSignedUserDetails()); contactIdentityObject.markContactAsCertifiedByOwnKeycloak(certifiedJsonIdentityDetails); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -740,7 +740,7 @@ public static void upgradeTable(Session session, int oldVersion, int newVersion) try { preparedStatement.setString(4, objectMapper.writeValueAsString(map)); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); // skip the contact continue; } @@ -1279,7 +1279,7 @@ private static void restoreContact(IdentityManagerSession identityManagerSession contactIdentity = Identity.of(pojo.contact_identity); } catch (DecodingException e) { Logger.e("Error recreating ContactIdentity from backup!"); - e.printStackTrace(); + Logger.x(e); } if (contactIdentity == null) { return; @@ -1316,7 +1316,7 @@ private static void restoreContactGroups(IdentityManagerSession identityManagerS contactIdentity = Identity.of(pojo.contact_identity); } catch (DecodingException e) { Logger.e("Error recreating ContactIdentityGroups from backup!"); - e.printStackTrace(); + Logger.x(e); } if (contactIdentity == null) { return; diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactIdentityDetails.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactIdentityDetails.java index 1e7eb875..c2234231 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactIdentityDetails.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactIdentityDetails.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.List; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.ObvDatabase; import io.olvid.engine.datatypes.Session; @@ -129,7 +130,7 @@ public static ContactIdentityDetails create(IdentityManagerSession identityManag contactIdentityDetails.insert(); return contactIdentityDetails; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -147,7 +148,7 @@ public static ContactIdentityDetails copy(IdentityManagerSession identityManager ownedIdentityDetails.insert(); return ownedIdentityDetails; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -192,7 +193,7 @@ private ContactIdentityDetails(IdentityManagerSession identityManagerSession, Re try { this.photoServerKey = (AuthEncKey) new Encoded(bytes).decodeSymmetricKey(); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); this.photoServerKey = null; } } @@ -380,7 +381,7 @@ public static ContactIdentityDetails restore(IdentityManagerSession identityMana photoServerKey = (AuthEncKey) new Encoded(pojo.photo_server_key).decodeSymmetricKey(); } } catch (DecodingException | ClassCastException e) { - e.printStackTrace(); + Logger.x(e); } ContactIdentityDetails contactIdentityDetails = new ContactIdentityDetails(identityManagerSession, contactIdentity, ownedIdentity, pojo.version, pojo.serialized_details, null, photoServerLabel, photoServerKey); contactIdentityDetails.insert(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactTrustOrigin.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactTrustOrigin.java index 7453ef9d..f907f064 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactTrustOrigin.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ContactTrustOrigin.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.List; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.ObvDatabase; import io.olvid.engine.datatypes.Session; @@ -258,7 +259,7 @@ public static ContactTrustOrigin create(IdentityManagerSession identityManagerSe contactTrustOrigin.insert(); return contactTrustOrigin; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -377,7 +378,7 @@ private static void restore(IdentityManagerSession identityManagerSession, Ident mediatorOrGroupOwnerIdentity = Identity.of(pojo.mediator_or_group_owner_identity); } } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } ContactTrustOrigin contactTrustOrigin = new ContactTrustOrigin(identityManagerSession, contactIdentity, ownedIdentity, pojo.timestamp, pojo.readTrust_type(), mediatorOrGroupOwnerIdentity, pojo.mediator_or_group_owner_trust_level_major, pojo.identity_server, pojo.raw_obv_group_v2_identifier); contactTrustOrigin.insert(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/KeycloakServer.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/KeycloakServer.java index a7af2119..e5c44c97 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/KeycloakServer.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/KeycloakServer.java @@ -165,7 +165,7 @@ public static KeycloakServer create(IdentityManagerSession identityManagerSessio keycloakServer.insert(); return keycloakServer; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedIdentity.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedIdentity.java index 352c15fd..99c1b434 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedIdentity.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedIdentity.java @@ -518,7 +518,7 @@ public static OwnedIdentity create(IdentityManagerSession identityManagerSession OwnedDevice.createCurrentDevice(identityManagerSession, identity, deviceDisplayName, prng); return ownedIdentity; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -611,7 +611,7 @@ public static void upgradeTable(Session session, int oldVersion, int newVersion) try { preparedStatement.setString(3, objectMapper.writeValueAsString(map)); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); // skip the contact continue; } @@ -866,7 +866,7 @@ public static ObvIdentity restore(IdentityManagerSession identityManagerSession, ownedIdentity = Identity.of(pojo.owned_identity); } catch (DecodingException e) { Logger.e("Error recreating OwnedIdentity from backup!"); - e.printStackTrace(); + Logger.x(e); } if (ownedIdentity == null) { return null; diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedIdentityDetails.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedIdentityDetails.java index deaf0e7c..7383597c 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedIdentityDetails.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedIdentityDetails.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.List; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.ObvDatabase; import io.olvid.engine.datatypes.Session; @@ -129,7 +130,7 @@ public static OwnedIdentityDetails create(IdentityManagerSession identityManager ownedIdentityDetails.insert(); return ownedIdentityDetails; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -145,7 +146,7 @@ public static OwnedIdentityDetails create(IdentityManagerSession identityManager ownedIdentityDetails.insert(); return ownedIdentityDetails; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -174,7 +175,7 @@ public static OwnedIdentityDetails copy(IdentityManagerSession identityManagerSe ownedIdentityDetails.insert(); return ownedIdentityDetails; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -224,7 +225,7 @@ private OwnedIdentityDetails(IdentityManagerSession identityManagerSession, Resu try { this.photoServerKey = (AuthEncKey) new Encoded(bytes).decodeSymmetricKey(); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); this.photoServerKey = null; } } @@ -437,7 +438,7 @@ public static OwnedIdentityDetails restore(IdentityManagerSession identityManage photoServerKey = (AuthEncKey) new Encoded(pojo.photo_server_key).decodeSymmetricKey(); } } catch (DecodingException | ClassCastException e) { - e.printStackTrace(); + Logger.x(e); } OwnedIdentityDetails ownedIdentityDetails = new OwnedIdentityDetails(identityManagerSession, ownedIdentity, pojo.version, pojo.serialized_details, null, photoServerLabel, photoServerKey); ownedIdentityDetails.insert(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedPreKey.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedPreKey.java index b94675da..65f9fa4b 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedPreKey.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/OwnedPreKey.java @@ -112,7 +112,7 @@ public static OwnedPreKey create(IdentityManagerSession identityManagerSession, return null; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/PendingGroupMember.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/PendingGroupMember.java index 5d66fb41..4022e731 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/PendingGroupMember.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/PendingGroupMember.java @@ -389,7 +389,7 @@ static void restore(IdentityManagerSession identityManagerSession, Identity owne pendingGroupMember.declined = pojo.declined; pendingGroupMember.insert(); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ServerUserData.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ServerUserData.java index 2372246e..303f48a8 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ServerUserData.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/ServerUserData.java @@ -268,7 +268,7 @@ public void updateNextRefreshTimestamp() { statement.executeUpdate(); this.nextRefreshTimestamp = timestamp; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/ContactSyncSnapshot.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/ContactSyncSnapshot.java index ec4b1a41..7ca1c15a 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/ContactSyncSnapshot.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/ContactSyncSnapshot.java @@ -134,7 +134,7 @@ public ContactIdentity restore(IdentityManagerSession identityManagerSession, Id mediatorOrGroupOwnerIdentity = Identity.of(trustOrigin.mediator_or_group_owner_identity); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } int trustType; switch (TrustOrigin.TrustType.fromIntValue(trustOrigin.trust_type)) { diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/GroupDetailsSyncSnapshot.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/GroupDetailsSyncSnapshot.java index c7b2b814..0adc46a5 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/GroupDetailsSyncSnapshot.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/GroupDetailsSyncSnapshot.java @@ -100,7 +100,7 @@ public ContactGroupDetails restoreGroup(IdentityManagerSession identityManagerSe photoServerLabel = new UID(photo_server_label); photoServerKey = (AuthEncKey) new Encoded(photo_server_key).decodeSymmetricKey(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); photoServerLabel = null; photoServerKey = null; } @@ -133,7 +133,7 @@ public ContactGroupV2Details restoreGroupV2(IdentityManagerSession identityManag photoServerLabel = new UID(photo_server_label); photoServerKey = (AuthEncKey) new Encoded(photo_server_key).decodeSymmetricKey(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); photoServerIdentity = null; photoServerLabel = null; photoServerKey = null; diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/GroupV2SyncSnapshot.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/GroupV2SyncSnapshot.java index a7099a93..303140c4 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/GroupV2SyncSnapshot.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/GroupV2SyncSnapshot.java @@ -211,7 +211,7 @@ public ContactGroupV2 restore(IdentityManagerSession identityManagerSession, Pro try { protocolStarterDelegate.initiateGroupV2ReDownloadWithinTransaction(identityManagerSession.session, ownedIdentity, groupIdentifier); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } return groupV2; diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/IdentityDetailsSyncSnapshot.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/IdentityDetailsSyncSnapshot.java index 38743438..bfaa2b21 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/IdentityDetailsSyncSnapshot.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/IdentityDetailsSyncSnapshot.java @@ -95,7 +95,7 @@ public OwnedIdentityDetails restoreOwned(IdentityManagerSession identityManagerS photoServerLabel = new UID(photo_server_label); photoServerKey = (AuthEncKey) new Encoded(photo_server_key).decodeSymmetricKey(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); photoServerLabel = null; photoServerKey = null; } @@ -125,7 +125,7 @@ public ContactIdentityDetails restoreContact(IdentityManagerSession identityMana photoServerLabel = new UID(photo_server_label); photoServerKey = (AuthEncKey) new Encoded(photo_server_key).decodeSymmetricKey(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); photoServerLabel = null; photoServerKey = null; } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/KeycloakSyncSnapshot.java b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/KeycloakSyncSnapshot.java index 6d2632c5..67c0c12c 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/KeycloakSyncSnapshot.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/identity/databases/sync/KeycloakSyncSnapshot.java @@ -88,7 +88,7 @@ public KeycloakServer restore(IdentityManagerSession identityManagerSession, Ide return keycloakServer; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/metamanager/MetaManager.java b/obv_engine/engine/src/main/java/io/olvid/engine/metamanager/MetaManager.java index 9ebdea17..00338db0 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/metamanager/MetaManager.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/metamanager/MetaManager.java @@ -67,7 +67,7 @@ public void initializationComplete() throws Exception { manager.initialisationComplete(); } catch (Exception e) { Logger.e("Exception in initialisationComplete() for " + manager.getClass()); - e.printStackTrace(); + Logger.x(e); } } }).start(); @@ -120,7 +120,7 @@ private void setManagerDelegate(ObvManager manager, Object delegate, String inte Method method = manager.getClass().getMethod("setDelegate", Class.forName(interfaceName)); method.invoke(manager, delegate); } catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); + Logger.x(e); } catch (NoSuchMethodException e) { Logger.e("ObvManager " + manager.getClass() + " requests a delegate of type " + interfaceName + " but does not implement the matching setDelegate method."); throw new RuntimeException(); @@ -137,7 +137,7 @@ private void checkInterfaceImplementations(Object delegatesImplementation) { throw new RuntimeException(); } } catch (ClassNotFoundException e ) { - e.printStackTrace(); + Logger.x(e); } } @@ -152,7 +152,7 @@ private void checkInterfaceImplementations(Object delegatesImplementation) { managersAwaitingInterfaceImplementations.remove(interfaceName); } } catch (ClassNotFoundException e ) { - e.printStackTrace(); + Logger.x(e); } } lockOnInterfaceImplementations.unlock(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/FetchManager.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/FetchManager.java index a64ee7a3..428b119a 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/FetchManager.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/FetchManager.java @@ -167,7 +167,7 @@ public void setDelegate(CreateSessionDelegate createSessionDelegate) { PendingServerQuery.createTable(fetchManagerSession.session); fetchManagerSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); throw new RuntimeException("Unable to createCurrentDevice network fetch databases"); } } @@ -627,7 +627,7 @@ public byte[] getServerAuthenticationToken(Identity ownedIdentity) { try (FetchManagerSession fetchManagerSession = getSession()) { return ServerSession.getToken(fetchManagerSession, ownedIdentity); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/CreateServerSessionCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/CreateServerSessionCoordinator.java index 1dc175de..43aae644 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/CreateServerSessionCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/CreateServerSessionCoordinator.java @@ -91,7 +91,7 @@ public void initialQueueing() { } fetchManagerSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadAttachmentCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadAttachmentCoordinator.java index 552ad7aa..6f285089 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadAttachmentCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadAttachmentCoordinator.java @@ -111,7 +111,7 @@ public void initialQueueing() { } fetchManagerSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -201,7 +201,7 @@ public void onCancelCallback(Operation operation) { fetchManagerSession.session.commit(); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } HashMap userInfo = new HashMap<>(); userInfo.put(DownloadNotifications.NOTIFICATION_ATTACHMENT_DOWNLOAD_FAILED_OWNED_IDENTITY_KEY, ownedIdentity); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadMessageExtendedPayloadCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadMessageExtendedPayloadCoordinator.java index 1362b44c..630af8e4 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadMessageExtendedPayloadCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadMessageExtendedPayloadCoordinator.java @@ -107,7 +107,7 @@ public void initialQueueing() { messageHasExtendedPayloadToDownload(inboxMessage.getOwnedIdentity(), inboxMessage.getUid()); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadMessagesAndListAttachmentsCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadMessagesAndListAttachmentsCoordinator.java index 12c2ebcb..1ed116c1 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadMessagesAndListAttachmentsCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/DownloadMessagesAndListAttachmentsCoordinator.java @@ -144,7 +144,7 @@ public void initialQueueing() { fetchManagerSession.session.commit(); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -308,7 +308,7 @@ public void callback(String notificationName, HashMap userInfo) downloadMessagesAndListAttachmentsOperationQueue.queue(op); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/RefreshInboxAttachmentSignedUrlCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/RefreshInboxAttachmentSignedUrlCoordinator.java index b83c8e3c..00aedc63 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/RefreshInboxAttachmentSignedUrlCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/RefreshInboxAttachmentSignedUrlCoordinator.java @@ -157,7 +157,7 @@ public void onCancelCallback(Operation operation) { fetchManagerSession.session.commit(); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } HashMap userInfo = new HashMap<>(); userInfo.put(DownloadNotifications.NOTIFICATION_ATTACHMENT_DOWNLOAD_FAILED_OWNED_IDENTITY_KEY, ownedIdentity); @@ -205,7 +205,7 @@ public void callback(String notificationName, HashMap userInfo) } awaitingIdentityReactivationOperationsLock.unlock(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/RegisterServerPushNotificationsCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/RegisterServerPushNotificationsCoordinator.java index 302812f9..28e97321 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/RegisterServerPushNotificationsCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/RegisterServerPushNotificationsCoordinator.java @@ -127,7 +127,7 @@ public void initialQueueing() { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -236,7 +236,7 @@ public void processAndroidPushNotification(String androidMaskingUidString) { downloadMessagesAndListAttachmentsDelegate.downloadMessagesAndListAttachments(identityAndUid.ownedIdentity, identityAndUid.uid); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -249,7 +249,7 @@ public Identity getOwnedIdentityFromMaskingUid(String androidMaskingUidString) { return identityAndUid.ownedIdentity; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } return null; diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerQueryCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerQueryCoordinator.java index 1e845541..d9663937 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerQueryCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerQueryCoordinator.java @@ -109,7 +109,7 @@ public void initialQueueing() { // commit, in case a WebSocket query was deleted fetchManagerSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } // only start processing queries after the initial queueing is performed (otherwise a query could be queued while its already being executed) @@ -188,7 +188,7 @@ public void callback(String notificationName, HashMap userInfo) } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } @@ -230,7 +230,7 @@ public void onCancelCallback(Operation operation) { fetchManagerSession.session.commit(); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -302,7 +302,7 @@ public void onFinishCallback(Operation operation) { serverUserDataCoordinator.newUserDataUploaded(serverQuery.getOwnedIdentity(), ((ServerQuery.PutUserDataQuery) serverQuery.getType()).serverLabel); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerQueryCoordinatorWebSocketModule.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerQueryCoordinatorWebSocketModule.java index eedbb777..c5d0d01f 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerQueryCoordinatorWebSocketModule.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerQueryCoordinatorWebSocketModule.java @@ -87,7 +87,7 @@ public void handleServerQuery(PendingServerQuery pendingServerQuery, boolean cal try { serverQuery = ServerQuery.of(pendingServerQuery.getEncodedQuery()); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); return; } @@ -240,7 +240,7 @@ public void handleServerQuery(PendingServerQuery pendingServerQuery, boolean cal } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); failProtocol(protocolInstanceUid); } }); @@ -286,7 +286,7 @@ private void sendServerQueryResponse(PendingServerQuery pendingServerQuery, Stri } success = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (success) { fetchManagerSession.session.commit(); @@ -295,7 +295,7 @@ private void sendServerQueryResponse(PendingServerQuery pendingServerQuery, Stri } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -332,7 +332,7 @@ public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) { try { handleServerQuery(clientAndQuery.pendingServerQuery, true); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } }); @@ -347,7 +347,7 @@ public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String rea @Override public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) { - t.printStackTrace(); + Logger.x(t); executor.execute(this::closeAndAbort); } @@ -430,7 +430,7 @@ private void onMessage(String text) { } } catch (Exception e) { // in case of exception when parsing, ignore it and simply forward the response to the protocol - e.printStackTrace(); + Logger.x(e); } // remove the pendingServerQuery diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerUserDataCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerUserDataCoordinator.java index 8e7f1a33..511e7ded 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerUserDataCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/ServerUserDataCoordinator.java @@ -163,7 +163,7 @@ public void initialQueueing() { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } // cleanup downloaded user data dir of orphan files @@ -185,12 +185,12 @@ public void initialQueueing() { //noinspection ResultOfMethodCallIgnored file.delete(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -377,7 +377,7 @@ public void callback(String notificationName, HashMap userInfo) } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/WebsocketCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/WebsocketCoordinator.java index 1260d693..ec93d2e9 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/WebsocketCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/WebsocketCoordinator.java @@ -180,7 +180,7 @@ public static OkHttpClient initializeOkHttpClientForWebSocket(SSLSocketFactory s builder.sslSocketFactory(sslSocketFactory, trustManager); } catch (Exception e) { Logger.e("Error initializing websocket okHttpClient trustManager"); - e.printStackTrace(); + Logger.x(e); } } @@ -254,7 +254,7 @@ public void initialQueueing() { identityAndUids.add(new IdentityAndUid(ownedIdentity, deviceUid)); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } resetWebsockets(); @@ -420,7 +420,7 @@ public void callback(String notificationName, HashMap userInfo) identityAndUids.add(new IdentityAndUid(ownedIdentity, deviceUid)); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } resetWebsockets(); @@ -501,7 +501,7 @@ public void doExecute() { new WebSocketClient(server, wsUrl); finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { setFinished(); @@ -579,7 +579,7 @@ public void doExecute() { webSocketClient.send(jsonObjectMapper.writeValueAsString(messageMap)); finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { setFinished(); @@ -591,7 +591,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -608,7 +608,7 @@ public void deleteReturnReceipt(Identity ownedIdentity, byte[] serverUid) { messageMap.put("serverUid", Base64.encodeBytes(serverUid)); webSocketClient.send(jsonObjectMapper.writeValueAsString(messageMap)); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } @@ -728,7 +728,7 @@ public void onMessage(WebSocket webSocket, String message) { ServerSession.deleteCurrentTokenIfEqualTo(fetchManagerSession, ownedIdentityServerSessionTokens.get(identity), identity); fetchManagerSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } synchronized (awaitingServerSessionIdentitiesLock) { @@ -744,7 +744,7 @@ public void onMessage(WebSocket webSocket, String message) { } } catch (IOException | DecodingException e) { Logger.d("Error decoding identity"); - e.printStackTrace(); + Logger.x(e); } break; } @@ -782,7 +782,7 @@ public void onMessage(WebSocket webSocket, String message) { downloadMessagesAndListAttachmentsDelegate.downloadMessagesAndListAttachments(identity, deviceUid); } catch (IOException | DecodingException e) { Logger.d("Error decoding identity"); - e.printStackTrace(); + Logger.x(e); } break; } @@ -812,7 +812,7 @@ public void onMessage(WebSocket webSocket, String message) { } } catch (Exception e) { Logger.d("Error parsing return receipt"); - e.printStackTrace(); + Logger.x(e); } } break; @@ -830,7 +830,7 @@ public void onMessage(WebSocket webSocket, String message) { } } catch (Exception e) { Logger.d("Error parsing push topic"); - e.printStackTrace(); + Logger.x(e); } } break; @@ -853,7 +853,7 @@ public void onMessage(WebSocket webSocket, String message) { timestamp = (long) timestampObj; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); // this is treated after } if (notificationPostingDelegate != null) { @@ -881,7 +881,7 @@ public void onMessage(WebSocket webSocket, String message) { notificationPostingDelegate.postNotification(DownloadNotifications.NOTIFICATION_PUSH_KEYCLOAK_UPDATE_REQUIRED, userInfo); } catch (IOException | DecodingException e) { Logger.d("Error decoding identity in keycloak websocket notification"); - e.printStackTrace(); + Logger.x(e); } break; } @@ -897,12 +897,12 @@ public void onMessage(WebSocket webSocket, String message) { try { protocolStarterDelegate.startOwnedDeviceDiscoveryProtocol(identity); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } } catch (IOException | DecodingException e) { Logger.d("Error decoding identity in ownedDevices websocket notification"); - e.printStackTrace(); + Logger.x(e); } break; } @@ -936,7 +936,7 @@ public void sendPing() { this.webSocket.send(jsonObjectMapper.writeValueAsString(messageMap)); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -968,7 +968,7 @@ public void onClosing(WebSocket webSocket, int code, String reason) { public void onFailure(WebSocket webSocket, Throwable t, Response response) { if (websocketConnected) { Logger.w("Websocket exception"); - t.printStackTrace(); + Logger.x(t); } close(); if (doConnect) { diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/WellKnownCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/WellKnownCoordinator.java index c8b128b8..90be9213 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/WellKnownCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/coordinators/WellKnownCoordinator.java @@ -123,12 +123,12 @@ public void run() { queueNewWellKnownDownloadOperation(server); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } }, Constants.WELL_KNOWN_REFRESH_INTERVAL, Constants.WELL_KNOWN_REFRESH_INTERVAL); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/CachedWellKnown.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/CachedWellKnown.java index 21a35e3c..0a4cc88f 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/CachedWellKnown.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/CachedWellKnown.java @@ -102,7 +102,7 @@ public static CachedWellKnown create(FetchManagerSession fetchManagerSession, St cachedWellKnown.insert(); return cachedWellKnown; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/InboxAttachment.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/InboxAttachment.java index 23b2df44..6a142b5f 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/InboxAttachment.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/InboxAttachment.java @@ -221,7 +221,7 @@ public void requestDownload(int priorityCategory) { commitHookBits |= HOOK_BIT_DOWNLOAD_REQUESTED; fetchManagerSession.session.addSessionCommitListener(this); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -238,7 +238,7 @@ public void pauseDownload() { this.downloadRequested = false; // No notification needed: the downloadSmallAttachment operation will cancel and the coordinator sends a "paused" notification } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -254,7 +254,7 @@ public void markForDeletion() { statement.executeUpdate(); this.markedForDeletion = true; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -369,7 +369,7 @@ public boolean writeToAttachmentFile(byte[] attachmentBytes, int encryptedLength return true; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return false; } } @@ -425,7 +425,7 @@ private InboxAttachment(FetchManagerSession fetchManagerSession, ResultSet res) try { this.ownedIdentity = Identity.of(res.getBytes(OWNED_IDENTITY)); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } this.messageUid = new UID(res.getBytes(MESSAGE_UID)); this.attachmentNumber = res.getInt(ATTACHMENT_NUMBER); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/InboxMessage.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/InboxMessage.java index 39cb16e4..34c00ca8 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/InboxMessage.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/InboxMessage.java @@ -266,7 +266,7 @@ public static InboxMessage create(FetchManagerSession fetchManagerSession, Ident inboxMessage.insert(); return inboxMessage; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -293,7 +293,7 @@ private InboxMessage(FetchManagerSession fetchManagerSession, ResultSet res) thr try { this.ownedIdentity = Identity.of(res.getBytes(OWNED_IDENTITY)); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } this.uid = new UID(res.getBytes(UID_)); byte[] bytes = res.getBytes(WRAPPED_KEY); @@ -310,7 +310,7 @@ private InboxMessage(FetchManagerSession fetchManagerSession, ResultSet res) thr try { this.fromIdentity = Identity.of(fromIdentityBytes); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } } this.downloadTimestamp = res.getLong(DOWNLOAD_TIMESTAMP); @@ -344,7 +344,7 @@ public static InboxMessage get(FetchManagerSession fetchManagerSession, Identity } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -362,7 +362,7 @@ public static boolean exists(FetchManagerSession fetchManagerSession, Identity o return res.next(); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return false; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/PendingServerQuery.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/PendingServerQuery.java index 6263baa4..c7a22c1d 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/PendingServerQuery.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/PendingServerQuery.java @@ -78,7 +78,7 @@ public static PendingServerQuery create(FetchManagerSession fetchManagerSession, pendingServerQuery.insert(); return pendingServerQuery; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/PushNotificationConfiguration.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/PushNotificationConfiguration.java index 14a704c2..27b1ba44 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/PushNotificationConfiguration.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/PushNotificationConfiguration.java @@ -111,7 +111,7 @@ public static PushNotificationConfiguration create(FetchManagerSession fetchMana pushNotificationConfiguration.insert(); return pushNotificationConfiguration; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -132,7 +132,7 @@ private PushNotificationConfiguration(FetchManagerSession fetchManagerSession, R try { this.ownedIdentity = Identity.of(res.getBytes(OWNED_IDENTITY)); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } this.deviceUid = new UID(res.getBytes(DEVICE_UID)); this.pushNotificationType = res.getByte(PUSH_NOTIFICATION_TYPE); @@ -221,7 +221,7 @@ public static PushNotificationConfiguration get(FetchManagerSession fetchManager } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -255,7 +255,7 @@ public void clearKickOtherDevices() { statement.executeUpdate(); this.multiDeviceConfiguration = newMultiDeviceConfiguration; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/ServerSession.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/ServerSession.java index d6257459..bf8fc323 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/ServerSession.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/databases/ServerSession.java @@ -155,7 +155,7 @@ public void setChallengeAndNonce(byte[] challenge, byte[] nonce) { this.challenge = challenge; this.nonce = nonce; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -175,7 +175,7 @@ public void setResponseForChallenge(byte[] challenge, byte[] response) { this.response = response; } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -200,7 +200,7 @@ public void setTokenAndPermissions(byte[] token, int apiKeyStatus, long permissi this.permissions = permissions; this.apiKeyExpirationTimestamp = apiKeyExpirationTimestamp; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -213,7 +213,7 @@ public static void deleteCurrentTokenIfEqualTo(FetchManagerSession fetchManagerS statement.setBytes(2, token); statement.executeUpdate(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -225,7 +225,7 @@ public static void deleteForIdentity(FetchManagerSession fetchManagerSession, Id statement.setBytes(1, ownedIdentity.getBytes()); statement.executeUpdate(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -261,7 +261,7 @@ private ServerSession(FetchManagerSession fetchManagerSession, ResultSet res) th try { this.ownedIdentity = Identity.of(res.getBytes(OWNED_IDENTITY)); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } this.nonce = res.getBytes(NONCE); this.challenge = res.getBytes(CHALLENGE); @@ -293,7 +293,7 @@ public static ServerSession get(FetchManagerSession fetchManagerSession, Identit } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/CreateServerSessionCompositeOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/CreateServerSessionCompositeOperation.java index eaa4d689..b4a1a5c5 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/CreateServerSessionCompositeOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/CreateServerSessionCompositeOperation.java @@ -23,6 +23,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.OperationQueue; @@ -108,7 +109,7 @@ public void doExecute() { } finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { setFinished(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DeleteMessageAndAttachmentFromServerAndLocalInboxesOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DeleteMessageAndAttachmentFromServerAndLocalInboxesOperation.java index 73cdbc22..5949f1c6 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DeleteMessageAndAttachmentFromServerAndLocalInboxesOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DeleteMessageAndAttachmentFromServerAndLocalInboxesOperation.java @@ -25,6 +25,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.ServerMethod; @@ -151,7 +152,7 @@ public void doExecute() { return; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -165,7 +166,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DeleteUserDataOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DeleteUserDataOperation.java index 31a2829a..d4b61946 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DeleteUserDataOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DeleteUserDataOperation.java @@ -24,6 +24,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.ServerMethod; @@ -117,7 +118,7 @@ public void doExecute() { return; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -131,7 +132,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadAttachmentOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadAttachmentOperation.java index 10d9866b..748a5902 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadAttachmentOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadAttachmentOperation.java @@ -25,6 +25,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.AuthEnc; import io.olvid.engine.crypto.Suite; import io.olvid.engine.datatypes.Chunk; @@ -220,7 +221,7 @@ public void onProgress(long byteCount) { } finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -235,7 +236,7 @@ public void onProgress(long byteCount) { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadMessagesAndListAttachmentsOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadMessagesAndListAttachmentsOperation.java index 88369133..f8a22eed 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadMessagesAndListAttachmentsOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadMessagesAndListAttachmentsOperation.java @@ -203,7 +203,7 @@ public void doExecute() { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -217,7 +217,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -308,7 +308,7 @@ protected void parseReceivedData(Encoded[] receivedData) { } messageAndAttachmentLengthsArray = list.toArray(new MessageAndAttachmentLengths[0]); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadMessagesExtendedPayloadOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadMessagesExtendedPayloadOperation.java index d3eb459b..5402fc62 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadMessagesExtendedPayloadOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/DownloadMessagesExtendedPayloadOperation.java @@ -23,6 +23,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.AuthEnc; import io.olvid.engine.crypto.Suite; import io.olvid.engine.datatypes.EncryptedBytes; @@ -143,7 +144,7 @@ public void doExecute() { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -157,7 +158,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -211,7 +212,7 @@ protected void parseReceivedData(Encoded[] receivedData) { try { encryptedMessageExtendedPayload = receivedData[0].decodeEncryptedData(); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/FreeTrialOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/FreeTrialOperation.java index d5b01fcb..d76e94d7 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/FreeTrialOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/FreeTrialOperation.java @@ -26,6 +26,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.ServerMethod; @@ -120,7 +121,7 @@ public void doExecute() { fetchManagerSession.notificationPostingDelegate.postNotification(DownloadNotifications.NOTIFICATION_FREE_TRIAL_QUERY_FAILED, userInfo); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -134,7 +135,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -189,7 +190,7 @@ protected void parseReceivedData(Encoded[] receivedData) { this.apiKey = receivedData[0].decodeUuid(); } } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/GetTokenOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/GetTokenOperation.java index 083d6ed3..6c58109e 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/GetTokenOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/GetTokenOperation.java @@ -26,6 +26,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Constants; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; @@ -129,7 +130,7 @@ public void doExecute() { return; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -143,7 +144,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -221,7 +222,7 @@ protected void parseReceivedData(Encoded[] receivedData) { this.permissions = receivedData[3].decodeLong(); this.apiKeyExpiration = receivedData[4].decodeLong(); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/GetTurnCredentialsOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/GetTurnCredentialsOperation.java index b2dbc572..d33df484 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/GetTurnCredentialsOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/GetTurnCredentialsOperation.java @@ -26,6 +26,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.ServerMethod; @@ -157,7 +158,7 @@ public void doExecute() { } finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -170,7 +171,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -244,7 +245,7 @@ protected void parseReceivedData(Encoded[] receivedData) { expiringUsername2 = receivedData[2].decodeString(); password2 = receivedData[3].decodeString(); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ProcessPreKeyMessagesForNewContactOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ProcessPreKeyMessagesForNewContactOperation.java index 2c4b9fcf..119e8840 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ProcessPreKeyMessagesForNewContactOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ProcessPreKeyMessagesForNewContactOperation.java @@ -77,12 +77,12 @@ public void doExecute() { fetchManagerSession.inboxMessageListener.messageWasDownloaded(inboxMessage.getNetworkReceivedMessage()); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { setFinished(); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ProcessWebsocketReceivedMessageOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ProcessWebsocketReceivedMessageOperation.java index 5e2c0447..1e11dbb3 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ProcessWebsocketReceivedMessageOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ProcessWebsocketReceivedMessageOperation.java @@ -22,6 +22,7 @@ import java.sql.SQLException; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.Hash; import io.olvid.engine.crypto.Suite; import io.olvid.engine.datatypes.EncryptedBytes; @@ -102,7 +103,7 @@ public void doExecute() { } finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -116,7 +117,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/QueryApiKeyStatusOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/QueryApiKeyStatusOperation.java index b6dc53e1..7bd650ce 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/QueryApiKeyStatusOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/QueryApiKeyStatusOperation.java @@ -25,6 +25,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.ServerMethod; @@ -147,7 +148,7 @@ protected void parseReceivedData(Encoded[] receivedData) { this.permissions = receivedData[1].decodeLong(); this.apiKeyExpiration = receivedData[2].decodeLong(); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RefreshInboxAttachmentSignedUrlOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RefreshInboxAttachmentSignedUrlOperation.java index c8790f62..812c1b65 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RefreshInboxAttachmentSignedUrlOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RefreshInboxAttachmentSignedUrlOperation.java @@ -23,6 +23,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.ServerMethod; @@ -114,7 +115,7 @@ public void doExecute() { return; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -128,7 +129,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -184,7 +185,7 @@ protected void parseReceivedData(Encoded[] receivedData) { } this.signedUrls = signedUrls; } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RefreshUserDataOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RefreshUserDataOperation.java index 0765ff44..68b26b26 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RefreshUserDataOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RefreshUserDataOperation.java @@ -124,7 +124,7 @@ public void doExecute() { return; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -138,7 +138,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RegisterPushNotificationOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RegisterPushNotificationOperation.java index 97196af6..6fcbb552 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RegisterPushNotificationOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RegisterPushNotificationOperation.java @@ -25,6 +25,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.Suite; import io.olvid.engine.datatypes.EncryptedBytes; import io.olvid.engine.datatypes.Identity; @@ -153,7 +154,7 @@ public void doExecute() { return; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -167,7 +168,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RequestChallengeOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RequestChallengeOperation.java index 7844d7ee..b52b89b8 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RequestChallengeOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/RequestChallengeOperation.java @@ -25,6 +25,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.PRNG; import io.olvid.engine.crypto.PRNGService; import io.olvid.engine.crypto.Suite; @@ -107,7 +108,7 @@ public void doExecute() { return; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -121,7 +122,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -178,7 +179,7 @@ protected void parseReceivedData(Encoded[] receivedData) { } this.challenge = challenge; } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ServerQueryOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ServerQueryOperation.java index 583b7e6c..d68b9387 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ServerQueryOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/ServerQueryOperation.java @@ -338,7 +338,7 @@ public void doExecute() { cancel(RFC_NETWORK_ERROR); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { setFinished(); @@ -350,7 +350,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -413,7 +413,7 @@ protected void parseReceivedData(Encoded[] receivedData) { receivedData[0].decodeDictionary(); serverResponse = receivedData[0]; } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } @@ -464,7 +464,7 @@ protected void parseReceivedData(Encoded[] receivedData) { receivedData[0].decodeEncryptedData(); serverResponse = receivedData[0]; } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } @@ -583,7 +583,7 @@ protected void parseReceivedData(Encoded[] receivedData) { } serverResponse = Encoded.of(userDataPath); } catch (DecodingException | IOException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } else if (returnStatus == ServerMethod.DELETED_FROM_SERVER) { @@ -641,7 +641,7 @@ protected void parseReceivedData(Encoded[] receivedData) { Logger.w("Server responded to verify server query: " + verificationSuccessful); serverResponse = Encoded.of(verificationSuccessful); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } @@ -767,7 +767,7 @@ protected void parseReceivedData(Encoded[] receivedData) { Encoded.of(nonce), }); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.MALFORMED_SERVER_RESPONSE; } } else if (returnStatus == ServerMethod.DELETED_FROM_SERVER) { @@ -844,7 +844,7 @@ protected void parseReceivedData(Encoded[] receivedData) { Encoded.of(lockNonce), }); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.MALFORMED_SERVER_RESPONSE; } } else if (returnStatus == ServerMethod.DELETED_FROM_SERVER @@ -1072,7 +1072,7 @@ protected void parseReceivedData(Encoded[] receivedData) { } serverResponse = Encoded.of(userDataPath); } catch (DecodingException | IOException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } else if (returnStatus == ServerMethod.DELETED_FROM_SERVER) { diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/SolveChallengeOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/SolveChallengeOperation.java index a87955ed..2ed0451b 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/SolveChallengeOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/SolveChallengeOperation.java @@ -21,6 +21,7 @@ import java.sql.SQLException; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.PRNG; import io.olvid.engine.crypto.PRNGService; import io.olvid.engine.crypto.Suite; @@ -88,7 +89,7 @@ public void doExecute() { finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -100,7 +101,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/StandaloneServerQueryOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/StandaloneServerQueryOperation.java index a3131551..ec0623b4 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/StandaloneServerQueryOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/StandaloneServerQueryOperation.java @@ -106,7 +106,7 @@ public void doExecute() { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { setFinished(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/VerifyReceiptOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/VerifyReceiptOperation.java index 3fb73925..bebd37ec 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/VerifyReceiptOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/VerifyReceiptOperation.java @@ -26,6 +26,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Constants; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; @@ -107,7 +108,7 @@ public void doExecute() { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); fetchManagerSession.session.rollback(); } finally { if (finished) { @@ -121,7 +122,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -175,7 +176,7 @@ protected void parseReceivedData(Encoded[] receivedData) { try { this.apiKey = receivedData[0].decodeUuid(); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/WellKnownDownloadOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/WellKnownDownloadOperation.java index 45c7a009..52ece723 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/WellKnownDownloadOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networkfetch/operations/WellKnownDownloadOperation.java @@ -34,6 +34,7 @@ import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.Hash; import io.olvid.engine.crypto.Suite; import io.olvid.engine.datatypes.Operation; @@ -136,7 +137,7 @@ public void doExecute() { try { downloadedWellKnown = objectMapper.readValue(responseData, WellKnownCoordinator.JsonWellKnown.class); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); cancel(RFC_MALFORMED_WELL_KNOWN); return; } @@ -163,7 +164,7 @@ public void doExecute() { finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { fetchManagerSession.session.commit(); @@ -176,7 +177,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/SendManager.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/SendManager.java index a9322acb..2625c4dd 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/SendManager.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/SendManager.java @@ -24,6 +24,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.PRNGService; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Session; @@ -94,7 +95,7 @@ public void setDelegate(CreateSessionDelegate createSessionDelegate) { ReturnReceipt.createTable(sendManagerSession.session); sendManagerSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); throw new RuntimeException("Unable to create network fetch databases"); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/CancelAttachmentUploadCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/CancelAttachmentUploadCoordinator.java index 90a842bf..a6fa6fe6 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/CancelAttachmentUploadCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/CancelAttachmentUploadCoordinator.java @@ -85,7 +85,7 @@ public void initialQueueing() { queueNewCancelAttachmentUploadCompositeOperation(attachment.getOwnedIdentity(), attachment.getMessageUid(), attachment.getAttachmentNumber()); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/RefreshOutboxAttachmentSignedUrlCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/RefreshOutboxAttachmentSignedUrlCoordinator.java index 0e2ea9d2..1c3027d8 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/RefreshOutboxAttachmentSignedUrlCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/RefreshOutboxAttachmentSignedUrlCoordinator.java @@ -160,7 +160,7 @@ public void onCancelCallback(Operation operation) { } sendManagerSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } break; } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendAttachmentCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendAttachmentCoordinator.java index 07824757..9277e206 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendAttachmentCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendAttachmentCoordinator.java @@ -108,7 +108,7 @@ public void initialQueueing() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendMessageCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendMessageCoordinator.java index 4541a90a..a1b002af 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendMessageCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendMessageCoordinator.java @@ -112,7 +112,7 @@ public void initialQueueing() { queueNewSendMessageCompositeOperation(outboxMessage.getServer(), outboxMessage.getOwnedIdentity(), outboxMessage.getUid(), outboxMessage.getAttachments().length != 0, outboxMessage.isApplicationMessage()); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendReturnReceiptCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendReturnReceiptCoordinator.java index fb7c6ccd..91116b88 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendReturnReceiptCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/coordinators/SendReturnReceiptCoordinator.java @@ -92,7 +92,7 @@ public void initialQueueing() { queueNewSendReturnReceiptOperation(returnReceipt.getContactIdentity().getServer(), returnReceipt.getOwnedIdentity(), returnReceipt.getId()); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/MessageHeader.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/MessageHeader.java index 07db1e94..a1466e66 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/MessageHeader.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/MessageHeader.java @@ -82,7 +82,7 @@ public static MessageHeader create(SendManagerSession sendManagerSession, Identi messageHeader.insert(); return messageHeader; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -101,14 +101,14 @@ private MessageHeader(SendManagerSession sendManagerSession, ResultSet res) thro try { this.ownedIdentity = Identity.of(res.getBytes(OWNED_IDENTITY)); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } this.messageUid = new UID(res.getBytes(MESSAGE_UID)); this.deviceUid = new UID(res.getBytes(DEVICE_UID)); try { this.toIdentity = Identity.of(res.getBytes(TO_IDENTITY)); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } this.wrappedKey = new EncryptedBytes(res.getBytes(WRAPPED_KEY)); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/OutboxAttachment.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/OutboxAttachment.java index 932867ab..2d8f64da 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/OutboxAttachment.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/OutboxAttachment.java @@ -248,7 +248,7 @@ public void setAcknowledgedChunkCount(int acknowledgedChunkCount) { } this.acknowledgedChunkCount = acknowledgedChunkCount; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -294,7 +294,7 @@ public static OutboxAttachment create(SendManagerSession session, Identity owned outboxAttachment.insert(); return outboxAttachment; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -320,7 +320,7 @@ private OutboxAttachment(SendManagerSession sendManagerSession, ResultSet res) t try { this.ownedIdentity = Identity.of(res.getBytes(OWNED_IDENTITY)); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } this.messageUid = new UID(res.getBytes(MESSAGE_UID)); this.attachmentNumber = res.getInt(ATTACHMENT_NUMBER); @@ -330,7 +330,7 @@ private OutboxAttachment(SendManagerSession sendManagerSession, ResultSet res) t try { this.key = (AuthEncKey) new Encoded(res.getBytes(KEY)).decodeSymmetricKey(); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } this.acknowledgedChunkCount = res.getInt(ACKNOWLEDGED_CHUNK_COUNT); this.acknowledged = res.getBoolean(ACKNOWLEDGED); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/OutboxMessage.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/OutboxMessage.java index d7e418c6..dc07a26f 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/OutboxMessage.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/OutboxMessage.java @@ -139,7 +139,7 @@ public void setUidFromServer(UID uidFromServer, byte[] nonce, long timestampFrom } sendManagerSession.session.addSessionCommitListener(this); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } } @@ -161,7 +161,7 @@ public static OutboxMessage create(SendManagerSession sendManagerSession, Identi } return outboxMessage; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -171,7 +171,7 @@ private OutboxMessage(SendManagerSession sendManagerSession, ResultSet res) thro try { this.ownedIdentity = Identity.of(res.getBytes(OWNED_IDENTITY)); } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); } this.uid = new UID(res.getBytes(UID_)); byte[] bytes = res.getBytes(UID_FROM_SERVER); @@ -265,7 +265,7 @@ public static OutboxMessage[] getAll(SendManagerSession sendManagerSession) { return list.toArray(new OutboxMessage[0]); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return new OutboxMessage[0]; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/ReturnReceipt.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/ReturnReceipt.java index bf18ec05..977c9450 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/ReturnReceipt.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/databases/ReturnReceipt.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.List; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.ObvDatabase; import io.olvid.engine.datatypes.Session; @@ -102,7 +103,7 @@ public static ReturnReceipt create(SendManagerSession sendManagerSession, Identi returnReceipt.insert(); return returnReceipt; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -127,7 +128,7 @@ private ReturnReceipt(SendManagerSession sendManagerSession, ResultSet res) thro this.key = (AuthEncKey) new Encoded(res.getBytes(KEY)).decodeSymmetricKey(); this.contactDeviceUids = new Encoded(res.getBytes(CONTACT_DEVICE_UIDS)).decodeUidArray(); } catch (DecodingException|ClassCastException e) { - e.printStackTrace(); + Logger.x(e); } this.status = res.getInt(STATUS); this.nonce = res.getBytes(NONCE); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/BatchUploadMessagesCompositeOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/BatchUploadMessagesCompositeOperation.java index 6905d4ec..46e4ec98 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/BatchUploadMessagesCompositeOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/BatchUploadMessagesCompositeOperation.java @@ -25,6 +25,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.Hash; import io.olvid.engine.crypto.Suite; import io.olvid.engine.datatypes.Operation; @@ -120,7 +121,7 @@ public void doExecute() { } finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { setFinished(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/BatchUploadMessagesOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/BatchUploadMessagesOperation.java index 43a8aaf8..1a9a4ce3 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/BatchUploadMessagesOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/BatchUploadMessagesOperation.java @@ -137,7 +137,7 @@ public void doExecute() { cancel(BatchUploadMessagesCompositeOperation.RFC_NETWORK_ERROR); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); sendManagerSession.session.rollback(); } finally { if (finished) { @@ -151,7 +151,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -234,7 +234,7 @@ protected void parseReceivedData(Encoded[] receivedData) { outboxMessageAndHeaders[i].timestampFromServer = encodeds[2].decodeLong(); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.OK_WITH_MALFORMED_SERVER_RESPONSE; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/CancelAttachmentUploadCompositeOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/CancelAttachmentUploadCompositeOperation.java index d727c50b..050f819f 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/CancelAttachmentUploadCompositeOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/CancelAttachmentUploadCompositeOperation.java @@ -22,6 +22,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.OperationQueue; @@ -99,7 +100,7 @@ public void doExecute() { } finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { setFinished(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/CancelAttachmentUploadOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/CancelAttachmentUploadOperation.java index 410b2f22..5263453b 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/CancelAttachmentUploadOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/CancelAttachmentUploadOperation.java @@ -122,7 +122,7 @@ public void doExecute() { cancel(CancelAttachmentUploadCompositeOperation.RFC_NETWORK_ERROR); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); sendManagerSession.session.rollback(); } finally { if (finished) { @@ -136,7 +136,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/RefreshOutboxAttachmentSignedUrlOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/RefreshOutboxAttachmentSignedUrlOperation.java index 5c848836..182872fe 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/RefreshOutboxAttachmentSignedUrlOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/RefreshOutboxAttachmentSignedUrlOperation.java @@ -23,6 +23,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.ServerMethod; @@ -127,7 +128,7 @@ public void doExecute() { return; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); sendManagerSession.session.rollback(); } finally { if (finished) { @@ -141,7 +142,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -200,7 +201,7 @@ protected void parseReceivedData(Encoded[] receivedData) { } this.signedUrls = signedUrls; } catch (DecodingException e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.GENERAL_ERROR; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/TryToDeleteMessageAndAttachmentsOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/TryToDeleteMessageAndAttachmentsOperation.java index 32f095f7..ac1efbc1 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/TryToDeleteMessageAndAttachmentsOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/TryToDeleteMessageAndAttachmentsOperation.java @@ -22,6 +22,7 @@ import java.io.File; import java.sql.SQLException; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.UID; @@ -100,7 +101,7 @@ public void doExecute() { outboxMessage.delete(); finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); sendManagerSession.session.rollback(); } finally { if (finished) { @@ -112,7 +113,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadAttachmentCompositeOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadAttachmentCompositeOperation.java index 1b119a97..fa5ccdb1 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadAttachmentCompositeOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadAttachmentCompositeOperation.java @@ -22,6 +22,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.OperationQueue; @@ -116,7 +117,7 @@ public void doExecute() { } finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { setFinished(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadAttachmentOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadAttachmentOperation.java index e8f105b4..667deba9 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadAttachmentOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadAttachmentOperation.java @@ -217,7 +217,7 @@ public void onProgress(long byteCount) { return; } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { sendManagerSession.session.commit(); @@ -230,7 +230,7 @@ public void onProgress(long byteCount) { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadMessageAndGetUidsOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadMessageAndGetUidsOperation.java index c5d7c6d4..44353aba 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadMessageAndGetUidsOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadMessageAndGetUidsOperation.java @@ -24,6 +24,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Constants; import io.olvid.engine.datatypes.EncryptedBytes; import io.olvid.engine.datatypes.Identity; @@ -150,7 +151,7 @@ public void doExecute() { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); sendManagerSession.session.rollback(); } finally { if (finished) { @@ -164,7 +165,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } @@ -277,7 +278,7 @@ protected void parseReceivedData(Encoded[] receivedData) { attachmentChunkUploadPrivateUrls[i] = encodeds[i].decodeStringArray(); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); returnStatus = ServerMethod.OK_WITH_MALFORMED_SERVER_RESPONSE; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadMessageCompositeOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadMessageCompositeOperation.java index 75a36890..083438c3 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadMessageCompositeOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadMessageCompositeOperation.java @@ -21,6 +21,7 @@ import javax.net.ssl.SSLSocketFactory; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.Operation; import io.olvid.engine.datatypes.OperationQueue; @@ -91,7 +92,7 @@ public void doExecute() { } finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { setFinished(); diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadReturnReceiptOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadReturnReceiptOperation.java index 09f942fe..c4cbf3ca 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadReturnReceiptOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/networksend/operations/UploadReturnReceiptOperation.java @@ -166,7 +166,7 @@ public void doExecute() { cancel(null); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); sendManagerSession.session.rollback(); } finally { if (finished) { @@ -180,7 +180,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/ProtocolManager.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/ProtocolManager.java index 0f090000..8cd5011f 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/ProtocolManager.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/ProtocolManager.java @@ -204,7 +204,7 @@ public void initialisationComplete() { protocolManagerSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } // schedulerForPeriodicSync.scheduleAtFixedRate(this::triggerOwnedDevicesSync, Constants.PERIODIC_OWNED_DEVICE_SYNC_INTERVAL, Constants.PERIODIC_OWNED_DEVICE_SYNC_INTERVAL, TimeUnit.MILLISECONDS); @@ -223,7 +223,7 @@ public void initialisationComplete() { // // protocolManagerSession.session.commit(); // } catch (Exception e) { -// e.printStackTrace(); +// Logger.x(e); // } // } @@ -245,7 +245,7 @@ public void setDelegate(CreateSessionDelegate createSessionDelegate) { IdentityDeletionSignatureReceived.createTable(protocolManagerSession.session); protocolManagerSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); throw new RuntimeException("Unable to create protocol databases"); } } @@ -314,7 +314,7 @@ public void callback(String notificationName, HashMap userInfo) startChannelCreationWithContactDeviceProtocol(ownedIdentity, contactIdentity, contactDeviceUid); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -327,7 +327,7 @@ public void callback(String notificationName, HashMap userInfo) startChannelCreationWithOwnedDeviceProtocol(ownedIdentity, ownedDeviceUid); } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -356,7 +356,7 @@ public void callback(String notificationName, HashMap userInfo) } // To improve: delete any other protocol related to this contact } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -384,7 +384,7 @@ public void callback(String notificationName, HashMap userInfo) } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -1469,7 +1469,7 @@ public void initiateSingleItemSync(Session session, Identity ownedIdentity, ObvS // protocolManagerSession.channelDelegate.post(protocolManagerSession.session, message, prng); // } // } catch (Exception e) { -// e.printStackTrace(); +// Logger.x(e); // } // } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/coordinators/ProtocolStepCoordinator.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/coordinators/ProtocolStepCoordinator.java index 5c562938..6665eb46 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/coordinators/ProtocolStepCoordinator.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/coordinators/ProtocolStepCoordinator.java @@ -80,7 +80,7 @@ public void initialQueueing() { } protocolManagerSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -105,7 +105,7 @@ public void onFinishCallback(Operation operation) { } protocolManagerSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } @@ -136,7 +136,7 @@ public void onCancelCallback(Operation operation) { message.delete(); protocolManagerSession.session.commit(); } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } } else { // retry to execute the step @@ -155,7 +155,7 @@ public void onCancelCallback(Operation operation) { protocolManagerSession.session.commit(); } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); } break; } @@ -171,7 +171,7 @@ public void onCancelCallback(Operation operation) { protocolManagerSession.session.commit(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } break; } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ChannelCreationPingSignatureReceived.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ChannelCreationPingSignatureReceived.java index 498be23c..f2088fa1 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ChannelCreationPingSignatureReceived.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ChannelCreationPingSignatureReceived.java @@ -51,7 +51,7 @@ public static ChannelCreationPingSignatureReceived create(ProtocolManagerSession channelCreationPingSignatureReceived.insert(); return channelCreationPingSignatureReceived; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ChannelCreationProtocolInstance.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ChannelCreationProtocolInstance.java index 60fbeae7..dec1acc6 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ChannelCreationProtocolInstance.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ChannelCreationProtocolInstance.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.List; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.ObvDatabase; import io.olvid.engine.datatypes.Session; @@ -68,7 +69,7 @@ public static ChannelCreationProtocolInstance create(ProtocolManagerSession prot channelCreationProtocolInstance.insert(); return channelCreationProtocolInstance; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/GroupV2SignatureReceived.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/GroupV2SignatureReceived.java index 1f3c5859..7cc2062c 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/GroupV2SignatureReceived.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/GroupV2SignatureReceived.java @@ -54,7 +54,7 @@ public static GroupV2SignatureReceived create(ProtocolManagerSession protocolMan groupV2SignatureReceived.insert(); return groupV2SignatureReceived; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/IdentityDeletionSignatureReceived.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/IdentityDeletionSignatureReceived.java index 1ecb7705..669d3791 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/IdentityDeletionSignatureReceived.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/IdentityDeletionSignatureReceived.java @@ -54,7 +54,7 @@ public static IdentityDeletionSignatureReceived create(ProtocolManagerSession pr identityDeletionSignatureReceived.insert(); return identityDeletionSignatureReceived; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/LinkBetweenProtocolInstances.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/LinkBetweenProtocolInstances.java index 58faf815..6d2d5aa4 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/LinkBetweenProtocolInstances.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/LinkBetweenProtocolInstances.java @@ -76,7 +76,7 @@ public static LinkBetweenProtocolInstances create(ProtocolManagerSession protoco linkBetweenProtocolInstances.insert(); return linkBetweenProtocolInstances; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/MutualScanSignatureReceived.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/MutualScanSignatureReceived.java index 3e45e105..6c7f535a 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/MutualScanSignatureReceived.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/MutualScanSignatureReceived.java @@ -54,7 +54,7 @@ public static MutualScanSignatureReceived create(ProtocolManagerSession protocol mutualScanSignatureReceived.insert(); return mutualScanSignatureReceived; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ProtocolInstance.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ProtocolInstance.java index 16e05b26..da8fcd4c 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ProtocolInstance.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ProtocolInstance.java @@ -121,7 +121,7 @@ public static ProtocolInstance create(ProtocolManagerSession protocolManagerSess protocolInstance.insert(); return protocolInstance; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ReceivedMessage.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ReceivedMessage.java index ad16364f..02218bfc 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ReceivedMessage.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/ReceivedMessage.java @@ -137,7 +137,7 @@ public static ReceivedMessage create(ProtocolManagerSession protocolManagerSessi receivedMessage.insert(); return receivedMessage; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -334,7 +334,7 @@ public static ReceivedMessage get(ProtocolManagerSession protocolManagerSession, } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/TrustEstablishmentCommitmentReceived.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/TrustEstablishmentCommitmentReceived.java index 25b8522c..546893a2 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/TrustEstablishmentCommitmentReceived.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/TrustEstablishmentCommitmentReceived.java @@ -24,6 +24,7 @@ import java.sql.SQLException; import java.sql.Statement; +import io.olvid.engine.Logger; import io.olvid.engine.datatypes.Identity; import io.olvid.engine.datatypes.ObvDatabase; import io.olvid.engine.datatypes.Session; @@ -51,7 +52,7 @@ public static TrustEstablishmentCommitmentReceived create(ProtocolManagerSession trustEstablishmentCommitmentReceived.insert(); return trustEstablishmentCommitmentReceived; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/WaitingForOneToOneContactProtocolInstance.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/WaitingForOneToOneContactProtocolInstance.java index 774d96ed..36d44231 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/WaitingForOneToOneContactProtocolInstance.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/databases/WaitingForOneToOneContactProtocolInstance.java @@ -164,7 +164,7 @@ public static WaitingForOneToOneContactProtocolInstance create(ProtocolManagerSe instance.insert(); return instance; } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ConcreteProtocol.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ConcreteProtocol.java index b2489165..fbda4f60 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ConcreteProtocol.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ConcreteProtocol.java @@ -258,7 +258,7 @@ public final ConcreteProtocolMessage getConcreteProtocolMessage(ReceivedMessage Constructor constructor = messageClass.getConstructor(ReceivedMessage.class); return (ConcreteProtocolMessage) constructor.newInstance(receivedMessage); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } @@ -281,7 +281,7 @@ public final ProtocolStep getStepToExecute(ConcreteProtocolMessage concreteProto } return (ProtocolStep) constructor.newInstance(currentState, concreteProtocolMessage, this); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); return null; } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ProtocolOperation.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ProtocolOperation.java index 948d2449..b6991c3d 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ProtocolOperation.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ProtocolOperation.java @@ -118,7 +118,7 @@ public void doExecute() { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } if (protocol == null) { cancel(RFC_UNABLE_TO_RECONSTRUCT_PROTOCOL); @@ -194,7 +194,7 @@ public void doExecute() { finished = true; } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } finally { if (finished) { protocolManagerSession.session.commit(); @@ -208,7 +208,7 @@ public void doExecute() { } } } catch (SQLException e) { - e.printStackTrace(); + Logger.x(e); cancel(null); processCancel(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ProtocolStep.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ProtocolStep.java index a0790fa6..e50bb0fd 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ProtocolStep.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocol_engine/ProtocolStep.java @@ -78,7 +78,7 @@ public void doExecute() { setFinished(); } catch (Exception e) { cancel(null); - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/ChannelCreationWithContactDeviceProtocol.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/ChannelCreationWithContactDeviceProtocol.java index 938f04bd..c92db261 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/ChannelCreationWithContactDeviceProtocol.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/ChannelCreationWithContactDeviceProtocol.java @@ -1086,7 +1086,7 @@ public ConcreteProtocolState executeStep() throws Exception { JsonIdentityDetailsWithVersionAndPhoto ownedDetailsWithVersionAndPhoto = protocolManagerSession.identityDelegate.getOwnedIdentityPublishedAndLatestDetails(protocolManagerSession.session, getOwnedIdentity())[0]; serializedDetailsWithVersionAndPhoto = protocol.getJsonObjectMapper().writeValueAsString(ownedDetailsWithVersionAndPhoto); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } CoreProtocolMessage coreProtocolMessage = buildCoreProtocolMessage(SendChannelInfo.createObliviousChannelInfo( @@ -1138,7 +1138,7 @@ public ConcreteProtocolState executeStep() throws Exception { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1183,7 +1183,7 @@ public ConcreteProtocolState executeStep() throws Exception { JsonIdentityDetailsWithVersionAndPhoto ownedDetailsWithVersionAndPhoto = protocolManagerSession.identityDelegate.getOwnedIdentityPublishedAndLatestDetails(protocolManagerSession.session, getOwnedIdentity())[0]; serializedDetailsWithVersionAndPhoto = protocol.getJsonObjectMapper().writeValueAsString(ownedDetailsWithVersionAndPhoto); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } CoreProtocolMessage coreProtocolMessage = buildCoreProtocolMessage(SendChannelInfo.createObliviousChannelInfo( @@ -1249,7 +1249,7 @@ public ConcreteProtocolState executeStep() throws Exception { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/ChannelCreationWithOwnedDeviceProtocol.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/ChannelCreationWithOwnedDeviceProtocol.java index 8c9842df..5ae4766c 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/ChannelCreationWithOwnedDeviceProtocol.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/ChannelCreationWithOwnedDeviceProtocol.java @@ -1055,7 +1055,7 @@ public ConcreteProtocolState executeStep() throws Exception { JsonIdentityDetailsWithVersionAndPhoto ownedDetailsWithVersionAndPhoto = protocolManagerSession.identityDelegate.getOwnedIdentityPublishedAndLatestDetails(protocolManagerSession.session, getOwnedIdentity())[0]; serializedDetailsWithVersionAndPhoto = protocol.getJsonObjectMapper().writeValueAsString(ownedDetailsWithVersionAndPhoto); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } CoreProtocolMessage coreProtocolMessage = buildCoreProtocolMessage(SendChannelInfo.createObliviousChannelInfo( @@ -1106,7 +1106,7 @@ public ConcreteProtocolState executeStep() throws Exception { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -1150,7 +1150,7 @@ public ConcreteProtocolState executeStep() throws Exception { JsonIdentityDetailsWithVersionAndPhoto ownedDetailsWithVersionAndPhoto = protocolManagerSession.identityDelegate.getOwnedIdentityPublishedAndLatestDetails(protocolManagerSession.session, getOwnedIdentity())[0]; serializedDetailsWithVersionAndPhoto = protocol.getJsonObjectMapper().writeValueAsString(ownedDetailsWithVersionAndPhoto); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } CoreProtocolMessage coreProtocolMessage = buildCoreProtocolMessage(SendChannelInfo.createObliviousChannelInfo( @@ -1214,7 +1214,7 @@ public ConcreteProtocolState executeStep() throws Exception { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DeviceDiscoveryProtocol.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DeviceDiscoveryProtocol.java index b6731aa2..98a0a87a 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DeviceDiscoveryProtocol.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DeviceDiscoveryProtocol.java @@ -337,7 +337,7 @@ public ConcreteProtocolState executeStep() throws Exception { } } catch (Exception e) { Logger.i("Malformed server response id device discovery"); - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadGroupPhotoChildProtocol.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadGroupPhotoChildProtocol.java index 1df9bcc6..683b74e0 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadGroupPhotoChildProtocol.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadGroupPhotoChildProtocol.java @@ -26,6 +26,7 @@ import java.io.File; import java.io.FileInputStream; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.PRNGService; import io.olvid.engine.crypto.Suite; import io.olvid.engine.datatypes.EncryptedBytes; @@ -304,7 +305,7 @@ public ConcreteProtocolState executeStep() throws Exception { //noinspection ResultOfMethodCallIgnored new File(protocolManagerSession.engineBaseDirectory, receivedMessage.photoPathToDelete).delete(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } return new PhotoDownloadedState(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadGroupV2PhotoProtocol.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadGroupV2PhotoProtocol.java index d2a3c81b..04148133 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadGroupV2PhotoProtocol.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadGroupV2PhotoProtocol.java @@ -26,6 +26,7 @@ import java.io.File; import java.io.FileInputStream; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.PRNGService; import io.olvid.engine.crypto.Suite; import io.olvid.engine.datatypes.EncryptedBytes; @@ -306,7 +307,7 @@ public ConcreteProtocolState executeStep() throws Exception { //noinspection ResultOfMethodCallIgnored new File(protocolManagerSession.engineBaseDirectory, receivedMessage.photoPathToDelete).delete(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } return new PhotoDownloadedState(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadIdentityPhotoChildProtocol.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadIdentityPhotoChildProtocol.java index 42f7fb55..0a273ead 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadIdentityPhotoChildProtocol.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/DownloadIdentityPhotoChildProtocol.java @@ -26,6 +26,7 @@ import java.io.File; import java.io.FileInputStream; +import io.olvid.engine.Logger; import io.olvid.engine.crypto.PRNGService; import io.olvid.engine.crypto.Suite; import io.olvid.engine.datatypes.EncryptedBytes; @@ -316,7 +317,7 @@ public ConcreteProtocolState executeStep() throws Exception { //noinspection ResultOfMethodCallIgnored new File(protocolManagerSession.engineBaseDirectory, receivedMessage.photoPathToDelete).delete(); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } return new PhotoDownloadedState(); } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/GroupsV2Protocol.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/GroupsV2Protocol.java index 2bcaae58..eef89bc1 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/GroupsV2Protocol.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/GroupsV2Protocol.java @@ -3422,7 +3422,7 @@ public ConcreteProtocolState executeStep() throws Exception { } } } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } } @@ -3662,7 +3662,7 @@ public ConcreteProtocolState executeStep() throws Exception { } } catch (Exception e) { Logger.w("Failed to decrypt/verify server blob during update"); - e.printStackTrace(); + Logger.x(e); unfreezeAndNotifyUpdateFailed(protocolManagerSession, true); return new FinalState(); } @@ -4811,7 +4811,7 @@ public ConcreteProtocolState executeStep() throws Exception { try { keycloakGroupBlob = protocol.getJsonObjectMapper().readValue(receivedMessage.serializedKeycloakGroupBlob, KeycloakGroupBlob.class); } catch (JsonProcessingException e) { - e.printStackTrace(); + Logger.x(e); // if the json can't be parsed, don't do anything return new FinalState(); } @@ -4845,7 +4845,7 @@ public ConcreteProtocolState executeStep() throws Exception { protocolManagerSession.channelDelegate.post(protocolManagerSession.session, messageToSend, getPrng()); } catch (Exception e) { // if photo download fails, do not abort the whole step - e.printStackTrace(); + Logger.x(e); } } @@ -4896,7 +4896,7 @@ public ConcreteProtocolState executeStep() throws Exception { protocolManagerSession.channelDelegate.post(protocolManagerSession.session, messageToSend, getPrng()); } catch (Exception e) { // if photo download fails, do not abort the whole step - e.printStackTrace(); + Logger.x(e); } } diff --git a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/OwnedIdentityTransferProtocol.java b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/OwnedIdentityTransferProtocol.java index a1cc46f3..43a61fd9 100644 --- a/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/OwnedIdentityTransferProtocol.java +++ b/obv_engine/engine/src/main/java/io/olvid/engine/protocol/protocols/OwnedIdentityTransferProtocol.java @@ -1595,7 +1595,7 @@ public ConcreteProtocolState executeStep() throws Exception { // trigger the device keep active request protocolManagerSession.protocolStarterDelegate.processDeviceManagementRequest(startState.transferredIdentity, ObvDeviceManagementRequest.createSetUnexpiringDeviceRequest(deviceUidToKeepActive.getBytes())); } catch (Exception e) { - e.printStackTrace(); + Logger.x(e); } }; // register it diff --git a/obv_messenger/.idea/inspectionProfiles/Project_Default.xml b/obv_messenger/.idea/inspectionProfiles/Project_Default.xml index c0b0a8fc..18daa719 100644 --- a/obv_messenger/.idea/inspectionProfiles/Project_Default.xml +++ b/obv_messenger/.idea/inspectionProfiles/Project_Default.xml @@ -1,14 +1,39 @@ diff --git a/obv_messenger/app/build.gradle b/obv_messenger/app/build.gradle index fd166d66..18b6c8cc 100644 --- a/obv_messenger/app/build.gradle +++ b/obv_messenger/app/build.gradle @@ -19,8 +19,8 @@ android { applicationId "io.olvid.messenger" minSdkVersion 21 targetSdk 34 - versionCode 254 - versionName "3.2.2" + versionCode 255 + versionName "3.3" vectorDrawables.useSupportLibrary true multiDexEnabled true resourceConfigurations += ['en', 'fr'] @@ -165,7 +165,7 @@ dependencies { implementation "com.google.accompanist:accompanist-permissions:$accompanist_version" implementation 'sh.calvin.reorderable:reorderable:2.3.3' - final def coil_version = "2.6.0" + final def coil_version = '2.7.0' implementation "io.coil-kt:coil-compose:$coil_version" implementation "io.coil-kt:coil-video:$coil_version" implementation "io.coil-kt:coil-svg:$coil_version" @@ -199,6 +199,7 @@ dependencies { implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.recyclerview:recyclerview:1.3.2' implementation "androidx.room:room-runtime:$roomVersion" + implementation "androidx.room:room-ktx:$roomVersion" implementation 'net.zetetic:sqlcipher-android:4.5.6@aar' implementation 'androidx.sharetarget:sharetarget:1.2.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' diff --git a/obv_messenger/app/schemas/io.olvid.messenger.databases.AppDatabase/70.json b/obv_messenger/app/schemas/io.olvid.messenger.databases.AppDatabase/70.json new file mode 100644 index 00000000..c25c8e5f --- /dev/null +++ b/obv_messenger/app/schemas/io.olvid.messenger.databases.AppDatabase/70.json @@ -0,0 +1,3042 @@ +{ + "formatVersion": 1, + "database": { + "version": 70, + "identityHash": "c1f527941e55c83610515d219f97715c", + "entities": [ + { + "tableName": "contact_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bytes_contact_identity` BLOB NOT NULL, `bytes_owned_identity` BLOB NOT NULL, `custom_display_name` TEXT, `display_name` TEXT NOT NULL, `first_name` TEXT, `sort_display_name` BLOB NOT NULL, `full_search_display_name` TEXT NOT NULL, `identity_details` TEXT, `new_published_details` INTEGER NOT NULL, `device_count` INTEGER NOT NULL, `established_channel_count` INTEGER NOT NULL, `pre_key_count` INTEGER NOT NULL, `photo_url` TEXT, `custom_photo_url` TEXT, `keycloak_managed` INTEGER NOT NULL, `custom_name_hue` INTEGER, `personal_note` TEXT, `active` INTEGER NOT NULL, `one_to_one` INTEGER NOT NULL, `recently_online` INTEGER NOT NULL, `trust_level` INTEGER NOT NULL, `capability_webrtc_continuous_ice` INTEGER NOT NULL, `capability_groups_v2` INTEGER NOT NULL, `capability_one_to_one_contacts` INTEGER NOT NULL, PRIMARY KEY(`bytes_owned_identity`, `bytes_contact_identity`), FOREIGN KEY(`bytes_owned_identity`) REFERENCES `identity_table`(`bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "bytesContactIdentity", + "columnName": "bytes_contact_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "customDisplayName", + "columnName": "custom_display_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "displayName", + "columnName": "display_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "firstName", + "columnName": "first_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sortDisplayName", + "columnName": "sort_display_name", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "fullSearchDisplayName", + "columnName": "full_search_display_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "identityDetails", + "columnName": "identity_details", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "newPublishedDetails", + "columnName": "new_published_details", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deviceCount", + "columnName": "device_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "establishedChannelCount", + "columnName": "established_channel_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "preKeyCount", + "columnName": "pre_key_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "photoUrl", + "columnName": "photo_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customPhotoUrl", + "columnName": "custom_photo_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "keycloakManaged", + "columnName": "keycloak_managed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "customNameHue", + "columnName": "custom_name_hue", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "personalNote", + "columnName": "personal_note", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "active", + "columnName": "active", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "oneToOne", + "columnName": "one_to_one", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recentlyOnline", + "columnName": "recently_online", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "trustLevel", + "columnName": "trust_level", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "capabilityWebrtcContinuousIce", + "columnName": "capability_webrtc_continuous_ice", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "capabilityGroupsV2", + "columnName": "capability_groups_v2", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "capabilityOneToOneContacts", + "columnName": "capability_one_to_one_contacts", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bytes_owned_identity", + "bytes_contact_identity" + ] + }, + "indices": [ + { + "name": "index_contact_table_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_table_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_owned_identity`)" + }, + { + "name": "index_contact_table_display_name", + "unique": false, + "columnNames": [ + "display_name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_table_display_name` ON `${TABLE_NAME}` (`display_name`)" + }, + { + "name": "index_contact_table_custom_display_name", + "unique": false, + "columnNames": [ + "custom_display_name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_table_custom_display_name` ON `${TABLE_NAME}` (`custom_display_name`)" + }, + { + "name": "index_contact_table_sort_display_name", + "unique": false, + "columnNames": [ + "sort_display_name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_table_sort_display_name` ON `${TABLE_NAME}` (`sort_display_name`)" + } + ], + "foreignKeys": [ + { + "table": "identity_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_owned_identity" + ] + } + ] + }, + { + "tableName": "group_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bytes_group_owner_and_uid` BLOB NOT NULL, `bytes_owned_identity` BLOB NOT NULL, `custom_name` TEXT, `name` TEXT NOT NULL, `new_published_details` INTEGER NOT NULL, `bytes_group_owner_identity` BLOB, `photo_url` TEXT, `group_members_names` TEXT NOT NULL, `custom_photo_url` TEXT, `personal_note` TEXT, `full_search_field` TEXT NOT NULL, PRIMARY KEY(`bytes_group_owner_and_uid`, `bytes_owned_identity`), FOREIGN KEY(`bytes_owned_identity`) REFERENCES `identity_table`(`bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`bytes_group_owner_identity`, `bytes_owned_identity`) REFERENCES `contact_table`(`bytes_contact_identity`, `bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "bytesGroupOwnerAndUid", + "columnName": "bytes_group_owner_and_uid", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "customName", + "columnName": "custom_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "newPublishedDetails", + "columnName": "new_published_details", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bytesGroupOwnerIdentity", + "columnName": "bytes_group_owner_identity", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "photoUrl", + "columnName": "photo_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "groupMembersNames", + "columnName": "group_members_names", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "customPhotoUrl", + "columnName": "custom_photo_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "personalNote", + "columnName": "personal_note", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "fullSearchField", + "columnName": "full_search_field", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bytes_group_owner_and_uid", + "bytes_owned_identity" + ] + }, + "indices": [ + { + "name": "index_group_table_name", + "unique": false, + "columnNames": [ + "name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_group_table_name` ON `${TABLE_NAME}` (`name`)" + }, + { + "name": "index_group_table_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_group_table_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_owned_identity`)" + }, + { + "name": "index_group_table_bytes_group_owner_identity_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_group_owner_identity", + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_group_table_bytes_group_owner_identity_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_group_owner_identity`, `bytes_owned_identity`)" + } + ], + "foreignKeys": [ + { + "table": "identity_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_owned_identity" + ] + }, + { + "table": "contact_table", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_group_owner_identity", + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_contact_identity", + "bytes_owned_identity" + ] + } + ] + }, + { + "tableName": "contact_group_join", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bytes_group_owner_and_uid` BLOB NOT NULL, `bytes_contact_identity` BLOB NOT NULL, `bytes_owned_identity` BLOB NOT NULL, `timestamp` INTEGER NOT NULL, PRIMARY KEY(`bytes_group_owner_and_uid`, `bytes_owned_identity`, `bytes_contact_identity`), FOREIGN KEY(`bytes_group_owner_and_uid`, `bytes_owned_identity`) REFERENCES `group_table`(`bytes_group_owner_and_uid`, `bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`bytes_contact_identity`, `bytes_owned_identity`) REFERENCES `contact_table`(`bytes_contact_identity`, `bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "bytesGroupUid", + "columnName": "bytes_group_owner_and_uid", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesContactIdentity", + "columnName": "bytes_contact_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bytes_group_owner_and_uid", + "bytes_owned_identity", + "bytes_contact_identity" + ] + }, + "indices": [ + { + "name": "index_contact_group_join_bytes_group_owner_and_uid_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_group_owner_and_uid", + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_group_join_bytes_group_owner_and_uid_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_group_owner_and_uid`, `bytes_owned_identity`)" + }, + { + "name": "index_contact_group_join_bytes_contact_identity_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_contact_identity", + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_group_join_bytes_contact_identity_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_contact_identity`, `bytes_owned_identity`)" + } + ], + "foreignKeys": [ + { + "table": "group_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_group_owner_and_uid", + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_group_owner_and_uid", + "bytes_owned_identity" + ] + }, + { + "table": "contact_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_contact_identity", + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_contact_identity", + "bytes_owned_identity" + ] + } + ] + }, + { + "tableName": "pending_group_member_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bytes_identity` BLOB NOT NULL, `display_name` TEXT NOT NULL, `bytes_owned_identity` BLOB NOT NULL, `bytes_group_owner_and_uid` BLOB NOT NULL, `declined` INTEGER NOT NULL, PRIMARY KEY(`bytes_identity`, `bytes_owned_identity`, `bytes_group_owner_and_uid`), FOREIGN KEY(`bytes_group_owner_and_uid`, `bytes_owned_identity`) REFERENCES `group_table`(`bytes_group_owner_and_uid`, `bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "bytesIdentity", + "columnName": "bytes_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "displayName", + "columnName": "display_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesGroupOwnerAndUid", + "columnName": "bytes_group_owner_and_uid", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "declined", + "columnName": "declined", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bytes_identity", + "bytes_owned_identity", + "bytes_group_owner_and_uid" + ] + }, + "indices": [ + { + "name": "index_pending_group_member_table_bytes_group_owner_and_uid_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_group_owner_and_uid", + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_pending_group_member_table_bytes_group_owner_and_uid_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_group_owner_and_uid`, `bytes_owned_identity`)" + } + ], + "foreignKeys": [ + { + "table": "group_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_group_owner_and_uid", + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_group_owner_and_uid", + "bytes_owned_identity" + ] + } + ] + }, + { + "tableName": "discussion_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT, `bytes_owned_identity` BLOB NOT NULL, `discussion_type` INTEGER NOT NULL, `bytes_discussion_identifier` BLOB NOT NULL, `sender_thread_identifier` TEXT NOT NULL, `last_outbound_message_sequence_number` INTEGER NOT NULL, `last_message_timestamp` INTEGER NOT NULL, `photo_url` TEXT, `keycloak_managed` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `pinned` INTEGER NOT NULL, `active` INTEGER NOT NULL, `trust_level` INTEGER, `status` INTEGER NOT NULL, FOREIGN KEY(`bytes_owned_identity`) REFERENCES `identity_table`(`bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "discussionType", + "columnName": "discussion_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bytesDiscussionIdentifier", + "columnName": "bytes_discussion_identifier", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "senderThreadIdentifier", + "columnName": "sender_thread_identifier", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastOutboundMessageSequenceNumber", + "columnName": "last_outbound_message_sequence_number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastMessageTimestamp", + "columnName": "last_message_timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "photoUrl", + "columnName": "photo_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "keycloakManaged", + "columnName": "keycloak_managed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "pinned", + "columnName": "pinned", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "active", + "columnName": "active", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "trustLevel", + "columnName": "trust_level", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_discussion_table_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_discussion_table_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_owned_identity`)" + }, + { + "name": "index_discussion_table_bytes_owned_identity_discussion_type_bytes_discussion_identifier", + "unique": true, + "columnNames": [ + "bytes_owned_identity", + "discussion_type", + "bytes_discussion_identifier" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_discussion_table_bytes_owned_identity_discussion_type_bytes_discussion_identifier` ON `${TABLE_NAME}` (`bytes_owned_identity`, `discussion_type`, `bytes_discussion_identifier`)" + }, + { + "name": "index_discussion_table_title", + "unique": false, + "columnNames": [ + "title" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_discussion_table_title` ON `${TABLE_NAME}` (`title`)" + } + ], + "foreignKeys": [ + { + "table": "identity_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_owned_identity" + ] + } + ] + }, + { + "tableName": "discussion_customization_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`discussion_id` INTEGER NOT NULL, `serialized_color_json` TEXT, `background_image_url` TEXT, `pref_send_read_receipt` INTEGER, `pref_mute_notifications` INTEGER NOT NULL, `pref_mute_notifications_except_mentioned` INTEGER NOT NULL, `pref_mute_notifications_timestamp` INTEGER, `pref_auto_open_limited_visibility_inbound` INTEGER, `pref_retain_wiped_outbound_messages` INTEGER, `pref_discussion_retention_count` INTEGER, `pref_discussion_retention_duration` INTEGER, `pref_use_custom_message_notification` INTEGER NOT NULL, `pref_message_notification_ringtone` TEXT, `pref_message_notification_vibration_pattern` TEXT, `pref_message_notification_led_color` TEXT, `pref_use_custom_call_notification` INTEGER NOT NULL, `pref_call_notification_ringtone` TEXT, `pref_call_notification_vibration_pattern` TEXT, `pref_call_notification_use_flash` INTEGER NOT NULL, `shared_settings_version` INTEGER, `setting_existence_duration` INTEGER, `setting_visibility_duration` INTEGER, `setting_read_once` INTEGER NOT NULL, PRIMARY KEY(`discussion_id`), FOREIGN KEY(`discussion_id`) REFERENCES `discussion_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "discussionId", + "columnName": "discussion_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "serializedColorJson", + "columnName": "serialized_color_json", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "backgroundImageUrl", + "columnName": "background_image_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "prefSendReadReceipt", + "columnName": "pref_send_read_receipt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "prefMuteNotifications", + "columnName": "pref_mute_notifications", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "prefMuteNotificationsExceptMentioned", + "columnName": "pref_mute_notifications_except_mentioned", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "prefMuteNotificationsTimestamp", + "columnName": "pref_mute_notifications_timestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "prefAutoOpenLimitedVisibilityInboundMessages", + "columnName": "pref_auto_open_limited_visibility_inbound", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "prefRetainWipedOutboundMessages", + "columnName": "pref_retain_wiped_outbound_messages", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "prefDiscussionRetentionCount", + "columnName": "pref_discussion_retention_count", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "prefDiscussionRetentionDuration", + "columnName": "pref_discussion_retention_duration", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "prefUseCustomMessageNotification", + "columnName": "pref_use_custom_message_notification", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "prefMessageNotificationRingtone", + "columnName": "pref_message_notification_ringtone", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "prefMessageNotificationVibrationPattern", + "columnName": "pref_message_notification_vibration_pattern", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "prefMessageNotificationLedColor", + "columnName": "pref_message_notification_led_color", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "prefUseCustomCallNotification", + "columnName": "pref_use_custom_call_notification", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "prefCallNotificationRingtone", + "columnName": "pref_call_notification_ringtone", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "prefCallNotificationVibrationPattern", + "columnName": "pref_call_notification_vibration_pattern", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "prefCallNotificationUseFlash", + "columnName": "pref_call_notification_use_flash", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sharedSettingsVersion", + "columnName": "shared_settings_version", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "settingExistenceDuration", + "columnName": "setting_existence_duration", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "settingVisibilityDuration", + "columnName": "setting_visibility_duration", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "settingReadOnce", + "columnName": "setting_read_once", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "discussion_id" + ] + }, + "indices": [ + { + "name": "index_discussion_customization_table_discussion_id", + "unique": false, + "columnNames": [ + "discussion_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_discussion_customization_table_discussion_id` ON `${TABLE_NAME}` (`discussion_id`)" + } + ], + "foreignKeys": [ + { + "table": "discussion_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "discussion_id" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "fyle_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `permanent_file_path` TEXT, `sha256` BLOB)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "filePath", + "columnName": "permanent_file_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sha256", + "columnName": "sha256", + "affinity": "BLOB", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_fyle_table_sha256", + "unique": true, + "columnNames": [ + "sha256" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_fyle_table_sha256` ON `${TABLE_NAME}` (`sha256`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "fyle_message_join_with_status", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`fyle_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `bytes_owned_identity` BLOB NOT NULL, `file_path` TEXT NOT NULL, `file_name` TEXT NOT NULL, `text_extracted` INTEGER NOT NULL, `text_content` TEXT, `file_type` TEXT, `status` INTEGER NOT NULL, `size` INTEGER NOT NULL, `progress` REAL NOT NULL, `engine_message_identifier` BLOB, `engine_number` INTEGER, `image_resolution` TEXT, `mini_preview` BLOB, `audio_played` INTEGER NOT NULL, `reception_status` INTEGER NOT NULL, PRIMARY KEY(`fyle_id`, `message_id`), FOREIGN KEY(`fyle_id`) REFERENCES `fyle_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`message_id`) REFERENCES `message_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`bytes_owned_identity`) REFERENCES `identity_table`(`bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "fields": [ + { + "fieldPath": "fyleId", + "columnName": "fyle_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "filePath", + "columnName": "file_path", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fileName", + "columnName": "file_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "textExtracted", + "columnName": "text_extracted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "textContent", + "columnName": "text_content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "mimeType", + "columnName": "file_type", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "size", + "columnName": "size", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "progress", + "columnName": "progress", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "engineMessageIdentifier", + "columnName": "engine_message_identifier", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "engineNumber", + "columnName": "engine_number", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "imageResolution", + "columnName": "image_resolution", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "miniPreview", + "columnName": "mini_preview", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "wasOpened", + "columnName": "audio_played", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "receptionStatus", + "columnName": "reception_status", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "fyle_id", + "message_id" + ] + }, + "indices": [ + { + "name": "index_fyle_message_join_with_status_fyle_id", + "unique": false, + "columnNames": [ + "fyle_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_fyle_message_join_with_status_fyle_id` ON `${TABLE_NAME}` (`fyle_id`)" + }, + { + "name": "index_fyle_message_join_with_status_message_id", + "unique": false, + "columnNames": [ + "message_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_fyle_message_join_with_status_message_id` ON `${TABLE_NAME}` (`message_id`)" + }, + { + "name": "index_fyle_message_join_with_status_engine_message_identifier_engine_number", + "unique": false, + "columnNames": [ + "engine_message_identifier", + "engine_number" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_fyle_message_join_with_status_engine_message_identifier_engine_number` ON `${TABLE_NAME}` (`engine_message_identifier`, `engine_number`)" + }, + { + "name": "index_fyle_message_join_with_status_message_id_engine_number", + "unique": false, + "columnNames": [ + "message_id", + "engine_number" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_fyle_message_join_with_status_message_id_engine_number` ON `${TABLE_NAME}` (`message_id`, `engine_number`)" + }, + { + "name": "index_fyle_message_join_with_status_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_fyle_message_join_with_status_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_owned_identity`)" + } + ], + "foreignKeys": [ + { + "table": "fyle_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "fyle_id" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "message_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "message_id" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "identity_table", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_owned_identity" + ] + } + ] + }, + { + "ftsVersion": "FTS4", + "ftsOptions": { + "tokenizer": "unicode61", + "tokenizerArgs": [ + "remove_diacritics=2" + ], + "contentTable": "fyle_message_join_with_status", + "languageIdColumnName": "", + "matchInfo": "FTS4", + "notIndexedColumns": [], + "prefixSizes": [], + "preferredOrder": "ASC" + }, + "contentSyncTriggers": [ + "CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_fyle_message_join_with_status_fts_BEFORE_UPDATE BEFORE UPDATE ON `fyle_message_join_with_status` BEGIN DELETE FROM `fyle_message_join_with_status_fts` WHERE `docid`=OLD.`rowid`; END", + "CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_fyle_message_join_with_status_fts_BEFORE_DELETE BEFORE DELETE ON `fyle_message_join_with_status` BEGIN DELETE FROM `fyle_message_join_with_status_fts` WHERE `docid`=OLD.`rowid`; END", + "CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_fyle_message_join_with_status_fts_AFTER_UPDATE AFTER UPDATE ON `fyle_message_join_with_status` BEGIN INSERT INTO `fyle_message_join_with_status_fts`(`docid`, `file_name`, `text_content`) VALUES (NEW.`rowid`, NEW.`file_name`, NEW.`text_content`); END", + "CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_fyle_message_join_with_status_fts_AFTER_INSERT AFTER INSERT ON `fyle_message_join_with_status` BEGIN INSERT INTO `fyle_message_join_with_status_fts`(`docid`, `file_name`, `text_content`) VALUES (NEW.`rowid`, NEW.`file_name`, NEW.`text_content`); END" + ], + "tableName": "fyle_message_join_with_status_fts", + "createSql": "CREATE VIRTUAL TABLE IF NOT EXISTS `${TABLE_NAME}` USING FTS4(`file_name` TEXT NOT NULL, `text_content` TEXT NOT NULL, tokenize=unicode61 `remove_diacritics=2`, content=`fyle_message_join_with_status`)", + "fields": [ + { + "fieldPath": "fileName", + "columnName": "file_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "textContent", + "columnName": "text_content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "invitation_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`dialog_uuid` TEXT NOT NULL, `bytes_owned_identity` BLOB NOT NULL, `bytes_contact_identity` BLOB, `associated_dialog` BLOB NOT NULL, `invitation_timestamp` INTEGER NOT NULL, `category_id` INTEGER NOT NULL, `discussion_id` INTEGER, PRIMARY KEY(`dialog_uuid`), FOREIGN KEY(`bytes_owned_identity`) REFERENCES `identity_table`(`bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "dialogUuid", + "columnName": "dialog_uuid", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesContactIdentity", + "columnName": "bytes_contact_identity", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "associatedDialog", + "columnName": "associated_dialog", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "invitationTimestamp", + "columnName": "invitation_timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "categoryId", + "columnName": "category_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "discussionId", + "columnName": "discussion_id", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "dialog_uuid" + ] + }, + "indices": [ + { + "name": "index_invitation_table_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_invitation_table_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_owned_identity`)" + } + ], + "foreignKeys": [ + { + "table": "identity_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_owned_identity" + ] + } + ] + }, + { + "tableName": "message_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `sender_sequence_number` INTEGER NOT NULL, `content_body` TEXT, `json_reply` TEXT, `json_expiration` TEXT, `json_return_receipt` TEXT, `json_location` TEXT, `location_type` INTEGER NOT NULL, `sort_index` REAL NOT NULL, `timestamp` INTEGER NOT NULL, `status` INTEGER NOT NULL, `wipe_status` INTEGER NOT NULL, `message_type` INTEGER NOT NULL, `discussion_id` INTEGER NOT NULL, `engine_message_identifier` BLOB, `sender_identifier` BLOB NOT NULL, `sender_thread_identifier` TEXT NOT NULL, `total_attachment_count` INTEGER NOT NULL, `image_count` INTEGER NOT NULL, `wiped_attachment_count` INTEGER NOT NULL, `edited` INTEGER NOT NULL, `forwarded` INTEGER NOT NULL, `mentioned` INTEGER NOT NULL, `bookmarked` INTEGER NOT NULL, `reactions` TEXT, `image_resolutions` TEXT, `missed_message_count` INTEGER NOT NULL, `expiration_start_timestamp` INTEGER NOT NULL, `limited_visibility` INTEGER NOT NULL, `link_preview_fyle_id` INTEGER, `json_mentions` TEXT, FOREIGN KEY(`discussion_id`) REFERENCES `discussion_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "senderSequenceNumber", + "columnName": "sender_sequence_number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "contentBody", + "columnName": "content_body", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "jsonReply", + "columnName": "json_reply", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "jsonExpiration", + "columnName": "json_expiration", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "jsonReturnReceipt", + "columnName": "json_return_receipt", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "jsonLocation", + "columnName": "json_location", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "locationType", + "columnName": "location_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sortIndex", + "columnName": "sort_index", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "wipeStatus", + "columnName": "wipe_status", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageType", + "columnName": "message_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "discussionId", + "columnName": "discussion_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "inboundMessageEngineIdentifier", + "columnName": "engine_message_identifier", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "senderIdentifier", + "columnName": "sender_identifier", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "senderThreadIdentifier", + "columnName": "sender_thread_identifier", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "totalAttachmentCount", + "columnName": "total_attachment_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "imageCount", + "columnName": "image_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "wipedAttachmentCount", + "columnName": "wiped_attachment_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "edited", + "columnName": "edited", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "forwarded", + "columnName": "forwarded", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "mentioned", + "columnName": "mentioned", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bookmarked", + "columnName": "bookmarked", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reactions", + "columnName": "reactions", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "imageResolutions", + "columnName": "image_resolutions", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "missedMessageCount", + "columnName": "missed_message_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "expirationStartTimestamp", + "columnName": "expiration_start_timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "limitedVisibility", + "columnName": "limited_visibility", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "linkPreviewFyleId", + "columnName": "link_preview_fyle_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "jsonMentions", + "columnName": "json_mentions", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_message_table_discussion_id", + "unique": false, + "columnNames": [ + "discussion_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_table_discussion_id` ON `${TABLE_NAME}` (`discussion_id`)" + }, + { + "name": "index_message_table_engine_message_identifier", + "unique": false, + "columnNames": [ + "engine_message_identifier" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_table_engine_message_identifier` ON `${TABLE_NAME}` (`engine_message_identifier`)" + }, + { + "name": "index_message_table_sort_index", + "unique": false, + "columnNames": [ + "sort_index" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_table_sort_index` ON `${TABLE_NAME}` (`sort_index`)" + }, + { + "name": "index_message_table_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_table_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + }, + { + "name": "index_message_table_message_type_status", + "unique": false, + "columnNames": [ + "message_type", + "status" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_table_message_type_status` ON `${TABLE_NAME}` (`message_type`, `status`)" + }, + { + "name": "index_message_table_discussion_id_status", + "unique": false, + "columnNames": [ + "discussion_id", + "status" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_table_discussion_id_status` ON `${TABLE_NAME}` (`discussion_id`, `status`)" + }, + { + "name": "index_message_table_sender_sequence_number_sender_thread_identifier_sender_identifier_discussion_id", + "unique": false, + "columnNames": [ + "sender_sequence_number", + "sender_thread_identifier", + "sender_identifier", + "discussion_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_table_sender_sequence_number_sender_thread_identifier_sender_identifier_discussion_id` ON `${TABLE_NAME}` (`sender_sequence_number`, `sender_thread_identifier`, `sender_identifier`, `discussion_id`)" + } + ], + "foreignKeys": [ + { + "table": "discussion_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "discussion_id" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "ftsVersion": "FTS4", + "ftsOptions": { + "tokenizer": "unicode61", + "tokenizerArgs": [ + "remove_diacritics=2" + ], + "contentTable": "message_table", + "languageIdColumnName": "", + "matchInfo": "FTS4", + "notIndexedColumns": [], + "prefixSizes": [], + "preferredOrder": "ASC" + }, + "contentSyncTriggers": [ + "CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_message_table_fts_BEFORE_UPDATE BEFORE UPDATE ON `message_table` BEGIN DELETE FROM `message_table_fts` WHERE `docid`=OLD.`rowid`; END", + "CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_message_table_fts_BEFORE_DELETE BEFORE DELETE ON `message_table` BEGIN DELETE FROM `message_table_fts` WHERE `docid`=OLD.`rowid`; END", + "CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_message_table_fts_AFTER_UPDATE AFTER UPDATE ON `message_table` BEGIN INSERT INTO `message_table_fts`(`docid`, `content_body`) VALUES (NEW.`rowid`, NEW.`content_body`); END", + "CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_message_table_fts_AFTER_INSERT AFTER INSERT ON `message_table` BEGIN INSERT INTO `message_table_fts`(`docid`, `content_body`) VALUES (NEW.`rowid`, NEW.`content_body`); END" + ], + "tableName": "message_table_fts", + "createSql": "CREATE VIRTUAL TABLE IF NOT EXISTS `${TABLE_NAME}` USING FTS4(`content_body` TEXT NOT NULL, tokenize=unicode61 `remove_diacritics=2`, content=`message_table`)", + "fields": [ + { + "fieldPath": "body", + "columnName": "content_body", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "message_expiration_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `message_id` INTEGER NOT NULL, `expiration_timestamp` INTEGER NOT NULL, `wipe_only` INTEGER NOT NULL, FOREIGN KEY(`message_id`) REFERENCES `message_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "expirationTimestamp", + "columnName": "expiration_timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "wipeOnly", + "columnName": "wipe_only", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_message_expiration_table_message_id", + "unique": false, + "columnNames": [ + "message_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_expiration_table_message_id` ON `${TABLE_NAME}` (`message_id`)" + }, + { + "name": "index_message_expiration_table_expiration_timestamp", + "unique": false, + "columnNames": [ + "expiration_timestamp" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_expiration_table_expiration_timestamp` ON `${TABLE_NAME}` (`expiration_timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "message_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "message_id" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "message_metadata_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `message_id` INTEGER NOT NULL, `kind` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `bytes_remote_identity` BLOB, FOREIGN KEY(`message_id`) REFERENCES `message_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "kind", + "columnName": "kind", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bytesRemoteIdentity", + "columnName": "bytes_remote_identity", + "affinity": "BLOB", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_message_metadata_table_message_id", + "unique": false, + "columnNames": [ + "message_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_metadata_table_message_id` ON `${TABLE_NAME}` (`message_id`)" + }, + { + "name": "index_message_metadata_table_message_id_kind", + "unique": false, + "columnNames": [ + "message_id", + "kind" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_metadata_table_message_id_kind` ON `${TABLE_NAME}` (`message_id`, `kind`)" + }, + { + "name": "index_message_metadata_table_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_metadata_table_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "message_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "message_id" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "message_recipient_info_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_id` INTEGER NOT NULL, `bytes_contact_identity` BLOB NOT NULL, `return_receipt_nonce` BLOB, `return_receipt_key` BLOB, `engine_message_identifier` BLOB, `unsent_attachment_numbers` TEXT, `timestamp_sent` INTEGER, `timestamp_delivered` INTEGER, `timestamp_read` INTEGER, `undelivered_attachment_numbers` TEXT, `unread_attachment_numbers` TEXT, PRIMARY KEY(`message_id`, `bytes_contact_identity`), FOREIGN KEY(`message_id`) REFERENCES `message_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bytesContactIdentity", + "columnName": "bytes_contact_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "returnReceiptNonce", + "columnName": "return_receipt_nonce", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "returnReceiptKey", + "columnName": "return_receipt_key", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "engineMessageIdentifier", + "columnName": "engine_message_identifier", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "unsentAttachmentNumbers", + "columnName": "unsent_attachment_numbers", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "timestampSent", + "columnName": "timestamp_sent", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestampDelivered", + "columnName": "timestamp_delivered", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "timestampRead", + "columnName": "timestamp_read", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "undeliveredAttachmentNumbers", + "columnName": "undelivered_attachment_numbers", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "unreadAttachmentNumbers", + "columnName": "unread_attachment_numbers", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "message_id", + "bytes_contact_identity" + ] + }, + "indices": [ + { + "name": "index_message_recipient_info_table_message_id", + "unique": false, + "columnNames": [ + "message_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_recipient_info_table_message_id` ON `${TABLE_NAME}` (`message_id`)" + }, + { + "name": "index_message_recipient_info_table_bytes_contact_identity", + "unique": false, + "columnNames": [ + "bytes_contact_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_recipient_info_table_bytes_contact_identity` ON `${TABLE_NAME}` (`bytes_contact_identity`)" + }, + { + "name": "index_message_recipient_info_table_return_receipt_nonce", + "unique": false, + "columnNames": [ + "return_receipt_nonce" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_recipient_info_table_return_receipt_nonce` ON `${TABLE_NAME}` (`return_receipt_nonce`)" + }, + { + "name": "index_message_recipient_info_table_engine_message_identifier", + "unique": false, + "columnNames": [ + "engine_message_identifier" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_recipient_info_table_engine_message_identifier` ON `${TABLE_NAME}` (`engine_message_identifier`)" + }, + { + "name": "index_message_recipient_info_table_message_id_bytes_contact_identity", + "unique": false, + "columnNames": [ + "message_id", + "bytes_contact_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_recipient_info_table_message_id_bytes_contact_identity` ON `${TABLE_NAME}` (`message_id`, `bytes_contact_identity`)" + } + ], + "foreignKeys": [ + { + "table": "message_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "message_id" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "identity_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bytes_owned_identity` BLOB NOT NULL, `display_name` TEXT NOT NULL, `identity_details` TEXT, `api_key_status` INTEGER NOT NULL, `unpublished_details` INTEGER NOT NULL, `photo_url` TEXT, `api_key_permissions` INTEGER NOT NULL, `api_key_expiration_timestamp` INTEGER, `keycloak_managed` INTEGER NOT NULL, `active` INTEGER NOT NULL, `custom_display_name` TEXT, `unlock_password` BLOB, `unlock_salt` BLOB, `pref_mute_notifications` INTEGER NOT NULL, `pref_mute_notifications_except_mentioned` INTEGER NOT NULL, `pref_mute_notifications_timestamp` INTEGER, `pref_show_neutral_notification_when_hidden` INTEGER NOT NULL, `capability_webrtc_continuous_ice` INTEGER NOT NULL, `capability_groups_v2` INTEGER NOT NULL, `capability_one_to_one_contacts` INTEGER NOT NULL, PRIMARY KEY(`bytes_owned_identity`))", + "fields": [ + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "displayName", + "columnName": "display_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "identityDetails", + "columnName": "identity_details", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "apiKeyStatus", + "columnName": "api_key_status", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unpublishedDetails", + "columnName": "unpublished_details", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "photoUrl", + "columnName": "photo_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "apiKeyPermissions", + "columnName": "api_key_permissions", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "apiKeyExpirationTimestamp", + "columnName": "api_key_expiration_timestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "keycloakManaged", + "columnName": "keycloak_managed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "active", + "columnName": "active", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "customDisplayName", + "columnName": "custom_display_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "unlockPassword", + "columnName": "unlock_password", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "unlockSalt", + "columnName": "unlock_salt", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "prefMuteNotifications", + "columnName": "pref_mute_notifications", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "prefMuteNotificationsExceptMentioned", + "columnName": "pref_mute_notifications_except_mentioned", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "prefMuteNotificationsTimestamp", + "columnName": "pref_mute_notifications_timestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "prefShowNeutralNotificationWhenHidden", + "columnName": "pref_show_neutral_notification_when_hidden", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "capabilityWebrtcContinuousIce", + "columnName": "capability_webrtc_continuous_ice", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "capabilityGroupsV2", + "columnName": "capability_groups_v2", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "capabilityOneToOneContacts", + "columnName": "capability_one_to_one_contacts", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bytes_owned_identity" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "owned_device_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bytes_owned_identity` BLOB NOT NULL, `bytes_device_uid` BLOB NOT NULL, `display_name` TEXT, `current_device` INTEGER NOT NULL, `trusted` INTEGER NOT NULL, `channel_confirmed` INTEGER NOT NULL, `has_pre_key` INTEGER NOT NULL, `last_registration_timestamp` INTEGER, `expiration_timestamp` INTEGER, PRIMARY KEY(`bytes_owned_identity`, `bytes_device_uid`), FOREIGN KEY(`bytes_owned_identity`) REFERENCES `identity_table`(`bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesDeviceUid", + "columnName": "bytes_device_uid", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "displayName", + "columnName": "display_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "currentDevice", + "columnName": "current_device", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "trusted", + "columnName": "trusted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "channelConfirmed", + "columnName": "channel_confirmed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hasPreKey", + "columnName": "has_pre_key", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastRegistrationTimestamp", + "columnName": "last_registration_timestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "expirationTimestamp", + "columnName": "expiration_timestamp", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bytes_owned_identity", + "bytes_device_uid" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "identity_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_owned_identity" + ] + } + ] + }, + { + "tableName": "call_log_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `bytes_owned_identity` BLOB NOT NULL, `bytes_group_owner_and_uid` BLOB, `timestamp` INTEGER NOT NULL, `call_type` INTEGER NOT NULL, `call_status` INTEGER NOT NULL, `duration` INTEGER NOT NULL, FOREIGN KEY(`bytes_owned_identity`) REFERENCES `identity_table`(`bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesGroupOwnerAndUidOrIdentifier", + "columnName": "bytes_group_owner_and_uid", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "callType", + "columnName": "call_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "callStatus", + "columnName": "call_status", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_call_log_table_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_call_log_table_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_owned_identity`)" + }, + { + "name": "index_call_log_table_timestamp", + "unique": false, + "columnNames": [ + "timestamp" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_call_log_table_timestamp` ON `${TABLE_NAME}` (`timestamp`)" + }, + { + "name": "index_call_log_table_bytes_group_owner_and_uid_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_group_owner_and_uid", + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_call_log_table_bytes_group_owner_and_uid_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_group_owner_and_uid`, `bytes_owned_identity`)" + } + ], + "foreignKeys": [ + { + "table": "identity_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_owned_identity" + ] + } + ] + }, + { + "tableName": "call_log_item_contact_join", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`call_log_item_id` INTEGER NOT NULL, `bytes_owned_identity` BLOB NOT NULL, `bytes_contact_identity` BLOB NOT NULL, PRIMARY KEY(`call_log_item_id`, `bytes_owned_identity`, `bytes_contact_identity`), FOREIGN KEY(`call_log_item_id`) REFERENCES `call_log_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`bytes_owned_identity`, `bytes_contact_identity`) REFERENCES `contact_table`(`bytes_owned_identity`, `bytes_contact_identity`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "callLogItemId", + "columnName": "call_log_item_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesContactIdentity", + "columnName": "bytes_contact_identity", + "affinity": "BLOB", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "call_log_item_id", + "bytes_owned_identity", + "bytes_contact_identity" + ] + }, + "indices": [ + { + "name": "index_call_log_item_contact_join_call_log_item_id", + "unique": false, + "columnNames": [ + "call_log_item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_call_log_item_contact_join_call_log_item_id` ON `${TABLE_NAME}` (`call_log_item_id`)" + }, + { + "name": "index_call_log_item_contact_join_bytes_owned_identity_bytes_contact_identity", + "unique": false, + "columnNames": [ + "bytes_owned_identity", + "bytes_contact_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_call_log_item_contact_join_bytes_owned_identity_bytes_contact_identity` ON `${TABLE_NAME}` (`bytes_owned_identity`, `bytes_contact_identity`)" + } + ], + "foreignKeys": [ + { + "table": "call_log_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "call_log_item_id" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "contact_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity", + "bytes_contact_identity" + ], + "referencedColumns": [ + "bytes_owned_identity", + "bytes_contact_identity" + ] + } + ] + }, + { + "tableName": "reactions_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_id` INTEGER NOT NULL, `bytes_identity` BLOB, `emoji` TEXT, `timestamp` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, FOREIGN KEY(`message_id`) REFERENCES `message_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bytesIdentity", + "columnName": "bytes_identity", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "emoji", + "columnName": "emoji", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_reactions_table_message_id", + "unique": false, + "columnNames": [ + "message_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_reactions_table_message_id` ON `${TABLE_NAME}` (`message_id`)" + }, + { + "name": "index_reactions_table_message_id_bytes_identity", + "unique": true, + "columnNames": [ + "message_id", + "bytes_identity" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_reactions_table_message_id_bytes_identity` ON `${TABLE_NAME}` (`message_id`, `bytes_identity`)" + } + ], + "foreignKeys": [ + { + "table": "message_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "message_id" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "remote_delete_and_edit_request_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`discussion_id` INTEGER NOT NULL, `sender_identifier` BLOB NOT NULL, `sender_thread_identifier` TEXT NOT NULL, `sender_sequence_number` INTEGER NOT NULL, `server_timestamp` INTEGER NOT NULL, `request_type` INTEGER NOT NULL, `body` TEXT, `mentions` TEXT, `remote_deleter` BLOB, PRIMARY KEY(`discussion_id`, `sender_identifier`, `sender_thread_identifier`, `sender_sequence_number`), FOREIGN KEY(`discussion_id`) REFERENCES `discussion_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "discussionId", + "columnName": "discussion_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "senderIdentifier", + "columnName": "sender_identifier", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "senderThreadIdentifier", + "columnName": "sender_thread_identifier", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderSequenceNumber", + "columnName": "sender_sequence_number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "serverTimestamp", + "columnName": "server_timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "requestType", + "columnName": "request_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "body", + "columnName": "body", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "mentions", + "columnName": "mentions", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "remoteDeleter", + "columnName": "remote_deleter", + "affinity": "BLOB", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "discussion_id", + "sender_identifier", + "sender_thread_identifier", + "sender_sequence_number" + ] + }, + "indices": [ + { + "name": "index_remote_delete_and_edit_request_table_discussion_id", + "unique": false, + "columnNames": [ + "discussion_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_remote_delete_and_edit_request_table_discussion_id` ON `${TABLE_NAME}` (`discussion_id`)" + }, + { + "name": "index_remote_delete_and_edit_request_table_server_timestamp", + "unique": false, + "columnNames": [ + "server_timestamp" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_remote_delete_and_edit_request_table_server_timestamp` ON `${TABLE_NAME}` (`server_timestamp`)" + } + ], + "foreignKeys": [ + { + "table": "discussion_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "discussion_id" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "known_certificate", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `domain_name` TEXT NOT NULL, `certificate_bytes` BLOB NOT NULL, `trust_timestamp` INTEGER, `expiration_timestamp` INTEGER NOT NULL, `issuers` TEXT NOT NULL, `encoded_full_chain` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "domainName", + "columnName": "domain_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "certificateBytes", + "columnName": "certificate_bytes", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "trustTimestamp", + "columnName": "trust_timestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "expirationTimestamp", + "columnName": "expiration_timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "issuers", + "columnName": "issuers", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "encodedFullChain", + "columnName": "encoded_full_chain", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_known_certificate_domain_name", + "unique": false, + "columnNames": [ + "domain_name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_known_certificate_domain_name` ON `${TABLE_NAME}` (`domain_name`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "latest_discussion_sender_sequence_number_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`discussion_id` INTEGER NOT NULL, `sender_identifier` BLOB NOT NULL, `sender_thread_identifier` TEXT NOT NULL, `latest_sequence_number` INTEGER NOT NULL, PRIMARY KEY(`discussion_id`, `sender_identifier`, `sender_thread_identifier`), FOREIGN KEY(`discussion_id`) REFERENCES `discussion_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "discussionId", + "columnName": "discussion_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "senderIdentifier", + "columnName": "sender_identifier", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "senderThreadIdentifier", + "columnName": "sender_thread_identifier", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "latestSequenceNumber", + "columnName": "latest_sequence_number", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "discussion_id", + "sender_identifier", + "sender_thread_identifier" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "discussion_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "discussion_id" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "reaction_request_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`discussion_id` INTEGER NOT NULL, `sender_identifier` BLOB NOT NULL, `sender_thread_identifier` TEXT NOT NULL, `sender_sequence_number` INTEGER NOT NULL, `reacter` BLOB NOT NULL, `server_timestamp` INTEGER NOT NULL, `reaction` TEXT, PRIMARY KEY(`discussion_id`, `sender_identifier`, `sender_thread_identifier`, `sender_sequence_number`, `reacter`), FOREIGN KEY(`discussion_id`) REFERENCES `discussion_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "discussionId", + "columnName": "discussion_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "senderIdentifier", + "columnName": "sender_identifier", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "senderThreadIdentifier", + "columnName": "sender_thread_identifier", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderSequenceNumber", + "columnName": "sender_sequence_number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reacter", + "columnName": "reacter", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "serverTimestamp", + "columnName": "server_timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reaction", + "columnName": "reaction", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "discussion_id", + "sender_identifier", + "sender_thread_identifier", + "sender_sequence_number", + "reacter" + ] + }, + "indices": [ + { + "name": "index_reaction_request_table_discussion_id", + "unique": false, + "columnNames": [ + "discussion_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_reaction_request_table_discussion_id` ON `${TABLE_NAME}` (`discussion_id`)" + }, + { + "name": "index_reaction_request_table_server_timestamp", + "unique": false, + "columnNames": [ + "server_timestamp" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_reaction_request_table_server_timestamp` ON `${TABLE_NAME}` (`server_timestamp`)" + }, + { + "name": "index_reaction_request_table_discussion_id_sender_identifier_sender_thread_identifier_sender_sequence_number", + "unique": false, + "columnNames": [ + "discussion_id", + "sender_identifier", + "sender_thread_identifier", + "sender_sequence_number" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_reaction_request_table_discussion_id_sender_identifier_sender_thread_identifier_sender_sequence_number` ON `${TABLE_NAME}` (`discussion_id`, `sender_identifier`, `sender_thread_identifier`, `sender_sequence_number`)" + } + ], + "foreignKeys": [ + { + "table": "discussion_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "discussion_id" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "action_shortcut_configuration_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`app_widget_id` INTEGER NOT NULL, `discussion_id` INTEGER NOT NULL, `serialized_configuration` TEXT NOT NULL, PRIMARY KEY(`app_widget_id`), FOREIGN KEY(`discussion_id`) REFERENCES `discussion_table`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "appWidgetId", + "columnName": "app_widget_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "discussionId", + "columnName": "discussion_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "serializedConfiguration", + "columnName": "serialized_configuration", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "app_widget_id" + ] + }, + "indices": [ + { + "name": "index_action_shortcut_configuration_table_discussion_id", + "unique": false, + "columnNames": [ + "discussion_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_action_shortcut_configuration_table_discussion_id` ON `${TABLE_NAME}` (`discussion_id`)" + } + ], + "foreignKeys": [ + { + "table": "discussion_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "discussion_id" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "group2_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bytes_owned_identity` BLOB NOT NULL, `bytes_group_identifier` BLOB NOT NULL, `keycloak_managed` INTEGER NOT NULL, `name` TEXT, `photo_url` TEXT, `group_members_names` TEXT NOT NULL, `update_in_progress` INTEGER NOT NULL, `new_published_details` INTEGER NOT NULL, `own_permission_admin` INTEGER NOT NULL, `own_permission_remote_delete_anything` INTEGER NOT NULL, `own_permission_edit_or_remote_delete_own_messages` INTEGER NOT NULL, `own_permission_change_settings` INTEGER NOT NULL, `own_permission_send_message` INTEGER NOT NULL, `custom_name` TEXT, `custom_photo_url` TEXT, `personal_note` TEXT, `full_search_field` TEXT NOT NULL, PRIMARY KEY(`bytes_owned_identity`, `bytes_group_identifier`), FOREIGN KEY(`bytes_owned_identity`) REFERENCES `identity_table`(`bytes_owned_identity`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesGroupIdentifier", + "columnName": "bytes_group_identifier", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "keycloakManaged", + "columnName": "keycloak_managed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "photoUrl", + "columnName": "photo_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "groupMembersNames", + "columnName": "group_members_names", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "updateInProgress", + "columnName": "update_in_progress", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "newPublishedDetails", + "columnName": "new_published_details", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ownPermissionAdmin", + "columnName": "own_permission_admin", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ownPermissionRemoteDeleteAnything", + "columnName": "own_permission_remote_delete_anything", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ownPermissionEditOrRemoteDeleteOwnMessages", + "columnName": "own_permission_edit_or_remote_delete_own_messages", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ownPermissionChangeSettings", + "columnName": "own_permission_change_settings", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ownPermissionSendMessage", + "columnName": "own_permission_send_message", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "customName", + "columnName": "custom_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customPhotoUrl", + "columnName": "custom_photo_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "personalNote", + "columnName": "personal_note", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "fullSearchField", + "columnName": "full_search_field", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bytes_owned_identity", + "bytes_group_identifier" + ] + }, + "indices": [ + { + "name": "index_group2_table_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_group2_table_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_owned_identity`)" + } + ], + "foreignKeys": [ + { + "table": "identity_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity" + ], + "referencedColumns": [ + "bytes_owned_identity" + ] + } + ] + }, + { + "tableName": "group2_pending_member_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bytes_owned_identity` BLOB NOT NULL, `bytes_group_identifier` BLOB NOT NULL, `bytes_contact_identity` BLOB NOT NULL, `display_name` TEXT NOT NULL, `first_name` TEXT, `sort_display_name` BLOB NOT NULL, `full_search_display_name` TEXT NOT NULL, `identity_details` TEXT, `permission_admin` INTEGER NOT NULL, `permission_remote_delete_anything` INTEGER NOT NULL, `permission_edit_or_remote_delete_own_messages` INTEGER NOT NULL, `permission_change_settings` INTEGER NOT NULL, `permission_send_message` INTEGER NOT NULL, PRIMARY KEY(`bytes_owned_identity`, `bytes_group_identifier`, `bytes_contact_identity`), FOREIGN KEY(`bytes_owned_identity`, `bytes_group_identifier`) REFERENCES `group2_table`(`bytes_owned_identity`, `bytes_group_identifier`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesGroupIdentifier", + "columnName": "bytes_group_identifier", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesContactIdentity", + "columnName": "bytes_contact_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "displayName", + "columnName": "display_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "firstName", + "columnName": "first_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sortDisplayName", + "columnName": "sort_display_name", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "fullSearchDisplayName", + "columnName": "full_search_display_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "identityDetails", + "columnName": "identity_details", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "permissionAdmin", + "columnName": "permission_admin", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "permissionRemoteDeleteAnything", + "columnName": "permission_remote_delete_anything", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "permissionEditOrRemoteDeleteOwnMessages", + "columnName": "permission_edit_or_remote_delete_own_messages", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "permissionChangeSettings", + "columnName": "permission_change_settings", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "permissionSendMessage", + "columnName": "permission_send_message", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bytes_owned_identity", + "bytes_group_identifier", + "bytes_contact_identity" + ] + }, + "indices": [ + { + "name": "index_group2_pending_member_table_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_group2_pending_member_table_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_owned_identity`)" + }, + { + "name": "index_group2_pending_member_table_bytes_owned_identity_bytes_group_identifier", + "unique": false, + "columnNames": [ + "bytes_owned_identity", + "bytes_group_identifier" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_group2_pending_member_table_bytes_owned_identity_bytes_group_identifier` ON `${TABLE_NAME}` (`bytes_owned_identity`, `bytes_group_identifier`)" + } + ], + "foreignKeys": [ + { + "table": "group2_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity", + "bytes_group_identifier" + ], + "referencedColumns": [ + "bytes_owned_identity", + "bytes_group_identifier" + ] + } + ] + }, + { + "tableName": "group2_member_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bytes_owned_identity` BLOB NOT NULL, `bytes_group_identifier` BLOB NOT NULL, `bytes_contact_identity` BLOB NOT NULL, `permission_admin` INTEGER NOT NULL, `permission_remote_delete_anything` INTEGER NOT NULL, `permission_edit_or_remote_delete_own_messages` INTEGER NOT NULL, `permission_change_settings` INTEGER NOT NULL, `permission_send_message` INTEGER NOT NULL, PRIMARY KEY(`bytes_owned_identity`, `bytes_group_identifier`, `bytes_contact_identity`), FOREIGN KEY(`bytes_owned_identity`, `bytes_group_identifier`) REFERENCES `group2_table`(`bytes_owned_identity`, `bytes_group_identifier`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`bytes_owned_identity`, `bytes_contact_identity`) REFERENCES `contact_table`(`bytes_owned_identity`, `bytes_contact_identity`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "bytesOwnedIdentity", + "columnName": "bytes_owned_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesGroupIdentifier", + "columnName": "bytes_group_identifier", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "bytesContactIdentity", + "columnName": "bytes_contact_identity", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "permissionAdmin", + "columnName": "permission_admin", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "permissionRemoteDeleteAnything", + "columnName": "permission_remote_delete_anything", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "permissionEditOrRemoteDeleteOwnMessages", + "columnName": "permission_edit_or_remote_delete_own_messages", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "permissionChangeSettings", + "columnName": "permission_change_settings", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "permissionSendMessage", + "columnName": "permission_send_message", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bytes_owned_identity", + "bytes_group_identifier", + "bytes_contact_identity" + ] + }, + "indices": [ + { + "name": "index_group2_member_table_bytes_owned_identity", + "unique": false, + "columnNames": [ + "bytes_owned_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_group2_member_table_bytes_owned_identity` ON `${TABLE_NAME}` (`bytes_owned_identity`)" + }, + { + "name": "index_group2_member_table_bytes_owned_identity_bytes_group_identifier", + "unique": false, + "columnNames": [ + "bytes_owned_identity", + "bytes_group_identifier" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_group2_member_table_bytes_owned_identity_bytes_group_identifier` ON `${TABLE_NAME}` (`bytes_owned_identity`, `bytes_group_identifier`)" + }, + { + "name": "index_group2_member_table_bytes_owned_identity_bytes_contact_identity", + "unique": false, + "columnNames": [ + "bytes_owned_identity", + "bytes_contact_identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_group2_member_table_bytes_owned_identity_bytes_contact_identity` ON `${TABLE_NAME}` (`bytes_owned_identity`, `bytes_contact_identity`)" + } + ], + "foreignKeys": [ + { + "table": "group2_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity", + "bytes_group_identifier" + ], + "referencedColumns": [ + "bytes_owned_identity", + "bytes_group_identifier" + ] + }, + { + "table": "contact_table", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bytes_owned_identity", + "bytes_contact_identity" + ], + "referencedColumns": [ + "bytes_owned_identity", + "bytes_contact_identity" + ] + } + ] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c1f527941e55c83610515d219f97715c')" + ] + } +} \ No newline at end of file diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/AppSingleton.java b/obv_messenger/app/src/main/java/io/olvid/messenger/AppSingleton.java index 66b44266..91bbb5ec 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/AppSingleton.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/AppSingleton.java @@ -81,6 +81,7 @@ import io.olvid.messenger.databases.entity.jsons.JsonExpiration; import io.olvid.messenger.databases.tasks.ContactDisplayNameFormatChangedTask; import io.olvid.messenger.databases.tasks.OwnedDevicesSynchronisationWithEngineTask; +import io.olvid.messenger.databases.tasks.UpdateAllGroupMembersNames; import io.olvid.messenger.databases.tasks.backup.RestoreAppDataFromBackupTask; import io.olvid.messenger.databases.tasks.migration.SetContactsAndPendingMembersFirstNamesTask; import io.olvid.messenger.discussion.compose.ComposeMessageFragment; @@ -234,23 +235,28 @@ private AppSingleton() { this.engine = new Engine(App.getContext().getNoBackupFilesDir(), new AppBackupAndSyncDelegate(), DatabaseKey.get(DatabaseKey.ENGINE_DATABASE_SECRET), this.sslSocketFactory, new Logger.LogOutputter() { @Override - public void d(String s, String s1) { - Log.d(s, s1); + public void d(String tag, String message) { + Log.d(tag, message); } @Override - public void i(String s, String s1) { - Log.i(s, s1); + public void i(String tag, String message) { + Log.i(tag, message); } @Override - public void w(String s, String s1) { - Log.w(s, s1); + public void w(String tag, String message) { + Log.w(tag, message); } @Override - public void e(String s, String s1) { - Log.e(s, s1); + public void e(String tag, String message) { + Log.e(tag, message); + } + + @Override + public void x(String tag, Throwable throwable) { + Log.w(tag, "", throwable); } }, SettingsActivity.useDebugLogLevel() ? Logger.DEBUG : BuildConfig.LOG_LEVEL); @@ -1208,6 +1214,12 @@ private void runBuildUpgrade(int lastBuildExecuted, int ignoredLastAndroidSdkVer if (lastBuildExecuted != 0 && lastBuildExecuted < 220) { App.openAppDialogIntroducingMultiDeviceAndDesktop(); } + if (lastBuildExecuted != 0 && lastBuildExecuted < 255) { + App.runThread(() -> { + new ContactDisplayNameFormatChangedTask().run(); + new UpdateAllGroupMembersNames().run(); + }); + } PeriodicTasksScheduler.resetAllPeriodicTasksFollowingAnUpdate(App.getContext()); saveLastExecutedVersions(BuildConfig.VERSION_CODE, Build.VERSION.SDK_INT); diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/EngineNotificationProcessorForGroups.java b/obv_messenger/app/src/main/java/io/olvid/messenger/EngineNotificationProcessorForGroups.java index e4648638..4c432e32 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/EngineNotificationProcessorForGroups.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/EngineNotificationProcessorForGroups.java @@ -19,6 +19,7 @@ package io.olvid.messenger; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -111,11 +112,14 @@ public void callback(String notificationName, final HashMap user } } + List fullSearchItems = new ArrayList<>(); + // add members boolean messageInserted = false; for (byte[] bytesGroupMemberIdentity : obvGroup.getBytesGroupMembersIdentities()) { Contact contact = db.contactDao().get(bytesOwnedIdentity, bytesGroupMemberIdentity); if (contact != null) { + fullSearchItems.add(contact.fullSearchDisplayName); ContactGroupJoin contactGroupJoin = new ContactGroupJoin(bytesGroupUid, contact.bytesOwnedIdentity, contact.bytesContactIdentity); db.contactGroupJoinDao().insert(contactGroupJoin); Message groupJoinedMessage = Message.createMemberJoinedGroupMessage(db, discussion.id, contact.bytesContactIdentity); @@ -144,7 +148,7 @@ public void callback(String notificationName, final HashMap user db.groupDao().getGroupMembersFirstNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid) : db.groupDao().getGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid)); - db.groupDao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.groupMembersNames); + db.groupDao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.groupMembersNames, group.computeFullSearch(fullSearchItems)); // if createdByMeOnOtherDevice, query my devices for the sharedSettings if (obvGroup.getBytesGroupOwnerIdentity() == null && createdOnOtherDevice && db.ownedDeviceDao().doesOwnedIdentityHaveAnotherDeviceWithChannel(bytesOwnedIdentity)) { @@ -205,7 +209,7 @@ public void callback(String notificationName, final HashMap user : db.groupDao().getGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid) ); - db.groupDao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.groupMembersNames); + db.groupDao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.groupMembersNames, group.fullSearchField + " " + contact.fullSearchDisplayName); Message groupJoinedMessage = Message.createMemberJoinedGroupMessage(db, discussion.id, contact.bytesContactIdentity); db.messageDao().insert(groupJoinedMessage); @@ -284,7 +288,15 @@ public void callback(String notificationName, final HashMap user : db.groupDao().getGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid) ); - db.groupDao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.groupMembersNames); + + List fullSearchItems = new ArrayList<>(); + for (Contact groupContact : db.contactGroupJoinDao().getGroupContactsSync(bytesOwnedIdentity, bytesGroupUid)) { + if (groupContact != null) { + fullSearchItems.add(groupContact.fullSearchDisplayName); + } + } + + db.groupDao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.groupMembersNames, group.computeFullSearch(fullSearchItems)); Message groupLeftMessage = Message.createMemberLeftGroupMessage(db, discussion.id, contact.bytesContactIdentity); db.messageDao().insert(groupLeftMessage); diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabase.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabase.java index 6e0b5c00..5bc32fec 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabase.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabase.java @@ -43,6 +43,7 @@ import io.olvid.messenger.databases.dao.DiscussionDao; import io.olvid.messenger.databases.dao.FyleDao; import io.olvid.messenger.databases.dao.FyleMessageJoinWithStatusDao; +import io.olvid.messenger.databases.dao.GlobalSearchDao; import io.olvid.messenger.databases.dao.Group2Dao; import io.olvid.messenger.databases.dao.Group2MemberDao; import io.olvid.messenger.databases.dao.Group2PendingMemberDao; @@ -125,7 +126,7 @@ ) @TypeConverters({ObvTypeConverters.class}) public abstract class AppDatabase extends RoomDatabase { - public static final int DB_SCHEMA_VERSION = 69; + public static final int DB_SCHEMA_VERSION = 70; public static final int DB_FTS_GLOBAL_SEARCH_VERSION = 1; public static final String DB_FILE_NAME = "app_database"; public static final String TMP_ENCRYPTED_DB_FILE_NAME = "encrypted_app_database"; @@ -182,6 +183,8 @@ public abstract class AppDatabase extends RoomDatabase { public abstract Group2PendingMemberDao group2PendingMemberDao(); + public abstract GlobalSearchDao globalSearchDao(); + private static final RoomDatabase.Callback roomDatabaseOpenCallback = new RoomDatabase.Callback() { @Override public void onOpen(@NonNull SupportSQLiteDatabase db) { diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabaseMigrations.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabaseMigrations.java index bbc4a7a8..020724fa 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabaseMigrations.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabaseMigrations.java @@ -41,6 +41,16 @@ class AppDatabaseMigrations { static final Migration[] MIGRATIONS = new Migration[]{ + new Migration(69, 70) { + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + Logger.w("ROOM MIGRATING FROM VERSION 69 TO 70"); + + database.execSQL("ALTER TABLE `group_table` ADD COLUMN `full_search_field` TEXT NOT NULL DEFAULT ''"); + database.execSQL("ALTER TABLE `group2_table` ADD COLUMN `full_search_field` TEXT NOT NULL DEFAULT ''"); + } + }, + new Migration(68, 69) { @Override public void migrate(@NonNull SupportSQLiteDatabase database) { diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabaseOpenCallback.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabaseOpenCallback.java index 04b21c08..6e53f74c 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabaseOpenCallback.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/AppDatabaseOpenCallback.java @@ -21,6 +21,7 @@ import java.io.File; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -580,7 +581,15 @@ private void syncEngineDatabases() { : db.groupDao().getGroupMembersNames(newGroup.bytesOwnedIdentity, newGroup.bytesGroupOwnerAndUid) ); - db.groupDao().updateGroupMembersNames(newGroup.bytesOwnedIdentity, newGroup.bytesGroupOwnerAndUid, newGroup.groupMembersNames); + + List fullSearchItems = new ArrayList<>(); + for (Contact groupContact : db.contactGroupJoinDao().getGroupContactsSync(newGroup.bytesOwnedIdentity, newGroup.bytesGroupOwnerAndUid)) { + if (groupContact != null) { + fullSearchItems.add(groupContact.fullSearchDisplayName); + } + } + + db.groupDao().updateGroupMembersNames(newGroup.bytesOwnedIdentity, newGroup.bytesGroupOwnerAndUid, newGroup.groupMembersNames, newGroup.computeFullSearch(fullSearchItems)); HashSet declinedSet = new HashSet<>(); for (byte[] bytesDeclinedPendingMember : obvGroup.getBytesDeclinedPendingMembers()) { @@ -646,7 +655,15 @@ private void syncEngineDatabases() { : db.groupDao().getGroupMembersNames(finalGroup.bytesOwnedIdentity, finalGroup.bytesGroupOwnerAndUid) ); - db.groupDao().updateGroupMembersNames(finalGroup.bytesOwnedIdentity, finalGroup.bytesGroupOwnerAndUid, finalGroup.groupMembersNames); + + List fullSearchItems = new ArrayList<>(); + for (Contact groupContact : db.contactGroupJoinDao().getGroupContactsSync(finalGroup.bytesOwnedIdentity, finalGroup.bytesGroupOwnerAndUid)) { + if (groupContact != null) { + fullSearchItems.add(groupContact.fullSearchDisplayName); + } + } + + db.groupDao().updateGroupMembersNames(finalGroup.bytesOwnedIdentity, finalGroup.bytesGroupOwnerAndUid, finalGroup.groupMembersNames, finalGroup.computeFullSearch(fullSearchItems)); if (finalGroup.bytesGroupOwnerIdentity == null && !contactToAdd.isEmpty()) { // owned group --> check the customization DiscussionCustomization discussionCustomization = db.discussionCustomizationDao().get(discussion.id); diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/ContactDao.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/ContactDao.java index 6f15d04a..8088d5a5 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/ContactDao.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/ContactDao.java @@ -105,10 +105,11 @@ public interface ContactDao { void updateCustomNameHue(byte[] bytesOwnedIdentity, byte[] bytesContactIdentity, Integer customNameHue); @Query("UPDATE " + Contact.TABLE_NAME + - " SET " + Contact.PERSONAL_NOTE + " = :personalNote " + + " SET " + Contact.PERSONAL_NOTE + " = :personalNote, " + + Contact.FULL_SEARCH_DISPLAY_NAME + " = :fullSearchDisplayName " + " WHERE " + Contact.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + " AND " + Contact.BYTES_CONTACT_IDENTITY + " = :bytesContactIdentity") - void updatePersonalNote(byte[] bytesOwnedIdentity, byte[] bytesContactIdentity, String personalNote); + void updatePersonalNote(byte[] bytesOwnedIdentity, byte[] bytesContactIdentity, String personalNote, String fullSearchDisplayName); @Query("UPDATE " + Contact.TABLE_NAME + " SET " + Contact.CUSTOM_PHOTO_URL + " = :customPhotoUrl " + diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/DiscussionDao.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/DiscussionDao.java index b21c10bf..c133faf8 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/DiscussionDao.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/DiscussionDao.java @@ -314,7 +314,8 @@ public abstract class DiscussionDao { public abstract LiveData> getLatestDiscussionsInWhichYouWrote(); @Query("SELECT " + PREFIX_DISCUSSION_COLUMNS + ", " + - " COALESCE(grp." + Group.GROUP_MEMBERS_NAMES + ", grpp." + Group2.GROUP_MEMBERS_NAMES + ") AS groupMemberNames " + + " COALESCE(grp." + Group.GROUP_MEMBERS_NAMES + ", grpp." + Group2.GROUP_MEMBERS_NAMES + ") AS groupMemberNames, " + + " COALESCE(grp." + Group.FULL_SEARCH_FIELD + ", grpp." + Group2.FULL_SEARCH_FIELD + ") AS patterMatchingField " + " FROM " + Discussion.TABLE_NAME + " AS disc " + " LEFT JOIN " + Group.TABLE_NAME + " AS grp " + " ON disc." + Discussion.BYTES_DISCUSSION_IDENTIFIER + " = grp." + Group.BYTES_GROUP_OWNER_AND_UID + @@ -358,6 +359,7 @@ public abstract class DiscussionDao { @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) // the columns is_group and status are used for sorting only @Query("SELECT " + PREFIX_DISCUSSION_COLUMNS + ", " + " COALESCE(grp." + Group.GROUP_MEMBERS_NAMES + ", grpp." + Group2.GROUP_MEMBERS_NAMES + ") AS groupMemberNames, " + + " COALESCE(grp." + Group.FULL_SEARCH_FIELD + ", grpp." + Group2.FULL_SEARCH_FIELD + ") AS patterMatchingField, " + " CASE WHEN disc." + Discussion.DISCUSSION_TYPE + " != " + Discussion.TYPE_CONTACT + " THEN 1 ELSE 0 END AS is_group, " + " CASE disc." + Discussion.STATUS + " WHEN " + Discussion.STATUS_NORMAL + " THEN 0 " + @@ -381,6 +383,7 @@ public abstract class DiscussionDao { @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) // the column status is used for sorting only @Query("SELECT " + PREFIX_DISCUSSION_COLUMNS + ", " + " COALESCE(grp." + Group.GROUP_MEMBERS_NAMES + ", grpp." + Group2.GROUP_MEMBERS_NAMES + ") AS groupMemberNames, " + + " COALESCE(grp." + Group.FULL_SEARCH_FIELD + ", grpp." + Group2.FULL_SEARCH_FIELD + ") AS patterMatchingField, " + " CASE disc." + Discussion.STATUS + " WHEN " + Discussion.STATUS_NORMAL + " THEN 0 " + " WHEN " + Discussion.STATUS_READ_ONLY + " THEN 0 " + @@ -402,6 +405,7 @@ public abstract class DiscussionDao { @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) // the columns is_group and status are used for sorting only @Query("SELECT " + PREFIX_DISCUSSION_COLUMNS + ", " + " COALESCE(grp." + Group.GROUP_MEMBERS_NAMES + ", grpp." + Group2.GROUP_MEMBERS_NAMES + ") AS groupMemberNames, " + + " COALESCE(grp." + Group.FULL_SEARCH_FIELD + ", grpp." + Group2.FULL_SEARCH_FIELD + ") AS patterMatchingField, " + " CASE WHEN disc." + Discussion.DISCUSSION_TYPE + " != " + Discussion.TYPE_CONTACT + " THEN 1 ELSE 0 END AS is_group, " + " CASE disc." + Discussion.STATUS + " WHEN " + Discussion.STATUS_NORMAL + " THEN 0 " + @@ -425,6 +429,7 @@ public abstract class DiscussionDao { @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) // the column is_group is used for sorting only @Query("SELECT " + PREFIX_DISCUSSION_COLUMNS + ", " + " COALESCE(grp." + Group.GROUP_MEMBERS_NAMES + ", grpp." + Group2.GROUP_MEMBERS_NAMES + ") AS groupMemberNames, " + + " COALESCE(grp." + Group.FULL_SEARCH_FIELD + ", grpp." + Group2.FULL_SEARCH_FIELD + ") AS patterMatchingField, " + " CASE WHEN disc." + Discussion.DISCUSSION_TYPE + " != " + Discussion.TYPE_CONTACT + " THEN 1 ELSE 0 END AS is_group " + " FROM " + Discussion.TABLE_NAME + " AS disc " + " LEFT JOIN " + Group.TABLE_NAME + " AS grp " + @@ -441,7 +446,8 @@ public abstract class DiscussionDao { public abstract LiveData> getAllWritableWithGroupMembersNames(byte[] ownedIdentityBytes); @Query("SELECT " + PREFIX_DISCUSSION_COLUMNS + ", " + - " COALESCE(grp." + Group.GROUP_MEMBERS_NAMES + ", grpp." + Group2.GROUP_MEMBERS_NAMES + ") AS groupMemberNames " + + " COALESCE(grp." + Group.GROUP_MEMBERS_NAMES + ", grpp." + Group2.GROUP_MEMBERS_NAMES + ") AS groupMemberNames, " + + " COALESCE(grp." + Group.FULL_SEARCH_FIELD + ", grpp." + Group2.FULL_SEARCH_FIELD + ") AS patterMatchingField " + " FROM " + Discussion.TABLE_NAME + " AS disc " + " LEFT JOIN " + Group.TABLE_NAME + " AS grp " + " ON disc." + Discussion.BYTES_DISCUSSION_IDENTIFIER + " = grp." + Group.BYTES_GROUP_OWNER_AND_UID + @@ -457,7 +463,8 @@ public abstract class DiscussionDao { public abstract LiveData> getAllWritableWithGroupMembersNamesOrderedByActivity(byte[] ownedIdentityBytes); @Query("SELECT " + PREFIX_DISCUSSION_COLUMNS + ", " + - " COALESCE(grp." + Group.GROUP_MEMBERS_NAMES + ", grpp." + Group2.GROUP_MEMBERS_NAMES + ") AS groupMemberNames " + + " COALESCE(grp." + Group.GROUP_MEMBERS_NAMES + ", grpp." + Group2.GROUP_MEMBERS_NAMES + ") AS groupMemberNames, " + + " COALESCE(grp." + Group.FULL_SEARCH_FIELD + ", grpp." + Group2.FULL_SEARCH_FIELD + ") AS patterMatchingField " + " FROM " + Discussion.TABLE_NAME + " AS disc " + " INNER JOIN ( SELECT " + ContactGroupJoin.BYTES_GROUP_OWNER_AND_UID + " AS gid, " + Discussion.TYPE_GROUP + " AS dt FROM " + ContactGroupJoin.TABLE_NAME + " WHERE " + ContactGroupJoin.BYTES_CONTACT_IDENTITY + " = :bytesContactIdentity " + @@ -555,6 +562,9 @@ public static class DiscussionAndGroupMembersNames { @Nullable public String groupMemberNames; + + @Nullable + public String patterMatchingField; } public static class DiscussionAndGroupMembersCount { diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/FyleMessageJoinWithStatusDao.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/FyleMessageJoinWithStatusDao.java index 94b520bd..77e1ba69 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/FyleMessageJoinWithStatusDao.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/FyleMessageJoinWithStatusDao.java @@ -376,36 +376,6 @@ public interface FyleMessageJoinWithStatusDao { " AND FMjoin." + FyleMessageJoinWithStatus.MIME_TYPE + " NOT LIKE 'video/%' " + " AND FMjoin." + FyleMessageJoinWithStatus.MIME_TYPE + " NOT LIKE 'image/%' "; - @Query("SELECT " + DiscussionDao.PREFIX_DISCUSSION_COLUMNS + ", " + MessageDao.PREFIX_MESSAGE_COLUMNS + ", fyle.*, FMjoin.* " + - " FROM " + FyleMessageJoinWithStatus.TABLE_NAME + " AS FMjoin " + - " INNER JOIN " + Fyle.TABLE_NAME + " AS fyle " + - " ON fyle.id = FMjoin." + FyleMessageJoinWithStatus.FYLE_ID + - " INNER JOIN " + Message.TABLE_NAME + " AS mess " + - " ON mess.id = FMjoin." + FyleMessageJoinWithStatus.MESSAGE_ID + - " AND mess." + Message.MESSAGE_TYPE + " != " + Message.TYPE_INBOUND_EPHEMERAL_MESSAGE + - " INNER JOIN " + Discussion.TABLE_NAME + " AS disc " + - " ON disc.id = mess." + Message.DISCUSSION_ID + - " AND disc." + Discussion.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + - " JOIN " + FyleMessageJoinWithStatus.FTS_TABLE_NAME + " ON FMJoin.rowid = " + FyleMessageJoinWithStatus.FTS_TABLE_NAME + ".rowid " + - " WHERE " + FyleMessageJoinWithStatus.FTS_TABLE_NAME + " MATCH :filter ORDER BY mess.timestamp DESC LIMIT :limit" - ) - List globalSearch(byte[] bytesOwnedIdentity, String filter, int limit); - - @Query("SELECT COUNT(*) " + - " FROM (SELECT " + FyleMessageJoinWithStatus.FYLE_ID + " FROM " + FyleMessageJoinWithStatus.TABLE_NAME + " AS FMjoin " + - " INNER JOIN " + Fyle.TABLE_NAME + " AS fyle " + - " ON fyle.id = FMjoin." + FyleMessageJoinWithStatus.FYLE_ID + - " INNER JOIN " + Message.TABLE_NAME + " AS mess " + - " ON mess.id = FMjoin." + FyleMessageJoinWithStatus.MESSAGE_ID + - " AND mess." + Message.MESSAGE_TYPE + " != " + Message.TYPE_INBOUND_EPHEMERAL_MESSAGE + - " INNER JOIN " + Discussion.TABLE_NAME + " AS disc " + - " ON disc.id = mess." + Message.DISCUSSION_ID + - " AND disc." + Discussion.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + - " JOIN " + FyleMessageJoinWithStatus.FTS_TABLE_NAME + " ON FMJoin.rowid = " + FyleMessageJoinWithStatus.FTS_TABLE_NAME + ".rowid " + - " WHERE " + FyleMessageJoinWithStatus.FTS_TABLE_NAME + " MATCH :filter LIMIT :limit)" - ) - int globalSearchCount(byte[] bytesOwnedIdentity, String filter, int limit); - @Query(MEDIA_FYLE_AND_ORIGIN_QUERY + " ORDER BY FMjoin." + FyleMessageJoinWithStatus.SIZE + " ASC ") LiveData> getMediaFyleAndOriginSizeAsc(byte[] bytesOwnedIdentity); @Query(MEDIA_FYLE_AND_ORIGIN_QUERY + " ORDER BY FMjoin." + FyleMessageJoinWithStatus.SIZE + " DESC ") diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/GlobalSearchDao.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/GlobalSearchDao.kt new file mode 100644 index 00000000..ebd7039c --- /dev/null +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/GlobalSearchDao.kt @@ -0,0 +1,68 @@ +/* + * Olvid for Android + * Copyright © 2019-2024 Olvid SAS + * + * This file is part of Olvid for Android. + * + * Olvid is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * Olvid is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Olvid. If not, see . + */ + +package io.olvid.messenger.databases.dao + +import androidx.room.Dao +import androidx.room.Query +import io.olvid.messenger.databases.dao.FyleMessageJoinWithStatusDao.FyleAndOrigin +import io.olvid.messenger.databases.dao.MessageDao.DiscussionAndMessage +import io.olvid.messenger.databases.entity.Discussion +import io.olvid.messenger.databases.entity.Fyle +import io.olvid.messenger.databases.entity.FyleMessageJoinWithStatus +import io.olvid.messenger.databases.entity.Message + +@Dao +interface GlobalSearchDao { + @Query( + "SELECT " + DiscussionDao.PREFIX_DISCUSSION_COLUMNS + ",m.* FROM " + Message.TABLE_NAME + " AS m " + + " INNER JOIN " + Discussion.TABLE_NAME + " AS disc ON disc.id = m." + Message.DISCUSSION_ID + + " AND disc." + Discussion.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + + " JOIN " + Message.FTS_TABLE_NAME + " ON m.id = " + Message.FTS_TABLE_NAME + ".rowid" + + " WHERE m." + Message.MESSAGE_TYPE + " <= " + Message.TYPE_OUTBOUND_MESSAGE + + " AND " + Message.FTS_TABLE_NAME + " MATCH :query ORDER BY m." + Message.TIMESTAMP + " DESC LIMIT :limit OFFSET :offset" + ) + suspend fun messageGlobalSearch( + bytesOwnedIdentity: ByteArray, + query: String, + limit: Int, + offset: Int + ): List + + @Query( + "SELECT " + DiscussionDao.PREFIX_DISCUSSION_COLUMNS + ", " + MessageDao.PREFIX_MESSAGE_COLUMNS + ", fyle.*, FMjoin.* " + + " FROM " + FyleMessageJoinWithStatus.TABLE_NAME + " AS FMjoin " + + " INNER JOIN " + Fyle.TABLE_NAME + " AS fyle " + + " ON fyle.id = FMjoin." + FyleMessageJoinWithStatus.FYLE_ID + + " INNER JOIN " + Message.TABLE_NAME + " AS mess " + + " ON mess.id = FMjoin." + FyleMessageJoinWithStatus.MESSAGE_ID + + " AND mess." + Message.MESSAGE_TYPE + " != " + Message.TYPE_INBOUND_EPHEMERAL_MESSAGE + + " INNER JOIN " + Discussion.TABLE_NAME + " AS disc " + + " ON disc.id = mess." + Message.DISCUSSION_ID + + " AND disc." + Discussion.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + + " JOIN " + FyleMessageJoinWithStatus.FTS_TABLE_NAME + " ON FMJoin.rowid = " + FyleMessageJoinWithStatus.FTS_TABLE_NAME + ".rowid " + + " WHERE " + FyleMessageJoinWithStatus.FTS_TABLE_NAME + " MATCH :filter ORDER BY mess.timestamp DESC LIMIT :limit OFFSET :offset" + ) + suspend fun attachmentsGlobalSearch( + bytesOwnedIdentity: ByteArray, + filter: String, + limit: Int, + offset: Int + ): List +} diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/Group2Dao.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/Group2Dao.java index c51ef573..9d505beb 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/Group2Dao.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/Group2Dao.java @@ -53,7 +53,8 @@ public interface Group2Dao { "grpp." + Group2.OWN_PERMISSION_SEND_MESSAGE + " AS group2_" + Group2.OWN_PERMISSION_SEND_MESSAGE + ", " + "grpp." + Group2.CUSTOM_NAME + " AS group2_" + Group2.CUSTOM_NAME + ", " + "grpp." + Group2.CUSTOM_PHOTO_URL + " AS group2_" + Group2.CUSTOM_PHOTO_URL + ", " + - "grpp." + Group2.PERSONAL_NOTE + " AS group2_" + Group2.PERSONAL_NOTE; + "grpp." + Group2.PERSONAL_NOTE + " AS group2_" + Group2.PERSONAL_NOTE + ", " + + "grpp." + Group2.FULL_SEARCH_FIELD + " AS group2_" + Group2.FULL_SEARCH_FIELD; String GROUP2_NULL_COLUMNS = " NULL AS group2_" + Group2.BYTES_OWNED_IDENTITY + ", " + " NULL AS group2_" + Group2.BYTES_GROUP_IDENTIFIER + ", " + @@ -70,7 +71,8 @@ public interface Group2Dao { " NULL AS group2_" + Group2.OWN_PERMISSION_SEND_MESSAGE + ", " + " NULL AS group2_" + Group2.CUSTOM_NAME + ", " + " NULL AS group2_" + Group2.CUSTOM_PHOTO_URL + ", " + - " NULL AS group2_" + Group2.PERSONAL_NOTE; + " NULL AS group2_" + Group2.PERSONAL_NOTE + ", " + + " NULL AS group2_" + Group2.FULL_SEARCH_FIELD; String GROUP_NULL_COLUMNS = " NULL AS group_" + Group.BYTES_GROUP_OWNER_AND_UID + ", " + " NULL AS group_" + Group.BYTES_OWNED_IDENTITY + ", " + @@ -81,7 +83,8 @@ public interface Group2Dao { " NULL AS group_" + Group.PHOTO_URL + ", " + " NULL AS group_" + Group.GROUP_MEMBERS_NAMES + ", " + " NULL AS group_" + Group.CUSTOM_PHOTO_URL + ", " + - " NULL AS group_" + Group.PERSONAL_NOTE; + " NULL AS group_" + Group.PERSONAL_NOTE + ", " + + " NULL AS group_" + Group.FULL_SEARCH_FIELD; @Insert void insert(Group2 group); @@ -99,10 +102,11 @@ public interface Group2Dao { void updatePhotoUrl(byte[] bytesOwnedIdentity, byte[] bytesGroupIdentifier, String photoUrl); @Query("UPDATE " + Group2.TABLE_NAME + " SET " + - Group2.CUSTOM_NAME + " = :customName " + + Group2.CUSTOM_NAME + " = :customName, " + + Group2.FULL_SEARCH_FIELD + " = :fullSearchField " + " WHERE " + Group2.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + " AND " + Group2.BYTES_GROUP_IDENTIFIER + " = :bytesGroupIdentifier ") - void updateCustomName(byte[] bytesOwnedIdentity, byte[] bytesGroupIdentifier, String customName); + void updateCustomName(byte[] bytesOwnedIdentity, byte[] bytesGroupIdentifier, String customName, String fullSearchField); @Query("UPDATE " + Group2.TABLE_NAME + " SET " + Group2.CUSTOM_PHOTO_URL + " = :customPhotoUrl " + @@ -111,10 +115,11 @@ public interface Group2Dao { void updateCustomPhotoUrl(byte[] bytesOwnedIdentity, byte[] bytesGroupIdentifier, String customPhotoUrl); @Query("UPDATE " + Group2.TABLE_NAME + " SET " + - Group2.PERSONAL_NOTE + " = :personalNote " + + Group2.PERSONAL_NOTE + " = :personalNote, " + + Group2.FULL_SEARCH_FIELD + " = :fullSearchField " + " WHERE " + Group2.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + " AND " + Group2.BYTES_GROUP_IDENTIFIER + " = :bytesGroupIdentifier ") - void updatePersonalNote(byte[] bytesOwnedIdentity, byte[] bytesGroupIdentifier, String personalNote); + void updatePersonalNote(byte[] bytesOwnedIdentity, byte[] bytesGroupIdentifier, String personalNote, String fullSearchField); @Query("UPDATE " + Group2.TABLE_NAME + " SET " + Group2.UPDATE_IN_PROGRESS + " = :updating " + @@ -129,10 +134,11 @@ public interface Group2Dao { void updateNewPublishedDetails(byte[] bytesOwnedIdentity, byte[] bytesGroupIdentifier, int newPublishedDetails); @Query("UPDATE " + Group2.TABLE_NAME + " SET " + - Group2.GROUP_MEMBERS_NAMES + " = :groupMembersNames " + + Group2.GROUP_MEMBERS_NAMES + " = :groupMembersNames, " + + Group2.FULL_SEARCH_FIELD + " = :fullSearchField " + " WHERE " + Group2.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + " AND " + Group2.BYTES_GROUP_IDENTIFIER + " = :bytesGroupIdentifier ") - void updateGroupMembersNames(byte[] bytesOwnedIdentity, byte[] bytesGroupIdentifier, String groupMembersNames); + void updateGroupMembersNames(byte[] bytesOwnedIdentity, byte[] bytesGroupIdentifier, String groupMembersNames, String fullSearchField); @Query("SELECT * FROM " + Group2.TABLE_NAME + " WHERE " + Group2.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/GroupDao.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/GroupDao.java index 80f498a3..754b9a85 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/GroupDao.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/GroupDao.java @@ -44,7 +44,8 @@ public interface GroupDao { "groop." + Group.PHOTO_URL + " AS group_" + Group.PHOTO_URL + ", " + "groop." + Group.GROUP_MEMBERS_NAMES + " AS group_" + Group.GROUP_MEMBERS_NAMES + ", " + "groop." + Group.CUSTOM_PHOTO_URL + " AS group_" + Group.CUSTOM_PHOTO_URL + ", " + - "groop." + Group.PERSONAL_NOTE + " AS group_" + Group.PERSONAL_NOTE; + "groop." + Group.PERSONAL_NOTE + " AS group_" + Group.PERSONAL_NOTE + ", " + + "groop." + Group.FULL_SEARCH_FIELD + " AS group_" + Group.FULL_SEARCH_FIELD; @Insert void insert(Group group); @@ -65,11 +66,12 @@ public interface GroupDao { " AND " + Group.BYTES_GROUP_OWNER_AND_UID + " = :bytesGroupOwnerAndUid") void updateNameAndPhoto(byte[] bytesOwnedIdentity, byte[] bytesGroupOwnerAndUid, String name, String photoUrl); - @Query("UPDATE " + Group.TABLE_NAME + - " SET " + Group.CUSTOM_NAME + " = :customName " + + @Query("UPDATE " + Group.TABLE_NAME + " SET " + + Group.CUSTOM_NAME + " = :customName, " + + Group.FULL_SEARCH_FIELD + " = :fullSearchField " + " WHERE " + Group.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + " AND " + Group.BYTES_GROUP_OWNER_AND_UID + " = :bytesGroupOwnerAndUid") - void updateCustomName(byte[] bytesOwnedIdentity, byte[] bytesGroupOwnerAndUid, String customName); + void updateCustomName(byte[] bytesOwnedIdentity, byte[] bytesGroupOwnerAndUid, String customName, String fullSearchField); @Query("UPDATE " + Group.TABLE_NAME + " SET " + Group.CUSTOM_PHOTO_URL + " = :customPhotoUrl " + @@ -77,11 +79,12 @@ public interface GroupDao { " AND " + Group.BYTES_GROUP_OWNER_AND_UID + " = :bytesGroupOwnerAndUid") void updateCustomPhotoUrl(byte[] bytesOwnedIdentity, byte[] bytesGroupOwnerAndUid, String customPhotoUrl); - @Query("UPDATE " + Group.TABLE_NAME + - " SET " + Group.PERSONAL_NOTE + " = :personalNote " + + @Query("UPDATE " + Group.TABLE_NAME + " SET " + + Group.PERSONAL_NOTE + " = :personalNote, " + + Group.FULL_SEARCH_FIELD + " = :fullSearchField " + " WHERE " + Group.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + " AND " + Group.BYTES_GROUP_OWNER_AND_UID + " = :bytesGroupOwnerAndUid") - void updatePersonalNote(byte[] bytesOwnedIdentity, byte[] bytesGroupOwnerAndUid, String personalNote); + void updatePersonalNote(byte[] bytesOwnedIdentity, byte[] bytesGroupOwnerAndUid, String personalNote, String fullSearchField); @Query("UPDATE " + Group.TABLE_NAME + " SET " + Group.PHOTO_URL + " = :photoUrl " + @@ -89,11 +92,12 @@ public interface GroupDao { " AND " + Group.BYTES_GROUP_OWNER_AND_UID + " = :bytesGroupOwnerAndUid") void updatePhotoUrl(byte[] bytesOwnedIdentity, byte[] bytesGroupOwnerAndUid, String photoUrl); - @Query("UPDATE " + Group.TABLE_NAME + - " SET " + Group.GROUP_MEMBERS_NAMES + " = :groupMembersNames " + + @Query("UPDATE " + Group.TABLE_NAME + " SET " + + Group.GROUP_MEMBERS_NAMES + " = :groupMembersNames, " + + Group.FULL_SEARCH_FIELD + " = :fullSearchField " + " WHERE " + Group.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + " AND " + Group.BYTES_GROUP_OWNER_AND_UID + " = :bytesGroupOwnerAndUid") - void updateGroupMembersNames(byte[] bytesOwnedIdentity, byte[] bytesGroupOwnerAndUid, String groupMembersNames); + void updateGroupMembersNames(byte[] bytesOwnedIdentity, byte[] bytesGroupOwnerAndUid, String groupMembersNames, String fullSearchField); @Query("SELECT * FROM " + Group.TABLE_NAME + " WHERE " + Group.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity AND " + Group.BYTES_GROUP_OWNER_AND_UID + " = :bytesGroupOwnerAndUid") Group get(byte[] bytesOwnedIdentity, byte[] bytesGroupOwnerAndUid); diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/MessageDao.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/MessageDao.java index 95a08a77..71270dd8 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/MessageDao.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/dao/MessageDao.java @@ -87,25 +87,9 @@ public interface MessageDao { @Update void update(Message message); - @Query("SELECT " + PREFIX_DISCUSSION_COLUMNS + ",m.* FROM " + Message.TABLE_NAME + " AS m " + - " INNER JOIN " + Discussion.TABLE_NAME + " AS disc ON disc.id = m." + Message.DISCUSSION_ID + - " AND disc." + Discussion.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + - " JOIN " + Message.FTS_TABLE_NAME + " ON m.id = " + Message.FTS_TABLE_NAME + ".rowid" + - " WHERE m." + Message.MESSAGE_TYPE + " != " + Message.TYPE_INBOUND_EPHEMERAL_MESSAGE + - " AND " + Message.FTS_TABLE_NAME + " MATCH :query ORDER BY m." + Message.TIMESTAMP + " DESC LIMIT :limit ") - List globalSearch(byte[] bytesOwnedIdentity, String query, int limit); - - @Query("SELECT COUNT(*) FROM (SELECT m.id FROM " + Message.TABLE_NAME + " AS m " + - " INNER JOIN " + Discussion.TABLE_NAME + " AS disc ON disc.id = m." + Message.DISCUSSION_ID + - " AND disc." + Discussion.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " + - " JOIN " + Message.FTS_TABLE_NAME + " ON m.id = " + Message.FTS_TABLE_NAME + ".rowid" + - " WHERE m." + Message.MESSAGE_TYPE + " != " + Message.TYPE_INBOUND_EPHEMERAL_MESSAGE + - " AND " + Message.FTS_TABLE_NAME + " MATCH :query LIMIT :limit)") - int globalSearchCount(byte[] bytesOwnedIdentity, String query, int limit); - @Query("SELECT m.id FROM " + Message.TABLE_NAME + " AS m " + " JOIN " + Message.FTS_TABLE_NAME + " ON m.id = " + Message.FTS_TABLE_NAME + ".rowid" + - " WHERE m." + Message.MESSAGE_TYPE + " != " + Message.TYPE_INBOUND_EPHEMERAL_MESSAGE + + " WHERE m." + Message.MESSAGE_TYPE + " <= " + Message.TYPE_OUTBOUND_MESSAGE + " AND m." + Message.DISCUSSION_ID + " = :discussionId" + " AND " + Message.FTS_TABLE_NAME + " MATCH :query ORDER BY m." + Message.TIMESTAMP + " DESC") List discussionSearch(long discussionId, String query); diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Contact.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Contact.java index 5c8c63d9..a21406ae 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Contact.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Contact.java @@ -237,14 +237,12 @@ public Contact(@NonNull byte[] bytesContactIdentity, @NonNull byte[] bytesOwnedI @NonNull private String computeFullSearchDisplayName(JsonIdentityDetails jsonIdentityDetails) { + String custDisp = this.customDisplayName == null ? "" : this.customDisplayName; + String persNote = personalNote == null ? "" : personalNote; if (jsonIdentityDetails == null) { - return this.customDisplayName == null ? "" : this.customDisplayName; + return StringUtils.unAccent(custDisp + " " + persNote); } else { - if (customDisplayName == null) { - return StringUtils.unAccent(jsonIdentityDetails.formatDisplayName(JsonIdentityDetails.FORMAT_STRING_FOR_SEARCH, false)); - } else { - return StringUtils.unAccent(customDisplayName + " " + jsonIdentityDetails.formatDisplayName(JsonIdentityDetails.FORMAT_STRING_FOR_SEARCH, false)); - } + return StringUtils.unAccent(custDisp + " " + jsonIdentityDetails.formatDisplayName(JsonIdentityDetails.FORMAT_STRING_FOR_SEARCH, false) + " " + persNote); } } @@ -274,6 +272,11 @@ public void setCustomDisplayName(@Nullable String customDisplayName) { this.fullSearchDisplayName = computeFullSearchDisplayName(identityDetails); } + public void setPersonalNote(@Nullable String personalNote) { + this.personalNote = personalNote; + this.fullSearchDisplayName = computeFullSearchDisplayName(getIdentityDetails()); + } + @Nullable public JsonIdentityDetails getIdentityDetails() { if (identityDetails == null) { diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Group.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Group.java index 0b630aa9..bf0f8f80 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Group.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Group.java @@ -28,7 +28,10 @@ import androidx.room.Ignore; import androidx.room.Index; +import java.util.List; + import io.olvid.engine.engine.types.JsonGroupDetails; +import io.olvid.messenger.customClasses.StringUtils; @Entity(tableName = Group.TABLE_NAME, primaryKeys = {Group.BYTES_GROUP_OWNER_AND_UID, Group.BYTES_OWNED_IDENTITY}, @@ -61,6 +64,7 @@ public class Group { public static final String GROUP_MEMBERS_NAMES = "group_members_names"; public static final String CUSTOM_PHOTO_URL = "custom_photo_url"; // set to "" to remove the default photo_url, null to use the default public static final String PERSONAL_NOTE = "personal_note"; + public static final String FULL_SEARCH_FIELD = "full_search_field"; public static final int PUBLISHED_DETAILS_NOTHING_NEW = 0; public static final int PUBLISHED_DETAILS_NEW_UNSEEN = 1; @@ -107,6 +111,9 @@ public class Group { @Nullable public String personalNote; + @ColumnInfo(name = FULL_SEARCH_FIELD) + @NonNull + public String fullSearchField; public String getCustomName() { if (customName == null) { @@ -118,14 +125,14 @@ public String getCustomName() { public String getCustomPhotoUrl() { if (customPhotoUrl == null) { return photoUrl; - } else if (customPhotoUrl.length() == 0) { + } else if (customPhotoUrl.isEmpty()) { return null; } return customPhotoUrl; } // default constructor required by Room - public Group(@NonNull byte[] bytesGroupOwnerAndUid, @NonNull byte[] bytesOwnedIdentity, @Nullable String customName, @NonNull String name, int newPublishedDetails, @Nullable byte[] bytesGroupOwnerIdentity, @Nullable String photoUrl, @NonNull String groupMembersNames, @Nullable String customPhotoUrl, @Nullable String personalNote) { + public Group(@NonNull byte[] bytesGroupOwnerAndUid, @NonNull byte[] bytesOwnedIdentity, @Nullable String customName, @NonNull String name, int newPublishedDetails, @Nullable byte[] bytesGroupOwnerIdentity, @Nullable String photoUrl, @NonNull String groupMembersNames, @Nullable String customPhotoUrl, @Nullable String personalNote, @NonNull String fullSearchField) { this.bytesGroupOwnerAndUid = bytesGroupOwnerAndUid; this.bytesOwnedIdentity = bytesOwnedIdentity; this.customName = customName; @@ -136,10 +143,10 @@ public Group(@NonNull byte[] bytesGroupOwnerAndUid, @NonNull byte[] bytesOwnedId this.groupMembersNames = groupMembersNames; this.customPhotoUrl = customPhotoUrl; this.personalNote = personalNote; + this.fullSearchField = fullSearchField; } - @Ignore public Group(@NonNull byte[] bytesGroupOwnerAndUid, @NonNull byte[] bytesOwnedIdentity, @NonNull JsonGroupDetails groupDetails, @Nullable String photoUrl, @Nullable byte[] bytesGroupOwnerIdentity, boolean hasMultipleDetails) { this.bytesGroupOwnerAndUid = bytesGroupOwnerAndUid; @@ -160,5 +167,21 @@ public Group(@NonNull byte[] bytesGroupOwnerAndUid, @NonNull byte[] bytesOwnedId this.bytesGroupOwnerIdentity = bytesGroupOwnerIdentity; this.groupMembersNames = ""; this.personalNote = null; + this.fullSearchField = ""; + } + + @NonNull + public String computeFullSearch(@NonNull List membersFullSearch) { + String suffix = ""; + if (customName != null) { + suffix += " " + customName; + } + if (personalNote != null) { + suffix += " " + personalNote; + } + if (name != null) { + suffix += " " + name; + } + return StringUtils.unAccent(String.join(" ", membersFullSearch) + suffix); } } diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Group2.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Group2.java index d4f5a014..0f45065f 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Group2.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/Group2.java @@ -28,11 +28,13 @@ import androidx.room.Index; import java.util.HashSet; +import java.util.List; import java.util.Objects; import io.olvid.engine.datatypes.containers.GroupV2; import io.olvid.messenger.App; import io.olvid.messenger.R; +import io.olvid.messenger.customClasses.StringUtils; @Entity(tableName = Group2.TABLE_NAME, primaryKeys = {Group2.BYTES_OWNED_IDENTITY, Group2.BYTES_GROUP_IDENTIFIER}, @@ -68,7 +70,7 @@ public class Group2 { public static final String CUSTOM_NAME = "custom_name"; public static final String CUSTOM_PHOTO_URL = "custom_photo_url"; // set to "" to remove the default photo_url, null to use the default public static final String PERSONAL_NOTE = "personal_note"; - + public static final String FULL_SEARCH_FIELD = "full_search_field"; public static final int PUBLISHED_DETAILS_NOTHING_NEW = 0; public static final int PUBLISHED_DETAILS_NEW_UNSEEN = 1; @@ -136,6 +138,10 @@ public class Group2 { @Nullable public String personalNote; + @ColumnInfo(name = FULL_SEARCH_FIELD) + @NonNull + public String fullSearchField; + @NonNull public String getCustomName() { if ((customName == null && name == null) @@ -165,7 +171,7 @@ public String getTruncatedCustomName() { public String getCustomPhotoUrl() { if (customPhotoUrl == null) { return photoUrl; - } else if (customPhotoUrl.length() == 0) { + } else if (customPhotoUrl.isEmpty()) { return null; } return customPhotoUrl; @@ -173,13 +179,13 @@ public String getCustomPhotoUrl() { // default constructor used by Room - public Group2(@NonNull byte[] bytesOwnedIdentity, @NonNull byte[] bytesGroupIdentifier, boolean keycloakManaged, @Nullable String name, @NonNull String groupMembersNames, @Nullable String photoUrl, int updateInProgress, int newPublishedDetails, boolean ownPermissionAdmin, boolean ownPermissionRemoteDeleteAnything, boolean ownPermissionEditOrRemoteDeleteOwnMessages, boolean ownPermissionChangeSettings, boolean ownPermissionSendMessage, @Nullable String customName, @Nullable String customPhotoUrl, @Nullable String personalNote) { + public Group2(@NonNull byte[] bytesOwnedIdentity, @NonNull byte[] bytesGroupIdentifier, boolean keycloakManaged, @Nullable String name, @Nullable String photoUrl, @NonNull String groupMembersNames, int updateInProgress, int newPublishedDetails, boolean ownPermissionAdmin, boolean ownPermissionRemoteDeleteAnything, boolean ownPermissionEditOrRemoteDeleteOwnMessages, boolean ownPermissionChangeSettings, boolean ownPermissionSendMessage, @Nullable String customName, @Nullable String customPhotoUrl, @Nullable String personalNote, @NonNull String fullSearchField) { this.bytesOwnedIdentity = bytesOwnedIdentity; this.bytesGroupIdentifier = bytesGroupIdentifier; this.keycloakManaged = keycloakManaged; this.name = name; - this.groupMembersNames = groupMembersNames; this.photoUrl = photoUrl; + this.groupMembersNames = groupMembersNames; this.updateInProgress = updateInProgress; this.newPublishedDetails = newPublishedDetails; this.ownPermissionAdmin = ownPermissionAdmin; @@ -190,6 +196,7 @@ public Group2(@NonNull byte[] bytesOwnedIdentity, @NonNull byte[] bytesGroupIden this.customName = customName; this.customPhotoUrl = customPhotoUrl; this.personalNote = personalNote; + this.fullSearchField = fullSearchField; } @Ignore @@ -211,5 +218,21 @@ public Group2(@NonNull byte[] bytesOwnedIdentity, @NonNull byte[] bytesGroupIden this.customName = null; this.customPhotoUrl = null; this.personalNote = null; + this.fullSearchField = ""; + } + + @NonNull + public String computeFullSearch(@NonNull List membersFullSearch) { + String suffix = ""; + if (customName != null) { + suffix += " " + customName; + } + if (personalNote != null) { + suffix += " " + personalNote; + } + if (name != null) { + suffix += " " + name; + } + return StringUtils.unAccent(String.join(" ", membersFullSearch) + suffix); } } diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/ContactSyncSnapshot.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/ContactSyncSnapshot.java index 7c2fb590..c51148dc 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/ContactSyncSnapshot.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/ContactSyncSnapshot.java @@ -81,12 +81,13 @@ public void restore(AppDatabase db, byte[] bytesOwnedIdentity, byte[] bytesConta db.discussionDao().updateTitleAndPhotoUrl(discussion.id, contact.getCustomDisplayName(), discussion.photoUrl); } } + if (domain.contains(PERSONAL_NOTE) && personal_note != null) { + contact.setPersonalNote(personal_note); + db.contactDao().updatePersonalNote(bytesOwnedIdentity, bytesContactIdentity, contact.personalNote, contact.fullSearchDisplayName); + } if (domain.contains(CUSTOM_HUE) && custom_hue != null) { db.contactDao().updateCustomNameHue(bytesOwnedIdentity, bytesContactIdentity, custom_hue); } - if (domain.contains(PERSONAL_NOTE) && personal_note != null) { - db.contactDao().updatePersonalNote(bytesOwnedIdentity, bytesContactIdentity, personal_note); - } if (discussion != null) { if (domain.contains(DISCUSSION_CUSTOMIZATION) && discussion_customization != null) { discussion_customization.restore(db, discussion.id); diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/GroupV1SyncSnapshot.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/GroupV1SyncSnapshot.java index b7ecd6a5..b43fd92d 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/GroupV1SyncSnapshot.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/GroupV1SyncSnapshot.java @@ -29,6 +29,7 @@ import io.olvid.engine.engine.types.sync.ObvSyncDiff; import io.olvid.engine.engine.types.sync.ObvSyncSnapshotNode; +import io.olvid.messenger.customClasses.StringUtils; import io.olvid.messenger.databases.AppDatabase; import io.olvid.messenger.databases.entity.Discussion; import io.olvid.messenger.databases.entity.DiscussionCustomization; @@ -69,13 +70,15 @@ public void restore(AppDatabase db, byte[] bytesOwnedIdentity, byte[] bytesGroup if (group != null) { Discussion discussion = db.discussionDao().getByGroupOwnerAndUid(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid); if (domain.contains(CUSTOM_NAME) && custom_name != null) { - db.groupDao().updateCustomName(bytesOwnedIdentity, bytesGroupOwnerAndUid, custom_name); + group.fullSearchField = group.fullSearchField + " " + StringUtils.unAccent(custom_name); + db.groupDao().updateCustomName(bytesOwnedIdentity, bytesGroupOwnerAndUid, custom_name, group.fullSearchField); if (discussion != null) { db.discussionDao().updateTitleAndPhotoUrl(discussion.id, custom_name, discussion.photoUrl); } } if (domain.contains(PERSONAL_NOTE) && personal_note != null) { - db.groupDao().updatePersonalNote(bytesOwnedIdentity, bytesGroupOwnerAndUid, personal_note); + group.fullSearchField = group.fullSearchField + " " + StringUtils.unAccent(personal_note); + db.groupDao().updatePersonalNote(bytesOwnedIdentity, bytesGroupOwnerAndUid, personal_note, group.fullSearchField); } if (domain.contains(DISCUSSION_CUSTOMIZATION) && discussion_customization != null) { if (discussion != null) { diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/GroupV2SyncSnapshot.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/GroupV2SyncSnapshot.java index b44fbcd0..faba3cf6 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/GroupV2SyncSnapshot.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/entity/sync/GroupV2SyncSnapshot.java @@ -29,6 +29,7 @@ import io.olvid.engine.engine.types.sync.ObvSyncDiff; import io.olvid.engine.engine.types.sync.ObvSyncSnapshotNode; +import io.olvid.messenger.customClasses.StringUtils; import io.olvid.messenger.databases.AppDatabase; import io.olvid.messenger.databases.entity.Discussion; import io.olvid.messenger.databases.entity.DiscussionCustomization; @@ -69,13 +70,15 @@ public void restore(AppDatabase db, byte[] bytesOwnedIdentity, byte[] bytesGroup if (group2 != null) { Discussion discussion = db.discussionDao().getByGroupIdentifier(group2.bytesOwnedIdentity, group2.bytesGroupIdentifier); if (domain.contains(CUSTOM_NAME) && custom_name != null) { - db.group2Dao().updateCustomName(bytesOwnedIdentity, bytesGroupIdentifier, custom_name); + group2.fullSearchField = group2.fullSearchField + " " + StringUtils.unAccent(custom_name); + db.group2Dao().updateCustomName(bytesOwnedIdentity, bytesGroupIdentifier, custom_name, group2.fullSearchField); if (discussion != null) { db.discussionDao().updateTitleAndPhotoUrl(discussion.id, custom_name, discussion.photoUrl); } } if (domain.contains(PERSONAL_NOTE) && personal_note != null) { - db.group2Dao().updatePersonalNote(bytesOwnedIdentity, bytesGroupIdentifier, personal_note); + group2.fullSearchField = group2.fullSearchField + " " + StringUtils.unAccent(personal_note); + db.group2Dao().updatePersonalNote(bytesOwnedIdentity, bytesGroupIdentifier, personal_note, group2.fullSearchField); } if (domain.contains(DISCUSSION_CUSTOMIZATION) && discussion_customization != null) { if (discussion != null) { diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/ContactDisplayNameFormatChangedTask.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/ContactDisplayNameFormatChangedTask.java index ff46e74a..aef3ad04 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/ContactDisplayNameFormatChangedTask.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/ContactDisplayNameFormatChangedTask.java @@ -60,6 +60,10 @@ public void run() { // then, compute the sortDisplayName contact.sortDisplayName = computeSortDisplayName(collator, identityDetails, contact.customDisplayName, lastNameSort); + //////// + // we do this to force a recompute of the full search field + contact.setPersonalNote(contact.personalNote); + db.contactDao().updateAllDisplayNames(contact.bytesOwnedIdentity, contact.bytesContactIdentity, contact.identityDetails, contact.displayName, contact.firstName, contact.customDisplayName, contact.sortDisplayName, contact.fullSearchDisplayName); Discussion discussion = db.discussionDao().getByContact(contact.bytesOwnedIdentity, contact.bytesContactIdentity); diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/CreateOrUpdateGroupV2Task.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/CreateOrUpdateGroupV2Task.java index 58840dd1..43785355 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/CreateOrUpdateGroupV2Task.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/CreateOrUpdateGroupV2Task.java @@ -46,6 +46,7 @@ import io.olvid.messenger.customClasses.BytesKey; import io.olvid.messenger.customClasses.StringUtils; import io.olvid.messenger.databases.AppDatabase; +import io.olvid.messenger.databases.dao.Group2MemberDao; import io.olvid.messenger.databases.dao.MessageRecipientInfoDao; import io.olvid.messenger.databases.entity.Contact; import io.olvid.messenger.databases.entity.Discussion; @@ -174,7 +175,7 @@ public void run() { } } group.ownPermissionSendMessage = groupV2.ownPermissions.contains(GroupV2.Permission.SEND_MESSAGE); - db.group2Dao().update(group); + db.group2Dao().update(group); // TODO: update fullSearchField too } if (group.ownPermissionChangeSettings) { @@ -542,13 +543,25 @@ public void run() { // update the group members name field + List fullSearchItems = new ArrayList<>(); + for (Group2MemberDao.Group2MemberOrPending group2MemberOrPending : db.group2MemberDao().getGroupMembersAndPendingSync(group.bytesOwnedIdentity, group.bytesGroupIdentifier)) { + if (group2MemberOrPending.contact != null) { + fullSearchItems.add(group2MemberOrPending.contact.fullSearchDisplayName); + } else { + try { + JsonIdentityDetails jsonIdentityDetails = AppSingleton.getJsonObjectMapper().readValue(group2MemberOrPending.identityDetails, JsonIdentityDetails.class); + fullSearchItems.add(StringUtils.unAccent(jsonIdentityDetails.formatDisplayName(JsonIdentityDetails.FORMAT_STRING_FOR_SEARCH, false))); + } catch (Exception ignored) {} + } + } + group.groupMembersNames = StringUtils.joinContactDisplayNames( SettingsActivity.getAllowContactFirstName() ? db.group2Dao().getGroupMembersFirstNames(groupV2.bytesOwnedIdentity, bytesGroupIdentifier) : db.group2Dao().getGroupMembersNames(groupV2.bytesOwnedIdentity, bytesGroupIdentifier) ); - db.group2Dao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupIdentifier, group.groupMembersNames); + db.group2Dao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupIdentifier, group.groupMembersNames, group.computeFullSearch(fullSearchItems)); if (!Objects.equals(discussion.title, group.getCustomName())) { discussion.title = group.getCustomName(); diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateAllGroupMembersNames.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateAllGroupMembersNames.java index 7c398c31..f5807207 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateAllGroupMembersNames.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateAllGroupMembersNames.java @@ -22,9 +22,16 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + +import io.olvid.engine.engine.types.JsonIdentityDetails; +import io.olvid.messenger.AppSingleton; import io.olvid.messenger.activities.ShortcutActivity; import io.olvid.messenger.customClasses.StringUtils; import io.olvid.messenger.databases.AppDatabase; +import io.olvid.messenger.databases.dao.Group2MemberDao; +import io.olvid.messenger.databases.entity.Contact; import io.olvid.messenger.databases.entity.Discussion; import io.olvid.messenger.databases.entity.Group; import io.olvid.messenger.databases.entity.Group2; @@ -61,7 +68,15 @@ public void run() { : db.groupDao().getGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid) ); - db.groupDao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.groupMembersNames); + + List fullSearchItems = new ArrayList<>(); + for (Contact groupContact : db.contactGroupJoinDao().getGroupContactsSync(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid)) { + if (groupContact != null) { + fullSearchItems.add(groupContact.fullSearchDisplayName); + } + } + + db.groupDao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.groupMembersNames, group.computeFullSearch(fullSearchItems)); } for (Group2 group : ((bytesOwnedIdentity == null) ? db.group2Dao().getAll() : (bytesContactIdentity == null) ? db.group2Dao().getAllForOwnedIdentity(bytesOwnedIdentity) : db.group2Dao().getAllForContact(bytesOwnedIdentity, bytesContactIdentity))) { @@ -71,7 +86,18 @@ public void run() { : db.group2Dao().getGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupIdentifier) ); - db.group2Dao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupIdentifier, group.groupMembersNames); + List fullSearchItems = new ArrayList<>(); + for (Group2MemberDao.Group2MemberOrPending group2MemberOrPending : db.group2MemberDao().getGroupMembersAndPendingSync(group.bytesOwnedIdentity, group.bytesGroupIdentifier)) { + if (group2MemberOrPending.contact != null) { + fullSearchItems.add(group2MemberOrPending.contact.fullSearchDisplayName); + } else { + try { + JsonIdentityDetails jsonIdentityDetails = AppSingleton.getJsonObjectMapper().readValue(group2MemberOrPending.identityDetails, JsonIdentityDetails.class); + fullSearchItems.add(StringUtils.unAccent(jsonIdentityDetails.formatDisplayName(JsonIdentityDetails.FORMAT_STRING_FOR_SEARCH, false))); + } catch (Exception ignored) {} + } + } + db.group2Dao().updateGroupMembersNames(group.bytesOwnedIdentity, group.bytesGroupIdentifier, group.groupMembersNames, group.computeFullSearch(fullSearchItems)); if (group.name == null && group.customName == null) { Discussion discussion = db.discussionDao().getByGroupIdentifier(group.bytesOwnedIdentity, group.bytesGroupIdentifier); diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateContactCustomDisplayNameAndPhotoTask.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateContactCustomDisplayNameAndPhotoTask.java index 88f33232..9402f159 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateContactCustomDisplayNameAndPhotoTask.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateContactCustomDisplayNameAndPhotoTask.java @@ -75,9 +75,10 @@ public void run() { } } + boolean refreshGroupNames = false; if (!Objects.equals(contact.personalNote, personalNote)) { - contact.personalNote = personalNote; - db.contactDao().updatePersonalNote(contact.bytesOwnedIdentity, contact.bytesContactIdentity, contact.personalNote); + contact.setPersonalNote(personalNote); + db.contactDao().updatePersonalNote(contact.bytesOwnedIdentity, contact.bytesContactIdentity, contact.personalNote, contact.fullSearchDisplayName); if (!propagated) { try { @@ -87,6 +88,7 @@ public void run() { e.printStackTrace(); } } + refreshGroupNames = true; } if (!Objects.equals(contact.customDisplayName, customDisplayName)) { @@ -105,7 +107,10 @@ public void run() { e.printStackTrace(); } } + refreshGroupNames = true; + } + if (refreshGroupNames) { new UpdateAllGroupMembersNames(contact.bytesOwnedIdentity, contact.bytesContactIdentity).run(); } diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateGroupCustomNameAndPhotoTask.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateGroupCustomNameAndPhotoTask.java index 3e2cbd33..202e40c8 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateGroupCustomNameAndPhotoTask.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateGroupCustomNameAndPhotoTask.java @@ -22,6 +22,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.UUID; @@ -31,6 +33,7 @@ import io.olvid.messenger.AppSingleton; import io.olvid.messenger.activities.ShortcutActivity; import io.olvid.messenger.databases.AppDatabase; +import io.olvid.messenger.databases.entity.Contact; import io.olvid.messenger.databases.entity.Discussion; import io.olvid.messenger.databases.entity.Group; @@ -60,8 +63,15 @@ public void run() { boolean changed = false; if (!Objects.equals(group.customName, customName)) { changed = true; + + List fullSearchItems = new ArrayList<>(); + for (Contact groupContact : db.contactGroupJoinDao().getGroupContactsSync(bytesOwnedIdentity, bytesGroupOwnerAndUid)) { + if (groupContact != null) { + fullSearchItems.add(groupContact.fullSearchDisplayName); + } + } group.customName = customName; - db.groupDao().updateCustomName(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.customName); + db.groupDao().updateCustomName(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.customName, group.computeFullSearch(fullSearchItems)); if (!propagated) { try { @@ -86,7 +96,7 @@ public void run() { } } - if (absoluteCustomPhotoUrl == null || "".equals(absoluteCustomPhotoUrl)) { + if (absoluteCustomPhotoUrl == null || absoluteCustomPhotoUrl.isEmpty()) { // custom photo was reset or removed group.customPhotoUrl = absoluteCustomPhotoUrl; } else { @@ -126,8 +136,15 @@ public void run() { } if (!Objects.equals(group.personalNote, personalNote)) { + List fullSearchItems = new ArrayList<>(); + for (Contact groupContact : db.contactGroupJoinDao().getGroupContactsSync(bytesOwnedIdentity, bytesGroupOwnerAndUid)) { + if (groupContact != null) { + fullSearchItems.add(groupContact.fullSearchDisplayName); + } + } + group.personalNote = personalNote; - db.groupDao().updatePersonalNote(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.personalNote); + db.groupDao().updatePersonalNote(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.personalNote, group.computeFullSearch(fullSearchItems)); if (!propagated) { try { diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateGroupV2CustomNameAndPhotoTask.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateGroupV2CustomNameAndPhotoTask.java index 6fa619c8..5f540dc4 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateGroupV2CustomNameAndPhotoTask.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/UpdateGroupV2CustomNameAndPhotoTask.java @@ -22,15 +22,21 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.UUID; import io.olvid.engine.Logger; +import io.olvid.engine.engine.types.JsonIdentityDetails; import io.olvid.engine.engine.types.sync.ObvSyncAtom; import io.olvid.messenger.App; import io.olvid.messenger.AppSingleton; import io.olvid.messenger.activities.ShortcutActivity; +import io.olvid.messenger.customClasses.StringUtils; import io.olvid.messenger.databases.AppDatabase; +import io.olvid.messenger.databases.dao.Group2MemberDao; +import io.olvid.messenger.databases.entity.Contact; import io.olvid.messenger.databases.entity.Discussion; import io.olvid.messenger.databases.entity.Group2; @@ -60,8 +66,20 @@ public void run() { boolean changed = false; if (!Objects.equals(group.customName, customName)) { changed = true; + + List fullSearchItems = new ArrayList<>(); + for (Group2MemberDao.Group2MemberOrPending group2MemberOrPending : db.group2MemberDao().getGroupMembersAndPendingSync(bytesOwnedIdentity, bytesGroupIdentifier)) { + if (group2MemberOrPending.contact != null) { + fullSearchItems.add(group2MemberOrPending.contact.fullSearchDisplayName); + } else { + try { + JsonIdentityDetails jsonIdentityDetails = AppSingleton.getJsonObjectMapper().readValue(group2MemberOrPending.identityDetails, JsonIdentityDetails.class); + fullSearchItems.add(StringUtils.unAccent(jsonIdentityDetails.formatDisplayName(JsonIdentityDetails.FORMAT_STRING_FOR_SEARCH, false))); + } catch (Exception ignored) {} + } + } group.customName = customName; - db.group2Dao().updateCustomName(group.bytesOwnedIdentity, group.bytesGroupIdentifier, group.customName); + db.group2Dao().updateCustomName(group.bytesOwnedIdentity, group.bytesGroupIdentifier, group.customName, group.computeFullSearch(fullSearchItems)); if (!propagated) { try { @@ -126,8 +144,19 @@ public void run() { } if (!Objects.equals(group.personalNote, personalNote)) { + List fullSearchItems = new ArrayList<>(); + for (Group2MemberDao.Group2MemberOrPending group2MemberOrPending : db.group2MemberDao().getGroupMembersAndPendingSync(bytesOwnedIdentity, bytesGroupIdentifier)) { + if (group2MemberOrPending.contact != null) { + fullSearchItems.add(group2MemberOrPending.contact.fullSearchDisplayName); + } else { + try { + JsonIdentityDetails jsonIdentityDetails = AppSingleton.getJsonObjectMapper().readValue(group2MemberOrPending.identityDetails, JsonIdentityDetails.class); + fullSearchItems.add(StringUtils.unAccent(jsonIdentityDetails.formatDisplayName(JsonIdentityDetails.FORMAT_STRING_FOR_SEARCH, false))); + } catch (Exception ignored) {} + } + } group.personalNote = personalNote; - db.group2Dao().updatePersonalNote(group.bytesOwnedIdentity, group.bytesGroupIdentifier, group.personalNote); + db.group2Dao().updatePersonalNote(group.bytesOwnedIdentity, group.bytesGroupIdentifier, group.personalNote, group.computeFullSearch(fullSearchItems)); if (!propagated) { try { diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/backup/RestoreAppDataFromBackupTask.java b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/backup/RestoreAppDataFromBackupTask.java index 93536f19..9396c7bb 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/backup/RestoreAppDataFromBackupTask.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/databases/tasks/backup/RestoreAppDataFromBackupTask.java @@ -26,6 +26,7 @@ import java.util.concurrent.Callable; import io.olvid.messenger.AppSingleton; +import io.olvid.messenger.customClasses.StringUtils; import io.olvid.messenger.databases.AppDatabase; import io.olvid.messenger.databases.entity.Contact; import io.olvid.messenger.databases.entity.Discussion; @@ -92,8 +93,8 @@ public Boolean call() { } if (contactPojo.personal_note != null) { - contact.personalNote = contactPojo.personal_note; - db.contactDao().updatePersonalNote(contact.bytesOwnedIdentity, contact.bytesContactIdentity, contact.personalNote); + contact.setPersonalNote(contactPojo.personal_note); + db.contactDao().updatePersonalNote(contact.bytesOwnedIdentity, contact.bytesContactIdentity, contact.personalNote, contact.fullSearchDisplayName); } if (contactPojo.discussion_customization != null) { @@ -221,13 +222,15 @@ public Boolean call() { } else { // group is joined if (groupPojo.custom_name != null) { + group.fullSearchField = group.fullSearchField + " " + StringUtils.unAccent(groupPojo.custom_name); group.customName = groupPojo.custom_name; - db.groupDao().updateCustomName(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.customName); + db.groupDao().updateCustomName(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.customName, group.fullSearchField); } if (groupPojo.personal_note != null) { + group.fullSearchField = group.fullSearchField + " " + StringUtils.unAccent(groupPojo.personal_note); group.personalNote = groupPojo.personal_note; - db.groupDao().updatePersonalNote(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.personalNote); + db.groupDao().updatePersonalNote(group.bytesOwnedIdentity, group.bytesGroupOwnerAndUid, group.personalNote, group.fullSearchField); } if (groupPojo.discussion_customization != null) { @@ -268,13 +271,15 @@ public Boolean call() { Group2 group2 = db.group2Dao().get(ownedIdentityPojo.owned_identity, group2Pojo.group_identifier); if (group2 != null) { if (group2Pojo.custom_name != null) { + group2.fullSearchField = group2.fullSearchField + " " + StringUtils.unAccent(group2Pojo.custom_name); group2.customName = group2Pojo.custom_name; - db.group2Dao().updateCustomName(group2.bytesOwnedIdentity, group2.bytesGroupIdentifier, group2.customName); + db.group2Dao().updateCustomName(group2.bytesOwnedIdentity, group2.bytesGroupIdentifier, group2.customName, group2.fullSearchField); } if (group2Pojo.personal_note != null) { + group2.fullSearchField = group2.fullSearchField + " " + StringUtils.unAccent(group2Pojo.personal_note); group2.personalNote = group2Pojo.personal_note; - db.group2Dao().updatePersonalNote(group2.bytesOwnedIdentity, group2.bytesGroupIdentifier, group2.personalNote); + db.group2Dao().updatePersonalNote(group2.bytesOwnedIdentity, group2.bytesGroupIdentifier, group2.personalNote, group2.fullSearchField); } if (group2Pojo.discussion_customization != null) { diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/designsystem/theme/Typography.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/designsystem/theme/Typography.kt index 8108f0cc..28db2c5b 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/designsystem/theme/Typography.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/designsystem/theme/Typography.kt @@ -23,6 +23,7 @@ import androidx.compose.material.Typography import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextDirection import androidx.compose.ui.unit.sp val OlvidTypography = Typography( @@ -30,31 +31,37 @@ val OlvidTypography = Typography( h1 = TextStyle( fontWeight = FontWeight.Normal, fontSize = 24.sp, - lineHeight = 29.sp + lineHeight = 29.sp, + textDirection = TextDirection.ContentOrLtr ), h2 = TextStyle( fontWeight = FontWeight.Bold, fontSize = 20.sp, - lineHeight = 24.sp + lineHeight = 24.sp, + textDirection = TextDirection.ContentOrLtr ), h3 = TextStyle( fontWeight = FontWeight.Medium, fontSize = 16.sp, lineHeight = 20.sp, + textDirection = TextDirection.ContentOrLtr ), body1 = TextStyle( fontWeight = FontWeight.Normal, fontSize = 16.sp, lineHeight = 20.sp, + textDirection = TextDirection.ContentOrLtr ), body2 = TextStyle( fontWeight = FontWeight.Normal, fontSize = 14.sp, - lineHeight = 17.sp + lineHeight = 17.sp, + textDirection = TextDirection.ContentOrLtr ), subtitle1 = TextStyle( fontWeight = FontWeight.Normal, fontSize = 12.sp, - lineHeight = 15.sp + lineHeight = 15.sp, + textDirection = TextDirection.ContentOrLtr ) ) diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/DiscussionActivity.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/DiscussionActivity.kt index 493968ed..4c0b7c48 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/DiscussionActivity.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/DiscussionActivity.kt @@ -855,6 +855,7 @@ class DiscussionActivity : LockableActivity(), OnClickListener, AttachmentLongCl linkPreviewViewModel = linkPreviewViewModel, messageExpiration = messageExpiration, discussionViewModel = discussionViewModel, + discussionSearch = discussionSearch, audioAttachmentServiceBinding = audioAttachmentServiceBinding, openDiscussionDetailsCallback = { toolbarClickedCallback?.run() diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/DiscussionSearch.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/DiscussionSearch.kt index b2c3751e..8db98a40 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/DiscussionSearch.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/DiscussionSearch.kt @@ -24,6 +24,8 @@ import android.view.Menu import android.view.MenuItem import android.view.MenuItem.OnActionExpandListener import android.view.MenuItem.OnMenuItemClickListener +import androidx.activity.ComponentActivity +import androidx.activity.viewModels import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView.OnQueryTextListener import androidx.compose.foundation.lazy.LazyListState @@ -36,6 +38,7 @@ import androidx.compose.ui.text.SpanStyle import androidx.core.content.ContextCompat import androidx.core.view.inputmethod.EditorInfoCompat import androidx.fragment.app.FragmentActivity +import androidx.lifecycle.ViewModel import io.olvid.messenger.App import io.olvid.messenger.R import io.olvid.messenger.customClasses.StringUtils @@ -57,9 +60,9 @@ class DiscussionSearch( private var matches: List = emptyList() var scrollTo: ((messageId: Long) -> Unit)? = null var lazyListState: LazyListState? = null + val viewModel: SearchViewModel by activity.viewModels() - companion object { - + class SearchViewModel: ViewModel() { var filterRegexes by mutableStateOf?>(null) fun highlight(context: Context, content: AnnotatedString): AnnotatedString { @@ -143,7 +146,7 @@ class DiscussionSearch( @Synchronized private fun filter(filterString: String?, firstVisibleMessageId: Long) { currentPosition = 0 - filterRegexes = filterString + viewModel.filterRegexes = filterString ?.trim() ?.split("\\s+".toRegex()) ?.filter { it.isNotEmpty() } diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/linkpreview/LinkPreview.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/linkpreview/LinkPreview.kt index 965b80e3..f7f63d50 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/linkpreview/LinkPreview.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/linkpreview/LinkPreview.kt @@ -84,27 +84,28 @@ fun LinkPreview( .observeAsState() linkPreviewFyle?.let { fyleAndStatus -> if (fyleAndStatus.fyle.isComplete) { - LaunchedEffect(fyleAndStatus.fyle.id) { - linkPreviewViewModel?.linkPreviewLoader( - fyleAndStatus.fyle, - fyleAndStatus.fyleMessageJoinWithStatus.fileName, - fyleAndStatus.fyleMessageJoinWithStatus.messageId - ) { - opengraph = it - it?.getSafeUri()?.let { uri -> - discussionViewModel?.messageLinkPreviewUrlCache?.put( - message.id, - uri.toString() - ) + LaunchedEffect(fyleAndStatus.fyle.id, message.messageType) { + if (message.messageType != Message.TYPE_INBOUND_EPHEMERAL_MESSAGE && message.wipeStatus != Message.WIPE_STATUS_REMOTE_DELETED && message.wipeStatus != Message.WIPE_STATUS_WIPED) { + linkPreviewViewModel?.linkPreviewLoader( + fyleAndStatus.fyle, + fyleAndStatus.fyleMessageJoinWithStatus.fileName, + fyleAndStatus.fyleMessageJoinWithStatus.messageId + ) { + if (message.wipeStatus != Message.WIPE_STATUS_REMOTE_DELETED && message.wipeStatus != Message.WIPE_STATUS_WIPED) { + opengraph = it + it?.getSafeUri()?.let { uri -> + discussionViewModel?.messageLinkPreviewUrlCache?.put( + message.id, + uri.toString() + ) + } + } } } } } } - } else if (message.messageType == Message.TYPE_INBOUND_MESSAGE && SettingsActivity.isLinkPreviewInbound( - LocalContext.current - ) - ) { + } else if (message.messageType == Message.TYPE_INBOUND_MESSAGE && SettingsActivity.isLinkPreviewInbound(LocalContext.current)) { val density = LocalDensity.current LaunchedEffect(message.id) { val size = with(density) { @@ -120,6 +121,11 @@ fun LinkPreview( } } } + LaunchedEffect(message.wipeStatus) { + if (message.wipeStatus == Message.WIPE_STATUS_REMOTE_DELETED || message.wipeStatus == Message.WIPE_STATUS_WIPED) { + opengraph = null + } + } opengraph?.let { if (!it.isEmpty()) { LinkPreviewContent( diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/message/Messages.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/message/Messages.kt index 9f46b7c5..2750172f 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/message/Messages.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/discussion/message/Messages.kt @@ -99,6 +99,7 @@ import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.style.TextDirection import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewLightDark @@ -252,6 +253,7 @@ fun Message( linkPreviewViewModel: LinkPreviewViewModel? = null, messageExpiration: MessageExpiration? = null, discussionViewModel: DiscussionViewModel? = null, + discussionSearch: DiscussionSearch? = null, audioAttachmentServiceBinding: AudioAttachmentServiceBinding?, openDiscussionDetailsCallback: (() -> Unit)? = null, openOnClick: Boolean = true, @@ -444,6 +446,7 @@ fun Message( onLongClick = if (message.isLocationMessage) onLocationLongClick else onLongClick, onCallBackButtonClicked = onCallBackButtonClicked, discussionViewModel = discussionViewModel, + discussionSearch = discussionSearch, scale = scale, openDiscussionDetailsCallback = openDiscussionDetailsCallback, messageBubbleInteractionSource = interactionSource @@ -700,7 +703,9 @@ private fun Replied( .background(color = colorResource(id = R.color.almostWhite)) .padding(4.dp) ) { - Text(text = message.jsonMessage?.jsonReply?.senderIdentifier?.let { + Text( + modifier = Modifier.fillMaxWidth(), + text = message.jsonMessage?.jsonReply?.senderIdentifier?.let { AppSingleton.getContactCustomDisplayName(it) } ?: stringResource(id = R.string.text_deleted_contact), style = OlvidTypography.body2, @@ -731,6 +736,7 @@ private fun Replied( ) ) ), + style = OlvidTypography.body2, color = colorResource(id = R.color.greyTint), maxLines = 3, overflow = TextOverflow.Ellipsis, @@ -791,6 +797,7 @@ fun MessageBody( onCallBackButtonClicked: (callLogId: Long) -> Unit, scale: Float, discussionViewModel: DiscussionViewModel? = null, + discussionSearch: DiscussionSearch? = null, openDiscussionDetailsCallback: (() -> Unit)? = null, messageBubbleInteractionSource: MutableInteractionSource, ) { @@ -1043,12 +1050,13 @@ fun MessageBody( val linkUrl by remember { derivedStateOf { discussionViewModel?.messageLinkPreviewUrlCache?.get(message.id) } } - val text = remember(linkUrl, DiscussionSearch.filterRegexes, message.contentBody) { + val text = remember(linkUrl, discussionSearch?.viewModel?.filterRegexes, message.contentBody) { getAnnotatedStringContent( context, message, linkUrl, - discussionViewModel?.discussion?.value?.bytesOwnedIdentity + discussionViewModel?.discussion?.value?.bytesOwnedIdentity, + discussionSearch?.viewModel ) } val uriHandler = LocalUriHandler.current @@ -1203,7 +1211,8 @@ fun getAnnotatedStringContent( context: Context, message: Message, linkPreviewUrl: String? = null, - bytesOwnedIdentity: ByteArray? = null + bytesOwnedIdentity: ByteArray? = null, + discussionSearchViewModel: DiscussionSearch.SearchViewModel?, ): AnnotatedString { return buildAnnotatedString { var stringContent = message.getStringContent(context) @@ -1252,10 +1261,14 @@ fun getAnnotatedStringContent( ) } }.run { - DiscussionSearch.highlight( - content = this, - context = context - ) + if (message.messageType == Message.TYPE_INBOUND_MESSAGE || message.messageType == Message.TYPE_OUTBOUND_MESSAGE) { + discussionSearchViewModel?.highlight( + content = this, + context = context + ) ?: this + } else { + this + } } } diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/main/contacts/ContactListScreen.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/main/contacts/ContactListScreen.kt index 0a2f57fb..fbe03f93 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/main/contacts/ContactListScreen.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/main/contacts/ContactListScreen.kt @@ -81,9 +81,6 @@ import androidx.compose.ui.unit.dp import com.google.accompanist.themeadapter.appcompat.AppCompatTheme import io.olvid.messenger.AppSingleton import io.olvid.messenger.R -import io.olvid.messenger.R.color -import io.olvid.messenger.R.drawable -import io.olvid.messenger.R.string import io.olvid.messenger.customClasses.StringUtils import io.olvid.messenger.customClasses.ifNull import io.olvid.messenger.databases.entity.Contact @@ -100,7 +97,7 @@ import kotlinx.coroutines.launch data class ContactFilterTab(val label: String, val filter: (ContactOrKeycloakDetails) -> Boolean) -@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class) +@OptIn(ExperimentalMaterialApi::class) @Composable fun ContactListScreen( modifier: Modifier = Modifier.fillMaxSize(), @@ -304,20 +301,20 @@ fun ContactListScreen( ) { if (contactListViewModel.isFiltering()) MainScreenEmptyList( - icon = drawable.ic_contacts_filter, - title = string.explanation_no_contact_match_filter, + icon = R.drawable.ic_contacts_filter, + title = R.string.explanation_no_contact_match_filter, subtitle = null ) else MainScreenEmptyList( - icon = drawable.tab_contacts, + icon = R.drawable.tab_contacts, title = when (page) { - 0 -> string.explanation_empty_contact_list + 0 -> R.string.explanation_empty_contact_list 1 -> R.string.explanation_empty_other_contact_list else -> R.string.explanation_empty_directory }, subtitle = when (page) { - 0 -> string.explanation_empty_contact_list_sub + 0 -> R.string.explanation_empty_contact_list_sub 1 -> R.string.explanation_empty_other_contact_list_sub else -> null } @@ -393,7 +390,7 @@ private fun Header( modifier = Modifier .padding(4.dp) .size(16.dp), - color = colorResource(id = color.olvid_gradient_light), + color = colorResource(id = R.color.olvid_gradient_light), strokeWidth = 2.dp ) }) { @@ -407,7 +404,7 @@ private fun Header( BadgedBox(badge = { Badge( modifier = Modifier.padding(4.dp), - backgroundColor = colorResource(id = color.olvid_gradient_light), + backgroundColor = colorResource(id = R.color.olvid_gradient_light), ) { Text( color = colorResource(id = R.color.almostWhite), @@ -447,16 +444,16 @@ private fun Contact( title = contactOrKeycloakDetails.getAnnotatedName() .highlight( SpanStyle( - background = colorResource(id = color.searchHighlightColor), - color = colorResource(id = color.black) + background = colorResource(id = R.color.searchHighlightColor), + color = colorResource(id = R.color.black) ), contactListViewModel.filterPatterns ), body = contactOrKeycloakDetails.getAnnotatedDescription() ?.highlight( SpanStyle( - background = colorResource(id = color.searchHighlightColor), - color = colorResource(id = color.black) + background = colorResource(id = R.color.searchHighlightColor), + color = colorResource(id = R.color.black) ), contactListViewModel.filterPatterns ), @@ -548,11 +545,11 @@ private fun KeycloakSearching() { .padding(top = 8.dp, start = 8.dp, end = 8.dp, bottom = 16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - CircularProgressIndicator(color = colorResource(id = color.olvid_gradient_light)) + CircularProgressIndicator(color = colorResource(id = R.color.olvid_gradient_light)) Text( - text = stringResource(id = string.label_searching_company_directory), + text = stringResource(id = R.string.label_searching_company_directory), color = colorResource( - id = color.grey + id = R.color.grey ) ) } @@ -576,7 +573,7 @@ private fun KeycloakMissingCount(missingResults: Int?) { .clip(RoundedCornerShape(8.dp)) .background( color = colorResource( - id = color.lighterGrey + id = R.color.lighterGrey ) ) @@ -592,8 +589,8 @@ private fun KeycloakMissingCount(missingResults: Int?) { missingResults ) } - ?: stringResource(id = string.text_keycloak_missing_some_search_result), - color = colorResource(id = color.grey), + ?: stringResource(id = R.string.text_keycloak_missing_some_search_result), + color = colorResource(id = R.color.grey), textAlign = TextAlign.Center, style = OlvidTypography.body2, fontStyle = FontStyle.Italic diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/main/search/GlobalSearchScreen.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/main/search/GlobalSearchScreen.kt index 2f930dbd..41c306fd 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/main/search/GlobalSearchScreen.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/main/search/GlobalSearchScreen.kt @@ -40,8 +40,12 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material.DropdownMenu import androidx.compose.material.LinearProgressIndicator +import androidx.compose.material.ScrollableTabRow +import androidx.compose.material.TabRow import androidx.compose.material.Text import androidx.compose.material3.DropdownMenuItem import androidx.compose.runtime.Composable @@ -49,9 +53,11 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.colorResource @@ -60,6 +66,12 @@ import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.paging.LoadState +import androidx.paging.compose.LazyPagingItems +import androidx.paging.compose.collectAsLazyPagingItems +import androidx.paging.compose.itemContentType +import androidx.paging.compose.itemKey +import io.olvid.engine.Logger import io.olvid.engine.engine.types.JsonIdentityDetails import io.olvid.messenger.App import io.olvid.messenger.AppSingleton @@ -79,218 +91,337 @@ import io.olvid.messenger.discussion.linkpreview.LinkPreviewViewModel import io.olvid.messenger.discussion.linkpreview.OpenGraph import io.olvid.messenger.main.InitialView import io.olvid.messenger.main.MainScreenEmptyList +import io.olvid.messenger.main.contacts.CustomTab import io.olvid.messenger.main.discussions.getAnnotatedBody import io.olvid.messenger.main.discussions.getAnnotatedTitle import io.olvid.messenger.settings.SettingsActivity import io.olvid.messenger.viewModels.FilteredDiscussionListViewModel.SearchableDiscussion +import kotlinx.coroutines.launch + +fun LazyPagingItems<*>?.isLoading() = (this?.loadState?.refresh == LoadState.Loading) || (this?.loadState?.append == LoadState.Loading) @Composable fun GlobalSearchScreen( globalSearchViewModel: GlobalSearchViewModel, linkPreviewViewModel: LinkPreviewViewModel, - bookmarks : List? = null + bookmarks: List? = null ) { val context = LocalContext.current + val coroutineScope = rememberCoroutineScope() val keyboardController = LocalSoftwareKeyboardController.current - val scrollState = rememberLazyListState() - LaunchedEffect(scrollState.isScrollInProgress) { - if (scrollState.isScrollInProgress) { - keyboardController?.hide() - } - } - if (globalSearchViewModel.searching || globalSearchViewModel.noResults.value.not() || bookmarks.isNullOrEmpty().not()) { - Box( - modifier = Modifier - .fillMaxSize() - .background(colorResource(id = R.color.almostWhite)), - contentAlignment = Alignment.TopStart - ) { - if (globalSearchViewModel.searching) { - LinearProgressIndicator(modifier = Modifier.fillMaxWidth()) - } - LazyColumn( - state = scrollState, - contentPadding = PaddingValues(bottom = 80.dp) + + val messages = globalSearchViewModel.messagesFound?.collectAsLazyPagingItems() + val attachments = globalSearchViewModel.fylesFound?.collectAsLazyPagingItems() + val pages = listOf( + // first -> label, second -> hasResults + R.string.global_search_result_contacts to { + globalSearchViewModel.otherDiscussionsFound.isNullOrEmpty() + .not() || globalSearchViewModel.contactsFound.isNullOrEmpty().not() + }, + R.string.global_search_result_groups to { + globalSearchViewModel.groupsFound.isNullOrEmpty().not() + }, + R.string.global_search_result_messages to { (messages?.itemCount ?: 0) > 0 }, + R.string.global_search_result_attachments to { (attachments?.itemCount ?: 0) > 0 }, + ) + + val pagerState = rememberPagerState { pages.size } + var loading = globalSearchViewModel.searching || messages.isLoading() || attachments.isLoading() + + Column(modifier = Modifier.fillMaxSize()) { + if (bookmarks != null) { + Box( + modifier = Modifier + .fillMaxSize() + .background(colorResource(id = R.color.almostWhite)), + contentAlignment = Alignment.TopStart ) { - globalSearchViewModel.contactsFound?.takeIf { it.isNotEmpty() }?.let { - item { - Text( - modifier = Modifier.padding(8.dp), - text = stringResource(id = R.string.global_search_result_contacts), - style = OlvidTypography.h2 - ) - } - items(it) { contact -> - SearchResult( - contact = contact, - globalSearchViewModel = globalSearchViewModel - ) - } - item { - Spacer(modifier = Modifier.height(8.dp)) + bookmarks.takeIf { it.isNotEmpty() }?.let { + LazyColumn( + contentPadding = PaddingValues(bottom = 80.dp) + ) { + items(it) { message -> + SearchResult( + discussionAndMessage = message, + globalSearchViewModel = globalSearchViewModel, + menuItems = listOf( + stringResource(id = R.string.menu_action_unbookmark) to { + App.runThread { + AppDatabase.getInstance().messageDao() + .updateBookmarked(message.message.id, false) + AppSingleton.getBytesCurrentIdentity() + ?.let { bytesOwnedIdentity -> + PropagateBookmarkedMessageChangeTask( + bytesOwnedIdentity, + message.message, + false + ).run() + } + } + } + ) + ) + } } + } ?: run { + NoBookmarksFound() } - globalSearchViewModel.groupsFound?.takeIf { it.isNotEmpty() }?.let { - item { - Text( - modifier = Modifier.padding(8.dp), - text = stringResource(id = R.string.global_search_result_groups), - style = OlvidTypography.h2 - ) - } - items(it) { searchableDiscussion -> - SearchResult( - searchableDiscussion = searchableDiscussion, - globalSearchViewModel = globalSearchViewModel - ) - } - item { - Spacer(modifier = Modifier.height(8.dp)) - } + } + } else { + var neverSwitchedTab by remember { mutableStateOf(true) } + + LaunchedEffect(pagerState.isScrollInProgress) { + if (pagerState.isScrollInProgress) { + neverSwitchedTab = false } + } - globalSearchViewModel.otherDiscussionsFound?.takeIf { it.isNotEmpty() }?.let { - item { - Text( - modifier = Modifier.padding(8.dp), - text = stringResource(id = R.string.global_search_result_other_discussions), - style = OlvidTypography.h2 - ) - } - items(it) { searchableDiscussion -> - SearchResult( - searchableDiscussion = searchableDiscussion, - globalSearchViewModel = globalSearchViewModel - ) - } - item { - Spacer(modifier = Modifier.height(8.dp)) + LaunchedEffect(loading) { + if (!loading && neverSwitchedTab) { + if (!globalSearchViewModel.otherDiscussionsFound.isNullOrEmpty() || !globalSearchViewModel.contactsFound.isNullOrEmpty()) { + pagerState.requestScrollToPage(0) + } else if (!globalSearchViewModel.groupsFound.isNullOrEmpty()) { + pagerState.requestScrollToPage(1) + } else if ((messages?.itemCount ?: 0) > 0) { + pagerState.requestScrollToPage(2) + } else if ((attachments?.itemCount ?: 0) > 0) { + pagerState.requestScrollToPage(3) } } + } - bookmarks?.takeIf { it.isNotEmpty() }?.let { - items(it) { message -> - SearchResult( - discussionAndMessage = message, - globalSearchViewModel = globalSearchViewModel, - menuItems = listOf( - stringResource(id = R.string.menu_action_unbookmark) to { - App.runThread { - AppDatabase.getInstance().messageDao().updateBookmarked(message.message.id, false) - AppSingleton.getBytesCurrentIdentity()?.let { bytesOwnedIdentity -> - PropagateBookmarkedMessageChangeTask(bytesOwnedIdentity, message.message, false).run() - } - } + Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.TopStart) { + ScrollableTabRow( + selectedTabIndex = pagerState.currentPage, + backgroundColor = colorResource(id = R.color.almostWhite), + contentColor = colorResource(id = R.color.almostBlack), + edgePadding = 0.dp + ) { + pages.forEachIndexed { index, page -> + CustomTab( + selected = pagerState.currentPage == index, + horizontalTextPadding = 8.dp, + onClick = { + coroutineScope.launch { + pagerState.animateScrollToPage(index) } - ) + }, + text = { + Text( + modifier = Modifier.alpha(if (page.second()) 1f else .3f), + text = stringResource(id = page.first), + softWrap = false, + ) + } ) } - item { - Spacer(modifier = Modifier.height(8.dp)) - } } + if (loading) { + LinearProgressIndicator(modifier = Modifier.fillMaxWidth()) + } + } - globalSearchViewModel.messagesFound?.takeIf { it.isNotEmpty() }?.let { - item { - Text( - modifier = Modifier.padding(8.dp), - text = stringResource(id = R.string.global_search_result_messages) + (globalSearchViewModel.messageLimitReachedCount?.let { count -> " (${it.size}/$count)" } ?: " (${it.size})"), - style = OlvidTypography.h2 - ) - } - items(it) { discussionAndMessage -> - SearchResult( - discussionAndMessage = discussionAndMessage, - globalSearchViewModel = globalSearchViewModel - ) - } - item { - Spacer(modifier = Modifier.height(8.dp)) + HorizontalPager( + state = pagerState + ) { page -> + val lazyListState = rememberLazyListState() + LaunchedEffect(lazyListState.isScrollInProgress) { + if (lazyListState.isScrollInProgress) { + keyboardController?.hide() } } - globalSearchViewModel.fylesFound?.takeIf { it.isNotEmpty() }?.let { - item { - Text( - modifier = Modifier.padding(8.dp), - text = stringResource(id = R.string.global_search_result_attachments) + (globalSearchViewModel.attachmentLimitReachedCount?.let { _ -> " (${it.size}+)" } ?: " (${it.size})"), - style = OlvidTypography.h2 - ) - } - items(it) { fyle -> - Column(modifier = Modifier.padding(bottom = 4.dp)) { - Row( - modifier = Modifier.padding(horizontal = 12.dp), - verticalAlignment = Alignment.CenterVertically - ) { - InitialView( - modifier = Modifier - .padding(end = 8.dp) - .requiredSize(20.dp), - initialViewSetup = { view -> - view.setFromCache(fyle.message.senderIdentifier) - }, - ) - Text( - modifier = Modifier.weight(1f), - text = AppSingleton.getContactCustomDisplayName(fyle.message.senderIdentifier) - ?: stringResource(id = R.string.text_deleted_contact), - style = OlvidTypography.body2, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - fontWeight = FontWeight.Medium - ) - Spacer(Modifier.width(8.dp)) - Text( - text = StringUtils.getNiceDateString( - context, - fyle.message.timestamp - ).toString(), - style = OlvidTypography.body2, - fontWeight = FontWeight.Medium - ) + Box( + modifier = Modifier + .fillMaxSize() + .background(colorResource(id = R.color.almostWhite)), + contentAlignment = Alignment.TopStart + ) { + when (page) { + 0 -> { + if (globalSearchViewModel.otherDiscussionsFound.isNullOrEmpty() && globalSearchViewModel.contactsFound.isNullOrEmpty()) { + if (!loading) { + NoResultsFound(0) + } + } else { + LazyColumn( + state = lazyListState, + contentPadding = PaddingValues(bottom = 80.dp) + ) { + globalSearchViewModel.contactsFound?.takeIf { it.isNotEmpty() } + ?.let { + items(it) { contact -> + SearchResult( + contact = contact, + globalSearchViewModel = globalSearchViewModel + ) + } + item { + Spacer(modifier = Modifier.height(8.dp)) + } + } + globalSearchViewModel.otherDiscussionsFound?.takeIf { it.isNotEmpty() } + ?.let { + item { + Text( + modifier = Modifier.padding(8.dp), + text = stringResource(id = R.string.global_search_result_other_discussions), + style = OlvidTypography.h2 + ) + } + items(it) { searchableDiscussion -> + SearchResult( + searchableDiscussion = searchableDiscussion, + globalSearchViewModel = globalSearchViewModel + ) + } + } + } + } + } + + 1 -> { + globalSearchViewModel.groupsFound?.takeIf { it.isNotEmpty() }?.let { + LazyColumn( + state = lazyListState, + contentPadding = PaddingValues(bottom = 80.dp) + ) { + items(it) { searchableDiscussion -> + SearchResult( + searchableDiscussion = searchableDiscussion, + globalSearchViewModel = globalSearchViewModel + ) + } + } + } ?: run { + if (!loading) { + NoResultsFound(1) + } } - when (fyle.fyleAndStatus.fyleMessageJoinWithStatus.nonNullMimeType) { - OpenGraph.MIME_TYPE -> { - LinkListItem( - fyleAndStatus = fyle.fyleAndStatus, - onClick = { - fyle.message.goto(context) - }, - linkPreviewViewModel = linkPreviewViewModel, - globalSearchViewModel = globalSearchViewModel - ) + } + + 2 -> { + messages?.takeIf { it.itemCount > 0 }?.let { + LazyColumn( + state = lazyListState, + contentPadding = PaddingValues(bottom = 80.dp) + ) { + items( + count = messages.itemCount, + key = messages.itemKey { it.message.id }, + contentType = messages.itemContentType { it.message.messageType } + ) { index -> + val discussionAndMessage = messages[index] + discussionAndMessage?.let { + SearchResult( + discussionAndMessage = it, + globalSearchViewModel = globalSearchViewModel + ) + } + } + } + } ?: run { + if (!loading) { + NoResultsFound(2) } + } + } - else -> { - FyleListItem(fyleAndStatus = fyle.fyleAndStatus, - fileName = globalSearchViewModel.highlight( - content = fyle.fyleAndStatus.fyleMessageJoinWithStatus.fileName - ), - extraHorizontalPadding = 4.dp, - onClick = { fyle.message.goto(context) }, - onLongClick = { - if (PreviewUtils.mimeTypeIsSupportedImageOrVideo( - PreviewUtils.getNonNullMimeType( - fyle.fyleAndStatus.fyleMessageJoinWithStatus.mimeType, - fyle.fyleAndStatus.fyleMessageJoinWithStatus.fileName - ) - ) && SettingsActivity.useInternalImageViewer() - ) { - App.openMessageGalleryActivity( - context, - fyle.fyleAndStatus.fyleMessageJoinWithStatus.messageId, - fyle.fyleAndStatus.fyleMessageJoinWithStatus.fyleId - ) - } else { - App.openFyleInExternalViewer( - context, - fyle.fyleAndStatus, + 3 -> { + attachments?.takeIf { it.itemCount > 0 }?.let { + LazyColumn( + state = lazyListState, + contentPadding = PaddingValues(top = 8.dp, bottom = 80.dp) + ) { + items( + count = attachments.itemCount, + key = attachments.itemKey { "${it.fyleAndStatus.fyleMessageJoinWithStatus.messageId}-${it.fyleAndStatus.fyleMessageJoinWithStatus.fyleId}" } + ) { index -> + attachments[index]?.let { fyle -> + Column(modifier = Modifier.padding(bottom = 4.dp)) { + Row( + modifier = Modifier.padding(horizontal = 12.dp), + verticalAlignment = Alignment.CenterVertically ) { - fyle.fyleAndStatus.fyleMessageJoinWithStatus.markAsOpened() + InitialView( + modifier = Modifier + .padding(end = 8.dp) + .requiredSize(20.dp), + initialViewSetup = { view -> + view.setFromCache(fyle.message.senderIdentifier) + }, + ) + Text( + modifier = Modifier.weight(1f), + text = AppSingleton.getContactCustomDisplayName( + fyle.message.senderIdentifier + ) + ?: stringResource(id = R.string.text_deleted_contact), + style = OlvidTypography.body2, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + fontWeight = FontWeight.Medium + ) + Spacer(Modifier.width(8.dp)) + Text( + text = StringUtils.getNiceDateString( + context, + fyle.message.timestamp + ).toString(), + style = OlvidTypography.body2, + fontWeight = FontWeight.Medium + ) + } + when (fyle.fyleAndStatus.fyleMessageJoinWithStatus.nonNullMimeType) { + OpenGraph.MIME_TYPE -> { + LinkListItem( + fyleAndStatus = fyle.fyleAndStatus, + onClick = { + fyle.message.goto(context) + }, + linkPreviewViewModel = linkPreviewViewModel, + globalSearchViewModel = globalSearchViewModel + ) + } + + else -> { + FyleListItem(fyleAndStatus = fyle.fyleAndStatus, + fileName = globalSearchViewModel.highlight( + content = fyle.fyleAndStatus.fyleMessageJoinWithStatus.fileName + ), + extraHorizontalPadding = 4.dp, + onClick = { fyle.message.goto(context) }, + onLongClick = { + if (PreviewUtils.mimeTypeIsSupportedImageOrVideo( + PreviewUtils.getNonNullMimeType( + fyle.fyleAndStatus.fyleMessageJoinWithStatus.mimeType, + fyle.fyleAndStatus.fyleMessageJoinWithStatus.fileName + ) + ) && SettingsActivity.useInternalImageViewer() + ) { + App.openMessageGalleryActivity( + context, + fyle.fyleAndStatus.fyleMessageJoinWithStatus.messageId, + fyle.fyleAndStatus.fyleMessageJoinWithStatus.fyleId + ) + } else { + App.openFyleInExternalViewer( + context, + fyle.fyleAndStatus, + ) { + fyle.fyleAndStatus.fyleMessageJoinWithStatus.markAsOpened() + } + } + } + ) + } } } } - ) + } + } + } ?: run { + if (!loading) { + NoResultsFound(3) } } } @@ -298,20 +429,43 @@ fun GlobalSearchScreen( } } } - } else { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - if (bookmarks != null) { - MainScreenEmptyList( - icon = R.drawable.ic_star, - title = R.string.explanation_empty_bookmarks - ) - } else { - MainScreenEmptyList( - icon = R.drawable.ic_search_anything, - title = R.string.explanation_empty_global_search - ) + } +} + +@Composable +private fun NoResultsFound(tabIndex: Int = -1) { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + MainScreenEmptyList( + icon = when (tabIndex) { + 0,1 -> R.drawable.ic_contacts_filter + else -> R.drawable.ic_search_anything + }, + title = when (tabIndex) { + 0 -> R.string.explanation_no_contact_match_filter + 1 -> R.string.explanation_no_group_match_filter + 2 -> R.string.explanation_no_message_found + 3 -> R.string.explanation_no_attachment_found + else -> R.string.explanation_empty_global_search } - } + ) + } +} + +@Composable +private fun NoBookmarksFound() { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + MainScreenEmptyList( + icon = R.drawable.ic_star, + title = R.string.explanation_empty_bookmarks + ) } } @@ -425,12 +579,17 @@ private fun SearchResult( ) { // Title Text( + modifier = Modifier.fillMaxWidth(), text = searchableDiscussion?.title?.let { globalSearchViewModel.highlight(it) } - ?: contact?.let { AnnotatedString(contact.customDisplayName ?: contact.getIdentityDetails() - ?.formatFirstAndLastName( - SettingsActivity.getContactDisplayNameFormat(), - SettingsActivity.getUppercaseLastName() - ) ?: contact.getCustomDisplayName()) }?.let { globalSearchViewModel.highlight(it) } + ?: contact?.let { + AnnotatedString( + contact.customDisplayName ?: contact.getIdentityDetails() + ?.formatFirstAndLastName( + SettingsActivity.getContactDisplayNameFormat(), + SettingsActivity.getUppercaseLastName() + ) ?: contact.getCustomDisplayName() + ) + }?.let { globalSearchViewModel.highlight(it) } ?: discussionAndMessage?.discussion?.getAnnotatedTitle(context) ?: AnnotatedString(stringResource(id = R.string.text_deleted_contact)), color = colorResource(id = R.color.primary700), @@ -458,10 +617,15 @@ private fun SearchResult( )?.let { AnnotatedString(it) } } } - ?: discussionAndMessage?.discussion?.getAnnotatedBody(context, discussionAndMessage.message.apply { - contentBody = globalSearchViewModel.truncateMessageBody(body = discussionAndMessage.message.getStringContent(context)) - }))?.let { + ?: discussionAndMessage?.discussion?.getAnnotatedBody( + context, + discussionAndMessage.message.apply { + contentBody = globalSearchViewModel.truncateMessageBody( + body = discussionAndMessage.message.getStringContent(context) + ) + }))?.let { Text( + modifier = Modifier.fillMaxWidth(), text = globalSearchViewModel.highlight(it), color = colorResource(id = R.color.greyTint), style = OlvidTypography.body2, @@ -473,6 +637,7 @@ private fun SearchResult( discussionAndMessage?.message?.timestamp?.let { // Date Text( + modifier = Modifier.fillMaxWidth(), text = StringUtils.getLongNiceDateString(context, it) as String, color = colorResource(id = R.color.grey), style = OlvidTypography.subtitle1, diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/main/search/GlobalSearchViewModel.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/main/search/GlobalSearchViewModel.kt index 36b006aa..f9be05ab 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/main/search/GlobalSearchViewModel.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/main/search/GlobalSearchViewModel.kt @@ -28,7 +28,14 @@ import androidx.compose.ui.res.colorResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.SpanStyle import androidx.lifecycle.ViewModel -import io.olvid.messenger.App +import androidx.lifecycle.viewModelScope +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData +import androidx.paging.PagingSource +import androidx.paging.PagingSource.LoadResult.Page +import androidx.paging.PagingState +import androidx.paging.cachedIn import io.olvid.messenger.R import io.olvid.messenger.customClasses.StringUtils import io.olvid.messenger.customClasses.StringUtils2 @@ -40,50 +47,73 @@ import io.olvid.messenger.databases.dao.MessageDao.DiscussionAndMessage import io.olvid.messenger.databases.entity.Contact import io.olvid.messenger.databases.entity.Discussion import io.olvid.messenger.viewModels.FilteredDiscussionListViewModel.SearchableDiscussion +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch +import kotlinx.coroutines.supervisorScope class GlobalSearchViewModel : ViewModel() { companion object { const val MESSAGE_SEARCH_LIMIT: Int = 50 const val ATTACHMENT_SEARCH_LIMIT: Int = 30 } + var filter by mutableStateOf(null) private set private var filterRegexes by mutableStateOf?>(null) - var currentSearchTask by mutableStateOf(null) + private var searchJob by mutableStateOf(null) var contactsFound by mutableStateOf?>(null) var groupsFound by mutableStateOf?>(null) var otherDiscussionsFound by mutableStateOf?>(null) - var messagesFound by mutableStateOf?>(null) + var messagesFound by mutableStateOf>?>(null) var bookmarksFound by mutableStateOf?>(null) - var fylesFound by mutableStateOf?>(null) + var fylesFound by mutableStateOf>?>(null) - val searching by derivedStateOf { currentSearchTask != null } - var noResults = derivedStateOf { - contactsFound.isNullOrEmpty() && groupsFound.isNullOrEmpty() && otherDiscussionsFound.isNullOrEmpty() && messagesFound.isNullOrEmpty() && bookmarksFound.isNullOrEmpty() && fylesFound.isNullOrEmpty() - } - var messageLimitReachedCount : String? by mutableStateOf(null) - var attachmentLimitReachedCount : String? by mutableStateOf(null) + val searching by derivedStateOf { searchJob != null } fun search(bytesOwnedIdentity: ByteArray, text: String) { + searchJob?.cancel() + searchJob = null filter = text - currentSearchTask?.cancel() - currentSearchTask = SearchTask(bytesOwnedIdentity, text) + filterRegexes = filter + ?.trim() + ?.split("\\s+".toRegex()) + ?.filter { it.isNotEmpty() } + ?.map { Regex.fromLiteral(StringUtils.unAccent(it)) } + val tokenizedQuery = GlobalSearchTokenizer.tokenize(text).fullTextSearchEscape() + searchJob = viewModelScope.launch { + supervisorScope { + searchMessages(bytesOwnedIdentity, tokenizedQuery) + searchFyles(bytesOwnedIdentity, tokenizedQuery) + val deferredSearches = listOf( + async(Dispatchers.IO) { + searchContacts(bytesOwnedIdentity) + }, + async(Dispatchers.IO) { + searchDiscussions(bytesOwnedIdentity) + } + ) + runCatching { deferredSearches.awaitAll() } + searchJob = null + } + } } fun clear() { filter = null filterRegexes = null - currentSearchTask?.cancel() - currentSearchTask = null + searchJob?.cancel() + searchJob = null messagesFound = null bookmarksFound = null contactsFound = null groupsFound = null otherDiscussionsFound = null - messageLimitReachedCount = null - attachmentLimitReachedCount = null } @Composable @@ -92,7 +122,7 @@ class GlobalSearchViewModel : ViewModel() { } @Composable - fun highlight(content: AnnotatedString) : AnnotatedString { + fun highlight(content: AnnotatedString): AnnotatedString { return AnnotatedString.Builder(content).apply { filterRegexes?.let { StringUtils2.computeHighlightRanges(content.toString(), it).forEach { range -> @@ -111,7 +141,7 @@ class GlobalSearchViewModel : ViewModel() { @Composable fun truncateMessageBody(body: String): String { - filterRegexes?.let { + filterRegexes?.let { val ranges = StringUtils2.computeHighlightRanges(body, it) if (ranges.isNotEmpty()) { val pos = body.lastIndexOf("\n", ranges.first().first) @@ -125,106 +155,80 @@ class GlobalSearchViewModel : ViewModel() { return body } - inner class SearchTask(val bytesOwnedIdentity: ByteArray, val text: String) { - private var cancelled = false - - init { - App.runThread(this::run) - } - - fun run() { - filterRegexes = filter - ?.trim() - ?.split("\\s+".toRegex()) - ?.filter { it.isNotEmpty() } - ?.map { Regex.fromLiteral(StringUtils.unAccent(it)) } - - val contacts = AppDatabase.getInstance().contactDao() - .getAllForOwnedIdentitySync(bytesOwnedIdentity) - .filter { contact -> - filterRegexes?.all { it.containsMatchIn(contact.fullSearchDisplayName) } == true - } - if (cancelled) { - return - } - contactsFound = contacts - - val groups: MutableList = ArrayList() - val otherDiscussions: MutableList = ArrayList() - AppDatabase.getInstance().discussionDao() - .getAllForGlobalSearch(bytesOwnedIdentity) - .filter { !it.discussion.isNormalOrReadOnly || it.discussion.discussionType != Discussion.TYPE_CONTACT } // filter out normal contact discussions - .map { SearchableDiscussion(it) } - .forEach { searchableDiscussion -> - if (filterRegexes?.all { it.containsMatchIn(searchableDiscussion.patternMatchingField) } == true) { - if (searchableDiscussion.isGroupDiscussion) { - groups.add(searchableDiscussion) - } else { - otherDiscussions.add(searchableDiscussion) - } - } - } - if (cancelled) { - return - } - groupsFound = groups - otherDiscussionsFound = otherDiscussions - - val tokenizedQuery = GlobalSearchTokenizer.tokenize(text).fullTextSearchEscape() - val messages = AppDatabase.getInstance().messageDao() - .globalSearch(bytesOwnedIdentity, tokenizedQuery, MESSAGE_SEARCH_LIMIT) - if (cancelled) { - return + private fun searchContacts(bytesOwnedIdentity: ByteArray) { + contactsFound = AppDatabase.getInstance().contactDao() + .getAllForOwnedIdentitySync(bytesOwnedIdentity) + .filter { contact -> + filterRegexes?.all { it.containsMatchIn(contact.fullSearchDisplayName) } == true } - messagesFound = messages - - messageLimitReachedCount = - if (messages.size >= MESSAGE_SEARCH_LIMIT) { - val count = AppDatabase.getInstance().messageDao().globalSearchCount(bytesOwnedIdentity, tokenizedQuery, 5 * MESSAGE_SEARCH_LIMIT + 1) - if (count > 5 * MESSAGE_SEARCH_LIMIT) { - "${5 * MESSAGE_SEARCH_LIMIT}+" - } else if (count > MESSAGE_SEARCH_LIMIT) { - count.toString() + } + + private fun searchDiscussions(bytesOwnedIdentity: ByteArray) { + val groups: MutableList = ArrayList() + val otherDiscussions: MutableList = ArrayList() + AppDatabase.getInstance().discussionDao() + .getAllForGlobalSearch(bytesOwnedIdentity) + .filter { !it.discussion.isNormalOrReadOnly || it.discussion.discussionType != Discussion.TYPE_CONTACT } // filter out normal contact discussions + .map { SearchableDiscussion(it) } + .forEach { searchableDiscussion -> + if (filterRegexes?.all { it.containsMatchIn(searchableDiscussion.patternMatchingField) } == true) { + if (searchableDiscussion.isGroupDiscussion) { + groups.add(searchableDiscussion) } else { - null + otherDiscussions.add(searchableDiscussion) } - } else { - null } - - val fyles = AppDatabase.getInstance().fyleMessageJoinWithStatusDao() - .globalSearch(bytesOwnedIdentity, tokenizedQuery, ATTACHMENT_SEARCH_LIMIT + 1) - if (cancelled) { - return - } - fylesFound = if (fyles.size > ATTACHMENT_SEARCH_LIMIT) { - fyles.subList(0, ATTACHMENT_SEARCH_LIMIT) - } else { - fyles } - attachmentLimitReachedCount = - if (fyles.size > ATTACHMENT_SEARCH_LIMIT) { - "${ATTACHMENT_SEARCH_LIMIT}+" -// val count = AppDatabase.getInstance().fyleMessageJoinWithStatusDao().globalSearchCount(bytesOwnedIdentity, tokenizedQuery, 5 * ATTACHMENT_SEARCH_LIMIT + 1) -// if (count > 5 * ATTACHMENT_SEARCH_LIMIT) { -// "${5 * ATTACHMENT_SEARCH_LIMIT}+" -// } else if (count > ATTACHMENT_SEARCH_LIMIT) { -// count.toString() -// } else { -// null -// } - } else { - null - } + groupsFound = groups + otherDiscussionsFound = otherDiscussions + } - if (!cancelled) { - currentSearchTask = null + private fun searchMessages(bytesOwnedIdentity: ByteArray, tokenizedQuery: String) { + messagesFound = pager(MESSAGE_SEARCH_LIMIT) { offset -> + AppDatabase.getInstance().globalSearchDao().messageGlobalSearch( + bytesOwnedIdentity, + tokenizedQuery, + MESSAGE_SEARCH_LIMIT, + offset) + }.flow.cachedIn(viewModelScope) + } + + private fun searchFyles(bytesOwnedIdentity: ByteArray, tokenizedQuery: String) { + fylesFound = pager(ATTACHMENT_SEARCH_LIMIT) { offset -> + AppDatabase.getInstance().globalSearchDao().attachmentsGlobalSearch(bytesOwnedIdentity, tokenizedQuery, ATTACHMENT_SEARCH_LIMIT, offset) + }.flow.cachedIn(viewModelScope) + } + + private fun pager( + searchLimit: Int, + loadData: suspend (offset: Int) -> List + ) = Pager( + config = PagingConfig( + pageSize = searchLimit, + prefetchDistance = 3 * searchLimit + ) + ) { + object : PagingSource() { + override fun getRefreshKey(state: PagingState): Int? { + return state.anchorPosition?.let { anchorPosition -> + val anchorPage = state.closestPageToPosition(anchorPosition) + anchorPage?.prevKey?.plus(searchLimit) + ?: anchorPage?.nextKey?.minus( + searchLimit + ) + } } - } - fun cancel() { - cancelled = true + override suspend fun load(params: LoadParams): LoadResult { + val offset = params.key ?: 0 + val data = loadData(offset) + return Page( + data = data, + prevKey = if (offset == 0) null else offset - searchLimit, + nextKey = if (data.size < searchLimit) null else offset + searchLimit + ) + } } } -} +} \ No newline at end of file diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/viewModels/FilteredDiscussionListViewModel.java b/obv_messenger/app/src/main/java/io/olvid/messenger/viewModels/FilteredDiscussionListViewModel.java index 92fe7ab1..b1215c25 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/viewModels/FilteredDiscussionListViewModel.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/viewModels/FilteredDiscussionListViewModel.java @@ -188,7 +188,7 @@ public SearchableDiscussion(@NonNull DiscussionDao.DiscussionAndGroupMembersName } this.title = discussionAndGroupMembersNames.discussion.title; this.groupMemberNameList = discussionAndGroupMembersNames.groupMemberNames == null ? "" : discussionAndGroupMembersNames.groupMemberNames; - this.patternMatchingField = StringUtils.unAccent(title + "\n" + groupMemberNameList); + this.patternMatchingField = discussionAndGroupMembersNames.patterMatchingField == null ? StringUtils.unAccent(title + "\n" + groupMemberNameList) : discussionAndGroupMembersNames.patterMatchingField; this.photoUrl = discussionAndGroupMembersNames.discussion.photoUrl; this.keycloakManaged = discussionAndGroupMembersNames.discussion.keycloakManaged; this.active = discussionAndGroupMembersNames.discussion.active; diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/CallParticipantAdditionDialogFragment.java b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/CallParticipantAdditionDialogFragment.java index 50ea019d..c3ca6341 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/CallParticipantAdditionDialogFragment.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/CallParticipantAdditionDialogFragment.java @@ -136,9 +136,6 @@ private void setWebrtcCallService(WebrtcCallService webrtcCallService) { if (filteredContactListFragment != null) { filteredContactListFragment.setUnfilteredContacts( Transformations.switchMap(this.webrtcCallService.getCallParticipantsLiveData(), callParticipantPojos -> { - if (callParticipantPojos == null) { - return AppDatabase.getInstance().contactDao().getAllForOwnedIdentityWithChannel(bytesOwnedIdentity); - } List excludedContacts = new ArrayList<>(callParticipantPojos.size()); for (WebrtcCallService.CallParticipantPojo callParticipantPojo: callParticipantPojos) { excludedContacts.add(callParticipantPojo.bytesContactIdentity); diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/IncomingCallRinger.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/IncomingCallRinger.kt index 4d0f170b..4dca4031 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/IncomingCallRinger.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/IncomingCallRinger.kt @@ -45,17 +45,14 @@ import java.io.IOException import java.util.UUID class IncomingCallRinger(private val context: Context) { - private val vibrator: Vibrator? + private val vibrator: Vibrator? = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator private var cameraManager: CameraManager? = null - private val cameraIdsToFlash: MutableSet - private val cameraIdsFlashThreads: HashMap + private val cameraIdsToFlash: MutableSet = HashSet() + private val cameraIdsFlashThreads: HashMap = HashMap() private var mediaPlayer: MediaPlayer? = null private var mediaSession: MediaSession? = null init { - vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator - cameraIdsToFlash = HashSet() - cameraIdsFlashThreads = HashMap() if (VERSION.SDK_INT >= VERSION_CODES.M) { cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager? cameraManager?.let { @@ -75,7 +72,7 @@ class IncomingCallRinger(private val context: Context) { } } - fun ring(callIdentifier: UUID?, discussionCustomization: DiscussionCustomization?) { + fun ring(call: WebrtcCallService.Call) { var ringerMode = AudioManager.RINGER_MODE_NORMAL val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager? if (audioManager != null) { @@ -85,22 +82,22 @@ class IncomingCallRinger(private val context: Context) { val ringtone: Uri val vibrationPattern: LongArray val useFlash: Boolean - if (discussionCustomization == null || !discussionCustomization.prefUseCustomCallNotification) { + if (call.discussionCustomization == null || !call.discussionCustomization.prefUseCustomCallNotification) { ringtone = SettingsActivity.getCallRingtone() vibrationPattern = SettingsActivity.getCallVibrationPattern() useFlash = SettingsActivity.useFlashOnIncomingCall() } else { ringtone = - if (discussionCustomization.prefCallNotificationRingtone == null) Uri.EMPTY else Uri.parse( - discussionCustomization.prefCallNotificationRingtone + if (call.discussionCustomization.prefCallNotificationRingtone == null) Uri.EMPTY else Uri.parse( + call.discussionCustomization.prefCallNotificationRingtone ) vibrationPattern = - if (discussionCustomization.prefCallNotificationVibrationPattern == null) LongArray( + if (call.discussionCustomization.prefCallNotificationVibrationPattern == null) LongArray( 0 ) else SettingsActivity.intToVibrationPattern( - discussionCustomization.prefCallNotificationVibrationPattern!!.toInt() + call.discussionCustomization.prefCallNotificationVibrationPattern!!.toInt() ) - useFlash = discussionCustomization.prefCallNotificationUseFlash + useFlash = call.discussionCustomization.prefCallNotificationUseFlash } try { mediaPlayer = MediaPlayer() @@ -129,10 +126,8 @@ class IncomingCallRinger(private val context: Context) { if (keyEvent != null && keyEvent.action == KeyEvent.ACTION_DOWN && (keyEvent.keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyEvent.keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyEvent.keyCode == KeyEvent.KEYCODE_MEDIA_PLAY || keyEvent.keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE)) { val answerCallIntent = Intent(context, WebrtcCallService::class.java) answerCallIntent.setAction(WebrtcCallService.ACTION_ANSWER_CALL) - answerCallIntent.putExtra( - WebrtcCallService.CALL_IDENTIFIER_INTENT_EXTRA, - Logger.getUuidString(callIdentifier) - ) + answerCallIntent.putExtra(WebrtcCallService.CALL_IDENTIFIER_INTENT_EXTRA, Logger.getUuidString(call.callIdentifier)) + answerCallIntent.putExtra(WebrtcCallService.BYTES_OWNED_IDENTITY_INTENT_EXTRA, call.bytesOwnedIdentity) context.startService(answerCallIntent) return true } diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcCallActivity.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcCallActivity.kt index be5cad3b..0a62709a 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcCallActivity.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcCallActivity.kt @@ -77,7 +77,6 @@ import com.google.accompanist.themeadapter.appcompat.AppCompatTheme import io.olvid.engine.Logger import io.olvid.messenger.App import io.olvid.messenger.R -import io.olvid.messenger.R.string import io.olvid.messenger.databases.entity.Contact import io.olvid.messenger.databases.entity.Discussion import io.olvid.messenger.discussion.DiscussionActivity @@ -110,7 +109,7 @@ class WebrtcCallActivity : AppCompatActivity() { var foreground = false private var outputDialogOpen = false private var addParticipantDialogOpen = false - var loudSpeakerOn = false + private var loudSpeakerOn = false private val mediaProjectionManager by lazy { getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager } private val screenCaptureIntent by lazy { @@ -167,18 +166,20 @@ class WebrtcCallActivity : AppCompatActivity() { } } else if (ANSWER_CALL_ACTION == intent.action) { val callIdentifier = intent.getStringExtra(ANSWER_CALL_EXTRA_CALL_IDENTIFIER) - if (callIdentifier != null) { - val serviceIntent = Intent(this, WebrtcCallService::class.java) - serviceIntent.setAction(WebrtcCallService.ACTION_ANSWER_CALL) - serviceIntent.putExtra( - WebrtcCallService.CALL_IDENTIFIER_INTENT_EXTRA, - callIdentifier + val bytesOwnedIdentity = intent.getByteArrayExtra(ANSWER_CALL_EXTRA_BYTES_OWNED_IDENTITY) + + if (callIdentifier != null && bytesOwnedIdentity != null) { + startService( + Intent(this, WebrtcCallService::class.java) + .setAction(WebrtcCallService.ACTION_ANSWER_CALL) + .putExtra(WebrtcCallService.CALL_IDENTIFIER_INTENT_EXTRA, callIdentifier) + .putExtra(WebrtcCallService.BYTES_OWNED_IDENTITY_INTENT_EXTRA, bytesOwnedIdentity) ) - startService(serviceIntent) } else { closeActivity() } } + intent.action = null webrtcServiceConnection = WebrtcServiceConnection().apply { val serviceBindIntent = Intent(this@WebrtcCallActivity, WebrtcCallService::class.java) @@ -318,7 +319,7 @@ class WebrtcCallActivity : AppCompatActivity() { Spacer(modifier = Modifier.weight(1f, true)) } TextButton(onClick = onDismiss) { - Text(text = stringResource(id = string.button_label_ok)) + Text(text = stringResource(id = R.string.button_label_ok)) } } }, @@ -339,7 +340,7 @@ class WebrtcCallActivity : AppCompatActivity() { mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT, KeyEvent::class.java) } else { @Suppress("DEPRECATION") - mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT) + mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT) } if (keyEvent != null && keyEvent.action == KeyEvent.ACTION_DOWN && (keyEvent.keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyEvent.keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyEvent.keyCode == KeyEvent.KEYCODE_MEDIA_PLAY || keyEvent.keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE)) { if (webrtcCallService != null) { @@ -357,7 +358,7 @@ class WebrtcCallActivity : AppCompatActivity() { ) != PackageManager.PERMISSION_GRANTED ) { SettingsActivity.setFirstCallAudioPermissionRequested(true) - permissionDialogToShow = PermissionDialog(string.dialog_title_webrtc_audio_permission, string.dialog_message_webrtc_audio_permission) { + permissionDialogToShow = PermissionDialog(R.string.dialog_title_webrtc_audio_permission, R.string.dialog_message_webrtc_audio_permission) { requestPermissionsIfNeeded(true) } } else { @@ -390,7 +391,7 @@ class WebrtcCallActivity : AppCompatActivity() { ) ) { SettingsActivity.setFirstCallBluetoothPermissionRequested(true) - permissionDialogToShow = PermissionDialog(string.dialog_title_android_12_bluetooth_access, string.dialog_message_android_12_bluetooth_access) { + permissionDialogToShow = PermissionDialog(R.string.dialog_title_android_12_bluetooth_access, R.string.dialog_message_android_12_bluetooth_access) { ActivityCompat.requestPermissions( this, arrayOf( permission.BLUETOOTH_CONNECT @@ -419,6 +420,7 @@ class WebrtcCallActivity : AppCompatActivity() { override fun onDestroy() { super.onDestroy() + webrtcCallService?.closeCallActivity = {} webrtcServiceConnection?.let { unbindService(it) } initWebrtcCallService(null) if (mediaSession != null) { @@ -439,6 +441,7 @@ class WebrtcCallActivity : AppCompatActivity() { } override fun onUserLeaveHint() { + super.onUserLeaveHint() if (webrtcCallService?.screenShareActive != true && webrtcCallService?.requestingScreenCast != true && webrtcCallService?.getState()?.value == WebrtcCallService.State.CALL_IN_PROGRESS) { @@ -579,15 +582,15 @@ class WebrtcCallActivity : AppCompatActivity() { if (!audioPermissionGranted) { if (requestCode == PERMISSIONS_REQUEST_CODE_AFTER_RATIONALE) { // user was prompted for permission, and he denied it --> hangup - App.toast(string.toast_message_audio_permission_denied, Toast.LENGTH_SHORT) + App.toast(R.string.toast_message_audio_permission_denied, Toast.LENGTH_SHORT) if (webrtcCallService != null) { webrtcCallService?.hangUpCall() } } else { // user was not prompted --> show dialog explaining that audio permission was permanently denied permissionDialogToShow = PermissionDialog( - titleStringResId = string.dialog_title_webrtc_permissions_audio_blocked, - messageStringResId = string.dialog_message_webrtc_permissions_audio_blocked, + titleStringResId = R.string.dialog_title_webrtc_permissions_audio_blocked, + messageStringResId = R.string.dialog_message_webrtc_permissions_audio_blocked, additionalButton = { TextButton(onClick = { val settingsIntent = Intent() @@ -608,12 +611,12 @@ class WebrtcCallActivity : AppCompatActivity() { if (!cameraPermissionGranted) { if (requestCode == PERMISSIONS_REQUEST_CODE_AFTER_RATIONALE) { // user was prompted for permission, and he denied it --> hangup - App.toast(string.toast_message_camera_permission_denied, Toast.LENGTH_SHORT) + App.toast(R.string.toast_message_camera_permission_denied, Toast.LENGTH_SHORT) } else { // user was not prompted --> show dialog explaining that audio permission was permanently denied permissionDialogToShow = PermissionDialog( - titleStringResId = string.dialog_title_webrtc_permissions_camera_blocked, - messageStringResId = string.dialog_message_webrtc_permissions_camera_blocked, + titleStringResId = R.string.dialog_title_webrtc_permissions_camera_blocked, + messageStringResId = R.string.dialog_message_webrtc_permissions_camera_blocked, additionalButton = { TextButton(onClick = { val settingsIntent = Intent() @@ -653,7 +656,9 @@ class WebrtcCallActivity : AppCompatActivity() { private fun initWebrtcCallService(webrtcCallService: WebrtcCallService?) { if (webrtcCallService != null) { - this.webrtcCallService = webrtcCallService + this.webrtcCallService = webrtcCallService.apply { + closeCallActivity = ::closeActivity + } refreshProximityLockStatus() } else { this.webrtcCallService = null @@ -688,9 +693,10 @@ class WebrtcCallActivity : AppCompatActivity() { const val CALL_BACK_EXTRA_DISCUSSION_ID = "discussion_id" const val ANSWER_CALL_ACTION = "answer_call" const val ANSWER_CALL_EXTRA_CALL_IDENTIFIER = "call_identifier" + const val ANSWER_CALL_EXTRA_BYTES_OWNED_IDENTITY = "bytes_owned_identity" } - public final data class PermissionDialog( + data class PermissionDialog( val titleStringResId: Int, val messageStringResId: Int, val additionalButton: (@Composable RowScope.() -> Unit)? = null, diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcCallService.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcCallService.kt index 8f3ff907..432b39ec 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcCallService.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcCallService.kt @@ -44,7 +44,6 @@ import android.media.projection.MediaProjection import android.net.wifi.WifiManager import android.net.wifi.WifiManager.WifiLock import android.os.Binder -import android.os.Build import android.os.Build.VERSION import android.os.Build.VERSION_CODES import android.os.Handler @@ -95,6 +94,7 @@ import io.olvid.messenger.databases.entity.CallLogItem import io.olvid.messenger.databases.entity.CallLogItemContactJoin import io.olvid.messenger.databases.entity.Contact import io.olvid.messenger.databases.entity.Discussion +import io.olvid.messenger.databases.entity.Discussion.TYPE_CONTACT import io.olvid.messenger.databases.entity.DiscussionCustomization import io.olvid.messenger.databases.entity.Message import io.olvid.messenger.databases.entity.jsons.JsonPayload @@ -104,6 +104,7 @@ import io.olvid.messenger.settings.SettingsActivity import io.olvid.messenger.webrtc.BluetoothHeadsetManager.State.HEADSET_UNAVAILABLE import io.olvid.messenger.webrtc.OutgoingCallRinger.Type import io.olvid.messenger.webrtc.OutgoingCallRinger.Type.RING +import io.olvid.messenger.webrtc.WebrtcCallActivity.Companion.ANSWER_CALL_ACTION import io.olvid.messenger.webrtc.WebrtcCallService.AudioOutput.BLUETOOTH import io.olvid.messenger.webrtc.WebrtcCallService.AudioOutput.HEADSET import io.olvid.messenger.webrtc.WebrtcCallService.AudioOutput.LOUDSPEAKER @@ -147,7 +148,6 @@ import io.olvid.messenger.webrtc.WebrtcPeerConnectionHolder.Companion.localVideo import io.olvid.messenger.webrtc.WebrtcPeerConnectionHolder.DataChannelMessageListener import io.olvid.messenger.webrtc.json.JsonAnswerCallMessage import io.olvid.messenger.webrtc.json.JsonAnsweredOrRejectedOnOtherDeviceMessage -import io.olvid.messenger.webrtc.json.JsonBusyMessage import io.olvid.messenger.webrtc.json.JsonDataChannelInnerMessage import io.olvid.messenger.webrtc.json.JsonDataChannelMessage import io.olvid.messenger.webrtc.json.JsonHangedUpInnerMessage @@ -183,7 +183,6 @@ import java.io.ByteArrayOutputStream import java.io.IOException import java.nio.ByteBuffer import java.nio.charset.StandardCharsets -import java.util.Arrays import java.util.Timer import java.util.TimerTask import java.util.TreeMap @@ -192,6 +191,8 @@ import java.util.zip.Deflater import java.util.zip.DeflaterOutputStream import java.util.zip.Inflater import java.util.zip.InflaterInputStream +import kotlin.concurrent.timer +import kotlin.concurrent.timerTask class WebrtcCallService : Service() { enum class Role { @@ -270,6 +271,7 @@ class WebrtcCallService : Service() { private val wiredHeadsetReceiver: WiredHeadsetReceiver = WiredHeadsetReceiver() private val objectMapper = AppSingleton.getJsonObjectMapper() private var role = NONE + var closeCallActivity : () -> Unit = {} @JvmField var callIdentifier: UUID? = null @@ -278,8 +280,7 @@ class WebrtcCallService : Service() { var bytesOwnedIdentity: ByteArray? = null @JvmField - var discussionType = - Discussion.TYPE_CONTACT // updated whenever bytesGroupOwnerAndUidOrIdentifier is set + var discussionType = TYPE_CONTACT // updated whenever bytesGroupOwnerAndUidOrIdentifier is set @JvmField var bytesGroupOwnerAndUidOrIdentifier: ByteArray? = null @@ -310,7 +311,7 @@ class WebrtcCallService : Service() { var screenShareActive by mutableStateOf(false) var cameraEnabled by mutableStateOf(false) private var availableCameras = emptyList() - val availableCamerasLiveData = MutableLiveData(availableCameras) + private val availableCamerasLiveData = MutableLiveData(availableCameras) private var selectedCamera: CameraAndFormat? = null val selectedCameraLiveData = MutableLiveData(selectedCamera) private var screenWidth: Int = 1080 @@ -342,6 +343,8 @@ class WebrtcCallService : Service() { private var disconnectSound = 0 private var reconnectingSound = 0 private var reconnectingStreamId: Int? = null + private var doubleCallSound = 0 + private var doubleCallStreamId: Int? = null private var phoneCallStateListener: PhoneCallStateListener? = null private var screenOffReceiver: ScreenOffReceiver? = null private var audioFocusRequest: AudioFocusRequestCompat? = null @@ -357,15 +360,156 @@ class WebrtcCallService : Service() { private set private var recipientTurnUserName: String? = null private var recipientTurnPassword: String? = null + + private val queuedIncomingCalls = emptyList().toMutableList() + + private fun dequeueIncomingCall(call: Call) { + queuedIncomingCalls.remove(call) + uncalledReceivedIceCandidates.remove(call.callIdentifier) + call.clearRingingTimeout() + stopThisServiceOrRefreshNotificationAndRingers() + } + + private var currentIncomingCallLiveData: MutableLiveData = MutableLiveData(null) + private var lastRoleWasNone: Boolean = true + + fun getCurrentIncomingCallLiveData() : LiveData { + return currentIncomingCallLiveData + } + + private fun stopThisServiceOrRefreshNotificationAndRingers() { + queuedIncomingCalls.firstOrNull()?.also { + val currentFirstIncomingCall = currentIncomingCallLiveData.value + // if nothing changed, no need to change what we are doing! + if (it == currentFirstIncomingCall && (lastRoleWasNone == (role == NONE))) { + return + } + if (currentFirstIncomingCall == null) { + registerScreenOffReceiver() + } + + if (role != NONE) { + playDoubleCallSound() + } else { + doubleCallStreamId?.let { + soundPool?.stop(it) + doubleCallStreamId = null + } + incomingCallRinger?.ring(it) + } + showIncomingCallForeground( + it.callIdentifier, + it.callerContact, + it.participantCount + ) + currentIncomingCallLiveData.postValue(it) + } ?: run { + doubleCallStreamId?.let { + soundPool?.stop(it) + doubleCallStreamId = null + } + incomingCallRinger?.stop() + unregisterScreenOffReceiver() + + if (role != NONE) { + showOngoingForeground() + } else { + @Suppress("DEPRECATION") + stopForeground(true) + + if (callIdentifier != null) { + uncalledReceivedIceCandidates.remove(callIdentifier) + } + if (VERSION.SDK_INT < VERSION_CODES.UPSIDE_DOWN_CAKE) { + unregisterDeviceOrientationChange() + } + Handler(Looper.getMainLooper()).postDelayed({ this.stopSelf() }, 300) + } + currentIncomingCallLiveData.postValue(null) + } + lastRoleWasNone = role == NONE + } + + inner class Call( + val callIdentifier: UUID, + val bytesOwnedIdentity: ByteArray, + val callerContact: Contact, + val bytesGroupOwnerAndUidOrIdentifier: ByteArray?, + val turnUserName: String?, + val turnPassword: String?, + val participantCount: Int, + val gatheringPolicy: GatheringPolicy, + var discussionType: Int, + val sessionDescriptionType: String, + val sessionDescription: String, + val discussionCustomization: DiscussionCustomization? + ) { + private var ringingTimer: Timer? = null + + init { + createRingingTimeout() + } + + private fun createRingingTimeout() { + ringingTimer?.cancel() + ringingTimer = Timer().apply { schedule(timerTask { + executor.execute { + dequeueIncomingCall(this@Call) + CallLogItem( + bytesOwnedIdentity, + bytesGroupOwnerAndUidOrIdentifier, + CallLogItem.TYPE_INCOMING, + CallLogItem.STATUS_MISSED + ).insert( + listOf( + ParticipantBytesAndRole( + callerContact.bytesContactIdentity, + CALLER + ) + ) + ) + } + }, RINGING_TIMEOUT_MILLIS) } + } + + fun clearRingingTimeout() { + ringingTimer?.cancel() + ringingTimer = null + } + } + + private fun setContactsAndRole( + bytesOwnedIdentity: ByteArray, + contacts: List, + callIdentifier: UUID, + iAmTheCaller: Boolean + ) { + this.bytesOwnedIdentity = bytesOwnedIdentity + this.callIdentifier = callIdentifier + role = if (iAmTheCaller) CALLER else RECIPIENT + callParticipants.clear() + callParticipantIndexes.clear() + callParticipantIndex = 0 + for (contact in contacts) { + val callParticipant = + CallParticipant(callIdentifier, contact, if (iAmTheCaller) RECIPIENT else CALLER) + callParticipantIndexes[BytesKey(contact.bytesContactIdentity)] = callParticipantIndex + callParticipants[callParticipantIndex] = callParticipant + callParticipantIndex++ + } + notifyCallParticipantsChanged() + stopThisServiceOrRefreshNotificationAndRingers() + } + + override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { if (intent.action != null) { initialize() intent.apply { when (action) { ACTION_START_CALL -> { - if (!intent.hasExtra(CONTACT_IDENTITIES_BUNDLE_INTENT_EXTRA) || !intent.hasExtra( - BYTES_OWNED_IDENTITY_INTENT_EXTRA - ) + if (!intent.hasExtra(CONTACT_IDENTITIES_BUNDLE_INTENT_EXTRA) + || !intent.hasExtra(BYTES_OWNED_IDENTITY_INTENT_EXTRA) ) { return@apply } @@ -500,13 +644,8 @@ class WebrtcCallService : Service() { } ANSWERED_OR_REJECTED_ON_OTHER_DEVICE_MESSAGE_TYPE -> { - // only accept this type of message from other owned devices - if (bytesOwnedIdentity != null && bytesContactIdentity != null && Arrays.equals( - bytesOwnedIdentity, - bytesContactIdentity - ) - ) { + if (bytesOwnedIdentity != null && bytesContactIdentity != null && bytesOwnedIdentity.contentEquals(bytesContactIdentity)) { val jsonAnsweredOrRejectedOnOtherDeviceMessage = objectMapper.readValue( serializedMessagePayload, @@ -527,45 +666,49 @@ class WebrtcCallService : Service() { } ACTION_ANSWER_CALL -> { - if (!intent.hasExtra(CALL_IDENTIFIER_INTENT_EXTRA)) { + if (!intent.hasExtra(CALL_IDENTIFIER_INTENT_EXTRA) || !intent.hasExtra(BYTES_OWNED_IDENTITY_INTENT_EXTRA)) { + return@apply + } + val callIdentifier = UUID.fromString(intent.getStringExtra(CALL_IDENTIFIER_INTENT_EXTRA)) + val bytesOwnedIdentity = intent.getByteArrayExtra(BYTES_OWNED_IDENTITY_INTENT_EXTRA) + if (callIdentifier == null || bytesOwnedIdentity == null) { return@apply } - val callIdentifier = UUID.fromString( - intent.getStringExtra( - CALL_IDENTIFIER_INTENT_EXTRA - ) - ) val audioPermissionGranted = ContextCompat.checkSelfPermission( this@WebrtcCallService, permission.RECORD_AUDIO ) == PackageManager.PERMISSION_GRANTED - recipientAnswerCall(callIdentifier, !audioPermissionGranted) + recipientAnswerCall(bytesOwnedIdentity, callIdentifier, !audioPermissionGranted) return START_NOT_STICKY } ACTION_REJECT_CALL -> { - if (!intent.hasExtra(CALL_IDENTIFIER_INTENT_EXTRA)) { + if (!intent.hasExtra(CALL_IDENTIFIER_INTENT_EXTRA) || !intent.hasExtra(BYTES_OWNED_IDENTITY_INTENT_EXTRA)) { return@apply } val callIdentifier = UUID.fromString( - intent.getStringExtra( - CALL_IDENTIFIER_INTENT_EXTRA - ) + intent.getStringExtra(CALL_IDENTIFIER_INTENT_EXTRA) ) - recipientRejectCall(callIdentifier) + val bytesOwnedIdentity = intent.getByteArrayExtra(BYTES_OWNED_IDENTITY_INTENT_EXTRA) + if (callIdentifier == null || bytesOwnedIdentity == null) { + return@apply + } + recipientRejectCall(bytesOwnedIdentity, callIdentifier) return START_NOT_STICKY } ACTION_HANG_UP -> { - if (!intent.hasExtra(CALL_IDENTIFIER_INTENT_EXTRA)) { + if (!intent.hasExtra(CALL_IDENTIFIER_INTENT_EXTRA) || !intent.hasExtra(BYTES_OWNED_IDENTITY_INTENT_EXTRA)) { return@apply } val callIdentifier = UUID.fromString( - intent.getStringExtra( - CALL_IDENTIFIER_INTENT_EXTRA - ) + intent.getStringExtra(CALL_IDENTIFIER_INTENT_EXTRA) ) - hangUpCall(callIdentifier) + val bytesOwnedIdentity = intent.getByteArrayExtra(BYTES_OWNED_IDENTITY_INTENT_EXTRA) + if (callIdentifier == null || bytesOwnedIdentity == null) { + return@apply + } + hangUpCall(bytesOwnedIdentity, callIdentifier) return START_NOT_STICKY } } @@ -581,10 +724,14 @@ class WebrtcCallService : Service() { val bytesContactIdentity = intent.getByteArrayExtra(BYTES_CONTACT_IDENTITY_INTENT_EXTRA) val callIdentifier = UUID.fromString(intent.getStringExtra(CALL_IDENTIFIER_INTENT_EXTRA)) + + if (bytesOwnedIdentity == null) { + return@execute + } + // if the message is for another call, ignore it - if (!Arrays.equals(bytesOwnedIdentity, this.bytesOwnedIdentity) || - callIdentifier != this.callIdentifier - ) { + if ((!bytesOwnedIdentity.contentEquals(this.bytesOwnedIdentity) || callIdentifier != this.callIdentifier ) + && queuedIncomingCalls.none { it.callIdentifier == callIdentifier && it.bytesOwnedIdentity.contentEquals(bytesOwnedIdentity) }) { return@execute } val messageType = intent.getIntExtra(MESSAGE_TYPE_INTENT_EXTRA, -1) @@ -593,14 +740,16 @@ class WebrtcCallService : Service() { ) ?: return@execute // if message does not contain a payload, ignore it - handleMessage(bytesContactIdentity, messageType, serializedMessagePayload) + handleMessage(bytesOwnedIdentity, bytesContactIdentity, messageType, serializedMessagePayload, callIdentifier) } } private fun handleMessage( + bytesOwnedIdentity: ByteArray, bytesContactIdentity: ByteArray?, messageType: Int, - serializedMessagePayload: String + serializedMessagePayload: String, + callIdentifier: UUID ) { try { when (messageType) { @@ -634,8 +783,27 @@ class WebrtcCallService : Service() { } HANGED_UP_MESSAGE_TYPE -> { - val callParticipant = getCallParticipant(bytesContactIdentity) - callParticipant?.let { handleHangedUpMessage(it) } + if (callIdentifier == this.callIdentifier && bytesOwnedIdentity.contentEquals(this.bytesOwnedIdentity)) { + val callParticipant = getCallParticipant(bytesContactIdentity) + callParticipant?.let { handleHangedUpMessage(it) } + } else { + queuedIncomingCalls.find { it.callIdentifier == callIdentifier && it.bytesOwnedIdentity.contentEquals(bytesOwnedIdentity)}?.let { + dequeueIncomingCall(it) + CallLogItem( + bytesOwnedIdentity, + bytesGroupOwnerAndUidOrIdentifier, + CallLogItem.TYPE_INCOMING, + CallLogItem.STATUS_MISSED + ).insert( + listOf( + ParticipantBytesAndRole( + it.callerContact.bytesContactIdentity, + CALLER + ) + ) + ) + } + } } BUSY_MESSAGE_TYPE -> { @@ -710,8 +878,8 @@ class WebrtcCallService : Service() { JsonNewIceCandidateMessage::class.java ) handleNewIceCandidateMessage( - callIdentifier!!, - bytesOwnedIdentity!!, + callIdentifier, + bytesOwnedIdentity, bytesContactIdentity!!, JsonIceCandidate( jsonNewIceCandidateMessage.sdp, @@ -727,8 +895,8 @@ class WebrtcCallService : Service() { JsonRemoveIceCandidatesMessage::class.java ) handleRemoveIceCandidatesMessage( - callIdentifier!!, - bytesOwnedIdentity!!, + callIdentifier, + bytesOwnedIdentity, bytesContactIdentity!!, jsonRemoveIceCandidatesMessage.candidates ) @@ -739,16 +907,6 @@ class WebrtcCallService : Service() { } } - private fun stopThisService() { - if (callIdentifier != null) { - executor.execute { uncalledReceivedIceCandidates.remove(callIdentifier) } - } - stopForeground(true) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - unregisterDeviceOrientationChange() - } - Handler(Looper.getMainLooper()).postDelayed({ this.stopSelf() }, 300) - } // region Steps private fun initialize() { @@ -775,6 +933,7 @@ class WebrtcCallService : Service() { connectSound = load(this@WebrtcCallService, raw.connect, 1) disconnectSound = load(this@WebrtcCallService, raw.disconnect, 1) reconnectingSound = load(this@WebrtcCallService, raw.reconnecting, 1) + doubleCallSound = load(this@WebrtcCallService, raw.double_call, 1) } if (ContextCompat.checkSelfPermission( @@ -792,7 +951,9 @@ class WebrtcCallService : Service() { ) { bluetoothPermissionGranted() } + @Suppress("DEPRECATION") audioManager!!.isSpeakerphoneOn = false + @Suppress("DEPRECATION") wiredHeadsetConnected = audioManager!!.isWiredHeadsetOn updateAvailableAudioOutputsList() updateCameraList() @@ -811,15 +972,7 @@ class WebrtcCallService : Service() { private fun handleUnknownOrInvalidIntent() { executor.execute { - if (_state == INITIAL) { - // we received an unknown intent and no call has been started - // --> we can safely stop the service - stopForeground(true) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - unregisterDeviceOrientationChange() - } - stopSelf() - } + stopThisServiceOrRefreshNotificationAndRingers() } } @@ -830,7 +983,7 @@ class WebrtcCallService : Service() { groupV2: Boolean ) { executor.execute { - if (_state != INITIAL) { + if (role != NONE) { App.toast(string.toast_message_already_in_a_call, Toast.LENGTH_SHORT) return@execute } @@ -849,10 +1002,10 @@ class WebrtcCallService : Service() { setContactsAndRole(bytesOwnedIdentity, contacts, callIdentifier, true) this.bytesGroupOwnerAndUidOrIdentifier = bytesGroupOwnerAndUidOrIdentifier discussionType = - if (bytesGroupOwnerAndUidOrIdentifier == null) Discussion.TYPE_CONTACT else if (groupV2) Discussion.TYPE_GROUP_V2 else Discussion.TYPE_GROUP + if (bytesGroupOwnerAndUidOrIdentifier == null) TYPE_CONTACT else if (groupV2) Discussion.TYPE_GROUP_V2 else Discussion.TYPE_GROUP // show notification - showOngoingForeground() + stopThisServiceOrRefreshNotificationAndRingers() callerStartCallInternal() } } @@ -864,7 +1017,7 @@ class WebrtcCallService : Service() { groupV2: Boolean ) { executor.execute { - if (_state != INITIAL) { + if (role != NONE) { App.toast(string.toast_message_already_in_a_call, Toast.LENGTH_SHORT) return@execute } @@ -883,7 +1036,7 @@ class WebrtcCallService : Service() { setContactsAndRole(bytesOwnedIdentity, contacts, callIdentifier, true) this.bytesGroupOwnerAndUidOrIdentifier = bytesGroupOwnerAndUidOrIdentifier discussionType = - if (bytesGroupOwnerAndUidOrIdentifier == null) Discussion.TYPE_CONTACT else if (groupV2) Discussion.TYPE_GROUP_V2 else Discussion.TYPE_GROUP + if (bytesGroupOwnerAndUidOrIdentifier == null) TYPE_CONTACT else if (groupV2) Discussion.TYPE_GROUP_V2 else Discussion.TYPE_GROUP setState(WAITING_FOR_AUDIO_PERMISSION) } } @@ -894,8 +1047,6 @@ class WebrtcCallService : Service() { return@execute } if (isCaller) { - // show notification - showOngoingForeground() callerStartCallInternal() } else { recipientAnswerCallInternal() @@ -971,7 +1122,7 @@ class WebrtcCallService : Service() { ) { // if my current identity can't call, check other identities for (ownedIdentity in AppDatabase.getInstance().ownedIdentityDao().allNotHidden) { - if (Arrays.equals(ownedIdentity.bytesOwnedIdentity, bytesOwnedIdentity)) { + if (ownedIdentity.bytesOwnedIdentity.contentEquals(bytesOwnedIdentity)) { // skip the current identity continue } @@ -1157,14 +1308,7 @@ class WebrtcCallService : Service() { callParticipant.setPeerState(PeerState.BUSY) // if all participants are busy, create a busy log entry - var allBusy = true - for (callParticipantOther in callParticipants.values) { - if (callParticipantOther.peerState != PeerState.BUSY) { - allBusy = false - break - } - } - if (allBusy) { + if (callParticipants.values.all { it.peerState == PeerState.BUSY }) { createLogEntry(CallLogItem.STATUS_BUSY) } if (_state == INITIALIZING_CALL) { @@ -1242,12 +1386,11 @@ class WebrtcCallService : Service() { } } - private fun hangUpCall(callIdentifier: UUID) { + private fun hangUpCall(bytesOwnedIdentity: ByteArray, callIdentifier: UUID) { executor.execute { - if (this.callIdentifier != callIdentifier) { - return@execute + if (this.callIdentifier == callIdentifier && this.bytesOwnedIdentity.contentEquals(bytesOwnedIdentity)) { + hangUpCallInternal(true) } - hangUpCallInternal(true) } } @@ -1255,17 +1398,54 @@ class WebrtcCallService : Service() { executor.execute { hangUpCallInternal(true) } } - private fun hangUpCallInternal(notifyPeers: Boolean) { - if (notifyPeers) { - // notify peer that you hung up (it's not just a connection loss) - sendHangedUpMessage(callParticipants.values) - } - if (_state == CALL_IN_PROGRESS && selectedAudioOutput != MUTED) { // do not play if state is already call ended - soundPool?.play(disconnectSound, 1f, 1f, 0, 0, 1f) + private fun hangUpCallInternal(notifyPeers: Boolean, closeActivity: Boolean = true) { + if (role != NONE) { + if (notifyPeers) { + // notify peer that you hung up (it's not just a connection loss) + sendHangedUpMessage(callParticipants.values) + } + if (_state == CALL_IN_PROGRESS && selectedAudioOutput != MUTED) { // do not play if state is already call ended + soundPool?.play(disconnectSound, 1f, 1f, 0, 0, 1f) + } + outgoingCallRinger?.stop() + if (_state != FAILED) { + setState(CALL_ENDED) + } + createLogEntry(CallLogItem.STATUS_MISSED) // this only create the log if it was not yet created + resetCallLogItem() + + role = NONE + callIdentifier = null + bytesOwnedIdentity = null + cameraEnabled = false + try { + localVideoTrack?.setEnabled(false) + } catch (_: Exception) { + localVideoTrack = null + } + try { + videoCapturer?.stopCapture() + } catch (e: InterruptedException) { + e.printStackTrace() + } finally { + videoCapturer = null + } + + requestingScreenCast = false + screenShareActive = false + try { + screenCapturerAndroid?.stopCapture() + localScreenTrack?.setEnabled(false) + } catch (_: InterruptedException) { + } finally { + screenCapturerAndroid?.dispose() + screenCapturerAndroid = null + } + if (closeActivity) { + closeCallActivity() + } + stopThisServiceOrRefreshNotificationAndRingers() } - createLogEntry(CallLogItem.STATUS_MISSED) - setState(CALL_ENDED) - stopThisService() } private fun recipientReceiveCall( @@ -1274,36 +1454,29 @@ class WebrtcCallService : Service() { callIdentifier: UUID, peerSdpType: String?, gzippedPeerSdpDescription: ByteArray, - turnUsername: String?, - turnPassword: String?, /* @Nullable List turnServers,*/ + turnName: String?, + turnPass: String?, /* @Nullable List turnServers,*/ participantCount: Int, bytesGroupOwnerAndUidOrIdentifier: ByteArray?, gatheringPolicy: GatheringPolicy ) { executor.execute { - if (_state != INITIAL && callIdentifier != this.callIdentifier) { - sendBusyMessage( - bytesOwnedIdentity, - bytesContactIdentity, - callIdentifier, - bytesGroupOwnerAndUidOrIdentifier - ) + if (callIdentifier == this.callIdentifier && !bytesOwnedIdentity.contentEquals(this.bytesOwnedIdentity)) { + // receiving a call from another profile on same device, ignoring it... return@execute } - if (callIdentifier == this.callIdentifier && !Arrays.equals( - bytesOwnedIdentity, - this.bytesOwnedIdentity - ) - ) { - // receiving a call from another profile on same device... - sendBusyMessage( - bytesOwnedIdentity, - bytesContactIdentity, - callIdentifier, - bytesGroupOwnerAndUidOrIdentifier - ) + + val peerSdpDescription = runCatching { gunzip(gzippedPeerSdpDescription) } + .onFailure { e -> Logger.x(e) } + .getOrNull() + + val contact = AppDatabase.getInstance().contactDao()[bytesOwnedIdentity, bytesContactIdentity] + + if (contact == null || peerSdpDescription == null || peerSdpType == null) { return@execute } + + val alreadyAnsweredOrRejectedOnOtherDevice = uncalledAnsweredOrRejectedOnOtherDevice.remove(callIdentifier) if (alreadyAnsweredOrRejectedOnOtherDevice != null) { @@ -1314,133 +1487,131 @@ class WebrtcCallService : Service() { CallLogItem.TYPE_INCOMING, if (alreadyAnsweredOrRejectedOnOtherDevice) CallLogItem.STATUS_ANSWERED_ON_OTHER_DEVICE else CallLogItem.STATUS_REJECTED_ON_OTHER_DEVICE ) - callLogItem.id = AppDatabase.getInstance().callLogItemDao().insert(callLogItem) - val callLogItemContactJoin = CallLogItemContactJoin( - callLogItem.id, - bytesOwnedIdentity, - bytesContactIdentity!! + callLogItem.insert(listOf( + ParticipantBytesAndRole( + contact.bytesContactIdentity, + CALLER ) - AppDatabase.getInstance().callLogItemDao().insert(callLogItemContactJoin) - var discussion: Discussion? = null - if (bytesGroupOwnerAndUidOrIdentifier != null) { - discussion = AppDatabase.getInstance().discussionDao() - .getByGroupOwnerAndUidOrIdentifier( - bytesOwnedIdentity, - bytesGroupOwnerAndUidOrIdentifier - ) - } - if (discussion == null) { - discussion = AppDatabase.getInstance().discussionDao() - .getByContact(bytesOwnedIdentity, bytesContactIdentity) - } - if (discussion != null) { - val callMessage = Message.createPhoneCallMessage( - AppDatabase.getInstance(), - discussion!!.id, - bytesContactIdentity, - callLogItem - ) - AppDatabase.getInstance().messageDao().insert(callMessage) - if (discussion!!.updateLastMessageTimestamp(callMessage.timestamp)) { - AppDatabase.getInstance().discussionDao().updateLastMessageTimestamp( - discussion!!.id, - discussion!!.lastMessageTimestamp - ) - } - } + )) } return@execute } - val peerSdpDescription: String - try { - peerSdpDescription = gunzip(gzippedPeerSdpDescription) - } catch (e: IOException) { - failReason = INTERNAL_ERROR - setState(FAILED) - e.printStackTrace() - return@execute - } - val contact = - AppDatabase.getInstance().contactDao()[bytesOwnedIdentity, bytesContactIdentity] - if (contact == null) { - failReason = CONTACT_NOT_FOUND - setState(FAILED) - return@execute - } - setContactsAndRole(bytesOwnedIdentity!!, listOf(contact), callIdentifier, false) - val callParticipant = getCallParticipant(bytesContactIdentity) - if (callParticipant == null) { - failReason = CONTACT_NOT_FOUND - setState(FAILED) - return@execute - } - this.bytesGroupOwnerAndUidOrIdentifier = bytesGroupOwnerAndUidOrIdentifier - this.turnUserName = turnUsername - this.turnPassword = turnPassword - incomingParticipantCount = participantCount - val discussion: Discussion? - if (bytesGroupOwnerAndUidOrIdentifier == null) { - discussion = AppDatabase.getInstance().discussionDao() - .getByContact(bytesOwnedIdentity, bytesContactIdentity) - discussionType = Discussion.TYPE_CONTACT - } else { - discussion = AppDatabase.getInstance().discussionDao() - .getByGroupOwnerAndUidOrIdentifier( - bytesOwnedIdentity, - bytesGroupOwnerAndUidOrIdentifier - ) - discussionType = discussion.discussionType - } - var discussionCustomization: DiscussionCustomization? = null - if (discussion != null) { - discussionCustomization = - AppDatabase.getInstance().discussionCustomizationDao()[discussion.id] + + if (queuedIncomingCalls.none { it.callIdentifier == callIdentifier && it.bytesOwnedIdentity.contentEquals(bytesOwnedIdentity)}) { + val discussion = getDiscussion(bytesOwnedIdentity, bytesContactIdentity, bytesGroupOwnerAndUidOrIdentifier) + val call = Call( + callIdentifier = callIdentifier, + bytesOwnedIdentity = bytesOwnedIdentity!!, + callerContact = contact, + bytesGroupOwnerAndUidOrIdentifier = bytesGroupOwnerAndUidOrIdentifier, + turnUserName = turnName, + turnPassword = turnPass, + participantCount = participantCount, + gatheringPolicy = gatheringPolicy, + discussionType = discussion?.discussionType ?: TYPE_CONTACT, + sessionDescriptionType = peerSdpType, + sessionDescription = peerSdpDescription, + discussionCustomization = getDiscussionCustomization(discussion) + ) + + // we comment this code for now as this is not properly supported on iOS/macOS +// // check if a simultaneous mutual call is occurring +// if (callParticipants.size == 1 // one to one only +// && callParticipant.bytesContactIdentity.contentEquals(callParticipants.values.first().bytesContactIdentity) // same contact in both outgoing and incoming call +// && callIdentifier != this.callIdentifier +// ) { +// if (!shouldISendTheOfferToCallParticipant(callParticipant)) { +// val audioPermissionGranted = ContextCompat.checkSelfPermission( +// this@WebrtcCallService, +// permission.RECORD_AUDIO +// ) == PackageManager.PERMISSION_GRANTED +// recipientAnswerCall(callIdentifier, !audioPermissionGranted) +// } else { +// this.callIdentifier?.let { recipientRejectCall(it) } +// return@execute +// } +// } + + sendRingingMessage(call) + + queuedIncomingCalls.add(call) + stopThisServiceOrRefreshNotificationAndRingers() } - callParticipant.peerConnectionHolder.setGatheringPolicy(gatheringPolicy) - callParticipant.peerConnectionHolder.setPeerSessionDescription( - peerSdpType, - peerSdpDescription - ) - callParticipant.peerConnectionHolder.setTurnCredentials( - turnUsername, - turnPassword /*, turnServers*/ - ) - showIncomingCallForeground(callParticipant.contact, participantCount) - sendRingingMessage(callParticipant) - registerScreenOffReceiver() - incomingCallRinger!!.ring(callIdentifier, discussionCustomization) - setState(State.RINGING) } } - private fun recipientAnswerCall(callIdentifier: UUID, waitForAudioPermission: Boolean) { + + private fun getDiscussion(bytesOwnedIdentity: ByteArray?, bytesContactIdentity: ByteArray?,bytesGroupOwnerAndUidOrIdentifier: ByteArray?) : Discussion? { + return if (bytesGroupOwnerAndUidOrIdentifier == null) { + AppDatabase.getInstance().discussionDao() + .getByContact(bytesOwnedIdentity, bytesContactIdentity) + } else { + AppDatabase.getInstance().discussionDao() + .getByGroupOwnerAndUidOrIdentifier( + bytesOwnedIdentity, + bytesGroupOwnerAndUidOrIdentifier + ) + } + } + private fun getDiscussionCustomization(discussion: Discussion?): DiscussionCustomization? { + return discussion?.let { + AppDatabase.getInstance().discussionCustomizationDao()[it.id] + } + } + + private fun playDoubleCallSound() { + if (doubleCallStreamId == null && selectedAudioOutput != MUTED) { + doubleCallStreamId = soundPool?.play(doubleCallSound, .5f, .5f, 0, -1, 1f) + } + } + + private fun recipientAnswerCall(bytesOwnedIdentity: ByteArray, callIdentifier: UUID, waitForAudioPermission: Boolean) { executor.execute { - if (_state != State.RINGING || this.callIdentifier != callIdentifier) { - return@execute - } + queuedIncomingCalls.find { it.callIdentifier == callIdentifier && it.bytesOwnedIdentity.contentEquals(bytesOwnedIdentity)}?.let { call -> + // stop current call if any + if (role != NONE) { + hangUpCallInternal(notifyPeers = true, closeActivity = false) + } + // apply call object to start + callParticipants.clear() + callParticipantIndexes.clear() + callParticipantIndex = 0 + setContactsAndRole( + call.bytesOwnedIdentity, + listOf(call.callerContact), + call.callIdentifier, + false + ) + this@WebrtcCallService.bytesGroupOwnerAndUidOrIdentifier = call.bytesGroupOwnerAndUidOrIdentifier + this@WebrtcCallService.incomingParticipantCount = call.participantCount + this@WebrtcCallService.discussionType = call.discussionType + this@WebrtcCallService.turnUserName = call.turnUserName + this@WebrtcCallService.turnPassword = call.turnPassword + + callerCallParticipant?.let { + it.peerConnectionHolder.setGatheringPolicy(call.gatheringPolicy) + it.peerConnectionHolder.setPeerSessionDescription( + call.sessionDescriptionType, + call.sessionDescription + ) + it.peerConnectionHolder.setTurnCredentials( + call.turnUserName, + call.turnPassword /*, turnServers*/ + ) + } - // stop ringing and listening for power button - incomingCallRinger!!.stop() - unregisterScreenOffReceiver() + dequeueIncomingCall(call) - // remove notification in case previous starting foreground failed - try { - val notificationManager = NotificationManagerCompat.from(this) - notificationManager.cancel(NOT_FOREGROUND_NOTIFICATION_ID) - } catch (e: Exception) { - // do nothing - } - if (waitForAudioPermission) { - setState(WAITING_FOR_AUDIO_PERMISSION) - } else { - recipientAnswerCallInternal() + if (waitForAudioPermission) { + setState(WAITING_FOR_AUDIO_PERMISSION) + } else { + recipientAnswerCallInternal() + } } } } private fun recipientAnswerCallInternal() { - showOngoingForeground() - // get audio focus requestAudioManagerFocus() @@ -1462,54 +1633,34 @@ class WebrtcCallService : Service() { setState(CONNECTING) } - private fun recipientRejectCall(callIdentifier: UUID) { + fun recipientRejectCall(bytesOwnedIdentity: ByteArray, callIdentifier: UUID) { executor.execute { - if (_state != State.RINGING || this.callIdentifier != callIdentifier) { - return@execute + queuedIncomingCalls.find { it.callIdentifier == callIdentifier && it.bytesOwnedIdentity.contentEquals(bytesOwnedIdentity)}?.let { call -> + rejectCallInternal(call = call, endedFromOtherDevice = false, answered = false) } - rejectCallInternal(endedFromOtherDevice = false, answered = false) - } - } - - fun recipientRejectCall() { - executor.execute { - if (_state != State.RINGING) { - return@execute - } - rejectCallInternal(endedFromOtherDevice = false, answered = false) } } /////////// // endedFromOtherDevice indicates the call should be ended because it was answered or rejected from another device // answered indicates that this other device picked up the call (this is ignored if endedFromOtherDevice is false) - private fun rejectCallInternal(endedFromOtherDevice: Boolean, answered: Boolean) { - // stop ringing and listening for power button - incomingCallRinger!!.stop() - unregisterScreenOffReceiver() - val callerCallParticipant = callerCallParticipant - if (callerCallParticipant == null) { - failReason = CONTACT_NOT_FOUND - setState(FAILED) - return - } - if (!endedFromOtherDevice) { - // notify peer of rejected call - sendRejectCallMessage(callerCallParticipant) - - // create log entry - createLogEntry(CallLogItem.STATUS_REJECTED) - } else { + private fun rejectCallInternal(call: Call, endedFromOtherDevice: Boolean, answered: Boolean) { + if (endedFromOtherDevice) { if (answered) { - createLogEntry(CallLogItem.STATUS_ANSWERED_ON_OTHER_DEVICE) + createLogEntry(CallLogItem.STATUS_ANSWERED_ON_OTHER_DEVICE, call) } else { - createLogEntry(CallLogItem.STATUS_REJECTED_ON_OTHER_DEVICE) + createLogEntry(CallLogItem.STATUS_REJECTED_ON_OTHER_DEVICE, call) } + } else { + // notify peer of rejected call + sendRejectCallMessage(call) + + // create log entry + createLogEntry(CallLogItem.STATUS_REJECTED, call) } - callerCallParticipant.setPeerState(CALL_REJECTED) - setState(CALL_ENDED) - stopThisService() + dequeueIncomingCall(call) } + fun peerConnectionHolderFailed(callParticipant: CallParticipant, failReason: FailReason) { executor.execute { @@ -1594,16 +1745,9 @@ class WebrtcCallService : Service() { callDurationTimer = null } callDuration.postValue(0) - callDurationTimer = Timer() - callDurationTimer!!.schedule(object : TimerTask() { - override fun run() { - var duration = callDuration.value - if (duration == null) { - duration = 0 - } - callDuration.postValue(duration + 1) - } - }, 0, 1000) + callDurationTimer = timer(period = 1000) { + callDuration.postValue((callDuration.value ?: 0) + 1) + } setState(CALL_IN_PROGRESS) } } @@ -1615,7 +1759,7 @@ class WebrtcCallService : Service() { } val newCallParticipants: MutableList = ArrayList() for (contact in contactsToAdd) { - if (!Arrays.equals(contact.bytesOwnedIdentity, bytesOwnedIdentity)) { + if (!contact.bytesOwnedIdentity.contentEquals(bytesOwnedIdentity)) { Logger.w("☎ Trying to add contact to call for a different ownedIdentity") continue } @@ -1624,7 +1768,7 @@ class WebrtcCallService : Service() { continue } Logger.d("☎ Adding a call participant") - val callParticipant = this.CallParticipant(contact, RECIPIENT) + val callParticipant = this.CallParticipant(callIdentifier!!, contact, RECIPIENT) newCallParticipants.add(callParticipant) callParticipantIndexes[BytesKey(callParticipant.bytesContactIdentity)] = callParticipantIndex @@ -1780,11 +1924,7 @@ class WebrtcCallService : Service() { ) { executor.execute { Logger.d("☎ received new ICE candidate") - if (Arrays.equals( - bytesOwnedIdentity, - this.bytesOwnedIdentity - ) && callIdentifier == this.callIdentifier - ) { + if (bytesOwnedIdentity.contentEquals(this.bytesOwnedIdentity) && callIdentifier == this.callIdentifier) { // we are in the right call, handle the message directly (if the participant is in the call) val callParticipant = getCallParticipant(bytesContactIdentity) if (callParticipant != null) { @@ -1794,18 +1934,9 @@ class WebrtcCallService : Service() { } } - // this is not the right call, store the candidate on the side - var callerCandidatesMap = uncalledReceivedIceCandidates[callIdentifier] - if (callerCandidatesMap == null) { - callerCandidatesMap = HashMap() - uncalledReceivedIceCandidates[callIdentifier] = callerCandidatesMap - } - var candidates = callerCandidatesMap[BytesKey(bytesContactIdentity)] - if (candidates == null) { - candidates = HashSet() - callerCandidatesMap[BytesKey(bytesContactIdentity)] = candidates - } + val callerCandidatesMap = uncalledReceivedIceCandidates.getOrPut(callIdentifier) { HashMap() } + val candidates = callerCandidatesMap.getOrPut(BytesKey(bytesContactIdentity)) { HashSet() } candidates.add(jsonIceCandidate) } } @@ -1817,11 +1948,7 @@ class WebrtcCallService : Service() { jsonIceCandidates: Array ) { executor.execute { - if (Arrays.equals( - bytesOwnedIdentity, - this.bytesOwnedIdentity - ) && callIdentifier == this.callIdentifier - ) { + if (bytesOwnedIdentity.contentEquals(this.bytesOwnedIdentity) && callIdentifier == this.callIdentifier) { // we are in the right call, handle the message directly val callParticipant = getCallParticipant(bytesContactIdentity) callParticipant?.peerConnectionHolder?.removeIceCandidates(jsonIceCandidates) @@ -1853,18 +1980,11 @@ class WebrtcCallService : Service() { ) { executor.execute { Logger.d("☎ Call handled on other owned device: " + if (answered) "answered" else "rejected") - if (Arrays.equals( - bytesOwnedIdentity, - this.bytesOwnedIdentity - ) && callIdentifier == this.callIdentifier - ) { - // we are in the right call, handle the message directly - if (_state != State.RINGING) { - return@execute - } - rejectCallInternal(true, answered) - } else { - // this is not the right call, remove the candidate from the side + // try rejecting from queue + queuedIncomingCalls.find { bytesOwnedIdentity.contentEquals(it.bytesOwnedIdentity) && callIdentifier == it.callIdentifier }?.also { call -> + rejectCallInternal(call, true, answered) + } ?: run { + // call not in the queue yet, mark it as already handled on other device uncalledAnsweredOrRejectedOnOtherDevice[callIdentifier] = answered } } @@ -1875,10 +1995,7 @@ class WebrtcCallService : Service() { val participantsToRemove: MutableSet = HashSet(callParticipantIndexes.keys) val newCallParticipants: MutableList = ArrayList() for (jsonContactBytesAndName in jsonUpdateParticipantsInnerMessage.callParticipants) { - if (Arrays.equals( - jsonContactBytesAndName.bytesContactIdentity, - bytesOwnedIdentity - )) { + if (jsonContactBytesAndName.bytesContactIdentity.contentEquals(bytesOwnedIdentity)) { // the received array contains the user himself continue } @@ -1888,6 +2005,7 @@ class WebrtcCallService : Service() { } else { // call participant not already in the call --> we add him val callParticipant = CallParticipant( + callIdentifier!!, bytesOwnedIdentity, jsonContactBytesAndName.bytesContactIdentity, jsonContactBytesAndName.displayName, @@ -1962,7 +2080,7 @@ class WebrtcCallService : Service() { if (state == FAILED) { // create the log entry --> this will only create one if one was not already created createLogEntry(CallLogItem.STATUS_FAILED) - stopThisService() + hangUpCallInternal(false) } else if (state == State.RINGING) { createRingingTimeout() } @@ -1972,24 +2090,6 @@ class WebrtcCallService : Service() { return stateLiveData } - private fun setContactsAndRole( - bytesOwnedIdentity: ByteArray, - contacts: List, - callIdentifier: UUID, - iAmTheCaller: Boolean - ) { - this.bytesOwnedIdentity = bytesOwnedIdentity - this.callIdentifier = callIdentifier - role = if (iAmTheCaller) CALLER else RECIPIENT - for (contact in contacts) { - val callParticipant = CallParticipant(contact, if (iAmTheCaller) RECIPIENT else CALLER) - callParticipantIndexes[BytesKey(contact.bytesContactIdentity)] = callParticipantIndex - callParticipants[callParticipantIndex] = callParticipant - callParticipantIndex++ - } - notifyCallParticipantsChanged() - } - fun getCallParticipantsLiveData(): LiveData> { return callParticipantsLiveData } @@ -2021,13 +2121,17 @@ class WebrtcCallService : Service() { if (cameraEnabled.not() && callParticipants.size <= MAXIMUM_OTHER_PARTICIPANTS_FOR_VIDEO) { try { localVideoTrack?.setEnabled(true) - } catch (ignored: Exception) { + } catch (_: Exception) { localVideoTrack = null } if (videoCapturer == null) { createLocalVideo() } else { - videoCapturer?.startCapture(selectedCamera?.captureFormat?.width ?: 1280, selectedCamera?.captureFormat?.height ?: 720, 30) + videoCapturer?.startCapture( + selectedCamera?.captureFormat?.width ?: 1280, + selectedCamera?.captureFormat?.height ?: 720, + 30 + ) } cameraEnabled = true // if output is PHONE --> toggle speaker on @@ -2038,7 +2142,7 @@ class WebrtcCallService : Service() { cameraEnabled = false try { localVideoTrack?.setEnabled(false) - } catch (ignored: Exception) { + } catch (_: Exception) { localVideoTrack = null } try { @@ -2046,11 +2150,6 @@ class WebrtcCallService : Service() { } catch (e: InterruptedException) { e.printStackTrace() } - try { - screenCapturerAndroid?.stopCapture() - } catch (e: InterruptedException) { - e.printStackTrace() - } } executor.execute { val jsonVideoSharingInnerMessage = JsonVideoSharingInnerMessage(cameraEnabled) @@ -2081,13 +2180,14 @@ class WebrtcCallService : Service() { } try { localScreenTrack?.setEnabled(true) - } catch (ignored: Exception) { } + } catch (_: Exception) { + } } else { screenShareActive = false try { screenCapturerAndroid?.stopCapture() localScreenTrack?.setEnabled(false) - } catch (ignored: InterruptedException) { + } catch (_: InterruptedException) { } finally { screenCapturerAndroid?.dispose() screenCapturerAndroid = null @@ -2103,15 +2203,20 @@ class WebrtcCallService : Service() { fun flipCamera() { if (availableCameras.size > 1) { - val currentIndex = availableCameras.indexOfFirst { it.cameraId == selectedCamera?.cameraId } + val currentIndex = + availableCameras.indexOfFirst { it.cameraId == selectedCamera?.cameraId } val newIndex = (currentIndex + 1) % availableCameras.size - val cameraAndFormat = availableCameras.get(newIndex) + val cameraAndFormat = availableCameras[newIndex] selectedCamera = cameraAndFormat selectedCameraLiveData.postValue(selectedCamera) (videoCapturer as? CameraVideoCapturer)?.let { it.switchCamera(object : CameraVideoCapturer.CameraSwitchHandler { override fun onCameraSwitchDone(p0: Boolean) { - it.changeCaptureFormat(cameraAndFormat.captureFormat.width, cameraAndFormat.captureFormat.height, 30) + it.changeCaptureFormat( + cameraAndFormat.captureFormat.width, + cameraAndFormat.captureFormat.height, + 30 + ) } override fun onCameraSwitchError(p0: String?) {} @@ -2136,7 +2241,11 @@ class WebrtcCallService : Service() { this, WebrtcPeerConnectionHolder.videoSource?.capturerObserver ) - videoCapturer!!.startCapture(selectedCamera?.captureFormat?.width ?: 1280, selectedCamera?.captureFormat?.height ?: 720, 30) + videoCapturer!!.startCapture( + selectedCamera?.captureFormat?.width ?: 1280, + selectedCamera?.captureFormat?.height ?: 720, + 30 + ) } private var videoCapturer: VideoCapturer? = null @@ -2145,14 +2254,16 @@ class WebrtcCallService : Service() { private fun createVideoCapturer(context: Context): VideoCapturer { val capturer = selectedCamera?.let { val cameraEnumerator = - if (Camera2Enumerator.isSupported(context)) Camera2Enumerator(context) else Camera1Enumerator(true) + if (Camera2Enumerator.isSupported(context)) Camera2Enumerator(context) else Camera1Enumerator( + true + ) cameraEnumerator.createCapturer(it.cameraId, null) } if (capturer == null) { Logger.e("No selected camera, unable to create video capturer") throw Exception() } - return capturer + return capturer } fun setScreenSize(width: Int, height: Int) { @@ -2165,7 +2276,7 @@ class WebrtcCallService : Service() { screenCapturerAndroid = ScreenCapturerAndroid(intent, object : MediaProjection.Callback() { override fun onCapturedContentResize(width: Int, height: Int) { super.onCapturedContentResize(width, height) - screenCapturerAndroid?.changeCaptureFormat(width, height, 0); + screenCapturerAndroid?.changeCaptureFormat(width, height, 0) } override fun onStop() { @@ -2216,9 +2327,18 @@ class WebrtcCallService : Service() { reconnectingStreamId?.let { soundPool?.stop(it) } + doubleCallStreamId?.let { + soundPool?.stop(it) + doubleCallStreamId = null + } soundPool + } else { + if (queuedIncomingCalls.isNotEmpty() && role != NONE) { + playDoubleCallSound() + } } + @Suppress("DEPRECATION") when (audioOutput) { PHONE, HEADSET, MUTED -> if (audioManager!!.isSpeakerphoneOn) { audioManager!!.isSpeakerphoneOn = false @@ -2249,7 +2369,7 @@ class WebrtcCallService : Service() { // region Helper methods fun shouldISendTheOfferToCallParticipant(callParticipant: CallParticipant): Boolean { - return BytesKey(bytesOwnedIdentity).compareTo(BytesKey(callParticipant.bytesContactIdentity)) > 0 + return BytesKey(bytesOwnedIdentity) > BytesKey(callParticipant.bytesContactIdentity) } fun synchronizeOnExecutor(runnable: Runnable) { @@ -2318,12 +2438,7 @@ class WebrtcCallService : Service() { } } if (allPeersAreInFinalState) { - createLogEntry(CallLogItem.STATUS_MISSED) // this only create the log if it was not yet created - if (_state != CALL_ENDED && selectedAudioOutput != MUTED) { - soundPool?.play(disconnectSound, 1f, 1f, 0, 0, 1f) - } - setState(CALL_ENDED) - stopThisService() + hangUpCallInternal(false) } } @@ -2368,8 +2483,20 @@ class WebrtcCallService : Service() { val backCameraId = cameras.firstOrNull { cameraEnumerator.isBackFacing(it) } try { availableCameras = listOfNotNull( - frontCameraId?.let { CameraAndFormat(it, true, getFormatForResolution(cameraEnumerator, it, targetResolution)) }, - backCameraId?.let { CameraAndFormat(it, false, getFormatForResolution(cameraEnumerator, it, targetResolution)) }, + frontCameraId?.let { + CameraAndFormat( + it, + true, + getFormatForResolution(cameraEnumerator, it, targetResolution) + ) + }, + backCameraId?.let { + CameraAndFormat( + it, + false, + getFormatForResolution(cameraEnumerator, it, targetResolution) + ) + }, ) } catch (e: Exception) { e.printStackTrace() @@ -2381,8 +2508,15 @@ class WebrtcCallService : Service() { } } - private fun getFormatForResolution(cameraEnumerator: CameraEnumerator, cameraId: String, targetResolution: Int) : CameraEnumerationAndroid.CaptureFormat { - return cameraEnumerator.getSupportedFormats(cameraId).sortedWith(compareByDescending { it.height }.then(compareByDescending { it.width })).first { it.height <= targetResolution && (it.width <= it.height*16f/9f + 10) } + private fun getFormatForResolution( + cameraEnumerator: CameraEnumerator, + cameraId: String, + targetResolution: Int + ): CameraEnumerationAndroid.CaptureFormat { + return cameraEnumerator.getSupportedFormats(cameraId).sortedWith( + compareByDescending { it.height }.then( + compareByDescending { it.width }) + ).first { it.height <= targetResolution && (it.width <= it.height * 16f / 9f + 10) } } private fun sendDataChannelMessage( @@ -2425,87 +2559,153 @@ class WebrtcCallService : Service() { } } - private fun createLogEntry(callLogItemStatus: Int) { - if (callLogItem != null) { - // a call log entry was already created, don't create a new one - return - } - if (callParticipants.isEmpty()) { - return + // if call is passed, then this is always for a queued incoming call + private fun createLogEntry(callLogItemStatus: Int, call: Call? = null) { + if (call == null) { + if (callLogItem != null) { + // a call log entry was already created, don't create a new one + return + } + if (callParticipants.isEmpty()) { + return + } } - val callParticipants = callParticipants.values.toTypedArray() - val type = if (isCaller) CallLogItem.TYPE_OUTGOING else CallLogItem.TYPE_INCOMING + val type = if (call == null && isCaller) CallLogItem.TYPE_OUTGOING else CallLogItem.TYPE_INCOMING var callLogItem: CallLogItem? = null when (callLogItemStatus) { - CallLogItem.STATUS_SUCCESSFUL, CallLogItem.STATUS_MISSED, CallLogItem.STATUS_BUSY, CallLogItem.STATUS_FAILED, CallLogItem.STATUS_REJECTED, CallLogItem.STATUS_ANSWERED_ON_OTHER_DEVICE, CallLogItem.STATUS_REJECTED_ON_OTHER_DEVICE -> callLogItem = - CallLogItem( - bytesOwnedIdentity!!, bytesGroupOwnerAndUidOrIdentifier, type, callLogItemStatus - ) - } - if (callLogItem != null) { - this.callLogItem = callLogItem - App.runThread { - this.callLogItem!!.id = - AppDatabase.getInstance().callLogItemDao().insert(this.callLogItem) - val callLogItemContactJoins = - arrayOfNulls(callParticipants.size) - for (i in callParticipants.indices) { - callLogItemContactJoins[i] = CallLogItemContactJoin( - this.callLogItem!!.id, - bytesOwnedIdentity!!, - callParticipants[i].bytesContactIdentity + CallLogItem.STATUS_SUCCESSFUL, + CallLogItem.STATUS_MISSED, + CallLogItem.STATUS_BUSY, + CallLogItem.STATUS_FAILED, + CallLogItem.STATUS_REJECTED, + CallLogItem.STATUS_ANSWERED_ON_OTHER_DEVICE, + CallLogItem.STATUS_REJECTED_ON_OTHER_DEVICE -> + if (call == null) { + if (bytesOwnedIdentity != null) { + callLogItem = CallLogItem( + bytesOwnedIdentity!!, + bytesGroupOwnerAndUidOrIdentifier, + type, + callLogItemStatus + ) + } + } else { + callLogItem = CallLogItem( + call.bytesOwnedIdentity, + call.bytesGroupOwnerAndUidOrIdentifier, + type, + callLogItemStatus ) } - AppDatabase.getInstance().callLogItemDao().insert(*callLogItemContactJoins) - if (this.callLogItem!!.callType == CallLogItem.TYPE_INCOMING - && (this.callLogItem!!.callStatus == CallLogItem.STATUS_MISSED || this.callLogItem!!.callStatus == CallLogItem.STATUS_FAILED || this.callLogItem!!.callStatus == CallLogItem.STATUS_BUSY) - ) { - for (callParticipant in callParticipants) { - if (callParticipant.role == CALLER) { - AndroidNotificationManager.displayMissedCallNotification( - bytesOwnedIdentity!!, - callParticipant.bytesContactIdentity - ) - break + } + callLogItem?.let { + if (call == null) { + this.callLogItem = it + it.insert(callParticipants.values.toList().map { callParticipant -> ParticipantBytesAndRole(callParticipant.bytesContactIdentity, callParticipant.role) }) + } else { + it.insert(listOf(ParticipantBytesAndRole(call.callerContact.bytesContactIdentity, CALLER))) + } + } + } + + private fun CallLogItem.insert(callParticipants: List) { + App.runThread { + id = AppDatabase.getInstance().callLogItemDao().insert(this) + val callLogItemContactJoins = + arrayOfNulls(callParticipants.size) + for (i in callParticipants.indices) { + callLogItemContactJoins[i] = CallLogItemContactJoin( + id, + bytesOwnedIdentity, + callParticipants[i].bytesContactIdentity + ) + } + AppDatabase.getInstance().callLogItemDao().insert(*callLogItemContactJoins) + if (callType == CallLogItem.TYPE_INCOMING + && (callStatus == CallLogItem.STATUS_MISSED || callStatus == CallLogItem.STATUS_FAILED || callStatus == CallLogItem.STATUS_BUSY) + ) { + for (callParticipant in callParticipants) { + if (callParticipant.role == CALLER) { + AndroidNotificationManager.displayMissedCallNotification( + bytesOwnedIdentity, + callParticipant.bytesContactIdentity + ) + break + } + } + } + if (callType == CallLogItem.TYPE_OUTGOING) { + if (bytesGroupOwnerAndUidOrIdentifier != null) { + // group discussion + val discussion = AppDatabase.getInstance().discussionDao() + .getByGroupOwnerAndUidOrIdentifier( + bytesOwnedIdentity, + bytesGroupOwnerAndUidOrIdentifier + ) + if (discussion != null) { + val callMessage = Message.createPhoneCallMessage( + AppDatabase.getInstance(), + discussion.id, + bytesOwnedIdentity, + this + ) + AppDatabase.getInstance().messageDao().insert(callMessage) + if (discussion.updateLastMessageTimestamp(callMessage.timestamp)) { + AppDatabase.getInstance().discussionDao() + .updateLastMessageTimestamp( + discussion.id, + discussion.lastMessageTimestamp + ) + } + } + } else if (callParticipants.size == 1) { + // one-to-one discussion + val discussion = AppDatabase.getInstance().discussionDao().getByContact( + bytesOwnedIdentity, + callParticipants[0].bytesContactIdentity + ) + if (discussion != null) { + val callMessage = Message.createPhoneCallMessage( + AppDatabase.getInstance(), + discussion.id, + callParticipants[0].bytesContactIdentity, + this + ) + AppDatabase.getInstance().messageDao().insert(callMessage) + if (discussion.updateLastMessageTimestamp(callMessage.timestamp)) { + AppDatabase.getInstance().discussionDao() + .updateLastMessageTimestamp( + discussion.id, + discussion.lastMessageTimestamp + ) } } } - if (this.callLogItem!!.callType == CallLogItem.TYPE_OUTGOING) { - if (this.callLogItem!!.bytesGroupOwnerAndUidOrIdentifier != null) { - // group discussion - val discussion = AppDatabase.getInstance().discussionDao() - .getByGroupOwnerAndUidOrIdentifier( - bytesOwnedIdentity, - this.callLogItem!!.bytesGroupOwnerAndUidOrIdentifier - ) - if (discussion != null) { - val callMessage = Message.createPhoneCallMessage( - AppDatabase.getInstance(), - discussion.id, + // for multi-call without a discussion, we do not insert a message in any discussion + } else { + // find the caller, then insert either in a group discussion, or in his one-to-one discussion + for (callParticipant in callParticipants) { + if (callParticipant.role == CALLER) { + var discussion: Discussion? = null + if (bytesGroupOwnerAndUidOrIdentifier != null) { + discussion = AppDatabase.getInstance().discussionDao() + .getByGroupOwnerAndUidOrIdentifier( + bytesOwnedIdentity, + bytesGroupOwnerAndUidOrIdentifier + ) + } + if (discussion == null) { + discussion = AppDatabase.getInstance().discussionDao().getByContact( bytesOwnedIdentity, - this.callLogItem + callParticipant.bytesContactIdentity ) - AppDatabase.getInstance().messageDao().insert(callMessage) - if (discussion.updateLastMessageTimestamp(callMessage.timestamp)) { - AppDatabase.getInstance().discussionDao() - .updateLastMessageTimestamp( - discussion.id, - discussion.lastMessageTimestamp - ) - } } - } else if (callParticipants.size == 1) { - // one-to-one discussion - val discussion = AppDatabase.getInstance().discussionDao().getByContact( - bytesOwnedIdentity, - callParticipants[0].bytesContactIdentity - ) if (discussion != null) { val callMessage = Message.createPhoneCallMessage( AppDatabase.getInstance(), discussion.id, - callParticipants[0].bytesContactIdentity, - this.callLogItem + callParticipant.bytesContactIdentity, + this ) AppDatabase.getInstance().messageDao().insert(callMessage) if (discussion.updateLastMessageTimestamp(callMessage.timestamp)) { @@ -2516,44 +2716,7 @@ class WebrtcCallService : Service() { ) } } - } - // for multi-call without a discussion, we do not insert a message in any discussion - } else { - // find the caller, then insert either in a group discussion, or in his one-to-one discussion - for (callParticipant in callParticipants) { - if (callParticipant.role == CALLER) { - var discussion: Discussion? = null - if (this.callLogItem!!.bytesGroupOwnerAndUidOrIdentifier != null) { - discussion = AppDatabase.getInstance().discussionDao() - .getByGroupOwnerAndUidOrIdentifier( - bytesOwnedIdentity, - this.callLogItem!!.bytesGroupOwnerAndUidOrIdentifier - ) - } - if (discussion == null) { - discussion = AppDatabase.getInstance().discussionDao().getByContact( - bytesOwnedIdentity, - callParticipant.bytesContactIdentity - ) - } - if (discussion != null) { - val callMessage = Message.createPhoneCallMessage( - AppDatabase.getInstance(), - discussion.id, - callParticipant.bytesContactIdentity, - this.callLogItem - ) - AppDatabase.getInstance().messageDao().insert(callMessage) - if (discussion.updateLastMessageTimestamp(callMessage.timestamp)) { - AppDatabase.getInstance().discussionDao() - .updateLastMessageTimestamp( - discussion.id, - discussion.lastMessageTimestamp - ) - } - } - break - } + break } } } @@ -2561,20 +2724,24 @@ class WebrtcCallService : Service() { } private fun updateLogEntry(newCallParticipants: List) { - if (callLogItem == null || newCallParticipants.isEmpty()) { + if (newCallParticipants.isEmpty()) { return } - App.runThread { - val callLogItemContactJoins = - arrayOfNulls(newCallParticipants.size) - for (i in newCallParticipants.indices) { - callLogItemContactJoins[i] = CallLogItemContactJoin( - callLogItem!!.id, - bytesOwnedIdentity!!, - newCallParticipants[i].bytesContactIdentity - ) + bytesOwnedIdentity?.let { boi -> + callLogItem?.let { + App.runThread { + val callLogItemContactJoins = + arrayOfNulls(newCallParticipants.size) + for (i in newCallParticipants.indices) { + callLogItemContactJoins[i] = CallLogItemContactJoin( + it.id, + boi, + newCallParticipants[i].bytesContactIdentity + ) + } + AppDatabase.getInstance().callLogItemDao().insert(*callLogItemContactJoins) + } } - AppDatabase.getInstance().callLogItemDao().insert(*callLogItemContactJoins) } } @@ -2604,12 +2771,14 @@ class WebrtcCallService : Service() { @SuppressLint("ForegroundServiceType") private fun showOngoingForeground() { if (callParticipants.isEmpty()) { + @Suppress("DEPRECATION") stopForeground(true) return } val endCallIntent = Intent(this, WebrtcCallService::class.java) endCallIntent.setAction(ACTION_HANG_UP) endCallIntent.putExtra(CALL_IDENTIFIER_INTENT_EXTRA, Logger.getUuidString(callIdentifier)) + endCallIntent.putExtra(BYTES_OWNED_IDENTITY_INTENT_EXTRA, bytesOwnedIdentity) val endCallPendingIntent = PendingIntent.getService( this, 0, @@ -2742,13 +2911,21 @@ class WebrtcCallService : Service() { } @SuppressLint("ForegroundServiceType", "MissingPermission") - private fun showIncomingCallForeground(contact: Contact?, participantCount: Int) { + private fun showIncomingCallForeground( + callIdentifier: UUID, + contact: Contact, + participantCount: Int + ) { val rejectCallIntent = Intent(this, WebrtcCallService::class.java) rejectCallIntent.setAction(ACTION_REJECT_CALL) rejectCallIntent.putExtra( CALL_IDENTIFIER_INTENT_EXTRA, Logger.getUuidString(callIdentifier) ) + rejectCallIntent.putExtra( + BYTES_OWNED_IDENTITY_INTENT_EXTRA, + contact.bytesOwnedIdentity + ) val rejectCallPendingIntent = PendingIntent.getService( this, 0, @@ -2756,11 +2933,9 @@ class WebrtcCallService : Service() { PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE ) val answerCallIntent = Intent(this, WebrtcCallActivity::class.java) - answerCallIntent.setAction(WebrtcCallActivity.ANSWER_CALL_ACTION) - answerCallIntent.putExtra( - WebrtcCallActivity.ANSWER_CALL_EXTRA_CALL_IDENTIFIER, - Logger.getUuidString(callIdentifier) - ) + answerCallIntent.setAction(ANSWER_CALL_ACTION) + answerCallIntent.putExtra(WebrtcCallActivity.ANSWER_CALL_EXTRA_CALL_IDENTIFIER, Logger.getUuidString(callIdentifier)) + answerCallIntent.putExtra(BYTES_OWNED_IDENTITY_INTENT_EXTRA, contact.bytesOwnedIdentity) answerCallIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) val answerCallPendingIntent = PendingIntent.getActivity( this, @@ -2778,7 +2953,7 @@ class WebrtcCallService : Service() { val initialView = InitialView(App.getContext()) val size = App.getContext().resources.getDimensionPixelSize(dimen.notification_icon_size) initialView.setSize(size, size) - initialView.setContact(contact!!) + initialView.setContact(contact) val largeIcon = Bitmap.createBitmap(size, size, ARGB_8888) initialView.drawOnCanvas(Canvas(largeIcon)) if (VERSION.SDK_INT >= VERSION_CODES.S) { @@ -2872,7 +3047,7 @@ class WebrtcCallService : Service() { builder.setLargeIcon(largeIcon) val redReject = SpannableString(getString(string.notification_action_reject)) redReject.setSpan( - ForegroundColorSpan(resources.getColor(color.red)), + ForegroundColorSpan(ContextCompat.getColor(this, color.red)), 0, redReject.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE @@ -2880,7 +3055,7 @@ class WebrtcCallService : Service() { builder.addAction(drawable.ic_end_call, redReject, rejectCallPendingIntent) val greenAccept = SpannableString(getString(string.notification_action_accept)) greenAccept.setSpan( - ForegroundColorSpan(resources.getColor(color.green)), + ForegroundColorSpan(ContextCompat.getColor(this, color.green)), 0, greenAccept.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE @@ -2947,24 +3122,38 @@ class WebrtcCallService : Service() { ) } + private fun resetCallLogItem() { + callLogItem?.let { + if (it.callStatus == CallLogItem.STATUS_SUCCESSFUL && callDuration.value != null) { + it.duration = callDuration.value!! + + + App.runThread { + AppDatabase.getInstance().callLogItemDao().update(it) + } + } + callLogItem = null + callDuration.postValue(0) + } + } + override fun onDestroy() { super.onDestroy() executor.shutdownNow() - if (callLogItem != null && callLogItem!!.callStatus == CallLogItem.STATUS_SUCCESSFUL && callDuration.value != null) { - callLogItem!!.duration = callDuration.value!! - App.runThread { AppDatabase.getInstance().callLogItemDao().update(callLogItem) } - } + resetCallLogItem() outgoingCallRinger?.stop() incomingCallRinger?.stop() soundPool?.release() try { videoCapturer?.stopCapture() - } catch (ignored: InterruptedException) { } + } catch (_: InterruptedException) { + } videoCapturer?.dispose() videoCapturer = null try { screenCapturerAndroid?.stopCapture() - } catch (ignored: InterruptedException) { } + } catch (_: InterruptedException) { + } screenCapturerAndroid?.dispose() screenCapturerAndroid = null unregisterScreenOffReceiver() @@ -2985,6 +3174,7 @@ class WebrtcCallService : Service() { } if (audioManager != null && audioFocusRequest != null) { AudioManagerCompat.abandonAudioFocusRequest(audioManager!!, audioFocusRequest!!) + @Suppress("DEPRECATION") audioManager!!.isSpeakerphoneOn = false audioManager!!.mode = savedAudioManagerMode } @@ -3034,7 +3224,7 @@ class WebrtcCallService : Service() { private inner class ScreenOffReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - incomingCallRinger!!.stop() + incomingCallRinger?.stop() } } @@ -3089,7 +3279,7 @@ class WebrtcCallService : Service() { userInfo[EngineNotifications.TURN_CREDENTIALS_RECEIVED_USERNAME_2_KEY] as String? val recipientPassword = userInfo[EngineNotifications.TURN_CREDENTIALS_RECEIVED_PASSWORD_2_KEY] as String? - val turnServers = + @Suppress("UNCHECKED_CAST") val turnServers = userInfo[EngineNotifications.TURN_CREDENTIALS_RECEIVED_SERVERS_KEY] as List? if (callerUsername == null || callerPassword == null || recipientUsername == null || recipientPassword == null || turnServers == null) { callerFailedTurnCredentials(UNABLE_TO_CONTACT_SERVER) @@ -3177,8 +3367,12 @@ class WebrtcCallService : Service() { } if (lockWifi) { val wifiManager = applicationContext.getSystemService(WIFI_SERVICE) as WifiManager? + @Suppress("DEPRECATION") wifiLock = wifiManager?.createWifiLock( - WifiManager.WIFI_MODE_FULL_HIGH_PERF, + if (VERSION.SDK_INT >= VERSION_CODES.Q) + WifiManager.WIFI_MODE_FULL_LOW_LATENCY + else + WifiManager.WIFI_MODE_FULL_HIGH_PERF, "io.olvid:wifi_lock" )?.apply { acquire() } } @@ -3316,7 +3510,7 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" ) } } - } catch (ignored: IOException) { + } catch (_: IOException) { // failed to serialize inner message } } @@ -3348,7 +3542,7 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" ) } } - } catch (ignored: IOException) { + } catch (_: IOException) { // failed to serialize inner message } } @@ -3375,75 +3569,83 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" } } - private fun sendRingingMessage(callParticipant: CallParticipant) { - postMessage(listOf(callParticipant), JsonRingingMessage()) + private fun sendRingingMessage(call: Call) { + postMessage( + JsonRingingMessage(), + call.bytesOwnedIdentity, + listOf(call.callerContact.bytesContactIdentity), + call.callIdentifier + ) } - private fun sendRejectCallMessage(callParticipant: CallParticipant) { - postMessage(listOf(callParticipant), JsonRejectCallMessage()) - if (AppDatabase.getInstance().ownedDeviceDao() - .doesOwnedIdentityHaveAnotherDeviceWithChannel(bytesOwnedIdentity) - ) { + private fun sendRejectCallMessage(call: Call) { + postMessage( + JsonRejectCallMessage(), + call.bytesOwnedIdentity, + listOf(call.callerContact.bytesContactIdentity), + call.callIdentifier + ) + if (AppDatabase.getInstance().ownedDeviceDao().doesOwnedIdentityHaveAnotherDeviceWithChannel(call.bytesOwnedIdentity)) { postMessage( JsonAnsweredOrRejectedOnOtherDeviceMessage(false), - bytesOwnedIdentity, - listOf(bytesOwnedIdentity), - callIdentifier + call.bytesOwnedIdentity, + listOf(call.bytesOwnedIdentity), + call.callIdentifier ) } } - private fun sendBusyMessage( - bytesOwnedIdentity: ByteArray?, - bytesContactIdentity: ByteArray?, - callIdentifier: UUID?, - bytesGroupOwnerAndUid: ByteArray? - ) { - App.runThread { - val callLogItem = CallLogItem( - bytesOwnedIdentity!!, - bytesGroupOwnerAndUid, - CallLogItem.TYPE_INCOMING, - CallLogItem.STATUS_BUSY - ) - callLogItem.id = AppDatabase.getInstance().callLogItemDao().insert(callLogItem) - val callLogItemContactJoin = - CallLogItemContactJoin(callLogItem.id, bytesOwnedIdentity, bytesContactIdentity!!) - AppDatabase.getInstance().callLogItemDao().insert(callLogItemContactJoin) - AndroidNotificationManager.displayMissedCallNotification( - bytesOwnedIdentity, - bytesContactIdentity - ) - postMessage( - JsonBusyMessage(), - bytesOwnedIdentity, - listOf(bytesContactIdentity), - callIdentifier - ) - var discussion: Discussion? = null - if (bytesGroupOwnerAndUid != null) { - discussion = AppDatabase.getInstance().discussionDao() - .getByGroupOwnerAndUidOrIdentifier(bytesOwnedIdentity, bytesGroupOwnerAndUid) - } - if (discussion == null) { - discussion = AppDatabase.getInstance().discussionDao() - .getByContact(bytesOwnedIdentity, bytesContactIdentity) - } - if (discussion != null) { - val busyCallMessage = Message.createPhoneCallMessage( - AppDatabase.getInstance(), - discussion.id, - bytesContactIdentity, - callLogItem - ) - AppDatabase.getInstance().messageDao().insert(busyCallMessage) - if (discussion.updateLastMessageTimestamp(busyCallMessage.timestamp)) { - AppDatabase.getInstance().discussionDao() - .updateLastMessageTimestamp(discussion.id, discussion.lastMessageTimestamp) - } - } - } - } +// private fun sendBusyMessage( +// bytesOwnedIdentity: ByteArray?, +// bytesContactIdentity: ByteArray?, +// callIdentifier: UUID?, +// bytesGroupOwnerAndUid: ByteArray? +// ) { +// App.runThread { +// val callLogItem = CallLogItem( +// bytesOwnedIdentity!!, +// bytesGroupOwnerAndUid, +// CallLogItem.TYPE_INCOMING, +// CallLogItem.STATUS_BUSY +// ) +// callLogItem.id = AppDatabase.getInstance().callLogItemDao().insert(callLogItem) +// val callLogItemContactJoin = +// CallLogItemContactJoin(callLogItem.id, bytesOwnedIdentity, bytesContactIdentity!!) +// AppDatabase.getInstance().callLogItemDao().insert(callLogItemContactJoin) +// AndroidNotificationManager.displayMissedCallNotification( +// bytesOwnedIdentity, +// bytesContactIdentity +// ) +// postMessage( +// JsonBusyMessage(), +// bytesOwnedIdentity, +// listOf(bytesContactIdentity), +// callIdentifier +// ) +// var discussion: Discussion? = null +// if (bytesGroupOwnerAndUid != null) { +// discussion = AppDatabase.getInstance().discussionDao() +// .getByGroupOwnerAndUidOrIdentifier(bytesOwnedIdentity, bytesGroupOwnerAndUid) +// } +// if (discussion == null) { +// discussion = AppDatabase.getInstance().discussionDao() +// .getByContact(bytesOwnedIdentity, bytesContactIdentity) +// } +// if (discussion != null) { +// val busyCallMessage = Message.createPhoneCallMessage( +// AppDatabase.getInstance(), +// discussion.id, +// bytesContactIdentity, +// callLogItem +// ) +// AppDatabase.getInstance().messageDao().insert(busyCallMessage) +// if (discussion.updateLastMessageTimestamp(busyCallMessage.timestamp)) { +// AppDatabase.getInstance().discussionDao() +// .updateLastMessageTimestamp(discussion.id, discussion.lastMessageTimestamp) +// } +// } +// } +// } @Throws(IOException::class) fun sendReconnectCallMessage( @@ -3570,13 +3772,18 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" protocolMessage: JsonWebrtcProtocolMessage ): Boolean { val bytesContactIdentities: MutableList = ArrayList(callParticipants.size) + var callId = callIdentifier + var ownedIdentity = this.bytesOwnedIdentity for (callParticipant in callParticipants) { if (callParticipant.contact != null && callParticipant.contact.hasChannelOrPreKey()) { bytesContactIdentities.add(callParticipant.bytesContactIdentity) } + // get call identifier from participant + callId = callParticipant.callIdentifier + ownedIdentity = callParticipant.bytesOwnedIdentity } - return if (bytesContactIdentities.size > 0) { - postMessage(protocolMessage, bytesOwnedIdentity, bytesContactIdentities, callIdentifier) + return if (bytesContactIdentities.isNotEmpty()) { + postMessage(protocolMessage, ownedIdentity, bytesContactIdentities, callId) } else false } @@ -3627,7 +3834,10 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" sendDataChannelMessage(callParticipant, JsonMutedInnerMessage(microphoneMuted)) sendDataChannelMessage(callParticipant, JsonVideoSupportedInnerMessage(true)) sendDataChannelMessage(callParticipant, JsonVideoSharingInnerMessage(cameraEnabled)) - sendDataChannelMessage(callParticipant, JsonScreenSharingInnerMessage(screenShareActive)) + sendDataChannelMessage( + callParticipant, + JsonScreenSharingInnerMessage(screenShareActive) + ) if (isCaller) { sendDataChannelMessage( callParticipant, @@ -3681,7 +3891,10 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" jsonDataChannelMessage.serializedMessage, JsonVideoSupportedInnerMessage::class.java ) - if (jsonVideoSupportedInnerMessage.isVideoSupported && shouldISendTheOfferToCallParticipant(callParticipant)) { + if (jsonVideoSupportedInnerMessage.isVideoSupported && shouldISendTheOfferToCallParticipant( + callParticipant + ) + ) { executor.execute { Logger.d("☎ received video supported message (${jsonVideoSupportedInnerMessage.isVideoSupported})") callParticipant.setPeerVideoIsSupported( @@ -3742,11 +3955,15 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" val serializedMessagePayload = jsonRelayedInnerMessage.serializedMessagePayload executor.execute { - handleMessage( - bytesContactIdentity, - messageType, - serializedMessagePayload - ) + if (bytesOwnedIdentity != null && callIdentifier != null) { + handleMessage( + bytesOwnedIdentity!!, + bytesContactIdentity, + messageType, + serializedMessagePayload, + callIdentifier!! + ) + } } } @@ -3764,6 +3981,8 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" inner class CallParticipant { internal val role: Role + val callIdentifier: UUID + val bytesOwnedIdentity: ByteArray? @JvmField val bytesContactIdentity: ByteArray @@ -3789,11 +4008,15 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" var timeoutTask: TimerTask? constructor( + callIdentifier: UUID, bytesOwnedIdentity: ByteArray?, bytesContactIdentity: ByteArray, displayName: String, gatheringPolicy: GatheringPolicy ) { + + this.callIdentifier = callIdentifier + this.bytesOwnedIdentity = bytesOwnedIdentity this.role = RECIPIENT this.bytesContactIdentity = bytesContactIdentity contact = @@ -3817,8 +4040,10 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" addUncalledReceivedIceCandidates() } - constructor(contact: Contact, contactRole: Role) { + constructor(callIdentifier: UUID, contact: Contact, contactRole: Role) { this.role = contactRole + this.callIdentifier = callIdentifier + this.bytesOwnedIdentity = contact.bytesOwnedIdentity bytesContactIdentity = contact.bytesContactIdentity this.contact = contact gatheringPolicy = @@ -3845,6 +4070,9 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" if (candidates != null) { peerConnectionHolder.addIceCandidates(candidates) } + if (map.isEmpty()) { + uncalledReceivedIceCandidates.remove(callIdentifier) + } } } @@ -3901,7 +4129,7 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" } override fun hashCode(): Int { - return Arrays.hashCode(bytesContactIdentity) + return bytesContactIdentity.contentHashCode() } override fun equals(other: Any?): Boolean { @@ -3911,6 +4139,8 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" } } + data class ParticipantBytesAndRole(val bytesContactIdentity: ByteArray, val role: Role) + fun getAudioLevel(bytesIdentity: ByteArray?): Double? { if (bytesIdentity == null) return null return if (bytesIdentity.contentEquals(bytesOwnedIdentity)) @@ -3921,39 +4151,25 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" class CallParticipantPojo(callParticipant: CallParticipant) : Comparable { @JvmField - val bytesContactIdentity: ByteArray + val bytesContactIdentity: ByteArray = callParticipant.bytesContactIdentity @JvmField - val contact: Contact? + val contact: Contact? = callParticipant.contact @JvmField - val displayName: String? + val displayName: String? = callParticipant.displayName @JvmField - val peerIsMuted: Boolean + val peerIsMuted: Boolean = callParticipant._peerIsMuted @JvmField - val peerVideoSharing: Boolean + val peerVideoSharing: Boolean = callParticipant._peerVideoSharing @JvmField - val peerScreenSharing: Boolean + val peerScreenSharing: Boolean = callParticipant._peerScreenSharing @JvmField - val peerVideoIsSupported: Boolean - - @JvmField - val peerState: PeerState - - init { - bytesContactIdentity = callParticipant.bytesContactIdentity - contact = callParticipant.contact - displayName = callParticipant.displayName - peerIsMuted = callParticipant._peerIsMuted - peerVideoSharing = callParticipant._peerVideoSharing - peerScreenSharing = callParticipant._peerScreenSharing - peerVideoIsSupported = callParticipant._peerVideoIsSupported - peerState = callParticipant.peerState - } + val peerState: PeerState = callParticipant.peerState override fun compareTo(other: CallParticipantPojo): Int { val myName = contact?.getCustomDisplayName() ?: displayName ?: "" @@ -3963,11 +4179,12 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" } // device orientation change listener for screen capture on API < 34 - private val orientationChangeBroadcastReceiver = object: BroadcastReceiver() { + private val orientationChangeBroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { context?.resources?.configuration?.let { configuration -> if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT && screenWidth > screenHeight - || configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && screenWidth < screenHeight) { + || configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && screenWidth < screenHeight + ) { // swap both values val tmp = screenHeight screenHeight = screenWidth @@ -3981,13 +4198,17 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" } private fun registerDeviceOrientationChange() { - registerReceiver(orientationChangeBroadcastReceiver, IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED)) + registerReceiver( + orientationChangeBroadcastReceiver, + IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED) + ) } private fun unregisterDeviceOrientationChange() { try { unregisterReceiver(orientationChangeBroadcastReceiver) - } catch (ignored: Exception) { } + } catch (_: Exception) { + } } data class CameraAndFormat( @@ -4047,8 +4268,7 @@ ${jsonIceCandidate.sdpMLineIndex} -> ${jsonIceCandidate.sdp}""" // HashMap containing ICE candidates received while outside a call: callIdentifier -> (bytesContactIdentity -> candidate) // with continuous gathering, we may send/receive candidates before actually sending/receiving the startCall message - private val uncalledReceivedIceCandidates = - HashMap>>() - private val uncalledAnsweredOrRejectedOnOtherDevice = HashMap() + private val uncalledReceivedIceCandidates = HashMap>>() // TODO: Use ownedIdentity in key too + private val uncalledAnsweredOrRejectedOnOtherDevice = HashMap() // TODO: Use ownedIdentity in key too } } diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcIncomingCallActivity.java b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcIncomingCallActivity.java index 7da39708..c1fee9c2 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcIncomingCallActivity.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcIncomingCallActivity.java @@ -34,18 +34,11 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.NotificationManagerCompat; -import androidx.lifecycle.LiveData; import androidx.lifecycle.Observer; -import androidx.lifecycle.Transformations; - -import java.util.List; import io.olvid.engine.Logger; import io.olvid.messenger.R; import io.olvid.messenger.customClasses.InitialView; -import io.olvid.messenger.databases.AppDatabase; -import io.olvid.messenger.databases.entity.Contact; -import io.olvid.messenger.databases.entity.Discussion; import io.olvid.messenger.databases.entity.DiscussionCustomization; import io.olvid.messenger.settings.SettingsActivity; @@ -53,9 +46,7 @@ public class WebrtcIncomingCallActivity extends AppCompatActivity implements Vie WebrtcServiceConnection webrtcServiceConnection; WebrtcCallService webrtcCallService = null; - CallParticipantsObserver callParticipantsObserver; - CallStatusObserver callStatusObserver; - DiscussionCustomizationObserver discussionCustomizationObserver; + CallObserver callObserver; InitialView contactInitialView; ImageView contactColorCircleImageView; @@ -65,6 +56,8 @@ public class WebrtcIncomingCallActivity extends AppCompatActivity implements Vie View rejectCallButton; View answerCallButton; + private @Nullable WebrtcCallService.Call currentCall = null; + @Override protected void attachBaseContext(Context baseContext) { super.attachBaseContext(SettingsActivity.overrideContextScales(baseContext)); @@ -82,9 +75,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { Intent serviceBindIntent = new Intent(this, WebrtcCallService.class); bindService(serviceBindIntent, webrtcServiceConnection, 0); - callParticipantsObserver = new CallParticipantsObserver(); - callStatusObserver = new CallStatusObserver(); - discussionCustomizationObserver = new DiscussionCustomizationObserver(); + callObserver = new CallObserver(); setContentView(R.layout.activity_webrtc_incoming_call); @@ -113,86 +104,52 @@ protected void onDestroy() { public void onClick(View v) { int id = v.getId(); if (id == R.id.accept_call_button) { - if (webrtcCallService != null) { + if (currentCall != null) { Intent answerCallIntent = new Intent(this, WebrtcCallActivity.class); answerCallIntent.setAction(WebrtcCallActivity.ANSWER_CALL_ACTION); - answerCallIntent.putExtra(WebrtcCallActivity.ANSWER_CALL_EXTRA_CALL_IDENTIFIER, Logger.getUuidString(webrtcCallService.callIdentifier)); + answerCallIntent.putExtra(WebrtcCallActivity.ANSWER_CALL_EXTRA_CALL_IDENTIFIER, Logger.getUuidString(currentCall.getCallIdentifier())); + answerCallIntent.putExtra(WebrtcCallActivity.ANSWER_CALL_EXTRA_BYTES_OWNED_IDENTITY, currentCall.getBytesOwnedIdentity()); answerCallIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(answerCallIntent); } closeActivity(); } else if (id == R.id.reject_call_button) { - if (webrtcCallService != null) { - webrtcCallService.recipientRejectCall(); + if (webrtcCallService != null && currentCall != null) { + webrtcCallService.recipientRejectCall(currentCall.getBytesOwnedIdentity(), currentCall.getCallIdentifier()); } - closeActivity(); + // do not close activity here, the live data will take car of it } } - private class CallParticipantsObserver implements Observer> { + private class CallObserver implements Observer { @Override - public void onChanged(List callParticipants) { - final Contact callParticipantContact = (callParticipants == null || callParticipants.size() == 0) ? null : callParticipants.get(0).contact; - if (callParticipantContact == null) { - contactInitialView.setVisibility(View.INVISIBLE); - contactNameTextView.setText(null); - othersCountTextView.setVisibility(View.GONE); - bigCountTextView.setVisibility(View.GONE); + public void onChanged(@Nullable WebrtcCallService.Call call) { + currentCall = call; + if (call == null) { + closeActivity(); } else { contactInitialView.setVisibility(View.VISIBLE); - contactInitialView.setContact(callParticipantContact); - contactNameTextView.setText(callParticipantContact.getCustomDisplayName()); - if (webrtcCallService != null) { - int count = webrtcCallService.getIncomingParticipantCount() - 1; - if (count > 0) { - othersCountTextView.setVisibility(View.VISIBLE); - othersCountTextView.setText(getResources().getQuantityString(R.plurals.text_and_x_other, count, count)); - bigCountTextView.setVisibility(View.VISIBLE); - bigCountTextView.setText(getString(R.string.plus_count, count)); - } else { - othersCountTextView.setVisibility(View.GONE); - bigCountTextView.setVisibility(View.GONE); - } - } - } - } - } - - private class CallStatusObserver implements Observer { - @Override - public void onChanged(WebrtcCallService.State state) { - switch (state) { - case INITIAL: - case WAITING_FOR_AUDIO_PERMISSION: - case GETTING_TURN_CREDENTIALS: - case RINGING: - case BUSY: - break; - case CALL_ENDED: - case FAILED: - case INITIALIZING_CALL: - case CONNECTING: - case CALL_IN_PROGRESS: { - closeActivity(); - break; + contactInitialView.setContact(call.getCallerContact()); + contactNameTextView.setText(call.getCallerContact().getCustomDisplayName()); + int count = call.getParticipantCount() - 1; + if (count > 0) { + othersCountTextView.setVisibility(View.VISIBLE); + othersCountTextView.setText(getResources().getQuantityString(R.plurals.text_and_x_other, count, count)); + bigCountTextView.setVisibility(View.VISIBLE); + bigCountTextView.setText(getString(R.string.plus_count, count)); + } else { + othersCountTextView.setVisibility(View.GONE); + bigCountTextView.setVisibility(View.GONE); } - } - } - } - private class DiscussionCustomizationObserver implements Observer { - @Override - public void onChanged(DiscussionCustomization discussionCustomization) { - if (discussionCustomization != null) { - DiscussionCustomization.ColorJson colorJson = discussionCustomization.getColorJson(); + DiscussionCustomization.ColorJson colorJson = call.getDiscussionCustomization() == null ? null : call.getDiscussionCustomization().getColorJson(); if (colorJson != null) { contactColorCircleImageView.setVisibility(View.VISIBLE); contactColorCircleImageView.setColorFilter(0xff000000 + colorJson.color, android.graphics.PorterDuff.Mode.SRC_IN); - return; + } else { + contactColorCircleImageView.setVisibility(View.GONE); } } - - contactColorCircleImageView.setVisibility(View.GONE); } } @@ -215,26 +172,11 @@ private void closeActivity() { private void setWebrtcCallService(WebrtcCallService webrtcCallService) { if (webrtcCallService != null) { this.webrtcCallService = webrtcCallService; - this.webrtcCallService.getCallParticipantsLiveData().observe(this, callParticipantsObserver); - this.webrtcCallService.getState().observe(this, callStatusObserver); - LiveData discussionCustomizationLiveData = Transformations.switchMap(this.webrtcCallService.getCallParticipantsLiveData(), (List callParticipants) -> { - final Contact callParticipantContact = (callParticipants == null || callParticipants.size() == 0) ? null : callParticipants.get(0).contact; - if (callParticipantContact == null) { - return null; - } - return Transformations.switchMap(AppDatabase.getInstance().discussionDao().getByContactLiveData(callParticipantContact.bytesOwnedIdentity, callParticipantContact.bytesContactIdentity), (Discussion discussion) -> { - if (discussion == null) { - return null; - } - return AppDatabase.getInstance().discussionCustomizationDao().getLiveData(discussion.id); - }); - }); - discussionCustomizationLiveData.observe(this, discussionCustomizationObserver); + this.webrtcCallService.getCurrentIncomingCallLiveData().observe(this, callObserver); } else { if (this.webrtcCallService != null) { - // remove observers - this.webrtcCallService.getState().removeObservers(this); - this.webrtcCallService.getCallParticipantsLiveData().removeObservers(this); + // remove observer + this.webrtcCallService.getCurrentIncomingCallLiveData().removeObservers(this); } this.webrtcCallService = null; } diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcPeerConnectionHolder.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcPeerConnectionHolder.kt index 00abacc6..73942410 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcPeerConnectionHolder.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/WebrtcPeerConnectionHolder.kt @@ -93,8 +93,8 @@ import java.net.URI import java.nio.ByteBuffer import java.nio.charset.StandardCharsets import java.util.Timer -import java.util.TimerTask import java.util.regex.Pattern +import kotlin.concurrent.timer import kotlin.text.RegexOption.MULTILINE class WebrtcPeerConnectionHolder( @@ -216,9 +216,8 @@ class WebrtcPeerConnectionHolder( } catch (e: Exception) { e.printStackTrace() } - val userAgentProperty = System.getProperty("http.agent") - if (userAgentProperty != null) { - builder.setUserAgent(userAgentProperty) + System.getProperty("http.agent")?.let { + builder.setUserAgent(it) } peerConnectionFactory = builder.createPeerConnectionFactory() audioSource = peerConnectionFactory?.createAudioSource(MediaConstraints()) @@ -342,54 +341,42 @@ class WebrtcPeerConnectionHolder( private fun startLocalAudioLevelListener() { if (localAudioLevelListener == null) { - localAudioLevelListener = Timer().apply { - schedule(object : TimerTask() { - override fun run() { - try { - peerConnection?.getStats( - audioSender - ) { - (it.statsMap.values.find { it.type == "media-source" }?.members?.getOrDefault( - "audioLevel", - null - ) as? Double)?.let { - if (webrtcCallService.microphoneMuted && webrtcCallService.speakingWhileMuted.not() && it > 0.3) { - webrtcCallService.speakingWhileMuted = true - } - localAudioLevel = if (webrtcCallService.microphoneMuted) 0.0 else it - } - + localAudioLevelListener = timer(period = 200) { + runCatching { + peerConnection?.getStats( + audioSender + ) { report -> + (report.statsMap.values.find { it.type == "media-source" }?.members?.getOrDefault( + "audioLevel", + null + ) as? Double)?.let { + if (webrtcCallService.microphoneMuted && webrtcCallService.speakingWhileMuted.not() && it > 0.3) { + webrtcCallService.speakingWhileMuted = true } - } catch (ignored: Exception) { - cancel() + localAudioLevel = if (webrtcCallService.microphoneMuted) 0.0 else it } + } - }, 0, 200) + }.onFailure { cancel() } } } } private fun startPeerAudioLevelListener() { if (peerAudioLevelListener == null) { - peerAudioLevelListener = Timer().apply { - schedule(object : TimerTask() { - override fun run() { - try { - peerConnection?.getStats( - audioReceiver - ) { - (it.statsMap.values.find { it.type == "inbound-rtp" }?.members?.getOrDefault( - "audioLevel", - null - ) as? Double)?.let { - peerAudioLevel = it - } - } - } catch (ignored: Exception) { - cancel() + peerAudioLevelListener = timer(period = 200) { + runCatching { + peerConnection?.getStats( + audioReceiver + ) { report -> + (report.statsMap.values.find { it.type == "inbound-rtp" }?.members?.getOrDefault( + "audioLevel", + null + ) as? Double)?.let { + peerAudioLevel = it } } - }, 0, 200) + }.onFailure { cancel() } } } } @@ -526,7 +513,7 @@ class WebrtcPeerConnectionHolder( } fun createLocalDescription(reason: String) { - Logger.d("☎ createLocalDescription " + reason) + Logger.d("☎ createLocalDescription $reason") // only called from onRenegotiationNeeded when (peerConnection?.signalingState()) { STABLE -> { diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/components/CallScreen.kt b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/components/CallScreen.kt index 355a59bf..36faed93 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/components/CallScreen.kt +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/webrtc/components/CallScreen.kt @@ -1188,7 +1188,7 @@ private fun VideoCallContent( webrtcCallService.getCallParticipant(participants.firstOrNull()?.bytesContactIdentity)?.peerConnectionHolder?.remoteVideoTrack val remoteScreenTrack = webrtcCallService.getCallParticipant(participants.firstOrNull()?.bytesContactIdentity)?.peerConnectionHolder?.remoteScreenTrack - if (webrtcCallService.selectedParticipant.contentEquals(webrtcCallService.bytesOwnedIdentity!!) + if (webrtcCallService.selectedParticipant.contentEquals(webrtcCallService.bytesOwnedIdentity) .not() ) { CallParticipant( @@ -1209,7 +1209,7 @@ private fun VideoCallContent( .padding(start = 10.dp, top = 10.dp) .clickable { webrtcCallService.selectedParticipant = - webrtcCallService.bytesOwnedIdentity!! + webrtcCallService.bytesOwnedIdentity } .border( width = 2.dp, diff --git a/obv_messenger/app/src/main/java/io/olvid/messenger/widget/ActionShortcutConfigurationActivity.java b/obv_messenger/app/src/main/java/io/olvid/messenger/widget/ActionShortcutConfigurationActivity.java index 53b5fca6..05336152 100644 --- a/obv_messenger/app/src/main/java/io/olvid/messenger/widget/ActionShortcutConfigurationActivity.java +++ b/obv_messenger/app/src/main/java/io/olvid/messenger/widget/ActionShortcutConfigurationActivity.java @@ -399,7 +399,7 @@ private void bindDiscussion(DiscussionDao.DiscussionAndGroupMembersNames discuss discussionInitialView.setDiscussion(discussionAndContactNames.discussion); discussionTitleTextView.setVisibility(View.VISIBLE); - if (discussionAndContactNames.discussion.title.length() == 0) { + if (discussionAndContactNames.discussion.title.isEmpty()) { SpannableString spannableString = new SpannableString(getString(R.string.text_unnamed_discussion)); spannableString.setSpan(new StyleSpan(Typeface.ITALIC), 0, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); discussionTitleTextView.setText(spannableString); @@ -409,7 +409,7 @@ private void bindDiscussion(DiscussionDao.DiscussionAndGroupMembersNames discuss if (discussionAndContactNames.discussion.discussionType == Discussion.TYPE_GROUP) { discussionTitleTextView.setMaxLines(1); discussionGroupMembersTextView.setVisibility(View.VISIBLE); - if (discussionAndContactNames.groupMemberNames == null || discussionAndContactNames.groupMemberNames.length() == 0) { + if (discussionAndContactNames.groupMemberNames == null || discussionAndContactNames.groupMemberNames.isEmpty()) { StyleSpan sp = new StyleSpan(Typeface.ITALIC); SpannableString ss = new SpannableString(getString(R.string.text_nobody)); ss.setSpan(sp, 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); @@ -424,7 +424,7 @@ private void bindDiscussion(DiscussionDao.DiscussionAndGroupMembersNames discuss } else { discussionTitleTextView.setMaxLines(1); discussionGroupMembersTextView.setVisibility(View.VISIBLE); - if (discussionAndContactNames.groupMemberNames == null || discussionAndContactNames.groupMemberNames.length() == 0) { + if (discussionAndContactNames.groupMemberNames == null || discussionAndContactNames.groupMemberNames.isEmpty()) { StyleSpan sp = new StyleSpan(Typeface.ITALIC); SpannableString ss = new SpannableString(getString(R.string.text_nobody)); ss.setSpan(sp, 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); diff --git a/obv_messenger/app/src/main/res/raw/double_call.mp3 b/obv_messenger/app/src/main/res/raw/double_call.mp3 new file mode 100644 index 00000000..1bbd3916 Binary files /dev/null and b/obv_messenger/app/src/main/res/raw/double_call.mp3 differ diff --git a/obv_messenger/app/src/main/res/values-fr/strings.xml b/obv_messenger/app/src/main/res/values-fr/strings.xml index 1d8361f6..3e67719e 100644 --- a/obv_messenger/app/src/main/res/values-fr/strings.xml +++ b/obv_messenger/app/src/main/res/values-fr/strings.xml @@ -94,7 +94,10 @@ Un administrateur a mis à jour les détails du groupe. La nouvelle version est affichée ci-dessous.\n\nUtilisez cette version en appuyant sur «\u00a0mettre à jour\u00a0». Votre contact a mis à jour son Olvid Card. L\'ancienne version et la nouvelle sont affichées ci-dessous.\n\nActualisez les informations de votre contact en cliquant "mettre à jour". Un canal sécurisé est actuellement en cours d\'établissement. Vous ne pouvez pas entamer de discussion avec ce contact tant que cela n\'est pas terminé. Ce processus devrait seulement prendre quelques secondes si vous et votre contact êtes tous deux en ligne.\n\nSi vous pensez que quelque chose s\'est mal passé, vous pouvez redémarrer l\'établissement de canal. - Aucun contact trouvé pour cette recherche + Aucun contact trouvé + Aucun groupe trouvé + Aucun message trouvé + Auncune pièce jointe trouvée %1$s : %2$s Société (facultatif) Écrire un message diff --git a/obv_messenger/app/src/main/res/values/strings.xml b/obv_messenger/app/src/main/res/values/strings.xml index 7411ce88..89672701 100644 --- a/obv_messenger/app/src/main/res/values/strings.xml +++ b/obv_messenger/app/src/main/res/values/strings.xml @@ -95,7 +95,10 @@ One of the group administrators updated the group details. The new version is shown above.\n\nPress \"update\" to use this new version. Your contact updated their Olvid Card. Both the old and new versions are shown below.\n\nPress \"update\" to update your contact\'s information with this new version. A secure discussion channel is currently being established. You cannot start any discussion with this contact until this is done. This process should take a few seconds if both you and your contact are online.\n\nIf you believe that something went wrong, you can restart the channel establishment. - No matching contact name + No contact found + No group found + No message found + No attachment found %1$s: %2$s Company (optional) Write message diff --git a/obv_messenger/build.gradle b/obv_messenger/build.gradle index 6f89ccf4..784f66bc 100644 --- a/obv_messenger/build.gradle +++ b/obv_messenger/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.7.1' + classpath 'com.android.tools.build:gradle:8.7.2' classpath 'androidx.navigation:navigation-safe-args-gradle-plugin:2.8.2' classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6' diff --git a/obv_messenger/libwebrtc/olvid_6478.patch b/obv_messenger/libwebrtc/olvid_6478.patch index 12de2cf7..ec1a90c4 100644 --- a/obv_messenger/libwebrtc/olvid_6478.patch +++ b/obv_messenger/libwebrtc/olvid_6478.patch @@ -598,6 +598,700 @@ index b6e1697682..09e9aa5fe9 100644 rtc_source_set("gtest_prod") { sources = [ "gtest_prod_util.h" ] } +diff --git a/rtc_base/http_common.cc b/rtc_base/http_common.cc +new file mode 100644 +index 0000000000..621b854b53 +--- /dev/null ++++ b/rtc_base/http_common.cc +@@ -0,0 +1,555 @@ ++/* ++ * Copyright 2004 The WebRTC Project Authors. All rights reserved. ++ * ++ * Use of this source code is governed by a BSD-style license ++ * that can be found in the LICENSE file in the root of the source ++ * tree. An additional intellectual property rights grant can be found ++ * in the file PATENTS. All contributing project authors may ++ * be found in the AUTHORS file in the root of the source tree. ++ */ ++ ++#include ++ ++#include "absl/strings/string_view.h" ++ ++#if defined(WEBRTC_WIN) ++#include ++#include ++#include ++ ++#define SECURITY_WIN32 ++#include ++#endif ++ ++#include // for isspace ++#include // for sprintf ++ ++#include // for pair ++#include ++ ++#include "absl/strings/match.h" ++#include "rtc_base/crypt_string.h" // for CryptString ++#include "rtc_base/http_common.h" ++#include "rtc_base/logging.h" ++#include "rtc_base/message_digest.h" ++#include "rtc_base/socket_address.h" ++#include "rtc_base/string_utils.h" ++#include "rtc_base/strings/string_builder.h" ++#include "rtc_base/third_party/base64/base64.h" // for Base64 ++#include "rtc_base/zero_memory.h" // for ExplicitZeroMemory ++ ++namespace rtc { ++namespace { ++#if defined(WEBRTC_WIN) && !defined(WINUWP) ++/////////////////////////////////////////////////////////////////////////////// ++// ConstantToLabel can be used to easily generate string names from constant ++// values. This can be useful for logging descriptive names of error messages. ++// Usage: ++// const ConstantToLabel LIBRARY_ERRORS[] = { ++// KLABEL(SOME_ERROR), ++// KLABEL(SOME_OTHER_ERROR), ++// ... ++// LASTLABEL ++// } ++// ++// int err = LibraryFunc(); ++// LOG(LS_ERROR) << "LibraryFunc returned: " ++// << GetErrorName(err, LIBRARY_ERRORS); ++struct ConstantToLabel { ++ int value; ++ const char* label; ++}; ++ ++const char* LookupLabel(int value, const ConstantToLabel entries[]) { ++ for (int i = 0; entries[i].label; ++i) { ++ if (value == entries[i].value) { ++ return entries[i].label; ++ } ++ } ++ return 0; ++} ++ ++std::string GetErrorName(int err, const ConstantToLabel* err_table) { ++ if (err == 0) ++ return "No error"; ++ ++ if (err_table != 0) { ++ if (const char* value = LookupLabel(err, err_table)) ++ return value; ++ } ++ ++ char buffer[16]; ++ snprintf(buffer, sizeof(buffer), "0x%08x", err); ++ return buffer; ++} ++ ++#define KLABEL(x) \ ++ { x, #x } ++#define LASTLABEL \ ++ { 0, 0 } ++ ++const ConstantToLabel SECURITY_ERRORS[] = { ++ KLABEL(SEC_I_COMPLETE_AND_CONTINUE), ++ KLABEL(SEC_I_COMPLETE_NEEDED), ++ KLABEL(SEC_I_CONTEXT_EXPIRED), ++ KLABEL(SEC_I_CONTINUE_NEEDED), ++ KLABEL(SEC_I_INCOMPLETE_CREDENTIALS), ++ KLABEL(SEC_I_RENEGOTIATE), ++ KLABEL(SEC_E_CERT_EXPIRED), ++ KLABEL(SEC_E_INCOMPLETE_MESSAGE), ++ KLABEL(SEC_E_INSUFFICIENT_MEMORY), ++ KLABEL(SEC_E_INTERNAL_ERROR), ++ KLABEL(SEC_E_INVALID_HANDLE), ++ KLABEL(SEC_E_INVALID_TOKEN), ++ KLABEL(SEC_E_LOGON_DENIED), ++ KLABEL(SEC_E_NO_AUTHENTICATING_AUTHORITY), ++ KLABEL(SEC_E_NO_CREDENTIALS), ++ KLABEL(SEC_E_NOT_OWNER), ++ KLABEL(SEC_E_OK), ++ KLABEL(SEC_E_SECPKG_NOT_FOUND), ++ KLABEL(SEC_E_TARGET_UNKNOWN), ++ KLABEL(SEC_E_UNKNOWN_CREDENTIALS), ++ KLABEL(SEC_E_UNSUPPORTED_FUNCTION), ++ KLABEL(SEC_E_UNTRUSTED_ROOT), ++ KLABEL(SEC_E_WRONG_PRINCIPAL), ++ LASTLABEL}; ++#undef KLABEL ++#undef LASTLABEL ++#endif // defined(WEBRTC_WIN) && !defined(WINUWP) ++ ++typedef std::pair HttpAttribute; ++typedef std::vector HttpAttributeList; ++ ++inline bool IsEndOfAttributeName(size_t pos, absl::string_view data) { ++ if (pos >= data.size()) ++ return true; ++ if (isspace(static_cast(data[pos]))) ++ return true; ++ // The reason for this complexity is that some attributes may contain trailing ++ // equal signs (like base64 tokens in Negotiate auth headers) ++ if ((pos + 1 < data.size()) && (data[pos] == '=') && ++ !isspace(static_cast(data[pos + 1])) && ++ (data[pos + 1] != '=')) { ++ return true; ++ } ++ return false; ++} ++ ++void HttpParseAttributes(absl::string_view data, ++ HttpAttributeList& attributes) { ++ size_t pos = 0; ++ const size_t len = data.size(); ++ while (true) { ++ // Skip leading whitespace ++ while ((pos < len) && isspace(static_cast(data[pos]))) { ++ ++pos; ++ } ++ ++ // End of attributes? ++ if (pos >= len) ++ return; ++ ++ // Find end of attribute name ++ size_t start = pos; ++ while (!IsEndOfAttributeName(pos, data)) { ++ ++pos; ++ } ++ ++ HttpAttribute attribute; ++ attribute.first.assign(data.data() + start, data.data() + pos); ++ ++ // Attribute has value? ++ if ((pos < len) && (data[pos] == '=')) { ++ ++pos; // Skip '=' ++ // Check if quoted value ++ if ((pos < len) && (data[pos] == '"')) { ++ while (++pos < len) { ++ if (data[pos] == '"') { ++ ++pos; ++ break; ++ } ++ if ((data[pos] == '\\') && (pos + 1 < len)) ++ ++pos; ++ attribute.second.append(1, data[pos]); ++ } ++ } else { ++ while ((pos < len) && !isspace(static_cast(data[pos])) && ++ (data[pos] != ',')) { ++ attribute.second.append(1, data[pos++]); ++ } ++ } ++ } ++ ++ attributes.push_back(attribute); ++ if ((pos < len) && (data[pos] == ',')) ++ ++pos; // Skip ',' ++ } ++} ++ ++bool HttpHasAttribute(const HttpAttributeList& attributes, ++ absl::string_view name, ++ std::string* value) { ++ for (HttpAttributeList::const_iterator it = attributes.begin(); ++ it != attributes.end(); ++it) { ++ if (it->first == name) { ++ if (value) { ++ *value = it->second; ++ } ++ return true; ++ } ++ } ++ return false; ++} ++ ++bool HttpHasNthAttribute(HttpAttributeList& attributes, ++ size_t index, ++ std::string* name, ++ std::string* value) { ++ if (index >= attributes.size()) ++ return false; ++ ++ if (name) ++ *name = attributes[index].first; ++ if (value) ++ *value = attributes[index].second; ++ return true; ++} ++ ++std::string quote(absl::string_view str) { ++ std::string result; ++ result.push_back('"'); ++ for (size_t i = 0; i < str.size(); ++i) { ++ if ((str[i] == '"') || (str[i] == '\\')) ++ result.push_back('\\'); ++ result.push_back(str[i]); ++ } ++ result.push_back('"'); ++ return result; ++} ++ ++#if defined(WEBRTC_WIN) && !defined(WINUWP) ++struct NegotiateAuthContext : public HttpAuthContext { ++ CredHandle cred; ++ CtxtHandle ctx; ++ size_t steps; ++ bool specified_credentials; ++ ++ NegotiateAuthContext(absl::string_view auth, CredHandle c1, CtxtHandle c2) ++ : HttpAuthContext(auth), ++ cred(c1), ++ ctx(c2), ++ steps(0), ++ specified_credentials(false) {} ++ ++ ~NegotiateAuthContext() override { ++ DeleteSecurityContext(&ctx); ++ FreeCredentialsHandle(&cred); ++ } ++}; ++#endif // defined(WEBRTC_WIN) && !defined(WINUWP) ++ ++} // anonymous namespace ++ ++HttpAuthResult HttpAuthenticate(absl::string_view challenge, ++ const SocketAddress& server, ++ absl::string_view method, ++ absl::string_view uri, ++ absl::string_view username, ++ const CryptString& password, ++ HttpAuthContext*& context, ++ std::string& response, ++ std::string& auth_method) { ++ HttpAttributeList args; ++ HttpParseAttributes(challenge, args); ++ HttpHasNthAttribute(args, 0, &auth_method, nullptr); ++ ++ if (context && (context->auth_method != auth_method)) ++ return HAR_IGNORE; ++ ++ // BASIC ++ if (absl::EqualsIgnoreCase(auth_method, "basic")) { ++ if (context) ++ return HAR_CREDENTIALS; // Bad credentials ++ if (username.empty()) ++ return HAR_CREDENTIALS; // Missing credentials ++ ++ context = new HttpAuthContext(auth_method); ++ ++ // TODO(bugs.webrtc.org/8905): Convert sensitive to a CryptString and also ++ // return response as CryptString so contents get securely deleted ++ // automatically. ++ // std::string decoded = username + ":" + password; ++ size_t len = username.size() + password.GetLength() + 2; ++ char* sensitive = new char[len]; ++ size_t pos = strcpyn(sensitive, len, username); ++ pos += strcpyn(sensitive + pos, len - pos, ":"); ++ password.CopyTo(sensitive + pos, true); ++ ++ response = auth_method; ++ response.append(" "); ++ // TODO: create a sensitive-source version of Base64::encode ++ response.append(Base64::Encode(sensitive)); ++ ExplicitZeroMemory(sensitive, len); ++ delete[] sensitive; ++ return HAR_RESPONSE; ++ } ++ ++ // DIGEST ++ if (absl::EqualsIgnoreCase(auth_method, "digest")) { ++ if (context) ++ return HAR_CREDENTIALS; // Bad credentials ++ if (username.empty()) ++ return HAR_CREDENTIALS; // Missing credentials ++ ++ context = new HttpAuthContext(auth_method); ++ ++ std::string cnonce, ncount; ++ char buffer[256]; ++ snprintf(buffer, sizeof(buffer), "%d", static_cast(time(0))); ++ cnonce = MD5(buffer); ++ ncount = "00000001"; ++ ++ std::string realm, nonce, qop, opaque; ++ HttpHasAttribute(args, "realm", &realm); ++ HttpHasAttribute(args, "nonce", &nonce); ++ bool has_qop = HttpHasAttribute(args, "qop", &qop); ++ bool has_opaque = HttpHasAttribute(args, "opaque", &opaque); ++ ++ // TODO(bugs.webrtc.org/8905): Convert sensitive to a CryptString and also ++ // return response as CryptString so contents get securely deleted ++ // automatically. ++ // std::string A1 = username + ":" + realm + ":" + password; ++ size_t len = username.size() + realm.size() + password.GetLength() + 3; ++ char* sensitive = new char[len]; // A1 ++ size_t pos = strcpyn(sensitive, len, username); ++ pos += strcpyn(sensitive + pos, len - pos, ":"); ++ pos += strcpyn(sensitive + pos, len - pos, realm); ++ pos += strcpyn(sensitive + pos, len - pos, ":"); ++ password.CopyTo(sensitive + pos, true); ++ ++ std::string A2 = std::string(method) + ":" + std::string(uri); ++ std::string middle; ++ if (has_qop) { ++ qop = "auth"; ++ middle = nonce + ":" + ncount + ":" + cnonce + ":" + qop; ++ } else { ++ middle = nonce; ++ } ++ std::string HA1 = MD5(sensitive); ++ ExplicitZeroMemory(sensitive, len); ++ delete[] sensitive; ++ std::string HA2 = MD5(A2); ++ std::string dig_response = MD5(HA1 + ":" + middle + ":" + HA2); ++ ++ rtc::StringBuilder ss; ++ ss << auth_method; ++ ss << " username=" << quote(username); ++ ss << ", realm=" << quote(realm); ++ ss << ", nonce=" << quote(nonce); ++ ss << ", uri=" << quote(uri); ++ if (has_qop) { ++ ss << ", qop=" << qop; ++ ss << ", nc=" << ncount; ++ ss << ", cnonce=" << quote(cnonce); ++ } ++ ss << ", response=\"" << dig_response << "\""; ++ if (has_opaque) { ++ ss << ", opaque=" << quote(opaque); ++ } ++ response = ss.str(); ++ return HAR_RESPONSE; ++ } ++ ++#if defined(WEBRTC_WIN) && !defined(WINUWP) ++#if 1 ++ bool want_negotiate = absl::EqualsIgnoreCase(auth_method, "negotiate"); ++ bool want_ntlm = absl::EqualsIgnoreCase(auth_method, "ntlm"); ++ // SPNEGO & NTLM ++ if (want_negotiate || want_ntlm) { ++ const size_t MAX_MESSAGE = 12000, MAX_SPN = 256; ++ char out_buf[MAX_MESSAGE], spn[MAX_SPN]; ++ ++#if 0 // Requires funky windows versions ++ DWORD len = MAX_SPN; ++ if (DsMakeSpn("HTTP", server.HostAsURIString().c_str(), nullptr, ++ server.port(), ++ 0, &len, spn) != ERROR_SUCCESS) { ++ RTC_LOG_F(LS_WARNING) << "(Negotiate) - DsMakeSpn failed"; ++ return HAR_IGNORE; ++ } ++#else ++ snprintf(spn, MAX_SPN, "HTTP/%s", server.ToString().c_str()); ++#endif ++ ++ SecBuffer out_sec; ++ out_sec.pvBuffer = out_buf; ++ out_sec.cbBuffer = sizeof(out_buf); ++ out_sec.BufferType = SECBUFFER_TOKEN; ++ ++ SecBufferDesc out_buf_desc; ++ out_buf_desc.ulVersion = 0; ++ out_buf_desc.cBuffers = 1; ++ out_buf_desc.pBuffers = &out_sec; ++ ++ const ULONG NEG_FLAGS_DEFAULT = ++ // ISC_REQ_ALLOCATE_MEMORY ++ ISC_REQ_CONFIDENTIALITY ++ //| ISC_REQ_EXTENDED_ERROR ++ //| ISC_REQ_INTEGRITY ++ | ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT ++ //| ISC_REQ_STREAM ++ //| ISC_REQ_USE_SUPPLIED_CREDS ++ ; ++ ++ ::TimeStamp lifetime; ++ SECURITY_STATUS ret = S_OK; ++ ULONG ret_flags = 0, flags = NEG_FLAGS_DEFAULT; ++ ++ bool specify_credentials = !username.empty(); ++ size_t steps = 0; ++ ++ // uint32_t now = Time(); ++ ++ NegotiateAuthContext* neg = static_cast(context); ++ if (neg) { ++ const size_t max_steps = 10; ++ if (++neg->steps >= max_steps) { ++ RTC_LOG(LS_WARNING) << "AsyncHttpsProxySocket::Authenticate(Negotiate) " ++ "too many retries"; ++ return HAR_ERROR; ++ } ++ steps = neg->steps; ++ ++ std::string challenge, decoded_challenge; ++ if (HttpHasNthAttribute(args, 1, &challenge, nullptr) && ++ Base64::Decode(challenge, Base64::DO_STRICT, &decoded_challenge, ++ nullptr)) { ++ SecBuffer in_sec; ++ in_sec.pvBuffer = const_cast(decoded_challenge.data()); ++ in_sec.cbBuffer = static_cast(decoded_challenge.size()); ++ in_sec.BufferType = SECBUFFER_TOKEN; ++ ++ SecBufferDesc in_buf_desc; ++ in_buf_desc.ulVersion = 0; ++ in_buf_desc.cBuffers = 1; ++ in_buf_desc.pBuffers = &in_sec; ++ ++ ret = InitializeSecurityContextA( ++ &neg->cred, &neg->ctx, spn, flags, 0, SECURITY_NATIVE_DREP, ++ &in_buf_desc, 0, &neg->ctx, &out_buf_desc, &ret_flags, &lifetime); ++ if (FAILED(ret)) { ++ RTC_LOG(LS_ERROR) << "InitializeSecurityContext returned: " ++ << GetErrorName(ret, SECURITY_ERRORS); ++ return HAR_ERROR; ++ } ++ } else if (neg->specified_credentials) { ++ // Try again with default credentials ++ specify_credentials = false; ++ delete context; ++ context = neg = 0; ++ } else { ++ return HAR_CREDENTIALS; ++ } ++ } ++ ++ if (!neg) { ++ unsigned char userbuf[256], passbuf[256], domainbuf[16]; ++ SEC_WINNT_AUTH_IDENTITY_A auth_id, *pauth_id = 0; ++ if (specify_credentials) { ++ memset(&auth_id, 0, sizeof(auth_id)); ++ size_t len = password.GetLength() + 1; ++ char* sensitive = new char[len]; ++ password.CopyTo(sensitive, true); ++ absl::string_view::size_type pos = username.find('\\'); ++ if (pos == absl::string_view::npos) { ++ auth_id.UserLength = static_cast( ++ std::min(sizeof(userbuf) - 1, username.size())); ++ memcpy(userbuf, username.data(), auth_id.UserLength); ++ userbuf[auth_id.UserLength] = 0; ++ auth_id.DomainLength = 0; ++ domainbuf[auth_id.DomainLength] = 0; ++ auth_id.PasswordLength = static_cast( ++ std::min(sizeof(passbuf) - 1, password.GetLength())); ++ memcpy(passbuf, sensitive, auth_id.PasswordLength); ++ passbuf[auth_id.PasswordLength] = 0; ++ } else { ++ auth_id.UserLength = static_cast( ++ std::min(sizeof(userbuf) - 1, username.size() - pos - 1)); ++ memcpy(userbuf, username.data() + pos + 1, auth_id.UserLength); ++ userbuf[auth_id.UserLength] = 0; ++ auth_id.DomainLength = ++ static_cast(std::min(sizeof(domainbuf) - 1, pos)); ++ memcpy(domainbuf, username.data(), auth_id.DomainLength); ++ domainbuf[auth_id.DomainLength] = 0; ++ auth_id.PasswordLength = static_cast( ++ std::min(sizeof(passbuf) - 1, password.GetLength())); ++ memcpy(passbuf, sensitive, auth_id.PasswordLength); ++ passbuf[auth_id.PasswordLength] = 0; ++ } ++ ExplicitZeroMemory(sensitive, len); ++ delete[] sensitive; ++ auth_id.User = userbuf; ++ auth_id.Domain = domainbuf; ++ auth_id.Password = passbuf; ++ auth_id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; ++ pauth_id = &auth_id; ++ RTC_LOG(LS_VERBOSE) ++ << "Negotiate protocol: Using specified credentials"; ++ } else { ++ RTC_LOG(LS_VERBOSE) << "Negotiate protocol: Using default credentials"; ++ } ++ ++ CredHandle cred; ++ ret = AcquireCredentialsHandleA( ++ 0, const_cast(want_negotiate ? NEGOSSP_NAME_A : NTLMSP_NAME_A), ++ SECPKG_CRED_OUTBOUND, 0, pauth_id, 0, 0, &cred, &lifetime); ++ if (ret != SEC_E_OK) { ++ RTC_LOG(LS_ERROR) << "AcquireCredentialsHandle error: " ++ << GetErrorName(ret, SECURITY_ERRORS); ++ return HAR_IGNORE; ++ } ++ ++ // CSecBufferBundle<5, CSecBufferBase::FreeSSPI> sb_out; ++ ++ CtxtHandle ctx; ++ ret = InitializeSecurityContextA(&cred, 0, spn, flags, 0, ++ SECURITY_NATIVE_DREP, 0, 0, &ctx, ++ &out_buf_desc, &ret_flags, &lifetime); ++ if (FAILED(ret)) { ++ RTC_LOG(LS_ERROR) << "InitializeSecurityContext returned: " ++ << GetErrorName(ret, SECURITY_ERRORS); ++ FreeCredentialsHandle(&cred); ++ return HAR_IGNORE; ++ } ++ ++ RTC_DCHECK(!context); ++ context = neg = new NegotiateAuthContext(auth_method, cred, ctx); ++ neg->specified_credentials = specify_credentials; ++ neg->steps = steps; ++ } ++ ++ if ((ret == SEC_I_COMPLETE_NEEDED) || ++ (ret == SEC_I_COMPLETE_AND_CONTINUE)) { ++ ret = CompleteAuthToken(&neg->ctx, &out_buf_desc); ++ RTC_LOG(LS_VERBOSE) << "CompleteAuthToken returned: " ++ << GetErrorName(ret, SECURITY_ERRORS); ++ if (FAILED(ret)) { ++ return HAR_ERROR; ++ } ++ } ++ ++ std::string decoded(out_buf, out_buf + out_sec.cbBuffer); ++ response = auth_method; ++ response.append(" "); ++ response.append(Base64::Encode(decoded)); ++ return HAR_RESPONSE; ++ } ++#endif ++#endif // defined(WEBRTC_WIN) && !defined(WINUWP) ++ ++ return HAR_IGNORE; ++} ++ ++////////////////////////////////////////////////////////////////////// ++ ++} // namespace rtc +diff --git a/rtc_base/http_common.h b/rtc_base/http_common.h +new file mode 100644 +index 0000000000..06e42c6703 +--- /dev/null ++++ b/rtc_base/http_common.h +@@ -0,0 +1,53 @@ ++/* ++ * Copyright 2004 The WebRTC Project Authors. All rights reserved. ++ * ++ * Use of this source code is governed by a BSD-style license ++ * that can be found in the LICENSE file in the root of the source ++ * tree. An additional intellectual property rights grant can be found ++ * in the file PATENTS. All contributing project authors may ++ * be found in the AUTHORS file in the root of the source tree. ++ */ ++ ++#ifndef RTC_BASE_HTTP_COMMON_H_ ++#define RTC_BASE_HTTP_COMMON_H_ ++ ++#include ++ ++#include "absl/strings/string_view.h" ++ ++namespace rtc { ++ ++class CryptString; ++class SocketAddress; ++ ++////////////////////////////////////////////////////////////////////// ++// Http Authentication ++////////////////////////////////////////////////////////////////////// ++ ++struct HttpAuthContext { ++ std::string auth_method; ++ HttpAuthContext(absl::string_view auth) : auth_method(auth) {} ++ virtual ~HttpAuthContext() {} ++}; ++ ++enum HttpAuthResult { HAR_RESPONSE, HAR_IGNORE, HAR_CREDENTIALS, HAR_ERROR }; ++ ++// 'context' is used by this function to record information between calls. ++// Start by passing a null pointer, then pass the same pointer each additional ++// call. When the authentication attempt is finished, delete the context. ++// TODO(bugs.webrtc.org/8905): Change "response" to "ZeroOnFreeBuffer". ++HttpAuthResult HttpAuthenticate(absl::string_view challenge, ++ const SocketAddress& server, ++ absl::string_view method, ++ absl::string_view uri, ++ absl::string_view username, ++ const CryptString& password, ++ HttpAuthContext*& context, ++ std::string& response, ++ std::string& auth_method); ++ ++////////////////////////////////////////////////////////////////////// ++ ++} // namespace rtc ++ ++#endif // RTC_BASE_HTTP_COMMON_H_ +diff --git a/rtc_base/proxy_info.cc b/rtc_base/proxy_info.cc +new file mode 100644 +index 0000000000..23d60afa74 +--- /dev/null ++++ b/rtc_base/proxy_info.cc +@@ -0,0 +1,23 @@ ++/* ++ * Copyright 2004 The WebRTC Project Authors. All rights reserved. ++ * ++ * Use of this source code is governed by a BSD-style license ++ * that can be found in the LICENSE file in the root of the source ++ * tree. An additional intellectual property rights grant can be found ++ * in the file PATENTS. All contributing project authors may ++ * be found in the AUTHORS file in the root of the source tree. ++ */ ++ ++#include "rtc_base/proxy_info.h" ++ ++namespace rtc { ++ ++const char* ProxyToString(ProxyType proxy) { ++ const char* const PROXY_NAMES[] = {"none", "https", "socks5", "unknown"}; ++ return PROXY_NAMES[proxy]; ++} ++ ++ProxyInfo::ProxyInfo() : type(PROXY_NONE), autodetect(false) {} ++ProxyInfo::~ProxyInfo() = default; ++ ++} // namespace rtc +diff --git a/rtc_base/proxy_info.h b/rtc_base/proxy_info.h +new file mode 100644 +index 0000000000..e614692025 +--- /dev/null ++++ b/rtc_base/proxy_info.h +@@ -0,0 +1,39 @@ ++/* ++ * Copyright 2004 The WebRTC Project Authors. All rights reserved. ++ * ++ * Use of this source code is governed by a BSD-style license ++ * that can be found in the LICENSE file in the root of the source ++ * tree. An additional intellectual property rights grant can be found ++ * in the file PATENTS. All contributing project authors may ++ * be found in the AUTHORS file in the root of the source tree. ++ */ ++ ++#ifndef RTC_BASE_PROXY_INFO_H_ ++#define RTC_BASE_PROXY_INFO_H_ ++ ++#include ++ ++#include "rtc_base/crypt_string.h" ++#include "rtc_base/socket_address.h" ++ ++namespace rtc { ++ ++enum ProxyType { PROXY_NONE, PROXY_HTTPS, PROXY_SOCKS5, PROXY_UNKNOWN }; ++const char* ProxyToString(ProxyType proxy); ++ ++struct ProxyInfo { ++ ProxyType type; ++ SocketAddress address; ++ std::string autoconfig_url; ++ bool autodetect; ++ std::string bypass_list; ++ std::string username; ++ CryptString password; ++ ++ ProxyInfo(); ++ ~ProxyInfo(); ++}; ++ ++} // namespace rtc ++ ++#endif // RTC_BASE_PROXY_INFO_H_ diff --git a/rtc_base/socket_adapters.cc b/rtc_base/socket_adapters.cc index 2a157bfc49..f6fa182f5d 100644 --- a/rtc_base/socket_adapters.cc diff --git a/obv_messenger/sardine-android/build.gradle b/obv_messenger/sardine-android/build.gradle index 79955419..c9925f3a 100644 --- a/obv_messenger/sardine-android/build.gradle +++ b/obv_messenger/sardine-android/build.gradle @@ -4,7 +4,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:8.7.1' + classpath 'com.android.tools.build:gradle:8.7.2' } }