edit view contacts
This commit is contained in:
		
							parent
							
								
									aac0a25c4d
								
							
						
					
					
						commit
						374bd1713b
					
				@ -1240,6 +1240,7 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "Обновить" : {
 | 
			
		||||
      "comment" : "Contacts retry button",
 | 
			
		||||
      "localizations" : {
 | 
			
		||||
        "en" : {
 | 
			
		||||
          "stringUnit" : {
 | 
			
		||||
@ -1828,6 +1829,9 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "Просмотр \"%1$@\" появится позже." : {
 | 
			
		||||
      "comment" : "Contacts placeholder message"
 | 
			
		||||
    },
 | 
			
		||||
    "Профиль" : {
 | 
			
		||||
      "localizations" : {
 | 
			
		||||
        "en" : {
 | 
			
		||||
@ -2055,7 +2059,7 @@
 | 
			
		||||
      "comment" : "Search placeholder copy"
 | 
			
		||||
    },
 | 
			
		||||
    "Скоро" : {
 | 
			
		||||
      "comment" : "Add blocked user placeholder title"
 | 
			
		||||
      "comment" : "Add blocked user placeholder title\nContacts placeholder title"
 | 
			
		||||
    },
 | 
			
		||||
    "Скоро появится мини-игра, где можно заработать очки для кастомизации профиля. Следите за обновлениями!" : {
 | 
			
		||||
      "comment" : "Concept tab placeholder description"
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
import SwiftUI
 | 
			
		||||
import Foundation
 | 
			
		||||
 | 
			
		||||
struct ContactsTab: View {
 | 
			
		||||
    @State private var contacts: [Contact] = []
 | 
			
		||||
@ -17,15 +18,23 @@ struct ContactsTab: View {
 | 
			
		||||
            } else if contacts.isEmpty {
 | 
			
		||||
                emptyState
 | 
			
		||||
            } else {
 | 
			
		||||
                Section(header: Text(NSLocalizedString("Контакты", comment: ""))) {
 | 
			
		||||
                ForEach(contacts) { contact in
 | 
			
		||||
                    Button {
 | 
			
		||||
                        activeAlert = .info(
 | 
			
		||||
                            title: NSLocalizedString("Скоро", comment: "Contacts placeholder title"),
 | 
			
		||||
                            message: String(format: NSLocalizedString("Просмотр \"%1$@\" появится позже.", comment: "Contacts placeholder message"), contact.displayName)
 | 
			
		||||
                        )
 | 
			
		||||
                    } label: {
 | 
			
		||||
                        ContactRow(contact: contact)
 | 
			
		||||
                            .contentShape(Rectangle())
 | 
			
		||||
                    }
 | 
			
		||||
                    .buttonStyle(.plain)
 | 
			
		||||
                    .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        }
 | 
			
		||||
        .listStyle(.insetGrouped)
 | 
			
		||||
        .background(Color(.systemGroupedBackground))
 | 
			
		||||
        .background(Color(UIColor.systemBackground))
 | 
			
		||||
        .listStyle(.plain)
 | 
			
		||||
        .task {
 | 
			
		||||
            await loadContacts()
 | 
			
		||||
        }
 | 
			
		||||
@ -40,30 +49,50 @@ struct ContactsTab: View {
 | 
			
		||||
                    message: Text(message),
 | 
			
		||||
                    dismissButton: .default(Text(NSLocalizedString("OK", comment: "Common OK")))
 | 
			
		||||
                )
 | 
			
		||||
            case .info(_, let title, let message):
 | 
			
		||||
                return Alert(
 | 
			
		||||
                    title: Text(title),
 | 
			
		||||
                    message: Text(message),
 | 
			
		||||
                    dismissButton: .default(Text(NSLocalizedString("OK", comment: "Common OK")))
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var loadingState: some View {
 | 
			
		||||
        Section {
 | 
			
		||||
        HStack {
 | 
			
		||||
            Spacer()
 | 
			
		||||
            ProgressView()
 | 
			
		||||
                .frame(maxWidth: .infinity, alignment: .center)
 | 
			
		||||
                .progressViewStyle(CircularProgressViewStyle())
 | 
			
		||||
            Spacer()
 | 
			
		||||
        }
 | 
			
		||||
        .padding(.vertical, 24)
 | 
			
		||||
        .listRowInsets(EdgeInsets(top: 24, leading: 16, bottom: 24, trailing: 16))
 | 
			
		||||
        .listRowSeparator(.hidden)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private func errorState(_ message: String) -> some View {
 | 
			
		||||
        Section {
 | 
			
		||||
        HStack(alignment: .center, spacing: 8) {
 | 
			
		||||
            Image(systemName: "exclamationmark.triangle.fill")
 | 
			
		||||
                .foregroundColor(.orange)
 | 
			
		||||
            Text(message)
 | 
			
		||||
                .foregroundColor(.red)
 | 
			
		||||
                .frame(maxWidth: .infinity, alignment: .center)
 | 
			
		||||
                .font(.subheadline)
 | 
			
		||||
                .foregroundColor(.orange)
 | 
			
		||||
            Spacer()
 | 
			
		||||
            Button(action: { Task { await loadContacts() } }) {
 | 
			
		||||
                Text(NSLocalizedString("Обновить", comment: "Contacts retry button"))
 | 
			
		||||
                    .font(.subheadline)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        .padding(.vertical, 12)
 | 
			
		||||
        .listRowInsets(EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16))
 | 
			
		||||
        .listRowSeparator(.hidden)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var emptyState: some View {
 | 
			
		||||
        Section {
 | 
			
		||||
        VStack(spacing: 12) {
 | 
			
		||||
            Image(systemName: "person.crop.circle.badge.questionmark")
 | 
			
		||||
                    .font(.system(size: 48))
 | 
			
		||||
                .font(.system(size: 52))
 | 
			
		||||
                .foregroundColor(.secondary)
 | 
			
		||||
            Text(NSLocalizedString("Контактов пока нет", comment: "Contacts empty state title"))
 | 
			
		||||
                .font(.headline)
 | 
			
		||||
@ -74,8 +103,9 @@ struct ContactsTab: View {
 | 
			
		||||
                .multilineTextAlignment(.center)
 | 
			
		||||
        }
 | 
			
		||||
        .frame(maxWidth: .infinity)
 | 
			
		||||
            .padding(.vertical, 24)
 | 
			
		||||
        }
 | 
			
		||||
        .padding(.vertical, 36)
 | 
			
		||||
        .listRowInsets(EdgeInsets(top: 24, leading: 16, bottom: 24, trailing: 16))
 | 
			
		||||
        .listRowSeparator(.hidden)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @MainActor
 | 
			
		||||
@ -104,38 +134,50 @@ private struct ContactRow: View {
 | 
			
		||||
    let contact: Contact
 | 
			
		||||
 | 
			
		||||
    var body: some View {
 | 
			
		||||
        HStack(spacing: 12) {
 | 
			
		||||
        HStack(alignment: .top, spacing: 14) {
 | 
			
		||||
            Circle()
 | 
			
		||||
                .fill(Color.accentColor.opacity(0.15))
 | 
			
		||||
                .frame(width: 44, height: 44)
 | 
			
		||||
                .frame(width: 52, height: 52)
 | 
			
		||||
                .overlay(
 | 
			
		||||
                    Text(contact.initials)
 | 
			
		||||
                        .font(.headline)
 | 
			
		||||
                        .foregroundColor(.accentColor)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            VStack(alignment: .leading, spacing: 4) {
 | 
			
		||||
            VStack(alignment: .leading, spacing: 6) {
 | 
			
		||||
                HStack(alignment: .firstTextBaseline) {
 | 
			
		||||
                    Text(contact.displayName)
 | 
			
		||||
                    .font(.body)
 | 
			
		||||
                        .font(.headline)
 | 
			
		||||
                        .foregroundColor(.primary)
 | 
			
		||||
                    Spacer()
 | 
			
		||||
                    Text(contact.formattedCreatedAt)
 | 
			
		||||
                        .font(.caption)
 | 
			
		||||
                        .foregroundColor(.secondary)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if let handle = contact.handle {
 | 
			
		||||
                    Text(handle)
 | 
			
		||||
                        .font(.caption)
 | 
			
		||||
                        .foregroundColor(.secondary)
 | 
			
		||||
                }
 | 
			
		||||
                HStack(spacing: 8) {
 | 
			
		||||
 | 
			
		||||
                if contact.friendCode {
 | 
			
		||||
                        Label(NSLocalizedString("Код дружбы", comment: "Friend code badge"), systemImage: "heart.circle")
 | 
			
		||||
                            .font(.caption2)
 | 
			
		||||
                            .foregroundColor(.secondary)
 | 
			
		||||
                    }
 | 
			
		||||
                    Text(contact.formattedCreatedAt)
 | 
			
		||||
                        .font(.caption2)
 | 
			
		||||
                        .foregroundColor(.secondary)
 | 
			
		||||
                    friendCodeBadge
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            Spacer()
 | 
			
		||||
            .frame(maxWidth: .infinity, alignment: .leading)
 | 
			
		||||
        }
 | 
			
		||||
        .padding(.vertical, 6)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var friendCodeBadge: some View {
 | 
			
		||||
        Text(NSLocalizedString("Код дружбы", comment: "Friend code badge"))
 | 
			
		||||
            .font(.caption2.weight(.semibold))
 | 
			
		||||
            .foregroundColor(Color.accentColor)
 | 
			
		||||
            .padding(.horizontal, 8)
 | 
			
		||||
            .padding(.vertical, 4)
 | 
			
		||||
            .background(Color.accentColor.opacity(0.12))
 | 
			
		||||
            .clipShape(Capsule())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -203,10 +245,11 @@ private struct Contact: Identifiable, Equatable {
 | 
			
		||||
 | 
			
		||||
private enum ContactsAlert: Identifiable {
 | 
			
		||||
    case error(id: UUID = UUID(), message: String)
 | 
			
		||||
    case info(id: UUID = UUID(), title: String, message: String)
 | 
			
		||||
 | 
			
		||||
    var id: String {
 | 
			
		||||
        switch self {
 | 
			
		||||
        case .error(let id, _):
 | 
			
		||||
        case .error(let id, _), .info(let id, _, _):
 | 
			
		||||
            return id.uuidString
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user