diff --git a/app/src/main/java/org/thoughtcrime/securesms/MessageDetailsActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MessageDetailsActivity.java index cb673cf978..5789d6f791 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MessageDetailsActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MessageDetailsActivity.java @@ -454,8 +454,8 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity UpdateMessageData updateMessageData = UpdateMessageData.Companion.fromJSON(messageRecord.getBody()); if (updateMessageData.getKind() instanceof UpdateMessageData.Kind.OpenGroupInvitation) { UpdateMessageData.Kind.OpenGroupInvitation data = (UpdateMessageData.Kind.OpenGroupInvitation)updateMessageData.getKind(); - openGroupInvitation.setGroupName(data.getGroupName()); - openGroupInvitation.setGroupUrl(data.getGroupUrl()); + openGroupInvitation.setName(data.getGroupName()); + openGroupInvitation.setUrl(data.getGroupUrl()); } message.setOpenGroupInvitation(openGroupInvitation); } else { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 6c8f5047b2..8143b5df5f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -1859,19 +1859,18 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity sendComplete(allocatedThreadId); } - private void sendOpenGroupInvitations(String[] contactsID) { + private void sendOpenGroupInvitations(String[] contactIDs) { final Context context = getApplicationContext(); OpenGroupV2 openGroup = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(threadId); - for (String contactId: contactsID) { - Recipient recipient = Recipient.from(context, Address.fromSerialized(contactId), true); + for (String contactID : contactIDs) { + Recipient recipient = Recipient.from(context, Address.fromSerialized(contactID), true); VisibleMessage message = new VisibleMessage(); message.setSentTimestamp(System.currentTimeMillis()); OpenGroupInvitation openGroupInvitationMessage = new OpenGroupInvitation(); - openGroupInvitationMessage.setGroupName(openGroup.getName()); - openGroupInvitationMessage.setGroupUrl(openGroup.getJoinURL()); + openGroupInvitationMessage.setName(openGroup.getName()); + openGroupInvitationMessage.setUrl(openGroup.getJoinURL()); message.setOpenGroupInvitation(openGroupInvitationMessage); OutgoingTextMessage outgoingTextMessage = OutgoingTextMessage.fromOpenGroupInvitation(openGroupInvitationMessage, recipient, message.getSentTimestamp()); - DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(-1, outgoingTextMessage, message.getSentTimestamp()); MessageSender.send(message, recipient.getAddress()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java index 3826c28faf..81ec17bd0e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java @@ -48,7 +48,8 @@ public interface MmsSmsColumns { OUTGOING_CALL_TYPE}; - //TODO clean unused keys + // TODO: Clean unused keys + // Message attributes protected static final long MESSAGE_FORCE_SMS_BIT = 0x40; @@ -74,9 +75,10 @@ public interface MmsSmsColumns { protected static final long EXPIRATION_TIMER_UPDATE_BIT = 0x40000; protected static final long GROUP_UPDATE_MESSAGE_BIT = 0x80000; - // Data Extraction Information + // Data Extraction Notification protected static final long MEDIA_SAVED_EXTRACTION_BIT = 0x01000; protected static final long SCREENSHOT_EXTRACTION_BIT = 0x02000; + // Open Group Invitation protected static final long OPEN_GROUP_INVITATION_BIT = 0x04000; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index dc30c69bad..1651405d4c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -165,7 +165,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, mmsDatabase.endTransaction() } else { val smsDatabase = DatabaseFactory.getSmsDatabase(context) - val isOpenGroupInvitation = message.openGroupInvitation != null + val isOpenGroupInvitation = (message.openGroupInvitation != null) val insertResult = if (message.sender == getUserPublicKey()) { val textMessage = if (isOpenGroupInvitation) OutgoingTextMessage.fromOpenGroupInvitation(message.openGroupInvitation, targetRecipient, message.sentTimestamp) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java index 21d69d4770..35a10fce3c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java @@ -145,8 +145,6 @@ public abstract class DisplayRecord { return isMediaSavedExtraction() || isScreenshotExtraction(); } - // Open Group Invitation - public boolean isOpenGroupInvitation() { return MmsSmsColumns.Types.isOpenGroupInvitation(type); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/views/OpenGroupInvitationView.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/views/OpenGroupInvitationView.kt index 98d13e8f5f..e1a26f1669 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/views/OpenGroupInvitationView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/views/OpenGroupInvitationView.kt @@ -1,12 +1,11 @@ package org.thoughtcrime.securesms.loki.views import android.content.Context +import android.content.res.ColorStateList +import android.graphics.Color import android.util.AttributeSet import android.view.View -import android.widget.FrameLayout -import android.widget.ImageView -import android.widget.TextView -import android.widget.Toast +import android.widget.* import androidx.appcompat.app.AlertDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -20,17 +19,12 @@ import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities class OpenGroupInvitationView : FrameLayout { - - companion object { - private const val TAG = "OpenGroupInvitationView" - } - private val joinButton: ImageView - private val openGroupIcon: ImageView - private val groupName: TextView - private val displayedUrl: TextView - - private var groupUrl: String = "" + private val openGroupIconContainer: RelativeLayout + private val openGroupIconImageView: ImageView + private val nameTextView: TextView + private val urlTextView: TextView + private var url: String = "" constructor(context: Context): this(context, null) @@ -38,40 +32,31 @@ class OpenGroupInvitationView : FrameLayout { constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr) { View.inflate(context, R.layout.open_group_invitation_view, this) - joinButton = findViewById(R.id.join_open_group) - openGroupIcon = findViewById(R.id.open_group_icon) - groupName = findViewById(R.id.group_name) - displayedUrl = findViewById(R.id.group_url) - - joinButton.setOnClickListener { joinPublicGroup(groupUrl) } + joinButton = findViewById(R.id.join_open_group_button) + openGroupIconContainer = findViewById(R.id.open_group_icon_image_view_container) + openGroupIconImageView = findViewById(R.id.open_group_icon_image_view) + nameTextView = findViewById(R.id.name_text_view) + urlTextView = findViewById(R.id.url_text_view) + joinButton.setOnClickListener { joinOpenGroup(url) } } fun setOpenGroup(name: String, url: String, isOutgoing: Boolean = false) { - groupName.text = name - displayedUrl.text = OpenGroupUrlParser.trimQueryParameter(url) - groupUrl = url - - if(isOutgoing) { - joinButton.visibility = View.GONE - openGroupIcon.visibility = View.VISIBLE - } else { - joinButton.visibility = View.VISIBLE - openGroupIcon.visibility = View.GONE - } + nameTextView.text = name + urlTextView.text = OpenGroupUrlParser.trimQueryParameter(url) + this.url = url + joinButton.visibility = if (isOutgoing) View.GONE else View.VISIBLE + openGroupIconContainer.visibility = if (isOutgoing) View.VISIBLE else View.GONE } - private fun joinPublicGroup(url: String) { + private fun joinOpenGroup(url: String) { val openGroup = OpenGroupUrlParser.parseUrl(url) val builder = AlertDialog.Builder(context) - builder.setTitle(context.getString(R.string.ConversationActivity_join_open_group, groupName.text.toString())) - builder.setIconAttribute(R.attr.dialog_info_icon) + builder.setTitle(context.getString(R.string.ConversationActivity_join_open_group, nameTextView.text.toString())) builder.setCancelable(true) - - var message: String = - context.getString(R.string.ConversationActivity_join_open_group_confirmation_message, groupName.text.toString()) - + val message: String = + context.getString(R.string.ConversationActivity_join_open_group_confirmation_message, nameTextView.text.toString()) builder.setMessage(message) - builder.setPositiveButton(R.string.yes) { dialog, which -> + builder.setPositiveButton(R.string.yes) { dialog, _ -> GlobalScope.launch(Dispatchers.IO) { try { dialog.dismiss() @@ -81,23 +66,14 @@ class OpenGroupInvitationView : FrameLayout { openGroup.room, openGroup.serverPublicKey ) - val threadID = GroupManager.getOpenGroupThreadID(group.id, context) - val groupID = GroupUtil.getEncodedOpenGroupID(group.id.toByteArray()) - MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(context) } catch (e: Exception) { - Log.e("JoinPublicChatActivity", "Failed to join open group.", e) - Toast.makeText( - context, - R.string.activity_join_public_chat_error, - Toast.LENGTH_SHORT - ).show() + Log.e("Loki", "Failed to join open group.", e) + Toast.makeText(context, R.string.activity_join_public_chat_error, Toast.LENGTH_SHORT).show() } } } - builder.setNegativeButton(R.string.no, null) builder.show() } - } \ No newline at end of file diff --git a/app/src/main/res/layout/open_group_invitation_view.xml b/app/src/main/res/layout/open_group_invitation_view.xml index 4074ca3174..2a360a4a62 100644 --- a/app/src/main/res/layout/open_group_invitation_view.xml +++ b/app/src/main/res/layout/open_group_invitation_view.xml @@ -1,73 +1,74 @@ - - + android:paddingHorizontal="@dimen/medium_spacing" + android:orientation="horizontal"> - - + android:background="@drawable/circle_tintable" + android:backgroundTint="#00E076"> + + + + + \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingTextMessage.java b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingTextMessage.java index 6cd5a45cac..690143a188 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingTextMessage.java +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingTextMessage.java @@ -12,7 +12,6 @@ import org.session.libsession.messaging.utilities.UpdateMessageData; import org.session.libsession.utilities.GroupUtil; import org.session.libsignal.libsignal.util.guava.Optional; import org.session.libsignal.service.api.messages.SignalServiceGroup; -import org.session.libsignal.utilities.logging.Log; public class IncomingTextMessage implements Parcelable { @@ -112,7 +111,11 @@ public class IncomingTextMessage implements Parcelable { public static IncomingTextMessage fromOpenGroupInvitation(OpenGroupInvitation openGroupInvitation, Address sender, Long sentTimestamp) { - String body = UpdateMessageData.Companion.buildOpenGroupInvitation(openGroupInvitation.getGroupUrl(), openGroupInvitation.getGroupName()).toJSON(); + String url = openGroupInvitation.getUrl(); + String name = openGroupInvitation.getName(); + if (url == null || name == null) { return null; } + // FIXME: Doing toJSON() to get the body here is weird + String body = UpdateMessageData.Companion.buildOpenGroupInvitation(url, name).toJSON(); IncomingTextMessage incomingTextMessage = new IncomingTextMessage(sender, 1, sentTimestamp, body, Optional.absent(), 0, false); incomingTextMessage.isOpenGroupInvitation = true; return incomingTextMessage; diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/OutgoingTextMessage.java b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/OutgoingTextMessage.java index c56c61ba6b..ac5b240404 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/OutgoingTextMessage.java +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/OutgoingTextMessage.java @@ -6,14 +6,12 @@ import org.session.libsession.messaging.threads.recipients.Recipient; import org.session.libsession.messaging.utilities.UpdateMessageData; public class OutgoingTextMessage { - private final Recipient recipient; private final String message; private final int subscriptionId; private final long expiresIn; private final long sentTimestampMillis; - - private boolean isOpenGroupInvitation = false; + private boolean isOpenGroupInvitation = false; public OutgoingTextMessage(Recipient recipient, String message, long expiresIn, int subscriptionId, long sentTimestampMillis) { this.recipient = recipient; @@ -28,7 +26,11 @@ public class OutgoingTextMessage { } public static OutgoingTextMessage fromOpenGroupInvitation(OpenGroupInvitation openGroupInvitation, Recipient recipient, Long sentTimestamp) { - String body = UpdateMessageData.Companion.buildOpenGroupInvitation(openGroupInvitation.getGroupUrl(), openGroupInvitation.getGroupName()).toJSON(); + String url = openGroupInvitation.getUrl(); + String name = openGroupInvitation.getName(); + if (url == null || name == null) { return null; } + // FIXME: Doing toJSON() to get the body here is weird + String body = UpdateMessageData.Companion.buildOpenGroupInvitation(url, name).toJSON(); OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipient, body, 0, -1, sentTimestamp); outgoingTextMessage.isOpenGroupInvitation = true; return outgoingTextMessage; diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/visible/OpenGroupInvitation.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/visible/OpenGroupInvitation.kt index 9896aec836..8c521df067 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/visible/OpenGroupInvitation.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/visible/OpenGroupInvitation.kt @@ -1,42 +1,37 @@ package org.session.libsession.messaging.messages.visible -import org.session.libsession.messaging.messages.control.ControlMessage import org.session.libsignal.service.internal.push.SignalServiceProtos import org.session.libsignal.utilities.logging.Log class OpenGroupInvitation() { + var url: String? = null + var name: String? = null - var groupUrl: String? = null; - var groupName: String? = null; + fun isValid(): Boolean { + return (url != null && name != null) + } companion object { const val TAG = "OpenGroupInvitation" - fun fromProto(proto: SignalServiceProtos.DataMessage.OpenGroupInvitation): OpenGroupInvitation? { - val groupUrl = proto.url - val groupName = proto.name - return OpenGroupInvitation(groupUrl, groupName) + fun fromProto(proto: SignalServiceProtos.DataMessage.OpenGroupInvitation): OpenGroupInvitation { + return OpenGroupInvitation(proto.url, proto.name) } } constructor(url: String?, serverName: String?): this() { - this.groupUrl = url - this.groupName = serverName - } - - fun isValid(): Boolean { - return (groupUrl != null && groupName != null) + this.url = url + this.name = serverName } fun toProto(): SignalServiceProtos.DataMessage.OpenGroupInvitation? { val openGroupInvitationProto = SignalServiceProtos.DataMessage.OpenGroupInvitation.newBuilder() - openGroupInvitationProto.url = groupUrl - openGroupInvitationProto.name = groupName - + openGroupInvitationProto.url = url + openGroupInvitationProto.name = name return try { openGroupInvitationProto.build() } catch (e: Exception) { - Log.w(TAG, "Couldn't construct open group invitation proto from: $this") + Log.w(TAG, "Couldn't construct open group invitation proto from: $this.") null } } diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt index 1e5b77912e..864a919bd1 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt @@ -58,9 +58,9 @@ class VisibleMessage : Message() { result.linkPreview = linkPreview } val openGroupInvitationProto = if (dataMessage.hasOpenGroupInvitation()) dataMessage.openGroupInvitation else null - openGroupInvitationProto?.let { + if (openGroupInvitationProto != null) { val openGroupInvitation = OpenGroupInvitation.fromProto(openGroupInvitationProto) - openGroupInvitation?.let { result.openGroupInvitation = openGroupInvitation} + result.openGroupInvitation = openGroupInvitation } // TODO Contact val profile = Profile.fromProto(dataMessage) @@ -73,7 +73,7 @@ class VisibleMessage : Message() { val proto = SignalServiceProtos.Content.newBuilder() val dataMessage: SignalServiceProtos.DataMessage.Builder // Profile - val profileProto = profile?.let { it.toProto() } + val profileProto = profile?.toProto() if (profileProto != null) { dataMessage = profileProto.toBuilder() } else { @@ -82,19 +82,19 @@ class VisibleMessage : Message() { // Text if (text != null) { dataMessage.body = text } // Quote - val quoteProto = quote?.let { it.toProto() } + val quoteProto = quote?.toProto() if (quoteProto != null) { dataMessage.quote = quoteProto } // Link preview - val linkPreviewProto = linkPreview?.let { it.toProto() } + val linkPreviewProto = linkPreview?.toProto() if (linkPreviewProto != null) { dataMessage.addAllPreview(listOf(linkPreviewProto)) } - //Open group invitation - openGroupInvitation?.let { - val openGroupInvitationProto = it.toProto() - if (openGroupInvitationProto != null) dataMessage.openGroupInvitation = openGroupInvitationProto + // Open group invitation + val openGroupInvitationProto = openGroupInvitation?.toProto() + if (openGroupInvitationProto != null) { + dataMessage.openGroupInvitation = openGroupInvitationProto } // Attachments val database = MessagingModuleConfiguration.shared.messageDataProvider diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt index 46c9d0390b..57c06af221 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt @@ -53,8 +53,7 @@ fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content, } } -//region ControlMessage - +// region Control Messages private fun MessageReceiver.handleReadReceipt(message: ReadReceipt) { val context = MessagingModuleConfiguration.shared.context SSKEnvironment.shared.readReceiptManager.processReadReceipts(context, message.sender!!, message.timestamps!!, message.receivedTimestamp!!) @@ -143,13 +142,9 @@ private fun handleConfigurationMessage(message: ConfigurationMessage) { } storage.addContacts(message.contacts) } - //endregion -//region VisibleMessage - -// Visible message handling - +// region Visible Messages fun MessageReceiver.handleVisibleMessage(message: VisibleMessage, proto: SignalServiceProtos.Content, openGroupID: String?) { val storage = MessagingModuleConfiguration.shared.storage val context = MessagingModuleConfiguration.shared.context @@ -242,11 +237,9 @@ fun MessageReceiver.handleVisibleMessage(message: VisibleMessage, proto: SignalS //Notify the user if needed SSKEnvironment.shared.notificationManager.updateNotification(context, threadID) } - //endregion -//region ClosedGroupControlMessage - +// region Closed Groups private fun MessageReceiver.handleClosedGroupControlMessage(message: ClosedGroupControlMessage) { when (message.kind!!) { is ClosedGroupControlMessage.Kind.New -> handleNewClosedGroup(message) @@ -571,5 +564,4 @@ fun MessageReceiver.disableLocalGroupAndUnsubscribe(groupPublicKey: String, grou // Notify the PN server PushNotificationAPI.performOperation(PushNotificationAPI.ClosedGroupOperation.Unsubscribe, groupPublicKey, userPublicKey) } - -//endregion +// endregion diff --git a/libsession/src/main/java/org/session/libsession/utilities/OpenGroupUrlParser.kt b/libsession/src/main/java/org/session/libsession/utilities/OpenGroupUrlParser.kt index 22e9abae2e..ac7f9ad64f 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/OpenGroupUrlParser.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/OpenGroupUrlParser.kt @@ -33,4 +33,4 @@ object OpenGroupUrlParser { } } -class V2OpenGroupInfo(val server: String, val room: String, val serverPublicKey: String) {} +class V2OpenGroupInfo(val server: String, val room: String, val serverPublicKey: String)