mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-09-10 12:03:18 +02:00
avatar: save the original source of the avatar instead of the cropped
Change-Id: I0e92189f9661ada19ae62025a3114541e41ea587
This commit is contained in:
parent
ba45e39db7
commit
0de0f6ecb0
15 changed files with 96 additions and 96 deletions
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include "qtutils.h"
|
||||
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#undef REGISTERED
|
||||
#include "../daemon/src/dring/account_const.h"
|
||||
|
||||
|
@ -89,13 +91,12 @@ AccountAdapter::connectFailure()
|
|||
void
|
||||
AccountAdapter::createJamiAccount(QString registeredName,
|
||||
const QVariantMap& settings,
|
||||
QString photoBoothImgBase64,
|
||||
bool isCreating)
|
||||
{
|
||||
Utils::oneShotConnect(
|
||||
&LRCInstance::accountModel(),
|
||||
&lrc::api::NewAccountModel::accountAdded,
|
||||
[this, registeredName, settings, isCreating, photoBoothImgBase64](const QString& accountId) {
|
||||
[this, registeredName, settings, isCreating](const QString& accountId) {
|
||||
auto showBackup = isCreating
|
||||
&& !AppSettingsManager::getValue(Settings::Key::NeverShowMeAgain)
|
||||
.toBool();
|
||||
|
@ -124,16 +125,6 @@ AccountAdapter::createJamiAccount(QString registeredName,
|
|||
showBackup,
|
||||
LRCInstance::accountModel().getAccountList().indexOf(accountId));
|
||||
}
|
||||
|
||||
// set up avatar pixmap from photobooth
|
||||
QImage avatarImg;
|
||||
const bool ret = avatarImg.loadFromData(
|
||||
QByteArray::fromBase64(photoBoothImgBase64.toLatin1()));
|
||||
if (!ret) {
|
||||
qDebug() << "No image provided for JAMI account creation";
|
||||
} else {
|
||||
LRCInstance::setAvatarForAccount(QPixmap::fromImage(avatarImg), accountId);
|
||||
}
|
||||
});
|
||||
|
||||
connectFailure();
|
||||
|
@ -156,11 +147,11 @@ AccountAdapter::createJamiAccount(QString registeredName,
|
|||
}
|
||||
|
||||
void
|
||||
AccountAdapter::createSIPAccount(const QVariantMap& settings, QString photoBoothImgBase64)
|
||||
AccountAdapter::createSIPAccount(const QVariantMap& settings)
|
||||
{
|
||||
Utils::oneShotConnect(&LRCInstance::accountModel(),
|
||||
&lrc::api::NewAccountModel::accountAdded,
|
||||
[this, settings, photoBoothImgBase64](const QString& accountId) {
|
||||
[this, settings](const QString& accountId) {
|
||||
auto confProps = LRCInstance::accountModel().getAccountConfig(
|
||||
accountId);
|
||||
// set SIP details
|
||||
|
@ -170,17 +161,6 @@ AccountAdapter::createSIPAccount(const QVariantMap& settings, QString photoBooth
|
|||
confProps.routeset = settings["proxy"].toString();
|
||||
LRCInstance::accountModel().setAccountConfig(accountId, confProps);
|
||||
|
||||
// set up photobooth avatar to SIP avatar
|
||||
QImage avatarImg;
|
||||
const bool ret = avatarImg.loadFromData(
|
||||
QByteArray::fromBase64(photoBoothImgBase64.toLatin1()));
|
||||
if (!ret) {
|
||||
qDebug() << "SIP account creation BASE64 image loading failed";
|
||||
} else {
|
||||
LRCInstance::setAvatarForAccount(QPixmap::fromImage(avatarImg),
|
||||
accountId);
|
||||
}
|
||||
|
||||
emit LRCInstance::instance().accountListChanged();
|
||||
emit accountAdded(accountId,
|
||||
false,
|
||||
|
@ -294,6 +274,22 @@ AccountAdapter::getCurrentAccountType()
|
|||
return LRCInstance::getCurrentAccountInfo().profileInfo.type;
|
||||
}
|
||||
|
||||
void
|
||||
AccountAdapter::setCurrAccAvatar(bool fromFile, const QString& source)
|
||||
{
|
||||
QtConcurrent::run([fromFile, source]() {
|
||||
QPixmap image;
|
||||
bool success;
|
||||
if (fromFile)
|
||||
success = image.load(source);
|
||||
else
|
||||
success = image.loadFromData(Utils::base64StringToByteArray(source));
|
||||
|
||||
if (success)
|
||||
LRCInstance::setCurrAccAvatar(image);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
AccountAdapter::onCurrentAccountChanged()
|
||||
{
|
||||
|
|
|
@ -66,9 +66,8 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE void createJamiAccount(QString registeredName,
|
||||
const QVariantMap& settings,
|
||||
QString photoBoothImgBase64,
|
||||
bool isCreating);
|
||||
Q_INVOKABLE void createSIPAccount(const QVariantMap& settings, QString photoBoothImgBase64);
|
||||
Q_INVOKABLE void createSIPAccount(const QVariantMap& settings);
|
||||
Q_INVOKABLE void createJAMSAccount(const QVariantMap& settings);
|
||||
/*
|
||||
* Delete current account
|
||||
|
@ -102,6 +101,8 @@ public:
|
|||
Q_INVOKABLE void setSelectedConvId(const QString& convId = {});
|
||||
Q_INVOKABLE lrc::api::profile::Type getCurrentAccountType();
|
||||
|
||||
Q_INVOKABLE void setCurrAccAvatar(bool fromFile, const QString& source);
|
||||
|
||||
signals:
|
||||
/*
|
||||
* Trigger other components to reconnect account related signals.
|
||||
|
|
|
@ -99,7 +99,7 @@ AvAdapter::captureScreen(int screenNumber)
|
|||
QBuffer buffer;
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
pixmap.save(&buffer, "PNG");
|
||||
return QString::fromLatin1(buffer.data().toBase64().data());
|
||||
return Utils::byteArrayToBase64String(buffer.data());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
* 2. file_ + file path
|
||||
* 3. contact_+ contact uri
|
||||
* 4. conversation_+ conversation uid
|
||||
* 5. base64_ + base64 string
|
||||
*/
|
||||
QImage requestImage(const QString& id, QSize* size, const QSize& requestedSize) override
|
||||
{
|
||||
|
@ -65,11 +66,13 @@ public:
|
|||
return Utils::fallbackAvatar(QString(), idContent, requestedSize);
|
||||
} else if (idType == "default") {
|
||||
return Utils::fallbackAvatar(QString(), QString(), requestedSize);
|
||||
} else if (idType == "base64") {
|
||||
return Utils::cropImage(QImage::fromData(Utils::base64StringToByteArray(idContent)))
|
||||
.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
} else {
|
||||
auto image = Utils::cropImage(QImage(idContent));
|
||||
return image.scaled(requestedSize,
|
||||
Qt::KeepAspectRatioByExpanding,
|
||||
Qt::SmoothTransformation);
|
||||
QImage image = QImage(idContent);
|
||||
return Utils::getCirclePhoto(image, image.size().width())
|
||||
.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -24,19 +24,19 @@ import net.jami.Constants 1.0
|
|||
Item {
|
||||
id: root
|
||||
|
||||
// FromUrl here is for grabToImage image url
|
||||
enum Mode {
|
||||
FromAccount = 0,
|
||||
FromFile,
|
||||
FromContactUri,
|
||||
FromConvUid,
|
||||
FromUrl,
|
||||
FromBase64,
|
||||
FromTemporaryName,
|
||||
Default
|
||||
}
|
||||
|
||||
property alias fillMode: rootImage.fillMode
|
||||
property alias sourceSize: rootImage.sourceSize
|
||||
property bool saveToConfig: false
|
||||
property int mode: AvatarImage.Mode.FromAccount
|
||||
property string imageProviderIdPrefix: {
|
||||
switch(mode) {
|
||||
|
@ -50,6 +50,8 @@ Item {
|
|||
return "conversation_"
|
||||
case AvatarImage.Mode.FromTemporaryName:
|
||||
return "fallback_"
|
||||
case AvatarImage.Mode.FromBase64:
|
||||
return "base64_"
|
||||
case AvatarImage.Mode.Default:
|
||||
return "default_"
|
||||
default:
|
||||
|
@ -69,6 +71,19 @@ Item {
|
|||
|
||||
signal imageIsReady
|
||||
|
||||
function saveAvatarToConfig() {
|
||||
switch(mode) {
|
||||
case AvatarImage.Mode.FromFile:
|
||||
AccountAdapter.setCurrAccAvatar(true, imageId)
|
||||
break
|
||||
case AvatarImage.Mode.FromBase64:
|
||||
AccountAdapter.setCurrAccAvatar(false, imageId)
|
||||
break
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function updateImage(updatedId, oneTimeForceUpdateUrl) {
|
||||
imageId = updatedId
|
||||
if (oneTimeForceUpdateUrl === undefined)
|
||||
|
@ -76,10 +91,10 @@ Item {
|
|||
else
|
||||
forceUpdateUrl = oneTimeForceUpdateUrl
|
||||
|
||||
if (mode === AvatarImage.Mode.FromUrl)
|
||||
rootImage.source = imageId
|
||||
else
|
||||
rootImage.source = imageProviderUrl + imageId
|
||||
rootImage.source = imageProviderUrl + imageId
|
||||
|
||||
if (saveToConfig)
|
||||
saveAvatarToConfig()
|
||||
}
|
||||
|
||||
Image {
|
||||
|
@ -192,5 +207,4 @@ Item {
|
|||
radius: 30
|
||||
color: JamiTheme.notificationRed
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,9 +12,8 @@ ColumnLayout {
|
|||
property int photoState: PhotoboothView.PhotoState.Default
|
||||
property bool avatarSet: false
|
||||
// saveToConfig is to specify whether the image should be saved to account config
|
||||
property bool saveToConfig: false
|
||||
property alias saveToConfig: avatarImg.saveToConfig
|
||||
property string fileName: ""
|
||||
property var boothImg: ""
|
||||
|
||||
property int boothWidth: 224
|
||||
|
||||
|
@ -50,7 +49,7 @@ ColumnLayout {
|
|||
|
||||
function setAvatarImage(mode = AvatarImage.Mode.FromAccount,
|
||||
imageId = AccountAdapter.currentAccountId){
|
||||
if (mode !== AvatarImage.Mode.FromUrl)
|
||||
if (mode !== AvatarImage.Mode.FromBase64)
|
||||
avatarImg.enableAnimation = true
|
||||
else
|
||||
avatarImg.enableAnimation = false
|
||||
|
@ -58,7 +57,6 @@ ColumnLayout {
|
|||
avatarImg.mode = mode
|
||||
|
||||
if (mode === AvatarImage.Mode.Default) {
|
||||
boothImg = ""
|
||||
avatarImg.updateImage(imageId)
|
||||
return
|
||||
}
|
||||
|
@ -67,6 +65,10 @@ ColumnLayout {
|
|||
avatarImg.updateImage(imageId)
|
||||
}
|
||||
|
||||
function manualSaveToConfig() {
|
||||
avatarImg.saveAvatarToConfig()
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if(!visible){
|
||||
stopBooth()
|
||||
|
@ -141,21 +143,12 @@ ColumnLayout {
|
|||
}
|
||||
|
||||
onImageIsReady: {
|
||||
if (mode === AvatarImage.Mode.FromUrl)
|
||||
if (mode === AvatarImage.Mode.FromBase64)
|
||||
photoState = PhotoboothView.PhotoState.Taken
|
||||
|
||||
if (photoState === PhotoboothView.PhotoState.Taken) {
|
||||
avatarImg.state = ""
|
||||
avatarImg.state = "flashIn"
|
||||
} else {
|
||||
// Once image is loaded (updated), save to boothImg (choose from file)
|
||||
avatarImg.grabToImage(function(result) {
|
||||
if (mode !== AvatarImage.Mode.Default)
|
||||
boothImg = result.image
|
||||
|
||||
if (saveToConfig)
|
||||
SettingsAdapter.setCurrAccAvatar(result.image)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,17 +248,11 @@ ColumnLayout {
|
|||
startBooth()
|
||||
return
|
||||
} else {
|
||||
previewWidget.grabToImage(function(result) {
|
||||
boothImg = result.image
|
||||
setAvatarImage(AvatarImage.Mode.FromBase64,
|
||||
previewWidget.takePhoto(boothWidth))
|
||||
|
||||
if (saveToConfig)
|
||||
SettingsAdapter.setCurrAccAvatar(result.image)
|
||||
|
||||
setAvatarImage(AvatarImage.Mode.FromUrl, result.url)
|
||||
|
||||
avatarSet = true
|
||||
stopBooth()
|
||||
})
|
||||
avatarSet = true
|
||||
stopBooth()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -396,7 +396,7 @@ MessagesAdapter::pasteKeyDetected()
|
|||
QBuffer bu(&ba);
|
||||
bu.open(QIODevice::WriteOnly);
|
||||
pixmap.save(&bu, "PNG");
|
||||
auto str = QString::fromLatin1(ba.toBase64().data());
|
||||
auto str = Utils::byteArrayToBase64String(ba);
|
||||
|
||||
setMessagesImageContent(str, true);
|
||||
} else if (mimeData->hasUrls()) {
|
||||
|
|
|
@ -112,6 +112,16 @@ PhotoboothPreviewRender::PhotoboothPreviewRender(QQuickItem* parent)
|
|||
|
||||
PhotoboothPreviewRender::~PhotoboothPreviewRender() {}
|
||||
|
||||
QString
|
||||
PhotoboothPreviewRender::takePhoto(int size)
|
||||
{
|
||||
if (auto previewImage = LRCInstance::renderer()->getPreviewFrame()) {
|
||||
return Utils::byteArrayToBase64String(Utils::QImageToByteArray(
|
||||
previewImage->copy()
|
||||
.scaled(size, size, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PhotoboothPreviewRender::paint(QPainter* painter)
|
||||
{
|
||||
|
|
|
@ -63,6 +63,8 @@ public:
|
|||
explicit PhotoboothPreviewRender(QQuickItem* parent = 0);
|
||||
virtual ~PhotoboothPreviewRender();
|
||||
|
||||
Q_INVOKABLE QString takePhoto(int size);
|
||||
|
||||
signals:
|
||||
void hideBooth();
|
||||
|
||||
|
|
|
@ -263,26 +263,6 @@ SettingsAdapter::getAccountBestName()
|
|||
return LRCInstance::accountModel().bestNameForAccount(LRCInstance::getCurrAccId());
|
||||
}
|
||||
|
||||
bool
|
||||
SettingsAdapter::getIsDefaultAvatar()
|
||||
{
|
||||
auto& accountInfo = LRCInstance::getCurrentAccountInfo();
|
||||
|
||||
return accountInfo.profileInfo.avatar.isEmpty();
|
||||
}
|
||||
|
||||
void
|
||||
SettingsAdapter::setCurrAccAvatar(QVariant avatarImg)
|
||||
{
|
||||
LRCInstance::setCurrAccAvatar(QPixmap::fromImage(avatarImg.value<QImage>()));
|
||||
}
|
||||
|
||||
void
|
||||
SettingsAdapter::clearCurrentAvatar()
|
||||
{
|
||||
LRCInstance::setCurrAccAvatar(QPixmap());
|
||||
}
|
||||
|
||||
lrc::api::account::ConfProperties_t
|
||||
SettingsAdapter::getAccountConfig()
|
||||
{
|
||||
|
|
|
@ -93,11 +93,6 @@ public:
|
|||
Q_INVOKABLE int getCurrentAccount_Profile_Info_Type();
|
||||
Q_INVOKABLE QString getAccountBestName();
|
||||
|
||||
// getters and setters of avatar image
|
||||
Q_INVOKABLE bool getIsDefaultAvatar();
|
||||
Q_INVOKABLE void setCurrAccAvatar(QVariant avatarImg);
|
||||
Q_INVOKABLE void clearCurrentAvatar();
|
||||
|
||||
/*
|
||||
* getters and setters of ConfProperties_t
|
||||
*/
|
||||
|
|
|
@ -265,7 +265,7 @@ Utils::contactPhoto(const QString& contactUri, const QSize& size)
|
|||
&& contactInfo.profileInfo.uri.isEmpty()) {
|
||||
photo = Utils::fallbackAvatar(QString(), QString());
|
||||
} else if (!contactPhoto.isEmpty()) {
|
||||
QByteArray byteArray = contactPhoto.toLocal8Bit();
|
||||
QByteArray byteArray = Utils::base64StringToByteArray(contactPhoto);
|
||||
photo = contactPhotoFromBase64(byteArray, nullptr);
|
||||
if (photo.isNull()) {
|
||||
auto avatarName = contactInfo.profileInfo.uri == bestName ? QString() : bestName;
|
||||
|
@ -284,7 +284,7 @@ QImage
|
|||
Utils::contactPhotoFromBase64(const QByteArray& data, const QString& type)
|
||||
{
|
||||
QImage avatar;
|
||||
const bool ret = avatar.loadFromData(QByteArray::fromBase64(data), type.toLatin1());
|
||||
const bool ret = avatar.loadFromData(data, type.toLatin1());
|
||||
if (!ret) {
|
||||
qDebug() << "Utils: vCard image loading failed";
|
||||
return QImage();
|
||||
|
@ -587,6 +587,18 @@ Utils::QImageToByteArray(QImage image)
|
|||
return ba;
|
||||
}
|
||||
|
||||
QString
|
||||
Utils::byteArrayToBase64String(QByteArray byteArray)
|
||||
{
|
||||
return QString::fromLatin1(byteArray.toBase64().data());
|
||||
}
|
||||
|
||||
QByteArray
|
||||
Utils::base64StringToByteArray(QString base64)
|
||||
{
|
||||
return QByteArray::fromBase64(base64.toLatin1());
|
||||
}
|
||||
|
||||
QImage
|
||||
Utils::cropImage(const QImage& img)
|
||||
{
|
||||
|
@ -718,7 +730,7 @@ Utils::accountPhoto(const lrc::api::account::Info& accountInfo, const QSize& siz
|
|||
{
|
||||
QImage photo;
|
||||
if (!accountInfo.profileInfo.avatar.isEmpty()) {
|
||||
QByteArray ba = accountInfo.profileInfo.avatar.toLocal8Bit();
|
||||
QByteArray ba = Utils::base64StringToByteArray(accountInfo.profileInfo.avatar);
|
||||
photo = contactPhotoFromBase64(ba, nullptr);
|
||||
} else {
|
||||
auto bestId = LRCInstance::accountModel().bestIdForAccount(accountInfo.id);
|
||||
|
|
|
@ -101,6 +101,8 @@ QImage fallbackAvatar(const std::string& alias,
|
|||
const std::string& uri,
|
||||
const QSize& size = defaultAvatarSize);
|
||||
QByteArray QImageToByteArray(QImage image);
|
||||
QString byteArrayToBase64String(QByteArray byteArray);
|
||||
QByteArray base64StringToByteArray(QString base64);
|
||||
QByteArray QByteArrayFromFile(const QString& filename);
|
||||
QPixmap generateTintedPixmap(const QString& filename, QColor color);
|
||||
QPixmap generateTintedPixmap(const QPixmap& pix, QColor color);
|
||||
|
|
|
@ -238,7 +238,6 @@ Rectangle {
|
|||
AccountAdapter.createJamiAccount(
|
||||
createAccountPage.text_usernameEditAlias,
|
||||
inputParaObject,
|
||||
createAccountPage.boothImgBase64,
|
||||
true)
|
||||
showBackUp = !isRdv
|
||||
showBottom = true
|
||||
|
@ -391,8 +390,7 @@ Rectangle {
|
|||
}
|
||||
|
||||
onSaveProfile: {
|
||||
if (profilePage.profileImg)
|
||||
SettingsAdapter.setCurrAccAvatar(profilePage.profileImg)
|
||||
avatarBooth.manualSaveToConfig()
|
||||
AccountAdapter.setCurrAccDisplayName(profilePage.displayName)
|
||||
leave()
|
||||
}
|
||||
|
|
|
@ -27,11 +27,11 @@ Rectangle {
|
|||
id: root
|
||||
|
||||
property string createdAccountId: ""
|
||||
property alias profileImg: setAvatarWidget.boothImg
|
||||
property int preferredHeight: profilePageColumnLayout.implicitHeight
|
||||
property var showBottom: false
|
||||
property alias displayName: aliasEdit.text
|
||||
property bool isRdv: false
|
||||
property alias avatarBooth: setAvatarWidget
|
||||
|
||||
signal leavePage
|
||||
signal saveProfile
|
||||
|
|
Loading…
Add table
Reference in a new issue