| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -15,6 +15,15 @@ final class ConversationTitleView : UIView {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    // MARK: Components
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private lazy var profilePictureView: ProfilePictureView = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let result = ProfilePictureView()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let size = Values.smallProfilePictureSize
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result.set(.width, to: size)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result.set(.height, to: size)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result.size = size
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return result
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private lazy var titleLabel: UILabel = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let result = UILabel()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result.textColor = Colors.text
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -37,6 +46,7 @@ final class ConversationTitleView : UIView {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        super.init(frame: CGRect.zero)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        setUpViewHierarchy()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        updateTitle()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        updateProfilePicture()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        updateSubtitleForCurrentStatus()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let notificationCenter = NotificationCenter.default
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        notificationCenter.addObserver(self, selector: #selector(handleProfileChangedNotification(_:)), name: NSNotification.Name(rawValue: kNSNotificationName_OtherUsersProfileDidChange), object: nil)
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -56,11 +66,13 @@ final class ConversationTitleView : UIView {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private func setUpViewHierarchy() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let stackView = UIStackView(arrangedSubviews: [ titleLabel, subtitleLabel ])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        stackView.axis = .vertical
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let labelStackView = UIStackView(arrangedSubviews: [ titleLabel, subtitleLabel ])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        labelStackView.axis = .vertical
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        labelStackView.alignment = .leading
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let stackView = UIStackView(arrangedSubviews: [ profilePictureView, labelStackView ])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        stackView.axis = .horizontal
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        stackView.alignment = .center
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        stackView.layoutMargins = UIEdgeInsets(top: 4, left: 8, bottom: 4, right: 0) // Compensate for settings button trailing margin
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        stackView.isLayoutMarginsRelativeArrangement = true
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        stackView.spacing = Values.smallSpacing
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        addSubview(stackView)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        stackView.pin(to: self)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -88,11 +100,39 @@ final class ConversationTitleView : UIView {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        titleLabel.text = title
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private func updateProfilePicture() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if let thread = thread as? TSGroupThread {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if thread.name() == "Loki Public Chat" || thread.name() == "Session Public Chat" { // Override the profile picture for the Loki Public Chat and the Session Public Chat
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                profilePictureView.hexEncodedPublicKey = ""
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                profilePictureView.isRSSFeed = true
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            } else if let openGroupProfilePicture = thread.groupModel.groupImage { // An open group with a profile picture
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                profilePictureView.openGroupProfilePicture = openGroupProfilePicture
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                profilePictureView.isRSSFeed = false
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            } else if thread.groupModel.groupType == .openGroup || thread.groupModel.groupType == .rssFeed { // An open group without a profile picture or an RSS feed
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                profilePictureView.hexEncodedPublicKey = ""
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                profilePictureView.isRSSFeed = true
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            } else { // A closed group
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                var users = MentionsManager.userPublicKeyCache[thread.uniqueId!] ?? []
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                users.remove(getUserHexEncodedPublicKey())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                let randomUsers = users.sorted().prefix(2) // Sort to provide a level of stability
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                profilePictureView.hexEncodedPublicKey = randomUsers.count >= 1 ? randomUsers[0] : ""
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                profilePictureView.additionalHexEncodedPublicKey = randomUsers.count >= 2 ? randomUsers[1] : ""
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                profilePictureView.isRSSFeed = false
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        } else { // A one-on-one chat
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            profilePictureView.hexEncodedPublicKey = thread.contactIdentifier()!
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            profilePictureView.additionalHexEncodedPublicKey = nil
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            profilePictureView.isRSSFeed = false
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        profilePictureView.update()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    @objc private func handleProfileChangedNotification(_ notification: Notification) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        guard let hexEncodedPublicKey = notification.userInfo?[kNSNotificationKey_ProfileRecipientId] as? String, let thread = self.thread as? TSContactThread,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            hexEncodedPublicKey == thread.contactIdentifier() else { return }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        updateTitle()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        updateProfilePicture()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    @objc private func handleCalculatingPoWNotification(_ notification: Notification) {
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |