Compare commits
3 Commits
048b9eaf1c
...
fa10e389cd
| Author | SHA1 | Date | |
|---|---|---|---|
| fa10e389cd | |||
| c7f51b30cd | |||
| fc3a534496 |
@ -3,4 +3,22 @@
|
||||
uuid = "AEE1609A-17B4-4FCC-80A6-0D556940F4D7"
|
||||
type = "1"
|
||||
version = "2.0">
|
||||
<Breakpoints>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "09699199-8124-4F89-892D-6880A0EB7C04"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "yobble/Views/Contacts/ContactEditView.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "74"
|
||||
endingLineNumber = "74"
|
||||
landmarkName = "ContactEditView"
|
||||
landmarkType = "14">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
||||
|
||||
@ -97,8 +97,8 @@ struct ContactAddView: View {
|
||||
|
||||
private var avatarInitial: String {
|
||||
let trimmedName = displayName.trimmedNonEmpty ?? contact.preferredName
|
||||
if let first = trimmedName.trimmingCharacters(in: .whitespacesAndNewlines).first {
|
||||
return String(first).uppercased()
|
||||
if let initials = initials(from: trimmedName) {
|
||||
return initials
|
||||
}
|
||||
if let login = contact.login?.trimmingCharacters(in: .whitespacesAndNewlines), !login.isEmpty {
|
||||
return String(login.prefix(1)).uppercased()
|
||||
@ -185,3 +185,12 @@ private extension String {
|
||||
return value.isEmpty ? nil : value
|
||||
}
|
||||
}
|
||||
|
||||
private func initials(from text: String) -> String? {
|
||||
let components = text
|
||||
.split { $0.isWhitespace }
|
||||
.filter { !$0.isEmpty }
|
||||
let letters = components.prefix(2).compactMap { $0.first }
|
||||
guard !letters.isEmpty else { return nil }
|
||||
return letters.map { String($0).uppercased() }.joined()
|
||||
}
|
||||
|
||||
@ -203,8 +203,8 @@ struct ContactEditView: View {
|
||||
|
||||
private var avatarInitial: String {
|
||||
let trimmedName = displayName.trimmedNonEmpty ?? contact.preferredName
|
||||
if let first = trimmedName.trimmingCharacters(in: .whitespacesAndNewlines).first {
|
||||
return String(first).uppercased()
|
||||
if let initials = initials(from: trimmedName) {
|
||||
return initials
|
||||
}
|
||||
if let login = contact.login?.trimmingCharacters(in: .whitespacesAndNewlines), !login.isEmpty {
|
||||
return String(login.prefix(1)).uppercased()
|
||||
@ -336,3 +336,12 @@ private extension String {
|
||||
return value.isEmpty ? nil : value
|
||||
}
|
||||
}
|
||||
|
||||
private func initials(from text: String) -> String? {
|
||||
let components = text
|
||||
.split { $0.isWhitespace }
|
||||
.filter { !$0.isEmpty }
|
||||
let letters = components.prefix(2).compactMap { $0.first }
|
||||
guard !letters.isEmpty else { return nil }
|
||||
return letters.map { String($0).uppercased() }.joined()
|
||||
}
|
||||
|
||||
@ -22,9 +22,10 @@ struct EditProfileView: View {
|
||||
@State private var avatarViewerState: AvatarViewerState?
|
||||
@State private var shareItems: [Any] = []
|
||||
@State private var showShareSheet = false
|
||||
|
||||
|
||||
private let profileService = ProfileService()
|
||||
private let descriptionLimit = 1024
|
||||
private let nameLimit = 32
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
@ -75,13 +76,18 @@ struct EditProfileView: View {
|
||||
|
||||
Section(header: Text("Публичная информация")) {
|
||||
TextField("Отображаемое имя", text: $displayName)
|
||||
.onChange(of: displayName) { newValue in
|
||||
if newValue.count > nameLimit {
|
||||
displayName = String(newValue.prefix(nameLimit))
|
||||
}
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("Описание")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
TextEditor(text: $description)
|
||||
.frame(height: 150)
|
||||
Text("Описание")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
TextEditor(text: $description)
|
||||
.frame(height: 150)
|
||||
.onChange(of: description) { newValue in
|
||||
if newValue.count > descriptionLimit {
|
||||
description = String(newValue.prefix(descriptionLimit))
|
||||
@ -154,11 +160,27 @@ struct EditProfileView: View {
|
||||
.fill(Color.secondary.opacity(0.2))
|
||||
.frame(width: 120, height: 120)
|
||||
.overlay(
|
||||
Image(systemName: "person.fill")
|
||||
.font(.system(size: 60))
|
||||
Text(profileInitials)
|
||||
.font(.system(size: 48, weight: .semibold))
|
||||
.foregroundColor(.gray)
|
||||
)
|
||||
}
|
||||
|
||||
private var profileInitials: String {
|
||||
if let initials = initials(from: displayName) {
|
||||
return initials
|
||||
}
|
||||
if let profile = profile,
|
||||
let name = profile.fullName?.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!name.isEmpty,
|
||||
let initials = initials(from: name) {
|
||||
return initials
|
||||
}
|
||||
if let username = profile?.login.trimmingCharacters(in: .whitespacesAndNewlines), !username.isEmpty {
|
||||
return String(username.prefix(1)).uppercased()
|
||||
}
|
||||
return "?"
|
||||
}
|
||||
|
||||
private func avatarUrl(for profile: ProfileDataPayload, fileId: String) -> URL? {
|
||||
return URL(string: "\(AppConfig.API_SERVER)/v1/storage/download/avatar/\(profile.userId)?file_id=\(fileId)")
|
||||
@ -360,6 +382,15 @@ struct EditProfileView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private func initials(from text: String) -> String? {
|
||||
let components = text
|
||||
.split { $0.isWhitespace }
|
||||
.filter { !$0.isEmpty }
|
||||
let letters = components.prefix(2).compactMap { $0.first }
|
||||
guard !letters.isEmpty else { return nil }
|
||||
return letters.map { String($0).uppercased() }.joined()
|
||||
}
|
||||
|
||||
struct ImagePicker: UIViewControllerRepresentable {
|
||||
@Binding var image: UIImage?
|
||||
var allowsEditing: Bool = false
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user