// // ChatView.swift // Chat // // Created by Sergey Tarasov on 24.07.2022. // import SwiftUI import XMPPFramework import XMPPFrameworkSwift extension CGFloat { static let sidePadding: CGFloat = 14 } struct ChatView: View, KeyboardReadable { @ObservedObject var viewModel: ChatViewModel @State private var isKeyboardVisible = false var body: some View { VStack(alignment: .center, spacing: 0) { ScrollView { ScrollViewReader { value in VStack { withAnimation { ForEach(viewModel.messages, id: \.self) { message in HStack { if message.from?.bare == StreamManager.shared.stream.myJID?.bare { Spacer(minLength: 40) MessageView(text: message.body ?? "-", time: "", isSelf: true) } else { MessageView(text: message.body ?? "-", time: "", isSelf: false) Spacer(minLength: 40) } } } .onChange(of: viewModel.messages) { _ in withAnimation { value.scrollTo(viewModel.messages.count - 1, anchor: .bottomTrailing) } } .onReceive(keyboardPublisher) { newIsKeyboardVisible in isKeyboardVisible = newIsKeyboardVisible withAnimation { value.scrollTo(viewModel.messages.count - 2, anchor: .topTrailing) } } .onAppear { value.scrollTo(viewModel.messages.count - 1, anchor: .top) } } } .padding(.horizontal, .sidePadding) .padding(.vertical, 12) .background(Color.indigo.opacity(0.0)) } } Divider() HStack { TextField("Сообщение", text: $viewModel.messageText) .textFieldStyle(.automatic) .padding(.vertical, 6) .padding(.horizontal, 12) .background(.background) Button { viewModel.messageText = "" } label: { Image(systemName: "arrow.up.circle.fill") .font(.title) .foregroundColor(viewModel.messageText.isEmpty ? .gray : .accentColor) } .disabled(viewModel.messageText.isEmpty) } .padding(.horizontal, .sidePadding) .padding(.vertical, 6) .background() } .navigationTitle(viewModel.manager.room.roomJID.user ?? "Room") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { viewModel.fetchMessages() } label: { Image(systemName: "arrow.counterclockwise") } } } .onAppear { viewModel.fetchMessages() } } } struct ChatView_Previews: PreviewProvider { static var viewModel: ChatViewModel = ChatViewModel(with: "") static var previews: some View { Group { NavigationView { ChatView(viewModel: viewModel) } NavigationView { ChatView(viewModel: viewModel) .preferredColorScheme(.dark) } } } }