1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-09-03 21:53:43 +02:00

mainview: call flow review

- incoming / outgoing call UI management
- add system native notifications
- incoming call page same model as outgoing
- UserInfoCallPage is used to display common information for incoming / outgoing calls

Gitlab: #32
Change-Id: If33196a30c51698b4edad55cb8f718066034e422
This commit is contained in:
ababi 2020-08-31 13:17:44 +02:00
parent 3e1f151f83
commit be70e36bf7
21 changed files with 617 additions and 551 deletions

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="24px" height="24px"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>

After

Width:  |  Height:  |  Size: 215 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="24px" height="24px"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>

After

Width:  |  Height:  |  Size: 256 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="24px" height="24px"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/></svg>

After

Width:  |  Height:  |  Size: 205 B

View file

@ -112,5 +112,6 @@
<file>src/wizardview/components/AccountCreationStepIndicator.qml</file>
<file>src/commoncomponents/SpinnerButton.qml</file>
<file>src/commoncomponents/UsernameLineEdit.qml</file>
<file>src/mainview/components/UserInfoCallPage.qml</file>
</qresource>
</RCC>

View file

@ -119,5 +119,6 @@
<file>images/icons/person_add-24px.svg</file>
<file>images/icons/router-24px.svg</file>
<file>images/icons/insert_drive_file-24dp.svg</file>
<file>images/icons/arrow_back-white-24dp.svg</file>
</qresource>
</RCC>

View file

@ -23,10 +23,10 @@
*/
#include "calladapter.h"
#include "globalsystemtray.h"
#include "utils.h"
#include <QApplication>
CallAdapter::CallAdapter(QObject* parent)
: QmlAdapterBase(parent)
, oneSecondTimer_(new QTimer(this))
@ -94,7 +94,6 @@ CallAdapter::refuseACall(const QString& accountId, const QString& convUid)
void
CallAdapter::acceptACall(const QString& accountId, const QString& convUid)
{
emit incomingCallNeedToSetupMainView(accountId, convUid);
auto* convModel = LRCInstance::getCurrentConversationModel();
const auto convInfo = convModel->getConversationForUID(convUid);
if (!convInfo.uid.isEmpty()) {
@ -107,50 +106,35 @@ CallAdapter::acceptACall(const QString& accountId, const QString& convUid)
void
CallAdapter::slotShowIncomingCallView(const QString& accountId, const conversation::Info& convInfo)
{
auto selectedAccountId = LRCInstance::getCurrAccId();
auto* callModel = LRCInstance::getCurrentCallModel();
if (!callModel->hasCall(convInfo.callId)) {
/*
* Connection to close potential incoming call page when it is not current account.
*/
auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
QObject::disconnect(closeIncomingCallPageConnection_);
closeIncomingCallPageConnection_
= QObject::connect(accInfo.callModel.get(),
&lrc::api::NewCallModel::callStatusChanged,
[this, accountId, uid = convInfo.uid](const QString& callId) {
auto& accInfo = LRCInstance::accountModel().getAccountInfo(
accountId);
auto& callModel = accInfo.callModel;
auto call = callModel->getCall(callId);
switch (call.status) {
case lrc::api::call::Status::INVALID:
case lrc::api::call::Status::INACTIVE:
case lrc::api::call::Status::ENDED:
case lrc::api::call::Status::PEER_BUSY:
case lrc::api::call::Status::TIMEOUT:
case lrc::api::call::Status::TERMINATING: {
if (!uid.isEmpty())
emit closePotentialIncomingCallPageWindow(accountId, uid);
break;
}
default:
break;
}
emit updateConversationSmartList();
QObject::disconnect(closeIncomingCallPageConnection_);
});
/*
* Show incoming call page only.
*/
auto accountProperties = LRCInstance::accountModel().getAccountConfig(accountId);
if (!accountProperties.autoAnswer && !accountProperties.isRendezVous) {
emit showIncomingCallPage(accountId, convInfo.uid);
if (QApplication::focusObject() == nullptr || accountId != selectedAccountId) {
showNotification(accountId, convInfo);
return;
}
auto* convModel = LRCInstance::getCurrentConversationModel();
const auto currentConvUid = LRCInstance::getCurrentConvUid();
const auto currentConvInfo = convModel->getConversationForUID(currentConvUid);
// Call in current conversation
auto currentConvHasCall = callModel->hasCall(currentConvInfo.callId);
// Check INCOMING / OUTGOING call in current conversation
if (currentConvHasCall) {
auto currentCall = callModel->getCall(currentConvInfo.callId);
if (currentCall.status == lrc::api::call::Status::CONNECTED ||
currentCall.status == lrc::api::call::Status::IN_PROGRESS) {
showNotification(accountId, convInfo);
return;
}
}
emit incomingCallNeedToSetupMainView(accountId, convInfo.uid);
emit showIncomingCallPage(accountId, convInfo.uid);
emit showCallStack(accountId, convInfo.uid, true);
emit updateConversationSmartList();
return;
}
@ -163,15 +147,55 @@ CallAdapter::slotShowIncomingCallView(const QString& accountId, const conversati
emit showCallStack(accountId, convInfo.uid);
}
} else {
auto selectedAccountId = LRCInstance::getCurrentAccountInfo().id;
auto showIncomingCall = false;
auto accountProperties = LRCInstance::accountModel().getAccountConfig(selectedAccountId);
if (!accountProperties.autoAnswer && !accountProperties.isRendezVous) {
// App not focused or in different account
if (QApplication::focusObject() == nullptr || accountId != selectedAccountId) {
showNotification(accountId, convInfo);
return;
}
auto* convModel = LRCInstance::getCurrentConversationModel();
const auto currentConvUid = LRCInstance::getCurrentConvUid();
const auto currentConvInfo = convModel->getConversationForUID(currentConvUid);
// Call in current conversation
auto currentConvHasCall = callModel->hasCall(currentConvInfo.callId);
// Check INCOMING / OUTGOING call in current conversation
if (isCallSelected) {
if (currentConvHasCall) {
auto currentCall = callModel->getCall(currentConvInfo.callId);
if (currentCall.status == lrc::api::call::Status::OUTGOING_RINGING) {
showNotification(accountId, convInfo);
} else {
showIncomingCall = true;
}
} else {
showIncomingCall = true;
}
} else { // Not current conversation
if (currentConvHasCall) {
auto currentCall = callModel->getCall(currentConvInfo.callId);
if (currentCall.status == lrc::api::call::Status::CONNECTED ||
currentCall.status == lrc::api::call::Status::IN_PROGRESS) {
showNotification(accountId, convInfo);
return;
}
}
showIncomingCall = true;
}
}
if (showIncomingCall) {
emit incomingCallNeedToSetupMainView(accountId, convInfo.uid);
emit showIncomingCallPage(accountId, convInfo.uid);
emit showCallStack(accountId, convInfo.uid, true);
}
}
emit callStatusChanged(static_cast<int>(call.status), accountId, convInfo.uid);
emit updateConversationSmartList();
}
@ -275,6 +299,48 @@ CallAdapter::getConferencesInfos()
return map;
}
void
CallAdapter::showNotification(const QString& accountId, const lrc::api::conversation::Info& convInfo)
{
// Hack for handling multiple consecutive calls to slotShowIncomingCallView (bug)
// Do not set notification if it is already active for the account and conversation
if (accountId == GlobalSystemTray::instance().getTriggeredAccountId() &&
convInfo.uid == GlobalSystemTray::instance().getPossibleOnGoingConversationUid()) {
return;
}
QString sender = convInfo.uid;
if (accountId != "") {
auto& accInfo = LRCInstance::getAccountInfo(accountId);
if (!convInfo.participants.isEmpty()) {
auto &contact = accInfo.contactModel->getContact(convInfo.participants[0]);
sender = Utils::bestNameForContact(contact);
}
}
GlobalSystemTray::instance().setPossibleOnGoingConversationUid(convInfo.uid);
QObject::connect(&GlobalSystemTray::instance(), &GlobalSystemTray::messageClicked,
this, [this, accountId, convInfo]() {
if (accountId != "" && convInfo.uid != "") {
emit incomingCallNeedToSetupMainView(accountId, convInfo.uid, true);
auto call = LRCInstance::getCallInfoForConversation(convInfo);
if (call->status == lrc::api::call::Status::INCOMING_RINGING) {
emit showIncomingCallPage(accountId, convInfo.uid);
emit showCallStack(accountId, convInfo.uid, true);
}
emit updateConversationSmartList();
}
GlobalSystemTray::instance().setTriggeredAccountId("");
GlobalSystemTray::instance().setPossibleOnGoingConversationUid("");
}, Qt::UniqueConnection);
Utils::showSystemNotification(QApplication::focusWidget(), sender, tr("is calling you"), 0, accountId);
}
void
CallAdapter::connectCallModel(const QString& accountId)
{
@ -385,7 +451,6 @@ CallAdapter::connectCallModel(const QString& accountId)
}
} else {
emit closeCallStack(accountId, convInfo.uid);
emit closePotentialIncomingCallPageWindow(accountId, convInfo.uid);
}
break;

