Added getFriendRequestUIState and tests.

pull/175/head
Mikunj 5 years ago
parent 9a08bb8d3b
commit d6ff50fac4

@ -216,7 +216,7 @@ ConversationColorName const kConversationColorName_Default = ConversationColorNa
if (!IsNoteToSelfEnabled()) {
return NO;
}
return [LKSessionProtocol isMessageNoteToSelf:self];
return [LKSessionProtocol isThreadNoteToSelf:self];
}
#pragma mark - To be subclassed.

@ -15,19 +15,25 @@ public final class FriendRequestProtocol : NSObject {
internal static var storage: OWSPrimaryStorage { OWSPrimaryStorage.shared() }
// MARK: - Enums
// FIXME: Better naming :(
@objc public enum FriendRequestUIState : Int {
case friends, received, sent, none
}
// MARK: - General
@objc(shouldInputBarBeEnabledForThread:)
public static func shouldInputBarBeEnabled(for thread: TSThread) -> Bool {
// Friend requests have nothing to do with groups, so if this isn't a contact thread the input bar should be enabled
guard let thread = thread as? TSContactThread else { return true }
// If this is a note to self, the input bar should be enabled
if SessionProtocol.isMessageNoteToSelf(thread) { return true }
if thread.isNoteToSelf() { return true }
let contactID = thread.contactIdentifier()
var friendRequestStatuses: [LKFriendRequestStatus] = []
storage.dbReadConnection.read { transaction in
let linkedDeviceThreads = LokiDatabaseUtilities.getLinkedDeviceThreads(for: contactID, in: transaction)
friendRequestStatuses = linkedDeviceThreads.map { device in
return storage.getFriendRequestStatus(for: device.contactIdentifier(), transaction: transaction)
let linkedDevices = LokiDatabaseUtilities.getLinkedDeviceHexEncodedPublicKeys(for: contactID, in: transaction)
friendRequestStatuses = linkedDevices.map { device in
return storage.getFriendRequestStatus(for: device, transaction: transaction)
}
}
// If the current user is friends with any of the other user's devices, the input bar should be enabled
@ -43,13 +49,13 @@ public final class FriendRequestProtocol : NSObject {
// Friend requests have nothing to do with groups, so if this isn't a contact thread the attachment button should be enabled
guard let thread = thread as? TSContactThread else { return true }
// If this is a note to self, the attachment button should be enabled
if SessionProtocol.isMessageNoteToSelf(thread) { return true }
if thread.isNoteToSelf() { return true }
let contactID = thread.contactIdentifier()
var friendRequestStatuses: [LKFriendRequestStatus] = []
storage.dbReadConnection.read { transaction in
let linkedDeviceThreads = LokiDatabaseUtilities.getLinkedDeviceThreads(for: contactID, in: transaction)
friendRequestStatuses = linkedDeviceThreads.map { thread in
storage.getFriendRequestStatus(for: thread.contactIdentifier(), transaction: transaction)
let linkedDevices = LokiDatabaseUtilities.getLinkedDeviceHexEncodedPublicKeys(for: contactID, in: transaction)
friendRequestStatuses = linkedDevices.map { device in
storage.getFriendRequestStatus(for: device, transaction: transaction)
}
}
// If the current user is friends with any of the other user's devices, the attachment button should be enabled
@ -58,6 +64,27 @@ public final class FriendRequestProtocol : NSObject {
return false
}
@objc(getFriendRequestUIStateForThread:)
public static func getFriendRequestUIState(for thread: TSThread) -> FriendRequestUIState {
// Friend requests have nothing to do with groups
guard let thread = thread as? TSContactThread else { return .none }
// If this is a note to self then we don't want to show the friend request
if thread.isNoteToSelf() { return .none }
var friendRequestStatuses: [LKFriendRequestStatus] = []
storage.dbReadConnection.read { transaction in
let linkedDevices = LokiDatabaseUtilities.getLinkedDeviceHexEncodedPublicKeys(for: thread.contactIdentifier(), in: transaction)
friendRequestStatuses = linkedDevices.map { device in
return storage.getFriendRequestStatus(for: device, transaction: transaction)
}
}
if friendRequestStatuses.contains(where: { $0 == .friends }) { return .friends }
if friendRequestStatuses.contains(where: { $0 == .requestReceived }) { return .received }
if friendRequestStatuses.contains(where: { $0 == .requestSent }) { return .sent }
return .none
}
// MARK: - Sending
@objc(acceptFriendRequestFromHexEncodedPublicKey:using:)
public static func acceptFriendRequest(from hexEncodedPublicKey: String, using transaction: YapDatabaseReadWriteTransaction) {

@ -104,7 +104,7 @@ class FriendRequestProtocolTests : XCTestCase {
func test_shouldInputBarBeEnabledReturnsTrueWhenStatusIsNotPending() {
let validStatuses: [LKFriendRequestStatus] = [.none, .requestExpired, .friends]
let device = Curve25519.generateKeyPair().hexEncodedPublicKey
let device = generateHexEncodedPublicKey()
let thread = createContactThread(for: device)
for status in validStatuses {
@ -117,7 +117,7 @@ class FriendRequestProtocolTests : XCTestCase {
func test_shouldInputBarBeEnabledReturnsFalseWhenStatusIsPending() {
let pendingStatuses: [LKFriendRequestStatus] = [.requestSending, .requestSent, .requestReceived]
let device = Curve25519.generateKeyPair().hexEncodedPublicKey
let device = generateHexEncodedPublicKey()
let thread = createContactThread(for: device)
for status in pendingStatuses {
@ -202,6 +202,25 @@ class FriendRequestProtocolTests : XCTestCase {
}
}
func test_shouldInputBarEnabledShouldStillWorkIfLinkedDeviceThreadDoesNotExist() {
let master = generateHexEncodedPublicKey()
let slave = generateHexEncodedPublicKey()
guard let masterDevice = getDevice(for: master) else { return XCTFail() }
guard let slaveDevice = getDevice(for: slave) else { return XCTFail() }
let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.addDeviceLink(deviceLink, in: transaction)
self.storage.setFriendRequestStatus(.requestSent, for: master, transaction: transaction)
self.storage.setFriendRequestStatus(.friends, for: slave, transaction: transaction)
}
let masterThread = createContactThread(for: master)
XCTAssertTrue(FriendRequestProtocol.shouldInputBarBeEnabled(for: masterThread))
}
// MARK: - shouldAttachmentButtonBeEnabled
func test_shouldAttachmentButtonBeEnabledReturnsTrueOnGroupThread() {
@ -234,7 +253,7 @@ class FriendRequestProtocolTests : XCTestCase {
}
func test_shouldAttachmentButtonBeEnabledReturnsTrueWhenFriends() {
let device = Curve25519.generateKeyPair().hexEncodedPublicKey
let device = generateHexEncodedPublicKey()
let thread = createContactThread(for: device)
storage.dbReadWriteConnection.readWrite { transaction in
@ -245,7 +264,7 @@ class FriendRequestProtocolTests : XCTestCase {
func test_shouldAttachmentButtonBeEnabledReturnsFalseWhenNotFriends() {
let nonFriendStatuses: [LKFriendRequestStatus] = [.requestSending, .requestSent, .requestReceived, .none, .requestExpired]
let device = Curve25519.generateKeyPair().hexEncodedPublicKey
let device = generateHexEncodedPublicKey()
let thread = createContactThread(for: device)
for status in nonFriendStatuses {
@ -277,16 +296,162 @@ class FriendRequestProtocolTests : XCTestCase {
XCTAssertTrue(FriendRequestProtocol.shouldAttachmentButtonBeEnabled(for: slaveThread))
}
func test_shouldAttachmentButtonBeEnabledShouldStillWorkIfLinkedDeviceThreadDoesNotExist() {
let master = generateHexEncodedPublicKey()
let slave = generateHexEncodedPublicKey()
guard let masterDevice = getDevice(for: master) else { return XCTFail() }
guard let slaveDevice = getDevice(for: slave) else { return XCTFail() }
let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.addDeviceLink(deviceLink, in: transaction)
self.storage.setFriendRequestStatus(.none, for: master, transaction: transaction)
self.storage.setFriendRequestStatus(.friends, for: slave, transaction: transaction)
}
let masterThread = createContactThread(for: master)
XCTAssertTrue(FriendRequestProtocol.shouldAttachmentButtonBeEnabled(for: masterThread))
}
// MARK: - getFriendRequestUIState
func test_getFriendRequestUIStateShouldReturnNoneForGroupThreads() {
let allGroupTypes: [GroupType] = [.closedGroup, .openGroup, .rssFeed]
for groupType in allGroupTypes {
guard let groupThread = createGroupThread(groupType: groupType) else { return XCTFail() }
XCTAssertTrue(FriendRequestProtocol.getFriendRequestUIState(for: groupThread) == .none)
}
}
func test_getFriendRequestUIStateShouldReturnNoneOnNoteToSelf() {
guard let master = OWSIdentityManager.shared().identityKeyPair()?.hexEncodedPublicKey else { return XCTFail() }
let slave = generateHexEncodedPublicKey()
guard let masterDevice = getDevice(for: master) else { return XCTFail() }
guard let slaveDevice = getDevice(for: slave) else { return XCTFail() }
let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.addDeviceLink(deviceLink, in: transaction)
self.storage.setFriendRequestStatus(.friends, for: master, transaction: transaction)
self.storage.setFriendRequestStatus(.friends, for: slave, transaction: transaction)
}
let masterThread = createContactThread(for: master)
let slaveThread = createContactThread(for: slave)
XCTAssertTrue(FriendRequestProtocol.getFriendRequestUIState(for: masterThread) == .none)
XCTAssertTrue(FriendRequestProtocol.getFriendRequestUIState(for: slaveThread) == .none )
}
func test_getFriendRequestUIStateShouldReturnTheCorrectStates() {
let bob = generateHexEncodedPublicKey()
let bobThread = createContactThread(for: bob)
let expectedStates: [LKFriendRequestStatus : FriendRequestProtocol.FriendRequestUIState] = [
.none: .none,
.requestExpired: .none,
.requestSending: .none,
.requestSent: .sent,
.requestReceived: .received,
.friends: .friends,
]
for (friendRequestStatus, uiState) in expectedStates {
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.setFriendRequestStatus(friendRequestStatus, for: bob, transaction: transaction)
}
XCTAssertEqual(FriendRequestProtocol.getFriendRequestUIState(for: bobThread), uiState, "Expected FriendRequestUIState to be \(uiState)")
}
}
func test_getFriendRequestUIStateShouldWorkWithMultiDevice() {
let master = generateHexEncodedPublicKey()
let slave = generateHexEncodedPublicKey()
guard let masterDevice = getDevice(for: master) else { return XCTFail() }
guard let slaveDevice = getDevice(for: slave) else { return XCTFail() }
let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.addDeviceLink(deviceLink, in: transaction)
self.storage.setFriendRequestStatus(.none, for: master, transaction: transaction)
}
let masterThread = createContactThread(for: master)
let slaveThread = createContactThread(for: slave)
let expectedStates: [LKFriendRequestStatus : FriendRequestProtocol.FriendRequestUIState] = [
.none: .none,
.requestExpired: .none,
.requestSending: .none,
.requestSent: .sent,
.requestReceived: .received,
.friends: .friends,
]
for (friendRequestStatus, uiState) in expectedStates {
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.setFriendRequestStatus(friendRequestStatus, for: slave, transaction: transaction)
}
XCTAssertEqual(FriendRequestProtocol.getFriendRequestUIState(for: masterThread), uiState, "Expected FriendRequestUIState to be \(uiState.rawValue)")
XCTAssertEqual(FriendRequestProtocol.getFriendRequestUIState(for: slaveThread), uiState, "Expected FriendRequestUIState to be \(uiState.rawValue)")
}
}
func test_getFriendRequestUIStateShouldPreferFriendsOverRequestReceived() {
// Case: We don't want to confuse the user by showing a friend request box when they're already friends
let master = generateHexEncodedPublicKey()
let slave = generateHexEncodedPublicKey()
guard let masterDevice = getDevice(for: master) else { return XCTFail() }
guard let slaveDevice = getDevice(for: slave) else { return XCTFail() }
let masterThread = createContactThread(for: master)
let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.addDeviceLink(deviceLink, in: transaction)
self.storage.setFriendRequestStatus(.requestReceived, for: master, transaction: transaction)
self.storage.setFriendRequestStatus(.friends, for: slave, transaction: transaction)
}
XCTAssertTrue(FriendRequestProtocol.getFriendRequestUIState(for: masterThread) == .friends)
}
func test_getFriendRequestUIStateShouldPreferReceivedOverSent() {
// Case: We sent Bob a friend request and he sent one back to us through another device.
// If something went wrong then we should be able to fallback to manually accepting the friend request even if we sent one.
let master = generateHexEncodedPublicKey()
let slave = generateHexEncodedPublicKey()
guard let masterDevice = getDevice(for: master) else { return XCTFail() }
guard let slaveDevice = getDevice(for: slave) else { return XCTFail() }
let masterThread = createContactThread(for: master)
let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.addDeviceLink(deviceLink, in: transaction)
self.storage.setFriendRequestStatus(.requestSent, for: master, transaction: transaction)
self.storage.setFriendRequestStatus(.requestReceived, for: slave, transaction: transaction)
}
XCTAssertTrue(FriendRequestProtocol.getFriendRequestUIState(for: masterThread) == .received)
}
// MARK: - acceptFriendRequest
// TODO: Add test to see if message was sent?
func test_acceptFriendRequestShouldSetStatusToFriendsIfWeReceivedAFriendRequest() {
// Case: Bob sent us a friend request, we should become friends with him on accepting
let bob = Curve25519.generateKeyPair().hexEncodedPublicKey
let bob = generateHexEncodedPublicKey()
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.setFriendRequestStatus(.requestReceived, for: bob, transaction: transaction)
}
storage.dbReadWriteConnection.readWrite { transaction in
@ -300,7 +465,7 @@ class FriendRequestProtocolTests : XCTestCase {
// Since user accepted then we should send a friend request message
let statuses: [LKFriendRequestStatus] = [.none, .requestExpired]
for status in statuses {
let bob = Curve25519.generateKeyPair().hexEncodedPublicKey
let bob = generateHexEncodedPublicKey()
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.setFriendRequestStatus(status, for: bob, transaction: transaction)
}
@ -315,7 +480,7 @@ class FriendRequestProtocolTests : XCTestCase {
func test_acceptFriendRequestShouldNotDoAnythingIfRequestHasBeenSent() {
// Case: We sent Bob a friend request.
// We can't accept because we don't have keys to communicate with Bob.
let bob = Curve25519.generateKeyPair().hexEncodedPublicKey
let bob = generateHexEncodedPublicKey()
storage.dbReadWriteConnection.readWrite { transaction in
self.storage.setFriendRequestStatus(.requestSent, for: bob, transaction: transaction)

@ -67,8 +67,8 @@ public final class SessionProtocol : NSObject {
// TODO: Check that the behaviors described above make sense
@objc(isMessageNoteToSelf:)
public static func isMessageNoteToSelf(_ thread: TSThread) -> Bool {
@objc(isThreadNoteToSelf:)
public static func isThreadNoteToSelf(_ thread: TSThread) -> Bool {
guard let thread = thread as? TSContactThread else { return false }
var isNoteToSelf = false
storage.dbReadConnection.read { transaction in
@ -101,14 +101,14 @@ public final class SessionProtocol : NSObject {
/// send them if certain conditions are met.
@objc(shouldSendTypingIndicatorForThread:)
public static func shouldSendTypingIndicator(for thread: TSThread) -> Bool {
return !thread.isGroupThread() && !isMessageNoteToSelf(thread)
return !thread.isGroupThread() && !isThreadNoteToSelf(thread)
}
// MARK: Receipts
// Used from OWSReadReceiptManager
@objc(shouldSendReadReceiptForThread:)
public static func shouldSendReadReceipt(for thread: TSThread) -> Bool {
return !isMessageNoteToSelf(thread) && !thread.isGroupThread()
return !isThreadNoteToSelf(thread) && !thread.isGroupThread()
}
// TODO: Not sure how these two relate. EDIT: I think the one below is used to block delivery receipts. That means that

Loading…
Cancel
Save