add patch to search

This commit is contained in:
cheykrym 2025-10-07 05:35:10 +03:00
parent 26b8dfc71a
commit a5b2c2702c
2 changed files with 101 additions and 24 deletions

View File

@ -27,28 +27,85 @@ struct SearchProfile: Decodable {
extension UserSearchResult { extension UserSearchResult {
var displayName: String { var displayName: String {
if let customName = customName, !customName.isEmpty { if let custom = preferredCustomName {
return customName return custom
} }
if let fullName = fullName, !fullName.isEmpty { if let official = officialFullName {
return fullName return official
} }
if let profileName = profile?.customName, !profileName.isEmpty { if let profileCustom = trimmed(profile?.customName) {
return profileName return profileCustom
} }
if let profileFullName = profile?.fullName, !profileFullName.isEmpty { if let profileFull = trimmed(profile?.fullName) {
return profileFullName return profileFull
} }
return "@\(login)" return loginHandle
} }
var secondaryText: String? { var secondaryText: String? {
if let fullName = fullName, !fullName.isEmpty, fullName != displayName { // Отдельное поле для совместимости с существующими вызовами
return fullName if let official = officialFullName, official != displayName {
return official
} }
if let profileLogin = profile?.login, !profileLogin.isEmpty, profileLogin != login { if let profileLogin = trimmed(profile?.login), profileLogin != login {
return "@\(profileLogin)" return "@\(profileLogin)"
} }
return nil 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
}
} }

View File

@ -361,22 +361,42 @@ struct ChatsTab: View {
} }
private func globalSearchRow(for user: UserSearchResult) -> some View { private func globalSearchRow(for user: UserSearchResult) -> some View {
VStack(alignment: .leading, spacing: 4) { HStack(spacing: 12) {
Text(user.displayName) Circle()
.font(.headline) .fill(user.isOfficial ? Color.accentColor.opacity(0.85) : Color.accentColor.opacity(0.15))
.frame(width: 44, height: 44)
.overlay(
Text(user.avatarInitial)
.font(.headline)
.foregroundColor(user.isOfficial ? .white : Color.accentColor)
)
if user.displayName != "@\(user.login)" { VStack(alignment: .leading, spacing: 4) {
Text("@\(user.login)") HStack(spacing: 6) {
.font(.subheadline) Text(user.displayName)
.foregroundColor(.secondary) .fontWeight(user.isOfficial ? .semibold : .regular)
} else if let secondary = user.secondaryText { .foregroundColor(.primary)
Text(secondary) .lineLimit(1)
.font(.subheadline) .truncationMode(.tail)
.foregroundColor(.secondary)
if user.isOfficial {
Image(systemName: "checkmark.seal.fill")
.foregroundColor(Color.accentColor)
.font(.caption)
}
}
if let secondary = user.secondaryLabelForSearch {
Text(secondary)
.font(.footnote)
.foregroundColor(.secondary)
.lineLimit(1)
.truncationMode(.tail)
}
} }
.frame(maxWidth: .infinity, alignment: .leading)
} }
.padding(.vertical, 8) .padding(.vertical, 8)
.frame(maxWidth: .infinity, alignment: .leading)
.listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16)) .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16))
} }
} }