mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-05-30 11:43:55 +02:00
Support on-hover autoplay and position save.
This commit is contained in:
parent
e8034189df
commit
6a415cf232
9 changed files with 223 additions and 97 deletions
|
@ -61,6 +61,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "settings/settings_privacy_security.h"
|
#include "settings/settings_privacy_security.h"
|
||||||
#include "settings/settings_chat.h"
|
#include "settings/settings_chat.h"
|
||||||
#include "settings/settings_premium.h"
|
#include "settings/settings_premium.h"
|
||||||
|
#include "storage/storage_account.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "main/main_account.h"
|
#include "main/main_account.h"
|
||||||
#include "main/main_app_config.h"
|
#include "main/main_app_config.h"
|
||||||
|
@ -782,8 +783,8 @@ bool OpenMediaTimestamp(
|
||||||
if (!controller) {
|
if (!controller) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto time = match->captured(2).toInt();
|
const auto position = match->captured(2).toInt();
|
||||||
if (time < 0) {
|
if (position < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto base = match->captured(1);
|
const auto base = match->captured(1);
|
||||||
|
@ -796,7 +797,7 @@ bool OpenMediaTimestamp(
|
||||||
const auto session = &controller->session();
|
const auto session = &controller->session();
|
||||||
const auto document = session->data().document(documentId);
|
const auto document = session->data().document(documentId);
|
||||||
const auto context = session->data().message(itemId);
|
const auto context = session->data().message(itemId);
|
||||||
const auto timeMs = time * crl::time(1000);
|
const auto time = position * crl::time(1000);
|
||||||
if (document->isVideoFile()) {
|
if (document->isVideoFile()) {
|
||||||
controller->window().openInMediaView(Media::View::OpenRequest(
|
controller->window().openInMediaView(Media::View::OpenRequest(
|
||||||
controller,
|
controller,
|
||||||
|
@ -804,11 +805,9 @@ bool OpenMediaTimestamp(
|
||||||
context,
|
context,
|
||||||
context ? context->topicRootId() : MsgId(0),
|
context ? context->topicRootId() : MsgId(0),
|
||||||
false,
|
false,
|
||||||
timeMs));
|
time));
|
||||||
} else if (document->isSong() || document->isVoiceMessage()) {
|
} else if (document->isSong() || document->isVoiceMessage()) {
|
||||||
session->settings().setMediaLastPlaybackPosition(
|
session->local().setMediaLastPlaybackPosition(documentId, time);
|
||||||
documentId,
|
|
||||||
timeMs);
|
|
||||||
Media::Player::instance()->play({ document, itemId });
|
Media::Player::instance()->play({ document, itemId });
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -58,6 +58,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_document_media.h"
|
#include "data/data_document_media.h"
|
||||||
#include "data/data_web_page.h"
|
#include "data/data_web_page.h"
|
||||||
|
#include "storage/storage_account.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
|
|
||||||
#include <QSvgRenderer>
|
#include <QSvgRenderer>
|
||||||
|
@ -406,11 +407,17 @@ bool Gif::downloadInCorner() const {
|
||||||
&& !_data->inappPlaybackFailed();
|
&& !_data->inappPlaybackFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Gif::autoplayUnderCursor() const {
|
||||||
|
return (_videoTimestamp || _hasVideoCover);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Gif::underCursor() const {
|
||||||
|
return ClickHandler::getActive() == currentVideoLink();
|
||||||
|
}
|
||||||
|
|
||||||
bool Gif::autoplayEnabled() const {
|
bool Gif::autoplayEnabled() const {
|
||||||
if (_realParent->isSponsored()) {
|
if (_realParent->isSponsored()) {
|
||||||
return true;
|
return true;
|
||||||
} else if (_videoTimestamp || _hasVideoCover) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return Data::AutoDownload::ShouldAutoPlay(
|
return Data::AutoDownload::ShouldAutoPlay(
|
||||||
_data->session().settings().autoDownload(),
|
_data->session().settings().autoDownload(),
|
||||||
|
@ -425,6 +432,8 @@ bool Gif::hideMessageText() const {
|
||||||
void Gif::draw(Painter &p, const PaintContext &context) const {
|
void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
|
|
||||||
|
_smallGroupPart = false;
|
||||||
|
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
const auto item = _parent->data();
|
const auto item = _parent->data();
|
||||||
const auto loaded = dataLoaded();
|
const auto loaded = dataLoaded();
|
||||||
|
@ -481,11 +490,14 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
validateSpoilerImageCache(rthumb.size(), rounding);
|
validateSpoilerImageCache(rthumb.size(), rounding);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto startPlay = autoplay
|
const auto canStartPlay = autoplay
|
||||||
&& !_streamed
|
&& !_streamed
|
||||||
&& !activeRoundPlaying
|
&& !activeRoundPlaying
|
||||||
&& !fullHiddenBySpoiler;
|
&& !fullHiddenBySpoiler;
|
||||||
if (startPlay) {
|
const auto shouldBePlaying = !autoplayUnderCursor() || underCursor();
|
||||||
|
if (!shouldBePlaying && _videoTimestamp != 0) {
|
||||||
|
const_cast<Gif*>(this)->stopAnimation();
|
||||||
|
} else if (canStartPlay) {
|
||||||
const_cast<Gif*>(this)->playAnimation(true);
|
const_cast<Gif*>(this)->playAnimation(true);
|
||||||
} else {
|
} else {
|
||||||
checkStreamedIsStarted();
|
checkStreamedIsStarted();
|
||||||
|
@ -526,8 +538,9 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
|
|
||||||
const auto skipDrawingContent = context.skipDrawingParts
|
const auto skipDrawingContent = context.skipDrawingParts
|
||||||
== PaintContext::SkipDrawingParts::Content;
|
== PaintContext::SkipDrawingParts::Content;
|
||||||
if (streamed && !skipDrawingContent && !fullHiddenBySpoiler) {
|
const auto drawStreamed = streamed && (shouldBePlaying || !_videoCover);
|
||||||
auto paused = context.paused;
|
if (drawStreamed && !skipDrawingContent && !fullHiddenBySpoiler) {
|
||||||
|
auto paused = context.paused || !shouldBePlaying;
|
||||||
auto request = ::Media::Streaming::FrameRequest{
|
auto request = ::Media::Streaming::FrameRequest{
|
||||||
.outer = QSize(usew, painth) * style::DevicePixelRatio(),
|
.outer = QSize(usew, painth) * style::DevicePixelRatio(),
|
||||||
.blurredBackground = true,
|
.blurredBackground = true,
|
||||||
|
@ -594,8 +607,8 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
validateThumbCache({ usew, painth }, isRound, rounding);
|
validateThumbCache({ usew, painth }, isRound, rounding);
|
||||||
p.drawImage(rthumb, _thumbCache);
|
p.drawImage(rthumb, _thumbCache);
|
||||||
paintTimestampMark(p, rthumb, rounding);
|
|
||||||
}
|
}
|
||||||
|
paintTimestampMark(p, rthumb, rounding);
|
||||||
|
|
||||||
if (revealed < 1.) {
|
if (revealed < 1.) {
|
||||||
p.setOpacity(1. - revealed);
|
p.setOpacity(1. - revealed);
|
||||||
|
@ -885,7 +898,7 @@ void Gif::paintTimestampMark(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
QRect rthumb,
|
QRect rthumb,
|
||||||
std::optional<Ui::BubbleRounding> rounding) const {
|
std::optional<Ui::BubbleRounding> rounding) const {
|
||||||
if (_videoTimestamp <= 0) {
|
if (_videoTimestamp <= 0 && _videoPosition < crl::time(200)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto convert = [](Ui::BubbleCornerRounding rounding) {
|
const auto convert = [](Ui::BubbleCornerRounding rounding) {
|
||||||
|
@ -902,15 +915,18 @@ void Gif::paintTimestampMark(
|
||||||
? convert(rounding->bottomRight)
|
? convert(rounding->bottomRight)
|
||||||
: st::roundRadiusSmall;
|
: st::roundRadiusSmall;
|
||||||
const auto line = st::historyVideoTimestampProgressLine;
|
const auto line = st::historyVideoTimestampProgressLine;
|
||||||
const auto duration = _data->duration() / 1000;
|
const auto duration = _data->duration();
|
||||||
|
const auto position = (_videoPosition > 0)
|
||||||
|
? _videoPosition
|
||||||
|
: (_videoTimestamp * crl::time(1000));
|
||||||
if (rthumb.height() <= line
|
if (rthumb.height() <= line
|
||||||
|| rthumb.width() <= radiusl + radiusr
|
|| rthumb.width() <= radiusl + radiusr
|
||||||
|| _videoTimestamp >= duration) {
|
|| position > duration) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto hq = PainterHighQualityEnabler(p);
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
const auto used = rthumb.width() - radiusl - radiusr;
|
const auto used = rthumb.width() - radiusl - radiusr;
|
||||||
const auto progress = _videoTimestamp / float64(duration);
|
const auto progress = position / float64(duration);
|
||||||
const auto edge = radiusl + int(base::SafeRound(used * progress));
|
const auto edge = radiusl + int(base::SafeRound(used * progress));
|
||||||
const auto top = rthumb.y() + rthumb.height() - line;
|
const auto top = rthumb.y() + rthumb.height() - line;
|
||||||
p.save();
|
p.save();
|
||||||
|
@ -1278,15 +1294,7 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
|
||||||
: (isRound && _parent->data()->media()->ttlSeconds())
|
: (isRound && _parent->data()->media()->ttlSeconds())
|
||||||
? _openl // Overriden.
|
? _openl // Overriden.
|
||||||
: _spoiler->link)
|
: _spoiler->link)
|
||||||
: _data->uploading()
|
: currentVideoLink();
|
||||||
? _cancell
|
|
||||||
: _realParent->isSending()
|
|
||||||
? nullptr
|
|
||||||
: (dataLoaded() || _dataMedia->canBePlayed(_realParent))
|
|
||||||
? _openl
|
|
||||||
: _data->loading()
|
|
||||||
? _cancell
|
|
||||||
: _savel;
|
|
||||||
}
|
}
|
||||||
const auto checkBottomInfo = !inWebPage
|
const auto checkBottomInfo = !inWebPage
|
||||||
&& (unwrapped || !bubble || isBubbleBottom());
|
&& (unwrapped || !bubble || isBubbleBottom());
|
||||||
|
@ -1394,8 +1402,8 @@ void Gif::drawGrouped(
|
||||||
|| _data->displayLoading();
|
|| _data->displayLoading();
|
||||||
const auto st = context.st;
|
const auto st = context.st;
|
||||||
const auto sti = context.imageStyle();
|
const auto sti = context.imageStyle();
|
||||||
const auto fullFeatured = fullFeaturedGrouped(sides);
|
_smallGroupPart = !fullFeaturedGrouped(sides);
|
||||||
const auto cornerDownload = fullFeatured && downloadInCorner();
|
const auto cornerDownload = !_smallGroupPart && downloadInCorner();
|
||||||
const auto canBePlayed = _dataMedia->canBePlayed(_realParent);
|
const auto canBePlayed = _dataMedia->canBePlayed(_realParent);
|
||||||
|
|
||||||
const auto revealed = _spoiler
|
const auto revealed = _spoiler
|
||||||
|
@ -1406,16 +1414,22 @@ void Gif::drawGrouped(
|
||||||
validateSpoilerImageCache(geometry.size(), rounding);
|
validateSpoilerImageCache(geometry.size(), rounding);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto autoplay = fullFeatured
|
const auto autoplay = !_smallGroupPart
|
||||||
&& autoplayEnabled()
|
&& autoplayEnabled()
|
||||||
&& canBePlayed
|
&& canBePlayed
|
||||||
&& CanPlayInline(_data);
|
&& CanPlayInline(_data);
|
||||||
const auto startPlay = autoplay && !_streamed;
|
const auto canStartPlay = autoplay
|
||||||
if (startPlay) {
|
&& !_streamed
|
||||||
|
&& !fullHiddenBySpoiler;
|
||||||
|
const auto shouldBePlaying = !autoplayUnderCursor() || underCursor();
|
||||||
|
if (!shouldBePlaying && _videoTimestamp != 0) {
|
||||||
|
const_cast<Gif*>(this)->stopAnimation();
|
||||||
|
} else if (canStartPlay) {
|
||||||
const_cast<Gif*>(this)->playAnimation(true);
|
const_cast<Gif*>(this)->playAnimation(true);
|
||||||
} else {
|
} else {
|
||||||
checkStreamedIsStarted();
|
checkStreamedIsStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto streamingMode = _streamed || autoplay;
|
const auto streamingMode = _streamed || autoplay;
|
||||||
const auto activeOwnPlaying = activeOwnStreamed();
|
const auto activeOwnPlaying = activeOwnStreamed();
|
||||||
|
|
||||||
|
@ -1468,7 +1482,9 @@ void Gif::drawGrouped(
|
||||||
activeOwnPlaying->frozenStatusText = QString();
|
activeOwnPlaying->frozenStatusText = QString();
|
||||||
}
|
}
|
||||||
p.drawImage(geometry, streamed->frame(request));
|
p.drawImage(geometry, streamed->frame(request));
|
||||||
if (!context.paused) {
|
const auto paused = context.paused
|
||||||
|
|| (autoplayUnderCursor() && !underCursor());
|
||||||
|
if (!paused) {
|
||||||
streamed->markFrameShown();
|
streamed->markFrameShown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1583,7 +1599,7 @@ void Gif::drawGrouped(
|
||||||
}
|
}
|
||||||
p.setOpacity(1.);
|
p.setOpacity(1.);
|
||||||
}
|
}
|
||||||
if (fullFeatured) {
|
if (!_smallGroupPart) {
|
||||||
drawCornerStatus(p, context, geometry.topLeft());
|
drawCornerStatus(p, context, geometry.topLeft());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1596,8 +1612,7 @@ TextState Gif::getStateGrouped(
|
||||||
if (!geometry.contains(point)) {
|
if (!geometry.contains(point)) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const auto isFullFeaturedGrouped = fullFeaturedGrouped(sides);
|
if (!_smallGroupPart) {
|
||||||
if (isFullFeaturedGrouped) {
|
|
||||||
const auto state = cornerStatusTextState(
|
const auto state = cornerStatusTextState(
|
||||||
point,
|
point,
|
||||||
request,
|
request,
|
||||||
|
@ -1607,20 +1622,27 @@ TextState Gif::getStateGrouped(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
|
|
||||||
auto link = (_spoiler && !_spoiler->revealed)
|
auto link = (_spoiler && !_spoiler->revealed)
|
||||||
? (_sensitiveSpoiler ? spoilerTagLink() : _spoiler->link)
|
? (_sensitiveSpoiler ? spoilerTagLink() : _spoiler->link)
|
||||||
: _data->uploading()
|
: currentVideoLink();
|
||||||
|
return TextState(_parent, std::move(link));
|
||||||
|
}
|
||||||
|
|
||||||
|
ClickHandlerPtr Gif::currentVideoLink() const {
|
||||||
|
return _data->uploading()
|
||||||
? _cancell
|
? _cancell
|
||||||
: _realParent->isSending()
|
: _realParent->isSending()
|
||||||
? nullptr
|
? nullptr
|
||||||
: dataLoaded()
|
: dataLoaded()
|
||||||
? _openl
|
? _openl
|
||||||
: (_data->loading() && !isFullFeaturedGrouped)
|
: (_data->loading() && _smallGroupPart)
|
||||||
? _cancell
|
? _cancell
|
||||||
: _dataMedia->canBePlayed(_realParent)
|
: _dataMedia->canBePlayed(_realParent)
|
||||||
? _openl
|
? _openl
|
||||||
|
: _data->loading()
|
||||||
|
? _cancell
|
||||||
: _savel;
|
: _savel;
|
||||||
return TextState(_parent, std::move(link));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gif::ensureDataMediaCreated() const {
|
void Gif::ensureDataMediaCreated() const {
|
||||||
|
@ -1859,7 +1881,8 @@ void Gif::updateStatusText() const {
|
||||||
}
|
}
|
||||||
const auto round = activeRoundStreamed();
|
const auto round = activeRoundStreamed();
|
||||||
const auto own = activeOwnStreamed();
|
const auto own = activeOwnStreamed();
|
||||||
if (round || (own && own->frozenFrame.isNull() && _data->isVideoFile())) {
|
if (round || (own && _data->isVideoFile())) {
|
||||||
|
const auto frozen = !own->frozenFrame.isNull();
|
||||||
const auto streamed = round ? round : &own->instance;
|
const auto streamed = round ? round : &own->instance;
|
||||||
const auto state = streamed->player().prepareLegacyState();
|
const auto state = streamed->player().prepareLegacyState();
|
||||||
if (state.length) {
|
if (state.length) {
|
||||||
|
@ -1869,9 +1892,17 @@ void Gif::updateStatusText() const {
|
||||||
} else if (!::Media::Player::IsStoppedOrStopping(state.state)) {
|
} else if (!::Media::Player::IsStoppedOrStopping(state.state)) {
|
||||||
position = state.position;
|
position = state.position;
|
||||||
}
|
}
|
||||||
statusSize = -1 - int((state.length - position) / state.frequency + 1);
|
if (!frozen) {
|
||||||
|
statusSize = -1 - int((state.length - position) / state.frequency + 1);
|
||||||
|
}
|
||||||
|
_videoPosition = std::max(
|
||||||
|
position * crl::time(1000) / state.frequency,
|
||||||
|
crl::time(1));
|
||||||
} else {
|
} else {
|
||||||
statusSize = -1 - (_data->duration() / 1000);
|
if (!frozen) {
|
||||||
|
statusSize = -1 - (_data->duration() / 1000);
|
||||||
|
}
|
||||||
|
_videoPosition = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (statusSize != _statusSize) {
|
if (statusSize != _statusSize) {
|
||||||
|
@ -2031,6 +2062,10 @@ void Gif::startStreamedPlayer() const {
|
||||||
//if (!_streamed->withSound) {
|
//if (!_streamed->withSound) {
|
||||||
options.mode = ::Media::Streaming::Mode::Video;
|
options.mode = ::Media::Streaming::Mode::Video;
|
||||||
options.loop = true;
|
options.loop = true;
|
||||||
|
options.position = _videoTimestamp
|
||||||
|
? (_videoTimestamp * crl::time(1000))
|
||||||
|
: _parent->history()->session().local().mediaLastPlaybackPosition(
|
||||||
|
_data->id);
|
||||||
//}
|
//}
|
||||||
_streamed->instance.play(options);
|
_streamed->instance.play(options);
|
||||||
}
|
}
|
||||||
|
@ -2038,10 +2073,12 @@ void Gif::startStreamedPlayer() const {
|
||||||
void Gif::checkStreamedIsStarted() const {
|
void Gif::checkStreamedIsStarted() const {
|
||||||
if (!_streamed || _streamed->instance.playerLocked()) {
|
if (!_streamed || _streamed->instance.playerLocked()) {
|
||||||
return;
|
return;
|
||||||
} else if (_streamed->instance.paused()) {
|
|
||||||
_streamed->instance.resume();
|
|
||||||
}
|
}
|
||||||
if (!_streamed->instance.active() && !_streamed->instance.failed()) {
|
if (_streamed->instance.active()) {
|
||||||
|
if (_streamed->instance.paused()) {
|
||||||
|
_streamed->instance.resume();
|
||||||
|
}
|
||||||
|
} else if (!_streamed->instance.failed()) {
|
||||||
startStreamedPlayer();
|
startStreamedPlayer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2054,6 +2091,7 @@ void Gif::setStreamed(std::unique_ptr<Streamed> value) {
|
||||||
history()->owner().registerHeavyViewPart(_parent);
|
history()->owner().registerHeavyViewPart(_parent);
|
||||||
togglePollingStory(true);
|
togglePollingStory(true);
|
||||||
} else if (removed) {
|
} else if (removed) {
|
||||||
|
_videoPosition = 0;
|
||||||
_parent->checkHeavyPart();
|
_parent->checkHeavyPart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,8 @@ private:
|
||||||
void dataMediaCreated() const;
|
void dataMediaCreated() const;
|
||||||
|
|
||||||
[[nodiscard]] bool autoplayEnabled() const;
|
[[nodiscard]] bool autoplayEnabled() const;
|
||||||
|
[[nodiscard]] bool autoplayUnderCursor() const;
|
||||||
|
[[nodiscard]] bool underCursor() const;
|
||||||
|
|
||||||
void playAnimation(bool autoplay) override;
|
void playAnimation(bool autoplay) override;
|
||||||
QSize countOptimalSize() override;
|
QSize countOptimalSize() override;
|
||||||
|
@ -210,6 +212,7 @@ private:
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request,
|
StateRequest request,
|
||||||
QPoint position) const;
|
QPoint position) const;
|
||||||
|
[[nodiscard]] ClickHandlerPtr currentVideoLink() const;
|
||||||
|
|
||||||
void togglePollingStory(bool enabled) const;
|
void togglePollingStory(bool enabled) const;
|
||||||
|
|
||||||
|
@ -228,12 +231,14 @@ private:
|
||||||
QString _downloadSize;
|
QString _downloadSize;
|
||||||
mutable QImage _thumbCache;
|
mutable QImage _thumbCache;
|
||||||
mutable QImage _roundingMask;
|
mutable QImage _roundingMask;
|
||||||
|
mutable crl::time _videoPosition = 0;
|
||||||
mutable TimeId _videoTimestamp = 0;
|
mutable TimeId _videoTimestamp = 0;
|
||||||
mutable std::optional<Ui::BubbleRounding> _thumbCacheRounding;
|
mutable std::optional<Ui::BubbleRounding> _thumbCacheRounding;
|
||||||
mutable bool _thumbCacheBlurred : 1 = false;
|
mutable bool _thumbCacheBlurred : 1 = false;
|
||||||
mutable bool _thumbIsEllipse : 1 = false;
|
mutable bool _thumbIsEllipse : 1 = false;
|
||||||
mutable bool _pollingStory : 1 = false;
|
mutable bool _pollingStory : 1 = false;
|
||||||
mutable bool _purchasedPriceTag : 1 = false;
|
mutable bool _purchasedPriceTag : 1 = false;
|
||||||
|
mutable bool _smallGroupPart : 1 = false;
|
||||||
const bool _sensitiveSpoiler : 1 = false;
|
const bool _sensitiveSpoiler : 1 = false;
|
||||||
const bool _hasVideoCover : 1 = false;
|
const bool _hasVideoCover : 1 = false;
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ namespace {
|
||||||
constexpr auto kLegacyCallsPeerToPeerNobody = 4;
|
constexpr auto kLegacyCallsPeerToPeerNobody = 4;
|
||||||
constexpr auto kVersionTag = -1;
|
constexpr auto kVersionTag = -1;
|
||||||
constexpr auto kVersion = 2;
|
constexpr auto kVersion = 2;
|
||||||
constexpr auto kMaxSavedPlaybackPositions = 16;
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -38,8 +37,7 @@ QByteArray SessionSettings::serialize() const {
|
||||||
+ _groupStickersSectionHidden.size() * sizeof(quint64)
|
+ _groupStickersSectionHidden.size() * sizeof(quint64)
|
||||||
+ sizeof(qint32) * 4
|
+ sizeof(qint32) * 4
|
||||||
+ Serialize::bytearraySize(autoDownload)
|
+ Serialize::bytearraySize(autoDownload)
|
||||||
+ sizeof(qint32) * 5
|
+ sizeof(qint32) * 4
|
||||||
+ _mediaLastPlaybackPosition.size() * 2 * sizeof(quint64)
|
|
||||||
+ sizeof(qint32) * 5
|
+ sizeof(qint32) * 5
|
||||||
+ sizeof(qint32)
|
+ sizeof(qint32)
|
||||||
+ (_mutePeriods.size() * sizeof(quint64))
|
+ (_mutePeriods.size() * sizeof(quint64))
|
||||||
|
@ -71,11 +69,6 @@ QByteArray SessionSettings::serialize() const {
|
||||||
<< qint32(_archiveCollapsed.current() ? 1 : 0)
|
<< qint32(_archiveCollapsed.current() ? 1 : 0)
|
||||||
<< qint32(_archiveInMainMenu.current() ? 1 : 0)
|
<< qint32(_archiveInMainMenu.current() ? 1 : 0)
|
||||||
<< qint32(_skipArchiveInSearch.current() ? 1 : 0)
|
<< qint32(_skipArchiveInSearch.current() ? 1 : 0)
|
||||||
<< qint32(_mediaLastPlaybackPosition.size());
|
|
||||||
for (const auto &[id, time] : _mediaLastPlaybackPosition) {
|
|
||||||
stream << quint64(id) << qint64(time);
|
|
||||||
}
|
|
||||||
stream
|
|
||||||
<< qint32(0) // very old _hiddenPinnedMessages.size());
|
<< qint32(0) // very old _hiddenPinnedMessages.size());
|
||||||
<< qint32(_dialogsFiltersEnabled ? 1 : 0)
|
<< qint32(_dialogsFiltersEnabled ? 1 : 0)
|
||||||
<< qint32(_supportAllSilent ? 1 : 0)
|
<< qint32(_supportAllSilent ? 1 : 0)
|
||||||
|
@ -156,7 +149,6 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
|
||||||
qint32 appSuggestEmoji = app.suggestEmoji() ? 1 : 0;
|
qint32 appSuggestEmoji = app.suggestEmoji() ? 1 : 0;
|
||||||
qint32 appSuggestStickersByEmoji = app.suggestStickersByEmoji() ? 1 : 0;
|
qint32 appSuggestStickersByEmoji = app.suggestStickersByEmoji() ? 1 : 0;
|
||||||
qint32 appSpellcheckerEnabled = app.spellcheckerEnabled() ? 1 : 0;
|
qint32 appSpellcheckerEnabled = app.spellcheckerEnabled() ? 1 : 0;
|
||||||
std::vector<std::pair<DocumentId, crl::time>> mediaLastPlaybackPosition;
|
|
||||||
qint32 appVideoPlaybackSpeed = app.videoPlaybackSpeedSerialized();
|
qint32 appVideoPlaybackSpeed = app.videoPlaybackSpeedSerialized();
|
||||||
QByteArray appVideoPipGeometry = app.videoPipGeometry();
|
QByteArray appVideoPipGeometry = app.videoPipGeometry();
|
||||||
std::vector<int> appDictionariesEnabled;
|
std::vector<int> appDictionariesEnabled;
|
||||||
|
@ -313,7 +305,7 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
|
||||||
"Bad data for SessionSettings::addFromSerialized()"));
|
"Bad data for SessionSettings::addFromSerialized()"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mediaLastPlaybackPosition.emplace_back(documentId, time);
|
// Old mediaLastPlaybackPosition.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,7 +478,6 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
|
||||||
_archiveCollapsed = (archiveCollapsed == 1);
|
_archiveCollapsed = (archiveCollapsed == 1);
|
||||||
_archiveInMainMenu = (archiveInMainMenu == 1);
|
_archiveInMainMenu = (archiveInMainMenu == 1);
|
||||||
_skipArchiveInSearch = (skipArchiveInSearch == 1);
|
_skipArchiveInSearch = (skipArchiveInSearch == 1);
|
||||||
_mediaLastPlaybackPosition = std::move(mediaLastPlaybackPosition);
|
|
||||||
_hiddenPinnedMessages = std::move(hiddenPinnedMessages);
|
_hiddenPinnedMessages = std::move(hiddenPinnedMessages);
|
||||||
_dialogsFiltersEnabled = (dialogsFiltersEnabled == 1);
|
_dialogsFiltersEnabled = (dialogsFiltersEnabled == 1);
|
||||||
_supportAllSilent = (supportAllSilent == 1);
|
_supportAllSilent = (supportAllSilent == 1);
|
||||||
|
@ -567,34 +558,6 @@ rpl::producer<bool> SessionSettings::supportAllSearchResultsValue() const {
|
||||||
return _supportAllSearchResults.value();
|
return _supportAllSearchResults.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionSettings::setMediaLastPlaybackPosition(DocumentId id, crl::time time) {
|
|
||||||
auto &map = _mediaLastPlaybackPosition;
|
|
||||||
const auto i = ranges::find(
|
|
||||||
map,
|
|
||||||
id,
|
|
||||||
&std::pair<DocumentId, crl::time>::first);
|
|
||||||
if (i != map.end()) {
|
|
||||||
if (time > 0) {
|
|
||||||
i->second = time;
|
|
||||||
} else {
|
|
||||||
map.erase(i);
|
|
||||||
}
|
|
||||||
} else if (time > 0) {
|
|
||||||
if (map.size() >= kMaxSavedPlaybackPositions) {
|
|
||||||
map.erase(map.begin());
|
|
||||||
}
|
|
||||||
map.emplace_back(id, time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crl::time SessionSettings::mediaLastPlaybackPosition(DocumentId id) const {
|
|
||||||
const auto i = ranges::find(
|
|
||||||
_mediaLastPlaybackPosition,
|
|
||||||
id,
|
|
||||||
&std::pair<DocumentId, crl::time>::first);
|
|
||||||
return (i != _mediaLastPlaybackPosition.end()) ? i->second : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SessionSettings::setArchiveCollapsed(bool collapsed) {
|
void SessionSettings::setArchiveCollapsed(bool collapsed) {
|
||||||
_archiveCollapsed = collapsed;
|
_archiveCollapsed = collapsed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,9 +85,6 @@ public:
|
||||||
_groupEmojiSectionHidden.remove(peerId);
|
_groupEmojiSectionHidden.remove(peerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMediaLastPlaybackPosition(DocumentId id, crl::time time);
|
|
||||||
[[nodiscard]] crl::time mediaLastPlaybackPosition(DocumentId id) const;
|
|
||||||
|
|
||||||
[[nodiscard]] Data::AutoDownload::Full &autoDownload() {
|
[[nodiscard]] Data::AutoDownload::Full &autoDownload() {
|
||||||
return _autoDownload;
|
return _autoDownload;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +163,6 @@ private:
|
||||||
rpl::variable<bool> _archiveCollapsed = false;
|
rpl::variable<bool> _archiveCollapsed = false;
|
||||||
rpl::variable<bool> _archiveInMainMenu = false;
|
rpl::variable<bool> _archiveInMainMenu = false;
|
||||||
rpl::variable<bool> _skipArchiveInSearch = false;
|
rpl::variable<bool> _skipArchiveInSearch = false;
|
||||||
std::vector<std::pair<DocumentId, crl::time>> _mediaLastPlaybackPosition;
|
|
||||||
base::flat_map<ThreadId, MsgId> _hiddenPinnedMessages;
|
base::flat_map<ThreadId, MsgId> _hiddenPinnedMessages;
|
||||||
bool _dialogsFiltersEnabled = false;
|
bool _dialogsFiltersEnabled = false;
|
||||||
int _photoEditorHintShowsCount = 0;
|
int _photoEditorHintShowsCount = 0;
|
||||||
|
|
|
@ -34,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "main/main_account.h" // session->account().sessionChanges().
|
#include "main/main_account.h" // session->account().sessionChanges().
|
||||||
#include "main/main_session_settings.h"
|
#include "main/main_session_settings.h"
|
||||||
|
#include "storage/storage_account.h"
|
||||||
|
|
||||||
namespace Media {
|
namespace Media {
|
||||||
namespace Player {
|
namespace Player {
|
||||||
|
@ -50,7 +51,8 @@ constexpr auto kIdsPreloadAfter = 28;
|
||||||
constexpr auto kShufflePlaylistLimit = 10'000;
|
constexpr auto kShufflePlaylistLimit = 10'000;
|
||||||
constexpr auto kRememberShuffledOrderItems = 16;
|
constexpr auto kRememberShuffledOrderItems = 16;
|
||||||
|
|
||||||
constexpr auto kMinLengthForSavePosition = 20 * TimeId(60); // 20 minutes.
|
constexpr auto kMinLengthForSavePositionVideo = TimeId(60); // 1 minute.
|
||||||
|
constexpr auto kMinLengthForSavePositionMusic = 20 * TimeId(60); // 20.
|
||||||
|
|
||||||
base::options::toggle OptionDisableAutoplayNext({
|
base::options::toggle OptionDisableAutoplayNext({
|
||||||
.id = kOptionDisableAutoplayNext,
|
.id = kOptionDisableAutoplayNext,
|
||||||
|
@ -108,18 +110,20 @@ void finish(not_null<Audio::Instance*> instance) {
|
||||||
void SaveLastPlaybackPosition(
|
void SaveLastPlaybackPosition(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
const TrackState &state) {
|
const TrackState &state) {
|
||||||
|
const auto limit = document->isVideoFile()
|
||||||
|
? kMinLengthForSavePositionVideo
|
||||||
|
: kMinLengthForSavePositionMusic;
|
||||||
const auto time = (state.position == kTimeUnknown
|
const auto time = (state.position == kTimeUnknown
|
||||||
|| state.length == kTimeUnknown
|
|| state.length == kTimeUnknown
|
||||||
|| state.state == State::PausedAtEnd
|
|| state.state == State::PausedAtEnd
|
||||||
|| IsStopped(state.state))
|
|| IsStopped(state.state))
|
||||||
? TimeId(0)
|
? TimeId(0)
|
||||||
: (state.length >= kMinLengthForSavePosition * state.frequency)
|
: (state.length >= limit * state.frequency)
|
||||||
? (state.position / state.frequency) * crl::time(1000)
|
? (state.position / state.frequency) * crl::time(1000)
|
||||||
: TimeId(0);
|
: TimeId(0);
|
||||||
auto &session = document->session();
|
auto &session = document->session();
|
||||||
if (session.settings().mediaLastPlaybackPosition(document->id) != time) {
|
if (session.local().mediaLastPlaybackPosition(document->id) != time) {
|
||||||
session.settings().setMediaLastPlaybackPosition(document->id, time);
|
session.local().setMediaLastPlaybackPosition(document->id, time);
|
||||||
session.saveSettingsDelayed();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,9 +853,9 @@ Streaming::PlaybackOptions Instance::streamingOptions(
|
||||||
if (position >= 0) {
|
if (position >= 0) {
|
||||||
result.position = position;
|
result.position = position;
|
||||||
} else if (document) {
|
} else if (document) {
|
||||||
auto &settings = document->session().settings();
|
auto &local = document->session().local();
|
||||||
result.position = settings.mediaLastPlaybackPosition(document->id);
|
result.position = local.mediaLastPlaybackPosition(document->id);
|
||||||
settings.setMediaLastPlaybackPosition(document->id, 0);
|
local.setMediaLastPlaybackPosition(document->id, 0);
|
||||||
} else {
|
} else {
|
||||||
result.position = 0;
|
result.position = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ using Database = Cache::Database;
|
||||||
|
|
||||||
constexpr auto kDelayedWriteTimeout = crl::time(1000);
|
constexpr auto kDelayedWriteTimeout = crl::time(1000);
|
||||||
constexpr auto kWriteSearchSuggestionsDelay = 5 * crl::time(1000);
|
constexpr auto kWriteSearchSuggestionsDelay = 5 * crl::time(1000);
|
||||||
|
constexpr auto kMaxSavedPlaybackPositions = 256;
|
||||||
|
|
||||||
constexpr auto kStickersVersionTag = quint32(-1);
|
constexpr auto kStickersVersionTag = quint32(-1);
|
||||||
constexpr auto kStickersSerializeVersion = 4;
|
constexpr auto kStickersSerializeVersion = 4;
|
||||||
|
@ -96,6 +97,7 @@ enum { // Local Storage Keys
|
||||||
lskWebviewTokens = 0x19, // data: QByteArray bots, QByteArray other
|
lskWebviewTokens = 0x19, // data: QByteArray bots, QByteArray other
|
||||||
lskRoundPlaceholder = 0x1a, // no data
|
lskRoundPlaceholder = 0x1a, // no data
|
||||||
lskInlineBotsDownloads = 0x1b, // no data
|
lskInlineBotsDownloads = 0x1b, // no data
|
||||||
|
lskMediaLastPlaybackPositions = 0x1c, // no data
|
||||||
};
|
};
|
||||||
|
|
||||||
auto EmptyMessageDraftSources()
|
auto EmptyMessageDraftSources()
|
||||||
|
@ -228,6 +230,7 @@ base::flat_set<QString> Account::collectGoodNames() const {
|
||||||
_searchSuggestionsKey,
|
_searchSuggestionsKey,
|
||||||
_roundPlaceholderKey,
|
_roundPlaceholderKey,
|
||||||
_inlineBotsDownloadsKey,
|
_inlineBotsDownloadsKey,
|
||||||
|
_mediaLastPlaybackPositionsKey,
|
||||||
};
|
};
|
||||||
auto result = base::flat_set<QString>{
|
auto result = base::flat_set<QString>{
|
||||||
"map0",
|
"map0",
|
||||||
|
@ -316,6 +319,7 @@ Account::ReadMapResult Account::readMapWith(
|
||||||
quint64 searchSuggestionsKey = 0;
|
quint64 searchSuggestionsKey = 0;
|
||||||
quint64 roundPlaceholderKey = 0;
|
quint64 roundPlaceholderKey = 0;
|
||||||
quint64 inlineBotsDownloadsKey = 0;
|
quint64 inlineBotsDownloadsKey = 0;
|
||||||
|
quint64 mediaLastPlaybackPositionsKey = 0;
|
||||||
QByteArray webviewStorageTokenBots, webviewStorageTokenOther;
|
QByteArray webviewStorageTokenBots, webviewStorageTokenOther;
|
||||||
while (!map.stream.atEnd()) {
|
while (!map.stream.atEnd()) {
|
||||||
quint32 keyType;
|
quint32 keyType;
|
||||||
|
@ -431,6 +435,9 @@ Account::ReadMapResult Account::readMapWith(
|
||||||
case lskInlineBotsDownloads: {
|
case lskInlineBotsDownloads: {
|
||||||
map.stream >> inlineBotsDownloadsKey;
|
map.stream >> inlineBotsDownloadsKey;
|
||||||
} break;
|
} break;
|
||||||
|
case lskMediaLastPlaybackPositions: {
|
||||||
|
map.stream >> mediaLastPlaybackPositionsKey;
|
||||||
|
} break;
|
||||||
case lskWebviewTokens: {
|
case lskWebviewTokens: {
|
||||||
map.stream
|
map.stream
|
||||||
>> webviewStorageTokenBots
|
>> webviewStorageTokenBots
|
||||||
|
@ -474,6 +481,7 @@ Account::ReadMapResult Account::readMapWith(
|
||||||
_searchSuggestionsKey = searchSuggestionsKey;
|
_searchSuggestionsKey = searchSuggestionsKey;
|
||||||
_roundPlaceholderKey = roundPlaceholderKey;
|
_roundPlaceholderKey = roundPlaceholderKey;
|
||||||
_inlineBotsDownloadsKey = inlineBotsDownloadsKey;
|
_inlineBotsDownloadsKey = inlineBotsDownloadsKey;
|
||||||
|
_mediaLastPlaybackPositionsKey = mediaLastPlaybackPositionsKey;
|
||||||
_oldMapVersion = mapData.version;
|
_oldMapVersion = mapData.version;
|
||||||
_webviewStorageIdBots.token = webviewStorageTokenBots;
|
_webviewStorageIdBots.token = webviewStorageTokenBots;
|
||||||
_webviewStorageIdOther.token = webviewStorageTokenOther;
|
_webviewStorageIdOther.token = webviewStorageTokenOther;
|
||||||
|
@ -590,6 +598,7 @@ void Account::writeMap() {
|
||||||
}
|
}
|
||||||
if (_roundPlaceholderKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_roundPlaceholderKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
if (_inlineBotsDownloadsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_inlineBotsDownloadsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
|
if (_mediaLastPlaybackPositionsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
|
|
||||||
EncryptedDescriptor mapData(mapSize);
|
EncryptedDescriptor mapData(mapSize);
|
||||||
if (!self.isEmpty()) {
|
if (!self.isEmpty()) {
|
||||||
|
@ -668,6 +677,10 @@ void Account::writeMap() {
|
||||||
mapData.stream << quint32(lskInlineBotsDownloads);
|
mapData.stream << quint32(lskInlineBotsDownloads);
|
||||||
mapData.stream << quint64(_inlineBotsDownloadsKey);
|
mapData.stream << quint64(_inlineBotsDownloadsKey);
|
||||||
}
|
}
|
||||||
|
if (_mediaLastPlaybackPositionsKey) {
|
||||||
|
mapData.stream << quint32(lskMediaLastPlaybackPositions);
|
||||||
|
mapData.stream << quint64(_mediaLastPlaybackPositionsKey);
|
||||||
|
}
|
||||||
map.writeEncrypted(mapData, _localKey);
|
map.writeEncrypted(mapData, _localKey);
|
||||||
|
|
||||||
_mapChanged = false;
|
_mapChanged = false;
|
||||||
|
@ -699,6 +712,7 @@ void Account::reset() {
|
||||||
_searchSuggestionsKey = 0;
|
_searchSuggestionsKey = 0;
|
||||||
_roundPlaceholderKey = 0;
|
_roundPlaceholderKey = 0;
|
||||||
_inlineBotsDownloadsKey = 0;
|
_inlineBotsDownloadsKey = 0;
|
||||||
|
_mediaLastPlaybackPositionsKey = 0;
|
||||||
_oldMapVersion = 0;
|
_oldMapVersion = 0;
|
||||||
_fileLocations.clear();
|
_fileLocations.clear();
|
||||||
_fileLocationPairs.clear();
|
_fileLocationPairs.clear();
|
||||||
|
@ -709,6 +723,7 @@ void Account::reset() {
|
||||||
_cacheTotalTimeLimit = Database::Settings().totalTimeLimit;
|
_cacheTotalTimeLimit = Database::Settings().totalTimeLimit;
|
||||||
_cacheBigFileTotalSizeLimit = Database::Settings().totalSizeLimit;
|
_cacheBigFileTotalSizeLimit = Database::Settings().totalSizeLimit;
|
||||||
_cacheBigFileTotalTimeLimit = Database::Settings().totalTimeLimit;
|
_cacheBigFileTotalTimeLimit = Database::Settings().totalTimeLimit;
|
||||||
|
_mediaLastPlaybackPosition.clear();
|
||||||
|
|
||||||
const auto wvbots = _webviewStorageIdBots.path;
|
const auto wvbots = _webviewStorageIdBots.path;
|
||||||
const auto wvother = _webviewStorageIdOther.path;
|
const auto wvother = _webviewStorageIdOther.path;
|
||||||
|
@ -2943,6 +2958,96 @@ Export::Settings Account::readExportSettings() {
|
||||||
: Export::Settings();
|
: Export::Settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Account::setMediaLastPlaybackPosition(DocumentId id, crl::time time) {
|
||||||
|
auto &map = _mediaLastPlaybackPosition;
|
||||||
|
const auto i = ranges::find(
|
||||||
|
map,
|
||||||
|
id,
|
||||||
|
&std::pair<DocumentId, crl::time>::first);
|
||||||
|
if (i != map.end()) {
|
||||||
|
if (time > 0) {
|
||||||
|
if (i->second == time) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i->second = time;
|
||||||
|
std::rotate(i, i + 1, map.end());
|
||||||
|
} else {
|
||||||
|
map.erase(i);
|
||||||
|
}
|
||||||
|
} else if (time > 0) {
|
||||||
|
if (map.size() >= kMaxSavedPlaybackPositions) {
|
||||||
|
map.erase(map.begin());
|
||||||
|
}
|
||||||
|
map.emplace_back(id, time);
|
||||||
|
}
|
||||||
|
writeMediaLastPlaybackPositions();
|
||||||
|
}
|
||||||
|
|
||||||
|
crl::time Account::mediaLastPlaybackPosition(DocumentId id) const {
|
||||||
|
const_cast<Account*>(this)->readMediaLastPlaybackPositions();
|
||||||
|
const auto i = ranges::find(
|
||||||
|
_mediaLastPlaybackPosition,
|
||||||
|
id,
|
||||||
|
&std::pair<DocumentId, crl::time>::first);
|
||||||
|
return (i != _mediaLastPlaybackPosition.end()) ? i->second : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Account::writeMediaLastPlaybackPositions() {
|
||||||
|
if (_mediaLastPlaybackPosition.empty()) {
|
||||||
|
if (_mediaLastPlaybackPositionsKey) {
|
||||||
|
ClearKey(_mediaLastPlaybackPositionsKey, _basePath);
|
||||||
|
_mediaLastPlaybackPositionsKey = 0;
|
||||||
|
writeMapDelayed();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!_mediaLastPlaybackPositionsKey) {
|
||||||
|
_mediaLastPlaybackPositionsKey = GenerateKey(_basePath);
|
||||||
|
writeMapQueued();
|
||||||
|
}
|
||||||
|
quint32 size = sizeof(quint32)
|
||||||
|
+ _mediaLastPlaybackPosition.size() * sizeof(quint64) * 2;
|
||||||
|
EncryptedDescriptor data(size);
|
||||||
|
data.stream << quint32(_mediaLastPlaybackPosition.size());
|
||||||
|
for (const auto &[id, time] : _mediaLastPlaybackPosition) {
|
||||||
|
data.stream << quint64(id) << qint64(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileWriteDescriptor file(_mediaLastPlaybackPositionsKey, _basePath);
|
||||||
|
file.writeEncrypted(data, _localKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Account::readMediaLastPlaybackPositions() {
|
||||||
|
if (_mediaLastPlaybackPositionsRead) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_mediaLastPlaybackPositionsRead = true;
|
||||||
|
if (!_mediaLastPlaybackPositionsKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileReadDescriptor file;
|
||||||
|
if (!ReadEncryptedFile(
|
||||||
|
file,
|
||||||
|
_mediaLastPlaybackPositionsKey,
|
||||||
|
_basePath,
|
||||||
|
_localKey)) {
|
||||||
|
ClearKey(_mediaLastPlaybackPositionsKey, _basePath);
|
||||||
|
_mediaLastPlaybackPositionsKey = 0;
|
||||||
|
writeMapDelayed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 size = 0;
|
||||||
|
file.stream >> size;
|
||||||
|
for (auto i = 0; i < size; ++i) {
|
||||||
|
quint64 id = 0;
|
||||||
|
qint64 time = 0;
|
||||||
|
file.stream >> id >> time;
|
||||||
|
_mediaLastPlaybackPosition.emplace_back(DocumentId(id), time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Account::writeSearchSuggestionsDelayed() {
|
void Account::writeSearchSuggestionsDelayed() {
|
||||||
Expects(_owner->sessionExists());
|
Expects(_owner->sessionExists());
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,9 @@ public:
|
||||||
void writeExportSettings(const Export::Settings &settings);
|
void writeExportSettings(const Export::Settings &settings);
|
||||||
[[nodiscard]] Export::Settings readExportSettings();
|
[[nodiscard]] Export::Settings readExportSettings();
|
||||||
|
|
||||||
|
void setMediaLastPlaybackPosition(DocumentId id, crl::time time);
|
||||||
|
[[nodiscard]] crl::time mediaLastPlaybackPosition(DocumentId id) const;
|
||||||
|
|
||||||
void writeSearchSuggestionsDelayed();
|
void writeSearchSuggestionsDelayed();
|
||||||
void writeSearchSuggestionsIfNeeded();
|
void writeSearchSuggestionsIfNeeded();
|
||||||
void writeSearchSuggestions();
|
void writeSearchSuggestions();
|
||||||
|
@ -261,6 +264,9 @@ private:
|
||||||
void readTrustedBots();
|
void readTrustedBots();
|
||||||
void writeTrustedBots();
|
void writeTrustedBots();
|
||||||
|
|
||||||
|
void readMediaLastPlaybackPositions();
|
||||||
|
void writeMediaLastPlaybackPositions();
|
||||||
|
|
||||||
std::optional<RecentHashtagPack> saveRecentHashtags(
|
std::optional<RecentHashtagPack> saveRecentHashtags(
|
||||||
Fn<RecentHashtagPack()> getPack,
|
Fn<RecentHashtagPack()> getPack,
|
||||||
const QString &text);
|
const QString &text);
|
||||||
|
@ -311,6 +317,7 @@ private:
|
||||||
FileKey _searchSuggestionsKey = 0;
|
FileKey _searchSuggestionsKey = 0;
|
||||||
FileKey _roundPlaceholderKey = 0;
|
FileKey _roundPlaceholderKey = 0;
|
||||||
FileKey _inlineBotsDownloadsKey = 0;
|
FileKey _inlineBotsDownloadsKey = 0;
|
||||||
|
FileKey _mediaLastPlaybackPositionsKey = 0;
|
||||||
|
|
||||||
qint64 _cacheTotalSizeLimit = 0;
|
qint64 _cacheTotalSizeLimit = 0;
|
||||||
qint64 _cacheBigFileTotalSizeLimit = 0;
|
qint64 _cacheBigFileTotalSizeLimit = 0;
|
||||||
|
@ -323,6 +330,9 @@ private:
|
||||||
bool _recentHashtagsAndBotsWereRead = false;
|
bool _recentHashtagsAndBotsWereRead = false;
|
||||||
bool _searchSuggestionsRead = false;
|
bool _searchSuggestionsRead = false;
|
||||||
bool _inlineBotsDownloadsRead = false;
|
bool _inlineBotsDownloadsRead = false;
|
||||||
|
bool _mediaLastPlaybackPositionsRead = false;
|
||||||
|
|
||||||
|
std::vector<std::pair<DocumentId, crl::time>> _mediaLastPlaybackPosition;
|
||||||
|
|
||||||
Webview::StorageId _webviewStorageIdBots;
|
Webview::StorageId _webviewStorageIdBots;
|
||||||
Webview::StorageId _webviewStorageIdOther;
|
Webview::StorageId _webviewStorageIdOther;
|
||||||
|
|
|
@ -89,6 +89,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "support/support_helper.h"
|
#include "support/support_helper.h"
|
||||||
#include "storage/file_upload.h"
|
#include "storage/file_upload.h"
|
||||||
#include "storage/download_manager_mtproto.h"
|
#include "storage/download_manager_mtproto.h"
|
||||||
|
#include "storage/storage_account.h"
|
||||||
#include "window/themes/window_theme.h"
|
#include "window/themes/window_theme.h"
|
||||||
#include "window/window_peer_menu.h"
|
#include "window/window_peer_menu.h"
|
||||||
#include "window/window_session_controller_link_info.h"
|
#include "window/window_session_controller_link_info.h"
|
||||||
|
@ -2789,13 +2790,18 @@ void SessionController::openDocument(
|
||||||
} else if (showInMediaView) {
|
} else if (showInMediaView) {
|
||||||
using namespace Media::View;
|
using namespace Media::View;
|
||||||
const auto timestamp = item ? ExtractVideoTimestamp(item) : 0;
|
const auto timestamp = item ? ExtractVideoTimestamp(item) : 0;
|
||||||
|
const auto usedTimestamp = videoTimestampOverride
|
||||||
|
? ((*videoTimestampOverride) * crl::time(1000))
|
||||||
|
: timestamp
|
||||||
|
? (timestamp * crl::time(1000))
|
||||||
|
: session().local().mediaLastPlaybackPosition(document->id);
|
||||||
_window->openInMediaView(OpenRequest(
|
_window->openInMediaView(OpenRequest(
|
||||||
this,
|
this,
|
||||||
document,
|
document,
|
||||||
item,
|
item,
|
||||||
message.topicRootId,
|
message.topicRootId,
|
||||||
false,
|
false,
|
||||||
videoTimestampOverride.value_or(timestamp) * crl::time(1000)));
|
usedTimestamp));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Data::ResolveDocument(this, document, item, message.topicRootId);
|
Data::ResolveDocument(this, document, item, message.topicRootId);
|
||||||
|
|
Loading…
Add table
Reference in a new issue