mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-07-08 09:35:24 +02:00
avatars: add clear feature to photobooth
A property is provided to notify of changes to the content of the current account's stored avatar. If one is stored, then a button used to clear the avatar becomes available. Gitlab: #473 Change-Id: I37640acaea3ca43e5abd14678d68b4eeebb3829e
This commit is contained in:
parent
275530746a
commit
ab4c68adb5
6 changed files with 149 additions and 128 deletions
|
@ -26,39 +26,34 @@ import net.jami.Models 1.0
|
||||||
import net.jami.Adapters 1.0
|
import net.jami.Adapters 1.0
|
||||||
import net.jami.Constants 1.0
|
import net.jami.Constants 1.0
|
||||||
|
|
||||||
ColumnLayout {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
enum Mode { Static, Previewing }
|
property bool isPreviewing: false
|
||||||
property int mode: PhotoboothView.Mode.Static
|
|
||||||
property alias imageId: avatar.imageId
|
property alias imageId: avatar.imageId
|
||||||
|
required property real avatarSize
|
||||||
|
|
||||||
property int size: 224
|
width: avatarSize
|
||||||
|
height: boothLayout.height
|
||||||
signal avatarSet
|
|
||||||
|
|
||||||
function startBooth() {
|
function startBooth() {
|
||||||
AccountAdapter.startPreviewing(false)
|
AccountAdapter.startPreviewing(false)
|
||||||
mode = PhotoboothView.Mode.Previewing
|
isPreviewing = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopBooth(){
|
function stopBooth(){
|
||||||
if (!AccountAdapter.hasVideoCall()) {
|
if (!AccountAdapter.hasVideoCall()) {
|
||||||
AccountAdapter.stopPreviewing()
|
AccountAdapter.stopPreviewing()
|
||||||
}
|
}
|
||||||
mode = PhotoboothView.Mode.Static
|
isPreviewing = false
|
||||||
}
|
}
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (!visible) {
|
||||||
mode = PhotoboothView.Mode.Static
|
|
||||||
} else {
|
|
||||||
stopBooth()
|
stopBooth()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
JamiFileDialog {
|
JamiFileDialog {
|
||||||
id: importFromFileDialog
|
id: importFromFileDialog
|
||||||
|
|
||||||
|
@ -74,125 +69,139 @@ ColumnLayout {
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
var filePath = UtilsAdapter.getAbsPath(file)
|
var filePath = UtilsAdapter.getAbsPath(file)
|
||||||
AccountAdapter.setCurrentAccountAvatarFile(filePath)
|
AccountAdapter.setCurrentAccountAvatarFile(filePath)
|
||||||
avatarSet()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
ColumnLayout {
|
||||||
id: imageLayer
|
id: boothLayout
|
||||||
|
|
||||||
Layout.preferredWidth: size
|
spacing: JamiTheme.preferredMarginSize / 2
|
||||||
Layout.preferredHeight: size
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
|
|
||||||
Avatar {
|
Item {
|
||||||
id: avatar
|
id: imageLayer
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
Layout.preferredWidth: avatarSize
|
||||||
|
Layout.preferredHeight: avatarSize
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
radius: JamiTheme.primaryRadius
|
|
||||||
|
|
||||||
imageColor: JamiTheme.textColor
|
Avatar {
|
||||||
toolTipText: JamiStrings.takePhoto
|
id: avatar
|
||||||
|
|
||||||
source: mode === PhotoboothView.Mode.Static ?
|
anchors.fill: parent
|
||||||
"qrc:/images/icons/baseline-camera_alt-24px.svg" :
|
anchors.margins: 1
|
||||||
"qrc:/images/icons/round-add_a_photo-24px.svg"
|
|
||||||
|
|
||||||
onClicked: {
|
visible: !preview.visible
|
||||||
if (mode === PhotoboothView.Mode.Previewing) {
|
|
||||||
flashAnimation.start()
|
fillMode: Image.PreserveAspectCrop
|
||||||
AccountAdapter.setCurrentAccountAvatarBase64(
|
showPresenceIndicator: false
|
||||||
preview.takePhoto(size))
|
}
|
||||||
avatarSet()
|
|
||||||
|
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()
|
stopBooth()
|
||||||
return
|
AccountAdapter.setCurrentAccountAvatarBase64()
|
||||||
}
|
}
|
||||||
|
|
||||||
startBooth()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PushButton {
|
PushButton {
|
||||||
id: importButton
|
id: importButton
|
||||||
|
|
||||||
Layout.preferredWidth: JamiTheme.preferredFieldHeight
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.preferredHeight: JamiTheme.preferredFieldHeight
|
radius: JamiTheme.primaryRadius
|
||||||
Layout.alignment: Qt.AlignHCenter
|
source: "qrc:/images/icons/round-folder-24px.svg"
|
||||||
|
toolTipText: JamiStrings.importFromFile
|
||||||
|
imageColor: JamiTheme.textColor
|
||||||
|
|
||||||
radius: JamiTheme.primaryRadius
|
onClicked: {
|
||||||
source: "qrc:/images/icons/round-folder-24px.svg"
|
stopBooth()
|
||||||
|
importFromFileDialog.open()
|
||||||
toolTipText: JamiStrings.importFromFile
|
}
|
||||||
imageColor: JamiTheme.textColor
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
stopBooth()
|
|
||||||
importFromFileDialog.open()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -400,6 +400,7 @@ Item {
|
||||||
// PhotoBoothView
|
// PhotoBoothView
|
||||||
property string chooseAvatarImage: qsTr("Choose a picture as avatar")
|
property string chooseAvatarImage: qsTr("Choose a picture as avatar")
|
||||||
property string importFromFile: qsTr("Import avatar from image file")
|
property string importFromFile: qsTr("Import avatar from image file")
|
||||||
|
property string clearAvatar: qsTr("Clear avatar image")
|
||||||
property string takePhoto: qsTr("Take photo")
|
property string takePhoto: qsTr("Take photo")
|
||||||
|
|
||||||
// PluginSettingsPage
|
// PluginSettingsPage
|
||||||
|
|
|
@ -44,8 +44,21 @@ LRCInstance::LRCInstance(migrateCallback willMigrateCb,
|
||||||
accountModel().setTopAccount(currentAccountId_);
|
accountModel().setTopAccount(currentAccountId_);
|
||||||
Q_EMIT accountListChanged();
|
Q_EMIT accountListChanged();
|
||||||
|
|
||||||
|
auto profileInfo = getCurrentAccountInfo().profileInfo;
|
||||||
|
|
||||||
// update type
|
// 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
|
// set the current account if any
|
||||||
|
|
|
@ -57,6 +57,7 @@ class LRCInstance : public QObject
|
||||||
QML_PROPERTY(QString, selectedConvUid)
|
QML_PROPERTY(QString, selectedConvUid)
|
||||||
QML_PROPERTY(QString, currentAccountId)
|
QML_PROPERTY(QString, currentAccountId)
|
||||||
QML_RO_PROPERTY(lrc::api::profile::Type, currentAccountType)
|
QML_RO_PROPERTY(lrc::api::profile::Type, currentAccountType)
|
||||||
|
QML_PROPERTY(bool, currentAccountAvatarSet)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LRCInstance(migrateCallback willMigrateCb = {},
|
explicit LRCInstance(migrateCallback willMigrateCb = {},
|
||||||
|
|
|
@ -66,12 +66,10 @@ ColumnLayout {
|
||||||
PhotoboothView {
|
PhotoboothView {
|
||||||
id: currentAccountAvatar
|
id: currentAccountAvatar
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.alignment: Qt.AlignCenter
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
|
||||||
imageId: LRCInstance.currentAccountId
|
imageId: LRCInstance.currentAccountId
|
||||||
|
avatarSize: 180
|
||||||
size: 180
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialLineEdit {
|
MaterialLineEdit {
|
||||||
|
|
|
@ -32,11 +32,10 @@ Rectangle {
|
||||||
// trigger a default avatar prior to account generation
|
// trigger a default avatar prior to account generation
|
||||||
property string createdAccountId: "dummy"
|
property string createdAccountId: "dummy"
|
||||||
property int preferredHeight: profilePageColumnLayout.implicitHeight
|
property int preferredHeight: profilePageColumnLayout.implicitHeight
|
||||||
property var showBottom: false
|
property bool showBottom: false
|
||||||
property alias displayName: aliasEdit.text
|
property alias displayName: aliasEdit.text
|
||||||
property bool isRdv: false
|
property bool isRdv: false
|
||||||
property alias avatarBooth: setAvatarWidget
|
property alias avatarBooth: setAvatarWidget
|
||||||
property bool avatarSet
|
|
||||||
|
|
||||||
signal leavePage
|
signal leavePage
|
||||||
signal saveProfile
|
signal saveProfile
|
||||||
|
@ -45,7 +44,6 @@ Rectangle {
|
||||||
createdAccountId = "dummy"
|
createdAccountId = "dummy"
|
||||||
clearAllTextFields()
|
clearAllTextFields()
|
||||||
saveProfileBtn.spinnerTriggered = true
|
saveProfileBtn.spinnerTriggered = true
|
||||||
avatarSet = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearAllTextFields() {
|
function clearAllTextFields() {
|
||||||
|
@ -99,13 +97,14 @@ Rectangle {
|
||||||
id: setAvatarWidget
|
id: setAvatarWidget
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignCenter
|
Layout.alignment: Qt.AlignCenter
|
||||||
Layout.preferredWidth: size
|
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
imageId: createdAccountId
|
imageId: createdAccountId
|
||||||
onAvatarSet: root.avatarSet = true
|
avatarSize: 200
|
||||||
|
|
||||||
size: 200
|
onVisibleChanged: {
|
||||||
|
if (visible)
|
||||||
|
LRCInstance.currentAccountAvatarSet = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialLineEdit {
|
MaterialLineEdit {
|
||||||
|
@ -127,7 +126,7 @@ Rectangle {
|
||||||
fieldLayoutWidth: saveProfileBtn.width
|
fieldLayoutWidth: saveProfileBtn.width
|
||||||
|
|
||||||
onTextEdited: {
|
onTextEdited: {
|
||||||
if (root.avatarSet)
|
if (LRCInstance.currentAccountAvatarSet)
|
||||||
return
|
return
|
||||||
if (text.length === 0) {
|
if (text.length === 0) {
|
||||||
lastFirstChar = ""
|
lastFirstChar = ""
|
||||||
|
|
Loading…
Add table
Reference in a new issue