View file

@ -21,10 +21,12 @@
#include "lrcinstance.h"
#include "qmladapterbase.h"
#include "globalsystemtray.h"
#include <QObject>
#include <QString>
#include <QVariant>
#include <QSystemTrayIcon>
class CallAdapter final : public QmlAdapterBase
{
@ -70,14 +72,14 @@ signals:
void showVideoCallPage(const QString& accountId, const QString& convUid, const QString& callId);
void showCallStack(const QString& accountId, const QString& convUid, bool forceReset = false);
void closeCallStack(const QString& accountId, const QString& convUid);
void closePotentialIncomingCallPageWindow(const QString& accountId, const QString& convUid);
void callStatusChanged(int index, const QString& accountId, const QString& convUid);
void updateConversationSmartList();
void updateParticipantsInfos(const QVariantList& infos,
const QString& accountId,
const QString& callId);
void incomingCallNeedToSetupMainView(const QString& accountId, const QString& convUid);
void incomingCallNeedToSetupMainView(const QString& accountId, const QString& convUid,
bool fromNotification = false);
void previewVisibilityNeedToChange(bool visible);
/*
@ -105,6 +107,7 @@ private:
const QString& accountId = {},
bool forceCallOnly = false);
bool shouldShowPreview(bool force);
void showNotification(const QString& accountId, const lrc::api::conversation::Info& convInfo);
/*
* Current conf/call info.
@ -115,6 +118,7 @@ private:
QMetaObject::Connection callStatusChangedConnection_;
QMetaObject::Connection onParticipantsChangedConnection_;
QMetaObject::Connection closeIncomingCallPageConnection_;
QMetaObject::Connection appStateChangedConnection_;
/*
* For Call Overlay

View file

@ -33,13 +33,13 @@ GlobalSystemTray::getTriggeredAccountId()
}
void
GlobalSystemTray::setPossibleOnGoingConversationInfo(const lrc::api::conversation::Info& convInfo)
GlobalSystemTray::setPossibleOnGoingConversationUid(const QString& convUid)
{
triggeredOnGoingConvInfo_ = convInfo;
triggeredOnGoingConvUid_ = convUid;
}
const lrc::api::conversation::Info&
GlobalSystemTray::getPossibleOnGoingConversationInfo()
const QString&
GlobalSystemTray::getPossibleOnGoingConversationUid()
{
return triggeredOnGoingConvInfo_;
return triggeredOnGoingConvUid_;
}

View file

@ -41,13 +41,13 @@ public:
const QString& getTriggeredAccountId();
void setPossibleOnGoingConversationInfo(const lrc::api::conversation::Info& convInfo);
void setPossibleOnGoingConversationUid(const QString& convUid);
const lrc::api::conversation::Info& getPossibleOnGoingConversationInfo();
const QString& getPossibleOnGoingConversationUid();
private:
GlobalSystemTray();
QString triggeredAccountId_;
lrc::api::conversation::Info triggeredOnGoingConvInfo_;
QString triggeredOnGoingConvUid_;
};

View file

@ -25,7 +25,6 @@ import net.jami.Models 1.0
import net.jami.Adapters 1.0
// Import qml component files.
import "components"
import "../wizardview"
import "../settingsview"
@ -47,38 +46,76 @@ Window {
property int savedSidePanelViewMaxWidth: 0
property int savedWelcomeViewMinWidth: 0
property int savedWelcomeViewMaxWidth: 0
property bool sidePanelHidden: false
property bool sidePanelHidden: !mainViewStack.visible
// To calculate tab bar bottom border hidden rect left margin.
property int tabBarLeftMargin: 8
property int tabButtonShrinkSize: 8
property bool inSettingsView: false
property bool needToShowCallStack: false
property bool needToCloseCallStack: false
signal closeApp
signal noAccountIsAvailable
function pushCallStackView(){
if (mainViewStack.visible) {
mainViewStack.pop(null, StackView.Immediate)
mainViewStack.push(callStackView, StackView.Immediate)
} else {
sidePanelViewStack.pop(null, StackView.Immediate)
sidePanelViewStack.push(callStackView, StackView.Immediate)
function showWelcomeView() {
mainViewWindowSidePanel.deselectConversationSmartList()
if (communicationPageMessageWebView.visible || callStackView.visible) {
sidePanelViewStack.pop(StackView.Immediate)
if (!sidePanelHidden) {
mainViewStack.pop(welcomePage, StackView.Immediate)
}
}
}
function pushCommunicationMessageWebView(){
if (mainViewStack.visible) {
mainViewStack.pop(null, StackView.Immediate)
mainViewStack.push(communicationPageMessageWebView,
StackView.Immediate)
function setCallStackView() {
mainViewWindowSidePanel.deselectConversationSmartList()
var currentAccount = AccountAdapter.currentAccountId
var currentCallConv = UtilsAdapter.getCallConvForAccount(currentAccount)
ConversationsAdapter.selectConversation(currentCallConv)
var callId = UtilsAdapter.getCallId(currentAccount, currentCallConv)
var callStatus = UtilsAdapter.getCallStatus(callId)
switch (callStatus) {
case Call.Status.INCOMING_RINGING:
callStackView.showIncomingCallPage(currentAccount, currentCallConv)
break
case Call.Status.OUTGOING_RINGING:
callStackView.showOutgoingCallPage()
break
default:
if (UtilsAdapter.hasVideoCall()) {
callStackView.showVideoCallPage(callId)
} else {
callStackView.showAudioCallPage()
}
}
pushCallStackView()
callStackView.responsibleAccountId = currentAccount
callStackView.responsibleConvUid = currentCallConv
callStackView.updateCorrespondingUI()
}
function pushCallStackView() {
if (sidePanelHidden) {
sidePanelViewStack.push(callStackView, StackView.Immediate)
} else {
sidePanelViewStack.pop(null, StackView.Immediate)
sidePanelViewStack.push(
communicationPageMessageWebView,
StackView.Immediate)
sidePanelViewStack.pop(StackView.Immediate)
mainViewStack.pop(null, StackView.Immediate)
mainViewStack.push(callStackView, StackView.Immediate)
}
}
function pushCommunicationMessageWebView() {
if (sidePanelHidden) {
sidePanelViewStack.push(communicationPageMessageWebView, StackView.Immediate)
} else {
mainViewStack.pop(null, StackView.Immediate)
mainViewStack.push(communicationPageMessageWebView, StackView.Immediate)
}
}
@ -86,6 +123,10 @@ Window {
mainViewWindowSidePanel.refreshAccountComboBox(index)
}
function currentAccountIsCalling() {
return UtilsAdapter.hasCall(AccountAdapter.currentAccountId)
}
function recursionStackViewItemMove(stackOne, stackTwo, depth=1) {
// Move all items (expect the bottom item) to stacktwo by the same order in stackone.
@ -111,28 +152,25 @@ Window {
mainViewStack.push(settingsView, StackView.Immediate)
sidePanelViewStack.push(leftPanelSettingsView, StackView.Immediate)
}
ConversationsAdapter.disconnectConversationModel()
} else {
ConversationsAdapter.connectConversationModel(false)
ConversationsAdapter.refill() // to be sure to have latest informations
mainViewWindowSidePanel.forceUpdateConversationSmartListView()
if (!sidePanelHidden) {
sidePanelViewStack.pop(mainViewWindowSidePanel, StackView.Immediate)
mainViewStack.pop(StackView.Immediate)
} else {
if (sidePanelHidden) {
recursionStackViewItemMove(sidePanelViewStack, mainViewStack, 2)
sidePanelViewStack.pop(StackView.Immediate)
mainViewStack.pop(StackView.Immediate)
recursionStackViewItemMove(mainViewStack, sidePanelViewStack, 1)
}
if (needToCloseCallStack) {
pushCommunicationMessageWebView()
needToShowCallStack = false
needToCloseCallStack = false
if (currentAccountIsCalling()) {
setCallStackView()
} else {
mainViewWindowSidePanel.deselectConversationSmartList()
sidePanelViewStack.pop(StackView.Immediate)
if (!sidePanelHidden) {
mainViewStack.pop(welcomePage, StackView.Immediate)
}
}
}
inSettingsView = !inSettingsView
@ -150,13 +188,11 @@ Window {
function onShowCallStack(accountId, convUid, forceReset) {
needToShowCallStack = true
if (forceReset) {
callStackView.responsibleAccountId = accountId
callStackView.responsibleConvUid = convUid
}
// Check if it is coming from the current responsible call,
// and push views onto the correct stackview
if (callStackView.responsibleAccountId === accountId
@ -166,7 +202,6 @@ Window {
}
function onCloseCallStack(accountId, convUid) {
// Check if call stack view is on any of the stackview.
if (callStackView.responsibleAccountId === accountId
&& callStackView.responsibleConvUid === convUid) {
@ -174,20 +209,16 @@ Window {
return item.objectName === "callStackViewObject"
}) || sidePanelViewStack.find(function (item, index) {
return item.objectName === "callStackViewObject"
}) || (inSettingsView && needToShowCallStack)) {
callStackView.needToCloseInCallConversationAndPotentialWindow()
})) {
if (!inSettingsView) {
callStackView.needToCloseInCallConversationAndPotentialWindow()
pushCommunicationMessageWebView()
needToShowCallStack = false
} else {
needToCloseCallStack = true
}
}
}
}
function onIncomingCallNeedToSetupMainView(accountId, convUid) {
function onIncomingCallNeedToSetupMainView(accountId, convUid, fromNotification) {
// Set up the call stack view that is needed by call overlay.
if (!inSettingsView) {
@ -205,16 +236,14 @@ Window {
communicationPageMessageWebView.headerUserUserNameLabelText = (name !== id) ? id : ""
callStackView.needToCloseInCallConversationAndPotentialWindow()
callStackView.setLinkedWebview(
communicationPageMessageWebView)
callStackView.setLinkedWebview(communicationPageMessageWebView)
callStackView.responsibleAccountId = accountId
callStackView.responsibleConvUid = convUid
callStackView.updateCorrspondingUI()
callStackView.updateCorrespondingUI()
mainViewWindowSidePanel.refreshAccountComboBox(index)
ConversationsAdapter.selectConversation(accountId, convUid)
ConversationsAdapter.selectConversation(accountId, convUid, !fromNotification)
MessagesAdapter.setupChatView(convUid)
}
}
@ -264,7 +293,9 @@ Window {
Rectangle {
implicitWidth: 1
implicitHeight: splitView.height
color: SplitHandle.pressed ? JamiTheme.pressColor : (SplitHandle.hovered ? JamiTheme.hoverColor : JamiTheme.tabbarBorderColor)
color: SplitHandle.pressed ? JamiTheme.pressColor :
(SplitHandle.hovered ? JamiTheme.hoverColor :
JamiTheme.tabbarBorderColor)
}
}
@ -272,9 +303,10 @@ Window {
id: mainViewSidePanelRect
SplitView.minimumWidth: sidePanelViewStackPreferredWidth
SplitView.maximumWidth: (sidePanelHidden ? splitView.width :
splitView.width - sidePanelViewStackPreferredWidth)
splitView.width - sidePanelViewStackPreferredWidth)
SplitView.fillHeight: true
// AccountComboBox is always visible
AccountComboBox {
id: accountComboBox
@ -304,24 +336,26 @@ Window {
}
onAccountChanged: {
mainViewWindowSidePanel.deselectConversationSmartList()
mainViewWindowSidePanel.refreshAccountComboBox(index)
settingsView.slotAccountListChanged()
settingsView.setSelected(settingsView.selectedMenu, true)
if (needToShowCallStack
&& callStackView.responsibleAccountId === UtilsAdapter.getCurrAccId()){
if (!AccountAdapter.hasVideoCall()) {
pushCommunicationMessageWebView()
needToShowCallStack = false
} else if (needToShowCallStack) {
pushCallStackView()
if (!inSettingsView) {
if (currentAccountIsCalling()) {
setCallStackView()
} else {
showWelcomeView()
}
}
}
onNeedToBackToWelcomePage: {
if (!inSettingsView)
if (!inSettingsView && !currentAccountIsCalling()) {
mainViewWindowSidePanel.accountComboBoxNeedToShowWelcomePage()
}
}
onNewAccountButtonClicked: {
@ -338,7 +372,8 @@ Window {
initialItem: mainViewWindowSidePanel
anchors.top: accountComboBox.visible ? accountComboBox.bottom : mainViewSidePanelRect.top
anchors.top: accountComboBox.visible ? accountComboBox.bottom :
mainViewSidePanelRect.top
width: mainViewSidePanelRect.width
height: accountComboBox.visible ? mainViewSidePanelRect.height - accountComboBox.height :
mainViewSidePanelRect.height
@ -352,7 +387,8 @@ Window {
initialItem: welcomePage
SplitView.maximumWidth: sidePanelHidden ? splitView.width : splitView.width - sidePanelViewStackPreferredWidth
SplitView.maximumWidth: sidePanelHidden ? splitView.width :
splitView.width - sidePanelViewStackPreferredWidth
SplitView.minimumWidth: sidePanelViewStackPreferredWidth
SplitView.fillHeight: true
@ -410,7 +446,6 @@ Window {
}
}
SidePanel {
id: mainViewWindowSidePanel
@ -422,11 +457,11 @@ Window {
callStackView.needToCloseInCallConversationAndPotentialWindow()
callStackView.responsibleAccountId = UtilsAdapter.getCurrAccId()
callStackView.responsibleConvUid = currentUID
callStackView.updateCorrspondingUI()
callStackView.updateCorrespondingUI()
if (callStackViewShouldShow) {
if (callState === Call.Status.IN_PROGRESS || callState === Call.Status.PAUSED) {
UtilsAdapter.setCurrentCall(UtilsAdapter.getCurrAccId(), currentUID)
UtilsAdapter.setCurrentCall(AccountAdapter.currentAccountId, currentUID)
if (isAudioOnly)
callStackView.showAudioCallPage()
else
@ -434,15 +469,17 @@ Window {
UtilsAdapter.getCallId(
callStackView.responsibleAccountId,
callStackView.responsibleConvUid))
} else if (callState === Call.Status.INCOMING_RINGING) {
callStackView.showIncomingCallPage(AccountAdapter.currentAccountId,
currentUID)
} else {
callStackView.showOutgoingCallPage(callStateStr)
callStackView.showOutgoingCallPage()
}
}
// Set up chatview.
MessagesAdapter.setupChatView(currentUID)
callStackView.setLinkedWebview(
communicationPageMessageWebView)
callStackView.setLinkedWebview(communicationPageMessageWebView)
if (mainViewStack.find(function (item, index) {
return item.objectName === "communicationPageMessageWebView"
@ -453,7 +490,6 @@ Window {
return
}
// Push messageWebView or callStackView onto the correct stackview
mainViewStack.pop(null, StackView.Immediate)
sidePanelViewStack.pop(null, StackView.Immediate)
@ -483,13 +519,13 @@ Window {
onAccountComboBoxNeedToShowWelcomePage: {
// If the item argument is specified, all items down to (but not including) item will be popped.
if (!inSettingsView) {
mainViewStack.pop(welcomePage)
if (!inSettingsView && !currentAccountIsCalling()) {
showWelcomeView()
}
}
onConversationSmartListViewNeedToShowWelcomePage: {
mainViewStack.pop(welcomePage)
showWelcomeView()
}
onNeedToUpdateConversationForAddedContact: {
@ -559,22 +595,15 @@ Window {
}
onNeedToGoBackToWelcomeView: {
mainViewWindowSidePanel.deselectConversationSmartList()
if (communicationPageMessageWebView.visible
&& !mainViewStack.visible) {
sidePanelViewStack.pop()
} else if (communicationPageMessageWebView.visible
&& mainViewStack.visible) {
mainViewStack.pop()
}
showWelcomeView()
recordBox.visible = false
}
Component.onCompleted: {
sidePanelViewStack.SplitView.maximumWidth = Qt.binding(function() {
return (hiddenView ? splitView.width :
splitView.width - sidePanelViewStackPreferedWidth)
return (sidePanelHidden ? splitView.width :
splitView.width - sidePanelViewStackPreferredWidth)
})
recordBox.x = Qt.binding(function() {
@ -592,7 +621,6 @@ Window {
sidePanelViewStack.height + recordBox.y_offset
})
// Set qml MessageWebView object pointer to c++.
MessagesAdapter.setQmlObject(this)
}
@ -604,7 +632,6 @@ Window {
+ mainViewStackPreferredWidth - 5
&& mainViewStack.visible) {
mainViewStack.visible = false
sidePanelHidden = true
// The find callback function is called for each item in the stack.
var inWelcomeViewStack = mainViewStack.find(
@ -621,7 +648,6 @@ Window {
+ mainViewStackPreferredWidth + 5
&& !mainViewStack.visible) {
mainViewStack.visible = true
sidePanelHidden = false
var inSidePanelViewStack = sidePanelViewStack.find(
function (item, index) {
@ -631,6 +657,9 @@ Window {
recursionStackViewItemMove(sidePanelViewStack, mainViewStack, (inSettingsView ? 2 : 1))
}
if (!inSettingsView && currentAccountIsCalling())
pushCallStackView()
mainViewWindow.update()
}
}

View file

@ -151,6 +151,31 @@ Rectangle {
anchors.fill: parent
HoverableButton {
id: backButton
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.preferredWidth: JamiTheme.preferredFieldHeight
Layout.preferredHeight: JamiTheme.preferredFieldHeight
Layout.rightMargin: JamiTheme.preferredMarginSize
Layout.topMargin: JamiTheme.preferredMarginSize
Layout.leftMargin: JamiTheme.preferredMarginSize
radius: 32
source: "qrc:/images/icons/arrow_back-white-24dp.svg"
backgroundColor: "transparent"
onExitColor: "transparent"
onEnterColor: JamiTheme.lightGrey_
toolTipText: qsTr("Toggle to display side panel")
hoverEnabled: true
visible: mainViewWindow.sidePanelHidden
onClicked: {
mainViewWindow.showWelcomeView() // TODO: refactor with msg manager
}
}
Text {
id: jamiBestNameText

View file

@ -32,6 +32,12 @@ Rectangle {
anchors.fill: parent
Shortcut {
sequence: "Ctrl+D"
context: Qt.ApplicationShortcut
onActivated: CallAdapter.hangUpThisCall()
}
// When selected conversation is changed,
// these values will also be changed.
property string responsibleConvUid: ""
@ -41,7 +47,6 @@ Rectangle {
audioCallPage.closeInCallConversation()
videoCallPage.closeInCallConversation()
// Close potential window, context menu releated windows.
audioCallPage.closeContextMenuAndRelatedWindows()
@ -54,9 +59,10 @@ Rectangle {
videoCallPage.setLinkedWebview(webViewId)
}
function updateCorrspondingUI() {
function updateCorrespondingUI() {
audioCallPage.updateUI(responsibleAccountId, responsibleConvUid)
outgoingCallPage.updateUI(responsibleAccountId, responsibleConvUid)
incomingCallPage.updateUI(responsibleAccountId, responsibleConvUid)
videoCallPage.updateUI(responsibleAccountId, responsibleConvUid)
}
@ -73,7 +79,7 @@ Rectangle {
audioCallPage.updateUI(responsibleAccountId, responsibleConvUid)
}
function showOutgoingCallPage(currentCallStatus) {
function showOutgoingCallPage() {
var itemToFind = callStackMainView.find(function (item) {
return item.stackNumber === 1
})
@ -83,8 +89,21 @@ Rectangle {
} else {
callStackMainView.pop(itemToFind, StackView.Immediate)
}
if (currentCallStatus)
outgoingCallPage.callStatus = currentCallStatus
}
function showIncomingCallPage(accountId, convUid) {
var itemToFind = callStackMainView.find(function (item) {
return item.stackNumber === 3
})
if (!itemToFind) {
callStackMainView.push(incomingCallPage, StackView.Immediate)
} else {
callStackMainView.pop(itemToFind, StackView.Immediate)
}
responsibleAccountId = accountId
responsibleConvUid = convUid
incomingCallPage.updateUI(accountId, convUid)
}
function showVideoCallPage(callId) {
@ -106,7 +125,6 @@ Rectangle {
function onShowOutgoingCallPage(accountId, convUid) {
// Need to check whether it is the current selected conversation.
if (responsibleConvUid === convUid
&& responsibleAccountId === accountId) {
@ -115,18 +133,7 @@ Rectangle {
}
function onShowIncomingCallPage(accountId, convUid) {
// Check is done within the js.
IncomingCallPageCreation.createincomingCallPageWindowObjects(
accountId, convUid)
IncomingCallPageCreation.showIncomingCallPageWindow(accountId,
convUid)
}
function onClosePotentialIncomingCallPageWindow(accountId, convUid) {
IncomingCallPageCreation.closeIncomingCallPageWindow(accountId,
convUid)
showIncomingCallPage(accountId, convUid)
}
function onShowAudioCallPage(accountId, convUid) {
@ -196,6 +203,20 @@ Rectangle {
}
}
IncomingCallPage {
id: incomingCallPage
property int stackNumber: 3
onCallAcceptButtonIsClicked: {
CallAdapter.acceptACall(responsibleAccountId, responsibleConvUid)
}
onCallCancelButtonIsClicked: {
CallAdapter.hangUpACall(responsibleAccountId, responsibleConvUid)
}
}
StackView {
id: callStackMainView

View file

@ -25,313 +25,128 @@ import net.jami.Models 1.0
import "../../commoncomponents"
// IncomingCallPage as a seperate window,
// exist at the right bottom, as a notification to user that
// a call is incoming.
Window {
Rectangle {
id: incomingCallPage
property int minWidth: 300
property int minHeight: 400
property int buttonPreferredSize: 48
signal callCancelButtonIsClicked
signal callAcceptButtonIsClicked
// The unique identifier for incomingCallPage
property string responsibleAccountId: ""
property string responsibleConvUid: ""
color: "black"
property string contactImgSource: ""
property string bestName: "Best Name"
property string bestId: "Best Id"
property int buttonPreferredSize: 50
property variant clickPos: "1,1"
function updateUI() {
incomingCallPage.contactImgSource = "data:image/png;base64,"
+ UtilsAdapter.getContactImageString(responsibleAccountId,
responsibleConvUid)
incomingCallPage.bestName = UtilsAdapter.getBestName(
responsibleAccountId, responsibleConvUid)
var id = UtilsAdapter.getBestId(responsibleAccountId,
responsibleConvUid)
incomingCallPage.bestId = (incomingCallPage.bestName !== id) ? id : ""
function updateUI(accountId, convUid) {
userInfoIncomingCallPage.updateUI(accountId, convUid)
}
function updatePositionToRightBottom() {
// Screen right bottom,
// since the qt screen.virtualY, virtualX does not work properly,
// we need to calculate the screen x, y ourselves, by
// using to fact that window will always be in the middle if no x or y
// specificed.
// ex: https://doc.qt.io/qt-5/qscreen.html#geometry-prop
var virtualX = (incomingCallPage.x + width / 2) - screen.width / 2
incomingCallPage.x = virtualX + screen.width - width
incomingCallPage.y = screen.height - height - 50
// Prevent right click propagate to VideoCallPage.
MouseArea {
anchors.fill: parent
propagateComposedEvents: false
acceptedButtons: Qt.RightButton
}
minimumWidth: minWidth
minimumHeight: minHeight
maximumWidth: minWidth + 300
maximumHeight: minHeight + 300
flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
screen: Qt.application.screens[0]
Rectangle {
id: incomingCallPageColumnLayoutMainRect
ColumnLayout {
id: incomingCallPageColumnLayout
anchors.fill: parent
radius: 15
color: "black"
// Simulate window drag. (top with height 30).
MouseArea {
id: dragMouseArea
anchors.left: incomingCallPageColumnLayoutMainRect.left
anchors.top: incomingCallPageColumnLayoutMainRect.top
width: incomingCallPageColumnLayoutMainRect.width - closeButton.width - 10
height: 30
onPressed: {
clickPos = Qt.point(mouse.x, mouse.y)
}
onPositionChanged: {
var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y)
incomingCallPage.x += delta.x
incomingCallPage.y += delta.y
}
// Common elements with OutgoingCallPage
UserInfoCallPage {
id: userInfoIncomingCallPage
Layout.fillWidth: true
Layout.fillHeight: true
}
HoverableButton {
id: closeButton
Text {
id: talkToYouText
anchors.top: incomingCallPageColumnLayoutMainRect.top
anchors.topMargin: 10
anchors.right: incomingCallPageColumnLayoutMainRect.right
anchors.rightMargin: 10
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: incomingCallPage.width
Layout.preferredHeight: 32
width: 30
height: 30
font.pointSize: JamiTheme.textFontSize
radius: 30
source: "qrc:/images/icons/ic_close_white_24dp.png"
backgroundColor: "black"
onEnterColor: JamiTheme.closeButtonLighterBlack
onExitColor: "black"
onPressColor: JamiTheme.declineButtonPressedRed
onReleaseColor: "black"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: "white"
onClicked: {
incomingCallPage.close()
CallAdapter.refuseACall(responsibleAccountId,
responsibleConvUid)
}
text: "is calling you"
}
ColumnLayout {
id: incomingCallPageColumnLayout
RowLayout {
id: incomingCallPageRowLayout
anchors.fill: parent
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.bottomMargin: 48
Layout.topMargin: 48
Image {
id: contactImg
Layout.preferredWidth: incomingCallPage.width - 200
Layout.maximumWidth: 200
Layout.preferredHeight: buttonPreferredSize
Layout.alignment: Qt.AlignCenter
Layout.topMargin: 30
ColumnLayout {
id: callAnswerButtonColumnLayout
Layout.preferredWidth: 100
Layout.preferredHeight: 100
Layout.alignment: Qt.AlignLeft
fillMode: Image.PreserveAspectFit
source: contactImgSource
}
HoverableButton {
id: callAnswerButton
Rectangle {
id: incomingCallPageTextRect
Layout.alignment: Qt.AlignCenter
Layout.alignment: Qt.AlignCenter
Layout.topMargin: 5
Layout.preferredWidth: buttonPreferredSize
Layout.preferredHeight: buttonPreferredSize
Layout.preferredWidth: incomingCallPage.width
Layout.preferredHeight: jamiBestNameText.height + jamiBestIdText.height
+ talkToYouText.height + 20
backgroundColor: JamiTheme.acceptButtonGreen
onEnterColor: JamiTheme.acceptButtonHoverGreen
onPressColor: JamiTheme.acceptButtonPressedGreen
onReleaseColor: JamiTheme.acceptButtonHoverGreen
onExitColor: JamiTheme.acceptButtonGreen
ColumnLayout {
id: incomingCallPageTextRectColumnLayout
buttonImageHeight: buttonPreferredSize / 2
buttonImageWidth: buttonPreferredSize / 2
source: "qrc:/images/icons/ic_check_white_18dp_2x.png"
radius: 32
Text {
id: jamiBestNameText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: incomingCallPageTextRect.width
Layout.preferredHeight: 50
font.pointSize: JamiTheme.textFontSize + 3
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: textMetricsjamiBestNameText.elidedText
color: "white"
TextMetrics {
id: textMetricsjamiBestNameText
font: jamiBestNameText.font
text: bestName
elideWidth: incomingCallPageTextRect.width - 30
elide: Qt.ElideMiddle
}
}
Text {
id: jamiBestIdText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: incomingCallPageTextRect.width
Layout.preferredHeight: 30
font.pointSize: JamiTheme.textFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: textMetricsjamiBestIdText.elidedText
color: "white"
TextMetrics {
id: textMetricsjamiBestIdText
font: jamiBestIdText.font
text: bestId
elideWidth: incomingCallPageTextRect.width - 30
elide: Qt.ElideMiddle
}
}
Text {
id: talkToYouText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: incomingCallPageTextRect.width
Layout.preferredHeight: 30
font.pointSize: JamiTheme.textFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: "white"
text: "is calling you"
onClicked: {
callAcceptButtonIsClicked()
}
}
color: "transparent"
}
RowLayout {
id: incomingCallPageRowLayout
ColumnLayout {
id: callDeclineButtonColumnLayout
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.bottomMargin: 5
Layout.alignment: Qt.AlignRight
Layout.preferredWidth: incomingCallPage.width - 100
Layout.preferredHeight: buttonPreferredSize
HoverableButton {
id: callDeclineButton
ColumnLayout {
id: callAnswerButtonColumnLayout
Layout.alignment: Qt.AlignCenter
Layout.alignment: Qt.AlignLeft
Layout.preferredWidth: buttonPreferredSize
Layout.preferredHeight: buttonPreferredSize
HoverableButton {
id: callAnswerButton
backgroundColor: JamiTheme.declineButtonRed
onEnterColor: JamiTheme.declineButtonHoverRed
onPressColor: JamiTheme.declineButtonPressedRed
onReleaseColor: JamiTheme.declineButtonHoverRed
onExitColor: JamiTheme.declineButtonRed
Layout.alignment: Qt.AlignCenter
buttonImageHeight: buttonPreferredSize / 2
buttonImageWidth: buttonPreferredSize / 2
source: "qrc:/images/icons/ic_close_white_24dp.png"
radius: 32
Layout.preferredWidth: buttonPreferredSize
Layout.preferredHeight: buttonPreferredSize
backgroundColor: JamiTheme.acceptButtonGreen
onEnterColor: JamiTheme.acceptButtonHoverGreen
onPressColor: JamiTheme.acceptButtonPressedGreen
onReleaseColor: JamiTheme.acceptButtonHoverGreen
onExitColor: JamiTheme.acceptButtonGreen
buttonImageHeight: buttonPreferredSize / 2
buttonImageWidth: buttonPreferredSize / 2
source: "qrc:/images/icons/ic_check_white_18dp_2x.png"
radius: 30
onClicked: {
incomingCallPage.close()
CallAdapter.acceptACall(responsibleAccountId,
responsibleConvUid)
}
}
Text {
id: answerText
Layout.alignment: Qt.AlignCenter
font.pointSize: JamiTheme.textFontSize - 2
text: qsTr("Answer")
}
}
ColumnLayout {
id: callDeclineButtonColumnLayout
Layout.alignment: Qt.AlignRight
HoverableButton {
id: callDeclineButton
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: buttonPreferredSize
Layout.preferredHeight: buttonPreferredSize
backgroundColor: JamiTheme.declineButtonRed
onEnterColor: JamiTheme.declineButtonHoverRed
onPressColor: JamiTheme.declineButtonPressedRed
onReleaseColor: JamiTheme.declineButtonHoverRed
onExitColor: JamiTheme.declineButtonRed
buttonImageHeight: buttonPreferredSize / 2
buttonImageWidth: buttonPreferredSize / 2
source: "qrc:/images/icons/ic_close_white_24dp.png"
radius: 30
onClicked: {
incomingCallPage.close()
CallAdapter.refuseACall(responsibleAccountId,
responsibleConvUid)
}
}
Text {
id: ignoreText
Layout.alignment: Qt.AlignCenter
font.pointSize: JamiTheme.textFontSize - 2
text: qsTr("Ignore")
onClicked: {
callCancelButtonIsClicked()
}
}
}
}
}
color: "transparent"
Shortcut {
sequence: "Ctrl+Y"
context: Qt.ApplicationShortcut

View file

@ -30,25 +30,16 @@ Rectangle {
property int buttonPreferredSize: 50
property int callStatus: 0
property string contactImgSource: ""
property string bestName: "Best Name"
property string bestId: "Best Id"
signal callCancelButtonIsClicked
function updateUI(accountId, convUid) {
contactImgSource = "data:image/png;base64," + UtilsAdapter.getContactImageString(
accountId, convUid)
bestName = UtilsAdapter.getBestName(accountId, convUid)
var id = UtilsAdapter.getBestId(accountId, convUid)
bestId = (bestName !== id) ? id : ""
userInfoCallPage.updateUI(accountId, convUid)
}
anchors.fill: parent
color: "black"
// Prevent right click propagate to VideoCallPage.
MouseArea {
anchors.fill: parent
@ -61,114 +52,43 @@ Rectangle {
anchors.fill: parent
Image {
id: contactImg
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: 100
Layout.preferredHeight: 100
fillMode: Image.PreserveAspectFit
source: contactImgSource
asynchronous: true
UserInfoCallPage {
id: userInfoCallPage
Layout.fillHeight: true
Layout.fillWidth: true
}
Rectangle {
id: outgoingCallPageTextRect
AnimatedImage {
id: spinnerImage
Layout.alignment: Qt.AlignCenter
Layout.topMargin: 5
Layout.preferredWidth: 24
Layout.preferredHeight: 8
source: "qrc:/images/waiting.gif"
}
Text {
id: callStatusText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: outgoingCallPageRect.width
Layout.preferredHeight: jamiBestNameText.height + jamiBestIdText.height
+ callStatusText.height + spinnerImage.height + 20
Layout.preferredHeight: 30
color: "transparent"
font.pointSize: JamiTheme.textFontSize
ColumnLayout {
id: outgoingCallPageTextRectColumnLayout
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
Text {
id: jamiBestNameText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: outgoingCallPageTextRect.width
Layout.preferredHeight: 50
font.pointSize: JamiTheme.textFontSize + 3
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: textMetricsjamiBestNameText.elidedText
color: "white"
TextMetrics {
id: textMetricsjamiBestNameText
font: jamiBestNameText.font
text: bestName
elideWidth: outgoingCallPageTextRect.width - 50
elide: Qt.ElideMiddle
}
}
Text {
id: jamiBestIdText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: outgoingCallPageTextRect.width
Layout.preferredHeight: 30
font.pointSize: JamiTheme.textFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: textMetricsjamiBestIdText.elidedText
color: Qt.lighter("white", 1.5)
TextMetrics {
id: textMetricsjamiBestIdText
font: jamiBestIdText.font
text: bestId
elideWidth: outgoingCallPageTextRect.width - 50
elide: Qt.ElideMiddle
}
}
AnimatedImage {
id: spinnerImage
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: 20
Layout.preferredHeight: 5
source: "qrc:/images/waiting.gif"
}
Text {
id: callStatusText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: outgoingCallPageTextRect.width
Layout.preferredHeight: 30
font.pointSize: JamiTheme.textFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: UtilsAdapter.getCallStatusStr(callStatus) + "..."
color: Qt.lighter("white", 1.5)
}
}
text: UtilsAdapter.getCallStatusStr(callStatus) + "..."
color: Qt.lighter("white", 1.5)
}
ColumnLayout {
id: callCancelButtonColumnLayout
Layout.alignment: Qt.AlignCenter
Layout.bottomMargin: 48
HoverableButton {
id: callCancelButton
@ -192,18 +112,9 @@ Rectangle {
toolTipText: qsTr("Cancel the call")
onClicked: {
outgoingCallPageRect.callCancelButtonIsClicked()
callCancelButtonIsClicked()
}
}
Text {
id: cancelText
Layout.alignment: Qt.AlignCenter
font.pointSize: JamiTheme.textFontSize - 2
text: qsTr("Cancel")
}
}
}
}

View file

@ -32,7 +32,7 @@ Rectangle {
property int pendingRequestCount: 0
property int totalUnreadMessagesCount: 0
signal conversationSmartListNeedToAccessMessageWebView(string currentUserDisplayName, string currentUserAlias, string currentUID, bool callStackViewShouldShow, bool isAudioOnly, string callState)
signal conversationSmartListNeedToAccessMessageWebView(string currentUserDisplayName, string currentUserAlias, string currentUID, bool callStackViewShouldShow, bool isAudioOnly, int callState)
signal accountComboBoxNeedToShowWelcomePage()
signal conversationSmartListViewNeedToShowWelcomePage
signal needToUpdateConversationForAddedContact
@ -188,8 +188,7 @@ Rectangle {
target: ConversationsAdapter
function onShowChatView(accountId, convUid) {
conversationSmartListView.needToShowChatView(accountId,
convUid)
conversationSmartListView.needToShowChatView(accountId, convUid)
}
function onShowConversationTabs(visible) {

View file

@ -0,0 +1,154 @@
/*
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Albert Babí <albert.babi@savoirfairelinux.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtQuick.Controls.Universal 2.12
import net.jami.Models 1.0
import net.jami.Adapters 1.0
import "../../commoncomponents"
// Common element for IncomingCallPage and OutgoingCallPage
Rectangle {
id: userInfoCallRect
property int buttonPreferredSize: 48
property string contactImgSource: ""
property string bestName: "Best Name"
property string bestId: "Best Id"
function updateUI(accountId, convUid) {
contactImgSource = "data:image/png;base64," + UtilsAdapter.getContactImageString(
accountId, convUid)
bestName = UtilsAdapter.getBestName(accountId, convUid)
var id = UtilsAdapter.getBestId(accountId, convUid)
bestId = (bestName !== id) ? id : ""
}
color: "black"
ColumnLayout {
id: userInfoCallColumnLayout
anchors.fill: parent
HoverableButton {
id: backButton
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.preferredWidth: JamiTheme.preferredFieldHeight
Layout.preferredHeight: JamiTheme.preferredFieldHeight
Layout.rightMargin: JamiTheme.preferredMarginSize
Layout.topMargin: JamiTheme.preferredMarginSize
Layout.leftMargin: JamiTheme.preferredMarginSize
radius: 32
source: "qrc:/images/icons/arrow_back-white-24dp.svg"
backgroundColor: "transparent"
onExitColor: "transparent"
onEnterColor: JamiTheme.lightGrey_
toolTipText: qsTr("Toggle to display side panel")
hoverEnabled: true
visible: mainViewWindow.sidePanelHidden
onClicked: {
mainViewWindow.showWelcomeView() // TODO: refactor with msg manager
}
}
Image {
id: contactImg
Layout.alignment: Qt.AlignCenter
Layout.topMargin: 48
Layout.preferredWidth: 100
Layout.preferredHeight: 100
fillMode: Image.PreserveAspectFit
source: contactImgSource
asynchronous: true
}
Rectangle {
id: userInfoCallPageTextRect
Layout.alignment: Qt.AlignCenter
Layout.topMargin: 8
Layout.preferredWidth: userInfoCallRect.width
Layout.preferredHeight: jamiBestNameText.height + jamiBestIdText.height + 100
color: "transparent"
ColumnLayout {
id: userInfoCallPageTextRectColumnLayout
Text {
id: jamiBestNameText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: userInfoCallPageTextRect.width
Layout.preferredHeight: 48
font.pointSize: JamiTheme.headerFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: textMetricsjamiBestNameText.elidedText
color: "white"
TextMetrics {
id: textMetricsjamiBestNameText
font: jamiBestNameText.font
text: bestName
elideWidth: userInfoCallPageTextRect.width - 48
elide: Qt.ElideMiddle
}
}
Text {
id: jamiBestIdText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: userInfoCallPageTextRect.width
Layout.preferredHeight: 32
font.pointSize: JamiTheme.textFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: textMetricsjamiBestIdText.elidedText
color: Qt.lighter("white", 1.5)
TextMetrics {
id: textMetricsjamiBestIdText
font: jamiBestIdText.font
text: bestId
elideWidth: userInfoCallPageTextRect.width - 48
elide: Qt.ElideMiddle
}
}
}
}
}
}

View file

@ -112,7 +112,7 @@ Rectangle {
Connections {
id: accountConnections_ContactModel
target: AccountAdapter.contactModel
enabled: accountViewRect.visible
enabled: root.visible
function onModelUpdated(uri, needsSorted) {
updateAndShowBannedContactsSlot()
@ -130,7 +130,7 @@ Rectangle {
Connections {
id: accountConnections_DeviceModel
target: AccountAdapter.deviceModel
enabled: accountViewRect.visible
enabled: root.visible
function onDeviceAdded(id) {
updateAndShowDevicesSlot()

View file

@ -335,7 +335,8 @@ SmartListModel::getConversationItemData(const conversation::Info& item,
return QVariant(callModel->hasCall(convInfo.callId)
&& ((!call.isOutgoing
&& (call.status == lrc::api::call::Status::IN_PROGRESS
|| call.status == lrc::api::call::Status::PAUSED))
|| call.status == lrc::api::call::Status::PAUSED
|| call.status == lrc::api::call::Status::INCOMING_RINGING))
|| call.isOutgoing));
}
return QVariant(false);

View file

@ -45,7 +45,7 @@
#include <windows.h>
#undef ERROR
#else
#define LPCWSTR char*
#define LPCWSTR char *
#endif
#include "api/account.h"
@ -58,8 +58,8 @@ namespace Utils {
/*
* App/System
*/
bool CreateStartupLink(const std::wstring& wstrAppName);
void DeleteStartupLink(const std::wstring& wstrAppName);
bool CreateStartupLink(const std::wstring &wstrAppName);
void DeleteStartupLink(const std::wstring &wstrAppName);
bool CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink);
bool CheckStartupLink(const std::wstring& wstrAppName);
const char* WinGetEnv(const char* name);
@ -69,14 +69,14 @@ QString GetISODate();
void showSystemNotification(QWidget* widget,
const QString& message,
long delay = 5000,
const QString& triggeredAccountId = "");
void showSystemNotification(QWidget* widget,
const QString& sender,
const QString& message,
const QString &triggeredAccountId = "");
void showSystemNotification(QWidget *widget,
const QString &sender,
const QString &message,
long delay = 5000,
const QString& triggeredAccountId = "");
QSize getRealSize(QScreen* screen);
void forceDeleteAsync(const QString& path);
const QString &triggeredAccountId = "");
QSize getRealSize(QScreen *screen);
void forceDeleteAsync(const QString &path);
QString getChangeLog();
QString getProjectCredits();
void removeOldVersions();
@ -90,8 +90,8 @@ static constexpr bool isBeta = true;
static constexpr bool isBeta = false;
#endif
void cleanUpdateFiles();
void checkForUpdates(bool withUI, QWidget* parent = nullptr);
void applyUpdates(bool updateToBeta, QWidget* parent = nullptr);
void checkForUpdates(bool withUI, QWidget *parent = nullptr);
void applyUpdates(bool updateToBeta, QWidget *parent = nullptr);
/*
* LRC helpers
@ -118,8 +118,8 @@ bool getReplyMessageBox(QWidget* widget, const QString& title, const QString& te
static const QSize defaultAvatarSize {128, 128};
QString getContactImageString(const QString& accountId, const QString& uid);
QImage getCirclePhoto(const QImage original, int sizePhoto);
QImage conversationPhoto(const QString& convUid,
const lrc::api::account::Info& accountInfo,
QImage conversationPhoto(const QString &convUid,
const lrc::api::account::Info &accountInfo,
bool filtered = false);
QColor getAvatarColor(const QString& canonicalUri);
QImage fallbackAvatar(const QString& canonicalUriStr,

View file

@ -233,6 +233,32 @@ UtilsAdapter::hasVideoCall()
return LRCInstance::hasVideoCall();
}
bool
UtilsAdapter::hasCall(const QString &accountId)
{
auto activeCalls = LRCInstance::getActiveCalls();
for (const auto &callId : activeCalls) {
auto &accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
if (accountInfo.callModel->hasCall(callId)) {
return true;
}
}
return false;
}
const QString
UtilsAdapter::getCallConvForAccount(const QString &accountId)
{
// TODO: Currently returning first call, establish priority according to state?
for (const auto &callId : LRCInstance::getActiveCalls()) {
auto &accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
if (accountInfo.callModel->hasCall(callId)) {
return LRCInstance::getConversationFromCallId(callId, accountId).uid;
}
}
return "";
}
const QString
UtilsAdapter::getCallId(const QString& accountId, const QString& convUid)
{
@ -251,6 +277,14 @@ UtilsAdapter::getCallId(const QString& accountId, const QString& convUid)
return call->id;
}
int
UtilsAdapter::getCallStatus(const QString &callId)
{
const auto callStatus = LRCInstance::getCallInfo(
callId, LRCInstance::getCurrAccId());
return static_cast<int>(callStatus->status);
}
const QString
UtilsAdapter::getCallStatusStr(int statusInt)
{

View file

@ -64,7 +64,10 @@ public:
Q_INVOKABLE void startPreviewing(bool force);
Q_INVOKABLE void stopPreviewing();
Q_INVOKABLE bool hasVideoCall();
Q_INVOKABLE bool hasCall(const QString &accountId);
Q_INVOKABLE const QString getCallConvForAccount(const QString &accountId);
Q_INVOKABLE const QString getCallId(const QString& accountId, const QString& convUid);
Q_INVOKABLE int getCallStatus(const QString &callId);
Q_INVOKABLE const QString getCallStatusStr(int statusInt);
Q_INVOKABLE QString getStringUTF8(QString string);
Q_INVOKABLE bool validateRegNameForm(const QString& regName);