mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 02:58:07 +00:00
Add message search feature
This commit is contained in:
parent
6575a4b0f2
commit
d111e03eef
6 changed files with 290 additions and 139 deletions
|
|
@ -2,6 +2,6 @@ import Foundation
|
|||
|
||||
public enum AppGitInfo {
|
||||
public static let branch = "master"
|
||||
public static let commit = "990d2f36a"
|
||||
public static let commit = "6575a4b0f"
|
||||
public static let tag = "6.1.0-alpha"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,8 +251,11 @@
|
|||
"conversation_info_participant_is_admin_label" = "Admin";
|
||||
"conversation_info_participants_list_title" = "Group members (%d)";
|
||||
"conversation_invalid_participant_due_to_security_mode_toast" = "Can't create conversation with a participant not on the same domain due to security restrictions!";
|
||||
"conversation_menu_configure_ephemeral_messages" = "Ephemeral messages";
|
||||
"conversation_menu_search_in_messages" = "Search";
|
||||
"conversation_menu_go_to_info" = "Conversation info";
|
||||
"conversation_menu_configure_ephemeral_messages" = "Ephemeral messages";
|
||||
"conversation_menu_media_files" = "Media";
|
||||
"conversation_menu_documents_files" = "Documents";
|
||||
"conversation_message_forward_cancelled_toast" = "Message forward was cancelled";
|
||||
"conversation_message_forwarded_toast" = "Message was forwarded";
|
||||
"conversation_message_meeting_cancelled_label" = "Meeting has been cancelled!";
|
||||
|
|
|
|||
|
|
@ -251,8 +251,11 @@
|
|||
"conversation_info_participant_is_admin_label" = "Administrateur";
|
||||
"conversation_info_participants_list_title" = "Participants (%d)";
|
||||
"conversation_invalid_participant_due_to_security_mode_toast" = "Pour des raisons de sécurité, la création d'une conversation avec un participant d'un domaine tiers est désactivé.";
|
||||
"conversation_menu_configure_ephemeral_messages" = "Messages éphémères";
|
||||
"conversation_menu_search_in_messages" = "Chercher";
|
||||
"conversation_menu_go_to_info" = "Informations";
|
||||
"conversation_menu_configure_ephemeral_messages" = "Messages éphémères";
|
||||
"conversation_menu_media_files" = "Médias";
|
||||
"conversation_menu_documents_files" = "Documents";
|
||||
"conversation_message_forward_cancelled_toast" = "Transfert annulé";
|
||||
"conversation_message_forwarded_toast" = "Message transféré";
|
||||
"conversation_message_meeting_cancelled_label" = "La réunion a été annulée";
|
||||
|
|
|
|||
|
|
@ -981,7 +981,7 @@ struct DynamicLinkText: View {
|
|||
if
|
||||
let encoded = word.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
|
||||
let url = URL(string: encoded),
|
||||
["http", "https"].contains(url.scheme)
|
||||
["http", "https", "sip", "sips"].contains(url.scheme)
|
||||
{
|
||||
var link = AttributedString(word)
|
||||
link.link = url
|
||||
|
|
@ -999,7 +999,7 @@ struct DynamicLinkText: View {
|
|||
var mention = AttributedString("@" + participant.name)
|
||||
mention.link = mentionURL
|
||||
mention.foregroundColor = Color.orangeMain500
|
||||
mention.font = .system(size: 14, weight: .semibold)
|
||||
mention.font = .system(size: 14)
|
||||
result.append(mention)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ struct ConversationFragment: View {
|
|||
@State var isMenuOpen = false
|
||||
@State private var isMuted: Bool = false
|
||||
|
||||
@FocusState var isSearchTextFocused: Bool
|
||||
@FocusState var isMessageTextFocused: Bool
|
||||
|
||||
@State var offset: CGPoint = .zero
|
||||
|
|
@ -81,11 +82,13 @@ struct ConversationFragment: View {
|
|||
@Binding var isShowConversationInfoPopup: Bool
|
||||
@Binding var conversationInfoPopupText: String
|
||||
|
||||
@State var searchText: String = ""
|
||||
@State var messageText: String = ""
|
||||
|
||||
@State private var chosen: String?
|
||||
@State private var showPicker = false
|
||||
@State private var isSheetVisible = false
|
||||
@State private var isSearchVisible = false
|
||||
|
||||
@State private var isImdnOrReactionsSheetVisible = false
|
||||
|
||||
|
|
@ -292,6 +295,7 @@ struct ConversationFragment: View {
|
|||
.edgesIgnoringSafeArea(.top)
|
||||
.frame(height: 0)
|
||||
|
||||
if !isSearchVisible {
|
||||
HStack {
|
||||
if (!(orientation == .landscapeLeft || orientation == .landscapeRight
|
||||
|| UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height)) || isShowConversationFragment {
|
||||
|
|
@ -398,6 +402,25 @@ struct ConversationFragment: View {
|
|||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
isMenuOpen = false
|
||||
withAnimation {
|
||||
isSearchVisible = true
|
||||
}
|
||||
isSearchTextFocused = true
|
||||
} label: {
|
||||
HStack {
|
||||
Text("conversation_menu_search_in_messages")
|
||||
Spacer()
|
||||
Image("magnifying-glass")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c500)
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
}
|
||||
}
|
||||
|
||||
if !(SharedMainViewModel.shared.displayedConversation?.isReadOnly ?? cachedConversation!.isReadOnly) {
|
||||
Button {
|
||||
isMenuOpen = false
|
||||
|
|
@ -456,6 +479,64 @@ struct ConversationFragment: View {
|
|||
.padding(.horizontal)
|
||||
.padding(.bottom, 4)
|
||||
.background(.white)
|
||||
} else {
|
||||
HStack {
|
||||
Image("caret-left")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c500)
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
.padding(.top, 4)
|
||||
.padding(.leading, -10)
|
||||
.onTapGesture {
|
||||
searchText = ""
|
||||
conversationViewModel.latestMatch = nil
|
||||
withAnimation {
|
||||
isSearchVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
TextField("conversation_menu_search_in_messages", text: $searchText)
|
||||
.default_text_style(styleSize: 15)
|
||||
.focused($isSearchTextFocused)
|
||||
.padding(.vertical, 5)
|
||||
.submitLabel(.search)
|
||||
.onSubmit {
|
||||
conversationViewModel.searchChatMessage(direction: .Up, textToSearch: searchText)
|
||||
}
|
||||
|
||||
Button {
|
||||
// TODO
|
||||
} label: {
|
||||
Image("caret-up")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c500)
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
.padding(.top, 4)
|
||||
}
|
||||
|
||||
Button {
|
||||
// TODO
|
||||
} label: {
|
||||
Image("caret-down")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c500)
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
.padding(.top, 4)
|
||||
}
|
||||
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 50)
|
||||
.padding(.horizontal)
|
||||
.padding(.bottom, 4)
|
||||
.background(.white)
|
||||
}
|
||||
|
||||
if #available(iOS 16.0, *) {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
|
|
@ -593,7 +674,7 @@ struct ConversationFragment: View {
|
|||
.transition(.move(edge: .bottom))
|
||||
}
|
||||
|
||||
if !(SharedMainViewModel.shared.displayedConversation?.isReadOnly ?? cachedConversation!.isReadOnly) {
|
||||
if !(SharedMainViewModel.shared.displayedConversation?.isReadOnly ?? cachedConversation!.isReadOnly) && !isSearchVisible {
|
||||
if conversationViewModel.messageToReply != nil {
|
||||
ZStack(alignment: .top) {
|
||||
HStack {
|
||||
|
|
|
|||
|
|
@ -106,6 +106,10 @@ class ConversationViewModel: ObservableObject {
|
|||
|
||||
@Published var isSwiping = false
|
||||
|
||||
@Published var searchInProgress = false
|
||||
|
||||
var latestMatch: EventLogMessage?
|
||||
|
||||
struct SheetCategory: Identifiable {
|
||||
let id = UUID()
|
||||
let name: String
|
||||
|
|
@ -2964,6 +2968,66 @@ class ConversationViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func searchChatMessage(direction: SearchDirection, textToSearch: String) {
|
||||
if let displayedConversation = self.sharedMainViewModel.displayedConversation {
|
||||
searchInProgress = true
|
||||
|
||||
if let match = displayedConversation.chatRoom.searchChatMessageByText(text: textToSearch, from: latestMatch?.eventModel.eventLog ?? nil, direction: direction) {
|
||||
|
||||
Log.info("\(ConversationViewModel.TAG) Found result \(match.chatMessage?.messageId ?? "No message id") while looking up for message with text \(textToSearch) in direction \(direction) starting from message \(latestMatch?.eventModel.eventLog.chatMessage?.messageId ?? "No message id")"
|
||||
)
|
||||
|
||||
if let sectionIndex = conversationMessagesSection.firstIndex(where: {
|
||||
$0.chatRoomID == displayedConversation.id
|
||||
}),
|
||||
let rowIndex = conversationMessagesSection[sectionIndex].rows.firstIndex(where: {
|
||||
$0.eventModel.eventLogId == match.chatMessage?.messageId
|
||||
}) {
|
||||
latestMatch = conversationMessagesSection[sectionIndex].rows[rowIndex]
|
||||
|
||||
Log.info("\(ConversationViewModel.TAG) Found result is already in history, no need to load more history")
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onScrollToIndex"), object: nil, userInfo: ["index": rowIndex, "animated": true])
|
||||
}
|
||||
print("searchChatMessageAAA 00")
|
||||
|
||||
searchInProgress = false
|
||||
} else {
|
||||
latestMatch = nil
|
||||
|
||||
Log.info("\(ConversationViewModel.TAG) Found result isn't in currently loaded history, loading missing events")
|
||||
//loadMessagesUpTo(match)
|
||||
print("searchChatMessageAAA 11")
|
||||
}
|
||||
|
||||
//canSearchDown = true
|
||||
} else {
|
||||
Log.info("\(ConversationViewModel.TAG) No match found while looking up for message with text \(textToSearch) in direction \(direction) starting from message \(latestMatch?.eventModel.eventLog.chatMessage?.messageId ?? "No message id")"
|
||||
)
|
||||
searchInProgress = false
|
||||
if latestMatch == nil {
|
||||
print("searchChatMessageAAA 22")
|
||||
// R.string.conversation_search_no_match_found
|
||||
} else {
|
||||
print("searchChatMessageAAA 33")
|
||||
// Scroll to last matching event anyway, user may have scrolled away
|
||||
if let sectionIndex = conversationMessagesSection.firstIndex(where: {
|
||||
$0.chatRoomID == displayedConversation.id
|
||||
}), let latestMatchTmp = latestMatch,
|
||||
let rowIndex = conversationMessagesSection[sectionIndex].rows.firstIndex(of: latestMatchTmp) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onScrollToIndex"), object: nil, userInfo: ["index": rowIndex, "animated": true])
|
||||
}
|
||||
print("searchChatMessageAAA 33Bis")
|
||||
}
|
||||
// R.string.conversation_search_no_more_match
|
||||
}
|
||||
// showRedToast(message, R.drawable.magnifying_glass)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// swiftlint:enable line_length
|
||||
// swiftlint:enable type_body_length
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue