mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Add 'Loop animated stickers' setting.
This commit is contained in:
parent
abf49e1672
commit
708b1d7ad4
31 changed files with 285 additions and 105 deletions
|
@ -395,6 +395,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_settings_performance" = "Performance";
|
"lng_settings_performance" = "Performance";
|
||||||
"lng_settings_enable_animations" = "Enable animations";
|
"lng_settings_enable_animations" = "Enable animations";
|
||||||
"lng_settings_autoplay_gifs" = "Autoplay GIFs";
|
"lng_settings_autoplay_gifs" = "Autoplay GIFs";
|
||||||
|
"lng_settings_loop_stickers" = "Loop animated stickers";
|
||||||
|
|
||||||
"lng_backgrounds_header" = "Choose your new chat background";
|
"lng_backgrounds_header" = "Choose your new chat background";
|
||||||
"lng_theme_sure_keep" = "Keep this theme?";
|
"lng_theme_sure_keep" = "Keep this theme?";
|
||||||
|
|
|
@ -548,6 +548,17 @@ bool InnerWidget::elementIntersectsRange(
|
||||||
return (top < till && bottom > from);
|
return (top < till && bottom > from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InnerWidget::elementStartStickerLoop(not_null<const Element*> view) {
|
||||||
|
if (_controller->session().settings().loopAnimatedStickers()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return !_animatedStickersPlayed.contains(view->data()->fullId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void InnerWidget::elementStickerLoopStarted(not_null<const Element*> view) {
|
||||||
|
_animatedStickersPlayed.emplace(view->data()->fullId());
|
||||||
|
}
|
||||||
|
|
||||||
void InnerWidget::saveState(not_null<SectionMemento*> memento) {
|
void InnerWidget::saveState(not_null<SectionMemento*> memento) {
|
||||||
memento->setFilter(std::move(_filter));
|
memento->setFilter(std::move(_filter));
|
||||||
memento->setAdmins(std::move(_admins));
|
memento->setAdmins(std::move(_admins));
|
||||||
|
@ -1024,15 +1035,15 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
cancelContextDownload(document);
|
cancelContextDownload(document);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (document->loaded() && document->isGifv()) {
|
if (document->loaded()
|
||||||
if (!cAutoPlayGif()) {
|
&& document->isGifv()
|
||||||
const auto itemId = view
|
&& !document->session().settings().autoplayGifs()) {
|
||||||
? view->data()->fullId()
|
const auto itemId = view
|
||||||
: FullMsgId();
|
? view->data()->fullId()
|
||||||
_menu->addAction(tr::lng_context_open_gif(tr::now), [=] {
|
: FullMsgId();
|
||||||
openContextGif(itemId);
|
_menu->addAction(tr::lng_context_open_gif(tr::now), [=] {
|
||||||
});
|
openContextGif(itemId);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
if (!document->filepath(DocumentData::FilePathResolve::Checked).isEmpty()) {
|
if (!document->filepath(DocumentData::FilePathResolve::Checked).isEmpty()) {
|
||||||
_menu->addAction(Platform::IsMac() ? tr::lng_context_show_in_finder(tr::now) : tr::lng_context_show_in_folder(tr::now), [=] {
|
_menu->addAction(Platform::IsMac() ? tr::lng_context_show_in_finder(tr::now) : tr::lng_context_show_in_folder(tr::now), [=] {
|
||||||
|
|
|
@ -99,6 +99,10 @@ public:
|
||||||
not_null<const HistoryView::Element*> view,
|
not_null<const HistoryView::Element*> view,
|
||||||
int from,
|
int from,
|
||||||
int till) override;
|
int till) override;
|
||||||
|
bool elementStartStickerLoop(
|
||||||
|
not_null<const HistoryView::Element*> view) override;
|
||||||
|
void elementStickerLoopStarted(
|
||||||
|
not_null<const HistoryView::Element*> view) override;
|
||||||
|
|
||||||
~InnerWidget();
|
~InnerWidget();
|
||||||
|
|
||||||
|
@ -219,6 +223,7 @@ private:
|
||||||
std::vector<OwnedItem> _items;
|
std::vector<OwnedItem> _items;
|
||||||
std::set<uint64> _eventIds;
|
std::set<uint64> _eventIds;
|
||||||
std::map<not_null<const HistoryItem*>, not_null<Element*>> _itemsByData;
|
std::map<not_null<const HistoryItem*>, not_null<Element*>> _itemsByData;
|
||||||
|
base::flat_set<FullMsgId> _animatedStickersPlayed;
|
||||||
int _itemsTop = 0;
|
int _itemsTop = 0;
|
||||||
int _itemsWidth = 0;
|
int _itemsWidth = 0;
|
||||||
int _itemsHeight = 0;
|
int _itemsHeight = 0;
|
||||||
|
|
|
@ -1555,7 +1555,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
const auto lnkIsVoice = document->isVoiceMessage();
|
const auto lnkIsVoice = document->isVoiceMessage();
|
||||||
const auto lnkIsAudio = document->isAudioFile();
|
const auto lnkIsAudio = document->isAudioFile();
|
||||||
if (document->loaded() && document->isGifv()) {
|
if (document->loaded() && document->isGifv()) {
|
||||||
if (!cAutoPlayGif()) {
|
if (!document->session().settings().autoplayGifs()) {
|
||||||
_menu->addAction(tr::lng_context_open_gif(tr::now), [=] {
|
_menu->addAction(tr::lng_context_open_gif(tr::now), [=] {
|
||||||
openContextGif(itemId);
|
openContextGif(itemId);
|
||||||
});
|
});
|
||||||
|
@ -2384,6 +2384,18 @@ bool HistoryInner::elementIntersectsRange(
|
||||||
return (top < till && bottom > from);
|
return (top < till && bottom > from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HistoryInner::elementStartStickerLoop(
|
||||||
|
not_null<const Element*> view) const {
|
||||||
|
return _controller->session().settings().loopAnimatedStickers()
|
||||||
|
|| !_animatedStickersPlayed.contains(view->data()->fullId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryInner::elementStickerLoopStarted(not_null<const Element*> view) {
|
||||||
|
if (!_controller->session().settings().loopAnimatedStickers()) {
|
||||||
|
_animatedStickersPlayed.emplace(view->data()->fullId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto HistoryInner::getSelectionState() const
|
auto HistoryInner::getSelectionState() const
|
||||||
-> HistoryView::TopBarWidget::SelectedState {
|
-> HistoryView::TopBarWidget::SelectedState {
|
||||||
auto result = HistoryView::TopBarWidget::SelectedState {};
|
auto result = HistoryView::TopBarWidget::SelectedState {};
|
||||||
|
@ -3234,6 +3246,18 @@ not_null<HistoryView::ElementDelegate*> HistoryInner::ElementDelegate() {
|
||||||
? Instance->elementIntersectsRange(view, from, till)
|
? Instance->elementIntersectsRange(view, from, till)
|
||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
|
bool elementStartStickerLoop(
|
||||||
|
not_null<const Element*> view) override {
|
||||||
|
return Instance
|
||||||
|
? Instance->elementStartStickerLoop(view)
|
||||||
|
: true;
|
||||||
|
}
|
||||||
|
void elementStickerLoopStarted(
|
||||||
|
not_null<const Element*> view) override {
|
||||||
|
if (Instance) {
|
||||||
|
Instance->elementStickerLoopStarted(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,8 @@ public:
|
||||||
not_null<const Element*> view,
|
not_null<const Element*> view,
|
||||||
int from,
|
int from,
|
||||||
int till) const;
|
int till) const;
|
||||||
|
bool elementStartStickerLoop(not_null<const Element*> view) const;
|
||||||
|
void elementStickerLoopStarted(not_null<const Element*> view);
|
||||||
|
|
||||||
void updateBotInfo(bool recount = true);
|
void updateBotInfo(bool recount = true);
|
||||||
|
|
||||||
|
@ -330,6 +332,8 @@ private:
|
||||||
style::cursor _cursor = style::cur_default;
|
style::cursor _cursor = style::cur_default;
|
||||||
SelectedItems _selected;
|
SelectedItems _selected;
|
||||||
|
|
||||||
|
base::flat_set<FullMsgId> _animatedStickersPlayed;
|
||||||
|
|
||||||
MouseAction _mouseAction = MouseAction::None;
|
MouseAction _mouseAction = MouseAction::None;
|
||||||
TextSelectType _mouseSelectType = TextSelectType::Letters;
|
TextSelectType _mouseSelectType = TextSelectType::Letters;
|
||||||
QPoint _dragStartPosition;
|
QPoint _dragStartPosition;
|
||||||
|
|
|
@ -1639,7 +1639,7 @@ void HistoryWidget::showHistory(
|
||||||
cancelTypingAction();
|
cancelTypingAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cAutoPlayGif()) {
|
if (!session().settings().autoplayGifs()) {
|
||||||
session().data().stopAutoplayAnimations();
|
session().data().stopAutoplayAnimations();
|
||||||
}
|
}
|
||||||
clearReplyReturns();
|
clearReplyReturns();
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
#include "media/audio/media_audio.h"
|
#include "media/audio/media_audio.h"
|
||||||
#include "media/clip/media_clip_reader.h"
|
#include "media/clip/media_clip_reader.h"
|
||||||
#include "media/player/media_player_instance.h"
|
#include "media/player/media_player_instance.h"
|
||||||
|
@ -228,6 +229,10 @@ QSize HistoryGif::videoSize() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HistoryGif::autoplayEnabled() const {
|
||||||
|
return history()->session().settings().autoplayGifs();
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
|
|
||||||
|
@ -238,7 +243,7 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, crl::
|
||||||
auto selected = (selection == FullSelection);
|
auto selected = (selection == FullSelection);
|
||||||
|
|
||||||
if (loaded
|
if (loaded
|
||||||
&& cAutoPlayGif()
|
&& autoplayEnabled()
|
||||||
&& !_gif
|
&& !_gif
|
||||||
&& !_gif.isBad()
|
&& !_gif.isBad()
|
||||||
&& !activeRoundPlayer()) {
|
&& !activeRoundPlayer()) {
|
||||||
|
@ -370,7 +375,7 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, crl::
|
||||||
App::complexOverlayRect(p, rthumb, roundRadius, roundCorners);
|
App::complexOverlayRect(p, rthumb, roundRadius, roundCorners);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (radial || (!reader && !player && (_gif.isBad() || (!loaded && !_data->loading()) || !cAutoPlayGif()))) {
|
if (radial || (!reader && !player && (_gif.isBad() || (!loaded && !_data->loading()) || !autoplayEnabled()))) {
|
||||||
auto radialOpacity = (radial && loaded && item->id > 0) ? _animation->radial.opacity() : 1.;
|
auto radialOpacity = (radial && loaded && item->id > 0) ? _animation->radial.opacity() : 1.;
|
||||||
auto inner = QRect(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
auto inner = QRect(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
|
@ -852,7 +857,7 @@ void HistoryGif::playAnimation(bool autoplay) {
|
||||||
return;
|
return;
|
||||||
} else if (_gif && autoplay) {
|
} else if (_gif && autoplay) {
|
||||||
return;
|
return;
|
||||||
} else if (_gif && cAutoPlayGif()) {
|
} else if (_gif && autoplayEnabled()) {
|
||||||
Core::App().showDocument(_data, _parent->data());
|
Core::App().showDocument(_data, _parent->data());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -860,7 +865,7 @@ void HistoryGif::playAnimation(bool autoplay) {
|
||||||
if (_gif) {
|
if (_gif) {
|
||||||
stopAnimation();
|
stopAnimation();
|
||||||
} else if (_data->loaded(DocumentData::FilePathResolve::Checked)) {
|
} else if (_data->loaded(DocumentData::FilePathResolve::Checked)) {
|
||||||
if (!cAutoPlayGif()) {
|
if (!autoplayEnabled()) {
|
||||||
history()->owner().stopAutoplayAnimations();
|
history()->owner().stopAutoplayAnimations();
|
||||||
}
|
}
|
||||||
setClipReader(Media::Clip::MakeReader(
|
setClipReader(Media::Clip::MakeReader(
|
||||||
|
|
|
@ -85,6 +85,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
[[nodiscard]] bool autoplayEnabled() const;
|
||||||
void playAnimation(bool autoplay) override;
|
void playAnimation(bool autoplay) override;
|
||||||
QSize countOptimalSize() override;
|
QSize countOptimalSize() override;
|
||||||
QSize countCurrentSize(int newWidth) override;
|
QSize countCurrentSize(int newWidth) override;
|
||||||
|
|
|
@ -122,7 +122,11 @@ void HistorySticker::unloadLottie() {
|
||||||
_parent->data()->history()->owner().unregisterHeavyViewPart(_parent);
|
_parent->data()->history()->owner().unregisterHeavyViewPart(_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistorySticker::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
void HistorySticker::draw(
|
||||||
|
Painter &p,
|
||||||
|
const QRect &r,
|
||||||
|
TextSelection selection,
|
||||||
|
crl::time ms) const {
|
||||||
auto sticker = _data->sticker();
|
auto sticker = _data->sticker();
|
||||||
if (!sticker) return;
|
if (!sticker) return;
|
||||||
|
|
||||||
|
@ -197,19 +201,24 @@ void HistorySticker::draw(Painter &p, const QRect &r, TextSelection selection, c
|
||||||
if (selected) {
|
if (selected) {
|
||||||
request.colored = st::msgStickerOverlay->c;
|
request.colored = st::msgStickerOverlay->c;
|
||||||
}
|
}
|
||||||
const auto paused = App::wnd()->sessionController()->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
|
const auto frame = _lottie->frameInfo(request);
|
||||||
if (!paused) {
|
const auto size = frame.image.size() / cIntRetinaFactor();
|
||||||
_lottie->markFrameShown();
|
|
||||||
}
|
|
||||||
const auto frame = _lottie->frame(request);
|
|
||||||
const auto size = frame.size() / cIntRetinaFactor();
|
|
||||||
p.drawImage(
|
p.drawImage(
|
||||||
QRect(
|
QRect(
|
||||||
QPoint(
|
QPoint(
|
||||||
usex + (usew - size.width()) / 2,
|
usex + (usew - size.width()) / 2,
|
||||||
(minHeight() - size.height()) / 2),
|
(minHeight() - size.height()) / 2),
|
||||||
size),
|
size),
|
||||||
frame);
|
frame.image);
|
||||||
|
|
||||||
|
const auto paused = App::wnd()->sessionController()->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
|
||||||
|
if (!paused
|
||||||
|
&& (frame.index != 0
|
||||||
|
|| _parent->delegate()->elementStartStickerLoop(_parent))
|
||||||
|
&& _lottie->markFrameShown()
|
||||||
|
&& !frame.index) {
|
||||||
|
_parent->delegate()->elementStickerLoopStarted(_parent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!inWebPage) {
|
if (!inWebPage) {
|
||||||
auto fullRight = usex + usew;
|
auto fullRight = usex + usew;
|
||||||
|
|
|
@ -162,12 +162,12 @@ void AddDocumentActions(
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (document->loaded() && document->isGifv()) {
|
if (document->loaded()
|
||||||
if (!cAutoPlayGif()) {
|
&& document->isGifv()
|
||||||
menu->addAction(tr::lng_context_open_gif(tr::now), [=] {
|
&& !document->session().settings().autoplayGifs()) {
|
||||||
OpenGif(contextId);
|
menu->addAction(tr::lng_context_open_gif(tr::now), [=] {
|
||||||
});
|
OpenGif(contextId);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
if (document->sticker()
|
if (document->sticker()
|
||||||
&& document->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
|
&& document->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
|
||||||
|
|
|
@ -84,6 +84,15 @@ bool SimpleElementDelegate::elementIntersectsRange(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SimpleElementDelegate::elementStartStickerLoop(
|
||||||
|
not_null<const Element*> view) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimpleElementDelegate::elementStickerLoopStarted(
|
||||||
|
not_null<const Element*> view) {
|
||||||
|
}
|
||||||
|
|
||||||
TextSelection UnshiftItemSelection(
|
TextSelection UnshiftItemSelection(
|
||||||
TextSelection selection,
|
TextSelection selection,
|
||||||
uint16 byLength) {
|
uint16 byLength) {
|
||||||
|
|
|
@ -50,6 +50,9 @@ public:
|
||||||
not_null<const Element*> view,
|
not_null<const Element*> view,
|
||||||
int from,
|
int from,
|
||||||
int till) = 0;
|
int till) = 0;
|
||||||
|
virtual bool elementStartStickerLoop(not_null<const Element*> view) = 0;
|
||||||
|
virtual void elementStickerLoopStarted(
|
||||||
|
not_null<const Element*> view) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,6 +72,10 @@ public:
|
||||||
not_null<const Element*> view,
|
not_null<const Element*> view,
|
||||||
int from,
|
int from,
|
||||||
int till) override;
|
int till) override;
|
||||||
|
bool elementStartStickerLoop(
|
||||||
|
not_null<const Element*> view) override;
|
||||||
|
void elementStickerLoopStarted(not_null<const Element*> view) override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TextSelection UnshiftItemSelection(
|
TextSelection UnshiftItemSelection(
|
||||||
|
|
|
@ -1141,6 +1141,17 @@ bool ListWidget::elementIntersectsRange(
|
||||||
return (top < till && bottom > from);
|
return (top < till && bottom > from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ListWidget::elementStartStickerLoop(not_null<const Element*> view) {
|
||||||
|
return _controller->session().settings().loopAnimatedStickers()
|
||||||
|
|| !_animatedStickersPlayed.contains(view->data()->fullId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListWidget::elementStickerLoopStarted(not_null<const Element*> view) {
|
||||||
|
if (!_controller->session().settings().loopAnimatedStickers()) {
|
||||||
|
_animatedStickersPlayed.emplace(view->data()->fullId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ListWidget::saveState(not_null<ListMemento*> memento) {
|
void ListWidget::saveState(not_null<ListMemento*> memento) {
|
||||||
memento->setAroundPosition(_aroundPosition);
|
memento->setAroundPosition(_aroundPosition);
|
||||||
auto state = countScrollState();
|
auto state = countScrollState();
|
||||||
|
|
|
@ -184,12 +184,15 @@ public:
|
||||||
bool elementUnderCursor(not_null<const Element*> view) override;
|
bool elementUnderCursor(not_null<const Element*> view) override;
|
||||||
void elementAnimationAutoplayAsync(
|
void elementAnimationAutoplayAsync(
|
||||||
not_null<const Element*> view) override;
|
not_null<const Element*> view) override;
|
||||||
crl::time elementHighlightTime(not_null<const Element*> element) override;
|
crl::time elementHighlightTime(
|
||||||
|
not_null<const Element*> element) override;
|
||||||
bool elementInSelectionMode() override;
|
bool elementInSelectionMode() override;
|
||||||
bool elementIntersectsRange(
|
bool elementIntersectsRange(
|
||||||
not_null<const Element*> view,
|
not_null<const Element*> view,
|
||||||
int from,
|
int from,
|
||||||
int till) override;
|
int till) override;
|
||||||
|
bool elementStartStickerLoop(not_null<const Element*> view) override;
|
||||||
|
void elementStickerLoopStarted(not_null<const Element*> view) override;
|
||||||
|
|
||||||
~ListWidget();
|
~ListWidget();
|
||||||
|
|
||||||
|
@ -441,6 +444,7 @@ private:
|
||||||
int _itemsWidth = 0;
|
int _itemsWidth = 0;
|
||||||
int _itemsHeight = 0;
|
int _itemsHeight = 0;
|
||||||
int _itemAverageHeight = 0;
|
int _itemAverageHeight = 0;
|
||||||
|
base::flat_set<FullMsgId> _animatedStickersPlayed;
|
||||||
|
|
||||||
int _minHeight = 0;
|
int _minHeight = 0;
|
||||||
int _visibleTop = 0;
|
int _visibleTop = 0;
|
||||||
|
|
|
@ -54,7 +54,6 @@ void PrepareSupportMode() {
|
||||||
Global::SetDesktopNotify(false);
|
Global::SetDesktopNotify(false);
|
||||||
Global::SetSoundNotify(false);
|
Global::SetSoundNotify(false);
|
||||||
Auth().settings().autoDownload() = Full::FullDisabled();
|
Auth().settings().autoDownload() = Full::FullDisabled();
|
||||||
cSetAutoPlayGif(false);
|
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -228,4 +228,19 @@ QImage Animation::frame(const FrameRequest &request) const {
|
||||||
return PrepareFrameByRequest(frame, !changed);
|
return PrepareFrameByRequest(frame, !changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Animation::frameInfo(const FrameRequest &request) const -> FrameInfo {
|
||||||
|
Expects(_state != nullptr);
|
||||||
|
|
||||||
|
const auto frame = _state->frameForPaint();
|
||||||
|
const auto changed = (frame->request != request);
|
||||||
|
if (changed) {
|
||||||
|
frame->request = request;
|
||||||
|
_player->updateFrameRequest(this, request);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
PrepareFrameByRequest(frame, !changed),
|
||||||
|
frame->index % _state->framesCount()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Lottie
|
} // namespace Lottie
|
||||||
|
|
|
@ -10,7 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lottie/lottie_common.h"
|
#include "lottie/lottie_common.h"
|
||||||
#include "base/weak_ptr.h"
|
#include "base/weak_ptr.h"
|
||||||
|
|
||||||
class QImage;
|
#include <QtGui/QImage>
|
||||||
|
|
||||||
class QString;
|
class QString;
|
||||||
class QByteArray;
|
class QByteArray;
|
||||||
|
|
||||||
|
@ -39,6 +40,11 @@ std::unique_ptr<rlottie::Animation> CreateFromContent(
|
||||||
|
|
||||||
class Animation final : public base::has_weak_ptr {
|
class Animation final : public base::has_weak_ptr {
|
||||||
public:
|
public:
|
||||||
|
struct FrameInfo {
|
||||||
|
QImage image;
|
||||||
|
int index = 0;
|
||||||
|
};
|
||||||
|
|
||||||
Animation(
|
Animation(
|
||||||
not_null<Player*> player,
|
not_null<Player*> player,
|
||||||
const QByteArray &content,
|
const QByteArray &content,
|
||||||
|
@ -55,6 +61,7 @@ public:
|
||||||
[[nodiscard]] bool ready() const;
|
[[nodiscard]] bool ready() const;
|
||||||
[[nodiscard]] QImage frame() const;
|
[[nodiscard]] QImage frame() const;
|
||||||
[[nodiscard]] QImage frame(const FrameRequest &request) const;
|
[[nodiscard]] QImage frame(const FrameRequest &request) const;
|
||||||
|
[[nodiscard]] FrameInfo frameInfo(const FrameRequest &request) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initDone(details::InitData &&data);
|
void initDone(details::InitData &&data);
|
||||||
|
|
|
@ -210,12 +210,46 @@ void FrameRendererObject::queueGenerateFrames() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Information SharedState::CalculateInformation(
|
||||||
|
Quality quality,
|
||||||
|
rlottie::Animation *animation,
|
||||||
|
Cache *cache) {
|
||||||
|
Expects(animation != nullptr || cache != nullptr);
|
||||||
|
|
||||||
|
auto width = size_t(0);
|
||||||
|
auto height = size_t(0);
|
||||||
|
if (animation) {
|
||||||
|
animation->size(width, height);
|
||||||
|
} else {
|
||||||
|
width = cache->originalSize().width();
|
||||||
|
height = cache->originalSize().height();
|
||||||
|
}
|
||||||
|
const auto rate = animation
|
||||||
|
? GetLottieFrameRate(animation, quality)
|
||||||
|
: cache->frameRate();
|
||||||
|
const auto count = animation
|
||||||
|
? GetLottieFramesCount(animation, quality)
|
||||||
|
: cache->framesCount();
|
||||||
|
|
||||||
|
auto result = Information();
|
||||||
|
result.size = QSize(
|
||||||
|
(width > 0 && width <= kMaxSize) ? int(width) : 0,
|
||||||
|
(height > 0 && height <= kMaxSize) ? int(height) : 0);
|
||||||
|
result.frameRate = (rate > 0 && rate <= kMaxFrameRate) ? int(rate) : 0;
|
||||||
|
result.framesCount = (count > 0 && count <= kMaxFramesCount)
|
||||||
|
? int(count)
|
||||||
|
: 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
SharedState::SharedState(
|
SharedState::SharedState(
|
||||||
std::unique_ptr<rlottie::Animation> animation,
|
std::unique_ptr<rlottie::Animation> animation,
|
||||||
const FrameRequest &request,
|
const FrameRequest &request,
|
||||||
Quality quality)
|
Quality quality)
|
||||||
: _animation(std::move(animation))
|
: _info(CalculateInformation(quality, animation.get(), nullptr))
|
||||||
, _quality(quality) {
|
, _quality(quality)
|
||||||
|
, _animation(std::move(animation)) {
|
||||||
construct(request);
|
construct(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,15 +259,15 @@ SharedState::SharedState(
|
||||||
std::unique_ptr<Cache> cache,
|
std::unique_ptr<Cache> cache,
|
||||||
const FrameRequest &request,
|
const FrameRequest &request,
|
||||||
Quality quality)
|
Quality quality)
|
||||||
: _content(content)
|
: _info(CalculateInformation(quality, animation.get(), cache.get()))
|
||||||
, _animation(std::move(animation))
|
|
||||||
, _quality(quality)
|
, _quality(quality)
|
||||||
, _cache(std::move(cache)) {
|
, _cache(std::move(cache))
|
||||||
|
, _animation(std::move(animation))
|
||||||
|
, _content(content) {
|
||||||
construct(request);
|
construct(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedState::construct(const FrameRequest &request) {
|
void SharedState::construct(const FrameRequest &request) {
|
||||||
calculateProperties();
|
|
||||||
if (!isValid()) {
|
if (!isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -243,39 +277,20 @@ void SharedState::construct(const FrameRequest &request) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_cache) {
|
if (_cache) {
|
||||||
_cache->init(_size, _frameRate, _framesCount, request);
|
_cache->init(
|
||||||
|
_info.size,
|
||||||
|
_info.frameRate,
|
||||||
|
_info.framesCount,
|
||||||
|
request);
|
||||||
}
|
}
|
||||||
renderFrame(cover, request, 0);
|
renderFrame(cover, request, 0);
|
||||||
init(std::move(cover), request);
|
init(std::move(cover), request);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedState::calculateProperties() {
|
|
||||||
Expects(_animation != nullptr || _cache != nullptr);
|
|
||||||
|
|
||||||
auto width = size_t(0);
|
|
||||||
auto height = size_t(0);
|
|
||||||
if (_animation) {
|
|
||||||
_animation->size(width, height);
|
|
||||||
} else {
|
|
||||||
width = _cache->originalSize().width();
|
|
||||||
height = _cache->originalSize().height();
|
|
||||||
}
|
|
||||||
const auto rate = _animation
|
|
||||||
? GetLottieFrameRate(_animation.get(), _quality)
|
|
||||||
: _cache->frameRate();
|
|
||||||
const auto count = _animation
|
|
||||||
? GetLottieFramesCount(_animation.get(), _quality)
|
|
||||||
: _cache->framesCount();
|
|
||||||
|
|
||||||
_size = QSize(
|
|
||||||
(width > 0 && width <= kMaxSize) ? int(width) : 0,
|
|
||||||
(height > 0 && height <= kMaxSize) ? int(height) : 0);
|
|
||||||
_frameRate = (rate > 0 && rate <= kMaxFrameRate) ? int(rate) : 0;
|
|
||||||
_framesCount = (count > 0 && count <= kMaxFramesCount) ? int(count) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedState::isValid() const {
|
bool SharedState::isValid() const {
|
||||||
return (_framesCount > 0) && (_frameRate > 0) && !_size.isEmpty();
|
return (_info.framesCount > 0)
|
||||||
|
&& (_info.frameRate > 0)
|
||||||
|
&& !_info.size.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedState::renderFrame(
|
void SharedState::renderFrame(
|
||||||
|
@ -286,7 +301,9 @@ void SharedState::renderFrame(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto size = request.box.isEmpty() ? _size : request.size(_size);
|
const auto size = request.box.isEmpty()
|
||||||
|
? _info.size
|
||||||
|
: request.size(_info.size);
|
||||||
if (!GoodStorageForFrame(image, size)) {
|
if (!GoodStorageForFrame(image, size)) {
|
||||||
image = CreateFrameStorage(size);
|
image = CreateFrameStorage(size);
|
||||||
}
|
}
|
||||||
|
@ -339,9 +356,12 @@ bool IsRendered(not_null<const Frame*> frame) {
|
||||||
void SharedState::renderNextFrame(
|
void SharedState::renderNextFrame(
|
||||||
not_null<Frame*> frame,
|
not_null<Frame*> frame,
|
||||||
const FrameRequest &request) {
|
const FrameRequest &request) {
|
||||||
Expects(_framesCount > 0);
|
Expects(_info.framesCount > 0);
|
||||||
|
|
||||||
renderFrame(frame->original, request, (++_frameIndex) % _framesCount);
|
renderFrame(
|
||||||
|
frame->original,
|
||||||
|
request,
|
||||||
|
(++_frameIndex) % _info.framesCount);
|
||||||
frame->request = request;
|
frame->request = request;
|
||||||
PrepareFrameByRequest(frame);
|
PrepareFrameByRequest(frame);
|
||||||
frame->index = _frameIndex;
|
frame->index = _frameIndex;
|
||||||
|
@ -392,7 +412,7 @@ auto SharedState::renderNextFrame(const FrameRequest &request)
|
||||||
crl::time SharedState::countFrameDisplayTime(int index) const {
|
crl::time SharedState::countFrameDisplayTime(int index) const {
|
||||||
return _started
|
return _started
|
||||||
+ _delay
|
+ _delay
|
||||||
+ crl::time(1000) * (_skippedFrames + index) / _frameRate;
|
+ crl::time(1000) * (_skippedFrames + index) / _info.frameRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SharedState::counter() const {
|
int SharedState::counter() const {
|
||||||
|
@ -416,14 +436,7 @@ not_null<const Frame*> SharedState::getFrame(int index) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Information SharedState::information() const {
|
Information SharedState::information() const {
|
||||||
if (!isValid()) {
|
return isValid() ? _info : Information();
|
||||||
return {};
|
|
||||||
}
|
|
||||||
auto result = Information();
|
|
||||||
result.frameRate = _frameRate;
|
|
||||||
result.size = _size;
|
|
||||||
result.framesCount = _framesCount;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<Frame*> SharedState::frameForPaint() {
|
not_null<Frame*> SharedState::frameForPaint() {
|
||||||
|
@ -434,6 +447,10 @@ not_null<Frame*> SharedState::frameForPaint() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SharedState::framesCount() const {
|
||||||
|
return _info.framesCount;
|
||||||
|
}
|
||||||
|
|
||||||
crl::time SharedState::nextFrameDisplayTime() const {
|
crl::time SharedState::nextFrameDisplayTime() const {
|
||||||
const auto frameDisplayTime = [&](int counter) {
|
const auto frameDisplayTime = [&](int counter) {
|
||||||
const auto next = (counter + 1) % (2 * kFramesCount);
|
const auto next = (counter + 1) % (2 * kFramesCount);
|
||||||
|
|
|
@ -72,6 +72,7 @@ public:
|
||||||
[[nodiscard]] bool initialized() const;
|
[[nodiscard]] bool initialized() const;
|
||||||
|
|
||||||
[[nodiscard]] not_null<Frame*> frameForPaint();
|
[[nodiscard]] not_null<Frame*> frameForPaint();
|
||||||
|
[[nodiscard]] int framesCount() const;
|
||||||
[[nodiscard]] crl::time nextFrameDisplayTime() const;
|
[[nodiscard]] crl::time nextFrameDisplayTime() const;
|
||||||
void addTimelineDelay(crl::time delayed, int skippedFrames = 0);
|
void addTimelineDelay(crl::time delayed, int skippedFrames = 0);
|
||||||
void markFrameDisplayed(crl::time now);
|
void markFrameDisplayed(crl::time now);
|
||||||
|
@ -88,8 +89,12 @@ public:
|
||||||
~SharedState();
|
~SharedState();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static Information CalculateInformation(
|
||||||
|
Quality quality,
|
||||||
|
rlottie::Animation *animation,
|
||||||
|
Cache *cache);
|
||||||
|
|
||||||
void construct(const FrameRequest &request);
|
void construct(const FrameRequest &request);
|
||||||
void calculateProperties();
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
void init(QImage cover, const FrameRequest &request);
|
void init(QImage cover, const FrameRequest &request);
|
||||||
void renderNextFrame(
|
void renderNextFrame(
|
||||||
|
@ -100,10 +105,6 @@ private:
|
||||||
[[nodiscard]] not_null<const Frame*> getFrame(int index) const;
|
[[nodiscard]] not_null<const Frame*> getFrame(int index) const;
|
||||||
[[nodiscard]] int counter() const;
|
[[nodiscard]] int counter() const;
|
||||||
|
|
||||||
QByteArray _content;
|
|
||||||
std::unique_ptr<rlottie::Animation> _animation;
|
|
||||||
Quality _quality = Quality::Default;
|
|
||||||
|
|
||||||
// crl::queue changes 0,2,4,6 to 1,3,5,7.
|
// crl::queue changes 0,2,4,6 to 1,3,5,7.
|
||||||
// main thread changes 1,3,5,7 to 2,4,6,0.
|
// main thread changes 1,3,5,7 to 2,4,6,0.
|
||||||
static constexpr auto kCounterUninitialized = -1;
|
static constexpr auto kCounterUninitialized = -1;
|
||||||
|
@ -121,11 +122,13 @@ private:
|
||||||
|
|
||||||
int _frameIndex = 0;
|
int _frameIndex = 0;
|
||||||
int _skippedFrames = 0;
|
int _skippedFrames = 0;
|
||||||
int _framesCount = 0;
|
const Information _info;
|
||||||
int _frameRate = 0;
|
const Quality _quality = Quality::Default;
|
||||||
QSize _size;
|
|
||||||
|
|
||||||
std::unique_ptr<Cache> _cache;
|
const std::unique_ptr<Cache> _cache;
|
||||||
|
|
||||||
|
std::unique_ptr<rlottie::Animation> _animation;
|
||||||
|
const QByteArray _content;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -369,7 +369,7 @@ void MultiPlayer::addTimelineDelay(crl::time delayed) {
|
||||||
_delay += delayed;
|
_delay += delayed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiPlayer::markFrameShown() {
|
bool MultiPlayer::markFrameShown() {
|
||||||
if (_nextFrameTime == kFrameDisplayTimeAlreadyDone) {
|
if (_nextFrameTime == kFrameDisplayTimeAlreadyDone) {
|
||||||
_nextFrameTime = kTimeUnknown;
|
_nextFrameTime = kTimeUnknown;
|
||||||
}
|
}
|
||||||
|
@ -381,7 +381,9 @@ void MultiPlayer::markFrameShown() {
|
||||||
}
|
}
|
||||||
if (count) {
|
if (count) {
|
||||||
_renderer->frameShown();
|
_renderer->frameShown();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Lottie
|
} // namespace Lottie
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
void updateFrameRequest(
|
void updateFrameRequest(
|
||||||
not_null<const Animation*> animation,
|
not_null<const Animation*> animation,
|
||||||
const FrameRequest &request) override;
|
const FrameRequest &request) override;
|
||||||
void markFrameShown() override;
|
bool markFrameShown() override;
|
||||||
void checkStep() override;
|
void checkStep() override;
|
||||||
|
|
||||||
not_null<Animation*> append(
|
not_null<Animation*> append(
|
||||||
|
|
|
@ -25,7 +25,7 @@ public:
|
||||||
virtual void updateFrameRequest(
|
virtual void updateFrameRequest(
|
||||||
not_null<const Animation*> animation,
|
not_null<const Animation*> animation,
|
||||||
const FrameRequest &request) = 0;
|
const FrameRequest &request) = 0;
|
||||||
virtual void markFrameShown() = 0;
|
virtual bool markFrameShown() = 0;
|
||||||
virtual void checkStep() = 0;
|
virtual void checkStep() = 0;
|
||||||
|
|
||||||
virtual ~Player() = default;
|
virtual ~Player() = default;
|
||||||
|
|
|
@ -79,6 +79,11 @@ QImage SinglePlayer::frame(const FrameRequest &request) const {
|
||||||
return _animation.frame(request);
|
return _animation.frame(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Animation::FrameInfo SinglePlayer::frameInfo(
|
||||||
|
const FrameRequest &request) const {
|
||||||
|
return _animation.frameInfo(request);
|
||||||
|
}
|
||||||
|
|
||||||
void SinglePlayer::checkStep() {
|
void SinglePlayer::checkStep() {
|
||||||
if (_nextFrameTime == kFrameDisplayTimeAlreadyDone) {
|
if (_nextFrameTime == kFrameDisplayTimeAlreadyDone) {
|
||||||
return;
|
return;
|
||||||
|
@ -128,7 +133,7 @@ void SinglePlayer::updateFrameRequest(
|
||||||
_renderer->updateFrameRequest(_state, request);
|
_renderer->updateFrameRequest(_state, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SinglePlayer::markFrameShown() {
|
bool SinglePlayer::markFrameShown() {
|
||||||
Expects(_state != nullptr);
|
Expects(_state != nullptr);
|
||||||
|
|
||||||
if (_nextFrameTime == kFrameDisplayTimeAlreadyDone) {
|
if (_nextFrameTime == kFrameDisplayTimeAlreadyDone) {
|
||||||
|
@ -136,7 +141,9 @@ void SinglePlayer::markFrameShown() {
|
||||||
}
|
}
|
||||||
if (_state->markFrameShown()) {
|
if (_state->markFrameShown()) {
|
||||||
_renderer->frameShown();
|
_renderer->frameShown();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Lottie
|
} // namespace Lottie
|
||||||
|
|
|
@ -49,7 +49,7 @@ public:
|
||||||
void updateFrameRequest(
|
void updateFrameRequest(
|
||||||
not_null<const Animation*> animation,
|
not_null<const Animation*> animation,
|
||||||
const FrameRequest &request) override;
|
const FrameRequest &request) override;
|
||||||
void markFrameShown() override;
|
bool markFrameShown() override;
|
||||||
void checkStep() override;
|
void checkStep() override;
|
||||||
|
|
||||||
rpl::producer<Update, Error> updates() const;
|
rpl::producer<Update, Error> updates() const;
|
||||||
|
@ -57,6 +57,8 @@ public:
|
||||||
[[nodiscard]] bool ready() const;
|
[[nodiscard]] bool ready() const;
|
||||||
[[nodiscard]] QImage frame() const;
|
[[nodiscard]] QImage frame() const;
|
||||||
[[nodiscard]] QImage frame(const FrameRequest &request) const;
|
[[nodiscard]] QImage frame(const FrameRequest &request) const;
|
||||||
|
[[nodiscard]] Animation::FrameInfo frameInfo(
|
||||||
|
const FrameRequest &request) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void checkNextFrameAvailability();
|
void checkNextFrameAvailability();
|
||||||
|
|
|
@ -49,7 +49,7 @@ Settings::Variables::Variables()
|
||||||
|
|
||||||
QByteArray Settings::serialize() const {
|
QByteArray Settings::serialize() const {
|
||||||
const auto autoDownload = _variables.autoDownload.serialize();
|
const auto autoDownload = _variables.autoDownload.serialize();
|
||||||
auto size = sizeof(qint32) * 23;
|
auto size = sizeof(qint32) * 30;
|
||||||
for (auto i = _variables.soundOverrides.cbegin(), e = _variables.soundOverrides.cend(); i != e; ++i) {
|
for (auto i = _variables.soundOverrides.cbegin(), e = _variables.soundOverrides.cend(); i != e; ++i) {
|
||||||
size += Serialize::stringSize(i.key()) + Serialize::stringSize(i.value());
|
size += Serialize::stringSize(i.key()) + Serialize::stringSize(i.value());
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,8 @@ QByteArray Settings::serialize() const {
|
||||||
stream << qint32(_variables.notifyAboutPinned.current() ? 1 : 0);
|
stream << qint32(_variables.notifyAboutPinned.current() ? 1 : 0);
|
||||||
stream << qint32(_variables.archiveInMainMenu.current() ? 1 : 0);
|
stream << qint32(_variables.archiveInMainMenu.current() ? 1 : 0);
|
||||||
stream << qint32(_variables.skipArchiveInSearch.current() ? 1 : 0);
|
stream << qint32(_variables.skipArchiveInSearch.current() ? 1 : 0);
|
||||||
|
stream << qint32(_variables.autoplayGifs ? 1 : 0);
|
||||||
|
stream << qint32(_variables.loopAnimatedStickers ? 1 : 0);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -139,6 +141,8 @@ void Settings::constructFromSerialized(const QByteArray &serialized) {
|
||||||
qint32 notifyAboutPinned = _variables.notifyAboutPinned.current() ? 1 : 0;
|
qint32 notifyAboutPinned = _variables.notifyAboutPinned.current() ? 1 : 0;
|
||||||
qint32 archiveInMainMenu = _variables.archiveInMainMenu.current() ? 1 : 0;
|
qint32 archiveInMainMenu = _variables.archiveInMainMenu.current() ? 1 : 0;
|
||||||
qint32 skipArchiveInSearch = _variables.skipArchiveInSearch.current() ? 1 : 0;
|
qint32 skipArchiveInSearch = _variables.skipArchiveInSearch.current() ? 1 : 0;
|
||||||
|
qint32 autoplayGifs = _variables.autoplayGifs ? 1 : 0;
|
||||||
|
qint32 loopAnimatedStickers = _variables.loopAnimatedStickers ? 1 : 0;
|
||||||
|
|
||||||
stream >> selectorTab;
|
stream >> selectorTab;
|
||||||
stream >> lastSeenWarningSeen;
|
stream >> lastSeenWarningSeen;
|
||||||
|
@ -230,6 +234,10 @@ void Settings::constructFromSerialized(const QByteArray &serialized) {
|
||||||
if (!stream.atEnd()) {
|
if (!stream.atEnd()) {
|
||||||
stream >> skipArchiveInSearch;
|
stream >> skipArchiveInSearch;
|
||||||
}
|
}
|
||||||
|
if (!stream.atEnd()) {
|
||||||
|
stream >> autoplayGifs;
|
||||||
|
stream >> loopAnimatedStickers;
|
||||||
|
}
|
||||||
if (stream.status() != QDataStream::Ok) {
|
if (stream.status() != QDataStream::Ok) {
|
||||||
LOG(("App Error: "
|
LOG(("App Error: "
|
||||||
"Bad data for Settings::constructFromSerialized()"));
|
"Bad data for Settings::constructFromSerialized()"));
|
||||||
|
@ -303,6 +311,8 @@ void Settings::constructFromSerialized(const QByteArray &serialized) {
|
||||||
_variables.notifyAboutPinned = (notifyAboutPinned == 1);
|
_variables.notifyAboutPinned = (notifyAboutPinned == 1);
|
||||||
_variables.archiveInMainMenu = (archiveInMainMenu == 1);
|
_variables.archiveInMainMenu = (archiveInMainMenu == 1);
|
||||||
_variables.skipArchiveInSearch = (skipArchiveInSearch == 1);
|
_variables.skipArchiveInSearch = (skipArchiveInSearch == 1);
|
||||||
|
_variables.autoplayGifs = (autoplayGifs == 1);
|
||||||
|
_variables.loopAnimatedStickers = (loopAnimatedStickers == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setSupportChatsTimeSlice(int slice) {
|
void Settings::setSupportChatsTimeSlice(int slice) {
|
||||||
|
|
|
@ -230,6 +230,18 @@ public:
|
||||||
void setExeLaunchWarning(bool warning) {
|
void setExeLaunchWarning(bool warning) {
|
||||||
_variables.exeLaunchWarning = warning;
|
_variables.exeLaunchWarning = warning;
|
||||||
}
|
}
|
||||||
|
bool autoplayGifs() const {
|
||||||
|
return _variables.autoplayGifs;
|
||||||
|
}
|
||||||
|
void setAutoplayGifs(bool value) {
|
||||||
|
_variables.autoplayGifs = value;
|
||||||
|
}
|
||||||
|
bool loopAnimatedStickers() const {
|
||||||
|
return _variables.loopAnimatedStickers;
|
||||||
|
}
|
||||||
|
void setLoopAnimatedStickers(bool value) {
|
||||||
|
_variables.loopAnimatedStickers = value;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Variables {
|
struct Variables {
|
||||||
|
@ -264,6 +276,8 @@ private:
|
||||||
rpl::variable<bool> archiveInMainMenu = false;
|
rpl::variable<bool> archiveInMainMenu = false;
|
||||||
rpl::variable<bool> notifyAboutPinned = true;
|
rpl::variable<bool> notifyAboutPinned = true;
|
||||||
rpl::variable<bool> skipArchiveInSearch = false;
|
rpl::variable<bool> skipArchiveInSearch = false;
|
||||||
|
bool autoplayGifs = true;
|
||||||
|
bool loopAnimatedStickers = true;
|
||||||
|
|
||||||
static constexpr auto kDefaultSupportChatsLimitSlice
|
static constexpr auto kDefaultSupportChatsLimitSlice
|
||||||
= 7 * 24 * 60 * 60;
|
= 7 * 24 * 60 * 60;
|
||||||
|
|
|
@ -123,6 +123,7 @@ void LoaderMtproto::sendNext() {
|
||||||
|
|
||||||
const auto usedFileReference = _location.fileReference();
|
const auto usedFileReference = _location.fileReference();
|
||||||
const auto id = _sender.request(MTPupload_GetFile(
|
const auto id = _sender.request(MTPupload_GetFile(
|
||||||
|
MTP_flags(0),
|
||||||
_location.tl(Auth().userId()),
|
_location.tl(Auth().userId()),
|
||||||
MTP_int(offset),
|
MTP_int(offset),
|
||||||
MTP_int(kPartSize)
|
MTP_int(kPartSize)
|
||||||
|
|
|
@ -72,4 +72,3 @@ int gOtherOnline = 0;
|
||||||
int32 gAutoDownloadPhoto = 0; // all auto download
|
int32 gAutoDownloadPhoto = 0; // all auto download
|
||||||
int32 gAutoDownloadAudio = 0;
|
int32 gAutoDownloadAudio = 0;
|
||||||
int32 gAutoDownloadGif = 0;
|
int32 gAutoDownloadGif = 0;
|
||||||
bool gAutoPlayGif = true;
|
|
||||||
|
|
|
@ -158,7 +158,6 @@ DeclareSetting(float64, RetinaFactor);
|
||||||
DeclareSetting(int32, IntRetinaFactor);
|
DeclareSetting(int32, IntRetinaFactor);
|
||||||
|
|
||||||
DeclareSetting(int, OtherOnline);
|
DeclareSetting(int, OtherOnline);
|
||||||
DeclareSetting(bool, AutoPlayGif);
|
|
||||||
|
|
||||||
constexpr auto kInterfaceScaleAuto = 0;
|
constexpr auto kInterfaceScaleAuto = 0;
|
||||||
constexpr auto kInterfaceScaleMin = 100;
|
constexpr auto kInterfaceScaleMin = 100;
|
||||||
|
|
|
@ -424,21 +424,36 @@ void SetupPerformance(
|
||||||
not_null<Ui::VerticalLayout*> container) {
|
not_null<Ui::VerticalLayout*> container) {
|
||||||
SetupAnimations(container);
|
SetupAnimations(container);
|
||||||
|
|
||||||
|
const auto session = &controller->session();
|
||||||
AddButton(
|
AddButton(
|
||||||
container,
|
container,
|
||||||
tr::lng_settings_autoplay_gifs(),
|
tr::lng_settings_autoplay_gifs(),
|
||||||
st::settingsButton
|
st::settingsButton
|
||||||
)->toggleOn(
|
)->toggleOn(
|
||||||
rpl::single(cAutoPlayGif())
|
rpl::single(session->settings().autoplayGifs())
|
||||||
)->toggledValue(
|
)->toggledValue(
|
||||||
) | rpl::filter([](bool enabled) {
|
) | rpl::filter([=](bool enabled) {
|
||||||
return (enabled != cAutoPlayGif());
|
return (enabled != session->settings().autoplayGifs());
|
||||||
}) | rpl::start_with_next([=](bool enabled) {
|
}) | rpl::start_with_next([=](bool enabled) {
|
||||||
cSetAutoPlayGif(enabled);
|
session->settings().setAutoplayGifs(enabled);
|
||||||
if (!cAutoPlayGif()) {
|
if (!enabled) {
|
||||||
controller->session().data().stopAutoplayAnimations();
|
session->data().stopAutoplayAnimations();
|
||||||
}
|
}
|
||||||
Local::writeUserSettings();
|
session->saveSettingsDelayed();
|
||||||
|
}, container->lifetime());
|
||||||
|
|
||||||
|
AddButton(
|
||||||
|
container,
|
||||||
|
tr::lng_settings_loop_stickers(),
|
||||||
|
st::settingsButton
|
||||||
|
)->toggleOn(
|
||||||
|
rpl::single(session->settings().loopAnimatedStickers())
|
||||||
|
)->toggledValue(
|
||||||
|
) | rpl::filter([=](bool enabled) {
|
||||||
|
return enabled != session->settings().loopAnimatedStickers();
|
||||||
|
}) | rpl::start_with_next([=](bool enabled) {
|
||||||
|
session->settings().setLoopAnimatedStickers(enabled);
|
||||||
|
session->saveSettingsDelayed();
|
||||||
}, container->lifetime());
|
}, container->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -580,7 +580,7 @@ enum {
|
||||||
dbiAutoDownloadOld = 0x34,
|
dbiAutoDownloadOld = 0x34,
|
||||||
dbiSavedGifsLimit = 0x35,
|
dbiSavedGifsLimit = 0x35,
|
||||||
dbiShowingSavedGifsOld = 0x36,
|
dbiShowingSavedGifsOld = 0x36,
|
||||||
dbiAutoPlay = 0x37,
|
dbiAutoPlayOld = 0x37,
|
||||||
dbiAdaptiveForWide = 0x38,
|
dbiAdaptiveForWide = 0x38,
|
||||||
dbiHiddenPinnedMessages = 0x39,
|
dbiHiddenPinnedMessages = 0x39,
|
||||||
dbiRecentEmoji = 0x3a,
|
dbiRecentEmoji = 0x3a,
|
||||||
|
@ -1104,12 +1104,12 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
|
||||||
set(Type::VideoMessage, gif);
|
set(Type::VideoMessage, gif);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dbiAutoPlay: {
|
case dbiAutoPlayOld: {
|
||||||
qint32 gif;
|
qint32 gif;
|
||||||
stream >> gif;
|
stream >> gif;
|
||||||
if (!_checkStreamStatus(stream)) return false;
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
|
||||||
cSetAutoPlayGif(gif == 1);
|
GetStoredSessionSettings().setAutoplayGifs(gif == 1);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dbiDialogsMode: {
|
case dbiDialogsMode: {
|
||||||
|
@ -2087,7 +2087,6 @@ void _writeUserSettings() {
|
||||||
data.stream << quint32(dbiVideoVolume) << qint32(qRound(Global::VideoVolume() * 1e6));
|
data.stream << quint32(dbiVideoVolume) << qint32(qRound(Global::VideoVolume() * 1e6));
|
||||||
data.stream << quint32(dbiDialogsMode) << qint32(Global::DialogsModeEnabled() ? 1 : 0) << static_cast<qint32>(Global::DialogsMode());
|
data.stream << quint32(dbiDialogsMode) << qint32(Global::DialogsModeEnabled() ? 1 : 0) << static_cast<qint32>(Global::DialogsMode());
|
||||||
data.stream << quint32(dbiModerateMode) << qint32(Global::ModerateModeEnabled() ? 1 : 0);
|
data.stream << quint32(dbiModerateMode) << qint32(Global::ModerateModeEnabled() ? 1 : 0);
|
||||||
data.stream << quint32(dbiAutoPlay) << qint32(cAutoPlayGif() ? 1 : 0);
|
|
||||||
data.stream << quint32(dbiUseExternalVideoPlayer) << qint32(cUseExternalVideoPlayer());
|
data.stream << quint32(dbiUseExternalVideoPlayer) << qint32(cUseExternalVideoPlayer());
|
||||||
data.stream << quint32(dbiCacheSettings) << qint64(_cacheTotalSizeLimit) << qint32(_cacheTotalTimeLimit) << qint64(_cacheBigFileTotalSizeLimit) << qint32(_cacheBigFileTotalTimeLimit);
|
data.stream << quint32(dbiCacheSettings) << qint64(_cacheTotalSizeLimit) << qint32(_cacheTotalTimeLimit) << qint64(_cacheBigFileTotalSizeLimit) << qint32(_cacheBigFileTotalTimeLimit);
|
||||||
if (!userData.isEmpty()) {
|
if (!userData.isEmpty()) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue