Fix messages list in conversation

This commit is contained in:
Benoit Martins 2024-02-29 17:28:11 +01:00
parent be09968a31
commit d8d867d798
6 changed files with 250 additions and 77 deletions

View file

@ -28,26 +28,34 @@ struct ChatBubbleView: View {
var body: some View {
if index < conversationViewModel.conversationMessagesList.count
&& conversationViewModel.conversationMessagesList[index].eventLog.chatMessage != nil {
HStack {
if conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.isOutgoing {
Spacer()
VStack {
if index == 0 && conversationViewModel.displayedConversationHistorySize > conversationViewModel.conversationMessagesList.count {
ProgressView()
.frame(idealWidth: .infinity, maxWidth: .infinity, alignment: .center)
.id(UUID())
}
VStack {
Text(conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.utf8Text ?? "")
.foregroundStyle(Color.grayMain2c700)
.default_text_style(styleSize: 16)
}
.padding(.all, 15)
.background(conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.isOutgoing ? Color.orangeMain100 : Color.grayMain2c100)
.clipShape(RoundedRectangle(cornerRadius: 16))
if !conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.isOutgoing {
Spacer()
HStack {
if conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.isOutgoing {
Spacer()
}
VStack {
Text(conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.utf8Text ?? "")
.foregroundStyle(Color.grayMain2c700)
.default_text_style(styleSize: 16)
}
.padding(.all, 15)
.background(conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.isOutgoing ? Color.orangeMain100 : Color.grayMain2c100)
.clipShape(RoundedRectangle(cornerRadius: 16))
if !conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.isOutgoing {
Spacer()
}
}
.padding(.leading, conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.isOutgoing ? 40 : 0)
.padding(.trailing, !conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.isOutgoing ? 40 : 0)
}
.padding(.leading, conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.isOutgoing ? 40 : 0)
.padding(.trailing, !conversationViewModel.conversationMessagesList[index].eventLog.chatMessage!.isOutgoing ? 40 : 0)
}
}
}

View file

@ -32,6 +32,8 @@ struct ConversationFragment: View {
@FocusState var isMessageTextFocused: Bool
@State var offset: CGPoint = .zero
var body: some View {
NavigationView {
GeometryReader { geometry in
@ -140,64 +142,169 @@ struct ConversationFragment: View {
.padding(.bottom, 4)
.background(.white)
/*
List {
ForEach(0..<conversationViewModel.conversationMessagesList.count, id: \.self) { index in
ChatBubbleView(conversationViewModel: conversationViewModel, index: index)
.id(conversationViewModel.conversationMessagesList[index])
.scaleEffect(x: 1, y: -1, anchor: .center)
.listRowInsets(EdgeInsets(top: 2, leading: 10, bottom: 2, trailing: 10))
.listRowSeparator(.hidden)
.transition(.move(edge: .top))
}
}
.scaleEffect(x: 1, y: -1, anchor: .center)
.listStyle(.plain)
.frame(maxWidth: .infinity)
.background(.white)
.onTapGesture {
UIApplication.shared.endEditing()
}
.onDisappear {
conversationViewModel.resetMessage()
}
*/
List {
ForEach(0..<conversationViewModel.conversationMessagesList.count, id: \.self) { index in
ChatBubbleView(conversationViewModel: conversationViewModel, index: index)
.id(conversationViewModel.conversationMessagesList[index])
.scaleEffect(x: 1, y: -1, anchor: .center)
.listRowInsets(EdgeInsets(top: 2, leading: 10, bottom: 2, trailing: 10))
.listRowSeparator(.hidden)
.transition(.move(edge: .top))
ScrollViewReader { proxy in
List {
ForEach(0..<conversationViewModel.conversationMessagesList.count, id: \.self) { index in
ChatBubbleView(conversationViewModel: conversationViewModel, index: index)
.id(conversationViewModel.conversationMessagesList[index])
.listRowInsets(EdgeInsets(top: 2, leading: 10, bottom: 2, trailing: 10))
.listRowSeparator(.hidden)
.onAppear {
if index == 0 && conversationViewModel.displayedConversationHistorySize > conversationViewModel.conversationMessagesList.count {
//DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
conversationViewModel.getOldMessages()
//}
}
}
}
}
.listStyle(.plain)
.onTapGesture {
UIApplication.shared.endEditing()
}
.onAppear {
conversationViewModel.getMessages()
}
.onChange(of: conversationViewModel.conversationMessagesList) { _ in
if conversationViewModel.conversationMessagesList.count <= 30 {
proxy.scrollTo(
conversationViewModel.conversationMessagesList.last, anchor: .top
)
} else if conversationViewModel.conversationMessagesList.count >= conversationViewModel.displayedConversationHistorySize {
print("ChatBubbleViewChatBubbleView 1 "
+ "\(conversationViewModel.conversationMessagesList.count) "
+ "\(conversationViewModel.displayedConversationHistorySize - 30) "
+ "\(conversationViewModel.conversationMessagesList.first?.eventLog.chatMessage!.utf8Text ?? "") "
+ "\(conversationViewModel.conversationMessagesList[29].eventLog.chatMessage!.utf8Text ?? "")"
)
proxy.scrollTo(
conversationViewModel.conversationMessagesList[conversationViewModel.displayedConversationHistorySize%30], anchor: .top
)
} else {
print("ChatBubbleViewChatBubbleView 2 "
+ "\(conversationViewModel.conversationMessagesList.count) "
+ "\(conversationViewModel.displayedConversationHistorySize - 30) "
+ "\(conversationViewModel.conversationMessagesList.first?.eventLog.chatMessage!.utf8Text ?? "") "
+ "\(conversationViewModel.conversationMessagesList[29].eventLog.chatMessage!.utf8Text ?? "")"
)
proxy.scrollTo(30, anchor: .top)
}
}
.onDisappear {
conversationViewModel.resetMessage()
}
}
.scaleEffect(x: 1, y: -1, anchor: .center)
.listStyle(.plain)
.frame(maxWidth: .infinity)
.background(.white)
.onTapGesture {
UIApplication.shared.endEditing()
}
.onDisappear {
conversationViewModel.resetMessage()
}
/*
ScrollViewReader { proxy in
ScrollView {
LazyVStack {
ForEach(0..<conversationViewModel.conversationMessagesList.count, id: \.self) { index in
ChatBubbleView(conversationViewModel: conversationViewModel, index: index)
.id(conversationViewModel.conversationMessagesList[index])
GeometryReader { reader in
ScrollViewReader { proxy in
if #available(iOS 17.0, *) {
ScrollView(.vertical) {
VStack(spacing: 4) {
Spacer()
ForEach(0..<conversationViewModel.conversationMessagesList.count, id: \.self) { index in
ChatBubbleView(conversationViewModel: conversationViewModel, index: index)
.id(conversationViewModel.conversationMessagesList[index])
}
}
.frame(minHeight: reader.size.height)
.padding(.horizontal, 10)
.padding(.bottom, 8)
.background(GeometryReader { geometry -> Color in
DispatchQueue.main.async {
//self.offset = -geometry.frame(in: .named("scroll")).origin.y
let offsetMax = geometry.size.height - reader.size.height
//print("ScrollOffsetPreferenceKey >> \(self.offset) \(offsetMax)")
if -geometry.frame(in: .named("scroll")).origin.y <= 0 && self.offset > 0 {
conversationViewModel.getOldMessages()
print("ScrollOffsetPreferenceKey >> \(self.offset) \(-geometry.frame(in: .named("scroll")).origin.y) \(offsetMax)")
//proxy.scrollTo(conversationViewModel.conversationMessagesList[19], anchor: .top)
}
self.offset = -geometry.frame(in: .named("scroll")).origin.y
}
return Color.clear
})
/*/
.background(GeometryReader { geometry in
Color.clear
.preference(key: ScrollOffsetPreferenceKey.self, value: (geometry.frame(in: .named("scroll")).origin))
})
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
//self.scrollOffset = value
print("ScrollOffsetPreferenceKey \(value)")
if value.y > 0 {
print("ScrollOffsetPreferenceKey \(value) \(conversationViewModel.conversationMessagesList.count)")
conversationViewModel.getOldMessages()
}
}
*/
}
}
.frame(maxWidth: .infinity)
.background(.white)
.onTapGesture {
UIApplication.shared.endEditing()
}
.onAppear {
if conversationViewModel.conversationMessagesList.last != nil {
proxy.scrollTo(conversationViewModel.conversationMessagesList.last!, anchor: .bottom)
.coordinateSpace(name: "scroll")
.onTapGesture {
UIApplication.shared.endEditing()
}
.onAppear {
conversationViewModel.getMessages()
}
.onDisappear {
conversationViewModel.resetMessage()
}
.defaultScrollAnchor(.bottom)
} else {
ScrollView(.vertical) {
VStack {
ForEach(0..<conversationViewModel.conversationMessagesList.count, id: \.self) { index in
ChatBubbleView(conversationViewModel: conversationViewModel, index: index)
.id(conversationViewModel.conversationMessagesList[index])
}
}
}
.onTapGesture {
UIApplication.shared.endEditing()
}
.onAppear {
conversationViewModel.getMessages()
}
.onChange(of: conversationViewModel.conversationMessagesList) { _ in
withAnimation {
proxy.scrollTo(conversationViewModel.conversationMessagesList.last, anchor: .top)
}
}
.onDisappear {
conversationViewModel.resetMessage()
}
}
.onDisappear {
conversationViewModel.resetMessage()
}
}
}
*/
*/
/*
ScrollViewReader { proxy in
@ -320,6 +427,7 @@ struct ConversationFragment: View {
if conversationViewModel.messageText.isEmpty {
Button {
conversationViewModel.getOldMessages()
} label: {
Image("microphone")
.renderingMode(.template)

View file

@ -175,7 +175,8 @@ struct ConversationsListBottomSheet: View {
.frame(maxWidth: .infinity)
}
Button {
Button {
conversationsListViewModel.selectedConversation!.deleteChatRoom()
conversationsListViewModel.computeChatRoomsList(filter: "")
if #available(iOS 16.0, *) {

View file

@ -135,7 +135,8 @@ struct ConversationsListFragment: View {
.onTapGesture {
withAnimation {
conversationViewModel.changeDisplayedChatRoom(conversationModel: conversationsListViewModel.conversationsList[index])
conversationViewModel.getMessage()
conversationsListViewModel.conversationsList[index].markAsRead()
conversationsListViewModel.updateUnreadMessagesCount()
}
}
.onLongPressGesture(minimumDuration: 0.2) {

View file

@ -109,6 +109,11 @@ class ConversationModel: ObservableObject {
func markAsRead() {
coreContext.doOnCoreQueue { _ in
self.chatRoom.markAsRead()
let unreadMessagesCountTmp = self.chatRoom.unreadMessagesCount
DispatchQueue.main.async {
self.unreadMessagesCount = unreadMessagesCountTmp
}
}
}
@ -228,4 +233,10 @@ class ConversationModel: ObservableObject {
}
}
}
func deleteChatRoom() {
CoreContext.shared.doOnCoreQueue { core in
core.deleteChatRoom(chatRoom: self.chatRoom)
}
}
}

View file

@ -27,6 +27,7 @@ class ConversationViewModel: ObservableObject {
private var coreContext = CoreContext.shared
@Published var displayedConversation: ConversationModel?
@Published var displayedConversationHistorySize: Int = 0
@Published var messageText: String = ""
@ -54,36 +55,79 @@ class ConversationViewModel: ObservableObject {
self.chatRoomSuscriptions.removeAll()
}
func getMessage() {
func getHistorySize() {
coreContext.doOnCoreQueue { _ in
if self.displayedConversation != nil {
let historySize = self.displayedConversation!.chatRoom.historySize
DispatchQueue.main.async {
self.displayedConversationHistorySize = historySize
}
}
}
}
func getMessages() {
self.getHistorySize()
coreContext.doOnCoreQueue { _ in
if self.displayedConversation != nil {
let historyEvents = self.displayedConversation!.chatRoom.getHistoryRangeEvents(begin: self.conversationMessagesList.count, end: self.conversationMessagesList.count + 30)
//For List
/*
historyEvents.reversed().forEach { eventLog in
DispatchQueue.main.async {
self.conversationMessagesList.append(LinphoneCustomEventLog(eventLog: eventLog))
}
}
*/
//For ScrollView
historyEvents.forEach { eventLog in
DispatchQueue.main.async {
self.conversationMessagesList.append(LinphoneCustomEventLog(eventLog: eventLog))
}
}
}
}
}
func getNewMessages(eventLogs: [EventLog]) {
//let conversationMessagesListTmp = self.conversationMessagesList
//self.conversationMessagesList = []
eventLogs.forEach { eventLog in
DispatchQueue.main.async {
func getOldMessages() {
coreContext.doOnCoreQueue { _ in
if self.displayedConversation != nil {
let historyEvents = self.displayedConversation!.chatRoom.getHistoryRangeEvents(begin: self.conversationMessagesList.count, end: self.conversationMessagesList.count + 30)
//For List
/*
withAnimation {
self.conversationMessagesList.append(LinphoneCustomEventLog(eventLog: eventLog))
historyEvents.reversed().forEach { eventLog in
DispatchQueue.main.async {
self.conversationMessagesList.append(LinphoneCustomEventLog(eventLog: eventLog))
}
}
*/
//For ScrollView
var conversationMessagesListTmp: [LinphoneCustomEventLog] = []
historyEvents.reversed().forEach { eventLog in
conversationMessagesListTmp.insert(LinphoneCustomEventLog(eventLog: eventLog), at: 0)
}
self.conversationMessagesList.append(contentsOf: conversationMessagesListTmp)
*/
withAnimation(.spring(duration: 2)) {
self.conversationMessagesList.insert(LinphoneCustomEventLog(eventLog: eventLog), at: 0)
DispatchQueue.main.async {
self.conversationMessagesList.insert(contentsOf: conversationMessagesListTmp, at: 0)
}
}
}
}
func getNewMessages(eventLogs: [EventLog]) {
eventLogs.forEach { eventLog in
DispatchQueue.main.async {
withAnimation {
//For List
//self.conversationMessagesList.insert(LinphoneCustomEventLog(eventLog: eventLog), at: 0)
//For ScrollView
self.conversationMessagesList.append(LinphoneCustomEventLog(eventLog: eventLog))
}
}
}