112 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
import Foundation
 | 
						||
 | 
						||
struct SearchDataPayload: Decodable {
 | 
						||
    let users: [UserSearchResult]
 | 
						||
}
 | 
						||
 | 
						||
struct UserSearchResult: Decodable, Identifiable {
 | 
						||
    let userId: UUID
 | 
						||
    let login: String
 | 
						||
    let fullName: String?
 | 
						||
    let customName: String?
 | 
						||
    let createdAt: Date?
 | 
						||
    let profile: SearchProfile?
 | 
						||
 | 
						||
    var id: UUID { userId }
 | 
						||
}
 | 
						||
 | 
						||
struct SearchProfile: Decodable {
 | 
						||
    let userId: UUID
 | 
						||
    let login: String?
 | 
						||
    let fullName: String?
 | 
						||
    let customName: String?
 | 
						||
    let bio: String?
 | 
						||
    let lastSeen: Int?
 | 
						||
    let createdAt: Date?
 | 
						||
}
 | 
						||
 | 
						||
extension UserSearchResult {
 | 
						||
    var displayName: String {
 | 
						||
        if let official = officialFullName {
 | 
						||
            return official
 | 
						||
        }
 | 
						||
        if let custom = preferredCustomName {
 | 
						||
            return custom
 | 
						||
        }
 | 
						||
        if let profileFull = trimmed(profile?.fullName) {
 | 
						||
            return profileFull
 | 
						||
        }
 | 
						||
        if let profileCustom = trimmed(profile?.customName) {
 | 
						||
            return profileCustom
 | 
						||
        }
 | 
						||
        return loginHandle
 | 
						||
    }
 | 
						||
 | 
						||
    var secondaryText: String? {
 | 
						||
        // Отдельное поле для совместимости с существующими вызовами
 | 
						||
//        if let official = officialFullName, official != displayName {
 | 
						||
//            return official
 | 
						||
//        }
 | 
						||
        if let profileLogin = trimmed(profile?.login), profileLogin != login {
 | 
						||
            return "@\(profileLogin)"
 | 
						||
        }
 | 
						||
        return nil
 | 
						||
    }
 | 
						||
 | 
						||
    var officialFullName: String? {
 | 
						||
        trimmed(fullName) ?? trimmed(profile?.fullName)
 | 
						||
    }
 | 
						||
 | 
						||
    var preferredCustomName: String? {
 | 
						||
        trimmed(customName) ?? trimmed(profile?.customName)
 | 
						||
    }
 | 
						||
 | 
						||
    var loginHandle: String {
 | 
						||
        "@\(login)"
 | 
						||
    }
 | 
						||
 | 
						||
    var secondaryLabelForSearch: String? {
 | 
						||
        if let official = officialFullName {
 | 
						||
//            if let custom = preferredCustomName, custom != official {
 | 
						||
//                return custom
 | 
						||
//            }
 | 
						||
            if official != loginHandle {
 | 
						||
                return loginHandle
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        if let secondary = secondaryText, secondary != displayName {
 | 
						||
            return secondary
 | 
						||
        }
 | 
						||
 | 
						||
        if displayName != loginHandle {
 | 
						||
            return loginHandle
 | 
						||
        }
 | 
						||
 | 
						||
        return nil
 | 
						||
    }
 | 
						||
 | 
						||
    var avatarInitial: String {
 | 
						||
        let source = officialFullName
 | 
						||
            ?? preferredCustomName
 | 
						||
            ?? trimmed(profile?.login)
 | 
						||
            ?? login
 | 
						||
 | 
						||
        if let character = source.first(where: { !$0.isWhitespace && $0 != "@" }) {
 | 
						||
            return String(character).uppercased()
 | 
						||
        }
 | 
						||
        return "?"
 | 
						||
    }
 | 
						||
 | 
						||
    var isOfficial: Bool {
 | 
						||
        officialFullName != nil
 | 
						||
    }
 | 
						||
 | 
						||
    private func trimmed(_ value: String?) -> String? {
 | 
						||
        guard let value = value?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else {
 | 
						||
            return nil
 | 
						||
        }
 | 
						||
        return value
 | 
						||
    }
 | 
						||
}
 |