mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Implement per-topic shared media.
This commit is contained in:
parent
eec4b72d9a
commit
58b8eb8e96
58 changed files with 434 additions and 269 deletions
|
@ -2913,24 +2913,26 @@ void ApiWrap::resolveJumpToHistoryDate(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::requestSharedMediaCount(
|
|
||||||
not_null<PeerData*> peer,
|
|
||||||
Storage::SharedMediaType type) {
|
|
||||||
requestSharedMedia(peer, type, 0, SliceType::Before);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApiWrap::requestSharedMedia(
|
void ApiWrap::requestSharedMedia(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
SharedMediaType type,
|
SharedMediaType type,
|
||||||
MsgId messageId,
|
MsgId messageId,
|
||||||
SliceType slice) {
|
SliceType slice) {
|
||||||
const auto key = std::make_tuple(peer, type, messageId, slice);
|
const auto key = SharedMediaRequest{
|
||||||
|
peer,
|
||||||
|
topicRootId,
|
||||||
|
type,
|
||||||
|
messageId,
|
||||||
|
slice,
|
||||||
|
};
|
||||||
if (_sharedMediaRequests.contains(key)) {
|
if (_sharedMediaRequests.contains(key)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto prepared = Api::PrepareSearchRequest(
|
const auto prepared = Api::PrepareSearchRequest(
|
||||||
peer,
|
peer,
|
||||||
|
topicRootId,
|
||||||
type,
|
type,
|
||||||
QString(),
|
QString(),
|
||||||
messageId,
|
messageId,
|
||||||
|
@ -2946,7 +2948,6 @@ void ApiWrap::requestSharedMedia(
|
||||||
return request(
|
return request(
|
||||||
std::move(*prepared)
|
std::move(*prepared)
|
||||||
).done([=](const Api::SearchRequestResult &result) {
|
).done([=](const Api::SearchRequestResult &result) {
|
||||||
const auto key = std::make_tuple(peer, type, messageId, slice);
|
|
||||||
_sharedMediaRequests.remove(key);
|
_sharedMediaRequests.remove(key);
|
||||||
auto parsed = Api::ParseSearchResult(
|
auto parsed = Api::ParseSearchResult(
|
||||||
peer,
|
peer,
|
||||||
|
@ -2954,7 +2955,7 @@ void ApiWrap::requestSharedMedia(
|
||||||
messageId,
|
messageId,
|
||||||
slice,
|
slice,
|
||||||
result);
|
result);
|
||||||
sharedMediaDone(peer, type, std::move(parsed));
|
sharedMediaDone(peer, topicRootId, type, std::move(parsed));
|
||||||
finish();
|
finish();
|
||||||
}).fail([=] {
|
}).fail([=] {
|
||||||
_sharedMediaRequests.remove(key);
|
_sharedMediaRequests.remove(key);
|
||||||
|
@ -2966,10 +2967,12 @@ void ApiWrap::requestSharedMedia(
|
||||||
|
|
||||||
void ApiWrap::sharedMediaDone(
|
void ApiWrap::sharedMediaDone(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
SharedMediaType type,
|
SharedMediaType type,
|
||||||
Api::SearchResult &&parsed) {
|
Api::SearchResult &&parsed) {
|
||||||
_session->storage().add(Storage::SharedMediaAddSlice(
|
_session->storage().add(Storage::SharedMediaAddSlice(
|
||||||
peer->id,
|
peer->id,
|
||||||
|
topicRootId,
|
||||||
type,
|
type,
|
||||||
std::move(parsed.messageIds),
|
std::move(parsed.messageIds),
|
||||||
parsed.noSkipRange,
|
parsed.noSkipRange,
|
||||||
|
|
|
@ -265,12 +265,10 @@ public:
|
||||||
using SliceType = Data::LoadDirection;
|
using SliceType = Data::LoadDirection;
|
||||||
void requestSharedMedia(
|
void requestSharedMedia(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
Storage::SharedMediaType type,
|
Storage::SharedMediaType type,
|
||||||
MsgId messageId,
|
MsgId messageId,
|
||||||
SliceType slice);
|
SliceType slice);
|
||||||
void requestSharedMediaCount(
|
|
||||||
not_null<PeerData*> peer,
|
|
||||||
Storage::SharedMediaType type);
|
|
||||||
|
|
||||||
void readFeaturedSetDelayed(uint64 setId);
|
void readFeaturedSetDelayed(uint64 setId);
|
||||||
|
|
||||||
|
@ -465,6 +463,7 @@ private:
|
||||||
|
|
||||||
void sharedMediaDone(
|
void sharedMediaDone(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
SharedMediaType type,
|
SharedMediaType type,
|
||||||
Api::SearchResult &&parsed);
|
Api::SearchResult &&parsed);
|
||||||
|
|
||||||
|
@ -579,11 +578,18 @@ private:
|
||||||
mtpRequestId _contactsRequestId = 0;
|
mtpRequestId _contactsRequestId = 0;
|
||||||
mtpRequestId _contactsStatusesRequestId = 0;
|
mtpRequestId _contactsStatusesRequestId = 0;
|
||||||
|
|
||||||
base::flat_set<std::tuple<
|
struct SharedMediaRequest {
|
||||||
not_null<PeerData*>,
|
not_null<PeerData*> peer;
|
||||||
SharedMediaType,
|
MsgId topicRootId = 0;
|
||||||
MsgId,
|
SharedMediaType mediaType = {};
|
||||||
SliceType>> _sharedMediaRequests;
|
MsgId aroundId = 0;
|
||||||
|
SliceType sliceType = {};
|
||||||
|
|
||||||
|
friend inline constexpr auto operator<=>(
|
||||||
|
const SharedMediaRequest&,
|
||||||
|
const SharedMediaRequest&) = default;
|
||||||
|
};
|
||||||
|
base::flat_set<SharedMediaRequest> _sharedMediaRequests;
|
||||||
|
|
||||||
std::unique_ptr<DialogsLoadState> _dialogsLoadState;
|
std::unique_ptr<DialogsLoadState> _dialogsLoadState;
|
||||||
TimeId _dialogsLoadTill = 0;
|
TimeId _dialogsLoadTill = 0;
|
||||||
|
|
|
@ -19,10 +19,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
[[nodiscard]] bool IsOldForPin(MsgId id, not_null<PeerData*> peer) {
|
[[nodiscard]] bool IsOldForPin(
|
||||||
|
MsgId id,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId) {
|
||||||
const auto normal = peer->migrateToOrMe();
|
const auto normal = peer->migrateToOrMe();
|
||||||
const auto migrated = normal->migrateFrom();
|
const auto migrated = normal->migrateFrom();
|
||||||
const auto top = Data::ResolveTopPinnedId(normal, migrated);
|
const auto top = Data::ResolveTopPinnedId(normal, topicRootId, migrated);
|
||||||
if (!top) {
|
if (!top) {
|
||||||
return false;
|
return false;
|
||||||
} else if (peer == migrated) {
|
} else if (peer == migrated) {
|
||||||
|
@ -46,7 +49,7 @@ void PinMessageBox(
|
||||||
mtpRequestId requestId = 0;
|
mtpRequestId requestId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto pinningOld = IsOldForPin(msgId, peer);
|
const auto pinningOld = IsOldForPin(msgId, peer, MsgId(0));
|
||||||
const auto state = box->lifetime().make_state<State>();
|
const auto state = box->lifetime().make_state<State>();
|
||||||
const auto api = box->lifetime().make_state<MTP::Sender>(
|
const auto api = box->lifetime().make_state<MTP::Sender>(
|
||||||
&peer->session().mtp());
|
&peer->session().mtp());
|
||||||
|
|
|
@ -538,6 +538,7 @@ bool OpenMediaTimestamp(
|
||||||
controller,
|
controller,
|
||||||
document,
|
document,
|
||||||
session->data().message(itemId),
|
session->data().message(itemId),
|
||||||
|
MsgId(0), // #TODO forum shared media
|
||||||
false,
|
false,
|
||||||
timeMs));
|
timeMs));
|
||||||
} else if (document->isSong() || document->isVoiceMessage()) {
|
} else if (document->isSong() || document->isVoiceMessage()) {
|
||||||
|
|
|
@ -942,7 +942,7 @@ void ApplyChannelUpdate(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (const auto pinned = update.vpinned_msg_id()) {
|
if (const auto pinned = update.vpinned_msg_id()) {
|
||||||
SetTopPinnedMessageId(channel, pinned->v);
|
SetTopPinnedMessageId(channel, MsgId(0), pinned->v);
|
||||||
}
|
}
|
||||||
if (channel->isMegagroup()) {
|
if (channel->isMegagroup()) {
|
||||||
auto commands = ranges::views::all(
|
auto commands = ranges::views::all(
|
||||||
|
|
|
@ -474,7 +474,7 @@ void ApplyChatUpdate(not_null<ChatData*> chat, const MTPDchatFull &update) {
|
||||||
chat->session().api().inviteLinks().clearMyPermanent(chat);
|
chat->session().api().inviteLinks().clearMyPermanent(chat);
|
||||||
}
|
}
|
||||||
if (const auto pinned = update.vpinned_msg_id()) {
|
if (const auto pinned = update.vpinned_msg_id()) {
|
||||||
SetTopPinnedMessageId(chat, pinned->v);
|
SetTopPinnedMessageId(chat, MsgId(0), pinned->v);
|
||||||
}
|
}
|
||||||
chat->checkFolder(update.vfolder_id().value_or_empty());
|
chat->checkFolder(update.vfolder_id().value_or_empty());
|
||||||
chat->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
|
chat->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
|
||||||
|
|
|
@ -234,7 +234,8 @@ base::binary_guard ReadBackgroundImageAsync(
|
||||||
void ResolveDocument(
|
void ResolveDocument(
|
||||||
Window::SessionController *controller,
|
Window::SessionController *controller,
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
HistoryItem *item) {
|
HistoryItem *item,
|
||||||
|
MsgId topicRootId) {
|
||||||
if (document->isNull()) {
|
if (document->isNull()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -246,7 +247,7 @@ void ResolveDocument(
|
||||||
&& !document->filepath().isEmpty()) {
|
&& !document->filepath().isEmpty()) {
|
||||||
File::Launch(document->location(false).fname);
|
File::Launch(document->location(false).fname);
|
||||||
} else if (controller) {
|
} else if (controller) {
|
||||||
controller->openDocument(document, msgId, true);
|
controller->openDocument(document, msgId, topicRootId, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ base::binary_guard ReadBackgroundImageAsync(
|
||||||
void ResolveDocument(
|
void ResolveDocument(
|
||||||
Window::SessionController *controller,
|
Window::SessionController *controller,
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
HistoryItem *item);
|
HistoryItem *item,
|
||||||
|
MsgId topicRootId);
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -1203,7 +1203,10 @@ std::optional<QString> RestrictionError(
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetTopPinnedMessageId(not_null<PeerData*> peer, MsgId messageId) {
|
void SetTopPinnedMessageId(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
|
MsgId messageId) {
|
||||||
if (const auto channel = peer->asChannel()) {
|
if (const auto channel = peer->asChannel()) {
|
||||||
if (messageId <= channel->availableMinId()) {
|
if (messageId <= channel->availableMinId()) {
|
||||||
return;
|
return;
|
||||||
|
@ -1217,6 +1220,7 @@ void SetTopPinnedMessageId(not_null<PeerData*> peer, MsgId messageId) {
|
||||||
}
|
}
|
||||||
session.storage().add(Storage::SharedMediaAddExisting(
|
session.storage().add(Storage::SharedMediaAddExisting(
|
||||||
peer->id,
|
peer->id,
|
||||||
|
topicRootId,
|
||||||
Storage::SharedMediaType::Pinned,
|
Storage::SharedMediaType::Pinned,
|
||||||
messageId,
|
messageId,
|
||||||
{ messageId, ServerMaxMsgId }));
|
{ messageId, ServerMaxMsgId }));
|
||||||
|
@ -1225,20 +1229,23 @@ void SetTopPinnedMessageId(not_null<PeerData*> peer, MsgId messageId) {
|
||||||
|
|
||||||
FullMsgId ResolveTopPinnedId(
|
FullMsgId ResolveTopPinnedId(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
PeerData *migrated) {
|
PeerData *migrated) {
|
||||||
const auto slice = peer->session().storage().snapshot(
|
const auto slice = peer->session().storage().snapshot(
|
||||||
Storage::SharedMediaQuery(
|
Storage::SharedMediaQuery(
|
||||||
Storage::SharedMediaKey(
|
Storage::SharedMediaKey(
|
||||||
peer->id,
|
peer->id,
|
||||||
|
topicRootId,
|
||||||
Storage::SharedMediaType::Pinned,
|
Storage::SharedMediaType::Pinned,
|
||||||
ServerMaxMsgId - 1),
|
ServerMaxMsgId - 1),
|
||||||
1,
|
1,
|
||||||
1));
|
1));
|
||||||
const auto old = migrated
|
const auto old = (!topicRootId && migrated)
|
||||||
? migrated->session().storage().snapshot(
|
? migrated->session().storage().snapshot(
|
||||||
Storage::SharedMediaQuery(
|
Storage::SharedMediaQuery(
|
||||||
Storage::SharedMediaKey(
|
Storage::SharedMediaKey(
|
||||||
migrated->id,
|
migrated->id,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
Storage::SharedMediaType::Pinned,
|
Storage::SharedMediaType::Pinned,
|
||||||
ServerMaxMsgId - 1),
|
ServerMaxMsgId - 1),
|
||||||
1,
|
1,
|
||||||
|
@ -1259,20 +1266,23 @@ FullMsgId ResolveTopPinnedId(
|
||||||
|
|
||||||
FullMsgId ResolveMinPinnedId(
|
FullMsgId ResolveMinPinnedId(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
PeerData *migrated) {
|
PeerData *migrated) {
|
||||||
const auto slice = peer->session().storage().snapshot(
|
const auto slice = peer->session().storage().snapshot(
|
||||||
Storage::SharedMediaQuery(
|
Storage::SharedMediaQuery(
|
||||||
Storage::SharedMediaKey(
|
Storage::SharedMediaKey(
|
||||||
peer->id,
|
peer->id,
|
||||||
|
topicRootId,
|
||||||
Storage::SharedMediaType::Pinned,
|
Storage::SharedMediaType::Pinned,
|
||||||
1),
|
1),
|
||||||
1,
|
1,
|
||||||
1));
|
1));
|
||||||
const auto old = migrated
|
const auto old = (!topicRootId && migrated)
|
||||||
? migrated->session().storage().snapshot(
|
? migrated->session().storage().snapshot(
|
||||||
Storage::SharedMediaQuery(
|
Storage::SharedMediaQuery(
|
||||||
Storage::SharedMediaKey(
|
Storage::SharedMediaKey(
|
||||||
migrated->id,
|
migrated->id,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
Storage::SharedMediaType::Pinned,
|
Storage::SharedMediaType::Pinned,
|
||||||
1),
|
1),
|
||||||
1,
|
1,
|
||||||
|
@ -1291,34 +1301,4 @@ FullMsgId ResolveMinPinnedId(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<int> ResolvePinnedCount(
|
|
||||||
not_null<PeerData*> peer,
|
|
||||||
PeerData *migrated) {
|
|
||||||
const auto slice = peer->session().storage().snapshot(
|
|
||||||
Storage::SharedMediaQuery(
|
|
||||||
Storage::SharedMediaKey(
|
|
||||||
peer->id,
|
|
||||||
Storage::SharedMediaType::Pinned,
|
|
||||||
0),
|
|
||||||
0,
|
|
||||||
0));
|
|
||||||
const auto old = migrated
|
|
||||||
? migrated->session().storage().snapshot(
|
|
||||||
Storage::SharedMediaQuery(
|
|
||||||
Storage::SharedMediaKey(
|
|
||||||
migrated->id,
|
|
||||||
Storage::SharedMediaType::Pinned,
|
|
||||||
0),
|
|
||||||
0,
|
|
||||||
0))
|
|
||||||
: Storage::SharedMediaResult{
|
|
||||||
.count = 0,
|
|
||||||
.skippedBefore = 0,
|
|
||||||
.skippedAfter = 0,
|
|
||||||
};
|
|
||||||
return (slice.count.has_value() && old.count.has_value())
|
|
||||||
? std::make_optional(*slice.count + *old.count)
|
|
||||||
: std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -495,15 +495,17 @@ std::optional<QString> RestrictionError(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
UserRestriction restriction);
|
UserRestriction restriction);
|
||||||
|
|
||||||
void SetTopPinnedMessageId(not_null<PeerData*> peer, MsgId messageId);
|
void SetTopPinnedMessageId(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
|
MsgId messageId);
|
||||||
[[nodiscard]] FullMsgId ResolveTopPinnedId(
|
[[nodiscard]] FullMsgId ResolveTopPinnedId(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
PeerData *migrated);
|
PeerData *migrated);
|
||||||
[[nodiscard]] FullMsgId ResolveMinPinnedId(
|
[[nodiscard]] FullMsgId ResolveMinPinnedId(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
PeerData *migrated);
|
MsgId topicRootId,
|
||||||
[[nodiscard]] std::optional<int> ResolvePinnedCount(
|
|
||||||
not_null<PeerData*> peer,
|
|
||||||
PeerData *migrated);
|
PeerData *migrated);
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -30,8 +30,7 @@ constexpr auto kRequestTimeLimit = 60 * crl::time(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] MsgId LocalToRemoteMsgId(MsgId id) {
|
[[nodiscard]] MsgId LocalToRemoteMsgId(MsgId id) {
|
||||||
Expects(id > ServerMaxMsgId);
|
Expects(IsScheduledMsgId(id));
|
||||||
Expects(id < ServerMaxMsgId + ScheduledMsgIdsRange);
|
|
||||||
|
|
||||||
return (id - ServerMaxMsgId - 1);
|
return (id - ServerMaxMsgId - 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ constexpr auto kDefaultSearchTimeoutMs = crl::time(200);
|
||||||
|
|
||||||
std::optional<SearchRequest> PrepareSearchRequest(
|
std::optional<SearchRequest> PrepareSearchRequest(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
Storage::SharedMediaType type,
|
Storage::SharedMediaType type,
|
||||||
const QString &query,
|
const QString &query,
|
||||||
MsgId messageId,
|
MsgId messageId,
|
||||||
|
@ -90,12 +91,13 @@ std::optional<SearchRequest> PrepareSearchRequest(
|
||||||
offsetId.bare,
|
offsetId.bare,
|
||||||
int64(0),
|
int64(0),
|
||||||
int64(0x3FFFFFFF)));
|
int64(0x3FFFFFFF)));
|
||||||
|
using Flag = MTPmessages_Search::Flag;
|
||||||
return MTPmessages_Search(
|
return MTPmessages_Search(
|
||||||
MTP_flags(0),
|
MTP_flags(topicRootId ? Flag::f_top_msg_id : Flag(0)),
|
||||||
peer->input,
|
peer->input,
|
||||||
MTP_string(query),
|
MTP_string(query),
|
||||||
MTP_inputPeerEmpty(),
|
MTP_inputPeerEmpty(),
|
||||||
MTPint(), // top_msg_id
|
MTP_int(topicRootId),
|
||||||
filter,
|
filter,
|
||||||
MTP_int(0), // min_date
|
MTP_int(0), // min_date
|
||||||
MTP_int(0), // max_date
|
MTP_int(0), // max_date
|
||||||
|
@ -234,11 +236,13 @@ rpl::producer<SparseIdsMergedSlice> SearchController::idsSlice(
|
||||||
auto query = (const Query&)_current->first;
|
auto query = (const Query&)_current->first;
|
||||||
auto createSimpleViewer = [=](
|
auto createSimpleViewer = [=](
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
|
MsgId topicRootId,
|
||||||
SparseIdsSlice::Key simpleKey,
|
SparseIdsSlice::Key simpleKey,
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
int limitAfter) {
|
int limitAfter) {
|
||||||
return simpleIdsSlice(
|
return simpleIdsSlice(
|
||||||
peerId,
|
peerId,
|
||||||
|
topicRootId,
|
||||||
simpleKey,
|
simpleKey,
|
||||||
query,
|
query,
|
||||||
limitBefore,
|
limitBefore,
|
||||||
|
@ -247,6 +251,7 @@ rpl::producer<SparseIdsMergedSlice> SearchController::idsSlice(
|
||||||
return SparseIdsMergedSlice::CreateViewer(
|
return SparseIdsMergedSlice::CreateViewer(
|
||||||
SparseIdsMergedSlice::Key(
|
SparseIdsMergedSlice::Key(
|
||||||
query.peerId,
|
query.peerId,
|
||||||
|
query.topicRootId,
|
||||||
query.migratedPeerId,
|
query.migratedPeerId,
|
||||||
aroundId),
|
aroundId),
|
||||||
limitBefore,
|
limitBefore,
|
||||||
|
@ -256,6 +261,7 @@ rpl::producer<SparseIdsMergedSlice> SearchController::idsSlice(
|
||||||
|
|
||||||
rpl::producer<SparseIdsSlice> SearchController::simpleIdsSlice(
|
rpl::producer<SparseIdsSlice> SearchController::simpleIdsSlice(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
|
MsgId topicRootId,
|
||||||
MsgId aroundId,
|
MsgId aroundId,
|
||||||
const Query &query,
|
const Query &query,
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
|
@ -264,8 +270,8 @@ rpl::producer<SparseIdsSlice> SearchController::simpleIdsSlice(
|
||||||
Expects(IsServerMsgId(aroundId) || (aroundId == 0));
|
Expects(IsServerMsgId(aroundId) || (aroundId == 0));
|
||||||
Expects((aroundId != 0)
|
Expects((aroundId != 0)
|
||||||
|| (limitBefore == 0 && limitAfter == 0));
|
|| (limitBefore == 0 && limitAfter == 0));
|
||||||
Expects((query.peerId == peerId)
|
Expects((query.peerId == peerId && query.topicRootId == topicRootId)
|
||||||
|| (query.migratedPeerId == peerId));
|
|| (query.migratedPeerId == peerId && MsgId(0) == topicRootId));
|
||||||
|
|
||||||
auto it = _cache.find(query);
|
auto it = _cache.find(query);
|
||||||
if (it == _cache.end()) {
|
if (it == _cache.end()) {
|
||||||
|
@ -298,7 +304,8 @@ rpl::producer<SparseIdsSlice> SearchController::simpleIdsSlice(
|
||||||
|
|
||||||
_session->data().itemRemoved(
|
_session->data().itemRemoved(
|
||||||
) | rpl::filter([=](not_null<const HistoryItem*> item) {
|
) | rpl::filter([=](not_null<const HistoryItem*> item) {
|
||||||
return (item->history()->peer->id == peerId);
|
return (item->history()->peer->id == peerId)
|
||||||
|
&& (!topicRootId || item->topicRootId() == topicRootId);
|
||||||
}) | rpl::filter([=](not_null<const HistoryItem*> item) {
|
}) | rpl::filter([=](not_null<const HistoryItem*> item) {
|
||||||
return builder->removeOne(item->id);
|
return builder->removeOne(item->id);
|
||||||
}) | rpl::start_with_next(pushNextSnapshot, lifetime);
|
}) | rpl::start_with_next(pushNextSnapshot, lifetime);
|
||||||
|
@ -370,6 +377,7 @@ void SearchController::requestMore(
|
||||||
}
|
}
|
||||||
auto prepared = PrepareSearchRequest(
|
auto prepared = PrepareSearchRequest(
|
||||||
listData->peer,
|
listData->peer,
|
||||||
|
query.topicRootId,
|
||||||
query.type,
|
query.type,
|
||||||
query.query,
|
query.query,
|
||||||
key.aroundId,
|
key.aroundId,
|
||||||
|
|
|
@ -34,6 +34,7 @@ using SearchRequestResult = MTPmessages_Messages;
|
||||||
|
|
||||||
std::optional<SearchRequest> PrepareSearchRequest(
|
std::optional<SearchRequest> PrepareSearchRequest(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
Storage::SharedMediaType type,
|
Storage::SharedMediaType type,
|
||||||
const QString &query,
|
const QString &query,
|
||||||
MsgId messageId,
|
MsgId messageId,
|
||||||
|
@ -53,6 +54,7 @@ public:
|
||||||
using MediaType = Storage::SharedMediaType;
|
using MediaType = Storage::SharedMediaType;
|
||||||
|
|
||||||
PeerId peerId = 0;
|
PeerId peerId = 0;
|
||||||
|
MsgId topicRootId = 0;
|
||||||
PeerId migratedPeerId = 0;
|
PeerId migratedPeerId = 0;
|
||||||
MediaType type = MediaType::kCount;
|
MediaType type = MediaType::kCount;
|
||||||
QString query;
|
QString query;
|
||||||
|
@ -75,6 +77,7 @@ public:
|
||||||
|
|
||||||
Query query() const {
|
Query query() const {
|
||||||
Expects(_current != _cache.cend());
|
Expects(_current != _cache.cend());
|
||||||
|
|
||||||
return _current->first;
|
return _current->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,18 +109,11 @@ private:
|
||||||
std::optional<Data> migratedData;
|
std::optional<Data> migratedData;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CacheLess {
|
using Cache = base::flat_map<Query, std::unique_ptr<CacheEntry>>;
|
||||||
inline bool operator()(const Query &a, const Query &b) const {
|
|
||||||
return (a < b);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
using Cache = base::flat_map<
|
|
||||||
Query,
|
|
||||||
std::unique_ptr<CacheEntry>,
|
|
||||||
CacheLess>;
|
|
||||||
|
|
||||||
rpl::producer<SparseIdsSlice> simpleIdsSlice(
|
rpl::producer<SparseIdsSlice> simpleIdsSlice(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
|
MsgId topicRootId,
|
||||||
MsgId aroundId,
|
MsgId aroundId,
|
||||||
const Query &query,
|
const Query &query,
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
|
|
|
@ -109,10 +109,12 @@ rpl::producer<SparseIdsSlice> SharedMediaViewer(
|
||||||
limitAfter);
|
limitAfter);
|
||||||
auto requestMediaAround = [
|
auto requestMediaAround = [
|
||||||
peer = session->data().peer(key.peerId),
|
peer = session->data().peer(key.peerId),
|
||||||
|
topicRootId = key.topicRootId,
|
||||||
type = key.type
|
type = key.type
|
||||||
](const SparseIdsSliceBuilder::AroundData &data) {
|
](const SparseIdsSliceBuilder::AroundData &data) {
|
||||||
peer->session().api().requestSharedMedia(
|
peer->session().api().requestSharedMedia(
|
||||||
peer,
|
peer,
|
||||||
|
topicRootId,
|
||||||
type,
|
type,
|
||||||
data.aroundId,
|
data.aroundId,
|
||||||
data.direction);
|
data.direction);
|
||||||
|
@ -128,6 +130,7 @@ rpl::producer<SparseIdsSlice> SharedMediaViewer(
|
||||||
session->storage().sharedMediaSliceUpdated(
|
session->storage().sharedMediaSliceUpdated(
|
||||||
) | rpl::filter([=](const SliceUpdate &update) {
|
) | rpl::filter([=](const SliceUpdate &update) {
|
||||||
return (update.peerId == key.peerId)
|
return (update.peerId == key.peerId)
|
||||||
|
&& (update.topicRootId == key.topicRootId)
|
||||||
&& (update.type == key.type);
|
&& (update.type == key.type);
|
||||||
}) | rpl::filter([=](const SliceUpdate &update) {
|
}) | rpl::filter([=](const SliceUpdate &update) {
|
||||||
return builder->applyUpdate(update.data);
|
return builder->applyUpdate(update.data);
|
||||||
|
@ -146,7 +149,7 @@ rpl::producer<SparseIdsSlice> SharedMediaViewer(
|
||||||
session->storage().sharedMediaAllRemoved(
|
session->storage().sharedMediaAllRemoved(
|
||||||
) | rpl::filter([=](const AllRemoved &update) {
|
) | rpl::filter([=](const AllRemoved &update) {
|
||||||
return (update.peerId == key.peerId)
|
return (update.peerId == key.peerId)
|
||||||
&& (update.types.test(key.type));
|
&& update.types.test(key.type);
|
||||||
}) | rpl::filter([=] {
|
}) | rpl::filter([=] {
|
||||||
return builder->removeAll();
|
return builder->removeAll();
|
||||||
}) | rpl::start_with_next(pushNextSnapshot, lifetime);
|
}) | rpl::start_with_next(pushNextSnapshot, lifetime);
|
||||||
|
@ -229,6 +232,7 @@ rpl::producer<SparseIdsMergedSlice> SharedMediaMergedViewer(
|
||||||
int limitAfter) {
|
int limitAfter) {
|
||||||
auto createSimpleViewer = [=](
|
auto createSimpleViewer = [=](
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
|
MsgId topicRootId,
|
||||||
SparseIdsSlice::Key simpleKey,
|
SparseIdsSlice::Key simpleKey,
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
int limitAfter) {
|
int limitAfter) {
|
||||||
|
@ -236,6 +240,7 @@ rpl::producer<SparseIdsMergedSlice> SharedMediaMergedViewer(
|
||||||
session,
|
session,
|
||||||
Storage::SharedMediaKey(
|
Storage::SharedMediaKey(
|
||||||
peerId,
|
peerId,
|
||||||
|
topicRootId,
|
||||||
key.type,
|
key.type,
|
||||||
simpleKey),
|
simpleKey),
|
||||||
limitBefore,
|
limitBefore,
|
||||||
|
@ -462,7 +467,7 @@ rpl::producer<SharedMediaWithLastSlice> SharedMediaWithLastViewer(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.scheduled) {
|
if (key.topicRootId == SharedMediaWithLastSlice::kScheduledTopicId) {
|
||||||
return SharedScheduledMediaViewer(
|
return SharedScheduledMediaViewer(
|
||||||
session,
|
session,
|
||||||
std::move(viewerKey),
|
std::move(viewerKey),
|
||||||
|
|
|
@ -67,36 +67,32 @@ public:
|
||||||
MessageId,
|
MessageId,
|
||||||
not_null<PhotoData*>>;
|
not_null<PhotoData*>>;
|
||||||
|
|
||||||
|
static constexpr auto kScheduledTopicId
|
||||||
|
= SparseIdsMergedSlice::kScheduledTopicId;
|
||||||
struct Key {
|
struct Key {
|
||||||
Key(
|
Key(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
|
MsgId topicRootId,
|
||||||
PeerId migratedPeerId,
|
PeerId migratedPeerId,
|
||||||
Type type,
|
Type type,
|
||||||
UniversalMsgId universalId,
|
UniversalMsgId universalId)
|
||||||
bool scheduled = false)
|
|
||||||
: peerId(peerId)
|
: peerId(peerId)
|
||||||
|
, topicRootId(topicRootId)
|
||||||
, migratedPeerId(migratedPeerId)
|
, migratedPeerId(migratedPeerId)
|
||||||
, type(type)
|
, type(type)
|
||||||
, universalId(universalId)
|
, universalId(universalId) {
|
||||||
, scheduled(scheduled) {
|
|
||||||
Expects(v::is<MessageId>(universalId) || type == Type::ChatPhoto);
|
Expects(v::is<MessageId>(universalId) || type == Type::ChatPhoto);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Key &other) const {
|
friend inline constexpr auto operator<=>(
|
||||||
return (peerId == other.peerId)
|
const Key&,
|
||||||
&& (migratedPeerId == other.migratedPeerId)
|
const Key&) = default;
|
||||||
&& (type == other.type)
|
|
||||||
&& (universalId == other.universalId);
|
|
||||||
}
|
|
||||||
bool operator!=(const Key &other) const {
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
PeerId peerId = 0;
|
PeerId peerId = 0;
|
||||||
|
MsgId topicRootId = 0;
|
||||||
PeerId migratedPeerId = 0;
|
PeerId migratedPeerId = 0;
|
||||||
Type type = Type::kCount;
|
Type type = Type::kCount;
|
||||||
UniversalMsgId universalId;
|
UniversalMsgId universalId;
|
||||||
bool scheduled = false;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,6 +118,7 @@ public:
|
||||||
static SparseIdsMergedSlice::Key ViewerKey(const Key &key) {
|
static SparseIdsMergedSlice::Key ViewerKey(const Key &key) {
|
||||||
return {
|
return {
|
||||||
key.peerId,
|
key.peerId,
|
||||||
|
key.topicRootId,
|
||||||
key.migratedPeerId,
|
key.migratedPeerId,
|
||||||
v::is<MessageId>(key.universalId)
|
v::is<MessageId>(key.universalId)
|
||||||
? v::get<MessageId>(key.universalId)
|
? v::get<MessageId>(key.universalId)
|
||||||
|
@ -131,6 +128,7 @@ public:
|
||||||
static SparseIdsMergedSlice::Key EndingKey(const Key &key) {
|
static SparseIdsMergedSlice::Key EndingKey(const Key &key) {
|
||||||
return {
|
return {
|
||||||
key.peerId,
|
key.peerId,
|
||||||
|
key.topicRootId,
|
||||||
key.migratedPeerId,
|
key.migratedPeerId,
|
||||||
ServerMaxMsgId - 1
|
ServerMaxMsgId - 1
|
||||||
};
|
};
|
||||||
|
|
|
@ -377,6 +377,7 @@ rpl::producer<SparseIdsMergedSlice> SparseIdsMergedSlice::CreateViewer(
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
int limitAfter,
|
int limitAfter,
|
||||||
Fn<SimpleViewerFunction> simpleViewer) {
|
Fn<SimpleViewerFunction> simpleViewer) {
|
||||||
|
Expects(!key.topicRootId || !key.migratedPeerId);
|
||||||
Expects(IsServerMsgId(key.universalId)
|
Expects(IsServerMsgId(key.universalId)
|
||||||
|| (key.universalId == 0)
|
|| (key.universalId == 0)
|
||||||
|| (IsServerMsgId(ServerMaxMsgId + key.universalId) && key.migratedPeerId != 0));
|
|| (IsServerMsgId(ServerMaxMsgId + key.universalId) && key.migratedPeerId != 0));
|
||||||
|
@ -386,6 +387,7 @@ rpl::producer<SparseIdsMergedSlice> SparseIdsMergedSlice::CreateViewer(
|
||||||
return [=](auto consumer) {
|
return [=](auto consumer) {
|
||||||
auto partViewer = simpleViewer(
|
auto partViewer = simpleViewer(
|
||||||
key.peerId,
|
key.peerId,
|
||||||
|
key.topicRootId,
|
||||||
SparseIdsMergedSlice::PartKey(key),
|
SparseIdsMergedSlice::PartKey(key),
|
||||||
limitBefore,
|
limitBefore,
|
||||||
limitAfter
|
limitAfter
|
||||||
|
@ -402,6 +404,7 @@ rpl::producer<SparseIdsMergedSlice> SparseIdsMergedSlice::CreateViewer(
|
||||||
}
|
}
|
||||||
auto migratedViewer = simpleViewer(
|
auto migratedViewer = simpleViewer(
|
||||||
key.migratedPeerId,
|
key.migratedPeerId,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
SparseIdsMergedSlice::MigratedKey(key),
|
SparseIdsMergedSlice::MigratedKey(key),
|
||||||
limitBefore,
|
limitBefore,
|
||||||
limitAfter);
|
limitAfter);
|
||||||
|
|
|
@ -27,32 +27,29 @@ using SparseUnsortedIdsSlice = AbstractSparseIds<std::vector<MsgId>>;
|
||||||
class SparseIdsMergedSlice {
|
class SparseIdsMergedSlice {
|
||||||
public:
|
public:
|
||||||
using UniversalMsgId = MsgId;
|
using UniversalMsgId = MsgId;
|
||||||
|
static constexpr MsgId kScheduledTopicId
|
||||||
|
= ServerMaxMsgId + ScheduledMsgIdsRange;
|
||||||
|
|
||||||
struct Key {
|
struct Key {
|
||||||
Key(
|
Key(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
|
MsgId topicRootId,
|
||||||
PeerId migratedPeerId,
|
PeerId migratedPeerId,
|
||||||
UniversalMsgId universalId,
|
UniversalMsgId universalId)
|
||||||
bool scheduled = false)
|
|
||||||
: peerId(peerId)
|
: peerId(peerId)
|
||||||
, scheduled(scheduled)
|
, topicRootId(topicRootId)
|
||||||
, migratedPeerId(scheduled ? 0 : migratedPeerId)
|
, migratedPeerId(topicRootId ? 0 : migratedPeerId)
|
||||||
, universalId(universalId) {
|
, universalId(universalId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Key &other) const {
|
friend inline constexpr bool operator==(
|
||||||
return (peerId == other.peerId)
|
const Key &,
|
||||||
&& (migratedPeerId == other.migratedPeerId)
|
const Key &) = default;
|
||||||
&& (universalId == other.universalId);
|
|
||||||
}
|
|
||||||
bool operator!=(const Key &other) const {
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
PeerId peerId = 0;
|
PeerId peerId = 0;
|
||||||
bool scheduled = false;
|
MsgId topicRootId = 0;
|
||||||
PeerId migratedPeerId = 0;
|
PeerId migratedPeerId = 0;
|
||||||
UniversalMsgId universalId = 0;
|
UniversalMsgId universalId = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SparseIdsMergedSlice(Key key);
|
SparseIdsMergedSlice(Key key);
|
||||||
|
@ -75,6 +72,7 @@ public:
|
||||||
|
|
||||||
using SimpleViewerFunction = rpl::producer<SparseIdsSlice>(
|
using SimpleViewerFunction = rpl::producer<SparseIdsSlice>(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
|
MsgId topicRootId,
|
||||||
SparseIdsSlice::Key simpleKey,
|
SparseIdsSlice::Key simpleKey,
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
int limitAfter);
|
int limitAfter);
|
||||||
|
|
|
@ -331,7 +331,7 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
|
||||||
user->setBotInfoVersion(-1);
|
user->setBotInfoVersion(-1);
|
||||||
}
|
}
|
||||||
if (const auto pinned = update.vpinned_msg_id()) {
|
if (const auto pinned = update.vpinned_msg_id()) {
|
||||||
SetTopPinnedMessageId(user, pinned->v);
|
SetTopPinnedMessageId(user, MsgId(0), pinned->v);
|
||||||
}
|
}
|
||||||
const auto canReceiveGifts = (update.vflags().v
|
const auto canReceiveGifts = (update.vflags().v
|
||||||
& MTPDuserFull::Flag::f_premium_gifts)
|
& MTPDuserFull::Flag::f_premium_gifts)
|
||||||
|
|
|
@ -624,14 +624,14 @@ void InnerWidget::elementShowPollResults(
|
||||||
void InnerWidget::elementOpenPhoto(
|
void InnerWidget::elementOpenPhoto(
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
FullMsgId context) {
|
FullMsgId context) {
|
||||||
_controller->openPhoto(photo, context);
|
_controller->openPhoto(photo, context, MsgId(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::elementOpenDocument(
|
void InnerWidget::elementOpenDocument(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
FullMsgId context,
|
FullMsgId context,
|
||||||
bool showInMediaView) {
|
bool showInMediaView) {
|
||||||
_controller->openDocument(document, context, showInMediaView);
|
_controller->openDocument(document, context, MsgId(0), showInMediaView);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::elementCancelUpload(const FullMsgId &context) {
|
void InnerWidget::elementCancelUpload(const FullMsgId &context) {
|
||||||
|
@ -1378,7 +1378,7 @@ void InnerWidget::openContextGif(FullMsgId itemId) {
|
||||||
if (const auto item = session().data().message(itemId)) {
|
if (const auto item = session().data().message(itemId)) {
|
||||||
if (const auto media = item->media()) {
|
if (const auto media = item->media()) {
|
||||||
if (const auto document = media->document()) {
|
if (const auto document = media->document()) {
|
||||||
_controller->openDocument(document, itemId, true);
|
_controller->openDocument(document, itemId, MsgId(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -778,6 +778,7 @@ not_null<HistoryItem*> History::addNewToBack(
|
||||||
auto till = loadedAtBottom() ? ServerMaxMsgId : maxMsgId();
|
auto till = loadedAtBottom() ? ServerMaxMsgId : maxMsgId();
|
||||||
session().storage().add(Storage::SharedMediaAddExisting(
|
session().storage().add(Storage::SharedMediaAddExisting(
|
||||||
peer->id,
|
peer->id,
|
||||||
|
MsgId(0),
|
||||||
sharedMediaTypes,
|
sharedMediaTypes,
|
||||||
item->id,
|
item->id,
|
||||||
{ from, till }));
|
{ from, till }));
|
||||||
|
@ -1047,6 +1048,7 @@ void History::applyServiceChanges(
|
||||||
if (item) {
|
if (item) {
|
||||||
session().storage().add(Storage::SharedMediaAddSlice(
|
session().storage().add(Storage::SharedMediaAddSlice(
|
||||||
peer->id,
|
peer->id,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
Storage::SharedMediaType::Pinned,
|
Storage::SharedMediaType::Pinned,
|
||||||
{ id },
|
{ id },
|
||||||
{ id, ServerMaxMsgId }));
|
{ id, ServerMaxMsgId }));
|
||||||
|
@ -1268,6 +1270,7 @@ void History::addEdgesToSharedMedia() {
|
||||||
const auto type = static_cast<Storage::SharedMediaType>(i);
|
const auto type = static_cast<Storage::SharedMediaType>(i);
|
||||||
session().storage().add(Storage::SharedMediaAddSlice(
|
session().storage().add(Storage::SharedMediaAddSlice(
|
||||||
peer->id,
|
peer->id,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
type,
|
type,
|
||||||
{},
|
{},
|
||||||
{ from, till }));
|
{ from, till }));
|
||||||
|
@ -1460,6 +1463,7 @@ void History::addToSharedMedia(
|
||||||
const auto type = static_cast<Storage::SharedMediaType>(i);
|
const auto type = static_cast<Storage::SharedMediaType>(i);
|
||||||
session().storage().add(Storage::SharedMediaAddSlice(
|
session().storage().add(Storage::SharedMediaAddSlice(
|
||||||
peer->id,
|
peer->id,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
type,
|
type,
|
||||||
std::move(medias[i]),
|
std::move(medias[i]),
|
||||||
{ from, till }));
|
{ from, till }));
|
||||||
|
|
|
@ -2596,7 +2596,7 @@ void HistoryInner::openContextGif(FullMsgId itemId) {
|
||||||
if (const auto item = session().data().message(itemId)) {
|
if (const auto item = session().data().message(itemId)) {
|
||||||
if (const auto media = item->media()) {
|
if (const auto media = item->media()) {
|
||||||
if (const auto document = media->document()) {
|
if (const auto document = media->document()) {
|
||||||
_controller->openDocument(document, itemId, true);
|
_controller->openDocument(document, itemId, MsgId(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3248,14 +3248,14 @@ void HistoryInner::elementShowPollResults(
|
||||||
void HistoryInner::elementOpenPhoto(
|
void HistoryInner::elementOpenPhoto(
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
FullMsgId context) {
|
FullMsgId context) {
|
||||||
_controller->openPhoto(photo, context);
|
_controller->openPhoto(photo, context, MsgId(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::elementOpenDocument(
|
void HistoryInner::elementOpenDocument(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
FullMsgId context,
|
FullMsgId context,
|
||||||
bool showInMediaView) {
|
bool showInMediaView) {
|
||||||
_controller->openDocument(document, context, showInMediaView);
|
_controller->openDocument(document, context, MsgId(0), showInMediaView);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::elementCancelUpload(const FullMsgId &context) {
|
void HistoryInner::elementCancelUpload(const FullMsgId &context) {
|
||||||
|
|
|
@ -482,6 +482,7 @@ void HistoryItem::setIsPinned(bool pinned) {
|
||||||
_flags |= MessageFlag::Pinned;
|
_flags |= MessageFlag::Pinned;
|
||||||
history()->session().storage().add(Storage::SharedMediaAddExisting(
|
history()->session().storage().add(Storage::SharedMediaAddExisting(
|
||||||
history()->peer->id,
|
history()->peer->id,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
Storage::SharedMediaType::Pinned,
|
Storage::SharedMediaType::Pinned,
|
||||||
id,
|
id,
|
||||||
{ id, id }));
|
{ id, id }));
|
||||||
|
|
|
@ -1464,9 +1464,9 @@ void HistoryWidget::applyInlineBotQuery(UserData *bot, const QString &query) {
|
||||||
if (result.open) {
|
if (result.open) {
|
||||||
const auto request = result.result->openRequest();
|
const auto request = result.result->openRequest();
|
||||||
if (const auto photo = request.photo()) {
|
if (const auto photo = request.photo()) {
|
||||||
controller()->openPhoto(photo, FullMsgId());
|
controller()->openPhoto(photo, {}, {});
|
||||||
} else if (const auto document = request.document()) {
|
} else if (const auto document = request.document()) {
|
||||||
controller()->openDocument(document, FullMsgId());
|
controller()->openDocument(document, {}, {});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sendInlineResult(result);
|
sendInlineResult(result);
|
||||||
|
@ -6138,6 +6138,7 @@ void HistoryWidget::updatePinnedViewer() {
|
||||||
if (_pinnedClickedId && !_minPinnedId) {
|
if (_pinnedClickedId && !_minPinnedId) {
|
||||||
_minPinnedId = Data::ResolveMinPinnedId(
|
_minPinnedId = Data::ResolveMinPinnedId(
|
||||||
_peer,
|
_peer,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
_migrated ? _migrated->peer.get() : nullptr);
|
_migrated ? _migrated->peer.get() : nullptr);
|
||||||
}
|
}
|
||||||
if (_pinnedClickedId && _minPinnedId && _minPinnedId >= _pinnedClickedId) {
|
if (_pinnedClickedId && _minPinnedId && _minPinnedId >= _pinnedClickedId) {
|
||||||
|
@ -6183,6 +6184,7 @@ void HistoryWidget::checkPinnedBarState() {
|
||||||
: session().settings().hiddenPinnedMessageId(_peer->id);
|
: session().settings().hiddenPinnedMessageId(_peer->id);
|
||||||
const auto currentPinnedId = Data::ResolveTopPinnedId(
|
const auto currentPinnedId = Data::ResolveTopPinnedId(
|
||||||
_peer,
|
_peer,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
_migrated ? _migrated->peer.get() : nullptr);
|
_migrated ? _migrated->peer.get() : nullptr);
|
||||||
const auto universalPinnedId = !currentPinnedId
|
const auto universalPinnedId = !currentPinnedId
|
||||||
? int32(0)
|
? int32(0)
|
||||||
|
@ -6217,6 +6219,7 @@ void HistoryWidget::checkPinnedBarState() {
|
||||||
});
|
});
|
||||||
auto pinnedRefreshed = Info::Profile::SharedMediaCountValue(
|
auto pinnedRefreshed = Info::Profile::SharedMediaCountValue(
|
||||||
_peer,
|
_peer,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
nullptr,
|
nullptr,
|
||||||
Storage::SharedMediaType::Pinned
|
Storage::SharedMediaType::Pinned
|
||||||
) | rpl::distinct_until_changed(
|
) | rpl::distinct_until_changed(
|
||||||
|
|
|
@ -2662,9 +2662,9 @@ void ComposeControls::applyInlineBotQuery(
|
||||||
if (result.open) {
|
if (result.open) {
|
||||||
const auto request = result.result->openRequest();
|
const auto request = result.result->openRequest();
|
||||||
if (const auto photo = request.photo()) {
|
if (const auto photo = request.photo()) {
|
||||||
_window->openPhoto(photo, FullMsgId());
|
_window->openPhoto(photo, {}, {});
|
||||||
} else if (const auto document = request.document()) {
|
} else if (const auto document = request.document()) {
|
||||||
_window->openDocument(document, FullMsgId());
|
_window->openDocument(document, {}, {});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_inlineResultChosen.fire_copy(result);
|
_inlineResultChosen.fire_copy(result);
|
||||||
|
|
|
@ -189,13 +189,12 @@ void SaveGif(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGif(
|
void OpenGif(not_null<ListWidget*> list, FullMsgId itemId) {
|
||||||
not_null<Window::SessionController*> controller,
|
const auto controller = list->controller();
|
||||||
FullMsgId itemId) {
|
|
||||||
if (const auto item = controller->session().data().message(itemId)) {
|
if (const auto item = controller->session().data().message(itemId)) {
|
||||||
if (const auto media = item->media()) {
|
if (const auto media = item->media()) {
|
||||||
if (const auto document = media->document()) {
|
if (const auto document = media->document()) {
|
||||||
controller->openDocument(document, itemId, true);
|
list->elementOpenDocument(document, itemId, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,8 +260,11 @@ void AddDocumentActions(
|
||||||
item->history()->peer,
|
item->history()->peer,
|
||||||
document);
|
document);
|
||||||
if (notAutoplayedGif) {
|
if (notAutoplayedGif) {
|
||||||
|
const auto weak = Ui::MakeWeak(list.get());
|
||||||
menu->addAction(tr::lng_context_open_gif(tr::now), [=] {
|
menu->addAction(tr::lng_context_open_gif(tr::now), [=] {
|
||||||
OpenGif(list->controller(), contextId);
|
if (const auto strong = weak.data()) {
|
||||||
|
OpenGif(strong, contextId);
|
||||||
|
}
|
||||||
}, &st::menuIconShowInChat);
|
}, &st::menuIconShowInChat);
|
||||||
}
|
}
|
||||||
if (!list->hasCopyRestriction(item)) {
|
if (!list->hasCopyRestriction(item)) {
|
||||||
|
|
|
@ -1549,14 +1549,14 @@ void ListWidget::elementShowPollResults(
|
||||||
void ListWidget::elementOpenPhoto(
|
void ListWidget::elementOpenPhoto(
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
FullMsgId context) {
|
FullMsgId context) {
|
||||||
_controller->openPhoto(photo, context);
|
_delegate->listOpenPhoto(photo, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::elementOpenDocument(
|
void ListWidget::elementOpenDocument(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
FullMsgId context,
|
FullMsgId context,
|
||||||
bool showInMediaView) {
|
bool showInMediaView) {
|
||||||
_controller->openDocument(document, context, showInMediaView);
|
_delegate->listOpenDocument(document, context, showInMediaView);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::elementCancelUpload(const FullMsgId &context) {
|
void ListWidget::elementCancelUpload(const FullMsgId &context) {
|
||||||
|
|
|
@ -125,6 +125,13 @@ public:
|
||||||
virtual auto listAllowedReactionsValue()
|
virtual auto listAllowedReactionsValue()
|
||||||
-> rpl::producer<Data::AllowedReactions> = 0;
|
-> rpl::producer<Data::AllowedReactions> = 0;
|
||||||
virtual void listShowPremiumToast(not_null<DocumentData*> document) = 0;
|
virtual void listShowPremiumToast(not_null<DocumentData*> document) = 0;
|
||||||
|
virtual void listOpenPhoto(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
FullMsgId context) = 0;
|
||||||
|
virtual void listOpenDocument(
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
FullMsgId context,
|
||||||
|
bool showInMediaView) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SelectionData {
|
struct SelectionData {
|
||||||
|
|
|
@ -453,28 +453,6 @@ void PinnedWidget::listDeleteRequest() {
|
||||||
confirmDeleteSelected();
|
confirmDeleteSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<int> SharedMediaCountValue(
|
|
||||||
not_null<PeerData*> peer,
|
|
||||||
PeerData *migrated,
|
|
||||||
Storage::SharedMediaType type) {
|
|
||||||
auto aroundId = 0;
|
|
||||||
auto limit = 0;
|
|
||||||
auto updated = SharedMediaMergedViewer(
|
|
||||||
&peer->session(),
|
|
||||||
SharedMediaMergedKey(
|
|
||||||
SparseIdsMergedSlice::Key(
|
|
||||||
peer->id,
|
|
||||||
migrated ? migrated->id : 0,
|
|
||||||
aroundId),
|
|
||||||
type),
|
|
||||||
limit,
|
|
||||||
limit
|
|
||||||
) | rpl::map([](const SparseIdsMergedSlice &slice) {
|
|
||||||
return slice.fullCount();
|
|
||||||
}) | rpl::filter_optional();
|
|
||||||
return rpl::single(0) | rpl::then(std::move(updated));
|
|
||||||
}
|
|
||||||
|
|
||||||
rpl::producer<Data::MessagesSlice> PinnedWidget::listSource(
|
rpl::producer<Data::MessagesSlice> PinnedWidget::listSource(
|
||||||
Data::MessagePosition aroundId,
|
Data::MessagePosition aroundId,
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
|
@ -488,6 +466,7 @@ rpl::producer<Data::MessagesSlice> PinnedWidget::listSource(
|
||||||
SharedMediaMergedKey(
|
SharedMediaMergedKey(
|
||||||
SparseIdsMergedSlice::Key(
|
SparseIdsMergedSlice::Key(
|
||||||
_history->peer->id,
|
_history->peer->id,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
_migratedPeer ? _migratedPeer->id : 0,
|
_migratedPeer ? _migratedPeer->id : 0,
|
||||||
messageId),
|
messageId),
|
||||||
Storage::SharedMediaType::Pinned),
|
Storage::SharedMediaType::Pinned),
|
||||||
|
@ -611,6 +590,19 @@ auto PinnedWidget::listAllowedReactionsValue()
|
||||||
void PinnedWidget::listShowPremiumToast(not_null<DocumentData*> document) {
|
void PinnedWidget::listShowPremiumToast(not_null<DocumentData*> document) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PinnedWidget::listOpenPhoto(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
FullMsgId context) {
|
||||||
|
controller()->openPhoto(photo, context, MsgId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PinnedWidget::listOpenDocument(
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
FullMsgId context,
|
||||||
|
bool showInMediaView) {
|
||||||
|
controller()->openDocument(document, context, MsgId(), showInMediaView);
|
||||||
|
}
|
||||||
|
|
||||||
void PinnedWidget::confirmDeleteSelected() {
|
void PinnedWidget::confirmDeleteSelected() {
|
||||||
ConfirmDeleteSelectedItems(_inner);
|
ConfirmDeleteSelectedItems(_inner);
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,13 @@ public:
|
||||||
auto listAllowedReactionsValue()
|
auto listAllowedReactionsValue()
|
||||||
-> rpl::producer<Data::AllowedReactions> override;
|
-> rpl::producer<Data::AllowedReactions> override;
|
||||||
void listShowPremiumToast(not_null<DocumentData*> document) override;
|
void listShowPremiumToast(not_null<DocumentData*> document) override;
|
||||||
|
void listOpenPhoto(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
FullMsgId context) override;
|
||||||
|
void listOpenDocument(
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
FullMsgId context,
|
||||||
|
bool showInMediaView) override;
|
||||||
|
|
||||||
// CornerButtonsDelegate delegate.
|
// CornerButtonsDelegate delegate.
|
||||||
void cornerButtonsShowAtPosition(
|
void cornerButtonsShowAtPosition(
|
||||||
|
|
|
@ -82,6 +82,7 @@ void PinnedTracker::refreshViewer() {
|
||||||
SharedMediaMergedKey(
|
SharedMediaMergedKey(
|
||||||
SparseIdsMergedSlice::Key(
|
SparseIdsMergedSlice::Key(
|
||||||
_history->peer->id,
|
_history->peer->id,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
_migratedPeer ? _migratedPeer->id : 0,
|
_migratedPeer ? _migratedPeer->id : 0,
|
||||||
_viewerAroundId),
|
_viewerAroundId),
|
||||||
Storage::SharedMediaType::Pinned),
|
Storage::SharedMediaType::Pinned),
|
||||||
|
|
|
@ -233,7 +233,6 @@ RepliesWidget::RepliesWidget(
|
||||||
|
|
||||||
setupRoot();
|
setupRoot();
|
||||||
setupRootView();
|
setupRootView();
|
||||||
setupTopicViewer();
|
|
||||||
|
|
||||||
session().api().requestFullPeer(_history->peer);
|
session().api().requestFullPeer(_history->peer);
|
||||||
|
|
||||||
|
@ -339,14 +338,17 @@ RepliesWidget::RepliesWidget(
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
_history->session().changes().historyUpdates(
|
if (!_topic) {
|
||||||
_history,
|
_history->session().changes().historyUpdates(
|
||||||
Data::HistoryUpdate::Flag::OutboxRead
|
_history,
|
||||||
) | rpl::start_with_next([=] {
|
Data::HistoryUpdate::Flag::OutboxRead
|
||||||
_inner->update();
|
) | rpl::start_with_next([=] {
|
||||||
}, lifetime());
|
_inner->update();
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
setupComposeControls();
|
setupComposeControls();
|
||||||
|
setupTopicViewer();
|
||||||
orderWidgets();
|
orderWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -890,6 +892,7 @@ void RepliesWidget::sendingFilesConfirmed(
|
||||||
_composeControls->cancelReplyMessage();
|
_composeControls->cancelReplyMessage();
|
||||||
refreshTopBarActiveChat();
|
refreshTopBarActiveChat();
|
||||||
}
|
}
|
||||||
|
finishSending();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RepliesWidget::confirmSendingFiles(
|
bool RepliesWidget::confirmSendingFiles(
|
||||||
|
@ -2059,6 +2062,19 @@ void RepliesWidget::listShowPremiumToast(not_null<DocumentData*> document) {
|
||||||
_stickerToast->showFor(document);
|
_stickerToast->showFor(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RepliesWidget::listOpenPhoto(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
FullMsgId context) {
|
||||||
|
controller()->openPhoto(photo, context, _rootId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepliesWidget::listOpenDocument(
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
FullMsgId context,
|
||||||
|
bool showInMediaView) {
|
||||||
|
controller()->openDocument(document, context, _rootId, showInMediaView);
|
||||||
|
}
|
||||||
|
|
||||||
void RepliesWidget::confirmDeleteSelected() {
|
void RepliesWidget::confirmDeleteSelected() {
|
||||||
ConfirmDeleteSelectedItems(_inner);
|
ConfirmDeleteSelectedItems(_inner);
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,6 +150,13 @@ public:
|
||||||
auto listAllowedReactionsValue()
|
auto listAllowedReactionsValue()
|
||||||
->rpl::producer<Data::AllowedReactions> override;
|
->rpl::producer<Data::AllowedReactions> override;
|
||||||
void listShowPremiumToast(not_null<DocumentData*> document) override;
|
void listShowPremiumToast(not_null<DocumentData*> document) override;
|
||||||
|
void listOpenPhoto(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
FullMsgId context) override;
|
||||||
|
void listOpenDocument(
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
FullMsgId context,
|
||||||
|
bool showInMediaView) override;
|
||||||
|
|
||||||
// CornerButtonsDelegate delegate.
|
// CornerButtonsDelegate delegate.
|
||||||
void cornerButtonsShowAtPosition(
|
void cornerButtonsShowAtPosition(
|
||||||
|
|
|
@ -1267,6 +1267,19 @@ void ScheduledWidget::listShowPremiumToast(
|
||||||
_stickerToast->showFor(document);
|
_stickerToast->showFor(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScheduledWidget::listOpenPhoto(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
FullMsgId context) {
|
||||||
|
controller()->openPhoto(photo, context, MsgId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScheduledWidget::listOpenDocument(
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
FullMsgId context,
|
||||||
|
bool showInMediaView) {
|
||||||
|
controller()->openDocument(document, context, MsgId(), showInMediaView);
|
||||||
|
}
|
||||||
|
|
||||||
void ScheduledWidget::confirmSendNowSelected() {
|
void ScheduledWidget::confirmSendNowSelected() {
|
||||||
ConfirmSendNowSelectedItems(_inner);
|
ConfirmSendNowSelectedItems(_inner);
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,6 +135,13 @@ public:
|
||||||
auto listAllowedReactionsValue()
|
auto listAllowedReactionsValue()
|
||||||
-> rpl::producer<Data::AllowedReactions> override;
|
-> rpl::producer<Data::AllowedReactions> override;
|
||||||
void listShowPremiumToast(not_null<DocumentData*> document) override;
|
void listShowPremiumToast(not_null<DocumentData*> document) override;
|
||||||
|
void listOpenPhoto(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
FullMsgId context) override;
|
||||||
|
void listOpenDocument(
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
FullMsgId context,
|
||||||
|
bool showInMediaView) override;
|
||||||
|
|
||||||
// CornerButtonsDelegate delegate.
|
// CornerButtonsDelegate delegate.
|
||||||
void cornerButtonsShowAtPosition(
|
void cornerButtonsShowAtPosition(
|
||||||
|
|
|
@ -100,15 +100,21 @@ rpl::producer<SparseIdsMergedSlice> AbstractController::mediaSource(
|
||||||
return false;
|
return false;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
auto mediaViewer = isScheduled
|
const auto mediaViewer = isScheduled
|
||||||
? SharedScheduledMediaViewer
|
? SharedScheduledMediaViewer
|
||||||
: SharedMediaMergedViewer;
|
: SharedMediaMergedViewer;
|
||||||
|
const auto topicId = isScheduled
|
||||||
|
? SparseIdsMergedSlice::kScheduledTopicId
|
||||||
|
: topic()
|
||||||
|
? topic()->rootId()
|
||||||
|
: MsgId(0);
|
||||||
|
|
||||||
return mediaViewer(
|
return mediaViewer(
|
||||||
&session(),
|
&session(),
|
||||||
SharedMediaMergedKey(
|
SharedMediaMergedKey(
|
||||||
SparseIdsMergedSlice::Key(
|
SparseIdsMergedSlice::Key(
|
||||||
peer()->id,
|
peer()->id,
|
||||||
|
topicId,
|
||||||
migratedPeerId(),
|
migratedPeerId(),
|
||||||
aroundId),
|
aroundId),
|
||||||
section().mediaType()),
|
section().mediaType()),
|
||||||
|
@ -363,6 +369,7 @@ rpl::producer<SparseIdsMergedSlice> Controller::mediaSource(
|
||||||
SharedMediaMergedKey(
|
SharedMediaMergedKey(
|
||||||
SparseIdsMergedSlice::Key(
|
SparseIdsMergedSlice::Key(
|
||||||
query.peerId,
|
query.peerId,
|
||||||
|
query.topicRootId,
|
||||||
query.migratedPeerId,
|
query.migratedPeerId,
|
||||||
aroundId),
|
aroundId),
|
||||||
query.type),
|
query.type),
|
||||||
|
|
|
@ -129,6 +129,9 @@ public:
|
||||||
|
|
||||||
PeerData *peer() const;
|
PeerData *peer() const;
|
||||||
PeerId migratedPeerId() const;
|
PeerId migratedPeerId() const;
|
||||||
|
Data::ForumTopic *topic() const {
|
||||||
|
return key().topic();
|
||||||
|
}
|
||||||
UserData *settingsSelf() const {
|
UserData *settingsSelf() const {
|
||||||
return key().settingsSelf();
|
return key().settingsSelf();
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,12 +83,13 @@ inline auto AddButton(
|
||||||
Ui::VerticalLayout *parent,
|
Ui::VerticalLayout *parent,
|
||||||
not_null<Window::SessionNavigation*> navigation,
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
PeerData *migrated,
|
PeerData *migrated,
|
||||||
Type type,
|
Type type,
|
||||||
Ui::MultiSlideTracker &tracker) {
|
Ui::MultiSlideTracker &tracker) {
|
||||||
auto result = AddCountedButton(
|
auto result = AddCountedButton(
|
||||||
parent,
|
parent,
|
||||||
Profile::SharedMediaCountValue(peer, migrated, type),
|
Profile::SharedMediaCountValue(peer, topicRootId, migrated, type),
|
||||||
MediaText(type),
|
MediaText(type),
|
||||||
tracker)->entity();
|
tracker)->entity();
|
||||||
result->addClickHandler([=] {
|
result->addClickHandler([=] {
|
||||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "info/media/info_media_empty_widget.h"
|
#include "info/media/info_media_empty_widget.h"
|
||||||
#include "info/profile/info_profile_icon.h"
|
#include "info/profile/info_profile_icon.h"
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
|
#include "data/data_forum_topic.h"
|
||||||
#include "ui/widgets/discrete_sliders.h"
|
#include "ui/widgets/discrete_sliders.h"
|
||||||
#include "ui/widgets/shadow.h"
|
#include "ui/widgets/shadow.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
|
@ -87,7 +88,11 @@ void InnerWidget::createTypeButtons() {
|
||||||
st::infoProfileSkip));
|
st::infoProfileSkip));
|
||||||
|
|
||||||
auto tracker = Ui::MultiSlideTracker();
|
auto tracker = Ui::MultiSlideTracker();
|
||||||
auto addMediaButton = [&](
|
const auto peer = _controller->key().peer();
|
||||||
|
const auto topic = _controller->key().topic();
|
||||||
|
const auto topicRootId = topic ? topic->rootId() : MsgId();
|
||||||
|
const auto migrated = _controller->migrated();
|
||||||
|
const auto addMediaButton = [&](
|
||||||
Type buttonType,
|
Type buttonType,
|
||||||
const style::icon &icon) {
|
const style::icon &icon) {
|
||||||
if (buttonType == type()) {
|
if (buttonType == type()) {
|
||||||
|
@ -96,8 +101,9 @@ void InnerWidget::createTypeButtons() {
|
||||||
auto result = AddButton(
|
auto result = AddButton(
|
||||||
content,
|
content,
|
||||||
_controller,
|
_controller,
|
||||||
_controller->key().peer(),
|
peer,
|
||||||
_controller->migrated(),
|
topicRootId,
|
||||||
|
migrated,
|
||||||
buttonType,
|
buttonType,
|
||||||
tracker);
|
tracker);
|
||||||
object_ptr<Profile::FloatingIcon>(
|
object_ptr<Profile::FloatingIcon>(
|
||||||
|
|
|
@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_file_click_handler.h"
|
#include "data/data_file_click_handler.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_download_manager.h"
|
#include "data/data_download_manager.h"
|
||||||
|
#include "data/data_forum_topic.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/view/history_view_cursor_state.h"
|
#include "history/view/history_view_cursor_state.h"
|
||||||
|
@ -467,7 +468,7 @@ bool ListWidget::tooltipWindowActive() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::openPhoto(not_null<PhotoData*> photo, FullMsgId id) {
|
void ListWidget::openPhoto(not_null<PhotoData*> photo, FullMsgId id) {
|
||||||
_controller->parentController()->openPhoto(photo, id);
|
_controller->parentController()->openPhoto(photo, id, topicRootId());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::openDocument(
|
void ListWidget::openDocument(
|
||||||
|
@ -477,6 +478,7 @@ void ListWidget::openDocument(
|
||||||
_controller->parentController()->openDocument(
|
_controller->parentController()->openDocument(
|
||||||
document,
|
document,
|
||||||
id,
|
id,
|
||||||
|
topicRootId(),
|
||||||
showInMediaView);
|
showInMediaView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,6 +741,11 @@ void ListWidget::restoreScrollState() {
|
||||||
_scrollTopState = ListScrollTopState();
|
_scrollTopState = ListScrollTopState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MsgId ListWidget::topicRootId() const {
|
||||||
|
const auto topic = _controller->key().topic();
|
||||||
|
return topic ? topic->rootId() : MsgId(0);
|
||||||
|
}
|
||||||
|
|
||||||
QMargins ListWidget::padding() const {
|
QMargins ListWidget::padding() const {
|
||||||
return st::infoMediaMargin;
|
return st::infoMediaMargin;
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,8 @@ private:
|
||||||
|
|
||||||
void setupSelectRestriction();
|
void setupSelectRestriction();
|
||||||
|
|
||||||
|
[[nodiscard]] MsgId topicRootId() const;
|
||||||
|
|
||||||
QMargins padding() const;
|
QMargins padding() const;
|
||||||
bool isItemLayout(
|
bool isItemLayout(
|
||||||
not_null<const HistoryItem*> item,
|
not_null<const HistoryItem*> item,
|
||||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_chat.h"
|
#include "data/data_chat.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
|
#include "data/data_forum_topic.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/data_peer_values.h"
|
#include "data/data_peer_values.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
@ -61,6 +62,9 @@ constexpr auto kPreloadedScreensCountFull
|
||||||
Provider::Provider(not_null<AbstractController*> controller)
|
Provider::Provider(not_null<AbstractController*> controller)
|
||||||
: _controller(controller)
|
: _controller(controller)
|
||||||
, _peer(_controller->key().peer())
|
, _peer(_controller->key().peer())
|
||||||
|
, _topicRootId(_controller->key().topic()
|
||||||
|
? _controller->key().topic()->rootId()
|
||||||
|
: 0)
|
||||||
, _migrated(_controller->migrated())
|
, _migrated(_controller->migrated())
|
||||||
, _type(_controller->section().mediaType())
|
, _type(_controller->section().mediaType())
|
||||||
, _slice(sliceKey(_universalAroundId)) {
|
, _slice(sliceKey(_universalAroundId)) {
|
||||||
|
@ -348,14 +352,14 @@ void Provider::setSearchQuery(QString query) {
|
||||||
SparseIdsMergedSlice::Key Provider::sliceKey(
|
SparseIdsMergedSlice::Key Provider::sliceKey(
|
||||||
UniversalMsgId universalId) const {
|
UniversalMsgId universalId) const {
|
||||||
using Key = SparseIdsMergedSlice::Key;
|
using Key = SparseIdsMergedSlice::Key;
|
||||||
if (_migrated) {
|
if (!_topicRootId && _migrated) {
|
||||||
return Key(_peer->id, _migrated->id, universalId);
|
return Key(_peer->id, _topicRootId, _migrated->id, universalId);
|
||||||
}
|
}
|
||||||
if (universalId < 0) {
|
if (universalId < 0) {
|
||||||
// Convert back to plain id for non-migrated histories.
|
// Convert back to plain id for non-migrated histories.
|
||||||
universalId = universalId + ServerMaxMsgId;
|
universalId = universalId + ServerMaxMsgId;
|
||||||
}
|
}
|
||||||
return Key(_peer->id, 0, universalId);
|
return Key(_peer->id, _topicRootId, 0, universalId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Provider::itemRemoved(not_null<const HistoryItem*> item) {
|
void Provider::itemRemoved(not_null<const HistoryItem*> item) {
|
||||||
|
|
|
@ -104,6 +104,7 @@ private:
|
||||||
const not_null<AbstractController*> _controller;
|
const not_null<AbstractController*> _controller;
|
||||||
|
|
||||||
const not_null<PeerData*> _peer;
|
const not_null<PeerData*> _peer;
|
||||||
|
const MsgId _topicRootId = 0;
|
||||||
PeerData * const _migrated = nullptr;
|
PeerData * const _migrated = nullptr;
|
||||||
const Type _type = Type::Photo;
|
const Type _type = Type::Photo;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "info/media/info_media_buttons.h"
|
#include "info/media/info_media_buttons.h"
|
||||||
#include "boxes/abstract_box.h"
|
#include "boxes/abstract_box.h"
|
||||||
#include "boxes/add_contact_box.h"
|
#include "boxes/add_contact_box.h"
|
||||||
|
#include "data/data_forum_topic.h"
|
||||||
#include "ui/boxes/confirm_box.h"
|
#include "ui/boxes/confirm_box.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
@ -77,8 +78,7 @@ object_ptr<Ui::RpWidget> InnerWidget::setupContent(
|
||||||
}, _cover->lifetime());
|
}, _cover->lifetime());
|
||||||
_cover->setOnlineCount(rpl::single(0));
|
_cover->setOnlineCount(rpl::single(0));
|
||||||
if (_topic) {
|
if (_topic) {
|
||||||
// #TODO forum shared media
|
result->add(setupSharedMedia(result.data()));
|
||||||
//result->add(setupSharedMedia(result.data()));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +127,7 @@ object_ptr<Ui::RpWidget> InnerWidget::setupSharedMedia(
|
||||||
content,
|
content,
|
||||||
_controller,
|
_controller,
|
||||||
_peer,
|
_peer,
|
||||||
|
_topic ? _topic->rootId() : 0,
|
||||||
_migrated,
|
_migrated,
|
||||||
type,
|
type,
|
||||||
tracker);
|
tracker);
|
||||||
|
|
|
@ -400,6 +400,7 @@ rpl::producer<int> KickedCountValue(not_null<ChannelData*> channel) {
|
||||||
|
|
||||||
rpl::producer<int> SharedMediaCountValue(
|
rpl::producer<int> SharedMediaCountValue(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
PeerData *migrated,
|
PeerData *migrated,
|
||||||
Storage::SharedMediaType type) {
|
Storage::SharedMediaType type) {
|
||||||
auto aroundId = 0;
|
auto aroundId = 0;
|
||||||
|
@ -409,6 +410,7 @@ rpl::producer<int> SharedMediaCountValue(
|
||||||
SharedMediaMergedKey(
|
SharedMediaMergedKey(
|
||||||
SparseIdsMergedSlice::Key(
|
SparseIdsMergedSlice::Key(
|
||||||
peer->id,
|
peer->id,
|
||||||
|
topicRootId,
|
||||||
migrated ? migrated->id : 0,
|
migrated ? migrated->id : 0,
|
||||||
aroundId),
|
aroundId),
|
||||||
type),
|
type),
|
||||||
|
|
|
@ -85,6 +85,7 @@ rpl::producer<not_null<PeerData*>> MigratedOrMeValue(
|
||||||
not_null<ChannelData*> channel);
|
not_null<ChannelData*> channel);
|
||||||
[[nodiscard]] rpl::producer<int> SharedMediaCountValue(
|
[[nodiscard]] rpl::producer<int> SharedMediaCountValue(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
MsgId topicRootId,
|
||||||
PeerData *migrated,
|
PeerData *migrated,
|
||||||
Storage::SharedMediaType type);
|
Storage::SharedMediaType type);
|
||||||
[[nodiscard]] rpl::producer<int> CommonGroupsCountValue(
|
[[nodiscard]] rpl::producer<int> CommonGroupsCountValue(
|
||||||
|
|
|
@ -336,10 +336,11 @@ bool Result::onChoose(Layout::ItemBase *layout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Media::View::OpenRequest Result::openRequest() {
|
Media::View::OpenRequest Result::openRequest() {
|
||||||
|
using namespace Media::View;
|
||||||
if (_document) {
|
if (_document) {
|
||||||
return Media::View::OpenRequest(nullptr, _document, nullptr);
|
return OpenRequest(nullptr, _document, nullptr, MsgId());
|
||||||
} else if (_photo) {
|
} else if (_photo) {
|
||||||
return Media::View::OpenRequest(nullptr, _photo, nullptr);
|
return OpenRequest(nullptr, _photo, nullptr, MsgId());
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ struct Instance::ShuffleData {
|
||||||
std::vector<UniversalMsgId> nonPlayedIds;
|
std::vector<UniversalMsgId> nonPlayedIds;
|
||||||
std::vector<UniversalMsgId> playedIds;
|
std::vector<UniversalMsgId> playedIds;
|
||||||
History *history = nullptr;
|
History *history = nullptr;
|
||||||
|
MsgId topicRootId = 0;
|
||||||
History *migrated = nullptr;
|
History *migrated = nullptr;
|
||||||
bool scheduled = false;
|
bool scheduled = false;
|
||||||
int indexInPlayedIds = 0;
|
int indexInPlayedIds = 0;
|
||||||
|
@ -243,6 +244,7 @@ void Instance::setHistory(
|
||||||
Main::Session *sessionFallback) {
|
Main::Session *sessionFallback) {
|
||||||
if (history) {
|
if (history) {
|
||||||
data->history = history->migrateToOrMe();
|
data->history = history->migrateToOrMe();
|
||||||
|
data->topicRootId = 0;
|
||||||
data->migrated = data->history->migrateFrom();
|
data->migrated = data->history->migrateFrom();
|
||||||
setSession(data, &history->session());
|
setSession(data, &history->session());
|
||||||
} else {
|
} else {
|
||||||
|
@ -349,8 +351,8 @@ bool Instance::validPlaylist(not_null<const Data*> data) const {
|
||||||
using Key = SliceKey;
|
using Key = SliceKey;
|
||||||
const auto inSameDomain = [](const Key &a, const Key &b) {
|
const auto inSameDomain = [](const Key &a, const Key &b) {
|
||||||
return (a.peerId == b.peerId)
|
return (a.peerId == b.peerId)
|
||||||
&& (a.migratedPeerId == b.migratedPeerId)
|
&& (a.topicRootId == b.topicRootId)
|
||||||
&& (a.scheduled == b.scheduled);
|
&& (a.migratedPeerId == b.migratedPeerId);
|
||||||
};
|
};
|
||||||
const auto countDistanceInData = [&](const Key &a, const Key &b) {
|
const auto countDistanceInData = [&](const Key &a, const Key &b) {
|
||||||
return [&](const SparseIdsMergedSlice &data) {
|
return [&](const SparseIdsMergedSlice &data) {
|
||||||
|
@ -382,7 +384,8 @@ void Instance::validatePlaylist(not_null<Data*> data) {
|
||||||
if (const auto key = playlistKey(data)) {
|
if (const auto key = playlistKey(data)) {
|
||||||
data->playlistRequestedKey = key;
|
data->playlistRequestedKey = key;
|
||||||
|
|
||||||
const auto sharedMediaViewer = key->scheduled
|
const auto sharedMediaViewer = (key->topicRootId
|
||||||
|
== SparseIdsMergedSlice::kScheduledTopicId)
|
||||||
? SharedScheduledMediaViewer
|
? SharedScheduledMediaViewer
|
||||||
: SharedMediaMergedViewer;
|
: SharedMediaMergedViewer;
|
||||||
sharedMediaViewer(
|
sharedMediaViewer(
|
||||||
|
@ -419,9 +422,11 @@ auto Instance::playlistKey(not_null<const Data*> data) const
|
||||||
: (contextId.msg - ServerMaxMsgId);
|
: (contextId.msg - ServerMaxMsgId);
|
||||||
return SliceKey(
|
return SliceKey(
|
||||||
data->history->peer->id,
|
data->history->peer->id,
|
||||||
|
(item->isScheduled()
|
||||||
|
? SparseIdsMergedSlice::kScheduledTopicId
|
||||||
|
: data->topicRootId),
|
||||||
data->migrated ? data->migrated->peer->id : 0,
|
data->migrated ? data->migrated->peer->id : 0,
|
||||||
universalId,
|
universalId);
|
||||||
item->isScheduled());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Instance::validOtherPlaylist(not_null<const Data*> data) const {
|
bool Instance::validOtherPlaylist(not_null<const Data*> data) const {
|
||||||
|
@ -476,13 +481,13 @@ auto Instance::playlistOtherKey(not_null<const Data*> data) const
|
||||||
|
|
||||||
return SliceKey(
|
return SliceKey(
|
||||||
data->history->peer->id,
|
data->history->peer->id,
|
||||||
|
data->topicRootId,
|
||||||
data->migrated ? data->migrated->peer->id : 0,
|
data->migrated ? data->migrated->peer->id : 0,
|
||||||
(data->playlistSlice->skippedBefore() == 0
|
(data->playlistSlice->skippedBefore() == 0
|
||||||
? ServerMaxMsgId - 1
|
? ServerMaxMsgId - 1
|
||||||
: data->migrated
|
: data->migrated
|
||||||
? (1 - ServerMaxMsgId)
|
? (1 - ServerMaxMsgId)
|
||||||
: 1),
|
: 1));
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *Instance::itemByIndex(not_null<Data*> data, int index) {
|
HistoryItem *Instance::itemByIndex(not_null<Data*> data, int index) {
|
||||||
|
@ -892,8 +897,10 @@ void Instance::validateShuffleData(not_null<Data*> data) {
|
||||||
}
|
}
|
||||||
const auto raw = data->shuffleData.get();
|
const auto raw = data->shuffleData.get();
|
||||||
const auto key = playlistKey(data);
|
const auto key = playlistKey(data);
|
||||||
const auto scheduled = key && key->scheduled;
|
const auto scheduled = key
|
||||||
|
&& (key->topicRootId == SparseIdsMergedSlice::kScheduledTopicId);
|
||||||
if (raw->history != data->history
|
if (raw->history != data->history
|
||||||
|
|| raw->topicRootId != data->topicRootId
|
||||||
|| raw->migrated != data->migrated
|
|| raw->migrated != data->migrated
|
||||||
|| raw->scheduled != scheduled) {
|
|| raw->scheduled != scheduled) {
|
||||||
raw->history = data->history;
|
raw->history = data->history;
|
||||||
|
@ -950,9 +957,9 @@ void Instance::validateShuffleData(not_null<Data*> data) {
|
||||||
SharedMediaMergedKey(
|
SharedMediaMergedKey(
|
||||||
SliceKey(
|
SliceKey(
|
||||||
raw->history->peer->id,
|
raw->history->peer->id,
|
||||||
|
raw->topicRootId,
|
||||||
raw->migrated ? raw->migrated->peer->id : 0,
|
raw->migrated ? raw->migrated->peer->id : 0,
|
||||||
last,
|
last),
|
||||||
false),
|
|
||||||
data->overview),
|
data->overview),
|
||||||
kIdsLimit,
|
kIdsLimit,
|
||||||
kIdsLimit
|
kIdsLimit
|
||||||
|
|
|
@ -195,6 +195,7 @@ private:
|
||||||
rpl::lifetime sessionLifetime;
|
rpl::lifetime sessionLifetime;
|
||||||
rpl::event_stream<> playlistChanges;
|
rpl::event_stream<> playlistChanges;
|
||||||
History *history = nullptr;
|
History *history = nullptr;
|
||||||
|
MsgId topicRootId = 0;
|
||||||
History *migrated = nullptr;
|
History *migrated = nullptr;
|
||||||
Main::Session *session = nullptr;
|
Main::Session *session = nullptr;
|
||||||
bool isPlaying = false;
|
bool isPlaying = false;
|
||||||
|
|
|
@ -28,10 +28,12 @@ public:
|
||||||
OpenRequest(
|
OpenRequest(
|
||||||
Window::SessionController *controller,
|
Window::SessionController *controller,
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
HistoryItem *item)
|
HistoryItem *item,
|
||||||
|
MsgId topicRootId)
|
||||||
: _controller(controller)
|
: _controller(controller)
|
||||||
, _photo(photo)
|
, _photo(photo)
|
||||||
, _item(item) {
|
, _item(item)
|
||||||
|
, _topicRootId(topicRootId) {
|
||||||
}
|
}
|
||||||
OpenRequest(
|
OpenRequest(
|
||||||
Window::SessionController *controller,
|
Window::SessionController *controller,
|
||||||
|
@ -46,11 +48,13 @@ public:
|
||||||
Window::SessionController *controller,
|
Window::SessionController *controller,
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
HistoryItem *item,
|
HistoryItem *item,
|
||||||
|
MsgId topicRootId,
|
||||||
bool continueStreaming = false,
|
bool continueStreaming = false,
|
||||||
crl::time startTime = 0)
|
crl::time startTime = 0)
|
||||||
: _controller(controller)
|
: _controller(controller)
|
||||||
, _document(document)
|
, _document(document)
|
||||||
, _item(item)
|
, _item(item)
|
||||||
|
, _topicRootId(topicRootId)
|
||||||
, _continueStreaming(continueStreaming)
|
, _continueStreaming(continueStreaming)
|
||||||
, _startTime(startTime) {
|
, _startTime(startTime) {
|
||||||
}
|
}
|
||||||
|
@ -63,35 +67,39 @@ public:
|
||||||
, _cloudTheme(cloudTheme) {
|
, _cloudTheme(cloudTheme) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerData *peer() const {
|
[[nodiscard]] PeerData *peer() const {
|
||||||
return _peer;
|
return _peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhotoData *photo() const {
|
[[nodiscard]] PhotoData *photo() const {
|
||||||
return _photo;
|
return _photo;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *item() const {
|
[[nodiscard]] HistoryItem *item() const {
|
||||||
return _item;
|
return _item;
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentData *document() const {
|
[[nodiscard]] MsgId topicRootId() const {
|
||||||
|
return _topicRootId;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] DocumentData *document() const {
|
||||||
return _document;
|
return _document;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Data::CloudTheme> cloudTheme() const {
|
[[nodiscard]] std::optional<Data::CloudTheme> cloudTheme() const {
|
||||||
return _cloudTheme;
|
return _cloudTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::SessionController *controller() const {
|
[[nodiscard]] Window::SessionController *controller() const {
|
||||||
return _controller;
|
return _controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool continueStreaming() const {
|
[[nodiscard]] bool continueStreaming() const {
|
||||||
return _continueStreaming;
|
return _continueStreaming;
|
||||||
}
|
}
|
||||||
|
|
||||||
crl::time startTime() const {
|
[[nodiscard]] crl::time startTime() const {
|
||||||
return _startTime;
|
return _startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +109,7 @@ private:
|
||||||
PhotoData *_photo = nullptr;
|
PhotoData *_photo = nullptr;
|
||||||
PeerData *_peer = nullptr;
|
PeerData *_peer = nullptr;
|
||||||
HistoryItem *_item = nullptr;
|
HistoryItem *_item = nullptr;
|
||||||
|
MsgId _topicRootId = 0;
|
||||||
std::optional<Data::CloudTheme> _cloudTheme = std::nullopt;
|
std::optional<Data::CloudTheme> _cloudTheme = std::nullopt;
|
||||||
bool _continueStreaming = false;
|
bool _continueStreaming = false;
|
||||||
crl::time _startTime = 0;
|
crl::time _startTime = 0;
|
||||||
|
|
|
@ -244,7 +244,6 @@ struct OverlayWidget::PipWrap {
|
||||||
PipWrap(
|
PipWrap(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
FullMsgId contextId,
|
|
||||||
std::shared_ptr<Streaming::Document> shared,
|
std::shared_ptr<Streaming::Document> shared,
|
||||||
FnMut<void()> closeAndContinue,
|
FnMut<void()> closeAndContinue,
|
||||||
FnMut<void()> destroy);
|
FnMut<void()> destroy);
|
||||||
|
@ -279,7 +278,6 @@ OverlayWidget::Streamed::Streamed(
|
||||||
OverlayWidget::PipWrap::PipWrap(
|
OverlayWidget::PipWrap::PipWrap(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
FullMsgId contextId,
|
|
||||||
std::shared_ptr<Streaming::Document> shared,
|
std::shared_ptr<Streaming::Document> shared,
|
||||||
FnMut<void()> closeAndContinue,
|
FnMut<void()> closeAndContinue,
|
||||||
FnMut<void()> destroy)
|
FnMut<void()> destroy)
|
||||||
|
@ -287,7 +285,6 @@ OverlayWidget::PipWrap::PipWrap(
|
||||||
, wrapped(
|
, wrapped(
|
||||||
&delegate,
|
&delegate,
|
||||||
document,
|
document,
|
||||||
contextId,
|
|
||||||
std::move(shared),
|
std::move(shared),
|
||||||
std::move(closeAndContinue),
|
std::move(closeAndContinue),
|
||||||
std::move(destroy)) {
|
std::move(destroy)) {
|
||||||
|
@ -1708,7 +1705,11 @@ void OverlayWidget::handleDocumentClick() {
|
||||||
if (_document->loading()) {
|
if (_document->loading()) {
|
||||||
saveCancel();
|
saveCancel();
|
||||||
} else {
|
} else {
|
||||||
Data::ResolveDocument(findWindow(), _document, _message);
|
Data::ResolveDocument(
|
||||||
|
findWindow(),
|
||||||
|
_document,
|
||||||
|
_message,
|
||||||
|
_topicRootId);
|
||||||
if (_document->loading() && !_radial.animating()) {
|
if (_document->loading() && !_radial.animating()) {
|
||||||
_radial.start(_documentMedia->progress());
|
_radial.start(_documentMedia->progress());
|
||||||
}
|
}
|
||||||
|
@ -1975,8 +1976,9 @@ auto OverlayWidget::sharedMediaKey() const -> std::optional<SharedMediaKey> {
|
||||||
&& !_user
|
&& !_user
|
||||||
&& _photo
|
&& _photo
|
||||||
&& _peer->userpicPhotoId() == _photo->id) {
|
&& _peer->userpicPhotoId() == _photo->id) {
|
||||||
return SharedMediaKey {
|
return SharedMediaKey{
|
||||||
_history->peer->id,
|
_history->peer->id,
|
||||||
|
MsgId(0), // topicRootId
|
||||||
_migrated ? _migrated->peer->id : 0,
|
_migrated ? _migrated->peer->id : 0,
|
||||||
SharedMediaType::ChatPhoto,
|
SharedMediaType::ChatPhoto,
|
||||||
_photo
|
_photo
|
||||||
|
@ -1989,12 +1991,14 @@ auto OverlayWidget::sharedMediaKey() const -> std::optional<SharedMediaKey> {
|
||||||
const auto keyForType = [&](SharedMediaType type) -> SharedMediaKey {
|
const auto keyForType = [&](SharedMediaType type) -> SharedMediaKey {
|
||||||
return {
|
return {
|
||||||
_history->peer->id,
|
_history->peer->id,
|
||||||
|
(isScheduled
|
||||||
|
? SparseIdsMergedSlice::kScheduledTopicId
|
||||||
|
: _topicRootId),
|
||||||
_migrated ? _migrated->peer->id : 0,
|
_migrated ? _migrated->peer->id : 0,
|
||||||
type,
|
type,
|
||||||
(_message->history() == _history
|
(_message->history() == _history
|
||||||
? _message->id
|
? _message->id
|
||||||
: (_message->id - ServerMaxMsgId)),
|
: (_message->id - ServerMaxMsgId))
|
||||||
isScheduled
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (!_message->isRegular() && !isScheduled) {
|
if (!_message->isRegular() && !isScheduled) {
|
||||||
|
@ -2038,8 +2042,8 @@ bool OverlayWidget::validSharedMedia() const {
|
||||||
auto inSameDomain = [](const Key &a, const Key &b) {
|
auto inSameDomain = [](const Key &a, const Key &b) {
|
||||||
return (a.type == b.type)
|
return (a.type == b.type)
|
||||||
&& (a.peerId == b.peerId)
|
&& (a.peerId == b.peerId)
|
||||||
&& (a.migratedPeerId == b.migratedPeerId)
|
&& (a.topicRootId == b.topicRootId)
|
||||||
&& (a.scheduled == b.scheduled);
|
&& (a.migratedPeerId == b.migratedPeerId);
|
||||||
};
|
};
|
||||||
auto countDistanceInData = [&](const Key &a, const Key &b) {
|
auto countDistanceInData = [&](const Key &a, const Key &b) {
|
||||||
return [&](const SharedMediaWithLastSlice &data) {
|
return [&](const SharedMediaWithLastSlice &data) {
|
||||||
|
@ -2432,6 +2436,7 @@ void OverlayWidget::show(OpenRequest request) {
|
||||||
const auto photo = request.photo();
|
const auto photo = request.photo();
|
||||||
const auto contextItem = request.item();
|
const auto contextItem = request.item();
|
||||||
const auto contextPeer = request.peer();
|
const auto contextPeer = request.peer();
|
||||||
|
const auto contextTopicRootId = request.topicRootId();
|
||||||
if (photo) {
|
if (photo) {
|
||||||
if (contextItem && contextPeer) {
|
if (contextItem && contextPeer) {
|
||||||
return;
|
return;
|
||||||
|
@ -2441,7 +2446,7 @@ void OverlayWidget::show(OpenRequest request) {
|
||||||
if (contextPeer) {
|
if (contextPeer) {
|
||||||
setContext(contextPeer);
|
setContext(contextPeer);
|
||||||
} else if (contextItem) {
|
} else if (contextItem) {
|
||||||
setContext(contextItem);
|
setContext(ItemContext{ contextItem, contextTopicRootId });
|
||||||
} else {
|
} else {
|
||||||
setContext(v::null);
|
setContext(v::null);
|
||||||
}
|
}
|
||||||
|
@ -2457,7 +2462,7 @@ void OverlayWidget::show(OpenRequest request) {
|
||||||
setSession(&document->session());
|
setSession(&document->session());
|
||||||
|
|
||||||
if (contextItem) {
|
if (contextItem) {
|
||||||
setContext(contextItem);
|
setContext(ItemContext{ contextItem, contextTopicRootId });
|
||||||
} else {
|
} else {
|
||||||
setContext(v::null);
|
setContext(v::null);
|
||||||
}
|
}
|
||||||
|
@ -3299,19 +3304,20 @@ void OverlayWidget::switchToPip() {
|
||||||
|
|
||||||
const auto document = _document;
|
const auto document = _document;
|
||||||
const auto message = _message;
|
const auto message = _message;
|
||||||
|
const auto topicRootId = _topicRootId;
|
||||||
const auto closeAndContinue = [=] {
|
const auto closeAndContinue = [=] {
|
||||||
_showAsPip = false;
|
_showAsPip = false;
|
||||||
show(OpenRequest(
|
show(OpenRequest(
|
||||||
findWindow(false),
|
findWindow(false),
|
||||||
document,
|
document,
|
||||||
message,
|
message,
|
||||||
|
topicRootId,
|
||||||
true));
|
true));
|
||||||
};
|
};
|
||||||
_showAsPip = true;
|
_showAsPip = true;
|
||||||
_pip = std::make_unique<PipWrap>(
|
_pip = std::make_unique<PipWrap>(
|
||||||
_widget,
|
_widget,
|
||||||
document,
|
document,
|
||||||
message ? message->fullId() : FullMsgId(),
|
|
||||||
_streamed->instance.shared(),
|
_streamed->instance.shared(),
|
||||||
closeAndContinue,
|
closeAndContinue,
|
||||||
[=] { _pip = nullptr; });
|
[=] { _pip = nullptr; });
|
||||||
|
@ -4091,9 +4097,9 @@ OverlayWidget::Entity OverlayWidget::entityForCollage(int index) const {
|
||||||
return { v::null, nullptr };
|
return { v::null, nullptr };
|
||||||
}
|
}
|
||||||
if (const auto document = std::get_if<DocumentData*>(&items[index])) {
|
if (const auto document = std::get_if<DocumentData*>(&items[index])) {
|
||||||
return { *document, _message };
|
return { *document, _message, _topicRootId };
|
||||||
} else if (const auto photo = std::get_if<PhotoData*>(&items[index])) {
|
} else if (const auto photo = std::get_if<PhotoData*>(&items[index])) {
|
||||||
return { *photo, _message };
|
return { *photo, _message, _topicRootId };
|
||||||
}
|
}
|
||||||
return { v::null, nullptr };
|
return { v::null, nullptr };
|
||||||
}
|
}
|
||||||
|
@ -4104,12 +4110,12 @@ OverlayWidget::Entity OverlayWidget::entityForItemId(const FullMsgId &itemId) co
|
||||||
if (const auto item = _session->data().message(itemId)) {
|
if (const auto item = _session->data().message(itemId)) {
|
||||||
if (const auto media = item->media()) {
|
if (const auto media = item->media()) {
|
||||||
if (const auto photo = media->photo()) {
|
if (const auto photo = media->photo()) {
|
||||||
return { photo, item };
|
return { photo, item, _topicRootId };
|
||||||
} else if (const auto document = media->document()) {
|
} else if (const auto document = media->document()) {
|
||||||
return { document, item };
|
return { document, item, _topicRootId };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { v::null, item };
|
return { v::null, item, _topicRootId };
|
||||||
}
|
}
|
||||||
return { v::null, nullptr };
|
return { v::null, nullptr };
|
||||||
}
|
}
|
||||||
|
@ -4128,25 +4134,29 @@ OverlayWidget::Entity OverlayWidget::entityByIndex(int index) const {
|
||||||
void OverlayWidget::setContext(
|
void OverlayWidget::setContext(
|
||||||
std::variant<
|
std::variant<
|
||||||
v::null_t,
|
v::null_t,
|
||||||
not_null<HistoryItem*>,
|
ItemContext,
|
||||||
not_null<PeerData*>> context) {
|
not_null<PeerData*>> context) {
|
||||||
if (const auto item = std::get_if<not_null<HistoryItem*>>(&context)) {
|
if (const auto item = std::get_if<ItemContext>(&context)) {
|
||||||
_message = (*item);
|
_message = item->item;
|
||||||
|
_topicRootId = item->topicRootId;
|
||||||
_history = _message->history();
|
_history = _message->history();
|
||||||
_peer = _history->peer;
|
_peer = _history->peer;
|
||||||
} else if (const auto peer = std::get_if<not_null<PeerData*>>(&context)) {
|
} else if (const auto peer = std::get_if<not_null<PeerData*>>(&context)) {
|
||||||
_peer = *peer;
|
_peer = *peer;
|
||||||
_history = _peer->owner().history(_peer);
|
_history = _peer->owner().history(_peer);
|
||||||
_message = nullptr;
|
_message = nullptr;
|
||||||
|
_topicRootId = MsgId();
|
||||||
} else {
|
} else {
|
||||||
_message = nullptr;
|
_message = nullptr;
|
||||||
|
_topicRootId = MsgId();
|
||||||
_history = nullptr;
|
_history = nullptr;
|
||||||
_peer = nullptr;
|
_peer = nullptr;
|
||||||
}
|
}
|
||||||
_migrated = nullptr;
|
_migrated = nullptr;
|
||||||
if (_history) {
|
if (_history) {
|
||||||
if (_history->peer->migrateFrom()) {
|
if (_history->peer->migrateFrom()) {
|
||||||
_migrated = _history->owner().history(_history->peer->migrateFrom());
|
_migrated = _history->owner().history(
|
||||||
|
_history->peer->migrateFrom());
|
||||||
} else if (_history->peer->migrateTo()) {
|
} else if (_history->peer->migrateTo()) {
|
||||||
_migrated = _history;
|
_migrated = _history;
|
||||||
_history = _history->owner().history(_history->peer->migrateTo());
|
_history = _history->owner().history(_history->peer->migrateTo());
|
||||||
|
@ -4211,7 +4221,7 @@ bool OverlayWidget::moveToEntity(const Entity &entity, int preloadDelta) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (const auto item = entity.item) {
|
if (const auto item = entity.item) {
|
||||||
setContext(item);
|
setContext(ItemContext{ item, entity.topicRootId });
|
||||||
} else if (_peer) {
|
} else if (_peer) {
|
||||||
setContext(_peer);
|
setContext(_peer);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -131,7 +131,8 @@ private:
|
||||||
v::null_t,
|
v::null_t,
|
||||||
not_null<PhotoData*>,
|
not_null<PhotoData*>,
|
||||||
not_null<DocumentData*>> data;
|
not_null<DocumentData*>> data;
|
||||||
HistoryItem *item;
|
HistoryItem *item = nullptr;
|
||||||
|
MsgId topicRootId = 0;
|
||||||
};
|
};
|
||||||
enum class SavePhotoVideo {
|
enum class SavePhotoVideo {
|
||||||
None,
|
None,
|
||||||
|
@ -241,9 +242,14 @@ private:
|
||||||
Entity entityByIndex(int index) const;
|
Entity entityByIndex(int index) const;
|
||||||
Entity entityForItemId(const FullMsgId &itemId) const;
|
Entity entityForItemId(const FullMsgId &itemId) const;
|
||||||
bool moveToEntity(const Entity &entity, int preloadDelta = 0);
|
bool moveToEntity(const Entity &entity, int preloadDelta = 0);
|
||||||
|
|
||||||
|
struct ItemContext {
|
||||||
|
not_null<HistoryItem*> item;
|
||||||
|
MsgId topicRootId = 0;
|
||||||
|
};
|
||||||
void setContext(std::variant<
|
void setContext(std::variant<
|
||||||
v::null_t,
|
v::null_t,
|
||||||
not_null<HistoryItem*>,
|
ItemContext,
|
||||||
not_null<PeerData*>> context);
|
not_null<PeerData*>> context);
|
||||||
|
|
||||||
void refreshLang();
|
void refreshLang();
|
||||||
|
@ -519,6 +525,7 @@ private:
|
||||||
|
|
||||||
History *_migrated = nullptr;
|
History *_migrated = nullptr;
|
||||||
History *_history = nullptr; // if conversation photos or files overview
|
History *_history = nullptr; // if conversation photos or files overview
|
||||||
|
MsgId _topicRootId = 0;
|
||||||
PeerData *_peer = nullptr;
|
PeerData *_peer = nullptr;
|
||||||
UserData *_user = nullptr; // if user profile photos overview
|
UserData *_user = nullptr; // if user profile photos overview
|
||||||
|
|
||||||
|
|
|
@ -906,13 +906,11 @@ void PipPanel::updateDecorations() {
|
||||||
Pip::Pip(
|
Pip::Pip(
|
||||||
not_null<Delegate*> delegate,
|
not_null<Delegate*> delegate,
|
||||||
not_null<DocumentData*> data,
|
not_null<DocumentData*> data,
|
||||||
FullMsgId contextId,
|
|
||||||
std::shared_ptr<Streaming::Document> shared,
|
std::shared_ptr<Streaming::Document> shared,
|
||||||
FnMut<void()> closeAndContinue,
|
FnMut<void()> closeAndContinue,
|
||||||
FnMut<void()> destroy)
|
FnMut<void()> destroy)
|
||||||
: _delegate(delegate)
|
: _delegate(delegate)
|
||||||
, _data(data)
|
, _data(data)
|
||||||
, _contextId(contextId)
|
|
||||||
, _instance(std::move(shared), [=] { waitingAnimationCallback(); })
|
, _instance(std::move(shared), [=] { waitingAnimationCallback(); })
|
||||||
, _panel(
|
, _panel(
|
||||||
_delegate->pipParentWidget(),
|
_delegate->pipParentWidget(),
|
||||||
|
|
|
@ -135,7 +135,6 @@ public:
|
||||||
Pip(
|
Pip(
|
||||||
not_null<Delegate*> delegate,
|
not_null<Delegate*> delegate,
|
||||||
not_null<DocumentData*> data,
|
not_null<DocumentData*> data,
|
||||||
FullMsgId contextId,
|
|
||||||
std::shared_ptr<Streaming::Document> shared,
|
std::shared_ptr<Streaming::Document> shared,
|
||||||
FnMut<void()> closeAndContinue,
|
FnMut<void()> closeAndContinue,
|
||||||
FnMut<void()> destroy);
|
FnMut<void()> destroy);
|
||||||
|
@ -254,7 +253,6 @@ private:
|
||||||
|
|
||||||
const not_null<Delegate*> _delegate;
|
const not_null<Delegate*> _delegate;
|
||||||
const not_null<DocumentData*> _data;
|
const not_null<DocumentData*> _data;
|
||||||
FullMsgId _contextId;
|
|
||||||
Streaming::Instance _instance;
|
Streaming::Instance _instance;
|
||||||
bool _opengl = false;
|
bool _opengl = false;
|
||||||
PipPanel _panel;
|
PipPanel _panel;
|
||||||
|
|
|
@ -11,13 +11,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace Storage {
|
namespace Storage {
|
||||||
|
|
||||||
std::map<PeerId, SharedMedia::Lists>::iterator
|
auto SharedMedia::enforceLists(Key key)
|
||||||
SharedMedia::enforceLists(PeerId peer) {
|
-> std::map<Key, SharedMedia::Lists>::iterator {
|
||||||
auto result = _lists.find(peer);
|
auto result = _lists.find(key);
|
||||||
if (result != _lists.end()) {
|
if (result != _lists.end()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = _lists.emplace(peer, Lists {}).first;
|
result = _lists.emplace(key, Lists {}).first;
|
||||||
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
||||||
auto &list = result->second[index];
|
auto &list = result->second[index];
|
||||||
auto type = static_cast<SharedMediaType>(index);
|
auto type = static_cast<SharedMediaType>(index);
|
||||||
|
@ -25,7 +25,8 @@ std::map<PeerId, SharedMedia::Lists>::iterator
|
||||||
list.sliceUpdated(
|
list.sliceUpdated(
|
||||||
) | rpl::map([=](const SparseIdsSliceUpdate &update) {
|
) | rpl::map([=](const SparseIdsSliceUpdate &update) {
|
||||||
return SharedMediaSliceUpdate(
|
return SharedMediaSliceUpdate(
|
||||||
peer,
|
key.peerId,
|
||||||
|
key.topicRootId,
|
||||||
type,
|
type,
|
||||||
update);
|
update);
|
||||||
}) | rpl::start_to_stream(_sliceUpdated, _lifetime);
|
}) | rpl::start_to_stream(_sliceUpdated, _lifetime);
|
||||||
|
@ -34,22 +35,26 @@ std::map<PeerId, SharedMedia::Lists>::iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedMedia::add(SharedMediaAddNew &&query) {
|
void SharedMedia::add(SharedMediaAddNew &&query) {
|
||||||
auto peer = query.peerId;
|
auto peerIt = enforceLists({ query.peerId, MsgId(0) });
|
||||||
auto peerIt = enforceLists(peer);
|
while (peerIt != end(_lists) && peerIt->first.peerId == query.peerId) {
|
||||||
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
||||||
auto type = static_cast<SharedMediaType>(index);
|
auto type = static_cast<SharedMediaType>(index);
|
||||||
if (query.types.test(type)) {
|
if (query.types.test(type)) {
|
||||||
peerIt->second[index].addNew(query.messageId);
|
peerIt->second[index].addNew(query.messageId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
++peerIt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedMedia::add(SharedMediaAddExisting &&query) {
|
void SharedMedia::add(SharedMediaAddExisting &&query) {
|
||||||
auto peerIt = enforceLists(query.peerId);
|
auto peerIt = enforceLists({ query.peerId, query.topicRootId });
|
||||||
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
||||||
auto type = static_cast<SharedMediaType>(index);
|
auto type = static_cast<SharedMediaType>(index);
|
||||||
if (query.types.test(type)) {
|
if (query.types.test(type)) {
|
||||||
peerIt->second[index].addExisting(query.messageId, query.noSkipRange);
|
peerIt->second[index].addExisting(
|
||||||
|
query.messageId,
|
||||||
|
query.noSkipRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +62,7 @@ void SharedMedia::add(SharedMediaAddExisting &&query) {
|
||||||
void SharedMedia::add(SharedMediaAddSlice &&query) {
|
void SharedMedia::add(SharedMediaAddSlice &&query) {
|
||||||
Expects(IsValidSharedMediaType(query.type));
|
Expects(IsValidSharedMediaType(query.type));
|
||||||
|
|
||||||
auto peerIt = enforceLists(query.peerId);
|
auto peerIt = enforceLists({ query.peerId, query.topicRootId });
|
||||||
auto index = static_cast<int>(query.type);
|
auto index = static_cast<int>(query.type);
|
||||||
peerIt->second[index].addSlice(
|
peerIt->second[index].addSlice(
|
||||||
std::move(query.messageIds),
|
std::move(query.messageIds),
|
||||||
|
@ -66,45 +71,48 @@ void SharedMedia::add(SharedMediaAddSlice &&query) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedMedia::remove(SharedMediaRemoveOne &&query) {
|
void SharedMedia::remove(SharedMediaRemoveOne &&query) {
|
||||||
auto peerIt = _lists.find(query.peerId);
|
auto peerIt = _lists.find({ query.peerId, MsgId(0) });
|
||||||
if (peerIt != _lists.end()) {
|
while (peerIt != end(_lists) && peerIt->first.peerId == query.peerId) {
|
||||||
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
||||||
auto type = static_cast<SharedMediaType>(index);
|
auto type = static_cast<SharedMediaType>(index);
|
||||||
if (query.types.test(type)) {
|
if (query.types.test(type)) {
|
||||||
peerIt->second[index].removeOne(query.messageId);
|
peerIt->second[index].removeOne(query.messageId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_oneRemoved.fire(std::move(query));
|
++peerIt;
|
||||||
}
|
}
|
||||||
|
_oneRemoved.fire(std::move(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedMedia::remove(SharedMediaRemoveAll &&query) {
|
void SharedMedia::remove(SharedMediaRemoveAll &&query) {
|
||||||
auto peerIt = _lists.find(query.peerId);
|
auto peerIt = _lists.find({ query.peerId, MsgId(0) });
|
||||||
if (peerIt != _lists.end()) {
|
while (peerIt != end(_lists) && peerIt->first.peerId == query.peerId) {
|
||||||
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
||||||
auto type = static_cast<SharedMediaType>(index);
|
auto type = static_cast<SharedMediaType>(index);
|
||||||
if (query.types.test(type)) {
|
if (query.types.test(type)) {
|
||||||
peerIt->second[index].removeAll();
|
peerIt->second[index].removeAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_allRemoved.fire(std::move(query));
|
++peerIt;
|
||||||
}
|
}
|
||||||
|
_allRemoved.fire(std::move(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedMedia::invalidate(SharedMediaInvalidateBottom &&query) {
|
void SharedMedia::invalidate(SharedMediaInvalidateBottom &&query) {
|
||||||
auto peerIt = _lists.find(query.peerId);
|
auto peerIt = _lists.find({ query.peerId, MsgId(0) });
|
||||||
if (peerIt != _lists.end()) {
|
while (peerIt != end(_lists) && peerIt->first.peerId == query.peerId) {
|
||||||
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
for (auto index = 0; index != kSharedMediaTypeCount; ++index) {
|
||||||
peerIt->second[index].invalidateBottom();
|
peerIt->second[index].invalidateBottom();
|
||||||
}
|
}
|
||||||
_bottomInvalidated.fire(std::move(query));
|
++peerIt;
|
||||||
}
|
}
|
||||||
|
_bottomInvalidated.fire(std::move(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<SharedMediaResult> SharedMedia::query(SharedMediaQuery &&query) const {
|
rpl::producer<SharedMediaResult> SharedMedia::query(SharedMediaQuery &&query) const {
|
||||||
Expects(IsValidSharedMediaType(query.key.type));
|
Expects(IsValidSharedMediaType(query.key.type));
|
||||||
|
|
||||||
auto peerIt = _lists.find(query.key.peerId);
|
auto peerIt = _lists.find({ query.key.peerId, query.key.topicRootId });
|
||||||
if (peerIt != _lists.end()) {
|
if (peerIt != _lists.end()) {
|
||||||
auto index = static_cast<int>(query.key.type);
|
auto index = static_cast<int>(query.key.type);
|
||||||
return peerIt->second[index].query(SparseIdsListQuery(
|
return peerIt->second[index].query(SparseIdsListQuery(
|
||||||
|
@ -121,7 +129,7 @@ rpl::producer<SharedMediaResult> SharedMedia::query(SharedMediaQuery &&query) co
|
||||||
SharedMediaResult SharedMedia::snapshot(const SharedMediaQuery &query) const {
|
SharedMediaResult SharedMedia::snapshot(const SharedMediaQuery &query) const {
|
||||||
Expects(IsValidSharedMediaType(query.key.type));
|
Expects(IsValidSharedMediaType(query.key.type));
|
||||||
|
|
||||||
auto peerIt = _lists.find(query.key.peerId);
|
auto peerIt = _lists.find({ query.key.peerId, query.key.topicRootId });
|
||||||
if (peerIt != _lists.end()) {
|
if (peerIt != _lists.end()) {
|
||||||
auto index = static_cast<int>(query.key.type);
|
auto index = static_cast<int>(query.key.type);
|
||||||
return peerIt->second[index].snapshot(SparseIdsListQuery(
|
return peerIt->second[index].snapshot(SparseIdsListQuery(
|
||||||
|
@ -135,7 +143,7 @@ SharedMediaResult SharedMedia::snapshot(const SharedMediaQuery &query) const {
|
||||||
bool SharedMedia::empty(const SharedMediaKey &key) const {
|
bool SharedMedia::empty(const SharedMediaKey &key) const {
|
||||||
Expects(IsValidSharedMediaType(key.type));
|
Expects(IsValidSharedMediaType(key.type));
|
||||||
|
|
||||||
auto peerIt = _lists.find(key.peerId);
|
auto peerIt = _lists.find({ key.peerId, key.topicRootId });
|
||||||
if (peerIt != _lists.end()) {
|
if (peerIt != _lists.end()) {
|
||||||
auto index = static_cast<int>(key.type);
|
auto index = static_cast<int>(key.type);
|
||||||
return peerIt->second[index].empty();
|
return peerIt->second[index].empty();
|
||||||
|
|
|
@ -39,8 +39,13 @@ constexpr bool IsValidSharedMediaType(SharedMediaType type) {
|
||||||
using SharedMediaTypesMask = base::enum_mask<SharedMediaType>;
|
using SharedMediaTypesMask = base::enum_mask<SharedMediaType>;
|
||||||
|
|
||||||
struct SharedMediaAddNew {
|
struct SharedMediaAddNew {
|
||||||
SharedMediaAddNew(PeerId peerId, SharedMediaTypesMask types, MsgId messageId)
|
SharedMediaAddNew(
|
||||||
: peerId(peerId), messageId(messageId), types(types) {
|
PeerId peerId,
|
||||||
|
SharedMediaTypesMask types,
|
||||||
|
MsgId messageId)
|
||||||
|
: peerId(peerId)
|
||||||
|
, messageId(messageId)
|
||||||
|
, types(types) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerId peerId = 0;
|
PeerId peerId = 0;
|
||||||
|
@ -52,16 +57,19 @@ struct SharedMediaAddNew {
|
||||||
struct SharedMediaAddExisting {
|
struct SharedMediaAddExisting {
|
||||||
SharedMediaAddExisting(
|
SharedMediaAddExisting(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
|
MsgId topicRootId,
|
||||||
SharedMediaTypesMask types,
|
SharedMediaTypesMask types,
|
||||||
MsgId messageId,
|
MsgId messageId,
|
||||||
MsgRange noSkipRange)
|
MsgRange noSkipRange)
|
||||||
: peerId(peerId)
|
: peerId(peerId)
|
||||||
, messageId(messageId)
|
, topicRootId(topicRootId)
|
||||||
, noSkipRange(noSkipRange)
|
, messageId(messageId)
|
||||||
, types(types) {
|
, noSkipRange(noSkipRange)
|
||||||
|
, types(types) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerId peerId = 0;
|
PeerId peerId = 0;
|
||||||
|
MsgId topicRootId = 0;
|
||||||
MsgId messageId = 0;
|
MsgId messageId = 0;
|
||||||
MsgRange noSkipRange;
|
MsgRange noSkipRange;
|
||||||
SharedMediaTypesMask types;
|
SharedMediaTypesMask types;
|
||||||
|
@ -71,18 +79,21 @@ struct SharedMediaAddExisting {
|
||||||
struct SharedMediaAddSlice {
|
struct SharedMediaAddSlice {
|
||||||
SharedMediaAddSlice(
|
SharedMediaAddSlice(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
|
MsgId topicRootId,
|
||||||
SharedMediaType type,
|
SharedMediaType type,
|
||||||
std::vector<MsgId> &&messageIds,
|
std::vector<MsgId> &&messageIds,
|
||||||
MsgRange noSkipRange,
|
MsgRange noSkipRange,
|
||||||
std::optional<int> count = std::nullopt)
|
std::optional<int> count = std::nullopt)
|
||||||
: peerId(peerId)
|
: peerId(peerId)
|
||||||
, messageIds(std::move(messageIds))
|
, topicRootId(topicRootId)
|
||||||
, noSkipRange(noSkipRange)
|
, messageIds(std::move(messageIds))
|
||||||
, type(type)
|
, noSkipRange(noSkipRange)
|
||||||
, count(count) {
|
, type(type)
|
||||||
|
, count(count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerId peerId = 0;
|
PeerId peerId = 0;
|
||||||
|
MsgId topicRootId = 0;
|
||||||
std::vector<MsgId> messageIds;
|
std::vector<MsgId> messageIds;
|
||||||
MsgRange noSkipRange;
|
MsgRange noSkipRange;
|
||||||
SharedMediaType type = SharedMediaType::kCount;
|
SharedMediaType type = SharedMediaType::kCount;
|
||||||
|
@ -130,23 +141,21 @@ struct SharedMediaInvalidateBottom {
|
||||||
struct SharedMediaKey {
|
struct SharedMediaKey {
|
||||||
SharedMediaKey(
|
SharedMediaKey(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
|
MsgId topicRootId,
|
||||||
SharedMediaType type,
|
SharedMediaType type,
|
||||||
MsgId messageId)
|
MsgId messageId)
|
||||||
: peerId(peerId)
|
: peerId(peerId)
|
||||||
|
, topicRootId(topicRootId)
|
||||||
, type(type)
|
, type(type)
|
||||||
, messageId(messageId) {
|
, messageId(messageId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const SharedMediaKey &other) const {
|
friend inline constexpr auto operator<=>(
|
||||||
return (peerId == other.peerId)
|
const SharedMediaKey &,
|
||||||
&& (type == other.type)
|
const SharedMediaKey &) = default;
|
||||||
&& (messageId == other.messageId);
|
|
||||||
}
|
|
||||||
bool operator!=(const SharedMediaKey &other) const {
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
PeerId peerId = 0;
|
PeerId peerId = 0;
|
||||||
|
MsgId topicRootId = 0;
|
||||||
SharedMediaType type = SharedMediaType::kCount;
|
SharedMediaType type = SharedMediaType::kCount;
|
||||||
MsgId messageId = 0;
|
MsgId messageId = 0;
|
||||||
|
|
||||||
|
@ -173,14 +182,17 @@ using SharedMediaResult = SparseIdsListResult;
|
||||||
struct SharedMediaSliceUpdate {
|
struct SharedMediaSliceUpdate {
|
||||||
SharedMediaSliceUpdate(
|
SharedMediaSliceUpdate(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
|
MsgId topicRootId,
|
||||||
SharedMediaType type,
|
SharedMediaType type,
|
||||||
const SparseIdsSliceUpdate &data)
|
const SparseIdsSliceUpdate &data)
|
||||||
: peerId(peerId)
|
: peerId(peerId)
|
||||||
|
, topicRootId(topicRootId)
|
||||||
, type(type)
|
, type(type)
|
||||||
, data(data) {
|
, data(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerId peerId = 0;
|
PeerId peerId = 0;
|
||||||
|
MsgId topicRootId = 0;
|
||||||
SharedMediaType type = SharedMediaType::kCount;
|
SharedMediaType type = SharedMediaType::kCount;
|
||||||
SparseIdsSliceUpdate data;
|
SparseIdsSliceUpdate data;
|
||||||
};
|
};
|
||||||
|
@ -205,11 +217,17 @@ public:
|
||||||
rpl::producer<SharedMediaInvalidateBottom> bottomInvalidated() const;
|
rpl::producer<SharedMediaInvalidateBottom> bottomInvalidated() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Key {
|
||||||
|
PeerId peerId = 0;
|
||||||
|
MsgId topicRootId = 0;
|
||||||
|
|
||||||
|
friend inline constexpr auto operator<=>(Key, Key) = default;
|
||||||
|
};
|
||||||
using Lists = std::array<SparseIdsList, kSharedMediaTypeCount>;
|
using Lists = std::array<SparseIdsList, kSharedMediaTypeCount>;
|
||||||
|
|
||||||
std::map<PeerId, Lists>::iterator enforceLists(PeerId peer);
|
std::map<Key, Lists>::iterator enforceLists(Key key);
|
||||||
|
|
||||||
std::map<PeerId, Lists> _lists;
|
std::map<Key, Lists> _lists;
|
||||||
|
|
||||||
rpl::event_stream<SharedMediaSliceUpdate> _sliceUpdated;
|
rpl::event_stream<SharedMediaSliceUpdate> _sliceUpdated;
|
||||||
rpl::event_stream<SharedMediaRemoveOne> _oneRemoved;
|
rpl::event_stream<SharedMediaRemoveOne> _oneRemoved;
|
||||||
|
|
|
@ -1443,7 +1443,7 @@ void HidePinnedBar(
|
||||||
close();
|
close();
|
||||||
auto &session = peer->session();
|
auto &session = peer->session();
|
||||||
const auto migrated = peer->migrateFrom();
|
const auto migrated = peer->migrateFrom();
|
||||||
const auto top = Data::ResolveTopPinnedId(peer, migrated);
|
const auto top = Data::ResolveTopPinnedId(peer, MsgId(0), migrated);
|
||||||
const auto universal = !top
|
const auto universal = !top
|
||||||
? MsgId(0)
|
? MsgId(0)
|
||||||
: (migrated && !peerIsChannel(top.peer))
|
: (migrated && !peerIsChannel(top.peer))
|
||||||
|
|
|
@ -1707,11 +1707,13 @@ void SessionController::hideLayer(anim::type animated) {
|
||||||
|
|
||||||
void SessionController::openPhoto(
|
void SessionController::openPhoto(
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
FullMsgId contextId) {
|
FullMsgId contextId,
|
||||||
|
MsgId topicRootId) {
|
||||||
_window->openInMediaView(Media::View::OpenRequest(
|
_window->openInMediaView(Media::View::OpenRequest(
|
||||||
this,
|
this,
|
||||||
photo,
|
photo,
|
||||||
session().data().message(contextId)));
|
session().data().message(contextId),
|
||||||
|
topicRootId));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionController::openPhoto(
|
void SessionController::openPhoto(
|
||||||
|
@ -1723,18 +1725,21 @@ void SessionController::openPhoto(
|
||||||
void SessionController::openDocument(
|
void SessionController::openDocument(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
FullMsgId contextId,
|
FullMsgId contextId,
|
||||||
|
MsgId topicRootId,
|
||||||
bool showInMediaView) {
|
bool showInMediaView) {
|
||||||
if (showInMediaView) {
|
if (showInMediaView) {
|
||||||
_window->openInMediaView(Media::View::OpenRequest(
|
_window->openInMediaView(Media::View::OpenRequest(
|
||||||
this,
|
this,
|
||||||
document,
|
document,
|
||||||
session().data().message(contextId)));
|
session().data().message(contextId),
|
||||||
|
topicRootId));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Data::ResolveDocument(
|
Data::ResolveDocument(
|
||||||
this,
|
this,
|
||||||
document,
|
document,
|
||||||
session().data().message(contextId));
|
session().data().message(contextId),
|
||||||
|
topicRootId);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SessionController::cachedChatThemeValue(
|
auto SessionController::cachedChatThemeValue(
|
||||||
|
|
|
@ -441,11 +441,15 @@ public:
|
||||||
void showPassportForm(const Passport::FormRequest &request);
|
void showPassportForm(const Passport::FormRequest &request);
|
||||||
void clearPassportForm();
|
void clearPassportForm();
|
||||||
|
|
||||||
void openPhoto(not_null<PhotoData*> photo, FullMsgId contextId);
|
void openPhoto(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
FullMsgId contextId,
|
||||||
|
MsgId topicRootId);
|
||||||
void openPhoto(not_null<PhotoData*> photo, not_null<PeerData*> peer);
|
void openPhoto(not_null<PhotoData*> photo, not_null<PeerData*> peer);
|
||||||
void openDocument(
|
void openDocument(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
FullMsgId contextId,
|
FullMsgId contextId,
|
||||||
|
MsgId topicRootId,
|
||||||
bool showInMediaView = false);
|
bool showInMediaView = false);
|
||||||
|
|
||||||
void showChooseReportMessages(
|
void showChooseReportMessages(
|
||||||
|
|
Loading…
Add table
Reference in a new issue