mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Save last camera image as a placeholder.
This commit is contained in:
parent
9ce6636c6a
commit
ccc6c6daa5
5 changed files with 113 additions and 22 deletions
|
@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "media/player/media_player_instance.h"
|
||||
#include "media/streaming/media_streaming_instance.h"
|
||||
#include "media/streaming/media_streaming_round_preview.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "ui/controls/round_video_recorder.h"
|
||||
#include "ui/controls/send_button.h"
|
||||
#include "ui/effects/animation_value.h"
|
||||
|
@ -2362,7 +2363,13 @@ bool VoiceRecordBar::createVideoRecorder() {
|
|||
.hidden = hidden,
|
||||
.capturer = std::move(capturer),
|
||||
.track = std::move(track),
|
||||
.placeholder = _show->session().local().readRoundPlaceholder(),
|
||||
});
|
||||
_videoRecorder->placeholderUpdates(
|
||||
) | rpl::start_with_next([=](QImage &&placeholder) {
|
||||
_show->session().local().writeRoundPlaceholder(placeholder);
|
||||
}, _videoCapturerLifetime);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@ enum { // Local Storage Keys
|
|||
lskCustomEmojiKeys = 0x17, // no data
|
||||
lskSearchSuggestions = 0x18, // no data
|
||||
lskWebviewTokens = 0x19, // data: QByteArray bots, QByteArray other
|
||||
lskRoundPlaceholder = 0x1a, // no data
|
||||
};
|
||||
|
||||
auto EmptyMessageDraftSources()
|
||||
|
@ -220,6 +221,7 @@ base::flat_set<QString> Account::collectGoodNames() const {
|
|||
_featuredCustomEmojiKey,
|
||||
_archivedCustomEmojiKey,
|
||||
_searchSuggestionsKey,
|
||||
_roundPlaceholderKey,
|
||||
};
|
||||
auto result = base::flat_set<QString>{
|
||||
"map0",
|
||||
|
@ -306,6 +308,7 @@ Account::ReadMapResult Account::readMapWith(
|
|||
quint64 legacyBackgroundKeyDay = 0, legacyBackgroundKeyNight = 0;
|
||||
quint64 userSettingsKey = 0, recentHashtagsAndBotsKey = 0, exportSettingsKey = 0;
|
||||
quint64 searchSuggestionsKey = 0;
|
||||
quint64 roundPlaceholderKey = 0;
|
||||
QByteArray webviewStorageTokenBots, webviewStorageTokenOther;
|
||||
while (!map.stream.atEnd()) {
|
||||
quint32 keyType;
|
||||
|
@ -415,6 +418,9 @@ Account::ReadMapResult Account::readMapWith(
|
|||
case lskSearchSuggestions: {
|
||||
map.stream >> searchSuggestionsKey;
|
||||
} break;
|
||||
case lskRoundPlaceholder: {
|
||||
map.stream >> roundPlaceholderKey;
|
||||
} break;
|
||||
case lskWebviewTokens: {
|
||||
map.stream
|
||||
>> webviewStorageTokenBots
|
||||
|
@ -456,6 +462,7 @@ Account::ReadMapResult Account::readMapWith(
|
|||
_recentHashtagsAndBotsKey = recentHashtagsAndBotsKey;
|
||||
_exportSettingsKey = exportSettingsKey;
|
||||
_searchSuggestionsKey = searchSuggestionsKey;
|
||||
_roundPlaceholderKey = roundPlaceholderKey;
|
||||
_oldMapVersion = mapData.version;
|
||||
_webviewStorageIdBots.token = webviewStorageTokenBots;
|
||||
_webviewStorageIdOther.token = webviewStorageTokenOther;
|
||||
|
@ -570,6 +577,7 @@ void Account::writeMap() {
|
|||
+ Serialize::bytearraySize(_webviewStorageIdBots.token)
|
||||
+ Serialize::bytearraySize(_webviewStorageIdOther.token);
|
||||
}
|
||||
if (_roundPlaceholderKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
|
||||
EncryptedDescriptor mapData(mapSize);
|
||||
if (!self.isEmpty()) {
|
||||
|
@ -640,6 +648,10 @@ void Account::writeMap() {
|
|||
<< _webviewStorageIdBots.token
|
||||
<< _webviewStorageIdOther.token;
|
||||
}
|
||||
if (_roundPlaceholderKey) {
|
||||
mapData.stream << quint32(lskRoundPlaceholder);
|
||||
mapData.stream << quint64(_roundPlaceholderKey);
|
||||
}
|
||||
map.writeEncrypted(mapData, _localKey);
|
||||
|
||||
_mapChanged = false;
|
||||
|
@ -669,6 +681,7 @@ void Account::reset() {
|
|||
_legacyBackgroundKeyDay = _legacyBackgroundKeyNight = 0;
|
||||
_settingsKey = _recentHashtagsAndBotsKey = _exportSettingsKey = 0;
|
||||
_searchSuggestionsKey = 0;
|
||||
_roundPlaceholderKey = 0;
|
||||
_oldMapVersion = 0;
|
||||
_fileLocations.clear();
|
||||
_fileLocationPairs.clear();
|
||||
|
@ -3178,6 +3191,52 @@ Webview::StorageId Account::resolveStorageIdOther() {
|
|||
return _webviewStorageIdOther;
|
||||
}
|
||||
|
||||
QImage Account::readRoundPlaceholder() {
|
||||
if (!_roundPlaceholder.isNull()) {
|
||||
return _roundPlaceholder;
|
||||
} else if (!_roundPlaceholderKey) {
|
||||
return QImage();
|
||||
}
|
||||
|
||||
FileReadDescriptor placeholder;
|
||||
if (!ReadEncryptedFile(
|
||||
placeholder,
|
||||
_roundPlaceholderKey,
|
||||
_basePath,
|
||||
_localKey)) {
|
||||
ClearKey(_roundPlaceholderKey, _basePath);
|
||||
_roundPlaceholderKey = 0;
|
||||
writeMapDelayed();
|
||||
return QImage();
|
||||
}
|
||||
|
||||
auto bytes = QByteArray();
|
||||
placeholder.stream >> bytes;
|
||||
_roundPlaceholder = Images::Read({ .content = bytes }).image;
|
||||
return _roundPlaceholder;
|
||||
}
|
||||
|
||||
void Account::writeRoundPlaceholder(const QImage &placeholder) {
|
||||
if (placeholder.isNull()) {
|
||||
return;
|
||||
}
|
||||
_roundPlaceholder = placeholder;
|
||||
|
||||
auto bytes = QByteArray();
|
||||
auto buffer = QBuffer(&bytes);
|
||||
placeholder.save(&buffer, "JPG", 87);
|
||||
|
||||
quint32 size = Serialize::bytearraySize(bytes);
|
||||
if (!_roundPlaceholderKey) {
|
||||
_roundPlaceholderKey = GenerateKey(_basePath);
|
||||
writeMapQueued();
|
||||
}
|
||||
EncryptedDescriptor data(size);
|
||||
data.stream << bytes;
|
||||
FileWriteDescriptor file(_roundPlaceholderKey, _basePath);
|
||||
file.writeEncrypted(data, _localKey);
|
||||
}
|
||||
|
||||
bool Account::encrypt(
|
||||
const void *src,
|
||||
void *dst,
|
||||
|
|
|
@ -174,6 +174,9 @@ public:
|
|||
[[nodiscard]] Webview::StorageId resolveStorageIdBots();
|
||||
[[nodiscard]] Webview::StorageId resolveStorageIdOther();
|
||||
|
||||
[[nodiscard]] QImage readRoundPlaceholder();
|
||||
void writeRoundPlaceholder(const QImage &placeholder);
|
||||
|
||||
[[nodiscard]] bool encrypt(
|
||||
const void *src,
|
||||
void *dst,
|
||||
|
@ -302,6 +305,7 @@ private:
|
|||
FileKey _featuredCustomEmojiKey = 0;
|
||||
FileKey _archivedCustomEmojiKey = 0;
|
||||
FileKey _searchSuggestionsKey = 0;
|
||||
FileKey _roundPlaceholderKey = 0;
|
||||
|
||||
qint64 _cacheTotalSizeLimit = 0;
|
||||
qint64 _cacheBigFileTotalSizeLimit = 0;
|
||||
|
@ -325,6 +329,8 @@ private:
|
|||
bool _mapChanged = false;
|
||||
bool _locationsChanged = false;
|
||||
|
||||
QImage _roundPlaceholder;
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]] Webview::StorageId TonSiteStorageId();
|
||||
|
|
|
@ -1052,6 +1052,10 @@ Fn<void(Media::Capture::Chunk)> RoundVideoRecorder::audioChunkProcessor() {
|
|||
};
|
||||
}
|
||||
|
||||
rpl::producer<QImage> RoundVideoRecorder::placeholderUpdates() const {
|
||||
return _placeholderUpdates.events();
|
||||
}
|
||||
|
||||
int RoundVideoRecorder::previewSize() const {
|
||||
return _side;
|
||||
}
|
||||
|
@ -1096,6 +1100,31 @@ void RoundVideoRecorder::progressTo(float64 progress) {
|
|||
_preview->update();
|
||||
}
|
||||
|
||||
void RoundVideoRecorder::preparePlaceholder(const QImage &placeholder) {
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
const auto full = QSize(_side, _side) * ratio;
|
||||
if (!placeholder.isNull()) {
|
||||
_framePlaceholder = Images::Circle(
|
||||
placeholder.scaled(
|
||||
full,
|
||||
Qt::KeepAspectRatio,
|
||||
Qt::SmoothTransformation));
|
||||
_framePlaceholder.setDevicePixelRatio(ratio);
|
||||
} else {
|
||||
_framePlaceholder = QImage(
|
||||
full,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
_framePlaceholder.fill(Qt::transparent);
|
||||
_framePlaceholder.setDevicePixelRatio(ratio);
|
||||
|
||||
auto p = QPainter(&_framePlaceholder);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(Qt::black);
|
||||
p.drawEllipse(0, 0, _side, _side);
|
||||
}
|
||||
}
|
||||
|
||||
void RoundVideoRecorder::prepareFrame(bool blurred) {
|
||||
if (_frameOriginal.isNull()) {
|
||||
return;
|
||||
|
@ -1124,18 +1153,14 @@ void RoundVideoRecorder::prepareFrame(bool blurred) {
|
|||
const auto ratio = style::DevicePixelRatio();
|
||||
if (blurred) {
|
||||
static constexpr auto kRadius = 16;
|
||||
_framePlaceholder = Images::Circle(
|
||||
Images::BlurLargeImage(
|
||||
copy.scaled(
|
||||
QSize(kBlurredSize, kBlurredSize),
|
||||
Qt::KeepAspectRatio,
|
||||
Qt::FastTransformation),
|
||||
kRadius
|
||||
).scaled(
|
||||
QSize(_side, _side) * ratio,
|
||||
auto image = Images::BlurLargeImage(
|
||||
copy.scaled(
|
||||
QSize(kBlurredSize, kBlurredSize),
|
||||
Qt::KeepAspectRatio,
|
||||
Qt::SmoothTransformation));
|
||||
_framePlaceholder.setDevicePixelRatio(ratio);
|
||||
Qt::FastTransformation),
|
||||
kRadius);
|
||||
preparePlaceholder(image);
|
||||
_placeholderUpdates.fire(std::move(image));
|
||||
} else {
|
||||
_framePrepared = Images::Circle(copy.scaled(
|
||||
QSize(_side, _side) * ratio,
|
||||
|
@ -1147,17 +1172,7 @@ void RoundVideoRecorder::prepareFrame(bool blurred) {
|
|||
|
||||
void RoundVideoRecorder::createImages() {
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
_framePlaceholder = QImage(
|
||||
QSize(_side, _side) * ratio,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
_framePlaceholder.fill(Qt::transparent);
|
||||
_framePlaceholder.setDevicePixelRatio(ratio);
|
||||
auto p = QPainter(&_framePlaceholder);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(Qt::black);
|
||||
p.drawEllipse(0, 0, _side, _side);
|
||||
preparePlaceholder(_descriptor.placeholder);
|
||||
|
||||
const auto side = _side + 2 * _extent;
|
||||
_shadow = QImage(
|
||||
|
|
|
@ -38,6 +38,7 @@ struct RoundVideoRecorderDescriptor {
|
|||
Fn<void(not_null<RoundVideoRecorder*>)> hidden;
|
||||
std::shared_ptr<tgcalls::VideoCaptureInterface> capturer;
|
||||
std::shared_ptr<Webrtc::VideoTrack> track;
|
||||
QImage placeholder;
|
||||
};
|
||||
|
||||
struct RoundVideoResult {
|
||||
|
@ -62,6 +63,7 @@ public:
|
|||
|
||||
[[nodiscard]] int previewSize() const;
|
||||
[[nodiscard]] Fn<void(Media::Capture::Chunk)> audioChunkProcessor();
|
||||
[[nodiscard]] rpl::producer<QImage> placeholderUpdates() const;
|
||||
|
||||
void pause(Fn<void(RoundVideoResult)> done = nullptr);
|
||||
void resume(RoundVideoPartial partial);
|
||||
|
@ -84,6 +86,7 @@ private:
|
|||
|
||||
void setup();
|
||||
void prepareFrame(bool blurred = false);
|
||||
void preparePlaceholder(const QImage &placeholder);
|
||||
void createImages();
|
||||
void progressTo(float64 progress);
|
||||
void fade(bool visible);
|
||||
|
@ -100,6 +103,7 @@ private:
|
|||
Ui::Animations::Simple _progressAnimation;
|
||||
Ui::Animations::Simple _fadeAnimation;
|
||||
Ui::Animations::Simple _fadeContentAnimation;
|
||||
rpl::event_stream<QImage> _placeholderUpdates;
|
||||
|
||||
std::shared_ptr<Ui::DynamicImage> _silentPreview;
|
||||
std::shared_ptr<Ui::DynamicImage> _soundedPreview;
|
||||
|
|
Loading…
Add table
Reference in a new issue