diff --git a/CHANGELOG.md b/CHANGELOG.md index 72eea40c1..02f88ac08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Download path and emojis size settings - Mac emoji font. +- Better SVG preview in thumbnails. +- Unstable forward message menu. ### Added +- Dedicated call history view. - Chat reactions +- Update UI layouts. + +## Removed +- Call events from chats. +- Missed call count in application side (done by SDK). ## 5.1.3 - Undefined diff --git a/linphone-app/CMakeLists.txt b/linphone-app/CMakeLists.txt index a9134ce17..3a95af8e2 100644 --- a/linphone-app/CMakeLists.txt +++ b/linphone-app/CMakeLists.txt @@ -282,6 +282,9 @@ set(SOURCES src/components/file/TemporaryFile.cpp src/components/file/FileMediaModel.cpp src/components/friend/FriendListListener.cpp + src/components/history/CallHistoryModel.cpp + src/components/history/CallHistoryListModel.cpp + src/components/history/CallHistoryProxyModel.cpp src/components/history/HistoryModel.cpp src/components/history/HistoryProxyModel.cpp src/components/ldap/LdapModel.cpp @@ -429,6 +432,9 @@ set(HEADERS src/components/file/TemporaryFile.hpp src/components/file/FileMediaModel.hpp src/components/friend/FriendListListener.hpp + src/components/history/CallHistoryModel.hpp + src/components/history/CallHistoryListModel.hpp + src/components/history/CallHistoryProxyModel.hpp src/components/history/HistoryModel.hpp src/components/history/HistoryProxyModel.hpp src/components/ldap/LdapModel.hpp diff --git a/linphone-app/assets/images/call_history_custom.svg b/linphone-app/assets/images/call_history_custom.svg index ca74e1541..969706ad7 100644 --- a/linphone-app/assets/images/call_history_custom.svg +++ b/linphone-app/assets/images/call_history_custom.svg @@ -4,7 +4,7 @@ height="80" version="1.1" id="svg4" - sodipodi:docname="call_history_custom2.svg" + sodipodi:docname="call_custom.svg" inkscape:version="1.1 (c68e22c387, 2021-05-23)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" @@ -21,11 +21,11 @@ inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" showgrid="false" - inkscape:zoom="6.7098284" - inkscape:cx="2.6081144" - inkscape:cy="59.763078" + inkscape:zoom="4.7445652" + inkscape:cx="-20.760596" + inkscape:cy="12.013746" inkscape:window-width="1920" - inkscape:window-height="1131" + inkscape:window-height="1043" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" @@ -33,21 +33,10 @@ - + id="path2" /> diff --git a/linphone-app/assets/images/chat_amount.svg b/linphone-app/assets/images/chat_amount.svg index f957095f3..c532c20b9 100644 --- a/linphone-app/assets/images/chat_amount.svg +++ b/linphone-app/assets/images/chat_amount.svg @@ -11,7 +11,7 @@ - + diff --git a/linphone-app/assets/images/filter_params_custom.svg b/linphone-app/assets/images/filter_params_custom.svg index 194fecd9b..43fc2726c 100644 --- a/linphone-app/assets/images/filter_params_custom.svg +++ b/linphone-app/assets/images/filter_params_custom.svg @@ -1,105 +1,112 @@ - - - - - - - - - - - + xmlns:svg="http://www.w3.org/2000/svg"> + + + + + + + + + + + + + + + + + + diff --git a/linphone-app/assets/images/missed_incoming_call_custom.svg b/linphone-app/assets/images/missed_incoming_call_custom.svg index 2024d69e9..a53e5a81f 100644 --- a/linphone-app/assets/images/missed_incoming_call_custom.svg +++ b/linphone-app/assets/images/missed_incoming_call_custom.svg @@ -4,8 +4,8 @@ height="80" version="1.1" id="svg4" - sodipodi:docname="close_custom.svg" - inkscape:version="1.1 (c68e22c387, 2021-05-23)" + sodipodi:docname="missed_incoming_call_custom.svg" + inkscape:version="1.2.2 (b0a8486541, 2022-12-01)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" @@ -24,16 +24,18 @@ inkscape:zoom="4.1971154" inkscape:cx="-29.66323" inkscape:cy="23.34937" - inkscape:window-width="1920" - inkscape:window-height="1131" - inkscape:window-x="0" - inkscape:window-y="0" - inkscape:window-maximized="1" - inkscape:current-layer="svg4" /> + inkscape:window-width="1499" + inkscape:window-height="1111" + inkscape:window-x="26" + inkscape:window-y="23" + inkscape:window-maximized="0" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1" /> + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1" /> Šifrování médií + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -920,6 +948,11 @@ Adresa URL není nakonfigurována. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. Schůzka byla smazána + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1030,12 +1063,9 @@ Adresa URL není nakonfigurována. selectAllContacts + 'All' : Filter label to display all items. Vše - - selectConnectedContacts - Připojeno - addContact PŘIDAT KONTAKT @@ -1049,21 +1079,24 @@ Adresa URL není nakonfigurována. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. Chcete-li vytvořit chatovací místnost založenou na konferenci, musíte v nastavení účtu nastavit URI konference. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + Místní kontakty + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + KONTAKTY + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - VŠE - - - displayCalls - HOVORY - - - displayMessages - ZPRÁVY - removeAllEntriesDescription Jste si jisti, že chcete tuto historii vymazat? @@ -1855,11 +1888,6 @@ Klikněte zde: <a href="%1">%1</a> mainSearchBarPlaceholder Vyhledejte kontakt, začněte hovor nebo chat… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - KONTAKTY - autoAnswerStatus automaticky @@ -1877,26 +1905,11 @@ Klikněte zde: <a href="%1">%1</a> 'Start a chat room' : Tooltip to illustrate a button Založit chatovací místnost - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - Skrýt události - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - Otevřít časovou osu - openHome 'Open Home' : Tooltip for a button that open the home view Domů - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - Schůzky - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1913,9 +1926,24 @@ Klikněte zde: <a href="%1">%1</a> Chcete stáhnout a použít konfiguraci z této adresy URL? - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. - Místní kontakty + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list + @@ -3944,26 +3972,6 @@ Klikněte zde: <a href="%1">%1</a> Timeline - - timelineFilter - A title for filtering mode. - Filtr - - - timelineFilterAll - 'All' The mode for timelines filtering. - Vše - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - Vlastní - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - Místnosti s 1 a více účastníky - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3974,45 +3982,15 @@ Klikněte zde: <a href="%1">%1</a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). Skupiny chatu - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - Povoleny mizející zprávy - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list Hledat v seznamu - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - Všechny úrovně zabezpečení - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - Standardní místnosti - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - Jakékoli konverzace - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - Mizející zap/vyp - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - Bez mizejících - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. - Konference + chatsTitle + 'Messages' : Title for conversations + diff --git a/linphone-app/assets/languages/da.ts b/linphone-app/assets/languages/da.ts index b1e9f5b2f..f77b25099 100644 --- a/linphone-app/assets/languages/da.ts +++ b/linphone-app/assets/languages/da.ts @@ -451,6 +451,34 @@ + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -913,6 +941,11 @@ Server url ikke konfigureret. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1023,12 +1056,9 @@ Server url ikke konfigureret. selectAllContacts + 'All' : Filter label to display all items. Alle - - selectConnectedContacts - Forbundet - addContact OPRET KONTAKT @@ -1042,21 +1072,24 @@ Server url ikke konfigureret. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + KONTAKTER + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - ALLE - - - displayCalls - OPKALD - - - displayMessages - BESKEDER - removeAllEntriesDescription Er du sikker på at du vil rydde op historikken? @@ -1844,11 +1877,6 @@ Klik her: <a href="%1">%1</a> mainSearchBarPlaceholder Søg en kontakt, start en samtale eller en chat… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - KONTAKTER - autoAnswerStatus auto @@ -1866,26 +1894,11 @@ Klik her: <a href="%1">%1</a> 'Start a chat room' : Tooltip to illustrate a button - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - - openHome 'Open Home' : Tooltip for a button that open the home view - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1902,8 +1915,23 @@ Klik her: <a href="%1">%1</a> - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3906,26 +3934,6 @@ Klik her: <a href="%1">%1</a> Timeline - - timelineFilter - A title for filtering mode. - - - - timelineFilterAll - 'All' The mode for timelines filtering. - - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3936,44 +3944,14 @@ Klik her: <a href="%1">%1</a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. + chatsTitle + 'Messages' : Title for conversations diff --git a/linphone-app/assets/languages/de.ts b/linphone-app/assets/languages/de.ts index 6f739ec14..42d8e9790 100644 --- a/linphone-app/assets/languages/de.ts +++ b/linphone-app/assets/languages/de.ts @@ -451,6 +451,34 @@ Medienverschlüsselung + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -913,6 +941,11 @@ Server URL ist nicht konfiguriert. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. Diese Besprechungen wurde gelöscht + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1023,12 +1056,9 @@ Server URL ist nicht konfiguriert. selectAllContacts + 'All' : Filter label to display all items. Alle - - selectConnectedContacts - Verbunden - addContact KONTAKT HINZUFÜGEN @@ -1042,21 +1072,24 @@ Server URL ist nicht konfiguriert. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. Sie müssen eine Konferenz-URI in den Kontoeinstellungen festlegen um einen konferenzbasierten Chatraum zu erstellen. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + KONTAKTE + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - ALLE - - - displayCalls - ANRUFE - - - displayMessages - NACHRICHTEN - removeAllEntriesDescription Möchten Sie diese Historie wirklich löschen? @@ -1844,11 +1877,6 @@ Klicken Sie hier: <a href="%1">%1</a> mainSearchBarPlaceholder Suche Kontakte, starte einen Anruf oder Chat… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - KONTAKTE - autoAnswerStatus automatisch @@ -1866,26 +1894,11 @@ Klicken Sie hier: <a href="%1">%1</a> 'Start a chat room' : Tooltip to illustrate a button Starte einen Chatraum - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - Verlauf verstecken - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - Verlauf öffnen - openHome 'Open Home' : Tooltip for a button that open the home view Startseite öffnen - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - Besprechungen - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1902,8 +1915,23 @@ Klicken Sie hier: <a href="%1">%1</a> - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3906,26 +3934,6 @@ Klicken Sie hier: <a href="%1">%1</a> Timeline - - timelineFilter - A title for filtering mode. - Filter - - - timelineFilterAll - 'All' The mode for timelines filtering. - Alle - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - Individuell - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - Einfache Räume - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3936,44 +3944,14 @@ Klicken Sie hier: <a href="%1">%1</a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). Chatgruppen - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - Kurzlebiges - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list In der Liste suchen - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. + chatsTitle + 'Messages' : Title for conversations diff --git a/linphone-app/assets/languages/en.ts b/linphone-app/assets/languages/en.ts index 78a6c30dc..dbc9e3e7e 100644 --- a/linphone-app/assets/languages/en.ts +++ b/linphone-app/assets/languages/en.ts @@ -451,6 +451,34 @@ Media encryption + + CallTimeline + + callListTitle + 'Call list' : Call histories title + Call list + + + incomingFilter + 'Incoming' : Filter label for incoming call + Incoming + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + Outgoing + + + missedFilter + 'Missed' : Filter label for missed call + Missed + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + Search in the list + + CallTransfer @@ -913,6 +941,11 @@ Server URL not configured. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. The meeting has been deleted + + createMeeting + 'Create Meeting' : Button label to create a meeting + Create Meeting + ConfirmDialog @@ -1023,12 +1056,9 @@ Server URL not configured. selectAllContacts + 'All' : Filter label to display all items. All - - selectConnectedContacts - Connected - addContact ADD CONTACT @@ -1042,21 +1072,24 @@ Server URL not configured. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. You need to set the conference URI in your account settings to create a conference based chat room. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + Local contacts + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + Contacts + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + Online + Conversation - - displayCallsAndMessages - ALL - - - displayCalls - CALLS - - - displayMessages - MESSAGES - removeAllEntriesDescription Are you sure you want to clear this history? @@ -1844,11 +1877,6 @@ Click here: <a href="%1">%1</a> mainSearchBarPlaceholder Search contact, start a call or a chat… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - CONTACTS - autoAnswerStatus auto @@ -1866,26 +1894,11 @@ Click here: <a href="%1">%1</a> 'Start a chat room' : Tooltip to illustrate a button Start a chat room - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - Hide Timeline - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - Open Timeline - openHome 'Open Home' : Tooltip for a button that open the home view Open Home - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - Meetings - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1902,9 +1915,24 @@ Click here: <a href="%1">%1</a> Do you want to download and apply configuration from this URL? - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. - Local contacts + openCalls + 'Open call history' : Tooltip for a button that open the call history view + Open call history + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + Open chats + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + Open contacts + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list + Open meetings @@ -3931,26 +3959,6 @@ Click here: <a href="%1">%1</a> Timeline - - timelineFilter - A title for filtering mode. - Filter - - - timelineFilterAll - 'All' The mode for timelines filtering. - All - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - Custom - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - Simple rooms - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3961,45 +3969,15 @@ Click here: <a href="%1">%1</a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). Chat groups - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - Ephemerals - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list Search in the list - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - All security levels - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - Standard rooms - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - Any conversations - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - Ephemerals on/off - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - Without ephemerals - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. - Conferences + chatsTitle + 'Messages' : Title for conversations + Messages diff --git a/linphone-app/assets/languages/es.ts b/linphone-app/assets/languages/es.ts index 63d8255a5..2db10bc90 100644 --- a/linphone-app/assets/languages/es.ts +++ b/linphone-app/assets/languages/es.ts @@ -451,6 +451,34 @@ + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -913,6 +941,11 @@ URL del servidor no configurada. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1023,12 +1056,9 @@ URL del servidor no configurada. selectAllContacts + 'All' : Filter label to display all items. Todo - - selectConnectedContacts - Conectado - addContact AÑADIR CONTACTO @@ -1042,21 +1072,24 @@ URL del servidor no configurada. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. Debe configurar el URL de la conferencia en la configuración de su cuenta para crear una conferencia basada en una sala de chat. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + CONTACTOS + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - TODO - - - displayCalls - LLAMADAS - - - displayMessages - MENSAJES - removeAllEntriesDescription ¿Estás seguro de que quieres limpiar este historial? @@ -1844,11 +1877,6 @@ Haga clic aquí: <a href="%1">%1 </a> mainSearchBarPlaceholder Buscar contacto, empezar una llamada o un chat… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - CONTACTOS - autoAnswerStatus automático @@ -1866,26 +1894,11 @@ Haga clic aquí: <a href="%1">%1 </a> 'Start a chat room' : Tooltip to illustrate a button - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - - openHome 'Open Home' : Tooltip for a button that open the home view - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1902,8 +1915,23 @@ Haga clic aquí: <a href="%1">%1 </a> - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3906,26 +3934,6 @@ Haga clic aquí: <a href="%1">%1 </a> Timeline - - timelineFilter - A title for filtering mode. - - - - timelineFilterAll - 'All' The mode for timelines filtering. - - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3936,44 +3944,14 @@ Haga clic aquí: <a href="%1">%1 </a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. + chatsTitle + 'Messages' : Title for conversations diff --git a/linphone-app/assets/languages/fr_FR.ts b/linphone-app/assets/languages/fr_FR.ts index cf406224a..c6de378b1 100644 --- a/linphone-app/assets/languages/fr_FR.ts +++ b/linphone-app/assets/languages/fr_FR.ts @@ -451,6 +451,34 @@ Chiffrement du média + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -913,6 +941,11 @@ URL du serveur non configurée. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. La réunion a été supprimée + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1023,12 +1056,9 @@ URL du serveur non configurée. selectAllContacts + 'All' : Filter label to display all items. Tous - - selectConnectedContacts - Connectés - addContact AJOUTER UN CONTACT @@ -1042,21 +1072,24 @@ URL du serveur non configurée. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. Vous devez définir l'URI de la conférence dans les paramètres de votre compte pour créer une conférence. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + Contacts locaux + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + CONTACTS + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - TOUT - - - displayCalls - APPELS - - - displayMessages - MESSAGES - removeAllEntriesDescription Êtes-vous sûr de vouloir supprimer cet historique ? @@ -1844,11 +1877,6 @@ Cliquez ici : <a href="%1">%1</a> mainSearchBarPlaceholder Chercher un contact, appeler ou envoyer un message… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - CONTACTS - autoAnswerStatus auto @@ -1866,26 +1894,11 @@ Cliquez ici : <a href="%1">%1</a> 'Start a chat room' : Tooltip to illustrate a button Commencer une conversation - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - Masquer la chronologie - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - Afficher la chronologie - openHome 'Open Home' : Tooltip for a button that open the home view Ouvrir la page d'accueil - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - Réunions - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1902,9 +1915,24 @@ Cliquez ici : <a href="%1">%1</a> Voulez-vous télécharger et appliquer la configuration depuis cette adresse ? - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. - Contacts locaux + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list + @@ -3906,26 +3934,6 @@ Cliquez ici : <a href="%1">%1</a> Timeline - - timelineFilter - A title for filtering mode. - Filtre - - - timelineFilterAll - 'All' The mode for timelines filtering. - Tous - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - Personnalisé - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - Standards - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3936,45 +3944,15 @@ Cliquez ici : <a href="%1">%1</a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). Groupes standards - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - Éphémères - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list Rechercher dans la chronologie - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - Tous les niveaux de sécurité - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - Standards - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - Tous les types - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - Éphémères on/off - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - Sans éphémères - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. - Conférences + chatsTitle + 'Messages' : Title for conversations + diff --git a/linphone-app/assets/languages/hu.ts b/linphone-app/assets/languages/hu.ts index 4ec330b81..cdd9892f7 100644 --- a/linphone-app/assets/languages/hu.ts +++ b/linphone-app/assets/languages/hu.ts @@ -451,6 +451,34 @@ Média titkosítás + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -906,6 +934,11 @@ A kiszolgáló URL-je nincs konfigurálva. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1016,12 +1049,9 @@ A kiszolgáló URL-je nincs konfigurálva. selectAllContacts + 'All' : Filter label to display all items. Összes - - selectConnectedContacts - Kapcsolódva - addContact Névjegy hozzáadása @@ -1035,21 +1065,24 @@ A kiszolgáló URL-je nincs konfigurálva. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. Konferenciaalapú csevegőszoba létrehozásához be kell állítania a konferencia URI-címét a fiókbeállításokban. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + Névjegyek + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - Összes - - - displayCalls - Hívások - - - displayMessages - Üzenetek - removeAllEntriesDescription Biztosan törölni kívánja ezt az előzményt? @@ -1833,11 +1866,6 @@ Kattintson ide: <a href="%1">%1</a> mainSearchBarPlaceholder Névjegy keresése, hívás indítása vagy csevegés kezdése… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - Névjegyek - autoAnswerStatus önműködő @@ -1855,26 +1883,11 @@ Kattintson ide: <a href="%1">%1</a> 'Start a chat room' : Tooltip to illustrate a button Csevegőszoba indítása - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - Idővonal elrejtése - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - Idővonal megnyitása - openHome 'Open Home' : Tooltip for a button that open the home view Kezdőlap megnyitása - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1891,8 +1904,23 @@ Kattintson ide: <a href="%1">%1</a> - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3892,26 +3920,6 @@ Kattintson ide: <a href="%1">%1</a> Timeline - - timelineFilter - A title for filtering mode. - Szűrő - - - timelineFilterAll - 'All' The mode for timelines filtering. - Összes - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - Egyéni - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - Egyszerű szobák - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3922,44 +3930,14 @@ Kattintson ide: <a href="%1">%1</a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). Csevegőcsoportok - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - Elmúlók - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list Keresés a listában - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - Minden biztonsági szint - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - Szabványos szobák - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - Minden beszélgetés - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - Elmúlók be/ki - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - Elmúlók nélkül - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. + chatsTitle + 'Messages' : Title for conversations diff --git a/linphone-app/assets/languages/it.ts b/linphone-app/assets/languages/it.ts index 5dfe64ce2..5564589f1 100644 --- a/linphone-app/assets/languages/it.ts +++ b/linphone-app/assets/languages/it.ts @@ -451,6 +451,34 @@ Criptaggio dei dati multimediali + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -913,6 +941,11 @@ URL del server non configurato. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1023,12 +1056,9 @@ URL del server non configurato. selectAllContacts + 'All' : Filter label to display all items. Tutti - - selectConnectedContacts - Connesso - addContact AGGIUNGI UN CONTATTO @@ -1042,21 +1072,24 @@ URL del server non configurato. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. Per creare una chat di gruppo è necessario impostare la URI del gruppo nelle impostazioni del tuo account. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + CONTATTI + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - TUTTI - - - displayCalls - CHIAMATE - - - displayMessages - MESSAGGI - removeAllEntriesDescription Sei sicuro di voler cancellare questa cronologia? @@ -1844,11 +1877,6 @@ Clicca: <a href="%1">%1</a> mainSearchBarPlaceholder Cerca un contatto, avvia una chiamata o una chat… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - CONTATTI - autoAnswerStatus auto @@ -1866,26 +1894,11 @@ Clicca: <a href="%1">%1</a> 'Start a chat room' : Tooltip to illustrate a button Crea una chat di gruppo - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - Nascondi Timeline - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - Apri Timeline - openHome 'Open Home' : Tooltip for a button that open the home view Apri Home - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - Riunioni - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1902,8 +1915,23 @@ Clicca: <a href="%1">%1</a> - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3906,26 +3934,6 @@ Clicca: <a href="%1">%1</a> Timeline - - timelineFilter - A title for filtering mode. - - - - timelineFilterAll - 'All' The mode for timelines filtering. - - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3936,44 +3944,14 @@ Clicca: <a href="%1">%1</a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. + chatsTitle + 'Messages' : Title for conversations diff --git a/linphone-app/assets/languages/ja.ts b/linphone-app/assets/languages/ja.ts index e85314b7c..d8995af6d 100644 --- a/linphone-app/assets/languages/ja.ts +++ b/linphone-app/assets/languages/ja.ts @@ -451,6 +451,34 @@ メディア暗号化 + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -906,6 +934,11 @@ 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. ミーティングが削除されました + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1016,12 +1049,9 @@ selectAllContacts + 'All' : Filter label to display all items. 全て - - selectConnectedContacts - 接続済 - addContact 連絡先に追加 @@ -1035,21 +1065,24 @@ 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. 会議ベースのチャットルームを作成するには、アカウント設定で会議URIを設定する必要があります。 + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + ローカルの連絡先 + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + 連絡先 + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - 全て - - - displayCalls - を呼び出します - - - displayMessages - メッセージ - removeAllEntriesDescription 履歴をクリアしてよろしいですか? @@ -1833,11 +1866,6 @@ mainSearchBarPlaceholder 連絡先を検索するか、通話もしくはチャットを始める… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - 連絡先 - autoAnswerStatus 自動 @@ -1855,26 +1883,11 @@ 'Start a chat room' : Tooltip to illustrate a button チャットルームを開始 - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - タイムラインを非表示にする - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - タイムラインを開く - openHome 'Open Home' : Tooltip for a button that open the home view ホームを開く - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - ミーティング - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1891,9 +1904,24 @@ このURLから設定をダウンロードして適用しますか? - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. - ローカルの連絡先 + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list + @@ -3892,26 +3920,6 @@ Timeline - - timelineFilter - A title for filtering mode. - フィルター - - - timelineFilterAll - 'All' The mode for timelines filtering. - すべて - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - カスタム - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - シンプルなルーム - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3922,46 +3930,16 @@ 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). チャットグループ - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - 一時的 - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list リストから検索 - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - すべてのセキュリティレベル - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - スタンダードなルーム - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. + chatsTitle + 'Messages' : Title for conversations - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - 一時的 ON/OFF - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - 一時的を含まない - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. - 会議 - TimelineItem diff --git a/linphone-app/assets/languages/lt.ts b/linphone-app/assets/languages/lt.ts index a0284f060..131e58d51 100644 --- a/linphone-app/assets/languages/lt.ts +++ b/linphone-app/assets/languages/lt.ts @@ -451,6 +451,34 @@ + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -920,6 +948,11 @@ Nesukonfigūruotas serverio url. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1030,12 +1063,9 @@ Nesukonfigūruotas serverio url. selectAllContacts + 'All' : Filter label to display all items. Visi - - selectConnectedContacts - Prisijungę - addContact PRIDĖTI KONTAKTĄ @@ -1049,21 +1079,24 @@ Nesukonfigūruotas serverio url. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + KONTAKTAI + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - VISKAS - - - displayCalls - SKAMBUČIAI - - - displayMessages - ŽINUTĖS - removeAllEntriesDescription Ar tikrai norite išvalyti šią istoriją? @@ -1855,11 +1888,6 @@ Spustelėkite čia: <a href="%1">%1</a> mainSearchBarPlaceholder Ieškoti kontaktų, pradėti skambutį ar pokalbį… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - KONTAKTAI - autoAnswerStatus automatinis @@ -1877,26 +1905,11 @@ Spustelėkite čia: <a href="%1">%1</a> 'Start a chat room' : Tooltip to illustrate a button - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - - openHome 'Open Home' : Tooltip for a button that open the home view - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1913,8 +1926,23 @@ Spustelėkite čia: <a href="%1">%1</a> - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3920,26 +3948,6 @@ Spustelėkite čia: <a href="%1">%1</a> Timeline - - timelineFilter - A title for filtering mode. - - - - timelineFilterAll - 'All' The mode for timelines filtering. - - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3950,44 +3958,14 @@ Spustelėkite čia: <a href="%1">%1</a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. + chatsTitle + 'Messages' : Title for conversations diff --git a/linphone-app/assets/languages/pt_BR.ts b/linphone-app/assets/languages/pt_BR.ts index bc9346f19..165202935 100644 --- a/linphone-app/assets/languages/pt_BR.ts +++ b/linphone-app/assets/languages/pt_BR.ts @@ -451,6 +451,34 @@ Encriptação da media + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -913,6 +941,11 @@ URL do servidor não configurado. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. A reunião foi excluída + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1023,12 +1056,9 @@ URL do servidor não configurado. selectAllContacts + 'All' : Filter label to display all items. Todos - - selectConnectedContacts - Conectado - addContact ADICIONAR CONTATO @@ -1042,21 +1072,24 @@ URL do servidor não configurado. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. Você precisa definir o URI da conferência nas configurações da sua conta para criar uma sala de bate-papo baseada em conferência. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + CONTATOS + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - TODOS - - - displayCalls - CHAMADAS - - - displayMessages - MENSAGENS - removeAllEntriesDescription Tem certeza de que deseja limpar esse histórico? @@ -1844,11 +1877,6 @@ Clique aqui: <a href="%1">%1 </a> mainSearchBarPlaceholder Pesquisar contato, iniciar uma chamada ou um bate-papo… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - CONTATOS - autoAnswerStatus Automático @@ -1866,26 +1894,11 @@ Clique aqui: <a href="%1">%1 </a> 'Start a chat room' : Tooltip to illustrate a button Iniciar uma sala de chat - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - Ocultar linha do tempo - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - Abrir linha do tempo - openHome 'Open Home' : Tooltip for a button that open the home view Abrir a página inicial - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - Reuniões - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1902,8 +1915,23 @@ Clique aqui: <a href="%1">%1 </a> Você deseja fazer o download e aplicar a configuração a partir desta URL? - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3906,26 +3934,6 @@ Clique aqui: <a href="%1">%1 </a> Timeline - - timelineFilter - A title for filtering mode. - Filtro - - - timelineFilterAll - 'All' The mode for timelines filtering. - Todos - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - Personalização - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - Salas simples - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3936,45 +3944,15 @@ Clique aqui: <a href="%1">%1 </a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). Grupo de chat - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - Efêmeros - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list Pesquisar na lista - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - Todos níveis de segurança - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - Salas padrão - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - Todas conversas - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - Efêmeros ligado/desligado - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - Sem efêmeros - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. - Conferências + chatsTitle + 'Messages' : Title for conversations + diff --git a/linphone-app/assets/languages/ru.ts b/linphone-app/assets/languages/ru.ts index 9bceba4f6..4f0c1c501 100644 --- a/linphone-app/assets/languages/ru.ts +++ b/linphone-app/assets/languages/ru.ts @@ -451,6 +451,34 @@ Шифрование потока + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -920,6 +948,11 @@ 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. Встреча была удалена + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1030,12 +1063,9 @@ selectAllContacts + 'All' : Filter label to display all items. Все - - selectConnectedContacts - Подключенные - addContact ДОБАВИТЬ КОНТАКТ @@ -1049,21 +1079,24 @@ 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. Вам необходимо установить URI конференции в настройках вашего аккаунта, чтобы создать чат-комнату на основе конференции. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + КОНТАКТЫ + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - ВСЕ - - - displayCalls - ЗВОНКИ - - - displayMessages - СООБЩЕНИЯ - removeAllEntriesDescription Вы уверены, что хотите очистить эту историю? @@ -1855,11 +1888,6 @@ mainSearchBarPlaceholder Найти контакт, начать звонок или чат… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - КОНТАКТЫ - autoAnswerStatus авто @@ -1877,26 +1905,11 @@ 'Start a chat room' : Tooltip to illustrate a button Начать чат-комнату - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - Скрыть шкалу времени - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - Открыть шкалу времени - openHome 'Open Home' : Tooltip for a button that open the home view Открыть главную - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - Встречи - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1913,8 +1926,23 @@ Вы хотите загрузить и применить конфигурацию с этого URL-адреса? - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3920,26 +3948,6 @@ Timeline - - timelineFilter - A title for filtering mode. - Фильтр - - - timelineFilterAll - 'All' The mode for timelines filtering. - Все - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - Пользовательский - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - Простые комнаты - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3950,45 +3958,15 @@ 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). Чат-группы - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - Недолговечные - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list Поиск в списке - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - Все уровни безопасности - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - Стандартные комнаты - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - Любые разговоры - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - Недолговечные вкл/выкл - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - Без недолговечных - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. - Конференции + chatsTitle + 'Messages' : Title for conversations + diff --git a/linphone-app/assets/languages/sv.ts b/linphone-app/assets/languages/sv.ts index baa778ae2..41b977d2d 100644 --- a/linphone-app/assets/languages/sv.ts +++ b/linphone-app/assets/languages/sv.ts @@ -451,6 +451,34 @@ Mediekryptering + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -913,6 +941,11 @@ Serverwebbadressen är inte konfigurerad. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1023,12 +1056,9 @@ Serverwebbadressen är inte konfigurerad. selectAllContacts + 'All' : Filter label to display all items. Alla - - selectConnectedContacts - Ansluten - addContact LÄGG TILL KONTAKT @@ -1042,21 +1072,24 @@ Serverwebbadressen är inte konfigurerad. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + KONTAKTER + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - ALLA - - - displayCalls - SAMTAL - - - displayMessages - MEDDELANDEN - removeAllEntriesDescription Är du säker på att du vill rensa den här historiken? @@ -1844,11 +1877,6 @@ Klicka här: <a href="%1">%1</a> mainSearchBarPlaceholder Sök kontakt, starta ett samtal eller en chatt… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - KONTAKTER - autoAnswerStatus automatiskt @@ -1866,26 +1894,11 @@ Klicka här: <a href="%1">%1</a> 'Start a chat room' : Tooltip to illustrate a button - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - - openHome 'Open Home' : Tooltip for a button that open the home view - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1902,8 +1915,23 @@ Klicka här: <a href="%1">%1</a> - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3906,26 +3934,6 @@ Klicka här: <a href="%1">%1</a> Timeline - - timelineFilter - A title for filtering mode. - - - - timelineFilterAll - 'All' The mode for timelines filtering. - - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3936,44 +3944,14 @@ Klicka här: <a href="%1">%1</a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. + chatsTitle + 'Messages' : Title for conversations diff --git a/linphone-app/assets/languages/tr.ts b/linphone-app/assets/languages/tr.ts index b675d9d92..f92295c69 100644 --- a/linphone-app/assets/languages/tr.ts +++ b/linphone-app/assets/languages/tr.ts @@ -451,6 +451,34 @@ + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -906,6 +934,11 @@ Sunucu url'si yapılandırılmadı. 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1016,12 +1049,9 @@ Sunucu url'si yapılandırılmadı. selectAllContacts + 'All' : Filter label to display all items. Tümü - - selectConnectedContacts - Bağlı - addContact KİŞİ EKLE @@ -1035,21 +1065,24 @@ Sunucu url'si yapılandırılmadı. 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. Toplantı tabanlı konuşma odası oluşturmak için hesap ayarlarınızda toplantı URI'si belirlemelisiniz. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + KİŞİLER + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - TÜMÜ - - - displayCalls - ÇAĞRILAR - - - displayMessages - İLETİLER - removeAllEntriesDescription Bu geçmişi temizlemek istediğinize emin misiniz? @@ -1833,11 +1866,6 @@ Buraya tıklayın: <a href="%1">%1</a> mainSearchBarPlaceholder Kişi ara, çağrı veya sohbet başlat… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - KİŞİLER - autoAnswerStatus kendiliğinden @@ -1855,26 +1883,11 @@ Buraya tıklayın: <a href="%1">%1</a> 'Start a chat room' : Tooltip to illustrate a button Konuşma odası başlat - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - Zaman Çizelgesini Gizle - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - Zaman Çizelgesini Aç - openHome 'Open Home' : Tooltip for a button that open the home view Evi Aç - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1891,8 +1904,23 @@ Buraya tıklayın: <a href="%1">%1</a> - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3892,26 +3920,6 @@ Buraya tıklayın: <a href="%1">%1</a> Timeline - - timelineFilter - A title for filtering mode. - Süzgeç - - - timelineFilterAll - 'All' The mode for timelines filtering. - Tümü - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - Özel - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - Basit odalar - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3922,45 +3930,15 @@ Buraya tıklayın: <a href="%1">%1</a> 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). Konuşma kümeleri - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - Kısa ömürlüler - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list Listede ara - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - Tüm güvenlik düzeyleri - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - Standart odalar - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - Herhangi konuşmalar - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - Kısa ömürlüler açık/kapalı - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - Kısa ömürlüler olmadan - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. - Toplantılar + chatsTitle + 'Messages' : Title for conversations + diff --git a/linphone-app/assets/languages/uk.ts b/linphone-app/assets/languages/uk.ts index f3005a3f6..6220e0bc9 100644 --- a/linphone-app/assets/languages/uk.ts +++ b/linphone-app/assets/languages/uk.ts @@ -451,6 +451,34 @@ + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -920,6 +948,11 @@ 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1030,12 +1063,9 @@ selectAllContacts + 'All' : Filter label to display all items. Усі - - selectConnectedContacts - Під'єднані - addContact ДОДАТИ КОНТАКТ @@ -1049,21 +1079,24 @@ 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + КОНТАКТИ + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - УСІ - - - displayCalls - ВИКЛИКИ - - - displayMessages - ПОВІДОМЛЕННЯ - removeAllEntriesDescription Ви впевнені, що волієте вичистити цю історію? @@ -1855,11 +1888,6 @@ mainSearchBarPlaceholder Знайти контакт, почати дзвінок або чат… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - КОНТАКТИ - autoAnswerStatus авто @@ -1877,26 +1905,11 @@ 'Start a chat room' : Tooltip to illustrate a button - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - - openHome 'Open Home' : Tooltip for a button that open the home view - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1913,8 +1926,23 @@ - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3920,26 +3948,6 @@ Timeline - - timelineFilter - A title for filtering mode. - - - - timelineFilterAll - 'All' The mode for timelines filtering. - - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3950,44 +3958,14 @@ 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. + chatsTitle + 'Messages' : Title for conversations diff --git a/linphone-app/assets/languages/zh_CN.ts b/linphone-app/assets/languages/zh_CN.ts index 6a737f55a..a9496eb2c 100644 --- a/linphone-app/assets/languages/zh_CN.ts +++ b/linphone-app/assets/languages/zh_CN.ts @@ -451,6 +451,34 @@ 媒体加密 + + CallTimeline + + callListTitle + 'Call list' : Call histories title + + + + incomingFilter + 'Incoming' : Filter label for incoming call + + + + outgoingFilter + 'Outgoing' : Filter label for outgoing call + + + + missedFilter + 'Missed' : Filter label for missed call + + + + searchListPlaceholderText + 'Search in the list' : ths is a placeholder when searching something in a list + + + CallTransfer @@ -906,6 +934,11 @@ 'The meeting has been deleted' : Message text in a banner to warn the user that the meeting has been deleted. + + createMeeting + 'Create Meeting' : Button label to create a meeting + + ConfirmDialog @@ -1016,12 +1049,9 @@ selectAllContacts + 'All' : Filter label to display all items. 全部 - - selectConnectedContacts - 已连接 - addContact 添加联系人 @@ -1035,21 +1065,24 @@ 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration. 您需要在帐户设置中设置会议 URI 以创建基于会议的聊天室。 + + localContactsEntry + 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + + + + contactsEntry + 'Contacts' : Contacts section label in main waindow. + 联系人 + + + selectOnlineContacts + 'Online' : Filter label to display only online contacts. + + Conversation - - displayCallsAndMessages - 全部 - - - displayCalls - 通话 - - - displayMessages - 信息 - removeAllEntriesDescription 你确定要清除该历史吗? @@ -1833,11 +1866,6 @@ mainSearchBarPlaceholder 搜索联系人,并开始通话或聊天… - - contactsEntry - 'Contacts' : Contacts section label in main waindow. - 联系人 - autoAnswerStatus 自动 @@ -1855,26 +1883,11 @@ 'Start a chat room' : Tooltip to illustrate a button 创建聊天室 - - hideTimeline - 'Hide Timeline' : Tooltip for a button that hide the timeline - 隐藏时间线 - - - openTimeline - 'Open Timeline' : Tooltip for a button that open the timeline - 公开时间线 - openHome 'Open Home' : Tooltip for a button that open the home view 开放主页 - - mainWindowConferencesTitle - 'Meetings' : Meeting title for main window. - - newChatRoomUriMissing 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action. @@ -1891,8 +1904,23 @@ - localContactsEntry - 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + openCalls + 'Open call history' : Tooltip for a button that open the call history view + + + + openChats + 'Open chats' : Tooltip for a button that open the conversations view + + + + openContacts + 'Open contacts' : Tooltip for a button that open the contacts view + + + + openMeetings + 'Open meetings' : Tooltip for a button that open the meetings list @@ -3892,26 +3920,6 @@ Timeline - - timelineFilter - A title for filtering mode. - 筛选 - - - timelineFilterAll - 'All' The mode for timelines filtering. - 全部 - - - timelineFilterCustom - 'Custom' The mode for timelines filtering. - 自定义 - - - timelineFilterSimpleRooms - 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - 基础聊天室 - timelineFilterSecureRooms 'Secure rooms' : Filter item. Selecting it will show all secure rooms. @@ -3922,44 +3930,14 @@ 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). 聊天群 - - timelineFilterEphemerals - 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - 阅后即焚 - timelineSearchPlaceholderText 'Search in the list' : ths is a placeholder when searching something in the timeline list 在列表中查找 - timelineFilterAllSecureLevelRooms - 'All security levels' : Filter item. Selecting it will not do any filter on security level. - - - - timelineFilterStandardRooms - 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - - - - timelineFilterAnyChatRooms - 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - - - - timelineFilterAnyEphemerals - 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - - - - timelineFilterNoEphemerals - 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - - - - timelineFilterConferences - 'Conferences' : Filter item. Selecting it will show all conferences. + chatsTitle + 'Messages' : Title for conversations diff --git a/linphone-app/resources.qrc b/linphone-app/resources.qrc index 94c12a836..bbc54cd79 100644 --- a/linphone-app/resources.qrc +++ b/linphone-app/resources.qrc @@ -432,6 +432,7 @@ ui/modules/Linphone/Styles/Sticker/DecorationStickerStyle.qml ui/modules/Linphone/Styles/Sticker/StickerStyle.qml ui/modules/Linphone/Styles/TelKeypad/TelKeypadStyle.qml + ui/modules/Linphone/Styles/Timeline/CallTimelineStyle.qml ui/modules/Linphone/Styles/Timeline/TimelineStyle.qml ui/modules/Linphone/Styles/View/ParticipantsListViewStyle.qml ui/modules/Linphone/Styles/View/ParticipantsViewStyle.qml @@ -439,6 +440,8 @@ ui/modules/Linphone/TelKeypad/TelKeypadButton.qml ui/modules/Linphone/TelKeypad/TelKeypad.js ui/modules/Linphone/TelKeypad/TelKeypad.qml + ui/modules/Linphone/Timeline/CallTimeline.qml + ui/modules/Linphone/Timeline/CallTimelineItem.qml ui/modules/Linphone/Timeline/Timeline.js ui/modules/Linphone/Timeline/Timeline.qml ui/modules/Linphone/Timeline/TimelineItem.qml @@ -477,12 +480,14 @@ ui/views/App/Main/Assistant/UseAppSipAccountWithPhoneNumber.qml ui/views/App/Main/Assistant/UseAppSipAccountWithUsername.qml ui/views/App/Main/Assistant/UseOtherSipAccount.qml + ui/views/App/Main/Calls.qml ui/views/App/Main/Conferences.qml ui/views/App/Main/ContactEdit.js ui/views/App/Main/ContactEdit.qml ui/views/App/Main/Contacts.qml ui/views/App/Main/Conversation.js ui/views/App/Main/Conversation.qml + ui/views/App/Main/Conversations.qml ui/views/App/Main/Dialogs/About.qml ui/views/App/Main/Dialogs/AuthenticationRequest.js ui/views/App/Main/Dialogs/AuthenticationRequest.qml diff --git a/linphone-app/src/app/App.cpp b/linphone-app/src/app/App.cpp index e6f115c11..8f43b008f 100644 --- a/linphone-app/src/app/App.cpp +++ b/linphone-app/src/app/App.cpp @@ -51,6 +51,8 @@ #include "translator/DefaultTranslator.hpp" #include "utils/Utils.hpp" #include "utils/Constants.hpp" +#include "components/history/CallHistoryModel.hpp" +#include "components/history/CallHistoryProxyModel.hpp" #include "components/other/desktop-tools/DesktopTools.hpp" #include "components/other/date/DateModel.hpp" @@ -747,6 +749,7 @@ void App::registerTypes () { registerType("TemporaryFile"); registerType("TimeZoneProxyModel"); + registerType("CallHistoryProxyModel"); registerType("ColorProxyModel"); registerType("ImageColorsProxyModel"); registerType("ImageProxyModel"); @@ -765,6 +768,7 @@ void App::registerTypes () { registerUncreatableType("CallModel"); + registerUncreatableType("CallHistoryModel"); registerUncreatableType("ChatCallModel"); registerUncreatableType("ChatMessageModel"); registerUncreatableType("ChatNoticeModel"); diff --git a/linphone-app/src/components/chat-events/ChatMessageListener.cpp b/linphone-app/src/components/chat-events/ChatMessageListener.cpp index 77ae497a6..d479b341f 100644 --- a/linphone-app/src/components/chat-events/ChatMessageListener.cpp +++ b/linphone-app/src/components/chat-events/ChatMessageListener.cpp @@ -61,3 +61,6 @@ void ChatMessageListener::onEphemeralMessageTimerStarted(const std::shared_ptr & message){ emit ephemeralMessageDeleted(message); } +void ChatMessageListener::onReactionRemoved(const std::shared_ptr & message, const std::shared_ptr & address) { + emit reactionRemoved(message, address); +} diff --git a/linphone-app/src/components/chat-events/ChatMessageListener.hpp b/linphone-app/src/components/chat-events/ChatMessageListener.hpp index 29f40d149..4a9546c0c 100644 --- a/linphone-app/src/components/chat-events/ChatMessageListener.hpp +++ b/linphone-app/src/components/chat-events/ChatMessageListener.hpp @@ -45,6 +45,7 @@ public: virtual void onParticipantImdnStateChanged(const std::shared_ptr & message, const std::shared_ptr & state) override; virtual void onEphemeralMessageTimerStarted(const std::shared_ptr & message) override; virtual void onEphemeralMessageDeleted(const std::shared_ptr & message) override; + virtual void onReactionRemoved(const std::shared_ptr & message, const std::shared_ptr & address) override; signals: void fileTransferRecv(const std::shared_ptr & message, const std::shared_ptr & content, const std::shared_ptr & buffer); void fileTransferSendChunk(const std::shared_ptr & message, const std::shared_ptr & content, size_t offset, size_t size, const std::shared_ptr & buffer); @@ -55,6 +56,7 @@ signals: void participantImdnStateChanged(const std::shared_ptr & message, const std::shared_ptr & state); void ephemeralMessageTimerStarted(const std::shared_ptr & message); void ephemeralMessageDeleted(const std::shared_ptr & message); + void reactionRemoved(const std::shared_ptr & message, const std::shared_ptr & address); }; Q_DECLARE_METATYPE(ChatMessageListener*) diff --git a/linphone-app/src/components/chat-events/ChatMessageModel.cpp b/linphone-app/src/components/chat-events/ChatMessageModel.cpp index 0efdebc91..fbef41454 100644 --- a/linphone-app/src/components/chat-events/ChatMessageModel.cpp +++ b/linphone-app/src/components/chat-events/ChatMessageModel.cpp @@ -68,6 +68,7 @@ void ChatMessageModel::connectTo(ChatMessageListener * listener){ connect(listener, &ChatMessageListener::ephemeralMessageTimerStarted, this, &ChatMessageModel::onEphemeralMessageTimerStarted); connect(listener, &ChatMessageListener::ephemeralMessageDeleted, this, &ChatMessageModel::onEphemeralMessageDeleted); connect(listener, &ChatMessageListener::participantImdnStateChanged, this->getParticipantImdnStates().get(), &ParticipantImdnStateListModel::onParticipantImdnStateChanged); + connect(listener, &ChatMessageListener::reactionRemoved, this, &ChatMessageModel::onReactionRemoved); } // ============================================================================= @@ -153,6 +154,12 @@ QString ChatMessageModel::getToSipAddress() const{ return mChatMessage ? Utils::cleanSipAddress(Utils::coreStringToAppString(mChatMessage->getToAddress()->asStringUriOnly())) : ""; } +QString ChatMessageModel::getMyReaction() const { + if(!mChatMessage) return ""; + auto myReaction = mChatMessage->getOwnReaction(); + return myReaction ? Utils::coreStringToAppString(myReaction->getBody()) : ""; +} + ContactModel * ChatMessageModel::getContactModel() const{ return mChatMessage ? CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(Utils::cleanSipAddress(Utils::coreStringToAppString(mChatMessage->getFromAddress()->asStringUriOnly()))).get() : nullptr; } @@ -256,13 +263,16 @@ void ChatMessageModel::resendMessage (){ } void ChatMessageModel::sendChatReaction(const QString& reaction){ - auto chatReaction = mChatMessage->createReaction(Utils::appStringToCoreString(reaction)); - if( mChatReactionListModel->exists(chatReaction)) { - chatReaction = mChatMessage->createReaction(""); - return; // TODO : remove return when sending empty emoji will be supported. + auto myReaction = mChatMessage->getOwnReaction(); + if( myReaction && Utils::coreStringToAppString(myReaction->getBody()) == reaction) { + auto chatReaction = mChatMessage->createReaction(""); + chatReaction->send(); + //emit reactionRemoved(mChatMessage, chatReaction->getFromAddress()); // Do not emit because we want to display what the server got + }else{ + auto chatReaction = mChatMessage->createReaction(Utils::appStringToCoreString(reaction)); + chatReaction->send(); + //emit newMessageReaction(mChatMessage, chatReaction);// Do not emit because we want to display what the server got } - chatReaction->send(); - emit newMessageReaction(mChatMessage, chatReaction); } void ChatMessageModel::deleteEvent(){ @@ -327,6 +337,8 @@ void ChatMessageModel::onMsgStateChanged (const std::shared_ptr & message, const std::shared_ptr & reaction){ + if(reaction->getFromAddress()->weakEqual(message->getLocalAddress())) + emit myReactionChanged(); emit newMessageReaction(message, reaction); } @@ -342,6 +354,12 @@ void ChatMessageModel::onEphemeralMessageDeleted(const std::shared_ptrremoveDownloadedFiles(); emit remove(this); } + +void ChatMessageModel::onReactionRemoved(const std::shared_ptr & message, const std::shared_ptr & address) { + if(address->weakEqual(message->getLocalAddress())) + emit myReactionChanged(); + emit reactionRemoved(message, address); +} //------------------------------------------------------------------------------------------------------- diff --git a/linphone-app/src/components/chat-events/ChatMessageModel.hpp b/linphone-app/src/components/chat-events/ChatMessageModel.hpp index c246bc03b..58f3c8bb1 100644 --- a/linphone-app/src/components/chat-events/ChatMessageModel.hpp +++ b/linphone-app/src/components/chat-events/ChatMessageModel.hpp @@ -74,6 +74,7 @@ public: Q_PROPERTY(bool isForward READ isForward CONSTANT) Q_PROPERTY(QString getForwardInfo READ getForwardInfo CONSTANT) Q_PROPERTY(QString getForwardInfoDisplayName READ getForwardInfoDisplayName CONSTANT) + Q_PROPERTY(QString myReaction READ getMyReaction NOTIFY myReactionChanged) std::shared_ptr getChatMessage(); @@ -86,6 +87,7 @@ public: QString getFromSipAddress() const; QString getToDisplayName() const; QString getToSipAddress() const; + QString getMyReaction() const; ContactModel * getContactModel() const; bool isEphemeral() const; Q_INVOKABLE qint64 getEphemeralExpireTime() const; @@ -129,6 +131,7 @@ public: void onParticipantImdnStateChanged(const std::shared_ptr & message, const std::shared_ptr & state); void onEphemeralMessageTimerStarted(const std::shared_ptr & message); void onEphemeralMessageDeleted(const std::shared_ptr & message); + void onReactionRemoved(const std::shared_ptr & message, const std::shared_ptr & address); //---------------------------------------------------------------------------- bool mWasDownloaded; @@ -145,8 +148,10 @@ signals: void isOutgoingChanged(); void fileContentChanged(); void remove(ChatMessageModel* model); + void myReactionChanged(); void newMessageReaction(const std::shared_ptr & message, const std::shared_ptr & reaction); + void reactionRemoved(const std::shared_ptr & message, const std::shared_ptr & address); private: void connectTo(ChatMessageListener * listener); diff --git a/linphone-app/src/components/chat-reaction/ChatReactionListModel.cpp b/linphone-app/src/components/chat-reaction/ChatReactionListModel.cpp index a428943a4..dd5b699ea 100644 --- a/linphone-app/src/components/chat-reaction/ChatReactionListModel.cpp +++ b/linphone-app/src/components/chat-reaction/ChatReactionListModel.cpp @@ -31,11 +31,15 @@ ChatReactionListModel::ChatReactionListModel (ChatMessageModel * message, QObjec } void ChatReactionListModel::setChatMessageModel(ChatMessageModel * message) { - if(mParent) + if(mParent) { disconnect(message, &ChatMessageModel::newMessageReaction, this, &ChatReactionListModel::onNewMessageReaction); + disconnect(message, &ChatMessageModel::reactionRemoved, this, &ChatReactionListModel::onReactionRemoved); + } mParent = message; - if(mParent) + if(mParent) { connect(message, &ChatMessageModel::newMessageReaction, this, &ChatReactionListModel::onNewMessageReaction); + connect(message, &ChatMessageModel::reactionRemoved, this, &ChatReactionListModel::onReactionRemoved); + } if(message){ auto reactions = message->getChatMessage()->getReactions(); mReactions.clear(); @@ -176,3 +180,12 @@ QStringList ChatReactionListModel::getBodies() const { void ChatReactionListModel::onNewMessageReaction(const std::shared_ptr & message, const std::shared_ptr & reaction){ updateChatReaction(reaction); } +void ChatReactionListModel::onReactionRemoved(const std::shared_ptr & message, const std::shared_ptr & address) { + mReactions.remove(Utils::coreStringToAppString(address->asStringUriOnly())); + mBodies.clear(); + for(auto it : mReactions) + mBodies[it->getBody()].push_back(it); + updateList(); + emit chatReactionCountChanged(); + emit bodiesChanged(); +} \ No newline at end of file diff --git a/linphone-app/src/components/chat-reaction/ChatReactionListModel.hpp b/linphone-app/src/components/chat-reaction/ChatReactionListModel.hpp index b83302d9d..aaad755a0 100644 --- a/linphone-app/src/components/chat-reaction/ChatReactionListModel.hpp +++ b/linphone-app/src/components/chat-reaction/ChatReactionListModel.hpp @@ -65,6 +65,7 @@ public: void updateList(); void onNewMessageReaction(const std::shared_ptr & message, const std::shared_ptr & reaction); + void onReactionRemoved(const std::shared_ptr & message, const std::shared_ptr & address); signals: void chatReactionsChanged(); void chatReactionCountChanged(); diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.cpp b/linphone-app/src/components/chat-room/ChatRoomModel.cpp index 46b4c02ee..d9cdff814 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -126,9 +127,6 @@ ChatRoomModel::ChatRoomModel (const std::shared_ptr& chatRoo // Get messages. mList.clear(); - mUnreadMessagesCount = mChatRoom->getUnreadMessagesCount(); - mMissedCallsCount = 0; - QElapsedTimer timer; timer.start(); CoreHandlers *coreHandlers = mCoreHandlers.get(); @@ -145,7 +143,8 @@ ChatRoomModel::ChatRoomModel (const std::shared_ptr& chatRoo QObject::connect(coreManager->getContactsListModel(), &ContactsListModel::contactUpdated, this, &ChatRoomModel::avatarChanged); connect(this, &ChatRoomModel::fullPeerAddressChanged, this, &ChatRoomModel::usernameChanged); - connect(this, &ChatRoomModel::stateChanged, this, &ChatRoomModel::updatingChanged); + connect(this, &ChatRoomModel::messageCountReset, this, &ChatRoomModel::unreadMessagesCountChanged); + connect(this, &ChatRoomModel::unreadMessagesCountChanged, coreManager, &CoreManager::eventCountChanged); if(mChatRoom){ mParticipantListModel = QSharedPointer::create(this); @@ -408,6 +407,10 @@ LinphoneEnums::ChatRoomState ChatRoomModel::getState() const { return mChatRoom ? LinphoneEnums::fromLinphone(mChatRoom->getState()) : LinphoneEnums::ChatRoomStateNone; } +int ChatRoomModel::getUnreadMessagesCount() const{ + return mChatRoom ? mChatRoom->getUnreadMessagesCount() : 0; +} + bool ChatRoomModel::isReadOnly() const{ return mChatRoom && mChatRoom->isReadOnly(); } @@ -531,10 +534,6 @@ QString ChatRoomModel::getParticipantAddress() const{ } } -int ChatRoomModel::getAllUnreadCount(){ - return mUnreadMessagesCount + mMissedCallsCount; -} - //------------------------------------------------------------------------------------------------ void ChatRoomModel::setSubject(QString& subject){ @@ -564,31 +563,6 @@ void ChatRoomModel::updateLastUpdateTime(){ } } -void ChatRoomModel::setUnreadMessagesCount(const int& count){ - updateNewMessageNotice(count); - if(count != mUnreadMessagesCount){ - mUnreadMessagesCount = count; - emit unreadMessagesCountChanged(); - } -} - -void ChatRoomModel::setMissedCallsCount(const int& count){ - if(count != mMissedCallsCount){ - mMissedCallsCount = count; - emit missedCallsCountChanged(); - } -} - -void ChatRoomModel::addMissedCallsCount(std::shared_ptr call){ - insertCall(call->getCallLog()); - auto timeline = CoreManager::getInstance()->getTimelineListModel()->getTimeline(mChatRoom, false); - if(!timeline || !timeline->mSelected){ - setMissedCallsCount(mMissedCallsCount+1); - if(call->dataExists("call-model")) - CoreManager::getInstance()->getEventCountNotifier()->handleCallMissed(&call->getData("call-model")); - } -} - void ChatRoomModel::setEphemeralEnabled(bool enabled){ if(isEphemeralEnabled() != enabled){ mChatRoom->enableEphemeral(enabled); @@ -658,22 +632,6 @@ void ChatRoomModel::leaveChatRoom (){ void ChatRoomModel::updateParticipants(const QVariantList& participants){ - /* - std::shared_ptr params = core->createDefaultChatRoomParams(); - std::list > chatRoomParticipants; - std::shared_ptr localAddress; - for(auto p : participants){ - ParticipantModel* participant = p.value(); - auto address = Utils::interpretUrl(participant->getSipAddress()); - if( address) - chatRoomParticipants.push_back( address ); - } - if(mChatRoom->canHandleParticipants()) { - mChatRoom->addParticipants(newParticipants); - mChatRoom->removeParticipants(removeParticipants); - } - - linphone::ChatRoom;*/ } // ----------------------------------------------------------------------------- @@ -751,12 +709,8 @@ void ChatRoomModel::resetMessageCount () { if (mChatRoom->getUnreadMessagesCount() > 0){ mChatRoom->markAsRead();// Marking as read is only for messages. Not for calls. } - setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); - }else - setUnreadMessagesCount(0); - setMissedCallsCount(0); + } emit messageCountReset(); - CoreManager::getInstance()->updateUnreadMessageCount(); } } //------------------------------------------------- @@ -976,21 +930,7 @@ void ChatRoomModel::initEntries(){ // Get events for(auto &eventLog : mChatRoom->getHistoryEvents(mFirstLastEntriesStep)) prepareEntries << EntrySorterHelper(eventLog->getCreationTime() , NoticeEntry, eventLog); - // Get calls. - bool secureChatEnabled = CoreManager::getInstance()->getSettingsModel()->getSecureChatEnabled(); - bool standardChatEnabled = CoreManager::getInstance()->getSettingsModel()->getStandardChatEnabled(); - bool noChat = !secureChatEnabled && !standardChatEnabled; - if(noChat || (isOneToOne() && (secureChatEnabled && !standardChatEnabled && isSecure() - || standardChatEnabled && !isSecure())) ) { - auto callHistory = CallsListModel::getCallHistory(getParticipantAddress(), Utils::coreStringToAppString(mChatRoom->getLocalAddress()->asStringUriOnly())); - // callhistory is sorted from newest to oldest - int count = 0; - for (auto callLog = callHistory.begin() ; count < mFirstLastEntriesStep && callLog != callHistory.end() ; ++callLog, ++count ){ - if(!(*callLog)->wasConference()) - prepareEntries << EntrySorterHelper((*callLog)->getStartDate(), CallEntry, *callLog); - } - } EntrySorterHelper::getLimitedSelection(&entries, prepareEntries, mFirstLastEntriesStep, this); qDebug() << "Internal Entries : Built"; if(entries.size() >0){ @@ -1053,27 +993,7 @@ int ChatRoomModel::loadMoreEntries(){ if(!haveEntry) prepareEntries << EntrySorterHelper(ChatMessageModel::initReceivedTimestamp(message, false).toTime_t() ,MessageEntry, message); } - - // Calls - bool secureChatEnabled = CoreManager::getInstance()->getSettingsModel()->getSecureChatEnabled(); - bool standardChatEnabled = CoreManager::getInstance()->getSettingsModel()->getStandardChatEnabled(); - bool noChat = !secureChatEnabled && !standardChatEnabled; - - if( noChat || (isOneToOne() && (secureChatEnabled && !standardChatEnabled && isSecure() - || standardChatEnabled && !isSecure())) ) { - auto callHistory = CallsListModel::getCallHistory(getParticipantAddress(), Utils::coreStringToAppString(mChatRoom->getLocalAddress()->asStringUriOnly())); - int count = 0; - auto itCallHistory = callHistory.begin(); - while(count < entriesCounts[1] && itCallHistory != callHistory.end()){ - ++itCallHistory; - ++count; - } - count = 0; - while( count < mLastEntriesStep && itCallHistory != callHistory.end()){ - prepareEntries << EntrySorterHelper((*itCallHistory)->getStartDate(), CallEntry, *itCallHistory); - ++itCallHistory; - } - } + // Notices for (auto &eventLog : mChatRoom->getHistoryRangeEvents(entriesCounts[2], entriesCounts[2]+mLastEntriesStep)){ auto itEntries = mList.begin(); @@ -1114,58 +1034,12 @@ int ChatRoomModel::loadMoreEntries(){ //------------------------------------------------- void ChatRoomModel::onCallEnded(std::shared_ptr call){ - if( call->getCallLog()->getStatus() == linphone::Call::Status::Missed) - addMissedCallsCount(call); - else{ - insertCall(call->getCallLog()); - } // When a call is end, a new log WILL be written in database. It may have information on display name. QTimer::singleShot(100, this, &ChatRoomModel::fullPeerAddressChanged); } // ----------------------------------------------------------------------------- -void ChatRoomModel::insertCall (const std::shared_ptr &callLog) { - if(mIsInitialized){ - QSharedPointer model = ChatCallModel::create(callLog, true); - if(model){ - int row = mList.count(); - beginInsertRows(QModelIndex(), row, row); - mList << model; - endInsertRows(); - auto lastIndex = index(mList.size()-1,0); - emit dataChanged(lastIndex,lastIndex ); - if (callLog->getStatus() == linphone::Call::Status::Success) { - model = ChatCallModel::create(callLog, false); - if(model) - add(model); - } - updateLastUpdateTime(); - } - } -} - -void ChatRoomModel::insertCalls (const QList > &calls) { - if(mIsInitialized){ - QList > entries; - for(auto callLog : calls) { - QSharedPointer model = ChatCallModel::create(callLog, true); - if(model){ - entries << model; - if (callLog->getStatus() == linphone::Call::Status::Success) { - model = ChatCallModel::create(callLog, false); - if(model){ - entries << model; - } - } - } - } - if(entries.size() > 0){ - prepend(entries); - } - } -} - QSharedPointer ChatRoomModel::insertMessageAtEnd (const std::shared_ptr &message) { QSharedPointer model; if(mIsInitialized && !exists(message)){ @@ -1173,7 +1047,7 @@ QSharedPointer ChatRoomModel::insertMessageAtEnd (const std::s if(model){ qDebug() << "Adding at end" << model->getReceivedTimestamp().toString("hh:mm:ss.zzz") << model->getTimestamp().toString("hh:mm:ss.zzz") << QString(message->getUtf8Text().c_str()).left(5); connect(model.get(), &ChatMessageModel::remove, this, &ChatRoomModel::removeEntry); - setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); + emit unreadMessagesCountChanged(); add(model); } } @@ -1192,7 +1066,7 @@ void ChatRoomModel::insertMessages (const QList 0){ prepend(entries); - setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); + emit unreadMessagesCountChanged(); } } } @@ -1234,30 +1108,9 @@ QString ChatRoomModel::getChatRoomId(const std::shared_ptr& return getChatRoomId(Utils::coreStringToAppString(localAddress->asStringUriOnly()), (chatRoom->getPeerAddress() ? Utils::coreStringToAppString(chatRoom->getPeerAddress()->asStringUriOnly()) : "")); } -// ----------------------------------------------------------------------------- -/* -void ChatRoomModel::removeUnreadMessagesNotice() { - -}*/ // ----------------------------------------------------------------------------- void ChatRoomModel::handleCallStateChanged (const std::shared_ptr &call, linphone::Call::State state) { - -/* - if (state == linphone::Call::State::End || state == linphone::Call::State::Error){ - shared_ptr core = CoreManager::getInstance()->getCore(); - std::shared_ptr params = core->createDefaultChatRoomParams(); - std::list> participants; - - auto chatRoom = core->searchChatRoom(params, mChatRoom->getLocalAddress() - , call->getRemoteAddress() - , participants); - if( mChatRoom == chatRoom){ - insertCall(call->getCallLog()); - setMissedCallsCount(mMissedCallsCount+1); - } - } - */ } void ChatRoomModel::handleCallCreated(const shared_ptr &call){ @@ -1269,8 +1122,6 @@ void ChatRoomModel::handlePresenceStatusReceived(std::shared_ptrgetAddresses(); for( auto itContactAddress = contactAddresses.begin() ; !canUpdatePresence && itContactAddress != contactAddresses.end() ; ++itContactAddress){ - //auto cleanContactAddress = (*itContactAddress)->clone(); - //cleanContactAddress->clean(); canUpdatePresence = mChatRoom->getLocalAddress()->weakEqual(*itContactAddress); if(!canUpdatePresence && !isGroupEnabled() && mChatRoom->getNbParticipants() == 1){ auto participants = getParticipants(false); @@ -1285,7 +1136,6 @@ void ChatRoomModel::handlePresenceStatusReceived(std::shared_ptrgetPresenceModel()->getConsolidatedPresence()); emit presenceStatusChanged(); } } @@ -1308,23 +1158,21 @@ void ChatRoomModel::onIsComposingReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message){ if(message) ChatMessageModel::initReceivedTimestamp(message, true); - setUnreadMessagesCount(chatRoom->getUnreadMessagesCount()); + emit unreadMessagesCountChanged(); updateLastUpdateTime(); } void ChatRoomModel::onMessagesReceived(const std::shared_ptr & chatRoom, const std::list> & messages){ for(auto message : messages) if(message) ChatMessageModel::initReceivedTimestamp(message, true); - setUnreadMessagesCount(chatRoom->getUnreadMessagesCount()); + emit unreadMessagesCountChanged(); updateLastUpdateTime(); } void ChatRoomModel::onNewEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ if(eventLog){ - if( eventLog->getType() == linphone::EventLog::Type::ConferenceCallEnded ){ - setMissedCallsCount(mMissedCallsCount+1); - }else if( eventLog->getType() == linphone::EventLog::Type::ConferenceCreated ){ + if( eventLog->getType() == linphone::EventLog::Type::ConferenceCreated ){ emit fullPeerAddressChanged(); } updateLastUpdateTime(); @@ -1332,17 +1180,12 @@ void ChatRoomModel::onNewEvent(const std::shared_ptr & chatR } void ChatRoomModel::onNewEvents(const std::shared_ptr & chatRoom, const std::list> & eventLogs){ - int missCount = 0; bool updatePeerAddress = false; for(auto eventLog : eventLogs) if(eventLog){ - if( eventLog->getType() == linphone::EventLog::Type::ConferenceCallEnded ) - ++missCount; if( eventLog->getType() == linphone::EventLog::Type::ConferenceCreated ) updatePeerAddress = true; } - if(missCount > 0) - setMissedCallsCount(mMissedCallsCount+missCount); if(updatePeerAddress) emit fullPeerAddressChanged(); updateLastUpdateTime(); @@ -1470,7 +1313,7 @@ void ChatRoomModel::onConferenceJoined(const std::shared_ptr if(e != events.end() ) insertNotice(*e); } - setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); // Update message count. In the case of joining conference, the conference id was not valid thus, the missing count was not about the chat room but a global one. + emit unreadMessagesCountChanged();// Update message count. In the case of joining conference, the conference id was not valid thus, the missing count was not about the chat room but a global one. updateLastUpdateTime(); emit usernameChanged(); emit conferenceJoined(eventLog); diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.hpp b/linphone-app/src/components/chat-room/ChatRoomModel.hpp index 7b8286b8f..8375be467 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.hpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.hpp @@ -61,8 +61,7 @@ public: Q_PROPERTY(QString subject READ getSubject WRITE setSubject NOTIFY subjectChanged) Q_PROPERTY(QDateTime lastUpdateTime MEMBER mLastUpdateTime WRITE setLastUpdateTime NOTIFY lastUpdateTimeChanged) - Q_PROPERTY(int unreadMessagesCount MEMBER mUnreadMessagesCount WRITE setUnreadMessagesCount NOTIFY unreadMessagesCountChanged) - Q_PROPERTY(int missedCallsCount MEMBER mMissedCallsCount WRITE setMissedCallsCount NOTIFY missedCallsCountChanged) + Q_PROPERTY(int unreadMessagesCount READ getUnreadMessagesCount NOTIFY unreadMessagesCountChanged) Q_PROPERTY(int securityLevel READ getSecurityLevel NOTIFY securityLevelChanged) Q_PROPERTY(bool groupEnabled READ isGroupEnabled NOTIFY groupEnabledChanged) @@ -124,6 +123,7 @@ public: int getPresenceStatus() const; QDateTime getPresenceTimestamp() const; LinphoneEnums::ChatRoomState getState() const; + int getUnreadMessagesCount() const; bool isReadOnly() const; bool isEphemeralEnabled() const; long getEphemeralLifetime() const; @@ -149,7 +149,6 @@ public: std::list> getParticipants(const bool& withMe = true) const; std::shared_ptr getChatRoom(); QList getComposers(); - int getAllUnreadCount(); // Return unread messages and missed call. //---- Setters void setSubject(QString& subject); @@ -157,9 +156,6 @@ public: void updateLastUpdateTime(); void setEntriesLoading(const bool& loading); - void setUnreadMessagesCount(const int& count); - void setMissedCallsCount(const int& count); - void addMissedCallsCount(std::shared_ptr call); void setEphemeralEnabled(bool enabled); void setEphemeralLifetime(long lifetime); void enableMarkAsRead(const bool& enable); @@ -196,8 +192,6 @@ public: virtual void resetData() override; QDateTime mLastUpdateTime; - int mUnreadMessagesCount = 0; - int mMissedCallsCount = 0; bool mIsInitialized = false; bool mDeleteChatRoom = false; // Use as workaround because of core->deleteChatRoom() that call destructor without takking account of count ref : call it in ChatRoomModel destructor @@ -206,9 +200,6 @@ public: bool mMarkAsReadEnabled = true; bool mEntriesLoading = false; - - void insertCall (const std::shared_ptr &callLog); - void insertCalls (const QList > &calls); QSharedPointer insertMessageAtEnd (const std::shared_ptr &message); void insertMessages (const QList > &messages); void insertNotice (const std::shared_ptr &enventLog); @@ -280,7 +271,6 @@ signals: void presenceStatusChanged(); void lastUpdateTimeChanged(); void unreadMessagesCountChanged(); - void missedCallsCountChanged(); void securityLevelChanged(int securityLevel); void groupEnabledChanged(bool groupEnabled); diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp index 4aa339a07..fe0238636 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp @@ -53,7 +53,10 @@ using namespace std; // ----------------------------------------------------------------------------- QSharedPointer ConferenceInfoModel::create(std::shared_ptr conferenceInfo){ - return QSharedPointer::create(conferenceInfo); + if(conferenceInfo) + return QSharedPointer::create(conferenceInfo); + else + return nullptr; } // Callable from QML diff --git a/linphone-app/src/components/contacts/ContactsListProxyModel.cpp b/linphone-app/src/components/contacts/ContactsListProxyModel.cpp index 4f58bbefc..3dc3f245f 100644 --- a/linphone-app/src/components/contacts/ContactsListProxyModel.cpp +++ b/linphone-app/src/components/contacts/ContactsListProxyModel.cpp @@ -79,10 +79,10 @@ bool ContactsListProxyModel::filterAcceptsRow ( mWeights[contact] = uint(round(computeContactWeight(contact))); - return mWeights[contact] > 0 && ( - !mUseConnectedFilter || - contact->getPresenceLevel() != Presence::PresenceLevel::White - ); + return mWeights[contact] > 0 + && (!mUseConnectedFilter || contact->getPresenceLevel() != Presence::PresenceLevel::White) + && (!mUseOnlineFilter || contact->getPresenceLevel() == Presence::PresenceLevel::Green) + ; } bool ContactsListProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { @@ -150,3 +150,10 @@ void ContactsListProxyModel::setConnectedFilter (bool useConnectedFilter) { invalidate(); } } + +void ContactsListProxyModel::setOnlineFilter (bool useOnlineFilter) { + if (useOnlineFilter != mUseOnlineFilter) { + mUseOnlineFilter = useOnlineFilter; + invalidate(); + } +} \ No newline at end of file diff --git a/linphone-app/src/components/contacts/ContactsListProxyModel.hpp b/linphone-app/src/components/contacts/ContactsListProxyModel.hpp index 3fe08400f..cd6b30c27 100644 --- a/linphone-app/src/components/contacts/ContactsListProxyModel.hpp +++ b/linphone-app/src/components/contacts/ContactsListProxyModel.hpp @@ -31,11 +31,8 @@ class ContactsListModel; class ContactsListProxyModel : public QSortFilterProxyModel { Q_OBJECT; - Q_PROPERTY( - bool useConnectedFilter - READ isConnectedFilterUsed - WRITE setConnectedFilter - ); + Q_PROPERTY(bool useConnectedFilter READ isConnectedFilterUsed WRITE setConnectedFilter); + Q_PROPERTY(bool useOnlineFilter READ isOnlineFilterUsed WRITE setOnlineFilter); public: ContactsListProxyModel (QObject *parent = Q_NULLPTR); @@ -53,11 +50,16 @@ private: bool isConnectedFilterUsed () const { return mUseConnectedFilter; } + bool isOnlineFilterUsed () const { + return mUseOnlineFilter; + } void setConnectedFilter (bool useConnectedFilter); + void setOnlineFilter (bool useOnlineFilter); QString mFilter; bool mUseConnectedFilter = false; + bool mUseOnlineFilter = false; // It's just a cache to save values computed by `filterAcceptsRow` // and reused by `lessThan`. diff --git a/linphone-app/src/components/core/CoreHandlers.cpp b/linphone-app/src/components/core/CoreHandlers.cpp index 357a68a42..c0fc47b98 100644 --- a/linphone-app/src/components/core/CoreHandlers.cpp +++ b/linphone-app/src/components/core/CoreHandlers.cpp @@ -142,6 +142,8 @@ void CoreHandlers::onCallStateChanged ( const string & ) { emit callStateChanged(call, state); + if (state == linphone::Call::State::End || state == linphone::Call::State::Error) + emit eventCountChanged(); SettingsModel *settingsModel = CoreManager::getInstance()->getSettingsModel(); if ( diff --git a/linphone-app/src/components/core/CoreHandlers.hpp b/linphone-app/src/components/core/CoreHandlers.hpp index 90f3be1d0..e2d790e0f 100644 --- a/linphone-app/src/components/core/CoreHandlers.hpp +++ b/linphone-app/src/components/core/CoreHandlers.hpp @@ -61,6 +61,8 @@ signals: void setLastRemoteProvisioningState(const linphone::Config::ConfiguringState &state); void conferenceInfoReceived(const std::shared_ptr & conferenceInfo); void foundQRCode(const std::string & result); + + void eventCountChanged(); //-------------------- CORE HANDLER diff --git a/linphone-app/src/components/core/CoreListener.cpp b/linphone-app/src/components/core/CoreListener.cpp index 87ad06770..00aecdb42 100644 --- a/linphone-app/src/components/core/CoreListener.cpp +++ b/linphone-app/src/components/core/CoreListener.cpp @@ -93,6 +93,10 @@ void CoreListener::onNotifyPresenceReceived (const std::shared_ptr & core, const std::string & result){ emit qrcodeFound(core, result); } +void CoreListener::onReactionRemoved(const std::shared_ptr & core, const std::shared_ptr & chatRoom, const std::shared_ptr & message, const std::shared_ptr & address) { + emit reactionRemoved(core, chatRoom, message, address); +} + void CoreListener::onTransferStateChanged (const std::shared_ptr &core,const std::shared_ptr &call,linphone::Call::State state){ emit transferStateChanged (core,call,state); } diff --git a/linphone-app/src/components/core/CoreListener.hpp b/linphone-app/src/components/core/CoreListener.hpp index 705c17c4a..b9293a6f5 100644 --- a/linphone-app/src/components/core/CoreListener.hpp +++ b/linphone-app/src/components/core/CoreListener.hpp @@ -56,6 +56,7 @@ public: virtual void onNotifyPresenceReceivedForUriOrTel (const std::shared_ptr &core,const std::shared_ptr &linphoneFriend,const std::string &uriOrTel,const std::shared_ptr &presenceModel) override; virtual void onNotifyPresenceReceived (const std::shared_ptr &core,const std::shared_ptr &linphoneFriend) override; virtual void onQrcodeFound(const std::shared_ptr & core, const std::string & result) override; + virtual void onReactionRemoved(const std::shared_ptr & core, const std::shared_ptr & chatRoom, const std::shared_ptr & message, const std::shared_ptr & address) override; virtual void onTransferStateChanged (const std::shared_ptr &core,const std::shared_ptr &call,linphone::Call::State state) override; virtual void onVersionUpdateCheckResultReceived (const std::shared_ptr & core,linphone::VersionUpdateCheckResult result,const std::string &version,const std::string &url) override; virtual void onEcCalibrationResult(const std::shared_ptr & core,linphone::EcCalibratorStatus status,int delayMs) override; @@ -83,6 +84,7 @@ signals: void notifyPresenceReceivedForUriOrTel (const std::shared_ptr &core,const std::shared_ptr &linphoneFriend,const std::string &uriOrTel,const std::shared_ptr &presenceModel); void notifyPresenceReceived (const std::shared_ptr &core,const std::shared_ptr &linphoneFriend); void qrcodeFound(const std::shared_ptr & core, const std::string & result); + void reactionRemoved(const std::shared_ptr & core, const std::shared_ptr & chatRoom, const std::shared_ptr & message, const std::shared_ptr & address); void transferStateChanged (const std::shared_ptr &core,const std::shared_ptr &call,linphone::Call::State state); void versionUpdateCheckResultReceived (const std::shared_ptr & core,linphone::VersionUpdateCheckResult result,const std::string &version,const std::string &url); void ecCalibrationResult(const std::shared_ptr & core,linphone::EcCalibratorStatus status,int delayMs); diff --git a/linphone-app/src/components/core/CoreManager.cpp b/linphone-app/src/components/core/CoreManager.cpp index 52eab87a1..b4aa2e138 100644 --- a/linphone-app/src/components/core/CoreManager.cpp +++ b/linphone-app/src/components/core/CoreManager.cpp @@ -78,6 +78,7 @@ CoreManager::CoreManager (QObject *parent, const QString &configPath) : QObject::connect(coreHandlers, &CoreHandlers::coreStopped, this, &CoreManager::stopIterate, Qt::QueuedConnection); QObject::connect(coreHandlers, &CoreHandlers::logsUploadStateChanged, this, &CoreManager::handleLogsUploadStateChanged); QObject::connect(coreHandlers, &CoreHandlers::callLogUpdated, this, &CoreManager::callLogsCountChanged); + QObject::connect(coreHandlers, &CoreHandlers::eventCountChanged, this, &CoreManager::eventCountChanged); QTimer::singleShot(10, [this, configPath](){// Delay the creation in order to have the CoreManager instance set before createLinphoneCore(configPath); @@ -97,6 +98,8 @@ void CoreManager::initCoreManager(){ mContactsListModel = new ContactsListModel(this); mSipAddressesModel = new SipAddressesModel(this); // at first in order to prioritzed on handler signals. mAccountSettingsModel = new AccountSettingsModel(this); + connect(this, &CoreManager::eventCountChanged, mAccountSettingsModel, &AccountSettingsModel::missedCallsCountChanged); + connect(this, &CoreManager::eventCountChanged, mAccountSettingsModel, &AccountSettingsModel::unreadMessagesCountChanged); mSettingsModel = new SettingsModel(this); mEmojisSettingsModel = new EmojisSettingsModel(this); mCallsListModel = new CallsListModel(this); @@ -106,8 +109,6 @@ void CoreManager::initCoreManager(){ mLdapListModel = new LdapListModel(this); mEventCountNotifier = new EventCountNotifier(this); mTimelineListModel = new TimelineListModel(this); - mEventCountNotifier->updateUnreadMessageCount(); - QObject::connect(mEventCountNotifier, &EventCountNotifier::eventCountChanged,this, &CoreManager::eventCountChanged); migrate(); mStarted = true; @@ -179,10 +180,16 @@ void CoreManager::forceRefreshRegisters () { qInfo() << QStringLiteral("Refresh registers."); mCore->refreshRegisters(); } -void CoreManager::updateUnreadMessageCount(){ - mEventCountNotifier->updateUnreadMessageCount(); -} +void CoreManager::resetMissedCallsCount(){ + auto account = CoreManager::getInstance()->getCore()->getDefaultAccount(); + if(account) + account->resetMissedCallsCount(); + else + CoreManager::getInstance()->getCore()->resetMissedCallsCount(); + emit eventCountChanged(); +} + void CoreManager::stateChanged(Qt::ApplicationState pState){ if(mCbsTimer){ if(pState == Qt::ApplicationActive) @@ -403,12 +410,6 @@ int CoreManager::getEventCount () const { int CoreManager::getCallLogsCount() const{ return mCore->getCallLogs().size(); } -int CoreManager::getMissedCallCount(const QString &peerAddress, const QString &localAddress)const{ - return mEventCountNotifier ? mEventCountNotifier->getMissedCallCount(peerAddress, localAddress) : 0; -} -int CoreManager::getMissedCallCountFromLocal( const QString &localAddress)const{ - return mEventCountNotifier ? mEventCountNotifier->getMissedCallCountFromLocal(localAddress) : 0; -} std::list> CoreManager::getAccountList()const{ std::list> accounts; diff --git a/linphone-app/src/components/core/CoreManager.hpp b/linphone-app/src/components/core/CoreManager.hpp index 34b04191c..fc30f287a 100644 --- a/linphone-app/src/components/core/CoreManager.hpp +++ b/linphone-app/src/components/core/CoreManager.hpp @@ -155,15 +155,13 @@ public: Q_INVOKABLE VcardModel *createDetachedVcardModel () const; Q_INVOKABLE void forceRefreshRegisters (); - void updateUnreadMessageCount(); + void resetMissedCallsCount();// Reset current default account or core if no default. void stateChanged(Qt::ApplicationState pState); Q_INVOKABLE void sendLogs () const; Q_INVOKABLE void cleanLogs () const; int getCallLogsCount() const; - int getMissedCallCount(const QString &peerAddress, const QString &localAddress) const;// Get missed call count from a chat (useful for showing bubbles on Timelines) - int getMissedCallCountFromLocal(const QString &localAddress) const;// Get missed call count from a chat (useful for showing bubbles on Timelines) std::list> getAccountList()const; diff --git a/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp b/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp index 41795095d..ce218288e 100644 --- a/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp +++ b/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp @@ -21,13 +21,8 @@ #include #include "components/call/CallModel.hpp" -#include "components/calls/CallsListModel.hpp" -#include "components/chat-room/ChatRoomModel.hpp" -#include "components/core/CoreHandlers.hpp" #include "components/core/CoreManager.hpp" -#include "components/history/HistoryModel.hpp" #include "components/settings/SettingsModel.hpp" -#include "utils/Utils.hpp" #include "AbstractEventCountNotifier.hpp" @@ -37,116 +32,23 @@ using namespace std; AbstractEventCountNotifier::AbstractEventCountNotifier (QObject *parent) : QObject(parent) { CoreManager *coreManager = CoreManager::getInstance(); - QObject::connect( - coreManager, &CoreManager::chatRoomModelCreated, - this, &AbstractEventCountNotifier::handleChatRoomModelCreated - ); - QObject::connect( - coreManager, &CoreManager::historyModelCreated, - this, &AbstractEventCountNotifier::handleHistoryModelCreated - ); - QObject::connect( - coreManager->getHandlers().get(), &CoreHandlers::messagesReceived, - this, &AbstractEventCountNotifier::updateUnreadMessageCount - ); - QObject::connect( - coreManager->getSettingsModel(), &SettingsModel::standardChatEnabledChanged, - this, &AbstractEventCountNotifier::internalnotifyEventCount - ); - QObject::connect( - coreManager->getSettingsModel(), &SettingsModel::secureChatEnabledChanged, - this, &AbstractEventCountNotifier::internalnotifyEventCount - ); - QObject::connect(coreManager->getSettingsModel(), &SettingsModel::standardChatEnabledChanged, this, &AbstractEventCountNotifier::updateUnreadMessageCount); - QObject::connect(coreManager->getSettingsModel(), &SettingsModel::secureChatEnabledChanged, this, &AbstractEventCountNotifier::updateUnreadMessageCount); - /* - QObject::connect( - coreManager->getCallsListModel(), &CallsListModel::callMissed, - this, &AbstractEventCountNotifier::handleCallMissed - );*/ + connect(coreManager, &CoreManager::eventCountChanged, this, &AbstractEventCountNotifier::eventCountChanged); + connect(this, &AbstractEventCountNotifier::eventCountChanged, this, &AbstractEventCountNotifier::internalNotifyEventCount); } // ----------------------------------------------------------------------------- -void AbstractEventCountNotifier::updateUnreadMessageCount () { +int AbstractEventCountNotifier::getEventCount () const { auto coreManager = CoreManager::getInstance(); - if(!coreManager->getSettingsModel()->getStandardChatEnabled() && !coreManager->getSettingsModel()->getSecureChatEnabled()) - mUnreadMessageCount = 0; - else - mUnreadMessageCount = CoreManager::getInstance()->getCore()->getUnreadChatMessageCountFromActiveLocals(); - internalnotifyEventCount(); -} - -void AbstractEventCountNotifier::internalnotifyEventCount () { - int n = mUnreadMessageCount + getMissedCallCount(); - qInfo() << QStringLiteral("Notify event count: %1.").arg(n); - n = n > 99 ? 99 : n; - - notifyEventCount(CoreManager::getInstance()->getSettingsModel()->getStandardChatEnabled() || CoreManager::getInstance()->getSettingsModel()->getSecureChatEnabled()? n : 0); - emit eventCountChanged(); -} - -// Get missed call from a chat (useful for showing bubbles on Timelines) -int AbstractEventCountNotifier::getMissedCallCount(const QString &peerAddress, const QString &localAddress) const{ - auto it = mMissedCalls.find({ Utils::cleanSipAddress(peerAddress), Utils::cleanSipAddress(localAddress) }); - if (it != mMissedCalls.cend()) - return *it; - else - return 0; -} -// Get missed call from a chat (useful for showing bubbles on Timelines) -int AbstractEventCountNotifier::getMissedCallCountFromLocal(const QString &localAddress) const{ - QString cleanAddress = Utils::cleanSipAddress(localAddress); - int count = 0; - for(auto it = mMissedCalls.cbegin() ; it != mMissedCalls.cend() ; ++it){ - if(it.key().second == cleanAddress) - count += *it; - } + int count = coreManager->getCore()->getMissedCallsCount(); + if( coreManager->getSettingsModel()->getStandardChatEnabled() || coreManager->getSettingsModel()->getSecureChatEnabled()) + count += coreManager->getCore()->getUnreadChatMessageCount(); return count; } -// ----------------------------------------------------------------------------- -void AbstractEventCountNotifier::handleChatRoomModelCreated (const QSharedPointer &chatRoomModel) { - ChatRoomModel *chatRoomModelPtr = chatRoomModel.get(); - QObject::connect( - chatRoomModelPtr, &ChatRoomModel::messageCountReset, - this, &AbstractEventCountNotifier::updateUnreadMessageCount - ); - QObject::connect( - chatRoomModelPtr, &ChatRoomModel::focused, - this, [this, chatRoomModelPtr]() { handleResetMissedCalls(chatRoomModelPtr); } - ); - QObject::connect( - chatRoomModelPtr, &ChatRoomModel::messageCountReset, - this, [this, chatRoomModelPtr]() { handleResetMissedCalls(chatRoomModelPtr); } - ); -} - -void AbstractEventCountNotifier::handleHistoryModelCreated (HistoryModel *historyModel) { - QObject::connect(historyModel, &HistoryModel::callCountReset - , this, &AbstractEventCountNotifier::handleResetAllMissedCalls); -} - -void AbstractEventCountNotifier::handleResetAllMissedCalls () { - mMissedCalls.clear(); - internalnotifyEventCount(); -} - - -void AbstractEventCountNotifier::handleResetMissedCalls (ChatRoomModel *chatRoomModel) { - auto it = mMissedCalls.find({ Utils::cleanSipAddress(chatRoomModel->getPeerAddress()), Utils::cleanSipAddress(chatRoomModel->getLocalAddress()) }); - if (it != mMissedCalls.cend()) { - mMissedCalls.erase(it); - internalnotifyEventCount(); - } -} - -void AbstractEventCountNotifier::handleCallMissed (CallModel *callModel) { - ++mMissedCalls[{ Utils::cleanSipAddress(callModel->getPeerAddress()), Utils::cleanSipAddress(callModel->getLocalAddress()) }]; - internalnotifyEventCount(); -} - -void AbstractEventCountNotifier::handleCallMissed (const QString& localAddress, const QString& peerAddress) { - ++mMissedCalls[{ peerAddress, localAddress }]; - internalnotifyEventCount(); -} +void AbstractEventCountNotifier::internalNotifyEventCount () { + int n = getEventCount(); + qInfo() << QStringLiteral("Notify event count: %1.").arg(n); + n = n > 99 ? 99 : n; + notifyEventCount(n); +} \ No newline at end of file diff --git a/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp b/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp index d58bed4bb..e5a438152 100644 --- a/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp +++ b/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp @@ -43,41 +43,18 @@ class AbstractEventCountNotifier : public QObject { public: AbstractEventCountNotifier (QObject *parent = Q_NULLPTR); - void updateUnreadMessageCount (); - - int getUnreadMessageCount () const { return mUnreadMessageCount; } - int getMissedCallCount () const { - int t = 0; - for (int n : mMissedCalls) t += n; - return t; - } - - int getEventCount () const { return mUnreadMessageCount + getMissedCallCount(); } - int getMissedCallCount(const QString &peerAddress, const QString &localAddress) const;// Get missed call count from a chat (useful for showing bubbles on Timelines) - int getMissedCallCountFromLocal(const QString &localAddress) const;// Get missed call count from a chat (useful for showing bubbles on Timelines) - + int getUnreadMessageCount () const; + int getMissedCallCount () const; + int getEventCount () const; signals: void eventCountChanged (); - -public slots: - void handleCallMissed (const QString& localAddress, const QString& peerAddress); - void handleResetAllMissedCalls (); - void handleResetMissedCalls (ChatRoomModel *chatRoomModel); - void handleCallMissed (CallModel *callModel); - + protected: virtual void notifyEventCount (int n) = 0; private: - using ConferenceId = QPair; - void internalnotifyEventCount (); - - void handleChatRoomModelCreated (const QSharedPointer &chatRoomModel); - void handleHistoryModelCreated (HistoryModel *historyModel); - - QHash mMissedCalls; - int mUnreadMessageCount = 0; + void internalNotifyEventCount (); }; #endif // ABSTRACT_EVENT_COUNT_NOTIFIER_H_ diff --git a/linphone-app/src/components/core/event-count-notifier/EventCountNotifierSystemTrayIcon.cpp b/linphone-app/src/components/core/event-count-notifier/EventCountNotifierSystemTrayIcon.cpp index ccc6e73c8..707710feb 100644 --- a/linphone-app/src/components/core/event-count-notifier/EventCountNotifierSystemTrayIcon.cpp +++ b/linphone-app/src/components/core/event-count-notifier/EventCountNotifierSystemTrayIcon.cpp @@ -60,11 +60,6 @@ EventCountNotifier::EventCountNotifier (QObject *parent) : AbstractEventCountNot mBlinkTimer = new QTimer(this); mBlinkTimer->setInterval(IconCounterBlinkInterval); QObject::connect(mBlinkTimer, &QTimer::timeout, this, &EventCountNotifier::update); - - Utils::connectOnce( - App::getInstance(), &App::focusWindowChanged, - this, &EventCountNotifier::updateUnreadMessageCount - ); } EventCountNotifier::~EventCountNotifier () { diff --git a/linphone-app/src/components/history/CallHistoryListModel.cpp b/linphone-app/src/components/history/CallHistoryListModel.cpp new file mode 100644 index 000000000..1269e8802 --- /dev/null +++ b/linphone-app/src/components/history/CallHistoryListModel.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CallHistoryListModel.hpp" +#include "CallHistoryModel.hpp" + +#include "components/core/CoreManager.hpp" +#include "components/core/CoreHandlers.hpp" +#include "components/settings/AccountSettingsModel.hpp" +#include "utils/Utils.hpp" + +// ============================================================================= + +CallHistoryListModel::CallHistoryListModel (QObject *parent) : ProxyListModel(parent) { + reload(); + connect(CoreManager::getInstance()->getHandlers().get(), &CoreHandlers::callLogUpdated, this, &CallHistoryListModel::onCallLogUpdated); +} + +QString reorder(const QString& address){ + QStringList splitted = address.split(";"); + QString newAddress = splitted[0]; + splitted.removeFirst(); + splitted.sort(); + return newAddress + splitted.join(";"); +} + +void CallHistoryListModel::reload() { + beginResetModel(); + mList.clear(); + endResetModel(); + auto account = CoreManager::getInstance()->getCore()->getDefaultAccount(); + auto callLogs = account ? account->getCallLogs() : CoreManager::getInstance()->getCore()->getCallLogs(); + add(callLogs); + CoreManager::getInstance()->resetMissedCallsCount(); + if(mList.size() > 0) + QTimer::singleShot(1, [&](){ + mList.at(0).objectCast()->selectOnly(); + }); +} + +CallHistoryListModel::~CallHistoryListModel(){ +} + +void CallHistoryListModel::add(const std::list>& callLogs){ + QList> toAdd; + for(auto callLog : callLogs) { + if(!callLog->getLocalAddress()->weakEqual(CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress())) + continue; + QString confUri; + auto remoteAddress = callLog->getRemoteAddress()->clone(); + remoteAddress->clean(); + QString address = reorder(Utils::coreStringToAppString(remoteAddress->asStringUriOnly())); + if( callLog->getConferenceInfo()) { + confUri = reorder(Utils::coreStringToAppString(callLog->getConferenceInfo()->getUri()->asStringUriOnly())); + } + QString keyName = address + "/"+confUri; + if(!mCalls.contains(keyName)) { + auto call = QSharedPointer::create(callLog); + mCalls[keyName] = call; + connect(call.get(), &CallHistoryModel::selectOnlyRequested, this, &CallHistoryListModel::onSelectOnlyRequested); + connect(call.get(), &CallHistoryModel::selectedChanged, this, &CallHistoryListModel::onSelectedChanged); + connect(call.get(), &CallHistoryModel::hasBeenRemoved, this, &CallHistoryListModel::onHasBeenRemoved); + connect(call.get(), &CallHistoryModel::lastCallDateChanged, this, &CallHistoryListModel::lastCallDateChanged); + toAdd << call; + }else{ + mCalls[keyName]->update(callLog); + } + } + + ProxyListModel::add(toAdd); +} + +void CallHistoryListModel::onCallLogUpdated(const std::shared_ptr &call){ + add(std::list>{call}); +} + +void CallHistoryListModel::onSelectOnlyRequested() { + for(auto model : mList){ + auto callModel = model.objectCast(); + if(callModel != sender()) + callModel->setSelected(false); + } +} + +void CallHistoryListModel::onSelectedChanged(bool selected, CallHistoryModel * model) { + if(selected) { + emit selectedChanged(model); + CoreManager::getInstance()->resetMissedCallsCount(); + } +} +void CallHistoryListModel::onHasBeenRemoved(){ + QString confUri; + auto model = qobject_cast(sender()); + QString address = reorder(model->getRemoteAddress()); + if( model->wasConference()) { + confUri = reorder(Utils::coreStringToAppString(model->getConferenceInfoModel()->getConferenceInfo()->getUri()->asStringUriOnly())); + } + remove(sender()); + QString keyName = address + "/"+confUri; + mCalls.remove(keyName); + if(model->mSelected) { + if(mList.size() > 0){ + mList.at(0).objectCast()->selectOnly(); + } + } +} diff --git a/linphone-app/src/components/history/CallHistoryListModel.hpp b/linphone-app/src/components/history/CallHistoryListModel.hpp new file mode 100644 index 000000000..37888dbae --- /dev/null +++ b/linphone-app/src/components/history/CallHistoryListModel.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef CALL_HISTORY_LIST_MODEL_H_ +#define CALL_HISTORY_LIST_MODEL_H_ + +#include +#include +#include "app/proxyModel/ProxyListModel.hpp" + + +class CallHistoryModel; +// ============================================================================= + +class CallHistoryListModel : public ProxyListModel { + Q_OBJECT +public: + + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) + + CallHistoryListModel (QObject *parent = Q_NULLPTR); + virtual ~CallHistoryListModel(); + + void reload(); + void add(const std::list>& callLog); + void onCallLogUpdated(const std::shared_ptr &call); + void onSelectedChanged(bool selected, CallHistoryModel * model); + void onSelectOnlyRequested(); + void onHasBeenRemoved(); +signals: + void countChanged(); + void selectedChanged(CallHistoryModel * model); + void lastCallDateChanged(); +private: + QHash> mCalls; +}; + +#endif diff --git a/linphone-app/src/components/history/CallHistoryModel.cpp b/linphone-app/src/components/history/CallHistoryModel.cpp new file mode 100644 index 000000000..2bf986f48 --- /dev/null +++ b/linphone-app/src/components/history/CallHistoryModel.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2010-2023 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CallHistoryModel.hpp" + +#include "utils/Utils.hpp" + +#include + +CallHistoryModel::CallHistoryModel(QObject *parent) : QObject(parent){ + +} + +CallHistoryModel::CallHistoryModel(const std::shared_ptr callLog, QObject *parent) : QObject(parent){ + mRemoteAddress = callLog->getRemoteAddress()->clone(); + mRemoteAddress->clean(); + mLastCallStatus = LinphoneEnums::fromLinphone(callLog->getStatus()); + if(mShowEnd && mLastCallStatus == LinphoneEnums::CallStatusSuccess){ + mLastCallDate = QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000); + mLastCallIsStart = false; + }else { + mLastCallDate = QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000); + mLastCallIsStart = true; + } + mLastCallIsOutgoing = callLog->getDir() == linphone::Call::Dir::Outgoing; + mConferenceInfoModel = ConferenceInfoModel::create(callLog->getConferenceInfo()); + if(!mConferenceInfoModel && callLog->wasConference()) + qWarning() << "Was conf without info : " << Utils::coreStringToAppString(mRemoteAddress->asStringUriOnly()); +} + +QString CallHistoryModel::getRemoteAddress() const{ + return Utils::coreStringToAppString(mRemoteAddress->asStringUriOnly()); +} + +QString CallHistoryModel::getSipAddress() const{ + if( mConferenceInfoModel ) + return Utils::coreStringToAppString(mConferenceInfoModel->getConferenceInfo()->getUri()->asStringUriOnly()); + else + return Utils::coreStringToAppString(mRemoteAddress->asStringUriOnly()); +} + + +ConferenceInfoModel * CallHistoryModel::getConferenceInfoModel() const { + return mConferenceInfoModel.get(); +} + +bool CallHistoryModel::wasConference() const { + return mConferenceInfoModel; +} + +QString CallHistoryModel::getTitle() const { + if(mConferenceInfoModel) + return mConferenceInfoModel->getSubject(); + else + return ""; +} + +void CallHistoryModel::update(const std::shared_ptr callLog){ + QDateTime callDate; + if(mShowEnd && mLastCallStatus == LinphoneEnums::CallStatusSuccess){ + callDate = QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000); + }else { + callDate = QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000); + } + if(callDate >= mLastCallDate){ + setLastCallStatus(LinphoneEnums::fromLinphone(callLog->getStatus())); + if(mShowEnd && mLastCallStatus == LinphoneEnums::CallStatusSuccess){ + setLastCallDate(QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000)); + setLastCallIsStart(false); + }else { + setLastCallDate(QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000)); + setLastCallIsStart(true); + } + mConferenceInfoModel = ConferenceInfoModel::create(callLog->getConferenceInfo()); + emit conferenceInfoModelChanged(); + } +} + +void CallHistoryModel::setLastCallStatus(LinphoneEnums::CallStatus status) { + if(mLastCallStatus != status){ + mLastCallStatus = status; + emit lastCallStatusChanged(); + } +} + +void CallHistoryModel::setLastCallDate(const QDateTime& date) { + if( mLastCallDate != date) { + mLastCallDate = date; + emit lastCallDateChanged(); + } +} + +void CallHistoryModel::setLastCallIsStart(const bool& start) { + if( mLastCallIsStart != start) { + mLastCallIsStart = start; + emit lastCallIsStartChanged(); + } +} + +void CallHistoryModel::setLastCallIsOutgoing(const bool& outgoing){ + if( mLastCallIsOutgoing != outgoing) { + mLastCallIsOutgoing = outgoing; + emit lastCallIsOutgoingChanged(); + } +} + +void CallHistoryModel::setSelected(const bool& selected){ + if(selected != mSelected || selected){ + mSelected = selected; + if(mSelected){ + qInfo() << "Call room selected : Address :" << getRemoteAddress(); + }else{ + qInfo() << "Unselect call room "<< getRemoteAddress(); + } + emit selectedChanged(mSelected, this); + } +} + +void CallHistoryModel::selectOnly(){ + setSelected(true); + emit selectOnlyRequested(); +} + diff --git a/linphone-app/src/components/history/CallHistoryModel.hpp b/linphone-app/src/components/history/CallHistoryModel.hpp new file mode 100644 index 000000000..eca666d59 --- /dev/null +++ b/linphone-app/src/components/history/CallHistoryModel.hpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2010-2023 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef CALL_HISTORY_MODEL_H_ +#define CALL_HISTORY_MODEL_H_ + +#include +#include +#include + +#include "components/conferenceInfo/ConferenceInfoModel.hpp" +#include "utils/LinphoneEnums.hpp" + +class CallHistoryModel : public QObject { + Q_OBJECT + +public: + Q_PROPERTY(QString remoteAddress READ getRemoteAddress CONSTANT) // strip from gruu/conf-id + Q_PROPERTY(QString sipAddress READ getSipAddress NOTIFY conferenceInfoModelChanged) // Use to call + Q_PROPERTY(bool selected MEMBER mSelected WRITE setSelected NOTIFY selectedChanged) + + Q_PROPERTY(LinphoneEnums::CallStatus lastCallStatus MEMBER mLastCallStatus WRITE setLastCallStatus NOTIFY lastCallStatusChanged) + Q_PROPERTY(QDateTime lastCallDate MEMBER mLastCallDate WRITE setLastCallDate NOTIFY lastCallDateChanged) + Q_PROPERTY(bool lastCallIsStart MEMBER mLastCallIsStart WRITE setLastCallIsStart NOTIFY lastCallIsStartChanged) + Q_PROPERTY(bool lastCallIsOutgoing MEMBER mLastCallIsOutgoing WRITE setLastCallIsOutgoing NOTIFY lastCallIsOutgoingChanged) + Q_PROPERTY(ConferenceInfoModel * conferenceInfoModel READ getConferenceInfoModel NOTIFY conferenceInfoModelChanged) + Q_PROPERTY(bool wasConference READ wasConference NOTIFY conferenceInfoModelChanged) + Q_PROPERTY(QString title READ getTitle NOTIFY conferenceInfoModelChanged) + + CallHistoryModel(QObject *parent = nullptr); + CallHistoryModel(const std::shared_ptr callLogs, QObject *parent = nullptr); + + QString getRemoteAddress() const; + QString getSipAddress() const; + ConferenceInfoModel * getConferenceInfoModel() const; + bool wasConference() const; + QString getTitle() const; + + void update(const std::shared_ptr callLog); + + void setLastCallStatus(LinphoneEnums::CallStatus status); + void setLastCallDate(const QDateTime& date); + void setLastCallIsStart(const bool& start); + void setLastCallIsOutgoing(const bool& outgoing); + + void setSelected(const bool& selected); + Q_INVOKABLE void selectOnly(); // Select this item and remove others in parent lists + + QDateTime mLastCallDate; + bool mSelected = false; + bool mLastCallIsOutgoing; + LinphoneEnums::CallStatus mLastCallStatus; + +signals: + void selectOnlyRequested(); + void selectedChanged(bool selected, CallHistoryModel * model); + void lastCallStatusChanged(); + void lastCallDateChanged(); + void lastCallIsStartChanged(); + void lastCallIsOutgoingChanged(); + void conferenceInfoModelChanged(); + void hasBeenRemoved(); + +private: + std::shared_ptr mRemoteAddress; + bool mLastCallIsStart; + QSharedPointer mConferenceInfoModel; + + bool mShowEnd = false; // Display ended call (start + duration) +}; + +#endif diff --git a/linphone-app/src/components/history/CallHistoryProxyModel.cpp b/linphone-app/src/components/history/CallHistoryProxyModel.cpp new file mode 100644 index 000000000..6376a60d4 --- /dev/null +++ b/linphone-app/src/components/history/CallHistoryProxyModel.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CallHistoryProxyModel.hpp" +#include "CallHistoryListModel.hpp" +#include "CallHistoryModel.hpp" + +#include "app/App.hpp" +#include "components/core/CoreManager.hpp" +#include "components/settings/AccountSettingsModel.hpp" +#include "utils/Utils.hpp" +#include +#include + + +// ============================================================================= + +// ----------------------------------------------------------------------------- + +CallHistoryProxyModel::CallHistoryProxyModel (QObject *parent) : QSortFilterProxyModel(parent) { + auto model = new CallHistoryListModel(); + setSourceModel(model); + sort(0); + connect(CoreManager::getInstance()->getAccountSettingsModel(), &AccountSettingsModel::defaultAccountChanged, model, &CallHistoryListModel::reload); + connect(model, &CallHistoryListModel::lastCallDateChanged, this, &CallHistoryProxyModel::invalidate); + App *app = App::getInstance(); + connect(app->getMainWindow(), &QWindow::activeChanged, this, [this]() { + handleIsActiveChanged(App::getInstance()->getMainWindow()); + }); +} + +// ----------------------------------------------------------------------------- + +void CallHistoryProxyModel::setFilterFlags(int filterFlags){ + if( mFilterFlags != filterFlags){ + mFilterFlags = filterFlags; + invalidate(); + emit filterFlagsChanged(); + } +} + +void CallHistoryProxyModel::setFilterText(const QString& text){ + if( mFilterText != text){ + mFilterText = text; + invalidate(); + emit filterTextChanged(); + } +} + +// ----------------------------------------------------------------------------- + +bool CallHistoryProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const { + if(!sourceModel()) + return false; + bool show = true; + + const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + auto timeline = sourceModel()->data(index).value(); + + if( mFilterFlags > 0) { + show = ( ((mFilterFlags & CallTimelineFilter::Incoming) == CallTimelineFilter::Incoming) && !timeline->mLastCallIsOutgoing) + || ( ((mFilterFlags & CallTimelineFilter::Outgoing) == CallTimelineFilter::Outgoing) && timeline->mLastCallIsOutgoing) + || ( ((mFilterFlags & CallTimelineFilter::Missed) == CallTimelineFilter::Missed) && timeline->mLastCallStatus == LinphoneEnums::CallStatusMissed) + ; + } + + + if(show && mFilterText != ""){ + QRegularExpression search(QRegularExpression::escape(mFilterText), QRegularExpression::CaseInsensitiveOption | QRegularExpression::UseUnicodePropertiesOption); + show = ( timeline->getTitle().contains(search) + //|| timeline->getRemoteAddress().contains(search) + || Utils::getDisplayName(timeline->getRemoteAddress()).contains(search) + ); + //|| timeline->getChatRoomModel()->getFullPeerAddress().contains(search); not enough significant? + } + return show; +} + +bool CallHistoryProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { + if( !sourceModel()) + return false; + const CallHistoryModel* a = sourceModel()->data(left).value(); + const CallHistoryModel* b = sourceModel()->data(right).value(); + return a->mLastCallDate > b->mLastCallDate; +} + +static inline QWindow *getParentWindow (QObject *object) { + App *app = App::getInstance(); + const QWindow *mainWindow = app->getMainWindow(); + const QWindow *callsWindow = app->getCallsWindow(); + for (QObject *parent = object->parent(); parent; parent = parent->parent()) + if (parent == mainWindow || parent == callsWindow) + return static_cast(parent); + return nullptr; +} + +void CallHistoryProxyModel::handleIsActiveChanged (QWindow *window) { + if (window->isActive() && getParentWindow(this) == window) { + CoreManager::getInstance()->resetMissedCallsCount(); + } +} \ No newline at end of file diff --git a/linphone-app/src/components/history/CallHistoryProxyModel.hpp b/linphone-app/src/components/history/CallHistoryProxyModel.hpp new file mode 100644 index 000000000..4ac38efe0 --- /dev/null +++ b/linphone-app/src/components/history/CallHistoryProxyModel.hpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020-2023 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef CALL_HISTORY_PROXY_MODEL_H_ +#define CALL_HISTORY_PROXY_MODEL_H_ + +#include +#include + +class CallHistoryModel; +class QWindow; + +// ============================================================================= + +class CallHistoryProxyModel : public QSortFilterProxyModel { + Q_OBJECT +public: + CallHistoryProxyModel (QObject *parent = Q_NULLPTR); + + enum CallTimelineFilter { + Incoming = 1, + Outgoing = 2, + Missed = 4, + All = 0 + }; + Q_ENUM(CallTimelineFilter) + + Q_PROPERTY(int filterFlags MEMBER mFilterFlags WRITE setFilterFlags NOTIFY filterFlagsChanged) + Q_PROPERTY(QString filterText MEMBER mFilterText WRITE setFilterText NOTIFY filterTextChanged) + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) + + void setFilterFlags(int flags); + Q_INVOKABLE void setFilterText(const QString& text); + + void handleIsActiveChanged (QWindow *window); + +signals: + void countChanged(); + void filterTextChanged(); + void selectedChanged(const QString& remoteAddress); + void filterFlagsChanged(); + +protected: + + bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override; + bool lessThan (const QModelIndex &left, const QModelIndex &right) const override; + +private: + QString mFilterText; + int mFilterFlags = -1; +}; + +#endif diff --git a/linphone-app/src/components/history/HistoryModel.cpp b/linphone-app/src/components/history/HistoryModel.cpp index b0e0ced54..ae60b3038 100644 --- a/linphone-app/src/components/history/HistoryModel.cpp +++ b/linphone-app/src/components/history/HistoryModel.cpp @@ -31,8 +31,10 @@ #include #include +#include "CallHistoryModel.hpp" #include "components/core/CoreHandlers.hpp" #include "components/core/CoreManager.hpp" +#include "components/settings/AccountSettingsModel.hpp" #include "utils/Utils.hpp" #include "HistoryModel.hpp" @@ -83,10 +85,19 @@ HistoryModel::HistoryModel (QObject *parent) :QAbstractListModel(parent){ setSipAddresses(); CoreHandlers *coreHandlers = mCoreHandlers.get(); QObject::connect(coreHandlers, &CoreHandlers::callStateChanged, this, &HistoryModel::handleCallStateChanged); +} + +HistoryModel::HistoryModel (CallHistoryModel * callHistoryModel, QObject *parent) :QAbstractListModel(parent){ + CoreManager *coreManager = CoreManager::getInstance(); + mCoreHandlers = coreManager->getHandlers(); + setSipAddresses(callHistoryModel); + CoreHandlers *coreHandlers = mCoreHandlers.get(); + QObject::connect(coreHandlers, &CoreHandlers::callStateChanged, this, &HistoryModel::handleCallStateChanged); } HistoryModel::~HistoryModel () { + qWarning() << "Destroying HistoryModel"; } QHash HistoryModel::roleNames () const { @@ -148,23 +159,110 @@ bool HistoryModel::removeRows (int row, int count, const QModelIndex &parent) { return true; } -void HistoryModel::setSipAddresses () { +static bool hasSameParameters(const QStringList& a, const QStringList& b){ + if(a.size() != b.size()) + return false; + int i = 0; + while(i < a.size()) { + if(b.contains(a[i])) + ++i; + else + break; + } + return i >= a.size(); +} +// Why complicated? +// - Address parameters can be stored in different order and getCallHistory() reorder address parameters => need to get on pure address without parameters. +// - A call to/from someone (no gruu and no conf-id) can a conference call => the pair remotre address + URI need to be check (watchout of parameters order) +void HistoryModel::setSipAddresses (CallHistoryModel *callModel) { shared_ptr core = CoreManager::getInstance()->getCore(); + beginResetModel(); mEntries.clear(); QElapsedTimer timer; timer.start(); // Get calls. - for (auto &callLog : core->getCallLogs()) - insertCall(callLog); + if(!callModel) + for (auto &callLog : core->getCallLogs()) + insertCall(callLog); + else{ + mRemoteAddress = callModel->getRemoteAddress(); + auto address = Utils::interpretUrl(mRemoteAddress);// already cleaned + auto conferenceInfoModel = callModel->getConferenceInfoModel(); + QStringList conferenceInfoModelParams; + if(conferenceInfoModel) { + mConferenceUri = conferenceInfoModel->getUri(); + conferenceInfoModelParams = mConferenceUri.split(";"); + } + for (auto &callLog : core->getCallHistory(address, CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress())) { + bool toInsert = false; + auto callLogConferenceInfoModel = callLog->getConferenceInfo(); + if(conferenceInfoModel && callLogConferenceInfoModel) { + QStringList logConfUriParams = Utils::coreStringToAppString(callLogConferenceInfoModel->getUri()->asStringUriOnly()).split(";"); + if(hasSameParameters(conferenceInfoModelParams, logConfUriParams)) {// Uri addresses are equal + toInsert = true; + } + }else if(!conferenceInfoModel && !callLogConferenceInfoModel) + toInsert = true; + if(toInsert) + insertCall(callLog); + } + + + /* + QString uriOnly = Utils::coreStringToAppString(address->asStringUriOnly()); + QStringList parameters = uriOnly.split(";"); + auto conferenceInfoModel = callModel->getConferenceInfoModel(); + QStringList conferenceInfoModelParams; + if(conferenceInfoModel) { + conferenceInfoModelParams = conferenceInfoModel->getUri().split(";"); + } + for (auto &callLog : core->getCallHistory(Utils::interpretUrl(parameters[0]), CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress())) { + + + if(parameters.size() > 2) { // We have to check address with mixed parameters order from the result of getCallHistory() + for (auto &callLog : core->getCallHistory(Utils::interpretUrl(parameters[0]), CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress())) { + QStringList logParams = Utils::coreStringToAppString(callLog->getRemoteAddress()->asStringUriOnly()).split(";"); + if(hasSameParameters(parameters, logParams)) {// Remote address are equal + bool toInsert = false; + auto callLogConferenceInfoModel = callLog->getConferenceInfo(); + if(conferenceInfoModel && callLogConferenceInfoModel) { + QStringList logConfUriParams = Utils::coreStringToAppString(callLogConferenceInfoModel->getUri()->asStringUriOnly()).split(";"); + if(hasSameParameters(conferenceInfoModelParams, logConfUriParams)) {// Uri addresses are equal + toInsert = true; + } + }else if(!conferenceInfoModel && !callLogConferenceInfoModel) + toInsert = true; + if(toInsert) + insertCall(callLog); + } + } + }else { + for (auto &callLog : core->getCallHistory(address, CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress())) { + auto callLogConferenceInfoModel = callLog->getConferenceInfo(); + bool toInsert = false; + if(conferenceInfoModel && callLogConferenceInfoModel) { + QStringList logConfUriParams = Utils::coreStringToAppString(callLogConferenceInfoModel->getUri()->asStringUriOnly()).split(";"); + if(hasSameParameters(conferenceInfoModelParams, logConfUriParams)) {// Uri addresses are equal + toInsert = true; + } + }else if(!conferenceInfoModel && !callLogConferenceInfoModel) + toInsert = true; + if(toInsert) + + + insertCall(callLog); + } + }*/ + } qInfo() << QStringLiteral("HistoryModel loaded in %3 milliseconds.").arg(timer.elapsed()); - + endResetModel(); } void HistoryModel::reload(){ beginResetModel(); - setSipAddresses(); + //setSipAddresses(); endResetModel(); } // ----------------------------------------------------------------------------- @@ -267,7 +365,25 @@ void HistoryModel::resetMessageCount () { // ----------------------------------------------------------------------------- void HistoryModel::handleCallStateChanged (const shared_ptr &call, linphone::Call::State state) { - if (state == linphone::Call::State::End || state == linphone::Call::State::Error) - insertCall(call->getCallLog()); + if (state == linphone::Call::State::End || state == linphone::Call::State::Error) { + auto address = Utils::interpretUrl(mRemoteAddress);// already cleaned + QStringList conferenceInfoModelParams = mConferenceUri.split(";"); + bool toInsert = false; + auto callLog = call->getCallLog(); + auto callLogConferenceInfoModel = callLog->getConferenceInfo(); + if(mRemoteAddress.isEmpty()) + toInsert = true; + else if(address->weakEqual(callLog->getRemoteAddress()) && callLog->getLocalAddress()->weakEqual(CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress())) { + if(!mConferenceUri.isEmpty() && callLogConferenceInfoModel) { + QStringList logConfUriParams = Utils::coreStringToAppString(callLogConferenceInfoModel->getUri()->asStringUriOnly()).split(";"); + if(hasSameParameters(conferenceInfoModelParams, logConfUriParams)) {// Uri addresses are equal + toInsert = true; + } + }else if(mConferenceUri.isEmpty() && !callLogConferenceInfoModel) + toInsert = true; + } + if(toInsert) + insertCall(callLog); + } } diff --git a/linphone-app/src/components/history/HistoryModel.hpp b/linphone-app/src/components/history/HistoryModel.hpp index 4111b7023..f5fe3ec39 100644 --- a/linphone-app/src/components/history/HistoryModel.hpp +++ b/linphone-app/src/components/history/HistoryModel.hpp @@ -30,6 +30,7 @@ // ============================================================================= class CoreHandlers; +class CallHistoryModel; class HistoryModel : public QAbstractListModel { @@ -59,6 +60,7 @@ public: Q_ENUM(CallStatus) HistoryModel (QObject *parent = Q_NULLPTR); + HistoryModel (CallHistoryModel *callHistoryModel, QObject *parent = Q_NULLPTR); virtual ~HistoryModel (); int rowCount (const QModelIndex &index = QModelIndex()) const override; @@ -72,6 +74,8 @@ public: void removeEntry (int id); void removeAllEntries (); + void setSipAddresses (CallHistoryModel * callModel = nullptr); + void resetMessageCount (); Q_INVOKABLE void reload(); @@ -86,13 +90,14 @@ signals: private: typedef QPair> HistoryEntryData; - void setSipAddresses (); + void removeEntry (HistoryEntryData &entry); void insertCall (const std::shared_ptr &callLog); void handleCallStateChanged (const std::shared_ptr &call, linphone::Call::State state); mutable QList mEntries; - + QString mRemoteAddress; + QString mConferenceUri; QSharedPointer mCoreHandlers; }; diff --git a/linphone-app/src/components/history/HistoryProxyModel.cpp b/linphone-app/src/components/history/HistoryProxyModel.cpp index bf2527e8b..e4129c414 100644 --- a/linphone-app/src/components/history/HistoryProxyModel.cpp +++ b/linphone-app/src/components/history/HistoryProxyModel.cpp @@ -24,6 +24,7 @@ #include "components/core/CoreManager.hpp" #include "HistoryProxyModel.hpp" +#include "CallHistoryModel.hpp" #include "components/sip-addresses/SipAddressesModel.hpp" // ============================================================================= @@ -55,6 +56,13 @@ protected: return data["type"].toInt() == mEntryTypeFilter; } + bool lessThan (const QModelIndex &left, const QModelIndex &right) const override { + if( !sourceModel()) + return false; + auto a = sourceModel()->data(left).value(); + auto b = sourceModel()->data(right).value(); + return a["receivedTimestamp"] > b["receivedTimestamp"]; + } private: HistoryModel::EntryType mEntryTypeFilter = HistoryModel::EntryType::GenericEntry; }; @@ -64,8 +72,7 @@ private: HistoryProxyModel::HistoryProxyModel (QObject *parent) : QSortFilterProxyModel(parent) { setSourceModel(new HistoryModelFilter(this)); - reload(); - + sort(0); App *app = App::getInstance(); QObject::connect(app->getMainWindow(), &QWindow::activeChanged, this, [this]() { handleIsActiveChanged(App::getInstance()->getMainWindow()); @@ -78,20 +85,22 @@ HistoryProxyModel::HistoryProxyModel (QObject *parent) : QSortFilterProxyModel(p }); } +void HistoryProxyModel::setCallHistoryModel(CallHistoryModel * model) { + if(mCallHistoryModel != model){ + mCallHistoryModel = model; + reload(); + emit callHistoryModelChanged(); + } +} // ----------------------------------------------------------------------------- void HistoryProxyModel::removeAllEntries(){ - auto model = CoreManager::getInstance()->getHistoryModel(); - if (!model) - return; - model->removeAllEntries(); + static_cast(static_cast(sourceModel())->sourceModel())->removeAllEntries(); + emit mCallHistoryModel->hasBeenRemoved(); } void HistoryProxyModel::removeEntry (int id){ - auto model = CoreManager::getInstance()->getHistoryModel(); - if (!model) - return; QModelIndex sourceIndex = mapToSource(index(id, 0)); - model->removeEntry(static_cast(sourceModel())->mapToSource(sourceIndex).row() ); + static_cast(static_cast(sourceModel())->sourceModel())->removeEntry(static_cast(sourceModel())->mapToSource(sourceIndex).row() ); } // ----------------------------------------------------------------------------- @@ -128,19 +137,31 @@ bool HistoryProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &) co return sourceModel()->rowCount() - sourceRow <= mMaxDisplayedEntries; } +bool HistoryProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const{ + if( !sourceModel()) + return false; + auto a = sourceModel()->data(left).value(); + auto b = sourceModel()->data(right).value(); + return a["receivedTimestamp"] > b["receivedTimestamp"]; + } + // ----------------------------------------------------------------------------- void HistoryProxyModel::reload () { mMaxDisplayedEntries = EntriesChunkSize; - auto model = CoreManager::getInstance()->getHistoryModel(); + //auto model = CoreManager::getInstance()->getHistoryModel(); //model->reload(); - static_cast(sourceModel())->setSourceModel(model); + static_cast(sourceModel())->setSourceModel(new HistoryModel(mCallHistoryModel)); + invalidate(); } void HistoryProxyModel::resetMessageCount(){ + static_cast(static_cast(sourceModel())->sourceModel())->resetMessageCount(); +/* auto model = CoreManager::getInstance()->getHistoryModel(); if( model){ model->resetMessageCount(); } + */ } // ----------------------------------------------------------------------------- diff --git a/linphone-app/src/components/history/HistoryProxyModel.hpp b/linphone-app/src/components/history/HistoryProxyModel.hpp index a5b7e9c80..db6797f3e 100644 --- a/linphone-app/src/components/history/HistoryProxyModel.hpp +++ b/linphone-app/src/components/history/HistoryProxyModel.hpp @@ -32,11 +32,14 @@ class QWindow; class HistoryProxyModel : public QSortFilterProxyModel { class HistoryModelFilter; - Q_OBJECT; + Q_OBJECT public: + Q_PROPERTY(CallHistoryModel *callHistoryModel MEMBER mCallHistoryModel WRITE setCallHistoryModel NOTIFY callHistoryModelChanged) HistoryProxyModel (QObject *parent = Q_NULLPTR); + void setCallHistoryModel(CallHistoryModel * model); + Q_INVOKABLE void loadMoreEntries (); Q_INVOKABLE void setEntryTypeFilter (HistoryModel::EntryType type = HistoryModel::EntryType::CallEntry); Q_INVOKABLE void removeEntry (int id); @@ -48,17 +51,18 @@ public: Q_INVOKABLE void reload(); signals: - void moreEntriesLoaded (int n); - void entryTypeFilterChanged (HistoryModel::EntryType type); + void callHistoryModelChanged(); protected: bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override; + bool lessThan (const QModelIndex &left, const QModelIndex &right) const override; private: void handleIsActiveChanged (QWindow *window); + CallHistoryModel * mCallHistoryModel = nullptr; int mMaxDisplayedEntries = EntriesChunkSize; diff --git a/linphone-app/src/components/other/colors/ColorListModel.hpp b/linphone-app/src/components/other/colors/ColorListModel.hpp index eb6612290..fa9713089 100644 --- a/linphone-app/src/components/other/colors/ColorListModel.hpp +++ b/linphone-app/src/components/other/colors/ColorListModel.hpp @@ -155,6 +155,8 @@ class ColorListModel : public ProxyListModel { ADD_COLOR("progress_bg", "black", "Background of round progress bar") ADD_COLOR("progress_remaining_fg", "white", "Remaining progression color") + ADD_COLOR("timeline_header_bg", "#E1E4E7", "Header Timeline background") + ADD_COLOR("timeline_bg_1", "#EFF0F2", "Timeline background color 1") ADD_COLOR("timeline_bg_2", "#FFFFFF", "Timeline background color 2") diff --git a/linphone-app/src/components/other/images/ImageModel.cpp b/linphone-app/src/components/other/images/ImageModel.cpp index 53aad3eab..9c4db2965 100644 --- a/linphone-app/src/components/other/images/ImageModel.cpp +++ b/linphone-app/src/components/other/images/ImageModel.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "app/App.hpp" #include "utils/Utils.hpp" @@ -88,22 +89,36 @@ QImage ImageModel::createThumbnail(const QString& path, QImage originalImage){ QExifImageHeader exifImageHeader; if (exifImageHeader.loadFromJpeg(path)) rotation = int(exifImageHeader.value(QExifImageHeader::ImageTag::Orientation).toShort()); - // Fill with color to replace transparency with white color instead of black (default). - QImage image(originalImage.size(), originalImage.format()); - image.fill(QColor(Qt::white).rgb()); - QPainter painter(&image); - painter.drawImage(0, 0, originalImage); - //-------------------- - double factor = image.width() / (double)image.height(); + double factor = originalImage.width() / (double)originalImage.height(); Qt::AspectRatioMode aspectRatio = Qt::KeepAspectRatio; if(factor < 0.2 || factor > 5) aspectRatio = Qt::KeepAspectRatioByExpanding; - thumbnail = image.scaled( - Constants::ThumbnailImageFileWidth, Constants::ThumbnailImageFileHeight, - aspectRatio , Qt::SmoothTransformation - ); - if(aspectRatio == Qt::KeepAspectRatioByExpanding) - thumbnail = thumbnail.copy(0,0,Constants::ThumbnailImageFileWidth, Constants::ThumbnailImageFileHeight); + QImageReader reader(path); + if(reader.format() == "svg"){ + QSvgRenderer svgRenderer(path); + if(svgRenderer.isValid()){ + thumbnail = QImage(Constants::ThumbnailImageFileWidth, Constants::ThumbnailImageFileHeight, originalImage.format()); + thumbnail.fill(QColor(Qt::transparent)); + QPainter painter(&thumbnail); + svgRenderer.setAspectRatioMode(aspectRatio); + svgRenderer.render(&painter); + } + } + if(thumbnail.isNull()){ + QImage image(originalImage.size(), originalImage.format()); + // Fill with color to replace transparency with white color instead of black (default). + image.fill(QColor(Qt::white).rgb()); + QPainter painter(&image); + painter.drawImage(0, 0, originalImage); + //-------------------- + thumbnail = image.scaled( + Constants::ThumbnailImageFileWidth, Constants::ThumbnailImageFileHeight, + aspectRatio , Qt::SmoothTransformation + ); + if(aspectRatio == Qt::KeepAspectRatioByExpanding)// Cut + thumbnail = thumbnail.copy(0,0,Constants::ThumbnailImageFileWidth, Constants::ThumbnailImageFileHeight); + } + if (rotation != 0) { QTransform transform; diff --git a/linphone-app/src/components/settings/AccountSettingsModel.cpp b/linphone-app/src/components/settings/AccountSettingsModel.cpp index 177ae62fa..f3e257e53 100644 --- a/linphone-app/src/components/settings/AccountSettingsModel.cpp +++ b/linphone-app/src/components/settings/AccountSettingsModel.cpp @@ -58,10 +58,9 @@ static inline AccountSettingsModel::RegistrationState mapLinphoneRegistrationSta AccountSettingsModel::AccountSettingsModel (QObject *parent) : QObject(parent) { CoreManager *coreManager = CoreManager::getInstance(); - QObject::connect( - coreManager->getHandlers().get(), &CoreHandlers::registrationStateChanged, - this, &AccountSettingsModel::handleRegistrationStateChanged - ); + QObject::connect(coreManager->getHandlers().get(), &CoreHandlers::registrationStateChanged, this, &AccountSettingsModel::handleRegistrationStateChanged); + QObject::connect(coreManager, &CoreManager::callLogsCountChanged, this, &AccountSettingsModel::missedCallsCountChanged); + //QObject::connect(coreManager, &CoreManager::eventCountChanged, this, [this]() { emit accountSettingsUpdated(); }); QObject::connect(this, &AccountSettingsModel::accountSettingsUpdated, this, &AccountSettingsModel::usernameChanged); @@ -75,6 +74,8 @@ AccountSettingsModel::AccountSettingsModel (QObject *parent) : QObject(parent) { QObject::connect(this, &AccountSettingsModel::accountSettingsUpdated, this, &AccountSettingsModel::primaryUsernameChanged); QObject::connect(this, &AccountSettingsModel::accountSettingsUpdated, this, &AccountSettingsModel::primarySipAddressChanged); QObject::connect(this, &AccountSettingsModel::accountSettingsUpdated, this, &AccountSettingsModel::accountsChanged); + QObject::connect(this, &AccountSettingsModel::accountsChanged, this, &AccountSettingsModel::missedCallsCountChanged); + QObject::connect(this, &AccountSettingsModel::accountsChanged, this, &AccountSettingsModel::unreadMessagesCountChanged); mSelectedAccount = coreManager->getCore()->getDefaultAccount(); } @@ -251,6 +252,19 @@ bool AccountSettingsModel::getUseInternationalPrefixForCallsAndChats() const{ return false; } +int AccountSettingsModel::getMissedCallsCount() const { + shared_ptr core = CoreManager::getInstance()->getCore(); + shared_ptr account = core->getDefaultAccount(); + return account ? account->getMissedCallsCount() : core->getMissedCallsCount(); +} + +int AccountSettingsModel::getUnreadMessagesCount() const { + shared_ptr core = CoreManager::getInstance()->getCore(); + shared_ptr account = core->getDefaultAccount(); + return account ? account->getUnreadChatMessageCount() : core->getUnreadChatMessageCount(); +} + + void AccountSettingsModel::setDefaultAccount (const shared_ptr &account) { shared_ptr core = CoreManager::getInstance()->getCore(); if (mSelectedAccount != account) { @@ -602,8 +616,8 @@ QVariantList AccountSettingsModel::getAccounts () const { QVariantMap account; account["sipAddress"] = Utils::coreStringToAppString(core->createPrimaryContactParsed()->asStringUriOnly()); account["fullSipAddress"] = Utils::coreStringToAppString(core->createPrimaryContactParsed()->asString()); - account["unreadMessageCount"] = settingsModel->getStandardChatEnabled() || settingsModel->getSecureChatEnabled() ? core->getUnreadChatMessageCountFromLocal(core->createPrimaryContactParsed()) : 0; - account["missedCallCount"] = CoreManager::getInstance()->getMissedCallCountFromLocal(account["sipAddress"].toString()); + account["unreadMessageCount"] = settingsModel->getStandardChatEnabled() || settingsModel->getSecureChatEnabled() ? core->getUnreadChatMessageCount() : 0; + account["missedCallCount"] = core->getMissedCallsCount(); account["account"].setValue(nullptr); accounts << account; } @@ -615,7 +629,7 @@ QVariantList AccountSettingsModel::getAccounts () const { accountMap["fullSipAddress"] = Utils::coreStringToAppString(params->getIdentityAddress()->asString()); accountMap["account"].setValue(account); accountMap["unreadMessageCount"] = settingsModel->getStandardChatEnabled() || settingsModel->getSecureChatEnabled() ? account->getUnreadChatMessageCount() : 0; - accountMap["missedCallCount"] = CoreManager::getInstance()->getMissedCallCountFromLocal(accountMap["sipAddress"].toString()); + accountMap["missedCallCount"] = account->getMissedCallsCount(); accountMap["registerEnabled"] = params->registerEnabled(); accounts << accountMap; } diff --git a/linphone-app/src/components/settings/AccountSettingsModel.hpp b/linphone-app/src/components/settings/AccountSettingsModel.hpp index 2e9e46d2a..847041541 100644 --- a/linphone-app/src/components/settings/AccountSettingsModel.hpp +++ b/linphone-app/src/components/settings/AccountSettingsModel.hpp @@ -51,6 +51,9 @@ class AccountSettingsModel : public QObject { Q_PROPERTY(QString defaultAccountDomain READ getDefaultAccountDomain NOTIFY defaultAccountChanged) Q_PROPERTY(QVariantList accounts READ getAccounts NOTIFY accountsChanged) + Q_PROPERTY(int missedCallsCount READ getMissedCallsCount NOTIFY missedCallsCountChanged) + Q_PROPERTY(int unreadMessagesCount READ getUnreadMessagesCount NOTIFY unreadMessagesCountChanged) + public: enum RegistrationState { @@ -80,6 +83,8 @@ public: QString getVideoConferenceUri() const; QString getLimeServerUrl() const; bool getUseInternationalPrefixForCallsAndChats() const; + int getMissedCallsCount() const; + int getUnreadMessagesCount() const; Q_INVOKABLE void setDefaultAccount (const std::shared_ptr &account = nullptr); Q_INVOKABLE void setDefaultAccountFromSipAddress (const QString &sipAddress); @@ -120,6 +125,8 @@ signals: void defaultAccountChanged(); void publishPresenceChanged(); void defaultRegistrationChanged(); + void missedCallsCountChanged(); + void unreadMessagesCountChanged(); private: QString getUsername () const; diff --git a/linphone-app/src/components/sip-addresses/SipAddressObserver.cpp b/linphone-app/src/components/sip-addresses/SipAddressObserver.cpp index 2dbb3269e..4a124e559 100644 --- a/linphone-app/src/components/sip-addresses/SipAddressObserver.cpp +++ b/linphone-app/src/components/sip-addresses/SipAddressObserver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2020 Belledonne Communications SARL. + * Copyright (c) 2010-2023 Belledonne Communications SARL. * * This file is part of linphone-desktop * (see https://www.linphone.org). @@ -50,11 +50,3 @@ void SipAddressObserver::setPresenceTimestamp(const QDateTime &presenceTimestamp mPresenceTimestamp = presenceTimestamp; emit presenceTimestampChanged(presenceTimestamp); } - -void SipAddressObserver::setUnreadMessageCount (int unreadMessageCount) { - if (unreadMessageCount == mUnreadMessageCount) - return; - - mUnreadMessageCount = unreadMessageCount; - emit unreadMessageCountChanged(unreadMessageCount); -} diff --git a/linphone-app/src/components/sip-addresses/SipAddressObserver.hpp b/linphone-app/src/components/sip-addresses/SipAddressObserver.hpp index f37cc93f1..ce8e10ff3 100644 --- a/linphone-app/src/components/sip-addresses/SipAddressObserver.hpp +++ b/linphone-app/src/components/sip-addresses/SipAddressObserver.hpp @@ -41,7 +41,6 @@ class SipAddressObserver : public QObject { Q_PROPERTY(ContactModel *contact READ getContact NOTIFY contactChanged); Q_PROPERTY(Presence::PresenceStatus presenceStatus READ getPresenceStatus NOTIFY presenceStatusChanged); Q_PROPERTY(QDateTime presenceTimestamp READ getPresenceTimestamp NOTIFY presenceTimestampChanged); - Q_PROPERTY(int unreadMessageCount READ getUnreadMessageCount NOTIFY unreadMessageCountChanged); Q_PROPERTY(bool isOneToOne MEMBER isOneToOne CONSTANT); Q_PROPERTY(bool haveEncryption MEMBER haveEncryption CONSTANT); @@ -57,7 +56,6 @@ signals: void contactChanged (QSharedPointer); void presenceStatusChanged (const Presence::PresenceStatus &presenceStatus); void presenceTimestampChanged (const QDateTime &presenceTimestamp); - void unreadMessageCountChanged (int unreadMessageCount); private: QString getPeerAddress () const { @@ -89,20 +87,12 @@ private: void setPresenceTimestamp (const QDateTime &presenceTimestamp); // --------------------------------------------------------------------------- - - int getUnreadMessageCount () const { - return mUnreadMessageCount; - } - - void setUnreadMessageCount (int unreadMessageCount); - QString mPeerAddress; QString mLocalAddress; QSharedPointer mContact; Presence::PresenceStatus mPresenceStatus = Presence::PresenceStatus::Offline; QDateTime mPresenceTimestamp; - int mUnreadMessageCount = 0; }; Q_DECLARE_METATYPE(SipAddressObserver *); diff --git a/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp b/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp index 502700bb1..4bd24c2db 100644 --- a/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp +++ b/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2020 Belledonne Communications SARL. + * Copyright (c) 2010-2023 Belledonne Communications SARL. * * This file is part of linphone-desktop * (see https://www.linphone.org). @@ -177,10 +177,6 @@ SipAddressObserver *SipAddressesModel::getSipAddressObserver (const QString &pee model->setContact(it->contact); model->setPresenceStatus(it->presenceStatus); model->setPresenceTimestamp(it->presenceTimestamp); - - auto it2 = it->localAddressToConferenceEntry.find(cleanedLocalAddress); - if (it2 != it->localAddressToConferenceEntry.end()) - model->setUnreadMessageCount(it2->unreadMessageCount+it2->missedCallCount); } mObservers.insert(cleanedPeerAddress, model); @@ -327,17 +323,11 @@ void SipAddressesModel::handleChatRoomModelCreated (const QSharedPointer contact) { @@ -485,38 +475,6 @@ void SipAddressesModel::handleLastEntryRemoved (ChatRoomModel *chatRoomModel) { emit dataChanged(index(row, 0), index(row, 0)); } -void SipAddressesModel::handleAllCallCountReset () { - for( auto peer = mPeerAddressToSipAddressEntry.begin() ; peer != mPeerAddressToSipAddressEntry.end() ; ++peer){ - for( auto local = peer->localAddressToConferenceEntry.begin() ; local != peer->localAddressToConferenceEntry.end() ; ++local){ - local->missedCallCount = 0; - updateObservers(peer.key(), local.key(), local->unreadMessageCount, local->missedCallCount); - } - int row = mRefs.indexOf(&(*peer)); - emit dataChanged(index(row, 0), index(row, 0)); - } -} - -void SipAddressesModel::handleMessageCountReset (ChatRoomModel *chatRoomModel) { - const QString &peerAddress = Utils::cleanSipAddress(chatRoomModel->getPeerAddress()); - auto it = mPeerAddressToSipAddressEntry.find(peerAddress); - if (it == mPeerAddressToSipAddressEntry.end()) - return; - - const QString &localAddress = Utils::cleanSipAddress(chatRoomModel->getLocalAddress()); - auto it2 = it->localAddressToConferenceEntry.find(localAddress); - if (it2 == it->localAddressToConferenceEntry.end()) - return; - - it2->unreadMessageCount = 0; - it2->missedCallCount = 0; - - int row = mRefs.indexOf(&(*it)); - Q_ASSERT(row != -1); - emit dataChanged(index(row, 0), index(row, 0)); - - updateObservers(peerAddress, localAddress, 0, 0); -} - void SipAddressesModel::handleMessageSent (const shared_ptr &message) { if(message->getChatRoom() && message->getChatRoom()->getPeerAddress()){ auto lPeerAddress = message->getChatRoom()->getPeerAddress(); @@ -573,12 +531,10 @@ void SipAddressesModel::addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, conferenceEntry.timestamp = callLog->getStatus() == linphone::Call::Status::Success ? QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000) : QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000); - conferenceEntry.missedCallCount = CoreManager::getInstance()->getMissedCallCount(peerAddress, localAddress); QString oldDisplayName = sipAddressEntry.displayNames.get(); sipAddressEntry.displayNames.updateFromCall(lPeerAddress); if(oldDisplayName != sipAddressEntry.displayNames.get()) emit CoreManager::getInstance()->getContactsListModel()->contactUpdated(nullptr); - updateObservers(sipAddressEntry.sipAddress, localAddress, conferenceEntry.unreadMessageCount,conferenceEntry.missedCallCount); } void SipAddressesModel::addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, const shared_ptr &message) { @@ -595,10 +551,7 @@ void SipAddressesModel::addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, ConferenceEntry &conferenceEntry = sipAddressEntry.localAddressToConferenceEntry[localAddress]; conferenceEntry.timestamp = QDateTime::fromMSecsSinceEpoch(message->getTime() * 1000); - conferenceEntry.unreadMessageCount = count ; - conferenceEntry.missedCallCount = CoreManager::getInstance()->getMissedCallCount(peerAddress, localAddress); sipAddressEntry.displayNames.updateFromChatMessage(lPeerAddress); - updateObservers(sipAddressEntry.sipAddress, localAddress, count,conferenceEntry.missedCallCount); } template @@ -685,8 +638,6 @@ void SipAddressesModel::initSipAddressesFromChat () { QString localAddress(Utils::cleanSipAddress(Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly()))); getSipAddressEntry(peerAddress, lPeerAddress)->localAddressToConferenceEntry[localAddress] = { - chatRoom->getUnreadMessagesCount(), - CoreManager::getInstance()->getMissedCallCount(peerAddress, localAddress), false, QDateTime::fromMSecsSinceEpoch(lastMessage->getTime() * 1000) }; @@ -716,7 +667,7 @@ void SipAddressesModel::initSipAddressesFromCalls () { auto &localToConferenceEntry = sipAddressEntry->localAddressToConferenceEntry; auto it = localToConferenceEntry.find(localAddress); if (it == localToConferenceEntry.end()) { - localToConferenceEntry[localAddress] = { 0,0, false, move(timestamp) }; + localToConferenceEntry[localAddress] = { false, move(timestamp) }; sipAddressEntry->displayNames.mFromCallLogs = QString::fromStdString(callLog->getRemoteAddress()->getDisplayName()); }else if (it->timestamp.isNull() || timestamp > it->timestamp){ it->timestamp = move(timestamp); @@ -747,13 +698,4 @@ void SipAddressesModel::updateObservers (const QString &sipAddress, const Presen observer->setPresenceStatus(presenceStatus); observer->setPresenceTimestamp(presenceTimestamp); } -} - -void SipAddressesModel::updateObservers (const QString &peerAddress, const QString &localAddress, int messageCount, int missedCallCount) { - for (auto &observer : mObservers.values(peerAddress)) { - if (observer->getLocalAddress() == localAddress) { - observer->setUnreadMessageCount(messageCount+missedCallCount); - return; - } - } -} +} \ No newline at end of file diff --git a/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp b/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp index 7b152fb7c..76635d7ec 100644 --- a/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp +++ b/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2020 Belledonne Communications SARL. + * Copyright (c) 2010-2023 Belledonne Communications SARL. * * This file is part of linphone-desktop * (see https://www.linphone.org). @@ -37,12 +37,10 @@ class CoreHandlers; class HistoryModel; class SipAddressesModel : public QAbstractListModel { - Q_OBJECT; + Q_OBJECT public: struct ConferenceEntry { - int unreadMessageCount; - int missedCallCount; bool isComposing; QDateTime timestamp; }; @@ -81,8 +79,6 @@ public: QHash roleNames () const override; QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; - //Q_PROPERTY(QList resultExceptions READ getResultExceptions WRITE setResultExceptions NOTIFY resultExceptionsChanged) - Q_INVOKABLE QVariantMap find (const QString &sipAddress) const; Q_INVOKABLE ContactModel *mapSipAddressToContact (const QString &sipAddress) const; Q_INVOKABLE SipAddressObserver *getSipAddressObserver (const QString &peerAddress, const QString &localAddress); @@ -113,9 +109,6 @@ public: signals: void sipAddressReset();// The model has been reset -public slots: - void handleAllCallCountReset (); - private: bool removeRow (int row, const QModelIndex &parent = QModelIndex()); bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; @@ -140,8 +133,6 @@ private: void handleAllEntriesRemoved (ChatRoomModel *chatRoomModel); void handleLastEntryRemoved (ChatRoomModel *chatRoomModel); - void handleMessageCountReset (ChatRoomModel *chatRoomModel); - void handleMessageSent (const std::shared_ptr &message); void handleIsComposingChanged (const std::shared_ptr &chatRoom); @@ -166,7 +157,6 @@ private: void updateObservers (const QString &sipAddress, QSharedPointer contact); void updateObservers (const QString &sipAddress, const Presence::PresenceStatus &presenceStatus, const QDateTime &presenceTimestamp); - void updateObservers (const QString &peerAddress, const QString &localAddress, int messageCount, int missedCallCount); // --------------------------------------------------------------------------- diff --git a/linphone-app/src/components/timeline/TimelineListModel.cpp b/linphone-app/src/components/timeline/TimelineListModel.cpp index 0680b6ff2..8d5f96e2f 100644 --- a/linphone-app/src/components/timeline/TimelineListModel.cpp +++ b/linphone-app/src/components/timeline/TimelineListModel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2020 Belledonne Communications SARL. + * Copyright (c) 2010-2023 Belledonne Communications SARL. * * This file is part of linphone-desktop * (see https://www.linphone.org). @@ -25,8 +25,6 @@ #include "components/calls/CallsListModel.hpp" #include "components/settings/AccountSettingsModel.hpp" #include "components/settings/SettingsModel.hpp" -#include "components/sip-addresses/SipAddressesModel.hpp" -#include "components/contacts/ContactsListModel.hpp" #include "utils/Utils.hpp" @@ -327,7 +325,6 @@ void TimelineListModel::updateTimelines () { qInfo() << "Timelines adding :" << stepsTimer.restart() << "ms for " << models.size() << " new timelines"; add(models); qInfo() << "Timelines adding GUI :" << stepsTimer.restart() << "ms."; - CoreManager::getInstance()->updateUnreadMessageCount(); qInfo() << "Timelines initialized in:" << timer.elapsed() << "ms."; } @@ -460,7 +457,6 @@ void TimelineListModel::onCallCreated(const std::shared_ptr &cal } if(!found){// Create a default chat room QVariantList participants; - //participants << Utils::coreStringToAppString(callLog->getRemoteAddress()->asStringUriOnly()); // This allow chatting to a specific device but the current design is not adapted to show them auto remoteAddress = callLog->getRemoteAddress()->clone(); remoteAddress->clean(); participants << Utils::coreStringToAppString(remoteAddress->asStringUriOnly()); diff --git a/linphone-app/src/components/timeline/TimelineListModel.hpp b/linphone-app/src/components/timeline/TimelineListModel.hpp index 6a84005cd..1c10da79f 100644 --- a/linphone-app/src/components/timeline/TimelineListModel.hpp +++ b/linphone-app/src/components/timeline/TimelineListModel.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2020 Belledonne Communications SARL. + * Copyright (c) 2010-2023 Belledonne Communications SARL. * * This file is part of linphone-desktop * (see https://www.linphone.org). diff --git a/linphone-app/src/components/timeline/TimelineProxyModel.cpp b/linphone-app/src/components/timeline/TimelineProxyModel.cpp index bc64484b2..d12bf4d1c 100644 --- a/linphone-app/src/components/timeline/TimelineProxyModel.cpp +++ b/linphone-app/src/components/timeline/TimelineProxyModel.cpp @@ -61,6 +61,13 @@ void TimelineProxyModel::setFilterText(const QString& text){ emit filterTextChanged(); } } + +void TimelineProxyModel::setMode(const TimelineMode& mode) { + if(mMode != mode) { + mMode = mode; + emit modeChanged(); + } +} TimelineProxyModel::TimelineListSource TimelineProxyModel::getListSource() const{ return mListSource; @@ -115,15 +122,12 @@ bool TimelineProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &sou return false; bool show = (mFilterFlags==0);// Show all at 0 (no hide all) bool isGroup = timeline->getChatRoomModel()->isGroupEnabled(); - bool isEphemeral = timeline->getChatRoomModel()->isEphemeralEnabled(); if( mFilterFlags > 0) { - show = !(( ( (mFilterFlags & TimelineFilter::SimpleChatRoom) == TimelineFilter::SimpleChatRoom) && isGroup) - || ( ( (mFilterFlags & TimelineFilter::SecureChatRoom) == TimelineFilter::SecureChatRoom) && !haveEncryption) - || ( ( (mFilterFlags & TimelineFilter::GroupChatRoom) == TimelineFilter::GroupChatRoom) && !isGroup) - || ( ( (mFilterFlags & TimelineFilter::StandardChatRoom) == TimelineFilter::StandardChatRoom) && haveEncryption) - || ( ( (mFilterFlags & TimelineFilter::EphemeralChatRoom) == TimelineFilter::EphemeralChatRoom) && !isEphemeral) - || ( ( (mFilterFlags & TimelineFilter::NoEphemeralChatRoom) == TimelineFilter::NoEphemeralChatRoom) && isEphemeral)); + show = !( + ( ((mFilterFlags & TimelineFilter::SecureChatRoom) == TimelineFilter::SecureChatRoom) && !haveEncryption) + || ( ((mFilterFlags & TimelineFilter::GroupChatRoom) == TimelineFilter::GroupChatRoom) && !isGroup) + ); } if(show && mFilterText != ""){ @@ -142,8 +146,8 @@ bool TimelineProxyModel::lessThan (const QModelIndex &left, const QModelIndex &r return false; const TimelineModel* a = sourceModel()->data(left).value(); const TimelineModel* b = sourceModel()->data(right).value(); - bool aHaveUnread = a->getChatRoomModel()->getAllUnreadCount() > 0; - bool bHaveUnread = b->getChatRoomModel()->getAllUnreadCount() > 0; + bool aHaveUnread = a->getChatRoomModel()->getUnreadMessagesCount() > 0; + bool bHaveUnread = b->getChatRoomModel()->getUnreadMessagesCount() > 0; return (aHaveUnread && !bHaveUnread) || (aHaveUnread == bHaveUnread && a->getChatRoomModel()->mLastUpdateTime > b->getChatRoomModel()->mLastUpdateTime); } diff --git a/linphone-app/src/components/timeline/TimelineProxyModel.hpp b/linphone-app/src/components/timeline/TimelineProxyModel.hpp index b350e0de8..f0bf1a273 100644 --- a/linphone-app/src/components/timeline/TimelineProxyModel.hpp +++ b/linphone-app/src/components/timeline/TimelineProxyModel.hpp @@ -34,18 +34,19 @@ class TimelineProxyModel : public QSortFilterProxyModel { public: enum TimelineFilter { - StandardChatRoom=1, - SecureChatRoom=2, - SimpleChatRoom=4, - GroupChatRoom=8, - EphemeralChatRoom=16, - NoEphemeralChatRoom=32, - + SecureChatRoom = 1, + GroupChatRoom = 2, AllChatRooms = 0 }; Q_ENUM(TimelineFilter) - enum TimelineListSource{ + enum TimelineMode { + Chats, + Calls + }; + Q_ENUM(TimelineMode) + + enum TimelineListSource{ Undefined, Main, // Timeline list comes from the singleton stored in CoreManager. Copy // Timeline list is created from Main but have no attach to the main list (aside of root items). @@ -59,10 +60,12 @@ public: Q_PROPERTY(int filterFlags MEMBER mFilterFlags WRITE setFilterFlags NOTIFY filterFlagsChanged) Q_PROPERTY(QString filterText MEMBER mFilterText WRITE setFilterText NOTIFY filterTextChanged) Q_PROPERTY(int count READ rowCount NOTIFY countChanged) + Q_PROPERTY(TimelineMode mode MEMBER mMode WRITE setMode NOTIFY modeChanged) Q_INVOKABLE void unselectAll(); Q_INVOKABLE void setFilterFlags(const int& filterFlags); Q_INVOKABLE void setFilterText(const QString& text); + Q_INVOKABLE void setMode(const TimelineMode& mode); TimelineListSource getListSource() const; void setListSource(const TimelineListSource& source); @@ -74,6 +77,7 @@ signals: void filterFlagsChanged(); void filterTextChanged(); void listSourceChanged(); + void modeChanged(); protected: @@ -87,6 +91,7 @@ protected: private: int mFilterFlags = 0; QString mFilterText; + TimelineMode mMode = Chats; TimelineListSource mListSource = Undefined; }; diff --git a/linphone-app/src/utils/Utils.cpp b/linphone-app/src/utils/Utils.cpp index f252179b9..f4b829154 100644 --- a/linphone-app/src/utils/Utils.cpp +++ b/linphone-app/src/utils/Utils.cpp @@ -119,11 +119,11 @@ QDateTime Utils::getOffsettedUTC(const QDateTime& date){ return utc; } -QString Utils::toDateTimeString(QDateTime date){ +QString Utils::toDateTimeString(QDateTime date, const QString& format){ if(date.date() == QDate::currentDate()) return toTimeString(date); else{ - return getOffsettedUTC(date).toString("yyyy/MM/dd hh:mm:ss"); + return getOffsettedUTC(date).toString(format); } } @@ -223,7 +223,8 @@ bool Utils::isGreatherThan(const QDate& d1, const QDate& d2) { //-------------------------------------------------------------------------------------- QString Utils::getDisplayName(const QString& address){ - return getDisplayName(interpretUrl(address)); + QString displayName = getDisplayName(interpretUrl(address)); + return displayName.isEmpty() ? address : displayName; } QString Utils::getInitials(const QString& username){ diff --git a/linphone-app/src/utils/Utils.hpp b/linphone-app/src/utils/Utils.hpp index 61834890e..547a3801b 100644 --- a/linphone-app/src/utils/Utils.hpp +++ b/linphone-app/src/utils/Utils.hpp @@ -68,7 +68,7 @@ public: //***** DATE TIME Q_INVOKABLE static QDateTime addMinutes(QDateTime date, const int& min); static QDateTime getOffsettedUTC(const QDateTime& date); - Q_INVOKABLE static QString toDateTimeString(QDateTime date); + Q_INVOKABLE static QString toDateTimeString(QDateTime date, const QString& format = "yyyy/MM/dd hh:mm:ss"); Q_INVOKABLE static QString toTimeString(QDateTime date, const QString& format = "hh:mm:ss"); Q_INVOKABLE static QString toDateString(QDateTime date, const QString& format = ""); Q_INVOKABLE static QString toDateString(QDate date, const QString& format = ""); diff --git a/linphone-app/ui/modules/Common/Image/Icon.qml b/linphone-app/ui/modules/Common/Image/Icon.qml index bc9b74b95..0606e45c2 100644 --- a/linphone-app/ui/modules/Common/Image/Icon.qml +++ b/linphone-app/ui/modules/Common/Image/Icon.qml @@ -30,7 +30,7 @@ Item { image.colorOverwriteEnabled = false height: iconHeight > 0 ? iconHeight : iconSize width: iconWidth > 0 ? iconWidth : iconSize - + visible: icon != '' Image { id:image anchors.fill: parent diff --git a/linphone-app/ui/modules/Common/Menus/Menu.qml b/linphone-app/ui/modules/Common/Menus/Menu.qml index 71651a748..8dc575919 100644 --- a/linphone-app/ui/modules/Common/Menus/Menu.qml +++ b/linphone-app/ui/modules/Common/Menus/Menu.qml @@ -9,8 +9,10 @@ import Common.Styles 1.0 Controls.Menu { id: menu property var menuStyle : MenuStyle.normal + property alias radius: brackgroundArea.radius width: menuStyle.width ? menuStyle.width : parent.width background: Rectangle { + id: brackgroundArea implicitWidth: menu.width color: menuStyle.colorModel.color radius: menuStyle.radius diff --git a/linphone-app/ui/modules/Common/Menus/MenuItem.qml b/linphone-app/ui/modules/Common/Menus/MenuItem.qml index 4d07f3fc6..91e301dad 100644 --- a/linphone-app/ui/modules/Common/Menus/MenuItem.qml +++ b/linphone-app/ui/modules/Common/Menus/MenuItem.qml @@ -17,18 +17,22 @@ Controls.MenuItem { property alias iconSizeMenu: iconArea.iconSize property alias iconOverwriteColorMenu: iconArea.overwriteColor property alias iconLayoutDirection : rowArea.layoutDirection + property alias radius: backgroundArea.radius property var menuItemStyle : MenuItemStyle.normal onMenuItemStyleChanged: if(!menuItemStyle) menuItemStyle = MenuItemStyle.normal property alias textWeight : rowText.font.bold property int offsetTopMargin : 0 property int offsetBottomMargin : 0 + property bool displaySelection: true + property bool isTabBar: false height:visible?undefined:0 - Component.onCompleted: menu.width = Math.max(menu.width, implicitWidth) + Component.onCompleted: if(!isTabBar) menu.width = Math.max(menu.width, implicitWidth) - background: Rectangle { + background: Rectangle { + id: backgroundArea color: button.down ? menuItemStyle.background.color.pressed.color : ( @@ -40,7 +44,7 @@ Controls.MenuItem { } contentItem:RowLayout{ id:rowArea - spacing:10 + spacing: iconArea.icon? 10 : 0 Item{ Layout.fillHeight: true Layout.preferredWidth: iconArea.icon?height/rowText.lineCount:0 @@ -66,8 +70,8 @@ Controls.MenuItem { id:rowText Layout.fillWidth: true Layout.fillHeight: true - Layout.leftMargin:(iconLayoutDirection == Qt.LeftToRight ? 0 : menuItemStyle.leftMargin) - Layout.rightMargin:(iconLayoutDirection == Qt.LeftToRight ? menuItemStyle.rightMargin : 0) + Layout.leftMargin:(isTabBar || iconLayoutDirection == Qt.LeftToRight ? 0 : menuItemStyle.leftMargin) + (button.checkable ? CheckBoxTextStyle.size : 0) + Layout.rightMargin:(!isTabBar && iconLayoutDirection == Qt.LeftToRight ? menuItemStyle.rightMargin : 0) color: button.enabled ? (button.down ? menuItemStyle.text.color.pressed.color @@ -90,10 +94,55 @@ Controls.MenuItem { verticalAlignment: Text.AlignVCenter } } + indicator: Rectangle { + visible: button.checkable + border.color: button.down + ? CheckBoxTextStyle.color.pressed.color + : ( + button.hovered + ? CheckBoxTextStyle.color.hovered.color + : ( + button.checked + ? CheckBoxTextStyle.color.selected.color + : CheckBoxTextStyle.color.normal.color + ) + ) + + implicitHeight: CheckBoxTextStyle.size + implicitWidth: CheckBoxTextStyle.size + + radius: CheckBoxTextStyle.radius + + x: button.leftPadding + y: parent.height / 2 - height / 2 + + Rectangle { + color: button.down + ? CheckBoxTextStyle.color.pressed.color + : (button.hovered + ? CheckBoxTextStyle.color.hovered.color + : ( + button.checked + ? CheckBoxTextStyle.color.selected.color + : CheckBoxTextStyle.color.normal.color + ) + ) + + height: parent.height - y * 2 + width: parent.width - x * 2 + + radius: CheckBoxTextStyle.radius + visible: button.checked + + x: 4 // Fixed, no needed to use style file. + y: 4 // Same thing. + } + } hoverEnabled: true MouseArea{ anchors.fill:parent + visible: button.displaySelection propagateComposedEvents:true acceptedButtons: Qt.NoButton cursorShape: parent.hovered diff --git a/linphone-app/ui/modules/Common/Styles/Form/Buttons/SmallButtonStyle.qml b/linphone-app/ui/modules/Common/Styles/Form/Buttons/SmallButtonStyle.qml index 9f5e058ef..fa3db76d2 100644 --- a/linphone-app/ui/modules/Common/Styles/Form/Buttons/SmallButtonStyle.qml +++ b/linphone-app/ui/modules/Common/Styles/Form/Buttons/SmallButtonStyle.qml @@ -8,8 +8,8 @@ import ColorsList 1.0 QtObject { property string sectionName: 'SmallButton' - property int leftPadding: 5 - property int rightPadding: 5 + property int leftPadding: 10 + property int rightPadding: 10 property QtObject background: QtObject { property int height: 22 diff --git a/linphone-app/ui/modules/Linphone/Account/AccountStatus.qml b/linphone-app/ui/modules/Linphone/Account/AccountStatus.qml index b0cbb373e..e695a68b2 100644 --- a/linphone-app/ui/modules/Linphone/Account/AccountStatus.qml +++ b/linphone-app/ui/modules/Linphone/Account/AccountStatus.qml @@ -30,37 +30,44 @@ Item { ColumnLayout { anchors.fill:parent - spacing: AccountStatusStyle.verticalSpacing - + spacing: 0 + Item{ + Layout.fillHeight: true + Layout.fillWidth: true + } RowLayout { - Layout.preferredHeight: parent.height / 2 + Layout.fillHeight: false + Layout.maximumHeight: parent.height / 2 Layout.maximumWidth: parent.width - Layout.alignment: Qt.AlignBottom | Qt.AlignLeft + Layout.alignment: Qt.AlignLeft spacing: AccountStatusStyle.horizontalSpacing Item { - Layout.alignment: !subtitle.visible ? Qt.AlignVCenter | Qt.AlignLeft: Qt.AlignBottom | Qt.AlignLeft - Layout.bottomMargin: AccountStatusStyle.presenceLevel.bottomMargin - Layout.preferredHeight: AccountStatusStyle.presenceLevel.size - Layout.preferredWidth: AccountStatusStyle.presenceLevel.size - visible: !accountStatus.noAccountConfigured + Layout.preferredHeight: visible ? AccountStatusStyle.presenceLevel.size : 0 + Layout.preferredWidth: visible ? AccountStatusStyle.presenceLevel.size : 0 + visible: !accountStatus.noAccountConfigured && (isRegistrated || isProgressing || haveErrors) + property bool isRegistrated: AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateRegistered + property bool isProgressing: AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateInProgress + property bool haveErrors: AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateNotRegistered || AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateNoProxy PresenceLevel { id:presenceLevel anchors.fill:parent level: OwnPresenceModel.presenceStatus===Presence.Offline?Presence.White:( SettingsModel.rlsUriEnabled ? OwnPresenceModel.presenceLevel : Presence.Green) - visible: AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateRegistered + visible: parent.isRegistrated } BusyIndicator { + id: registrationProcessing anchors.fill:parent - running: AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateInProgress + running: parent.isProgressing color: AccountStatusStyle.busyColor.color } Icon { + id: registrationError iconSize: parent.width icon: 'generic_error' - visible: AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateNotRegistered || AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateNoProxy + visible: parent.haveErrors TooltipArea{ text : 'Not Registered' } @@ -70,50 +77,47 @@ Item { Text { id:username Layout.fillWidth: true - Layout.preferredHeight: accountStatus.noAccountConfigured ? -1 : parent.height / 2 - Layout.alignment: !subtitle.visible ? Qt.AlignVCenter | Qt.AlignLeft : Qt.AlignBottom | Qt.AlignLeft color: AccountStatusStyle.username.colorModel.color elide: Text.ElideRight font.bold: true font.pointSize: AccountStatusStyle.username.pointSize //: 'No account configured' : Status text when there is no configured account. text: accountStatus.noAccountConfigured ? qsTr('noAccount'): AccountSettingsModel.username - verticalAlignment: Text.AlignBottom wrapMode: Text.WordWrap maximumLineCount: 3 } Item { - Layout.alignment: !subtitle.visible ? Qt.AlignVCenter | Qt.AlignLeft: Qt.AlignBottom | Qt.AlignLeft - Layout.bottomMargin: 5 - Layout.preferredHeight: AccountStatusStyle.presenceLevel.size - Layout.preferredWidth: AccountStatusStyle.presenceLevel.size + Layout.preferredHeight: username.height + Layout.preferredWidth: messageCounter.width visible: !accountStatus.noAccountConfigured MessageCounter { id: messageCounter - anchors.fill: parent + anchors.centerIn: parent count: CoreManager.eventCount + iconSize: AccountStatusStyle.messageCounter.iconSize + pointSize: AccountStatusStyle.messageCounter.pointSize MouseArea{ anchors.fill: parent onClicked: window.setView('HistoryView') } } } - Item{//Spacer - Layout.fillHeight: true - Layout.fillWidth: true - } }//RowLayout Text { id: subtitle - Layout.preferredHeight:parent.height / 2 + Layout.fillHeight: true + Layout.maximumHeight:parent.height / 2 Layout.preferredWidth:parent.width visible: !accountStatus.noAccountConfigured && text != username.text color: AccountStatusStyle.sipAddress.colorModel.color elide: Text.ElideRight font.pointSize: AccountStatusStyle.sipAddress.pointSize text: UtilsCpp.toDisplayString(AccountSettingsModel.sipAddress, SettingsModel.sipDisplayMode) - verticalAlignment: Text.AlignTop + } + Item{ + Layout.fillHeight: true + Layout.fillWidth: true } }//ColumnLayout diff --git a/linphone-app/ui/modules/Linphone/Chat/Chat.js b/linphone-app/ui/modules/Linphone/Chat/Chat.js index cebffbe97..8693b064b 100644 --- a/linphone-app/ui/modules/Linphone/Chat/Chat.js +++ b/linphone-app/ui/modules/Linphone/Chat/Chat.js @@ -80,24 +80,22 @@ function sendMessage (text) { } function forwardMessage(chatRoomModel, chatEntry, chatRoomConfig){ - Qt.callLater(function (){// This avoid to detach virtual window while selecting chatroom/user. This can be the case when we got an address from the smartsearch bar that need to close itself before doing this stuff. - window.detachVirtualWindow() - window.attachVirtualWindow(Utils.buildCommonDialogUri('ConfirmDialog'), { - flat: true, - //: 'Do you want to forward this message?' : text to confirm to forward a message - descriptionText: ''+qsTr('confirmForward'), - }, function (status) { - if (status) { - if(!chatRoomModel) { - var chat = CallsListModel.createChatRoom( chatRoomConfig.subject, chatRoomConfig.haveEncryption, chatRoomConfig.participants, chatRoomConfig.toSelect) - if(chat) - chatRoomModel = chat.chatRoomModel - } - if(chatRoomModel){ - chatRoomModel.forwardMessage(chatEntry) - Linphone.TimelineListModel.select(chatRoomModel) - } + window.attachVirtualWindow(Utils.buildCommonDialogUri('ConfirmDialog'), { + flat: true, + //: 'Do you want to forward this message?' : text to confirm to forward a message + descriptionText: ''+qsTr('confirmForward'), + }, function (status) { + if (status) { + if(!chatRoomModel) { + var chat = Linphone.CallsListModel.createChatRoom( chatRoomConfig.subject, chatRoomConfig.haveEncryption, chatRoomConfig.participants, chatRoomConfig.toSelect) + if(chat) + chatRoomModel = chat.chatRoomModel } - }) - }) + if(chatRoomModel){ + chatRoomModel.forwardMessage(chatEntry) + Linphone.TimelineListModel.select(chatRoomModel) + } + window.detachVirtualWindow() + } + }) } diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatMenu.qml b/linphone-app/ui/modules/Linphone/Chat/ChatMenu.qml index ab7ab3407..6b9b791c0 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatMenu.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatMenu.qml @@ -46,33 +46,45 @@ Item { Menu { id: messageMenu menuStyle : MenuStyle.aux - MenuItem { + RowLayout{ id: reactionBar property font customFont : SettingsModel.emojiFont - menuItemStyle : MenuItemStyle.aux - contentItem: RowLayout{ - Layout.fillWidth: true - spacing:0 - Repeater{ + width: parent.width + height: 50 + anchors.margins: 10 // Let parent border displayed + spacing: 0 + + Repeater{ model: ConstantsCpp.reactionsList - delegate: Text{ + delegate: MenuItem{ + isTabBar: true Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - text: modelData - font.family: reactionBar.customFont.family - font.pointSize: Units.dp * reactionBar.customFont.pointSize * 2 - MouseArea{ + Layout.fillHeight: true + Layout.topMargin: 5 + Layout.bottomMargin: 5 + Layout.leftMargin: 2 + Layout.rightMargin: 2 + + radius: messageMenu.radius + down: chatMessageModel && modelData && modelData == chatMessageModel.myReaction + onTriggered: { + chatMessageModel.sendChatReaction(modelData) + messageMenu.close() + } + Text{ + id: bodyItem anchors.fill: parent - onClicked: { - chatMessageModel.sendChatReaction(modelData) - messageMenu.close() - } + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: modelData + font.family: reactionBar.customFont.family + font.pointSize: Units.dp * reactionBar.customFont.pointSize * 2 } } } - } + } + MenuItem { //: 'Copy all' : Text menu to copy all message text into clipboard text: (container.lastTextSelected == '' ? qsTr('menuCopyAll') diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatReactions.qml b/linphone-app/ui/modules/Linphone/Chat/ChatReactions.qml index f7934eb33..202a70866 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatReactions.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatReactions.qml @@ -4,6 +4,7 @@ import QtQml.Models 2.15 import Common 1.0 import Linphone 1.0 +import Linphone.Styles 1.0 import Units 1.0 @@ -23,6 +24,8 @@ Rectangle{ visible: reactionList.count > 0 property font customFont : SettingsModel.textMessageFont property font customEmojiFont : SettingsModel.emojiFont + border.width: 1 + border.color: ChatStyle.colorModel.color RowLayout{ id: reactionLayout diff --git a/linphone-app/ui/modules/Linphone/Contact/Contact.qml b/linphone-app/ui/modules/Linphone/Contact/Contact.qml index 191e0c26f..4a1d66452 100644 --- a/linphone-app/ui/modules/Linphone/Contact/Contact.qml +++ b/linphone-app/ui/modules/Linphone/Contact/Contact.qml @@ -19,6 +19,8 @@ Rectangle { // entry should have these functions : presenceStatus, sipAddress, username, avatar (image) property alias subtitleColor: description.subtitleColor + property alias subtitleIconData: description.subtitleIconData + property alias subtitleText: description.subtitleText property alias titleColor: description.titleColor property alias statusText : description.statusText property alias isDarkMode: avatar.isDarkMode @@ -76,7 +78,8 @@ Rectangle { ? '' : item.username : item.username - isOneToOne: entry==undefined || entry.isOneToOne==undefined || entry.isOneToOne + isOneToOne: entry==undefined || (entry.isOneToOne==undefined || entry.isOneToOne) && !entry.conferenceInfoModel || false + //Component.onCompleted: console.log(username + " / " +entry + " / " +entry.conferenceInfoModel) Icon{ anchors.top:parent.top diff --git a/linphone-app/ui/modules/Linphone/Contact/ContactDescription.qml b/linphone-app/ui/modules/Linphone/Contact/ContactDescription.qml index b2b12b25b..deb93a447 100644 --- a/linphone-app/ui/modules/Linphone/Contact/ContactDescription.qml +++ b/linphone-app/ui/modules/Linphone/Contact/ContactDescription.qml @@ -12,6 +12,7 @@ Column { id:mainItem property alias titleText: title.fullText property alias subtitleText: subtitle.fullText + property QtObject subtitleIconData property string sipAddress property alias statusText : status.text @@ -96,38 +97,51 @@ Column { anchors.right: parent.right height: (parent.height-parent.topPadding-parent.bottomPadding)/parent.visibleChildren.length visible: subtitle.fullText != '' && subtitle.fullText != title.fullText - TextEdit { - id:subtitle - property string fullText + RowLayout{ anchors.fill: parent - color: subtitleColor - font.family: SettingsModel.textMessageFont.family - font.weight: contactDescriptionStyle.subtitle.weight - font.pointSize: contactDescriptionStyle.subtitle.pointSize - textFormat: Text.RichText - horizontalAlignment: horizontalTextAlignment - verticalAlignment: (title.visible?Text.AlignTop:Text.AlignVCenter) - - text: UtilsCpp.encodeTextToQmlRichFormat(subtitleMetrics.elidedText, {noLink:true}) - - onActiveFocusChanged: deselect(); - readOnly: true - selectByMouse: true - Text{// Workaround to get implicitWidth from text without eliding - id: subtitleImplicitWidthWorkaround - text: subtitle.fullText - font.weight: subtitle.font.weight - font.pointSize: subtitle.font.pointSize - visible: false - textFormat: Text.RichText + spacing: 0 + Icon { + Layout.preferredHeight: subtitleMetrics.height + Layout.preferredWidth: visible ? subtitleMetrics.height : 0 + Layout.alignment: (title.visible? Qt.AlignTop : Qt.AlignVCenter) + icon: mainItem.subtitleIconData ? mainItem.subtitleIconData.icon : null + overwriteColor: mainItem.subtitleIconData ? mainItem.subtitleIconData.colorModel.color: '' + iconSize: visible ? HistoryStyle.entry.event.iconSize : 0 } - - TextMetrics { - id: subtitleMetrics - font: subtitle.font - text: subtitle.fullText - elideWidth: subtitle.width - elide: Qt.ElideRight + TextEdit { + id:subtitle + property string fullText + Layout.fillWidth: true + Layout.fillHeight: true + color: subtitleColor + font.family: SettingsModel.textMessageFont.family + font.weight: contactDescriptionStyle.subtitle.weight + font.pointSize: contactDescriptionStyle.subtitle.pointSize + textFormat: Text.RichText + horizontalAlignment: horizontalTextAlignment + verticalAlignment: (title.visible?Text.AlignTop:Text.AlignVCenter) + + text: UtilsCpp.encodeTextToQmlRichFormat(subtitleMetrics.elidedText, {noLink:true}) + + onActiveFocusChanged: deselect(); + readOnly: true + selectByMouse: true + Text{// Workaround to get implicitWidth from text without eliding + id: subtitleImplicitWidthWorkaround + text: subtitle.fullText + font.weight: subtitle.font.weight + font.pointSize: subtitle.font.pointSize + visible: false + textFormat: Text.RichText + } + + TextMetrics { + id: subtitleMetrics + font: subtitle.font + text: subtitle.fullText + elideWidth: subtitle.width + elide: Qt.ElideRight + } } } } diff --git a/linphone-app/ui/modules/Linphone/Contact/ContactMessageCounter.qml b/linphone-app/ui/modules/Linphone/Contact/ContactMessageCounter.qml index f52ae82f0..eaec9ede7 100644 --- a/linphone-app/ui/modules/Linphone/Contact/ContactMessageCounter.qml +++ b/linphone-app/ui/modules/Linphone/Contact/ContactMessageCounter.qml @@ -5,6 +5,7 @@ import Common 1.0 import Linphone 1.0 import Linphone.Styles 1.0 +import 'qrc:/ui/scripts/Utils/utils.js' as Utils // ============================================================================= Item { @@ -17,7 +18,7 @@ Item { implicitHeight: counterIcon.height + ContactMessageCounterStyle.verticalMargins * 2 implicitWidth: counterIcon.width + ContactMessageCounterStyle.horizontalMargins * 2 - visible: count > 0 ?(entry.unreadMessagesCount !== null || entry.missedCallsCount !== null) && displayCounter:false + visible: count > 0 ?(entry.unreadMessagesCount !== null) && displayCounter:false MessageCounter { id: counterIcon @@ -28,10 +29,10 @@ Item { icon: messageCounter.isComposing ? ('chat_is_composing_' + counterIcon.composingIndex) - : 'chat_count' + : '' visible: messageCounter.count > 0 || messageCounter.isComposing - count: messageCounter.entry?Number(messageCounter.entry.unreadMessagesCount) + Number(messageCounter.entry.missedCallsCount):0 + count: messageCounter.entry?Number(messageCounter.entry.unreadMessagesCount):0 Timer { interval: 500 diff --git a/linphone-app/ui/modules/Linphone/Dialog/SipAddressDialog.qml b/linphone-app/ui/modules/Linphone/Dialog/SipAddressDialog.qml index 363334161..31b42f721 100644 --- a/linphone-app/ui/modules/Linphone/Dialog/SipAddressDialog.qml +++ b/linphone-app/ui/modules/Linphone/Dialog/SipAddressDialog.qml @@ -58,15 +58,15 @@ DialogPlus { return UtilsCpp.hasCapability(entry.sipAddress, LinphoneEnums.FriendCapabilityLimeX3Dh, true) }, handler: function (entry) { - console.debug("Call selected: " +entry + "/"+entry.sipAddress) + console.debug("Entry selected: " +entry + "/"+entry.sipAddress) smartSearchBar.entryClicked(entry) + smartSearchBar.closeMenu() }, }] onEntryClicked: { - console.debug("Call selected from button: " +entry + "/"+entry.sipAddress) + console.debug("Entry selected from button: " +entry + "/"+entry.sipAddress) mainItem.addressSelectedCallback(entry.sipAddress) - mainItem.exit(1) } } Text { @@ -108,7 +108,6 @@ DialogPlus { onEntrySelected:{ if( entry) { mainItem.chatRoomSelectedCallback(entry.chatRoomModel) - exit(1) } } } diff --git a/linphone-app/ui/modules/Linphone/History/Event.qml b/linphone-app/ui/modules/Linphone/History/Event.qml index 71ddb446e..9a7558b31 100644 --- a/linphone-app/ui/modules/Linphone/History/Event.qml +++ b/linphone-app/ui/modules/Linphone/History/Event.qml @@ -7,16 +7,19 @@ import Linphone.Styles 1.0 import Utils 1.0 import UtilsCpp 1.0 +import 'qrc:/ui/scripts/Utils/utils.js' as Utils + // ============================================================================= Row { id: mainItem signal entryClicked(var entry) - property var _sipAddressObserver: $historyEntry.sipAddress ? SipAddressesModel.getSipAddressObserver($historyEntry.sipAddress, '') : $historyEntry.title + property var sipAddressObserver: $historyEntry.sipAddress ? SipAddressesModel.getSipAddressObserver($historyEntry.sipAddress, '') : $historyEntry.title + property QtObject iconData property string translation - Component.onDestruction: _sipAddressObserver=null// Need to set it to null because of not calling destructor if not. + Component.onDestruction: sipAddressObserver=null// Need to set it to null because of not calling destructor if not. Component.onCompleted: { if ($historyEntry.status == LinphoneEnums.CallStatusSuccess) { if(!$historyEntry.isStart){ @@ -141,8 +144,8 @@ Row { height: parent.height text: $historyEntry && $historyEntry.title ? $historyEntry.title - : _sipAddressObserver - ? ( UtilsCpp.getDisplayName(_sipAddressObserver.peerAddress || $historyEntry.sipAddress) || _sipAddressObserver) + : sipAddressObserver + ? UtilsCpp.getDisplayName(sipAddressObserver.peerAddress || $historyEntry.sipAddress) || sipAddressObserver : '' verticalAlignment: Text.AlignVCenter MouseArea{ diff --git a/linphone-app/ui/modules/Linphone/History/History.js b/linphone-app/ui/modules/Linphone/History/History.js index f9091ea97..5adc56a02 100644 --- a/linphone-app/ui/modules/Linphone/History/History.js +++ b/linphone-app/ui/modules/Linphone/History/History.js @@ -29,13 +29,13 @@ function initView () { history.tryToLoadMoreEntries = false - history.bindToEnd = true + history.bindToStart = true } function loadMoreEntries () { - if (history.atYBeginning && !history.tryToLoadMoreEntries) { + if (history.atYEnd && !history.tryToLoadMoreEntries) { history.tryToLoadMoreEntries = true - history.positionViewAtBeginning() + history.positionViewAtEnd() container.proxyModel.loadMoreEntries() } } @@ -55,11 +55,11 @@ function handleMoreEntriesLoaded (n) { } function handleMovementEnded () { - if (history.atYEnd) { - history.bindToEnd = true + if (history.atYBeginning) { + history.bindToStart = true } } function handleMovementStarted () { - history.bindToEnd = false + history.bindToStart = false } diff --git a/linphone-app/ui/modules/Linphone/History/History.qml b/linphone-app/ui/modules/Linphone/History/History.qml index f4ed638ca..88c8850c5 100644 --- a/linphone-app/ui/modules/Linphone/History/History.qml +++ b/linphone-app/ui/modules/Linphone/History/History.qml @@ -31,7 +31,7 @@ Rectangle { // ----------------------------------------------------------------------- - property bool bindToEnd: false + property bool bindToStart: false property bool tryToLoadMoreEntries: true // ----------------------------------------------------------------------- @@ -196,6 +196,6 @@ Rectangle { repeat: true running: true - onTriggered: history.bindToEnd && history.positionViewAtEnd() + onTriggered: history.bindToStart && history.positionViewAtBeginning() } } diff --git a/linphone-app/ui/modules/Linphone/Misc/MessageCounter.qml b/linphone-app/ui/modules/Linphone/Misc/MessageCounter.qml index 4a3d4a023..b09967f53 100644 --- a/linphone-app/ui/modules/Linphone/Misc/MessageCounter.qml +++ b/linphone-app/ui/modules/Linphone/Misc/MessageCounter.qml @@ -7,7 +7,7 @@ import Linphone.Styles 1.0 Item{ id: messageCounter - property bool showOnlyNumber: false + property bool showOnlyNumber: backgroundIcon.icon == '' property int count: 0 property alias icon: backgroundIcon.icon property alias iconSize: amountIcon.iconSize @@ -20,15 +20,15 @@ Item{ Icon { id: backgroundIcon - icon: 'chat_count' - iconSize: MessageCounterStyle.iconSize.message + icon: '' + iconSize: visible ? MessageCounterStyle.iconSize.message : 0 visible: !messageCounter.showOnlyNumber } Icon { id: amountIcon anchors { - horizontalCenter: parent.right - verticalCenter: parent.bottom + horizontalCenter: messageCounter.showOnlyNumber ? parent.horizontalCenter : parent.right + verticalCenter: messageCounter.showOnlyNumber ? parent.verticalCenter : parent.bottom } icon: 'chat_amount' @@ -39,6 +39,7 @@ Item{ anchors.centerIn: parent color: MessageCounterStyle.text.colorModel.color font.pointSize: messageCounter.pointSize + font.weight: Font.Bold text: (messageCounter.count>99 ? '+' : messageCounter.count) } } diff --git a/linphone-app/ui/modules/Linphone/SmartSearchBar/SmartSearchBar.qml b/linphone-app/ui/modules/Linphone/SmartSearchBar/SmartSearchBar.qml index e238f422c..aae24d9c8 100644 --- a/linphone-app/ui/modules/Linphone/SmartSearchBar/SmartSearchBar.qml +++ b/linphone-app/ui/modules/Linphone/SmartSearchBar/SmartSearchBar.qml @@ -84,8 +84,7 @@ SearchBox { searchBox.launchChat(entry.sipAddress) searchBox.closeMenu() }, - visible: SettingsModel.standardChatEnabled, - zz: 'toto' + visible: SettingsModel.standardChatEnabled }, { colorSet: SettingsModel.getShowStartChatButton() ? SipAddressesViewStyle.chat : SipAddressesViewStyle.history, secure: 1, diff --git a/linphone-app/ui/modules/Linphone/Styles/Account/AccountStatusStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Account/AccountStatusStyle.qml index fc31badaf..963dd13ec 100644 --- a/linphone-app/ui/modules/Linphone/Styles/Account/AccountStatusStyle.qml +++ b/linphone-app/ui/modules/Linphone/Styles/Account/AccountStatusStyle.qml @@ -27,7 +27,7 @@ QtObject { property int pointSize: Units.dp * 11 } property QtObject messageCounter: QtObject { - property int bottomMargin: 4 - property int size: 16 + property int iconSize: 15 + property int pointSize: Units.dp * 9 } } diff --git a/linphone-app/ui/modules/Linphone/Styles/Timeline/CallTimelineStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Timeline/CallTimelineStyle.qml new file mode 100644 index 000000000..435fe4339 --- /dev/null +++ b/linphone-app/ui/modules/Linphone/Styles/Timeline/CallTimelineStyle.qml @@ -0,0 +1,34 @@ +pragma Singleton +import QtQml 2.2 + +import Units 1.0 +import ColorsList 1.0 + +// ============================================================================= + +QtObject { + property string sectionName: 'CallTimeline' + property var colorModel: ColorsList.add(sectionName+'_bg', 'd') + property QtObject backgroundColor: QtObject { + property var normal: ColorsList.add(sectionName+'_legend_bg_n', 'timeline_header_bg') + } + property int pointSize: Units.dp * 11 + property QtObject searchField: QtObject { + property var colorModel: ColorsList.add(sectionName+'_searchField', 'c') + property int pointSize: Units.dp * 9 + } + + property QtObject filterAction: QtObject { + property int iconSize: 30 + property string name : 'filter' + property string icon : 'filter_params_custom' + property var backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg') + property var backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg') + property var backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg') + property var backgroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 'me_p_b_bg') + property var foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_fg') + property var foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg') + property var foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg') + property var foregroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 'me_p_b_fg') + } +} diff --git a/linphone-app/ui/modules/Linphone/Styles/Timeline/TimelineStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Timeline/TimelineStyle.qml index 2fa8a216e..8e2179ecf 100644 --- a/linphone-app/ui/modules/Linphone/Styles/Timeline/TimelineStyle.qml +++ b/linphone-app/ui/modules/Linphone/Styles/Timeline/TimelineStyle.qml @@ -52,11 +52,10 @@ QtObject { property QtObject legend: QtObject { property QtObject backgroundColor: QtObject { - property var normal: ColorsList.add(sectionName+'_legend_bg_n', 'f') - property var hovered: ColorsList.add(sectionName+'_legend_bg_h', 'c') + property var normal: ColorsList.add(sectionName+'_legend_bg_n', 'timeline_header_bg') } property var colorModel: ColorsList.add(sectionName+'_legend', 'd') - property int pointSize: Units.dp * 10 + property int pointSize: Units.dp * 11 property int height: 30 property int iconSize: 28 property int leftMargin: 17 @@ -97,4 +96,17 @@ QtObject { property var foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg') property var foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg') } + property QtObject filterAction: QtObject { + property int iconSize: 30 + property string name : 'filter' + property string icon : 'filter_params_custom' + property var backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg') + property var backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg') + property var backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg') + property var backgroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 'me_p_b_bg') + property var foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_fg') + property var foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg') + property var foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg') + property var foregroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 'me_p_b_fg') + } } diff --git a/linphone-app/ui/modules/Linphone/Styles/qmldir b/linphone-app/ui/modules/Linphone/Styles/qmldir index e2deecd4a..dd33f4a5a 100644 --- a/linphone-app/ui/modules/Linphone/Styles/qmldir +++ b/linphone-app/ui/modules/Linphone/Styles/qmldir @@ -60,6 +60,7 @@ singleton StickerStyle 1.0 Sticker/StickerStyle.qml singleton TelKeypadStyle 1.0 TelKeypad/TelKeypadStyle.qml +singleton CallTimelineStyle 1.0 Timeline/CallTimelineStyle.qml singleton TimelineStyle 1.0 Timeline/TimelineStyle.qml singleton ParticipantsListViewStyle 1.0 View/ParticipantsListViewStyle.qml diff --git a/linphone-app/ui/modules/Linphone/Timeline/CallTimeline.qml b/linphone-app/ui/modules/Linphone/Timeline/CallTimeline.qml new file mode 100644 index 000000000..af5150ff6 --- /dev/null +++ b/linphone-app/ui/modules/Linphone/Timeline/CallTimeline.qml @@ -0,0 +1,139 @@ +import QtQuick 2.7 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.5 +import QtQuick.Shapes 1.10 + + +import Common 1.0 +import Common.Styles 1.0 +import Linphone 1.0 +import Linphone.Styles 1.0 +import ColorsList 1.0 + +import UtilsCpp 1.0 + +import 'Timeline.js' as Logic +import 'qrc:/ui/scripts/Utils/utils.js' as Utils + +// ============================================================================= +ColumnLayout{ + id: mainItem + signal entrySelected(var model) + + Layout.fillHeight: true + spacing: 0 +// HEADER + Rectangle { + id: legendArea + Layout.preferredWidth: mainItem.width + Layout.preferredHeight: 50 + Layout.alignment: Qt.AlignTop + color: CallTimelineStyle.backgroundColor.normal.color + RowLayout{ + anchors.fill: parent + spacing: 2 + Text { + Layout.preferredHeight: parent.height + Layout.fillWidth: true + Layout.leftMargin: 10 + color: CallTimelineStyle.colorModel.color + font.pointSize: CallTimelineStyle.pointSize + font.weight: Font.Bold + //: 'Call list' : Call histories title + text: qsTr('callListTitle') + verticalAlignment: Text.AlignVCenter + } + + ActionButton { + id:filterButton + Layout.alignment: Qt.AlignRight + isCustom: true + colorSet: CallTimelineStyle.filterAction + toggled: view.model.filterFlags != 0 && view.model.filterFlags != CallHistoryProxyModel.All + + onClicked: filterMenu.open() + Menu{ + id: filterMenu + MenuItem{ + id: incomingFilter + //: 'Incoming' : Filter label for incoming call + text: qsTr('incomingFilter') + checkable: true + } + MenuItem{ + id: outgoingFilter + //: 'Outgoing' : Filter label for outgoing call + text: qsTr('outgoingFilter') + checkable: true + } + MenuItem{ + id: missedFilter + //: 'Missed' : Filter label for missed call + text: qsTr('missedFilter') + checkable: true + } + } + } + } + } +// ------------------------------------------------------------------------- +// Search. +// ------------------------------------------------------------------------- + Rectangle{ + id:searchView + Layout.preferredWidth: mainItem.width + Layout.preferredHeight: 50 + Layout.alignment: Qt.AlignCenter + color: legendArea.color + TextField { + id:searchBar + anchors.fill: parent + anchors.rightMargin: 10 + anchors.leftMargin: 10 + anchors.topMargin: 5 + anchors.bottomMargin: 10 + width: parent.width - 14 + icon: text == '' ? 'search_custom' : 'close_custom' + iconSize: 30 + overwriteColor: CallTimelineStyle.searchField.colorModel.color + //: 'Search in the list' : ths is a placeholder when searching something in a list + placeholderText: qsTr('searchListPlaceholderText') + + onTextChanged: searchDelay.restart() + font.pointSize: CallTimelineStyle.searchField.pointSize + Timer{ + id: searchDelay + interval: 600 + repeat: false + onTriggered: view.model.filterText = searchBar.text + } + } + } + + ScrollableListView { + id: view + Layout.fillHeight: true + Layout.preferredWidth: mainItem.width + currentIndex: -1 + + model: CallHistoryProxyModel{ + filterFlags: (incomingFilter.checked ? CallHistoryProxyModel.Incoming : 0) + | (outgoingFilter.checked ? CallHistoryProxyModel.Outgoing : 0) + | (missedFilter.checked ? CallHistoryProxyModel.Missed : 0) + } + + delegate: CallTimelineItem{ + callHistoryModel: $modelData + modelIndex: index + Connections{ + target: $modelData + onSelectedChanged:{ + if(selected) { + view.currentIndex = index; + mainItem.entrySelected(model) + } + } + } + } + } +} \ No newline at end of file diff --git a/linphone-app/ui/modules/Linphone/Timeline/CallTimelineItem.qml b/linphone-app/ui/modules/Linphone/Timeline/CallTimelineItem.qml new file mode 100644 index 000000000..fbba63ea0 --- /dev/null +++ b/linphone-app/ui/modules/Linphone/Timeline/CallTimelineItem.qml @@ -0,0 +1,277 @@ +import QtQuick 2.7 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.5 + +import Common 1.0 +import Common.Styles 1.0 +import Linphone 1.0 +import LinphoneEnums 1.0 +import Linphone.Styles 1.0 +import ColorsList 1.0 + +import UtilsCpp 1.0 + +import 'Timeline.js' as Logic +import 'qrc:/ui/scripts/Utils/utils.js' as Utils + +// ============================================================================= +Rectangle { + id: mainItem + property CallHistoryModel callHistoryModel + property bool optionsTogglable: true // Right click => display/hide options + property bool optionsToggled: false + property int modelIndex: 0 + property var actions: [] + + height: TimelineStyle.contact.height + width: parent ? parent.width : 0 + + state: optionsToggled ? 'options' : 'normal' + states: [State { + name: "normal" + }, State { + name: "options" + } + ] + + transitions: [Transition { + from: 'normal' + to: 'options' + //NumberAnimation { target: contactView; property: 'x'; to:-contactView.width; duration: 200;} + NumberAnimation { target: optionsView; property: 'x'; to:0; duration: 200;} + }, + Transition { + from: 'options' + to: 'normal' + //NumberAnimation { target: contactView; property: 'x'; to:0; duration: 200;} + NumberAnimation { target: optionsView; property: 'x'; to:optionsView.width; duration: 200;} + } + ] + enabled: !contactView.showBusyIndicator + + color: contactView.isSelected + ? TimelineStyle.contact.backgroundColor.selected.color + : ( + mainItem.modelIndex % 2 == 0 + ? TimelineStyle.contact.backgroundColor.a.color + : TimelineStyle.contact.backgroundColor.b.color + ) + + RowLayout{ + anchors.fill: parent + anchors.rightMargin: 5 + spacing: 0 + Contact { + id: contactView + property bool isSelected: mainItem.callHistoryModel != undefined && mainItem.callHistoryModel.selected + Layout.fillHeight: true + Layout.fillWidth: true + color: isSelected + ? TimelineStyle.contact.backgroundColor.selected.color + : ( + mainItem.modelIndex % 2 == 0 + ? TimelineStyle.contact.backgroundColor.a.color + : TimelineStyle.contact.backgroundColor.b.color + ) + displayUnreadMessageCount: false + entry: mainItem.callHistoryModel && (mainItem.callHistoryModel.conferenceInfoModel && mainItem.callHistoryModel + || SipAddressesModel.getSipAddressObserver(mainItem.callHistoryModel.remoteAddress, '')) + + property var subtitleSelectedColors: TimelineStyle.contact.subtitle.color.selected + property var subtitleNormalColors: TimelineStyle.contact.subtitle.color.normal + property var titleSelectedColors: TimelineStyle.contact.title.color.selected + property var titleNormalColors: TimelineStyle.contact.title.color.normal + + function getIconData(){ + var iconData + if(!mainItem.callHistoryModel) + return HistoryStyle.entry.event.unknownCallEvent + if (mainItem.callHistoryModel.lastCallStatus == LinphoneEnums.CallStatusSuccess) { + if(!mainItem.callHistoryModel.lastCallIsStart){ + iconData = HistoryStyle.entry.event.endedCall + }else if(mainItem.callHistoryModel.lastCallIsOutgoing ){ + iconData = HistoryStyle.entry.event.outgoingCall + }else{ + iconData = HistoryStyle.entry.event.incomingCall + } + }else if(mainItem.callHistoryModel.lastCallStatus == LinphoneEnums.CallStatusDeclined) { + if(mainItem.callHistoryModel.lastCallIsOutgoing ){ + iconData = HistoryStyle.entry.event.declinedOutgoingCall + }else{ + iconData = HistoryStyle.entry.event.declinedIncomingCall + } + }else if(mainItem.callHistoryModel.lastCallStatus == LinphoneEnums.CallStatusMissed) { + if(mainItem.callHistoryModel.lastCallIsOutgoing ){ + iconData = HistoryStyle.entry.event.missedOutgoingCall + }else{ + iconData = HistoryStyle.entry.event.missedIncomingCall + } + }else if(mainItem.callHistoryModel.lastCallStatus == LinphoneEnums.CallStatusAborted) { + if(mainItem.callHistoryModel.lastCallIsOutgoing ){ + iconData = HistoryStyle.entry.event.outgoingCall + }else{ + iconData = HistoryStyle.entry.event.incomingCall + } + }else if(mainItem.callHistoryModel.lastCallStatus == LinphoneEnums.CallStatusDeclined) { + if(mainItem.callHistoryModel.lastCallIsOutgoing ){ + iconData = HistoryStyle.entry.event.declinedOutgoingCall + }else{ + iconData = HistoryStyle.entry.event.declinedIncomingCall + } + }else if(mainItem.callHistoryModel.lastCallStatus == LinphoneEnums.CallStatusEarlyAborted) { + if(mainItem.callHistoryModel.lastCallIsOutgoing ){ + iconData = HistoryStyle.entry.event.missedOutgoingCall + }else{ + iconData = HistoryStyle.entry.event.missedIncomingCall + } + }else if(mainItem.callHistoryModel.lastCallStatus == LinphoneEnums.CallStatusAcceptedElsewhere) { + if(mainItem.callHistoryModel.lastCallIsOutgoing ){ + iconData = HistoryStyle.entry.event.outgoingCall + }else{ + iconData = HistoryStyle.entry.event.incomingCall + } + }else if(mainItem.callHistoryModel.lastCallStatus == LinphoneEnums.CallStatusDeclinedElsewhere) { + if(mainItem.callHistoryModel.lastCallIsOutgoing ){ + iconData = HistoryStyle.entry.event.declinedOutgoingCall + }else{ + iconData = HistoryStyle.entry.event.declinedIncomingCall + } + }else { + iconData = HistoryStyle.entry.event.unknownCallEvent + } + return iconData + } + + subtitleColor: isSelected + ? subtitleSelectedColors.color + : subtitleNormalColors.color + titleColor: isSelected + ? titleSelectedColors.color + : titleNormalColors.color + subtitleIconData: getIconData() + subtitleText: mainItem.callHistoryModel && UtilsCpp.toDateTimeString(mainItem.callHistoryModel.lastCallDate, 'yyyy/MM/dd - hh:mm') || '' + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + propagateComposedEvents: true + preventStealing: false + onClicked: { + if(mouse.button == Qt.LeftButton){ + if(mainItem.callHistoryModel) + mainItem.callHistoryModel.selectOnly() + }else if(mainItem.optionsTogglable){ + mainItem.optionsToggled = !mainItem.optionsToggled + } + } + } + } + ColumnLayout{ + spacing: 0 + Layout.maximumWidth: statusLayout.count > 0 || unreadMessageCounter.visible ? -1 : 0 + Layout.fillHeight: true + RowLayout{ + Layout.alignment: Qt.AlignTop | Qt.AlignRight + Layout.fillHeight: true + spacing: 0 + ContactMessageCounter { + id: unreadMessageCounter + Layout.alignment: Qt.AlignTop + Layout.preferredWidth: implicitWidth + Layout.preferredHeight: implicitHeight + Layout.rightMargin: 9 + displayCounter: SettingsModel.standardChatEnabled || SettingsModel.secureChatEnabled + entry: contactView.entry + } + } + RowLayout{ + id: statusLayout + property int count : (ephemeralIcon.visible ? 1 : 0) + (notificationsIcon.visible ? 1 : 0) + spacing: 0 + Layout.alignment: Qt.AlignBottom | Qt.AlignRight + Layout.preferredHeight: TimelineStyle.status.iconSize + visible: false //SettingsModel.standardChatEnabled || SettingsModel.secureChatEnabled + Icon{ + id: notificationsIcon + Layout.preferredHeight: TimelineStyle.status.iconSize + Layout.preferredWidth: TimelineStyle.status.iconSize + icon: TimelineStyle.disabledNotifications.icon + iconSize: TimelineStyle.status.iconSize + //overwriteColor: mainItem.timelineModel && mainItem.timelineModel.selected ? TimelineStyle.disabledNotifications.selectedColorModel.color : TimelineStyle.disabledNotifications.colorModel.color + //visible: mainItem.timelineModel && !mainItem.timelineModel.chatRoomModel.notificationsEnabled + } + Icon{ + id: ephemeralIcon + Layout.preferredHeight: TimelineStyle.status.iconSize + Layout.preferredWidth: TimelineStyle.status.iconSize + icon: TimelineStyle.ephemeralTimer.icon + iconSize: TimelineStyle.status.iconSize + //overwriteColor: mainItem.timelineModel && mainItem.timelineModel.selected ? TimelineStyle.ephemeralTimer.selectedTimerColor.color : TimelineStyle.ephemeralTimer.timerColor.color + //visible: mainItem.timelineModel && mainItem.timelineModel.chatRoomModel.ephemeralEnabled + } + } + } + } + RowLayout{ + anchors.fill: parent + anchors.rightMargin: 5 + visible: mainItem.actions.length > 0 + Item{// Spacer + Layout.fillHeight: true + Layout.fillWidth: true + } + Repeater { + model: mainItem.actions + + ActionButton { + isCustom: true + backgroundRadius: 90 + colorSet: modelData.colorSet + + visible: modelData.visible + + onClicked: { + if( mainItem.callHistoryModel) + mainItem.actions[index].handler( // Do not use modelData on functions + mainItem.callHistoryModel + ) + } + + } + } + } + Item{ + id: optionsView + + height: mainItem.height + width: mainItem.width + + x:width + visible: x!=width + RowLayout{ + anchors.fill: parent + MouseArea { + Layout.fillHeight: true + Layout.fillWidth: true + onClicked: { + if(mainItem.optionsTogglable) + mainItem.optionsToggled = !mainItem.optionsToggled + } + } + + Rectangle{ + Layout.fillHeight: true + Layout.preferredWidth: optionsLayout.width + + color: contactView.color + MouseArea {// Grabber + anchors.fill: parent + cursorShape: Qt.ArrowCursor + } + RowLayout{ + id: optionsLayout + anchors.centerIn: parent + } + } + } + } +} \ No newline at end of file diff --git a/linphone-app/ui/modules/Linphone/Timeline/Timeline.qml b/linphone-app/ui/modules/Linphone/Timeline/Timeline.qml index 119b53953..415ec05a3 100644 --- a/linphone-app/ui/modules/Linphone/Timeline/Timeline.qml +++ b/linphone-app/ui/modules/Linphone/Timeline/Timeline.qml @@ -29,7 +29,7 @@ Rectangle { property var actions: [] // --------------------------------------------------------------------------- - signal entrySelected (TimelineModel entry) + signal entrySelected (var entry) signal showHistoryRequest() // --------------------------------------------------------------------------- @@ -40,7 +40,6 @@ Rectangle { anchors.fill: parent spacing: 0 - // ------------------------------------------------------------------------- Connections { @@ -56,254 +55,47 @@ Rectangle { // ------------------------------------------------------------------------- // Legend. // ------------------------------------------------------------------------- - Rectangle { id: legendArea - Layout.fillWidth: true - Layout.preferredHeight: TimelineStyle.legend.height + Layout.preferredWidth: timeline.width + Layout.preferredHeight: 50 Layout.alignment: Qt.AlignTop - color: showHistory.containsMouse?TimelineStyle.legend.backgroundColor.hovered.color:TimelineStyle.legend.backgroundColor.normal.color - visible: showHistoryButton || showFiltersButtons - - MouseArea{// no more showing history - id:showHistory - anchors.fill:parent - visible: showFiltersButtons - onClicked: { - timeline.showFilterView = !timeline.showFilterView - } - } + color: TimelineStyle.legend.backgroundColor.normal.color RowLayout{ - anchors.fill:parent - spacing:TimelineStyle.legend.spacing + anchors.fill: parent Text { Layout.preferredHeight: parent.height Layout.fillWidth: true - Layout.leftMargin: TimelineStyle.legend.leftMargin - visible: showFiltersButtons + Layout.leftMargin: 10 color: TimelineStyle.legend.colorModel.color font.pointSize: TimelineStyle.legend.pointSize - //: A title for filtering mode. - text: qsTr('timelineFilter')+' : ' - +(timeline.model.filterFlags == 0 || timeline.model.filterFlags == TimelineProxyModel.AllChatRooms - //: 'All' The mode for timelines filtering. - ? qsTr('timelineFilterAll') - //: 'Custom' The mode for timelines filtering. - : qsTr('timelineFilterCustom')) + font.weight: Font.Bold + //: 'Messages' : Title for conversations + text: qsTr('chatsTitle') verticalAlignment: Text.AlignVCenter } - Icon { + ActionButton { id:filterButton Layout.alignment: Qt.AlignRight - icon: 'filter_params_custom' - iconSize: TimelineStyle.legend.iconSize - overwriteColor: TimelineStyle.legend.colorModel.color - visible: showFiltersButtons - MouseArea{ - anchors.fill:parent - onClicked:{ - timeline.showFilterView = !timeline.showFilterView + isCustom: true + colorSet: TimelineStyle.filterAction + toggled: view.model.filterFlags != 0 && view.model.filterFlags != TimelineProxyModel.AllChatRooms + onClicked: filterMenu.open() + Menu{ + id: filterMenu + MenuItem{ + id: secureFilter + //: 'Secure rooms' : Filter item. Selecting it will show all secure rooms. + text: qsTr('timelineFilterSecureRooms') + checkable: true + } + MenuItem{ + id: chatGroupFilter + //: 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). + text: qsTr('timelineFilterChatGroups') + checkable: true } - } - } - MouseArea{ - Layout.alignment: Qt.AlignRight - Layout.fillHeight: true - Layout.preferredWidth: TimelineStyle.legend.iconSize - visible: showFiltersButtons - onClicked:{ - searchView.visible = !searchView.visible - } - - Icon { - id:searchButton - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - property bool searching: searchView.visible - icon: (searchView.visible? 'close_custom': 'search_custom') - iconSize: TimelineStyle.legend.iconSize - overwriteColor: TimelineStyle.legend.colorModel.color - } - } - MouseArea{ - Layout.alignment: Qt.AlignRight - Layout.rightMargin: TimelineStyle.legend.lastRightMargin - Layout.fillHeight: true - Layout.preferredWidth: TimelineStyle.legend.iconSize - visible: timeline.showHistoryButton - onClicked:{ - showHistoryRequest() - } - Icon { - id:callHistoryButton - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - property bool searching: searchView.visible - icon: 'call_history_custom' - iconSize: TimelineStyle.legend.iconSize - overwriteColor: TimelineStyle.legend.colorModel.color - } - } - } - } - // ------------------------------------------------------------------------- - // Filter. - // ------------------------------------------------------------------------- - Rectangle{ - id:exhaustiveFilterView - Layout.fillWidth: true - Layout.preferredHeight: filterChoices.height - Layout.alignment: Qt.AlignCenter - border.color: TimelineStyle.filterField.borderColor.color - border.width: 2 - visible: timeline.showFilterView && !SettingsModel.useMinimalTimelineFilter - - ColumnLayout{ - id:filterChoices - anchors.leftMargin: 20 - anchors.left:parent.left - anchors.right:parent.right - spacing:-4 - function getFilterFlags(){ - return secureFilter.model.get(secureFilter.currentIndex).value | groupFilter.model.get(groupFilter.currentIndex).value | ephemeralsFilter.model.get(ephemeralsFilter.currentIndex).value; - } - ComboBox { - Layout.fillWidth: true - id:secureFilter - currentIndex: 0 - onCurrentIndexChanged: timeline.model.filterFlags = filterChoices.getFilterFlags() - textRole: "key" - model: ListModel { - ListElement { - //: 'All security levels' : Filter item. Selecting it will not do any filter on security level. - key: qsTr('timelineFilterAllSecureLevelRooms'); value: 0} - ListElement { - //: 'Standard rooms' : Filter item. Selecting it will show all simple rooms. - key: qsTr('timelineFilterStandardRooms'); value: TimelineProxyModel.StandardChatRoom} - ListElement { - //: 'Secure rooms' : Filter item. Selecting it will show all secure rooms. - key: qsTr('timelineFilterSecureRooms'); value: TimelineProxyModel.SecureChatRoom} - } - - haveBorder: false - haveMargin: false - backgroundColor: 'transparent' - visible: SettingsModel.secureChatEnabled && SettingsModel.standardChatEnabled - } - ComboBox { - Layout.fillWidth: true - id:groupFilter - currentIndex: 0 - onCurrentIndexChanged: timeline.model.filterFlags = filterChoices.getFilterFlags() - textRole: "key" - model: ListModel { - ListElement { - //: 'Any conversations' : Filter item. Selecting it will not do any filter on the type of conversations. - key: qsTr('timelineFilterAnyChatRooms'); value: 0} - ListElement { - //: 'Simple rooms' : Filter item. Selecting it will show all secure chat groups (with more than one participant). - key: qsTr('timelineFilterSimpleRooms'); value: TimelineProxyModel.SimpleChatRoom} - ListElement { - //: 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). - key: qsTr('timelineFilterChatGroups'); value: TimelineProxyModel.GroupChatRoom} - } - - haveBorder: false - haveMargin: false - backgroundColor: 'transparent' - visible: SettingsModel.secureChatEnabled || SettingsModel.standardChatEnabled - } - ComboBox { - Layout.fillWidth: true - id:ephemeralsFilter - currentIndex: 0 - onCurrentIndexChanged: timeline.model.filterFlags = filterChoices.getFilterFlags() - textRole: "key" - model: ListModel { - ListElement { - //: 'Ephemerals on/off' : Filter item. Selecting it will not do any filter on ephemerals activation. - key: qsTr('timelineFilterAnyEphemerals'); value: 0} - ListElement { - //: 'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled. - key: qsTr('timelineFilterNoEphemerals'); value: TimelineProxyModel.NoEphemeralChatRoom} - ListElement { - //: 'Ephemerals' : Filter item. Selecting it will show all chat rooms where the ephemeral mode has been enabled. - key: qsTr('timelineFilterEphemerals'); value: TimelineProxyModel.EphemeralChatRoom} - } - - haveBorder: false - haveMargin: false - backgroundColor: 'transparent' - visible: SettingsModel.secureChatEnabled || SettingsModel.standardChatEnabled - } - } - } - Rectangle{ - id:minimalFilterView - Layout.fillWidth: true - Layout.preferredHeight: minimalFilterChoices.height - Layout.alignment: Qt.AlignCenter - border.color: TimelineStyle.filterField.borderColor.color - border.width: 2 - visible: timeline.showFilterView && SettingsModel.useMinimalTimelineFilter - - ColumnLayout{ - id:minimalFilterChoices - anchors.leftMargin: 20 - anchors.left:parent.left - anchors.right:parent.right - spacing:-4 - function getFilterFlags(){ - return securedCheckBox.getValue() | groupCheckBox.getValue() | conferenceCheckBox.getValue(); - } - CheckBoxText { - id: securedCheckBox - Layout.fillWidth: true - visible: SettingsModel.secureChatEnabled && SettingsModel.standardChatEnabled - //: 'Secure rooms' : Filter item. Selecting it will show all secure rooms. - text: qsTr('timelineFilterSecureRooms') - - onClicked: { - timeline.model.filterFlags = minimalFilterChoices.getFilterFlags() - } - function getValue(){ - if( checked) - return TimelineProxyModel.SecureChatRoom - else - return 0 - } - } - CheckBoxText { - id: groupCheckBox - Layout.fillWidth: true - visible: SettingsModel.secureChatEnabled || SettingsModel.standardChatEnabled - //: 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant). - text: qsTr('timelineFilterChatGroups') - - onClicked: { - timeline.model.filterFlags = minimalFilterChoices.getFilterFlags() - } - function getValue(){ - if( checked) - return TimelineProxyModel.GroupChatRoom - else - return 0 - } - } - - CheckBoxText { - id: conferenceCheckBox - Layout.fillWidth: true - visible: false - //: 'Conferences' : Filter item. Selecting it will show all conferences. - text: qsTr('timelineFilterConferences') - - onClicked: { - timeline.model.filterFlags = minimalFilterChoices.getFilterFlags() - } - function getValue(){ - return 0 } } } @@ -314,25 +106,16 @@ Rectangle { Rectangle{ id:searchView Layout.fillWidth: true - Layout.preferredHeight: 40 + Layout.preferredHeight: 50 Layout.alignment: Qt.AlignCenter - border.color: TimelineStyle.searchField.borderColor.color - border.width: 2 - visible:false - onVisibleChanged: if(visible){ - timeline.model.filterText = searchBar.text - searchBar.forceActiveFocus() - }else{ - timeline.model.filterText = '' - } - + color: legendArea.color TextField { id:searchBar anchors.fill: parent - anchors.rightMargin: 7 - anchors.leftMargin: 7 + anchors.rightMargin: 10 + anchors.leftMargin: 10 anchors.topMargin: 5 - anchors.bottomMargin: 5 + anchors.bottomMargin: 10 width: parent.width - 14 icon: text == '' ? 'search_custom' : 'close_custom' iconSize: 30 @@ -360,12 +143,18 @@ Rectangle { Layout.fillHeight: true Layout.fillWidth: true currentIndex: -1 + model: TimelineProxyModel{ + listSource: TimelineProxyModel.Main + filterFlags: (secureFilter.checked ? TimelineProxyModel.SecureChatRoom : 0) + | (chatGroupFilter.checked ? TimelineProxyModel.GroupChatRoom : 0) + } delegate: TimelineItem{ timelineModel: $modelData modelIndex: index optionsTogglable: timeline.optionsTogglable actions: timeline.actions + Connections{ target: $modelData onSelectedChanged:{ diff --git a/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml b/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml index 2c45120d7..064c65028 100644 --- a/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml +++ b/linphone-app/ui/modules/Linphone/Timeline/TimelineItem.qml @@ -100,7 +100,8 @@ Rectangle { preventStealing: false onClicked: { if(mouse.button == Qt.LeftButton){ - mainItem.timelineModel.selected = true + if(mainItem.timelineModel) + mainItem.timelineModel.selected = true }else if(mainItem.optionsTogglable){ mainItem.optionsToggled = !mainItem.optionsToggled } @@ -172,9 +173,10 @@ Rectangle { visible: modelData.visible onClicked: { - mainItem.actions[index].handler( // Do not use modelData on functions - mainItem.timelineModel - ) + if( mainItem.timelineModel) + mainItem.actions[index].handler( // Do not use modelData on functions + mainItem.timelineModel + ) } } @@ -225,7 +227,7 @@ Rectangle { id: deleteButton Layout.alignment: Qt.AlignCenter Layout.rightMargin: 6 - + visible: mainItem.timelineModel isCustom: true colorSet: contactView.isSelected ? TimelineStyle.selectedDeleteAction : TimelineStyle.deleteAction onClicked: window.attachVirtualWindow(Utils.buildCommonDialogUri('ConfirmDialog'), { @@ -233,7 +235,8 @@ Rectangle { descriptionText: qsTr('deleteTimeline'), }, function (status) { if (status) { - mainItem.timelineModel.chatRoomModel.deleteChatRoom() + if( mainItem.timelineModel) + mainItem.timelineModel.chatRoomModel.deleteChatRoom() } }) TooltipArea { diff --git a/linphone-app/ui/modules/Linphone/qmldir b/linphone-app/ui/modules/Linphone/qmldir index 043dc3847..b10384b45 100644 --- a/linphone-app/ui/modules/Linphone/qmldir +++ b/linphone-app/ui/modules/Linphone/qmldir @@ -65,6 +65,8 @@ Sticker 1.0 Sticker/Sticker.qml TelKeypad 1.0 TelKeypad/TelKeypad.qml +CallTimeline 1.0 Timeline/CallTimeline.qml +CallTimelineItem 1.0 Timeline/CallTimelineItem.qml Timeline 1.0 Timeline/Timeline.qml TimelineItem 1.0 Timeline/TimelineItem.qml diff --git a/linphone-app/ui/scripts/Utils/utils.js b/linphone-app/ui/scripts/Utils/utils.js index c0a131c4b..87b5e095d 100644 --- a/linphone-app/ui/scripts/Utils/utils.js +++ b/linphone-app/ui/scripts/Utils/utils.js @@ -522,6 +522,12 @@ function genRandomNumber (min, max) { return Math.random() * (max - min) + min } +function genRandomColor(){ + return '#'+ Math.floor(Math.random()*255).toString(16) + +Math.floor(Math.random()*255).toString(16) + +Math.floor(Math.random()*255).toString(16) +} + // ----------------------------------------------------------------------------- // Generate a random number between a set of intervals. diff --git a/linphone-app/ui/views/App/Main/Calls.qml b/linphone-app/ui/views/App/Main/Calls.qml new file mode 100644 index 000000000..237c05035 --- /dev/null +++ b/linphone-app/ui/views/App/Main/Calls.qml @@ -0,0 +1,43 @@ +import QtQuick 2.7 +import QtQuick.Layouts 1.3 + +import Clipboard 1.0 +import Common 1.0 +import Linphone 1.0 +import Utils 1.0 +import UtilsCpp 1.0 +import LinphoneEnums 1.0 + +import App.Styles 1.0 +import Common.Styles 1.0 +import Linphone.Styles 1.0 +import Units 1.0 + +import ColorsList 1.0 + + +import 'Conversation.js' as Logic + +// ============================================================================= + +RowLayout{ + spacing: 0 + CallTimeline{ + Layout.fillHeight: true + Layout.preferredWidth: MainWindowStyle.menu.width + + onEntrySelected:{ + content.setSource('HistoryView.qml', { + callHistoryModel: model + }) + } + } + Loader{ + id: content + Layout.fillHeight: true + Layout.fillWidth: true + } +} + + + diff --git a/linphone-app/ui/views/App/Main/Conferences.qml b/linphone-app/ui/views/App/Main/Conferences.qml index fd148f31e..2343a28d1 100644 --- a/linphone-app/ui/views/App/Main/Conferences.qml +++ b/linphone-app/ui/views/App/Main/Conferences.qml @@ -34,7 +34,7 @@ Item{ anchors.fill: parent verticalAlignment: Qt.AlignVCenter - anchors.leftMargin: 40 + anchors.leftMargin: 28 color: ConferencesStyle.bar.text.colorModel.color font { @@ -44,6 +44,25 @@ Item{ //: 'Meetings' : Conference list title. text: qsTr('conferencesTitle') } + TextButtonB { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 10 + addHeight: 10 + addWidth: 80 + //: 'Create Meeting' : Button label to create a meeting + text: qsTr('createMeeting') + capitalization: Font.Capitalize + onClicked: { + window.detachVirtualWindow() + window.attachVirtualWindow(Utils.buildAppDialogUri('NewConference') + ,{}, function (status) { + if( status){ + setView('Conferences') + } + }) + } + } } Rectangle { Layout.fillWidth: true diff --git a/linphone-app/ui/views/App/Main/Contacts.qml b/linphone-app/ui/views/App/Main/Contacts.qml index 0135fe46c..a2a55b02e 100644 --- a/linphone-app/ui/views/App/Main/Contacts.qml +++ b/linphone-app/ui/views/App/Main/Contacts.qml @@ -9,6 +9,7 @@ import LinphoneEnums 1.0 import App.Styles 1.0 +import 'qrc:/ui/scripts/Utils/utils.js' as Utils // ============================================================================= ColumnLayout { @@ -41,10 +42,26 @@ ColumnLayout { rightMargin: ContactsStyle.bar.rightMargin } spacing: ContactsStyle.spacing + Text { + Layout.preferredHeight: parent.height + Layout.preferredWidth: contentWidth + Layout.leftMargin: 10 + color: ContactsStyle.bar.foregroundColor.color + font.pointSize: ContactsStyle.bar.pointSize + font.weight: Font.Bold + font.capitalization: Font.Capitalize + text: LdapListModel.count > 0 + //: 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. + ? qsTr('localContactsEntry') + //: 'Contacts' : Contacts section label in main waindow. + : qsTr('contactsEntry') + verticalAlignment: Text.AlignVCenter + } TextField { Layout.fillWidth: true icon: ContactsStyle.filter.icon + iconSize: 35 overwriteColor: ContactsStyle.filter.colorModel.color placeholderText: qsTr('searchContactPlaceholder') @@ -53,16 +70,24 @@ ColumnLayout { ExclusiveButtons { texts: [ + //: 'All' : Filter label to display all items. qsTr('selectAllContacts'), - qsTr('selectConnectedContacts') + //: 'Online' : Filter label to display only online contacts. + qsTr('selectOnlineContacts') ] - - onClicked: contacts.useConnectedFilter = !!button + capitalization: Font.AllUppercase + onClicked: contacts.useOnlineFilter = !!button + } + Item{ + Layout.fillHeight: true + Layout.fillWidth: true } - TextButtonB { - addHeight: 15 - text: qsTr('addContact') + Layout.leftMargin: 20 + addHeight: 10 + addWidth: 80 + text: qsTr('addContact').toLowerCase() + capitalization: Font.Capitalize onClicked: window.setView('ContactEdit') } } @@ -209,17 +234,26 @@ ColumnLayout { target: lastChatRoom onStateChanged: if(state === 1) { console.debug("Load conversation from contacts") - window.setView('Conversation', { - chatRoomModel: lastChatRoom - }) + window.setView('Conversation') } } readonly property var handlers: [ CallsListModel.launchVideoCall, CallsListModel.launchAudioCall, - function (sipAddress) {CallsListModel.launchChat( sipAddress,0 )}, - function (sipAddress) {CallsListModel.launchChat( sipAddress,1 )} + function (sipAddress) { + var model = CallsListModel.launchChat( sipAddress,0 ) + if(model && model.chatRoomModel) { + lastChatRoom = model.chatRoomModel + window.setView('Conversations') + } + }, + function (sipAddress) { + var model = CallsListModel.launchChat( sipAddress,1 ) + if(model && model.chatRoomModel) { + lastChatRoom = model.chatRoomModel + window.setView('Conversations') + }} ] model: handlers diff --git a/linphone-app/ui/views/App/Main/Conversation.qml b/linphone-app/ui/views/App/Main/Conversation.qml index 969d51c24..45c3b249d 100644 --- a/linphone-app/ui/views/App/Main/Conversation.qml +++ b/linphone-app/ui/views/App/Main/Conversation.qml @@ -582,28 +582,13 @@ ColumnLayout { topWidth: ConversationStyle.filters.border.topWidth visible: chatRoomModel && (!chatRoomModel.haveEncryption && SettingsModel.standardChatEnabled || chatRoomModel.haveEncryption && SettingsModel.secureChatEnabled) - ExclusiveButtons { - id: filterButtons - anchors { - left: parent.left - leftMargin: ConversationStyle.filters.leftMargin - verticalCenter: parent.verticalCenter - } - - texts: [ - qsTr('displayCallsAndMessages'), - qsTr('displayCalls'), - qsTr('displayMessages') - ] - - onClicked: Logic.updateChatFilter(button) - } + BusyIndicator{ id: chatLoading width: 20 height: 20 - anchors.left: filterButtons.right - anchors.leftMargin: 50 + anchors.left: parent.left + anchors.leftMargin: parent.width/3 anchors.verticalCenter: parent.verticalCenter color: BusyIndicatorStyle.alternateColor.color running: chatArea.tryingToLoadMoreEntries @@ -654,6 +639,7 @@ ColumnLayout { } width: parent.width-14 icon: text != '' ? 'close_custom' : 'search_custom' + iconSize: 30 overwriteColor: ConversationStyle.filters.iconColor.color //: 'Search in messages' : this is a placeholder when searching something in the timeline list placeholderText: qsTr('searchMessagesPlaceholder') diff --git a/linphone-app/ui/views/App/Main/Conversations.qml b/linphone-app/ui/views/App/Main/Conversations.qml new file mode 100644 index 000000000..597ecd3e4 --- /dev/null +++ b/linphone-app/ui/views/App/Main/Conversations.qml @@ -0,0 +1,55 @@ +import QtQuick 2.7 +import QtQuick.Layouts 1.3 + +import Clipboard 1.0 +import Common 1.0 +import Linphone 1.0 +import Utils 1.0 +import UtilsCpp 1.0 +import LinphoneEnums 1.0 + +import App.Styles 1.0 +import Common.Styles 1.0 +import Units 1.0 + +import ColorsList 1.0 + + +import 'Conversation.js' as Logic + +// ============================================================================= +RowLayout{ + spacing: 0 + Component.onDestruction: timeline.model.unselectAll() + + Timeline{ + id: timeline + Layout.fillHeight: true + Layout.preferredWidth: MainWindowStyle.menu.width + + showHistoryButton: false + + onEntrySelected:{ + if( entry ) { + if( entry.selected){ + console.debug("Load conversation from entry selected on timeline") + content.setSource('Conversation.qml', { + chatRoomModel:entry.chatRoomModel + }) + } + }else{ + //window.setView('Home', {}) + } + //menu.resetSelectedEntry() + } + onShowHistoryRequest: { + //timeline.model.unselectAll() + //window.setView('HistoryView') + } + } + Loader{ + id: content + Layout.fillHeight: true + Layout.fillWidth: true + } +} diff --git a/linphone-app/ui/views/App/Main/HistoryView.js b/linphone-app/ui/views/App/Main/HistoryView.js index 844d644f2..36227b180 100644 --- a/linphone-app/ui/views/App/Main/HistoryView.js +++ b/linphone-app/ui/views/App/Main/HistoryView.js @@ -34,7 +34,7 @@ function removeAllEntries () { }, function (status) { if (status) { historyProxyModel.removeAllEntries() - window.setView('Home') + //window.setView('Home') } }) } diff --git a/linphone-app/ui/views/App/Main/HistoryView.qml b/linphone-app/ui/views/App/Main/HistoryView.qml index 17250e807..7dab1e14a 100644 --- a/linphone-app/ui/views/App/Main/HistoryView.qml +++ b/linphone-app/ui/views/App/Main/HistoryView.qml @@ -14,9 +14,10 @@ import 'HistoryView.js' as Logic ColumnLayout { id: historyView - property var entry + property var entry: callHistoryModel property string peerAddress : entry ? entry.sipAddress : '' property string fullPeerAddress : entry ? entry.sipAddress : '' + property alias callHistoryModel: historyProxyModel.callHistoryModel property var _sipAddressObserver: peerAddress?SipAddressesModel.getSipAddressObserver((fullPeerAddress?fullPeerAddress:peerAddress), ''):null @@ -114,14 +115,24 @@ ColumnLayout { visible: peerAddress && SettingsModel.standardChatEnabled && SettingsModel.getShowStartChatButton() && !historyView.entry.wasConference - onClicked: CallsListModel.launchChat(historyView.peerAddress, 0) + onClicked: { + var model = CallsListModel.launchChat(historyView.peerAddress, 0) + if(model && model.chatRoomModel) { + window.setView('Conversations') + } + } } ActionButton { isCustom: true backgroundRadius: 1000 colorSet: HistoryViewStyle.chat visible: peerAddress && SettingsModel.secureChatEnabled && SettingsModel.getShowStartChatButton() && !historyView.entry.wasConference - onClicked: CallsListModel.launchChat(historyView.peerAddress, 1) + onClicked: { + var model = CallsListModel.launchChat(historyView.peerAddress, 1) + if(model && model.chatRoomModel) { + window.setView('Conversations') + } + } Icon{ icon:'secure_level_1' iconSize: parent.height/2 diff --git a/linphone-app/ui/views/App/Main/MainWindow.js b/linphone-app/ui/views/App/Main/MainWindow.js index 81711be64..7f7637f53 100644 --- a/linphone-app/ui/views/App/Main/MainWindow.js +++ b/linphone-app/ui/views/App/Main/MainWindow.js @@ -104,15 +104,21 @@ function manageAccounts () { function updateSelectedEntry (view, props) { var item = mainLoader.item - var menu = item.menu + var mainMenu = item.mainMenu var timeline = item.timeline if (view === 'Home') { - menu.resetSelectedEntry() + mainMenu.currentMenu = 0 + } else if (view === 'Calls') { + mainMenu.currentMenu = 1 + } else if (view === 'Conversations') { + mainMenu.currentMenu = 2 } else if (view === 'Contacts') { - item.contactsEntry.select() + mainMenu.currentMenu = 3 } else if (view === 'Conferences') { - item.conferencesEntry.select() + mainMenu.currentMenu = 4 + }else{ + mainMenu.currentMenu = -1 } } diff --git a/linphone-app/ui/views/App/Main/MainWindow.qml b/linphone-app/ui/views/App/Main/MainWindow.qml index fbce85445..392f57d8e 100644 --- a/linphone-app/ui/views/App/Main/MainWindow.qml +++ b/linphone-app/ui/views/App/Main/MainWindow.qml @@ -72,13 +72,10 @@ ApplicationWindow { sourceComponent: ColumnLayout { // Workaround to get these properties in `MainWindow.js`. - readonly property alias contactsEntry: contactsEntry - readonly property alias conferencesEntry: conferencesEntry - readonly property alias contentLoader: contentLoader - readonly property alias menu: menu + readonly property alias mainMenu: mainMenu - readonly property alias timeline: timeline + //readonly property alias timeline: timeline readonly property alias mainSearchBar: toolBar.mainSearchBar spacing: 0 @@ -110,28 +107,14 @@ ApplicationWindow { } spacing: MainWindowStyle.toolBar.spacing - ActionButton { - icon: (leftPanel.visible?'panel_shown':'panel_hidden') + Avatar { + id: avatar + Layout.preferredHeight: smartSearchBar.height + Layout.preferredWidth: height - //: 'Hide Timeline' : Tooltip for a button that hide the timeline - tooltipText : (leftPanel.visible?qsTr('hideTimeline') - //: 'Open Timeline' : Tooltip for a button that open the timeline - :qsTr('openTimeline')) - iconSize: MainWindowStyle.panelButtonSize - //autoIcon: true - onClicked: leftPanel.visible = !leftPanel.visible + presenceLevel: OwnPresenceModel.presenceStatus===Presence.Offline?Presence.White:( SettingsModel.rlsUriEnabled ? OwnPresenceModel.presenceLevel : Presence.Green) + username: UtilsCpp.getDisplayName(AccountSettingsModel.username) } - ActionButton { - id: home - isCustom: true - backgroundRadius: 4 - colorSet: MainWindowStyle.buttons.home - //: 'Open Home' : Tooltip for a button that open the home view - tooltipText : qsTr('openHome') - //autoIcon: true - onClicked: setView('Home') - } - AccountStatus { id: accountStatus betterIcon:true @@ -198,11 +181,22 @@ ApplicationWindow { } onLaunchCall: CallsListModel.launchAudioCall(sipAddress, '') - onLaunchChat: CallsListModel.launchChat( sipAddress,0 ) - onLaunchSecureChat: CallsListModel.launchChat( sipAddress,1 ) + onLaunchChat: { + var model = CallsListModel.launchChat( sipAddress,0 ) + if(model && model.chatRoomModel) { + window.setView('Conversations') + } + } + onLaunchSecureChat: { + var model = CallsListModel.launchChat( sipAddress,1 ) + if(model && model.chatRoomModel) { + window.setView('Conversations') + } + } onLaunchVideoCall: CallsListModel.launchVideoCall(sipAddress, '') } ActionButton { + Layout.leftMargin: 30 isCustom: true backgroundRadius: 90 colorSet: MainWindowStyle.buttons.telKeyad @@ -210,7 +204,6 @@ ApplicationWindow { toggled: telKeypad.visible } ActionButton { - Layout.leftMargin: 30 isCustom: true backgroundRadius: 4 colorSet: MainWindowStyle.buttons.newChatGroup @@ -257,23 +250,6 @@ ApplicationWindow { text: qsTr('newConferenceUriMissing') } } - - ActionButton { - isCustom: true - backgroundRadius: 4 - colorSet: MainWindowStyle.buttons.burgerMenu - visible: Qt.platform.os !== 'osx' - - toggled: menuBar.isOpenned - onClicked: toggled ? menuBar.close() : menuBar.open()// a bit useless as Menu will depopup on losing focus but this code is kept for giving idea - MainWindowMenuBar { - id: menuBar - onDisplayRecordings: { - timeline.model.unselectAll() - setView('Recordings') - } - } - } } } @@ -288,115 +264,114 @@ ApplicationWindow { spacing: 0 // Main menu. - ColumnLayout { - id:leftPanel - Layout.maximumWidth: MainWindowStyle.menu.width - Layout.preferredWidth: MainWindowStyle.menu.width + Rectangle{ + id: mainMenu + property int currentMenu: 0 - spacing: 0 - - ApplicationMenu { - id: menu + Layout.fillHeight: true + Layout.preferredWidth: MainWindowStyle.menu.leftMargin + MainWindowStyle.menu.rightMargin + MainWindowStyle.menu.buttonSize + color: '#F3F3F3' + ColumnLayout { + anchors.fill: parent + spacing: 2*MainWindowStyle.menu.spacing + anchors.topMargin: MainWindowStyle.menu.spacing + anchors.bottomMargin: MainWindowStyle.menu.spacing + anchors.leftMargin: MainWindowStyle.menu.leftMargin + anchors.rightMargin: MainWindowStyle.menu.rightMargin - defaultSelectedEntry: null - entryHeight: MainWindowStyle.menu.height+10 - entryWidth: MainWindowStyle.menu.width - - ApplicationMenuEntry { - id: contactsEntry - - icon: MainWindowStyle.menu.contacts.icon - iconSize: MainWindowStyle.menu.contacts.iconSize - overwriteColor: isSelected ? MainWindowStyle.menu.contacts.selectedColor.color : MainWindowStyle.menu.contacts.colorModel.color - name: LdapListModel.count > 0 - //: 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application. - ? qsTr('localContactsEntry').toUpperCase() - //: 'Contacts' : Contacts section label in main waindow. - : qsTr('contactsEntry').toUpperCase() - - visible: SettingsModel.contactsEnabled - - onSelected: { + ActionButton { + id: homeButton + isCustom: true + backgroundRadius: 4 + colorSet: MainWindowStyle.buttons.home + //: 'Open Home' : Tooltip for a button that open the home view + tooltipText : qsTr('openHome') + //autoIcon: true + toggled: mainMenu.currentMenu == 0 + onClicked: window.setView('Home') + } + ActionButton { + isCustom: true + backgroundRadius: 4 + colorSet: MainWindowStyle.buttons.callHistoryMenu + //: 'Open call history' : Tooltip for a button that open the call history view + tooltipText : qsTr('openCalls') + //autoIcon: true + toggled: mainMenu.currentMenu == 1 + onClicked: { + window.setView('Calls') + } + MessageCounter { + id: callCounter + anchors.horizontalCenter: parent.right + anchors.verticalCenter: parent.top + count: AccountSettingsModel.missedCallsCount + } + } + ActionButton { + isCustom: true + backgroundRadius: 4 + colorSet: MainWindowStyle.buttons.chatMenu + //: 'Open chats' : Tooltip for a button that open the conversations view + tooltipText : qsTr('openChats') + //autoIcon: true + toggled: mainMenu.currentMenu == 2 + onClicked: { + onClicked: window.setView('Conversations') + } + MessageCounter { + id: messageCounter + anchors.horizontalCenter: parent.right + anchors.verticalCenter: parent.top + count: AccountSettingsModel.unreadMessagesCount + } + } + ActionButton { + isCustom: true + backgroundRadius: 4 + colorSet: MainWindowStyle.buttons.contactsMenu + //: 'Open contacts' : Tooltip for a button that open the contacts view + tooltipText : qsTr('openContacts') + //autoIcon: true + toggled: mainMenu.currentMenu == 3 + onClicked: { ContactsListModel.update() - timeline.model.unselectAll() - setView('Contacts') - } - onClicked:{ - ContactsListModel.update() - setView('Contacts') - } - Icon{ - anchors.right:parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.rightMargin: 10 - icon: MainWindowStyle.menu.direction.icon - overwriteColor: contactsEntry.overwriteColor - iconSize: MainWindowStyle.menu.direction.iconSize - + window.setView('Contacts') } } - - ApplicationMenuEntry { - id: conferencesEntry + ActionButton { + isCustom: true + backgroundRadius: 4 + colorSet: MainWindowStyle.buttons.meetingsMenu + //: 'Open meetings' : Tooltip for a button that open the meetings list + tooltipText : qsTr('openMeetings') + //autoIcon: true + toggled: mainMenu.currentMenu == 4 + onClicked: { + window.setView('Conferences') + } + } + Item{ + Layout.fillHeight: true + } + ActionButton { + isCustom: true + backgroundRadius: 4 + colorSet: MainWindowStyle.buttons.settingsMenu + visible: Qt.platform.os !== 'osx' - icon: MainWindowStyle.menu.conferences.icon - iconSize: MainWindowStyle.menu.conferences.iconSize - overwriteColor: isSelected ? MainWindowStyle.menu.conferences.selectedColor.color : MainWindowStyle.menu.conferences.colorModel.color - //: 'Meetings' : Meeting title for main window. - name: qsTr('mainWindowConferencesTitle').toUpperCase() - visible: SettingsModel.videoConferenceEnabled && SettingsModel.conferenceEnabled - - onSelected: { - timeline.model.unselectAll() - setView('Conferences') - } - onClicked:{ - setView('Conferences') - } - Icon{ - anchors.right:parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.rightMargin: 10 - icon: MainWindowStyle.menu.direction.icon - overwriteColor: conferencesEntry.overwriteColor - iconSize: MainWindowStyle.menu.direction.iconSize - } - } - } - - // History. - Timeline { - id: timeline - - Layout.fillHeight: true - Layout.fillWidth: true - model: TimelineProxyModel{ - listSource: TimelineProxyModel.Main - onListSourceChanged: console.log("listSourceChanged") - } - - onEntrySelected:{ - if( entry ) { - if( entry.selected){ - console.debug("Load conversation from entry selected on timeline") - window.setView('Conversation', { - chatRoomModel:entry.chatRoomModel - }) + toggled: menuBar.isOpenned + onClicked: toggled ? menuBar.close() : menuBar.open()// a bit useless as Menu will depopup on losing focus but this code is kept for giving idea + MainWindowMenuBar { + id: menuBar + onDisplayRecordings: { + setView('Recordings') } - }else{ - - window.setView('Home', {}) } - menu.resetSelectedEntry() - } - onShowHistoryRequest: { - timeline.model.unselectAll() - window.setView('HistoryView') } } } - // Main content. Item{ Layout.fillHeight: true @@ -427,8 +402,6 @@ ApplicationWindow { active:Qt.platform.os === 'osx' sourceComponent:MainWindowTopMenuBar{ onDisplayRecordings: { - if(mainLoader.item) - mainLoader.item.timeline.model.unselectAll() setView('Recordings') } } diff --git a/linphone-app/ui/views/App/Styles/Main/ContactsStyle.qml b/linphone-app/ui/views/App/Styles/Main/ContactsStyle.qml index b0b4c5b14..46d293c5e 100644 --- a/linphone-app/ui/views/App/Styles/Main/ContactsStyle.qml +++ b/linphone-app/ui/views/App/Styles/Main/ContactsStyle.qml @@ -12,14 +12,16 @@ QtObject { property int spacing: 20 property QtObject filter: QtObject { - property string icon: 'filter_custom' + property string icon: 'search_custom' property var colorModel: ColorsList.add(sectionName+'_filter_icon', 'c') } property QtObject bar: QtObject { property var backgroundColor: ColorsList.add(sectionName+'_bar_bg', 'e') + property var foregroundColor: ColorsList.add(sectionName+'_bar_fg', 'd') property int height: 60 property int leftMargin: 18 property int rightMargin: 18 + property int pointSize: Units.dp * 11 } property QtObject contact: QtObject { diff --git a/linphone-app/ui/views/App/Styles/Main/MainWindowStyle.qml b/linphone-app/ui/views/App/Styles/Main/MainWindowStyle.qml index affd15280..69f861522 100644 --- a/linphone-app/ui/views/App/Styles/Main/MainWindowStyle.qml +++ b/linphone-app/ui/views/App/Styles/Main/MainWindowStyle.qml @@ -33,6 +33,10 @@ QtObject { property QtObject menu: QtObject { property int height: 50 property int width: 250 + property int leftMargin: 15 + property int rightMargin: 15 + property int spacing: 10 + property int buttonSize: 38 property QtObject direction: QtObject { property string icon: 'panel_arrow_custom' @@ -71,23 +75,26 @@ QtObject { property int height: 70 property int leftMargin: 18 property int rightMargin: 18 - property int spacing: 16 + property int spacing: 10 property var background: Rectangle { property var colorModel: ColorsList.add(sectionName+'_toolbar_bg', 'f') color: colorModel.color } } + property QtObject buttons: QtObject { property QtObject home: QtObject { - property int iconSize: 40 + property int iconSize: menu.buttonSize property string name : 'home' property string icon : 'home_custom' property var backgroundNormalColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'ma_n_b_bg') property var backgroundHoveredColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'ma_h_b_bg') + property var backgroundUpdatingColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 'ma_h_b_bg') property var backgroundPressedColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'ma_p_b_bg') property var foregroundNormalColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'ma_n_b_fg') property var foregroundHoveredColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'ma_h_b_fg') + property var foregroundUpdatingColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 'ma_h_b_fg') property var foregroundPressedColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'ma_p_b_fg') } property QtObject telKeyad: QtObject { @@ -109,10 +116,12 @@ QtObject { property string icon : 'new_chat_group_custom' property var backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'ma_n_b_bg') property var backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'ma_h_b_bg') + property var backgroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 'ma_h_b_bg') property var backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'ma_p_b_bg') property var backgroundDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_d', icon, 'ma_d_b_bg') property var foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'ma_n_b_fg') property var foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'ma_h_b_fg') + property var foregroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 'ma_h_b_fg') property var foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'ma_p_b_fg') property var foregroundDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_d', icon, 'ma_d_b_fg') } @@ -122,15 +131,17 @@ QtObject { property string icon : 'conference_custom' property var backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'ma_n_b_bg') property var backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'ma_h_b_bg') + property var backgroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 'ma_h_b_bg') property var backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'ma_p_b_bg') property var backgroundDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_d', icon, 'ma_d_b_bg') property var foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'ma_n_b_fg') property var foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'ma_h_b_fg') + property var foregroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 'ma_h_b_fg') property var foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'ma_p_b_fg') property var foregroundDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_d', icon, 'ma_d_b_fg') } property QtObject burgerMenu: QtObject { - property int iconSize: 40 + property int iconSize: menu.buttonSize property string name : 'burgerMenu' property string icon : 'burger_menu_custom' property var backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'l_n_b_bg') @@ -142,5 +153,73 @@ QtObject { property var foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'l_h_b_fg') property var foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'l_p_b_fg') } + property QtObject settingsMenu: QtObject { + property int iconSize: menu.buttonSize + property string name : 'settingsMenu' + property string icon : 'options_custom' + property var backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'l_n_b_bg') + property var backgroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 'l_u_b_bg') + property var backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'l_h_b_bg') + property var backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'l_p_b_bg') + property var foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'l_n_b_fg') + property var foregroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 'l_u_b_fg') + property var foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'l_h_b_fg') + property var foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'l_p_b_fg') + } + property QtObject callHistoryMenu: QtObject { + property int iconSize: menu.buttonSize + property string name : 'callHistory' + property string icon : 'call_history_custom' + property var backgroundNormalColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'ma_n_b_bg') + property var backgroundHoveredColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'ma_h_b_bg') + property var backgroundUpdatingColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 'ma_h_b_bg') + property var backgroundPressedColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'ma_p_b_bg') + property var foregroundNormalColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'ma_n_b_fg') + property var foregroundHoveredColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'ma_h_b_fg') + property var foregroundUpdatingColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 'ma_h_b_fg') + property var foregroundPressedColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'ma_p_b_fg') + } + property QtObject chatMenu: QtObject { + property int iconSize: menu.buttonSize + property string name : 'chat' + property string icon : 'chat_custom' + property var backgroundNormalColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'ma_n_b_bg') + property var backgroundHoveredColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'ma_h_b_bg') + property var backgroundUpdatingColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 'ma_h_b_bg') + property var backgroundPressedColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'ma_p_b_bg') + property var foregroundNormalColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'ma_n_b_fg') + property var foregroundHoveredColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'ma_h_b_fg') + property var foregroundUpdatingColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 'ma_h_b_fg') + property var foregroundPressedColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'ma_p_b_fg') + } + + property QtObject contactsMenu: QtObject { + property int iconSize: menu.buttonSize + property string name : 'contacts' + property string icon : 'contact_custom' + property var backgroundNormalColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'ma_n_b_bg') + property var backgroundHoveredColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'ma_h_b_bg') + property var backgroundUpdatingColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 'ma_h_b_bg') + property var backgroundPressedColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'ma_p_b_bg') + property var foregroundNormalColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'ma_n_b_fg') + property var foregroundHoveredColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'ma_h_b_fg') + property var foregroundUpdatingColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 'ma_h_b_fg') + property var foregroundPressedColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'ma_p_b_fg') + } + + property QtObject meetingsMenu: QtObject { + property int iconSize: menu.buttonSize + property string name : 'meetings' + property string icon : 'meetings_custom' + property var backgroundNormalColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'ma_n_b_bg') + property var backgroundHoveredColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'ma_h_b_bg') + property var backgroundUpdatingColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 'ma_h_b_bg') + property var backgroundPressedColor: ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'ma_p_b_bg') + property var foregroundNormalColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'ma_n_b_fg') + property var foregroundHoveredColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'ma_h_b_fg') + property var foregroundUpdatingColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 'ma_h_b_fg') + property var foregroundPressedColor: ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'ma_p_b_fg') + } + } } diff --git a/linphone-sdk b/linphone-sdk index 0063e1fb6..fd8702387 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit 0063e1fb69a31662edb86e73f537b3eb854c7cfe +Subproject commit fd870238723c152091426e6554e41e0e59fefe0a