diff --git a/Linphone/core/conference/ConferenceCore.cpp b/Linphone/core/conference/ConferenceCore.cpp index 427d9cd4..ed8588c5 100644 --- a/Linphone/core/conference/ConferenceCore.cpp +++ b/Linphone/core/conference/ConferenceCore.cpp @@ -58,6 +58,18 @@ void ConferenceCore::setSelf(QSharedPointer me) { auto device = ParticipantDeviceCore::create(participantDevice); mConferenceModelConnection->invokeToCore([this, device]() { setActiveSpeaker(device); }); }); + mConferenceModelConnection->makeConnectToModel( + &ConferenceModel::participantDeviceAdded, + [this](const std::shared_ptr &participantDevice) { + int count = mConferenceModel->getParticipantDeviceCount(); + mConferenceModelConnection->invokeToCore([this, count]() { setParticipantDeviceCount(count); }); + }); + mConferenceModelConnection->makeConnectToModel( + &ConferenceModel::participantDeviceRemoved, + [this](const std::shared_ptr &participantDevice) { + int count = mConferenceModel->getParticipantDeviceCount(); + mConferenceModelConnection->invokeToCore([this, count]() { setParticipantDeviceCount(count); }); + }); } bool ConferenceCore::updateLocalParticipant() { // true if changed @@ -75,15 +87,22 @@ Q_INVOKABLE qint64 ConferenceCore::getElapsedSeconds() const { return 0; } +void ConferenceCore::setParticipantDeviceCount(int count) { + if (mParticipantDeviceCount != count) { + mParticipantDeviceCount = count; + emit participantDeviceCountChanged(); + } +} + int ConferenceCore::getParticipantDeviceCount() const { - return mParticipantDeviceCount + 1; + return mParticipantDeviceCount; } void ConferenceCore::setIsReady(bool state) { mustBeInMainThread(log().arg(Q_FUNC_INFO)); if (mIsReady != state) { mIsReady = state; - isReadyChanged(); + emit isReadyChanged(); } } diff --git a/Linphone/core/conference/ConferenceCore.hpp b/Linphone/core/conference/ConferenceCore.hpp index 6f80e6bb..1684f342 100644 --- a/Linphone/core/conference/ConferenceCore.hpp +++ b/Linphone/core/conference/ConferenceCore.hpp @@ -57,6 +57,8 @@ public: QDateTime getStartDate() const; Q_INVOKABLE qint64 getElapsedSeconds() const; int getParticipantDeviceCount() const; + void setParticipantDeviceCount(int count); + ParticipantDeviceCore *getActiveSpeaker() const; ParticipantDeviceGui *getActiveSpeakerGui() const; ParticipantGui *getMeGui() const; diff --git a/Linphone/model/call/CallModel.cpp b/Linphone/model/call/CallModel.cpp index c0aea1a6..7b65ea93 100644 --- a/Linphone/model/call/CallModel.cpp +++ b/Linphone/model/call/CallModel.cpp @@ -316,6 +316,7 @@ void CallModel::updateConferenceVideoLayout() { // auto settings = CoreManager::getInstance()->getSettingsModel(); auto newLayout = LinphoneEnums::fromLinphone(callParams->getConferenceVideoLayout()); if (!callParams->videoEnabled()) newLayout = LinphoneEnums::ConferenceLayout::AudioOnly; + if (!mConference) newLayout = LinphoneEnums::ConferenceLayout::ActiveSpeaker; if (mConferenceVideoLayout != newLayout) { // && !getPausedByUser()) { // Only update if not in pause. // if (mMonitor->getConference()) { // if (callParams->getConferenceVideoLayout() == linphone::Conference::Layout::Grid) diff --git a/Linphone/model/conference/ConferenceModel.cpp b/Linphone/model/conference/ConferenceModel.cpp index 82d380b8..9f40cd2f 100644 --- a/Linphone/model/conference/ConferenceModel.cpp +++ b/Linphone/model/conference/ConferenceModel.cpp @@ -71,6 +71,11 @@ void ConferenceModel::addParticipant(const std::shared_ptr &a mMonitor->addParticipant(address); } +int ConferenceModel::getParticipantDeviceCount() const { + mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); + return mMonitor->getParticipantDeviceList().size(); +} + void ConferenceModel::setMicrophoneMuted(bool isMuted) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); mMonitor->setMicrophoneMuted(isMuted); diff --git a/Linphone/model/conference/ConferenceModel.hpp b/Linphone/model/conference/ConferenceModel.hpp index b8b02786..94a2e61f 100644 --- a/Linphone/model/conference/ConferenceModel.hpp +++ b/Linphone/model/conference/ConferenceModel.hpp @@ -55,6 +55,8 @@ public: void removeParticipant(const std::shared_ptr &address); void addParticipant(const std::shared_ptr &address); + int getParticipantDeviceCount() const; + signals: void microphoneMutedChanged(bool isMuted); void speakerMutedChanged(bool isMuted); diff --git a/Linphone/view/App/AppWindow.qml b/Linphone/view/App/AppWindow.qml new file mode 100644 index 00000000..63f7f1b7 --- /dev/null +++ b/Linphone/view/App/AppWindow.qml @@ -0,0 +1,60 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.3 +import QtQuick.Controls +import Linphone +import UtilsCpp 1.0 +import SettingsCpp 1.0 + +ApplicationWindow { + id: mainWindow + + Component { + id: popupComp + InformationPopup{} + } + function removeFromPopupLayout(index) { + popupLayout.popupList.splice(index, 1) + } + function showInformationPopup(title, description, isSuccess) { + var infoPopup = popupComp.createObject(popupLayout, {"title": title, "description": description, "isSuccess": isSuccess}) + infoPopup.index = popupLayout.popupList.length + popupLayout.popupList.push(infoPopup) + infoPopup.open() + infoPopup.closePopup.connect(removeFromPopupLayout) + } + function showLoadingPopup(text) { + loadingPopup.text = text + loadingPopup.open() + } + function closeLoadingPopup() { + loadingPopup.close() + } + + ColumnLayout { + id: popupLayout + anchors.fill: parent + Layout.alignment: Qt.AlignBottom + property int nextY: mainWindow.height + property list popupList + property int popupCount: popupList.length + spacing: 15 * DefaultStyle.dp + onPopupCountChanged: { + nextY = mainWindow.height + for(var i = 0; i < popupCount; ++i) { + popupList[i].y = nextY - popupList[i].height + popupList[i].index = i + nextY = nextY - popupList[i].height - 15 + } + } + } + + LoadingPopup { + id: loadingPopup + modal: true + closePolicy: Popup.NoAutoClose + anchors.centerIn: parent + padding: 20 * DefaultStyle.dp + underlineColor: DefaultStyle.main1_500_main + radius: 15 * DefaultStyle.dp + } +} \ No newline at end of file diff --git a/Linphone/view/App/CallsWindow.qml b/Linphone/view/App/CallsWindow.qml index eab009a8..f4948d9b 100644 --- a/Linphone/view/App/CallsWindow.qml +++ b/Linphone/view/App/CallsWindow.qml @@ -7,7 +7,7 @@ import EnumsToStringCpp 1.0 import UtilsCpp 1.0 import SettingsCpp 1.0 -Window { +AppWindow { id: mainWindow width: 1512 * DefaultStyle.dp height: 982 * DefaultStyle.dp @@ -38,33 +38,9 @@ Window { } } - Component { - id: popupComp - InformationPopup{} - } - - function showInformationPopup(title, description, isSuccess) { - var infoPopup = popupComp.createObject(popupLayout, {"title": title, "description": description, "isSuccess": isSuccess}) - infoPopup.index = popupLayout.popupList.length - popupLayout.popupList.push(infoPopup) - infoPopup.open() - } - - ColumnLayout { - id: popupLayout - anchors.fill: parent - Layout.alignment: Qt.AlignBottom - property int nextY: mainWindow.height - property list popupList - property int popupCount: popupList.length - spacing: 15 * DefaultStyle.dp - onPopupCountChanged: { - nextY = mainWindow.height - for(var i = 0; i < popupCount; ++i) { - popupList[i].y = nextY - popupList[i].height - nextY = nextY - popupList[i].height - 15 * DefaultStyle.dp - } - } + function shareInvitation() { + UtilsCpp.copyToClipboard(conference.core.uri) + showInformationPopup(qsTr("Copié"), qsTr("Le lien de la réunion a été copié dans le presse-papier"), true) } function changeLayout(layoutIndex) { @@ -141,10 +117,13 @@ Window { function endCall(callToFinish) { if (callToFinish) callToFinish.core.lTerminate() } - function callEnded(){ + function callEnded(call){ if (!callsModel.haveCall) { - bottomButtonsLayout.setButtonsEnabled(false) - autoCloseWindow.restart() + if (call.core.conference) UtilsCpp.closeCallsWindow() + else { + bottomButtonsLayout.setButtonsEnabled(false) + autoCloseWindow.restart() + } } else { mainWindow.call = callsModel.currentCall } @@ -707,8 +686,7 @@ Window { } } onClicked: { - UtilsCpp.copyToClipboard(mainWindow.conference.core.uri) - UtilsCpp.showInformationPopup(qsTr("Copié"), qsTr("Le lien de la réunion a été copié dans le presse-papier"), true, mainWindow) + mainItem.shareInvitation() } } } @@ -741,6 +719,8 @@ Window { id: addParticipantComp AddParticipantsLayout { id: addParticipantLayout + searchBarColor: DefaultStyle.grey_0 + searchBarBorderColor: DefaultStyle.grey_200 onSelectedParticipantsCountChanged: { if (participantsStack.Control.StackView.status === Control.StackView.Active && Control.StackView.visible) { rightPanel.headerSubtitleText = qsTr("%1 participant%2 sélectionné").arg(selectedParticipants.length).arg(selectedParticipants.length > 1 ? "s" : "") @@ -755,13 +735,6 @@ Window { rightPanel.headerSubtitleText = qsTr("%1 participant%2 sélectionné%2").arg(addParticipantLayout.selectedParticipants.length).arg(addParticipantLayout.selectedParticipants.length > 1 ? "s" : "") } } - onParticipantAdded: { - addParticipantLayout.clearSelectedParticipants() - } - onValidateRequested: { - conferenceInfoGui.core.resetParticipants(contactList.selectedContacts) - returnRequested() - } } } } @@ -799,6 +772,7 @@ Window { anchors.topMargin: 10 * DefaultStyle.dp call: mainWindow.call callTerminatedByUser: mainWindow.callTerminatedByUser + onShareInvitationRequested: mainWindow.shareInvitation() } } } diff --git a/Linphone/view/App/Main.qml b/Linphone/view/App/Main.qml index 1c8d12fd..9b8c1309 100644 --- a/Linphone/view/App/Main.qml +++ b/Linphone/view/App/Main.qml @@ -5,7 +5,7 @@ import Linphone import UtilsCpp 1.0 import SettingsCpp 1.0 -ApplicationWindow { +AppWindow { id: mainWindow width: 1512 * DefaultStyle.dp height: 982 * DefaultStyle.dp @@ -33,57 +33,6 @@ ApplicationWindow { mainWindowStackView.currentItem.transferCallSucceed() } - function removeFromPopupLayout(index) { - popupLayout.popupList.splice(index, 1) - } - - Component { - id: popupComp - InformationPopup{} - } - function showInformationPopup(title, description, isSuccess) { - var infoPopup = popupComp.createObject(popupLayout, {"title": title, "description": description, "isSuccess": isSuccess}) - infoPopup.index = popupLayout.popupList.length - popupLayout.popupList.push(infoPopup) - infoPopup.open() - infoPopup.closePopup.connect(removeFromPopupLayout) - } - function showLoadingPopup(text) { - loadingPopup.text = text - loadingPopup.open() - } - function closeLoadingPopup() { - loadingPopup.close() - } - - ColumnLayout { - id: popupLayout - anchors.fill: parent - Layout.alignment: Qt.AlignBottom - property int nextY: mainWindow.height - property list popupList - property int popupCount: popupList.length - spacing: 15 * DefaultStyle.dp - onPopupCountChanged: { - nextY = mainWindow.height - for(var i = 0; i < popupCount; ++i) { - popupList[i].y = nextY - popupList[i].height - popupList[i].index = i - nextY = nextY - popupList[i].height - 15 - } - } - } - - LoadingPopup { - id: loadingPopup - modal: true - closePolicy: Popup.NoAutoClose - anchors.centerIn: parent - padding: 20 * DefaultStyle.dp - underlineColor: DefaultStyle.main1_500_main - radius: 15 * DefaultStyle.dp - } - AccountProxy { // TODO : change this so it does not display the main page for one second // when we fail trying to connect the first account (account is added and diff --git a/Linphone/view/CMakeLists.txt b/Linphone/view/CMakeLists.txt index 5f59ef64..993cfae5 100644 --- a/Linphone/view/CMakeLists.txt +++ b/Linphone/view/CMakeLists.txt @@ -2,6 +2,7 @@ list(APPEND _LINPHONEAPP_QML_FILES view/App/Main.qml view/App/CallsWindow.qml + view/App/AppWindow.qml view/App/Layout/LoginLayout.qml view/App/Layout/MainLayout.qml diff --git a/Linphone/view/Item/Contact/Avatar.qml b/Linphone/view/Item/Contact/Avatar.qml index 16e39a8d..bb96a7b3 100644 --- a/Linphone/view/Item/Contact/Avatar.qml +++ b/Linphone/view/Item/Contact/Avatar.qml @@ -28,7 +28,7 @@ StackView { || (contact && contact.core.pictureUri) || computedAvatarUri.length != 0 property string computedAvatarUri: UtilsCpp.findAvatarByAddress(address) - + onHaveAvatarChanged: replace(haveAvatar ? avatar : initials, StackView.Immediate) property bool secured: false diff --git a/Linphone/view/Item/Contact/ContactEdition.qml b/Linphone/view/Item/Contact/ContactEdition.qml index 0588b492..83781f48 100644 --- a/Linphone/view/Item/Contact/ContactEdition.qml +++ b/Linphone/view/Item/Contact/ContactEdition.qml @@ -236,12 +236,13 @@ RightPanelLayout { } RowLayout { FormItemLayout { + id: phoneNumberInput label: qsTr("Phone") contentItem: TextField { backgroundColor: DefaultStyle.grey_0 onEditingFinished: { - if (text.length != 0) mainItem.contact.core.appendPhoneNumber(label, text) - setText("") + if (text.length != 0) mainItem.contact.core.appendPhoneNumber(phoneNumberInput.label, text) + text = "" } } } diff --git a/Linphone/view/Item/Contact/Sticker.qml b/Linphone/view/Item/Contact/Sticker.qml index df6b5a75..6c4caae7 100644 --- a/Linphone/view/Item/Contact/Sticker.qml +++ b/Linphone/view/Item/Contact/Sticker.qml @@ -16,6 +16,8 @@ Item { width: 200 property bool previewEnabled property CallGui call: null + property ConferenceGui conference: call && call.core.conference || null + property var callState: call && call.core.state || undefined property AccountGui account: null property ParticipantDeviceGui participantDevice: null property bool displayBorder : participantDevice && participantDevice.core.isSpeaking || false @@ -38,7 +40,10 @@ Item { property bool displayAll : !!mainItem.call property bool bigBottomAddress: displayAll property bool mutedStatus: participantDevice ? participantDevice.core.isMuted : false - + onCallChanged: { + waitingTime.seconds = 0 + waitingTimer.restart() + } Rectangle { id: background color: noCameraLayout.visible ? mainItem.color : 'transparent' @@ -47,19 +52,60 @@ Item { border.color: DefaultStyle.main2_200 border.width: mainItem.displayBorder ? 3 * DefaultStyle.dp : 0 property int minSize: Math.min(height, width) - ColumnLayout { + Item { id: noCameraLayout anchors.fill: parent - spacing: 0 visible: !cameraLoader.active || cameraLoader.status != Loader.Ready || !cameraLoader.item.isReady + ColumnLayout { + anchors.top: parent.top + anchors.topMargin: 81 * DefaultStyle.dp + anchors.horizontalCenter: parent.horizontalCenter + // Layout.alignment: Qt.AlignHCenter |Qt.AlignTop + spacing: 0 + visible: !mainItem.account && (mainItem.callState === LinphoneEnums.CallState.OutgoingInit + || mainItem.callState === LinphoneEnums.CallState.OutgoingProgress + || mainItem.callState === LinphoneEnums.CallState.OutgoingRinging + || mainItem.callState === LinphoneEnums.CallState.OutgoingEarlyMedia + || mainItem.callState === LinphoneEnums.CallState.IncomingReceived) + BusyIndicator { + indicatorColor: DefaultStyle.main2_100 + Layout.alignment: Qt.AlignHCenter + indicatorHeight: 27 * DefaultStyle.dp + indicatorWidth: 27 * DefaultStyle.dp + } + Timer { + id: waitingTimer + interval: 1000 + repeat: true + onTriggered: waitingTime.seconds += 1 + } + Text { + id: waitingTime + property int seconds + text: UtilsCpp.formatElapsedTime(seconds) + color: DefaultStyle.grey_0 + Layout.alignment: Qt.AlignHCenter + horizontalAlignment: Text.AlignHCenter + Layout.topMargin: 25 * DefaultStyle.dp + font { + pixelSize: 30 * DefaultStyle.dp + weight: 300 * DefaultStyle.dp + } + Component.onCompleted: { + waitingTimer.restart() + } + } + } Item{ - Layout.alignment: Qt.AlignHCenter - // minSize = 372 => avatar = 142 - Layout.preferredHeight: background.minSize * 142 / 372 - Layout.preferredWidth: height + anchors.centerIn: parent + height: mainItem.conference + ? background.minSize * 142 / 372 + : 120 * DefaultStyle.dp + width: height + id: centerItem Avatar{ id: avatar - anchors.fill: parent + anchors.fill: parent visible: !joiningView.visible account: mainItem.account call: !mainItem.previewEnabled ? mainItem.call : null @@ -67,15 +113,11 @@ Item { } ColumnLayout{ id: joiningView - anchors.fill: parent + anchors.centerIn: parent spacing: 0 visible: mainItem.participantDevice && (mainItem.participantDevice.core.state == LinphoneEnums.ParticipantDeviceState.Joining || mainItem.participantDevice.core.state == LinphoneEnums.ParticipantDeviceState.Alerting) || false - Item{ - Layout.fillHeight: true - Layout.fillWidth: true - } BusyIndicator { - Layout.preferredHeight: 27 * DefaultStyle.dp + Layout.preferredHeight: 42 * DefaultStyle.dp indicatorColor: DefaultStyle.main2_100 Layout.alignment: Qt.AlignHCenter indicatorHeight: 42 * DefaultStyle.dp @@ -93,34 +135,34 @@ Item { weight: 500 * DefaultStyle.dp } } - Item{ - Layout.fillHeight: true - Layout.fillWidth: true + } + } + ColumnLayout { + spacing: 0 + visible: mainItem.displayAll + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: centerItem.bottom + anchors.topMargin: 21 * DefaultStyle.dp + Text { + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + text: mainItem.peerAddress + color: DefaultStyle.grey_0 + font { + pixelSize: 22 * DefaultStyle.dp + weight: 300 * DefaultStyle.dp + capitalization: Font.Capitalize } } - } - Text { - Layout.fillWidth: true - Layout.topMargin: 15 * DefaultStyle.dp - horizontalAlignment: Text.AlignHCenter - visible: mainItem.displayAll - text: mainItem.peerAddress - color: DefaultStyle.grey_0 - font { - pixelSize: 22 * DefaultStyle.dp - weight: 300 * DefaultStyle.dp - capitalization: Font.Capitalize - } - } - Text { - Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - visible: mainItem.displayAll - text: mainItem.call && mainItem.call.core.peerAddress - color: DefaultStyle.grey_0 - font { - pixelSize: 14 * DefaultStyle.dp - weight: 300 * DefaultStyle.dp + Text { + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + text: mainItem.call && mainItem.call.core.peerAddress + color: DefaultStyle.grey_0 + font { + pixelSize: 14 * DefaultStyle.dp + weight: 300 * DefaultStyle.dp + } } } } @@ -134,7 +176,7 @@ Item { triggeredOnStart: true onTriggered: {cameraLoader.reset = !cameraLoader.reset} } - active: mainItem.visible && mainItem.videoEnabled && !cameraLoader.reset + active: mainItem.visible && mainItem.callState != LinphoneEnums.CallState.End && mainItem.callState != LinphoneEnums.CallState.Released && mainItem.videoEnabled && !cameraLoader.reset onActiveChanged: console.log("("+mainItem.qmlName+") Camera active " + active +", visible="+mainItem.visible +", videoEnabled="+mainItem.videoEnabled +", reset="+cameraLoader.reset) sourceComponent: cameraComponent } diff --git a/Linphone/view/Layout/Call/ActiveSpeakerLayout.qml b/Linphone/view/Layout/Call/ActiveSpeakerLayout.qml index 6660a07e..c6ae3bd2 100644 --- a/Linphone/view/Layout/Call/ActiveSpeakerLayout.qml +++ b/Linphone/view/Layout/Call/ActiveSpeakerLayout.qml @@ -21,11 +21,7 @@ Item{ onCountChanged: console.log("Device count changed : " +count) Component.onCompleted: console.log("Loaded : " +allDevices) } - onCallChanged: { - waitingTime.seconds = 0 - waitingTimer.restart() - console.log("call changed", call, waitingTime.seconds) - } + onCallStateChanged: if (callState === LinphoneEnums.CallState.End || callState === LinphoneEnums.CallState.Released) preview.visible = false RowLayout{ anchors.fill: parent anchors.rightMargin: 10 * DefaultStyle.dp @@ -42,46 +38,6 @@ Item{ videoEnabled: (participantDevice && participantDevice.core.videoEnabled) || (!participantDevice && call && call.core.remoteVideoEnabled) qmlName: 'AS' displayPresence: false - - Timer { - id: waitingTimer - interval: 1000 - repeat: true - onTriggered: waitingTime.seconds += 1 - } - ColumnLayout { - id: waitingConnection - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - anchors.topMargin: 30 * DefaultStyle.dp - spacing: 0 - visible: mainItem.callState === LinphoneEnums.CallState.OutgoingInit - || mainItem.callState === LinphoneEnums.CallState.OutgoingProgress - || mainItem.callState === LinphoneEnums.CallState.OutgoingRinging - || mainItem.callState === LinphoneEnums.CallState.OutgoingEarlyMedia - || mainItem.callState === LinphoneEnums.CallState.IncomingReceived - BusyIndicator { - indicatorColor: DefaultStyle.main2_100 - Layout.alignment: Qt.AlignHCenter - indicatorHeight: 30 * DefaultStyle.dp - indicatorWidth: 30 * DefaultStyle.dp - } - Text { - id: waitingTime - property int seconds - text: UtilsCpp.formatElapsedTime(seconds) - color: DefaultStyle.grey_0 - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter - font { - pixelSize: 30 * DefaultStyle.dp - weight: 300 * DefaultStyle.dp - } - Component.onCompleted: { - waitingTimer.restart() - } - } - } } ListView{ Layout.fillHeight: true @@ -116,7 +72,7 @@ Item{ id: preview qmlName: 'P' previewEnabled: true - visible: mainItem.call && allDevices.count <= 2 && !waitingConnection.visible + visible: mainItem.call && allDevices.count <= 2 onVisibleChanged: console.log(visible + " : " +allDevices.count) height: 180 * DefaultStyle.dp width: 300 * DefaultStyle.dp diff --git a/Linphone/view/Layout/Call/CallLayout.qml b/Linphone/view/Layout/Call/CallLayout.qml index 6d63570e..cf579f72 100644 --- a/Linphone/view/Layout/Call/CallLayout.qml +++ b/Linphone/view/Layout/Call/CallLayout.qml @@ -12,36 +12,54 @@ import SettingsCpp 1.0 Item { id: mainItem property CallGui call + property ConferenceGui conference: call && call.core.conference property bool callTerminatedByUser: false readonly property var callState: call && call.core.state || undefined property int conferenceLayout: call && call.core.conferenceVideoLayout || 0 + property int participantDeviceCount: conference ? conference.core.participantDeviceCount : -1 + Component.onCompleted: setConferenceLayout() onConferenceLayoutChanged: { console.log("CallLayout change : " +conferenceLayout) + setConferenceLayout() + } + onCallStateChanged: { + if( callState === LinphoneEnums.CallState.Error) { + centerLayout.currentIndex = 1 + } else if( callState === LinphoneEnums.CallState.End) { + callTerminatedText.visible = true + } + } + + signal shareInvitationRequested() + function setConferenceLayout() { + if (mainItem.participantDeviceCount < 2 ) { + return + } callLayout.sourceComponent = undefined // unload old view before opening the new view to avoid conflicts in Video UI. callLayout.sourceComponent = mainItem.conferenceLayout == LinphoneEnums.ConferenceLayout.ActiveSpeaker - ? activeSpeakerComponent - : gridComponent + ? activeSpeakerComponent + : gridComponent } - onCallStateChanged: if (callState === LinphoneEnums.CallState.End) { - callTerminatedText.visible = true - }else if( callState === LinphoneEnums.CallState.Error) { - centerLayout.currentIndex = 1 - } - + Text { id: callTerminatedText - visible: false anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top anchors.topMargin: 25 * DefaultStyle.dp - text: mainItem.callTerminatedByUser ? qsTr("Vous avez terminé l'appel") : qsTr("Votre correspondant a terminé l'appel") - color: DefaultStyle.grey_0 z: 1 + visible: false + text: mainItem.conference + ? qsTr("Vous avez quitté la conférence") + : mainItem.callTerminatedByUser + ? qsTr("Vous avez terminé l'appel") + : qsTr("Votre correspondant a terminé l'appel") + color: DefaultStyle.grey_0 font { pixelSize: 22 * DefaultStyle.dp weight: 300 * DefaultStyle.dp } } + Layout.StackLayout { id: centerLayout currentIndex: 0 @@ -50,7 +68,9 @@ Item { id: callLayout Layout.Layout.fillWidth: true Layout.Layout.fillHeight: true - sourceComponent: gridComponent + sourceComponent: mainItem.conference && mainItem.participantDeviceCount < 2 + ? waitingForOthersComponent + : activeSpeakerComponent } Layout.ColumnLayout { id: userNotFoundLayout @@ -81,6 +101,50 @@ Item { call: mainItem.call } } + Component { + id: waitingForOthersComponent + Rectangle { + color: DefaultStyle.grey_600 + radius: 15 * DefaultStyle.dp + Layout.Layout.fillWidth: true + Layout.Layout.fillHeight: true + Layout.ColumnLayout { + id: waitingForOthersLayout + anchors.centerIn: parent + spacing: 22 * DefaultStyle.dp + Text { + text: qsTr("Waiting for other participants...") + Layout.Layout.preferredHeight: 67 * DefaultStyle.dp + Layout.Layout.alignment: Qt.AlignHCenter + horizontalAlignment: Text.AlignHCenter + color: DefaultStyle.grey_0 + font { + pixelSize: 30 * DefaultStyle.dp + weight: 300 * DefaultStyle.dp + } + } + Button { + color: "transparent" + borderColor: DefaultStyle.main2_400 + pressedColor: DefaultStyle.main2_500main + icon.source: AppIcons.shareNetwork + contentImageColor: DefaultStyle.main2_400 + text: qsTr("Share invitation") + topPadding: 11 * DefaultStyle.dp + bottomPadding: 11 * DefaultStyle.dp + leftPadding: 20 * DefaultStyle.dp + rightPadding: 20 * DefaultStyle.dp + Layout.Layout.alignment: Qt.AlignHCenter + textColor: DefaultStyle.main2_400 + onClicked: { + if (mainItem.conference) { + mainItem.shareInvitationRequested() + } + } + } + } + } + } } // TODO : waitingForParticipant // ColumnLayout { diff --git a/Linphone/view/Layout/Meeting/AddParticipantsLayout.qml b/Linphone/view/Layout/Meeting/AddParticipantsLayout.qml index ac2589e1..033b3bc0 100644 --- a/Linphone/view/Layout/Meeting/AddParticipantsLayout.qml +++ b/Linphone/view/Layout/Meeting/AddParticipantsLayout.qml @@ -14,6 +14,8 @@ ColumnLayout { property ConferenceInfoGui conferenceInfoGui property bool nameGroupCall: false readonly property string groupName: groupCallName.text + property color searchBarColor: DefaultStyle.grey_100 + property color searchBarBorderColor: "transparent" function clearSelectedParticipants() { // TODO @@ -47,7 +49,6 @@ ColumnLayout { ListView { id: participantList Layout.fillWidth: true - Layout.topMargin: 15 * DefaultStyle.dp Layout.preferredHeight: contentHeight Layout.maximumHeight: mainItem.height / 3 width: mainItem.width @@ -99,12 +100,14 @@ ColumnLayout { SearchBar { id: searchbar Layout.fillWidth: true - Layout.topMargin: 21 * DefaultStyle.dp + Layout.topMargin: 6 * DefaultStyle.dp Layout.rightMargin: 28 * DefaultStyle.dp placeholderText: mainItem.placeHolderText + color: mainItem.searchBarColor + borderColor: mainItem.searchBarColor } Text { - Layout.topMargin: 21 * DefaultStyle.dp + Layout.topMargin: 6 * DefaultStyle.dp text: qsTr("Contacts") font { pixelSize: 16 * DefaultStyle.dp