feat: Introduce system accounts and verification badges
- Added SystemAccounts enum to manage system account keys and titles. - Refactored Dialog model to replace isVerified with verified level. - Implemented effective verification logic for UI display in Dialog. - Updated DialogRepository to handle user verification levels. - Enhanced ProtocolManager and SessionManager to log user info with verification. - Modified AuthCoordinator to support back navigation to unlock screen. - Improved UnlockView and WelcomeView with new account creation flow. - Added VerifiedBadge component to visually represent account verification levels. - Updated ChatListView and SearchView to display verification badges for users. - Cleaned up debug print statements across various components.
This commit is contained in:
@@ -2,11 +2,14 @@ import SwiftUI
|
||||
|
||||
// MARK: - ChatRowView
|
||||
|
||||
/// Chat row matching Figma spec:
|
||||
/// Row: paddingLeft=10, paddingRight=16, height=78
|
||||
/// Avatar: 62px + 10pt right padding
|
||||
/// Title: SFPro-Medium 17pt, message: SFPro-Regular 15pt
|
||||
/// Time: SFPro-Regular 14pt, subtitle color: #3C3C43/60%
|
||||
/// Chat row matching Figma "Row - Chats" component spec:
|
||||
/// Row: height 78, paddingLeft 10, paddingRight 16, vertical center
|
||||
/// Avatar: 62px circle, 10pt trailing padding
|
||||
/// Title: SF Pro Medium 17pt, tracking -0.43, primary color
|
||||
/// Message: SF Pro Regular 15pt, tracking -0.23, secondary color
|
||||
/// Time: SF Pro Regular 14pt, tracking -0.23, secondary color
|
||||
/// Badges gap: 6pt — verified 12px, muted 12px
|
||||
/// Trailing: pt 8, pb 14 — readStatus + time (gap 2), pin/count at bottom
|
||||
struct ChatRowView: View {
|
||||
let dialog: Dialog
|
||||
|
||||
@@ -38,21 +41,27 @@ private extension ChatRowView {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Content Section
|
||||
// MARK: - Content Section (two-column: title+detail | trailing accessories)
|
||||
|
||||
private extension ChatRowView {
|
||||
var contentSection: some View {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
Spacer(minLength: 0)
|
||||
titleRow
|
||||
Spacer().frame(height: 3)
|
||||
subtitleRow
|
||||
Spacer(minLength: 0)
|
||||
HStack(alignment: .center, spacing: 6) {
|
||||
// Left column: title + message
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
titleRow
|
||||
messageRow
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.clipped()
|
||||
|
||||
// Right column: time + pin/badge
|
||||
trailingColumn
|
||||
}
|
||||
.frame(height: 63)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Title Row (name + badges + delivery + time)
|
||||
// MARK: - Title Row (name + badges)
|
||||
|
||||
private extension ChatRowView {
|
||||
var titleRow: some View {
|
||||
@@ -63,10 +72,11 @@ private extension ChatRowView {
|
||||
.foregroundStyle(RosettaColors.Adaptive.text)
|
||||
.lineLimit(1)
|
||||
|
||||
if dialog.isVerified {
|
||||
Image(systemName: "checkmark.seal.fill")
|
||||
.font(.system(size: 14))
|
||||
.foregroundStyle(RosettaColors.figmaBlue)
|
||||
if !dialog.isSavedMessages && dialog.effectiveVerified > 0 {
|
||||
VerifiedBadge(
|
||||
verified: dialog.effectiveVerified,
|
||||
size: 12
|
||||
)
|
||||
}
|
||||
|
||||
if dialog.isMuted {
|
||||
@@ -74,47 +84,19 @@ private extension ChatRowView {
|
||||
.font(.system(size: 12))
|
||||
.foregroundStyle(RosettaColors.Adaptive.textSecondary)
|
||||
}
|
||||
|
||||
Spacer(minLength: 4)
|
||||
|
||||
if dialog.lastMessageFromMe && !dialog.isSavedMessages {
|
||||
deliveryIcon
|
||||
}
|
||||
|
||||
Text(formattedTime)
|
||||
.font(.system(size: 14))
|
||||
.foregroundStyle(
|
||||
dialog.unreadCount > 0 && !dialog.isMuted
|
||||
? RosettaColors.figmaBlue
|
||||
: RosettaColors.Adaptive.textSecondary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Subtitle Row (message + pin + badge)
|
||||
// MARK: - Message Row
|
||||
|
||||
private extension ChatRowView {
|
||||
var subtitleRow: some View {
|
||||
HStack(spacing: 4) {
|
||||
Text(messageText)
|
||||
.font(.system(size: 15))
|
||||
.foregroundStyle(RosettaColors.Adaptive.textSecondary)
|
||||
.lineLimit(1)
|
||||
|
||||
Spacer(minLength: 4)
|
||||
|
||||
if dialog.isPinned && dialog.unreadCount == 0 {
|
||||
Image(systemName: "pin.fill")
|
||||
.font(.system(size: 13))
|
||||
.foregroundStyle(RosettaColors.Adaptive.textSecondary)
|
||||
.rotationEffect(.degrees(45))
|
||||
}
|
||||
|
||||
if dialog.unreadCount > 0 {
|
||||
unreadBadge
|
||||
}
|
||||
}
|
||||
var messageRow: some View {
|
||||
Text(messageText)
|
||||
.font(.system(size: 15))
|
||||
.tracking(-0.23)
|
||||
.foregroundStyle(RosettaColors.Adaptive.textSecondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
var messageText: String {
|
||||
@@ -123,6 +105,48 @@ private extension ChatRowView {
|
||||
}
|
||||
return dialog.lastMessage
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Trailing Column (time + delivery on top, pin/badge on bottom)
|
||||
|
||||
private extension ChatRowView {
|
||||
var trailingColumn: some View {
|
||||
VStack(alignment: .trailing, spacing: 0) {
|
||||
// Top: read status + time
|
||||
HStack(spacing: 2) {
|
||||
if dialog.lastMessageFromMe && !dialog.isSavedMessages {
|
||||
deliveryIcon
|
||||
}
|
||||
|
||||
Text(formattedTime)
|
||||
.font(.system(size: 14))
|
||||
.tracking(-0.23)
|
||||
.foregroundStyle(
|
||||
dialog.unreadCount > 0 && !dialog.isMuted
|
||||
? RosettaColors.figmaBlue
|
||||
: RosettaColors.Adaptive.textSecondary
|
||||
)
|
||||
}
|
||||
.padding(.top, 2)
|
||||
|
||||
Spacer(minLength: 0)
|
||||
|
||||
// Bottom: pin or unread badge
|
||||
HStack(spacing: 8) {
|
||||
if dialog.isPinned && dialog.unreadCount == 0 {
|
||||
Image(systemName: "pin.fill")
|
||||
.font(.system(size: 15))
|
||||
.foregroundStyle(RosettaColors.Adaptive.textSecondary)
|
||||
.rotationEffect(.degrees(45))
|
||||
}
|
||||
|
||||
if dialog.unreadCount > 0 {
|
||||
unreadBadge
|
||||
}
|
||||
}
|
||||
.padding(.bottom, 2)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
var deliveryIcon: some View {
|
||||
@@ -160,9 +184,11 @@ private extension ChatRowView {
|
||||
|
||||
return Text(text)
|
||||
.font(.system(size: 15))
|
||||
.tracking(-0.23)
|
||||
.foregroundStyle(.white)
|
||||
.padding(.horizontal, 4)
|
||||
.frame(minWidth: 20, minHeight: 20)
|
||||
.frame(maxWidth: 37)
|
||||
.background {
|
||||
Capsule()
|
||||
.fill(isMuted ? Color(hex: 0x787880) : RosettaColors.figmaBlue)
|
||||
@@ -208,7 +234,7 @@ private extension ChatRowView {
|
||||
lastMessage: "Hey, how are you?",
|
||||
lastMessageTimestamp: Int64(Date().timeIntervalSince1970 * 1000),
|
||||
unreadCount: 3, isOnline: true, lastSeen: 0,
|
||||
isVerified: true, iHaveSent: true,
|
||||
verified: 1, iHaveSent: true,
|
||||
isPinned: false, isMuted: false,
|
||||
lastMessageFromMe: true, lastMessageDelivered: .read
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user