hook up sending pipeline & clean

This commit is contained in:
Ryan ZHAO 2021-03-02 12:24:09 +11:00
parent 242eb90d21
commit d9eaedd6ae
79 changed files with 457 additions and 749 deletions

View File

@ -34,6 +34,7 @@ import com.google.firebase.iid.FirebaseInstanceId;
import org.conscrypt.Conscrypt;
import org.session.libsession.messaging.MessagingConfiguration;
import org.session.libsession.messaging.avatars.AvatarHelper;
import org.session.libsession.snode.SnodeConfiguration;
import org.session.libsession.utilities.SSKEnvironment;
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
@ -176,6 +177,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
DatabaseFactory.getStorage(this),
DatabaseFactory.getAttachmentProvider(this),
new SessionProtocolImpl(this));
SnodeConfiguration.Companion.configure(apiDB, broadcaster);
if (userPublicKey != null) {
SwarmAPI.Companion.configureIfNeeded(apiDB);
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);

View File

@ -37,7 +37,11 @@ import androidx.loader.app.LoaderManager.LoaderCallbacks;
import androidx.loader.content.Loader;
import org.session.libsession.messaging.messages.visible.LinkPreview;
import org.session.libsession.messaging.messages.visible.Quote;
import org.session.libsession.messaging.messages.visible.VisibleMessage;
import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.thoughtcrime.securesms.MessageDetailsRecipientAdapter.RecipientDeliveryStatus;
import org.session.libsession.utilities.color.MaterialColor;
import org.thoughtcrime.securesms.conversation.ConversationItem;
@ -50,12 +54,12 @@ import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.loaders.MessageDetailsLoader;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.session.libsession.messaging.threads.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.DateUtils;
import org.session.libsession.utilities.ExpirationUtil;
import org.session.libsession.utilities.Util;
@ -441,7 +445,28 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
}
private void onResendClicked(View v) {
MessageSender.resend(MessageDetailsActivity.this, messageRecord);
Recipient recipient = messageRecord.getRecipient();
VisibleMessage message = new VisibleMessage();
message.setId(messageRecord.getId());
message.setText(messageRecord.getBody());
message.setSentTimestamp(messageRecord.getTimestamp());
if (recipient.isGroupRecipient()) {
message.setGroupPublicKey(recipient.getAddress().toGroupString());
} else {
message.setRecipient(messageRecord.getRecipient().getAddress().serialize());
}
message.setThreadID(messageRecord.getThreadId());
if (messageRecord.isMms()) {
MmsMessageRecord mmsMessageRecord = (MmsMessageRecord) messageRecord;
if (!mmsMessageRecord.getLinkPreviews().isEmpty()) {
message.setLinkPreview(LinkPreview.Companion.from(mmsMessageRecord.getLinkPreviews().get(0)));
}
if (mmsMessageRecord.getQuote() != null) {
message.setQuote(Quote.Companion.from(mmsMessageRecord.getQuote().getQuoteModel()));
}
message.addSignalAttachments(mmsMessageRecord.getSlideDeck().asAttachments());
}
MessageSender.send(message, recipient.getAddress());
resendButton.setVisibility(View.GONE);
}
}

View File

@ -35,6 +35,7 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import org.session.libsession.messaging.threads.DistributionTypes;
import org.thoughtcrime.securesms.components.SearchToolbar;
import org.thoughtcrime.securesms.conversation.ConversationActivity;
import org.session.libsession.messaging.threads.Address;
@ -249,7 +250,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
public void onContactSelected(String number) {
Recipient recipient = Recipient.from(this, Address.fromExternal(this, number), true);
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient);
createConversation(existingThread, recipient.getAddress(), ThreadDatabase.DistributionTypes.DEFAULT);
createConversation(existingThread, recipient.getAddress(), DistributionTypes.DEFAULT);
}
@Override

View File

@ -79,7 +79,8 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
override fun isOutgoingMessage(timestamp: Long): Boolean {
val smsDatabase = DatabaseFactory.getSmsDatabase(context)
return smsDatabase.isOutgoingMessage(timestamp)
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
return smsDatabase.isOutgoingMessage(timestamp) || mmsDatabase.isOutgoingMessage(timestamp)
}
override fun getMessageID(serverID: Long): Long? {

View File

@ -4,6 +4,7 @@ package org.thoughtcrime.securesms.attachments;
import android.net.Uri;
import androidx.annotation.Nullable;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
@ -30,11 +31,11 @@ public class MmsNotificationAttachment extends Attachment {
if (status == MmsDatabase.Status.DOWNLOAD_INITIALIZED ||
status == MmsDatabase.Status.DOWNLOAD_NO_CONNECTIVITY)
{
return AttachmentDatabase.TRANSFER_PROGRESS_PENDING;
return AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING;
} else if (status == MmsDatabase.Status.DOWNLOAD_CONNECTING) {
return AttachmentDatabase.TRANSFER_PROGRESS_STARTED;
return AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED;
} else {
return AttachmentDatabase.TRANSFER_PROGRESS_FAILED;
return AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED;
}
}
}

View File

