Show when a message was sent using P2P
This commit is contained in:
parent
209996f86d
commit
35f2354327
|
@ -218,7 +218,18 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
timestampLabelText = [DateUtil formatMessageTimestamp:viewItem.interaction.timestamp];
|
||||
}
|
||||
|
||||
self.timestampLabel.text = timestampLabelText.localizedUppercaseString;
|
||||
TSMessage *message = (TSMessage *)[viewItem.interaction as:TSMessage.class];
|
||||
if (message != nil && message.isP2P) {
|
||||
NSString *string = [timestampLabelText.localizedUppercaseString stringByAppendingString:@" · P2P"];
|
||||
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
|
||||
NSRange range = [string rangeOfString:@"P2P"];
|
||||
[attributedString beginEditing];
|
||||
[attributedString addAttribute:NSFontAttributeName value:[UIFont.ows_dynamicTypeCaption1Font ows_bold] range:range];
|
||||
[attributedString endEditing];
|
||||
[self.timestampLabel setAttributedText:attributedString];
|
||||
} else {
|
||||
[self.timestampLabel setText:timestampLabelText.localizedUppercaseString];
|
||||
}
|
||||
}
|
||||
|
||||
- (CGSize)measureWithConversationViewItem:(id<ConversationViewItem>)viewItem
|
||||
|
|
|
@ -53,7 +53,7 @@ import PromiseKit
|
|||
}.map { Set($0) }.retryingIfNeeded(maxRetryCount: maxRetryCount)
|
||||
}
|
||||
|
||||
public static func sendSignalMessage(_ signalMessage: SignalMessage, to destination: String, with timestamp: UInt64) -> Promise<Set<RawResponsePromise>> {
|
||||
public static func sendSignalMessage(_ signalMessage: SignalMessage, to destination: String, with timestamp: UInt64, onP2PSuccess: @escaping () -> Void) -> Promise<Set<RawResponsePromise>> {
|
||||
guard let lokiMessage = Message.from(signalMessage: signalMessage, with: timestamp) else { return Promise(error: Error.messageConversionFailed) }
|
||||
let destination = lokiMessage.destination
|
||||
func sendLokiMessage(_ lokiMessage: Message, to target: Target) -> RawResponsePromise {
|
||||
|
@ -65,12 +65,13 @@ import PromiseKit
|
|||
let swarmPromise = getTargetSnodes(for: destination)
|
||||
return when(fulfilled: powPromise, swarmPromise).map { lokiMessageWithPoW, swarm in
|
||||
return Set(swarm.map { sendLokiMessage(lokiMessageWithPoW, to: $0) })
|
||||
}
|
||||
}.retryingIfNeeded(maxRetryCount: maxRetryCount)
|
||||
}
|
||||
if let p2pState = LokiP2PManager.getState(for: destination), (lokiMessage.isPing || p2pState.isOnline) {
|
||||
let target = Target(address: p2pState.address, port: p2pState.port)
|
||||
if let peer = LokiP2PManager.getInfo(for: destination), (lokiMessage.isPing || peer.isOnline) {
|
||||
let target = Target(address: peer.address, port: peer.port)
|
||||
return Promise.value([ target ]).mapValues { sendLokiMessage(lokiMessage, to: $0) }.map { Set($0) }.retryingIfNeeded(maxRetryCount: maxRetryCount).get { _ in
|
||||
LokiP2PManager.markOnline(destination)
|
||||
onP2PSuccess()
|
||||
}.recover { error -> Promise<Set<RawResponsePromise>> in
|
||||
LokiP2PManager.markOffline(destination)
|
||||
if lokiMessage.isPing {
|
||||
|
@ -82,16 +83,16 @@ import PromiseKit
|
|||
throw error
|
||||
}
|
||||
}
|
||||
return sendLokiMessageUsingSwarmAPI().retryingIfNeeded(maxRetryCount: maxRetryCount)
|
||||
return sendLokiMessageUsingSwarmAPI()
|
||||
}
|
||||
} else {
|
||||
return sendLokiMessageUsingSwarmAPI().retryingIfNeeded(maxRetryCount: maxRetryCount)
|
||||
return sendLokiMessageUsingSwarmAPI()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Public API (Obj-C)
|
||||
@objc public static func objc_sendSignalMessage(_ signalMessage: SignalMessage, to destination: String, with timestamp: UInt64) -> AnyPromise {
|
||||
let promise = sendSignalMessage(signalMessage, to: destination, with: timestamp).mapValues { AnyPromise.from($0) }.map { Set($0) }
|
||||
@objc public static func objc_sendSignalMessage(_ signalMessage: SignalMessage, to destination: String, with timestamp: UInt64, onP2PSuccess: @escaping () -> Void) -> AnyPromise {
|
||||
let promise = sendSignalMessage(signalMessage, to: destination, with: timestamp, onP2PSuccess: onP2PSuccess).mapValues { AnyPromise.from($0) }.map { Set($0) }
|
||||
return AnyPromise.from(promise)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
private static let offlinePingTime = 2 * kMinuteInterval
|
||||
|
||||
/// A p2p state struct
|
||||
internal struct P2PState {
|
||||
internal struct PeerInfo {
|
||||
var address: String
|
||||
var port: UInt16
|
||||
var isOnline: Bool
|
||||
|
@ -20,7 +20,7 @@
|
|||
private static var ourP2PAddress: LokiAPI.Target? = nil
|
||||
|
||||
/// This is where we store the p2p details of our contacts
|
||||
private static var contactP2PStates = [String:P2PState]()
|
||||
private static var peerInfo = [String:PeerInfo]()
|
||||
|
||||
// MARK: - Public functions
|
||||
|
||||
|
@ -46,12 +46,12 @@
|
|||
}
|
||||
|
||||
guard let thread = contactThread else {
|
||||
Logger.warn("[Loki][Ping] Failed to fetch thread for \(pubKey).")
|
||||
Logger.warn("[Loki] Failed to fetch thread when attempting to ping: \(pubKey).")
|
||||
return
|
||||
}
|
||||
|
||||
guard let message = lokiAddressMessage(for: thread, isPing: true) else {
|
||||
Logger.warn("[Loki][Ping] Failed to build ping message for \(pubKey).")
|
||||
guard let message = createLokiAddressMessage(for: thread, isPing: true) else {
|
||||
Logger.warn("[Loki] Failed to build ping message for \(pubKey).")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -77,8 +77,8 @@
|
|||
///
|
||||
/// - Parameter pubKey: The contact hex pubkey
|
||||
/// - Returns: The P2P Details or nil if they don't exist
|
||||
internal static func getState(for hexEncodedPublicKey: String) -> P2PState? {
|
||||
return contactP2PStates[hexEncodedPublicKey]
|
||||
internal static func getInfo(for hexEncodedPublicKey: String) -> PeerInfo? {
|
||||
return peerInfo[hexEncodedPublicKey]
|
||||
}
|
||||
|
||||
/// Get the `LokiAddressMessage` for the given thread.
|
||||
|
@ -86,7 +86,7 @@
|
|||
/// - Parameter thread: The contact thread.
|
||||
/// - Returns: The `LokiAddressMessage` for that thread.
|
||||
@objc public static func onlineBroadcastMessage(forThread thread: TSThread) -> LokiAddressMessage? {
|
||||
return lokiAddressMessage(for: thread, isPing: false)
|
||||
return createLokiAddressMessage(for: thread, isPing: false)
|
||||
}
|
||||
|
||||
/// Handle P2P logic when we receive a `LokiAddressMessage`
|
||||
|
@ -101,17 +101,17 @@
|
|||
let timerDuration = pubKey < ourHexEncodedPubKey ? 1 * kMinuteInterval : 2 * kMinuteInterval
|
||||
|
||||
// Get out current contact details
|
||||
let oldContactDetails = contactP2PStates[pubKey]
|
||||
let oldContactInfo = peerInfo[pubKey]
|
||||
|
||||
// Set the new contact details
|
||||
// A contact is always assumed to be offline unless the specific conditions below are met
|
||||
let details = P2PState(address: address, port: port, isOnline: false, timerDuration: timerDuration, pingTimer: nil)
|
||||
contactP2PStates[pubKey] = details
|
||||
let info = PeerInfo(address: address, port: port, isOnline: false, timerDuration: timerDuration, pingTimer: nil)
|
||||
peerInfo[pubKey] = info
|
||||
|
||||
// Set up our checks
|
||||
let oldContactExists = oldContactDetails != nil
|
||||
let wasOnline = oldContactDetails?.isOnline ?? false
|
||||
let p2pDetailsMatch = oldContactDetails?.address == address && oldContactDetails?.port == port
|
||||
let oldContactExists = oldContactInfo != nil
|
||||
let wasOnline = oldContactInfo?.isOnline ?? false
|
||||
let isPeerInfoMatching = oldContactInfo?.address == address && oldContactInfo?.port == port
|
||||
|
||||
/*
|
||||
We need to check if we should ping the user.
|
||||
|
@ -121,7 +121,7 @@
|
|||
- The old contact was set as `Online`
|
||||
- The new p2p details match the old one
|
||||
*/
|
||||
if oldContactExists && receivedThroughP2P && wasOnline && p2pDetailsMatch {
|
||||
if oldContactExists && receivedThroughP2P && wasOnline && isPeerInfoMatching {
|
||||
setOnline(true, forContact: pubKey)
|
||||
return
|
||||
}
|
||||
|
@ -153,16 +153,16 @@
|
|||
@objc internal static func setOnline(_ isOnline: Bool, forContact pubKey: String) {
|
||||
// Make sure we are on the main thread
|
||||
DispatchQueue.main.async {
|
||||
guard var details = contactP2PStates[pubKey] else { return }
|
||||
guard var info = peerInfo[pubKey] else { return }
|
||||
|
||||
let interval = isOnline ? details.timerDuration : offlinePingTime
|
||||
let interval = isOnline ? info.timerDuration : offlinePingTime
|
||||
|
||||
// Setup a new timer
|
||||
details.pingTimer?.invalidate()
|
||||
details.pingTimer = WeakTimer.scheduledTimer(timeInterval: interval, target: self, userInfo: nil, repeats: true) { _ in ping(contact: pubKey) }
|
||||
details.isOnline = isOnline
|
||||
info.pingTimer?.invalidate()
|
||||
info.pingTimer = WeakTimer.scheduledTimer(timeInterval: interval, target: self, userInfo: nil, repeats: true) { _ in ping(contact: pubKey) }
|
||||
info.isOnline = isOnline
|
||||
|
||||
contactP2PStates[pubKey] = details
|
||||
peerInfo[pubKey] = info
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@
|
|||
return friendThreadIds.compactMap { TSContactThread.fetch(uniqueId: $0) }
|
||||
}
|
||||
|
||||
private static func lokiAddressMessage(for thread: TSThread, isPing: Bool) -> LokiAddressMessage? {
|
||||
private static func createLokiAddressMessage(for thread: TSThread, isPing: Bool) -> LokiAddressMessage? {
|
||||
guard let ourAddress = ourP2PAddress else {
|
||||
Logger.error("P2P Address not set")
|
||||
return nil
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
|
||||
// This is basically OWSMessageServiceParams
|
||||
public typealias SignalMessage = [String:Any]
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef NS_ENUM(NSInteger, LKMessageFriendRequestStatus) {
|
|||
@property (nonatomic) uint64_t friendRequestExpiresAt;
|
||||
@property (nonatomic, readonly) BOOL isFriendRequest;
|
||||
@property (nonatomic, readonly) BOOL hasFriendRequestStatusMessage;
|
||||
@property (nonatomic) BOOL isP2P;
|
||||
// ========
|
||||
|
||||
- (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE;
|
||||
|
|
|
@ -1371,6 +1371,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
linkPreview:linkPreview
|
||||
serverTimestamp:serverTimestamp
|
||||
wasReceivedByUD:wasReceivedByUD];
|
||||
|
||||
if (envelope.isPtpMessage) { incomingMessage.isP2P = YES; }
|
||||
|
||||
NSArray<TSAttachmentPointer *> *attachmentPointers =
|
||||
[TSAttachmentPointer attachmentPointersFromProtos:dataMessage.attachments
|
||||
|
@ -1443,6 +1445,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
serverTimestamp:serverTimestamp
|
||||
wasReceivedByUD:wasReceivedByUD];
|
||||
|
||||
if (envelope.isPtpMessage) { incomingMessage.isP2P = YES; }
|
||||
|
||||
NSArray<TSAttachmentPointer *> *attachmentPointers =
|
||||
[TSAttachmentPointer attachmentPointersFromProtos:dataMessage.attachments albumMessage:incomingMessage];
|
||||
for (TSAttachmentPointer *pointer in attachmentPointers) {
|
||||
|
|
|
@ -1117,6 +1117,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
}
|
||||
}];
|
||||
// Convenience
|
||||
void (^onP2PSuccess)() = ^() { message.isP2P = YES; };
|
||||
void (^handleError)(NSError *error) = ^(NSError *error) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
// Update the thread if needed
|
||||
|
@ -1144,7 +1145,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
[self messageSendDidFail:messageSend deviceMessages:deviceMessages statusCode:statusCode error:error responseData:responseData];
|
||||
};
|
||||
// Convert the message to a Loki message and send it using the Loki API
|
||||
[[LokiAPI objc_sendSignalMessage:signalMessage to:recipient.recipientId with:message.timestamp]
|
||||
[[LokiAPI objc_sendSignalMessage:signalMessage to:recipient.recipientId with:message.timestamp onP2PSuccess:onP2PSuccess]
|
||||
.thenOn(OWSDispatch.sendingQueue, ^(id result) {
|
||||
NSSet<AnyPromise *> *promises = (NSSet<AnyPromise *> *)result;
|
||||
__block BOOL isSuccess = NO;
|
||||
|
|
Loading…
Reference in New Issue