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 custom = preferredCustomName {
|
||
return custom
|
||
}
|
||
if let official = officialFullName {
|
||
return official
|
||
}
|
||
if let profileCustom = trimmed(profile?.customName) {
|
||
return profileCustom
|
||
}
|
||
if let profileFull = trimmed(profile?.fullName) {
|
||
return profileFull
|
||
}
|
||
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
|
||
}
|
||
}
|