From 95df47c7170b4c0d01b91450b42293a97c47ace2 Mon Sep 17 00:00:00 2001 From: ababi <albert.babi@savoirfairelinux.com> Date: Mon, 14 Sep 2020 16:15:28 +0200 Subject: [PATCH] misc: fix contact request UI issues - switch between "conversations" - "invitations" smartlists according to call origin - "Accept Request" button from msg's view header: hide on contact accepted, set on view load according to userType - correct requests smartlist item selection on tab switch - accept incoming call from pending contact makes conversation permanent Gitlab: #74 Change-Id: Iadfef0d7e4032002d8007a4f18a9eae27f7ba230 --- src/accountadapter.cpp | 6 ++ src/accountadapter.h | 1 + src/calladapter.cpp | 16 ++++- src/conversationsadapter.cpp | 71 +++++++------------ src/conversationsadapter.h | 6 +- src/mainview/MainView.qml | 3 +- src/mainview/components/CallStackView.qml | 2 + .../ConversationSmartListContextMenu.qml | 8 ++- .../components/ConversationSmartListView.qml | 2 + .../ConversationSmartListViewItemDelegate.qml | 1 + src/mainview/components/IncomingCallPage.qml | 1 + src/mainview/components/MessageWebView.qml | 3 + .../components/MessageWebViewHeader.qml | 2 + src/mainview/components/SidePanel.qml | 6 +- src/mainview/components/SidePanelTabBar.qml | 49 +++++++------ src/messagesadapter.cpp | 15 ++-- src/messagesadapter.h | 1 + 17 files changed, 113 insertions(+), 80 deletions(-) diff --git a/src/accountadapter.cpp b/src/accountadapter.cpp index 442dbd88f..269ee2ef3 100644 --- a/src/accountadapter.cpp +++ b/src/accountadapter.cpp @@ -285,6 +285,12 @@ AccountAdapter::setSelectedConvId(const QString& convId) LRCInstance::setSelectedConvId(convId); } +lrc::api::profile::Type +AccountAdapter::getCurrentAccountType() +{ + return LRCInstance::getCurrentAccountInfo().profileInfo.type; +} + void AccountAdapter::onCurrentAccountChanged() { diff --git a/src/accountadapter.h b/src/accountadapter.h index 78abf7217..291f067a4 100644 --- a/src/accountadapter.h +++ b/src/accountadapter.h @@ -104,6 +104,7 @@ public: Q_INVOKABLE bool isPreviewing(); Q_INVOKABLE void setCurrAccDisplayName(const QString& text); Q_INVOKABLE void setSelectedConvId(const QString& convId = {}); + Q_INVOKABLE lrc::api::profile::Type getCurrentAccountType(); signals: /* diff --git a/src/calladapter.cpp b/src/calladapter.cpp index 8a4bc29c8..604534d56 100644 --- a/src/calladapter.cpp +++ b/src/calladapter.cpp @@ -100,6 +100,18 @@ CallAdapter::acceptACall(const QString& accountId, const QString& convUid) LRCInstance::getAccountInfo(accountId).callModel->accept(convInfo.callId); auto& accInfo = LRCInstance::getAccountInfo(convInfo.accountId); accInfo.callModel->setCurrentCall(convInfo.callId); + + auto contactUri = convInfo.participants.front(); + if (contactUri.isEmpty()) { + return; + } + try { + auto& contact = accInfo.contactModel->getContact(contactUri); + if (contact.profileInfo.type == lrc::api::profile::Type::PENDING) { + LRCInstance::getCurrentConversationModel()->makePermanent(convInfo.uid); + } + } catch (...) { + } } } @@ -294,7 +306,9 @@ CallAdapter::showNotification(const QString& accountId, const QString& convUid) #else emit LRCInstance::instance().notificationClicked(true); #endif - callSetupMainViewRequired(convInfo.accountId, convInfo.uid); + if (!convInfo.uid.isEmpty()) { + emit callSetupMainViewRequired(convInfo.accountId, convInfo.uid); + } }; emit LRCInstance::instance().updateSmartList(); Utils::showNotification(tr("is calling you"), from, accountId, convUid, onClicked); diff --git a/src/conversationsadapter.cpp b/src/conversationsadapter.cpp index 8d93b5e22..dd90dbc38 100644 --- a/src/conversationsadapter.cpp +++ b/src/conversationsadapter.cpp @@ -30,7 +30,11 @@ ConversationsAdapter::ConversationsAdapter(QObject* parent) : QmlAdapterBase(parent) -{} +{ + connect(this, &ConversationsAdapter::currentTypeFilterChanged, [this]() { + LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_); + }); +} void ConversationsAdapter::safeInit() @@ -56,6 +60,10 @@ ConversationsAdapter::safeInit() &ConversationsAdapter::onCurrentAccountIdChanged); connectConversationModel(); + + setProperty("currentTypeFilter", QVariant::fromValue( + LRCInstance::getCurrentAccountInfo().profileInfo.type)); + } void @@ -71,21 +79,22 @@ ConversationsAdapter::selectConversation(const QString& accountId, const QString auto* convModel = LRCInstance::getAccountInfo(accountId).conversationModel.get(); const auto& convInfo = convModel->getConversationForUID(convUid); - if (LRCInstance::getCurrentConvUid() != convInfo.uid - && convInfo.participants.size() > 0) { + if (LRCInstance::getCurrentConvUid() != convInfo.uid && convInfo.participants.size() > 0) { // If the account is not currently selected, do that first, then // proceed to select the conversation. - auto selectConversation = [convInfo] { + auto selectConversation = [this, convInfo] { auto& accInfo = LRCInstance::getAccountInfo(convInfo.accountId); LRCInstance::setSelectedConvId(convInfo.uid); accInfo.conversationModel->clearUnreadInteractions(convInfo.uid); + + // Set contact filter (for conversation tab selection) + auto& contact = accInfo.contactModel->getContact(convInfo.participants.front()); + setProperty("currentTypeFilter", QVariant::fromValue(contact.profileInfo.type)); }; if (convInfo.accountId != LRCInstance::getCurrAccId()) { Utils::oneShotConnect(&LRCInstance::instance(), &LRCInstance::currentAccountChanged, - [selectConversation] { - selectConversation(); - }); + [selectConversation] { selectConversation(); }); LRCInstance::setSelectedConvId(); // Hack UI LRCInstance::setSelectedAccountId(convInfo.accountId); } else { @@ -117,15 +126,11 @@ ConversationsAdapter::deselectConversation() void ConversationsAdapter::onCurrentAccountIdChanged() { - auto accountId = LRCInstance::getCurrAccId(); - - auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountId); - currentTypeFilter_ = accountInfo.profileInfo.type; - LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type); - updateConversationsFilterWidget(); - disconnectConversationModel(); connectConversationModel(); + + setProperty("currentTypeFilter", QVariant::fromValue( + LRCInstance::getCurrentAccountInfo().profileInfo.type)); } void @@ -141,7 +146,10 @@ ConversationsAdapter::onNewUnreadInteraction(const QString& accountId, auto& accInfo = LRCInstance::getAccountInfo(accountId); auto& contact = accInfo.contactModel->getContact(interaction.authorUri); auto from = Utils::bestNameForContact(contact); - auto onClicked = [this, accountId, convUid, uri = interaction.authorUri] { + auto onClicked = [this, + accountId, + convUid, + uri = interaction.authorUri] { #ifdef Q_OS_WINDOWS emit LRCInstance::instance().notificationClicked(); #else @@ -166,37 +174,11 @@ ConversationsAdapter::updateConversationsFilterWidget() // Update status of "Conversations" and "Invitations". auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount(); if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) { - currentTypeFilter_ = lrc::api::profile::Type::RING; - LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_); + setProperty("currentTypeFilter", QVariant::fromValue(lrc::api::profile::Type::RING)); } showConversationTabs(invites); } -void -ConversationsAdapter::setConversationFilter(const QString& type) -{ - // Set conversation filter according to type, - // type needs to be recognizable by lrc::api::profile::to_type. - if (type.isEmpty()) { - if (LRCInstance::getCurrentAccountInfo().profileInfo.type == lrc::api::profile::Type::RING) - setConversationFilter(lrc::api::profile::Type::RING); - else - setConversationFilter(lrc::api::profile::Type::SIP); - } else { - setConversationFilter(lrc::api::profile::to_type(type)); - } -} - -void -ConversationsAdapter::setConversationFilter(lrc::api::profile::Type filter) -{ - if (currentTypeFilter_ == filter) { - return; - } - currentTypeFilter_ = filter; - LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_); -} - void ConversationsAdapter::refill() { @@ -290,8 +272,9 @@ ConversationsAdapter::connectConversationModel(bool updateFilter) emit updateListViewRequested(); }); - if (updateFilter) - currentConversationModel->setFilter(""); + if (updateFilter) { + currentTypeFilter_ = lrc::api::profile::Type::INVALID; + } return true; } diff --git a/src/conversationsadapter.h b/src/conversationsadapter.h index a127a3814..ec7aac4c6 100644 --- a/src/conversationsadapter.h +++ b/src/conversationsadapter.h @@ -28,6 +28,9 @@ class ConversationsAdapter final : public QmlAdapterBase { Q_OBJECT + + Q_PROPERTY(lrc::api::profile::Type currentTypeFilter MEMBER currentTypeFilter_ NOTIFY + currentTypeFilterChanged) public: explicit ConversationsAdapter(QObject* parent = nullptr); ~ConversationsAdapter() = default; @@ -42,7 +45,6 @@ public: Q_INVOKABLE void deselectConversation(); Q_INVOKABLE void refill(); Q_INVOKABLE void updateConversationsFilterWidget(); - Q_INVOKABLE void setConversationFilter(const QString& type); signals: void showConversation(const QString& accountId, const QString& convUid); @@ -53,6 +55,7 @@ signals: void modelSorted(const QVariant& uri); void updateListViewRequested(); void navigateToWelcomePageRequested(); + void currentTypeFilterChanged(); private slots: void onCurrentAccountIdChanged(); @@ -62,7 +65,6 @@ private slots: const interaction::Info& interaction); private: - void setConversationFilter(lrc::api::profile::Type filter); void backToWelcomePage(); void updateConversationForNewContact(const QString& convUid); diff --git a/src/mainview/MainView.qml b/src/mainview/MainView.qml index daedafc2f..4f830d2e0 100644 --- a/src/mainview/MainView.qml +++ b/src/mainview/MainView.qml @@ -124,6 +124,7 @@ Window { return UtilsAdapter.hasCall(AccountAdapter.currentAccountId) } + // Only called onWidthChanged function recursionStackViewItemMove(stackOne, stackTwo, depth=1) { // Move all items (expect the bottom item) to stacktwo by the same order in stackone. if (stackOne.depth === depth) { @@ -461,7 +462,7 @@ Window { mainViewWindowSidePanel.forceUpdateConversationSmartListView() } - function onContactBanned() { + function onNavigateToWelcomePageRequested() { backToMainView() } } diff --git a/src/mainview/components/CallStackView.qml b/src/mainview/components/CallStackView.qml index 46ee0144d..f2497bcd7 100644 --- a/src/mainview/components/CallStackView.qml +++ b/src/mainview/components/CallStackView.qml @@ -192,6 +192,8 @@ Rectangle { onCallAcceptButtonIsClicked: { CallAdapter.acceptACall(responsibleAccountId, responsibleConvUid) + communicationPageMessageWebView.setSendContactRequestButtonVisible(false) + mainViewWindowSidePanel.selectTab(SidePanelTabBar.Conversations) } onCallCancelButtonIsClicked: { diff --git a/src/mainview/components/ConversationSmartListContextMenu.qml b/src/mainview/components/ConversationSmartListContextMenu.qml index a675332f8..6b096222c 100644 --- a/src/mainview/components/ConversationSmartListContextMenu.qml +++ b/src/mainview/components/ConversationSmartListContextMenu.qml @@ -43,6 +43,7 @@ Item { responsibleAccountId, responsibleConvUid, false) CallAdapter.placeCall() + communicationPageMessageWebView.setSendContactRequestButtonVisible(false) }) ContextMenuGenerator.addMenuItem(qsTr("Start audio call"), "qrc:/images/icons/ic_phone_24px.svg", @@ -51,6 +52,7 @@ Item { responsibleAccountId, responsibleConvUid, false) CallAdapter.placeAudioOnlyCall() + communicationPageMessageWebView.setSendContactRequestButtonVisible(false) }) ContextMenuGenerator.addMenuItem(qsTr("Clear conversation"), @@ -80,7 +82,8 @@ Item { }) } - if ((contactType === Profile.Type.RING || contactType === Profile.Type.PENDING)) { + if ((contactType === Profile.Type.RING || contactType === Profile.Type.PENDING + || contactType === Profile.Type.TEMPORARY)) { if (contactType === Profile.Type.PENDING || !hasCall) { ContextMenuGenerator.addMenuSeparator() } @@ -91,7 +94,10 @@ Item { function (){ MessagesAdapter.acceptInvitation( responsibleConvUid) + communicationPageMessageWebView. + setSendContactRequestButtonVisible(false) }) + ContextMenuGenerator.addMenuItem(JamiStrings.declineContactRequest, "qrc:/images/icons/round-close-24px.svg", function (){ diff --git a/src/mainview/components/ConversationSmartListView.qml b/src/mainview/components/ConversationSmartListView.qml index a6f7ada58..0a21df47b 100644 --- a/src/mainview/components/ConversationSmartListView.qml +++ b/src/mainview/components/ConversationSmartListView.qml @@ -89,6 +89,7 @@ ListView { enabled: root.visible onActivated: { CallAdapter.placeCall() + communicationPageMessageWebView.setSendContactRequestButtonVisible(false) } } @@ -98,6 +99,7 @@ ListView { enabled: root.visible onActivated: { CallAdapter.placeAudioOnlyCall() + communicationPageMessageWebView.setSendContactRequestButtonVisible(false) } } diff --git a/src/mainview/components/ConversationSmartListViewItemDelegate.qml b/src/mainview/components/ConversationSmartListViewItemDelegate.qml index df96d7762..09cbaffbc 100644 --- a/src/mainview/components/ConversationSmartListViewItemDelegate.qml +++ b/src/mainview/components/ConversationSmartListViewItemDelegate.qml @@ -175,6 +175,7 @@ ItemDelegate { UID, false) CallAdapter.placeCall() + communicationPageMessageWebView.setSendContactRequestButtonVisible(false) } } onReleased: { diff --git a/src/mainview/components/IncomingCallPage.qml b/src/mainview/components/IncomingCallPage.qml index d70ee89e0..f7afd3644 100644 --- a/src/mainview/components/IncomingCallPage.qml +++ b/src/mainview/components/IncomingCallPage.qml @@ -156,6 +156,7 @@ Rectangle { incomingCallPage.close() CallAdapter.acceptACall(responsibleAccountId, responsibleConvUid) + communicationPageMessageWebView.setSendContactRequestButtonVisible(false) } } diff --git a/src/mainview/components/MessageWebView.qml b/src/mainview/components/MessageWebView.qml index 41570b70e..1b9dd3636 100644 --- a/src/mainview/components/MessageWebView.qml +++ b/src/mainview/components/MessageWebView.qml @@ -152,14 +152,17 @@ Rectangle { function acceptInvitation() { MessagesAdapter.acceptInvitation() + messageWebViewHeader.sendContactRequestButtonVisible = false } function refuseInvitation() { MessagesAdapter.refuseInvitation() + messageWebViewHeader.sendContactRequestButtonVisible = false } function blockConversation() { MessagesAdapter.blockConversation() + messageWebViewHeader.sendContactRequestButtonVisible = false } function emitMessagesCleared() { diff --git a/src/mainview/components/MessageWebViewHeader.qml b/src/mainview/components/MessageWebViewHeader.qml index d8c696b9d..68e978dc2 100644 --- a/src/mainview/components/MessageWebViewHeader.qml +++ b/src/mainview/components/MessageWebViewHeader.qml @@ -150,6 +150,7 @@ Rectangle { onClicked: { MessagesAdapter.sendContactRequest() CallAdapter.placeAudioOnlyCall() + communicationPageMessageWebView.setSendContactRequestButtonVisible(false) } } @@ -171,6 +172,7 @@ Rectangle { onClicked: { MessagesAdapter.sendContactRequest() CallAdapter.placeCall() + communicationPageMessageWebView.setSendContactRequestButtonVisible(false) } } diff --git a/src/mainview/components/SidePanel.qml b/src/mainview/components/SidePanel.qml index 3ca544c04..04646ea66 100644 --- a/src/mainview/components/SidePanel.qml +++ b/src/mainview/components/SidePanel.qml @@ -61,8 +61,6 @@ Rectangle { function accountChangedUIReset() { contactSearchBar.clearText() - sidePanelTabBar.converstationTabDown = true - sidePanelTabBar.invitationTabDown = false } function refreshAccountComboBox(index) { @@ -80,6 +78,10 @@ Rectangle { conversationSmartListView.updateListView() } + function selectTab(tabIndex) { + sidePanelTabBar.selectTab(tabIndex) + } + // Intended -> since strange behavior will happen without this for stackview. anchors.top: parent.top anchors.fill: parent diff --git a/src/mainview/components/SidePanelTabBar.qml b/src/mainview/components/SidePanelTabBar.qml index e0190b689..b89c46bb5 100644 --- a/src/mainview/components/SidePanelTabBar.qml +++ b/src/mainview/components/SidePanelTabBar.qml @@ -1,4 +1,3 @@ - /* * Copyright (C) 2020 by Savoir-faire Linux * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> @@ -16,18 +15,40 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ + import QtQuick 2.14 import QtQuick.Controls 2.14 import QtQuick.Layouts 1.14 import QtGraphicalEffects 1.12 import net.jami.Models 1.0 +import net.jami.Adapters 1.0 import "../../commoncomponents" TabBar { id: tabBar - property alias converstationTabDown: pageOne.down - property alias invitationTabDown: pageTwo.down + enum TabIndex { + Conversations, + Requests + } + + Connections { + target: ConversationsAdapter + + function onCurrentTypeFilterChanged() { + pageOne.down = ConversationsAdapter.currentTypeFilter !== Profile.Type.PENDING + pageTwo.down = ConversationsAdapter.currentTypeFilter === Profile.Type.PENDING + setCurrentUidSmartListModelIndex() + forceReselectConversationSmartListCurrentIndex() + } + } + + function selectTab(tabIndex) { + ConversationsAdapter.currentTypeFilter = tabIndex === + SidePanelTabBar.Conversations ? AccountAdapter.getCurrentAccountType() : + Profile.Type.PENDING + } + property alias converstationTabWidth: pageOne.width property alias invitationTabWidth: pageTwo.width property alias converstationTabHeight: pageOne.height @@ -76,14 +97,6 @@ TabBar { height: tabBar.height color: JamiTheme.backgroundColor - function showConversations() { - ConversationsAdapter.setConversationFilter("") - pageOne.down = true - pageTwo.down = false - setCurrentUidSmartListModelIndex() - forceReselectConversationSmartListCurrentIndex() - } - Image { id: imgRectOne anchors.horizontalCenter: buttonRectOne.horizontalCenter @@ -135,7 +148,7 @@ TabBar { anchors.fill: parent hoverEnabled: true onPressed: { - buttonRectOne.showConversations() + selectTab(SidePanelTabBar.Conversations) } onReleased: { buttonRectOne.color = JamiTheme.backgroundColor @@ -153,7 +166,7 @@ TabBar { context: Qt.ApplicationShortcut enabled: buttonRectOne.visible onActivated: { - buttonRectOne.showConversations() + selectTab(SidePanelTabBar.Conversations) } } } @@ -195,12 +208,6 @@ TabBar { height: tabBar.height color: JamiTheme.backgroundColor - function showRequests() { - ConversationsAdapter.setConversationFilter("PENDING") - pageTwo.down = true - pageOne.down = false - } - Image { id: imgRectTwo anchors.horizontalCenter: buttonRectTwo.horizontalCenter @@ -254,7 +261,7 @@ TabBar { anchors.fill: parent hoverEnabled: true onPressed: { - buttonRectTwo.showRequests() + selectTab(SidePanelTabBar.Requests) } onReleased: { buttonRectTwo.color = JamiTheme.backgroundColor @@ -272,7 +279,7 @@ TabBar { context: Qt.ApplicationShortcut enabled: buttonRectTwo.visible onActivated: { - buttonRectTwo.showRequests() + selectTab(SidePanelTabBar.Requests) } } } diff --git a/src/messagesadapter.cpp b/src/messagesadapter.cpp index b36eb9226..f1e556b8a 100644 --- a/src/messagesadapter.cpp +++ b/src/messagesadapter.cpp @@ -67,22 +67,18 @@ MessagesAdapter::setupChatView(const QString& uid) QString contactURI = convInfo.participants.at(0); - bool isContact = false; auto selectedAccountId = LRCInstance::getCurrAccId(); auto& accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId); - lrc::api::profile::Type contactType; + lrc::api::profile::Type contactType = lrc::api::profile::Type::INVALID; try { auto contactInfo = accountInfo.contactModel->getContact(contactURI); - if (contactInfo.isTrusted) { - isContact = true; - } contactType = contactInfo.profileInfo.type; } catch (...) { } - bool shouldShowSendContactRequestBtn = !isContact - && contactType != lrc::api::profile::Type::SIP; + bool shouldShowSendContactRequestBtn = (contactType == lrc::api::profile::Type::PENDING + || contactType == lrc::api::profile::Type::TEMPORARY); QMetaObject::invokeMethod(qmlObj_, "setSendContactRequestButtonVisible", @@ -453,7 +449,8 @@ MessagesAdapter::setConversationProfileData(const lrc::api::conversation::Info& try { auto& contact = accInfo->contactModel->getContact(contactUri); auto bestName = Utils::bestNameForConversation(convInfo, *convModel); - setInvitation(contact.profileInfo.type == lrc::api::profile::Type::PENDING, + setInvitation(contact.profileInfo.type == lrc::api::profile::Type::PENDING + || contact.profileInfo.type == lrc::api::profile::Type::TEMPORARY, bestName, contactUri); @@ -652,6 +649,7 @@ MessagesAdapter::refuseInvitation(const QString& convUid) const auto currentConvUid = convUid.isEmpty() ? LRCInstance::getCurrentConvUid() : convUid; LRCInstance::getCurrentConversationModel()->removeConversation(currentConvUid, false); setInvitation(false); + emit navigateToWelcomePageRequested(); } void @@ -661,4 +659,5 @@ MessagesAdapter::blockConversation(const QString& convUid) LRCInstance::getCurrentConversationModel()->removeConversation(currentConvUid, true); setInvitation(false); emit contactBanned(); + emit navigateToWelcomePageRequested(); } diff --git a/src/messagesadapter.h b/src/messagesadapter.h index 41c89a5f6..05b2611d3 100644 --- a/src/messagesadapter.h +++ b/src/messagesadapter.h @@ -88,6 +88,7 @@ protected: signals: void needToUpdateSmartList(); void contactBanned(); + void navigateToWelcomePageRequested(); public slots: void slotSendMessageContentSaved(const QString& content); -- GitLab