@ -20,6 +20,8 @@ import com.pnikosis.materialishprogress.ProgressWheel;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import network.loki.messenger.R;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.events.PartProgressEvent;
import org.thoughtcrime.securesms.mms.DocumentSlide;
@ -94,7 +96,7 @@ public class DocumentView extends FrameLayout {
controlToggle.displayQuick(downloadButton);
downloadButton.setOnClickListener(new DownloadClickedListener(documentSlide));
if (downloadProgress.isSpinning()) downloadProgress.stopSpinning();
} else if (showControls && documentSlide.getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_STARTED) {
} else if (showControls && documentSlide.getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED) {
controlToggle.displayQuick(downloadProgress);
downloadProgress.spin();
} else {

View File

@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import android.util.AttributeSet;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.session.libsignal.utilities.logging.Log;
import android.view.View;
import android.view.ViewGroup;
@ -248,7 +249,7 @@ public class ThumbnailView extends FrameLayout {
}
if (slide.getThumbnailUri() != null && slide.hasPlayOverlay() &&
(slide.getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_DONE || isPreview))
(slide.getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_DONE || isPreview))
{
this.playOverlay.setVisibility(View.VISIBLE);
} else {
@ -402,7 +403,7 @@ public class ThumbnailView extends FrameLayout {
if (thumbnailClickListener != null &&
slide != null &&
slide.asAttachment().getDataUri() != null &&
slide.getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_DONE)
slide.getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_DONE)
{
thumbnailClickListener.onClick(view, slide);
} else if (parentClickListener != null) {

View File

@ -17,6 +17,7 @@ import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.events.PartProgressEvent;
import org.thoughtcrime.securesms.mms.Slide;
@ -105,17 +106,17 @@ public class TransferControlView extends FrameLayout {
}
for (Slide slide : slides) {
if (slide.asAttachment().getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_DONE) {
if (slide.asAttachment().getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_DONE) {
downloadProgress.put(slide.asAttachment(), 1f);
}
}
switch (getTransferState(slides)) {
case AttachmentDatabase.TRANSFER_PROGRESS_STARTED:
case AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED:
showProgressSpinner(calculateProgress(downloadProgress));
break;
case AttachmentDatabase.TRANSFER_PROGRESS_PENDING:
case AttachmentDatabase.TRANSFER_PROGRESS_FAILED:
case AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING:
case AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED:
downloadDetailsText.setText(getDownloadText(this.slides));
display(downloadDetails);
break;
@ -174,9 +175,9 @@ public class TransferControlView extends FrameLayout {
}
private int getTransferState(@NonNull List<Slide> slides) {
int transferState = AttachmentDatabase.TRANSFER_PROGRESS_DONE;
int transferState = AttachmentTransferProgress.TRANSFER_PROGRESS_DONE;
for (Slide slide : slides) {
if (slide.getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_PENDING && transferState == AttachmentDatabase.TRANSFER_PROGRESS_DONE) {
if (slide.getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING && transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_DONE) {
transferState = slide.getTransferState();
} else {
transferState = Math.max(transferState, slide.getTransferState());
@ -189,7 +190,7 @@ public class TransferControlView extends FrameLayout {
if (slides.size() == 1) {
return slides.get(0).getContentDescription();
} else {
int downloadCount = Stream.of(slides).reduce(0, (count, slide) -> slide.getTransferState() != AttachmentDatabase.TRANSFER_PROGRESS_DONE ? count + 1 : count);
int downloadCount = Stream.of(slides).reduce(0, (count, slide) -> slide.getTransferState() != AttachmentTransferProgress.TRANSFER_PROGRESS_DONE ? count + 1 : count);
return getContext().getResources().getQuantityString(R.plurals.TransferControlView_n_items, downloadCount, downloadCount);
}
}

View File

@ -85,6 +85,10 @@ import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate;
import org.session.libsession.messaging.messages.visible.VisibleMessage;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.threads.DistributionTypes;
import org.session.libsession.utilities.GroupUtil;
import org.session.libsession.utilities.MediaTypes;
import org.session.libsignal.libsignal.InvalidMessageException;
@ -124,6 +128,7 @@ import org.thoughtcrime.securesms.database.DraftDatabase.Draft;
import org.thoughtcrime.securesms.database.DraftDatabase.Drafts;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.MmsSmsColumns.Types;
import org.thoughtcrime.securesms.database.Storage;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
@ -153,7 +158,7 @@ import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.ImageSlide;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
import org.thoughtcrime.securesms.mms.QuoteId;
@ -168,9 +173,8 @@ import org.session.libsession.messaging.threads.recipients.Recipient;
import org.session.libsession.messaging.threads.recipients.RecipientFormattingException;
import org.session.libsession.messaging.threads.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.search.model.MessageResult;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.MediaUtil;
@ -197,7 +201,6 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@ -571,16 +574,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
final Context context = ConversationActivity.this.getApplicationContext();
sendMediaMessage(false,
message,
sendMediaMessage(message,
slideDeck,
inputPanel.getQuote().orNull(),
Collections.emptyList(),
Collections.emptyList(),
expiresIn,
subscriptionId,
initiating,
true).addListener(new AssertedSuccessListener<Void>() {
Optional.absent(),
initiating).addListener(new AssertedSuccessListener<Void>() {
@Override
public void onSuccess(Void result) {
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
@ -648,7 +646,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if (!isPushGroupConversation()) {
inflater.inflate(R.menu.conversation_mms_group_options, menu);
if (distributionType == ThreadDatabase.DistributionTypes.BROADCAST) {
if (distributionType == DistributionTypes.BROADCAST) {
menu.findItem(R.id.menu_distribution_broadcast).setChecked(true);
} else {
menu.findItem(R.id.menu_distribution_conversation).setChecked(true);
@ -808,8 +806,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
protected Void doInBackground(Void... params) {
DatabaseFactory.getRecipientDatabase(ConversationActivity.this).setExpireMessages(recipient, expirationTime);
OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(getRecipient(), System.currentTimeMillis(), expirationTime * 1000L);
MessageSender.send(ConversationActivity.this, outgoingMessage, threadId, false, null);
ExpirationTimerUpdate message = new ExpirationTimerUpdate();
message.setDuration(expirationTime * 1000);
MessageSender.send(message, recipient.getAddress());
return null;
}
@ -1040,7 +1039,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void handleDistributionBroadcastEnabled(MenuItem item) {
distributionType = ThreadDatabase.DistributionTypes.BROADCAST;
distributionType = DistributionTypes.BROADCAST;
item.setChecked(true);
if (threadId != -1) {
@ -1048,7 +1047,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
protected Void doInBackground(Void... params) {
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
.setDistributionType(threadId, ThreadDatabase.DistributionTypes.BROADCAST);
.setDistributionType(threadId, DistributionTypes.BROADCAST);
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
@ -1056,7 +1055,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void handleDistributionConversationEnabled(MenuItem item) {
distributionType = ThreadDatabase.DistributionTypes.CONVERSATION;
distributionType = DistributionTypes.CONVERSATION;
item.setChecked(true);
if (threadId != -1) {
@ -1064,7 +1063,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
protected Void doInBackground(Void... params) {
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
.setDistributionType(threadId, ThreadDatabase.DistributionTypes.CONVERSATION);
.setDistributionType(threadId, DistributionTypes.CONVERSATION);
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
@ -1335,7 +1334,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if (address == null) { finish(); return; }
recipient = Recipient.from(this, address, true);
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, DistributionTypes.DEFAULT);
glideRequests = GlideApp.with(this);
recipient.addListener(this);
@ -1483,14 +1482,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
else if (contactData.numbers.size() > 1) selectContactInfo(contactData);
}
private void sendSharedContact(List<Contact> contacts) {
int subscriptionId = -1;
long expiresIn = recipient.getExpireMessages() * 1000L;
boolean initiating = threadId == -1;
sendMediaMessage(false, "", attachmentManager.buildSlideDeck(), null, contacts, Collections.emptyList(), expiresIn, subscriptionId, initiating, false);
}
private void selectContactInfo(ContactData contactData) {
final CharSequence[] numbers = new CharSequence[contactData.numbers.size()];
final CharSequence[] numberItems = new CharSequence[contactData.numbers.size()];
@ -1735,8 +1726,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
String message = getMessage();
int subscriptionId = -1;
long expiresIn = recipient.getExpireMessages() * 1000L;
boolean initiating = threadId == -1;
boolean needsSplit = message.length() > characterCalculator.calculateCharacters(message).maxPrimaryMessageSize;
boolean isMediaMessage = attachmentManager.isAttachmentPresent() ||
@ -1747,9 +1736,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
needsSplit;
if (isMediaMessage) {
sendMediaMessage(expiresIn, subscriptionId, initiating);
sendMediaMessage(initiating);
} else {
sendTextMessage(expiresIn, subscriptionId, initiating);
sendTextMessage(initiating);
}
} catch (RecipientFormattingException ex) {
Log.w(TAG, ex);
@ -1764,23 +1753,18 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
}
private void sendMediaMessage(final long expiresIn, final int subscriptionId, boolean initiating)
private void sendMediaMessage(boolean initiating)
throws InvalidMessageException
{
Log.i(TAG, "Sending media message...");
sendMediaMessage(false, getMessage(), attachmentManager.buildSlideDeck(), inputPanel.getQuote().orNull(), Collections.emptyList(), linkPreviewViewModel.getActiveLinkPreviews(), expiresIn, subscriptionId, initiating, true);
sendMediaMessage(getMessage(), attachmentManager.buildSlideDeck(), inputPanel.getQuote().orNull(), linkPreviewViewModel.getActiveLinkPreview(), initiating);
}
private ListenableFuture<Void> sendMediaMessage(final boolean forceSms,
String body,
private ListenableFuture<Void> sendMediaMessage(String body,
SlideDeck slideDeck,
QuoteModel quote,
List<Contact> contacts,
List<LinkPreview> previews,
final long expiresIn,
final int subscriptionId,
final boolean initiating,
final boolean clearComposeBox)
Optional<LinkPreview> linkPreview,
final boolean initiating)
{
Pair<String, Optional<Slide>> splitMessage = getSplitMessage(body, characterCalculator.calculateCharacters(body).maxPrimaryMessageSize);
@ -1790,7 +1774,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
slideDeck.addSlide(splitMessage.second.get());
}
OutgoingMediaMessage outgoingMessageCandidate = new OutgoingMediaMessage(recipient, slideDeck, body, System.currentTimeMillis(), subscriptionId, expiresIn, distributionType, quote, contacts, previews);
List<Attachment> attachments = slideDeck.asAttachments();
VisibleMessage message = new VisibleMessage();
message.setSentTimestamp(System.currentTimeMillis());
message.setText(body);
OutgoingMediaMessage outgoingMessageCandidate = OutgoingMediaMessage.from(message, recipient, attachments, quote, linkPreview.orNull());
final SettableFuture<Void> future = new SettableFuture<>();
final Context context = getApplicationContext();
@ -1800,11 +1789,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
outgoingMessage = new OutgoingSecureMediaMessage(outgoingMessageCandidate);
ApplicationContext.getInstance(context).getTypingStatusSender().onTypingStopped(threadId);
if (clearComposeBox) {
inputPanel.clearQuote();
attachmentManager.clear(glideRequests, false);
silentlySetComposeText("");
}
inputPanel.clearQuote();
attachmentManager.clear(glideRequests, false);
silentlySetComposeText("");
final long id = fragment.stageOutgoingMessage(outgoingMessage);
@ -1812,43 +1799,54 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
}
long result = MessageSender.send(context, outgoingMessage, threadId, forceSms, () -> fragment.releaseOutgoingMessage(id));
sendComplete(result);
try {
long allocatedThreadId;
if (threadId == -1) {
allocatedThreadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
} else {
allocatedThreadId = threadId;
}
DatabaseFactory.getMmsDatabase(context).insertMessageOutbox(outgoingMessage, allocatedThreadId, false, ()->fragment.releaseOutgoingMessage(id));
MessageSender.send(message, recipient.getAddress(), attachments, quote, linkPreview.orNull());
sendComplete(allocatedThreadId);
} catch (MmsException e) {
Log.w(TAG, e);
sendComplete(threadId);
}
future.set(null);
return future;
}
private void sendTextMessage(final long expiresIn, final int subscriptionId, final boolean initiatingConversation)
private void sendTextMessage(final boolean initiating)
throws InvalidMessageException
{
final Context context = getApplicationContext();
final String messageBody = getMessage();
OutgoingTextMessage message;
message = new OutgoingEncryptedMessage(recipient, messageBody, expiresIn);
VisibleMessage message = new VisibleMessage();
message.setSentTimestamp(System.currentTimeMillis());
message.setText(messageBody);
OutgoingTextMessage outgoingTextMessage = OutgoingTextMessage.from(message, recipient);
ApplicationContext.getInstance(context).getTypingStatusSender().onTypingStopped(threadId);
silentlySetComposeText("");
final long id = fragment.stageOutgoingMessage(message);
final long id = fragment.stageOutgoingMessage(outgoingTextMessage);
if (initiatingConversation) {
if (initiating) {
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
}
long result = MessageSender.send(context, message, threadId, false, () -> fragment.releaseOutgoingMessage(id));
long allocatedThreadId;
if (threadId == -1) {
allocatedThreadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
} else {
allocatedThreadId = threadId;
}
DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(allocatedThreadId, outgoingTextMessage, false, message.getSentTimestamp(), ()->fragment.releaseOutgoingMessage(id));
MessageSender.send(message, recipient.getAddress());
sendComplete(result);
}
private void showDefaultSmsPrompt() {
new AlertDialog.Builder(this)
.setMessage(R.string.ConversationActivity_signal_cannot_sent_sms_mms_messages_because_it_is_not_your_default_sms_app)
.setNegativeButton(R.string.ConversationActivity_no, (dialog, which) -> dialog.dismiss())
.setPositiveButton(R.string.ConversationActivity_yes, (dialog, which) -> handleMakeDefaultSms())
.show();
sendComplete(allocatedThreadId);
}
private void updateToggleButtonState() {
@ -1934,7 +1932,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
SlideDeck slideDeck = new SlideDeck();
slideDeck.addSlide(audioSlide);
sendMediaMessage(false, "", slideDeck, inputPanel.getQuote().orNull(), Collections.emptyList(), Collections.emptyList(), expiresIn, subscriptionId, initiating, true).addListener(new AssertedSuccessListener<Void>() {
sendMediaMessage("", slideDeck, inputPanel.getQuote().orNull(), Optional.absent(), initiating).addListener(new AssertedSuccessListener<Void>() {
@Override
public void onSuccess(Void nothing) {
new AsyncTask<Void, Void, Void>() {

View File

@ -57,6 +57,8 @@ import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
import com.annimon.stream.Stream;
import org.session.libsession.messaging.messages.visible.Quote;
import org.session.libsession.messaging.messages.visible.VisibleMessage;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.MessageDetailsActivity;
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
@ -82,8 +84,9 @@ import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
@ -92,7 +95,6 @@ import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI;
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.ViewUtil;
@ -696,11 +698,32 @@ public class ConversationFragment extends Fragment
}
private void handleResendMessage(final MessageRecord message) {
final Context context = getActivity().getApplicationContext();
new AsyncTask<MessageRecord, Void, Void>() {
@Override
protected Void doInBackground(MessageRecord... messageRecords) {
MessageSender.resend(context, messageRecords[0]);
MessageRecord messageRecord = messageRecords[0];
Recipient recipient = messageRecord.getRecipient();
VisibleMessage message = new VisibleMessage();
message.setId(messageRecord.getId());
message.setText(messageRecord.getBody());
message.setSentTimestamp(messageRecord.getTimestamp());
if (recipient.isGroupRecipient()) {
message.setGroupPublicKey(recipient.getAddress().toGroupString());
} else {
message.setRecipient(messageRecord.getRecipient().getAddress().serialize());
}
message.setThreadID(messageRecord.getThreadId());
if (messageRecord.isMms()) {
MmsMessageRecord mmsMessageRecord = (MmsMessageRecord) messageRecord;
if (!mmsMessageRecord.getLinkPreviews().isEmpty()) {
message.setLinkPreview(org.session.libsession.messaging.messages.visible.LinkPreview.Companion.from(mmsMessageRecord.getLinkPreviews().get(0)));
}
if (mmsMessageRecord.getQuote() != null) {
message.setQuote(Quote.Companion.from(mmsMessageRecord.getQuote().getQuoteModel()));
}
message.addSignalAttachments(mmsMessageRecord.getSlideDeck().asAttachments());
}
MessageSender.send(message, recipient.getAddress());
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, message);

View File

@ -53,6 +53,7 @@ import androidx.annotation.Nullable;
import com.annimon.stream.Stream;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI;
@ -1003,10 +1004,10 @@ public class ConversationItem extends LinearLayout
if (messageRecord.isMms()) {
TextSlide slide = ((MmsMessageRecord) messageRecord).getSlideDeck().getTextSlide();
if (slide != null && slide.asAttachment().getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_DONE) {
if (slide != null && slide.asAttachment().getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_DONE) {
message = getResources().getString(R.string.ConversationItem_read_more);
action = () -> eventListener.onMoreTextClicked(conversationRecipient.getAddress(), messageRecord.getId(), messageRecord.isMms());
} else if (slide != null && slide.asAttachment().getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_STARTED) {
} else if (slide != null && slide.asAttachment().getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED) {
message = getResources().getString(R.string.ConversationItem_pending);
action = () -> {};
} else if (slide != null) {

View File

@ -38,6 +38,7 @@ import net.sqlcipher.database.SQLiteDatabase;
import org.json.JSONArray;
import org.json.JSONException;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.session.libsession.utilities.MediaTypes;
import org.session.libsignal.utilities.logging.Log;
@ -119,11 +120,6 @@ public class AttachmentDatabase extends Database {
static final String AUDIO_VISUAL_SAMPLES = "audio_visual_samples"; // Small amount of audio byte samples to visualise the content (e.g. draw waveform).
static final String AUDIO_DURATION = "audio_duration"; // Duration of the audio track in milliseconds.
public static final int TRANSFER_PROGRESS_DONE = 0;
public static final int TRANSFER_PROGRESS_STARTED = 1;
public static final int TRANSFER_PROGRESS_PENDING = 2;
public static final int TRANSFER_PROGRESS_FAILED = 3;
private static final String PART_ID_WHERE = ROW_ID + " = ? AND " + UNIQUE_ID + " = ?";
private static final String PART_AUDIO_ONLY_WHERE = CONTENT_TYPE + " LIKE \"audio/%\"";
@ -213,7 +209,7 @@ public class AttachmentDatabase extends Database {
{
SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(TRANSFER_STATE, TRANSFER_PROGRESS_FAILED);
values.put(TRANSFER_STATE, AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED);
database.update(TABLE_NAME, values, PART_ID_WHERE, attachmentId.toStrings());
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(mmsId));
@ -268,7 +264,7 @@ public class AttachmentDatabase extends Database {
Cursor cursor = null;
try {
cursor = database.query(TABLE_NAME, PROJECTION, TRANSFER_STATE + " = ?", new String[] {String.valueOf(TRANSFER_PROGRESS_STARTED)}, null, null, null);
cursor = database.query(TABLE_NAME, PROJECTION, TRANSFER_STATE + " = ?", new String[] {String.valueOf(AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED)}, null, null, null);
while (cursor != null && cursor.moveToNext()) {
attachments.addAll(getAttachment(cursor));
}
@ -372,7 +368,7 @@ public class AttachmentDatabase extends Database {
values.put(DATA_RANDOM, dataInfo.random);
}
values.put(TRANSFER_STATE, TRANSFER_PROGRESS_DONE);
values.put(TRANSFER_STATE, AttachmentTransferProgress.TRANSFER_PROGRESS_DONE);
values.put(CONTENT_LOCATION, (String)null);
values.put(CONTENT_DISPOSITION, (String)null);
values.put(DIGEST, (byte[])null);
@ -395,7 +391,7 @@ public class AttachmentDatabase extends Database {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(TRANSFER_STATE, TRANSFER_PROGRESS_DONE);
values.put(TRANSFER_STATE, AttachmentTransferProgress.TRANSFER_PROGRESS_DONE);
values.put(CONTENT_LOCATION, attachment.getLocation());
values.put(DIGEST, attachment.getDigest());
values.put(CONTENT_DISPOSITION, attachment.getKey());
@ -411,7 +407,7 @@ public class AttachmentDatabase extends Database {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(TRANSFER_STATE, TRANSFER_PROGRESS_FAILED);
values.put(TRANSFER_STATE, AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED);
database.update(TABLE_NAME, values, PART_ID_WHERE, id.toStrings());
}
@ -506,37 +502,17 @@ public class AttachmentDatabase extends Database {
databaseAttachment.getUrl());
}
public void updateAttachmentFileName(@NonNull AttachmentId attachmentId,
@Nullable String fileName)
{
SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues(1);
contentValues.put(FILE_NAME, ExternalStorageUtil.getCleanFileName(fileName));
database.update(TABLE_NAME, contentValues, PART_ID_WHERE, attachmentId.toStrings());
}
public void markAttachmentUploaded(long messageId, Attachment attachment) {
ContentValues values = new ContentValues(1);
SQLiteDatabase database = databaseHelper.getWritableDatabase();
values.put(TRANSFER_STATE, TRANSFER_PROGRESS_DONE);
values.put(TRANSFER_STATE, AttachmentTransferProgress.TRANSFER_PROGRESS_DONE);
database.update(TABLE_NAME, values, PART_ID_WHERE, ((DatabaseAttachment)attachment).getAttachmentId().toStrings());
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId));
((DatabaseAttachment) attachment).setUploaded(true);
}
public void setTransferState(long messageId, @NonNull Attachment attachment, int transferState) {
if (!(attachment instanceof DatabaseAttachment)) {
throw new AssertionError("Attempt to update attachment that doesn't belong to DB!");
}
setTransferState(messageId, ((DatabaseAttachment) attachment).getAttachmentId(), transferState);
}
public void setTransferState(long messageId, @NonNull AttachmentId attachmentId, int transferState) {
final ContentValues values = new ContentValues(1);
final SQLiteDatabase database = databaseHelper.getWritableDatabase();
@ -546,14 +522,6 @@ public class AttachmentDatabase extends Database {
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId));
}
public boolean hasStickerAttachments() {
String selection = STICKER_PACK_ID + " NOT NULL";
try (Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, selection, null, null, null, null, "1")) {
return cursor != null && cursor.moveToFirst();
}
}
@SuppressWarnings("WeakerAccess")
@VisibleForTesting
protected @Nullable InputStream getDataStream(AttachmentId attachmentId, String dataType, long offset)

View File

@ -7,9 +7,9 @@ import android.text.TextUtils;
import net.sqlcipher.database.SQLiteDatabase;
import org.thoughtcrime.securesms.database.documents.Document;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchList;
import org.session.libsession.database.documents.Document;
import org.session.libsession.database.documents.IdentityKeyMismatch;
import org.session.libsession.database.documents.IdentityKeyMismatchList;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.session.libsignal.utilities.logging.Log;
import org.session.libsignal.libsignal.IdentityKey;
@ -38,27 +38,6 @@ public abstract class MessagingDatabase extends Database implements MmsSmsColumn
public abstract void markAsSent(long messageId, boolean secure);
public abstract void markUnidentified(long messageId, boolean unidentified);
public void setMismatchedIdentity(long messageId, final Address address, final IdentityKey identityKey) {
List<IdentityKeyMismatch> items = new ArrayList<IdentityKeyMismatch>() {{
add(new IdentityKeyMismatch(address, identityKey));
}};
IdentityKeyMismatchList document = new IdentityKeyMismatchList(items);
SQLiteDatabase database = databaseHelper.getWritableDatabase();
database.beginTransaction();
try {
setDocument(database, messageId, MISMATCHED_IDENTITIES, document);
database.setTransactionSuccessful();
} catch (IOException ioe) {
Log.w(TAG, ioe);
} finally {
database.endTransaction();
}
}
public void addMismatchedIdentity(long messageId, Address address, IdentityKey identityKey) {
try {
addToDocument(messageId, MISMATCHED_IDENTITIES,

View File

@ -19,9 +19,7 @@ package org.thoughtcrime.securesms.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -38,10 +36,10 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.attachments.MmsNotificationAttachment;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchList;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.database.documents.NetworkFailureList;
import org.session.libsession.database.documents.IdentityKeyMismatch;
import org.session.libsession.database.documents.IdentityKeyMismatchList;
import org.session.libsession.database.documents.NetworkFailure;
import org.session.libsession.database.documents.NetworkFailureList;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;

View File

@ -23,8 +23,6 @@ import android.database.Cursor;
import android.text.TextUtils;
import android.util.Pair;
import androidx.annotation.NonNull;
import com.annimon.stream.Stream;
import net.sqlcipher.database.SQLiteDatabase;
@ -32,15 +30,15 @@ import net.sqlcipher.database.SQLiteStatement;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchList;
import org.session.libsession.database.documents.IdentityKeyMismatch;
import org.session.libsession.database.documents.IdentityKeyMismatchList;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.jobs.TrimThreadJob;
import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.session.libsession.messaging.messages.signal.IncomingGroupMessage;
import org.session.libsession.messaging.messages.signal.IncomingTextMessage;
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
import org.session.libsession.messaging.threads.Address;
import org.session.libsession.messaging.threads.recipients.Recipient;
@ -51,7 +49,6 @@ import org.session.libsignal.libsignal.util.guava.Optional;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

View File

@ -13,7 +13,6 @@ import org.session.libsession.messaging.messages.visible.VisibleMessage
import org.session.libsession.messaging.opengroups.OpenGroup
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
import org.session.libsession.messaging.sending_receiving.attachments.PointerAttachment
import org.session.libsession.messaging.sending_receiving.attachments.SessionServiceAttachment
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
import org.session.libsession.messaging.threads.Address
@ -41,9 +40,9 @@ import org.thoughtcrime.securesms.mms.IncomingMediaMessage
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage
import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.sms.IncomingGroupMessage
import org.thoughtcrime.securesms.sms.IncomingTextMessage
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
import org.session.libsession.messaging.messages.signal.IncomingGroupMessage
import org.session.libsession.messaging.messages.signal.IncomingTextMessage
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage
class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol {
override fun getUserPublicKey(): String? {
@ -125,7 +124,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}.mapNotNull {
PointerAttachment.forPointer(Optional.of(it)).orNull()
}
val mediaMessage = OutgoingMediaMessage.from(message, Recipient.from(context, targetAddress, false), attachments, quote.orNull(), linkPreviews.orNull())
val mediaMessage = OutgoingMediaMessage.from(message, Recipient.from(context, targetAddress, false), attachments, quote.orNull(), linkPreviews.orNull().firstOrNull())
mmsDatabase.insertSecureDecryptedMessageOutbox(mediaMessage, message.threadID ?: -1, message.sentTimestamp!!)
} else {
// It seems like we have replaced SignalServiceAttachment with SessionServiceAttachment
@ -331,9 +330,9 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
DatabaseFactory.getLokiMessageDatabase(context).setServerID(messageID, serverID)
}
override fun markAsSent(messageID: Long) {
override fun markAsSent(timestamp: Long, author: String) {
val database = DatabaseFactory.getMmsSmsDatabase(context)
val messageRecord = database.getMessageFor(messageID)!!
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
mmsDatabase.markAsSent(messageRecord.getId(), true)
@ -343,9 +342,9 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
}
override fun markUnidentified(messageID: Long) {
override fun markUnidentified(timestamp: Long, author: String) {
val database = DatabaseFactory.getMmsSmsDatabase(context)
val messageRecord = database.getMessageFor(messageID)!!
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
mmsDatabase.markUnidentified(messageRecord.getId(), true)

View File

@ -29,6 +29,7 @@ import com.annimon.stream.Stream;
import net.sqlcipher.database.SQLiteDatabase;
import org.session.libsession.messaging.threads.DistributionTypes;
import org.thoughtcrime.securesms.contactshare.ContactUtil;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
@ -596,14 +597,6 @@ public class ThreadDatabase extends Database {
return new Reader(cursor);
}
public static class DistributionTypes {
public static final int DEFAULT = 2;
public static final int BROADCAST = 1;
public static final int CONVERSATION = 2;
public static final int ARCHIVE = 3;
public static final int INBOX_ZERO = 4;
}
public class Reader implements Closeable {
private final Cursor cursor;

View File

@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase;
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsMigration;
public class SQLCipherOpenHelper extends SQLiteOpenHelper {
@ -52,9 +53,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
private static final int lokiV19 = 40;
private static final int lokiV20 = 41;
private static final int lokiV21 = 42;
private static final int lokiV22 = 43;
// Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
private static final int DATABASE_VERSION = lokiV21;
private static final int DATABASE_VERSION = lokiV22;
private static final String DATABASE_NAME = "signal.db";
private final Context context;
@ -121,6 +123,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
db.execSQL(LokiUserDatabase.getCreateDisplayNameTableCommand());
db.execSQL(LokiUserDatabase.getCreateServerDisplayNameTableCommand());
db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand());
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
executeStatements(db, SmsDatabase.CREATE_INDEXS);
executeStatements(db, MmsDatabase.CREATE_INDEXS);
@ -255,6 +258,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
"ResetThreadSessionJob");
}
if (oldVersion < lokiV22) {
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();

View File

@ -26,8 +26,8 @@ import org.session.libsession.messaging.sending_receiving.sharecontacts.Contact;
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.session.libsession.database.documents.IdentityKeyMismatch;
import org.session.libsession.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.session.libsession.messaging.threads.recipients.Recipient;

View File

@ -26,8 +26,8 @@ import android.text.style.StyleSpan;
import network.loki.messenger.R;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.session.libsession.database.documents.IdentityKeyMismatch;
import org.session.libsession.database.documents.NetworkFailure;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.session.libsession.utilities.ExpirationUtil;
@ -158,18 +158,10 @@ public abstract class MessageRecord extends DisplayRecord {
return SmsDatabase.Types.isIdentityDefault(type);
}
public boolean isIdentityMismatchFailure() {
return mismatches != null && !mismatches.isEmpty();
}
public boolean isBundleKeyExchange() {
return SmsDatabase.Types.isBundleKeyExchange(type);
}
public boolean isContentBundleKeyExchange() {
return SmsDatabase.Types.isContentBundleKeyExchange(type);
}
public boolean isIdentityUpdate() {
return SmsDatabase.Types.isIdentityUpdate(type);
}
@ -195,10 +187,6 @@ public abstract class MessageRecord extends DisplayRecord {
return individualRecipient;
}
public int getRecipientDeviceId() {
return recipientDeviceId;
}
public long getType() {
return type;
}
@ -211,10 +199,6 @@ public abstract class MessageRecord extends DisplayRecord {
return networkFailures;
}
public boolean hasNetworkFailures() {
return networkFailures != null && !networkFailures.isEmpty();
}
protected SpannableString emphasisAdded(String sequence) {
SpannableString spannable = new SpannableString(sequence);
spannable.setSpan(new RelativeSizeSpan(0.9f), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
@ -234,10 +218,6 @@ public abstract class MessageRecord extends DisplayRecord {
return (int)getId();
}
public int getSubscriptionId() {
return subscriptionId;
}
public long getExpiresIn() {
return expiresIn;
}

View File

@ -8,8 +8,8 @@ import org.session.libsession.messaging.sending_receiving.sharecontacts.Contact;
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.session.libsession.database.documents.IdentityKeyMismatch;
import org.session.libsession.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;

View File

@ -23,8 +23,8 @@ import android.text.SpannableString;
import network.loki.messenger.R;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.session.libsession.database.documents.IdentityKeyMismatch;
import org.session.libsession.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.session.libsession.messaging.threads.recipients.Recipient;

View File

@ -4,6 +4,7 @@ package org.thoughtcrime.securesms.database.model;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel;
import org.session.libsession.messaging.threads.Address;
import org.thoughtcrime.securesms.mms.SlideDeck;
@ -42,4 +43,8 @@ public class Quote {
public @NonNull SlideDeck getAttachment() {
return attachment;
}
public QuoteModel getQuoteModel() {
return new QuoteModel(id, author, text, missing, attachment.asAttachments());
}
}

View File

@ -24,7 +24,7 @@ import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.session.libsession.database.documents.IdentityKeyMismatch;
import org.session.libsession.messaging.threads.recipients.Recipient;
import java.util.LinkedList;

View File

@ -2,36 +2,23 @@ package org.thoughtcrime.securesms.groups;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.protobuf.ByteString;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.sending_receiving.attachments.UriAttachment;
import org.session.libsession.messaging.threads.Address;
import org.session.libsession.messaging.threads.DistributionTypes;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.session.libsession.utilities.GroupUtil;
import org.session.libsession.utilities.MediaTypes;
import org.session.libsession.utilities.TextSecurePreferences;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.session.libsignal.service.internal.push.SignalServiceProtos.GroupContext;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@ -72,7 +59,7 @@ public class GroupManager {
groupDatabase.updateProfilePicture(groupId, avatarBytes);
long threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(
groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
groupRecipient, DistributionTypes.CONVERSATION);
return new GroupActionResult(groupRecipient, threadID);
}
@ -95,82 +82,6 @@ public class GroupManager {
return groupDatabase.delete(groupId);
}
public static GroupActionResult updateGroup(@NonNull Context context,
@NonNull String groupId,
@NonNull Set<Recipient> members,
@Nullable Bitmap avatar,
@Nullable String name,
@NonNull Set<Recipient> admins)
{
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
final Set<Address> memberAddresses = getMemberAddresses(members);
final Set<Address> adminAddresses = getMemberAddresses(admins);
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
groupDatabase.updateAdmins(groupId, new LinkedList<>(adminAddresses));
groupDatabase.updateTitle(groupId, name);
groupDatabase.updateProfilePicture(groupId, avatarBytes);
if (!GroupUtil.isMmsGroup(groupId)) {
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes, adminAddresses);
} else {
Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), true);
long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient);
return new GroupActionResult(groupRecipient, threadId);
}
}
private static GroupActionResult sendGroupUpdate(@NonNull Context context,
@NonNull String groupId,
@NonNull Set<Address> members,
@Nullable String groupName,
@Nullable byte[] avatar,
@NonNull Set<Address> admins)
{
Attachment avatarAttachment = null;
Address groupAddress = Address.fromSerialized(groupId);
Recipient groupRecipient = Recipient.from(context, groupAddress, false);
List<String> numbers = new LinkedList<>();
for (Address member : members) {
numbers.add(member.serialize());
}
List<String> adminNumbers = new LinkedList<>();
for (Address admin : admins) {
adminNumbers.add(admin.serialize());
}
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
.setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupId)))
.setType(GroupContext.Type.UPDATE)
.addAllMembers(numbers)
.addAllAdmins(adminNumbers);
if (groupName != null) groupContextBuilder.setName(groupName);
GroupContext groupContext = groupContextBuilder.build();
if (avatar != null) {
Uri avatarUri = BlobProvider.getInstance().forData(avatar).createForSingleUseInMemory();
avatarAttachment = new UriAttachment(avatarUri, MediaTypes.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null, false, false, null);
}
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, 0, null, Collections.emptyList(), Collections.emptyList());
long threadId = MessageSender.send(context, outgoingMessage, -1, false, null);
return new GroupActionResult(groupRecipient, threadId);
}
private static Set<Address> getMemberAddresses(Collection<Recipient> recipients) {
final Set<Address> results = new HashSet<>();
for (Recipient recipient : recipients) {
results.add(recipient.getAddress());
}
return results;
}
public static class GroupActionResult {
private Recipient groupRecipient;
private long threadId;

View File

@ -7,6 +7,7 @@ import androidx.annotation.VisibleForTesting;
import org.greenrobot.eventbus.EventBus;
import org.session.libsession.messaging.jobs.Data;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.session.libsignal.libsignal.InvalidMessageException;
import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.crypto.AttachmentCipherInputStream;
@ -96,11 +97,11 @@ public class AttachmentDownloadJob extends BaseJob implements InjectableType {
final AttachmentDatabase database = DatabaseFactory.getAttachmentDatabase(context);
final AttachmentId attachmentId = new AttachmentId(partRowId, partUniqueId);
final DatabaseAttachment attachment = database.getAttachment(attachmentId);
final boolean pending = attachment != null && attachment.getTransferState() != AttachmentDatabase.TRANSFER_PROGRESS_DONE;
final boolean pending = attachment != null && attachment.getTransferState() != AttachmentTransferProgress.TRANSFER_PROGRESS_DONE;
if (pending && (manual || AttachmentUtil.isAutoDownloadPermitted(context, attachment))) {
Log.i(TAG, "onAdded() Marking attachment progress as 'started'");
database.setTransferState(messageId, attachmentId, AttachmentDatabase.TRANSFER_PROGRESS_STARTED);
database.setTransferState(messageId, attachmentId, AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED);
}
}
@ -129,12 +130,12 @@ public class AttachmentDownloadJob extends BaseJob implements InjectableType {
if (!manual && !AttachmentUtil.isAutoDownloadPermitted(context, attachment)) {
Log.w(TAG, "Attachment can't be auto downloaded...");
database.setTransferState(messageId, attachmentId, AttachmentDatabase.TRANSFER_PROGRESS_PENDING);
database.setTransferState(messageId, attachmentId, AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING);
return;
}
Log.i(TAG, "Downloading push part " + attachmentId);
database.setTransferState(messageId, attachmentId, AttachmentDatabase.TRANSFER_PROGRESS_STARTED);
database.setTransferState(messageId, attachmentId, AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED);
retrieveAttachment(messageId, attachmentId, attachment);
}

View File

@ -15,6 +15,7 @@ import com.annimon.stream.Collectors;
import com.annimon.stream.Stream;
import org.session.libsession.messaging.jobs.Data;
import org.session.libsession.messaging.threads.DistributionTypes;
import org.session.libsignal.metadata.InvalidMetadataMessageException;
import org.session.libsignal.metadata.ProtocolInvalidMessageException;
import org.session.libsignal.service.api.crypto.SignalServiceCipher;
@ -34,7 +35,6 @@ import org.session.libsession.utilities.TextSecurePreferences;
import org.thoughtcrime.securesms.contactshare.ContactModelMapper;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
@ -63,9 +63,9 @@ import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.session.libsession.messaging.messages.signal.IncomingEncryptedMessage;
import org.session.libsession.messaging.messages.signal.IncomingTextMessage;
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.SignalServiceMessageSender;
import org.session.libsignal.service.api.messages.SignalServiceContent;
@ -346,7 +346,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
attachments,
message.getTimestamp(), -1,
message.getExpiresInSeconds() * 1000,
ThreadDatabase.DistributionTypes.DEFAULT, quote.orNull(),
DistributionTypes.DEFAULT, quote.orNull(),
sharedContacts.or(Collections.emptyList()),
linkPreviews.or(Collections.emptyList()),
Collections.emptyList(), Collections.emptyList());

View File

@ -21,8 +21,8 @@ import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.session.libsession.database.documents.IdentityKeyMismatch;
import org.session.libsession.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.JobManager;

View File

@ -9,6 +9,7 @@ import androidx.annotation.Nullable;
import com.google.android.gms.common.util.IOUtils;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.session.libsession.utilities.MediaTypes;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
@ -192,7 +193,7 @@ public class LinkPreviewRepository implements InjectableType {
return Optional.of(new UriAttachment(uri,
uri,
contentType,
AttachmentDatabase.TRANSFER_PROGRESS_STARTED,
AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED,
bytes.length,
bitmap.getWidth(),
bitmap.getHeight(),

View File

@ -43,13 +43,13 @@ public class LinkPreviewViewModel extends ViewModel {
return linkPreviewState.getValue() != null && linkPreviewState.getValue().getLinkPreview().isPresent();
}
public @NonNull List<LinkPreview> getActiveLinkPreviews() {
public Optional<LinkPreview> getActiveLinkPreview() {
final LinkPreviewState state = linkPreviewState.getValue();
if (state == null || !state.getLinkPreview().isPresent()) {
return Collections.emptyList();
return Optional.absent();
} else {
return Collections.singletonList(state.getLinkPreview().get());
return state.getLinkPreview();
}
}

View File

@ -16,15 +16,14 @@ import nl.komponents.kovenant.ui.successUi
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.ConversationActivity
import org.session.libsession.messaging.threads.Address
import org.session.libsession.messaging.threads.DistributionTypes
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.loki.utilities.fadeIn
import org.thoughtcrime.securesms.loki.utilities.fadeOut
import org.thoughtcrime.securesms.mms.GlideApp
import org.session.libsession.messaging.threads.recipients.Recipient
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
//TODO Refactor to avoid using kotlinx.android.synthetic
class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), LoaderManager.LoaderCallbacks<List<String>> {
@ -128,7 +127,7 @@ class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), LoaderM
private fun openConversationActivity(context: Context, threadId: Long, recipient: Recipient) {
val intent = Intent(context, ConversationActivity::class.java)
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId)
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT)
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, DistributionTypes.DEFAULT)
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.address)
context.startActivity(intent)
}

View File

@ -18,6 +18,7 @@ import network.loki.messenger.R
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.ConversationActivity
import org.session.libsession.messaging.threads.Address
import org.session.libsession.messaging.threads.DistributionTypes
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment
@ -69,7 +70,7 @@ class CreatePrivateChatActivity : PassphraseRequiredActionBarActivity(), ScanQRC
intent.setDataAndType(getIntent().data, getIntent().type)
val existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient)
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread)
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT)
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, DistributionTypes.DEFAULT)
startActivity(intent)
finish()
}

View File

@ -301,8 +301,6 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
loaderContainer.fadeOut()
isLoading = false
}
} else {
GroupManager.updateGroup(this, groupID, members, null, name, admins)
}
}
}

View File

@ -17,6 +17,7 @@ import network.loki.messenger.R
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.ConversationActivity
import org.session.libsession.messaging.threads.Address
import org.session.libsession.messaging.threads.DistributionTypes
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment
@ -60,7 +61,7 @@ class QRCodeActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperF
intent.setDataAndType(getIntent().data, getIntent().type)
val existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient)
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread)
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT)
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, DistributionTypes.DEFAULT)
startActivity(intent)
finish()
}

View File

@ -12,7 +12,7 @@ import org.thoughtcrime.securesms.loki.utilities.*
class SessionJobDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
companion object {
private val sessionJobTable = "loki_thread_session_reset_database"
private val sessionJobTable = "session_job_database"
val jobID = "job_id"
val jobType = "job_type"
val failureCount = "failure_count"

View File

@ -26,8 +26,8 @@ import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager.ClosedGro
import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage
import org.thoughtcrime.securesms.sms.IncomingGroupMessage
import org.thoughtcrime.securesms.sms.IncomingTextMessage
import org.session.libsession.messaging.messages.signal.IncomingGroupMessage
import org.session.libsession.messaging.messages.signal.IncomingTextMessage
import org.session.libsignal.utilities.Hex
import org.session.libsession.messaging.threads.Address

View File

@ -20,6 +20,7 @@ import network.loki.messenger.R
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
import org.thoughtcrime.securesms.ApplicationContext
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
import org.thoughtcrime.securesms.audio.AudioSlidePlayer
@ -152,7 +153,7 @@ class MessageAudioView: FrameLayout, AudioSlidePlayer.Listener {
downloadProgress.progress = 0
}
}
(showControls && audio.transferState == AttachmentDatabase.TRANSFER_PROGRESS_STARTED) -> {
(showControls && audio.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED) -> {
controlToggle.displayQuick(downloadProgress)
seekBar.isEnabled = false
downloadProgress.isIndeterminate = true

View File

@ -25,6 +25,7 @@ import androidx.annotation.Nullable;
import network.loki.messenger.R;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.session.libsession.messaging.sending_receiving.attachments.UriAttachment;
import org.session.libsession.utilities.MediaTypes;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
@ -38,7 +39,7 @@ public class AudioSlide extends Slide {
}
public AudioSlide(Context context, Uri uri, long dataSize, String contentType, boolean voiceNote) {
super(context, new UriAttachment(uri, null, contentType, AttachmentDatabase.TRANSFER_PROGRESS_STARTED, dataSize, 0, 0, null, null, voiceNote, false, null));
super(context, new UriAttachment(uri, null, contentType, AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED, dataSize, 0, 0, null, null, voiceNote, false, null));
}
public AudioSlide(Context context, Attachment attachment) {

View File

@ -1,7 +1,7 @@
package org.thoughtcrime.securesms.mms;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.session.libsession.messaging.threads.DistributionTypes;
import org.session.libsession.messaging.threads.recipients.Recipient;
import java.util.Collections;
@ -11,7 +11,7 @@ public class OutgoingExpirationUpdateMessage extends OutgoingSecureMediaMessage
public OutgoingExpirationUpdateMessage(Recipient recipient, long sentTimeMillis, long expiresIn) {
super(recipient, "", new LinkedList<Attachment>(), sentTimeMillis,
ThreadDatabase.DistributionTypes.CONVERSATION, expiresIn, null, Collections.emptyList(),
DistributionTypes.CONVERSATION, expiresIn, null, Collections.emptyList(),
Collections.emptyList());
}

View File

@ -3,7 +3,7 @@ package org.thoughtcrime.securesms.mms;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.session.libsession.messaging.threads.DistributionTypes;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.sending_receiving.sharecontacts.Contact;
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
@ -32,7 +32,7 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
throws IOException
{
super(recipient, encodedGroupContext, avatar, sentTimeMillis,
ThreadDatabase.DistributionTypes.CONVERSATION, expiresIn, quote, contacts, previews);
DistributionTypes.CONVERSATION, expiresIn, quote, contacts, previews);
this.group = GroupContext.parseFrom(Base64.decode(encodedGroupContext));
}
@ -48,7 +48,7 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
super(recipient, Base64.encodeBytes(group.toByteArray()),
new LinkedList<Attachment>() {{if (avatar != null) add(avatar);}},
System.currentTimeMillis(),
ThreadDatabase.DistributionTypes.CONVERSATION, expireIn, quote, contacts, previews);
DistributionTypes.CONVERSATION, expireIn, quote, contacts, previews);
this.group = group;
}
@ -65,7 +65,7 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
super(recipient, Base64.encodeBytes(group.toByteArray()),
new LinkedList<Attachment>() {{if (avatar != null) add(avatar);}},
sentTime,
ThreadDatabase.DistributionTypes.CONVERSATION, expireIn, quote, contacts, previews);
DistributionTypes.CONVERSATION, expireIn, quote, contacts, previews);
this.group = group;
}

View File

@ -5,9 +5,9 @@ import androidx.annotation.Nullable;
import android.text.TextUtils;
import org.session.libsession.messaging.messages.visible.VisibleMessage;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.session.libsession.messaging.threads.DistributionTypes;
import org.session.libsession.database.documents.IdentityKeyMismatch;
import org.session.libsession.database.documents.NetworkFailure;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.sending_receiving.sharecontacts.Contact;
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
@ -17,6 +17,7 @@ import org.session.libsession.messaging.threads.recipients.Recipient;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
public class OutgoingMediaMessage {
@ -66,7 +67,7 @@ public class OutgoingMediaMessage {
@NonNull List<LinkPreview> linkPreviews)
{
this(recipient,
buildMessage(slideDeck, message),
buildMessage(message),
slideDeck.asAttachments(),
sentTimeMillis, subscriptionId,
expiresIn, distributionType, outgoingQuote,
@ -93,11 +94,15 @@ public class OutgoingMediaMessage {
Recipient recipient,
List<Attachment> attachments,
@Nullable QuoteModel outgoingQuote,
@NonNull List<LinkPreview> linkPreviews)
@Nullable LinkPreview linkPreview)
{
List<LinkPreview> previews = Collections.emptyList();
if (linkPreview != null) {
previews = Collections.singletonList(linkPreview);
}
return new OutgoingMediaMessage(recipient, message.getText(), attachments, message.getSentTimestamp(), -1,
recipient.getExpireMessages() * 1000, ThreadDatabase.DistributionTypes.DEFAULT, outgoingQuote, Collections.emptyList(),
linkPreviews, Collections.emptyList(), Collections.emptyList());
recipient.getExpireMessages() * 1000, DistributionTypes.DEFAULT, outgoingQuote, Collections.emptyList(),
previews, Collections.emptyList(), Collections.emptyList());
}
public Recipient getRecipient() {
@ -160,7 +165,7 @@ public class OutgoingMediaMessage {
return identityKeyMismatches;
}
private static String buildMessage(SlideDeck slideDeck, String message) {
private static String buildMessage(String message) {
if (!TextUtils.isEmpty(message)) {
return message;
}

View File

@ -23,7 +23,7 @@ import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.session.libsignal.libsignal.util.guava.Optional;
@ -135,8 +135,8 @@ public abstract class Slide {
}
public boolean isPendingDownload() {
return getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_FAILED ||
getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_PENDING;
return getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED ||
getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING;
}
public int getTransferState() {
@ -172,7 +172,7 @@ public abstract class Slide {
return new UriAttachment(uri,
hasThumbnail ? uri : null,
resolvedType,
AttachmentDatabase.TRANSFER_PROGRESS_STARTED,
AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED,
size,
width,
height,

View File

@ -25,18 +25,19 @@ import android.os.AsyncTask;
import android.os.Bundle;
import androidx.core.app.RemoteInput;
import org.session.libsession.messaging.messages.visible.VisibleMessage;
import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.thoughtcrime.securesms.ApplicationContext;
import org.session.libsession.messaging.threads.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
import org.session.libsignal.utilities.logging.Log;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
@ -72,17 +73,29 @@ public class AndroidAutoReplyReceiver extends BroadcastReceiver {
long replyThreadId;
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
long expiresIn = recipient.getExpireMessages() * 1000L;
if (threadId == -1) {
replyThreadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
} else {
replyThreadId = threadId;
}
VisibleMessage message = new VisibleMessage();
message.setText(responseText.toString());
message.setSentTimestamp(System.currentTimeMillis());
MessageSender.send(message, recipient.getAddress());
if (recipient.isGroupRecipient()) {
Log.w("AndroidAutoReplyReceiver", "GroupRecipient, Sending media message");
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipient, responseText.toString(), new LinkedList<>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
replyThreadId = MessageSender.send(context, reply, threadId, false, null);
OutgoingMediaMessage reply = OutgoingMediaMessage.from(message, recipient, Collections.emptyList(), null, null);
try {
DatabaseFactory.getMmsDatabase(context).insertMessageOutbox(reply, replyThreadId, false, null);
} catch (MmsException e) {
Log.w(TAG, e);
}
} else {
Log.w("AndroidAutoReplyReceiver", "Sending regular message ");
OutgoingTextMessage reply = new OutgoingTextMessage(recipient, responseText.toString(), expiresIn, subscriptionId);
replyThreadId = MessageSender.send(context, reply, threadId, false, null);
OutgoingTextMessage reply = OutgoingTextMessage.from(message, recipient);
DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(replyThreadId, reply, false, System.currentTimeMillis(), null);
}
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(replyThreadId, true);

View File

@ -25,17 +25,18 @@ import android.os.AsyncTask;
import android.os.Bundle;
import androidx.core.app.RemoteInput;
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
import org.session.libsession.messaging.messages.visible.VisibleMessage;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.session.libsession.messaging.threads.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
@ -68,21 +69,24 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
long threadId;
Recipient recipient = Recipient.from(context, address, false);
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
long expiresIn = recipient.getExpireMessages() * 1000L;
long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
VisibleMessage message = new VisibleMessage();
message.setText(responseText.toString());
switch (replyMethod) {
case GroupMessage: {
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipient, responseText.toString(), new LinkedList<>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
threadId = MessageSender.send(context, reply, -1, false, null);
OutgoingMediaMessage reply = OutgoingMediaMessage.from(message, recipient, Collections.emptyList(), null, null);
try {
DatabaseFactory.getMmsDatabase(context).insertMessageOutbox(reply, threadId, false, null);
} catch (MmsException e) {
Log.w(TAG, e);
}
break;
}
case SecureMessage: {
OutgoingEncryptedMessage reply = new OutgoingEncryptedMessage(recipient, responseText.toString(), expiresIn);
threadId = MessageSender.send(context, reply, -1, false, null);
OutgoingTextMessage reply = OutgoingTextMessage.from(message, recipient);
DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(threadId, reply, false, System.currentTimeMillis(), null);
break;
}
default:

View File

@ -103,17 +103,18 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
}
@Override
public void startAnyExpiration(long messageID) {
MessageRecord messageRecord = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(messageID);
public void startAnyExpiration(long timestamp, @NotNull String author) {
MessageRecord messageRecord = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(timestamp, author);
if (messageRecord != null) {
boolean mms = messageRecord.isMms();
Recipient recipient = messageRecord.getRecipient();
if (recipient.getExpireMessages() <= 0) return;
if (mms) {
mmsDatabase.markExpireStarted(messageID);
mmsDatabase.markExpireStarted(messageRecord.getId());
} else {
smsDatabase.markExpireStarted(messageID);
smsDatabase.markExpireStarted(messageRecord.getId());
}
scheduleDeletion(messageID, mms, recipient.getExpireMessages());
scheduleDeletion(messageRecord.getId(), mms, recipient.getExpireMessages());
}
}

View File

@ -7,11 +7,13 @@ import android.text.TextUtils;
import android.widget.Toast;
import network.loki.messenger.R;
import org.session.libsession.messaging.messages.visible.VisibleMessage;
import org.session.libsession.messaging.threads.Address;
import org.session.libsignal.utilities.logging.Log;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.Rfc5724Uri;
import java.net.URISyntaxException;
@ -47,13 +49,11 @@ public class QuickResponseService extends IntentService {
number = URLDecoder.decode(number);
}
Address address = Address.fromExternal(this, number);
Recipient recipient = Recipient.from(this, address, false);
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
long expiresIn = recipient.getExpireMessages() * 1000L;
if (!TextUtils.isEmpty(content)) {
MessageSender.send(this, new OutgoingTextMessage(recipient, content, expiresIn, subscriptionId), -1, false, null);
VisibleMessage message = new VisibleMessage();
message.setText(content);
message.setSentTimestamp(System.currentTimeMillis());
MessageSender.send(message, Address.fromExternal(this, number));
}
} catch (URISyntaxException e) {
Toast.makeText(this, R.string.QuickResponseService_problem_sending_message, Toast.LENGTH_LONG).show();

View File

@ -1,213 +0,0 @@
/*
* Copyright (C) 2011 Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.sms;
import android.content.Context;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.ApplicationContext;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.threads.Address;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobs.PushGroupSendJob;
import org.thoughtcrime.securesms.jobs.PushMediaSendJob;
import org.thoughtcrime.securesms.jobs.PushTextSendJob;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.session.libsession.messaging.threads.recipients.Recipient;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.session.libsession.utilities.TextSecurePreferences;
public class MessageSender {
private static final String TAG = MessageSender.class.getSimpleName();
public static long send(final Context context,
final OutgoingTextMessage message,
final long threadId,
final boolean forceSms,
final SmsDatabase.InsertListener insertListener)
{
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
Recipient recipient = message.getRecipient();
long allocatedThreadId;
if (threadId == -1) {
allocatedThreadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
} else {
allocatedThreadId = threadId;
}
long messageId = database.insertMessageOutbox(allocatedThreadId, message, forceSms, System.currentTimeMillis(), insertListener);
sendTextMessage(context, recipient, forceSms, messageId);
return allocatedThreadId;
}
public static long send(final Context context,
final OutgoingMediaMessage message,
final long threadId,
final boolean forceSms,
final SmsDatabase.InsertListener insertListener)
{
try {
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
long allocatedThreadId;
if (threadId == -1) {
allocatedThreadId = threadDatabase.getOrCreateThreadIdFor(message.getRecipient(), message.getDistributionType());
} else {
allocatedThreadId = threadId;
}
Recipient recipient = message.getRecipient();
long messageId = database.insertMessageOutbox(message, allocatedThreadId, forceSms, insertListener);
sendMediaMessage(context, recipient, forceSms, messageId, message.getExpiresIn());
return allocatedThreadId;
} catch (MmsException e) {
Log.w(TAG, e);
return threadId;
}
}
public static void resend(Context context, MessageRecord messageRecord) {
long messageId = messageRecord.getId();
boolean forceSms = messageRecord.isForcedSms();
long expiresIn = messageRecord.getExpiresIn();
Recipient recipient = messageRecord.getRecipient();
if (messageRecord.isMms()) {
sendMediaMessage(context, recipient, forceSms, messageId, expiresIn);
} else {
sendTextMessage(context, recipient, forceSms, messageId);
}
}
private static void sendMediaMessage(Context context, Recipient recipient, boolean forceSms, long messageId, long expiresIn)
{
if (isLocalSelfSend(context, recipient, forceSms)) {
sendLocalMediaSelf(context, messageId);
} else if (isGroupPushSend(recipient)) {
sendGroupPush(context, recipient, messageId, null);
} else {
sendMediaPush(context, recipient, messageId);
}
}
private static void sendTextMessage(Context context, Recipient recipient,
boolean forceSms, long messageId)
{
if (isLocalSelfSend(context, recipient, forceSms)) {
sendLocalTextSelf(context, messageId);
} else {
sendTextPush(context, recipient, messageId);
}
}
private static void sendTextPush(Context context, Recipient recipient, long messageId) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
jobManager.add(new PushTextSendJob(messageId, recipient.getAddress()));
}
private static void sendMediaPush(Context context, Recipient recipient, long messageId) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
PushMediaSendJob.enqueue(context, jobManager, messageId, recipient.getAddress());
}
private static void sendGroupPush(Context context, Recipient recipient, long messageId, Address filterAddress) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
PushGroupSendJob.enqueue(context, jobManager, messageId, recipient.getAddress(), filterAddress);
}
private static boolean isGroupPushSend(Recipient recipient) {
return recipient.getAddress().isGroup() &&
!recipient.getAddress().isMmsGroup();
}
private static boolean isLocalSelfSend(@NonNull Context context, @NonNull Recipient recipient, boolean forceSms) {
return recipient.isLocalNumber() &&
!forceSms &&
TextSecurePreferences.isPushRegistered(context);
}
private static void sendLocalMediaSelf(Context context, long messageId) {
try {
ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
OutgoingMediaMessage message = mmsDatabase.getOutgoingMessage(messageId);
SyncMessageId syncId = new SyncMessageId(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)), message.getSentTimeMillis());
for (Attachment attachment : message.getAttachments()) {
attachmentDatabase.markAttachmentUploaded(messageId, attachment);
}
mmsDatabase.markAsSent(messageId, true);
mmsDatabase.markUnidentified(messageId, true);
mmsSmsDatabase.incrementDeliveryReceiptCount(syncId, System.currentTimeMillis());
mmsSmsDatabase.incrementReadReceiptCount(syncId, System.currentTimeMillis());
if (message.getExpiresIn() > 0 && !message.isExpirationUpdate()) {
mmsDatabase.markExpireStarted(messageId);
expirationManager.scheduleDeletion(messageId, true, message.getExpiresIn());
}
} catch (NoSuchMessageException | MmsException e) {
Log.w("Failed to update self-sent message.", e);
}
}
private static void sendLocalTextSelf(Context context, long messageId) {
try {
ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
SmsMessageRecord message = smsDatabase.getMessage(messageId);
SyncMessageId syncId = new SyncMessageId(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)), message.getDateSent());
smsDatabase.markAsSent(messageId, true);
smsDatabase.markUnidentified(messageId, true);
mmsSmsDatabase.incrementDeliveryReceiptCount(syncId, System.currentTimeMillis());
mmsSmsDatabase.incrementReadReceiptCount(syncId, System.currentTimeMillis());
if (message.getExpiresIn() > 0) {
smsDatabase.markExpireStarted(messageId);
expirationManager.scheduleDeletion(message.getId(), message.isMms(), message.getExpiresIn());
}
} catch (NoSuchMessageException e) {
Log.w("Failed to update self-sent message.", e);
}
}
}

View File

@ -1,15 +0,0 @@
package org.thoughtcrime.securesms.sms;
import org.session.libsession.messaging.threads.recipients.Recipient;
public class OutgoingEncryptedMessage extends OutgoingTextMessage {
public OutgoingEncryptedMessage(Recipient recipient, String body, long expiresIn) {
super(recipient, body, expiresIn, -1);
}
@Override
public boolean isSecureMessage() {
return true;
}
}

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.database.documents;
package org.session.libsession.database.documents;
import java.util.List;

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.database.documents;
package org.session.libsession.database.documents;
import org.session.libsignal.utilities.logging.Log;

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.database.documents;
package org.session.libsession.database.documents;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.database.documents;
package org.session.libsession.database.documents;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.database.documents;
package org.session.libsession.database.documents;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

View File

@ -95,8 +95,8 @@ interface StorageProtocol {
fun getMessageIdInDatabase(timestamp: Long, author: String): Long?
fun setOpenGroupServerMessageID(messageID: Long, serverID: Long)
fun markAsSent(messageID: Long)
fun markUnidentified(messageID: Long)
fun markAsSent(timestamp: Long, author: String)
fun markUnidentified(timestamp: Long, author: String)
fun setErrorMessage(messageID: Long, error: Exception)
// Closed Groups

View File

@ -28,7 +28,7 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
// Settings
override val maxFailureCount: Int = 20
companion object {
val TAG = AttachmentUploadJob::class.qualifiedName
val TAG = AttachmentUploadJob::class.simpleName
val KEY: String = "AttachmentUploadJob"
val maxFailureCount: Int = 20

View File

@ -15,8 +15,8 @@ class MessageReceiveJob(val data: ByteArray, val isBackgroundPoll: Boolean, val
// Settings
override val maxFailureCount: Int = 10
companion object {
val TAG = MessageReceiveJob::class.qualifiedName
val KEY: String = "AttachmentUploadJob"
val TAG = MessageReceiveJob::class.simpleName
val KEY: String = "MessageReceiveJob"
//keys used for database storage purpose
private val KEY_DATA = "data"

View File

@ -19,7 +19,7 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
// Settings
override val maxFailureCount: Int = 10
companion object {
val TAG = MessageSendJob::class.qualifiedName
val TAG = MessageSendJob::class.simpleName
val KEY: String = "MessageSendJob"
//keys used for database storage purpose

View File

@ -18,8 +18,12 @@ abstract class Message {
// validation
open fun isValid(): Boolean {
sentTimestamp = if (sentTimestamp!! > 0) sentTimestamp else return false
receivedTimestamp = if (receivedTimestamp!! > 0) receivedTimestamp else return false
sentTimestamp?.let {
if (it <= 0) return false
}
receivedTimestamp?.let {
if (it <= 0) return false
}
return sender != null && recipient != null
}

View File

@ -5,6 +5,7 @@ import org.session.libsignal.service.internal.push.SignalServiceProtos
class ExpirationTimerUpdate() : ControlMessage() {
var syncTarget: String? = null
var duration: Int? = 0
companion object {
@ -12,7 +13,7 @@ class ExpirationTimerUpdate() : ControlMessage() {
fun fromProto(proto: SignalServiceProtos.Content): ExpirationTimerUpdate? {
val dataMessageProto = proto.dataMessage ?: return null
val isExpirationTimerUpdate = (dataMessageProto.flags and SignalServiceProtos.DataMessage.Flags.EXPIRATION_TIMER_UPDATE_VALUE) != 0 //TODO validate that 'and' operator equivalent to Swift '&'
val isExpirationTimerUpdate = dataMessageProto.flags.and(SignalServiceProtos.DataMessage.Flags.EXPIRATION_TIMER_UPDATE_VALUE) != 0
if (!isExpirationTimerUpdate) return null
val duration = dataMessageProto.expireTimer
return ExpirationTimerUpdate(duration)

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.sms;
package org.session.libsession.messaging.messages.signal;
public class IncomingEncryptedMessage extends IncomingTextMessage {

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.sms;
package org.session.libsession.messaging.messages.signal;
import static org.session.libsignal.service.internal.push.SignalServiceProtos.GroupContext;

View File

@ -1,20 +1,14 @@
package org.thoughtcrime.securesms.sms;
package org.session.libsession.messaging.messages.signal;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.telephony.SmsMessage;
import org.session.libsession.messaging.messages.visible.VisibleMessage;
import org.session.libsession.messaging.threads.Address;
import org.session.libsession.utilities.GroupUtil;
import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.messages.SignalServiceGroup;
import org.session.libsignal.service.api.push.SignalServiceAddress;
import java.util.List;
public class IncomingTextMessage implements Parcelable {

View File

@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.sms;
package org.session.libsession.messaging.messages.signal;
import org.session.libsession.messaging.messages.visible.VisibleMessage;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.session.libsession.messaging.threads.recipients.Recipient;
public class OutgoingTextMessage {
@ -39,14 +38,6 @@ public class OutgoingTextMessage {
}
public boolean isSecureMessage() {
return false;
}
public static OutgoingTextMessage from(SmsMessageRecord record) {
if (record.isSecure()) {
return new OutgoingEncryptedMessage(record.getRecipient(), record.getBody(), record.getExpiresIn());
} else {
return new OutgoingTextMessage(record.getRecipient(), record.getBody(), record.getExpiresIn(), record.getSubscriptionId());
}
return true;
}
}

View File

@ -32,7 +32,7 @@ class Attachment {
result.contentType = proto.contentType ?: inferContentType()
result.key = proto.key.toByteArray()
result.digest = proto.digest.toByteArray()
val kind: Kind = if (proto.hasFlags() && (proto.flags and SignalServiceProtos.AttachmentPointer.Flags.VOICE_MESSAGE_VALUE) > 0) { //TODO validate that 'and' operator = swift '&'
val kind: Kind = if (proto.hasFlags() && proto.flags.and(SignalServiceProtos.AttachmentPointer.Flags.VOICE_MESSAGE_VALUE) > 0) {
Kind.VOICE_MESSAGE
} else {
Kind.GENERIC
@ -42,7 +42,7 @@ class Attachment {
val size: Size = if (proto.hasWidth() && proto.width > 0 && proto.hasHeight() && proto.height > 0) {
Size(proto.width, proto.height)
} else {
Size(0,0) //TODO check that it's equivalent to swift: CGSize.zero
Size(0,0)
}
result.size = size
result.sizeInBytes = if (proto.size > 0) proto.size else null

View File

@ -1,6 +1,7 @@
package org.session.libsession.messaging.messages.visible
import org.session.libsession.messaging.MessagingConfiguration
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview as SignalLinkPreiview
import org.session.libsignal.utilities.logging.Log
import org.session.libsignal.service.internal.push.SignalServiceProtos
@ -18,6 +19,14 @@ class LinkPreview() {
val url = proto.url
return LinkPreview(title, url, null)
}
fun from(signalLinkPreview: SignalLinkPreiview?): LinkPreview? {
return if (signalLinkPreview == null) {
null
} else {
LinkPreview(signalLinkPreview.title, signalLinkPreview.url, signalLinkPreview.attachmentId?.rowId)
}
}
}
//constructor

View File

@ -2,6 +2,8 @@ package org.session.libsession.messaging.messages.visible
import com.goterl.lazycode.lazysodium.BuildConfig
import org.session.libsession.messaging.MessagingConfiguration
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel as SignalQuote
import org.session.libsignal.utilities.logging.Log
import org.session.libsignal.service.internal.push.SignalServiceProtos
@ -21,6 +23,15 @@ class Quote() {
val text = proto.text
return Quote(timestamp, publicKey, text, null)
}
fun from(signalQuote: SignalQuote?): Quote? {
return if (signalQuote == null) {
null
} else {
val attachmentID = (signalQuote.attachments?.firstOrNull() as? DatabaseAttachment)?.attachmentId?.rowId
Quote(signalQuote.id, signalQuote.author.serialize(), signalQuote.text, attachmentID)
}
}
}
//constructor

View File

@ -4,6 +4,8 @@ import com.goterl.lazycode.lazysodium.BuildConfig
import org.session.libsession.messaging.MessagingConfiguration
import org.session.libsession.messaging.messages.Message
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
import org.session.libsession.messaging.sending_receiving.attachments.Attachment as SignalAttachment
import org.session.libsignal.utilities.logging.Log
import org.session.libsignal.service.internal.push.SignalServiceProtos
@ -46,6 +48,14 @@ class VisibleMessage : Message() {
}
}
fun addSignalAttachments(signalAttachments: List<SignalAttachment>) {
val attachmentIDs = signalAttachments.map {
val databaseAttachment = it as DatabaseAttachment
databaseAttachment.attachmentId.rowId
}
this.attachmentIDs = attachmentIDs as ArrayList<Long>
}
fun isMediaMessage(): Boolean {
return attachmentIDs.isNotEmpty() || quote != null || linkPreview != null || contact != null
}

View File

@ -5,27 +5,31 @@ import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.deferred
import org.session.libsession.messaging.MessagingConfiguration
import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.messaging.jobs.MessageSendJob
import org.session.libsession.messaging.jobs.NotifyPNServerJob
import org.session.libsession.messaging.messages.Destination
import org.session.libsession.messaging.messages.Message
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage
import org.session.libsession.messaging.messages.control.ConfigurationMessage
import org.session.libsession.messaging.messages.visible.Attachment
import org.session.libsession.messaging.messages.visible.Profile
import org.session.libsession.messaging.messages.visible.VisibleMessage
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
import org.session.libsession.messaging.messages.visible.*
import org.session.libsession.messaging.sending_receiving.attachments.Attachment as SignalAttachment
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview as SignalLinkPreview
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel as SignalQuote
import org.session.libsession.messaging.opengroups.OpenGroupAPI
import org.session.libsession.messaging.opengroups.OpenGroupMessage
import org.session.libsession.messaging.threads.Address
import org.session.libsession.messaging.utilities.MessageWrapper
import org.session.libsession.snode.RawResponsePromise
import org.session.libsession.snode.SnodeAPI
import org.session.libsession.snode.SnodeConfiguration
import org.session.libsession.snode.SnodeMessage
import org.session.libsession.utilities.SSKEnvironment
import org.session.libsignal.utilities.logging.Log
import org.session.libsignal.service.api.messages.SignalServiceAttachment
import org.session.libsignal.service.internal.push.SignalServiceProtos
import org.session.libsignal.utilities.Base64
import org.session.libsignal.service.loki.api.crypto.ProofOfWork
import org.session.libsignal.service.loki.utilities.hexEncodedPublicKey
import org.session.libsignal.utilities.Base64
import org.session.libsignal.utilities.logging.Log
object MessageSender {
@ -56,25 +60,22 @@ object MessageSender {
}
// Preparation
fun prep(signalAttachments: List<SignalServiceAttachment>, message: VisibleMessage) {
// TODO: Deal with SignalServiceAttachmentStream
fun prep(signalAttachments: List<SignalAttachment>, message: VisibleMessage) {
val attachments = mutableListOf<Attachment>()
for (signalAttachment in signalAttachments) {
val attachment = Attachment()
if (signalAttachment.isPointer) {
val signalAttachmentPointer = signalAttachment.asPointer()
attachment.fileName = signalAttachmentPointer.fileName.orNull()
attachment.caption = signalAttachmentPointer.caption.orNull()
attachment.contentType = signalAttachmentPointer.contentType
attachment.digest = signalAttachmentPointer.digest.orNull()
attachment.key = signalAttachmentPointer.key
attachment.sizeInBytes = signalAttachmentPointer.size.orNull()
attachment.url = signalAttachmentPointer.url
attachment.size = Size(signalAttachmentPointer.width, signalAttachmentPointer.height)
attachments.add(attachment)
}
attachment.fileName = signalAttachment.fileName
attachment.caption = signalAttachment.caption
attachment.contentType = signalAttachment.contentType
attachment.digest = signalAttachment.digest
attachment.key = Base64.decode(signalAttachment.key)
attachment.sizeInBytes = signalAttachment.size.toInt()
attachment.url = signalAttachment.url
attachment.size = Size(signalAttachment.width, signalAttachment.height)
attachments.add(attachment)
}
val attachmentIDs = MessagingConfiguration.shared.storage.persistAttachments(message.id ?: 0, attachments)
val attachmentIDs = MessagingConfiguration.shared.storage.persistAttachments(message.id
?: 0, attachments)
message.attachmentIDs.addAll(attachmentIDs)
}
@ -170,7 +171,7 @@ object MessageSender {
val wrappedMessage = MessageWrapper.wrap(kind, message.sentTimestamp!!, senderPublicKey, ciphertext)
// Calculate proof of work
if (destination is Destination.Contact && message is VisibleMessage && !isSelfSend) {
//TODO Notify user for proof of work calculating
SnodeConfiguration.shared.broadcaster.broadcast("calculatingPoW", message.sentTimestamp!!)
}
val recipient = message.recipient!!
val base64EncodedData = Base64.encodeBytes(wrappedMessage)
@ -178,6 +179,9 @@ object MessageSender {
val nonce = ProofOfWork.calculate(base64EncodedData, recipient, timestamp, message.ttl.toInt()) ?: throw Error.ProofOfWorkCalculationFailed
// Send the result
snodeMessage = SnodeMessage(recipient, base64EncodedData, message.ttl, timestamp, nonce)
if (destination is Destination.Contact && message is VisibleMessage && !isSelfSend) {
SnodeConfiguration.shared.broadcaster.broadcast("sendingMessage", message.sentTimestamp!!)
}
SnodeAPI.sendMessage(snodeMessage).success { promises: Set<RawResponsePromise> ->
var isSuccess = false
val promiseCount = promises.size
@ -187,7 +191,7 @@ object MessageSender {
if (isSuccess) { return@success } // Succeed as soon as the first promise succeeds
isSuccess = true
if (destination is Destination.Contact && message is VisibleMessage && !isSelfSend) {
//TODO Notify user for message sent
SnodeConfiguration.shared.broadcaster.broadcast("messageSent", message.sentTimestamp!!)
}
handleSuccessfulMessageSend(message, destination, isSyncMessage)
var shouldNotify = (message is VisibleMessage && !isSyncMessage)
@ -199,7 +203,6 @@ object MessageSender {
JobQueue.shared.add(notifyPNServerJob)
deferred.resolve(Unit)
}
}
promise.fail {
errorCount += 1
@ -277,17 +280,19 @@ object MessageSender {
storage.setOpenGroupServerMessageID(messageId, message.openGroupServerMessageID!!)
}
// Mark the message as sent
storage.markAsSent(messageId)
storage.markUnidentified(messageId)
storage.markAsSent(message.sentTimestamp!!, message.sender!!)
storage.markUnidentified(message.sentTimestamp!!, message.sender!!)
// Start the disappearing messages timer if needed
SSKEnvironment.shared.messageExpirationManager.startAnyExpiration(messageId)
SSKEnvironment.shared.messageExpirationManager.startAnyExpiration(message.sentTimestamp!!, message.sender!!)
// Sync the message if:
// • it's a visible message
// • the destination was a contact
// • we didn't sync it already
val userPublicKey = storage.getUserPublicKey()!!
if (destination is Destination.Contact && !isSyncMessage && message is VisibleMessage) {
sendToSnodeDestination(Destination.Contact(userPublicKey), message, true).get()
if (destination is Destination.Contact && !isSyncMessage) {
if (message is VisibleMessage) { message.syncTarget = destination.publicKey }
if (message is ExpirationTimerUpdate) { message.syncTarget = destination.publicKey }
sendToSnodeDestination(Destination.Contact(userPublicKey), message, true)
}
}
@ -295,5 +300,36 @@ object MessageSender {
val storage = MessagingConfiguration.shared.storage
val messageId = storage.getMessageIdInDatabase(message.sentTimestamp!!, message.sender!!) ?: return
storage.setErrorMessage(messageId, error)
SnodeConfiguration.shared.broadcaster.broadcast("messageFailed", message.sentTimestamp!!)
}
// Convenience
@JvmStatic
fun send(message: VisibleMessage, address: Address, attachments: List<SignalAttachment>, quote: SignalQuote?, linkPreview: SignalLinkPreview?) {
prep(attachments, message)
message.quote = Quote.from(quote)
message.linkPreview = LinkPreview.from(linkPreview)
send(message, address)
}
@JvmStatic
fun send(message: Message, address: Address) {
val threadID = MessagingConfiguration.shared.storage.getOrCreateThreadIdFor(address)
message.threadID = threadID
val destination = Destination.from(address)
val job = MessageSendJob(message, destination)
JobQueue.shared.add(job)
}
fun sendNonDurably(message: VisibleMessage, attachments: List<SignalAttachment>, address: Address): Promise<Unit, Exception> {
prep(attachments, message)
return sendNonDurably(message, address)
}
fun sendNonDurably(message: Message, address: Address): Promise<Unit, Exception> {
val threadID = MessagingConfiguration.shared.storage.getOrCreateThreadIdFor(address)
message.threadID = threadID
val destination = Destination.from(address)
return send(message, destination)
}
}

View File

@ -1,38 +0,0 @@
package org.session.libsession.messaging.sending_receiving
import nl.komponents.kovenant.Promise
import org.session.libsession.messaging.MessagingConfiguration
import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.messaging.jobs.MessageSendJob
import org.session.libsession.messaging.messages.Destination
import org.session.libsession.messaging.messages.Message
import org.session.libsession.messaging.messages.visible.VisibleMessage
import org.session.libsession.messaging.threads.Address
import org.session.libsignal.service.api.messages.SignalServiceAttachment
fun MessageSender.send(message: VisibleMessage, attachments: List<SignalServiceAttachment>, address: Address) {
prep(attachments, message)
send(message, address)
}
fun MessageSender.send(message: Message, address: Address) {
val threadID = MessagingConfiguration.shared.storage.getOrCreateThreadIdFor(address)
message.threadID = threadID
val destination = Destination.from(address)
val job = MessageSendJob(message, destination)
JobQueue.shared.add(job)
}
fun MessageSender.sendNonDurably(message: VisibleMessage, attachments: List<SignalServiceAttachment>, address: Address): Promise<Unit, Exception> {
prep(attachments, message)
return sendNonDurably(message, address)
}
fun MessageSender.sendNonDurably(message: Message, address: Address): Promise<Unit, Exception> {
val threadID = MessagingConfiguration.shared.storage.getOrCreateThreadIdFor(address)
message.threadID = threadID
val destination = Destination.from(address)
return MessageSender.send(message, destination)
}

View File

@ -12,10 +12,10 @@ import org.session.libsession.utilities.Util;
public class AttachmentId implements Parcelable {
@JsonProperty
private final long rowId;
private final long rowId; // This is the field id in the database
@JsonProperty
private final long uniqueId;
private final long uniqueId; // This is the timestamp when the attachment is written into the database
public AttachmentId(@JsonProperty("rowId") long rowId, @JsonProperty("uniqueId") long uniqueId) {
this.rowId = rowId;

View File

@ -7,10 +7,10 @@ import org.session.libsession.messaging.MessagingConfiguration
import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.messaging.jobs.MessageReceiveJob
import org.session.libsession.messaging.utilities.MessageWrapper
import org.session.libsession.snode.Snode
import org.session.libsession.snode.SnodeAPI
import org.session.libsession.snode.SnodeConfiguration
import org.session.libsignal.service.loki.api.Snode
import org.session.libsignal.utilities.logging.Log
import org.session.libsignal.utilities.Base64

View File

@ -0,0 +1,9 @@
package org.session.libsession.messaging.threads
object DistributionTypes {
const val DEFAULT = 2
const val BROADCAST = 1
const val CONVERSATION = 2
const val ARCHIVE = 3
const val INBOX_ZERO = 4
}

View File

@ -10,7 +10,7 @@ import org.session.libsession.utilities.AESGCM
import org.session.libsignal.utilities.logging.Log
import org.session.libsignal.utilities.Base64
import org.session.libsignal.utilities.*
import org.session.libsignal.service.loki.api.*
import org.session.libsignal.service.loki.api.Snode
import org.session.libsignal.service.loki.api.fileserver.FileServerAPI
import org.session.libsignal.service.loki.api.utilities.*
import org.session.libsession.utilities.AESGCM.EncryptionResult
@ -74,7 +74,7 @@ object OnionRequestAPI {
)
internal sealed class Destination {
class Snode(val snode: org.session.libsession.snode.Snode) : Destination()
class Snode(val snode: org.session.libsignal.service.loki.api.Snode) : Destination()
class Server(val host: String, val target: String, val x25519PublicKey: String) : Destination()
}

View File

@ -1,6 +1,6 @@
package org.session.libsession.snode
public class Snode(val address: String, val port: Int, val publicKeySet: KeySet?) {
class Snode(val address: String, val port: Int, val publicKeySet: KeySet?) {
val ip: String get() = address.removePrefix("https://")

View File

@ -10,6 +10,9 @@ import org.session.libsession.snode.utilities.getRandomElement
import org.session.libsignal.utilities.logging.Log
import org.session.libsignal.service.loki.api.utilities.HTTP
import org.session.libsignal.service.loki.api.Snode
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
import org.session.libsignal.service.loki.utilities.Broadcaster
import org.session.libsignal.service.loki.utilities.prettifiedDescription
import org.session.libsignal.service.loki.utilities.retryIfNeeded
import org.session.libsignal.utilities.*
@ -17,10 +20,11 @@ import org.session.libsignal.utilities.*
import java.security.SecureRandom
object SnodeAPI {
val database = SnodeConfiguration.shared.storage
val broadcaster = SnodeConfiguration.shared.broadcaster
val database: LokiAPIDatabaseProtocol
get() = SnodeConfiguration.shared.storage
val broadcaster: Broadcaster
get() = SnodeConfiguration.shared.broadcaster
val sharedContext = Kovenant.createContext()
val messageSendingContext = Kovenant.createContext()
val messagePollingContext = Kovenant.createContext()
internal var snodeFailureCount: MutableMap<Snode, Int> = mutableMapOf()
@ -158,7 +162,7 @@ object SnodeAPI {
val parameters = mapOf( "pubKey" to publicKey )
return getRandomSnode().bind {
invoke(Snode.Method.GetSwarm, it, publicKey, parameters)
}.map(SnodeAPI.sharedContext) {
}.map(sharedContext) {
parseSnodes(it).toSet()
}.success {
database.setSwarm(publicKey, it)
@ -182,19 +186,12 @@ object SnodeAPI {
fun sendMessage(message: SnodeMessage): Promise<Set<RawResponsePromise>, Exception> {
val destination = message.recipient
fun broadcast(event: String) {
val dayInMs: Long = 86400000
if (message.ttl != dayInMs && message.ttl != 4 * dayInMs) { return }
broadcaster.broadcast(event, message.timestamp)
}
broadcast("calculatingPoW")
return retryIfNeeded(maxRetryCount) {
getTargetSnodes(destination).map(messageSendingContext) { swarm ->
getTargetSnodes(destination).map { swarm ->
swarm.map { snode ->
broadcast("sendingMessage")
val parameters = message.toJSON()
retryIfNeeded(maxRetryCount) {
invoke(Snode.Method.SendMessage, snode, destination, parameters).map(messageSendingContext) { rawResponse ->
invoke(Snode.Method.SendMessage, snode, destination, parameters).map { rawResponse ->
val json = rawResponse as? Map<*, *>
val powDifficulty = json?.get("difficulty") as? Int
if (powDifficulty != null) {

View File

@ -1,12 +1,13 @@
package org.session.libsession.snode
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
import org.session.libsignal.service.loki.utilities.Broadcaster
class SnodeConfiguration(val storage: SnodeStorageProtocol, val broadcaster: Broadcaster) {
class SnodeConfiguration(val storage: LokiAPIDatabaseProtocol, val broadcaster: Broadcaster) {
companion object {
lateinit var shared: SnodeConfiguration
fun configure(storage: SnodeStorageProtocol, broadcaster: Broadcaster) {
fun configure(storage: LokiAPIDatabaseProtocol, broadcaster: Broadcaster) {
if (Companion::shared.isInitialized) { return }
shared = SnodeConfiguration(storage, broadcaster)
}

View File

@ -38,7 +38,7 @@ class SSKEnvironment(
interface MessageExpirationManagerProtocol {
fun setExpirationTimer(messageID: Long?, duration: Int, senderPublicKey: String, content: SignalServiceProtos.Content)
fun disableExpirationTimer(messageID: Long?, senderPublicKey: String, content: SignalServiceProtos.Content)
fun startAnyExpiration(messageID: Long)
fun startAnyExpiration(timestamp: Long, author: String)
}
companion object {

View File

@ -26,14 +26,6 @@ public class SendMessageResult {
return new SendMessageResult(address, null, true, false, null, null);
}
public static SendMessageResult unregisteredFailure(SignalServiceAddress address) {
return new SendMessageResult(address, null, false, true, null, null);
}
public static SendMessageResult identityFailure(SignalServiceAddress address, IdentityKey identityKey) {
return new SendMessageResult(address, null, false, false, new IdentityFailure(identityKey), null);
}
public SignalServiceAddress getAddress() {
return address;
}

View File

@ -4,7 +4,7 @@ public class Snode(val address: String, val port: Int, val publicKeySet: KeySet?
val ip: String get() = address.removePrefix("https://")
internal enum class Method(val rawValue: String) {
enum class Method(val rawValue: String) {
/**
* Only supported by snode targets.
*/