Исправления UI: центрирование Saved Messages, размеры тулбара звонков, отображение "Connecting...", локальная отправка в Saved Messages
This commit is contained in:
@@ -262,9 +262,7 @@ private extension ChatListView {
|
||||
ToolbarItem(placement: .principal) {
|
||||
HStack(spacing: 4) {
|
||||
ToolbarStoriesAvatar()
|
||||
Text("Chats")
|
||||
.font(.system(size: 17, weight: .semibold))
|
||||
.foregroundStyle(RosettaColors.Adaptive.text)
|
||||
ToolbarTitleView()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,9 +300,7 @@ private extension ChatListView {
|
||||
ToolbarItem(placement: .principal) {
|
||||
HStack(spacing: 4) {
|
||||
ToolbarStoriesAvatar()
|
||||
Text("Chats")
|
||||
.font(.system(size: 17, weight: .semibold))
|
||||
.foregroundStyle(RosettaColors.Adaptive.text)
|
||||
ToolbarTitleView()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,6 +351,30 @@ private struct ChatListToolbarBackgroundModifier: ViewModifier {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Toolbar Title (observation-isolated)
|
||||
|
||||
/// Reads `ProtocolManager.shared.connectionState` in its own observation scope.
|
||||
/// Connection state changes during handshake (4+ rapid transitions) are absorbed here,
|
||||
/// not cascaded to the parent ChatListView / NavigationStack.
|
||||
private struct ToolbarTitleView: View {
|
||||
var body: some View {
|
||||
let state = ProtocolManager.shared.connectionState
|
||||
let title: String = switch state {
|
||||
case .disconnected: "Connecting..."
|
||||
case .connecting: "Connecting..."
|
||||
case .connected: "Connected"
|
||||
case .handshaking: "Authenticating..."
|
||||
case .deviceVerificationRequired: "Device Verification..."
|
||||
case .authenticated: "Chats"
|
||||
}
|
||||
Text(title)
|
||||
.font(.system(size: 17, weight: .semibold))
|
||||
.foregroundStyle(RosettaColors.Adaptive.text)
|
||||
.contentTransition(.numericText())
|
||||
.animation(.easeInOut(duration: 0.25), value: state)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Toolbar Stories Avatar (observation-isolated)
|
||||
|
||||
/// Reads `AccountManager` and `SessionManager` in its own observation scope.
|
||||
@@ -470,23 +490,25 @@ private struct ChatListDialogContent: View {
|
||||
.listRowSeparatorTint(RosettaColors.Adaptive.divider)
|
||||
.alignmentGuide(.listRowSeparatorLeading) { _ in 82 }
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
||||
Button {
|
||||
viewModel.toggleMute(dialog)
|
||||
Button(role: .destructive) {
|
||||
withAnimation { viewModel.deleteDialog(dialog) }
|
||||
} label: {
|
||||
Label(
|
||||
dialog.isMuted ? "Unmute" : "Mute",
|
||||
systemImage: dialog.isMuted ? "bell" : "bell.slash"
|
||||
)
|
||||
Label("Delete", systemImage: "trash")
|
||||
}
|
||||
|
||||
if !dialog.isSavedMessages {
|
||||
Button {
|
||||
viewModel.toggleMute(dialog)
|
||||
} label: {
|
||||
Label(
|
||||
dialog.isMuted ? "Unmute" : "Mute",
|
||||
systemImage: dialog.isMuted ? "bell" : "bell.slash"
|
||||
)
|
||||
}
|
||||
.tint(dialog.isMuted ? .green : .indigo)
|
||||
}
|
||||
.tint(dialog.isMuted ? .green : .indigo)
|
||||
}
|
||||
.swipeActions(edge: .leading, allowsFullSwipe: true) {
|
||||
Button {
|
||||
viewModel.markAsRead(dialog)
|
||||
} label: {
|
||||
Label("Read", systemImage: "envelope.open")
|
||||
}
|
||||
.tint(RosettaColors.figmaBlue)
|
||||
Button {
|
||||
viewModel.togglePin(dialog)
|
||||
} label: {
|
||||
|
||||
Reference in New Issue
Block a user