From 19939dcf6147cdc1280f37d6105adcd14f7ae39a Mon Sep 17 00:00:00 2001 From: cheykrym Date: Thu, 11 Dec 2025 01:28:39 +0300 Subject: [PATCH] fix relationships --- yobble/Network/ChatModels.swift | 16 +++++ yobble/Resources/Localizable.xcstrings | 3 + yobble/Views/Chat/MessageProfileView.swift | 77 ++++++++++++++++++---- 3 files changed, 83 insertions(+), 13 deletions(-) diff --git a/yobble/Network/ChatModels.swift b/yobble/Network/ChatModels.swift index 52076b1..0d42395 100644 --- a/yobble/Network/ChatModels.swift +++ b/yobble/Network/ChatModels.swift @@ -310,9 +310,25 @@ struct ChatProfilePermissions: Decodable { } struct RelationshipStatus: Decodable { + let isTargetInContactsOfCurrentUser: Bool let isCurrentUserInContactsOfTarget: Bool let isTargetUserBlockedByCurrentUser: Bool let isCurrentUserInBlacklistOfTarget: Bool + + private enum CodingKeys: String, CodingKey { + case isTargetInContactsOfCurrentUser + case isCurrentUserInContactsOfTarget + case isTargetUserBlockedByCurrentUser + case isCurrentUserInBlacklistOfTarget + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.isTargetInContactsOfCurrentUser = try container.decodeIfPresent(Bool.self, forKey: .isTargetInContactsOfCurrentUser) ?? false + self.isCurrentUserInContactsOfTarget = try container.decodeIfPresent(Bool.self, forKey: .isCurrentUserInContactsOfTarget) ?? false + self.isTargetUserBlockedByCurrentUser = try container.decodeIfPresent(Bool.self, forKey: .isTargetUserBlockedByCurrentUser) ?? false + self.isCurrentUserInBlacklistOfTarget = try container.decodeIfPresent(Bool.self, forKey: .isCurrentUserInBlacklistOfTarget) ?? false + } } enum JSONValue: Decodable { diff --git a/yobble/Resources/Localizable.xcstrings b/yobble/Resources/Localizable.xcstrings index 0780033..50163de 100644 --- a/yobble/Resources/Localizable.xcstrings +++ b/yobble/Resources/Localizable.xcstrings @@ -295,6 +295,9 @@ "был(а) %@" : { "comment" : "Message profile last seen relative format" }, + "В ваших контактах" : { + "comment" : "Message profile user in contacts tag" + }, "в сети" : { "comment" : "Message profile online status" }, diff --git a/yobble/Views/Chat/MessageProfileView.swift b/yobble/Views/Chat/MessageProfileView.swift index b8d7aa2..6c61eab 100644 --- a/yobble/Views/Chat/MessageProfileView.swift +++ b/yobble/Views/Chat/MessageProfileView.swift @@ -253,6 +253,35 @@ struct MessageProfileView: View { title: NSLocalizedString("Рейтинг собеседника", comment: "Message profile rating title"), value: ratingDisplayValue ) + + if shouldShowRelationshipQuickActions { + rowDivider + VStack(spacing: 8) { + buttonRow( + icon: "person.badge.plus", + title: NSLocalizedString("Добавить в контакты", comment: "Message profile add to contacts title"), + subtitle: NSLocalizedString("Появится отдельная запись в адресной книге Yobble.", comment: "Message profile add to contacts subtitle"), + iconTint: .accentColor + ) { + handleAddContactTap() + } + + buttonRow( + icon: "hand.raised.slash.fill", + title: isBlockedByCurrentUser + ? NSLocalizedString("Разблокировать", comment: "Message profile unblock title") + : NSLocalizedString("Заблокировать", comment: "Message profile block title"), + subtitle: isBlockedByCurrentUser + ? NSLocalizedString("Пользователь снова сможет писать вам.", comment: "Message profile unblock subtitle") + : NSLocalizedString("Перестанет появляться в чате и не сможет писать.", comment: "Message profile block subtitle"), + iconTint: .red, + destructive: true + ) { + handleBlockToggleTap() + } + } + .padding(.top, 4) + } } } @@ -407,10 +436,7 @@ struct MessageProfileView: View { subtitle: NSLocalizedString("Появится отдельная запись в адресной книге Yobble.", comment: "Message profile add to contacts subtitle"), iconTint: .accentColor ) { - showPlaceholderAction( - title: NSLocalizedString("Добавить контакт", comment: "Message profile add contact alert title"), - message: NSLocalizedString("Редактор контактов скоро появится. Мы сохраним имя, телефон и заметку.", comment: "Message profile add contact alert message") - ) + handleAddContactTap() } rowDivider @@ -449,15 +475,7 @@ struct MessageProfileView: View { iconTint: .red, destructive: true ) { - let message = isBlockedByCurrentUser - ? NSLocalizedString("Скоро появится разблокировка с подтверждением и синхронизацией.", comment: "Message profile unblock alert message") - : NSLocalizedString("Блокировка чата пока в дизайне. Готовим отдельный экран со статусом и жалобой.", comment: "Message profile block alert message") - showPlaceholderAction( - title: isBlockedByCurrentUser - ? NSLocalizedString("Разблокировать", comment: "Message profile unblock alert title") - : NSLocalizedString("Заблокировать", comment: "Message profile block alert title"), - message: message - ) + handleBlockToggleTap() } rowDivider @@ -609,6 +627,23 @@ struct MessageProfileView: View { placeholderAlert = PlaceholderAlert(title: title, message: message) } + private func handleAddContactTap() { + showPlaceholderAction( + title: NSLocalizedString("Добавить контакт", comment: "Message profile add contact alert title"), + message: NSLocalizedString("Редактор контактов скоро появится. Мы сохраним имя, телефон и заметку.", comment: "Message profile add contact alert message") + ) + } + + private func handleBlockToggleTap() { + let title = isBlockedByCurrentUser + ? NSLocalizedString("Разблокировать", comment: "Message profile unblock alert title") + : NSLocalizedString("Заблокировать", comment: "Message profile block alert title") + let message = isBlockedByCurrentUser + ? NSLocalizedString("Скоро появится разблокировка с подтверждением и синхронизацией.", comment: "Message profile unblock alert message") + : NSLocalizedString("Блокировка чата пока в дизайне. Готовим отдельный экран со статусом и жалобой.", comment: "Message profile block alert message") + showPlaceholderAction(title: title, message: message) + } + // MARK: - Derived Data private var profileBio: String? { @@ -625,6 +660,11 @@ struct MessageProfileView: View { ) } + private var shouldShowRelationshipQuickActions: Bool { + guard let relationship = chat.chatData?.relationship else { return false } + return !relationship.isTargetInContactsOfCurrentUser + } + private var ratingDisplayValue: String { guard let rating = chat.chatData?.rating else { return NSLocalizedString("Недоступно", comment: "Message profile rating unavailable") @@ -696,6 +736,17 @@ struct MessageProfileView: View { } if let relationship = chat.chatData?.relationship { + if relationship.isTargetInContactsOfCurrentUser { + tags.append( + StatusTag( + icon: "person.crop.circle.badge.checkmark", + text: NSLocalizedString("В ваших контактах", comment: "Message profile user in contacts tag"), + background: Color.white.opacity(0.14), + tint: .white + ) + ) + } + if relationship.isCurrentUserInContactsOfTarget { tags.append( StatusTag(