1
0
Fork 0
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:
Ming Rui Zhang 2020-12-03 13:25:34 -05:00
parent ba45e39db7
commit 0de0f6ecb0
15 changed files with 96 additions and 96 deletions

View file

@ -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()
{

View file

@ -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.

View file

@ -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

View file

@ -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);
}
}
};

View file

@ -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
}
}

View file

@ -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()
}
}
}

View file

@ -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()) {

View file

@ -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)
{

View file

@ -63,6 +63,8 @@ public:
explicit PhotoboothPreviewRender(QQuickItem* parent = 0);
virtual ~PhotoboothPreviewRender();
Q_INVOKABLE QString takePhoto(int size);
signals:
void hideBooth();

View file

@ -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()
{

View file

@ -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
*/

View file

@ -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);

View file

@ -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);

View file

@ -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()
}

View file

@ -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