Quickfixes Contacts.

- losing focus after search.
- sections margins.
- hide magic search popup on loading instead of showing spinner.
- Display complete suggestions in participants/calls/magicBar.
- Limit adaptation with suggestions/contacts.
- Empty list when only suggestions.
- Avoid autoscroll outside lists.
- ResetSelection after contact deletion.
This commit is contained in:
Julien Wadel 2024-11-21 09:49:01 +01:00
parent ea2612acbb
commit f847054385
7 changed files with 71 additions and 57 deletions

View file

@ -87,6 +87,12 @@ public:
AbstractListProxy<QSharedPointer<QObject>>::prepend(items);
}
virtual void resetData() {
beginResetModel();
mList.clear();
endResetModel();
}
template <class T>
void resetData(QList<QSharedPointer<T>> items) {
beginResetModel();

View file

@ -79,6 +79,7 @@ void MagicSearchList::setSelf(QSharedPointer<MagicSearchList> me) {
&MagicSearchList::lSearch,
[this](QString filter, int sourceFlags, LinphoneEnums::MagicSearchAggregation aggregationFlag,
int maxResults) {
resetData();
mModelConnection->invokeToModel([this, filter, sourceFlags, aggregationFlag, maxResults]() {
mMagicSearch->search(filter, sourceFlags, aggregationFlag, maxResults);
});

View file

@ -50,9 +50,9 @@ void MagicSearchModel::search(QString filter,
!SettingsModel::getInstance()->getSyncLdapContacts())
sourceFlags &= ~(int)LinphoneEnums::MagicSearchSource::LdapServers;
// For complete search, we search only on local contacts.
sourceFlags &= ~(int)LinphoneEnums::MagicSearchSource::CallLogs;
sourceFlags &= ~(int)LinphoneEnums::MagicSearchSource::ChatRooms;
sourceFlags &= ~(int)LinphoneEnums::MagicSearchSource::ConferencesInfo;
// sourceFlags &= ~(int)LinphoneEnums::MagicSearchSource::CallLogs;
// sourceFlags &= ~(int)LinphoneEnums::MagicSearchSource::ChatRooms;
// sourceFlags &= ~(int)LinphoneEnums::MagicSearchSource::ConferencesInfo;
}
qInfo() << log().arg("Searching ") << filter << " from " << sourceFlags << " with limit " << maxResults;
mMonitor->getContactsListAsync(filter != "*" ? Utils::appStringToCoreString(filter) : "", "", sourceFlags,

View file

@ -45,7 +45,7 @@ Flickable{
property int sectionsSpacing: 18 * DefaultStyle.dp
property int itemsRightMargin: 39 * DefaultStyle.dp
property int count: contactsList.count
property int count: contactsList.count + suggestionsList.count + favoritesList.count
signal resultsReceived()
signal contactStarredChanged()
@ -94,6 +94,13 @@ Flickable{
return index != -1
}
function resetSelections(){
mainItem.highlightedContact = null
favoritesList.currentIndex = -1
contactsList.currentIndex = -1
suggestionsList.currentIndex = -1
}
onHighlightedContactChanged:{
favoritesList.highlightedContact = highlightedContact
contactsList.highlightedContact = highlightedContact
@ -116,7 +123,7 @@ Flickable{
}
onSearchTextChanged: loading = true
onAtYEndChanged: if(atYEnd) {
if( contactsProxy.haveMore || mainItem.hideSuggestions) contactsProxy.displayMore()
if( (contactsProxy.haveMore && contactList.expanded ) || mainItem.hideSuggestions) contactsProxy.displayMore()
else suggestionsProxy.displayMore()
}
function findNextList(item, count, direction){
@ -134,7 +141,7 @@ Flickable{
function updatePosition(list){
var item = list.itemAtIndex(list.currentIndex)
var centerPos = list.y - height/2
if( item){
if( item && list.expanded){
// For debugging just in case
//var listPosition = item.mapToItem(favoriteList, item.x, item.y)
//var newPosition = favoriteList.mapToItem(mainItem, listPosition.x, listPosition.y)
@ -149,7 +156,7 @@ Flickable{
//console.log("Moving to " + (headerItem.y+item.y))
centerPos += item.y
}
mainItem.contentY = Math.max(0, centerPos)
mainItem.contentY = Math.min(Math.max(0, centerPos), mainItem.contentHeight - mainItem.height)
}
Behavior on contentY{
NumberAnimation {
@ -163,9 +170,9 @@ Flickable{
var newItem
var direction = (event.key == Qt.Key_Up ? -1 : 1)
if(suggestionsList.activeFocus) newItem = findNextList(suggestionsList, 0, direction)
if(contactsList.activeFocus) newItem = findNextList(contactsList, 0, direction)
if(favoritesList.activeFocus) newItem = findNextList(favoritesList, 0, direction)
else if(contactsList.activeFocus) newItem = findNextList(contactsList, 0, direction)
else if(favoritesList.activeFocus) newItem = findNextList(favoritesList, 0, direction)
else newItem = findNextList(suggestionsList, 0, direction)
if(newItem){
newItem.selectIndex(direction > 0 ? -1 : newItem.model.count - 1)
event.accepted = true
@ -194,7 +201,10 @@ Flickable{
searchText: mainItem.searchText
aggregationFlag: LinphoneEnums.MagicSearchAggregation.Friend
sourceFlags: mainItem.sourceFlags
onModelReset: mainItem.resultsReceived()
onModelReset: {
mainItem.resetSelections()
mainItem.resultsReceived()
}
onInitialized: {
if(mainItem.searchOnEmpty || searchText != '' ) {
@ -219,7 +229,7 @@ Flickable{
ColumnLayout{
id: contentsLayout
width: parent.width
spacing: 0
BusyIndicator {
Layout.alignment: Qt.AlignCenter
Layout.preferredHeight: visible ? 60 * DefaultStyle.dp : 0
@ -265,6 +275,7 @@ Flickable{
id: contactsList
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight
Layout.topMargin: favoritesList.height > 0 ? 4 * DefaultStyle.dp : 0
interactive: false
highlightText: mainItem.highlightText
showActions: mainItem.showActions
@ -284,7 +295,7 @@ Flickable{
onContactDeletionRequested: (contact) => {mainItem.contactDeletionRequested(contact)}
onAddContactToSelection: (address) => {mainItem.addContactToSelection(address)}
onRemoveContactFromSelection: (index) => {mainItem.removeContactFromSelection(index)}
model:MagicSearchProxy {
id: contactsProxy
parentProxy: mainItem.mainModel
@ -300,6 +311,7 @@ Flickable{
id: suggestionsList
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight
Layout.topMargin: contactsList.height + favoritesList.height > 0 ? 4 * DefaultStyle.dp : 0
interactive: false
showInitials: false
highlightText: mainItem.highlightText
@ -319,13 +331,14 @@ Flickable{
onContactDeletionRequested: (contact) => {mainItem.contactDeletionRequested(contact)}
onAddContactToSelection: (address) => {mainItem.addContactToSelection(address)}
onRemoveContactFromSelection: (index) => {mainItem.removeContactFromSelection(index)}
model:MagicSearchProxy {
id: suggestionsProxy
parentProxy: mainItem.mainModel
filterType: mainItem.hideSuggestions ? MagicSearchProxy.FilteringTypes.None : MagicSearchProxy.FilteringTypes.Other
initialDisplayItems: 0
initialDisplayItems: contactsProxy.haveMore && contactsList.expanded ? 0 : 20
onInitialDisplayItemsChanged: maxDisplayItems = initialDisplayItems
displayItemsStep: 5
onModelReset: maxDisplayItems = initialDisplayItems
}
}
}

View file

@ -6,7 +6,7 @@ import Linphone
import UtilsCpp 1.0
import ConstantsCpp 1.0
import SettingsCpp
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils
ListView {
id: mainItem
@ -53,8 +53,8 @@ ListView {
clip: true
highlightFollowsCurrentItem: false
cacheBuffer: 400
implicitHeight: contentHeight + headerItem?.height
spacing: 4 * DefaultStyle.dp
implicitHeight: contentHeight
spacing: expanded ? 4 * DefaultStyle.dp : 0
property bool _moveToIndex: false
@ -72,14 +72,17 @@ ListView {
}else{
mainItem.currentIndex = -1
mainItem.highlightedContact = null
if(headerItem) headerItem.forceActiveFocus()
if(headerItem) {
headerItem.forceActiveFocus()
}
}
}
onCountChanged: if(_moveToIndex >= 0 && count > mainItem.currentIndex ){
onCountChanged: if(_moveToIndex && count > mainItem.currentIndex ){
_moveToIndex = false
selectIndex(mainItem.currentIndex)
}
}
onContactSelected: updatePosition()
onExpandedChanged: if(!expanded) updatePosition()
keyNavigationEnabled: false
Keys.onPressed: (event)=> {
if(event.key == Qt.Key_Up || event.key == Qt.Key_Down){
@ -123,10 +126,11 @@ ListView {
ColumnLayout {
id: headerContents
width: parent.width
spacing: mainItem.count > 0 ? sectionsSpacing : 0
spacing: 0
Item{// Do not use directly RowLayout : there is an issue where the layout doesn't update on visible
Layout.fillWidth: true
Layout.preferredHeight: mainItem.count > 0 ? headerTitleLayout.implicitHeight : 0
Layout.bottomMargin: 4 * DefaultStyle.dp
RowLayout {
id: headerTitleLayout
anchors.fill: parent
@ -182,7 +186,7 @@ ListView {
onIsSelectedChanged: if(isSelected) mainItem.currentIndex = index
onContactDeletionRequested: (contact) => mainItem.contactDeletionRequested(contact)
onClicked: (mouse) => {
if (mouse && mouse.button == Qt.RightButton) {
friendPopup.open()

View file

@ -198,11 +198,11 @@ Item {
width: magicSearchBar.width
property int maxHeight: 400 * DefaultStyle.dp
property bool displayScrollbar: contactList.contentHeight + topPadding + bottomPadding> maxHeight
height: Math.min(contactList.contentHeight + topPadding + bottomPadding, maxHeight)
height: contactList.haveContacts ? Math.min(contactList.contentHeight + topPadding + bottomPadding, maxHeight) : 0
y: magicSearchBar.height
// closePolicy: Popup.NoAutoClose
topPadding: 20 * DefaultStyle.dp
bottomPadding: 20 * DefaultStyle.dp
topPadding: contactList.haveContacts ? 20 * DefaultStyle.dp : 0
bottomPadding: contactList.haveContacts ? 20 * DefaultStyle.dp : 0
rightPadding: 10 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp
@ -240,8 +240,8 @@ Item {
}
contentItem: AllContactListView {
id: contactList
visible: magicSearchBar.text.length != 0
Layout.preferredHeight: contentHeight
visible: !loading && magicSearchBar.text.length != 0
Layout.preferredHeight: visible ? contentHeight : 0
Layout.fillWidth: true
itemsRightMargin: 5 * DefaultStyle.dp //(Actions have already 10 of margin)
showInitials: false

View file

@ -20,7 +20,7 @@ AbstractMainPage {
onVisibleChanged: if (!visible) {
rightPanelStackView.clear()
if(contactLoader.item) contactLoader.item.currentIndex = -1
contactList.resetSelections()
}
onSelectedContactChanged: {
@ -51,7 +51,7 @@ AbstractMainPage {
// rightPanelStackView.initialItem: contactDetail
showDefaultItem: rightPanelStackView.depth == 0 && contactLoader.item?.count === 0 && searchBar.text.length === 0
showDefaultItem: rightPanelStackView.depth == 0 && !contactList.haveContacts && searchBar.text.length === 0
function deleteContact(contact) {
if (!contact) return
@ -63,6 +63,7 @@ AbstractMainPage {
if (confirmed) {
var name = contact.core.fullName
contact.core.remove()
contactList.resetSelections()
UtilsCpp.showInformationPopup(qsTr("Supprimé"), qsTr("%1 a été supprimé").arg(name)) }
}
)
@ -211,13 +212,13 @@ AbstractMainPage {
Layout.fillWidth: true
placeholderText: qsTr("Rechercher un contact")
KeyNavigation.up: createContactButton
KeyNavigation.down: contactLoader.item
KeyNavigation.down: contactList
}
ColumnLayout {
id: content
spacing: 15 * DefaultStyle.dp
Text {
visible: contactLoader.item && !contactLoader.item.loading && !contactLoader.item.haveContacts
visible: !contactList.loading && !contactList.haveContacts
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: 137 * DefaultStyle.dp
text: qsTr("Aucun contact%1").arg(searchBar.text.length !== 0 ? " correspondant" : "")
@ -226,35 +227,24 @@ AbstractMainPage {
weight: 800 * DefaultStyle.dp
}
}
Loader{
// This is a hack for an incomprehensible behavior on sections title where they doesn't match with their delegate and can be unordered after resetting models.
id: contactLoader
AllContactListView{
id: contactList
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: 45 * DefaultStyle.dp
property string t: searchBar.text
active: leftPanel.visible
onTChanged: {
contactLoader.active = false
Qt.callLater(function(){contactLoader.active=true})
searchBarText: searchBar.text
hideSuggestions: true
showDefaultAddress: false
sourceFlags: LinphoneEnums.MagicSearchSource.Friends | LinphoneEnums.MagicSearchSource.FavoriteFriends | LinphoneEnums.MagicSearchSource.LdapServers
onHighlightedContactChanged: mainItem.selectedContact = highlightedContact
onContactDeletionRequested: (contact) => {
mainItem.deleteContact(contact)
}
//-------------------------------------------------------------
sourceComponent: AllContactListView{
id: contactList
searchBarText: searchBar.text
hideSuggestions: true
showDefaultAddress: false
sourceFlags: LinphoneEnums.MagicSearchSource.Friends | LinphoneEnums.MagicSearchSource.FavoriteFriends | LinphoneEnums.MagicSearchSource.LdapServers
onHighlightedContactChanged: mainItem.selectedContact = highlightedContact
onContactDeletionRequested: (contact) => {
mainItem.deleteContact(contact)
}
onLoadingChanged: {
if(!loading && initialFriendToDisplay.length !== 0) {
Qt.callLater(function(){
if (selectContact(initialFriendToDisplay) != -1) initialFriendToDisplay = ""
})
}
onLoadingChanged: {
if(!loading && initialFriendToDisplay.length !== 0) {
Qt.callLater(function(){
if (selectContact(initialFriendToDisplay) != -1) initialFriendToDisplay = ""
})
}
}
}