diff --git a/Linphone/view/Page/Layout/Settings/AccountSettingsParametersLayout.qml b/Linphone/view/Page/Layout/Settings/AccountSettingsParametersLayout.qml index d12724efc..f47655fcc 100644 --- a/Linphone/view/Page/Layout/Settings/AccountSettingsParametersLayout.qml +++ b/Linphone/view/Page/Layout/Settings/AccountSettingsParametersLayout.qml @@ -8,145 +8,148 @@ import SettingsCpp 1.0 import UtilsCpp AbstractSettingsLayout { - id: mainItem - width: parent?.width - contentModel: [ - { - title: qsTr("Paramètres"), - subTitle: "", - contentComponent: generalParametersComponent - }, - { - title: qsTr("Paramètres de compte"), - subTitle: "", - contentComponent: advancedParametersComponent - } - ] + id: mainItem + width: parent?.width + contentModel: [{ + "title": qsTr("Paramètres"), + "subTitle": "", + "contentComponent": generalParametersComponent + }, { + "title": qsTr("Paramètres de compte"), + "subTitle": "", + "contentComponent": advancedParametersComponent + }] - property alias account: mainItem.model + property alias account: mainItem.model - onSave: { - account.core.save() - } - onUndo: account.core.undo() - Connections { - target: account.core - function onIsSavedChanged() { - if (account.core.isSaved) UtilsCpp.showInformationPopup(qsTr("Succès"), qsTr("Les changements ont été sauvegardés"), true, mainWindow) - } - } - - // General parameters - ///////////////////// + onSave: { + account.core.save() + } + onUndo: account.core.undo() + Connections { + target: account.core + function onIsSavedChanged() { + if (account.core.isSaved) + UtilsCpp.showInformationPopup( + qsTr("Succès"), + qsTr("Les changements ont été sauvegardés"), true, + mainWindow) + } + } - Component { - id: generalParametersComponent - ColumnLayout { - id: column - Layout.fillWidth: true - spacing: 20 * DefaultStyle.dp - DecoratedTextField { - propertyName: "mwiServerAddress" - propertyOwnerGui: account - title: qsTr("URI du serveur de messagerie vocale") - Layout.fillWidth: true - isValid: function(text) { return text.length == 0 || !text.endsWith(".") } // work around sdk crash when adress ends with . - toValidate: true - } - DecoratedTextField { - propertyName: "voicemailAddress" - propertyOwnerGui: account - title: qsTr("URI de messagerie vocale") - Layout.fillWidth: true - toValidate: true - } - } - } - - // Advanced parameters - ///////////////////// - - Component { - id: advancedParametersComponent - ColumnLayout { - Layout.fillWidth: true - spacing: 20 * DefaultStyle.dp - Text { - text: qsTr("Transport") - color: DefaultStyle.main2_600 - font: Typography.p2l - } - ComboSetting { - Layout.fillWidth: true - Layout.topMargin: -15 * DefaultStyle.dp - entries: account.core.transports - propertyName: "transport" - propertyOwnerGui: account - } - DecoratedTextField { - Layout.fillWidth: true - title: qsTr("URL du serveur mandataire") - propertyName: "serverAddress" - propertyOwnerGui: account - toValidate: true - } - SwitchSetting { - titleText: qsTr("Serveur mandataire sortant") - propertyName: "outboundProxyEnabled" - propertyOwnerGui: account - } - DecoratedTextField { - Layout.fillWidth: true - propertyName: "stunServer" - propertyOwnerGui: account - title: qsTr("Adresse du serveur STUN") - toValidate: true - } - SwitchSetting { - titleText: qsTr("Activer ICE") - propertyName: "iceEnabled" - propertyOwnerGui: account - } - SwitchSetting { - titleText: qsTr("AVPF") - propertyName: "avpfEnabled" - propertyOwnerGui: account - } - SwitchSetting { - titleText: qsTr("Mode bundle") - propertyName: "bundleModeEnabled" - propertyOwnerGui: account - } - DecoratedTextField { - Layout.fillWidth: true - propertyName: "expire" - propertyOwnerGui: account - title: qsTr("Expiration (en seconde)") - canBeEmpty: false - isValid: function(text) { return !isNaN(Number(text)) } - toValidate: true - } - DecoratedTextField { - Layout.fillWidth: true - title: qsTr("URI de l’usine à conversations") - propertyName: "conferenceFactoryAddress" - propertyOwnerGui: account - toValidate: true - } - DecoratedTextField { - Layout.fillWidth: true - title: qsTr("URI de l’usine à réunions") - propertyName: "audioVideoConferenceFactoryAddress" - propertyOwnerGui: account + // General parameters + ///////////////////// + Component { + id: generalParametersComponent + ColumnLayout { + id: column + Layout.fillWidth: true + spacing: 20 * DefaultStyle.dp + DecoratedTextField { + propertyName: "mwiServerAddress" + propertyOwnerGui: account + title: qsTr("URI du serveur de messagerie vocale") + Layout.fillWidth: true + isValid: function (text) { + return text.length == 0 || !text.endsWith(".") + } // work around sdk crash when adress ends with . toValidate: true - } - DecoratedTextField { - Layout.fillWidth: true - title: qsTr("URL du serveur d’échange de clés de chiffrement") - propertyName: "limeServerUrl" - propertyOwnerGui: account - toValidate: true - } - } - } + } + DecoratedTextField { + propertyName: "voicemailAddress" + propertyOwnerGui: account + title: qsTr("URI de messagerie vocale") + Layout.fillWidth: true + toValidate: true + } + } + } + + // Advanced parameters + ///////////////////// + Component { + id: advancedParametersComponent + ColumnLayout { + Layout.fillWidth: true + spacing: 20 * DefaultStyle.dp + Text { + text: qsTr("Transport") + color: DefaultStyle.main2_600 + font: Typography.p2l + } + ComboSetting { + Layout.fillWidth: true + Layout.topMargin: -15 * DefaultStyle.dp + entries: account.core.transports + propertyName: "transport" + propertyOwnerGui: account + } + DecoratedTextField { + Layout.fillWidth: true + title: qsTr("URL du serveur mandataire") + propertyName: "serverAddress" + propertyOwnerGui: account + toValidate: true + } + SwitchSetting { + titleText: qsTr("Serveur mandataire sortant") + propertyName: "outboundProxyEnabled" + propertyOwnerGui: account + } + DecoratedTextField { + Layout.fillWidth: true + propertyName: "stunServer" + propertyOwnerGui: account + title: qsTr("Adresse du serveur STUN") + toValidate: true + } + SwitchSetting { + titleText: qsTr("Activer ICE") + propertyName: "iceEnabled" + propertyOwnerGui: account + } + SwitchSetting { + titleText: qsTr("AVPF") + propertyName: "avpfEnabled" + propertyOwnerGui: account + } + SwitchSetting { + titleText: qsTr("Mode bundle") + propertyName: "bundleModeEnabled" + propertyOwnerGui: account + } + DecoratedTextField { + Layout.fillWidth: true + propertyName: "expire" + propertyOwnerGui: account + title: qsTr("Expiration (en seconde)") + canBeEmpty: false + isValid: function (text) { + return !isNaN(Number(text)) + } + toValidate: true + } + DecoratedTextField { + Layout.fillWidth: true + title: qsTr("URI de l’usine à conversations") + propertyName: "conferenceFactoryAddress" + propertyOwnerGui: account + toValidate: true + } + DecoratedTextField { + Layout.fillWidth: true + title: qsTr("URI de l’usine à réunions") + propertyName: "audioVideoConferenceFactoryAddress" + propertyOwnerGui: account + toValidate: true + } + DecoratedTextField { + Layout.fillWidth: true + title: qsTr("URL du serveur d’échange de clés de chiffrement") + propertyName: "limeServerUrl" + propertyOwnerGui: account + toValidate: true + } + } + } } diff --git a/Linphone/view/Page/Main/Call/CallPage.qml b/Linphone/view/Page/Main/Call/CallPage.qml index be4ec187e..e1ba8c623 100644 --- a/Linphone/view/Page/Main/Call/CallPage.qml +++ b/Linphone/view/Page/Main/Call/CallPage.qml @@ -5,226 +5,242 @@ import QtQuick.Controls.Basic as Control import Linphone import UtilsCpp import SettingsCpp -import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle -import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils +import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle +import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils AbstractMainPage { - id: mainItem - noItemButtonText: qsTr("Nouvel appel") - emptyListText: qsTr("Historique d'appel vide") - newItemIconSource: AppIcons.newCall + id: mainItem + noItemButtonText: qsTr("Nouvel appel") + emptyListText: qsTr("Historique d'appel vide") + newItemIconSource: AppIcons.newCall - property var selectedRowHistoryGui - signal listViewUpdated() + property var selectedRowHistoryGui + signal listViewUpdated - onVisibleChanged: if (!visible) { - goToCallHistory() - } + onVisibleChanged: if (!visible) { + goToCallHistory() + } - //Group call properties - property ConferenceInfoGui confInfoGui - property AccountProxy accounts: AccountProxy { - id: accountProxy - sourceModel: AppCpp.accounts - } - property AccountGui account: accountProxy.defaultAccount - property var state: account && account.core?.registrationState || 0 - property bool isRegistered: account ? account.core?.registrationState == LinphoneEnums.RegistrationState.Ok : false - property int selectedParticipantsCount - signal startGroupCallRequested() - signal createCallFromSearchBarRequested() - signal createContactRequested(string name, string address) - signal openNumPadRequest() - - property alias numericPadPopup: numericPadPopupItem + //Group call properties + property ConferenceInfoGui confInfoGui + property AccountProxy accounts: AccountProxy { + id: accountProxy + sourceModel: AppCpp.accounts + } + property AccountGui account: accountProxy.defaultAccount + property var state: account && account.core?.registrationState || 0 + property bool isRegistered: account ? account.core?.registrationState + == LinphoneEnums.RegistrationState.Ok : false + property int selectedParticipantsCount + signal startGroupCallRequested + signal createCallFromSearchBarRequested + signal createContactRequested(string name, string address) + signal openNumPadRequest - Connections { - enabled: confInfoGui - target: confInfoGui ? confInfoGui.core : null - function onConferenceSchedulerStateChanged() { - if (confInfoGui.core.schedulerState === LinphoneEnums.ConferenceSchedulerState.Ready) { - listStackView.pop() - } - } - } + property alias numericPadPopup: numericPadPopupItem - onSelectedRowHistoryGuiChanged: { - if (selectedRowHistoryGui) rightPanelStackView.replace(contactDetailComp, Control.StackView.Immediate) - else rightPanelStackView.replace(emptySelection, Control.StackView.Immediate) - } - rightPanelStackView.initialItem: emptySelection - rightPanelStackView.width: 360 * DefaultStyle.dp + Connections { + enabled: confInfoGui + target: confInfoGui ? confInfoGui.core : null + function onConferenceSchedulerStateChanged() { + if (confInfoGui.core.schedulerState === LinphoneEnums.ConferenceSchedulerState.Ready) { + listStackView.pop() + } + } + } - onNoItemButtonPressed: goToNewCall() + onSelectedRowHistoryGuiChanged: { + if (selectedRowHistoryGui) + rightPanelStackView.replace(contactDetailComp, + Control.StackView.Immediate) + else + rightPanelStackView.replace(emptySelection, + Control.StackView.Immediate) + } + rightPanelStackView.initialItem: emptySelection + rightPanelStackView.width: 360 * DefaultStyle.dp - showDefaultItem: listStackView.currentItem && listStackView.currentItem.objectName == "historyListItem" && listStackView.currentItem.listView.count === 0 || false + onNoItemButtonPressed: goToNewCall() - function goToNewCall() { - if (listStackView.currentItem && listStackView.currentItem.objectName != "newCallItem") listStackView.push(newCallItem) - } - function goToCallHistory() { - if (listStackView.currentItem && listStackView.currentItem.objectName != "historyListItem") listStackView.replace(historyListItem) - } + showDefaultItem: listStackView.currentItem + && listStackView.currentItem.objectName == "historyListItem" + && listStackView.currentItem.listView.count === 0 || false - Dialog { - id: deleteHistoryPopup - width: 278 * DefaultStyle.dp - text: qsTr("L'historique d'appel sera supprimé. Souhaitez-vous continuer ?") - } - Dialog { - id: deleteForUserPopup - width: 278 * DefaultStyle.dp - text: qsTr("L'historique d'appel de l'utilisateur sera supprimé. Souhaitez-vous continuer ?") - } + function goToNewCall() { + if (listStackView.currentItem + && listStackView.currentItem.objectName != "newCallItem") + listStackView.push(newCallItem) + } + function goToCallHistory() { + if (listStackView.currentItem + && listStackView.currentItem.objectName != "historyListItem") + listStackView.replace(historyListItem) + } - leftPanelContent: Item { - id: leftPanel - Layout.fillWidth: true - Layout.fillHeight: true + Dialog { + id: deleteHistoryPopup + width: 278 * DefaultStyle.dp + text: qsTr("L'historique d'appel sera supprimé. Souhaitez-vous continuer ?") + } + Dialog { + id: deleteForUserPopup + width: 278 * DefaultStyle.dp + text: qsTr( + "L'historique d'appel de l'utilisateur sera supprimé. Souhaitez-vous continuer ?") + } - Control.StackView { - id: listStackView - anchors.fill: parent - anchors.leftMargin: 45 * DefaultStyle.dp - clip: true - initialItem: historyListItem - focus: true - onActiveFocusChanged: if(activeFocus){ - currentItem.forceActiveFocus() - } - } + leftPanelContent: Item { + id: leftPanel + Layout.fillWidth: true + Layout.fillHeight: true - Item { - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - height: 402 * DefaultStyle.dp - NumericPadPopup { - id: numericPadPopupItem - width: parent.width - height: parent.height - visible: false - onLaunchCall: { - mainItem.createCallFromSearchBarRequested() - // TODO : auto completion instead of sip linphone - } - } - } - } + Control.StackView { + id: listStackView + anchors.fill: parent + anchors.leftMargin: 45 * DefaultStyle.dp + clip: true + initialItem: historyListItem + focus: true + onActiveFocusChanged: if (activeFocus) { + currentItem.forceActiveFocus() + } + } - Component { - id: historyListItem - FocusScope{ - objectName: "historyListItem" - property alias listView: historyListView - ColumnLayout { - anchors.fill: parent - spacing: 0 - RowLayout { - id: titleCallLayout - spacing: 16 * DefaultStyle.dp - Text { - text: qsTr("Appels") - color: DefaultStyle.main2_700 - font.pixelSize: 29 * DefaultStyle.dp - font.weight: 800 * DefaultStyle.dp - } - Item { - Layout.fillWidth: true - } - PopupButton { - id: removeHistory - width: 24 * DefaultStyle.dp - height: 24 * DefaultStyle.dp - focus: true - popup.x: 0 - KeyNavigation.right: newCallButton - KeyNavigation.down: listStackView - popup.contentItem: ColumnLayout { - IconLabelButton { - Layout.fillWidth: true - focus: visible - text: qsTr("Supprimer l'historique") - icon.source: AppIcons.trashCan - style: ButtonStyle.hoveredBackgroundRed - onClicked: { - removeHistory.close() - deleteHistoryPopup.open() - } - } - } - Connections { - target: deleteHistoryPopup - onAccepted: { - if (listStackView.currentItem.listView) listStackView.currentItem.listView.model.removeAllEntries() - } - } - } - Button { - id: newCallButton - style: ButtonStyle.noBackground - icon.source: AppIcons.newCall - Layout.preferredWidth: 28 * DefaultStyle.dp - Layout.preferredHeight: 28 * DefaultStyle.dp - Layout.rightMargin: 39 * DefaultStyle.dp - icon.width: 28 * DefaultStyle.dp - icon.height: 28 * DefaultStyle.dp - KeyNavigation.left: removeHistory - KeyNavigation.down: listStackView - onClicked: { - console.debug("[CallPage]User: create new call") - listStackView.push(newCallItem) - } - } - } - SearchBar { - id: searchBar - Layout.fillWidth: true - Layout.topMargin: 18 * DefaultStyle.dp - Layout.rightMargin: 39 * DefaultStyle.dp - placeholderText: qsTr("Rechercher un appel") + Item { + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + height: 402 * DefaultStyle.dp + NumericPadPopup { + id: numericPadPopupItem + width: parent.width + height: parent.height + visible: false + onLaunchCall: { + mainItem.createCallFromSearchBarRequested() + // TODO : auto completion instead of sip linphone + } + } + } + } + + Component { + id: historyListItem + FocusScope { + objectName: "historyListItem" + property alias listView: historyListView + ColumnLayout { + anchors.fill: parent + spacing: 0 + RowLayout { + id: titleCallLayout + spacing: 16 * DefaultStyle.dp + Text { + text: qsTr("Appels") + color: DefaultStyle.main2_700 + font.pixelSize: 29 * DefaultStyle.dp + font.weight: 800 * DefaultStyle.dp + } + Item { + Layout.fillWidth: true + } + PopupButton { + id: removeHistory + width: 24 * DefaultStyle.dp + height: 24 * DefaultStyle.dp + focus: true + popup.x: 0 + KeyNavigation.right: newCallButton + KeyNavigation.down: listStackView + popup.contentItem: ColumnLayout { + IconLabelButton { + Layout.fillWidth: true + focus: visible + text: qsTr("Supprimer l'historique") + icon.source: AppIcons.trashCan + style: ButtonStyle.hoveredBackgroundRed + onClicked: { + removeHistory.close() + deleteHistoryPopup.open() + } + } + } + Connections { + target: deleteHistoryPopup + onAccepted: { + if (listStackView.currentItem.listView) + listStackView.currentItem.listView.model.removeAllEntries() + } + } + } + Button { + id: newCallButton + style: ButtonStyle.noBackground + icon.source: AppIcons.newCall + Layout.preferredWidth: 28 * DefaultStyle.dp + Layout.preferredHeight: 28 * DefaultStyle.dp + Layout.rightMargin: 39 * DefaultStyle.dp + icon.width: 28 * DefaultStyle.dp + icon.height: 28 * DefaultStyle.dp + KeyNavigation.left: removeHistory + KeyNavigation.down: listStackView + onClicked: { + console.debug("[CallPage]User: create new call") + listStackView.push(newCallItem) + } + } + } + SearchBar { + id: searchBar + Layout.fillWidth: true + Layout.topMargin: 18 * DefaultStyle.dp + Layout.rightMargin: 39 * DefaultStyle.dp + placeholderText: qsTr("Rechercher un appel") visible: historyListView.count !== 0 || text.length !== 0 - focus: true - KeyNavigation.up: newCallButton - KeyNavigation.down: historyListView - Binding { - target: mainItem - property: "showDefaultItem" - when: searchBar.text.length != 0 - value: false - } - } + focus: true + KeyNavigation.up: newCallButton + KeyNavigation.down: historyListView + Binding { + target: mainItem + property: "showDefaultItem" + when: searchBar.text.length != 0 + value: false + } + } Item { - Layout.fillWidth: true - Layout.fillHeight: true + Layout.fillWidth: true + Layout.fillHeight: true Control.Control { id: listLayout anchors.fill: parent anchors.rightMargin: 39 * DefaultStyle.dp padding: 0 - background: Item{} + background: Item {} contentItem: ColumnLayout { - Text { - visible: historyListView.count === 0 + Text { + visible: historyListView.count === 0 Layout.alignment: Qt.AlignHCenter Layout.topMargin: 137 * DefaultStyle.dp - text: qsTr("Aucun appel%1").arg(searchBar.text.length != 0 ? " correspondant" : "") - font { - pixelSize: 16 * DefaultStyle.dp - weight: 800 * DefaultStyle.dp - } - } - CallHistoryListView { - id: historyListView - Layout.fillWidth: true + text: qsTr("Aucun appel%1").arg( + searchBar.text.length != 0 ? " correspondant" : "") + font { + pixelSize: 16 * DefaultStyle.dp + weight: 800 * DefaultStyle.dp + } + } + CallHistoryListView { + id: historyListView + Layout.fillWidth: true Layout.fillHeight: true Layout.topMargin: 38 * DefaultStyle.dp - searchBar: searchBar + searchBar: searchBar Control.ScrollBar.vertical: scrollbar BusyIndicator { anchors.horizontalCenter: historyListView.horizontalCenter - visible: historyListView.loading && historyListView.count === 0 && searchBar.text.length === 0 + visible: historyListView.loading + && historyListView.count === 0 + && searchBar.text.length === 0 height: visible ? historyListView.busyIndicatorSize : 0 width: historyListView.busyIndicatorSize indicatorHeight: historyListView.busyIndicatorSize @@ -232,20 +248,22 @@ AbstractMainPage { indicatorColor: DefaultStyle.main1_500_main } - Connections{ - target: mainItem - function onListViewUpdated(){ - historyListView.model.reload() - } - } - onCurrentIndexChanged: { - mainItem.selectedRowHistoryGui = model.getAt(currentIndex) - } - onCountChanged: { - mainItem.selectedRowHistoryGui = model.getAt(currentIndex) - } - } - } + Connections { + target: mainItem + function onListViewUpdated() { + historyListView.model.reload() + } + } + onCurrentIndexChanged: { + mainItem.selectedRowHistoryGui = model.getAt( + currentIndex) + } + onCountChanged: { + mainItem.selectedRowHistoryGui = model.getAt( + currentIndex) + } + } + } } ScrollBar { id: scrollbar @@ -258,307 +276,348 @@ AbstractMainPage { policy: Control.ScrollBar.AsNeeded } } - } - } - } + } + } + } - Component { - id: newCallItem - FocusScope{ - objectName: "newCallItem" - width: parent?.width - height: parent?.height - Control.StackView.onActivated:{ - callContactsList.forceActiveFocus() - } - ColumnLayout { - anchors.fill: parent - spacing: 0 - RowLayout { - spacing: 10 * DefaultStyle.dp - Button { - Layout.preferredWidth: 24 * DefaultStyle.dp - Layout.preferredHeight: 24 * DefaultStyle.dp - style: ButtonStyle.noBackground - icon.source: AppIcons.leftArrow - focus: true - KeyNavigation.down: listStackView - onClicked: { - console.debug("[CallPage]User: return to call history") - listStackView.pop() - listStackView.forceActiveFocus() - } - } - Text { - text: qsTr("Nouvel appel") - color: DefaultStyle.main2_700 - font.pixelSize: 29 * DefaultStyle.dp - font.weight: 800 * DefaultStyle.dp - } - Item { - Layout.fillWidth: true - } - } - NewCallForm { - id: callContactsList - Layout.topMargin: 18 * DefaultStyle.dp - Layout.fillWidth: true - Layout.fillHeight: true - focus: true - numPadPopup: numericPadPopupItem - groupCallVisible: true - searchBarColor: DefaultStyle.grey_100 - onContactClicked: (contact) => { - mainWindow.startCallWithContact(contact, false, callContactsList) - } - onGroupCallCreationRequested: { - console.log("groupe call requetsed") - listStackView.push(groupCallItem) - } - Connections { - target: mainItem - function onCreateCallFromSearchBarRequested(){ UtilsCpp.createCall(callContactsList.searchBar.text)} - } - } - } - } - } - - Component { - id: groupCallItem - FocusScope{ - objectName: "groupCallItem" - Control.StackView.onActivated: { - addParticipantsLayout.forceActiveFocus() - } - ColumnLayout { - spacing: 0 - anchors.fill: parent - RowLayout { - spacing: 10 * DefaultStyle.dp - visible: !SettingsCpp.disableMeetingsFeature - Button { - id: backGroupCallButton - style: ButtonStyle.noBackgroundOrange - icon.source: AppIcons.leftArrow - Layout.preferredWidth: 24 * DefaultStyle.dp - Layout.preferredHeight: 24 * DefaultStyle.dp - KeyNavigation.down: listStackView - KeyNavigation.right: groupCallButton - KeyNavigation.left: groupCallButton - onClicked: { - listStackView.pop() - listStackView.currentItem?.forceActiveFocus() - } - } - ColumnLayout { - spacing: 3 * DefaultStyle.dp - Text { - text: qsTr("Appel de groupe") - color: DefaultStyle.main1_500_main - maximumLineCount: 1 - font { - pixelSize: 18 * DefaultStyle.dp - weight: 800 * DefaultStyle.dp - } - Layout.fillWidth: true - } - Text { - text: qsTr("%1 participant%2 sélectionné").arg(mainItem.selectedParticipantsCount).arg(mainItem.selectedParticipantsCount > 1 ? "s" : "") - color: DefaultStyle.main2_500main - maximumLineCount: 1 - font { - pixelSize: 12 * DefaultStyle.dp - weight: 300 * DefaultStyle.dp - } - Layout.fillWidth: true - } - } - SmallButton { - id: groupCallButton - enabled: mainItem.selectedParticipantsCount.length != 0 - Layout.rightMargin: 21 * DefaultStyle.dp - text: qsTr("Lancer") - style: ButtonStyle.main - KeyNavigation.down: listStackView - KeyNavigation.left: backGroupCallButton - KeyNavigation.right: backGroupCallButton - onClicked: { - mainItem.startGroupCallRequested() - } - } - } - RowLayout { - spacing: 0 - Layout.topMargin: 18 * DefaultStyle.dp - Layout.rightMargin: 38 * DefaultStyle.dp - Text { - font.pixelSize: 13 * DefaultStyle.dp - font.weight: 700 * DefaultStyle.dp - text: qsTr("Nom du groupe") - } - Item{Layout.fillWidth: true} - Text { - font.pixelSize: 12 * DefaultStyle.dp - font.weight: 300 * DefaultStyle.dp - text: qsTr("Requis") - } - } - TextField { - id: groupCallName - Layout.fillWidth: true - Layout.rightMargin: 38 * DefaultStyle.dp - Layout.preferredHeight: 49 * DefaultStyle.dp - focus: true - KeyNavigation.down: addParticipantsLayout//participantList.count > 0 ? participantList : searchbar - } - AddParticipantsForm { - id: addParticipantsLayout - Layout.fillWidth: true - Layout.fillHeight: true - Layout.topMargin: 15 * DefaultStyle.dp - onSelectedParticipantsCountChanged: mainItem.selectedParticipantsCount = selectedParticipantsCount - focus: true - Connections { - target: mainItem - function onStartGroupCallRequested() { - if (groupCallName.text.length === 0) { - UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("Un nom doit être donné à l'appel de groupe"), false) - } else if(!mainItem.isRegistered) { - UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("Vous n'etes pas connecté"), false) - } else { - mainItem.confInfoGui = Qt.createQmlObject('import Linphone - ConferenceInfoGui{ - }', mainItem) - mainItem.confInfoGui.core.subject = groupCallName.text - mainItem.confInfoGui.core.isScheduled = false - mainItem.confInfoGui.core.addParticipants(addParticipantsLayout.selectedParticipants) - mainItem.confInfoGui.core.save() - } - } - } - } - } - } - } - - Component{ - id: emptySelection - Item{objectName: "emptySelection"} - } - Component { - id: contactDetailComp - FocusScope{ - width: parent?.width - height: parent?.height - CallHistoryLayout { - id: contactDetail - anchors.fill: parent - anchors.topMargin: 45 * DefaultStyle.dp - anchors.bottomMargin: 45 * DefaultStyle.dp - visible: mainItem.selectedRowHistoryGui != undefined - callHistoryGui: selectedRowHistoryGui - - property var contactObj: UtilsCpp.findFriendByAddress(specificAddress) - - contact: contactObj && contactObj.value || null - specificAddress: callHistoryGui && callHistoryGui.core.remoteAddress || "" - - buttonContent: PopupButton { - id: detailOptions - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - popup.x: width - popup.contentItem: FocusScope { - implicitHeight: detailsButtons.implicitHeight - implicitWidth: detailsButtons.implicitWidth - Keys.onPressed: (event)=> { - if (event.key == Qt.Key_Left || event.key == Qt.Key_Escape) { - detailOptions.popup.close() - event.accepted = true; - } - } - ColumnLayout { - id: detailsButtons - anchors.fill: parent - IconLabelButton { - Layout.fillWidth: true - property bool isLdap: contactDetail.contact?.core?.isLdap || false - property bool isCardDAV: contactDetail.contact?.core?.isCardDAV || false - text: contactDetail.contact ? qsTr("Voir le contact") : qsTr("Ajouter aux contacts") - icon.source: AppIcons.plusCircle - icon.width: 32 * DefaultStyle.dp - icon.height: 32 * DefaultStyle.dp - visible: !isLdap && !isCardDAV - onClicked: { - detailOptions.close() - if (contactDetail.contact) mainWindow.displayContactPage(contactDetail.contactAddress) - else mainItem.createContactRequested(contactDetail.contactName, contactDetail.contactAddress) - } - } - IconLabelButton { - Layout.fillWidth: true - text: qsTr("Copier l'adresse SIP") - icon.source: AppIcons.copy - icon.width: 32 * DefaultStyle.dp - icon.height: 32 * DefaultStyle.dp - onClicked: { - detailOptions.close() - var success = UtilsCpp.copyToClipboard(mainItem.selectedRowHistoryGui && mainItem.selectedRowHistoryGui.core.remoteAddress) - if (success) UtilsCpp.showInformationPopup(qsTr("Copié"), qsTr("L'adresse a été copiée dans le presse-papier"), true) - else UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("Erreur lors de la copie de l'adresse"), false) - } - } - // IconLabelButton { - // background: Item {} - // enabled: false - // contentItem: IconLabel { - // text: qsTr("Bloquer") - // iconSource: AppIcons.empty - // } - // onClicked: console.debug("[CallPage.qml] TODO : block user") - // } - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: 2 * DefaultStyle.dp - color: DefaultStyle.main2_400 - } - - IconLabelButton { - Layout.fillWidth: true - text: qsTr("Supprimer l'historique") - icon.source: AppIcons.trashCan - icon.width: 32 * DefaultStyle.dp - icon.height: 32 * DefaultStyle.dp - style: ButtonStyle.hoveredBackgroundRed - Connections { - target: deleteForUserPopup - function onAccepted() { - detailListView.model.removeEntriesWithFilter(detailListView.searchText) - mainItem.listViewUpdated() - } - } - onClicked: { - detailOptions.close() - deleteForUserPopup.open() - } - } - } - } - } - detailContent: RoundedPane { - id: detailControl - Layout.preferredWidth: 360 * DefaultStyle.dp + Component { + id: newCallItem + FocusScope { + objectName: "newCallItem" + width: parent?.width + height: parent?.height + Control.StackView.onActivated: { + callContactsList.forceActiveFocus() + } + ColumnLayout { + anchors.fill: parent + spacing: 0 + RowLayout { + spacing: 10 * DefaultStyle.dp + Button { + Layout.preferredWidth: 24 * DefaultStyle.dp + Layout.preferredHeight: 24 * DefaultStyle.dp + style: ButtonStyle.noBackground + icon.source: AppIcons.leftArrow + focus: true + KeyNavigation.down: listStackView + onClicked: { + console.debug( + "[CallPage]User: return to call history") + listStackView.pop() + listStackView.forceActiveFocus() + } + } + Text { + text: qsTr("Nouvel appel") + color: DefaultStyle.main2_700 + font.pixelSize: 29 * DefaultStyle.dp + font.weight: 800 * DefaultStyle.dp + } + Item { + Layout.fillWidth: true + } + } + NewCallForm { + id: callContactsList + Layout.topMargin: 18 * DefaultStyle.dp + Layout.fillWidth: true Layout.fillHeight: true -// height: Math.min(430 * DefaultStyle.dp, detailListView.contentHeight) + topPadding + bottomPadding + focus: true + numPadPopup: numericPadPopupItem + groupCallVisible: true + searchBarColor: DefaultStyle.grey_100 + onContactClicked: contact => { + mainWindow.startCallWithContact( + contact, false, callContactsList) + } + onGroupCallCreationRequested: { + console.log("groupe call requetsed") + listStackView.push(groupCallItem) + } + Connections { + target: mainItem + function onCreateCallFromSearchBarRequested() { + UtilsCpp.createCall(callContactsList.searchBar.text) + } + } + } + } + } + } + + Component { + id: groupCallItem + FocusScope { + objectName: "groupCallItem" + Control.StackView.onActivated: { + addParticipantsLayout.forceActiveFocus() + } + ColumnLayout { + spacing: 0 + anchors.fill: parent + RowLayout { + spacing: 10 * DefaultStyle.dp + visible: !SettingsCpp.disableMeetingsFeature + Button { + id: backGroupCallButton + style: ButtonStyle.noBackgroundOrange + icon.source: AppIcons.leftArrow + Layout.preferredWidth: 24 * DefaultStyle.dp + Layout.preferredHeight: 24 * DefaultStyle.dp + KeyNavigation.down: listStackView + KeyNavigation.right: groupCallButton + KeyNavigation.left: groupCallButton + onClicked: { + listStackView.pop() + listStackView.currentItem?.forceActiveFocus() + } + } + ColumnLayout { + spacing: 3 * DefaultStyle.dp + Text { + text: qsTr("Appel de groupe") + color: DefaultStyle.main1_500_main + maximumLineCount: 1 + font { + pixelSize: 18 * DefaultStyle.dp + weight: 800 * DefaultStyle.dp + } + Layout.fillWidth: true + } + Text { + text: qsTr("%1 participant%2 sélectionné").arg( + mainItem.selectedParticipantsCount).arg( + mainItem.selectedParticipantsCount > 1 ? "s" : "") + color: DefaultStyle.main2_500main + maximumLineCount: 1 + font { + pixelSize: 12 * DefaultStyle.dp + weight: 300 * DefaultStyle.dp + } + Layout.fillWidth: true + } + } + SmallButton { + id: groupCallButton + enabled: mainItem.selectedParticipantsCount.length != 0 + Layout.rightMargin: 21 * DefaultStyle.dp + text: qsTr("Lancer") + style: ButtonStyle.main + KeyNavigation.down: listStackView + KeyNavigation.left: backGroupCallButton + KeyNavigation.right: backGroupCallButton + onClicked: { + mainItem.startGroupCallRequested() + } + } + } + RowLayout { + spacing: 0 + Layout.topMargin: 18 * DefaultStyle.dp + Layout.rightMargin: 38 * DefaultStyle.dp + Text { + font.pixelSize: 13 * DefaultStyle.dp + font.weight: 700 * DefaultStyle.dp + text: qsTr("Nom du groupe") + } + Item { + Layout.fillWidth: true + } + Text { + font.pixelSize: 12 * DefaultStyle.dp + font.weight: 300 * DefaultStyle.dp + text: qsTr("Requis") + } + } + TextField { + id: groupCallName + Layout.fillWidth: true + Layout.rightMargin: 38 * DefaultStyle.dp + Layout.preferredHeight: 49 * DefaultStyle.dp + focus: true + KeyNavigation.down: addParticipantsLayout //participantList.count > 0 ? participantList : searchbar + } + AddParticipantsForm { + id: addParticipantsLayout + Layout.fillWidth: true + Layout.fillHeight: true + Layout.topMargin: 15 * DefaultStyle.dp + onSelectedParticipantsCountChanged: mainItem.selectedParticipantsCount + = selectedParticipantsCount + focus: true + Connections { + target: mainItem + function onStartGroupCallRequested() { + if (groupCallName.text.length === 0) { + UtilsCpp.showInformationPopup( + qsTr("Erreur"), qsTr( + "Un nom doit être donné à l'appel de groupe"), + false) + } else if (!mainItem.isRegistered) { + UtilsCpp.showInformationPopup( + qsTr("Erreur"), + qsTr("Vous n'etes pas connecté"), + false) + } else { + mainItem.confInfoGui = Qt.createQmlObject( + 'import Linphone +ConferenceInfoGui{ +}', mainItem) + mainItem.confInfoGui.core.subject = groupCallName.text + mainItem.confInfoGui.core.isScheduled = false + mainItem.confInfoGui.core.addParticipants( + addParticipantsLayout.selectedParticipants) + mainItem.confInfoGui.core.save() + } + } + } + } + } + } + } + + Component { + id: emptySelection + Item { + objectName: "emptySelection" + } + } + Component { + id: contactDetailComp + FocusScope { + width: parent?.width + height: parent?.height + CallHistoryLayout { + id: contactDetail + anchors.fill: parent + anchors.topMargin: 45 * DefaultStyle.dp + anchors.bottomMargin: 45 * DefaultStyle.dp + visible: mainItem.selectedRowHistoryGui != undefined + callHistoryGui: selectedRowHistoryGui + + property var contactObj: UtilsCpp.findFriendByAddress( + specificAddress) + + contact: contactObj && contactObj.value || null + specificAddress: callHistoryGui + && callHistoryGui.core.remoteAddress || "" + + buttonContent: PopupButton { + id: detailOptions + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + popup.x: width + popup.contentItem: FocusScope { + implicitHeight: detailsButtons.implicitHeight + implicitWidth: detailsButtons.implicitWidth + Keys.onPressed: event => { + if (event.key == Qt.Key_Left + || event.key == Qt.Key_Escape) { + detailOptions.popup.close() + event.accepted = true + } + } + ColumnLayout { + id: detailsButtons + anchors.fill: parent + IconLabelButton { + Layout.fillWidth: true + property bool isLdap: contactDetail.contact?.core?.isLdap + || false + property bool isCardDAV: contactDetail.contact?.core?.isCardDAV + || false + text: contactDetail.contact ? qsTr("Voir le contact") : qsTr( + "Ajouter aux contacts") + icon.source: AppIcons.plusCircle + icon.width: 32 * DefaultStyle.dp + icon.height: 32 * DefaultStyle.dp + visible: !isLdap && !isCardDAV + onClicked: { + detailOptions.close() + if (contactDetail.contact) + mainWindow.displayContactPage( + contactDetail.contactAddress) + else + mainItem.createContactRequested( + contactDetail.contactName, + contactDetail.contactAddress) + } + } + IconLabelButton { + Layout.fillWidth: true + text: qsTr("Copier l'adresse SIP") + icon.source: AppIcons.copy + icon.width: 32 * DefaultStyle.dp + icon.height: 32 * DefaultStyle.dp + onClicked: { + detailOptions.close() + var success = UtilsCpp.copyToClipboard( + mainItem.selectedRowHistoryGui + && mainItem.selectedRowHistoryGui.core.remoteAddress) + if (success) + UtilsCpp.showInformationPopup( + qsTr("Copié"), qsTr( + "L'adresse a été copiée dans le presse-papier"), + true) + else + UtilsCpp.showInformationPopup( + qsTr("Erreur"), qsTr( + "Erreur lors de la copie de l'adresse"), + false) + } + } + // IconLabelButton { + // background: Item {} + // enabled: false + // contentItem: IconLabel { + // text: qsTr("Bloquer") + // iconSource: AppIcons.empty + // } + // onClicked: console.debug("[CallPage.qml] TODO : block user") + // } + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 2 * DefaultStyle.dp + color: DefaultStyle.main2_400 + } + + IconLabelButton { + Layout.fillWidth: true + text: qsTr("Supprimer l'historique") + icon.source: AppIcons.trashCan + icon.width: 32 * DefaultStyle.dp + icon.height: 32 * DefaultStyle.dp + style: ButtonStyle.hoveredBackgroundRed + Connections { + target: deleteForUserPopup + function onAccepted() { + detailListView.model.removeEntriesWithFilter( + detailListView.searchText) + mainItem.listViewUpdated() + } + } + onClicked: { + detailOptions.close() + deleteForUserPopup.open() + } + } + } + } + } + detailContent: RoundedPane { + id: detailControl + Layout.preferredWidth: 360 * DefaultStyle.dp + Layout.fillHeight: true + + // height: Math.min(430 * DefaultStyle.dp, detailListView.contentHeight) + topPadding + bottomPadding + background: Rectangle { + id: detailListBackground + anchors.fill: parent + color: DefaultStyle.grey_0 + radius: 15 * DefaultStyle.dp + } - background: Rectangle { - id: detailListBackground - anchors.fill: parent - color: DefaultStyle.grey_0 - radius: 15 * DefaultStyle.dp - } - contentItem: CallHistoryListView { id: detailListView Layout.fillWidth: true @@ -570,7 +629,8 @@ AbstractMainPage { BusyIndicator { anchors.horizontalCenter: detailListView.horizontalCenter - visible: detailListView.loading && detailListView.count === 0 + visible: detailListView.loading + && detailListView.count === 0 height: visible ? detailListView.busyIndicatorSize : 0 width: detailListView.busyIndicatorSize indicatorHeight: detailListView.busyIndicatorSize @@ -579,7 +639,7 @@ AbstractMainPage { } delegate: Item { - width:detailListView.width + width: detailListView.width height: 56 * DefaultStyle.dp RowLayout { anchors.fill: parent @@ -591,42 +651,28 @@ AbstractMainPage { RowLayout { EffectImage { id: statusIcon - imageSource: modelData.core.status === LinphoneEnums.CallStatus.Declined - || modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere - || modelData.core.status === LinphoneEnums.CallStatus.Aborted - || modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted - ? AppIcons.arrowElbow - : modelData.core.isOutgoing - ? AppIcons.arrowUpRight - : AppIcons.arrowDownLeft - colorizationColor: modelData.core.status === LinphoneEnums.CallStatus.Declined - || modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere - || modelData.core.status === LinphoneEnums.CallStatus.Aborted - || modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted - || modelData.core.status === LinphoneEnums.CallStatus.Missed - ? DefaultStyle.danger_500main - : modelData.core.isOutgoing - ? DefaultStyle.info_500_main - : DefaultStyle.success_500main + imageSource: modelData.core.status + === LinphoneEnums.CallStatus.Declined + || modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere + || modelData.core.status + === LinphoneEnums.CallStatus.Aborted + || modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted ? AppIcons.arrowElbow : modelData.core.isOutgoing ? AppIcons.arrowUpRight : AppIcons.arrowDownLeft + colorizationColor: modelData.core.status === LinphoneEnums.CallStatus.Declined || modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere || modelData.core.status === LinphoneEnums.CallStatus.Aborted || modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted || modelData.core.status === LinphoneEnums.CallStatus.Missed ? DefaultStyle.danger_500main : modelData.core.isOutgoing ? DefaultStyle.info_500_main : DefaultStyle.success_500main Layout.preferredWidth: 16 * DefaultStyle.dp Layout.preferredHeight: 16 * DefaultStyle.dp transform: Rotation { - angle: modelData.core.isOutgoing && (modelData.core.status === LinphoneEnums.CallStatus.Declined - || modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere - || modelData.core.status === LinphoneEnums.CallStatus.Aborted - || modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted) ? 180 : 0 + angle: modelData.core.isOutgoing + && (modelData.core.status + === LinphoneEnums.CallStatus.Declined + || modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere || modelData.core.status === LinphoneEnums.CallStatus.Aborted || modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted) ? 180 : 0 origin { - x: statusIcon.width/2 - y: statusIcon.height/2 + x: statusIcon.width / 2 + y: statusIcon.height / 2 } } } Text { - text: modelData.core.status === LinphoneEnums.CallStatus.Missed - ? qsTr("Appel manqué") - : modelData.core.isOutgoing - ? qsTr("Appel sortant") - : qsTr("Appel entrant") + text: modelData.core.status === LinphoneEnums.CallStatus.Missed ? qsTr("Appel manqué") : modelData.core.isOutgoing ? qsTr("Appel sortant") : qsTr("Appel entrant") font { pixelSize: 14 * DefaultStyle.dp weight: 400 * DefaultStyle.dp @@ -634,8 +680,9 @@ AbstractMainPage { } } Text { - text: UtilsCpp.formatDate(modelData.core.date) - color: modelData.core.status === LinphoneEnums.CallStatus.Missed? DefaultStyle.danger_500main : DefaultStyle.main2_500main + text: UtilsCpp.formatDate( + modelData.core.date) + color: modelData.core.status === LinphoneEnums.CallStatus.Missed ? DefaultStyle.danger_500main : DefaultStyle.main2_500main font { pixelSize: 12 * DefaultStyle.dp weight: 300 * DefaultStyle.dp @@ -647,7 +694,8 @@ AbstractMainPage { Layout.fillWidth: true } Text { - text: UtilsCpp.formatElapsedTime(modelData.core.duration, false) + text: UtilsCpp.formatElapsedTime( + modelData.core.duration, false) font { pixelSize: 12 * DefaultStyle.dp weight: 300 * DefaultStyle.dp @@ -656,33 +704,33 @@ AbstractMainPage { } } } - } - Item{ - Layout.fillHeight: true - } - } - } - } + } + Item { + Layout.fillHeight: true + } + } + } + } - component IconLabel: RowLayout { - id: iconLabel - property string text - property string iconSource - property color colorizationColor: DefaultStyle.main2_500main - EffectImage { - imageSource: iconLabel.iconSource - Layout.preferredWidth: 24 * DefaultStyle.dp - Layout.preferredHeight: 24 * DefaultStyle.dp - fillMode: Image.PreserveAspectFit - colorizationColor: iconLabel.colorizationColor - } - Text { - text: iconLabel.text - color: iconLabel.colorizationColor - font { - pixelSize: 14 * DefaultStyle.dp - weight: 400 * DefaultStyle.dp - } - } - } + component IconLabel: RowLayout { + id: iconLabel + property string text + property string iconSource + property color colorizationColor: DefaultStyle.main2_500main + EffectImage { + imageSource: iconLabel.iconSource + Layout.preferredWidth: 24 * DefaultStyle.dp + Layout.preferredHeight: 24 * DefaultStyle.dp + fillMode: Image.PreserveAspectFit + colorizationColor: iconLabel.colorizationColor + } + Text { + text: iconLabel.text + color: iconLabel.colorizationColor + font { + pixelSize: 14 * DefaultStyle.dp + weight: 400 * DefaultStyle.dp + } + } + } } diff --git a/Linphone/view/Page/Main/Contact/ContactPage.qml b/Linphone/view/Page/Main/Contact/ContactPage.qml index 156b87e28..b98b18a12 100644 --- a/Linphone/view/Page/Main/Contact/ContactPage.qml +++ b/Linphone/view/Page/Main/Contact/ContactPage.qml @@ -6,768 +6,831 @@ import Linphone import UtilsCpp import EnumsToStringCpp import SettingsCpp -import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle +import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle AbstractMainPage { - id: mainItem - noItemButtonText: qsTr("Ajouter un contact") - emptyListText: qsTr("Aucun contact pour le moment") - newItemIconSource: AppIcons.plusCircle + id: mainItem + noItemButtonText: qsTr("Ajouter un contact") + emptyListText: qsTr("Aucun contact pour le moment") + newItemIconSource: AppIcons.plusCircle - // disable left panel contact list interaction while a contact is being edited - property bool leftPanelEnabled: !rightPanelStackView.currentItem || rightPanelStackView.currentItem.objectName != "contactEdition" - property FriendGui selectedContact - property string initialFriendToDisplay - onInitialFriendToDisplayChanged: { - if (initialFriendToDisplay != '' && contactList.selectContact(initialFriendToDisplay) != -1) initialFriendToDisplay = "" - else if(initialFriendToDisplay != '') console.warn("Abstract not selected yet: ", initialFriendToDisplay) - } + // disable left panel contact list interaction while a contact is being edited + property bool leftPanelEnabled: !rightPanelStackView.currentItem + || rightPanelStackView.currentItem.objectName + != "contactEdition" + property FriendGui selectedContact + property string initialFriendToDisplay + onInitialFriendToDisplayChanged: { + if (initialFriendToDisplay != '' && contactList.selectContact( + initialFriendToDisplay) != -1) + initialFriendToDisplay = "" + else if (initialFriendToDisplay != '') + console.warn("Abstract not selected yet: ", initialFriendToDisplay) + } - onVisibleChanged: if (!visible) { - rightPanelStackView.clear() - contactList.resetSelections() - } - function goToContactDetails(){ - if (selectedContact) { - var firstItem = rightPanelStackView.get(0) - if( firstItem && firstItem.objectName == "contactDetail")// Go directly to detail - rightPanelStackView.popToIndex(0) - else{ - if(rightPanelStackView.depth >= 1) {// Replace in background and go back to it - rightPanelStackView.replace(firstItem, contactDetail) - rightPanelStackView.popToIndex(0) - }else{// empty - rightPanelStackView.push(contactDetail) - } - } - } else { - rightPanelStackView.clear() - } - } - onSelectedContactChanged: { - goToContactDetails() - } + onVisibleChanged: if (!visible) { + rightPanelStackView.clear() + contactList.resetSelections() + } + function goToContactDetails() { + if (selectedContact) { + var firstItem = rightPanelStackView.get(0) + if (firstItem && firstItem.objectName == "contactDetail") + // Go directly to detail + rightPanelStackView.popToIndex(0) + else { + if (rightPanelStackView.depth >= 1) { + // Replace in background and go back to it + rightPanelStackView.replace(firstItem, contactDetail) + rightPanelStackView.popToIndex(0) + } else { + // empty + rightPanelStackView.push(contactDetail) + } + } + } else { + rightPanelStackView.clear() + } + } + onSelectedContactChanged: { + goToContactDetails() + } - onNoItemButtonPressed: createContact("", "") + onNoItemButtonPressed: createContact("", "") - function createContact(name, address) { - var friendGui = Qt.createQmlObject('import Linphone - FriendGui{ - }', mainItem) - friendGui.core.givenName = UtilsCpp.getGivenNameFromFullName(name) - friendGui.core.familyName = UtilsCpp.getFamilyNameFromFullName(name) - friendGui.core.appendAddress(address) - if (!rightPanelStackView.currentItem || rightPanelStackView.currentItem.objectName != "contactEdition") - rightPanelStackView.push(contactEdition, {"contact": friendGui, "title": qsTr("Nouveau contact"), "saveButtonText": qsTr("Créer")}) - } + function createContact(name, address) { + var friendGui = Qt.createQmlObject('import Linphone +FriendGui{ +}', mainItem) + friendGui.core.givenName = UtilsCpp.getGivenNameFromFullName(name) + friendGui.core.familyName = UtilsCpp.getFamilyNameFromFullName(name) + friendGui.core.appendAddress(address) + if (!rightPanelStackView.currentItem + || rightPanelStackView.currentItem.objectName != "contactEdition") + rightPanelStackView.push(contactEdition, { + "contact": friendGui, + "title": qsTr("Nouveau contact"), + "saveButtonText": qsTr("Créer") + }) + } - function editContact(friendGui) { - rightPanelStackView.push(contactEdition, {"contact": friendGui, "title": qsTr("Modifier contact"), "saveButtonText": qsTr("Enregistrer")}) - } + function editContact(friendGui) { + rightPanelStackView.push(contactEdition, { + "contact": friendGui, + "title": qsTr("Modifier contact"), + "saveButtonText": qsTr("Enregistrer") + }) + } - // rightPanelStackView.initialItem: contactDetail - - showDefaultItem: rightPanelStackView.depth == 0 && !contactList.haveContacts && searchBar.text.length === 0 - - function deleteContact(contact) { - if (!contact) return - var mainWin = UtilsCpp.getMainWindow() - mainWin.showConfirmationLambdaPopup("", - qsTr("%1 sera supprimé des contacts. Voulez-vous continuer ?").arg(contact.core.fullName), - "", - function (confirmed) { - if (confirmed) { - var name = contact.core.fullName - contact.core.remove() - contactList.resetSelections() - UtilsCpp.showInformationPopup(qsTr("Supprimé"), qsTr("%1 a été supprimé").arg(name)) } - } - ) - } + // rightPanelStackView.initialItem: contactDetail + showDefaultItem: rightPanelStackView.depth == 0 && !contactList.haveContacts + && searchBar.text.length === 0 - Dialog { - id: verifyDevicePopup - property string deviceName - property string deviceAddress - padding: 30 * DefaultStyle.dp - width: 637 * DefaultStyle.dp - anchors.centerIn: parent - closePolicy: Control.Popup.CloseOnEscape - modal: true - onAboutToHide: neverDisplayAgainCheckbox.checked = false - title: qsTr("Augmenter la confiance") - text: qsTr("Pour augmenter le niveau de confiance vous devez appeler les différents appareils de votre contact et valider un code.

Vous êtes sur le point d’appeler “%1” voulez vous continuer ?").arg(verifyDevicePopup.deviceName) - buttons: RowLayout { - RowLayout { - spacing: 7 * DefaultStyle.dp - CheckBox{ - id: neverDisplayAgainCheckbox - } - Text { - text: qsTr("Ne plus afficher") - font.pixelSize: 14 * DefaultStyle.dp - MouseArea { - anchors.fill: parent - onClicked: neverDisplayAgainCheckbox.toggle() - } - } - } - Item{Layout.fillWidth: true} - RowLayout { - spacing: 15 * DefaultStyle.dp - BigButton { - style: ButtonStyle.secondary - text: qsTr("Annuler") - onClicked: verifyDevicePopup.close() - } - BigButton { - style: ButtonStyle.main - text: qsTr("Appeler") - onClicked: { - SettingsCpp.setDisplayDeviceCheckConfirmation(!neverDisplayAgainCheckbox.checked) - UtilsCpp.createCall(verifyDevicePopup.deviceAddress, {}, LinphoneEnums.MediaEncryption.Zrtp) - onClicked: verifyDevicePopup.close() - } - } - } - } - } - Dialog { - id: trustInfoDialog - width: 637 * DefaultStyle.dp - title: qsTr("Niveau de confiance") - text: qsTr("Vérifiez les appareils de votre contact pour confirmer que vos communications seront sécurisées et sans compromission.
Quand tous seront vérifiés, vous atteindrez le niveau de confiance maximal.") - content: RowLayout { - spacing: 50 * DefaultStyle.dp - Avatar { - _address: "sip:a.c@sip.linphone.org" - Layout.preferredWidth: 45 * DefaultStyle.dp - Layout.preferredHeight: 45 * DefaultStyle.dp - } - EffectImage { - imageSource: AppIcons.arrowRight - colorizationColor: DefaultStyle.main2_600 - Layout.preferredWidth: 45 * DefaultStyle.dp - Layout.preferredHeight: 45 * DefaultStyle.dp - } - Avatar { - _address: "sip:a.c@sip.linphone.org" - secured: true - Layout.preferredWidth: 45 * DefaultStyle.dp - Layout.preferredHeight: 45 * DefaultStyle.dp - } - } - buttons: Button { - text: qsTr("Ok") - style: ButtonStyle.main - leftPadding: 30 * DefaultStyle.dp - rightPadding: 30 * DefaultStyle.dp - onClicked: trustInfoDialog.close() - } - } + function deleteContact(contact) { + if (!contact) + return + var mainWin = UtilsCpp.getMainWindow() + mainWin.showConfirmationLambdaPopup( + "", qsTr( + "%1 sera supprimé des contacts. Voulez-vous continuer ?").arg( + contact.core.fullName), "", function (confirmed) { + if (confirmed) { + var name = contact.core.fullName + contact.core.remove() + contactList.resetSelections() + UtilsCpp.showInformationPopup( + qsTr("Supprimé"), + qsTr("%1 a été supprimé").arg(name)) + } + }) + } - leftPanelContent: FocusScope { - id: leftPanel - property int leftMargin: 45 * DefaultStyle.dp - property int rightMargin: 39 * DefaultStyle.dp - Layout.fillHeight: true - Layout.fillWidth: true + Dialog { + id: verifyDevicePopup + property string deviceName + property string deviceAddress + padding: 30 * DefaultStyle.dp + width: 637 * DefaultStyle.dp + anchors.centerIn: parent + closePolicy: Control.Popup.CloseOnEscape + modal: true + onAboutToHide: neverDisplayAgainCheckbox.checked = false + title: qsTr("Augmenter la confiance") + text: qsTr("Pour augmenter le niveau de confiance vous devez appeler les différents appareils de votre contact et valider un code.

Vous êtes sur le point d’appeler “%1” voulez vous continuer ?").arg( + verifyDevicePopup.deviceName) + buttons: RowLayout { + RowLayout { + spacing: 7 * DefaultStyle.dp + CheckBox { + id: neverDisplayAgainCheckbox + } + Text { + text: qsTr("Ne plus afficher") + font.pixelSize: 14 * DefaultStyle.dp + MouseArea { + anchors.fill: parent + onClicked: neverDisplayAgainCheckbox.toggle() + } + } + } + Item { + Layout.fillWidth: true + } + RowLayout { + spacing: 15 * DefaultStyle.dp + BigButton { + style: ButtonStyle.secondary + text: qsTr("Annuler") + onClicked: verifyDevicePopup.close() + } + BigButton { + style: ButtonStyle.main + text: qsTr("Appeler") + onClicked: { + SettingsCpp.setDisplayDeviceCheckConfirmation( + !neverDisplayAgainCheckbox.checked) + UtilsCpp.createCall(verifyDevicePopup.deviceAddress, + {}, + LinphoneEnums.MediaEncryption.Zrtp) + onClicked: verifyDevicePopup.close() + } + } + } + } + } + Dialog { + id: trustInfoDialog + width: 637 * DefaultStyle.dp + title: qsTr("Niveau de confiance") + text: qsTr("Vérifiez les appareils de votre contact pour confirmer que vos communications seront sécurisées et sans compromission.
Quand tous seront vérifiés, vous atteindrez le niveau de confiance maximal.") + content: RowLayout { + spacing: 50 * DefaultStyle.dp + Avatar { + _address: "sip:a.c@sip.linphone.org" + Layout.preferredWidth: 45 * DefaultStyle.dp + Layout.preferredHeight: 45 * DefaultStyle.dp + } + EffectImage { + imageSource: AppIcons.arrowRight + colorizationColor: DefaultStyle.main2_600 + Layout.preferredWidth: 45 * DefaultStyle.dp + Layout.preferredHeight: 45 * DefaultStyle.dp + } + Avatar { + _address: "sip:a.c@sip.linphone.org" + secured: true + Layout.preferredWidth: 45 * DefaultStyle.dp + Layout.preferredHeight: 45 * DefaultStyle.dp + } + } + buttons: Button { + text: qsTr("Ok") + style: ButtonStyle.main + leftPadding: 30 * DefaultStyle.dp + rightPadding: 30 * DefaultStyle.dp + onClicked: trustInfoDialog.close() + } + } - RowLayout { - id: title - spacing: 0 - anchors.top: leftPanel.top - anchors.right: leftPanel.right - anchors.left: leftPanel.left - anchors.leftMargin: leftPanel.leftMargin - anchors.rightMargin: leftPanel.rightMargin + leftPanelContent: FocusScope { + id: leftPanel + property int leftMargin: 45 * DefaultStyle.dp + property int rightMargin: 39 * DefaultStyle.dp + Layout.fillHeight: true + Layout.fillWidth: true - Text { - text: qsTr("Contacts") - color: DefaultStyle.main2_700 - font.pixelSize: 29 * DefaultStyle.dp - font.weight: 800 * DefaultStyle.dp - } - Item { - Layout.fillWidth: true - } - Button { - id: createContactButton - visible: !rightPanelStackView.currentItem || rightPanelStackView.currentItem.objectName !== "contactEdition" - style: ButtonStyle.noBackground - icon.source: AppIcons.plusCircle - Layout.preferredWidth: 28 * DefaultStyle.dp - Layout.preferredHeight: 28 * DefaultStyle.dp - icon.width: 28 * DefaultStyle.dp - icon.height: 28 * DefaultStyle.dp - onClicked: { - mainItem.createContact("", "") - } - KeyNavigation.down: searchBar - } - } - - ColumnLayout { - anchors.top: title.bottom - anchors.right: leftPanel.right + RowLayout { + id: title + spacing: 0 + anchors.top: leftPanel.top + anchors.right: leftPanel.right anchors.left: leftPanel.left anchors.leftMargin: leftPanel.leftMargin - anchors.bottom: leftPanel.bottom - enabled: mainItem.leftPanelEnabled + anchors.rightMargin: leftPanel.rightMargin + + Text { + text: qsTr("Contacts") + color: DefaultStyle.main2_700 + font.pixelSize: 29 * DefaultStyle.dp + font.weight: 800 * DefaultStyle.dp + } + Item { + Layout.fillWidth: true + } + Button { + id: createContactButton + visible: !rightPanelStackView.currentItem + || rightPanelStackView.currentItem.objectName !== "contactEdition" + style: ButtonStyle.noBackground + icon.source: AppIcons.plusCircle + Layout.preferredWidth: 28 * DefaultStyle.dp + Layout.preferredHeight: 28 * DefaultStyle.dp + icon.width: 28 * DefaultStyle.dp + icon.height: 28 * DefaultStyle.dp + onClicked: { + mainItem.createContact("", "") + } + KeyNavigation.down: searchBar + } + } + + ColumnLayout { + anchors.top: title.bottom + anchors.right: leftPanel.right + anchors.left: leftPanel.left + anchors.leftMargin: leftPanel.leftMargin + anchors.bottom: leftPanel.bottom + enabled: mainItem.leftPanelEnabled spacing: 38 * DefaultStyle.dp - SearchBar { - id: searchBar + SearchBar { + id: searchBar visible: contactList.haveContacts || text.length !== 0 Layout.rightMargin: leftPanel.rightMargin - Layout.topMargin: 18 * DefaultStyle.dp - Layout.fillWidth: true - placeholderText: qsTr("Rechercher un contact") - KeyNavigation.up: createContactButton - KeyNavigation.down: contactList - } - ColumnLayout { - id: content + Layout.topMargin: 18 * DefaultStyle.dp + Layout.fillWidth: true + placeholderText: qsTr("Rechercher un contact") + KeyNavigation.up: createContactButton + KeyNavigation.down: contactList + } + ColumnLayout { + id: content spacing: 15 * DefaultStyle.dp - Text { - visible: !contactList.loading && !contactList.haveContacts + Text { + visible: !contactList.loading && !contactList.haveContacts Layout.alignment: Qt.AlignHCenter - Layout.topMargin: 137 * DefaultStyle.dp - text: qsTr("Aucun contact%1").arg(searchBar.text.length !== 0 ? " correspondant" : "") - font { - pixelSize: 16 * DefaultStyle.dp - weight: 800 * DefaultStyle.dp - } - } - AllContactListView{ - id: contactList - Layout.fillWidth: true - Layout.fillHeight: true + Layout.topMargin: 137 * DefaultStyle.dp + text: qsTr("Aucun contact%1").arg( + searchBar.text.length !== 0 ? " correspondant" : "") + font { + pixelSize: 16 * DefaultStyle.dp + weight: 800 * DefaultStyle.dp + } + } + AllContactListView { + id: contactList + Layout.fillWidth: true + Layout.fillHeight: true Layout.rightMargin: 8 * DefaultStyle.dp - searchBarText: searchBar.text - hideSuggestions: true - showDefaultAddress: false - sourceFlags: LinphoneEnums.MagicSearchSource.Friends | LinphoneEnums.MagicSearchSource.FavoriteFriends | LinphoneEnums.MagicSearchSource.LdapServers | LinphoneEnums.MagicSearchSource.RemoteCardDAV - onHighlightedContactChanged: mainItem.selectedContact = highlightedContact - onContactDeletionRequested: (contact) => { - mainItem.deleteContact(contact) - } - onLoadingChanged: { - if(!loading && initialFriendToDisplay.length !== 0) { - Qt.callLater(function(){ - if (selectContact(initialFriendToDisplay) != -1) initialFriendToDisplay = "" - }) - } - } - } - } - } - } + searchBarText: searchBar.text + hideSuggestions: true + showDefaultAddress: false + sourceFlags: LinphoneEnums.MagicSearchSource.Friends + | LinphoneEnums.MagicSearchSource.FavoriteFriends + | LinphoneEnums.MagicSearchSource.LdapServers + | LinphoneEnums.MagicSearchSource.RemoteCardDAV + onHighlightedContactChanged: mainItem.selectedContact = highlightedContact + onContactDeletionRequested: contact => { + mainItem.deleteContact( + contact) + } + onLoadingChanged: { + if (!loading && initialFriendToDisplay.length !== 0) { + Qt.callLater(function () { + if (selectContact(initialFriendToDisplay) != -1) + initialFriendToDisplay = "" + }) + } + } + } + } + } + } - Component { - id: contactDetail - Item { - width: parent?.width - height: parent?.height - property string objectName: "contactDetail" - component ContactDetailLayout: ColumnLayout { - id: contactDetailLayout - spacing: 15 * DefaultStyle.dp - property string label - property var icon - property alias content: contentControl.contentItem - signal titleIconClicked() - RowLayout { - spacing: 10 * DefaultStyle.dp - Text { - text: contactDetailLayout.label - color: DefaultStyle.main1_500_main - font { - pixelSize: 16 * DefaultStyle.dp - weight: 800 * DefaultStyle.dp - } - } - RoundButton { - visible: contactDetailLayout.icon != undefined - icon.source: contactDetailLayout.icon - style: ButtonStyle.noBackgroundOrange - onClicked: contactDetailLayout.titleIconClicked() - } - Item{Layout.fillWidth: true} - RoundButton { - id: expandButton - style: ButtonStyle.noBackground - checkable: true - checked: true - icon.source: checked ? AppIcons.upArrow : AppIcons.downArrow - KeyNavigation.down: contentControl - } - } - RoundedPane { - id: contentControl - visible: expandButton.checked - Layout.fillWidth: true - leftPadding: 20 * DefaultStyle.dp - rightPadding: 20 * DefaultStyle.dp - topPadding: 17 * DefaultStyle.dp - bottomPadding: 17 * DefaultStyle.dp - } - } - ContactLayout { - id: contactDetail - anchors.fill: parent - contact: mainItem.selectedContact - button.color: DefaultStyle.main1_100 - button.text: qsTr("Modifier") - button.style: ButtonStyle.tertiary - button.icon.source: AppIcons.pencil - button.onClicked: mainItem.editContact(mainItem.selectedContact) - button.visible: !mainItem.selectedContact?.core.readOnly - property string contactAddress: contact ? contact.core.defaultAddress : "" - property var computedContactNameObj: UtilsCpp.getDisplayName(contactAddress) - property string computedContactName: computedContactNameObj ? computedContactNameObj.value : "" - property string contactName: contact - ? contact.core.fullName - : computedContactName - component LabelButton: ColumnLayout { - id: labelButton - // property alias image: buttonImg - property alias button: button - property string label - spacing: 8 * DefaultStyle.dp - RoundButton { - id: button - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: 56 * DefaultStyle.dp - Layout.preferredHeight: 56 * DefaultStyle.dp - style: ButtonStyle.grey - } - Text { - Layout.alignment: Qt.AlignHCenter - text: labelButton.label - font { - pixelSize: 14 * DefaultStyle.dp - weight: 400 * DefaultStyle.dp - } - } - } - component ActionsButtons: RowLayout { - spacing: 58 * DefaultStyle.dp - LabelButton { - button.icon.source: AppIcons.phone - label: qsTr("Appel") - width: 56 * DefaultStyle.dp - height: 56 * DefaultStyle.dp - button.icon.width: 24 * DefaultStyle.dp - button.icon.height: 24 * DefaultStyle.dp - button.onClicked: mainWindow.startCallWithContact(contactDetail.contact, false, mainItem) - } - LabelButton { - button.icon.source: AppIcons.chatTeardropText - visible: !SettingsCpp.disableChatFeature - label: qsTr("Message") - width: 56 * DefaultStyle.dp - height: 56 * DefaultStyle.dp - button.icon.width: 24 * DefaultStyle.dp - button.icon.height: 24 * DefaultStyle.dp - button.onClicked: console.debug("[ContactLayout.qml] TODO : open conversation") - } - LabelButton { - button.icon.source: AppIcons.videoCamera - label: qsTr("Appel vidéo") - width: 56 * DefaultStyle.dp - height: 56 * DefaultStyle.dp - button.icon.width: 24 * DefaultStyle.dp - button.icon.height: 24 * DefaultStyle.dp - button.onClicked: mainWindow.startCallWithContact(contactDetail.contact, true, mainItem) - } - } - bannerContent: [ - ColumnLayout { - spacing: 0 - Text { - text: contactDetail.contactName - Layout.fillWidth: true - maximumLineCount: 1 - font { - pixelSize: 29 * DefaultStyle.dp - weight: 800 * DefaultStyle.dp - capitalization: Font.Capitalize - } - } - Text { - visible: contactDetail.contact - property var mode : contactDetail.contact ? contactDetail.contact.core.consolidatedPresence : -1 - horizontalAlignment: Text.AlignLeft - Layout.fillWidth: true - text: mode === LinphoneEnums.ConsolidatedPresence.Online - ? qsTr("En ligne") - : mode === LinphoneEnums.ConsolidatedPresence.Busy - ? qsTr("Occupé") - : mode === LinphoneEnums.ConsolidatedPresence.DoNotDisturb - ? qsTr("Ne pas déranger") - : qsTr("Hors ligne") - color: mode === LinphoneEnums.ConsolidatedPresence.Online - ? DefaultStyle.success_500main - : mode === LinphoneEnums.ConsolidatedPresence.Busy - ? DefaultStyle.warning_600 - : mode === LinphoneEnums.ConsolidatedPresence.DoNotDisturb - ? DefaultStyle.danger_500main - : DefaultStyle.main2_500main - font.pixelSize: 14 * DefaultStyle.dp - } - }, - ActionsButtons { - visible: !contactDetail.useVerticalLayout - } - ] - secondLineContent: ActionsButtons{} - content: Flickable { - contentWidth: parent.width - ColumnLayout { - spacing: 32 * DefaultStyle.dp - anchors.left: parent.left - anchors.right: parent.right - ColumnLayout { - spacing: 15 * DefaultStyle.dp - Layout.fillWidth: true - ContactDetailLayout { - id: infoLayout - Layout.fillWidth: true - label: qsTr("Informations") - content: ListView { - id: addrList - height: contentHeight - implicitHeight: contentHeight - width: parent.width - clip: true - spacing: 9 * DefaultStyle.dp - model: VariantList { - model: (mainItem.selectedContact ? UtilsCpp.append(mainItem.selectedContact.core.addresses, mainItem.selectedContact.core.phoneNumbers): []) - } - delegate: Item { - property var listViewModelData: modelData - width: addrList.width - height: 46 * DefaultStyle.dp + Component { + id: contactDetail + Item { + width: parent?.width + height: parent?.height + property string objectName: "contactDetail" + component ContactDetailLayout: ColumnLayout { + id: contactDetailLayout + spacing: 15 * DefaultStyle.dp + property string label + property var icon + property alias content: contentControl.contentItem + signal titleIconClicked + RowLayout { + spacing: 10 * DefaultStyle.dp + Text { + text: contactDetailLayout.label + color: DefaultStyle.main1_500_main + font { + pixelSize: 16 * DefaultStyle.dp + weight: 800 * DefaultStyle.dp + } + } + RoundButton { + visible: contactDetailLayout.icon != undefined + icon.source: contactDetailLayout.icon + style: ButtonStyle.noBackgroundOrange + onClicked: contactDetailLayout.titleIconClicked() + } + Item { + Layout.fillWidth: true + } + RoundButton { + id: expandButton + style: ButtonStyle.noBackground + checkable: true + checked: true + icon.source: checked ? AppIcons.upArrow : AppIcons.downArrow + KeyNavigation.down: contentControl + } + } + RoundedPane { + id: contentControl + visible: expandButton.checked + Layout.fillWidth: true + leftPadding: 20 * DefaultStyle.dp + rightPadding: 20 * DefaultStyle.dp + topPadding: 17 * DefaultStyle.dp + bottomPadding: 17 * DefaultStyle.dp + } + } + ContactLayout { + id: contactDetail + anchors.fill: parent + contact: mainItem.selectedContact + button.color: DefaultStyle.main1_100 + button.text: qsTr("Modifier") + button.style: ButtonStyle.tertiary + button.icon.source: AppIcons.pencil + button.onClicked: mainItem.editContact(mainItem.selectedContact) + button.visible: !mainItem.selectedContact?.core.readOnly + property string contactAddress: contact ? contact.core.defaultAddress : "" + property var computedContactNameObj: UtilsCpp.getDisplayName( + contactAddress) + property string computedContactName: computedContactNameObj ? computedContactNameObj.value : "" + property string contactName: contact ? contact.core.fullName : computedContactName + component LabelButton: ColumnLayout { + id: labelButton + // property alias image: buttonImg + property alias button: button + property string label + spacing: 8 * DefaultStyle.dp + RoundButton { + id: button + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: 56 * DefaultStyle.dp + Layout.preferredHeight: 56 * DefaultStyle.dp + style: ButtonStyle.grey + } + Text { + Layout.alignment: Qt.AlignHCenter + text: labelButton.label + font { + pixelSize: 14 * DefaultStyle.dp + weight: 400 * DefaultStyle.dp + } + } + } + component ActionsButtons: RowLayout { + spacing: 58 * DefaultStyle.dp + LabelButton { + button.icon.source: AppIcons.phone + label: qsTr("Appel") + width: 56 * DefaultStyle.dp + height: 56 * DefaultStyle.dp + button.icon.width: 24 * DefaultStyle.dp + button.icon.height: 24 * DefaultStyle.dp + button.onClicked: mainWindow.startCallWithContact( + contactDetail.contact, + false, mainItem) + } + LabelButton { + button.icon.source: AppIcons.chatTeardropText + visible: !SettingsCpp.disableChatFeature + label: qsTr("Message") + width: 56 * DefaultStyle.dp + height: 56 * DefaultStyle.dp + button.icon.width: 24 * DefaultStyle.dp + button.icon.height: 24 * DefaultStyle.dp + button.onClicked: console.debug( + "[ContactLayout.qml] TODO : open conversation") + } + LabelButton { + button.icon.source: AppIcons.videoCamera + label: qsTr("Appel vidéo") + width: 56 * DefaultStyle.dp + height: 56 * DefaultStyle.dp + button.icon.width: 24 * DefaultStyle.dp + button.icon.height: 24 * DefaultStyle.dp + button.onClicked: mainWindow.startCallWithContact( + contactDetail.contact, + true, mainItem) + } + } + bannerContent: [ + ColumnLayout { + spacing: 0 + Text { + text: contactDetail.contactName + Layout.fillWidth: true + maximumLineCount: 1 + font { + pixelSize: 29 * DefaultStyle.dp + weight: 800 * DefaultStyle.dp + capitalization: Font.Capitalize + } + } + Text { + visible: contactDetail.contact + property var mode: contactDetail.contact ? contactDetail.contact.core.consolidatedPresence : -1 + horizontalAlignment: Text.AlignLeft + Layout.fillWidth: true + text: mode === LinphoneEnums.ConsolidatedPresence.Online ? qsTr("En ligne") : mode === LinphoneEnums.ConsolidatedPresence.Busy ? qsTr("Occupé") : mode === LinphoneEnums.ConsolidatedPresence.DoNotDisturb ? qsTr("Ne pas déranger") : qsTr("Hors ligne") + color: mode === LinphoneEnums.ConsolidatedPresence.Online ? DefaultStyle.success_500main : mode === LinphoneEnums.ConsolidatedPresence.Busy ? DefaultStyle.warning_600 : mode === LinphoneEnums.ConsolidatedPresence.DoNotDisturb ? DefaultStyle.danger_500main : DefaultStyle.main2_500main + font.pixelSize: 14 * DefaultStyle.dp + } + }, + ActionsButtons { + visible: !contactDetail.useVerticalLayout + } + ] + secondLineContent: ActionsButtons {} + content: Flickable { + contentWidth: parent.width + ColumnLayout { + spacing: 32 * DefaultStyle.dp + anchors.left: parent.left + anchors.right: parent.right + ColumnLayout { + spacing: 15 * DefaultStyle.dp + Layout.fillWidth: true + ContactDetailLayout { + id: infoLayout + Layout.fillWidth: true + label: qsTr("Informations") + content: ListView { + id: addrList + height: contentHeight + implicitHeight: contentHeight + width: parent.width + clip: true + spacing: 9 * DefaultStyle.dp + model: VariantList { + model: (mainItem.selectedContact ? UtilsCpp.append(mainItem.selectedContact.core.addresses, mainItem.selectedContact.core.phoneNumbers) : []) + } + delegate: Item { + property var listViewModelData: modelData + width: addrList.width + height: 46 * DefaultStyle.dp - ColumnLayout { - anchors.fill: parent - // anchors.topMargin: 5 * DefaultStyle.dp - RowLayout { - Layout.fillWidth: true - // Layout.fillHeight: true - // Layout.alignment: Qt.AlignVCenter - // Layout.topMargin: 10 * DefaultStyle.dp - // Layout.bottomMargin: 10 * DefaultStyle.dp - ColumnLayout { - Layout.fillWidth: true - Text { - Layout.fillWidth: true - text: listViewModelData.label - font { - pixelSize: 13 * DefaultStyle.dp - weight: 700 * DefaultStyle.dp - } - } - Text { - Layout.fillWidth: true - property string _text: listViewModelData.address - text: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(_text) : _text - font { - pixelSize: 14 * DefaultStyle.dp - weight: 400 * DefaultStyle.dp - } - } - } - Item { - Layout.fillWidth: true - } - RoundButton { - style: ButtonStyle.noBackground - icon.source: AppIcons.phone - onClicked: { - UtilsCpp.createCall(listViewModelData.address) - } - } - } + ColumnLayout { + anchors.fill: parent + // anchors.topMargin: 5 * DefaultStyle.dp + RowLayout { + Layout.fillWidth: true + // Layout.fillHeight: true + // Layout.alignment: Qt.AlignVCenter + // Layout.topMargin: 10 * DefaultStyle.dp + // Layout.bottomMargin: 10 * DefaultStyle.dp + ColumnLayout { + Layout.fillWidth: true + Text { + Layout.fillWidth: true + text: listViewModelData.label + font { + pixelSize: 13 * DefaultStyle.dp + weight: 700 * DefaultStyle.dp + } + } + Text { + Layout.fillWidth: true + property string _text: listViewModelData.address + text: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(_text) : _text + font { + pixelSize: 14 * DefaultStyle.dp + weight: 400 * DefaultStyle.dp + } + } + } + Item { + Layout.fillWidth: true + } + RoundButton { + style: ButtonStyle.noBackground + icon.source: AppIcons.phone + onClicked: { + UtilsCpp.createCall( + listViewModelData.address) + } + } + } - Rectangle { - visible: index != addrList.model.count - 1 - Layout.fillWidth: true - Layout.preferredHeight: 1 * DefaultStyle.dp - Layout.rightMargin: 3 * DefaultStyle.dp - Layout.leftMargin: 3 * DefaultStyle.dp - color: DefaultStyle.main2_200 - clip: true - } - } - } - } - } - RoundedPane { - visible: infoLayout.visible && companyText.text.length != 0 || jobText.text.length != 0 - Layout.fillWidth: true - topPadding: 17 * DefaultStyle.dp - bottomPadding: 17 * DefaultStyle.dp - leftPadding: 20 * DefaultStyle.dp - rightPadding: 20 * DefaultStyle.dp + Rectangle { + visible: index != addrList.model.count - 1 + Layout.fillWidth: true + Layout.preferredHeight: 1 * DefaultStyle.dp + Layout.rightMargin: 3 * DefaultStyle.dp + Layout.leftMargin: 3 * DefaultStyle.dp + color: DefaultStyle.main2_200 + clip: true + } + } + } + } + } + RoundedPane { + visible: infoLayout.visible + && companyText.text.length != 0 + || jobText.text.length != 0 + Layout.fillWidth: true + topPadding: 17 * DefaultStyle.dp + bottomPadding: 17 * DefaultStyle.dp + leftPadding: 20 * DefaultStyle.dp + rightPadding: 20 * DefaultStyle.dp - contentItem: ColumnLayout { - RowLayout { - height: 50 * DefaultStyle.dp - visible: companyText.text.length != 0 - Text { - text: qsTr("Société :") - font { - pixelSize: 13 * DefaultStyle.dp - weight: 700 * DefaultStyle.dp - } - } - Text { - id: companyText - text: mainItem.selectedContact && mainItem.selectedContact.core.organization - font { - pixelSize: 14 * DefaultStyle.dp - weight: 400 * DefaultStyle.dp - } - } - } - RowLayout { - height: 50 * DefaultStyle.dp - visible: jobText.text.length != 0 - Text { - text: qsTr("Poste :") - font { - pixelSize: 13 * DefaultStyle.dp - weight: 700 * DefaultStyle.dp - } - } - Text { - id: jobText - text: mainItem.selectedContact && mainItem.selectedContact.core.job - font { - pixelSize: 14 * DefaultStyle.dp - weight: 400 * DefaultStyle.dp - } - } - } - } - } - } - ContactDetailLayout { - visible: !SettingsCpp.disableChatFeature - label: qsTr("Medias") - Layout.fillWidth: true - content: Button { - style: ButtonStyle.noBackground - contentItem: RowLayout { - EffectImage { - Layout.preferredWidth: 24 * DefaultStyle.dp - Layout.preferredHeight: 24 * DefaultStyle.dp - source: AppIcons.shareNetwork - colorizationColor: DefaultStyle.main2_600 - } - Text { - text: qsTr("Afficher les medias partagés") - font { - pixelSize: Typography.p1.pixelSize - weight: Typography.p1.weight - } - } - Item{Layout.fillWidth: true} - EffectImage { - Layout.preferredWidth: 24 * DefaultStyle.dp - Layout.preferredHeight: 24 * DefaultStyle.dp - imageSource: AppIcons.rightArrow - colorizationColor: DefaultStyle.main2_600 - } - } - onClicked: console.debug("TODO : go to shared media") - } - } - ContactDetailLayout { - Layout.fillWidth: true - label: qsTr("Confiance") - icon: AppIcons.question - onTitleIconClicked: trustInfoDialog.open() - content: ColumnLayout { - spacing: 13 * DefaultStyle.dp - Text { - text: qsTr("Niveau de confiance - Appareils vérifiés") - font { - pixelSize: 13 * DefaultStyle.dp - weight: 700 * DefaultStyle.dp - } - } - Text { - visible: deviceList.count === 0 - text: qsTr("Aucun appareil") - } - ProgressBar { - visible: deviceList.count > 0 - Layout.fillWidth: true - Layout.preferredHeight: 28 * DefaultStyle.dp + contentItem: ColumnLayout { + RowLayout { + height: 50 * DefaultStyle.dp + visible: companyText.text.length != 0 + Text { + text: qsTr("Société :") + font { + pixelSize: 13 * DefaultStyle.dp + weight: 700 * DefaultStyle.dp + } + } + Text { + id: companyText + text: mainItem.selectedContact + && mainItem.selectedContact.core.organization + font { + pixelSize: 14 * DefaultStyle.dp + weight: 400 * DefaultStyle.dp + } + } + } + RowLayout { + height: 50 * DefaultStyle.dp + visible: jobText.text.length != 0 + Text { + text: qsTr("Poste :") + font { + pixelSize: 13 * DefaultStyle.dp + weight: 700 * DefaultStyle.dp + } + } + Text { + id: jobText + text: mainItem.selectedContact + && mainItem.selectedContact.core.job + font { + pixelSize: 14 * DefaultStyle.dp + weight: 400 * DefaultStyle.dp + } + } + } + } + } + } + ContactDetailLayout { + visible: !SettingsCpp.disableChatFeature + label: qsTr("Medias") + Layout.fillWidth: true + content: Button { + style: ButtonStyle.noBackground + contentItem: RowLayout { + EffectImage { + Layout.preferredWidth: 24 * DefaultStyle.dp + Layout.preferredHeight: 24 * DefaultStyle.dp + source: AppIcons.shareNetwork + colorizationColor: DefaultStyle.main2_600 + } + Text { + text: qsTr("Afficher les medias partagés") + font { + pixelSize: Typography.p1.pixelSize + weight: Typography.p1.weight + } + } + Item { + Layout.fillWidth: true + } + EffectImage { + Layout.preferredWidth: 24 * DefaultStyle.dp + Layout.preferredHeight: 24 * DefaultStyle.dp + imageSource: AppIcons.rightArrow + colorizationColor: DefaultStyle.main2_600 + } + } + onClicked: console.debug( + "TODO : go to shared media") + } + } + ContactDetailLayout { + Layout.fillWidth: true + label: qsTr("Confiance") + icon: AppIcons.question + onTitleIconClicked: trustInfoDialog.open() + content: ColumnLayout { + spacing: 13 * DefaultStyle.dp + Text { + text: qsTr("Niveau de confiance - Appareils vérifiés") + font { + pixelSize: 13 * DefaultStyle.dp + weight: 700 * DefaultStyle.dp + } + } + Text { + visible: deviceList.count === 0 + text: qsTr("Aucun appareil") + } + ProgressBar { + visible: deviceList.count > 0 + Layout.fillWidth: true + Layout.preferredHeight: 28 * DefaultStyle.dp value: mainItem.selectedContact ? mainItem.selectedContact.core.verifiedDeviceCount / deviceList.count : 0 - } - ListView { - id: deviceList - Layout.fillWidth: true - Layout.preferredHeight: Math.min(200 * DefaultStyle.dp, contentHeight) - clip: true - model: mainItem.selectedContact ? mainItem.selectedContact.core.devices : [] - spacing: 16 * DefaultStyle.dp - delegate: RowLayout { - id: deviceDelegate - width: deviceList.width - height: 30 * DefaultStyle.dp - property var listViewModelData: modelData - property var callObj - property CallGui deviceCall: callObj ? callObj.value : null - property string deviceName: listViewModelData.name.length != 0 ? listViewModelData.name : qsTr("Appareil sans nom") - Text { - text: deviceDelegate.deviceName - font.pixelSize: 14 * DefaultStyle.dp - } - Item{Layout.fillWidth: true} - EffectImage { - visible: listViewModelData.securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified - imageSource: AppIcons.trusted - Layout.preferredWidth: 22 * DefaultStyle.dp - Layout.preferredHeight: 22 * DefaultStyle.dp - } - - SmallButton { - // Layout.preferredHeight: 30 * DefaultStyle.dp - visible: listViewModelData.securityLevel != LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified - icon.source: AppIcons.warningCircle - style: ButtonStyle.tertiary - text: qsTr("Vérifier") - onClicked: { - if (SettingsCpp.getDisplayDeviceCheckConfirmation()) { - verifyDevicePopup.deviceName = deviceDelegate.deviceName - verifyDevicePopup.deviceAddress = listViewModelData.address - verifyDevicePopup.open() - } - else { - UtilsCpp.createCall(listViewModelData.address, {}, LinphoneEnums.MediaEncryption.Zrtp) - parent.callObj = UtilsCpp.getCallByAddress(listViewModelData.address) - } - } - } - } - } - } - } - ContactDetailLayout { - Layout.fillWidth: true - label: qsTr("Autres actions") - content: ColumnLayout { - width: parent.width - IconLabelButton { - Layout.fillWidth: true - Layout.preferredHeight: 50 * DefaultStyle.dp - icon.source: AppIcons.pencil - text: qsTr("Éditer") - onClicked: mainItem.editContact(mainItem.selectedContact) - visible: !mainItem.selectedContact?.core.readOnly - style: ButtonStyle.noBackground - } - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: 1 * DefaultStyle.dp - color: DefaultStyle.main2_200 - } - IconLabelButton { - Layout.fillWidth: true - Layout.preferredHeight: 50 * DefaultStyle.dp - icon.source: mainItem.selectedContact && mainItem.selectedContact.core.starred ? AppIcons.heartFill : AppIcons.heart - text: mainItem.selectedContact && mainItem.selectedContact.core.starred ? qsTr("Retirer des favoris") : qsTr("Ajouter aux favoris") - style: ButtonStyle.noBackground - onClicked: if (mainItem.selectedContact) mainItem.selectedContact.core.lSetStarred(!mainItem.selectedContact.core.starred) - } - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: 1 * DefaultStyle.dp - color: DefaultStyle.main2_200 - } - IconLabelButton { - Layout.fillWidth: true - Layout.preferredHeight: 50 * DefaultStyle.dp - icon.source: AppIcons.shareNetwork - text: qsTr("Partager") - style: ButtonStyle.noBackground - onClicked: { - if (mainItem.selectedContact) { - var vcard = mainItem.selectedContact.core.getVCard() - var username = mainItem.selectedContact.core.givenName + mainItem.selectedContact.core.familyName - var filepath = UtilsCpp.createVCardFile(username, vcard) - if (filepath == "") UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("La création du fichier vcard a échoué"), false) - else mainWindow.showInformationPopup(qsTr("VCard créée"), qsTr("VCard du contact enregistrée dans %1").arg(filepath)) - UtilsCpp.shareByEmail(qsTr("Partage de contact"), vcard, filepath) - } - } - } - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: 1 * DefaultStyle.dp - color: DefaultStyle.main2_200 - } - // IconLabelButton { - // Layout.fillWidth: true - // Layout.preferredHeight: 50 * DefaultStyle.dp - // icon.source: AppIcons.bellSlash - // text: qsTr("Mettre en sourdine") - // onClicked: console.log("TODO : mute contact") - // } - // Rectangle { - // Layout.fillWidth: true - // Layout.preferredHeight: 1 * DefaultStyle.dp - // color: DefaultStyle.main2_200 - // } - // IconLabelButton { - // Layout.fillWidth: true - // Layout.preferredHeight: 50 * DefaultStyle.dp - // icon.source: AppIcons.empty - // text: qsTr("Bloquer") - // onClicked: console.log("TODO : block contact") - // } - // Rectangle { - // Layout.fillWidth: true - // Layout.preferredHeight: 1 * DefaultStyle.dp - // color: DefaultStyle.main2_200 - // } - IconLabelButton { - Layout.fillWidth: true - Layout.preferredHeight: 50 * DefaultStyle.dp - icon.source: AppIcons.trashCan - text: qsTr("Supprimer ce contact") - visible: !mainItem.selectedContact?.core.readOnly - onClicked: { - mainItem.deleteContact(mainItem.selectedContact) - } - style: ButtonStyle.noBackgroundRed - } - } - - } - Item{ - Layout.fillHeight: true - } - } - } - } - } - } + } + ListView { + id: deviceList + Layout.fillWidth: true + Layout.preferredHeight: Math.min( + 200 * DefaultStyle.dp, + contentHeight) + clip: true + model: mainItem.selectedContact ? mainItem.selectedContact.core.devices : [] + spacing: 16 * DefaultStyle.dp + delegate: RowLayout { + id: deviceDelegate + width: deviceList.width + height: 30 * DefaultStyle.dp + property var listViewModelData: modelData + property var callObj + property CallGui deviceCall: callObj ? callObj.value : null + property string deviceName: listViewModelData.name.length != 0 ? listViewModelData.name : qsTr("Appareil sans nom") + Text { + text: deviceDelegate.deviceName + font.pixelSize: 14 * DefaultStyle.dp + } + Item { + Layout.fillWidth: true + } + EffectImage { + visible: listViewModelData.securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified + imageSource: AppIcons.trusted + Layout.preferredWidth: 22 * DefaultStyle.dp + Layout.preferredHeight: 22 * DefaultStyle.dp + } - Component { - id: contactEdition - ContactEdition { - property string objectName: "contactEdition" - onCloseEdition: redirectAddress => { - goToContactDetails() - if(redirectAddress){ - initialFriendToDisplay = redirectAddress - } - } - } - } + SmallButton { + // Layout.preferredHeight: 30 * DefaultStyle.dp + visible: listViewModelData.securityLevel != LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified + icon.source: AppIcons.warningCircle + style: ButtonStyle.tertiary + text: qsTr("Vérifier") + onClicked: { + if (SettingsCpp.getDisplayDeviceCheckConfirmation( + )) { + verifyDevicePopup.deviceName + = deviceDelegate.deviceName + verifyDevicePopup.deviceAddress + = listViewModelData.address + verifyDevicePopup.open() + } else { + UtilsCpp.createCall( + listViewModelData.address, + {}, + LinphoneEnums.MediaEncryption.Zrtp) + parent.callObj = UtilsCpp.getCallByAddress( + listViewModelData.address) + } + } + } + } + } + } + } + ContactDetailLayout { + Layout.fillWidth: true + label: qsTr("Autres actions") + content: ColumnLayout { + width: parent.width + IconLabelButton { + Layout.fillWidth: true + Layout.preferredHeight: 50 * DefaultStyle.dp + icon.source: AppIcons.pencil + text: qsTr("Éditer") + onClicked: mainItem.editContact( + mainItem.selectedContact) + visible: !mainItem.selectedContact?.core.readOnly + style: ButtonStyle.noBackground + } + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 * DefaultStyle.dp + color: DefaultStyle.main2_200 + } + IconLabelButton { + Layout.fillWidth: true + Layout.preferredHeight: 50 * DefaultStyle.dp + icon.source: mainItem.selectedContact + && mainItem.selectedContact.core.starred ? AppIcons.heartFill : AppIcons.heart + text: mainItem.selectedContact + && mainItem.selectedContact.core.starred ? qsTr("Retirer des favoris") : qsTr("Ajouter aux favoris") + style: ButtonStyle.noBackground + onClicked: if (mainItem.selectedContact) + mainItem.selectedContact.core.lSetStarred( + !mainItem.selectedContact.core.starred) + } + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 * DefaultStyle.dp + color: DefaultStyle.main2_200 + } + IconLabelButton { + Layout.fillWidth: true + Layout.preferredHeight: 50 * DefaultStyle.dp + icon.source: AppIcons.shareNetwork + text: qsTr("Partager") + style: ButtonStyle.noBackground + onClicked: { + if (mainItem.selectedContact) { + var vcard = mainItem.selectedContact.core.getVCard() + var username = mainItem.selectedContact.core.givenName + + mainItem.selectedContact.core.familyName + var filepath = UtilsCpp.createVCardFile( + username, vcard) + if (filepath == "") + UtilsCpp.showInformationPopup( + qsTr("Erreur"), + qsTr("La création du fichier vcard a échoué"), + false) + else + mainWindow.showInformationPopup( + qsTr( + "VCard créée"), + qsTr("VCard du contact enregistrée dans %1").arg( + filepath)) + UtilsCpp.shareByEmail( + qsTr("Partage de contact"), + vcard, filepath) + } + } + } + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 * DefaultStyle.dp + color: DefaultStyle.main2_200 + } + // IconLabelButton { + // Layout.fillWidth: true + // Layout.preferredHeight: 50 * DefaultStyle.dp + // icon.source: AppIcons.bellSlash + // text: qsTr("Mettre en sourdine") + // onClicked: console.log("TODO : mute contact") + // } + // Rectangle { + // Layout.fillWidth: true + // Layout.preferredHeight: 1 * DefaultStyle.dp + // color: DefaultStyle.main2_200 + // } + // IconLabelButton { + // Layout.fillWidth: true + // Layout.preferredHeight: 50 * DefaultStyle.dp + // icon.source: AppIcons.empty + // text: qsTr("Bloquer") + // onClicked: console.log("TODO : block contact") + // } + // Rectangle { + // Layout.fillWidth: true + // Layout.preferredHeight: 1 * DefaultStyle.dp + // color: DefaultStyle.main2_200 + // } + IconLabelButton { + Layout.fillWidth: true + Layout.preferredHeight: 50 * DefaultStyle.dp + icon.source: AppIcons.trashCan + text: qsTr("Supprimer ce contact") + visible: !mainItem.selectedContact?.core.readOnly + onClicked: { + mainItem.deleteContact( + mainItem.selectedContact) + } + style: ButtonStyle.noBackgroundRed + } + } + } + Item { + Layout.fillHeight: true + } + } + } + } + } + } + + Component { + id: contactEdition + ContactEdition { + property string objectName: "contactEdition" + onCloseEdition: redirectAddress => { + goToContactDetails() + if (redirectAddress) { + initialFriendToDisplay = redirectAddress + } + } + } + } }