Add SharedMediaSliceMerged for migrated histories.

This commit is contained in:
John Preston 2017-08-27 14:59:08 +03:00
parent 2363a6bd44
commit 449986456e
9 changed files with 398 additions and 373 deletions

View File

@ -46,6 +46,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "numbers.h"
#include "observer_peer.h"
#include "auth_session.h"
#include "storage/storage_facade.h"
#include "storage/storage_shared_media.h"
#include "window/themes/window_theme.h"
#include "window/notifications_manager.h"
#include "platform/platform_notifications_manager.h"
@ -1029,6 +1031,13 @@ namespace {
existing->setViewsCount(m.has_views() ? m.vviews.v : -1);
existing->addToOverview(AddToOverviewNew);
if (auto sharedMediaTypes = existing->sharedMediaTypes()) {
Auth().storage().add(Storage::SharedMediaAddNew(
peerId,
sharedMediaTypes,
existing->id));
}
if (!existing->detached()) {
App::checkSavedGif(existing);
return true;

View File

@ -62,6 +62,42 @@ History *GetMigratedHistory(
} // namespace
base::optional<Storage::SharedMediaType> SharedMediaOverviewType(
Storage::SharedMediaType type) {
if (SharedMediaTypeToOverview(type) != OverviewCount) {
return type;
}
return base::none;
}
void SharedMediaShowOverview(
Storage::SharedMediaType type,
not_null<History*> history) {
if (SharedMediaOverviewType(type)) {
Ui::showPeerOverview(history, SharedMediaTypeToOverview(type));
}
}
QString SharedMediaSlice::debug() const {
auto before = _skippedBefore
? (*_skippedBefore
? ('(' + QString::number(*_skippedBefore) + ").. ")
: QString())
: QString(".. ");
auto after = _skippedAfter
? (*_skippedAfter
? (" ..(" + QString::number(*_skippedAfter) + ')')
: QString())
: QString(" ..");
auto middle = (size() > 2)
? QString::number((*this)[0]) + " .. " + QString::number((*this)[size() - 1])
: (size() > 1)
? QString::number((*this)[0]) + ' ' + QString::number((*this)[1])
: ((size() > 0) ? QString((*this)[0]) : QString());
return before + middle + after;
}
SharedMediaViewer::SharedMediaViewer(
Key key,
int limitBefore,
@ -70,22 +106,8 @@ SharedMediaViewer::SharedMediaViewer(
, _limitBefore(limitBefore)
, _limitAfter(limitAfter)
, _data(_key) {
}
base::optional<Storage::SharedMediaType> SharedMediaOverviewType(
Storage::SharedMediaType type) {
if (SharedMediaTypeToOverview(type) != OverviewCount) {
return type;
}
return base::none;
}
void SharedMediaShowOverview(
Storage::SharedMediaType type,
not_null<History*> history) {
if (SharedMediaOverviewType(type)) {
Ui::showPeerOverview(history, SharedMediaTypeToOverview(type));
}
Expects(IsServerMsgId(key.messageId) || (key.messageId == 0));
Expects((key.messageId != 0) || (limitBefore == 0 && limitAfter == 0));
}
void SharedMediaViewer::start() {
@ -125,10 +147,15 @@ void SharedMediaViewer::mergeSliceData(
base::optional<int> skippedBefore,
base::optional<int> skippedAfter) {
if (messageIds.empty()) {
if (count && *_data._fullCount != *count) {
if (count && _data._fullCount != count) {
_data._fullCount = count;
if (*_data._fullCount <= _data.size()) {
_data._fullCount = _data.size();
_data._skippedBefore = _data._skippedAfter = 0;
}
updated.notify(_data);
}
sliceToLimits();
return;
}
if (count) {
@ -285,125 +312,71 @@ void SharedMediaViewer::requestMessages(RequestDirection direction) {
requestAroundData.second);
}
//
//base::optional<int> SharedMediaViewerMerged::Data::fullCount() const {
// if (_historyCount && _migratedCount) {
// return (*_historyCount + *_migratedCount);
// }
// return base::none;
//}
//base::optional<int> SharedMediaViewerMerged::Data::skippedBefore() const {
// if (_ids.empty()) {
// return base::none;
// } else if (!IsServerMsgId(_ids.front())) {
// return _migratedSkippedBefore;
// } else if (_historySkippedBefore && _migratedCount) {
// return *_historySkippedBefore + *_migratedCount;
// }
// return base::none;
//}
//
//base::optional<int> SharedMediaViewerMerged::Data::skippedAfter() const {
// if (_ids.empty()) {
// return base::none;
// } else if (IsServerMsgId(_ids.back())) {
// return _historySkippedAfter;
// } else if (_migratedSkippedAfter && _historyCount) {
// return *_migratedSkippedAfter + *_historyCount;
// }
// return base::none;
//}
//
//SharedMediaViewerMerged::SharedMediaViewerMerged(
// Type type,
// not_null<History*> history,
// MsgId aroundId,
// int limitBefore,
// int limitAfter)
//: _type(type)
//, _history(GetActualHistory(history))
//, _migrated(GetMigratedHistory(history, _history))
//, _universalAroundId((_history == _migrated) ? -aroundId : aroundId)
//, _limitBefore(limitBefore)
//, _limitAfter(limitAfter)
//, _data(_history, _migrated) {
//}
//
//bool SharedMediaViewerMerged::hasOverview() const {
// return SharedMediaTypeToOverview(_type) != OverviewCount;
//}
//
//void SharedMediaViewerMerged::showOverview() const {
// if (hasOverview()) {
// Ui::showPeerOverview(_history, SharedMediaTypeToOverview(_type));
// }
//}
//
//bool SharedMediaViewerMerged::moveTo(const SharedMediaViewerMerged &other) {
// if (_history != other._history || _type != other._type) {
// return false;
// }
// _universalAroundId = other._universalAroundId;
// if (!containsAroundId()) {
// clearAfterMove();
// }
// load();
// return true;
//}
//
//bool SharedMediaViewerMerged::containsAroundId() const {
// if (_data._ids.empty()) {
// return false;
// }
// auto min = _data._ids.front();
// auto max = _data._ids.back();
// if (IsServerMsgId(_universalAroundId)) {
// return (!IsServerMsgId(min) || min <= aroundId())
// && (IsServerMsgId(max) && max >= aroundId());
// }
// return (!IsServerMsgId(min) && -min <= aroundId())
// && (IsServerMsgId(max) || -max >= aroundId());
//}
//
//bool SharedMediaViewerMerged::amAroundMigrated() const {
// return !IsServerMsgId(_universalAroundId);
//}
//
//not_null<History*> SharedMediaViewerMerged::aroundHistory() const {
// return amAroundMigrated() ? _migrated : _history;
//}
//
//MsgId SharedMediaViewerMerged::aroundId() const {
// return amAroundMigrated() ? -_universalAroundId : _universalAroundId;
//}
//
//void SharedMediaViewerMerged::clearAfterMove() {
// _data = Data(_history, _migrated, _data._historyCount, _data._migratedCount);
//}
//
//void SharedMediaViewerMerged::load() {
// auto weak = base::make_weak_unique(this);
// auto peer = aroundHistory()->peer;
// Auth().storage().query(Storage::SharedMediaQuery(
// peer->id,
// _type,
// aroundId(),
// _limitBefore,
// _limitAfter), [weak, peer](Storage::SharedMediaResult &&result) {
// if (weak) {
// weak->applyStoredResult(peer, std::move(result));
// }
// });
//}
//
//void SharedMediaViewerMerged::applyStoredResult(
// not_null<PeerData*> peer,
// Storage::SharedMediaResult &&result) {
// if (aroundHistory()->peer != peer) {
// return;
// }
// auto aroundMigrated = amAroundMigrated();
// if (result.count) {
// (aroundMigrated ? _data._migratedCount : _data._historyCount) = result.count;
// }
//}
SharedMediaViewerMerged::SharedMediaViewerMerged(
Key key,
int limitBefore,
int limitAfter)
: _key(key)
, _limitBefore(limitBefore)
, _limitAfter(limitAfter)
, _part(PartKey(_key), _limitBefore, _limitAfter)
, _migrated(MigratedViewer(_key, _limitBefore, _limitAfter))
, _data(_key, SharedMediaSlice(PartKey(_key)), MigratedSlice(_key)) {
Expects(IsServerMsgId(key.universalId)
|| (key.universalId == 0)
|| (IsServerMsgId(-key.universalId) && key.migratedPeerId != 0));
Expects((key.universalId != 0) || (limitBefore == 0 && limitAfter == 0));
}
SharedMediaSlice::Key SharedMediaViewerMerged::PartKey(const Key &key) {
return {
key.peerId,
key.type,
(key.universalId < 0) ? 1 : key.universalId
};
}
SharedMediaSlice::Key SharedMediaViewerMerged::MigratedKey(const Key &key) {
return {
key.migratedPeerId,
key.type,
(key.universalId <= 0) ? (-key.universalId) : (ServerMaxMsgId - 1)
};
}
std::unique_ptr<SharedMediaViewer> SharedMediaViewerMerged::MigratedViewer(
const Key &key,
int limitBefore,
int limitAfter) {
return key.migratedPeerId
? std::make_unique<SharedMediaViewer>(
MigratedKey(key),
limitBefore,
limitAfter)
: nullptr;
}
base::optional<SharedMediaSlice> SharedMediaViewerMerged::MigratedSlice(
const Key &key) {
if (!key.migratedPeerId) {
return base::none;
}
return SharedMediaSlice(MigratedKey(key));
}
void SharedMediaViewerMerged::start() {
subscribe(_part.updated, [this](const SharedMediaSlice &update) {
_data = SharedMediaSliceMerged(_key, update, _data._migrated);
updated.notify(_data);
});
if (_migrated) {
subscribe(_migrated->updated, [this](const SharedMediaSlice &update) {
_data = SharedMediaSliceMerged(_key, _data._part, update);
updated.notify(_data);
});
}
_part.start();
if (_migrated) {
_migrated->start();
}
}

View File

@ -42,6 +42,10 @@ public:
, _fullCount(fullCount) {
}
const Key &key() const {
return _key;
}
base::optional<int> fullCount() const {
return _fullCount;
}
@ -62,19 +66,10 @@ public:
return _ids.size();
}
using iterator = base::flat_set<MsgId>::const_iterator;
MsgId operator[](int index) const {
Expects(index >= 0 && index < size());
iterator begin() const {
return _ids.begin();
}
iterator end() const {
return _ids.end();
}
iterator cbegin() const {
return begin();
}
iterator cend() const {
return end();
return *(_ids.begin() + index);
}
base::optional<int> distance(const Key &a, const Key &b) const {
@ -84,14 +79,16 @@ public:
|| b.peerId != _key.peerId) {
return base::none;
}
auto i = _ids.find(a.messageId);
auto j = _ids.find(b.messageId);
if (i == _ids.end() || j == _ids.end()) {
return base::none;
if (auto i = indexOf(a.messageId)) {
if (auto j = indexOf(b.messageId)) {
return *j - *i;
}
}
return j - i;
return base::none;
}
QString debug() const;
private:
Key _key;
base::flat_set<MsgId> _ids;
@ -115,6 +112,8 @@ public:
Key key,
int limitBefore,
int limitAfter);
SharedMediaViewer(const SharedMediaViewer &other) = delete;
SharedMediaViewer(SharedMediaViewer &&other) = default;
void start();
@ -144,7 +143,6 @@ private:
base::optional<int> skippedBefore = base::none,
base::optional<int> skippedAfter = base::none);
Key _key;
int _limitBefore = 0;
int _limitAfter = 0;
@ -153,164 +151,196 @@ private:
SharedMediaSlice _data;
};
//
//class SharedMediaSliceMerged :
// private MTP::Sender,
// private base::Subscriber,
// public base::enable_weak_from_this {
//public:
// class Data;
//
//private:
// friend class Data;
// using UniversalMsgId = MsgId;
//
//public:
// using Type = Storage::SharedMediaType;
//
// SharedMediaSliceMerged(
// Type type,
// not_null<History*> history,
// MsgId aroundId,
// int limitBefore,
// int limitAfter);
//
// bool hasOverview() const;
// void showOverview() const;
// bool moveTo(const SharedMediaSliceMerged &other);
//
// void load();
//
// class Data {
// public:
// base::optional<int> fullCount() const;
// base::optional<int> skippedBefore() const;
// base::optional<int> skippedAfter() const;
// int size() const {
// return _ids.size();
// }
//
// class iterator {
// public:
// FullMsgId operator*() const {
// auto id = _data->_ids[_index];
// Assert(IsServerMsgId(id)
// || (_data->_migrated != nullptr && IsServerMsgId(-id)));
// return IsServerMsgId(id)
// ? FullMsgId(_data->_history->channelId(), id)
// : FullMsgId(_data->_migrated->channelId(), -id);
// }
// iterator &operator--() {
// --_index;
// return *this;
// }
// iterator operator--(int) {
// auto result = *this;
// --*this;
// return result;
// }
// iterator &operator++() {
// ++_index;
// return *this;
// }
// iterator operator++(int) {
// auto result = *this;
// ++*this;
// return result;
// }
// iterator &operator+=(int offset) {
// _index += offset;
// return *this;
// }
// iterator operator+(int offset) const {
// auto result = *this;
// return result += offset;
// }
// bool operator==(iterator other) const {
// return (_data == other._data) && (_index == other._index);
// }
// bool operator!=(iterator other) const {
// return !(*this == other);
// }
// bool operator<(iterator other) const {
// return (_data < other._data)
// || (_data == other._data && _index < other._index);
// }
//
// private:
// friend class Data;
//
// iterator(not_null<const Data*> data, int index)
// : _data(data)
// , _index(index) {
// }
//
// not_null<const Data*> _data;
// int _index = 0;
//
// };
//
// iterator begin() const {
// return iterator(this, 0);
// }
// iterator end() const {
// iterator(this, _ids.size());
// }
// iterator cbegin() const {
// return begin();
// }
// iterator cend() const {
// return end();
// }
//
// private:
// friend class iterator;
// friend class SharedMediaSliceMerged;
//
// Data(
// not_null<History*> history,
// History *migrated,
// base::optional<int> historyCount = base::none,
// base::optional<int> migratedCount = base::none)
// : _history(history)
// , _migrated(migrated)
// , _historyCount(historyCount)
// , _migratedCount(migratedCount) {
// if (!_migrated) {
// _migratedCount = 0;
// }
// }
//
// not_null<History*> _history;
// History *_migrated = nullptr;
// std::vector<UniversalMsgId> _ids;
// base::optional<int> _historyCount;
// base::optional<int> _historySkippedBefore;
// base::optional<int> _historySkippedAfter;
// base::optional<int> _migratedCount;
// base::optional<int> _migratedSkippedBefore;
// base::optional<int> _migratedSkippedAfter;
//
// };
// base::Observable<Data> updated;
//
//private:
// bool amAroundMigrated() const;
// not_null<History*> aroundHistory() const;
// MsgId aroundId() const;
//
// void applyStoredResult(
// not_null<PeerData*> peer,
// Storage::SharedMediaResult &&result);
// bool containsAroundId() const;
// void clearAfterMove();
//
// Type _type = Type::kCount;
// not_null<History*> _history;
// History *_migrated = nullptr;
// UniversalMsgId _universalAroundId = 0;
// int _limitBefore = 0;
// int _limitAfter = 0;
// Data _data;
//
//};
class SharedMediaViewerMerged;
class SharedMediaSliceMerged {
public:
using Type = Storage::SharedMediaType;
using UniversalMsgId = MsgId;
struct Key {
Key(
PeerId peerId,
PeerId migratedPeerId,
Type type,
UniversalMsgId universalId)
: peerId(peerId)
, migratedPeerId(migratedPeerId)
, type(type)
, universalId(universalId) {
}
bool operator==(const Key &other) const {
return (peerId == other.peerId)
&& (migratedPeerId == other.migratedPeerId)
&& (type == other.type)
&& (universalId == other.universalId);
}
PeerId peerId = 0;
PeerId migratedPeerId = 0;
Type type = Type::kCount;
UniversalMsgId universalId = 0;
};
SharedMediaSliceMerged(
Key key,
SharedMediaSlice part,
base::optional<SharedMediaSlice> migrated)
: _key(key)
, _part(part)
, _migrated(migrated) {
}
base::optional<int> fullCount() const {
return Add(
_part.fullCount(),
_migrated ? _migrated->fullCount() : 0);
}
base::optional<int> skippedBefore() const {
return Add(
isolatedInMigrated() ? 0 : _part.skippedBefore(),
_migrated
? (isolatedInPart()
? _migrated->fullCount()
: _migrated->skippedBefore())
: 0
);
}
base::optional<int> skippedAfter() const {
return Add(
isolatedInMigrated() ? _part.fullCount() : _part.skippedAfter(),
isolatedInPart() ? 0 : _migrated->skippedAfter()
);
}
base::optional<int> indexOf(FullMsgId fullId) const {
return isFromPart(fullId)
? (_part.indexOf(fullId.msg) | func::add(migratedSize()))
: isolatedInPart()
? base::none
: isFromMigrated(fullId)
? _migrated->indexOf(fullId.msg)
: base::none;
}
int size() const {
return (isolatedInPart() ? 0 : migratedSize())
+ (isolatedInMigrated() ? 0 : _part.size());
}
FullMsgId operator[](int index) const {
Expects(index >= 0 && index < size());
if (auto size = migratedSize()) {
if (index < size) {
return ComputeId(*_migrated, index);
}
index -= size;
}
return ComputeId(_part, index);
}
base::optional<int> distance(const Key &a, const Key &b) const {
if (a.type != _key.type
|| b.type != _key.type
|| a.peerId != _key.peerId
|| b.peerId != _key.peerId
|| a.migratedPeerId != _key.migratedPeerId
|| b.migratedPeerId != _key.migratedPeerId) {
return base::none;
}
if (auto i = indexOf(ComputeId(a))) {
if (auto j = indexOf(ComputeId(b))) {
return *j - *i;
}
}
return base::none;
}
QString debug() const {
return (_migrated ? (_migrated->debug() + '|') : QString()) + _part.debug();
}
private:
static bool IsFromSlice(const SharedMediaSlice &slice, FullMsgId fullId) {
auto peer = slice.key().peerId;
return peerIsChannel(peer)
? (peer == peerFromChannel(fullId.channel))
: !fullId.channel;
}
static FullMsgId ComputeId(PeerId peerId, MsgId msgId) {
return FullMsgId(
peerIsChannel(peerId) ? peerToBareInt(peerId) : 0,
msgId);
}
static FullMsgId ComputeId(const SharedMediaSlice &slice, int index) {
return ComputeId(slice.key().peerId, slice[index]);
};
static FullMsgId ComputeId(const Key &key) {
return (key.universalId > 0)
? ComputeId(key.peerId, key.universalId)
: ComputeId(key.migratedPeerId, -key.universalId);
}
static base::optional<int> Add(
const base::optional<int> &a,
const base::optional<int> &b) {
return (a && b) ? base::make_optional(*a + *b) : base::none;
}
bool isFromPart(FullMsgId fullId) const {
return IsFromSlice(_part, fullId);
}
bool isFromMigrated(FullMsgId fullId) const {
return _migrated ? IsFromSlice(*_migrated, fullId) : false;
}
int migratedSize() const {
return isolatedInPart() ? 0 : _migrated->size();
}
bool isolatedInPart() const {
return IsServerMsgId(_key.universalId)
&& (!_migrated || _part.skippedBefore() != 0);
}
bool isolatedInMigrated() const {
return IsServerMsgId(-_key.universalId)
&& (_migrated->skippedAfter() != 0);
}
Key _key;
SharedMediaSlice _part;
base::optional<SharedMediaSlice> _migrated;
friend class SharedMediaViewerMerged;
};
class SharedMediaViewerMerged : private base::Subscriber {
public:
using Type = SharedMediaSliceMerged::Type;
using Key = SharedMediaSliceMerged::Key;
SharedMediaViewerMerged(
Key key,
int limitBefore,
int limitAfter);
SharedMediaViewerMerged(const SharedMediaViewerMerged &other) = delete;
SharedMediaViewerMerged(SharedMediaViewerMerged &&other) = default;
void start();
base::Observable<SharedMediaSliceMerged> updated;
private:
static SharedMediaSlice::Key PartKey(const Key &key);
static SharedMediaSlice::Key MigratedKey(const Key &key);
static std::unique_ptr<SharedMediaViewer> MigratedViewer(
const Key &key,
int limitBefore,
int limitAfter);
static base::optional<SharedMediaSlice> MigratedSlice(const Key &key);
Key _key;
int _limitBefore = 0;
int _limitAfter = 0;
SharedMediaViewer _part;
std::unique_ptr<SharedMediaViewer> _migrated;
SharedMediaSliceMerged _data;
};

View File

@ -68,13 +68,13 @@ constexpr auto kIdsPreloadAfter = 28;
} // namespace
struct MediaView::SharedMedia {
SharedMedia(SharedMediaViewer::Key key)
SharedMedia(SharedMediaViewerMerged::Key key)
: key(key)
, slice(key, kIdsLimit, kIdsLimit) {
}
SharedMediaViewer::Key key;
SharedMediaViewer slice;
SharedMediaViewerMerged::Key key;
SharedMediaViewerMerged slice;
};
MediaView::MediaView() : TWidget(nullptr)
@ -192,7 +192,7 @@ void MediaView::moveToScreen() {
_saveMsg.moveTo((width() - _saveMsg.width()) / 2, (height() - _saveMsg.height()) / 2);
}
void MediaView::handleSharedMediaUpdate(const SharedMediaSlice &update) {
void MediaView::handleSharedMediaUpdate(const SharedMediaSliceMerged &update) {
if (isHidden() || (!_photo && !_doc) || !_sharedMedia) {
_index = _fullIndex = _fullCount = base::none;
return;
@ -275,9 +275,9 @@ void MediaView::documentUpdated(DocumentData *doc) {
}
void MediaView::changingMsgId(not_null<HistoryItem*> row, MsgId newId) {
if (row->id == _msgid) {
_msgid = newId;
validateSharedMedia();
if (row->fullId() == _msgid) {
_msgid = FullMsgId(_msgid.channel, newId);
refreshSharedMedia();
}
}
@ -367,7 +367,7 @@ void MediaView::updateControls() {
d = date(_photo->date);
} else if (_doc) {
d = date(_doc->date);
} else if (HistoryItem *item = App::histItemById(_msgmigrated ? 0 : _channel, _msgid)) {
} else if (auto item = App::histItemById(_msgid)) {
d = item->date;
}
if (d.date() == dNow.date()) {
@ -409,7 +409,7 @@ void MediaView::updateActions() {
if (_doc && _doc->loading()) {
_actions.push_back({ lang(lng_cancel), SLOT(onSaveCancel()) });
}
if (_msgid > 0 && _msgid < ServerMaxMsgId) {
if (IsServerMsgId(_msgid.msg)) {
_actions.push_back({ lang(lng_context_to_msg), SLOT(onToMessage()) });
}
if (_doc && !_doc->filepath(DocumentData::FilePathResolveChecked).isEmpty()) {
@ -535,12 +535,12 @@ void MediaView::step_radial(TimeMs ms, bool timer) {
_autoplayVideoDocument = _doc;
}
if (!_doc->data().isEmpty() && (_doc->isAnimation() || _doc->isVideo())) {
displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid));
displayDocument(_doc, App::histItemById(_msgid));
} else {
auto &location = _doc->location(true);
if (location.accessEnable()) {
if (_doc->isAnimation() || _doc->isVideo() || _doc->isTheme() || QImageReader(location.name()).canRead()) {
displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid));
displayDocument(_doc, App::histItemById(_msgid));
}
location.accessDisable();
}
@ -731,7 +731,7 @@ void MediaView::onScreenResized(int screen) {
}
if (!ignore) {
moveToScreen();
auto item = (_msgid ? App::histItemById(_msgmigrated ? 0 : _channel, _msgid) : nullptr);
auto item = (_msgid ? App::histItemById(_msgid) : nullptr);
if (_photo) {
displayPhoto(_photo, item);
} else if (_doc) {
@ -741,7 +741,7 @@ void MediaView::onScreenResized(int screen) {
}
void MediaView::onToMessage() {
if (auto item = _msgid ? App::histItemById(_msgmigrated ? 0 : _channel, _msgid) : 0) {
if (auto item = _msgid ? App::histItemById(_msgid) : 0) {
close();
Ui::showPeerHistoryAtItem(item);
}
@ -830,7 +830,7 @@ void MediaView::clipCallback(Media::Clip::Notification notification) {
switch (notification) {
case NotificationReinit: {
if (auto item = App::histItemById(_msgmigrated ? 0 : _channel, _msgid)) {
if (auto item = App::histItemById(_msgid)) {
if (_gif->state() == State::Error) {
stopGif();
updateControls();
@ -944,8 +944,10 @@ void MediaView::onShowInFolder() {
}
void MediaView::onForward() {
auto item = App::histItemById(_msgmigrated ? 0 : _channel, _msgid);
if (!_msgid || !item || item->id < 0 || item->serviceMsg()) return;
auto item = App::histItemById(_msgid);
if (!item || !IsServerMsgId(item->id) || item->serviceMsg()) {
return;
}
close();
if (auto main = App::main()) {
@ -970,7 +972,7 @@ void MediaView::onDelete() {
if (deletingPeerPhoto()) {
App::main()->deletePhotoLayer(_photo);
} else if (auto item = App::histItemById(_msgmigrated ? 0 : _channel, _msgid)) {
} else if (auto item = App::histItemById(_msgid)) {
App::contextItem(item);
App::main()->deleteLayer();
}
@ -1004,8 +1006,7 @@ void MediaView::onCopy() {
base::optional<MediaView::SharedMediaType> MediaView::sharedMediaType() const {
using Type = SharedMediaType;
auto channelId = _msgmigrated ? NoChannel : _channel;
if (auto item = App::histItemById(channelId, _msgid)) {
if (auto item = App::histItemById(_msgid)) {
if (_photo) {
if (item->toHistoryMessage()) {
return Type::Photo;
@ -1024,8 +1025,15 @@ base::optional<MediaView::SharedMediaType> MediaView::sharedMediaType() const {
}
base::optional<MediaView::SharedMediaKey> MediaView::sharedMediaKey() const {
if (!IsServerMsgId(_msgid.msg)) {
return base::none;
}
auto keyForType = [this](SharedMediaType type) -> SharedMediaKey {
return { (_msgmigrated ? _migrated : _history)->peer->id, type, _msgid };
return {
_history->peer->id,
_migrated ? _migrated->peer->id : 0,
type,
(_msgid.channel == _history->channelId()) ? _msgid.msg : -_msgid.msg };
};
return
sharedMediaType()
@ -1038,7 +1046,7 @@ bool MediaView::validSharedMedia() const {
return false;
}
auto countDistanceInData = [](const auto &a, const auto &b) {
return [&](const SharedMediaSlice &data) {
return [&](const SharedMediaSliceMerged &data) {
return data.distance(a, b);
};
};
@ -1046,7 +1054,7 @@ bool MediaView::validSharedMedia() const {
auto distance = (key == _sharedMedia->key) ? 0 :
_sharedMediaData
| countDistanceInData(*key, _sharedMedia->key)
| base::abs;
| func::abs;
if (distance) {
return (*distance < kIdsPreloadAfter);
}
@ -1057,7 +1065,7 @@ bool MediaView::validSharedMedia() const {
void MediaView::validateSharedMedia() {
if (auto key = sharedMediaKey()) {
_sharedMedia = std::make_unique<SharedMedia>(*key);
subscribe(_sharedMedia->slice.updated, [this](const SharedMediaSlice &data) {
subscribe(_sharedMedia->slice.updated, [this](const SharedMediaSliceMerged &data) {
handleSharedMediaUpdate(data);
});
_sharedMedia->slice.start();
@ -1103,14 +1111,12 @@ void MediaView::showPhoto(not_null<PhotoData*> photo, HistoryItem *context) {
}
if (!_animOpacities.isEmpty()) _animOpacities.clear();
_msgid = context ? context->id : 0;
_msgmigrated = context ? (context->history() == _migrated) : false;
_channel = _history ? _history->channelId() : NoChannel;
_msgid = context ? context->fullId() : FullMsgId();
_canForward = context ? context->canForward() : false;
_canDelete = context ? context->canDelete() : false;
_photo = photo;
validateSharedMedia();
refreshSharedMedia();
if (_history) {
if (context && !context->toHistoryMessage()) {
if (!_history->peer->isUser()) {
@ -1140,13 +1146,11 @@ void MediaView::showPhoto(not_null<PhotoData*> photo, PeerData *context) {
}
if (!_animOpacities.isEmpty()) _animOpacities.clear();
_msgid = 0;
_msgmigrated = false;
_channel = NoChannel;
_msgid = {};
_canForward = _canDelete = false;
_photo = photo;
validateSharedMedia();
refreshSharedMedia();
if (_user) {
//if (_user->photos.isEmpty() && _user->photosCount < 0 && _user->photoId && _user->photoId != UnknownPeerPhotoId) {
// _fullIndex = 0;
@ -1217,9 +1221,7 @@ void MediaView::showDocument(not_null<DocumentData*> document, HistoryItem *cont
}
if (!_animOpacities.isEmpty()) _animOpacities.clear();
_msgid = context ? context->id : 0;
_msgmigrated = context ? (context->history() == _migrated) : false;
_channel = _history ? _history->channelId() : NoChannel;
_msgid = context ? context->fullId() : FullMsgId();
_canForward = context ? context->canForward() : false;
_canDelete = context ? context->canDelete() : false;
@ -1239,7 +1241,7 @@ void MediaView::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item) {
_photo = photo;
_radial.stop();
validateSharedMedia();
refreshSharedMedia();
_photoRadialRect = QRect(QPoint((width() - st::radialSize.width()) / 2, (height() - st::radialSize.height()) / 2), st::radialSize);
@ -1299,7 +1301,7 @@ void MediaView::destroyThemePreview() {
}
void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty messages shown as docs: doc can be NULL
auto documentChanged = (!doc || doc != _doc || (item && (item->id != _msgid || (item->history() != (_msgmigrated ? _migrated : _history)))));
auto documentChanged = (!doc || doc != _doc || (item && item->fullId() != _msgid));
if (documentChanged || (!doc->isAnimation() && !doc->isVideo())) {
_fullScreenVideo = false;
_current = QPixmap();
@ -1314,7 +1316,7 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
_photo = nullptr;
_radial.stop();
validateSharedMedia();
refreshSharedMedia();
if (_autoplayVideoDocument && _doc != _autoplayVideoDocument) {
_autoplayVideoDocument = nullptr;
@ -1521,7 +1523,7 @@ void MediaView::createClipReader() {
_current = _doc->thumb->pixNoCache(_doc->thumb->width(), _doc->thumb->height(), videoThumbOptions(), st::mediaviewFileIconSize, st::mediaviewFileIconSize);
}
auto mode = (_doc->isVideo() || _doc->isRoundVideo()) ? Media::Clip::Reader::Mode::Video : Media::Clip::Reader::Mode::Gif;
_gif = Media::Clip::MakeReader(_doc, FullMsgId(_channel, _msgid), [this](Media::Clip::Notification notification) {
_gif = Media::Clip::MakeReader(_doc, _msgid, [this](Media::Clip::Notification notification) {
clipCallback(notification);
}, mode);
@ -1611,7 +1613,7 @@ void MediaView::setClipControllerGeometry() {
void MediaView::onVideoPauseResume() {
if (!_gif) return;
if (auto item = App::histItemById(_msgmigrated ? 0 : _channel, _msgid)) {
if (auto item = App::histItemById(_msgid)) {
if (_gif->state() == Media::Clip::State::Error) {
displayDocument(_doc, item);
} else if (_gif->state() == Media::Clip::State::Finished) {
@ -1637,7 +1639,7 @@ void MediaView::restartVideoAtSeekPosition(TimeMs positionMs) {
auto rounding = (_doc && _doc->isRoundVideo()) ? ImageRoundRadius::Ellipse : ImageRoundRadius::None;
_current = _gif->current(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), rounding, ImageRoundCorner::All, getms());
}
_gif = Media::Clip::MakeReader(_doc, FullMsgId(_channel, _msgid), [this](Media::Clip::Notification notification) {
_gif = Media::Clip::MakeReader(_doc, _msgid, [this](Media::Clip::Notification notification) {
clipCallback(notification);
}, Media::Clip::Reader::Mode::Video, positionMs);
@ -2215,11 +2217,9 @@ bool MediaView::moveToNext(int32 delta) {
if (newIndex < 0 || newIndex >= _sharedMediaData->size()) {
return false;
}
if (auto item = App::histItemById(_history->channelId(), *(_sharedMediaData->begin() + newIndex))) {
if (auto item = App::histItemById((*_sharedMediaData)[newIndex])) {
_index = newIndex;
_msgid = item->id;
_msgmigrated = (item->history() == _migrated);
_channel = _history ? _history->channelId() : NoChannel;
_msgid = item->fullId();
_canForward = item->canForward();
_canDelete = item->canDelete();
stopGif();
@ -2338,7 +2338,7 @@ void MediaView::preloadData(int32 delta) {
auto forgetIndex = *_index - delta * 2;
if (forgetIndex >= 0 && forgetIndex < _sharedMediaData->size()) {
if (auto item = App::histItemById(_history->channelId(), *(_sharedMediaData->begin() + forgetIndex))) {
if (auto item = App::histItemById((*_sharedMediaData)[forgetIndex])) {
if (auto media = item->getMedia()) {
switch (media->type()) {
case MediaTypePhoto: static_cast<HistoryPhoto*>(media)->photo()->forget(); break;
@ -2353,7 +2353,7 @@ void MediaView::preloadData(int32 delta) {
for (auto index = from; index != till; ++index) {
if (index >= 0 && index < _sharedMediaData->size()) {
if (auto item = App::histItemById(_history->channelId(), *(_sharedMediaData->begin() + index))) {
if (auto item = App::histItemById((*_sharedMediaData)[index])) {
if (auto media = item->getMedia()) {
switch (media->type()) {
case MediaTypePhoto: static_cast<HistoryPhoto*>(media)->photo()->download(); break;
@ -2568,7 +2568,7 @@ void MediaView::updateOver(QPoint pos) {
updateOverState(OverRightNav);
} else if (_nameNav.contains(pos)) {
updateOverState(OverName);
} else if ((_msgid > 0 && _msgid < ServerMaxMsgId) && _dateNav.contains(pos)) {
} else if (IsServerMsgId(_msgid.msg) && _dateNav.contains(pos)) {
updateOverState(OverDate);
} else if (_headerHasLink && _headerNav.contains(pos)) {
updateOverState(OverHeader);
@ -2985,7 +2985,8 @@ void MediaView::updateHeader() {
_headerText = _doc->name.isEmpty() ? lang(lng_mediaview_doc_image) : _doc->name;
} else if (_user) {
_headerText = lang(lng_mediaview_profile_photo);
} else if ((_channel && !_history->isMegagroup()) || (_peer && _peer->isChannel() && !_peer->isMegagroup())) {
} else if ((_history && _history->channelId() && !_history->isMegagroup())
|| (_peer && _peer->isChannel() && !_peer->isMegagroup())) {
_headerText = lang(lng_mediaview_channel_photo);
} else if (_peer) {
_headerText = lang(lng_mediaview_group_photo);

View File

@ -156,15 +156,15 @@ private:
void updateMixerVideoVolume() const;
struct SharedMedia;
using SharedMediaType = SharedMediaViewer::Type;
using SharedMediaKey = SharedMediaViewer::Key;
using SharedMediaType = SharedMediaViewerMerged::Type;
using SharedMediaKey = SharedMediaViewerMerged::Key;
base::optional<SharedMediaType> sharedMediaType() const;
base::optional<SharedMediaKey> sharedMediaKey() const;
void validateSharedMedia();
bool validSharedMedia() const;
std::unique_ptr<SharedMedia> createSharedMedia() const;
void refreshSharedMedia();
void handleSharedMediaUpdate(const SharedMediaSlice &update);
void handleSharedMediaUpdate(const SharedMediaSliceMerged &update);
void refreshNavVisibility();
void dropdownHidden();
@ -244,7 +244,7 @@ private:
PhotoData *_photo = nullptr;
DocumentData *_doc = nullptr;
std::unique_ptr<SharedMedia> _sharedMedia;
base::optional<SharedMediaSlice> _sharedMediaData;
base::optional<SharedMediaSliceMerged> _sharedMediaData;
QRect _closeNav, _closeNavIcon;
QRect _leftNav, _leftNavIcon, _rightNav, _rightNavIcon;
@ -326,9 +326,7 @@ private:
base::optional<int> _index; // Index in current _sharedMedia data.
base::optional<int> _fullIndex; // Index in full shared media.
base::optional<int> _fullCount;
MsgId _msgid = 0; // msgId of current photo or file
bool _msgmigrated = false; // msgId is from _migrated history
ChannelId _channel = NoChannel;
FullMsgId _msgid;
bool _canForward = false;
bool _canDelete = false;

View File

@ -74,6 +74,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "base/variant.h"
#include "base/optional.h"
#include "base/algorithm.h"
#include "base/functors.h"
namespace func = base::functors;
#include "base/flat_set.h"
#include "base/flat_map.h"

View File

@ -316,6 +316,13 @@ void SharedMedia::query(
if (peerIt != _lists.end()) {
auto index = static_cast<int>(query.key.type);
peerIt->second[index].query(query, std::move(callback));
} else {
base::TaskQueue::Main().Put(
[
callback = std::move(callback)
]() mutable {
callback(SharedMediaResult());
});
}
}

View File

@ -89,6 +89,9 @@ struct FullMsgId {
FullMsgId() = default;
FullMsgId(ChannelId channel, MsgId msg) : channel(channel), msg(msg) {
}
explicit operator bool() const {
return msg != 0;
}
ChannelId channel = NoChannel;
MsgId msg = 0;
};

View File

@ -5,6 +5,7 @@
<(src_loc)/base/enum_mask.h
<(src_loc)/base/flat_map.h
<(src_loc)/base/flat_set.h
<(src_loc)/base/functors.h
<(src_loc)/base/lambda.h
<(src_loc)/base/lambda_guard.h
<(src_loc)/base/index_based_iterator.h