mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			123 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			123 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Swift
		
	
| // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
 | |
| 
 | |
| import Foundation
 | |
| import GRDB
 | |
| import SessionUIKit
 | |
| import SessionMessagingKit
 | |
| 
 | |
| public enum MentionUtilities {
 | |
|     public static func highlightMentionsNoAttributes(
 | |
|         in string: String,
 | |
|         threadVariant: SessionThread.Variant,
 | |
|         currentUserPublicKey: String,
 | |
|         currentUserBlinded15PublicKey: String?,
 | |
|         currentUserBlinded25PublicKey: String?
 | |
|     ) -> String {
 | |
|         /// **Note:** We are returning the string here so the 'textColor' and 'primaryColor' values are irrelevant
 | |
|         return highlightMentions(
 | |
|             in: string,
 | |
|             threadVariant: threadVariant,
 | |
|             currentUserPublicKey: currentUserPublicKey,
 | |
|             currentUserBlinded15PublicKey: currentUserBlinded15PublicKey,
 | |
|             currentUserBlinded25PublicKey: currentUserBlinded25PublicKey,
 | |
|             isOutgoingMessage: false,
 | |
|             textColor: .black,
 | |
|             theme: .classicDark,
 | |
|             primaryColor: Theme.PrimaryColor.green,
 | |
|             attributes: [:]
 | |
|         ).string
 | |
|     }
 | |
| 
 | |
|     public static func highlightMentions(
 | |
|         in string: String,
 | |
|         threadVariant: SessionThread.Variant,
 | |
|         currentUserPublicKey: String?,
 | |
|         currentUserBlinded15PublicKey: String?,
 | |
|         currentUserBlinded25PublicKey: String?,
 | |
|         isOutgoingMessage: Bool,
 | |
|         textColor: UIColor,
 | |
|         theme: Theme,
 | |
|         primaryColor: Theme.PrimaryColor,
 | |
|         attributes: [NSAttributedString.Key: Any]
 | |
|     ) -> NSAttributedString {
 | |
|         guard
 | |
|             let regex: NSRegularExpression = try? NSRegularExpression(pattern: "@[0-9a-fA-F]{66}", options: []) // stringlint:disable
 | |
|         else {
 | |
|             return NSAttributedString(string: string)
 | |
|         }
 | |
|         
 | |
|         var string = string
 | |
|         var lastMatchEnd: Int = 0
 | |
|         var mentions: [(range: NSRange, isCurrentUser: Bool)] = []
 | |
|         let currentUserPublicKeys: Set<String> = [
 | |
|             currentUserPublicKey,
 | |
|             currentUserBlinded15PublicKey,
 | |
|             currentUserBlinded25PublicKey
 | |
|         ]
 | |
|         .compactMap { $0 }
 | |
|         .asSet()
 | |
|         
 | |
|         while let match: NSTextCheckingResult = regex.firstMatch(
 | |
|             in: string,
 | |
|             options: .withoutAnchoringBounds,
 | |
|             range: NSRange(location: lastMatchEnd, length: string.utf16.count - lastMatchEnd)
 | |
|         ) {
 | |
|             guard let range: Range = Range(match.range, in: string) else { break }
 | |
|             
 | |
|             let publicKey: String = String(string[range].dropFirst()) // Drop the @
 | |
|             let isCurrentUser: Bool = currentUserPublicKeys.contains(publicKey)
 | |
|             
 | |
|             guard let targetString: String = {
 | |
|                 guard !isCurrentUser else { return "onionRoutingPathYou".localized() }
 | |
|                 guard let displayName: String = Profile.displayNameNoFallback(id: publicKey, threadVariant: threadVariant) else {
 | |
|                     lastMatchEnd = (match.range.location + match.range.length)
 | |
|                     return nil
 | |
|                 }
 | |
|                 
 | |
|                 return displayName
 | |
|             }()
 | |
|             else { continue }
 | |
|             
 | |
|             string = string.replacingCharacters(in: range, with: "@\(targetString)") // stringlint:disable
 | |
|             lastMatchEnd = (match.range.location + targetString.utf16.count)
 | |
|             
 | |
|             mentions.append((
 | |
|                 // + 1 to include the @
 | |
|                 range: NSRange(location: match.range.location, length: targetString.utf16.count + 1),
 | |
|                 isCurrentUser: isCurrentUser
 | |
|             ))
 | |
|         }
 | |
|         
 | |
|         let sizeDiff: CGFloat = (Values.smallFontSize / Values.mediumFontSize)
 | |
|         let result: NSMutableAttributedString = NSMutableAttributedString(string: string, attributes: attributes)
 | |
|         mentions.forEach { mention in
 | |
|             result.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: Values.smallFontSize), range: mention.range)
 | |
|             
 | |
|             if mention.isCurrentUser {
 | |
|                 // Note: The designs don't match with the dynamic sizing so these values need to be calculated
 | |
|                 // to maintain a "rounded rect" effect rather than a "pill" effect
 | |
|                 result.addAttribute(.currentUserMentionBackgroundCornerRadius, value: (8 * sizeDiff), range: mention.range)
 | |
|                 result.addAttribute(.currentUserMentionBackgroundPadding, value: (3 * sizeDiff), range: mention.range)
 | |
|                 result.addAttribute(.currentUserMentionBackgroundColor, value: primaryColor.color, range: mention.range)
 | |
|                 result.addAttribute(
 | |
|                     .foregroundColor,
 | |
|                     value: UIColor.black,   // Note: This text should always be black
 | |
|                     range: mention.range
 | |
|                 )
 | |
|             }
 | |
|             else {
 | |
|                 result.addAttribute(
 | |
|                     .foregroundColor,
 | |
|                     value: (isOutgoingMessage || theme.interfaceStyle == .light ?
 | |
|                         textColor :
 | |
|                         primaryColor.color
 | |
|                     ),
 | |
|                     range: mention.range
 | |
|                 )
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return result
 | |
|     }
 | |
| }
 |