Фикс клавиатуры, скругления input, iOS 26 layout, доставка сообщений и синхронизация

This commit is contained in:
2026-03-24 20:31:30 +05:00
parent 1cdd392cf3
commit d482cdf62b
20 changed files with 565 additions and 235 deletions

View File

@@ -50,8 +50,15 @@ struct ChatRowView: View {
// MARK: - Avatar
private extension ChatRowView {
var avatarSection: some View {
/// Observation-isolated: reads `AvatarRepository.avatarVersion` in its own
/// scope so only the avatar re-renders when opponent avatar changes not the
/// entire ChatRowView (title, message preview, badge, etc.).
private struct ChatRowAvatar: View {
let dialog: Dialog
var body: some View {
// Establish @Observable tracking re-renders this view on avatar save/remove.
let _ = AvatarRepository.shared.avatarVersion
AvatarView(
initials: dialog.initials,
colorIndex: dialog.avatarColorIndex,
@@ -63,6 +70,12 @@ private extension ChatRowView {
}
}
private extension ChatRowView {
var avatarSection: some View {
ChatRowAvatar(dialog: dialog)
}
}
// MARK: - Content Section
// Figma "Contents": flex-col, h-full, items-start, justify-center, pb-px
// "Title and Trailing Accessories": flex-1, gap-6, items-center
@@ -209,22 +222,24 @@ private extension ChatRowView {
@ViewBuilder
var deliveryIcon: some View {
switch dialog.lastMessageDelivered {
case .waiting:
// Timer isolated to sub-view only .waiting rows create a timer.
DeliveryWaitingIcon(sentTimestamp: dialog.lastMessageTimestamp)
case .delivered:
SingleCheckmarkShape()
.fill(RosettaColors.Adaptive.textSecondary)
.frame(width: 14, height: 10.3)
case .read:
if dialog.lastMessageDelivered == .delivered && dialog.lastMessageRead {
DoubleCheckmarkShape()
.fill(RosettaColors.figmaBlue)
.frame(width: 17, height: 9.3)
case .error:
Image(systemName: "exclamationmark.circle.fill")
.font(.system(size: 14))
.foregroundStyle(RosettaColors.error)
} else {
switch dialog.lastMessageDelivered {
case .waiting:
// Timer isolated to sub-view only .waiting rows create a timer.
DeliveryWaitingIcon(sentTimestamp: dialog.lastMessageTimestamp)
case .delivered:
SingleCheckmarkShape()
.fill(RosettaColors.Adaptive.textSecondary)
.frame(width: 14, height: 10.3)
case .error:
Image(systemName: "exclamationmark.circle.fill")
.font(.system(size: 14))
.foregroundStyle(RosettaColors.error)
}
}
}
@@ -341,7 +356,8 @@ private extension ChatRowView {
unreadCount: 3, isOnline: true, lastSeen: 0,
verified: 1, iHaveSent: true,
isPinned: false, isMuted: false,
lastMessageFromMe: true, lastMessageDelivered: .read
lastMessageFromMe: true, lastMessageDelivered: .delivered,
lastMessageRead: true
)
VStack(spacing: 0) {