|  |  | @ -118,11 +118,18 @@ public final class ClosedGroupsProtocol : NSObject { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 print("[Loki] Can't remove self and others simultaneously.") |  |  |  |                 print("[Loki] Can't remove self and others simultaneously.") | 
			
		
	
		
		
			
				
					
					|  |  |  |                 return Promise(error: Error.invalidUpdate) |  |  |  |                 return Promise(error: Error.invalidUpdate) | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |             // Send the update to the group (don't include new ratchets as everyone should regenerate new ratchets individually) |  |  |  |             // Establish sessions if needed | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.info(groupPublicKey: Data(hex: groupPublicKey), name: name, senderKeys: [], |  |  |  |             establishSessionsIfNeeded(with: [String](members), using: transaction) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 members: membersAsData, admins: adminsAsData) |  |  |  |             // Send the update to the existing members using established channels (don't include new ratchets as everyone should regenerate new ratchets individually) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind) |  |  |  |             let promises: [Promise<Void>] = oldMembers.map { member in | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             SSKEnvironment.shared.messageSender.send(closedGroupUpdateMessage, success: { seal.fulfill(()) }, failure: { seal.reject($0) }) |  |  |  |                 let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 thread.save(with: transaction) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.info(groupPublicKey: Data(hex: groupPublicKey), name: name, senderKeys: [], | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     members: membersAsData, admins: adminsAsData) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 return SSKEnvironment.shared.messageSender.sendPromise(message: closedGroupUpdateMessage) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             when(resolved: promises).done2 { _ in seal.fulfill(()) }.catch2 { seal.reject($0) } | 
			
		
	
		
		
			
				
					
					|  |  |  |             promise.done { |  |  |  |             promise.done { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 try! Storage.writeSync { transaction in |  |  |  |                 try! Storage.writeSync { transaction in | 
			
		
	
		
		
			
				
					
					|  |  |  |                     // Delete all ratchets (it's important that this happens * after * sending out the update) |  |  |  |                     // Delete all ratchets (it's important that this happens * after * sending out the update) | 
			
		
	
	
		
		
			
				
					|  |  | @ -134,8 +141,6 @@ public final class ClosedGroupsProtocol : NSObject { | 
			
		
	
		
		
			
				
					
					|  |  |  |                         // Notify the PN server |  |  |  |                         // Notify the PN server | 
			
		
	
		
		
			
				
					
					|  |  |  |                         LokiPushNotificationManager.performOperation(.unsubscribe, for: groupPublicKey, publicKey: userPublicKey) |  |  |  |                         LokiPushNotificationManager.performOperation(.unsubscribe, for: groupPublicKey, publicKey: userPublicKey) | 
			
		
	
		
		
			
				
					
					|  |  |  |                     } else { |  |  |  |                     } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |                         // Establish sessions if needed |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                         establishSessionsIfNeeded(with: [String](members), using: transaction) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                         // Send closed group update messages to any new members using established channels |  |  |  |                         // Send closed group update messages to any new members using established channels | 
			
		
	
		
		
			
				
					
					|  |  |  |                         for member in newMembers { |  |  |  |                         for member in newMembers { | 
			
		
	
		
		
			
				
					
					|  |  |  |                             let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction) |  |  |  |                             let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction) | 
			
		
	
	
		
		
			
				
					|  |  | @ -203,13 +208,13 @@ public final class ClosedGroupsProtocol : NSObject { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return promise |  |  |  |         return promise | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// The returned promise is fulfilled when the message has been sent **to the group**. It doesn't wait for the user's new ratchet to be distributed. |  |  |  |     /// The returned promise is fulfilled when the group update message has been sent. It doesn't wait for the user's new ratchet to be distributed. | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     @objc(leaveGroupWithPublicKey:transaction:) |  |  |  |     @objc(leaveGroupWithPublicKey:transaction:) | 
			
		
	
		
		
			
				
					
					|  |  |  |     public static func objc_leave(_ groupPublicKey: String, using transaction: YapDatabaseReadWriteTransaction) -> AnyPromise { |  |  |  |     public static func objc_leave(_ groupPublicKey: String, using transaction: YapDatabaseReadWriteTransaction) -> AnyPromise { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return AnyPromise.from(leave(groupPublicKey, using: transaction)) |  |  |  |         return AnyPromise.from(leave(groupPublicKey, using: transaction)) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// The returned promise is fulfilled when the message has been sent **to the group**. It doesn't wait for the user's new ratchet to be distributed. |  |  |  |     /// The returned promise is fulfilled when the group update message has been sent. It doesn't wait for the user's new ratchet to be distributed. | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     public static func leave(_ groupPublicKey: String, using transaction: YapDatabaseReadWriteTransaction) -> Promise<Void> { |  |  |  |     public static func leave(_ groupPublicKey: String, using transaction: YapDatabaseReadWriteTransaction) -> Promise<Void> { | 
			
		
	
		
		
			
				
					
					|  |  |  |         let userPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] ?? getUserHexEncodedPublicKey() |  |  |  |         let userPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] ?? getUserHexEncodedPublicKey() | 
			
		
	
		
		
			
				
					
					|  |  |  |         let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey) |  |  |  |         let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey) | 
			
		
	
	
		
		
			
				
					|  |  | 
 |