diff --git a/src/commoncomponents/PhotoboothView.qml b/src/commoncomponents/PhotoboothView.qml index 4269a924..6772e988 100644 --- a/src/commoncomponents/PhotoboothView.qml +++ b/src/commoncomponents/PhotoboothView.qml @@ -26,39 +26,34 @@ import net.jami.Models 1.0 import net.jami.Adapters 1.0 import net.jami.Constants 1.0 -ColumnLayout { +Item { id: root - enum Mode { Static, Previewing } - property int mode: PhotoboothView.Mode.Static + property bool isPreviewing: false property alias imageId: avatar.imageId + required property real avatarSize - property int size: 224 - - signal avatarSet + width: avatarSize + height: boothLayout.height function startBooth() { AccountAdapter.startPreviewing(false) - mode = PhotoboothView.Mode.Previewing + isPreviewing = true } function stopBooth(){ if (!AccountAdapter.hasVideoCall()) { AccountAdapter.stopPreviewing() } - mode = PhotoboothView.Mode.Static + isPreviewing = false } onVisibleChanged: { - if (visible) { - mode = PhotoboothView.Mode.Static - } else { + if (!visible) { stopBooth() } } - spacing: 0 - JamiFileDialog { id: importFromFileDialog @@ -74,125 +69,139 @@ ColumnLayout { onAccepted: { var filePath = UtilsAdapter.getAbsPath(file) AccountAdapter.setCurrentAccountAvatarFile(filePath) - avatarSet() } } - Item { - id: imageLayer + ColumnLayout { + id: boothLayout - Layout.preferredWidth: size - Layout.preferredHeight: size - Layout.alignment: Qt.AlignHCenter + spacing: JamiTheme.preferredMarginSize / 2 - Avatar { - id: avatar - - anchors.fill: parent - anchors.margins: 1 - - visible: !preview.visible - - fillMode: Image.PreserveAspectCrop - showPresenceIndicator: false - } - - PhotoboothPreviewRender { - id: preview - - anchors.fill: parent - anchors.margins: 1 - - visible: mode === PhotoboothView.Mode.Previewing - - onRenderingStopped: stopBooth() - lrcInstance: LRCInstance - - layer.enabled: true - layer.effect: OpacityMask { - maskSource: Rectangle { - width: size - height: size - radius: size / 2 - } - } - } - - Rectangle { - id: flashRect - - anchors.fill: parent - anchors.margins: 0 - radius: size / 2 - color: "white" - opacity: 0 - - SequentialAnimation { - id: flashAnimation - - NumberAnimation { - target: flashRect; property: "opacity" - to: 1; duration: 0 - } - NumberAnimation { - target: flashRect; property: "opacity" - to: 0; duration: 500 - } - } - } - } - - RowLayout { - id: buttonsRowLayout - - Layout.fillWidth: true - Layout.preferredHeight: JamiTheme.preferredFieldHeight - Layout.topMargin: JamiTheme.preferredMarginSize / 2 - Layout.alignment: Qt.AlignHCenter - - PushButton { - id: takePhotoButton + Item { + id: imageLayer + Layout.preferredWidth: avatarSize + Layout.preferredHeight: avatarSize Layout.alignment: Qt.AlignHCenter - radius: JamiTheme.primaryRadius - imageColor: JamiTheme.textColor - toolTipText: JamiStrings.takePhoto + Avatar { + id: avatar - source: mode === PhotoboothView.Mode.Static ? - "qrc:/images/icons/baseline-camera_alt-24px.svg" : - "qrc:/images/icons/round-add_a_photo-24px.svg" + anchors.fill: parent + anchors.margins: 1 - onClicked: { - if (mode === PhotoboothView.Mode.Previewing) { - flashAnimation.start() - AccountAdapter.setCurrentAccountAvatarBase64( - preview.takePhoto(size)) - avatarSet() + visible: !preview.visible + + fillMode: Image.PreserveAspectCrop + showPresenceIndicator: false + } + + PhotoboothPreviewRender { + id: preview + + anchors.fill: parent + anchors.margins: 1 + + visible: isPreviewing + + onRenderingStopped: stopBooth() + lrcInstance: LRCInstance + + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Rectangle { + width: avatarSize + height: avatarSize + radius: avatarSize / 2 + } + } + } + + Rectangle { + id: flashRect + + anchors.fill: parent + anchors.margins: 0 + radius: avatarSize / 2 + color: "white" + opacity: 0 + + SequentialAnimation { + id: flashAnimation + + NumberAnimation { + target: flashRect; property: "opacity" + to: 1; duration: 0 + } + NumberAnimation { + target: flashRect; property: "opacity" + to: 0; duration: 500 + } + } + } + } + + RowLayout { + id: buttonsRowLayout + + Layout.fillWidth: true + Layout.preferredHeight: childrenRect.height + Layout.bottomMargin: parent.spacing + Layout.alignment: Qt.AlignHCenter + + PushButton { + id: takePhotoButton + + Layout.alignment: Qt.AlignHCenter + radius: JamiTheme.primaryRadius + imageColor: JamiTheme.textColor + toolTipText: JamiStrings.takePhoto + source: isPreviewing ? + "qrc:/images/icons/round-add_a_photo-24px.svg" : + "qrc:/images/icons/baseline-camera_alt-24px.svg" + + onClicked: { + if (isPreviewing) { + flashAnimation.start() + AccountAdapter.setCurrentAccountAvatarBase64( + preview.takePhoto(avatarSize)) + stopBooth() + return + } + + startBooth() + } + } + + PushButton { + id: clearButton + + visible: LRCInstance.currentAccountAvatarSet + Layout.alignment: Qt.AlignHCenter + radius: JamiTheme.primaryRadius + source: "qrc:/images/icons/round-close-24px.svg" + toolTipText: JamiStrings.clearAvatar + imageColor: JamiTheme.textColor + + onClicked: { stopBooth() - return + AccountAdapter.setCurrentAccountAvatarBase64() } - - startBooth() } - } - PushButton { - id: importButton + PushButton { + id: importButton - Layout.preferredWidth: JamiTheme.preferredFieldHeight - Layout.preferredHeight: JamiTheme.preferredFieldHeight - Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignHCenter + radius: JamiTheme.primaryRadius + source: "qrc:/images/icons/round-folder-24px.svg" + toolTipText: JamiStrings.importFromFile + imageColor: JamiTheme.textColor - radius: JamiTheme.primaryRadius - source: "qrc:/images/icons/round-folder-24px.svg" - - toolTipText: JamiStrings.importFromFile - imageColor: JamiTheme.textColor - - onClicked: { - stopBooth() - importFromFileDialog.open() + onClicked: { + stopBooth() + importFromFileDialog.open() + } } } } diff --git a/src/constant/JamiStrings.qml b/src/constant/JamiStrings.qml index 333c6020..8f905f35 100644 --- a/src/constant/JamiStrings.qml +++ b/src/constant/JamiStrings.qml @@ -400,6 +400,7 @@ Item { // PhotoBoothView property string chooseAvatarImage: qsTr("Choose a picture as avatar") property string importFromFile: qsTr("Import avatar from image file") + property string clearAvatar: qsTr("Clear avatar image") property string takePhoto: qsTr("Take photo") // PluginSettingsPage diff --git a/src/lrcinstance.cpp b/src/lrcinstance.cpp index 028ce40a..9380a237 100644 --- a/src/lrcinstance.cpp +++ b/src/lrcinstance.cpp @@ -44,8 +44,21 @@ LRCInstance::LRCInstance(migrateCallback willMigrateCb, accountModel().setTopAccount(currentAccountId_); Q_EMIT accountListChanged(); + auto profileInfo = getCurrentAccountInfo().profileInfo; + // update type - set_currentAccountType(getCurrentAccountInfo().profileInfo.type); + set_currentAccountType(profileInfo.type); + + // notify if the avatar is stored locally + set_currentAccountAvatarSet(!profileInfo.avatar.isEmpty()); + }); + + connect(&accountModel(), &NewAccountModel::profileUpdated, [this](const QString& id) { + if (id != currentAccountId_) + return; + + auto profileInfo = getCurrentAccountInfo().profileInfo; + set_currentAccountAvatarSet(!getCurrentAccountInfo().profileInfo.avatar.isEmpty()); }); // set the current account if any diff --git a/src/lrcinstance.h b/src/lrcinstance.h index b4e1b2f7..2182600c 100644 --- a/src/lrcinstance.h +++ b/src/lrcinstance.h @@ -57,6 +57,7 @@ class LRCInstance : public QObject QML_PROPERTY(QString, selectedConvUid) QML_PROPERTY(QString, currentAccountId) QML_RO_PROPERTY(lrc::api::profile::Type, currentAccountType) + QML_PROPERTY(bool, currentAccountAvatarSet) public: explicit LRCInstance(migrateCallback willMigrateCb = {}, diff --git a/src/settingsview/components/AccountProfile.qml b/src/settingsview/components/AccountProfile.qml index 22990427..8f3d0a15 100644 --- a/src/settingsview/components/AccountProfile.qml +++ b/src/settingsview/components/AccountProfile.qml @@ -66,12 +66,10 @@ ColumnLayout { PhotoboothView { id: currentAccountAvatar - Layout.fillWidth: true Layout.alignment: Qt.AlignCenter imageId: LRCInstance.currentAccountId - - size: 180 + avatarSize: 180 } MaterialLineEdit { diff --git a/src/wizardview/components/ProfilePage.qml b/src/wizardview/components/ProfilePage.qml index 13dd1b48..a92c16f8 100644 --- a/src/wizardview/components/ProfilePage.qml +++ b/src/wizardview/components/ProfilePage.qml @@ -32,11 +32,10 @@ Rectangle { // trigger a default avatar prior to account generation property string createdAccountId: "dummy" property int preferredHeight: profilePageColumnLayout.implicitHeight - property var showBottom: false + property bool showBottom: false property alias displayName: aliasEdit.text property bool isRdv: false property alias avatarBooth: setAvatarWidget - property bool avatarSet signal leavePage signal saveProfile @@ -45,7 +44,6 @@ Rectangle { createdAccountId = "dummy" clearAllTextFields() saveProfileBtn.spinnerTriggered = true - avatarSet = false } function clearAllTextFields() { @@ -99,13 +97,14 @@ Rectangle { id: setAvatarWidget Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: size - Layout.fillHeight: true imageId: createdAccountId - onAvatarSet: root.avatarSet = true + avatarSize: 200 - size: 200 + onVisibleChanged: { + if (visible) + LRCInstance.currentAccountAvatarSet = false + } } MaterialLineEdit { @@ -127,7 +126,7 @@ Rectangle { fieldLayoutWidth: saveProfileBtn.width onTextEdited: { - if (root.avatarSet) + if (LRCInstance.currentAccountAvatarSet) return if (text.length === 0) { lastFirstChar = ""