mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-05 15:45:39 +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.conscrypt.Conscrypt;
|
||||||
import org.session.libsession.messaging.MessagingConfiguration;
|
import org.session.libsession.messaging.MessagingConfiguration;
|
||||||
import org.session.libsession.messaging.avatars.AvatarHelper;
|
import org.session.libsession.messaging.avatars.AvatarHelper;
|
||||||
|
import org.session.libsession.snode.SnodeConfiguration;
|
||||||
import org.session.libsession.utilities.SSKEnvironment;
|
import org.session.libsession.utilities.SSKEnvironment;
|
||||||
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
|
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
|
||||||
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
|
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
|
||||||
@ -176,6 +177,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
DatabaseFactory.getStorage(this),
|
DatabaseFactory.getStorage(this),
|
||||||
DatabaseFactory.getAttachmentProvider(this),
|
DatabaseFactory.getAttachmentProvider(this),
|
||||||
new SessionProtocolImpl(this));
|
new SessionProtocolImpl(this));
|
||||||
|
SnodeConfiguration.Companion.configure(apiDB, broadcaster);
|
||||||
if (userPublicKey != null) {
|
if (userPublicKey != null) {
|
||||||
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||||
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||||
|
@ -37,7 +37,11 @@ import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
|||||||
import androidx.loader.content.Loader;
|
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.thoughtcrime.securesms.MessageDetailsRecipientAdapter.RecipientDeliveryStatus;
|
||||||
import org.session.libsession.utilities.color.MaterialColor;
|
import org.session.libsession.utilities.color.MaterialColor;
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationItem;
|
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.loaders.MessageDetailsLoader;
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
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.loki.database.LokiMessageDatabase;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
import org.session.libsession.messaging.threads.recipients.RecipientModifiedListener;
|
import org.session.libsession.messaging.threads.recipients.RecipientModifiedListener;
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
|
||||||
import org.thoughtcrime.securesms.util.DateUtils;
|
import org.thoughtcrime.securesms.util.DateUtils;
|
||||||
import org.session.libsession.utilities.ExpirationUtil;
|
import org.session.libsession.utilities.ExpirationUtil;
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
@ -441,7 +445,28 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onResendClicked(View v) {
|
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);
|
resendButton.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.threads.DistributionTypes;
|
||||||
import org.thoughtcrime.securesms.components.SearchToolbar;
|
import org.thoughtcrime.securesms.components.SearchToolbar;
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationActivity;
|
import org.thoughtcrime.securesms.conversation.ConversationActivity;
|
||||||
import org.session.libsession.messaging.threads.Address;
|
import org.session.libsession.messaging.threads.Address;
|
||||||
@ -249,7 +250,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
|||||||
public void onContactSelected(String number) {
|
public void onContactSelected(String number) {
|
||||||
Recipient recipient = Recipient.from(this, Address.fromExternal(this, number), true);
|
Recipient recipient = Recipient.from(this, Address.fromExternal(this, number), true);
|
||||||
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient);
|
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient);
|
||||||
createConversation(existingThread, recipient.getAddress(), ThreadDatabase.DistributionTypes.DEFAULT);
|
createConversation(existingThread, recipient.getAddress(), DistributionTypes.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -79,7 +79,8 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
|
|||||||
|
|
||||||
override fun isOutgoingMessage(timestamp: Long): Boolean {
|
override fun isOutgoingMessage(timestamp: Long): Boolean {
|
||||||
val smsDatabase = DatabaseFactory.getSmsDatabase(context)
|
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? {
|
override fun getMessageID(serverID: Long): Long? {
|
||||||
|
@ -4,6 +4,7 @@ package org.thoughtcrime.securesms.attachments;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
||||||
@ -30,11 +31,11 @@ public class MmsNotificationAttachment extends Attachment {
|
|||||||
if (status == MmsDatabase.Status.DOWNLOAD_INITIALIZED ||
|
if (status == MmsDatabase.Status.DOWNLOAD_INITIALIZED ||
|
||||||
status == MmsDatabase.Status.DOWNLOAD_NO_CONNECTIVITY)
|
status == MmsDatabase.Status.DOWNLOAD_NO_CONNECTIVITY)
|
||||||
{
|
{
|
||||||
return AttachmentDatabase.TRANSFER_PROGRESS_PENDING;
|
return AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING;
|
||||||
} else if (status == MmsDatabase.Status.DOWNLOAD_CONNECTING) {
|
} else if (status == MmsDatabase.Status.DOWNLOAD_CONNECTING) {
|
||||||
return AttachmentDatabase.TRANSFER_PROGRESS_STARTED;
|
return AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED;
|
||||||
} else {
|
} 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.Subscribe;
|
||||||
import org.greenrobot.eventbus.ThreadMode;
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||||
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
||||||
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
||||||
@ -94,7 +96,7 @@ public class DocumentView extends FrameLayout {
|
|||||||
controlToggle.displayQuick(downloadButton);
|
controlToggle.displayQuick(downloadButton);
|
||||||
downloadButton.setOnClickListener(new DownloadClickedListener(documentSlide));
|
downloadButton.setOnClickListener(new DownloadClickedListener(documentSlide));
|
||||||
if (downloadProgress.isSpinning()) downloadProgress.stopSpinning();
|
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);
|
controlToggle.displayQuick(downloadProgress);
|
||||||
downloadProgress.spin();
|
downloadProgress.spin();
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -248,7 +249,7 @@ public class ThumbnailView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (slide.getThumbnailUri() != null && slide.hasPlayOverlay() &&
|
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);
|
this.playOverlay.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
@ -402,7 +403,7 @@ public class ThumbnailView extends FrameLayout {
|
|||||||
if (thumbnailClickListener != null &&
|
if (thumbnailClickListener != null &&
|
||||||
slide != null &&
|
slide != null &&
|
||||||
slide.asAttachment().getDataUri() != null &&
|
slide.asAttachment().getDataUri() != null &&
|
||||||
slide.getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_DONE)
|
slide.getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_DONE)
|
||||||
{
|
{
|
||||||
thumbnailClickListener.onClick(view, slide);
|
thumbnailClickListener.onClick(view, slide);
|
||||||
} else if (parentClickListener != null) {
|
} else if (parentClickListener != null) {
|
||||||
|
@ -17,6 +17,7 @@ import org.greenrobot.eventbus.EventBus;
|
|||||||
import org.greenrobot.eventbus.Subscribe;
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
import org.greenrobot.eventbus.ThreadMode;
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
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.database.AttachmentDatabase;
|
||||||
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
@ -105,17 +106,17 @@ public class TransferControlView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Slide slide : slides) {
|
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);
|
downloadProgress.put(slide.asAttachment(), 1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (getTransferState(slides)) {
|
switch (getTransferState(slides)) {
|
||||||
case AttachmentDatabase.TRANSFER_PROGRESS_STARTED:
|
case AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED:
|
||||||
showProgressSpinner(calculateProgress(downloadProgress));
|
showProgressSpinner(calculateProgress(downloadProgress));
|
||||||
break;
|
break;
|
||||||
case AttachmentDatabase.TRANSFER_PROGRESS_PENDING:
|
case AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING:
|
||||||
case AttachmentDatabase.TRANSFER_PROGRESS_FAILED:
|
case AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED:
|
||||||
downloadDetailsText.setText(getDownloadText(this.slides));
|
downloadDetailsText.setText(getDownloadText(this.slides));
|
||||||
display(downloadDetails);
|
display(downloadDetails);
|
||||||
break;
|
break;
|
||||||
@ -174,9 +175,9 @@ public class TransferControlView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int getTransferState(@NonNull List<Slide> slides) {
|
private int getTransferState(@NonNull List<Slide> slides) {
|
||||||
int transferState = AttachmentDatabase.TRANSFER_PROGRESS_DONE;
|
int transferState = AttachmentTransferProgress.TRANSFER_PROGRESS_DONE;
|
||||||
for (Slide slide : slides) {
|
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();
|
transferState = slide.getTransferState();
|
||||||
} else {
|
} else {
|
||||||
transferState = Math.max(transferState, slide.getTransferState());
|
transferState = Math.max(transferState, slide.getTransferState());
|
||||||
@ -189,7 +190,7 @@ public class TransferControlView extends FrameLayout {
|
|||||||
if (slides.size() == 1) {
|
if (slides.size() == 1) {
|
||||||
return slides.get(0).getContentDescription();
|
return slides.get(0).getContentDescription();
|
||||||
} else {
|
} 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);
|
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.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.GroupUtil;
|
||||||
import org.session.libsession.utilities.MediaTypes;
|
import org.session.libsession.utilities.MediaTypes;
|
||||||
import org.session.libsignal.libsignal.InvalidMessageException;
|
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.DraftDatabase.Drafts;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||||
import org.thoughtcrime.securesms.database.MmsSmsColumns.Types;
|
import org.thoughtcrime.securesms.database.MmsSmsColumns.Types;
|
||||||
|
import org.thoughtcrime.securesms.database.Storage;
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
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.GlideRequests;
|
||||||
import org.thoughtcrime.securesms.mms.ImageSlide;
|
import org.thoughtcrime.securesms.mms.ImageSlide;
|
||||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
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.OutgoingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.QuoteId;
|
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.RecipientFormattingException;
|
||||||
import org.session.libsession.messaging.threads.recipients.RecipientModifiedListener;
|
import org.session.libsession.messaging.threads.recipients.RecipientModifiedListener;
|
||||||
import org.thoughtcrime.securesms.search.model.MessageResult;
|
import org.thoughtcrime.securesms.search.model.MessageResult;
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage;
|
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
import org.thoughtcrime.securesms.util.DateUtils;
|
import org.thoughtcrime.securesms.util.DateUtils;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
@ -197,7 +201,6 @@ import java.util.Collections;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
@ -571,16 +574,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
final Context context = ConversationActivity.this.getApplicationContext();
|
final Context context = ConversationActivity.this.getApplicationContext();
|
||||||
|
|
||||||
sendMediaMessage(false,
|
sendMediaMessage(message,
|
||||||
message,
|
|
||||||
slideDeck,
|
slideDeck,
|
||||||
inputPanel.getQuote().orNull(),
|
inputPanel.getQuote().orNull(),
|
||||||
Collections.emptyList(),
|
Optional.absent(),
|
||||||
Collections.emptyList(),
|
initiating).addListener(new AssertedSuccessListener<Void>() {
|
||||||
expiresIn,
|
|
||||||
subscriptionId,
|
|
||||||
initiating,
|
|
||||||
true).addListener(new AssertedSuccessListener<Void>() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Void result) {
|
public void onSuccess(Void result) {
|
||||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
||||||
@ -648,7 +646,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
if (!isPushGroupConversation()) {
|
if (!isPushGroupConversation()) {
|
||||||
inflater.inflate(R.menu.conversation_mms_group_options, menu);
|
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);
|
menu.findItem(R.id.menu_distribution_broadcast).setChecked(true);
|
||||||
} else {
|
} else {
|
||||||
menu.findItem(R.id.menu_distribution_conversation).setChecked(true);
|
menu.findItem(R.id.menu_distribution_conversation).setChecked(true);
|
||||||
@ -808,8 +806,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
DatabaseFactory.getRecipientDatabase(ConversationActivity.this).setExpireMessages(recipient, expirationTime);
|
DatabaseFactory.getRecipientDatabase(ConversationActivity.this).setExpireMessages(recipient, expirationTime);
|
||||||
OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(getRecipient(), System.currentTimeMillis(), expirationTime * 1000L);
|
ExpirationTimerUpdate message = new ExpirationTimerUpdate();
|
||||||
MessageSender.send(ConversationActivity.this, outgoingMessage, threadId, false, null);
|
message.setDuration(expirationTime * 1000);
|
||||||
|
MessageSender.send(message, recipient.getAddress());
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -1040,7 +1039,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleDistributionBroadcastEnabled(MenuItem item) {
|
private void handleDistributionBroadcastEnabled(MenuItem item) {
|
||||||
distributionType = ThreadDatabase.DistributionTypes.BROADCAST;
|
distributionType = DistributionTypes.BROADCAST;
|
||||||
item.setChecked(true);
|
item.setChecked(true);
|
||||||
|
|
||||||
if (threadId != -1) {
|
if (threadId != -1) {
|
||||||
@ -1048,7 +1047,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
|
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
|
||||||
.setDistributionType(threadId, ThreadDatabase.DistributionTypes.BROADCAST);
|
.setDistributionType(threadId, DistributionTypes.BROADCAST);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
@ -1056,7 +1055,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleDistributionConversationEnabled(MenuItem item) {
|
private void handleDistributionConversationEnabled(MenuItem item) {
|
||||||
distributionType = ThreadDatabase.DistributionTypes.CONVERSATION;
|
distributionType = DistributionTypes.CONVERSATION;
|
||||||
item.setChecked(true);
|
item.setChecked(true);
|
||||||
|
|
||||||
if (threadId != -1) {
|
if (threadId != -1) {
|
||||||
@ -1064,7 +1063,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
|
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
|
||||||
.setDistributionType(threadId, ThreadDatabase.DistributionTypes.CONVERSATION);
|
.setDistributionType(threadId, DistributionTypes.CONVERSATION);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
@ -1335,7 +1334,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
if (address == null) { finish(); return; }
|
if (address == null) { finish(); return; }
|
||||||
recipient = Recipient.from(this, address, true);
|
recipient = Recipient.from(this, address, true);
|
||||||
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
|
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);
|
glideRequests = GlideApp.with(this);
|
||||||
|
|
||||||
recipient.addListener(this);
|
recipient.addListener(this);
|
||||||
@ -1483,14 +1482,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
else if (contactData.numbers.size() > 1) selectContactInfo(contactData);
|
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) {
|
private void selectContactInfo(ContactData contactData) {
|
||||||
final CharSequence[] numbers = new CharSequence[contactData.numbers.size()];
|
final CharSequence[] numbers = new CharSequence[contactData.numbers.size()];
|
||||||
final CharSequence[] numberItems = 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();
|
String message = getMessage();
|
||||||
int subscriptionId = -1;
|
|
||||||
long expiresIn = recipient.getExpireMessages() * 1000L;
|
|
||||||
boolean initiating = threadId == -1;
|
boolean initiating = threadId == -1;
|
||||||
boolean needsSplit = message.length() > characterCalculator.calculateCharacters(message).maxPrimaryMessageSize;
|
boolean needsSplit = message.length() > characterCalculator.calculateCharacters(message).maxPrimaryMessageSize;
|
||||||
boolean isMediaMessage = attachmentManager.isAttachmentPresent() ||
|
boolean isMediaMessage = attachmentManager.isAttachmentPresent() ||
|
||||||
@ -1747,9 +1736,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
needsSplit;
|
needsSplit;
|
||||||
|
|
||||||
if (isMediaMessage) {
|
if (isMediaMessage) {
|
||||||
sendMediaMessage(expiresIn, subscriptionId, initiating);
|
sendMediaMessage(initiating);
|
||||||
} else {
|
} else {
|
||||||
sendTextMessage(expiresIn, subscriptionId, initiating);
|
sendTextMessage(initiating);
|
||||||
}
|
}
|
||||||
} catch (RecipientFormattingException ex) {
|
} catch (RecipientFormattingException ex) {
|
||||||
Log.w(TAG, 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
|
throws InvalidMessageException
|
||||||
{
|
{
|
||||||
Log.i(TAG, "Sending media message...");
|
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,
|
private ListenableFuture<Void> sendMediaMessage(String body,
|
||||||
String body,
|
|
||||||
SlideDeck slideDeck,
|
SlideDeck slideDeck,
|
||||||
QuoteModel quote,
|
QuoteModel quote,
|
||||||
List<Contact> contacts,
|
Optional<LinkPreview> linkPreview,
|
||||||
List<LinkPreview> previews,
|
final boolean initiating)
|
||||||
final long expiresIn,
|
|
||||||
final int subscriptionId,
|
|
||||||
final boolean initiating,
|
|
||||||
final boolean clearComposeBox)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
Pair<String, Optional<Slide>> splitMessage = getSplitMessage(body, characterCalculator.calculateCharacters(body).maxPrimaryMessageSize);
|
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());
|
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 SettableFuture<Void> future = new SettableFuture<>();
|
||||||
final Context context = getApplicationContext();
|
final Context context = getApplicationContext();
|
||||||
@ -1800,11 +1789,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
outgoingMessage = new OutgoingSecureMediaMessage(outgoingMessageCandidate);
|
outgoingMessage = new OutgoingSecureMediaMessage(outgoingMessageCandidate);
|
||||||
ApplicationContext.getInstance(context).getTypingStatusSender().onTypingStopped(threadId);
|
ApplicationContext.getInstance(context).getTypingStatusSender().onTypingStopped(threadId);
|
||||||
|
|
||||||
if (clearComposeBox) {
|
|
||||||
inputPanel.clearQuote();
|
inputPanel.clearQuote();
|
||||||
attachmentManager.clear(glideRequests, false);
|
attachmentManager.clear(glideRequests, false);
|
||||||
silentlySetComposeText("");
|
silentlySetComposeText("");
|
||||||
}
|
|
||||||
|
|
||||||
final long id = fragment.stageOutgoingMessage(outgoingMessage);
|
final long id = fragment.stageOutgoingMessage(outgoingMessage);
|
||||||
|
|
||||||
@ -1812,43 +1799,54 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
|
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
long result = MessageSender.send(context, outgoingMessage, threadId, forceSms, () -> fragment.releaseOutgoingMessage(id));
|
try {
|
||||||
|
long allocatedThreadId;
|
||||||
sendComplete(result);
|
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);
|
future.set(null);
|
||||||
|
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendTextMessage(final long expiresIn, final int subscriptionId, final boolean initiatingConversation)
|
private void sendTextMessage(final boolean initiating)
|
||||||
throws InvalidMessageException
|
throws InvalidMessageException
|
||||||
{
|
{
|
||||||
final Context context = getApplicationContext();
|
final Context context = getApplicationContext();
|
||||||
final String messageBody = getMessage();
|
final String messageBody = getMessage();
|
||||||
|
|
||||||
OutgoingTextMessage message;
|
VisibleMessage message = new VisibleMessage();
|
||||||
|
message.setSentTimestamp(System.currentTimeMillis());
|
||||||
message = new OutgoingEncryptedMessage(recipient, messageBody, expiresIn);
|
message.setText(messageBody);
|
||||||
|
OutgoingTextMessage outgoingTextMessage = OutgoingTextMessage.from(message, recipient);
|
||||||
ApplicationContext.getInstance(context).getTypingStatusSender().onTypingStopped(threadId);
|
ApplicationContext.getInstance(context).getTypingStatusSender().onTypingStopped(threadId);
|
||||||
|
|
||||||
silentlySetComposeText("");
|
silentlySetComposeText("");
|
||||||
final long id = fragment.stageOutgoingMessage(message);
|
final long id = fragment.stageOutgoingMessage(outgoingTextMessage);
|
||||||
|
|
||||||
if (initiatingConversation) {
|
if (initiating) {
|
||||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
|
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
long result = MessageSender.send(context, message, threadId, false, () -> fragment.releaseOutgoingMessage(id));
|
long allocatedThreadId;
|
||||||
|
if (threadId == -1) {
|
||||||
sendComplete(result);
|
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());
|
||||||
|
|
||||||
private void showDefaultSmsPrompt() {
|
sendComplete(allocatedThreadId);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateToggleButtonState() {
|
private void updateToggleButtonState() {
|
||||||
@ -1934,7 +1932,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
SlideDeck slideDeck = new SlideDeck();
|
SlideDeck slideDeck = new SlideDeck();
|
||||||
slideDeck.addSlide(audioSlide);
|
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
|
@Override
|
||||||
public void onSuccess(Void nothing) {
|
public void onSuccess(Void nothing) {
|
||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
|
@ -57,6 +57,8 @@ import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
|
|||||||
|
|
||||||
import com.annimon.stream.Stream;
|
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.ApplicationContext;
|
||||||
import org.thoughtcrime.securesms.MessageDetailsActivity;
|
import org.thoughtcrime.securesms.MessageDetailsActivity;
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
|
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.mms.Slide;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
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.CommunicationActions;
|
||||||
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
|
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
|
||||||
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
|
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.PublicChat;
|
||||||
import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI;
|
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.TextSecurePreferences;
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
import org.session.libsession.utilities.ViewUtil;
|
import org.session.libsession.utilities.ViewUtil;
|
||||||
@ -696,11 +698,32 @@ public class ConversationFragment extends Fragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleResendMessage(final MessageRecord message) {
|
private void handleResendMessage(final MessageRecord message) {
|
||||||
final Context context = getActivity().getApplicationContext();
|
|
||||||
new AsyncTask<MessageRecord, Void, Void>() {
|
new AsyncTask<MessageRecord, Void, Void>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(MessageRecord... messageRecords) {
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, message);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, message);
|
||||||
|
@ -53,6 +53,7 @@ import androidx.annotation.Nullable;
|
|||||||
import com.annimon.stream.Stream;
|
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.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
|
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
|
||||||
import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI;
|
import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI;
|
||||||
@ -1003,10 +1004,10 @@ public class ConversationItem extends LinearLayout
|
|||||||
if (messageRecord.isMms()) {
|
if (messageRecord.isMms()) {
|
||||||
TextSlide slide = ((MmsMessageRecord) messageRecord).getSlideDeck().getTextSlide();
|
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);
|
message = getResources().getString(R.string.ConversationItem_read_more);
|
||||||
action = () -> eventListener.onMoreTextClicked(conversationRecipient.getAddress(), messageRecord.getId(), messageRecord.isMms());
|
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);
|
message = getResources().getString(R.string.ConversationItem_pending);
|
||||||
action = () -> {};
|
action = () -> {};
|
||||||
} else if (slide != null) {
|
} else if (slide != null) {
|
||||||
|
@ -38,6 +38,7 @@ import net.sqlcipher.database.SQLiteDatabase;
|
|||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
|
||||||
import org.session.libsession.utilities.MediaTypes;
|
import org.session.libsession.utilities.MediaTypes;
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
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_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.
|
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_ID_WHERE = ROW_ID + " = ? AND " + UNIQUE_ID + " = ?";
|
||||||
private static final String PART_AUDIO_ONLY_WHERE = CONTENT_TYPE + " LIKE \"audio/%\"";
|
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();
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
ContentValues values = new ContentValues();
|
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());
|
database.update(TABLE_NAME, values, PART_ID_WHERE, attachmentId.toStrings());
|
||||||
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(mmsId));
|
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(mmsId));
|
||||||
@ -268,7 +264,7 @@ public class AttachmentDatabase extends Database {
|
|||||||
|
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
try {
|
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()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
attachments.addAll(getAttachment(cursor));
|
attachments.addAll(getAttachment(cursor));
|
||||||
}
|
}
|
||||||
@ -372,7 +368,7 @@ public class AttachmentDatabase extends Database {
|
|||||||
values.put(DATA_RANDOM, dataInfo.random);
|
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_LOCATION, (String)null);
|
||||||
values.put(CONTENT_DISPOSITION, (String)null);
|
values.put(CONTENT_DISPOSITION, (String)null);
|
||||||
values.put(DIGEST, (byte[])null);
|
values.put(DIGEST, (byte[])null);
|
||||||
@ -395,7 +391,7 @@ public class AttachmentDatabase extends Database {
|
|||||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
ContentValues values = new ContentValues();
|
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(CONTENT_LOCATION, attachment.getLocation());
|
||||||
values.put(DIGEST, attachment.getDigest());
|
values.put(DIGEST, attachment.getDigest());
|
||||||
values.put(CONTENT_DISPOSITION, attachment.getKey());
|
values.put(CONTENT_DISPOSITION, attachment.getKey());
|
||||||
@ -411,7 +407,7 @@ public class AttachmentDatabase extends Database {
|
|||||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
ContentValues values = new ContentValues();
|
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());
|
database.update(TABLE_NAME, values, PART_ID_WHERE, id.toStrings());
|
||||||
}
|
}
|
||||||
@ -506,37 +502,17 @@ public class AttachmentDatabase extends Database {
|
|||||||
databaseAttachment.getUrl());
|
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) {
|
public void markAttachmentUploaded(long messageId, Attachment attachment) {
|
||||||
ContentValues values = new ContentValues(1);
|
ContentValues values = new ContentValues(1);
|
||||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
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());
|
database.update(TABLE_NAME, values, PART_ID_WHERE, ((DatabaseAttachment)attachment).getAttachmentId().toStrings());
|
||||||
|
|
||||||
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId));
|
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId));
|
||||||
((DatabaseAttachment) attachment).setUploaded(true);
|
((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) {
|
public void setTransferState(long messageId, @NonNull AttachmentId attachmentId, int transferState) {
|
||||||
final ContentValues values = new ContentValues(1);
|
final ContentValues values = new ContentValues(1);
|
||||||
final SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
final SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
@ -546,14 +522,6 @@ public class AttachmentDatabase extends Database {
|
|||||||
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId));
|
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")
|
@SuppressWarnings("WeakerAccess")
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected @Nullable InputStream getDataStream(AttachmentId attachmentId, String dataType, long offset)
|
protected @Nullable InputStream getDataStream(AttachmentId attachmentId, String dataType, long offset)
|
||||||
|
@ -7,9 +7,9 @@ import android.text.TextUtils;
|
|||||||
|
|
||||||
import net.sqlcipher.database.SQLiteDatabase;
|
import net.sqlcipher.database.SQLiteDatabase;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.documents.Document;
|
import org.session.libsession.database.documents.Document;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchList;
|
import org.session.libsession.database.documents.IdentityKeyMismatchList;
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
import org.session.libsignal.libsignal.IdentityKey;
|
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 markAsSent(long messageId, boolean secure);
|
||||||
public abstract void markUnidentified(long messageId, boolean unidentified);
|
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) {
|
public void addMismatchedIdentity(long messageId, Address address, IdentityKey identityKey) {
|
||||||
try {
|
try {
|
||||||
addToDocument(messageId, MISMATCHED_IDENTITIES,
|
addToDocument(messageId, MISMATCHED_IDENTITIES,
|
||||||
|
@ -19,9 +19,7 @@ package org.thoughtcrime.securesms.database;
|
|||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@ -38,10 +36,10 @@ import org.json.JSONException;
|
|||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.thoughtcrime.securesms.attachments.MmsNotificationAttachment;
|
import org.thoughtcrime.securesms.attachments.MmsNotificationAttachment;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchList;
|
import org.session.libsession.database.documents.IdentityKeyMismatchList;
|
||||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
import org.session.libsession.database.documents.NetworkFailure;
|
||||||
import org.thoughtcrime.securesms.database.documents.NetworkFailureList;
|
import org.session.libsession.database.documents.NetworkFailureList;
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||||
|
@ -23,8 +23,6 @@ import android.database.Cursor;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
import net.sqlcipher.database.SQLiteDatabase;
|
import net.sqlcipher.database.SQLiteDatabase;
|
||||||
@ -32,15 +30,15 @@ import net.sqlcipher.database.SQLiteStatement;
|
|||||||
|
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchList;
|
import org.session.libsession.database.documents.IdentityKeyMismatchList;
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||||
import org.thoughtcrime.securesms.jobs.TrimThreadJob;
|
import org.thoughtcrime.securesms.jobs.TrimThreadJob;
|
||||||
import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
|
import org.session.libsession.messaging.messages.signal.IncomingGroupMessage;
|
||||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
import org.session.libsession.messaging.messages.signal.IncomingTextMessage;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
||||||
|
|
||||||
import org.session.libsession.messaging.threads.Address;
|
import org.session.libsession.messaging.threads.Address;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
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.io.IOException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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.opengroups.OpenGroup
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
|
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.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.linkpreview.LinkPreview
|
||||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||||
import org.session.libsession.messaging.threads.Address
|
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.OutgoingGroupMediaMessage
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority
|
import org.thoughtcrime.securesms.mms.PartAuthority
|
||||||
import org.thoughtcrime.securesms.sms.IncomingGroupMessage
|
import org.session.libsession.messaging.messages.signal.IncomingGroupMessage
|
||||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage
|
import org.session.libsession.messaging.messages.signal.IncomingTextMessage
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
|
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage
|
||||||
|
|
||||||
class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol {
|
class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol {
|
||||||
override fun getUserPublicKey(): String? {
|
override fun getUserPublicKey(): String? {
|
||||||
@ -125,7 +124,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
}.mapNotNull {
|
}.mapNotNull {
|
||||||
PointerAttachment.forPointer(Optional.of(it)).orNull()
|
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!!)
|
mmsDatabase.insertSecureDecryptedMessageOutbox(mediaMessage, message.threadID ?: -1, message.sentTimestamp!!)
|
||||||
} else {
|
} else {
|
||||||
// It seems like we have replaced SignalServiceAttachment with SessionServiceAttachment
|
// 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)
|
DatabaseFactory.getLokiMessageDatabase(context).setServerID(messageID, serverID)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun markAsSent(messageID: Long) {
|
override fun markAsSent(timestamp: Long, author: String) {
|
||||||
val database = DatabaseFactory.getMmsSmsDatabase(context)
|
val database = DatabaseFactory.getMmsSmsDatabase(context)
|
||||||
val messageRecord = database.getMessageFor(messageID)!!
|
val messageRecord = database.getMessageFor(timestamp, author) ?: return
|
||||||
if (messageRecord.isMms) {
|
if (messageRecord.isMms) {
|
||||||
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
|
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
|
||||||
mmsDatabase.markAsSent(messageRecord.getId(), true)
|
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 database = DatabaseFactory.getMmsSmsDatabase(context)
|
||||||
val messageRecord = database.getMessageFor(messageID)!!
|
val messageRecord = database.getMessageFor(timestamp, author) ?: return
|
||||||
if (messageRecord.isMms) {
|
if (messageRecord.isMms) {
|
||||||
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
|
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
|
||||||
mmsDatabase.markUnidentified(messageRecord.getId(), true)
|
mmsDatabase.markUnidentified(messageRecord.getId(), true)
|
||||||
|
@ -29,6 +29,7 @@ import com.annimon.stream.Stream;
|
|||||||
|
|
||||||
import net.sqlcipher.database.SQLiteDatabase;
|
import net.sqlcipher.database.SQLiteDatabase;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.threads.DistributionTypes;
|
||||||
import org.thoughtcrime.securesms.contactshare.ContactUtil;
|
import org.thoughtcrime.securesms.contactshare.ContactUtil;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||||
@ -596,14 +597,6 @@ public class ThreadDatabase extends Database {
|
|||||||
return new Reader(cursor);
|
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 {
|
public class Reader implements Closeable {
|
||||||
|
|
||||||
private final Cursor cursor;
|
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.LokiMessageDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsMigration;
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsMigration;
|
||||||
|
|
||||||
public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||||
@ -52,9 +53,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
private static final int lokiV19 = 40;
|
private static final int lokiV19 = 40;
|
||||||
private static final int lokiV20 = 41;
|
private static final int lokiV20 = 41;
|
||||||
private static final int lokiV21 = 42;
|
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
|
// 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 static final String DATABASE_NAME = "signal.db";
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
@ -121,6 +123,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
db.execSQL(LokiUserDatabase.getCreateDisplayNameTableCommand());
|
db.execSQL(LokiUserDatabase.getCreateDisplayNameTableCommand());
|
||||||
db.execSQL(LokiUserDatabase.getCreateServerDisplayNameTableCommand());
|
db.execSQL(LokiUserDatabase.getCreateServerDisplayNameTableCommand());
|
||||||
db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand());
|
db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand());
|
||||||
|
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
|
||||||
|
|
||||||
executeStatements(db, SmsDatabase.CREATE_INDEXS);
|
executeStatements(db, SmsDatabase.CREATE_INDEXS);
|
||||||
executeStatements(db, MmsDatabase.CREATE_INDEXS);
|
executeStatements(db, MmsDatabase.CREATE_INDEXS);
|
||||||
@ -255,6 +258,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
"ResetThreadSessionJob");
|
"ResetThreadSessionJob");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldVersion < lokiV22) {
|
||||||
|
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
|
||||||
|
}
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
} finally {
|
} finally {
|
||||||
db.endTransaction();
|
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.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
|
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
import org.session.libsession.database.documents.NetworkFailure;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ import android.text.style.StyleSpan;
|
|||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
import org.session.libsession.database.documents.NetworkFailure;
|
||||||
|
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
import org.session.libsession.utilities.ExpirationUtil;
|
import org.session.libsession.utilities.ExpirationUtil;
|
||||||
@ -158,18 +158,10 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||||||
return SmsDatabase.Types.isIdentityDefault(type);
|
return SmsDatabase.Types.isIdentityDefault(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isIdentityMismatchFailure() {
|
|
||||||
return mismatches != null && !mismatches.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBundleKeyExchange() {
|
public boolean isBundleKeyExchange() {
|
||||||
return SmsDatabase.Types.isBundleKeyExchange(type);
|
return SmsDatabase.Types.isBundleKeyExchange(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isContentBundleKeyExchange() {
|
|
||||||
return SmsDatabase.Types.isContentBundleKeyExchange(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isIdentityUpdate() {
|
public boolean isIdentityUpdate() {
|
||||||
return SmsDatabase.Types.isIdentityUpdate(type);
|
return SmsDatabase.Types.isIdentityUpdate(type);
|
||||||
}
|
}
|
||||||
@ -195,10 +187,6 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||||||
return individualRecipient;
|
return individualRecipient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRecipientDeviceId() {
|
|
||||||
return recipientDeviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getType() {
|
public long getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@ -211,10 +199,6 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||||||
return networkFailures;
|
return networkFailures;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasNetworkFailures() {
|
|
||||||
return networkFailures != null && !networkFailures.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SpannableString emphasisAdded(String sequence) {
|
protected SpannableString emphasisAdded(String sequence) {
|
||||||
SpannableString spannable = new SpannableString(sequence);
|
SpannableString spannable = new SpannableString(sequence);
|
||||||
spannable.setSpan(new RelativeSizeSpan(0.9f), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
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();
|
return (int)getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSubscriptionId() {
|
|
||||||
return subscriptionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getExpiresIn() {
|
public long getExpiresIn() {
|
||||||
return expiresIn;
|
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.sending_receiving.linkpreview.LinkPreview;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
import org.session.libsession.database.documents.NetworkFailure;
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ import android.text.SpannableString;
|
|||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
|
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
import org.session.libsession.database.documents.NetworkFailure;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
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.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel;
|
||||||
import org.session.libsession.messaging.threads.Address;
|
import org.session.libsession.messaging.threads.Address;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
|
|
||||||
@ -42,4 +43,8 @@ public class Quote {
|
|||||||
public @NonNull SlideDeck getAttachment() {
|
public @NonNull SlideDeck getAttachment() {
|
||||||
return attachment;
|
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.MmsSmsColumns;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
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 org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -2,36 +2,23 @@ package org.thoughtcrime.securesms.groups;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
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.Address;
|
||||||
|
import org.session.libsession.messaging.threads.DistributionTypes;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
import org.session.libsession.utilities.GroupUtil;
|
import org.session.libsession.utilities.GroupUtil;
|
||||||
import org.session.libsession.utilities.MediaTypes;
|
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
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.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.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -72,7 +59,7 @@ public class GroupManager {
|
|||||||
groupDatabase.updateProfilePicture(groupId, avatarBytes);
|
groupDatabase.updateProfilePicture(groupId, avatarBytes);
|
||||||
|
|
||||||
long threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(
|
long threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(
|
||||||
groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
groupRecipient, DistributionTypes.CONVERSATION);
|
||||||
return new GroupActionResult(groupRecipient, threadID);
|
return new GroupActionResult(groupRecipient, threadID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,82 +82,6 @@ public class GroupManager {
|
|||||||
return groupDatabase.delete(groupId);
|
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 {
|
public static class GroupActionResult {
|
||||||
private Recipient groupRecipient;
|
private Recipient groupRecipient;
|
||||||
private long threadId;
|
private long threadId;
|
||||||
|
@ -7,6 +7,7 @@ import androidx.annotation.VisibleForTesting;
|
|||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
import org.session.libsession.messaging.jobs.Data;
|
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.InvalidMessageException;
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.api.crypto.AttachmentCipherInputStream;
|
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 AttachmentDatabase database = DatabaseFactory.getAttachmentDatabase(context);
|
||||||
final AttachmentId attachmentId = new AttachmentId(partRowId, partUniqueId);
|
final AttachmentId attachmentId = new AttachmentId(partRowId, partUniqueId);
|
||||||
final DatabaseAttachment attachment = database.getAttachment(attachmentId);
|
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))) {
|
if (pending && (manual || AttachmentUtil.isAutoDownloadPermitted(context, attachment))) {
|
||||||
Log.i(TAG, "onAdded() Marking attachment progress as 'started'");
|
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)) {
|
if (!manual && !AttachmentUtil.isAutoDownloadPermitted(context, attachment)) {
|
||||||
Log.w(TAG, "Attachment can't be auto downloaded...");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "Downloading push part " + attachmentId);
|
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);
|
retrieveAttachment(messageId, attachmentId, attachment);
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import com.annimon.stream.Collectors;
|
|||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
import org.session.libsession.messaging.jobs.Data;
|
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.InvalidMetadataMessageException;
|
||||||
import org.session.libsignal.metadata.ProtocolInvalidMessageException;
|
import org.session.libsignal.metadata.ProtocolInvalidMessageException;
|
||||||
import org.session.libsignal.service.api.crypto.SignalServiceCipher;
|
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.contactshare.ContactModelMapper;
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
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.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
|
import org.session.libsession.messaging.messages.signal.IncomingEncryptedMessage;
|
||||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
import org.session.libsession.messaging.messages.signal.IncomingTextMessage;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.api.SignalServiceMessageSender;
|
import org.session.libsignal.service.api.SignalServiceMessageSender;
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceContent;
|
import org.session.libsignal.service.api.messages.SignalServiceContent;
|
||||||
@ -346,7 +346,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
attachments,
|
attachments,
|
||||||
message.getTimestamp(), -1,
|
message.getTimestamp(), -1,
|
||||||
message.getExpiresInSeconds() * 1000,
|
message.getExpiresInSeconds() * 1000,
|
||||||
ThreadDatabase.DistributionTypes.DEFAULT, quote.orNull(),
|
DistributionTypes.DEFAULT, quote.orNull(),
|
||||||
sharedContacts.or(Collections.emptyList()),
|
sharedContacts.or(Collections.emptyList()),
|
||||||
linkPreviews.or(Collections.emptyList()),
|
linkPreviews.or(Collections.emptyList()),
|
||||||
Collections.emptyList(), 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.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
import org.session.libsession.database.documents.NetworkFailure;
|
||||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||||
|
@ -9,6 +9,7 @@ import androidx.annotation.Nullable;
|
|||||||
|
|
||||||
import com.google.android.gms.common.util.IOUtils;
|
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.session.libsession.utilities.MediaTypes;
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||||
@ -192,7 +193,7 @@ public class LinkPreviewRepository implements InjectableType {
|
|||||||
return Optional.of(new UriAttachment(uri,
|
return Optional.of(new UriAttachment(uri,
|
||||||
uri,
|
uri,
|
||||||
contentType,
|
contentType,
|
||||||
AttachmentDatabase.TRANSFER_PROGRESS_STARTED,
|
AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED,
|
||||||
bytes.length,
|
bytes.length,
|
||||||
bitmap.getWidth(),
|
bitmap.getWidth(),
|
||||||
bitmap.getHeight(),
|
bitmap.getHeight(),
|
||||||
|
@ -43,13 +43,13 @@ public class LinkPreviewViewModel extends ViewModel {
|
|||||||
return linkPreviewState.getValue() != null && linkPreviewState.getValue().getLinkPreview().isPresent();
|
return linkPreviewState.getValue() != null && linkPreviewState.getValue().getLinkPreview().isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull List<LinkPreview> getActiveLinkPreviews() {
|
public Optional<LinkPreview> getActiveLinkPreview() {
|
||||||
final LinkPreviewState state = linkPreviewState.getValue();
|
final LinkPreviewState state = linkPreviewState.getValue();
|
||||||
|
|
||||||
if (state == null || !state.getLinkPreview().isPresent()) {
|
if (state == null || !state.getLinkPreview().isPresent()) {
|
||||||
return Collections.emptyList();
|
return Optional.absent();
|
||||||
} else {
|
} 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.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
||||||
import org.session.libsession.messaging.threads.Address
|
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.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
|
||||||
import org.thoughtcrime.securesms.loki.utilities.fadeIn
|
import org.thoughtcrime.securesms.loki.utilities.fadeIn
|
||||||
import org.thoughtcrime.securesms.loki.utilities.fadeOut
|
import org.thoughtcrime.securesms.loki.utilities.fadeOut
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import org.thoughtcrime.securesms.mms.GlideApp
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2
|
||||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
|
|
||||||
|
|
||||||
//TODO Refactor to avoid using kotlinx.android.synthetic
|
//TODO Refactor to avoid using kotlinx.android.synthetic
|
||||||
class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), LoaderManager.LoaderCallbacks<List<String>> {
|
class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), LoaderManager.LoaderCallbacks<List<String>> {
|
||||||
@ -128,7 +127,7 @@ class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), LoaderM
|
|||||||
private fun openConversationActivity(context: Context, threadId: Long, recipient: Recipient) {
|
private fun openConversationActivity(context: Context, threadId: Long, recipient: Recipient) {
|
||||||
val intent = Intent(context, ConversationActivity::class.java)
|
val intent = Intent(context, ConversationActivity::class.java)
|
||||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId)
|
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)
|
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.address)
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import network.loki.messenger.R
|
|||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
||||||
import org.session.libsession.messaging.threads.Address
|
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.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||||
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment
|
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment
|
||||||
@ -69,7 +70,7 @@ class CreatePrivateChatActivity : PassphraseRequiredActionBarActivity(), ScanQRC
|
|||||||
intent.setDataAndType(getIntent().data, getIntent().type)
|
intent.setDataAndType(getIntent().data, getIntent().type)
|
||||||
val existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient)
|
val existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient)
|
||||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread)
|
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)
|
startActivity(intent)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
@ -301,8 +301,6 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
loaderContainer.fadeOut()
|
loaderContainer.fadeOut()
|
||||||
isLoading = false
|
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.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
||||||
import org.session.libsession.messaging.threads.Address
|
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.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||||
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment
|
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment
|
||||||
@ -60,7 +61,7 @@ class QRCodeActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperF
|
|||||||
intent.setDataAndType(getIntent().data, getIntent().type)
|
intent.setDataAndType(getIntent().data, getIntent().type)
|
||||||
val existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient)
|
val existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient)
|
||||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread)
|
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)
|
startActivity(intent)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import org.thoughtcrime.securesms.loki.utilities.*
|
|||||||
class SessionJobDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
|
class SessionJobDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val sessionJobTable = "loki_thread_session_reset_database"
|
private val sessionJobTable = "session_job_database"
|
||||||
val jobID = "job_id"
|
val jobID = "job_id"
|
||||||
val jobType = "job_type"
|
val jobType = "job_type"
|
||||||
val failureCount = "failure_count"
|
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.api.SessionProtocolImpl
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase
|
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage
|
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage
|
||||||
import org.thoughtcrime.securesms.sms.IncomingGroupMessage
|
import org.session.libsession.messaging.messages.signal.IncomingGroupMessage
|
||||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage
|
import org.session.libsession.messaging.messages.signal.IncomingTextMessage
|
||||||
import org.session.libsignal.utilities.Hex
|
import org.session.libsignal.utilities.Hex
|
||||||
|
|
||||||
import org.session.libsession.messaging.threads.Address
|
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.EventBus
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||||
import org.thoughtcrime.securesms.audio.AudioSlidePlayer
|
import org.thoughtcrime.securesms.audio.AudioSlidePlayer
|
||||||
@ -152,7 +153,7 @@ class MessageAudioView: FrameLayout, AudioSlidePlayer.Listener {
|
|||||||
downloadProgress.progress = 0
|
downloadProgress.progress = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(showControls && audio.transferState == AttachmentDatabase.TRANSFER_PROGRESS_STARTED) -> {
|
(showControls && audio.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED) -> {
|
||||||
controlToggle.displayQuick(downloadProgress)
|
controlToggle.displayQuick(downloadProgress)
|
||||||
seekBar.isEnabled = false
|
seekBar.isEnabled = false
|
||||||
downloadProgress.isIndeterminate = true
|
downloadProgress.isIndeterminate = true
|
||||||
|
@ -25,6 +25,7 @@ import androidx.annotation.Nullable;
|
|||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
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.messaging.sending_receiving.attachments.UriAttachment;
|
||||||
import org.session.libsession.utilities.MediaTypes;
|
import org.session.libsession.utilities.MediaTypes;
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
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) {
|
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) {
|
public AudioSlide(Context context, Attachment attachment) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.mms;
|
package org.thoughtcrime.securesms.mms;
|
||||||
|
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
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 org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -11,7 +11,7 @@ public class OutgoingExpirationUpdateMessage extends OutgoingSecureMediaMessage
|
|||||||
|
|
||||||
public OutgoingExpirationUpdateMessage(Recipient recipient, long sentTimeMillis, long expiresIn) {
|
public OutgoingExpirationUpdateMessage(Recipient recipient, long sentTimeMillis, long expiresIn) {
|
||||||
super(recipient, "", new LinkedList<Attachment>(), sentTimeMillis,
|
super(recipient, "", new LinkedList<Attachment>(), sentTimeMillis,
|
||||||
ThreadDatabase.DistributionTypes.CONVERSATION, expiresIn, null, Collections.emptyList(),
|
DistributionTypes.CONVERSATION, expiresIn, null, Collections.emptyList(),
|
||||||
Collections.emptyList());
|
Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package org.thoughtcrime.securesms.mms;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
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.attachments.Attachment;
|
||||||
import org.session.libsession.messaging.sending_receiving.sharecontacts.Contact;
|
import org.session.libsession.messaging.sending_receiving.sharecontacts.Contact;
|
||||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||||
@ -32,7 +32,7 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
|
|||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
super(recipient, encodedGroupContext, avatar, sentTimeMillis,
|
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));
|
this.group = GroupContext.parseFrom(Base64.decode(encodedGroupContext));
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
|
|||||||
super(recipient, Base64.encodeBytes(group.toByteArray()),
|
super(recipient, Base64.encodeBytes(group.toByteArray()),
|
||||||
new LinkedList<Attachment>() {{if (avatar != null) add(avatar);}},
|
new LinkedList<Attachment>() {{if (avatar != null) add(avatar);}},
|
||||||
System.currentTimeMillis(),
|
System.currentTimeMillis(),
|
||||||
ThreadDatabase.DistributionTypes.CONVERSATION, expireIn, quote, contacts, previews);
|
DistributionTypes.CONVERSATION, expireIn, quote, contacts, previews);
|
||||||
|
|
||||||
this.group = group;
|
this.group = group;
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
|
|||||||
super(recipient, Base64.encodeBytes(group.toByteArray()),
|
super(recipient, Base64.encodeBytes(group.toByteArray()),
|
||||||
new LinkedList<Attachment>() {{if (avatar != null) add(avatar);}},
|
new LinkedList<Attachment>() {{if (avatar != null) add(avatar);}},
|
||||||
sentTime,
|
sentTime,
|
||||||
ThreadDatabase.DistributionTypes.CONVERSATION, expireIn, quote, contacts, previews);
|
DistributionTypes.CONVERSATION, expireIn, quote, contacts, previews);
|
||||||
|
|
||||||
this.group = group;
|
this.group = group;
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ import androidx.annotation.Nullable;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.session.libsession.messaging.threads.DistributionTypes;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
import org.session.libsession.database.documents.NetworkFailure;
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
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.sharecontacts.Contact;
|
||||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
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.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class OutgoingMediaMessage {
|
public class OutgoingMediaMessage {
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ public class OutgoingMediaMessage {
|
|||||||
@NonNull List<LinkPreview> linkPreviews)
|
@NonNull List<LinkPreview> linkPreviews)
|
||||||
{
|
{
|
||||||
this(recipient,
|
this(recipient,
|
||||||
buildMessage(slideDeck, message),
|
buildMessage(message),
|
||||||
slideDeck.asAttachments(),
|
slideDeck.asAttachments(),
|
||||||
sentTimeMillis, subscriptionId,
|
sentTimeMillis, subscriptionId,
|
||||||
expiresIn, distributionType, outgoingQuote,
|
expiresIn, distributionType, outgoingQuote,
|
||||||
@ -93,11 +94,15 @@ public class OutgoingMediaMessage {
|
|||||||
Recipient recipient,
|
Recipient recipient,
|
||||||
List<Attachment> attachments,
|
List<Attachment> attachments,
|
||||||
@Nullable QuoteModel outgoingQuote,
|
@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,
|
return new OutgoingMediaMessage(recipient, message.getText(), attachments, message.getSentTimestamp(), -1,
|
||||||
recipient.getExpireMessages() * 1000, ThreadDatabase.DistributionTypes.DEFAULT, outgoingQuote, Collections.emptyList(),
|
recipient.getExpireMessages() * 1000, DistributionTypes.DEFAULT, outgoingQuote, Collections.emptyList(),
|
||||||
linkPreviews, Collections.emptyList(), Collections.emptyList());
|
previews, Collections.emptyList(), Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Recipient getRecipient() {
|
public Recipient getRecipient() {
|
||||||
@ -160,7 +165,7 @@ public class OutgoingMediaMessage {
|
|||||||
return identityKeyMismatches;
|
return identityKeyMismatches;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildMessage(SlideDeck slideDeck, String message) {
|
private static String buildMessage(String message) {
|
||||||
if (!TextUtils.isEmpty(message)) {
|
if (!TextUtils.isEmpty(message)) {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import androidx.annotation.DrawableRes;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
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.thoughtcrime.securesms.util.MediaUtil;
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
|
|
||||||
@ -135,8 +135,8 @@ public abstract class Slide {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPendingDownload() {
|
public boolean isPendingDownload() {
|
||||||
return getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_FAILED ||
|
return getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED ||
|
||||||
getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_PENDING;
|
getTransferState() == AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTransferState() {
|
public int getTransferState() {
|
||||||
@ -172,7 +172,7 @@ public abstract class Slide {
|
|||||||
return new UriAttachment(uri,
|
return new UriAttachment(uri,
|
||||||
hasThumbnail ? uri : null,
|
hasThumbnail ? uri : null,
|
||||||
resolvedType,
|
resolvedType,
|
||||||
AttachmentDatabase.TRANSFER_PROGRESS_STARTED,
|
AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED,
|
||||||
size,
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
@ -25,18 +25,19 @@ import android.os.AsyncTask;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.core.app.RemoteInput;
|
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.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.session.libsession.messaging.threads.Address;
|
import org.session.libsession.messaging.threads.Address;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||||
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,17 +73,29 @@ public class AndroidAutoReplyReceiver extends BroadcastReceiver {
|
|||||||
|
|
||||||
long replyThreadId;
|
long replyThreadId;
|
||||||
|
|
||||||
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
|
if (threadId == -1) {
|
||||||
long expiresIn = recipient.getExpireMessages() * 1000L;
|
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()) {
|
if (recipient.isGroupRecipient()) {
|
||||||
Log.w("AndroidAutoReplyReceiver", "GroupRecipient, Sending media message");
|
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());
|
OutgoingMediaMessage reply = OutgoingMediaMessage.from(message, recipient, Collections.emptyList(), null, null);
|
||||||
replyThreadId = MessageSender.send(context, reply, threadId, false, null);
|
try {
|
||||||
|
DatabaseFactory.getMmsDatabase(context).insertMessageOutbox(reply, replyThreadId, false, null);
|
||||||
|
} catch (MmsException e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.w("AndroidAutoReplyReceiver", "Sending regular message ");
|
Log.w("AndroidAutoReplyReceiver", "Sending regular message ");
|
||||||
OutgoingTextMessage reply = new OutgoingTextMessage(recipient, responseText.toString(), expiresIn, subscriptionId);
|
OutgoingTextMessage reply = OutgoingTextMessage.from(message, recipient);
|
||||||
replyThreadId = MessageSender.send(context, reply, threadId, false, null);
|
DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(replyThreadId, reply, false, System.currentTimeMillis(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(replyThreadId, true);
|
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(replyThreadId, true);
|
||||||
|
@ -25,17 +25,18 @@ import android.os.AsyncTask;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.core.app.RemoteInput;
|
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.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.session.libsession.messaging.threads.Address;
|
import org.session.libsession.messaging.threads.Address;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||||
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
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.Collections;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,21 +69,24 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
|
|||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
long threadId;
|
|
||||||
|
|
||||||
Recipient recipient = Recipient.from(context, address, false);
|
Recipient recipient = Recipient.from(context, address, false);
|
||||||
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
|
long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
|
||||||
long expiresIn = recipient.getExpireMessages() * 1000L;
|
VisibleMessage message = new VisibleMessage();
|
||||||
|
message.setText(responseText.toString());
|
||||||
|
|
||||||
switch (replyMethod) {
|
switch (replyMethod) {
|
||||||
case GroupMessage: {
|
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());
|
OutgoingMediaMessage reply = OutgoingMediaMessage.from(message, recipient, Collections.emptyList(), null, null);
|
||||||
threadId = MessageSender.send(context, reply, -1, false, null);
|
try {
|
||||||
|
DatabaseFactory.getMmsDatabase(context).insertMessageOutbox(reply, threadId, false, null);
|
||||||
|
} catch (MmsException e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SecureMessage: {
|
case SecureMessage: {
|
||||||
OutgoingEncryptedMessage reply = new OutgoingEncryptedMessage(recipient, responseText.toString(), expiresIn);
|
OutgoingTextMessage reply = OutgoingTextMessage.from(message, recipient);
|
||||||
threadId = MessageSender.send(context, reply, -1, false, null);
|
DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(threadId, reply, false, System.currentTimeMillis(), null);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -103,17 +103,18 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startAnyExpiration(long messageID) {
|
public void startAnyExpiration(long timestamp, @NotNull String author) {
|
||||||
MessageRecord messageRecord = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(messageID);
|
MessageRecord messageRecord = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(timestamp, author);
|
||||||
if (messageRecord != null) {
|
if (messageRecord != null) {
|
||||||
boolean mms = messageRecord.isMms();
|
boolean mms = messageRecord.isMms();
|
||||||
Recipient recipient = messageRecord.getRecipient();
|
Recipient recipient = messageRecord.getRecipient();
|
||||||
|
if (recipient.getExpireMessages() <= 0) return;
|
||||||
if (mms) {
|
if (mms) {
|
||||||
mmsDatabase.markExpireStarted(messageID);
|
mmsDatabase.markExpireStarted(messageRecord.getId());
|
||||||
} else {
|
} 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 android.widget.Toast;
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||||
import org.session.libsession.messaging.threads.Address;
|
import org.session.libsession.messaging.threads.Address;
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
||||||
import org.thoughtcrime.securesms.util.Rfc5724Uri;
|
import org.thoughtcrime.securesms.util.Rfc5724Uri;
|
||||||
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
@ -47,13 +49,11 @@ public class QuickResponseService extends IntentService {
|
|||||||
number = URLDecoder.decode(number);
|
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)) {
|
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) {
|
} catch (URISyntaxException e) {
|
||||||
Toast.makeText(this, R.string.QuickResponseService_problem_sending_message, Toast.LENGTH_LONG).show();
|
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;
|
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;
|
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.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
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.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
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.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
@ -95,8 +95,8 @@ interface StorageProtocol {
|
|||||||
|
|
||||||
fun getMessageIdInDatabase(timestamp: Long, author: String): Long?
|
fun getMessageIdInDatabase(timestamp: Long, author: String): Long?
|
||||||
fun setOpenGroupServerMessageID(messageID: Long, serverID: Long)
|
fun setOpenGroupServerMessageID(messageID: Long, serverID: Long)
|
||||||
fun markAsSent(messageID: Long)
|
fun markAsSent(timestamp: Long, author: String)
|
||||||
fun markUnidentified(messageID: Long)
|
fun markUnidentified(timestamp: Long, author: String)
|
||||||
fun setErrorMessage(messageID: Long, error: Exception)
|
fun setErrorMessage(messageID: Long, error: Exception)
|
||||||
|
|
||||||
// Closed Groups
|
// Closed Groups
|
||||||
|
@ -28,7 +28,7 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
|
|||||||
// Settings
|
// Settings
|
||||||
override val maxFailureCount: Int = 20
|
override val maxFailureCount: Int = 20
|
||||||
companion object {
|
companion object {
|
||||||
val TAG = AttachmentUploadJob::class.qualifiedName
|
val TAG = AttachmentUploadJob::class.simpleName
|
||||||
val KEY: String = "AttachmentUploadJob"
|
val KEY: String = "AttachmentUploadJob"
|
||||||
|
|
||||||
val maxFailureCount: Int = 20
|
val maxFailureCount: Int = 20
|
||||||
|
@ -15,8 +15,8 @@ class MessageReceiveJob(val data: ByteArray, val isBackgroundPoll: Boolean, val
|
|||||||
// Settings
|
// Settings
|
||||||
override val maxFailureCount: Int = 10
|
override val maxFailureCount: Int = 10
|
||||||
companion object {
|
companion object {
|
||||||
val TAG = MessageReceiveJob::class.qualifiedName
|
val TAG = MessageReceiveJob::class.simpleName
|
||||||
val KEY: String = "AttachmentUploadJob"
|
val KEY: String = "MessageReceiveJob"
|
||||||
|
|
||||||
//keys used for database storage purpose
|
//keys used for database storage purpose
|
||||||
private val KEY_DATA = "data"
|
private val KEY_DATA = "data"
|
||||||
|
@ -19,7 +19,7 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
|
|||||||
// Settings
|
// Settings
|
||||||
override val maxFailureCount: Int = 10
|
override val maxFailureCount: Int = 10
|
||||||
companion object {
|
companion object {
|
||||||
val TAG = MessageSendJob::class.qualifiedName
|
val TAG = MessageSendJob::class.simpleName
|
||||||
val KEY: String = "MessageSendJob"
|
val KEY: String = "MessageSendJob"
|
||||||
|
|
||||||
//keys used for database storage purpose
|
//keys used for database storage purpose
|
||||||
|
@ -18,8 +18,12 @@ abstract class Message {
|
|||||||
|
|
||||||
// validation
|
// validation
|
||||||
open fun isValid(): Boolean {
|
open fun isValid(): Boolean {
|
||||||
sentTimestamp = if (sentTimestamp!! > 0) sentTimestamp else return false
|
sentTimestamp?.let {
|
||||||
receivedTimestamp = if (receivedTimestamp!! > 0) receivedTimestamp else return false
|
if (it <= 0) return false
|
||||||
|
}
|
||||||
|
receivedTimestamp?.let {
|
||||||
|
if (it <= 0) return false
|
||||||
|
}
|
||||||
return sender != null && recipient != null
|
return sender != null && recipient != null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import org.session.libsignal.service.internal.push.SignalServiceProtos
|
|||||||
|
|
||||||
class ExpirationTimerUpdate() : ControlMessage() {
|
class ExpirationTimerUpdate() : ControlMessage() {
|
||||||
|
|
||||||
|
var syncTarget: String? = null
|
||||||
var duration: Int? = 0
|
var duration: Int? = 0
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -12,7 +13,7 @@ class ExpirationTimerUpdate() : ControlMessage() {
|
|||||||
|
|
||||||
fun fromProto(proto: SignalServiceProtos.Content): ExpirationTimerUpdate? {
|
fun fromProto(proto: SignalServiceProtos.Content): ExpirationTimerUpdate? {
|
||||||
val dataMessageProto = proto.dataMessage ?: return null
|
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
|
if (!isExpirationTimerUpdate) return null
|
||||||
val duration = dataMessageProto.expireTimer
|
val duration = dataMessageProto.expireTimer
|
||||||
return ExpirationTimerUpdate(duration)
|
return ExpirationTimerUpdate(duration)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package org.thoughtcrime.securesms.sms;
|
package org.session.libsession.messaging.messages.signal;
|
||||||
|
|
||||||
public class IncomingEncryptedMessage extends IncomingTextMessage {
|
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;
|
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.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import android.telephony.SmsMessage;
|
|
||||||
|
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||||
import org.session.libsession.messaging.threads.Address;
|
import org.session.libsession.messaging.threads.Address;
|
||||||
import org.session.libsession.utilities.GroupUtil;
|
import org.session.libsession.utilities.GroupUtil;
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceGroup;
|
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 {
|
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.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
|
|
||||||
public class OutgoingTextMessage {
|
public class OutgoingTextMessage {
|
||||||
@ -39,14 +38,6 @@ public class OutgoingTextMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSecureMessage() {
|
public boolean isSecureMessage() {
|
||||||
return false;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -32,7 +32,7 @@ class Attachment {
|
|||||||
result.contentType = proto.contentType ?: inferContentType()
|
result.contentType = proto.contentType ?: inferContentType()
|
||||||
result.key = proto.key.toByteArray()
|
result.key = proto.key.toByteArray()
|
||||||
result.digest = proto.digest.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
|
Kind.VOICE_MESSAGE
|
||||||
} else {
|
} else {
|
||||||
Kind.GENERIC
|
Kind.GENERIC
|
||||||
@ -42,7 +42,7 @@ class Attachment {
|
|||||||
val size: Size = if (proto.hasWidth() && proto.width > 0 && proto.hasHeight() && proto.height > 0) {
|
val size: Size = if (proto.hasWidth() && proto.width > 0 && proto.hasHeight() && proto.height > 0) {
|
||||||
Size(proto.width, proto.height)
|
Size(proto.width, proto.height)
|
||||||
} else {
|
} else {
|
||||||
Size(0,0) //TODO check that it's equivalent to swift: CGSize.zero
|
Size(0,0)
|
||||||
}
|
}
|
||||||
result.size = size
|
result.size = size
|
||||||
result.sizeInBytes = if (proto.size > 0) proto.size else null
|
result.sizeInBytes = if (proto.size > 0) proto.size else null
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.session.libsession.messaging.messages.visible
|
package org.session.libsession.messaging.messages.visible
|
||||||
|
|
||||||
import org.session.libsession.messaging.MessagingConfiguration
|
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.utilities.logging.Log
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||||
|
|
||||||
@ -18,6 +19,14 @@ class LinkPreview() {
|
|||||||
val url = proto.url
|
val url = proto.url
|
||||||
return LinkPreview(title, url, null)
|
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
|
//constructor
|
||||||
|
@ -2,6 +2,8 @@ package org.session.libsession.messaging.messages.visible
|
|||||||
|
|
||||||
import com.goterl.lazycode.lazysodium.BuildConfig
|
import com.goterl.lazycode.lazysodium.BuildConfig
|
||||||
import org.session.libsession.messaging.MessagingConfiguration
|
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.utilities.logging.Log
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||||
|
|
||||||
@ -21,6 +23,15 @@ class Quote() {
|
|||||||
val text = proto.text
|
val text = proto.text
|
||||||
return Quote(timestamp, publicKey, text, null)
|
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
|
//constructor
|
||||||
|
@ -4,6 +4,8 @@ import com.goterl.lazycode.lazysodium.BuildConfig
|
|||||||
|
|
||||||
import org.session.libsession.messaging.MessagingConfiguration
|
import org.session.libsession.messaging.MessagingConfiguration
|
||||||
import org.session.libsession.messaging.messages.Message
|
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.utilities.logging.Log
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
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 {
|
fun isMediaMessage(): Boolean {
|
||||||
return attachmentIDs.isNotEmpty() || quote != null || linkPreview != null || contact != null
|
return attachmentIDs.isNotEmpty() || quote != null || linkPreview != null || contact != null
|
||||||
}
|
}
|
||||||
|
@ -5,27 +5,31 @@ import nl.komponents.kovenant.Promise
|
|||||||
import nl.komponents.kovenant.deferred
|
import nl.komponents.kovenant.deferred
|
||||||
import org.session.libsession.messaging.MessagingConfiguration
|
import org.session.libsession.messaging.MessagingConfiguration
|
||||||
import org.session.libsession.messaging.jobs.JobQueue
|
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.jobs.NotifyPNServerJob
|
||||||
import org.session.libsession.messaging.messages.Destination
|
import org.session.libsession.messaging.messages.Destination
|
||||||
import org.session.libsession.messaging.messages.Message
|
import org.session.libsession.messaging.messages.Message
|
||||||
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage
|
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage
|
||||||
import org.session.libsession.messaging.messages.control.ConfigurationMessage
|
import org.session.libsession.messaging.messages.control.ConfigurationMessage
|
||||||
import org.session.libsession.messaging.messages.visible.Attachment
|
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
|
||||||
import org.session.libsession.messaging.messages.visible.Profile
|
import org.session.libsession.messaging.messages.visible.*
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
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.OpenGroupAPI
|
||||||
import org.session.libsession.messaging.opengroups.OpenGroupMessage
|
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.messaging.utilities.MessageWrapper
|
||||||
import org.session.libsession.snode.RawResponsePromise
|
import org.session.libsession.snode.RawResponsePromise
|
||||||
import org.session.libsession.snode.SnodeAPI
|
import org.session.libsession.snode.SnodeAPI
|
||||||
|
import org.session.libsession.snode.SnodeConfiguration
|
||||||
import org.session.libsession.snode.SnodeMessage
|
import org.session.libsession.snode.SnodeMessage
|
||||||
import org.session.libsession.utilities.SSKEnvironment
|
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.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.api.crypto.ProofOfWork
|
||||||
import org.session.libsignal.service.loki.utilities.hexEncodedPublicKey
|
import org.session.libsignal.service.loki.utilities.hexEncodedPublicKey
|
||||||
|
import org.session.libsignal.utilities.Base64
|
||||||
|
import org.session.libsignal.utilities.logging.Log
|
||||||
|
|
||||||
|
|
||||||
object MessageSender {
|
object MessageSender {
|
||||||
@ -56,25 +60,22 @@ object MessageSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Preparation
|
// Preparation
|
||||||
fun prep(signalAttachments: List<SignalServiceAttachment>, message: VisibleMessage) {
|
fun prep(signalAttachments: List<SignalAttachment>, message: VisibleMessage) {
|
||||||
// TODO: Deal with SignalServiceAttachmentStream
|
|
||||||
val attachments = mutableListOf<Attachment>()
|
val attachments = mutableListOf<Attachment>()
|
||||||
for (signalAttachment in signalAttachments) {
|
for (signalAttachment in signalAttachments) {
|
||||||
val attachment = Attachment()
|
val attachment = Attachment()
|
||||||
if (signalAttachment.isPointer) {
|
attachment.fileName = signalAttachment.fileName
|
||||||
val signalAttachmentPointer = signalAttachment.asPointer()
|
attachment.caption = signalAttachment.caption
|
||||||
attachment.fileName = signalAttachmentPointer.fileName.orNull()
|
attachment.contentType = signalAttachment.contentType
|
||||||
attachment.caption = signalAttachmentPointer.caption.orNull()
|
attachment.digest = signalAttachment.digest
|
||||||
attachment.contentType = signalAttachmentPointer.contentType
|
attachment.key = Base64.decode(signalAttachment.key)
|
||||||
attachment.digest = signalAttachmentPointer.digest.orNull()
|
attachment.sizeInBytes = signalAttachment.size.toInt()
|
||||||
attachment.key = signalAttachmentPointer.key
|
attachment.url = signalAttachment.url
|
||||||
attachment.sizeInBytes = signalAttachmentPointer.size.orNull()
|
attachment.size = Size(signalAttachment.width, signalAttachment.height)
|
||||||
attachment.url = signalAttachmentPointer.url
|
|
||||||
attachment.size = Size(signalAttachmentPointer.width, signalAttachmentPointer.height)
|
|
||||||
attachments.add(attachment)
|
attachments.add(attachment)
|
||||||
}
|
}
|
||||||
}
|
val attachmentIDs = MessagingConfiguration.shared.storage.persistAttachments(message.id
|
||||||
val attachmentIDs = MessagingConfiguration.shared.storage.persistAttachments(message.id ?: 0, attachments)
|
?: 0, attachments)
|
||||||
message.attachmentIDs.addAll(attachmentIDs)
|
message.attachmentIDs.addAll(attachmentIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +171,7 @@ object MessageSender {
|
|||||||
val wrappedMessage = MessageWrapper.wrap(kind, message.sentTimestamp!!, senderPublicKey, ciphertext)
|
val wrappedMessage = MessageWrapper.wrap(kind, message.sentTimestamp!!, senderPublicKey, ciphertext)
|
||||||
// Calculate proof of work
|
// Calculate proof of work
|
||||||
if (destination is Destination.Contact && message is VisibleMessage && !isSelfSend) {
|
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 recipient = message.recipient!!
|
||||||
val base64EncodedData = Base64.encodeBytes(wrappedMessage)
|
val base64EncodedData = Base64.encodeBytes(wrappedMessage)
|
||||||
@ -178,6 +179,9 @@ object MessageSender {
|
|||||||
val nonce = ProofOfWork.calculate(base64EncodedData, recipient, timestamp, message.ttl.toInt()) ?: throw Error.ProofOfWorkCalculationFailed
|
val nonce = ProofOfWork.calculate(base64EncodedData, recipient, timestamp, message.ttl.toInt()) ?: throw Error.ProofOfWorkCalculationFailed
|
||||||
// Send the result
|
// Send the result
|
||||||
snodeMessage = SnodeMessage(recipient, base64EncodedData, message.ttl, timestamp, nonce)
|
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> ->
|
SnodeAPI.sendMessage(snodeMessage).success { promises: Set<RawResponsePromise> ->
|
||||||
var isSuccess = false
|
var isSuccess = false
|
||||||
val promiseCount = promises.size
|
val promiseCount = promises.size
|
||||||
@ -187,7 +191,7 @@ object MessageSender {
|
|||||||
if (isSuccess) { return@success } // Succeed as soon as the first promise succeeds
|
if (isSuccess) { return@success } // Succeed as soon as the first promise succeeds
|
||||||
isSuccess = true
|
isSuccess = true
|
||||||
if (destination is Destination.Contact && message is VisibleMessage && !isSelfSend) {
|
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)
|
handleSuccessfulMessageSend(message, destination, isSyncMessage)
|
||||||
var shouldNotify = (message is VisibleMessage && !isSyncMessage)
|
var shouldNotify = (message is VisibleMessage && !isSyncMessage)
|
||||||
@ -199,7 +203,6 @@ object MessageSender {
|
|||||||
JobQueue.shared.add(notifyPNServerJob)
|
JobQueue.shared.add(notifyPNServerJob)
|
||||||
deferred.resolve(Unit)
|
deferred.resolve(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
promise.fail {
|
promise.fail {
|
||||||
errorCount += 1
|
errorCount += 1
|
||||||
@ -277,17 +280,19 @@ object MessageSender {
|
|||||||
storage.setOpenGroupServerMessageID(messageId, message.openGroupServerMessageID!!)
|
storage.setOpenGroupServerMessageID(messageId, message.openGroupServerMessageID!!)
|
||||||
}
|
}
|
||||||
// Mark the message as sent
|
// Mark the message as sent
|
||||||
storage.markAsSent(messageId)
|
storage.markAsSent(message.sentTimestamp!!, message.sender!!)
|
||||||
storage.markUnidentified(messageId)
|
storage.markUnidentified(message.sentTimestamp!!, message.sender!!)
|
||||||
// Start the disappearing messages timer if needed
|
// Start the disappearing messages timer if needed
|
||||||
SSKEnvironment.shared.messageExpirationManager.startAnyExpiration(messageId)
|
SSKEnvironment.shared.messageExpirationManager.startAnyExpiration(message.sentTimestamp!!, message.sender!!)
|
||||||
// Sync the message if:
|
// Sync the message if:
|
||||||
// • it's a visible message
|
// • it's a visible message
|
||||||
// • the destination was a contact
|
// • the destination was a contact
|
||||||
// • we didn't sync it already
|
// • we didn't sync it already
|
||||||
val userPublicKey = storage.getUserPublicKey()!!
|
val userPublicKey = storage.getUserPublicKey()!!
|
||||||
if (destination is Destination.Contact && !isSyncMessage && message is VisibleMessage) {
|
if (destination is Destination.Contact && !isSyncMessage) {
|
||||||
sendToSnodeDestination(Destination.Contact(userPublicKey), message, true).get()
|
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 storage = MessagingConfiguration.shared.storage
|
||||||
val messageId = storage.getMessageIdInDatabase(message.sentTimestamp!!, message.sender!!) ?: return
|
val messageId = storage.getMessageIdInDatabase(message.sentTimestamp!!, message.sender!!) ?: return
|
||||||
storage.setErrorMessage(messageId, error)
|
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 {
|
public class AttachmentId implements Parcelable {
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private final long rowId;
|
private final long rowId; // This is the field id in the database
|
||||||
|
|
||||||
@JsonProperty
|
@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) {
|
public AttachmentId(@JsonProperty("rowId") long rowId, @JsonProperty("uniqueId") long uniqueId) {
|
||||||
this.rowId = rowId;
|
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.JobQueue
|
||||||
import org.session.libsession.messaging.jobs.MessageReceiveJob
|
import org.session.libsession.messaging.jobs.MessageReceiveJob
|
||||||
import org.session.libsession.messaging.utilities.MessageWrapper
|
import org.session.libsession.messaging.utilities.MessageWrapper
|
||||||
import org.session.libsession.snode.Snode
|
|
||||||
import org.session.libsession.snode.SnodeAPI
|
import org.session.libsession.snode.SnodeAPI
|
||||||
import org.session.libsession.snode.SnodeConfiguration
|
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.logging.Log
|
||||||
import org.session.libsignal.utilities.Base64
|
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.logging.Log
|
||||||
import org.session.libsignal.utilities.Base64
|
import org.session.libsignal.utilities.Base64
|
||||||
import org.session.libsignal.utilities.*
|
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.fileserver.FileServerAPI
|
||||||
import org.session.libsignal.service.loki.api.utilities.*
|
import org.session.libsignal.service.loki.api.utilities.*
|
||||||
import org.session.libsession.utilities.AESGCM.EncryptionResult
|
import org.session.libsession.utilities.AESGCM.EncryptionResult
|
||||||
@ -74,7 +74,7 @@ object OnionRequestAPI {
|
|||||||
)
|
)
|
||||||
|
|
||||||
internal sealed class Destination {
|
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()
|
class Server(val host: String, val target: String, val x25519PublicKey: String) : Destination()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.session.libsession.snode
|
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://")
|
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.utilities.logging.Log
|
||||||
import org.session.libsignal.service.loki.api.utilities.HTTP
|
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.prettifiedDescription
|
||||||
import org.session.libsignal.service.loki.utilities.retryIfNeeded
|
import org.session.libsignal.service.loki.utilities.retryIfNeeded
|
||||||
import org.session.libsignal.utilities.*
|
import org.session.libsignal.utilities.*
|
||||||
@ -17,10 +20,11 @@ import org.session.libsignal.utilities.*
|
|||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
|
|
||||||
object SnodeAPI {
|
object SnodeAPI {
|
||||||
val database = SnodeConfiguration.shared.storage
|
val database: LokiAPIDatabaseProtocol
|
||||||
val broadcaster = SnodeConfiguration.shared.broadcaster
|
get() = SnodeConfiguration.shared.storage
|
||||||
|
val broadcaster: Broadcaster
|
||||||
|
get() = SnodeConfiguration.shared.broadcaster
|
||||||
val sharedContext = Kovenant.createContext()
|
val sharedContext = Kovenant.createContext()
|
||||||
val messageSendingContext = Kovenant.createContext()
|
|
||||||
val messagePollingContext = Kovenant.createContext()
|
val messagePollingContext = Kovenant.createContext()
|
||||||
|
|
||||||
internal var snodeFailureCount: MutableMap<Snode, Int> = mutableMapOf()
|
internal var snodeFailureCount: MutableMap<Snode, Int> = mutableMapOf()
|
||||||
@ -158,7 +162,7 @@ object SnodeAPI {
|
|||||||
val parameters = mapOf( "pubKey" to publicKey )
|
val parameters = mapOf( "pubKey" to publicKey )
|
||||||
return getRandomSnode().bind {
|
return getRandomSnode().bind {
|
||||||
invoke(Snode.Method.GetSwarm, it, publicKey, parameters)
|
invoke(Snode.Method.GetSwarm, it, publicKey, parameters)
|
||||||
}.map(SnodeAPI.sharedContext) {
|
}.map(sharedContext) {
|
||||||
parseSnodes(it).toSet()
|
parseSnodes(it).toSet()
|
||||||
}.success {
|
}.success {
|
||||||
database.setSwarm(publicKey, it)
|
database.setSwarm(publicKey, it)
|
||||||
@ -182,19 +186,12 @@ object SnodeAPI {
|
|||||||
|
|
||||||
fun sendMessage(message: SnodeMessage): Promise<Set<RawResponsePromise>, Exception> {
|
fun sendMessage(message: SnodeMessage): Promise<Set<RawResponsePromise>, Exception> {
|
||||||
val destination = message.recipient
|
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) {
|
return retryIfNeeded(maxRetryCount) {
|
||||||
getTargetSnodes(destination).map(messageSendingContext) { swarm ->
|
getTargetSnodes(destination).map { swarm ->
|
||||||
swarm.map { snode ->
|
swarm.map { snode ->
|
||||||
broadcast("sendingMessage")
|
|
||||||
val parameters = message.toJSON()
|
val parameters = message.toJSON()
|
||||||
retryIfNeeded(maxRetryCount) {
|
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 json = rawResponse as? Map<*, *>
|
||||||
val powDifficulty = json?.get("difficulty") as? Int
|
val powDifficulty = json?.get("difficulty") as? Int
|
||||||
if (powDifficulty != null) {
|
if (powDifficulty != null) {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package org.session.libsession.snode
|
package org.session.libsession.snode
|
||||||
|
|
||||||
|
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
|
||||||
import org.session.libsignal.service.loki.utilities.Broadcaster
|
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 {
|
companion object {
|
||||||
lateinit var shared: SnodeConfiguration
|
lateinit var shared: SnodeConfiguration
|
||||||
|
|
||||||
fun configure(storage: SnodeStorageProtocol, broadcaster: Broadcaster) {
|
fun configure(storage: LokiAPIDatabaseProtocol, broadcaster: Broadcaster) {
|
||||||
if (Companion::shared.isInitialized) { return }
|
if (Companion::shared.isInitialized) { return }
|
||||||
shared = SnodeConfiguration(storage, broadcaster)
|
shared = SnodeConfiguration(storage, broadcaster)
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ class SSKEnvironment(
|
|||||||
interface MessageExpirationManagerProtocol {
|
interface MessageExpirationManagerProtocol {
|
||||||
fun setExpirationTimer(messageID: Long?, duration: Int, senderPublicKey: String, content: SignalServiceProtos.Content)
|
fun setExpirationTimer(messageID: Long?, duration: Int, senderPublicKey: String, content: SignalServiceProtos.Content)
|
||||||
fun disableExpirationTimer(messageID: Long?, 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 {
|
companion object {
|
||||||
|
@ -26,14 +26,6 @@ public class SendMessageResult {
|
|||||||
return new SendMessageResult(address, null, true, false, null, null);
|
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() {
|
public SignalServiceAddress getAddress() {
|
||||||
return address;
|
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://")
|
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.
|
* Only supported by snode targets.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user