mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 10:05:15 +00:00
hook up sending pipeline & clean
This commit is contained in:
parent
242eb90d21
commit
d9eaedd6ae
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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? {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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>() {
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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(),
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -301,8 +301,6 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
loaderContainer.fadeOut()
|
||||
isLoading = false
|
||||
}
|
||||
} else {
|
||||
GroupManager.updateGroup(this, groupID, members, null, name, admins)
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.database.documents;
|
||||
package org.session.libsession.database.documents;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.database.documents;
|
||||
package org.session.libsession.database.documents;
|
||||
|
||||
import org.session.libsignal.utilities.logging.Log;
|
||||
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
package org.session.libsession.messaging.messages.signal;
|
||||
|
||||
public class IncomingEncryptedMessage extends IncomingTextMessage {
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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://")
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user