import Combine import Foundation import Martin import SwiftUI struct ConversationScreen: View { @EnvironmentObject var store: AppStore @State private var autoScroll = true var body: some View { ZStack { // Background color Color.Main.backgroundLight .ignoresSafeArea() // Content VStack(spacing: 0) { // Header ConversationHeader() // Msg list let messages = store.state.conversationsState.currentMessages if !messages.isEmpty { ScrollViewReader { proxy in List { ForEach(messages) { message in ConversationMessageRow(message: message) .id(message.id) .onAppear { if message.id == messages.last?.id { autoScroll = true } } .onDisappear { if message.id == messages.last?.id { autoScroll = false } } } } .listStyle(.plain) .background(Color.Main.backgroundLight) .scrollDismissesKeyboard(.immediately) .scrollIndicators(.hidden) .onChange(of: messages) { _ in if autoScroll { withAnimation { proxy.scrollTo(messages.last?.id, anchor: .bottom) } } } .onChange(of: autoScroll) { new in if new { withAnimation { proxy.scrollTo(messages.last?.id, anchor: .bottom) } } } .onAppear { proxy.scrollTo(messages.last?.id, anchor: .bottom) } } } else { Spacer() } } .onTapGesture { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } // Jump to last button if !autoScroll { Button { autoScroll = true } label: { Text("TEST") } } } .safeAreaInset(edge: .bottom, spacing: 0) { ConversationTextInput() } } } // Preview #if DEBUG struct ConversationScreen_Previews: PreviewProvider { static var previews: some View { ConversationScreen() .environmentObject(pStore) } static var pStore: AppStore { let state = pState return AppStore(initialState: state, reducer: AppState.reducer, middlewares: []) } static var pState: AppState { var state = AppState() let acc = "user@test.com" let contact = "some@test.com" state.conversationsState.currentChat = Chat(id: "1", account: acc, participant: contact, type: .chat) state.conversationsState.currentMessages = [ Message( id: "1", type: .chat, contentType: .text, from: contact, to: acc, body: "this is for test sdgdsfg dsfg dsfgdg dsfgdfgsdgsdfgdfg sdfgdsfgdfsg dsfgdsfgsdfg dsfgdfgsdg fgf fgfg sdfsdf sdfsdf sdf sdfsdf sdf sdfsdf sdfsdfsdf sdfsdf ", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: true, sentError: false ), Message( id: "2", type: .chat, contentType: .text, from: contact, to: acc, body: "this is for testsdfsdf sdfsdf sdfs sdf sdffsdf sdf sdf sdf sdf sdf sdff sdfffwwe ", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false ), Message(id: "3", type: .chat, contentType: .text, from: contact, to: acc, body: "this is for test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: true), Message( id: "4", type: .chat, contentType: .text, from: acc, to: contact, body: "this is for test sdfkjwek jwkjfh jwerf jdfhskjdhf jsdhfjhwefh sjdhfh fsdjhfh sd ", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false ), Message(id: "5", type: .chat, contentType: .text, from: contact, to: acc, body: "this is for test sdfjkkeke kekkddjw;; w;edkdjfj l kjwekrjfk wef", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false), Message(id: "6", type: .chat, contentType: .text, from: acc, to: contact, body: "this is for testsdf dsdkkekkddn wejkjfj ", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false), Message( id: "7", type: .chat, contentType: .text, from: acc, to: contact, body: "this is for test sdgdsfg dsfg dsfgdg dsfgdfgsdgsdfgdfg sdfgdsfgdfsg dsfgdsfgsdfg dsfgdfgsdg fgf fgfg sdfsdf sdfsdf sdf sdfsdf sdf sdfsdf sdfsdfsdf sdfsdf ", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false ), Message(id: "8", type: .chat, contentType: .text, from: acc, to: contact, body: "so test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false), Message(id: "9", type: .chat, contentType: .text, from: contact, to: acc, body: "so test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false), Message(id: "10", type: .chat, contentType: .text, from: acc, to: contact, body: "so test so test so test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false), Message(id: "11", type: .chat, contentType: .text, from: contact, to: acc, body: "xD", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false) ] state.conversationsState.replyText = "> Some Text here! And if it a long and very long text sdfsadfsadfsafsadfsadfsadfsadfassadfsadfsafsafdsadfsafdsadfsadfas sdf sdf asdf sdfasdfsd sdfasdf sdfsdfdsasdfsdfa dsafsaf" return state } } #endif