diff --git a/Linphone/core/chat/message/EventLogProxy.cpp b/Linphone/core/chat/message/EventLogProxy.cpp index bf6ec9e0..cca0a677 100644 --- a/Linphone/core/chat/message/EventLogProxy.cpp +++ b/Linphone/core/chat/message/EventLogProxy.cpp @@ -94,10 +94,26 @@ int EventLogProxy::findFirstUnreadIndex() { return std::max(0, getCount() - 1); } +int EventLogProxy::findIndexCorrespondingToFilter(int startIndex, bool goingBackward) { + auto filter = getFilterText(); + if (filter.isEmpty()) return startIndex; + int endIndex = goingBackward ? 0 : getCount() - 1; + startIndex = goingBackward ? startIndex - 1 : startIndex + 1; + for (int i = startIndex; (goingBackward ? i >= 0 : i < getCount() - 1); (goingBackward ? --i : ++i)) { + auto eventLog = getItemAt(i); + if (!eventLog) continue; + if (auto message = eventLog->getChatMessageCore()) { + auto text = message->getText(); + int regexIndex = text.indexOf(filter, 0, Qt::CaseInsensitive); + if (regexIndex != -1) return i; + } + } + return -1; +} + bool EventLogProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { - // auto l = getItemAtSource(sourceRow); - // return l != nullptr; - return true; + auto l = getItemAtSource(sourceRow); + return l != nullptr; } bool EventLogProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const { diff --git a/Linphone/core/chat/message/EventLogProxy.hpp b/Linphone/core/chat/message/EventLogProxy.hpp index efc33490..5ca46352 100644 --- a/Linphone/core/chat/message/EventLogProxy.hpp +++ b/Linphone/core/chat/message/EventLogProxy.hpp @@ -46,6 +46,7 @@ public: Q_INVOKABLE EventLogGui *getEventAtIndex(int index); Q_INVOKABLE int findFirstUnreadIndex(); + Q_INVOKABLE int findIndexCorrespondingToFilter(int startIndex, bool goingBackward = false); signals: void eventChanged(); diff --git a/Linphone/data/languages/de.ts b/Linphone/data/languages/de.ts index 4680d6ff..0f93bfac 100644 --- a/Linphone/data/languages/de.ts +++ b/Linphone/data/languages/de.ts @@ -691,7 +691,7 @@ media_encryption_dtls DTLS - DTLS + @@ -703,7 +703,7 @@ media_encryption_srtp SRTP - SRTP + @@ -788,6 +788,26 @@ CallHistoryLayout + + contact_presence_status_online + "En ligne" + Online + + + contact_presence_status_busy + "Occupé" + Beschäftigt + + + contact_presence_status_do_not_disturb + "Ne pas déranger" + Nicht stören + + + contact_presence_status_offline + "Hors ligne" + Offline + meeting_info_join_title @@ -1034,6 +1054,16 @@ "Lancer" Starten + + history_group_call_start_dialog_subject_hint + "Nom du groupe" + Gruppenname + + + required + "Requis" + Erforderlich + @@ -1777,79 +1807,79 @@ ChatMessage - + chat_message_copy_selection "Copy selection" - + chat_message_copy "Copy" - + chat_message_copied_to_clipboard_title Copied - + chat_message_copied_to_clipboard_toast "to clipboard" - + chat_message_remote_replied %1 replied - - chat_message_forward - Forward - - - - - chat_message_remote_replied_to - %1 replied to %2 - - - - + chat_message_forwarded Forwarded - + + chat_message_remote_replied_to + %1 replied to %2 + + + + chat_message_user_replied_to You replied to %1 - + chat_message_user_replied You replied - + chat_message_reception_info "Reception info" - + chat_message_reply Reply - + + chat_message_forward + Forward + + + + chat_message_delete "Delete" @@ -2004,20 +2034,45 @@ Error ChatMessagesListView - + + + popup_info_find_message_title + Find message + + + + + info_popup_no_result_message + No result found + + + + + info_popup_first_result_message + First result reached + + + + + info_popup_last_result_message + Last result reached + + + + chat_message_list_encrypted_header_title End to end encrypted chat - + chat_message_list_encrypted_header_message Les messages de cette conversation sont chiffrés de bout en bout. Seul votre correspondant peut les déchiffrer. - + chat_message_is_writing_info %1 is writing… @@ -2187,6 +2242,26 @@ Error Contact + + drawer_menu_account_connection_status_connected + "Connecté" + Verbunden + + + drawer_menu_account_connection_status_cleared + "Désactivé" + Deaktiviert + + + drawer_menu_account_connection_status_refreshing + "Connexion…" + Verbinden… + + + drawer_menu_account_connection_status_failed + "Erreur" + Fehler + information_popup_error_title @@ -2216,74 +2291,74 @@ Error - + contact_editor_dialog_cancel_change_message "Les changements seront annulés. Souhaitez-vous continuer ?" Änderungen werden verworfen. Möchten Sie fortfahren? - + contact_editor_mandatory_first_name_not_filled "Veuillez saisir un prénom" Bitte geben Sie einen Vornamen ein - + contact_editor_mandatory_address_or_number_not_filled "Veuillez saisir une adresse ou un numéro de téléphone" Bitte geben Sie eine SIP-Adresse oder Telefonnummer ein - + contact_editor_add_image_label "Ajouter une image" Bild hinzufügen - + contact_details_edit "Modifier" Bearbeiten - + contact_details_delete "Supprimer" Löschen - + contact_editor_first_name "Prénom" Vorname - + contact_editor_last_name "Nom" Nachname - + contact_editor_company "Entreprise" Unternehmen - + contact_editor_job_title "Fonction" Beruf - - + + sip_address SIP-Adresse - - + + phone "Téléphone" Telefon @@ -2500,6 +2575,26 @@ Error "Appel vidéo" Videoanruf + + contact_presence_status_online + "En ligne" + Online + + + contact_presence_status_busy + "Occupé" + Beschäftigt + + + contact_presence_status_do_not_disturb + "Ne pas déranger" + Nicht stören + + + contact_presence_status_offline + "Hors ligne" + Offline + contact_details_numbers_and_addresses_title @@ -3068,26 +3163,32 @@ Error GroupConversationInfos - + group_infos_call "Appel" Anrufen - + group_infos_mute Stummschalten - + group_infos_unmute "Sourdine" Unmute + group_infos_search + "Rechercher" + + + + group_infos_meeting - "Réunion" + Schedule a meeting Meeting @@ -3101,6 +3202,11 @@ Error Medias & documents Medien & Dokumente + + group_infos_shared_media + Shared medias + Geteilte Medien + group_infos_shared_docs @@ -3108,44 +3214,47 @@ Error Geteilte Dokumente - + group_infos_other_actions + Other actions Weitere Aktionen - + group_infos_enable_ephemerals Flüchtige Nachrichten aktivieren - + group_infos_ephemerals Ephemeral messages : - + group_infos_leave_room + Leave chat room - + group_infos_delete_history + Delete history Verlauf löschen - + group_infos_delete_history_toast_title Delete history ? Verlauf löschen? - + group_infos_delete_history_toast_message All the messages will be removed from the chat room. Do you want to continue ? Alle Nachrichten werden aus dem Chat entfernt. Möchten Sie fortfahren? - + group_infos_leave_room_toast_title Leave Chat Room ? Chatraum verlassen? @@ -3157,7 +3266,7 @@ Error - + group_infos_leave_room_toast_message All the messages will be removed from the chat room. Do you want to continue ? Alle Nachrichten werden aus dem Chat entfernt. Möchten Sie fortfahren? @@ -3943,6 +4052,10 @@ Error meeting_schedule_add_participants_apply Apply + + add + Hinzufügen + group_call_participant_selected @@ -4078,6 +4191,11 @@ Error "Appels en cours" Laufender Anruf + + search_bar_look_for_contact_text + "Rechercher un contact" + Kontakt suchen + call_start_group_call_title @@ -4259,82 +4377,82 @@ Error OneOneConversationInfos - + one_one_infos_call "Appel" Anrufen - + one_one_infos_mute Stummschalten - + one_one_infos_unmute "Sourdine" Unmute - + one_one_infos_search "Rechercher" Suchen - + one_one_infos_media_docs Medien & Dokumente - + one_one_infos_shared_media Geteilte Medien - + one_one_infos_shared_docs Geteilte Dokumente - + one_one_infos_other_actions Weitere Aktionen - + one_one_infos_enable_ephemerals Flüchtige Nachrichten aktivieren - + one_one_infos_ephemerals Ephemeral messages : - + one_one_infos_delete_history Verlauf löschen - + one_one_infos_delete_history_toast_title Delete history ? Verlauf löschen? - + one_one_infos_delete_history_toast_message All the messages will be removed from the chat room. Do you want to continue ? Alle Nachrichten werden aus dem Chat entfernt. Möchten Sie fortfahren? - + one_one_infos_open_contact Kontakt öffnen - + one_one_infos_create_contact Kontakt erstellen @@ -4405,10 +4523,22 @@ Error QObject + + DTLS + DTLS + + + None + Nichts + + + SRTP + SRTP + media_encryption_dtls - DTLS + @@ -4418,7 +4548,7 @@ Error media_encryption_srtp - SRTP + @@ -4865,36 +4995,36 @@ Pour les activer dans un projet commercial, merci de nous contacter. SelectedChatView - + chat_view_group_call_toast_message Start a group call ? - + reply_to_label Reply to %1 - + shared_medias_title Shared medias - + shared_documents_title Shared documents - + forward_to_title - Transfer to... + Forward to… - + conversations_title Conversations diff --git a/Linphone/data/languages/en.ts b/Linphone/data/languages/en.ts index 9f96e513..bd1abb6e 100644 --- a/Linphone/data/languages/en.ts +++ b/Linphone/data/languages/en.ts @@ -1769,79 +1769,79 @@ ChatMessage - + chat_message_copy_selection "Copy selection" Copy selection - + chat_message_copy "Copy" Copy - + chat_message_copied_to_clipboard_title Copied Copied - + chat_message_copied_to_clipboard_toast "to clipboard" in clipboard - + chat_message_remote_replied %1 replied %1 replied to - - chat_message_forward - Forward - Forward - - - - chat_message_remote_replied_to - %1 replied to %2 - %1 replied to %2 - - - + chat_message_forwarded Forwarded Forwarded - + + chat_message_remote_replied_to + %1 replied to %2 + %1 replied to %2 + + + chat_message_user_replied_to You replied to %1 You replied to %1 - + chat_message_user_replied You replied You replied - + chat_message_reception_info "Reception info" Reception info - + chat_message_reply Reply Reply - + + chat_message_forward + Forward + Forward + + + chat_message_delete "Delete" Delete @@ -1996,13 +1996,38 @@ Error ChatMessagesListView - + + + popup_info_find_message_title + Find message + Find message + + + + info_popup_no_result_message + No result found + No result found + + + + info_popup_first_result_message + First result reached + First result reached + + + + info_popup_last_result_message + Last result reached + Last result reached + + + chat_message_list_encrypted_header_title End to end encrypted chat End to end encrypted chat - + chat_message_list_encrypted_header_message Les messages de cette conversation sont chiffrés de bout en bout. Seul votre correspondant peut les déchiffrer. @@ -2010,7 +2035,7 @@ Error Only your correspondent can decrypt them. - + chat_message_is_writing_info %1 is writing… %1 is writing… @@ -2209,74 +2234,74 @@ Only your correspondent can decrypt them. - + contact_editor_dialog_cancel_change_message "Les changements seront annulés. Souhaitez-vous continuer ?" Changes will be discarded. Do you wish to continue? - + contact_editor_mandatory_first_name_not_filled "Veuillez saisir un prénom" Please enter a first name - + contact_editor_mandatory_address_or_number_not_filled "Veuillez saisir une adresse ou un numéro de téléphone" Please enter a SIP address or phone number - + contact_editor_add_image_label "Ajouter une image" Add an image - + contact_details_edit "Modifier" Edit - + contact_details_delete "Supprimer" Delete - + contact_editor_first_name "Prénom" First name - + contact_editor_last_name "Nom" Last name - + contact_editor_company "Entreprise" Company - + contact_editor_job_title "Fonction" Job - - + + sip_address SIP address - - + + phone "Téléphone" Phone @@ -3063,33 +3088,39 @@ Expiration : %1 GroupConversationInfos - + group_infos_call "Appel" Call - + group_infos_mute Mute - + group_infos_unmute "Sourdine" Unmute - + group_infos_meeting - "Réunion" - Meeting + Schedule a meeting + Schedule a meeting group_infos_participants Participants (%1) + + + group_infos_search + "Rechercher" + Search + group_infos_media_docs @@ -3109,50 +3140,53 @@ Expiration : %1 Shared documents - + group_infos_other_actions + Other actions Other actions - + group_infos_enable_ephemerals Enable ephemeral messages - + group_infos_ephemerals Ephemeral messages : - + group_infos_delete_history + Delete history Delete history - + group_infos_delete_history_toast_title Delete history ? Delete history ? - + group_infos_delete_history_toast_message All the messages will be removed from the chat room. Do you want to continue ? All the messages will be removed from the chat room. Do you want to continue ? - + group_infos_leave_room + Leave chat room Leave Chat Room - + group_infos_leave_room_toast_title Leave Chat Room ? Leave Chat Room ? - + group_infos_leave_room_toast_message All the messages will be removed from the chat room. Do you want to continue ? All the messages will be removed from the chat room. Do you want to continue ? @@ -4249,82 +4283,82 @@ Expiration : %1 OneOneConversationInfos - + one_one_infos_call "Appel" Call - + one_one_infos_mute Mute - + one_one_infos_unmute "Sourdine" Unmute - + one_one_infos_search "Rechercher" Search - + one_one_infos_media_docs Medias & documents - + one_one_infos_shared_media Shared medias - + one_one_infos_shared_docs Shared documents - + one_one_infos_other_actions Other actions - + one_one_infos_enable_ephemerals Enable ephemeral messages - + one_one_infos_ephemerals Ephemeral messages : - + one_one_infos_delete_history Delete history - + one_one_infos_delete_history_toast_title Delete history ? Delete history ? - + one_one_infos_delete_history_toast_message All the messages will be removed from the chat room. Do you want to continue ? All the messages will be removed from the chat room. Do you want to continue ? - + one_one_infos_open_contact Show contact - + one_one_infos_create_contact Create contact @@ -4855,36 +4889,36 @@ To enable them in a commercial project, please contact us. SelectedChatView - + chat_view_group_call_toast_message Start a group call ? - + reply_to_label Reply to %1 Reply to %1 - + shared_medias_title Shared medias Shared medias - + shared_documents_title Shared documents Shared documents - + forward_to_title - Transfer to... - Transfer to… + Forward to… + Froward to… - + conversations_title Conversations Conversations diff --git a/Linphone/data/languages/fr_FR.ts b/Linphone/data/languages/fr_FR.ts index 69cf47f3..0b672aa3 100644 --- a/Linphone/data/languages/fr_FR.ts +++ b/Linphone/data/languages/fr_FR.ts @@ -1769,79 +1769,79 @@ ChatMessage - + chat_message_copy_selection "Copy selection" Copier la sélection - + chat_message_copy "Copy" Copier - + chat_message_copied_to_clipboard_title Copied Copié - + chat_message_copied_to_clipboard_toast "to clipboard" dans le presse-papiers - + chat_message_remote_replied %1 replied %1 a répondu - - chat_message_forward - Forward - Transférer - - - - chat_message_remote_replied_to - %1 replied to %2 - %1 a répondu à %2 - - - + chat_message_forwarded Forwarded Transféré - + + chat_message_remote_replied_to + %1 replied to %2 + %1 a répondu à %2 + + + chat_message_user_replied_to You replied to %1 Vous avez répondu à %1 - + chat_message_user_replied You replied Vous avez répondu - + chat_message_reception_info "Reception info" Info de réception - + chat_message_reply Reply Répondre - + + chat_message_forward + Forward + Transférer + + + chat_message_delete "Delete" Supprimer @@ -1996,13 +1996,38 @@ Error ChatMessagesListView - + + + popup_info_find_message_title + Find message + Trouver un message + + + + info_popup_no_result_message + No result found + Aucun résultat trouvé + + + + info_popup_first_result_message + First result reached + Premier résultat atteint + + + + info_popup_last_result_message + Last result reached + Dernier résultat atteint + + + chat_message_list_encrypted_header_title End to end encrypted chat Conversation chiffrée de bout en bout - + chat_message_list_encrypted_header_message Les messages de cette conversation sont chiffrés de bout en bout. Seul votre correspondant peut les déchiffrer. @@ -2010,7 +2035,7 @@ Error en bout. Seul votre correspondant peut les déchiffrer. - + chat_message_is_writing_info %1 is writing… %1 est en train d'écrire… @@ -2209,74 +2234,74 @@ en bout. Seul votre correspondant peut les déchiffrer. - + contact_editor_dialog_cancel_change_message "Les changements seront annulés. Souhaitez-vous continuer ?" Les changements seront annulés. Souhaitez-vous continuer ? - + contact_editor_mandatory_first_name_not_filled "Veuillez saisir un prénom" Veuillez saisir un prénom - + contact_editor_mandatory_address_or_number_not_filled "Veuillez saisir une adresse ou un numéro de téléphone" Veuillez saisir une adresse ou un numéro de téléphone - + contact_editor_add_image_label "Ajouter une image" Ajouter une image - + contact_details_edit "Modifier" Modifier - + contact_details_delete "Supprimer" Supprimer - + contact_editor_first_name "Prénom" Prénom - + contact_editor_last_name "Nom" Nom - + contact_editor_company "Entreprise" Entreprise - + contact_editor_job_title "Fonction" Fonction - - + + sip_address Adresse SIP - - + + phone "Téléphone" Téléphone @@ -3063,33 +3088,39 @@ Expiration : %1 GroupConversationInfos - + group_infos_call "Appel" Appel - + group_infos_mute Sourdine - + group_infos_unmute "Sourdine" Réactiver les notifications - + group_infos_meeting - "Réunion" - Réunion + Schedule a meeting + Programmer une réunion group_infos_participants Participants (%1) + + + group_infos_search + "Rechercher" + Rechercher + group_infos_media_docs @@ -3109,50 +3140,53 @@ Expiration : %1 Documents partagés - + group_infos_other_actions + Other actions Autres actions - + group_infos_enable_ephemerals Activer les messages éphémères - + group_infos_ephemerals Messages éphémères : - + group_infos_delete_history + Delete history Supprimer l'historique - + group_infos_delete_history_toast_title Delete history ? Supprimer l'historique ? - + group_infos_delete_history_toast_message All the messages will be removed from the chat room. Do you want to continue ? Tous les messages seront supprimés. Souhaitez-vous continuer ? - + group_infos_leave_room + Leave chat room Quitter la conversation - + group_infos_leave_room_toast_title Leave Chat Room ? Quitter la conversation ? - + group_infos_leave_room_toast_message All the messages will be removed from the chat room. Do you want to continue ? Vous ne recevrez ni pourrez envoyer des messages dans cette conversation, quitter ? @@ -4249,82 +4283,82 @@ Expiration : %1 OneOneConversationInfos - + one_one_infos_call "Appel" Appel - + one_one_infos_mute Sourdine - + one_one_infos_unmute "Sourdine" Réactiver les notifications - + one_one_infos_search "Rechercher" Rechercher - + one_one_infos_media_docs Medias & documents - + one_one_infos_shared_media Médias partagés - + one_one_infos_shared_docs Documents partagés - + one_one_infos_other_actions Autres actions - + one_one_infos_enable_ephemerals Activer les messages éphémères - + one_one_infos_ephemerals Messages éphémères : - + one_one_infos_delete_history Supprimer l'historique - + one_one_infos_delete_history_toast_title Delete history ? Supprimer l'historique ? - + one_one_infos_delete_history_toast_message All the messages will be removed from the chat room. Do you want to continue ? Tous les messages seront supprimés. Souhaitez-vous continuer ? - + one_one_infos_open_contact Voir le contact - + one_one_infos_create_contact Créer un contact @@ -4855,36 +4889,36 @@ Pour les activer dans un projet commercial, merci de nous contacter. SelectedChatView - + chat_view_group_call_toast_message Démarrer un appel de groupe ? - + reply_to_label Reply to %1 Réponse à %1 - + shared_medias_title Shared medias Médias partagés - + shared_documents_title Shared documents Documents partagés - + forward_to_title - Transfer to... + Forward to… Transférer à… - + conversations_title Conversations Conversations @@ -5207,7 +5241,7 @@ Failed to create 1-1 conversation with %1 ! chat_message_forward_error Cannot forward an invalid message - Transfert impossible: message invalide + Impossible de transférer : message invalide @@ -5230,25 +5264,25 @@ Failed to create 1-1 conversation with %1 ! info_popup_send_forward_message_error_message Failed to create forward message - Le transfert du message a échoué + Impossible de créer le message chat_message_reply_error Cannot reply to invalid message - Impossible de répondre: message invalide + Impossible de répondre : message invalide info_popup_reply_message_error Could not send reply message : %1 - Impossible d'envoyer la réponse: %1 + Impossible d'envoyer la réponse : %1 info_popup_send_reply_message_error_message Failed to create reply message - La création du message a échoué + Impossible de créer le message diff --git a/Linphone/view/Control/Container/Main/MainRightPanel.qml b/Linphone/view/Control/Container/Main/MainRightPanel.qml index 968217f2..c1451517 100644 --- a/Linphone/view/Control/Container/Main/MainRightPanel.qml +++ b/Linphone/view/Control/Container/Main/MainRightPanel.qml @@ -8,28 +8,36 @@ import UtilsCpp 1.0 ColumnLayout { id: mainItem property color panelColor: DefaultStyle.grey_100 - property alias headerContent: rightPanelHeader.children + property alias headerContentItem: rightPanelHeader.contentItem property alias content: rightPanelContent.children property alias header: rightPanelHeader spacing: 0 - Item { - Layout.preferredHeight: Math.round(57 * DefaultStyle.dp) + Control.Control { + id: rightPanelHeader Layout.fillWidth: true z: rightPanelContent.z + 1 - Rectangle { - id: rightPanelHeader + topPadding: Math.round(30 * DefaultStyle.dp) + bottomPadding: Math.round(24 * DefaultStyle.dp) + leftPadding: Math.round(32 * DefaultStyle.dp) + rightPadding: Math.round(32 * DefaultStyle.dp) + + background: Item { anchors.fill: parent - color: DefaultStyle.grey_0 - } - MultiEffect { - anchors.fill: rightPanelHeader - source: rightPanelHeader - shadowEnabled: true - shadowColor: DefaultStyle.grey_1000 - shadowBlur: 1 - shadowOpacity: 0.05 - shadowVerticalOffset: Math.round(10 * DefaultStyle.dp) + Rectangle { + id: bg + anchors.fill: parent + color: DefaultStyle.grey_0 + } + MultiEffect { + anchors.fill: bg + source: bg + shadowEnabled: true + shadowColor: DefaultStyle.grey_1000 + shadowBlur: 1 + shadowOpacity: 0.05 + shadowVerticalOffset: Math.round(10 * DefaultStyle.dp) + } } } Rectangle { diff --git a/Linphone/view/Control/Display/Chat/ChatMessage.qml b/Linphone/view/Control/Display/Chat/ChatMessage.qml index a625bf43..d431379c 100644 --- a/Linphone/view/Control/Display/Chat/ChatMessage.qml +++ b/Linphone/view/Control/Display/Chat/ChatMessage.qml @@ -16,6 +16,7 @@ Control.Control { property ChatMessageGui chatMessage property ChatGui chat + property string searchedTextPart property string ownReaction: chatMessage? chatMessage.core.ownReaction : "" property string fromAddress: chatMessage? chatMessage.core.fromAddress : "" property bool isRemoteMessage: chatMessage? chatMessage.core.isRemoteMessage : false @@ -37,6 +38,17 @@ Control.Control { signal replyToMessageRequested() signal forwardMessageRequested() + Timer { + id: hightlightTimer + interval: 1000 + repeat: false + onTriggered: highlightRectangle.opacity = 0 + } + function requestHighlight() { + highlightRectangle.opacity = 0.8 + hightlightTimer.start() + } + background: Item { anchors.fill: parent } @@ -214,6 +226,21 @@ Control.Control { height: Math.round(parent.height / 4) color: mainItem.backgroundColor } + Rectangle { + id: highlightRectangle + anchors.fill: parent + radius: Math.round(16 * DefaultStyle.dp) + color: Qt.lighter(mainItem.backgroundColor, 2) + border.color: mainItem.backgroundColor + border.width: Math.round(2 * DefaultStyle.dp) + opacity: 0 + Behavior on opacity { + NumberAnimation { + duration: 300 + easing.type: Easing.InOutQuad + } + } + } } contentItem: ColumnLayout { spacing: Math.round(5 * DefaultStyle.dp) @@ -222,6 +249,7 @@ Control.Control { Layout.fillWidth: true Layout.fillHeight: true chatGui: mainItem.chat + searchedTextPart: mainItem.searchedTextPart chatMessageGui: mainItem.chatMessage onMouseEvent: (event) => { mainItem.handleDefaultMouseEvent(event) diff --git a/Linphone/view/Control/Display/Chat/ChatMessageContent.qml b/Linphone/view/Control/Display/Chat/ChatMessageContent.qml index d7964224..e9306f3c 100644 --- a/Linphone/view/Control/Display/Chat/ChatMessageContent.qml +++ b/Linphone/view/Control/Display/Chat/ChatMessageContent.qml @@ -20,6 +20,7 @@ ColumnLayout { property string selectedText property color textColor + property string searchedTextPart property int fileBorderWidth : 0 @@ -89,6 +90,7 @@ ColumnLayout { // height: implicitHeight contentGui: modelData chatGui: mainItem.chatGui + searchedTextPart: mainItem.searchedTextPart onLastTextSelectedChanged: mainItem.selectedText = selectedText // onRightClicked: mainItem.rightClicked() } diff --git a/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml b/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml index 32fd6b1b..81d64301 100644 --- a/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml +++ b/Linphone/view/Control/Display/Chat/ChatMessagesListView.qml @@ -5,9 +5,6 @@ import QtQuick.Controls.Basic as Control import Qt.labs.qmlmodels import Linphone import UtilsCpp -import SettingsCpp -import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle -import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils ListView { id: mainItem @@ -19,6 +16,41 @@ ListView { signal showImdnStatusForMessageRequested(ChatMessageGui chatMessage) signal replyToMessageRequested(ChatMessageGui chatMessage) signal forwardMessageRequested(ChatMessageGui chatMessage) + signal requestHighlight(int indexToHighlight) + + property string filterText + onFilterTextChanged: { + if (filterText === "") return + eventLogProxy.filterText = filterText + var indexVisible = indexAt(contentX, contentY) + var found = eventLogProxy.findIndexCorrespondingToFilter(indexVisible) + if (found !== -1) { + currentIndex = found + positionViewAtIndex(found, ListView.Center) + requestHighlight(found) + } else { + //: Find message + UtilsCpp.showInformationPopup(qsTr("popup_info_find_message_title"), + //: No result found + qsTr("info_popup_no_result_message"), false) + } + } + signal findIndexWithFilter(bool goingBackward) + onFindIndexWithFilter: (goingBackward) => { + var nextIndex = eventLogProxy.findIndexCorrespondingToFilter(currentIndex, goingBackward) + if (nextIndex !== -1 && nextIndex !== currentIndex) { + currentIndex = nextIndex + positionViewAtIndex(nextIndex, ListView.Center) + requestHighlight(nextIndex) + } else if (currentIndex !== -1) { + //: Find message + UtilsCpp.showInformationPopup(qsTr("popup_info_find_message_title"), + //: First result reached + goingBackward ? qsTr("info_popup_first_result_message") + //: Last result reached + : qsTr("info_popup_last_result_message"), false) + } + } Component.onCompleted: { Qt.callLater(function() { @@ -57,6 +89,7 @@ ListView { id: eventLogProxy chatGui: mainItem.chat // scroll when in view and message inserted + filterText: mainItem.filterText onEventInserted: (index, gui) => { if (!mainItem.visible) return mainItem.positionViewAtIndex(index, ListView.End) @@ -132,6 +165,7 @@ ListView { } chatMessage: modelData chat: mainItem.chat + searchedTextPart: mainItem.filterText maxWidth: Math.round(mainItem.width * (3/4)) onVisibleChanged: { if (visible) { @@ -152,6 +186,14 @@ ListView { onShowImdnStatusForMessageRequested: mainItem.showImdnStatusForMessageRequested(modelData) onReplyToMessageRequested: mainItem.replyToMessageRequested(modelData) onForwardMessageRequested: mainItem.forwardMessageRequested(modelData) + Connections { + target: mainItem + function onRequestHighlight(indexToHighlight) { + if (indexToHighlight === index) { + requestHighlight() + } + } + } } } @@ -193,9 +235,9 @@ ListView { property bool showTopMargin: !header.visible && index == 0 width: mainItem.width //height: 40 * DefaultStyle.dp - height: (showTopMargin ? 30 : 0 * DefaultStyle.dp) + eventItem.height + height: (showTopMargin ? 30 : 0 * DefaultStyle.dp) + ephemeralEventItem.height EphemeralEvent { - id: eventItem + id: ephemeralEventItem anchors.top: parent.top anchors.topMargin: showTopMargin ? 30 : 0 * DefaultStyle.dp eventLogGui: modelData diff --git a/Linphone/view/Control/Display/Chat/ChatTextContent.qml b/Linphone/view/Control/Display/Chat/ChatTextContent.qml index ff16a86f..bb3bdad5 100644 --- a/Linphone/view/Control/Display/Chat/ChatTextContent.qml +++ b/Linphone/view/Control/Display/Chat/ChatTextContent.qml @@ -13,6 +13,7 @@ TextEdit { property ChatMessageContentGui contentGui property ChatGui chatGui: null property string lastTextSelected : '' + property string searchedTextPart color: DefaultStyle.main2_700 font { pixelSize: (contentGui && UtilsCpp.isOnlyEmojis(contentGui.core.text)) ? Typography.h1.pixelSize : Typography.p1.pixelSize @@ -27,7 +28,11 @@ TextEdit { property var encodeTextObj: visible ? UtilsCpp.encodeTextToQmlRichFormat(contentGui.core.utf8Text, {}, mainItem.chatGui) : '' - text: encodeTextObj && encodeTextObj.value || "" + text: encodeTextObj + && (searchedTextPart !== "" + ? UtilsCpp.boldTextPart(encodeTextObj.value, searchedTextPart) + : encodeTextObj.value) + || "" textFormat: Text.RichText // To supports links and imgs. wrapMode: TextEdit.Wrap diff --git a/Linphone/view/Control/Input/SearchBar.qml b/Linphone/view/Control/Input/SearchBar.qml index be31fd37..cb999688 100644 --- a/Linphone/view/Control/Input/SearchBar.qml +++ b/Linphone/view/Control/Input/SearchBar.qml @@ -66,7 +66,7 @@ FocusScope { anchors.verticalCenter: parent.verticalCenter property string searchText - + focus: true placeholderText: mainItem.placeholderText placeholderTextColor: mainItem.placeholderTextColor diff --git a/Linphone/view/Page/Form/Chat/SelectedChatView.qml b/Linphone/view/Page/Form/Chat/SelectedChatView.qml index dbce5bd0..0a9c52da 100644 --- a/Linphone/view/Page/Form/Chat/SelectedChatView.qml +++ b/Linphone/view/Page/Form/Chat/SelectedChatView.qml @@ -17,8 +17,9 @@ RowLayout { property var contactObj: chat ? UtilsCpp.findFriendByAddress(mainItem.chat.core.peerAddress) : null property var contact: contactObj?.value || null property CallGui call - property alias callHeaderContent: splitPanel.headerContent + property alias callHeaderContent: splitPanel.headerContentItem property bool replyingToMessage: false + property bool showSearchBar: false spacing: 0 enum PanelType { MessageReactions, SharedFiles, Medias, ImdnStatus, ForwardToList, ManageParticipants, EphemeralSettings, None} @@ -61,73 +62,131 @@ RowLayout { panelColor: DefaultStyle.grey_0 header.visible: !mainItem.call clip: true - headerContent: [ + header.leftPadding: Math.round(32 * DefaultStyle.dp) + header.rightPadding: Math.round(32 * DefaultStyle.dp) + header.topPadding: Math.round(6 * DefaultStyle.dp) + header.bottomPadding: mainItem.showSearchBar ? Math.round(3 * DefaultStyle.dp) : Math.round(6 * DefaultStyle.dp) + + headerContentItem: ColumnLayout { + anchors.left: parent?.left + anchors.leftMargin: mainItem.call ? 0 : Math.round(31 * DefaultStyle.dp) + anchors.verticalCenter: parent?.verticalCenter + anchors.right: parent.right + anchors.rightMargin: Math.round(41 * DefaultStyle.dp) + spacing: searchBarLayout.visible ? Math.round(9 * DefaultStyle.dp) : 0 RowLayout { - anchors.left: parent?.left - anchors.leftMargin: mainItem.call ? 0 : Math.round(31 * DefaultStyle.dp) - anchors.verticalCenter: parent?.verticalCenter - spacing: Math.round(12 * DefaultStyle.dp) - Avatar { - property var contactObj: mainItem.chat ? UtilsCpp.findFriendByAddress(mainItem.chat?.core.peerAddress) : null - contact: contactObj?.value || null - displayNameVal: contact ? "" : mainItem.chat.core.avatarUri - Layout.preferredWidth: Math.round(45 * DefaultStyle.dp) - Layout.preferredHeight: Math.round(45 * DefaultStyle.dp) - } - Text { - text: mainItem.chat?.core.title || "" - color: DefaultStyle.main2_600 - Layout.fillWidth: true - maximumLineCount: 1 - font { - pixelSize: Typography.h4.pixelSize - weight: Math.round(400 * DefaultStyle.dp) - capitalization: Font.Capitalize + RowLayout { + id: chatHeader + spacing: Math.round(12 * DefaultStyle.dp) + Avatar { + property var contactObj: mainItem.chat ? UtilsCpp.findFriendByAddress(mainItem.chat?.core.peerAddress) : null + contact: contactObj?.value || null + displayNameVal: contact ? "" : mainItem.chat.core.avatarUri + Layout.preferredWidth: Math.round(45 * DefaultStyle.dp) + Layout.preferredHeight: Math.round(45 * DefaultStyle.dp) + } + Text { + text: mainItem.chat?.core.title || "" + color: DefaultStyle.main2_600 + Layout.fillWidth: true + maximumLineCount: 1 + font { + pixelSize: Typography.h4.pixelSize + weight: Math.round(400 * DefaultStyle.dp) + capitalization: Font.Capitalize + } + } + EffectImage { + visible: mainItem.chat?.core.muted + Layout.preferredWidth: 20 * DefaultStyle.dp + Layout.alignment: Qt.AlignVCenter + Layout.preferredHeight: 20 * DefaultStyle.dp + colorizationColor: DefaultStyle.main1_500_main + imageSource: AppIcons.bellSlash } } - EffectImage { - visible: mainItem.chat?.core.muted - Layout.preferredWidth: 20 * DefaultStyle.dp - Layout.alignment: Qt.AlignVCenter - Layout.preferredHeight: 20 * DefaultStyle.dp - colorizationColor: DefaultStyle.main1_500_main - imageSource: AppIcons.bellSlash - } - }, - RowLayout { - anchors.right: parent.right - anchors.rightMargin: Math.round(41 * DefaultStyle.dp) - anchors.verticalCenter: parent.verticalCenter - BigButton { - style: ButtonStyle.noBackground - icon.source: AppIcons.phone - onPressed: { - if (mainItem.chat.core.isGroupChat) { - mainItem.groupCall() - } else { - mainItem.oneOneCall(false) - } - } - } - BigButton { - style: ButtonStyle.noBackground - icon.source: AppIcons.videoCamera - visible: !mainItem.chat.core.isGroupChat - onPressed: mainItem.oneOneCall(true) - } - BigButton { - id: detailsPanelButton - style: ButtonStyle.noBackground - checkable: true - checkedImageColor: DefaultStyle.main1_500_main - icon.source: AppIcons.info - checked: detailsPanel.visible - onCheckedChanged: { - detailsPanel.visible = checked + Item{Layout.fillWidth: true} + RowLayout { + spacing: Math.round(16 * DefaultStyle.dp) + RoundButton { + style: ButtonStyle.noBackground + icon.source: AppIcons.phone + onPressed: { + if (mainItem.chat.core.isGroupChat) { + mainItem.groupCall() + } else { + mainItem.oneOneCall(false) + } + } + } + RoundButton { + style: ButtonStyle.noBackground + icon.source: AppIcons.videoCamera + visible: !mainItem.chat.core.isGroupChat + onPressed: mainItem.oneOneCall(true) + } + RoundButton { + id: detailsPanelButton + style: ButtonStyle.noBackground + checkable: true + checkedImageColor: DefaultStyle.main1_500_main + icon.source: AppIcons.info + checked: detailsPanel.visible + onCheckedChanged: { + detailsPanel.visible = checked + } } } } - ] + RowLayout { + id: searchBarLayout + visible: mainItem.showSearchBar + onVisibleChanged: { + if(!visible) chatMessagesSearchBar.clearText() + else chatMessagesSearchBar.forceActiveFocus() + } + spacing: Math.round(50 * DefaultStyle.dp) + height: Math.round(65 * DefaultStyle.dp) + SearchBar { + id: chatMessagesSearchBar + Layout.fillWidth: true + Layout.rightMargin: Math.round(10 * DefaultStyle.dp) + delaySearch: false + Keys.onPressed: (event) => { + if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) { + if (chatMessagesListView.filterText !== text) { + chatMessagesListView.filterText = text + } else { + if (event.modifiers & Qt.ShiftModifier) { + chatMessagesListView.findIndexWithFilter(true) + } else { + chatMessagesListView.findIndexWithFilter(false) + } + } + } + } + } + RowLayout { + spacing: Math.round(10 * DefaultStyle.dp) + RoundButton { + icon.source: AppIcons.upArrow + style: ButtonStyle.noBackground + onClicked: chatMessagesListView.findIndexWithFilter(true) + } + RoundButton { + icon.source: AppIcons.downArrow + style: ButtonStyle.noBackground + onClicked: chatMessagesListView.findIndexWithFilter(false) + } + } + RoundButton { + icon.source: AppIcons.closeX + Layout.rightMargin: Math.round(20 * DefaultStyle.dp) + onClicked: mainItem.showSearchBar = false + style: ButtonStyle.noBackground + } + } + } content: Control.SplitView { anchors.fill: parent @@ -472,6 +531,10 @@ RowLayout { onEphemeralSettingsRequested: contentLoader.panelType = SelectedChatView.PanelType.EphemeralSettings onShowSharedFilesRequested: (showMedias) => { contentLoader.panelType = showMedias ? SelectedChatView.PanelType.SharedFiles : SelectedChatView.PanelType.Medias + } + onSearchInHistoryRequested: { + mainItem.showSearchBar = true + detailsPanel.visible = false } } } @@ -485,6 +548,10 @@ RowLayout { contentLoader.panelType = showMedias ? SelectedChatView.PanelType.SharedFiles : SelectedChatView.PanelType.Medias } onEphemeralSettingsRequested: contentLoader.panelType = SelectedChatView.PanelType.EphemeralSettings + onSearchInHistoryRequested: { + mainItem.showSearchBar = true + detailsPanel.visible = false + } } } @@ -545,7 +612,7 @@ RowLayout { Component { id: forwardToListsComponent MessageInfosLayout { - //: Transfer to... + //: Forward to… title: qsTr("forward_to_title") // width: detailsPanel.width // RectangleTest{anchors.fill: parent} diff --git a/Linphone/view/Page/Form/Contact/ContactEdition.qml b/Linphone/view/Page/Form/Contact/ContactEdition.qml index def43e71..152a2c5d 100644 --- a/Linphone/view/Page/Form/Contact/ContactEdition.qml +++ b/Linphone/view/Page/Form/Contact/ContactEdition.qml @@ -41,38 +41,33 @@ MainRightPanel { text: qsTr("contact_editor_dialog_cancel_change_message") } - headerContent: [ - Text { - anchors.left: parent.left - anchors.leftMargin: Math.round(31 * DefaultStyle.dp) - anchors.verticalCenter: parent.verticalCenter - text: mainItem.title - font { - pixelSize: Math.round(20 * DefaultStyle.dp) - weight: Typography.h4.weight - } - }, - Button { - style: ButtonStyle.noBackground - anchors.right: parent.right - anchors.rightMargin: Math.round(41 * DefaultStyle.dp) - anchors.verticalCenter: parent.verticalCenter - width: Math.round(24 * DefaultStyle.dp) - height: Math.round(24 * DefaultStyle.dp) - icon.source: AppIcons.closeX - icon.width: Math.round(24 * DefaultStyle.dp) - icon.height: Math.round(24 * DefaultStyle.dp) - onClicked: { - if (contact.core.isSaved) mainItem.closeEdition('') - else showConfirmationLambdaPopup("", qsTr("contact_editor_dialog_cancel_change_message"), "", function(confirmed) { - if (confirmed) { - mainItem.contact.core.undo() - mainItem.closeEdition('') - } - }) - } + headerContentItem: RowLayout { + Text { + text: mainItem.title + font { + pixelSize: Math.round(20 * DefaultStyle.dp) + weight: Typography.h4.weight } - ] + } + Item{Layout.fillWidth: true} + Button { + style: ButtonStyle.noBackground + width: Math.round(24 * DefaultStyle.dp) + height: Math.round(24 * DefaultStyle.dp) + icon.source: AppIcons.closeX + icon.width: Math.round(24 * DefaultStyle.dp) + icon.height: Math.round(24 * DefaultStyle.dp) + onClicked: { + if (contact.core.isSaved) mainItem.closeEdition('') + else showConfirmationLambdaPopup("", qsTr("contact_editor_dialog_cancel_change_message"), "", function(confirmed) { + if (confirmed) { + mainItem.contact.core.undo() + mainItem.closeEdition('') + } + }) + } + } + } content: ContactLayout { anchors.fill: parent diff --git a/Linphone/view/Page/Layout/Chat/ChatInfoActionsGroup.qml b/Linphone/view/Page/Layout/Chat/ChatInfoActionsGroup.qml index eb81dad0..e8bbb68a 100644 --- a/Linphone/view/Page/Layout/Chat/ChatInfoActionsGroup.qml +++ b/Linphone/view/Page/Layout/Chat/ChatInfoActionsGroup.qml @@ -43,7 +43,7 @@ ColumnLayout { Item { Layout.fillWidth: true - Layout.preferredHeight: Math.round(56 * DefaultStyle.dp) + Layout.preferredHeight: visible ? Math.round(56 * DefaultStyle.dp) : 0 visible: modelData.visible RowLayout { diff --git a/Linphone/view/Page/Layout/Chat/GroupConversationInfos.qml b/Linphone/view/Page/Layout/Chat/GroupConversationInfos.qml index 62608150..5e4b3027 100644 --- a/Linphone/view/Page/Layout/Chat/GroupConversationInfos.qml +++ b/Linphone/view/Page/Layout/Chat/GroupConversationInfos.qml @@ -18,6 +18,7 @@ ColumnLayout { signal manageParticipantsRequested() signal ephemeralSettingsRequested() signal showSharedFilesRequested(bool showMedias) + signal searchInHistoryRequested() spacing: 0 @@ -144,7 +145,6 @@ ColumnLayout { button.onClicked: parentView.groupCall() } LabelButton { - visible: !SettingsCpp.disableMeetingsFeature text.Layout.fillWidth: true text.horizontalAlignment: Text.AlignHCenter text.wrapMode: Text.Wrap @@ -153,11 +153,11 @@ ColumnLayout { Layout.maximumWidth: Math.round(130 * DefaultStyle.dp) button.icon.width: Math.round(24 * DefaultStyle.dp) button.icon.height: Math.round(24 * DefaultStyle.dp) - button.icon.source: AppIcons.videoconference - //: "Réunion" - label: qsTr("group_infos_meeting") + button.icon.source: AppIcons.search + //: "Rechercher" + label: qsTr("group_infos_search") button.onClicked: { - UtilsCpp.getMainWindow().scheduleMeeting(mainItem.chatCore.title, mainItem.chatCore.participantsAddresses) + mainItem.searchInHistoryRequested() } } } @@ -232,6 +232,7 @@ ColumnLayout { ChatInfoActionsGroup { Layout.topMargin: Math.round(17 * DefaultStyle.dp) + //: Other actions title: qsTr("group_infos_other_actions") entries: [ { @@ -244,9 +245,21 @@ ColumnLayout { mainItem.ephemeralSettingsRequested() } }, + { + visible: !SettingsCpp.disableMeetingsFeature, + icon: AppIcons.videoconference, + color: DefaultStyle.main2_600, + showRightArrow: false, + //: Schedule a meeting + text: qsTr("group_infos_meeting"), + action: function() { + UtilsCpp.getMainWindow().scheduleMeeting(mainItem.chatCore.title, mainItem.chatCore.participantsAddresses) + } + }, { icon: AppIcons.signOut, visible: !mainItem.chatCore.isReadOnly, + //: Leave chat room text: qsTr("group_infos_leave_room"), color: DefaultStyle.main2_600, showRightArrow: false, @@ -266,6 +279,7 @@ ColumnLayout { { icon: AppIcons.trashCan, visible: true, + //: Delete history text: qsTr("group_infos_delete_history"), color: DefaultStyle.danger_500main, showRightArrow: false, diff --git a/Linphone/view/Page/Layout/Chat/OneOneConversationInfos.qml b/Linphone/view/Page/Layout/Chat/OneOneConversationInfos.qml index 29707f78..6819628b 100644 --- a/Linphone/view/Page/Layout/Chat/OneOneConversationInfos.qml +++ b/Linphone/view/Page/Layout/Chat/OneOneConversationInfos.qml @@ -18,6 +18,7 @@ ColumnLayout { spacing: 0 signal ephemeralSettingsRequested() signal showSharedFilesRequested() + signal searchInHistoryRequested() Avatar { @@ -102,7 +103,7 @@ ColumnLayout { //: "Rechercher" label: qsTr("one_one_infos_search") button.onClicked: { - //TODO + mainItem.searchInHistoryRequested() } } }