Compare commits
3 Commits
aac0a25c4d
...
910eef3703
| Author | SHA1 | Date | |
|---|---|---|---|
| 910eef3703 | |||
| e6d7258b70 | |||
| 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: 0, leading: 12, bottom: 0, trailing: 12))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.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, 18)
|
||||
.listRowInsets(EdgeInsets(top: 18, leading: 12, bottom: 18, trailing: 12))
|
||||
.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, 10)
|
||||
.listRowInsets(EdgeInsets(top: 10, leading: 12, bottom: 10, trailing: 12))
|
||||
.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, 28)
|
||||
.listRowInsets(EdgeInsets(top: 20, leading: 12, bottom: 20, trailing: 12))
|
||||
.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: 10) {
|
||||
Circle()
|
||||
.fill(Color.accentColor.opacity(0.15))
|
||||
.frame(width: 44, height: 44)
|
||||
.frame(width: 40, height: 40)
|
||||
.overlay(
|
||||
Text(contact.initials)
|
||||
.font(.headline)
|
||||
.foregroundColor(.accentColor)
|
||||
)
|
||||
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
VStack(alignment: .leading, spacing: 3) {
|
||||
HStack(alignment: .firstTextBaseline) {
|
||||
Text(contact.displayName)
|
||||
.font(.body)
|
||||
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)
|
||||
}
|
||||
.font(.subheadline.weight(.semibold))
|
||||
.foregroundColor(.primary)
|
||||
Spacer()
|
||||
Text(contact.formattedCreatedAt)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
if let handle = contact.handle {
|
||||
Text(handle)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
Spacer()
|
||||
|
||||
if contact.friendCode {
|
||||
friendCodeBadge
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
.padding(.vertical, 6)
|
||||
}
|
||||
|
||||
private var friendCodeBadge: some View {
|
||||
Text(NSLocalizedString("Код дружбы", comment: "Friend code badge"))
|
||||
.font(.caption2.weight(.medium))
|
||||
.foregroundColor(Color.accentColor)
|
||||
.padding(.horizontal, 6)
|
||||
.padding(.vertical, 3)
|
||||
.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