Fix conversation for iOS 15

This commit is contained in:
Benoit Martins 2024-05-17 11:17:00 +02:00
parent a011e7643b
commit 415cf274b1
4 changed files with 95 additions and 54 deletions

View file

@ -42,6 +42,8 @@ struct ConversationFragment: View {
@StateObject private var viewModel = ChatViewModel()
@StateObject private var paginationState = PaginationState()
@State private var displayFloatingButton = false
var body: some View {
NavigationView {
GeometryReader { geometry in
@ -158,8 +160,7 @@ struct ConversationFragment: View {
isScrolledToBottom: $isScrolledToBottom,
showMessageMenuOnLongPress: showMessageMenuOnLongPress,
geometryProxy: geometry,
sections: conversationViewModel.conversationMessagesSection,
ids: conversationViewModel.conversationMessagesIds
sections: conversationViewModel.conversationMessagesSection
)
if !isScrolledToBottom {
@ -217,56 +218,99 @@ struct ConversationFragment: View {
conversationViewModel.resetMessage()
}
} else {
/*
ScrollViewReader { proxy in
List {
ForEach(0..<conversationViewModel.conversationMessagesList.count, id: \.self) { index in
if index < conversationViewModel.conversationMessagesSection.first!.rows.count {
ChatBubbleView(conversationViewModel: conversationViewModel, message: conversationViewModel.conversationMessagesSection.first!.rows[index], geometryProxy: geometry)
.id(conversationViewModel.conversationMessagesList[index])
.listRowInsets(EdgeInsets(top: 2, leading: 10, bottom: 2, trailing: 10))
.listRowSeparator(.hidden)
.scaleEffect(x: 1, y: -1, anchor: .center)
.onAppear {
if index == conversationViewModel.conversationMessagesList.count - 1 && conversationViewModel.displayedConversationHistorySize > conversationViewModel.conversationMessagesList.count {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
conversationViewModel.getOldMessages()
}
}
}
ZStack(alignment: .bottomTrailing) {
List {
if conversationViewModel.conversationMessagesSection.first != nil {
let counter = conversationViewModel.conversationMessagesSection.first!.rows.count
ForEach(0..<counter, id: \.self) { index in
ChatBubbleView(conversationViewModel: conversationViewModel, message: conversationViewModel.conversationMessagesSection.first!.rows[index], geometryProxy: geometry)
.id(conversationViewModel.conversationMessagesSection.first!.rows[index].id)
.listRowInsets(EdgeInsets(top: 2, leading: 10, bottom: 2, trailing: 10))
.listRowSeparator(.hidden)
.scaleEffect(x: 1, y: -1, anchor: .center)
.onAppear {
if index == counter - 1
&& conversationViewModel.displayedConversationHistorySize > conversationViewModel.conversationMessagesSection.first!.rows.count {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
conversationViewModel.getOldMessages()
}
}
if index == 0 {
displayFloatingButton = false
}
}
.onDisappear {
if index == 0 {
displayFloatingButton = true
}
}
}
}
}
.scaleEffect(x: 1, y: -1, anchor: .center)
.listStyle(.plain)
if displayFloatingButton {
Button {
if conversationViewModel.conversationMessagesSection.first != nil && conversationViewModel.conversationMessagesSection.first!.rows.first != nil {
withAnimation {
proxy.scrollTo(conversationViewModel.conversationMessagesSection.first!.rows.first!.id)
}
}
} label: {
ZStack {
Image("caret-down")
.renderingMode(.template)
.foregroundStyle(.white)
.padding()
.background(Color.orangeMain500)
.clipShape(Circle())
.shadow(color: .black.opacity(0.2), radius: 4)
if conversationViewModel.displayedConversationUnreadMessagesCount > 0 {
VStack {
HStack {
Spacer()
HStack {
Text(
conversationViewModel.displayedConversationUnreadMessagesCount < 99
? String(conversationViewModel.displayedConversationUnreadMessagesCount)
: "99+"
)
.foregroundStyle(.white)
.default_text_style(styleSize: 10)
.lineLimit(1)
}
.frame(width: 18, height: 18)
.background(Color.redDanger500)
.cornerRadius(50)
}
Spacer()
}
}
}
}
.frame(width: 50, height: 50)
.padding()
}
}
.scaleEffect(x: 1, y: -1, anchor: .center)
.listStyle(.plain)
.onTapGesture {
UIApplication.shared.endEditing()
}
.onAppear {
conversationViewModel.getMessages()
}
.onChange(of: conversationViewModel.conversationMessagesList) { _ in
/*
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
if conversationViewModel.conversationMessagesList.count <= 30 {
proxy.scrollTo(
conversationViewModel.conversationMessagesList.first, anchor: .top
)
} else if conversationViewModel.conversationMessagesList.count >= conversationViewModel.displayedConversationHistorySize {
proxy.scrollTo(
conversationViewModel.conversationMessagesList[conversationViewModel.displayedConversationHistorySize%30], anchor: .top
)
} else {
proxy.scrollTo(30, anchor: .top)
}
}
*/
}
.onDisappear {
conversationViewModel.resetMessage()
}
}
*/
}
HStack(spacing: 0) {
@ -399,6 +443,13 @@ struct ConversationFragment: View {
}
}
struct ScrollOffsetPreferenceKey: PreferenceKey {
static var defaultValue: CGPoint = .zero
static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) {
}
}
extension UIApplication {
func endEditing() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)

View file

@ -35,7 +35,6 @@ struct UIList: UIViewRepresentable {
let showMessageMenuOnLongPress: Bool
let geometryProxy: GeometryProxy
let sections: [MessagesSection]
let ids: [String]
@State private var isScrolledToTop = false
@ -153,7 +152,6 @@ struct UIList: UIViewRepresentable {
// apply the rest of the changes to table's dataSource, i.e. inserts
//print("5 apply inserts")
context.coordinator.sections = sections
context.coordinator.ids = ids
tableView.beginUpdates()
for operation in insertOperations {
@ -164,7 +162,6 @@ struct UIList: UIViewRepresentable {
updateSemaphore.signal()
}
} else {
context.coordinator.ids = ids
updateSemaphore.signal()
}
}
@ -312,8 +309,7 @@ struct UIList: UIViewRepresentable {
isScrolledToTop: $isScrolledToTop,
showMessageMenuOnLongPress: showMessageMenuOnLongPress,
geometryProxy: geometryProxy,
sections: sections,
ids: ids
sections: sections
)
}
@ -329,9 +325,8 @@ struct UIList: UIViewRepresentable {
let showMessageMenuOnLongPress: Bool
let geometryProxy: GeometryProxy
var sections: [MessagesSection]
var ids: [String]
init(conversationViewModel: ConversationViewModel, viewModel: ChatViewModel, paginationState: PaginationState, isScrolledToBottom: Binding<Bool>, isScrolledToTop: Binding<Bool>, showMessageMenuOnLongPress: Bool, geometryProxy: GeometryProxy, sections: [MessagesSection], ids: [String]) {
init(conversationViewModel: ConversationViewModel, viewModel: ChatViewModel, paginationState: PaginationState, isScrolledToBottom: Binding<Bool>, isScrolledToTop: Binding<Bool>, showMessageMenuOnLongPress: Bool, geometryProxy: GeometryProxy, sections: [MessagesSection]) {
self.conversationViewModel = conversationViewModel
self.viewModel = viewModel
self.paginationState = paginationState
@ -340,7 +335,6 @@ struct UIList: UIViewRepresentable {
self.showMessageMenuOnLongPress = showMessageMenuOnLongPress
self.geometryProxy = geometryProxy
self.sections = sections
self.ids = ids
}
func numberOfSections(in tableView: UITableView) -> Int {
@ -384,8 +378,6 @@ struct UIList: UIViewRepresentable {
}
.minSize(width: 0, height: 0)
.margins(.all, 0)
} else {
// Fallback on earlier versions
}
tableViewCell.transform = CGAffineTransformMakeScale(1, -1)
@ -395,7 +387,7 @@ struct UIList: UIViewRepresentable {
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let row = sections[indexPath.section].rows[indexPath.row]
paginationState.handle(row, ids: ids)
paginationState.handle(row)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
@ -452,13 +444,10 @@ final class PaginationState: ObservableObject {
self.offset = offset
}
func handle(_ message: Message, ids: [String]) {
func handle(_ message: Message) {
guard shouldHandlePagination else {
return
}
if ids.prefix(offset + 1).contains(message.id) {
onEvent?(message)
}
}
}

View file

@ -36,7 +36,6 @@ class ConversationViewModel: ObservableObject {
private var chatRoomSuscriptions = Set<AnyCancellable?>()
@Published var conversationMessagesIds: [String] = []
@Published var conversationMessagesSection: [MessagesSection] = []
@Published var participantConversationModel: [ContactAvatarModel] = []

View file

@ -21,6 +21,7 @@ import SwiftUI
import linphonesw
struct Avatar: View {
@State var id = UUID()
private var contactsManager = ContactsManager.shared
@ -73,6 +74,7 @@ struct Avatar: View {
EmptyView()
}
}
.id(id)
} else if !contactAvatarModel.name.isEmpty {
Image(uiImage: contactsManager.textToImage(
firstName: contactAvatarModel.name,