fix #LINQT-1622 connection succeed popup

set new privacy policy and terms of use urls

fix mic volume tester visibility in call

fix #LINQT-1583 secured avatar on unsecured address in call history

fix #LINQT-1631 zrtp to verify devices

fix #LINQT-1526 title inside stackview to avoid freeze effect

fix #LINQT-1579 spacing in layouts

fix #LINQT-1625 right panel closes before new call starts

crop text sticker

fix verified icon size
This commit is contained in:
Gaelle Braud 2025-01-28 14:08:22 +01:00
parent 063cdfb33b
commit db6fc41480
17 changed files with 435 additions and 478 deletions

View file

@ -66,8 +66,8 @@ public:
static constexpr char VersionCheckReleaseUrl[] = "https://linphone.org/releases";
static constexpr char VersionCheckNightlyUrl[] = "https://linphone.org/snapshots";
static constexpr char PasswordRecoveryUrl[] = "https://subscribe.linphone.org/recovery/email";
static constexpr char CguUrl[] = "https://www.linphone.org/general-terms";
static constexpr char PrivatePolicyUrl[] = "https://www.linphone.org/privacy-policy";
static constexpr char CguUrl[] = "https://www.linphone.org/en/terms-of-use/";
static constexpr char PrivatePolicyUrl[] = "https://www.linphone.org/en/privacy-policy/";
static constexpr char ContactUrl[] = "https://www.linphone.org/contact";
static constexpr char TranslationUrl[] = "https://weblate.linphone.org/projects/linphone-desktop/";

View file

@ -135,8 +135,10 @@ void Utils::createCall(const QString &sipAddress,
LinphoneEnums::MediaEncryption mediaEncryption,
const QString &prepareTransfertAddress,
const QHash<QString, QString> &headers) {
mediaEncryption =
App::getInstance()->getSettings()->getMediaEncryption()["id"].value<LinphoneEnums::MediaEncryption>();
// if default value use the settings' value
if (mediaEncryption == LinphoneEnums::MediaEncryption::None)
mediaEncryption =
App::getInstance()->getSettings()->getMediaEncryption()["id"].value<LinphoneEnums::MediaEncryption>();
lDebug() << "[Utils] create call with uri :" << sipAddress << mediaEncryption;
App::postModelAsync([sipAddress, options, mediaEncryption, prepareTransfertAddress, headers]() {
QString errorMessage;

View file

@ -75,7 +75,7 @@ ColumnLayout {
_address: mainItem.conferenceInfo
? mainItem.conferenceInfo.core.subject
: mainItem.contactAddress || mainItem.contactName
secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncrypted
secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
}
Item {
id: rightButton

View file

@ -215,7 +215,7 @@ Flickable{
ColumnLayout{
id: contentsLayout
width: parent.width
spacing: 0
spacing: 20 * DefaultStyle.dp
BusyIndicator {
Layout.alignment: Qt.AlignCenter
Layout.preferredHeight: visible ? 60 * DefaultStyle.dp : 0
@ -228,6 +228,7 @@ Flickable{
ContactListView{
id: favoritesList
visible: contentHeight > 0
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight
interactive: false
@ -259,6 +260,7 @@ Flickable{
ContactListView{
id: contactsList
visible: contentHeight > 0
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight
Layout.topMargin: favoritesList.height > 0 ? 4 * DefaultStyle.dp : 0
@ -296,6 +298,7 @@ Flickable{
}
ContactListView{
id: suggestionsList
visible: contentHeight > 0
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight
Layout.topMargin: contactsList.height + favoritesList.height > 0 ? 4 * DefaultStyle.dp : 0

View file

@ -41,7 +41,7 @@ Loader{
property string computedAvatarUri: avatarObj ? avatarObj.value : ''
// To get the secured property for a specific address,
// override it as secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncrypted
// override it as secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
property var securityLevelObj: UtilsCpp.getFriendAddressSecurityLevel(_address)
property var securityLevel: securityLevelObj ? securityLevelObj.value : LinphoneEnums.SecurityLevel.None
property bool secured: call && call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp

View file

@ -245,10 +245,13 @@ Item {
}
Text {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.leftMargin: 10 * DefaultStyle.dp
anchors.rightMargin: 10 * DefaultStyle.dp
anchors.bottomMargin: 10 * DefaultStyle.dp
width: implicitWidth
maximumLineCount: 1
property string _text: mainItem.displayName != ''
? mainItem.displayName
: mainItem.account && mainItem.identityAddress

View file

@ -8,7 +8,6 @@ import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
ColumnLayout {
id: mainItem
spacing: 10 * DefaultStyle.dp
signal connectionSucceed()
FormItemLayout {
id: username
@ -47,11 +46,6 @@ ColumnLayout {
if (passwordEdit.text.length > 0 || usernameEdit.text.length > 0)
errorText.setText(LoginPageCpp.errorMessage)
}
function onRegistrationStateChanged() {
if (LoginPageCpp.registrationState === LinphoneEnums.RegistrationState.Ok) {
mainItem.connectionSucceed()
}
}
}
}
}

View file

@ -227,7 +227,6 @@ ColumnLayout {
}
}
Connections {
enabled: !mainItem.call
target: SettingsCpp
onMicVolumeChanged: (value) => {
audioTestSlider.value = value

View file

@ -64,14 +64,12 @@ FocusScope {
}
onVisibleChanged: if (!visible) mainItem.numPadPopup.close()
contentItem: ColumnLayout {
// anchors.fill: parent
spacing: 10 * DefaultStyle.dp
spacing: 38 * DefaultStyle.dp
SearchBar {
id: searchBar
Layout.alignment: Qt.AlignTop
Layout.fillWidth: true
Layout.rightMargin: 39 * DefaultStyle.dp
//Layout.maximumWidth: mainItem.width
focus: true
color: mainItem.searchBarColor
borderColor: mainItem.searchBarBorderColor

View file

@ -14,7 +14,6 @@ LoginLayout {
signal useSIPButtonClicked()
signal useRemoteConfigButtonClicked()
signal goToRegister()
signal connectionSucceed()
titleContent: [
BigButton {
@ -82,7 +81,6 @@ LoginLayout {
spacing: 0
LoginForm {
id: loginForm
onConnectionSucceed: mainItem.connectionSucceed()
}
BigButton {
Layout.preferredWidth: loginForm.width

View file

@ -11,7 +11,6 @@ LoginLayout {
id: mainItem
signal goBack()
signal goToRegister()
signal connectionSucceed()
property bool showBackButton: false
titleContent: [
@ -271,11 +270,6 @@ LoginLayout {
function onErrorMessageChanged(error) {
errorText.setText(error)
}
function onRegistrationStateChanged() {
if (LoginPageCpp.registrationState === LinphoneEnums.RegistrationState.Ok) {
mainItem.connectionSucceed()
}
}
}
}

View file

@ -28,6 +28,7 @@ FocusScope{
ListView {
id: participantList
Layout.fillWidth: true
visible: contentHeight > 0
Layout.preferredHeight: contentHeight
Layout.maximumHeight: mainItem.height / 3
width: mainItem.width

View file

@ -81,27 +81,11 @@ AbstractMainPage {
id: leftPanel
Layout.fillWidth: true
Layout.fillHeight: true
Loader {
id: titleLoader
anchors.left: parent.left
anchors.leftMargin: 45 * DefaultStyle.dp
anchors.right: parent.right
asynchronous: false
onActiveFocusChanged:{
if(activeFocus && item){
item.forceActiveFocus()
}
}
}
Control.StackView {
id: listStackView
anchors.top: titleLoader.bottom
anchors.topMargin: 18 * DefaultStyle.dp
anchors.left: parent.left
anchors.fill: parent
anchors.leftMargin: 45 * DefaultStyle.dp
anchors.right: parent.right
anchors.bottom: parent.bottom
clip: true
initialItem: historyListItem
focus: true
@ -128,83 +112,75 @@ AbstractMainPage {
}
}
Component {
id: historyListTitle
FocusScope{
objectName: "historyListTitle"
width: parent.width
height: titleCallLayout.implicitHeight
RowLayout {
id: titleCallLayout
anchors.fill: parent
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)
}
}
}
}
}
Component {
id: historyListItem
FocusScope{
objectName: "historyListItem"
property alias listView: historyListView
Control.StackView.onActivated: titleLoader.sourceComponent = historyListTitle
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
@ -229,224 +205,224 @@ AbstractMainPage {
background: Item{}
contentItem: ColumnLayout {
Text {
visible: historyListView.count === 0
Layout.alignment: Qt.AlignHCenter
text: qsTr("Aucun appel%1").arg(searchBar.text.length != 0 ? " correspondant" : "")
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
ListView {
id: historyListView
clip: true
Layout.fillWidth: true
Layout.fillHeight: true
model: CallHistoryProxy {
id: callHistoryProxy
filterText: searchBar.text
onFilterTextChanged: maxDisplayItems = initialDisplayItems
initialDisplayItems: Math.max(20, 2 * historyListView.height / (56 * DefaultStyle.dp))
displayItemsStep: 3 * initialDisplayItems / 2
}
cacheBuffer: contentHeight>0 ? contentHeight : 0// cache all items
flickDeceleration: 10000
spacing: 10 * DefaultStyle.dp
Keys.onPressed: (event) => {
if(event.key == Qt.Key_Escape){
console.log("Back")
searchBar.forceActiveFocus()
event.accepted = true
}
}
// remove binding loop
onContentHeightChanged: Qt.callLater(function(){
historyListView.cacheBuffer = Math.max(contentHeight,0)
})
onActiveFocusChanged: if(activeFocus && currentIndex < 0 && count > 0) currentIndex = 0
onCountChanged: {
if(currentIndex < 0 && count > 0){
historyListView.currentIndex = 0 // Select first item after loading model
}
if(atYBeginning)
positionViewAtBeginning()// Stay at beginning
}
Connections {
target: deleteHistoryPopup
function onAccepted() {
historyListView.model.removeAllEntries()
}
}
Connections{
target: mainItem
function onListViewUpdated(){
callHistoryProxy.reload()
}
}
onAtYEndChanged: {
if(atYEnd && count > 0){
callHistoryProxy.displayMore()
}
}
//----------------------------------------------------------------
function moveToCurrentItem(){
if( historyListView.currentIndex >= 0)
Utils.updatePosition(historyListView, historyListView)
}
onCurrentItemChanged: {
moveToCurrentItem()
}
// Update position only if we are moving to current item and its position is changing.
property var _currentItemY: currentItem?.y
on_CurrentItemYChanged: if(_currentItemY && moveAnimation.running){
moveToCurrentItem()
}
Behavior on contentY{
NumberAnimation {
id: moveAnimation
duration: 500
easing.type: Easing.OutExpo
alwaysRunToEnd: true
}
}
//----------------------------------------------------------------
onCurrentIndexChanged: {
mainItem.selectedRowHistoryGui = model.getAt(currentIndex)
}
onVisibleChanged: {
if (!visible) currentIndex = -1
}
// Qt bug: sometimes, containsMouse may not be send and update on each MouseArea.
// So we need to use this variable to switch off all hovered items.
property int lastMouseContainsIndex: -1
delegate: FocusScope {
width:historyListView.width
height: 56 * DefaultStyle.dp
visible: !!modelData
RowLayout {
z: 1
anchors.fill: parent
anchors.leftMargin: 10 * DefaultStyle.dp
spacing: 10 * DefaultStyle.dp
Avatar {
id: historyAvatar
property var contactObj: UtilsCpp.findFriendByAddress(modelData.core.remoteAddress)
contact: contactObj?.value || null
_address: modelData.core.conferenceInfo
? modelData.core.conferenceInfo.core.subject
: modelData.core.remoteAddress
width: 45 * DefaultStyle.dp
height: 45 * DefaultStyle.dp
isConference: modelData.core.isConference
}
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
spacing: 5 * DefaultStyle.dp
Text {
id: friendAddress
Layout.fillWidth: true
maximumLineCount: 1
text: historyAvatar.displayNameVal
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
capitalization: Font.Capitalize
}
}
RowLayout {
spacing: 6 * DefaultStyle.dp
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
Layout.preferredWidth: 12 * DefaultStyle.dp
Layout.preferredHeight: 12 * 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
origin {
x: statusIcon.width/2
y: statusIcon.height/2
}
}
}
Text {
// text: modelData.core.date
text: UtilsCpp.formatDate(modelData.core.date)
font {
pixelSize: 12 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
}
}
}
BigButton {
style: ButtonStyle.noBackground
icon.source: AppIcons.phone
focus: true
activeFocusOnTab: false
onClicked: {
if (modelData.core.isConference) {
var callsWindow = UtilsCpp.getCallsWindow()
callsWindow.setupConference(modelData.core.conferenceInfo)
UtilsCpp.smartShowWindow(callsWindow)
}
else {
UtilsCpp.createCall(modelData.core.remoteAddress)
}
}
}
}
MouseArea {
hoverEnabled: true
anchors.fill: parent
focus: true
onContainsMouseChanged: {
if(containsMouse)
historyListView.lastMouseContainsIndex = index
else if( historyListView.lastMouseContainsIndex == index)
historyListView.lastMouseContainsIndex = -1
}
Rectangle {
anchors.fill: parent
opacity: 0.7
radius: 8 * DefaultStyle.dp
color: historyListView.currentIndex === index ? DefaultStyle.main2_200 : DefaultStyle.main2_100
visible: historyListView.lastMouseContainsIndex === index || historyListView.currentIndex === index
}
onPressed: {
historyListView.currentIndex = model.index
historyListView.forceActiveFocus()
}
}
}
Control.ScrollBar.vertical: scrollbar
Text {
visible: historyListView.count === 0
Layout.alignment: Qt.AlignHCenter
text: qsTr("Aucun appel%1").arg(searchBar.text.length != 0 ? " correspondant" : "")
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
ListView {
id: historyListView
clip: true
Layout.fillWidth: true
Layout.fillHeight: true
model: CallHistoryProxy {
id: callHistoryProxy
filterText: searchBar.text
onFilterTextChanged: maxDisplayItems = initialDisplayItems
initialDisplayItems: Math.max(20, 2 * historyListView.height / (56 * DefaultStyle.dp))
displayItemsStep: 3 * initialDisplayItems / 2
}
cacheBuffer: contentHeight>0 ? contentHeight : 0// cache all items
flickDeceleration: 10000
spacing: 10 * DefaultStyle.dp
Keys.onPressed: (event) => {
if(event.key == Qt.Key_Escape){
console.log("Back")
searchBar.forceActiveFocus()
event.accepted = true
}
}
// remove binding loop
onContentHeightChanged: Qt.callLater(function(){
historyListView.cacheBuffer = Math.max(contentHeight,0)
})
onActiveFocusChanged: if(activeFocus && currentIndex < 0 && count > 0) currentIndex = 0
onCountChanged: {
if(currentIndex < 0 && count > 0){
historyListView.currentIndex = 0 // Select first item after loading model
}
if(atYBeginning)
positionViewAtBeginning()// Stay at beginning
}
Connections {
target: deleteHistoryPopup
function onAccepted() {
historyListView.model.removeAllEntries()
}
}
Connections{
target: mainItem
function onListViewUpdated(){
callHistoryProxy.reload()
}
}
onAtYEndChanged: {
if(atYEnd && count > 0){
callHistoryProxy.displayMore()
}
}
//----------------------------------------------------------------
function moveToCurrentItem(){
if( historyListView.currentIndex >= 0)
Utils.updatePosition(historyListView, historyListView)
}
onCurrentItemChanged: {
moveToCurrentItem()
}
// Update position only if we are moving to current item and its position is changing.
property var _currentItemY: currentItem?.y
on_CurrentItemYChanged: if(_currentItemY && moveAnimation.running){
moveToCurrentItem()
}
Behavior on contentY{
NumberAnimation {
id: moveAnimation
duration: 500
easing.type: Easing.OutExpo
alwaysRunToEnd: true
}
}
//----------------------------------------------------------------
onCurrentIndexChanged: {
mainItem.selectedRowHistoryGui = model.getAt(currentIndex)
}
onVisibleChanged: {
if (!visible) currentIndex = -1
}
// Qt bug: sometimes, containsMouse may not be send and update on each MouseArea.
// So we need to use this variable to switch off all hovered items.
property int lastMouseContainsIndex: -1
delegate: FocusScope {
width:historyListView.width
height: 56 * DefaultStyle.dp
visible: !!modelData
RowLayout {
z: 1
anchors.fill: parent
anchors.leftMargin: 10 * DefaultStyle.dp
spacing: 10 * DefaultStyle.dp
Avatar {
id: historyAvatar
property var contactObj: UtilsCpp.findFriendByAddress(modelData.core.remoteAddress)
contact: contactObj?.value || null
_address: modelData.core.conferenceInfo
? modelData.core.conferenceInfo.core.subject
: modelData.core.remoteAddress
secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
width: 45 * DefaultStyle.dp
height: 45 * DefaultStyle.dp
isConference: modelData.core.isConference
}
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
spacing: 5 * DefaultStyle.dp
Text {
id: friendAddress
Layout.fillWidth: true
maximumLineCount: 1
text: historyAvatar.displayNameVal
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
capitalization: Font.Capitalize
}
}
RowLayout {
spacing: 6 * DefaultStyle.dp
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
Layout.preferredWidth: 12 * DefaultStyle.dp
Layout.preferredHeight: 12 * 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
origin {
x: statusIcon.width/2
y: statusIcon.height/2
}
}
}
Text {
// text: modelData.core.date
text: UtilsCpp.formatDate(modelData.core.date)
font {
pixelSize: 12 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
}
}
}
BigButton {
style: ButtonStyle.noBackground
icon.source: AppIcons.phone
focus: true
activeFocusOnTab: false
onClicked: {
if (modelData.core.isConference) {
var callsWindow = UtilsCpp.getCallsWindow()
callsWindow.setupConference(modelData.core.conferenceInfo)
UtilsCpp.smartShowWindow(callsWindow)
}
else {
UtilsCpp.createCall(modelData.core.remoteAddress)
}
}
}
}
MouseArea {
hoverEnabled: true
anchors.fill: parent
focus: true
onContainsMouseChanged: {
if(containsMouse)
historyListView.lastMouseContainsIndex = index
else if( historyListView.lastMouseContainsIndex == index)
historyListView.lastMouseContainsIndex = -1
}
Rectangle {
anchors.fill: parent
opacity: 0.7
radius: 8 * DefaultStyle.dp
color: historyListView.currentIndex === index ? DefaultStyle.main2_200 : DefaultStyle.main2_100
visible: historyListView.lastMouseContainsIndex === index || historyListView.currentIndex === index
}
onPressed: {
historyListView.currentIndex = model.index
historyListView.forceActiveFocus()
}
}
}
Control.ScrollBar.vertical: scrollbar
}
}
}
ScrollBar {
id: scrollbar
@ -462,40 +438,6 @@ AbstractMainPage {
}
}
Component {
id: newCallTitle
FocusScope{
objectName: "newCallTitle"
width: parent.width
height: parent.height
RowLayout {
anchors.fill: parent
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
}
}
}
}
Component {
id: newCallItem
FocusScope{
@ -503,14 +445,39 @@ AbstractMainPage {
width: parent?.width
height: parent?.height
Control.StackView.onActivated:{
titleLoader.sourceComponent = newCallTitle
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
@ -533,84 +500,73 @@ AbstractMainPage {
}
}
Component {
id: groupCallTitle
FocusScope{
objectName: "groupCallTitle"
width: parent.width
height: parent.height
RowLayout {
anchors.fill: parent
spacing: 10 * DefaultStyle.dp
visible: !SettingsCpp.disableMeetingsFeature
Button {
id: backGroupCallButton
style: ButtonStyle.noBackgroundOrange
icon.source: AppIcons.leftArrow
Layout.leftMargin: 21 * DefaultStyle.dp
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
KeyNavigation.down: listStackView
KeyNavigation.right: groupCallButton
KeyNavigation.left: groupCallButton
onClicked: {
listStackView.pop()
titleLoader.item.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()
}
}
}
}
}
Component {
id: groupCallItem
FocusScope{
objectName: "groupCallItem"
Control.StackView.onActivated: {
titleLoader.sourceComponent = groupCallTitle
addParticipantsLayout.forceActiveFocus()
}
ColumnLayout {
spacing: 5 * DefaultStyle.dp
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()
titleLoader.item.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
@ -636,6 +592,7 @@ AbstractMainPage {
id: addParticipantsLayout
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: 15 * DefaultStyle.dp
onSelectedParticipantsCountChanged: mainItem.selectedParticipantsCount = selectedParticipantsCount
focus: true
Connections {

View file

@ -628,11 +628,11 @@ AbstractMainPage {
font.pixelSize: 14 * DefaultStyle.dp
}
Item{Layout.fillWidth: true}
Image{
EffectImage {
visible: listViewModelData.securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
source: AppIcons.trusted
width: 22 * DefaultStyle.dp
height: 22 * DefaultStyle.dp
Layout.preferredWidth: 22 * DefaultStyle.dp
Layout.preferredHeight: 22 * DefaultStyle.dp
}
SmallButton {

View file

@ -454,24 +454,26 @@ AbstractMainPage {
ColumnLayout {
property Control.StackView container
property ConferenceInfoGui conferenceInfoGui
spacing: 18 * DefaultStyle.dp
FocusScope{
Layout.fillWidth: true
Layout.preferredHeight: addParticipantsButtons.implicitHeight
RowLayout {
id: addParticipantsButtons
spacing: 5 * DefaultStyle.dp
Button {
id: removeButton
style: ButtonStyle.noBackgroundOrange
icon.source: AppIcons.leftArrow
icon.width: 24 * DefaultStyle.dp
icon.height: 24 * DefaultStyle.dp
KeyNavigation.right: addButton
KeyNavigation.down: addParticipantLayout
onClicked: container.pop()
}
ColumnLayout {
spacing: 8 * DefaultStyle.dp
Layout.preferredHeight: childrenRect.height
ColumnLayout {
spacing: 4 * DefaultStyle.dp
Layout.fillWidth: true
RowLayout {
id: addParticipantsButtons
spacing: 10 * DefaultStyle.dp
Button {
id: addParticipantsBackButton
style: ButtonStyle.noBackgroundOrange
icon.source: AppIcons.leftArrow
icon.width: 24 * DefaultStyle.dp
icon.height: 24 * DefaultStyle.dp
KeyNavigation.right: addButton
KeyNavigation.down: addParticipantLayout
onClicked: container.pop()
}
Text {
text: qsTr("Ajouter des participants")
color: DefaultStyle.main1_500_main
@ -482,29 +484,30 @@ AbstractMainPage {
}
Layout.fillWidth: true
}
Text {
text: qsTr("%1 participant%2 sélectionné%2").arg(addParticipantLayout.selectedParticipantsCount).arg(addParticipantLayout.selectedParticipantsCount > 1 ? "s" : "")
color: DefaultStyle.main2_500main
maximumLineCount: 1
font {
pixelSize: 12 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
SmallButton {
id: addButton
enabled: addParticipantLayout.selectedParticipantsCount.length != 0
Layout.leftMargin: 11 * DefaultStyle.dp
focus: enabled
style: ButtonStyle.main
text: qsTr("Ajouter")
KeyNavigation.left: addParticipantsBackButton
KeyNavigation.down: addParticipantLayout
onClicked: {
mainItem.addParticipantsValidated(addParticipantLayout.selectedParticipants)
}
Layout.fillWidth: true
}
}
SmallButton {
id: addButton
enabled: addParticipantLayout.selectedParticipantsCount.length != 0
Layout.rightMargin: 21 * DefaultStyle.dp
focus: enabled
style: ButtonStyle.main
text: qsTr("Ajouter")
KeyNavigation.left: removeButton
KeyNavigation.down: addParticipantLayout
onClicked: {
mainItem.addParticipantsValidated(addParticipantLayout.selectedParticipants)
Text {
text: qsTr("%1 participant%2 sélectionné%2").arg(addParticipantLayout.selectedParticipantsCount).arg(addParticipantLayout.selectedParticipantsCount > 1 ? "s" : "")
color: DefaultStyle.main2_500main
Layout.leftMargin: addParticipantsBackButton.width + addParticipantsButtons.spacing
maximumLineCount: 1
font {
pixelSize: 12 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
Layout.fillWidth: true
}
}
}

View file

@ -647,9 +647,12 @@ AbstractWindow {
searchBarBorderColor: DefaultStyle.grey_200
numPadPopup: numericPad
onContactClicked: (contact) => {
rightPanel.visible = false
mainWindow.startCallWithContact(contact, false, rightPanel)
}
Connections {
target: mainWindow
function onCallChanged(){ if (newCallForm.Control.StackView.status === Control.StackView.Active) rightPanel.visible = false}
}
NumericPadPopup {
id: numericPad

View file

@ -29,8 +29,9 @@ AbstractWindow {
// color: DefaultStyle.grey_100
// }
function openMainPage(){
function openMainPage(connectionSucceed){
if (mainWindowStackView.currentItem.objectName !== "mainPage") mainWindowStackView.replace(mainPage, StackView.Immediate)
if (connectionSucceed) mainWindow.showInformationPopup(qsTr("Connexion réussie"), qsTr("Vous êtes connecté en mode %1").arg("interopérable"))
}
function goToCallHistory() {
openMainPage()
@ -46,7 +47,7 @@ AbstractWindow {
}
function transferCallSucceed() {
openMainPage()
UtilsCpp.showInformationPopup(qsTr("Appel transféré"), qsTr("Votre correspondant a été transféré au contact sélectionné"))
mainWindow.showInformationPopup(qsTr("Appel transféré"), qsTr("Votre correspondant a été transféré au contact sélectionné"))
}
function initStackViewItem() {
if(accountProxy && accountProxy.isInitialized) {
@ -96,6 +97,16 @@ AbstractWindow {
}
}
Connections {
target: LoginPageCpp
function onRegistrationStateChanged() {
if (LoginPageCpp.registrationState === LinphoneEnums.RegistrationState.Ok) {
openMainPage(true)
proposeH264CodecsDownload()
}
}
}
Loader {
id: accountProxyLoader
active: AppCpp.coreStarted
@ -144,10 +155,6 @@ AbstractWindow {
onGoBack: openMainPage()
onUseSIPButtonClicked: mainWindowStackView.push(sipLoginPage)
onGoToRegister: mainWindowStackView.replace(registerPage)
onConnectionSucceed: {
openMainPage()
proposeH264CodecsDownload()
}
StackView.onActivated:{
if (accountProxy?.haveAccount) showBackButton = true
}
@ -164,11 +171,6 @@ AbstractWindow {
mainWindowStackView.pop()
}
onGoToRegister: mainWindowStackView.replace(registerPage)
onConnectionSucceed: {
openMainPage()
proposeH264CodecsDownload()
}
StackView.onActivated:{
if (!SettingsCpp.assistantGoDirectlyToThirdPartySipAccountLogin || accountProxy?.haveAccount) showBackButton = true
}