mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Mark stories as read.
This commit is contained in:
parent
f323370752
commit
f814e401b9
7 changed files with 158 additions and 27 deletions
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_photo.h"
|
#include "data/data_photo.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
#include "data/data_stories.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_download_manager.h"
|
#include "data/data_download_manager.h"
|
||||||
|
@ -1685,6 +1686,9 @@ bool Application::readyToQuit() {
|
||||||
if (session->api().isQuitPrevent()) {
|
if (session->api().isQuitPrevent()) {
|
||||||
prevented = true;
|
prevented = true;
|
||||||
}
|
}
|
||||||
|
if (session->data().stories().isQuitPrevent()) {
|
||||||
|
prevented = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "api/api_text_entities.h"
|
#include "api/api_text_entities.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
#include "core/application.h"
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
|
@ -30,6 +31,7 @@ namespace {
|
||||||
constexpr auto kMaxResolveTogether = 100;
|
constexpr auto kMaxResolveTogether = 100;
|
||||||
constexpr auto kIgnorePreloadAroundIfLoaded = 15;
|
constexpr auto kIgnorePreloadAroundIfLoaded = 15;
|
||||||
constexpr auto kPreloadAroundCount = 30;
|
constexpr auto kPreloadAroundCount = 30;
|
||||||
|
constexpr auto kMarkAsReadDelay = 3 * crl::time(1000);
|
||||||
|
|
||||||
using UpdateFlag = StoryUpdate::Flag;
|
using UpdateFlag = StoryUpdate::Flag;
|
||||||
|
|
||||||
|
@ -61,7 +63,7 @@ std::optional<StoryMedia> ParseMedia(
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool StoriesList::unread() const {
|
bool StoriesList::unread() const {
|
||||||
return !ids.empty() && readTill < ids.front();
|
return !ids.empty() && readTill < ids.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
Story::Story(
|
Story::Story(
|
||||||
|
@ -188,7 +190,9 @@ bool Story::applyChanges(StoryMedia media, const MTPDstoryItem &data) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stories::Stories(not_null<Session*> owner) : _owner(owner) {
|
Stories::Stories(not_null<Session*> owner)
|
||||||
|
: _owner(owner)
|
||||||
|
, _markReadTimer([=] { sendMarkAsReadRequests(); }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Stories::~Stories() {
|
Stories::~Stories() {
|
||||||
|
@ -222,13 +226,13 @@ StoriesList Stories::parse(const MTPUserStories &stories) {
|
||||||
for (const auto &story : list) {
|
for (const auto &story : list) {
|
||||||
story.match([&](const MTPDstoryItem &data) {
|
story.match([&](const MTPDstoryItem &data) {
|
||||||
if (const auto story = parseAndApply(result.user, data)) {
|
if (const auto story = parseAndApply(result.user, data)) {
|
||||||
result.ids.push_back(story->id());
|
result.ids.emplace(story->id());
|
||||||
} else {
|
} else {
|
||||||
applyDeleted({ peerFromUser(userId), data.vid().v });
|
applyDeleted({ peerFromUser(userId), data.vid().v });
|
||||||
--result.total;
|
--result.total;
|
||||||
}
|
}
|
||||||
}, [&](const MTPDstoryItemSkipped &data) {
|
}, [&](const MTPDstoryItemSkipped &data) {
|
||||||
result.ids.push_back(data.vid().v);
|
result.ids.emplace(data.vid().v);
|
||||||
}, [&](const MTPDstoryItemDeleted &data) {
|
}, [&](const MTPDstoryItemDeleted &data) {
|
||||||
applyDeleted({ peerFromUser(userId), data.vid().v });
|
applyDeleted({ peerFromUser(userId), data.vid().v });
|
||||||
--result.total;
|
--result.total;
|
||||||
|
@ -434,13 +438,13 @@ void Stories::applyDeleted(FullStoryId id) {
|
||||||
return list.user->id;
|
return list.user->id;
|
||||||
});
|
});
|
||||||
if (j != end(_all)) {
|
if (j != end(_all)) {
|
||||||
const auto till = ranges::remove(j->ids, id.story);
|
const auto removed = j->ids.remove(id.story);
|
||||||
const auto removed = int(std::distance(till, end(j->ids)));
|
if (removed) {
|
||||||
if (till != end(j->ids)) {
|
|
||||||
j->ids.erase(till, end(j->ids));
|
|
||||||
j->total = std::max(j->total - removed, 0);
|
|
||||||
if (j->ids.empty()) {
|
if (j->ids.empty()) {
|
||||||
_all.erase(j);
|
_all.erase(j);
|
||||||
|
} else {
|
||||||
|
Assert(j->total > 0);
|
||||||
|
--j->total;
|
||||||
}
|
}
|
||||||
_allChanged.fire({});
|
_allChanged.fire({});
|
||||||
}
|
}
|
||||||
|
@ -534,8 +538,8 @@ void Stories::applyChanges(StoriesList &&list) {
|
||||||
if (i != end(_all)) {
|
if (i != end(_all)) {
|
||||||
auto added = false;
|
auto added = false;
|
||||||
for (const auto id : list.ids) {
|
for (const auto id : list.ids) {
|
||||||
if (!ranges::contains(i->ids, id)) {
|
if (!i->ids.contains(id)) {
|
||||||
i->ids.push_back(id);
|
i->ids.emplace(id);
|
||||||
++i->total;
|
++i->total;
|
||||||
added = true;
|
added = true;
|
||||||
}
|
}
|
||||||
|
@ -584,4 +588,78 @@ void Stories::loadAround(FullStoryId id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Stories::markAsRead(FullStoryId id) {
|
||||||
|
const auto i = ranges::find(_all, id.peer, [](const StoriesList &list) {
|
||||||
|
return list.user->id;
|
||||||
|
});
|
||||||
|
Assert(i != end(_all));
|
||||||
|
if (i->readTill >= id.story) {
|
||||||
|
return;
|
||||||
|
} else if (!_markReadPending.contains(id.peer)) {
|
||||||
|
sendMarkAsReadRequests();
|
||||||
|
}
|
||||||
|
_markReadPending.emplace(id.peer);
|
||||||
|
i->readTill = id.story;
|
||||||
|
_markReadTimer.callOnce(kMarkAsReadDelay);
|
||||||
|
_allChanged.fire({});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stories::sendMarkAsReadRequest(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
StoryId tillId) {
|
||||||
|
Expects(peer->isUser());
|
||||||
|
|
||||||
|
const auto peerId = peer->id;
|
||||||
|
_markReadRequests.emplace(peerId);
|
||||||
|
const auto finish = [=] {
|
||||||
|
_markReadRequests.remove(peerId);
|
||||||
|
if (!_markReadTimer.isActive()
|
||||||
|
&& _markReadPending.contains(peerId)) {
|
||||||
|
sendMarkAsReadRequests();
|
||||||
|
}
|
||||||
|
if (_markReadRequests.empty()) {
|
||||||
|
if (Core::Quitting()) {
|
||||||
|
LOG(("Stories doesn't prevent quit any more."));
|
||||||
|
}
|
||||||
|
Core::App().quitPreventFinished();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto api = &_owner->session().api();
|
||||||
|
api->request(MTPstories_ReadStories(
|
||||||
|
peer->asUser()->inputUser,
|
||||||
|
MTP_int(tillId)
|
||||||
|
)).done(finish).fail(finish).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stories::sendMarkAsReadRequests() {
|
||||||
|
_markReadTimer.cancel();
|
||||||
|
for (auto i = begin(_markReadPending); i != end(_markReadPending);) {
|
||||||
|
const auto peerId = *i;
|
||||||
|
if (_markReadRequests.contains(peerId)) {
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto j = ranges::find(_all, peerId, [](
|
||||||
|
const StoriesList &list) {
|
||||||
|
return list.user->id;
|
||||||
|
});
|
||||||
|
if (j != end(_all)) {
|
||||||
|
sendMarkAsReadRequest(j->user, j->readTill);
|
||||||
|
}
|
||||||
|
i = _markReadPending.erase(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Stories::isQuitPrevent() {
|
||||||
|
if (!_markReadPending.empty()) {
|
||||||
|
sendMarkAsReadRequests();
|
||||||
|
}
|
||||||
|
if (_markReadRequests.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LOG(("Stories prevents quit, marking as read..."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/expected.h"
|
#include "base/expected.h"
|
||||||
|
#include "base/timer.h"
|
||||||
|
|
||||||
class Image;
|
class Image;
|
||||||
class PhotoData;
|
class PhotoData;
|
||||||
|
@ -70,7 +71,7 @@ private:
|
||||||
|
|
||||||
struct StoriesList {
|
struct StoriesList {
|
||||||
not_null<UserData*> user;
|
not_null<UserData*> user;
|
||||||
std::vector<StoryId> ids;
|
base::flat_set<StoryId> ids;
|
||||||
StoryId readTill = 0;
|
StoryId readTill = 0;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
|
||||||
|
@ -113,6 +114,9 @@ public:
|
||||||
FullStoryId id) const;
|
FullStoryId id) const;
|
||||||
void resolve(FullStoryId id, Fn<void()> done);
|
void resolve(FullStoryId id, Fn<void()> done);
|
||||||
|
|
||||||
|
[[nodiscard]] bool isQuitPrevent();
|
||||||
|
void markAsRead(FullStoryId id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] StoriesList parse(const MTPUserStories &stories);
|
[[nodiscard]] StoriesList parse(const MTPUserStories &stories);
|
||||||
[[nodiscard]] Story *parseAndApply(
|
[[nodiscard]] Story *parseAndApply(
|
||||||
|
@ -129,6 +133,9 @@ private:
|
||||||
void applyDeleted(FullStoryId id);
|
void applyDeleted(FullStoryId id);
|
||||||
void removeDependencyStory(not_null<Story*> story);
|
void removeDependencyStory(not_null<Story*> story);
|
||||||
|
|
||||||
|
void sendMarkAsReadRequests();
|
||||||
|
void sendMarkAsReadRequest(not_null<PeerData*> peer, StoryId tillId);
|
||||||
|
|
||||||
const not_null<Session*> _owner;
|
const not_null<Session*> _owner;
|
||||||
base::flat_map<
|
base::flat_map<
|
||||||
PeerId,
|
PeerId,
|
||||||
|
@ -154,6 +161,10 @@ private:
|
||||||
|
|
||||||
mtpRequestId _loadMoreRequestId = 0;
|
mtpRequestId _loadMoreRequestId = 0;
|
||||||
|
|
||||||
|
base::flat_set<PeerId> _markReadPending;
|
||||||
|
base::Timer _markReadTimer;
|
||||||
|
base::flat_set<PeerId> _markReadRequests;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -37,11 +37,15 @@ struct List::Layout {
|
||||||
float64 userpicLeft = 0.;
|
float64 userpicLeft = 0.;
|
||||||
float64 photoLeft = 0.;
|
float64 photoLeft = 0.;
|
||||||
float64 left = 0.;
|
float64 left = 0.;
|
||||||
|
float64 single = 0.;
|
||||||
|
int leftFull = 0;
|
||||||
|
int leftSmall = 0;
|
||||||
|
int singleFull = 0;
|
||||||
|
int singleSmall = 0;
|
||||||
int startIndexSmall = 0;
|
int startIndexSmall = 0;
|
||||||
int endIndexSmall = 0;
|
int endIndexSmall = 0;
|
||||||
int startIndexFull = 0;
|
int startIndexFull = 0;
|
||||||
int endIndexFull = 0;
|
int endIndexFull = 0;
|
||||||
int singleFull = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
List::List(
|
List::List(
|
||||||
|
@ -277,11 +281,15 @@ List::Layout List::computeLayout() const {
|
||||||
.userpicLeft = userpicLeft,
|
.userpicLeft = userpicLeft,
|
||||||
.photoLeft = photoLeft,
|
.photoLeft = photoLeft,
|
||||||
.left = userpicLeft - photoLeft,
|
.left = userpicLeft - photoLeft,
|
||||||
|
.single = lerp(st.shift, singleFull),
|
||||||
|
.leftFull = leftFull,
|
||||||
|
.leftSmall = leftSmall,
|
||||||
|
.singleFull = singleFull,
|
||||||
|
.singleSmall = st.shift,
|
||||||
.startIndexSmall = startIndexSmall,
|
.startIndexSmall = startIndexSmall,
|
||||||
.endIndexSmall = endIndexSmall,
|
.endIndexSmall = endIndexSmall,
|
||||||
.startIndexFull = startIndexFull,
|
.startIndexFull = startIndexFull,
|
||||||
.endIndexFull = endIndexFull,
|
.endIndexFull = endIndexFull,
|
||||||
.singleFull = singleFull,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,8 +304,6 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
auto &rendering = _data.empty() ? _hidingData : _data;
|
auto &rendering = _data.empty() ? _hidingData : _data;
|
||||||
const auto line = lerp(st.lineTwice, full.lineTwice) / 2.;
|
const auto line = lerp(st.lineTwice, full.lineTwice) / 2.;
|
||||||
const auto lineRead = lerp(st.lineReadTwice, full.lineReadTwice) / 2.;
|
const auto lineRead = lerp(st.lineReadTwice, full.lineReadTwice) / 2.;
|
||||||
const auto singleSmall = st.shift;
|
|
||||||
const auto single = lerp(singleSmall, layout.singleFull);
|
|
||||||
const auto photoTopSmall = (st.height - st.photo) / 2.;
|
const auto photoTopSmall = (st.height - st.photo) / 2.;
|
||||||
const auto photoTop = lerp(photoTopSmall, full.photoTop);
|
const auto photoTop = lerp(photoTopSmall, full.photoTop);
|
||||||
const auto photo = lerp(st.photo, full.photo);
|
const auto photo = lerp(st.photo, full.photo);
|
||||||
|
@ -346,7 +352,7 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
const auto full = (drawFull && indexFull < layout.endIndexFull)
|
const auto full = (drawFull && indexFull < layout.endIndexFull)
|
||||||
? &rendering.items[indexFull]
|
? &rendering.items[indexFull]
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto x = layout.left + single * index;
|
const auto x = layout.left + layout.single * index;
|
||||||
return Single{ x, indexSmall, small, indexFull, full };
|
return Single{ x, indexSmall, small, indexFull, full };
|
||||||
};
|
};
|
||||||
const auto hasUnread = [&](const Single &single) {
|
const auto hasUnread = [&](const Single &single) {
|
||||||
|
@ -697,19 +703,17 @@ void List::updateSelected() {
|
||||||
const auto &full = st::dialogsStoriesFull;
|
const auto &full = st::dialogsStoriesFull;
|
||||||
const auto p = mapFromGlobal(_lastMousePosition);
|
const auto p = mapFromGlobal(_lastMousePosition);
|
||||||
const auto layout = computeLayout();
|
const auto layout = computeLayout();
|
||||||
const auto firstRightFull = full.left + layout.singleFull;
|
const auto firstRightFull = layout.leftFull
|
||||||
const auto firstRightSmall = st.left
|
+ (layout.startIndexFull + 1) * layout.singleFull;
|
||||||
|
const auto firstRightSmall = layout.leftSmall
|
||||||
+ st.photoLeft
|
+ st.photoLeft
|
||||||
+ st.photo;
|
+ st.photo;
|
||||||
const auto stepFull = layout.singleFull;
|
|
||||||
const auto stepSmall = st.shift;
|
|
||||||
const auto lastRightAddFull = 0;
|
const auto lastRightAddFull = 0;
|
||||||
const auto lastRightAddSmall = st.photoLeft;
|
const auto lastRightAddSmall = st.photoLeft;
|
||||||
const auto lerp = [&](float64 a, float64 b) {
|
const auto lerp = [&](float64 a, float64 b) {
|
||||||
return a + (b - a) * layout.ratio;
|
return a + (b - a) * layout.ratio;
|
||||||
};
|
};
|
||||||
const auto firstRight = lerp(firstRightSmall, firstRightFull);
|
const auto firstRight = lerp(firstRightSmall, firstRightFull);
|
||||||
const auto step = lerp(stepSmall, stepFull);
|
|
||||||
const auto lastRightAdd = lerp(lastRightAddSmall, lastRightAddFull);
|
const auto lastRightAdd = lerp(lastRightAddSmall, lastRightAddFull);
|
||||||
const auto activateFull = (layout.ratio >= 0.5);
|
const auto activateFull = (layout.ratio >= 0.5);
|
||||||
const auto startIndex = activateFull
|
const auto startIndex = activateFull
|
||||||
|
@ -721,14 +725,16 @@ void List::updateSelected() {
|
||||||
const auto x = p.x();
|
const auto x = p.x();
|
||||||
const auto infiniteIndex = (x < firstRight)
|
const auto infiniteIndex = (x < firstRight)
|
||||||
? 0
|
? 0
|
||||||
: int(std::floor(((x - firstRight) / step) + 1));
|
: int(std::floor(((x - firstRight) / layout.single) + 1));
|
||||||
const auto index = (endIndex == startIndex)
|
const auto index = (endIndex == startIndex)
|
||||||
? -1
|
? -1
|
||||||
: (infiniteIndex == endIndex - startIndex
|
: (infiniteIndex == endIndex - startIndex
|
||||||
&& x < firstRight
|
&& x < firstRight
|
||||||
+ (endIndex - startIndex - 1) * step
|
+ (endIndex - startIndex - 1) * layout.single
|
||||||
+ lastRightAdd)
|
+ lastRightAdd)
|
||||||
? (infiniteIndex - 1) // Last small part should still be clickable.
|
? (infiniteIndex - 1) // Last small part should still be clickable.
|
||||||
|
: (startIndex + infiniteIndex >= endIndex)
|
||||||
|
? -1
|
||||||
: infiniteIndex;
|
: infiniteIndex;
|
||||||
const auto selected = (index < 0
|
const auto selected = (index < 0
|
||||||
|| startIndex + index >= layout.itemsCount)
|
|| startIndex + index >= layout.itemsCount)
|
||||||
|
|
|
@ -41,6 +41,8 @@ constexpr auto kSiblingOutsidePart = 0.24;
|
||||||
constexpr auto kSiblingUserpicSize = 0.3;
|
constexpr auto kSiblingUserpicSize = 0.3;
|
||||||
constexpr auto kInnerHeightMultiplier = 1.6;
|
constexpr auto kInnerHeightMultiplier = 1.6;
|
||||||
constexpr auto kPreloadUsersCount = 3;
|
constexpr auto kPreloadUsersCount = 3;
|
||||||
|
constexpr auto kMarkAsReadAfterSeconds = 1;
|
||||||
|
constexpr auto kMarkAsReadAfterProgress = 0.2;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -360,7 +362,7 @@ void Controller::show(
|
||||||
showSiblings(lists, index);
|
showSiblings(lists, index);
|
||||||
|
|
||||||
const auto &list = lists[index];
|
const auto &list = lists[index];
|
||||||
const auto id = list.ids[subindex];
|
const auto id = *(begin(list.ids) + subindex);
|
||||||
const auto storyId = FullStoryId{
|
const auto storyId = FullStoryId{
|
||||||
.peer = list.user->id,
|
.peer = list.user->id,
|
||||||
.story = id,
|
.story = id,
|
||||||
|
@ -464,6 +466,7 @@ void Controller::updatePhotoPlayback(const Player::TrackState &state) {
|
||||||
void Controller::updatePlayback(const Player::TrackState &state) {
|
void Controller::updatePlayback(const Player::TrackState &state) {
|
||||||
_slider->updatePlayback(state);
|
_slider->updatePlayback(state);
|
||||||
updatePowerSaveBlocker(state);
|
updatePowerSaveBlocker(state);
|
||||||
|
maybeMarkAsRead(state);
|
||||||
if (Player::IsStoppedAtEnd(state.state)) {
|
if (Player::IsStoppedAtEnd(state.state)) {
|
||||||
if (!subjumpFor(1)) {
|
if (!subjumpFor(1)) {
|
||||||
_delegate->storiesClose();
|
_delegate->storiesClose();
|
||||||
|
@ -471,6 +474,26 @@ void Controller::updatePlayback(const Player::TrackState &state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Controller::maybeMarkAsRead(const Player::TrackState &state) {
|
||||||
|
const auto length = state.length;
|
||||||
|
const auto position = Player::IsStoppedAtEnd(state.state)
|
||||||
|
? state.length
|
||||||
|
: Player::IsStoppedOrStopping(state.state)
|
||||||
|
? 0
|
||||||
|
: state.position;
|
||||||
|
if (position > state.frequency * kMarkAsReadAfterSeconds) {
|
||||||
|
if (position > kMarkAsReadAfterProgress * length) {
|
||||||
|
markAsRead();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::markAsRead() {
|
||||||
|
Expects(_list.has_value());
|
||||||
|
|
||||||
|
_list->user->owner().stories().markAsRead(_shown);
|
||||||
|
}
|
||||||
|
|
||||||
bool Controller::subjumpAvailable(int delta) const {
|
bool Controller::subjumpAvailable(int delta) const {
|
||||||
const auto index = _index + delta;
|
const auto index = _index + delta;
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
|
@ -482,6 +505,9 @@ bool Controller::subjumpAvailable(int delta) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Controller::subjumpFor(int delta) {
|
bool Controller::subjumpFor(int delta) {
|
||||||
|
if (delta > 0) {
|
||||||
|
markAsRead();
|
||||||
|
}
|
||||||
const auto index = _index + delta;
|
const auto index = _index + delta;
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
if (_siblingLeft && _siblingLeft->shownId().valid()) {
|
if (_siblingLeft && _siblingLeft->shownId().valid()) {
|
||||||
|
@ -507,7 +533,7 @@ void Controller::subjumpTo(int index) {
|
||||||
|
|
||||||
const auto id = FullStoryId{
|
const auto id = FullStoryId{
|
||||||
.peer = _list->user->id,
|
.peer = _list->user->id,
|
||||||
.story = _list->ids[index]
|
.story = *(begin(_list->ids) + index)
|
||||||
};
|
};
|
||||||
auto &stories = _list->user->owner().stories();
|
auto &stories = _list->user->owner().stories();
|
||||||
if (stories.lookup(id)) {
|
if (stories.lookup(id)) {
|
||||||
|
@ -554,6 +580,9 @@ bool Controller::jumpFor(int delta) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (delta == 1) {
|
} else if (delta == 1) {
|
||||||
|
if (_list && _index + 1 >= _list->total) {
|
||||||
|
markAsRead();
|
||||||
|
}
|
||||||
if (const auto right = _siblingRight.get()) {
|
if (const auto right = _siblingRight.get()) {
|
||||||
_delegate->storiesJumpTo(
|
_delegate->storiesJumpTo(
|
||||||
&right->peer()->session(),
|
&right->peer()->session(),
|
||||||
|
|
|
@ -123,6 +123,8 @@ private:
|
||||||
void updatePhotoPlayback(const Player::TrackState &state);
|
void updatePhotoPlayback(const Player::TrackState &state);
|
||||||
void updatePlayback(const Player::TrackState &state);
|
void updatePlayback(const Player::TrackState &state);
|
||||||
void updatePowerSaveBlocker(const Player::TrackState &state);
|
void updatePowerSaveBlocker(const Player::TrackState &state);
|
||||||
|
void maybeMarkAsRead(const Player::TrackState &state);
|
||||||
|
void markAsRead();
|
||||||
|
|
||||||
void showSiblings(
|
void showSiblings(
|
||||||
const std::vector<Data::StoriesList> &lists,
|
const std::vector<Data::StoriesList> &lists,
|
||||||
|
|
|
@ -2486,7 +2486,8 @@ void SessionController::openPeerStories(PeerId peerId) {
|
||||||
return list.user->id;
|
return list.user->id;
|
||||||
});
|
});
|
||||||
if (i != end(all) && !i->ids.empty()) {
|
if (i != end(all) && !i->ids.empty()) {
|
||||||
openPeerStory(i->user, i->ids.front());
|
const auto j = i->ids.lower_bound(i->readTill + 1);
|
||||||
|
openPeerStory(i->user, j != i->ids.end() ? *j : i->ids.front());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue