From bd04775cbf094f29968d6198784d0cc2227235a0 Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Mon, 3 May 2021 15:13:18 +1000 Subject: [PATCH] Implement open group invitations UI --- Session.xcodeproj/project.pbxproj | 8 ++ .../OpenGroupInvitationView.swift | 78 +++++++++++++++++++ .../Message Cells/VisibleMessageCell.swift | 8 +- .../File Server/FileServerAPIV2.swift | 2 + SessionMessagingKit/Jobs/Job.swift | 2 +- .../ConfigurationMessage.swift | 10 +-- .../ExpirationTimerUpdate.swift | 2 +- .../Signal/TSIncomingMessage+Conversion.swift | 4 +- .../Messages/Signal/TSIncomingMessage.h | 4 +- .../Messages/Signal/TSIncomingMessage.m | 6 +- .../Messages/Signal/TSInfoMessage.m | 4 +- .../Messages/Signal/TSMessage.h | 6 +- .../Messages/Signal/TSMessage.m | 4 + .../Signal/TSOutgoingMessage+Conversion.swift | 4 +- .../Messages/Signal/TSOutgoingMessage.h | 4 +- .../Messages/Signal/TSOutgoingMessage.m | 14 +++- .../VisibleMessage+LinkPreview.swift | 4 +- .../VisibleMessage+OpenGroupInvitation.swift | 43 ++++++++++ .../VisibleMessage+Profile.swift | 4 +- .../VisibleMessage+Quote.swift | 6 +- .../Visible Messages/VisibleMessage.swift | 15 ++-- .../Sending & Receiving/MessageReceiver.swift | 32 ++++---- .../Sending & Receiving/MessageSender.swift | 6 +- .../Pollers/ClosedGroupPoller.swift | 2 +- .../Pollers/OpenGroupPoller.swift | 2 +- .../Sending & Receiving/Pollers/Poller.swift | 2 +- 26 files changed, 221 insertions(+), 55 deletions(-) create mode 100644 Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift create mode 100644 SessionMessagingKit/Messages/Visible Messages/VisibleMessage+OpenGroupInvitation.swift diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 687fe8f63..6cc48e38b 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -268,6 +268,8 @@ B8D64FCB25BA78A90029CFC0 /* SignalUtilitiesKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C33FD9AB255A548A00E217F9 /* SignalUtilitiesKit.framework */; }; B8D84EA325DF745A005A043E /* LinkPreviewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8D84EA225DF745A005A043E /* LinkPreviewState.swift */; }; B8D84ECF25E3108A005A043E /* ExpandingAttachmentsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8D84ECE25E3108A005A043E /* ExpandingAttachmentsButton.swift */; }; + B8EB20EE2640F28000773E52 /* VisibleMessage+OpenGroupInvitation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8EB20ED2640F28000773E52 /* VisibleMessage+OpenGroupInvitation.swift */; }; + B8EB20F02640F7F000773E52 /* OpenGroupInvitationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8EB20EF2640F7F000773E52 /* OpenGroupInvitationView.swift */; }; B8F5F52925EC4F8A003BF8D4 /* BlockListUIUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = B8F5F52825EC4F8A003BF8D4 /* BlockListUIUtils.m */; }; B8F5F54E25EC50A5003BF8D4 /* BlockListUIUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = B8F5F52725EC4F6A003BF8D4 /* BlockListUIUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; B8F5F56525EC8453003BF8D4 /* Notification+Contacts.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F5F56425EC8453003BF8D4 /* Notification+Contacts.swift */; }; @@ -1252,6 +1254,8 @@ B8D8F1BC25661C6F0092EF10 /* Storage+OnionRequests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+OnionRequests.swift"; sourceTree = ""; }; B8D8F1EF256621180092EF10 /* MessageSender+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "MessageSender+Convenience.swift"; path = "../../SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift"; sourceTree = ""; }; B8EB20E6263F7E4B00773E52 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Localizable.strings; sourceTree = ""; }; + B8EB20ED2640F28000773E52 /* VisibleMessage+OpenGroupInvitation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VisibleMessage+OpenGroupInvitation.swift"; sourceTree = ""; }; + B8EB20EF2640F7F000773E52 /* OpenGroupInvitationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupInvitationView.swift; sourceTree = ""; }; B8F5F52725EC4F6A003BF8D4 /* BlockListUIUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BlockListUIUtils.h; sourceTree = ""; }; B8F5F52825EC4F8A003BF8D4 /* BlockListUIUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BlockListUIUtils.m; sourceTree = ""; }; B8F5F56425EC8453003BF8D4 /* Notification+Contacts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+Contacts.swift"; sourceTree = ""; }; @@ -2110,6 +2114,7 @@ B8569AE225CBB19A00DBA3DB /* DocumentView.swift */, B849789525D4A2F500D0D0B3 /* LinkPreviewView.swift */, B8D84EA225DF745A005A043E /* LinkPreviewState.swift */, + B8EB20EF2640F7F000773E52 /* OpenGroupInvitationView.swift */, ); path = "Content Views"; sourceTree = ""; @@ -2380,6 +2385,7 @@ C3C2A75E2553A3C500C340D1 /* VisibleMessage+LinkPreview.swift */, C3C2A7672553A3D900C340D1 /* VisibleMessage+Contact.swift */, C300A5B12554AF9800555489 /* VisibleMessage+Profile.swift */, + B8EB20ED2640F28000773E52 /* VisibleMessage+OpenGroupInvitation.swift */, ); path = "Visible Messages"; sourceTree = ""; @@ -4732,6 +4738,7 @@ C3C2A7852553AAF300C340D1 /* SessionProtos.pb.swift in Sources */, B8566C63256F55930045A0B9 /* OWSLinkPreview+Conversion.swift in Sources */, C32C5B3F256DC1DF003C73A2 /* TSQuotedMessage+Conversion.swift in Sources */, + B8EB20EE2640F28000773E52 /* VisibleMessage+OpenGroupInvitation.swift in Sources */, C3C2A7712553A41E00C340D1 /* ControlMessage.swift in Sources */, C32C5D19256DD493003C73A2 /* OWSLinkPreview.swift in Sources */, C32C5CF0256DD3E4003C73A2 /* Storage+Shared.swift in Sources */, @@ -4971,6 +4978,7 @@ 45E5A6991F61E6DE001E4A8A /* MarqueeLabel.swift in Sources */, C302093E25DCBF08001F572D /* MentionSelectionView.swift in Sources */, C328251F25CA3A900062D0A7 /* QuoteView.swift in Sources */, + B8EB20F02640F7F000773E52 /* OpenGroupInvitationView.swift in Sources */, B86BD08423399ACF000F5AE3 /* Modal.swift in Sources */, C328254025CA55880062D0A7 /* ContextMenuVC.swift in Sources */, 3427C64320F500E000EEC730 /* OWSMessageTimerView.m in Sources */, diff --git a/Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift b/Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift new file mode 100644 index 000000000..30b5d56fa --- /dev/null +++ b/Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift @@ -0,0 +1,78 @@ + +final class OpenGroupInvitationView : UIView { + private let name: String + private let rawURL: String + private let textColor: UIColor + + private lazy var url: String = { + if let range = rawURL.range(of: "?public_key=") { + return String(rawURL[.. Profile? { + notImplemented() + } + + public func toProto() -> SNProtoDataMessage? { + notImplemented() + } + + // MARK: Description + public override var description: String { + """ + OpenGroupInvitation( + name: \(name ?? "null"), + url: \(url ?? "null") + ) + """ + } + } +} diff --git a/SessionMessagingKit/Messages/Visible Messages/VisibleMessage+Profile.swift b/SessionMessagingKit/Messages/Visible Messages/VisibleMessage+Profile.swift index 71bec53c3..d9e82f7e5 100644 --- a/SessionMessagingKit/Messages/Visible Messages/VisibleMessage+Profile.swift +++ b/SessionMessagingKit/Messages/Visible Messages/VisibleMessage+Profile.swift @@ -62,8 +62,8 @@ public extension VisibleMessage { public override var description: String { """ Profile( - displayName: \(displayName ?? "null") - profileKey: \(profileKey?.description ?? "null") + displayName: \(displayName ?? "null"), + profileKey: \(profileKey?.description ?? "null"), profilePictureURL: \(profilePictureURL ?? "null") ) """ diff --git a/SessionMessagingKit/Messages/Visible Messages/VisibleMessage+Quote.swift b/SessionMessagingKit/Messages/Visible Messages/VisibleMessage+Quote.swift index 2f818fdcd..2a0f9bf93 100644 --- a/SessionMessagingKit/Messages/Visible Messages/VisibleMessage+Quote.swift +++ b/SessionMessagingKit/Messages/Visible Messages/VisibleMessage+Quote.swift @@ -88,9 +88,9 @@ public extension VisibleMessage { public override var description: String { """ Quote( - timestamp: \(timestamp?.description ?? "null") - publicKey: \(publicKey ?? "null") - text: \(text ?? "null") + timestamp: \(timestamp?.description ?? "null"), + publicKey: \(publicKey ?? "null"), + text: \(text ?? "null"), attachmentID: \(attachmentID ?? "null") ) """ diff --git a/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift b/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift index 9e6e4e020..a8d856382 100644 --- a/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift +++ b/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift @@ -12,6 +12,7 @@ public final class VisibleMessage : Message { @objc public var linkPreview: LinkPreview? @objc public var contact: Contact? @objc public var profile: Profile? + @objc public var openGroupInvitation: OpenGroupInvitation? public override var isSelfSendValid: Bool { true } @@ -22,6 +23,7 @@ public final class VisibleMessage : Message { public override var isValid: Bool { guard super.isValid else { return false } if !attachmentIDs.isEmpty { return true } + if openGroupInvitation != nil { return true } if let text = text?.trimmingCharacters(in: .whitespacesAndNewlines), !text.isEmpty { return true } return false } @@ -36,6 +38,7 @@ public final class VisibleMessage : Message { if let linkPreview = coder.decodeObject(forKey: "linkPreview") as! LinkPreview? { self.linkPreview = linkPreview } // TODO: Contact if let profile = coder.decodeObject(forKey: "profile") as! Profile? { self.profile = profile } + if let openGroupInvitation = coder.decodeObject(forKey: "openGroupInvitation") as! OpenGroupInvitation? { self.openGroupInvitation = openGroupInvitation } } public override func encode(with coder: NSCoder) { @@ -47,6 +50,7 @@ public final class VisibleMessage : Message { coder.encode(linkPreview, forKey: "linkPreview") // TODO: Contact coder.encode(profile, forKey: "profile") + coder.encode(openGroupInvitation, forKey: "openGroupInvitation") } // MARK: Proto Conversion @@ -128,12 +132,13 @@ public final class VisibleMessage : Message { public override var description: String { """ VisibleMessage( - text: \(text ?? "null") - attachmentIDs: \(attachmentIDs) - quote: \(quote?.description ?? "null") - linkPreview: \(linkPreview?.description ?? "null") - contact: \(contact?.description ?? "null") + text: \(text ?? "null"), + attachmentIDs: \(attachmentIDs), + quote: \(quote?.description ?? "null"), + linkPreview: \(linkPreview?.description ?? "null"), + contact: \(contact?.description ?? "null"), profile: \(profile?.description ?? "null") + "openGroupInvitation": \(openGroupInvitation?.description ?? "null") ) """ } diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift index 3547681f3..cf724fe9f 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift @@ -92,22 +92,22 @@ public enum MessageReceiver { } groupPublicKey = envelope.source try decrypt() - -// do { -// try decrypt() -// } catch { -// do { -// let now = Date() -// // Don't spam encryption key pair requests -// let shouldRequestEncryptionKeyPair = given(lastEncryptionKeyPairRequest[groupPublicKey!]) { now.timeIntervalSince($0) > 30 } ?? true -// if shouldRequestEncryptionKeyPair { -// try MessageSender.requestEncryptionKeyPair(for: groupPublicKey!, using: transaction as! YapDatabaseReadWriteTransaction) -// lastEncryptionKeyPairRequest[groupPublicKey!] = now -// } -// } -// throw error // Throw the * decryption * error and not the error generated by requestEncryptionKeyPair (if it generated one) -// } - + /* + do { + try decrypt() + } catch { + do { + let now = Date() + // Don't spam encryption key pair requests + let shouldRequestEncryptionKeyPair = given(lastEncryptionKeyPairRequest[groupPublicKey!]) { now.timeIntervalSince($0) > 30 } ?? true + if shouldRequestEncryptionKeyPair { + try MessageSender.requestEncryptionKeyPair(for: groupPublicKey!, using: transaction as! YapDatabaseReadWriteTransaction) + lastEncryptionKeyPairRequest[groupPublicKey!] = now + } + } + throw error // Throw the * decryption * error and not the error generated by requestEncryptionKeyPair (if it generated one) + } + */ default: throw Error.unknownEnvelopeType } } diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index fe737b2ef..eb7be10e8 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -9,7 +9,6 @@ public final class MessageSender : NSObject { public enum Error : LocalizedError { case invalidMessage case protoConversionFailed - case proofOfWorkCalculationFailed case noUserX25519KeyPair case noUserED25519KeyPair case signingFailed @@ -22,7 +21,7 @@ public final class MessageSender : NSObject { internal var isRetryable: Bool { switch self { - case .invalidMessage, .protoConversionFailed, .proofOfWorkCalculationFailed, .invalidClosedGroupUpdate, .signingFailed, .encryptionFailed: return false + case .invalidMessage, .protoConversionFailed, .invalidClosedGroupUpdate, .signingFailed, .encryptionFailed: return false default: return true } } @@ -31,7 +30,6 @@ public final class MessageSender : NSObject { switch self { case .invalidMessage: return "Invalid message." case .protoConversionFailed: return "Couldn't convert message to proto." - case .proofOfWorkCalculationFailed: return "Proof of work calculation failed." case .noUserX25519KeyPair: return "Couldn't find user X25519 key pair." case .noUserED25519KeyPair: return "Couldn't find user ED25519 key pair." case .signingFailed: return "Couldn't sign message." @@ -48,8 +46,6 @@ public final class MessageSender : NSObject { // MARK: Initialization private override init() { } - public static let shared = MessageSender() // FIXME: Remove once requestSenderKey is static - // MARK: Preparation public static func prep(_ signalAttachments: [SignalAttachment], for message: VisibleMessage, using transaction: YapDatabaseReadWriteTransaction) { guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { diff --git a/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift index 89283dd03..111d57152 100644 --- a/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift +++ b/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift @@ -7,7 +7,7 @@ public final class ClosedGroupPoller : NSObject { private var timer: Timer? // MARK: Settings - private static let pollInterval: TimeInterval = 2 + private static let pollInterval: TimeInterval = 3 // MARK: Error private enum Error : LocalizedError { diff --git a/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift index 2a1c5286e..4dfc780a0 100644 --- a/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift +++ b/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift @@ -18,7 +18,7 @@ public final class OpenGroupPoller : NSObject { } // MARK: Settings - private let pollForNewMessagesInterval: TimeInterval = 4 + private let pollForNewMessagesInterval: TimeInterval = 8 private let pollForDeletedMessagesInterval: TimeInterval = 30 private let pollForModeratorsInterval: TimeInterval = 10 * 60 diff --git a/SessionMessagingKit/Sending & Receiving/Pollers/Poller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/Poller.swift index 6c338c0c4..85da45a78 100644 --- a/SessionMessagingKit/Sending & Receiving/Pollers/Poller.swift +++ b/SessionMessagingKit/Sending & Receiving/Pollers/Poller.swift @@ -9,7 +9,7 @@ public final class Poller : NSObject { private var pollCount = 0 // MARK: Settings - private static let pollInterval: TimeInterval = 1 + private static let pollInterval: TimeInterval = 1.5 private static let retryInterval: TimeInterval = 0.25 /// After polling a given snode this many times we always switch to a new one. ///