forked from mirrors/linphone-iphone
Fix messages list in conversation
This commit is contained in:
parent
be09968a31
commit
d8d867d798
6 changed files with 250 additions and 77 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -175,7 +175,8 @@ struct ConversationsListBottomSheet: View {
|
|||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
|
||||
Button {
|
||||
Button {
|
||||
conversationsListViewModel.selectedConversation!.deleteChatRoom()
|
||||
conversationsListViewModel.computeChatRoomsList(filter: "")
|
||||
|
||||
if #available(iOS 16.0, *) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue