mirror of
https://github.com/oxen-io/session-android.git
synced 2025-08-12 07:07:42 +00:00
Merge remote-tracking branch 'upstream/dev' into fix_profile_nulls
# Conflicts: # app/src/main/java/org/thoughtcrime/securesms/loki/api/BackgroundPollWorker.kt # app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt # libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt
This commit is contained in:
@@ -30,15 +30,17 @@ import androidx.lifecycle.ProcessLifecycleOwner;
|
||||
import androidx.multidex.MultiDexApplication;
|
||||
|
||||
import org.conscrypt.Conscrypt;
|
||||
import org.session.libsession.messaging.MessagingConfiguration;
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration;
|
||||
import org.session.libsession.messaging.avatars.AvatarHelper;
|
||||
import org.session.libsession.messaging.file_server.FileServerAPI;
|
||||
import org.session.libsession.messaging.jobs.JobQueue;
|
||||
import org.session.libsession.messaging.opengroups.OpenGroupAPI;
|
||||
import org.session.libsession.messaging.mentions.MentionsManager;
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI;
|
||||
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPoller;
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
|
||||
import org.session.libsession.messaging.threads.Address;
|
||||
import org.session.libsession.snode.SnodeConfiguration;
|
||||
import org.session.libsession.snode.SnodeModule;
|
||||
import org.session.libsession.utilities.IdentityKeyUtil;
|
||||
import org.session.libsession.utilities.SSKEnvironment;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
@@ -47,12 +49,7 @@ import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWr
|
||||
import org.session.libsession.utilities.dynamiclanguage.LocaleParser;
|
||||
import org.session.libsession.utilities.preferences.ProfileKeyUtil;
|
||||
import org.session.libsignal.service.api.util.StreamDetails;
|
||||
import org.session.libsignal.service.loki.api.PushNotificationAPI;
|
||||
import org.session.libsignal.service.loki.api.SnodeAPI;
|
||||
import org.session.libsignal.service.loki.api.SwarmAPI;
|
||||
import org.session.libsignal.service.loki.api.fileserver.FileServerAPI;
|
||||
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol;
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager;
|
||||
import org.session.libsignal.utilities.logging.Log;
|
||||
import org.signal.aesgcmprovider.AesGcmProvider;
|
||||
import org.thoughtcrime.securesms.components.TypingStatusSender;
|
||||
@@ -96,6 +93,7 @@ import org.webrtc.voiceengine.WebRtcAudioUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Security;
|
||||
import java.util.Date;
|
||||
@@ -173,17 +171,14 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(this);
|
||||
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
MessagingConfiguration.Companion.configure(this,
|
||||
MessagingModuleConfiguration.Companion.configure(this,
|
||||
DatabaseFactory.getStorage(this),
|
||||
DatabaseFactory.getAttachmentProvider(this),
|
||||
new SessionProtocolImpl(this));
|
||||
SnodeConfiguration.Companion.configure(apiDB, broadcaster);
|
||||
SnodeModule.Companion.configure(apiDB, broadcaster);
|
||||
if (userPublicKey != null) {
|
||||
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
||||
MentionsManager.Companion.configureIfNeeded(userPublicKey, userDB);
|
||||
}
|
||||
PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG);
|
||||
setUpStorageAPIIfNeeded();
|
||||
resubmitProfilePictureIfNeeded();
|
||||
publicChatManager = new PublicChatManager(this);
|
||||
@@ -428,7 +423,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
||||
LokiAPIDatabaseProtocol apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
FileServerAPI.Companion.configure(userPublicKey, userPrivateKey, apiDB);
|
||||
org.session.libsession.messaging.fileserver.FileServerAPI.Companion.configure(userPublicKey, userPrivateKey, apiDB);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -458,13 +452,10 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userPublicKey == null) return;
|
||||
if (poller != null) {
|
||||
SnodeAPI.shared.setUserPublicKey(userPublicKey);
|
||||
poller.setUserPublicKey(userPublicKey);
|
||||
return;
|
||||
}
|
||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||
poller = new Poller();
|
||||
closedGroupPoller = new ClosedGroupPoller();
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview;
|
||||
import org.session.libsession.messaging.threads.Address;
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||
|
||||
|
@@ -40,6 +40,7 @@ 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.open_groups.OpenGroup;
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.MessageDetailsRecipientAdapter.RecipientDeliveryStatus;
|
||||
@@ -64,7 +65,6 @@ import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.session.libsession.utilities.ExpirationUtil;
|
||||
import org.session.libsession.utilities.Util;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.sql.Date;
|
||||
@@ -263,7 +263,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
toFrom.setText(toFromRes);
|
||||
long threadID = messageRecord.getThreadId();
|
||||
PublicChat openGroup = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadID);
|
||||
OpenGroup openGroup = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadID);
|
||||
if (openGroup != null && messageRecord.isOutgoing()) {
|
||||
toFrom.setVisibility(View.GONE);
|
||||
separator.setVisibility(View.GONE);
|
||||
|
@@ -5,6 +5,7 @@ import android.text.TextUtils
|
||||
import com.google.protobuf.ByteString
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.session.libsession.database.MessageDataProvider
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.*
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
import org.session.libsession.messaging.utilities.DotNetAPI
|
||||
@@ -26,7 +27,6 @@ import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
||||
|
||||
class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), MessageDataProvider {
|
||||
|
||||
override fun getAttachmentStream(attachmentId: Long): SessionServiceAttachmentStream? {
|
||||
@@ -104,6 +104,10 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
|
||||
return smsDatabase.isOutgoingMessage(timestamp) || mmsDatabase.isOutgoingMessage(timestamp)
|
||||
}
|
||||
|
||||
override fun getOpenGroup(threadID: Long): OpenGroup? {
|
||||
return null // TODO: Implement
|
||||
}
|
||||
|
||||
override fun updateAttachmentAfterUploadSucceeded(attachmentId: Long, attachmentStream: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: DotNetAPI.UploadResult) {
|
||||
val database = DatabaseFactory.getAttachmentDatabase(context)
|
||||
val databaseAttachment = getDatabaseAttachment(attachmentId) ?: return
|
||||
|
@@ -30,7 +30,7 @@ import org.thoughtcrime.securesms.loki.utilities.MentionUtilities;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview;
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel;
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
|
@@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.ImageSlide;
|
||||
import org.thoughtcrime.securesms.mms.SlidesClickedListener;
|
||||
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
import okhttp3.HttpUrl;
|
||||
|
@@ -21,6 +21,7 @@ import androidx.annotation.RequiresApi;
|
||||
import com.annimon.stream.Stream;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup;
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
@@ -35,7 +36,6 @@ import org.session.libsession.messaging.threads.recipients.RecipientModifiedList
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
import org.session.libsession.utilities.ThemeUtil;
|
||||
import org.session.libsession.utilities.Util;
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -201,7 +201,7 @@ public class QuoteView extends FrameLayout implements RecipientModifiedListener
|
||||
|
||||
long threadID = DatabaseFactory.getThreadDatabase(getContext()).getOrCreateThreadIdFor(conversationRecipient);
|
||||
String senderHexEncodedPublicKey = author.getAddress().serialize();
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadID);
|
||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadID);
|
||||
if (senderHexEncodedPublicKey.equalsIgnoreCase(TextSecurePreferences.getLocalNumber(getContext()))) {
|
||||
quoteeDisplayName = TextSecurePreferences.getProfileName(getContext());
|
||||
} else if (publicChat != null) {
|
||||
|
@@ -85,17 +85,17 @@ import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
|
||||
import org.session.libsession.messaging.mentions.MentionsManager;
|
||||
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate;
|
||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup;
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
||||
import org.session.libsession.messaging.threads.DistributionTypes;
|
||||
import org.session.libsession.utilities.GroupUtil;
|
||||
import org.session.libsession.utilities.MediaTypes;
|
||||
import org.session.libsignal.libsignal.InvalidMessageException;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
|
||||
import org.session.libsignal.service.loki.utilities.mentions.Mention;
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager;
|
||||
import org.session.libsignal.service.loki.utilities.HexEncodingKt;
|
||||
import org.session.libsignal.service.loki.utilities.PublicKeyValidation;
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
@@ -183,7 +183,7 @@ import org.session.libsession.utilities.ServiceUtil;
|
||||
import org.session.libsession.utilities.Util;
|
||||
|
||||
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.link_preview.LinkPreview;
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel;
|
||||
import org.session.libsession.messaging.threads.GroupRecord;
|
||||
import org.session.libsession.utilities.ExpirationUtil;
|
||||
@@ -376,7 +376,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
MentionManagerUtilities.INSTANCE.populateUserPublicKeyCacheIfNeeded(threadId, this);
|
||||
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||
if (publicChat != null) {
|
||||
// Request open group info update and handle the successful result in #onOpenGroupInfoUpdated().
|
||||
PublicChatInfoUpdateWorker.scheduleInstant(this, publicChat.getServer(), publicChat.getChannel());
|
||||
@@ -1399,7 +1399,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onOpenGroupInfoUpdated(OpenGroupUtilities.GroupInfoUpdatedEvent event) {
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||
if (publicChat != null &&
|
||||
publicChat.getChannel() == event.getChannel() &&
|
||||
publicChat.getServer().equals(event.getUrl())) {
|
||||
@@ -2337,7 +2337,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
muteIndicatorImageView.setVisibility(View.VISIBLE);
|
||||
subtitleTextView.setText("Muted until " + DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault()));
|
||||
} else if (recipient.isGroupRecipient() && recipient.getName() != null && !recipient.getName().equals("Session Updates") && !recipient.getName().equals("Loki News")) {
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||
if (publicChat != null) {
|
||||
Integer userCount = DatabaseFactory.getLokiAPIDatabase(this).getUserCount(publicChat.getChannel(), publicChat.getServer());
|
||||
if (userCount == null) { userCount = 0; }
|
||||
|
@@ -60,7 +60,8 @@ import com.annimon.stream.Stream;
|
||||
import org.session.libsession.messaging.messages.control.DataExtractionNotification;
|
||||
import org.session.libsession.messaging.messages.visible.Quote;
|
||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||
import org.session.libsession.messaging.opengroups.OpenGroupAPI;
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup;
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI;
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.MessageDetailsActivity;
|
||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
|
||||
@@ -88,13 +89,12 @@ import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview;
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions;
|
||||
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
|
||||
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
|
||||
import org.session.libsession.utilities.task.ProgressDialogAsyncTask;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
|
||||
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
import org.session.libsession.utilities.Util;
|
||||
@@ -396,7 +396,7 @@ public class ConversationFragment extends Fragment
|
||||
boolean isGroupChat = recipient.isGroupRecipient();
|
||||
|
||||
if (isGroupChat) {
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||
boolean isPublicChat = (publicChat != null);
|
||||
int selectedMessageCount = messageRecords.size();
|
||||
boolean areAllSentByUser = true;
|
||||
@@ -508,7 +508,7 @@ public class ConversationFragment extends Fragment
|
||||
builder.setMessage(getActivity().getResources().getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messagesCount, messagesCount));
|
||||
builder.setCancelable(true);
|
||||
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||
|
||||
builder.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
@@ -591,7 +591,7 @@ public class ConversationFragment extends Fragment
|
||||
builder.setTitle(R.string.ConversationFragment_ban_selected_user);
|
||||
builder.setCancelable(true);
|
||||
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||
|
||||
builder.setPositiveButton(R.string.ban, (dialog, which) -> {
|
||||
ConversationAdapter chatAdapter = getListAdapter();
|
||||
|
@@ -54,10 +54,11 @@ import com.annimon.stream.Stream;
|
||||
|
||||
import org.session.libsession.messaging.jobs.AttachmentDownloadJob;
|
||||
import org.session.libsession.messaging.jobs.JobQueue;
|
||||
import org.session.libsession.messaging.opengroups.OpenGroupAPI;
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup;
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI;
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment;
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview;
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||
import org.session.libsession.messaging.threads.recipients.RecipientModifiedListener;
|
||||
import org.session.libsession.utilities.GroupUtil;
|
||||
@@ -67,7 +68,6 @@ import org.session.libsession.utilities.Util;
|
||||
import org.session.libsession.utilities.ViewUtil;
|
||||
import org.session.libsession.utilities.views.Stub;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
|
||||
import org.session.libsignal.utilities.logging.Log;
|
||||
import org.thoughtcrime.securesms.BindableConversationItem;
|
||||
import org.thoughtcrime.securesms.MediaPreviewActivity;
|
||||
@@ -724,7 +724,7 @@ public class ConversationItem extends LinearLayout
|
||||
String publicKey = recipient.getAddress().toString();
|
||||
profilePictureView.setPublicKey(publicKey);
|
||||
String displayName = recipient.getName();
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID);
|
||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID);
|
||||
if (displayName == null && publicChat != null) {
|
||||
displayName = DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(publicChat.getId(), publicKey);
|
||||
}
|
||||
@@ -911,7 +911,7 @@ public class ConversationItem extends LinearLayout
|
||||
profilePictureView.setVisibility(VISIBLE);
|
||||
int visibility = View.GONE;
|
||||
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(messageRecord.getThreadId());
|
||||
OpenGroup publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(messageRecord.getThreadId());
|
||||
if (publicChat != null) {
|
||||
boolean isModerator = OpenGroupAPI.isUserModerator(current.getRecipient().getAddress().toString(), publicChat.getChannel(), publicChat.getServer());
|
||||
visibility = isModerator ? View.VISIBLE : View.GONE;
|
||||
|
@@ -14,7 +14,7 @@ import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage;
|
||||
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage;
|
||||
import org.thoughtcrime.securesms.BindableConversationItem;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.loki.utilities.GeneralUtilitiesKt;
|
||||
|
@@ -28,7 +28,6 @@ import org.session.libsignal.service.api.messages.SignalServiceAttachmentPointer
|
||||
import org.session.libsignal.service.loki.database.LokiOpenGroupDatabaseProtocol;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
@@ -44,6 +43,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
||||
static final String GROUP_ID = "group_id";
|
||||
private static final String TITLE = "title";
|
||||
private static final String MEMBERS = "members";
|
||||
private static final String ZOMBIE_MEMBERS = "zombie_members";
|
||||
private static final String AVATAR = "avatar";
|
||||
private static final String AVATAR_ID = "avatar_id";
|
||||
private static final String AVATAR_KEY = "avatar_key";
|
||||
@@ -64,6 +64,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
||||
GROUP_ID + " TEXT, " +
|
||||
TITLE + " TEXT, " +
|
||||
MEMBERS + " TEXT, " +
|
||||
ZOMBIE_MEMBERS + " TEXT, " +
|
||||
AVATAR + " BLOB, " +
|
||||
AVATAR_ID + " INTEGER, " +
|
||||
AVATAR_KEY + " BLOB, " +
|
||||
@@ -81,7 +82,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
||||
};
|
||||
|
||||
private static final String[] GROUP_PROJECTION = {
|
||||
GROUP_ID, TITLE, MEMBERS, AVATAR, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST,
|
||||
GROUP_ID, TITLE, MEMBERS, ZOMBIE_MEMBERS, AVATAR, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST,
|
||||
TIMESTAMP, ACTIVE, MMS, AVATAR_URL, ADMINS
|
||||
};
|
||||
|
||||
@@ -162,7 +163,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
||||
}
|
||||
|
||||
public @NonNull List<Recipient> getGroupMembers(String groupId, boolean includeSelf) {
|
||||
List<Address> members = getCurrentMembers(groupId);
|
||||
List<Address> members = getCurrentMembers(groupId, false);
|
||||
List<Recipient> recipients = new LinkedList<>();
|
||||
|
||||
for (Address member : members) {
|
||||
@@ -177,6 +178,17 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
||||
return recipients;
|
||||
}
|
||||
|
||||
public @NonNull List<Recipient> getGroupZombieMembers(String groupId) {
|
||||
List<Address> members = getCurrentZombieMembers(groupId);
|
||||
List<Recipient> recipients = new LinkedList<>();
|
||||
|
||||
for (Address member : members) {
|
||||
recipients.add(Recipient.from(context, member, false));
|
||||
}
|
||||
|
||||
return recipients;
|
||||
}
|
||||
|
||||
public long create(@NonNull String groupId, @Nullable String title, @NonNull List<Address> members,
|
||||
@Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay, @Nullable List<Address> admins, @NonNull Long formationTimestamp)
|
||||
{
|
||||
@@ -300,6 +312,16 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
||||
});
|
||||
}
|
||||
|
||||
public void updateZombieMembers(String groupId, List<Address> members) {
|
||||
Collections.sort(members);
|
||||
|
||||
ContentValues contents = new ContentValues();
|
||||
contents.put(ZOMBIE_MEMBERS, Address.toSerializedList(members, ','));
|
||||
contents.put(ACTIVE, 1);
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
||||
new String[] {groupId});
|
||||
}
|
||||
|
||||
public void updateAdmins(String groupId, List<Address> admins) {
|
||||
Collections.sort(admins);
|
||||
|
||||
@@ -311,7 +333,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
||||
}
|
||||
|
||||
public void removeMember(String groupId, Address source) {
|
||||
List<Address> currentMembers = getCurrentMembers(groupId);
|
||||
List<Address> currentMembers = getCurrentMembers(groupId, false);
|
||||
currentMembers.remove(source);
|
||||
|
||||
ContentValues contents = new ContentValues();
|
||||
@@ -329,18 +351,22 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
||||
});
|
||||
}
|
||||
|
||||
private List<Address> getCurrentMembers(String groupId) {
|
||||
private List<Address> getCurrentMembers(String groupId, boolean zombieMembers) {
|
||||
Cursor cursor = null;
|
||||
|
||||
String membersColumn = MEMBERS;
|
||||
if (zombieMembers) membersColumn = ZOMBIE_MEMBERS;
|
||||
|
||||
try {
|
||||
cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {MEMBERS},
|
||||
cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {membersColumn},
|
||||
GROUP_ID + " = ?",
|
||||
new String[] {groupId},
|
||||
null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
String serializedMembers = cursor.getString(cursor.getColumnIndexOrThrow(MEMBERS));
|
||||
return Address.fromSerializedList(serializedMembers, ',');
|
||||
String serializedMembers = cursor.getString(cursor.getColumnIndexOrThrow(membersColumn));
|
||||
if (serializedMembers != null && !serializedMembers.isEmpty())
|
||||
return Address.fromSerializedList(serializedMembers, ',');
|
||||
}
|
||||
|
||||
return new LinkedList<>();
|
||||
@@ -350,6 +376,10 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
||||
}
|
||||
}
|
||||
|
||||
private List<Address> getCurrentZombieMembers(String groupId) {
|
||||
return getCurrentMembers(groupId, true);
|
||||
}
|
||||
|
||||
public boolean isActive(String groupId) {
|
||||
Optional<GroupRecord> record = getGroup(groupId);
|
||||
return record.isPresent() && record.get().isActive();
|
||||
|
@@ -28,7 +28,6 @@ import com.annimon.stream.Collectors;
|
||||
import com.annimon.stream.Stream;
|
||||
import com.google.android.mms.pdu_alt.NotificationInd;
|
||||
import com.google.android.mms.pdu_alt.PduHeaders;
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import net.sqlcipher.database.SQLiteDatabase;
|
||||
|
||||
@@ -60,7 +59,7 @@ import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId;
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment;
|
||||
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.link_preview.LinkPreview;
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel;
|
||||
import org.session.libsession.messaging.threads.Address;
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||
|
@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.database
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.google.protobuf.ByteString
|
||||
import org.session.libsession.messaging.StorageProtocol
|
||||
import org.session.libsession.messaging.jobs.AttachmentUploadJob
|
||||
import org.session.libsession.messaging.jobs.Job
|
||||
@@ -13,18 +12,17 @@ import org.session.libsession.messaging.messages.signal.*
|
||||
import org.session.libsession.messaging.messages.signal.IncomingTextMessage
|
||||
import org.session.libsession.messaging.messages.visible.Attachment
|
||||
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
||||
import org.session.libsession.messaging.opengroups.OpenGroup
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||
import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview
|
||||
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
import org.session.libsession.messaging.threads.Address.Companion.fromSerialized
|
||||
import org.session.libsession.messaging.threads.GroupRecord
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageBuilder
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageData
|
||||
import org.session.libsession.messaging.utilities.ClosedGroupUpdateMessageData
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsession.utilities.IdentityKeyUtil
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
@@ -34,7 +32,6 @@ import org.session.libsignal.libsignal.util.KeyHelper
|
||||
import org.session.libsignal.libsignal.util.guava.Optional
|
||||
import org.session.libsignal.service.api.messages.SignalServiceAttachmentPointer
|
||||
import org.session.libsignal.service.api.messages.SignalServiceGroup
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
||||
@@ -44,7 +41,6 @@ import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities
|
||||
import org.thoughtcrime.securesms.loki.utilities.get
|
||||
import org.thoughtcrime.securesms.loki.utilities.getString
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority
|
||||
import java.util.*
|
||||
|
||||
class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol {
|
||||
override fun getUserPublicKey(): String? {
|
||||
@@ -395,6 +391,10 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
DatabaseFactory.getGroupDatabase(context).setActive(groupID, value)
|
||||
}
|
||||
|
||||
override fun getZombieMember(groupID: String): Set<String> {
|
||||
return DatabaseFactory.getGroupDatabase(context).getGroupZombieMembers(groupID).map { it.address.serialize() }.toHashSet()
|
||||
}
|
||||
|
||||
override fun removeMember(groupID: String, member: Address) {
|
||||
DatabaseFactory.getGroupDatabase(context).removeMember(groupID, member)
|
||||
}
|
||||
@@ -403,10 +403,14 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
DatabaseFactory.getGroupDatabase(context).updateMembers(groupID, members)
|
||||
}
|
||||
|
||||
override fun updateZombieMembers(groupID: String, members: List<Address>) {
|
||||
DatabaseFactory.getGroupDatabase(context).updateZombieMembers(groupID, members)
|
||||
}
|
||||
|
||||
override fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type: SignalServiceGroup.Type, name: String, members: Collection<String>, admins: Collection<String>, sentTimestamp: Long) {
|
||||
val group = SignalServiceGroup(type, GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL, name, members.toList(), null, admins.toList())
|
||||
val m = IncomingTextMessage(Address.fromSerialized(senderPublicKey), 1, sentTimestamp, "", Optional.of(group), 0, true)
|
||||
val updateData = UpdateMessageData.buildGroupUpdate(type, name, members)?.toJSON()
|
||||
val updateData = ClosedGroupUpdateMessageData.buildGroupUpdate(type, name, members)?.toJSON()
|
||||
val infoMessage = IncomingGroupMessage(m, groupID, updateData, true)
|
||||
val smsDB = DatabaseFactory.getSmsDatabase(context)
|
||||
smsDB.insertMessageInbox(infoMessage)
|
||||
@@ -416,7 +420,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
val userPublicKey = getUserPublicKey()
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(groupID), false)
|
||||
|
||||
val updateData = UpdateMessageData.buildGroupUpdate(type, name, members)?.toJSON() ?: ""
|
||||
val updateData = ClosedGroupUpdateMessageData.buildGroupUpdate(type, name, members)?.toJSON() ?: ""
|
||||
val infoMessage = OutgoingGroupMediaMessage(recipient, updateData, groupID, null, sentTimestamp, 0, true, null, listOf(), listOf())
|
||||
val mmsDB = DatabaseFactory.getMmsDatabase(context)
|
||||
val mmsSmsDB = DatabaseFactory.getMmsSmsDatabase(context)
|
||||
|
@@ -54,9 +54,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
private static final int lokiV20 = 41;
|
||||
private static final int lokiV21 = 42;
|
||||
private static final int lokiV22 = 43;
|
||||
private static final int lokiV23 = 44;
|
||||
|
||||
// Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
|
||||
private static final int DATABASE_VERSION = lokiV22;
|
||||
private static final int DATABASE_VERSION = lokiV23;
|
||||
private static final String DATABASE_NAME = "signal.db";
|
||||
|
||||
private final Context context;
|
||||
@@ -272,6 +273,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
"SendDeliveryReceiptJob");
|
||||
}
|
||||
|
||||
if (oldVersion < lokiV23) {
|
||||
db.execSQL("ALTER TABLE groups ADD COLUMN zombie_members TEXT");
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
@@ -23,7 +23,7 @@ import android.text.SpannableString;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
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.link_preview.LinkPreview;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
|
||||
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||
|
@@ -25,9 +25,9 @@ import android.text.style.StyleSpan;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage;
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageBuilder;
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageData;
|
||||
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage;
|
||||
import org.session.libsession.messaging.utilities.ClosedGroupUpdateMessageBuilder;
|
||||
import org.session.libsession.messaging.utilities.ClosedGroupUpdateMessageData;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||
@@ -93,14 +93,14 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
@Override
|
||||
public SpannableString getDisplayBody(@NonNull Context context) {
|
||||
if(isGroupUpdateMessage()) {
|
||||
UpdateMessageData updateMessageData = UpdateMessageData.Companion.fromJSON(getBody());
|
||||
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildGroupUpdateMessage(context, updateMessageData, getIndividualRecipient().getAddress().serialize(), isOutgoing()));
|
||||
ClosedGroupUpdateMessageData updateMessageData = ClosedGroupUpdateMessageData.Companion.fromJSON(getBody());
|
||||
return new SpannableString(ClosedGroupUpdateMessageBuilder.INSTANCE.buildGroupUpdateMessage(context, updateMessageData, getIndividualRecipient().getAddress().serialize(), isOutgoing()));
|
||||
} else if (isExpirationTimerUpdate()) {
|
||||
int seconds = (int) (getExpiresIn() / 1000);
|
||||
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, getIndividualRecipient().getAddress().serialize(), isOutgoing()));
|
||||
return new SpannableString(ClosedGroupUpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, getIndividualRecipient().getAddress().serialize(), isOutgoing()));
|
||||
} else if (isDataExtraction()) {
|
||||
if (isScreenshotExtraction()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.SCREENSHOT, getIndividualRecipient().getAddress().serialize())));
|
||||
else if (isMediaSavedExtraction()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED, getIndividualRecipient().getAddress().serialize())));
|
||||
if (isScreenshotExtraction()) return new SpannableString((ClosedGroupUpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.SCREENSHOT, getIndividualRecipient().getAddress().serialize())));
|
||||
else if (isMediaSavedExtraction()) return new SpannableString((ClosedGroupUpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED, getIndividualRecipient().getAddress().serialize())));
|
||||
}
|
||||
// TODO below lines are left here for compatibility with older group update messages, it can be deleted later on
|
||||
else if (isGroupUpdate() && isOutgoing()) {
|
||||
|
@@ -5,7 +5,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
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.link_preview.LinkPreview;
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||
|
||||
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||
|
@@ -28,8 +28,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageBuilder;
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageData;
|
||||
import org.session.libsession.utilities.ExpirationUtil;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
|
@@ -4,6 +4,8 @@ import android.graphics.Bitmap;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.session.libsession.messaging.jobs.Data;
|
||||
import org.session.libsession.utilities.DownloadUtilities;
|
||||
import org.session.libsignal.service.api.crypto.AttachmentCipherInputStream;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.session.libsession.messaging.threads.GroupRecord;
|
||||
@@ -22,6 +24,7 @@ import org.session.libsignal.service.api.messages.SignalServiceAttachmentPointer
|
||||
import org.session.libsignal.service.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@@ -91,9 +94,20 @@ public class AvatarDownloadJob extends BaseJob implements InjectableType {
|
||||
attachment = File.createTempFile("avatar", "tmp", context.getCacheDir());
|
||||
attachment.deleteOnExit();
|
||||
|
||||
SignalServiceAttachmentPointer pointer = new SignalServiceAttachmentPointer(avatarId, contentType, key, Optional.of(0), Optional.absent(), 0, 0, digest, fileName, false, Optional.absent(), url);
|
||||
InputStream inputStream = receiver.retrieveAttachment(pointer, attachment, MAX_AVATAR_SIZE);
|
||||
Bitmap avatar = BitmapUtil.createScaledBitmap(context, new AttachmentModel(attachment, key, 0, digest), 500, 500);
|
||||
SignalServiceAttachmentPointer pointer = new SignalServiceAttachmentPointer(avatarId, contentType, key, Optional.of(0), Optional.absent(), 0, 0, digest, fileName, false, Optional.absent(), url);
|
||||
|
||||
if (pointer.getUrl().isEmpty()) throw new InvalidMessageException("Missing attachment URL.");
|
||||
DownloadUtilities.downloadFile(attachment, pointer.getUrl(), MAX_AVATAR_SIZE, null);
|
||||
|
||||
// Assume we're retrieving an attachment for an open group server if the digest is not set
|
||||
InputStream inputStream;
|
||||
if (!pointer.getDigest().isPresent()) {
|
||||
inputStream = new FileInputStream(attachment);
|
||||
} else {
|
||||
inputStream = AttachmentCipherInputStream.createForAttachment(attachment, pointer.getSize().or(0), pointer.getKey(), pointer.getDigest().get());
|
||||
}
|
||||
|
||||
Bitmap avatar = BitmapUtil.createScaledBitmap(context, new AttachmentModel(attachment, key, 0, digest), 500, 500);
|
||||
|
||||
database.updateProfilePicture(groupId, avatar);
|
||||
inputStream.close();
|
||||
|
@@ -10,9 +10,11 @@ import org.session.libsession.messaging.avatars.AvatarHelper;
|
||||
import org.session.libsession.messaging.jobs.Data;
|
||||
import org.session.libsession.messaging.threads.Address;
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||
import org.session.libsession.utilities.DownloadUtilities;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
import org.session.libsession.utilities.Util;
|
||||
import org.session.libsignal.service.api.SignalServiceMessageReceiver;
|
||||
import org.session.libsignal.service.api.crypto.ProfileCipherInputStream;
|
||||
import org.session.libsignal.service.api.push.exceptions.PushNetworkException;
|
||||
import org.session.libsignal.utilities.logging.Log;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
@@ -22,6 +24,7 @@ import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -102,7 +105,8 @@ public class RetrieveProfileAvatarJob extends BaseJob implements InjectableType
|
||||
File downloadDestination = File.createTempFile("avatar", ".jpg", context.getCacheDir());
|
||||
|
||||
try {
|
||||
InputStream avatarStream = receiver.retrieveProfileAvatar(profileAvatar, downloadDestination, profileKey, MAX_PROFILE_SIZE_BYTES);
|
||||
DownloadUtilities.downloadFile(downloadDestination, profileAvatar, MAX_PROFILE_SIZE_BYTES, null);
|
||||
InputStream avatarStream = new ProfileCipherInputStream(new FileInputStream(downloadDestination), profileKey);
|
||||
File decryptDestination = File.createTempFile("avatar", ".jpg", context.getCacheDir());
|
||||
|
||||
Util.copy(avatarStream, new FileOutputStream(decryptDestination));
|
||||
|
@@ -25,7 +25,7 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil.OpenGraph;
|
||||
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.UriAttachment;
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview;
|
||||
import org.session.libsession.utilities.concurrent.SignalExecutors;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@@ -13,9 +13,8 @@ import org.session.libsession.utilities.Debouncer;
|
||||
import org.session.libsession.utilities.Util;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
@@ -37,8 +37,14 @@ import java.io.IOException
|
||||
|
||||
class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
private val originalMembers = HashSet<String>()
|
||||
private val zombies = HashSet<String>()
|
||||
private val members = HashSet<String>()
|
||||
private val allMembers: Set<String>
|
||||
get() {
|
||||
return members + zombies
|
||||
}
|
||||
private var hasNameChanged = false
|
||||
private var isSelfAdmin = false
|
||||
private var isLoading = false
|
||||
set(newValue) { field = newValue; invalidateOptionsMenu() }
|
||||
|
||||
@@ -54,7 +60,10 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
}
|
||||
|
||||
private val memberListAdapter by lazy {
|
||||
EditClosedGroupMembersAdapter(this, GlideApp.with(this), this::onMemberClick)
|
||||
if (isSelfAdmin)
|
||||
EditClosedGroupMembersAdapter(this, GlideApp.with(this), isSelfAdmin, this::onMemberClick)
|
||||
else
|
||||
EditClosedGroupMembersAdapter(this, GlideApp.with(this), isSelfAdmin)
|
||||
}
|
||||
|
||||
private lateinit var mainContentContainer: LinearLayout
|
||||
@@ -81,7 +90,10 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
ThemeUtil.getThemedDrawableResId(this, R.attr.actionModeCloseDrawable))
|
||||
|
||||
groupID = intent.getStringExtra(groupIDKey)!!
|
||||
originalName = DatabaseFactory.getGroupDatabase(this).getGroup(groupID).get().title
|
||||
val groupInfo = DatabaseFactory.getGroupDatabase(this).getGroup(groupID).get()
|
||||
originalName = groupInfo.title
|
||||
isSelfAdmin = groupInfo.admins.any{ it.serialize() == TextSecurePreferences.getLocalNumber(this) }
|
||||
|
||||
name = originalName
|
||||
|
||||
mainContentContainer = findViewById(R.id.mainContentContainer)
|
||||
@@ -116,31 +128,35 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
LoaderManager.getInstance(this).initLoader(loaderID, null, object : LoaderManager.LoaderCallbacks<List<String>> {
|
||||
LoaderManager.getInstance(this).initLoader(loaderID, null, object : LoaderManager.LoaderCallbacks<GroupMembers> {
|
||||
|
||||
override fun onCreateLoader(id: Int, bundle: Bundle?): Loader<List<String>> {
|
||||
override fun onCreateLoader(id: Int, bundle: Bundle?): Loader<GroupMembers> {
|
||||
return EditClosedGroupLoader(this@EditClosedGroupActivity, groupID)
|
||||
}
|
||||
|
||||
override fun onLoadFinished(loader: Loader<List<String>>, members: List<String>) {
|
||||
override fun onLoadFinished(loader: Loader<GroupMembers>, groupMembers: GroupMembers) {
|
||||
// We no longer need any subsequent loading events
|
||||
// (they will occur on every activity resume).
|
||||
LoaderManager.getInstance(this@EditClosedGroupActivity).destroyLoader(loaderID)
|
||||
|
||||
members.clear()
|
||||
members.addAll(groupMembers.members.toHashSet())
|
||||
zombies.clear()
|
||||
zombies.addAll(groupMembers.zombieMembers.toHashSet())
|
||||
originalMembers.clear()
|
||||
originalMembers.addAll(members.toHashSet())
|
||||
updateMembers(originalMembers)
|
||||
originalMembers.addAll(members + zombies)
|
||||
updateMembers()
|
||||
}
|
||||
|
||||
override fun onLoaderReset(loader: Loader<List<String>>) {
|
||||
updateMembers(setOf())
|
||||
override fun onLoaderReset(loader: Loader<GroupMembers>) {
|
||||
updateMembers()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_edit_closed_group, menu)
|
||||
return members.isNotEmpty() && !isLoading
|
||||
return allMembers.isNotEmpty() && !isLoading
|
||||
}
|
||||
// endregion
|
||||
|
||||
@@ -153,8 +169,8 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
if (data == null || data.extras == null || !data.hasExtra(SelectContactsActivity.selectedContactsKey)) return
|
||||
|
||||
val selectedContacts = data.extras!!.getStringArray(SelectContactsActivity.selectedContactsKey)!!.toSet()
|
||||
val changedMembers = members + selectedContacts
|
||||
updateMembers(changedMembers)
|
||||
members.addAll(selectedContacts)
|
||||
updateMembers()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,17 +189,12 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateMembers(members: Set<String>) {
|
||||
this.members.clear()
|
||||
this.members.addAll(members)
|
||||
memberListAdapter.setMembers(members)
|
||||
private fun updateMembers() {
|
||||
memberListAdapter.setMembers(allMembers)
|
||||
memberListAdapter.setZombieMembers(zombies)
|
||||
|
||||
val admins = DatabaseFactory.getGroupDatabase(this).getGroup(groupID).get().admins.map { it.toString() }.toMutableSet()
|
||||
admins.remove(TextSecurePreferences.getLocalNumber(this))
|
||||
memberListAdapter.setLockedMembers(admins)
|
||||
|
||||
mainContentContainer.visibility = if (members.isEmpty()) View.GONE else View.VISIBLE
|
||||
emptyStateContainer.visibility = if (members.isEmpty()) View.VISIBLE else View.GONE
|
||||
mainContentContainer.visibility = if (allMembers.isEmpty()) View.GONE else View.VISIBLE
|
||||
emptyStateContainer.visibility = if (allMembers.isEmpty()) View.VISIBLE else View.GONE
|
||||
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
@@ -200,8 +211,9 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
private fun onMemberClick(member: String) {
|
||||
val bottomSheet = ClosedGroupEditingOptionsBottomSheet()
|
||||
bottomSheet.onRemoveTapped = {
|
||||
val changedMembers = members - member
|
||||
updateMembers(changedMembers)
|
||||
if (zombies.contains(member)) zombies.remove(member)
|
||||
else members.remove(member)
|
||||
updateMembers()
|
||||
bottomSheet.dismiss()
|
||||
}
|
||||
bottomSheet.show(supportFragmentManager, "GroupEditingOptionsBottomSheet")
|
||||
@@ -209,7 +221,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
|
||||
private fun onAddMembersClick() {
|
||||
val intent = Intent(this@EditClosedGroupActivity, SelectContactsActivity::class.java)
|
||||
intent.putExtra(SelectContactsActivity.usersToExcludeKey, members.toTypedArray())
|
||||
intent.putExtra(SelectContactsActivity.usersToExcludeKey, allMembers.toTypedArray())
|
||||
intent.putExtra(SelectContactsActivity.emptyStateTextKey, "No contacts to add")
|
||||
startActivityForResult(intent, addUsersRequestCode)
|
||||
}
|
||||
@@ -229,7 +241,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
}
|
||||
|
||||
private fun commitChanges() {
|
||||
val hasMemberListChanges = (members != originalMembers)
|
||||
val hasMemberListChanges = (allMembers != originalMembers)
|
||||
|
||||
if (!hasNameChanged && !hasMemberListChanges) {
|
||||
return finish()
|
||||
@@ -237,15 +249,13 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
|
||||
val name = if (hasNameChanged) this.name else originalName
|
||||
|
||||
val members = this.members.map {
|
||||
val members = this.allMembers.map {
|
||||
Recipient.from(this, Address.fromSerialized(it), false)
|
||||
}.toSet()
|
||||
val originalMembers = this.originalMembers.map {
|
||||
Recipient.from(this, Address.fromSerialized(it), false)
|
||||
}.toSet()
|
||||
|
||||
val admins = members.toSet() //TODO For now, consider all the users to be admins.
|
||||
|
||||
var isClosedGroup: Boolean
|
||||
var groupPublicKey: String?
|
||||
try {
|
||||
@@ -303,4 +313,6 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GroupMembers(val members: List<String>, val zombieMembers: List<String>) { }
|
||||
}
|
@@ -4,12 +4,19 @@ import android.content.Context
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.util.AsyncLoader
|
||||
|
||||
class EditClosedGroupLoader(context: Context, val groupID: String) : AsyncLoader<List<String>>(context) {
|
||||
class EditClosedGroupLoader(context: Context, val groupID: String) : AsyncLoader<EditClosedGroupActivity.GroupMembers>(context) {
|
||||
|
||||
override fun loadInBackground(): List<String> {
|
||||
val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupID, true)
|
||||
return members.map {
|
||||
it.address.toString()
|
||||
}
|
||||
override fun loadInBackground(): EditClosedGroupActivity.GroupMembers {
|
||||
val groupDatabase = DatabaseFactory.getGroupDatabase(context)
|
||||
val members = groupDatabase.getGroupMembers(groupID, true)
|
||||
val zombieMembers = groupDatabase.getGroupZombieMembers(groupID)
|
||||
return EditClosedGroupActivity.GroupMembers(
|
||||
members.map {
|
||||
it.address.toString()
|
||||
},
|
||||
zombieMembers.map {
|
||||
it.address.toString()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@@ -7,15 +7,17 @@ import org.session.libsession.messaging.threads.Address
|
||||
import org.thoughtcrime.securesms.loki.views.UserView
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
|
||||
class EditClosedGroupMembersAdapter(
|
||||
private val context: Context,
|
||||
private val glide: GlideRequests,
|
||||
private val admin: Boolean,
|
||||
private val memberClickListener: ((String) -> Unit)? = null
|
||||
) : RecyclerView.Adapter<EditClosedGroupMembersAdapter.ViewHolder>() {
|
||||
|
||||
private val members = ArrayList<String>()
|
||||
private val lockedMembers = HashSet<String>()
|
||||
private val zombieMembers = ArrayList<String>()
|
||||
|
||||
fun setMembers(members: Collection<String>) {
|
||||
this.members.clear()
|
||||
@@ -23,9 +25,9 @@ class EditClosedGroupMembersAdapter(
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun setLockedMembers(members: Collection<String>) {
|
||||
this.lockedMembers.clear()
|
||||
this.lockedMembers.addAll(members)
|
||||
fun setZombieMembers(members: Collection<String>) {
|
||||
this.zombieMembers.clear()
|
||||
this.zombieMembers.addAll(members)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
@@ -39,15 +41,20 @@ class EditClosedGroupMembersAdapter(
|
||||
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
|
||||
val member = members[position]
|
||||
|
||||
val lockedMember = lockedMembers.contains(member)
|
||||
val unlocked = admin && member != TextSecurePreferences.getLocalNumber(context)
|
||||
|
||||
viewHolder.view.bind(Recipient.from(
|
||||
context,
|
||||
Address.fromSerialized(member), false),
|
||||
glide,
|
||||
if (lockedMember) UserView.ActionIndicator.None else UserView.ActionIndicator.Menu)
|
||||
if (unlocked) UserView.ActionIndicator.Menu else UserView.ActionIndicator.None)
|
||||
|
||||
if (!lockedMember) {
|
||||
if (zombieMembers.contains(member))
|
||||
viewHolder.view.alpha = 0.5F
|
||||
else
|
||||
viewHolder.view.alpha = 1F
|
||||
|
||||
if (unlocked) {
|
||||
viewHolder.view.setOnClickListener { this.memberClickListener?.invoke(member) }
|
||||
}
|
||||
}
|
||||
|
@@ -30,10 +30,10 @@ import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import org.session.libsession.messaging.jobs.JobQueue
|
||||
import org.session.libsession.messaging.opengroups.OpenGroupAPI
|
||||
import org.session.libsession.messaging.mentions.MentionsManager
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||
import org.session.libsession.utilities.*
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager
|
||||
import org.session.libsignal.service.loki.utilities.toHexString
|
||||
import org.session.libsignal.utilities.ThreadUtils
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
@@ -139,7 +139,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
if (userPublicKey != null) {
|
||||
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
||||
MentionsManager.configureIfNeeded(userPublicKey, userDB)
|
||||
application.publicChatManager.startPollersIfNeeded()
|
||||
JobQueue.shared.resumePendingJobs()
|
||||
}
|
||||
|
@@ -19,12 +19,12 @@ import android.widget.Toast
|
||||
import androidx.annotation.ColorRes
|
||||
import kotlinx.android.synthetic.main.activity_path.*
|
||||
import network.loki.messenger.R
|
||||
import org.session.libsession.snode.OnionRequestAPI
|
||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||
import org.thoughtcrime.securesms.loki.utilities.*
|
||||
import org.thoughtcrime.securesms.loki.views.GlowViewUtilities
|
||||
import org.thoughtcrime.securesms.loki.views.PathDotView
|
||||
import org.session.libsignal.service.loki.api.Snode
|
||||
import org.session.libsignal.service.loki.api.onionrequests.OnionRequestAPI
|
||||
import org.session.libsignal.service.loki.Snode
|
||||
|
||||
class PathActivity : PassphraseRequiredActionBarActivity() {
|
||||
private val broadcastReceivers = mutableListOf<BroadcastReceiver>()
|
||||
|
@@ -28,13 +28,13 @@ import nl.komponents.kovenant.functional.bind
|
||||
import nl.komponents.kovenant.task
|
||||
import nl.komponents.kovenant.ui.alwaysUi
|
||||
import org.session.libsession.messaging.avatars.AvatarHelper
|
||||
import org.session.libsession.messaging.opengroups.OpenGroupAPI
|
||||
import org.session.libsession.messaging.file_server.FileServerAPI
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.preferences.ProfileKeyUtil
|
||||
import org.session.libsignal.service.api.util.StreamDetails
|
||||
import org.session.libsignal.service.loki.api.fileserver.FileServerAPI
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||
import org.thoughtcrime.securesms.avatar.AvatarSelection
|
||||
|
@@ -8,13 +8,14 @@ import nl.komponents.kovenant.Promise
|
||||
import nl.komponents.kovenant.all
|
||||
import nl.komponents.kovenant.functional.map
|
||||
import org.session.libsession.messaging.jobs.MessageReceiveJob
|
||||
import org.session.libsession.messaging.opengroups.OpenGroup
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPoller
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPoller
|
||||
import org.session.libsession.snode.SnodeAPI
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.service.loki.api.SnodeAPI
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class BackgroundPollWorker(val context: Context, params: WorkerParameters) : Worker(context, params) {
|
||||
@@ -70,7 +71,7 @@ class BackgroundPollWorker(val context: Context, params: WorkerParameters) : Wor
|
||||
|
||||
// Private chats
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
|
||||
val privateChatsPromise = SnodeAPI.shared.getMessages(userPublicKey).map { envelopes ->
|
||||
val privateChatsPromise = SnodeAPI.getMessages(userPublicKey).map { envelopes ->
|
||||
envelopes.map { envelope ->
|
||||
MessageReceiveJob(envelope.toByteArray(), false).executeAsync()
|
||||
}
|
||||
|
@@ -3,12 +3,12 @@ package org.thoughtcrime.securesms.loki.api
|
||||
import android.content.Context
|
||||
import nl.komponents.kovenant.functional.map
|
||||
import okhttp3.*
|
||||
import org.session.libsession.messaging.sending_receiving.notifications.PushNotificationAPI
|
||||
import org.session.libsession.snode.OnionRequestAPI
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.session.libsignal.utilities.JsonUtil
|
||||
import org.session.libsignal.service.loki.api.PushNotificationAPI
|
||||
import org.session.libsignal.service.loki.api.onionrequests.OnionRequestAPI
|
||||
import org.session.libsignal.service.loki.utilities.retryIfNeeded
|
||||
|
||||
object LokiPushNotificationManager {
|
||||
@@ -16,10 +16,10 @@ object LokiPushNotificationManager {
|
||||
private val tokenExpirationInterval = 12 * 60 * 60 * 1000
|
||||
|
||||
private val server by lazy {
|
||||
PushNotificationAPI.shared.server
|
||||
PushNotificationAPI.server
|
||||
}
|
||||
private val pnServerPublicKey by lazy {
|
||||
PushNotificationAPI.pnServerPublicKey
|
||||
PushNotificationAPI.serverPublicKey
|
||||
}
|
||||
|
||||
enum class ClosedGroupOperation {
|
||||
|
@@ -2,9 +2,9 @@ package org.thoughtcrime.securesms.loki.api
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.*
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat
|
||||
|
||||
/**
|
||||
* Delegates the [OpenGroupUtilities.updateGroupInfo] call to the work manager.
|
||||
@@ -40,7 +40,7 @@ class PublicChatInfoUpdateWorker(val context: Context, params: WorkerParameters)
|
||||
val serverUrl = inputData.getString(DATA_KEY_SERVER_URL)!!
|
||||
val channel = inputData.getLong(DATA_KEY_CHANNEL, -1)
|
||||
|
||||
val publicChatId = PublicChat.getId(channel, serverUrl)
|
||||
val publicChatId = OpenGroup.getId(channel, serverUrl)
|
||||
|
||||
return try {
|
||||
Log.v(TAG, "Updating open group info for $publicChatId.")
|
||||
|
@@ -5,14 +5,13 @@ import android.database.ContentObserver
|
||||
import android.graphics.Bitmap
|
||||
import android.text.TextUtils
|
||||
import androidx.annotation.WorkerThread
|
||||
import org.session.libsession.messaging.MessagingConfiguration
|
||||
import org.session.libsession.messaging.opengroups.OpenGroup
|
||||
import org.session.libsession.messaging.opengroups.OpenGroupAPI
|
||||
import org.session.libsession.messaging.opengroups.OpenGroupInfo
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupInfo
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPoller
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.Util
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat
|
||||
import org.thoughtcrime.securesms.database.DatabaseContentProviders
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
@@ -75,7 +74,7 @@ class PublicChatManager(private val context: Context) {
|
||||
|
||||
@WorkerThread
|
||||
public fun addChat(server: String, channel: Long, info: OpenGroupInfo): OpenGroup {
|
||||
val chat = PublicChat(channel, server, info.displayName, true)
|
||||
val chat = OpenGroup(channel, server, info.displayName, true)
|
||||
var threadID = GroupManager.getOpenGroupThreadID(chat.id, context)
|
||||
var profilePicture: Bitmap? = null
|
||||
// Create the group if we don't have one
|
||||
@@ -96,12 +95,12 @@ class PublicChatManager(private val context: Context) {
|
||||
// Start polling
|
||||
Util.runOnMain { startPollersIfNeeded() }
|
||||
|
||||
return OpenGroup.from(chat)
|
||||
return chat
|
||||
}
|
||||
|
||||
public fun removeChat(server: String, channel: Long) {
|
||||
val threadDB = DatabaseFactory.getThreadDatabase(context)
|
||||
val groupId = PublicChat.getId(channel, server)
|
||||
val groupId = OpenGroup.getId(channel, server)
|
||||
val threadId = GroupManager.getOpenGroupThreadID(groupId, context)
|
||||
val groupAddress = threadDB.getRecipientForThreadId(threadId)!!.address.serialize()
|
||||
GroupManager.deleteGroup(groupAddress, context)
|
||||
@@ -110,7 +109,7 @@ class PublicChatManager(private val context: Context) {
|
||||
}
|
||||
|
||||
private fun refreshChatsAndPollers() {
|
||||
val storage = MessagingConfiguration.shared.storage
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val chatsInDB = storage.getAllOpenGroups()
|
||||
val removedChatThreadIds = chats.keys.filter { !chatsInDB.keys.contains(it) }
|
||||
removedChatThreadIds.forEach { pollers.remove(it)?.stop() }
|
||||
|
@@ -6,8 +6,8 @@ import com.google.firebase.messaging.FirebaseMessagingService
|
||||
import com.google.firebase.messaging.RemoteMessage
|
||||
import org.session.libsession.messaging.jobs.JobQueue
|
||||
import org.session.libsession.messaging.jobs.MessageReceiveJob
|
||||
import org.session.libsession.messaging.utilities.MessageWrapper
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.service.loki.api.MessageWrapper
|
||||
import org.session.libsignal.utilities.Base64
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels
|
||||
|
@@ -7,7 +7,7 @@ import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.libsignal.ecc.DjbECPrivateKey
|
||||
import org.session.libsignal.libsignal.ecc.DjbECPublicKey
|
||||
import org.session.libsignal.libsignal.ecc.ECKeyPair
|
||||
import org.session.libsignal.service.loki.api.Snode
|
||||
import org.session.libsignal.service.loki.Snode
|
||||
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
|
||||
import org.session.libsignal.service.loki.utilities.PublicKeyValidation
|
||||
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
||||
|
@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.loki.database
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||
|
||||
import org.thoughtcrime.securesms.database.Database
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
@@ -12,13 +13,11 @@ import org.thoughtcrime.securesms.loki.utilities.*
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat
|
||||
|
||||
import org.session.libsignal.utilities.JsonUtil
|
||||
import org.session.libsignal.service.loki.database.LokiThreadDatabaseProtocol
|
||||
import org.session.libsignal.service.loki.utilities.PublicKeyValidation
|
||||
|
||||
class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiThreadDatabaseProtocol {
|
||||
class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
|
||||
|
||||
companion object {
|
||||
private val sessionResetTable = "loki_thread_session_reset_database"
|
||||
@@ -31,22 +30,22 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
||||
@JvmStatic val createPublicChatTableCommand = "CREATE TABLE $publicChatTable ($threadID INTEGER PRIMARY KEY, $publicChat TEXT);"
|
||||
}
|
||||
|
||||
override fun getThreadID(hexEncodedPublicKey: String): Long {
|
||||
fun getThreadID(hexEncodedPublicKey: String): Long {
|
||||
val address = Address.fromSerialized(hexEncodedPublicKey)
|
||||
val recipient = Recipient.from(context, address, false)
|
||||
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
||||
}
|
||||
|
||||
fun getAllPublicChats(): Map<Long, PublicChat> {
|
||||
fun getAllPublicChats(): Map<Long, OpenGroup> {
|
||||
val database = databaseHelper.readableDatabase
|
||||
var cursor: Cursor? = null
|
||||
val result = mutableMapOf<Long, PublicChat>()
|
||||
val result = mutableMapOf<Long, OpenGroup>()
|
||||
try {
|
||||
cursor = database.rawQuery("select * from $publicChatTable", null)
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
val threadID = cursor.getLong(threadID)
|
||||
val string = cursor.getString(publicChat)
|
||||
val publicChat = PublicChat.fromJSON(string)
|
||||
val publicChat = OpenGroup.fromJSON(string)
|
||||
if (publicChat != null) { result[threadID] = publicChat }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
@@ -61,16 +60,16 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
||||
return getAllPublicChats().values.fold(setOf()) { set, chat -> set.plus(chat.server) }
|
||||
}
|
||||
|
||||
override fun getPublicChat(threadID: Long): PublicChat? {
|
||||
fun getPublicChat(threadID: Long): OpenGroup? {
|
||||
if (threadID < 0) { return null }
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(publicChatTable, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
|
||||
val publicChatAsJSON = cursor.getString(publicChat)
|
||||
PublicChat.fromJSON(publicChatAsJSON)
|
||||
OpenGroup.fromJSON(publicChatAsJSON)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setPublicChat(publicChat: PublicChat, threadID: Long) {
|
||||
fun setPublicChat(publicChat: OpenGroup, threadID: Long) {
|
||||
if (threadID < 0) { return }
|
||||
val database = databaseHelper.writableDatabase
|
||||
val contentValues = ContentValues(2)
|
||||
@@ -79,7 +78,7 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
||||
database.insertOrUpdate(publicChatTable, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
||||
}
|
||||
|
||||
override fun removePublicChat(threadID: Long) {
|
||||
fun removePublicChat(threadID: Long) {
|
||||
databaseHelper.writableDatabase.delete(publicChatTable, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
||||
}
|
||||
}
|
@@ -31,6 +31,7 @@ import org.session.libsession.utilities.TextSecurePreferences
|
||||
import java.util.*
|
||||
|
||||
object ClosedGroupsProtocolV2 {
|
||||
|
||||
@JvmStatic
|
||||
fun handleMessage(context: Context, closedGroupUpdate: DataMessage.ClosedGroupControlMessage, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) {
|
||||
if (!isValid(context, closedGroupUpdate, senderPublicKey, sentTimestamp)) { return }
|
||||
@@ -40,7 +41,6 @@ object ClosedGroupsProtocolV2 {
|
||||
DataMessage.ClosedGroupControlMessage.Type.MEMBERS_ADDED -> handleClosedGroupMembersAdded(context, closedGroupUpdate, sentTimestamp, groupPublicKey, senderPublicKey)
|
||||
DataMessage.ClosedGroupControlMessage.Type.NAME_CHANGE -> handleClosedGroupNameChange(context, closedGroupUpdate, sentTimestamp, groupPublicKey, senderPublicKey)
|
||||
DataMessage.ClosedGroupControlMessage.Type.MEMBER_LEFT -> handleClosedGroupMemberLeft(context, sentTimestamp, groupPublicKey, senderPublicKey)
|
||||
DataMessage.ClosedGroupControlMessage.Type.UPDATE -> handleClosedGroupUpdate(context, closedGroupUpdate, sentTimestamp, groupPublicKey, senderPublicKey)
|
||||
DataMessage.ClosedGroupControlMessage.Type.ENCRYPTION_KEY_PAIR -> handleGroupEncryptionKeyPair(context, closedGroupUpdate, groupPublicKey, senderPublicKey)
|
||||
else -> {
|
||||
Log.d("Loki","Can't handle closed group update of unknown type: ${closedGroupUpdate.type}")
|
||||
@@ -64,7 +64,6 @@ object ClosedGroupsProtocolV2 {
|
||||
DataMessage.ClosedGroupControlMessage.Type.MEMBER_LEFT -> {
|
||||
senderPublicKey.isNotEmpty()
|
||||
}
|
||||
DataMessage.ClosedGroupControlMessage.Type.UPDATE,
|
||||
DataMessage.ClosedGroupControlMessage.Type.NAME_CHANGE -> {
|
||||
!closedGroupUpdate.name.isNullOrEmpty()
|
||||
}
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package org.thoughtcrime.securesms.loki.protocol
|
||||
|
||||
import android.content.Context
|
||||
import com.google.protobuf.ByteString
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.messages.Destination
|
||||
import org.session.libsession.messaging.messages.control.ConfigurationMessage
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||
|
@@ -7,7 +7,7 @@ import android.content.IntentFilter
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import com.opencsv.CSVReader
|
||||
import org.session.libsignal.service.loki.api.onionrequests.OnionRequestAPI
|
||||
import org.session.libsession.snode.OnionRequestAPI
|
||||
import org.session.libsignal.utilities.ThreadUtils
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
|
@@ -1,10 +1,10 @@
|
||||
package org.thoughtcrime.securesms.loki.utilities
|
||||
|
||||
import android.content.Context
|
||||
import org.session.libsession.messaging.mentions.MentionsManager
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager
|
||||
|
||||
object MentionManagerUtilities {
|
||||
|
||||
|
@@ -3,12 +3,11 @@ package org.thoughtcrime.securesms.loki.utilities
|
||||
import android.content.Context
|
||||
import androidx.annotation.WorkerThread
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.session.libsession.messaging.opengroups.OpenGroup
|
||||
import org.session.libsession.messaging.opengroups.OpenGroupAPI
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.preferences.ProfileKeyUtil
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
@@ -23,10 +22,10 @@ object OpenGroupUtilities {
|
||||
@Throws(Exception::class)
|
||||
fun addGroup(context: Context, url: String, channel: Long): OpenGroup {
|
||||
// Check for an existing group.
|
||||
val groupID = PublicChat.getId(channel, url)
|
||||
val groupID = OpenGroup.getId(channel, url)
|
||||
val threadID = GroupManager.getOpenGroupThreadID(groupID, context)
|
||||
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
||||
if (openGroup != null) { return OpenGroup.from(openGroup) }
|
||||
if (openGroup != null) { return openGroup }
|
||||
|
||||
// Add the new group.
|
||||
val application = ApplicationContext.getInstance(context)
|
||||
@@ -56,7 +55,7 @@ object OpenGroupUtilities {
|
||||
@Throws(Exception::class)
|
||||
fun updateGroupInfo(context: Context, url: String, channel: Long) {
|
||||
// Check if open group has a related DB record.
|
||||
val groupId = GroupUtil.getEncodedOpenGroupID(PublicChat.getId(channel, url).toByteArray())
|
||||
val groupId = GroupUtil.getEncodedOpenGroupID(OpenGroup.getId(channel, url).toByteArray())
|
||||
if (!DatabaseFactory.getGroupDatabase(context).hasGroup(groupId)) {
|
||||
throw IllegalStateException("Attempt to update open group info for non-existent DB record: $groupId")
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import kotlinx.android.synthetic.main.view_mention_candidate.view.*
|
||||
import network.loki.messenger.R
|
||||
import org.session.libsession.messaging.opengroups.OpenGroupAPI
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI
|
||||
import org.session.libsignal.service.loki.utilities.mentions.Mention
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
|
||||
|
@@ -11,9 +11,9 @@ import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.annotation.ColorInt
|
||||
import network.loki.messenger.R
|
||||
import org.session.libsession.snode.OnionRequestAPI
|
||||
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
|
||||
import org.thoughtcrime.securesms.loki.utilities.toPx
|
||||
import org.session.libsignal.service.loki.api.onionrequests.OnionRequestAPI
|
||||
|
||||
class PathStatusView : View {
|
||||
private val broadcastReceivers = mutableListOf<BroadcastReceiver>()
|
||||
|
@@ -11,10 +11,10 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import kotlinx.android.synthetic.main.view_profile_picture.view.*
|
||||
import network.loki.messenger.R
|
||||
import org.session.libsession.messaging.avatars.ProfileContactPhoto
|
||||
import org.session.libsession.messaging.mentions.MentionsManager
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.loki.utilities.AvatarPlaceholderGenerator
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
@@ -146,13 +146,13 @@ class ProfilePictureView : RelativeLayout {
|
||||
private fun setProfilePictureIfNeeded(imageView: ImageView, publicKey: String, displayName: String?, @DimenRes sizeResId: Int) {
|
||||
if (publicKey.isNotEmpty()) {
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false)
|
||||
if (imagesCached.contains(recipient.profileAvatar.orEmpty())) return
|
||||
if (imagesCached.contains(publicKey)) return
|
||||
val signalProfilePicture = recipient.contactPhoto
|
||||
if (signalProfilePicture != null && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "0"
|
||||
&& (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "") {
|
||||
glide.clear(imageView)
|
||||
glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).circleCrop().into(imageView)
|
||||
imagesCached.add(recipient.profileAvatar.orEmpty())
|
||||
imagesCached.add(publicKey)
|
||||
} else {
|
||||
val sizeInPX = resources.getDimensionPixelSize(sizeResId)
|
||||
glide.clear(imageView)
|
||||
@@ -162,7 +162,7 @@ class ProfilePictureView : RelativeLayout {
|
||||
publicKey,
|
||||
displayName
|
||||
)).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView)
|
||||
imagesCached.add(recipient.profileAvatar.orEmpty())
|
||||
imagesCached.add(publicKey)
|
||||
}
|
||||
} else {
|
||||
imageView.setImageDrawable(null)
|
||||
|
@@ -2,7 +2,7 @@ package org.thoughtcrime.securesms.mms;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.session.libsignal.service.loki.api.fileserver.FileServerAPI;
|
||||
import org.session.libsession.messaging.file_server.FileServerAPI;
|
||||
|
||||
public class PushMediaConstraints extends MediaConstraints {
|
||||
|
||||
|
Reference in New Issue
Block a user