mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-24 08:47:46 +00:00
Merge branch 'desktop-protocol-changes' into dev
This commit is contained in:
commit
da8bbbc9cf
@ -38,6 +38,7 @@ import org.thoughtcrime.securesms.components.TypingStatusSender;
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.dependencies.AxolotlStorageModule;
|
||||
@ -91,18 +92,20 @@ import org.webrtc.PeerConnectionFactory;
|
||||
import org.webrtc.PeerConnectionFactory.InitializationOptions;
|
||||
import org.webrtc.voiceengine.WebRtcAudioManager;
|
||||
import org.webrtc.voiceengine.WebRtcAudioUtils;
|
||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||
import org.whispersystems.libsignal.logging.SignalProtocolLoggerProvider;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPI;
|
||||
import org.whispersystems.signalservice.loki.api.LokiPoller;
|
||||
import org.whispersystems.signalservice.loki.api.LokiPushNotificationAcknowledgement;
|
||||
import org.whispersystems.signalservice.loki.api.LokiSwarmAPI;
|
||||
import org.whispersystems.signalservice.loki.api.Poller;
|
||||
import org.whispersystems.signalservice.loki.api.PushNotificationAcknowledgement;
|
||||
import org.whispersystems.signalservice.loki.api.SnodeAPI;
|
||||
import org.whispersystems.signalservice.loki.api.SwarmAPI;
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
||||
import org.whispersystems.signalservice.loki.api.p2p.LokiP2PAPI;
|
||||
import org.whispersystems.signalservice.loki.api.p2p.LokiP2PAPIDelegate;
|
||||
import org.whispersystems.signalservice.loki.api.shelved.p2p.LokiP2PAPI;
|
||||
import org.whispersystems.signalservice.loki.api.shelved.p2p.LokiP2PAPIDelegate;
|
||||
import org.whispersystems.signalservice.loki.database.LokiAPIDatabaseProtocol;
|
||||
import org.whispersystems.signalservice.loki.protocol.friendrequests.FriendRequestProtocol;
|
||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
|
||||
@ -151,7 +154,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
|
||||
// Loki
|
||||
public MessageNotifier messageNotifier = null;
|
||||
public LokiPoller lokiPoller = null;
|
||||
public Poller lokiPoller = null;
|
||||
public LokiPublicChatManager lokiPublicChatManager = null;
|
||||
private LokiPublicChatAPI lokiPublicChatAPI = null;
|
||||
public Broadcaster broadcaster = null;
|
||||
@ -184,8 +187,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
LokiSessionResetImplementation sessionResetImpl = new LokiSessionResetImplementation(this);
|
||||
if (userPublicKey != null) {
|
||||
LokiSwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||
LokiAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||
FriendRequestProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
||||
SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||
@ -194,7 +197,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
MultiDeviceProtocol.Companion.configureIfNeeded(apiDB);
|
||||
SessionManagementProtocol.Companion.configureIfNeeded(sessionResetImpl, threadDB, this);
|
||||
setUpP2PAPIIfNeeded();
|
||||
LokiPushNotificationAcknowledgement.Companion.configureIfNeeded(BuildConfig.DEBUG);
|
||||
PushNotificationAcknowledgement.Companion.configureIfNeeded(BuildConfig.DEBUG);
|
||||
if (setUpStorageAPIIfNeeded()) {
|
||||
if (userPublicKey != null) {
|
||||
Set<DeviceLink> deviceLinks = DatabaseFactory.getLokiAPIDatabase(this).getDeviceLinks(userPublicKey);
|
||||
@ -493,15 +496,15 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userPublicKey == null) return;
|
||||
if (lokiPoller != null) {
|
||||
LokiAPI.shared.setUserHexEncodedPublicKey(userPublicKey);
|
||||
lokiPoller.setUserHexEncodedPublicKey(userPublicKey);
|
||||
SnodeAPI.shared.setUserPublicKey(userPublicKey);
|
||||
lokiPoller.setUserPublicKey(userPublicKey);
|
||||
return;
|
||||
}
|
||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
Context context = this;
|
||||
LokiSwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||
LokiAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||
lokiPoller = new LokiPoller(userPublicKey, apiDB, protos -> {
|
||||
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||
lokiPoller = new Poller(userPublicKey, apiDB, protos -> {
|
||||
for (SignalServiceProtos.Envelope proto : protos) {
|
||||
new PushContentReceiveJob(context).processEnvelope(new SignalServiceEnvelope(proto), false);
|
||||
}
|
||||
@ -588,6 +591,18 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
|
||||
@Override
|
||||
public void sendSessionRequest(@NotNull String publicKey) {
|
||||
// It's never necessary to establish a session with self
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (publicKey.equals(userPublicKey)) { return; }
|
||||
// Check that we don't already have a session
|
||||
SignalProtocolAddress address = new SignalProtocolAddress(publicKey, SignalServiceAddress.DEFAULT_DEVICE_ID);
|
||||
boolean hasSession = new TextSecureSessionStore(this).containsSession(address);
|
||||
if (hasSession) { return; }
|
||||
// Check that we didn't already send or process a session request
|
||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
boolean hasSentOrProcessedSessionRequest = (apiDB.getSessionRequestTimestamp(publicKey) != null);
|
||||
if (hasSentOrProcessedSessionRequest) { return; }
|
||||
// Send the session request
|
||||
DatabaseFactory.getLokiAPIDatabase(this).setSessionRequestTimestamp(publicKey, new Date().getTime());
|
||||
EphemeralMessage sessionRequest = EphemeralMessage.createSessionRequest(publicKey);
|
||||
jobManager.add(new PushEphemeralMessageSendJob(sessionRequest));
|
||||
|
@ -44,6 +44,7 @@ import org.thoughtcrime.securesms.jobs.SmsSentJob;
|
||||
import org.thoughtcrime.securesms.jobs.TrimThreadJob;
|
||||
import org.thoughtcrime.securesms.jobs.TypingSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.UpdateApkJob;
|
||||
import org.thoughtcrime.securesms.loki.protocol.PushNullMessageSendJob;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -74,6 +75,7 @@ public class WorkManagerFactoryMappings {
|
||||
put(PushMediaSendJob.class.getName(), PushMediaSendJob.KEY);
|
||||
put(PushNotificationReceiveJob.class.getName(), PushNotificationReceiveJob.KEY);
|
||||
put(PushTextSendJob.class.getName(), PushTextSendJob.KEY);
|
||||
put(PushNullMessageSendJob.class.getName(), PushNullMessageSendJob.KEY);
|
||||
put(RefreshAttributesJob.class.getName(), RefreshAttributesJob.KEY);
|
||||
put(RefreshPreKeysJob.class.getName(), RefreshPreKeysJob.KEY);
|
||||
put(RefreshUnidentifiedDeliveryAbilityJob.class.getName(), RefreshUnidentifiedDeliveryAbilityJob.KEY);
|
||||
|
@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
|
||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceOpenGroupUpdateJob;
|
||||
import org.thoughtcrime.securesms.loki.protocol.PushEphemeralMessageSendJob;
|
||||
import org.thoughtcrime.securesms.loki.protocol.PushNullMessageSendJob;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@ -50,6 +51,7 @@ public final class JobManagerFactories {
|
||||
put(PushMediaSendJob.KEY, new PushMediaSendJob.Factory());
|
||||
put(PushNotificationReceiveJob.KEY, new PushNotificationReceiveJob.Factory());
|
||||
put(PushTextSendJob.KEY, new PushTextSendJob.Factory());
|
||||
put(PushNullMessageSendJob.KEY, new PushNullMessageSendJob.Factory());
|
||||
put(RefreshAttributesJob.KEY, new RefreshAttributesJob.Factory());
|
||||
put(RefreshPreKeysJob.KEY, new RefreshPreKeysJob.Factory());
|
||||
put(RefreshUnidentifiedDeliveryAbilityJob.KEY, new RefreshUnidentifiedDeliveryAbilityJob.Factory());
|
||||
|
@ -73,6 +73,7 @@ import org.thoughtcrime.securesms.loki.protocol.FriendRequestProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.PushEphemeralMessageSendJob;
|
||||
import org.thoughtcrime.securesms.loki.protocol.PushNullMessageSendJob;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SyncMessagesProtocol;
|
||||
@ -162,7 +163,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
private MessageNotifier messageNotifier;
|
||||
|
||||
@Inject SignalServiceMessageSender messageSender;
|
||||
private Address author;
|
||||
|
||||
public PushDecryptJob(Context context) {
|
||||
this(context, -1);
|
||||
@ -316,51 +316,13 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
} else if (isMediaMessage) {
|
||||
handleMediaMessage(content, message, smsMessageId, Optional.absent());
|
||||
|
||||
// Loki - This is needed for compatibility with refactored desktop clients
|
||||
if (!message.isGroupMessage()) {
|
||||
Recipient recipient = recipient(context, content.getSender());
|
||||
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context);
|
||||
LokiThreadFriendRequestStatus threadFriendRequestStatus = threadDB.getFriendRequestStatus(threadID);
|
||||
if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.NONE || threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_EXPIRED) {
|
||||
threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED);
|
||||
} else if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) {
|
||||
threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
|
||||
EphemeralMessage ephemeralMessage = EphemeralMessage.create(content.getSender());
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new PushEphemeralMessageSendJob(ephemeralMessage));
|
||||
SyncMessagesProtocol.syncContact(context, Address.fromSerialized(content.getSender()));
|
||||
}
|
||||
|
||||
// Loki - Handle friend request message if needed
|
||||
FriendRequestProtocol.handleFriendRequestMessageIfNeeded(context, content.getSender(), content);
|
||||
}
|
||||
// Loki - Handle friend request message if needed
|
||||
FriendRequestProtocol.handleFriendRequestMessageIfNeeded(context, content.getSender(), content);
|
||||
} else if (message.getBody().isPresent()) {
|
||||
handleTextMessage(content, message, smsMessageId, Optional.absent());
|
||||
|
||||
// Loki - This is needed for compatibility with refactored desktop clients
|
||||
if (!message.isGroupMessage()) {
|
||||
Recipient recipient = recipient(context, content.getSender());
|
||||
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context);
|
||||
LokiThreadFriendRequestStatus threadFriendRequestStatus = threadDB.getFriendRequestStatus(threadID);
|
||||
if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.NONE || threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_EXPIRED) {
|
||||
threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED);
|
||||
} else if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) {
|
||||
threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
|
||||
EphemeralMessage ephemeralMessage = EphemeralMessage.create(content.getSender());
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new PushEphemeralMessageSendJob(ephemeralMessage));
|
||||
SyncMessagesProtocol.syncContact(context, Address.fromSerialized(content.getSender()));
|
||||
}
|
||||
|
||||
// Loki - Handle friend request message if needed
|
||||
FriendRequestProtocol.handleFriendRequestMessageIfNeeded(context, content.getSender(), content);
|
||||
}
|
||||
} else {
|
||||
// Loki - This is needed for compatibility with refactored desktop clients
|
||||
if (envelope.isFriendRequest()) {
|
||||
EphemeralMessage ephemeralMessage = EphemeralMessage.create(content.getSender());
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new PushEphemeralMessageSendJob(ephemeralMessage));
|
||||
}
|
||||
// Loki - Handle friend request message if needed
|
||||
FriendRequestProtocol.handleFriendRequestMessageIfNeeded(context, content.getSender(), content);
|
||||
}
|
||||
|
||||
if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get()))) {
|
||||
@ -406,7 +368,27 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
} else if (content.getTypingMessage().isPresent()) {
|
||||
handleTypingMessage(content, content.getTypingMessage().get());
|
||||
} else {
|
||||
Log.w(TAG, "Got unrecognized message...");
|
||||
|
||||
// Loki - This is needed for compatibility with refactored desktop clients
|
||||
// ========
|
||||
if (content.isFriendRequest()) {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new PushNullMessageSendJob(content.getSender()));
|
||||
} else {
|
||||
Log.w(TAG, "Got unrecognized message...");
|
||||
}
|
||||
Recipient recipient = recipient(context, content.getSender());
|
||||
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context);
|
||||
LokiThreadFriendRequestStatus threadFriendRequestStatus = threadDB.getFriendRequestStatus(threadID);
|
||||
if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.NONE || threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_EXPIRED) {
|
||||
threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED);
|
||||
} else if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) {
|
||||
threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
|
||||
EphemeralMessage ephemeralMessage = EphemeralMessage.create(content.getSender());
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new PushEphemeralMessageSendJob(ephemeralMessage));
|
||||
SyncMessagesProtocol.syncContact(context, Address.fromSerialized(content.getSender()));
|
||||
}
|
||||
// ========
|
||||
}
|
||||
|
||||
resetRecipientToPush(Recipient.from(context, Address.fromSerialized(content.getSender()), false));
|
||||
|
@ -44,7 +44,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSy
|
||||
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPI;
|
||||
import org.whispersystems.signalservice.loki.api.SnodeAPI;
|
||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
@ -231,7 +231,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
database.addMismatchedIdentity(messageId, Address.fromSerialized(uie.getE164Number()), uie.getIdentityKey());
|
||||
database.markAsSentFailed(messageId);
|
||||
}
|
||||
} catch (LokiAPI.Error e) {
|
||||
} catch (SnodeAPI.Error e) {
|
||||
Log.d("Loki", "Couldn't send message due to error: " + e.getDescription());
|
||||
if (messageId >= 0) {
|
||||
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
|
||||
@ -257,7 +257,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
private boolean deliver(OutgoingMediaMessage message)
|
||||
throws RetryLaterException, InsecureFallbackApprovalException, UntrustedIdentityException,
|
||||
UndeliverableMessageException, LokiAPI.Error
|
||||
UndeliverableMessageException, SnodeAPI.Error
|
||||
{
|
||||
try {
|
||||
Recipient recipient = Recipient.from(context, destination, false);
|
||||
|
@ -32,7 +32,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPI;
|
||||
import org.whispersystems.signalservice.loki.api.SnodeAPI;
|
||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -173,7 +173,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
database.markAsSentFailed(record.getId());
|
||||
database.markAsPush(record.getId());
|
||||
}
|
||||
} catch (LokiAPI.Error e) {
|
||||
} catch (SnodeAPI.Error e) {
|
||||
Log.d("Loki", "Couldn't send message due to error: " + e.getDescription());
|
||||
if (messageId >= 0) {
|
||||
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
|
||||
@ -204,7 +204,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
}
|
||||
|
||||
private boolean deliver(SmsMessageRecord message)
|
||||
throws UntrustedIdentityException, InsecureFallbackApprovalException, RetryLaterException, LokiAPI.Error
|
||||
throws UntrustedIdentityException, InsecureFallbackApprovalException, RetryLaterException, SnodeAPI.Error
|
||||
{
|
||||
try {
|
||||
Recipient recipient = Recipient.from(context, destination, false);
|
||||
|
@ -9,7 +9,7 @@ import org.thoughtcrime.securesms.jobs.PushContentReceiveJob
|
||||
import org.thoughtcrime.securesms.service.PersistentAlarmManagerListener
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPI
|
||||
import org.whispersystems.signalservice.loki.api.SnodeAPI
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class BackgroundPollWorker : PersistentAlarmManagerListener() {
|
||||
@ -35,8 +35,8 @@ class BackgroundPollWorker : PersistentAlarmManagerListener() {
|
||||
try {
|
||||
val applicationContext = context.applicationContext as ApplicationContext
|
||||
val broadcaster = applicationContext.broadcaster
|
||||
LokiAPI.configureIfNeeded(userPublicKey, lokiAPIDatabase, broadcaster)
|
||||
LokiAPI.shared.getMessages().map { messages ->
|
||||
SnodeAPI.configureIfNeeded(userPublicKey, lokiAPIDatabase, broadcaster)
|
||||
SnodeAPI.shared.getMessages().map { messages ->
|
||||
messages.forEach {
|
||||
PushContentReceiveJob(context).processEnvelope(SignalServiceEnvelope(it), false)
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
||||
}
|
||||
val senderHexEncodedPublicKey = masterHexEncodedPublicKey ?: message.hexEncodedPublicKey
|
||||
val serviceDataMessage = getDataMessage(message)
|
||||
val serviceContent = SignalServiceContent(serviceDataMessage, senderHexEncodedPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.timestamp, false, false, false, false, false)
|
||||
val serviceContent = SignalServiceContent(serviceDataMessage, senderHexEncodedPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.timestamp, false, false, false, false)
|
||||
if (serviceDataMessage.quote.isPresent || (serviceDataMessage.attachments.isPresent && serviceDataMessage.attachments.get().size > 0) || serviceDataMessage.previews.isPresent) {
|
||||
PushDecryptJob(context).handleMediaMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
|
||||
} else {
|
||||
|
@ -5,14 +5,14 @@ import okhttp3.*
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.libsignal.logging.Log
|
||||
import org.whispersystems.signalservice.internal.util.JsonUtil
|
||||
import org.whispersystems.signalservice.loki.api.LokiPushNotificationAcknowledgement
|
||||
import org.whispersystems.signalservice.loki.api.PushNotificationAcknowledgement
|
||||
import java.io.IOException
|
||||
|
||||
object LokiPushNotificationManager {
|
||||
private val connection = OkHttpClient()
|
||||
|
||||
private val server by lazy {
|
||||
LokiPushNotificationAcknowledgement.shared.server
|
||||
PushNotificationAcknowledgement.shared.server
|
||||
}
|
||||
|
||||
private const val tokenExpirationInterval = 12 * 60 * 60 * 1000
|
||||
|
@ -7,7 +7,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.libsignal.logging.Log
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope
|
||||
import org.whispersystems.signalservice.internal.util.Base64
|
||||
import org.whispersystems.signalservice.loki.api.LokiMessageWrapper
|
||||
import org.whispersystems.signalservice.loki.api.MessageWrapper
|
||||
|
||||
class PushNotificationService : FirebaseMessagingService() {
|
||||
|
||||
@ -23,7 +23,7 @@ class PushNotificationService : FirebaseMessagingService() {
|
||||
val data = base64EncodedData?.let { Base64.decode(it) }
|
||||
if (data != null) {
|
||||
try {
|
||||
val envelope = LokiMessageWrapper.unwrap(data)
|
||||
val envelope = MessageWrapper.unwrap(data)
|
||||
PushContentReceiveJob(this).processEnvelope(SignalServiceEnvelope(envelope), true)
|
||||
} catch (e: Exception) {
|
||||
Log.d("Loki", "Failed to unwrap data for message.")
|
||||
|
@ -8,7 +8,7 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||
import org.thoughtcrime.securesms.loki.utilities.*
|
||||
import org.thoughtcrime.securesms.util.Base64
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPITarget
|
||||
import org.whispersystems.signalservice.loki.api.Snode
|
||||
import org.whispersystems.signalservice.loki.database.LokiAPIDatabaseProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
||||
|
||||
@ -77,7 +77,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
@JvmStatic val createSessionRequestTimestampCacheCommand = "CREATE TABLE $sessionRequestTimestampCache ($publicKey STRING PRIMARY KEY, $timestamp INTEGER DEFAULT 0);"
|
||||
}
|
||||
|
||||
override fun getSnodePool(): Set<LokiAPITarget> {
|
||||
override fun getSnodePool(): Set<Snode> {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(snodePoolCache, "${Companion.dummyKey} = ?", wrap("dummy_key")) { cursor ->
|
||||
val snodePoolAsString = cursor.getString(cursor.getColumnIndexOrThrow(snodePool))
|
||||
@ -87,12 +87,12 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
val port = components.getOrNull(1)?.toIntOrNull() ?: return@mapNotNull null
|
||||
val ed25519Key = components.getOrNull(2) ?: return@mapNotNull null
|
||||
val x25519Key = components.getOrNull(3) ?: return@mapNotNull null
|
||||
LokiAPITarget(address, port, LokiAPITarget.KeySet(ed25519Key, x25519Key))
|
||||
Snode(address, port, Snode.KeySet(ed25519Key, x25519Key))
|
||||
}
|
||||
}?.toSet() ?: setOf()
|
||||
}
|
||||
|
||||
override fun setSnodePool(newValue: Set<LokiAPITarget>) {
|
||||
override fun setSnodePool(newValue: Set<Snode>) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val snodePoolAsString = newValue.joinToString(", ") { snode ->
|
||||
var string = "${snode.address}-${snode.port}"
|
||||
@ -106,9 +106,9 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
database.insertOrUpdate(snodePoolCache, row, "${Companion.dummyKey} = ?", wrap("dummy_key"))
|
||||
}
|
||||
|
||||
override fun getOnionRequestPaths(): List<List<LokiAPITarget>> {
|
||||
override fun getOnionRequestPaths(): List<List<Snode>> {
|
||||
val database = databaseHelper.readableDatabase
|
||||
fun get(indexPath: String): LokiAPITarget? {
|
||||
fun get(indexPath: String): Snode? {
|
||||
return database.get(onionRequestPathCache, "${Companion.indexPath} = ?", wrap(indexPath)) { cursor ->
|
||||
val snodeAsString = cursor.getString(cursor.getColumnIndexOrThrow(snode))
|
||||
val components = snodeAsString.split("-")
|
||||
@ -117,7 +117,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
val ed25519Key = components.getOrNull(2)
|
||||
val x25519Key = components.getOrNull(3)
|
||||
if (port != null && ed25519Key != null && x25519Key != null) {
|
||||
LokiAPITarget(address, port, LokiAPITarget.KeySet(ed25519Key, x25519Key))
|
||||
Snode(address, port, Snode.KeySet(ed25519Key, x25519Key))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@ -139,7 +139,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
delete("1-1"); delete("1-2")
|
||||
}
|
||||
|
||||
override fun setOnionRequestPaths(newValue: List<List<LokiAPITarget>>) {
|
||||
override fun setOnionRequestPaths(newValue: List<List<Snode>>) {
|
||||
// FIXME: This is a bit of a dirty approach that assumes 2 paths of length 3 each. We should do better than this.
|
||||
if (newValue.count() != 2) { return }
|
||||
val path0 = newValue[0]
|
||||
@ -147,7 +147,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
if (path0.count() != 3 || path1.count() != 3) { return }
|
||||
Log.d("Loki", "Persisting onion request paths to database.")
|
||||
val database = databaseHelper.writableDatabase
|
||||
fun set(indexPath: String ,snode: LokiAPITarget) {
|
||||
fun set(indexPath: String ,snode: Snode) {
|
||||
var snodeAsString = "${snode.address}-${snode.port}"
|
||||
val keySet = snode.publicKeySet
|
||||
if (keySet != null) {
|
||||
@ -161,7 +161,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
set("1-1", path1[1]); set("1-2", path1[2])
|
||||
}
|
||||
|
||||
override fun getSwarm(hexEncodedPublicKey: String): Set<LokiAPITarget>? {
|
||||
override fun getSwarm(hexEncodedPublicKey: String): Set<Snode>? {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(swarmCache, "${Companion.hexEncodedPublicKey} = ?", wrap(hexEncodedPublicKey)) { cursor ->
|
||||
val swarmAsString = cursor.getString(cursor.getColumnIndexOrThrow(swarm))
|
||||
@ -171,12 +171,12 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
val port = components.getOrNull(1)?.toIntOrNull() ?: return@mapNotNull null
|
||||
val ed25519Key = components.getOrNull(2) ?: return@mapNotNull null
|
||||
val x25519Key = components.getOrNull(3) ?: return@mapNotNull null
|
||||
LokiAPITarget(address, port, LokiAPITarget.KeySet(ed25519Key, x25519Key))
|
||||
Snode(address, port, Snode.KeySet(ed25519Key, x25519Key))
|
||||
}
|
||||
}?.toSet()
|
||||
}
|
||||
|
||||
override fun setSwarm(hexEncodedPublicKey: String, newValue: Set<LokiAPITarget>) {
|
||||
override fun setSwarm(hexEncodedPublicKey: String, newValue: Set<Snode>) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val swarmAsString = newValue.joinToString(", ") { target ->
|
||||
var string = "${target.address}-${target.port}"
|
||||
@ -190,14 +190,14 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
database.insertOrUpdate(swarmCache, row, "${Companion.hexEncodedPublicKey} = ?", wrap(hexEncodedPublicKey))
|
||||
}
|
||||
|
||||
override fun getLastMessageHashValue(target: LokiAPITarget): String? {
|
||||
override fun getLastMessageHashValue(target: Snode): String? {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(lastMessageHashValueCache, "${Companion.target} = ?", wrap(target.address)) { cursor ->
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(lastMessageHashValue))
|
||||
}
|
||||
}
|
||||
|
||||
override fun setLastMessageHashValue(target: LokiAPITarget, newValue: String) {
|
||||
override fun setLastMessageHashValue(target: Snode, newValue: String) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val row = wrap(mapOf(Companion.target to target.address, lastMessageHashValue to newValue))
|
||||
database.insertOrUpdate(lastMessageHashValueCache, row, "${Companion.target} = ?", wrap(target.address))
|
||||
|
@ -21,7 +21,7 @@ import org.thoughtcrime.securesms.loki.utilities.QRCodeUtilities
|
||||
import org.thoughtcrime.securesms.loki.utilities.toPx
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPI
|
||||
import org.whispersystems.signalservice.loki.api.SnodeAPI
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
||||
@ -84,7 +84,7 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
|
||||
contentView.cancelButton.visibility = View.GONE
|
||||
contentView.authorizeButton.visibility = View.GONE
|
||||
}
|
||||
LokiFileServerAPI.shared.addDeviceLink(deviceLink).bind(LokiAPI.sharedContext) {
|
||||
LokiFileServerAPI.shared.addDeviceLink(deviceLink).bind(SnodeAPI.sharedContext) {
|
||||
MultiDeviceProtocol.signAndSendDeviceLinkMessage(context!!, deviceLink)
|
||||
}.success {
|
||||
TextSecurePreferences.setMultiDevice(context!!, true)
|
||||
|
@ -17,7 +17,7 @@ import org.whispersystems.libsignal.SignalProtocolAddress
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPI
|
||||
import org.whispersystems.signalservice.loki.api.SnodeAPI
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import java.util.*
|
||||
@ -106,13 +106,7 @@ object ClosedGroupsProtocol {
|
||||
allDevices.remove(userPublicKey)
|
||||
}
|
||||
for (device in allDevices) {
|
||||
val deviceAsAddress = SignalProtocolAddress(device, SignalServiceAddress.DEFAULT_DEVICE_ID)
|
||||
val hasSession = TextSecureSessionStore(context).containsSession(deviceAsAddress)
|
||||
if (hasSession) { continue }
|
||||
if (DatabaseFactory.getLokiAPIDatabase(context).getSessionRequestTimestamp(device) != null) { return }
|
||||
DatabaseFactory.getLokiAPIDatabase(context).setSessionRequestTimestamp(device, Date().time)
|
||||
val sessionRequest = EphemeralMessage.createSessionRequest(device)
|
||||
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(sessionRequest))
|
||||
ApplicationContext.getInstance(context).sendSessionRequest(device)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package org.thoughtcrime.securesms.loki.protocol
|
||||
|
||||
import com.google.protobuf.ByteString
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
|
||||
import org.thoughtcrime.securesms.database.Address
|
||||
import org.thoughtcrime.securesms.jobmanager.Data
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.jobs.BaseJob
|
||||
import org.thoughtcrime.securesms.logging.Log
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos
|
||||
import org.whispersystems.signalservice.loki.protocol.meta.TTLUtilities
|
||||
import java.io.IOException
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class PushNullMessageSendJob private constructor(parameters: Parameters, private val publicKey: String) : BaseJob(parameters) {
|
||||
|
||||
companion object {
|
||||
const val KEY = "PushNullMessageSendJob"
|
||||
}
|
||||
|
||||
constructor(publicKey: String) : this(Parameters.Builder()
|
||||
.addConstraint(NetworkConstraint.KEY)
|
||||
.setQueue(KEY)
|
||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
||||
.setMaxAttempts(1)
|
||||
.build(),
|
||||
publicKey)
|
||||
|
||||
override fun serialize(): Data {
|
||||
return Data.Builder().putString("publicKey", publicKey).build()
|
||||
}
|
||||
|
||||
override fun getFactoryKey(): String { return KEY }
|
||||
|
||||
public override fun onRun() {
|
||||
val contentMessage = SignalServiceProtos.Content.newBuilder()
|
||||
val nullMessage = SignalServiceProtos.NullMessage.newBuilder()
|
||||
val sr = SecureRandom()
|
||||
val paddingSize = sr.nextInt(512)
|
||||
val padding = ByteArray(paddingSize)
|
||||
sr.nextBytes(padding)
|
||||
nullMessage.padding = ByteString.copyFrom(padding)
|
||||
contentMessage.nullMessage = nullMessage.build()
|
||||
val serializedContentMessage = contentMessage.build().toByteArray()
|
||||
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
||||
val address = SignalServiceAddress(publicKey)
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false)
|
||||
val udAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient)
|
||||
val ttl = TTLUtilities.getTTL(TTLUtilities.MessageType.Ephemeral)
|
||||
try {
|
||||
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess,
|
||||
Date().time, serializedContentMessage, false, ttl, false,
|
||||
false, false, false, false)
|
||||
} catch (e: Exception) {
|
||||
Log.d("Loki", "Failed to send null message to: $publicKey due to error: $e.")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onShouldRetry(e: Exception): Boolean {
|
||||
// Disable since we have our own retrying
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onCanceled() { }
|
||||
|
||||
class Factory : Job.Factory<PushNullMessageSendJob> {
|
||||
|
||||
override fun create(parameters: Parameters, data: Data): PushNullMessageSendJob {
|
||||
try {
|
||||
val publicKey = data.getString("publicKey")
|
||||
return PushNullMessageSendJob(parameters, publicKey)
|
||||
} catch (e: IOException) {
|
||||
throw AssertionError(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.libsignal.loki.LokiSessionResetStatus
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
import java.util.*
|
||||
|
||||
object SessionManagementProtocol {
|
||||
|
||||
@ -59,6 +59,14 @@ object SessionManagementProtocol {
|
||||
val registrationID = TextSecurePreferences.getLocalRegistrationId(context) // TODO: It seems wrong to use the local registration ID for this?
|
||||
val lokiPreKeyBundleDatabase = DatabaseFactory.getLokiPreKeyBundleDatabase(context)
|
||||
Log.d("Loki", "Received a pre key bundle from: " + content.sender.toString() + ".")
|
||||
if (content.dataMessage.isPresent && content.dataMessage.get().isSessionRequest) {
|
||||
val sessionRequestTimestamp = DatabaseFactory.getLokiAPIDatabase(context).getSessionRequestTimestamp(content.sender)
|
||||
if (sessionRequestTimestamp != null && content.timestamp < sessionRequestTimestamp) {
|
||||
// We sent or processed a session request after this one was sent
|
||||
Log.d("Loki", "Ignoring session request from: ${content.sender}.")
|
||||
return
|
||||
}
|
||||
}
|
||||
val preKeyBundle = preKeyBundleMessage.getPreKeyBundle(registrationID)
|
||||
lokiPreKeyBundleDatabase.setPreKeyBundle(content.sender, preKeyBundle)
|
||||
}
|
||||
@ -66,11 +74,13 @@ object SessionManagementProtocol {
|
||||
@JvmStatic
|
||||
fun handleSessionRequestIfNeeded(context: Context, content: SignalServiceContent): Boolean {
|
||||
if (!content.dataMessage.isPresent || !content.dataMessage.get().isSessionRequest) { return false }
|
||||
val sentSessionRequestTimestamp = DatabaseFactory.getLokiAPIDatabase(context).getSessionRequestTimestamp(content.sender)
|
||||
if (sentSessionRequestTimestamp != null && content.timestamp < sentSessionRequestTimestamp) {
|
||||
// We sent a session request after this one was sent
|
||||
val sessionRequestTimestamp = DatabaseFactory.getLokiAPIDatabase(context).getSessionRequestTimestamp(content.sender)
|
||||
if (sessionRequestTimestamp != null && content.timestamp < sessionRequestTimestamp) {
|
||||
// We sent or processed a session request after this one was sent
|
||||
Log.d("Loki", "Ignoring session request from: ${content.sender}.")
|
||||
return false
|
||||
}
|
||||
DatabaseFactory.getLokiAPIDatabase(context).setSessionRequestTimestamp(content.sender, Date().time)
|
||||
val ephemeralMessage = EphemeralMessage.create(content.sender)
|
||||
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(ephemeralMessage))
|
||||
return true
|
||||
|
@ -14,8 +14,8 @@ import org.whispersystems.signalservice.api.messages.SignalServiceContent
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.loki.api.rssfeeds.LokiRSSFeed
|
||||
import org.whispersystems.signalservice.loki.api.rssfeeds.LokiRSSFeedProxy
|
||||
import org.whispersystems.signalservice.loki.api.shelved.rssfeeds.LokiRSSFeed
|
||||
import org.whispersystems.signalservice.loki.api.shelved.rssfeeds.LokiRSSFeedProxy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@ -66,7 +66,7 @@ class LokiRSSFeedPoller(private val context: Context, private val feed: LokiRSSF
|
||||
val id = feed.id.toByteArray()
|
||||
val x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.RSS_FEED, null, null, null, null)
|
||||
val x2 = SignalServiceDataMessage(timestamp, x1, null, body)
|
||||
val x3 = SignalServiceContent(x2, "Loki", SignalServiceAddress.DEFAULT_DEVICE_ID, timestamp, false, false, false, false, false)
|
||||
val x3 = SignalServiceContent(x2, "Loki", SignalServiceAddress.DEFAULT_DEVICE_ID, timestamp, false, false, false, false)
|
||||
PushDecryptJob(context).handleTextMessage(x3, x2, Optional.absent(), Optional.absent())
|
||||
}
|
||||
}.fail { exception ->
|
||||
|
@ -10,7 +10,7 @@ import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.loki.api.LokiPublicChatManager;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Debouncer;
|
||||
import org.whispersystems.signalservice.loki.api.LokiPoller;
|
||||
import org.whispersystems.signalservice.loki.api.Poller;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -40,9 +40,9 @@ public class OptimizedMessageNotifier implements MessageNotifier {
|
||||
|
||||
@Override
|
||||
public void updateNotification(@NonNull Context context) {
|
||||
LokiPoller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
Poller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
LokiPublicChatManager lokiPublicChatManager = ApplicationContext.getInstance(context).lokiPublicChatManager;
|
||||
Boolean isCaughtUp = false;
|
||||
boolean isCaughtUp = false;
|
||||
if (lokiPoller != null && lokiPublicChatManager != null) {
|
||||
isCaughtUp = lokiPoller.isCaughtUp() && lokiPublicChatManager.areAllCaughtUp();
|
||||
}
|
||||
@ -56,9 +56,9 @@ public class OptimizedMessageNotifier implements MessageNotifier {
|
||||
|
||||
@Override
|
||||
public void updateNotification(@NonNull Context context, long threadId) {
|
||||
LokiPoller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
Poller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
LokiPublicChatManager lokiPublicChatManager = ApplicationContext.getInstance(context).lokiPublicChatManager;
|
||||
Boolean isCaughtUp = false;
|
||||
boolean isCaughtUp = false;
|
||||
if (lokiPoller != null && lokiPublicChatManager != null) {
|
||||
isCaughtUp = lokiPoller.isCaughtUp() && lokiPublicChatManager.areAllCaughtUp();
|
||||
}
|
||||
@ -72,9 +72,9 @@ public class OptimizedMessageNotifier implements MessageNotifier {
|
||||
|
||||
@Override
|
||||
public void updateNotification(@NonNull Context context, long threadId, boolean signal) {
|
||||
LokiPoller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
Poller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
LokiPublicChatManager lokiPublicChatManager = ApplicationContext.getInstance(context).lokiPublicChatManager;
|
||||
Boolean isCaughtUp = false;
|
||||
boolean isCaughtUp = false;
|
||||
if (lokiPoller != null && lokiPublicChatManager != null) {
|
||||
isCaughtUp = lokiPoller.isCaughtUp() && lokiPublicChatManager.areAllCaughtUp();
|
||||
}
|
||||
@ -88,9 +88,9 @@ public class OptimizedMessageNotifier implements MessageNotifier {
|
||||
|
||||
@Override
|
||||
public void updateNotification(@android.support.annotation.NonNull Context context, boolean signal, int reminderCount) {
|
||||
LokiPoller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
Poller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
LokiPublicChatManager lokiPublicChatManager = ApplicationContext.getInstance(context).lokiPublicChatManager;
|
||||
Boolean isCaughtUp = false;
|
||||
boolean isCaughtUp = false;
|
||||
if (lokiPoller != null && lokiPublicChatManager != null) {
|
||||
isCaughtUp = lokiPoller.isCaughtUp() && lokiPublicChatManager.areAllCaughtUp();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user