mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 11:08:06 +00:00
Fix conversation for iOS 15
This commit is contained in:
parent
a011e7643b
commit
415cf274b1
4 changed files with 95 additions and 54 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ class ConversationViewModel: ObservableObject {
|
|||
|
||||
private var chatRoomSuscriptions = Set<AnyCancellable?>()
|
||||
|
||||
@Published var conversationMessagesIds: [String] = []
|
||||
@Published var conversationMessagesSection: [MessagesSection] = []
|
||||
@Published var participantConversationModel: [ContactAvatarModel] = []
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue