linphone-desktop/Linphone/view/Control/Display/Sticker.qml
Alexandre Jörgensen c73eea248f Format QML files
2026-03-10 12:32:35 +01:00

288 lines
11 KiB
QML

import QtQuick
import QtQuick.Effects
import QtQuick.Layouts
import QtQuick.Controls.Basic as Control
import Linphone
import UtilsCpp
import SettingsCpp
import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
// Display a sticker from a call or from an account.
// The Avatar is shown while the camera become available.
// The loader restart in case of resetting the renderer. This allow to display the avatar while loading.
// TODO: sizes, colors, decorations
Item {
id: mainItem
height: 300
width: 200
property bool previewEnabled
property bool securityBreach
property CallGui call: null
property ConferenceGui conference: call && call.core.conference || null
property var callState: call && call.core.state || undefined
property AccountGui account: null
property ParticipantDeviceGui participantDevice: null
property bool displayBorder: participantDevice && participantDevice.core.isSpeaking || false
property alias displayPresence: avatar.displayPresence
property color color: DefaultStyle.grey_600
property real radius: Utils.getSizeWithScreenRatio(15)
property bool remoteIsPaused: participantDevice ? participantDevice.core.isPaused : previewEnabled ? callState
=== LinphoneEnums.CallState.Paused : callState === LinphoneEnums.CallState.PausedByRemote
property string remoteAddress: account ? account.core.identityAddress : participantDevice
? participantDevice.core.address : call ? call.core.remoteAddress : ""
property var localNameObj: previewEnabled && call ? UtilsCpp.getDisplayName(call.core.localAddress) : null
property string localName: localNameObj ? localNameObj.value : ""
property string displayName: account ? account.core.displayName : participantDevice
? participantDevice.core.displayName : call ? previewEnabled ? localName : call.core.remoteName : ""
property var contactObj: call ? UtilsCpp.findFriendByAddress(call.core.remoteAddress) : null
property var contact: contactObj && contactObj.value || null
property var identityAddress: account ? UtilsCpp.getDisplayName(account.core.identityAddress) : null
property bool videoEnabled: (previewEnabled && call && call.core.cameraEnabled) || (!previewEnabled && call
&& call.core.remoteVideoEnabled) || (participantDevice && participantDevice.core.videoEnabled)
property string qmlName
property bool displayAll: !!mainItem.call
property bool mutedStatus: participantDevice ? participantDevice.core.isMuted : account && call ? call.core.conference
&& call.core.microphoneMuted : false
clip: false
Rectangle {
id: background
color: noCameraLayout.visible ? mainItem.color : 'transparent'
radius: mainItem.radius
anchors.fill: parent
border.color: DefaultStyle.main2_200
border.width: mainItem.displayBorder ? Utils.getSizeWithScreenRatio(3) : 0
property real minSize: Math.min(height, width)
Item {
id: noCameraLayout
anchors.fill: parent
visible: !cameraLoader.active || cameraLoader.status != Loader.Ready || !cameraLoader.item.isReady
ColumnLayout {
anchors.top: parent.top
anchors.topMargin: Utils.getSizeWithScreenRatio(81)
anchors.horizontalCenter: parent.horizontalCenter
// Layout.alignment: Qt.AlignHCenter |Qt.AlignTop
spacing: 0
visible: !mainItem.account && (mainItem.callState === LinphoneEnums.CallState.OutgoingInit || mainItem.callState
=== LinphoneEnums.CallState.OutgoingProgress || mainItem.callState
=== LinphoneEnums.CallState.OutgoingRinging || mainItem.callState
=== LinphoneEnums.CallState.OutgoingEarlyMedia || mainItem.callState
=== LinphoneEnums.CallState.IncomingReceived)
BusyIndicator {
indicatorColor: DefaultStyle.main2_100
Layout.alignment: Qt.AlignHCenter
indicatorHeight: Utils.getSizeWithScreenRatio(42)
indicatorWidth: Utils.getSizeWithScreenRatio(42)
}
}
Item {
id: centerItem
visible: !mainItem.remoteIsPaused
anchors.centerIn: parent
height: mainItem.conference ? background.minSize * 142 / 372 : Utils.getSizeWithScreenRatio(120)
width: height
Avatar {
id: avatar
anchors.fill: parent
visible: !joiningView.visible
account: mainItem.account
call: !mainItem.previewEnabled ? mainItem.call : null
displayNameVal: mainItem.displayName
securityBreach: mainItem.securityBreach ? mainItem.securityBreach : securityLevel
=== LinphoneEnums.SecurityLevel.Unsafe
secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
}
ColumnLayout {
id: joiningView
anchors.centerIn: parent
spacing: 0
visible: mainItem.participantDevice && (mainItem.participantDevice.core.state
== LinphoneEnums.ParticipantDeviceState.Joining || mainItem.participantDevice.core.state
== LinphoneEnums.ParticipantDeviceState.Alerting) || false
BusyIndicator {
Layout.preferredHeight: Utils.getSizeWithScreenRatio(42)
indicatorColor: DefaultStyle.main2_100
Layout.alignment: Qt.AlignHCenter
indicatorHeight: Utils.getSizeWithScreenRatio(42)
indicatorWidth: Utils.getSizeWithScreenRatio(42)
}
Text {
Layout.preferredHeight: Utils.getSizeWithScreenRatio(27)
Layout.topMargin: Utils.getSizeWithScreenRatio(15) // (84-27)-42
//: "rejoint…"
text: qsTr("conference_participant_joining_text")
color: DefaultStyle.grey_0
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
font {
pixelSize: Utils.getSizeWithScreenRatio(20)
weight: Utils.getSizeWithScreenRatio(500)
}
}
}
}
ColumnLayout {
anchors.centerIn: parent
spacing: Utils.getSizeWithScreenRatio(12)
visible: mainItem.remoteIsPaused
EffectImage {
imageSource: AppIcons.pause
colorizationColor: DefaultStyle.grey_0
Layout.preferredHeight: background.width / 8
Layout.preferredWidth: height
Layout.alignment: Qt.AlignHCenter
}
Text {
color: DefaultStyle.grey_0
Layout.alignment: Qt.AlignHCenter
//: "En pause"
text: qsTr("conference_participant_paused_text")
font {
pixelSize: Utils.getSizeWithScreenRatio(20)
weight: Utils.getSizeWithScreenRatio(500)
}
}
}
ColumnLayout {
spacing: 0
visible: mainItem.displayAll && !mainItem.remoteIsPaused && !mainItem.conference
anchors.top: centerItem.bottom
anchors.topMargin: Utils.getSizeWithScreenRatio(21)
anchors.left: parent.left
anchors.right: parent.right
Text {
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: mainItem.displayName
color: DefaultStyle.grey_0
font {
pixelSize: Utils.getSizeWithScreenRatio(22)
weight: Utils.getSizeWithScreenRatio(300)
capitalization: Font.Capitalize
}
}
Text {
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
property string _text: mainItem.call && mainItem.call.core.remoteAddress
text: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(_text) : _text
color: DefaultStyle.grey_0
font {
pixelSize: Utils.getSizeWithScreenRatio(14)
weight: Utils.getSizeWithScreenRatio(300)
}
}
}
}
Loader {
id: cameraLoader
anchors.fill: parent
property bool reset: false
Timer {
id: resetTimer
interval: 1
triggeredOnStart: true
onTriggered: {
cameraLoader.reset = !cameraLoader.reset;
}
}
active: mainItem.visible && !mainItem.remoteIsPaused && mainItem.videoEnabled && mainItem.callState
!== LinphoneEnums.CallState.End && mainItem.callState !== LinphoneEnums.CallState.Released && !cameraLoader.reset
onActiveChanged: console.log("(" + mainItem.qmlName + ") Camera active " + active + ", visible=" + mainItem.visible
+ ", videoEnabled=" + mainItem.videoEnabled + ", reset=" + cameraLoader.reset)
sourceComponent: cameraComponent
}
Component {
id: cameraComponent
Item {
height: cameraLoader.height
width: cameraLoader.width
property alias isReady: cameraItem.isReady
CameraGui {
id: cameraItem
anchors.fill: parent
visible: false
qmlName: mainItem.qmlName
isPreview: mainItem.previewEnabled
call: mainItem.call
participantDevice: mainItem.participantDevice
onRequestNewRenderer: {
console.log("Request new renderer for " + mainItem.qmlName);
resetTimer.restart();
}
layer.enabled: true
}
ShaderEffect {
id: roundEffect
property variant src: cameraItem
property real edge: 0.9
property real edgeSoftness: 0.9
property real radius: mainItem.radius
property real shadowSoftness: 0.5
property real shadowOffset: 0.01
anchors.fill: parent
visible: cameraItem.isReady
fragmentShader: 'qrc:/data/shaders/roundEffect.frag.qsb'
}
}
}
Text {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.leftMargin: Utils.getSizeWithScreenRatio(10)
anchors.rightMargin: Utils.getSizeWithScreenRatio(10)
anchors.bottomMargin: Utils.getSizeWithScreenRatio(10)
width: implicitWidth
maximumLineCount: 1
property string _text: mainItem.displayName != '' ? mainItem.displayName : mainItem.account
&& mainItem.identityAddress ? mainItem.identityAddress.value : ""
text: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(_text) : _text
color: DefaultStyle.grey_0
font {
pixelSize: Utils.getSizeWithScreenRatio(14)
weight: Utils.getSizeWithScreenRatio(500)
}
}
}
MultiEffect {
id: shadow
source: background
anchors.fill: background
shadowEnabled: true
shadowColor: DefaultStyle.grey_1000
shadowBlur: 1
shadowScale: 1.05
shadowOpacity: 0.5
}
RowLayout {
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: Utils.getSizeWithScreenRatio(8)
anchors.topMargin: Utils.getSizeWithScreenRatio(8)
height: Utils.getSizeWithScreenRatio(18)
spacing: 0
Rectangle {
id: muteIcon
Layout.preferredWidth: Math.min(Math.round(mainItem.width / 16), Utils.getSizeWithScreenRatio(20))
Layout.preferredHeight: Math.min(Math.round(mainItem.width / 16), Utils.getSizeWithScreenRatio(20))
visible: mainItem.mutedStatus
color: DefaultStyle.grey_0
radius: width / 2
EffectImage {
anchors.centerIn: parent
imageWidth: Math.min(Math.round(mainItem.width / 16), Utils.getSizeWithScreenRatio(20))
imageHeight: Math.min(Math.round(mainItem.width / 16), Utils.getSizeWithScreenRatio(20))
imageSource: AppIcons.microphoneSlash
colorizationColor: DefaultStyle.main2_500_main
}
}
}
}