mirror of https://github.com/procxx/kepka.git
Save last playback position for long videos.
This commit is contained in:
parent
b584204522
commit
e9620af6fb
|
@ -21,6 +21,7 @@ constexpr auto kAutoLockTimeoutLateMs = crl::time(3000);
|
||||||
constexpr auto kLegacyCallsPeerToPeerNobody = 4;
|
constexpr auto kLegacyCallsPeerToPeerNobody = 4;
|
||||||
constexpr auto kVersionTag = -1;
|
constexpr auto kVersionTag = -1;
|
||||||
constexpr auto kVersion = 1;
|
constexpr auto kVersion = 1;
|
||||||
|
constexpr auto kMaxSavedPlaybackPositions = 16;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -93,6 +94,10 @@ QByteArray Settings::serialize() const {
|
||||||
stream << qint32(_variables.suggestEmoji ? 1 : 0);
|
stream << qint32(_variables.suggestEmoji ? 1 : 0);
|
||||||
stream << qint32(_variables.suggestStickersByEmoji ? 1 : 0);
|
stream << qint32(_variables.suggestStickersByEmoji ? 1 : 0);
|
||||||
stream << qint32(_variables.spellcheckerEnabled.current() ? 1 : 0);
|
stream << qint32(_variables.spellcheckerEnabled.current() ? 1 : 0);
|
||||||
|
stream << qint32(_variables.mediaLastPlaybackPosition.size());
|
||||||
|
for (const auto &[id, time] : _variables.mediaLastPlaybackPosition) {
|
||||||
|
stream << quint64(id) << qint64(time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -142,6 +147,7 @@ void Settings::constructFromSerialized(const QByteArray &serialized) {
|
||||||
qint32 suggestEmoji = _variables.suggestEmoji ? 1 : 0;
|
qint32 suggestEmoji = _variables.suggestEmoji ? 1 : 0;
|
||||||
qint32 suggestStickersByEmoji = _variables.suggestStickersByEmoji ? 1 : 0;
|
qint32 suggestStickersByEmoji = _variables.suggestStickersByEmoji ? 1 : 0;
|
||||||
qint32 spellcheckerEnabled = _variables.spellcheckerEnabled.current() ? 1 : 0;
|
qint32 spellcheckerEnabled = _variables.spellcheckerEnabled.current() ? 1 : 0;
|
||||||
|
std::vector<std::pair<DocumentId, crl::time>> mediaLastPlaybackPosition;
|
||||||
|
|
||||||
stream >> versionTag;
|
stream >> versionTag;
|
||||||
if (versionTag == kVersionTag) {
|
if (versionTag == kVersionTag) {
|
||||||
|
@ -250,6 +256,18 @@ void Settings::constructFromSerialized(const QByteArray &serialized) {
|
||||||
if (!stream.atEnd()) {
|
if (!stream.atEnd()) {
|
||||||
stream >> spellcheckerEnabled;
|
stream >> spellcheckerEnabled;
|
||||||
}
|
}
|
||||||
|
if (!stream.atEnd()) {
|
||||||
|
auto count = qint32(0);
|
||||||
|
stream >> count;
|
||||||
|
if (stream.status() == QDataStream::Ok) {
|
||||||
|
for (auto i = 0; i != count; ++i) {
|
||||||
|
quint64 documentId;
|
||||||
|
qint64 time;
|
||||||
|
stream >> documentId >> time;
|
||||||
|
mediaLastPlaybackPosition.emplace_back(documentId, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (stream.status() != QDataStream::Ok) {
|
if (stream.status() != QDataStream::Ok) {
|
||||||
LOG(("App Error: "
|
LOG(("App Error: "
|
||||||
"Bad data for Main::Settings::constructFromSerialized()"));
|
"Bad data for Main::Settings::constructFromSerialized()"));
|
||||||
|
@ -336,6 +354,7 @@ void Settings::constructFromSerialized(const QByteArray &serialized) {
|
||||||
_variables.suggestEmoji = (suggestEmoji == 1);
|
_variables.suggestEmoji = (suggestEmoji == 1);
|
||||||
_variables.suggestStickersByEmoji = (suggestStickersByEmoji == 1);
|
_variables.suggestStickersByEmoji = (suggestStickersByEmoji == 1);
|
||||||
_variables.spellcheckerEnabled = (spellcheckerEnabled == 1);
|
_variables.spellcheckerEnabled = (spellcheckerEnabled == 1);
|
||||||
|
_variables.mediaLastPlaybackPosition = std::move(mediaLastPlaybackPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setSupportChatsTimeSlice(int slice) {
|
void Settings::setSupportChatsTimeSlice(int slice) {
|
||||||
|
@ -430,6 +449,34 @@ rpl::producer<int> Settings::thirdColumnWidthChanges() const {
|
||||||
return _variables.thirdColumnWidth.changes();
|
return _variables.thirdColumnWidth.changes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Settings::setMediaLastPlaybackPosition(DocumentId id, crl::time time) {
|
||||||
|
auto &map = _variables.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 Settings::mediaLastPlaybackPosition(DocumentId id) const {
|
||||||
|
const auto i = ranges::find(
|
||||||
|
_variables.mediaLastPlaybackPosition,
|
||||||
|
id,
|
||||||
|
&std::pair<DocumentId, crl::time>::first);
|
||||||
|
return (i != _variables.mediaLastPlaybackPosition.end()) ? i->second : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Settings::setArchiveCollapsed(bool collapsed) {
|
void Settings::setArchiveCollapsed(bool collapsed) {
|
||||||
_variables.archiveCollapsed = collapsed;
|
_variables.archiveCollapsed = collapsed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,6 +153,9 @@ public:
|
||||||
_variables.groupStickersSectionHidden.remove(peerId);
|
_variables.groupStickersSectionHidden.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 _variables.autoDownload;
|
return _variables.autoDownload;
|
||||||
}
|
}
|
||||||
|
@ -277,6 +280,7 @@ private:
|
||||||
bool suggestEmoji = true;
|
bool suggestEmoji = true;
|
||||||
bool suggestStickersByEmoji = true;
|
bool suggestStickersByEmoji = true;
|
||||||
rpl::variable<bool> spellcheckerEnabled = true;
|
rpl::variable<bool> spellcheckerEnabled = true;
|
||||||
|
std::vector<std::pair<DocumentId, crl::time>> mediaLastPlaybackPosition;
|
||||||
|
|
||||||
static constexpr auto kDefaultSupportChatsLimitSlice
|
static constexpr auto kDefaultSupportChatsLimitSlice
|
||||||
= 7 * 24 * 60 * 60;
|
= 7 * 24 * 60 * 60;
|
||||||
|
|
|
@ -80,6 +80,8 @@ constexpr auto kIdsLimit = 48;
|
||||||
// Preload next messages if we went further from current than that.
|
// Preload next messages if we went further from current than that.
|
||||||
constexpr auto kIdsPreloadAfter = 28;
|
constexpr auto kIdsPreloadAfter = 28;
|
||||||
|
|
||||||
|
constexpr auto kMinLengthForSavePosition = 20 * TimeId(60); // 20 minutes.
|
||||||
|
|
||||||
Images::Options VideoThumbOptions(not_null<DocumentData*> document) {
|
Images::Options VideoThumbOptions(not_null<DocumentData*> document) {
|
||||||
const auto result = Images::Option::Smooth | Images::Option::Blurred;
|
const auto result = Images::Option::Smooth | Images::Option::Blurred;
|
||||||
return (document && document->isVideoMessage())
|
return (document && document->isVideoMessage())
|
||||||
|
@ -435,6 +437,20 @@ bool OverlayWidget::documentBubbleShown() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::clearStreaming() {
|
void OverlayWidget::clearStreaming() {
|
||||||
|
if (_streamed && _doc) {
|
||||||
|
const auto state = _streamed->instance.player().prepareLegacyState();
|
||||||
|
const auto time = (state.position == kTimeUnknown
|
||||||
|
|| state.length == kTimeUnknown)
|
||||||
|
? TimeId(0)
|
||||||
|
: (state.length >= kMinLengthForSavePosition * state.frequency)
|
||||||
|
? (state.position / state.frequency) * crl::time(1000)
|
||||||
|
: TimeId(0);
|
||||||
|
auto &session = _doc->session();
|
||||||
|
if (session.settings().mediaLastPlaybackPosition(_doc->id) != time) {
|
||||||
|
session.settings().setMediaLastPlaybackPosition(_doc->id, time);
|
||||||
|
session.saveSettingsDelayed();
|
||||||
|
}
|
||||||
|
}
|
||||||
_fullScreenVideo = false;
|
_fullScreenVideo = false;
|
||||||
_streamed = nullptr;
|
_streamed = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -2018,7 +2034,10 @@ void OverlayWidget::startStreamingPlayer() {
|
||||||
if (!_streamed->withSound && _streamed->instance.player().playing()) {
|
if (!_streamed->withSound && _streamed->instance.player().playing()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
restartAtSeekPosition(0);
|
const auto position = _doc
|
||||||
|
? _doc->session().settings().mediaLastPlaybackPosition(_doc->id)
|
||||||
|
: 0;
|
||||||
|
restartAtSeekPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::initStreamingThumbnail() {
|
void OverlayWidget::initStreamingThumbnail() {
|
||||||
|
|
Loading…
Reference in New Issue