Beta 9034004 version:

Some lang grammar fixes, all "audio" changed to "voice message"
PeerData can have three loaded states (not loaded, minimal, full)
Interface/Interfaces renamed to Component/Composer
HistoryReply moved to a Component named HistoryMessageReply
This commit is contained in:
John Preston 2016-03-25 14:29:45 +03:00
parent a299c1f9e8
commit 599ede9a0b
22 changed files with 1036 additions and 1038 deletions

View file

@ -663,9 +663,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_stickers_count" = "{count:Loading...|# sticker|# stickers}";
"lng_in_dlg_photo" = "Photo";
"lng_in_dlg_video" = "Video";
"lng_in_dlg_video" = "Video file";
"lng_in_dlg_audio_file" = "Audio file";
"lng_in_dlg_contact" = "Contact";
"lng_in_dlg_audio" = "Audio";
"lng_in_dlg_audio" = "Voice message";
"lng_in_dlg_file" = "File";
"lng_in_dlg_sticker" = "Sticker";
"lng_in_dlg_sticker_emoji" = "{emoji} (sticker)";
@ -720,28 +721,29 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_user_typing" = "{user} is typing";
"lng_users_typing" = "{user} and {second_user} are typing";
"lng_many_typing" = "{count:_not_used_|# is|# are} typing";
"lng_send_action_record_video" = "recording video";
"lng_send_action_record_video" = "recording a video";
"lng_user_action_record_video" = "{user} is recording a video";
"lng_send_action_upload_video" = "sending video";
"lng_send_action_upload_video" = "sending a video";
"lng_user_action_upload_video" = "{user} is sending a video";
"lng_send_action_record_audio" = "recording audio";
"lng_user_action_record_audio" = "{user} is recording an audio";
"lng_send_action_upload_audio" = "sending audio";
"lng_user_action_upload_audio" = "{user} is sending an audio";
"lng_send_action_upload_photo" = "sending photo";
"lng_send_action_record_audio" = "recording a voice message";
"lng_user_action_record_audio" = "{user} is recording a voice message";
"lng_send_action_upload_audio" = "sending a voice message";
"lng_user_action_upload_audio" = "{user} is sending a voice message";
"lng_send_action_upload_photo" = "sending a photo";
"lng_user_action_upload_photo" = "{user} is sending a photo";
"lng_send_action_upload_file" = "sending file";
"lng_send_action_upload_file" = "sending a file";
"lng_user_action_upload_file" = "{user} is sending a file";
"lng_send_action_geo_location" = "picking location";
"lng_send_action_geo_location" = "picking a location";
"lng_user_action_geo_location" = "{user} is picking a location";
"lng_send_action_choose_contact" = "choosing contact";
"lng_send_action_choose_contact" = "choosing a contact";
"lng_user_action_choose_contact" = "{user} is choosing a contact";
"lng_unread_bar" = "{count:_not_used_|# unread message|# unread messages}";
"lng_maps_point" = "Location";
"lng_save_photo" = "Save image";
"lng_save_video" = "Save video";
"lng_save_audio" = "Save audio";
"lng_save_video" = "Save video file";
"lng_save_audio_file" = "Save audio file";
"lng_save_audio" = "Save voice message";
"lng_save_file" = "Save file";
"lng_save_downloaded" = "{ready} / {total} {mb}";
"lng_duration_and_size" = "{duration}, {size}";
@ -766,8 +768,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_context_cancel_download" = "Cancel Download";
"lng_context_show_in_folder" = "Show in Folder";
"lng_context_show_in_finder" = "Show in Finder";
"lng_context_save_video" = "Save Video As...";
"lng_context_save_audio" = "Save Audio As...";
"lng_context_save_video" = "Save Video File As...";
"lng_context_save_audio_file" = "Save Audio File As...";
"lng_context_save_audio" = "Save Voice Message As...";
"lng_context_pack_info" = "Pack Info";
"lng_context_pack_add" = "Add Stickers";
"lng_context_save_file" = "Save File As...";

View file

@ -478,7 +478,13 @@ namespace App {
if (!data) continue;
data->loaded = true;
if (minimal) {
if (data->loadedStatus == PeerData::NotLoaded) {
data->loadedStatus = PeerData::MinimalLoaded;
}
} else if (data->loadedStatus != PeerData::FullLoaded) {
data->loadedStatus = PeerData::FullLoaded;
}
if (status && !minimal) switch (status->type()) {
case mtpc_userStatusEmpty: data->onlineTill = 0; break;
case mtpc_userStatusRecently:
@ -655,7 +661,13 @@ namespace App {
}
if (!data) continue;
data->loaded = true;
if (minimal) {
if (data->loadedStatus == PeerData::NotLoaded) {
data->loadedStatus = PeerData::MinimalLoaded;
}
} else if (data->loadedStatus != PeerData::FullLoaded) {
data->loadedStatus = PeerData::FullLoaded;
}
if (App::main()) {
if (emitPeerUpdated) {
App::main()->peerUpdated(data);
@ -1000,7 +1012,7 @@ namespace App {
}
void checkSavedGif(HistoryItem *item) {
if (!item->Is<HistoryMessageForwarded>() && (item->out() || item->history()->peer == App::self())) {
if (!item->Has<HistoryMessageForwarded>() && (item->out() || item->history()->peer == App::self())) {
if (HistoryMedia *media = item->getMedia()) {
if (DocumentData *doc = media->getDocument()) {
if (doc->isGifv()) {
@ -1394,41 +1406,16 @@ namespace App {
return 0;
}
PeerData *peerLoaded(const PeerId &peer) {
PeersData::const_iterator i = peersData.constFind(peer);
return (i != peersData.cend()) ? i.value() : 0;
}
UserData *userLoaded(const PeerId &id) {
PeerData *peer = peerLoaded(id);
return (peer && peer->loaded) ? peer->asUser() : 0;
}
ChatData *chatLoaded(const PeerId &id) {
PeerData *peer = peerLoaded(id);
return (peer && peer->loaded) ? peer->asChat() : 0;
}
ChannelData *channelLoaded(const PeerId &id) {
PeerData *peer = peerLoaded(id);
return (peer && peer->loaded) ? peer->asChannel() : 0;
}
UserData *userLoaded(int32 user_id) {
return userLoaded(peerFromUser(user_id));
}
ChatData *chatLoaded(int32 chat_id) {
return chatLoaded(peerFromChat(chat_id));
}
ChannelData *channelLoaded(int32 channel_id) {
return channelLoaded(peerFromChannel(channel_id));
}
UserData *curUser() {
return user(MTP::authedId());
}
PeerData *peer(const PeerId &id) {
PeersData::const_iterator i = peersData.constFind(id);
PeerData *peer(const PeerId &id, PeerData::LoadedStatus restriction) {
if (!id) return nullptr;
auto i = peersData.constFind(id);
if (i == peersData.cend()) {
PeerData *newData = 0;
PeerData *newData = nullptr;
if (peerIsUser(id)) {
newData = new UserData(id);
} else if (peerIsChat(id)) {
@ -1436,33 +1423,26 @@ namespace App {
} else if (peerIsChannel(id)) {
newData = new ChannelData(id);
}
if (!newData) return 0;
t_assert(newData != nullptr);
newData->input = MTPinputPeer(MTP_inputPeerEmpty());
i = peersData.insert(id, newData);
}
switch (restriction) {
case PeerData::MinimalLoaded: {
if (i.value()->loadedStatus == PeerData::NotLoaded) {
return nullptr;
}
} break;
case PeerData::FullLoaded: {
if (i.value()->loadedStatus != PeerData::FullLoaded) {
return nullptr;
}
} break;
}
return i.value();
}
UserData *user(const PeerId &id) {
return peer(id)->asUser();
}
ChatData *chat(const PeerId &id) {
return peer(id)->asChat();
}
ChannelData *channel(const PeerId &id) {
return peer(id)->asChannel();
}
UserData *user(int32 user_id) {
return user(peerFromUser(user_id));
}
ChatData *chat(int32 chat_id) {
return chat(peerFromChat(chat_id));
}
ChannelData *channel(int32 channel_id) {
return channel(peerFromChannel(channel_id));
}
UserData *self() {
return ::self;
}

View file

@ -110,21 +110,47 @@ namespace App {
WebPageData *feedWebPage(const MTPDwebPagePending &webpage, WebPageData *convert = 0);
WebPageData *feedWebPage(const MTPWebPage &webpage);
PeerData *peerLoaded(const PeerId &id);
UserData *userLoaded(const PeerId &id);
ChatData *chatLoaded(const PeerId &id);
ChannelData *channelLoaded(const PeerId &id);
UserData *userLoaded(int32 user);
ChatData *chatLoaded(int32 chat);
ChannelData *channelLoaded(int32 channel);
PeerData *peer(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded);
inline UserData *user(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
return asUser(peer(id, restriction));
}
inline ChatData *chat(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
return asChat(peer(id, restriction));
}
inline ChannelData *channel(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
return asChannel(peer(id, restriction));
}
inline UserData *user(UserId userId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
return asUser(peer(peerFromUser(userId), restriction));
}
inline ChatData *chat(ChatId chatId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
return asChat(peer(peerFromChat(chatId), restriction));
}
inline ChannelData *channel(ChannelId channelId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
return asChannel(peer(peerFromChannel(channelId), restriction));
}
inline PeerData *peerLoaded(const PeerId &id) {
return peer(id, PeerData::FullLoaded);
}
inline UserData *userLoaded(const PeerId &id) {
return user(id, PeerData::FullLoaded);
}
inline ChatData *chatLoaded(const PeerId &id) {
return chat(id, PeerData::FullLoaded);
}
inline ChannelData *channelLoaded(const PeerId &id) {
return channel(id, PeerData::FullLoaded);
}
inline UserData *userLoaded(UserId userId) {
return user(userId, PeerData::FullLoaded);
}
inline ChatData *chatLoaded(ChatId chatId) {
return chat(chatId, PeerData::FullLoaded);
}
inline ChannelData *channelLoaded(ChannelId channelId) {
return channel(channelId, PeerData::FullLoaded);
}
PeerData *peer(const PeerId &id);
UserData *user(const PeerId &id);
ChatData *chat(const PeerId &id);
ChannelData *channel(const PeerId &id);
UserData *user(int32 user_id);
ChatData *chat(int32 chat_id);
ChannelData *channel(int32 channel_id);
UserData *self();
PeerData *peerByName(const QString &username);
QString peerName(const PeerData *peer, bool forDialogs = false);

View file

@ -224,18 +224,15 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) {
App::feedUsers(d.vusers);
const QVector<MTPImportedContact> &v(d.vimported.c_vector().v);
int32 uid = 0;
UserData *user = nullptr;
if (!v.isEmpty()) {
const MTPDimportedContact &c(v.front().c_importedContact());
if (c.vclient_id.v != _contactId) return;
uid = c.vuser_id.v;
if (uid && !App::userLoaded(uid)) {
uid = 0;
}
user = App::userLoaded(c.vuser_id.v);
}
if (uid) {
Notify::userIsContactChanged(App::userLoaded(peerFromUser(uid)), true);
if (user) {
Notify::userIsContactChanged(user, true);
Ui::hideLayer();
} else {
_save.hide();

View file

@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
static const int32 AppVersion = 9034;
static const wchar_t *AppVersionStr = L"0.9.34";
static const bool DevVersion = false;
#define BETA_VERSION (9034003ULL) // just comment this line to build public version
#define BETA_VERSION (9034004ULL) // just comment this line to build public version
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
static const wchar_t *AppName = L"Telegram Desktop";

View file

@ -2534,20 +2534,32 @@ Text::Text(style::font font, const QString &text, const TextParseOptions &option
}
}
Text::Text(const Text &other) :
_minResizeWidth(other._minResizeWidth), _maxWidth(other._maxWidth),
_minHeight(other._minHeight),
_text(other._text),
_font(other._font),
_blocks(other._blocks.size()),
_links(other._links),
_startDir(other._startDir)
{
Text::Text(const Text &other)
: _minResizeWidth(other._minResizeWidth)
, _maxWidth(other._maxWidth)
, _minHeight(other._minHeight)
, _text(other._text)
, _font(other._font)
, _blocks(other._blocks.size())
, _links(other._links)
, _startDir(other._startDir) {
for (int32 i = 0, l = _blocks.size(); i < l; ++i) {
_blocks[i] = other._blocks.at(i)->clone();
}
}
Text::Text(Text &&other)
: _minResizeWidth(other._minResizeWidth)
, _maxWidth(other._maxWidth)
, _minHeight(other._minHeight)
, _text(other._text)
, _font(other._font)
, _blocks(other._blocks)
, _links(other._links)
, _startDir(other._startDir) {
other.clearFields();
}
Text &Text::operator=(const Text &other) {
_minResizeWidth = other._minResizeWidth;
_maxWidth = other._maxWidth;
@ -2563,10 +2575,23 @@ Text &Text::operator=(const Text &other) {
return *this;
}
Text &Text::operator=(Text &&other) {
_minResizeWidth = other._minResizeWidth;
_maxWidth = other._maxWidth;
_minHeight = other._minHeight;
_text = other._text;
_font = other._font;
_blocks = other._blocks;
_links = other._links;
_startDir = other._startDir;
other.clearFields();
return *this;
}
void Text::setText(style::font font, const QString &text, const TextParseOptions &options) {
if (!_textStyle) _initDefault();
_font = font;
clean();
clear();
{
TextParser parser(this, text, options);
}
@ -2644,7 +2669,7 @@ void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
void Text::setMarkedText(style::font font, const QString &text, const EntitiesInText &entities, const TextParseOptions &options) {
if (!_textStyle) _initDefault();
_font = font;
clean();
clear();
{
// QString newText; // utf16 of the text for emoji
// newText.reserve(8 * text.size());
@ -3216,10 +3241,14 @@ EntitiesInText Text::originalEntities() const {
return result;
}
void Text::clean() {
void Text::clear() {
for (TextBlocks::iterator i = _blocks.begin(), e = _blocks.end(); i != e; ++i) {
delete *i;
}
clearFields();
}
void Text::clearFields() {
_blocks.clear();
_links.clear();
_maxWidth = _minHeight = 0;

View file

@ -598,7 +598,9 @@ public:
Text(int32 minResizeWidth = QFIXED_MAX);
Text(style::font font, const QString &text, const TextParseOptions &options = _defaultOptions, int32 minResizeWidth = QFIXED_MAX, bool richText = false);
Text(const Text &other);
Text(Text &&other);
Text &operator=(const Text &other);
Text &operator=(Text &&other);
int32 countWidth(int32 width) const;
int32 countHeight(int32 width) const;
@ -686,15 +688,19 @@ public:
return true;
}
void clean();
void clear();
~Text() {
clean();
clear();
}
private:
void recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir = Qt::LayoutDirectionAuto);
// clear() deletes all blocks and calls this method
// it is also called from move constructor / assignment operator
void clearFields();
QFixed _minResizeWidth, _maxWidth;
int32 _minHeight;

File diff suppressed because it is too large Load diff

View file

@ -936,7 +936,6 @@ protected:
};
class HistoryReply; // dynamic_cast optimize
class HistoryMessage; // dynamic_cast optimize
enum HistoryCursorState {
@ -962,43 +961,104 @@ enum HistoryItemType {
HistoryItemJoined
};
struct HistoryMessageVia : public BasicInterface<HistoryMessageVia> {
HistoryMessageVia(Interfaces *);
struct HistoryMessageVia : public BaseComponent<HistoryMessageVia> {
HistoryMessageVia(Composer*) {
}
void create(int32 userId);
void resize(int32 availw) const;
UserData *_bot;
UserData *_bot = nullptr;
mutable QString _text;
mutable int32 _width, _maxWidth;
mutable int _width = 0;
mutable int _maxWidth = 0;
TextLinkPtr _lnk;
};
struct HistoryMessageViews : public BasicInterface<HistoryMessageViews> {
HistoryMessageViews(Interfaces *);
struct HistoryMessageViews : public BaseComponent<HistoryMessageViews> {
HistoryMessageViews(Composer*) {
}
QString _viewsText;
int32 _views, _viewsWidth;
int _views = 0;
int _viewsWidth = 0;
};
struct HistoryMessageSigned : public BasicInterface<HistoryMessageSigned> {
HistoryMessageSigned(Interfaces *);
struct HistoryMessageSigned : public BaseComponent<HistoryMessageSigned> {
HistoryMessageSigned(Composer*) {
}
void create(UserData *from, const QDateTime &date);
int32 maxWidth() const;
int maxWidth() const;
Text _signature;
};
struct HistoryMessageForwarded : public BasicInterface<HistoryMessageForwarded> {
HistoryMessageForwarded(Interfaces *);
struct HistoryMessageForwarded : public BaseComponent<HistoryMessageForwarded> {
HistoryMessageForwarded(Composer*) {
}
void create(const HistoryMessageVia *via) const;
bool display(bool hasVia) const;
PeerData *_authorOriginal, *_fromOriginal;
MsgId _originalId;
mutable Text _text;
PeerData *_authorOriginal = nullptr;
PeerData *_fromOriginal = nullptr;
MsgId _originalId = 0;
mutable Text _text = { 1 };
};
struct HistoryMessageReply : public BaseComponent<HistoryMessageReply> {
HistoryMessageReply(Composer*) {
}
HistoryMessageReply &operator=(HistoryMessageReply &&other) {
replyToMsgId = other.replyToMsgId;
std::swap(replyToMsg, other.replyToMsg);
replyToLnk = std11::move(other.replyToLnk);
replyToName = std11::move(other.replyToName);
replyToText = std11::move(other.replyToText);
replyToVersion = other.replyToVersion;
_maxReplyWidth = other._maxReplyWidth;
std::swap(_replyToVia, other._replyToVia);
return *this;
}
~HistoryMessageReply() {
// clearData() should be called by holder
t_assert(replyToMsg == nullptr);
t_assert(_replyToVia == nullptr);
}
bool updateData(HistoryMessage *holder, bool force = false);
void clearData(HistoryMessage *holder); // must be called before destructor
void checkNameUpdate() const;
void updateName() const;
void resize(int width) const;
void itemRemoved(HistoryMessage *holder, HistoryItem *removed);
enum PaintFlag {
PaintInBubble = 0x01,
PaintSelected = 0x02,
};
Q_DECLARE_FLAGS(PaintFlags, PaintFlag);
void paint(Painter &p, const HistoryItem *holder, int x, int y, int w, PaintFlags flags) const;
MsgId replyToId() const {
return replyToMsgId;
}
int replyToWidth() const {
return _maxReplyWidth;
}
TextLinkPtr replyToLink() const {
return replyToLnk;
}
MsgId replyToMsgId = 0;
HistoryItem *replyToMsg = nullptr;
TextLinkPtr replyToLnk;
mutable Text replyToName, replyToText;
mutable int replyToVersion = 0;
mutable int _maxReplyWidth = 0;
HistoryMessageVia *_replyToVia = nullptr;
int toWidth = 0;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(HistoryMessageReply::PaintFlags);
class HistoryDependentItemCallback : public SharedCallback2<void, ChannelData*, MsgId> {
public:
HistoryDependentItemCallback(FullMsgId dependent) : _dependent(dependent) {
@ -1012,28 +1072,30 @@ private:
// any HistoryItem can have this Interface for
// displaying the day mark above the message
struct HistoryMessageDate : public BasicInterface<HistoryMessageDate> {
HistoryMessageDate(Interfaces *);
struct HistoryMessageDate : public BaseComponent<HistoryMessageDate> {
HistoryMessageDate(Composer*) {
}
void init(const QDateTime &date);
int height() const;
void paint(Painter &p, int y, int w) const;
QString _text;
int _width;
int _width = 0;
};
// any HistoryItem can have this Interface for
// displaying the unread messages bar above the message
struct HistoryMessageUnreadBar : public BasicInterface<HistoryMessageUnreadBar> {
HistoryMessageUnreadBar(Interfaces *);
struct HistoryMessageUnreadBar : public BaseComponent<HistoryMessageUnreadBar> {
HistoryMessageUnreadBar(Composer*) {
}
void init(int count);
int height() const;
void paint(Painter &p, int y, int w) const;
QString _text;
int _width;
int _width = 0;
// if unread bar is freezed the new messages do not
// increment the counter displayed by this bar
@ -1041,11 +1103,11 @@ struct HistoryMessageUnreadBar : public BasicInterface<HistoryMessageUnreadBar>
// it happens when we've opened the conversation and
// we've seen the bar and new messages are marked as read
// as soon as they are added to the chat history
bool _freezed;
bool _freezed = false;
};
class HistoryMedia;
class HistoryItem : public HistoryElem, public Interfaces {
class HistoryItem : public HistoryElem, public Composer {
public:
HistoryItem(const HistoryItem &) = delete;
@ -1075,8 +1137,11 @@ public:
return true;
}
virtual UserData *viaBot() const {
return 0;
UserData *viaBot() const {
if (const HistoryMessageVia *via = Get<HistoryMessageVia>()) {
return via->_bot;
}
return nullptr;
}
History *history() const {
@ -1165,6 +1230,9 @@ public:
bool isSilent() const {
return _flags & MTPDmessage::Flag::f_silent;
}
bool hasOutLayout() const {
return out() && !isPost();
}
virtual int32 viewsCount() const {
return hasViews() ? 1 : -1;
}
@ -1315,10 +1383,10 @@ public:
virtual const HistoryMessage *toHistoryMessage() const { // dynamic_cast optimize
return 0;
}
virtual HistoryReply *toHistoryReply() { // dynamic_cast optimize
return 0;
}
virtual const HistoryReply *toHistoryReply() const { // dynamic_cast optimize
MsgId replyToId() const {
if (auto *reply = Get<HistoryMessageReply>()) {
return reply->replyToId();
}
return 0;
}
@ -1433,7 +1501,7 @@ protected:
// this should be used only in previousItemChanged()
// to add required bits to the Interfaces mask
// after that always use Is<HistoryMessageDate>()
// after that always use Has<HistoryMessageDate>()
bool displayDate() const {
if (HistoryItem *prev = previous()) {
return prev->date.date().day() != date.date().day();
@ -1750,7 +1818,7 @@ public:
return _caption.original();
}
bool needsBubble(const HistoryItem *parent) const override {
return !_caption.isEmpty() || parent->Is<HistoryMessageForwarded>() || parent->toHistoryReply() || parent->viaBot();
return !_caption.isEmpty() || parent->Has<HistoryMessageForwarded>() || parent->Has<HistoryMessageReply>() || parent->viaBot();
}
bool customInfoLayout() const override {
return _caption.isEmpty();
@ -1819,7 +1887,7 @@ public:
return _caption.original();
}
bool needsBubble(const HistoryItem *parent) const override {
return !_caption.isEmpty() || parent->Is<HistoryMessageForwarded>() || parent->toHistoryReply() || parent->viaBot();
return !_caption.isEmpty() || parent->Has<HistoryMessageForwarded>() || parent->Has<HistoryMessageReply>() || parent->viaBot();
}
bool customInfoLayout() const override {
return _caption.isEmpty();
@ -1850,25 +1918,25 @@ private:
};
struct HistoryDocumentThumbed : public BasicInterface<HistoryDocumentThumbed> {
HistoryDocumentThumbed(Interfaces *interfaces) : _thumbw(0), _linkw(0) {
struct HistoryDocumentThumbed : public BaseComponent<HistoryDocumentThumbed> {
HistoryDocumentThumbed(Composer*) {
}
TextLinkPtr _linksavel, _linkcancell;
int32 _thumbw;
int _thumbw = 0;
mutable int32 _linkw;
mutable int _linkw = 0;
mutable QString _link;
};
struct HistoryDocumentCaptioned : public BasicInterface<HistoryDocumentCaptioned> {
HistoryDocumentCaptioned(Interfaces *interfaces) : _caption(st::msgFileMinWidth - st::msgPadding.left() - st::msgPadding.right()) {
struct HistoryDocumentCaptioned : public BaseComponent<HistoryDocumentCaptioned> {
HistoryDocumentCaptioned(Composer*) : _caption(st::msgFileMinWidth - st::msgPadding.left() - st::msgPadding.right()) {
}
Text _caption;
};
struct HistoryDocumentNamed : public BasicInterface<HistoryDocumentNamed> {
HistoryDocumentNamed(Interfaces *interfaces) : _namew(0) {
struct HistoryDocumentNamed : public BaseComponent<HistoryDocumentNamed> {
HistoryDocumentNamed(Composer*) {
}
QString _name;
int32 _namew;
int _namew = 0;
};
class HistoryDocument;
struct HistoryDocumentVoicePlayback {
@ -1878,18 +1946,22 @@ struct HistoryDocumentVoicePlayback {
anim::fvalue a_progress;
Animation _a_progress;
};
struct HistoryDocumentVoice : public BasicInterface<HistoryDocumentVoice> {
HistoryDocumentVoice(Interfaces *that) : _playback(0) {
struct HistoryDocumentVoice : public BaseComponent<HistoryDocumentVoice> {
HistoryDocumentVoice(Composer*) {
}
HistoryDocumentVoice &operator=(HistoryDocumentVoice &&other) {
std::swap(_playback, other._playback);
return *this;
}
~HistoryDocumentVoice() {
deleteAndMark(_playback);
}
void ensurePlayback(const HistoryDocument *interfaces) const;
void checkPlaybackFinished() const;
mutable HistoryDocumentVoicePlayback *_playback;
mutable HistoryDocumentVoicePlayback *_playback = nullptr;
};
class HistoryDocument : public HistoryFileMedia, public Interfaces {
class HistoryDocument : public HistoryFileMedia, public Composer {
public:
HistoryDocument(DocumentData *document, const QString &caption, const HistoryItem *parent);
@ -2021,7 +2093,7 @@ public:
return _caption.original();
}
bool needsBubble(const HistoryItem *parent) const override {
return !_caption.isEmpty() || parent->Is<HistoryMessageForwarded>() || parent->toHistoryReply() || parent->viaBot();
return !_caption.isEmpty() || parent->Has<HistoryMessageForwarded>() || parent->Has<HistoryMessageReply>() || parent->viaBot();
}
bool customInfoLayout() const override {
return _caption.isEmpty();
@ -2327,7 +2399,7 @@ public:
}
bool needsBubble(const HistoryItem *parent) const {
return !_title.isEmpty() || !_description.isEmpty() || parent->Is<HistoryMessageForwarded>() || parent->toHistoryReply() || parent->viaBot();
return !_title.isEmpty() || !_description.isEmpty() || parent->Has<HistoryMessageForwarded>() || parent->Has<HistoryMessageReply>() || parent->viaBot();
}
bool customInfoLayout() const {
return true;
@ -2365,14 +2437,14 @@ public:
static HistoryMessage *create(History *history, MsgId msgId, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *fwd) {
return _create(history, msgId, flags, date, from, fwd);
}
static HistoryMessage *create(History *history, MsgId msgId, MTPDmessage::Flags flags, int32 viaBotId, QDateTime date, int32 from, const QString &msg, const EntitiesInText &entities) {
return _create(history, msgId, flags, viaBotId, date, from, msg, entities);
static HistoryMessage *create(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, const QString &msg, const EntitiesInText &entities) {
return _create(history, msgId, flags, replyTo, viaBotId, date, from, msg, entities);
}
static HistoryMessage *create(History *history, MsgId msgId, MTPDmessage::Flags flags, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption) {
return _create(history, msgId, flags, viaBotId, date, from, doc, caption);
static HistoryMessage *create(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption) {
return _create(history, msgId, flags, replyTo, viaBotId, date, from, doc, caption);
}
static HistoryMessage *create(History *history, MsgId msgId, MTPDmessage::Flags flags, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption) {
return _create(history, msgId, flags, viaBotId, date, from, photo, caption);
static HistoryMessage *create(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption) {
return _create(history, msgId, flags, replyTo, viaBotId, date, from, photo, caption);
}
void initTime();
@ -2380,13 +2452,6 @@ public:
void initMediaFromDocument(DocumentData *doc, const QString &caption);
void fromNameUpdated(int32 width) const;
virtual UserData *viaBot() const override {
if (const HistoryMessageVia *via = Get<HistoryMessageVia>()) {
return via->_bot;
}
return 0;
}
int32 plainMaxWidth() const;
void countPositionAndSize(int32 &left, int32 &width) const;
@ -2403,7 +2468,7 @@ public:
if (!hasFromName()) return false;
if (isAttachedToPrevious()) return false;
return (!emptyText() || !_media || !_media->isDisplayed() || toHistoryReply() || Is<HistoryMessageForwarded>() || viaBot() || !_media->hideFromName());
return (!emptyText() || !_media || !_media->isDisplayed() || Has<HistoryMessageReply>() || Has<HistoryMessageForwarded>() || viaBot() || !_media->hideFromName());
}
bool uploading() const {
return _media && _media->uploading();
@ -2414,7 +2479,7 @@ public:
void setId(MsgId newId) override;
void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const override;
virtual void drawMessageText(Painter &p, QRect trect, uint32 selection) const;
void dependencyItemRemoved(HistoryItem *dependency) override;
void destroy() override;
@ -2422,7 +2487,6 @@ public:
bool pointInTime(int32 right, int32 bottom, int32 x, int32 y, InfoDisplayType type) const override;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const override;
virtual void getStateFromMessageText(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const QRect &r) const;
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const override;
uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const override {
@ -2491,6 +2555,16 @@ public:
return HistoryItem::viewsCount();
}
bool updateDependencyItem() override {
if (auto *reply = Get<HistoryMessageReply>()) {
return reply->updateData(this, true);
}
return true;
}
MsgId dependencyMsgId() const override {
return replyToId();
}
HistoryMessage *toHistoryMessage() override { // dynamic_cast optimize
return this;
}
@ -2509,23 +2583,26 @@ protected:
HistoryMessage(History *history, const MTPDmessage &msg);
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *fwd); // local forwarded
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, int32 viaBotId, QDateTime date, int32 from, const QString &msg, const EntitiesInText &entities); // local message
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption); // local document
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption); // local photo
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, const QString &msg, const EntitiesInText &entities); // local message
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption); // local document
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption); // local photo
friend class HistoryItemInstantiated<HistoryMessage>;
void initDimensions() override;
int resizeGetHeight_(int width) override;
void createInterfaces(int32 viaBotId, int32 viewsCount, const PeerId &authorIdOriginal = 0, const PeerId &fromIdOriginal = 0, MsgId originalId = 0);
bool displayForwardedFrom() const {
if (const HistoryMessageForwarded *fwd = Get<HistoryMessageForwarded>()) {
return Is<HistoryMessageVia>() || !_media || !_media->isDisplayed() || fwd->_authorOriginal->isChannel() || !_media->hideForwardedFrom();
return Has<HistoryMessageVia>() || !_media || !_media->isDisplayed() || fwd->_authorOriginal->isChannel() || !_media->hideForwardedFrom();
}
return false;
}
void paintForwardedInfo(Painter &p, int32 x, int32 y, int32 w, bool selected) const;
void paintForwardedInfo(Painter &p, QRect &trect, bool selected) const;
void paintReplyInfo(Painter &p, QRect &trect, bool selected) const;
// this method draws "via @bot" if it is not painted in forwarded info or in from name
void paintViaBotIdInfo(Painter &p, QRect &trect, bool selected) const;
Text _text = { int(st::msgMinWidth) };
@ -2536,79 +2613,8 @@ protected:
QString _timeText;
int _timeWidth = 0;
};
class HistoryReply : public HistoryMessage, private HistoryItemInstantiated<HistoryReply> {
public:
static HistoryReply *create(History *history, const MTPDmessage &msg) {
return _create(history, msg);
}
static HistoryReply *create(History *history, MsgId msgId, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption) {
return _create(history, msgId, flags, viaBotId, replyTo, date, from, doc, caption);
}
static HistoryReply *create(History *history, MsgId msgId, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption) {
return _create(history, msgId, flags, viaBotId, replyTo, date, from, photo, caption);
}
bool updateDependencyItem() override {
return updateReplyTo(true);
}
MsgId dependencyMsgId() const override {
return replyToId();
}
int32 replyToWidth() const;
TextLinkPtr replyToLink() const;
MsgId replyToId() const;
HistoryItem *replyToMessage() const;
void dependencyItemRemoved(HistoryItem *dependency) override;
void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const override;
void drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selected, bool likeService = false) const;
void drawMessageText(Painter &p, QRect trect, uint32 selection) const override;
void resizeVia(int32 w) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const override;
void getStateFromMessageText(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const QRect &r) const override;
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const override;
PeerData *replyTo() const {
return replyToMsg ? replyToMsg->author() : 0;
}
QString selectedText(uint32 selection) const override;
HistoryReply *toHistoryReply() override { // dynamic_cast optimize
return this;
}
const HistoryReply *toHistoryReply() const override { // dynamic_cast optimize
return this;
}
~HistoryReply();
protected:
HistoryReply(History *history, const MTPDmessage &msg);
HistoryReply(History *history, MsgId msgId, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption);
HistoryReply(History *history, MsgId msgId, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption);
using HistoryItemInstantiated<HistoryReply>::_create;
friend class HistoryItemInstantiated<HistoryReply>;
void initDimensions() override;
int resizeGetHeight_(int width) override;
bool updateReplyTo(bool force = false);
void replyToNameUpdated() const;
MsgId replyToMsgId;
HistoryItem *replyToMsg;
TextLinkPtr replyToLnk;
mutable Text replyToName, replyToText;
mutable int32 replyToVersion;
mutable int32 _maxReplyWidth;
HistoryMessageVia *_replyToVia;
int32 toWidth;
void createInterfacesHelper(MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId);
void createInterfaces(MsgId replyTo, int32 viaBotId, int32 viewsCount, const PeerId &authorIdOriginal = 0, const PeerId &fromIdOriginal = 0, MsgId originalId = 0);
};
@ -2627,7 +2633,7 @@ inline MTPDmessage::Flags newForwardedFlags(PeerData *p, int32 from, HistoryMess
if (from) {
result |= MTPDmessage::Flag::f_from_id;
}
if (fwd->Is<HistoryMessageVia>()) {
if (fwd->Has<HistoryMessageVia>()) {
result |= MTPDmessage::Flag::f_via_bot_id;
}
if (!p->isChannel()) {
@ -2642,21 +2648,22 @@ inline MTPDmessage::Flags newForwardedFlags(PeerData *p, int32 from, HistoryMess
return result;
}
struct HistoryServicePinned : public BasicInterface<HistoryServicePinned> {
HistoryServicePinned(Interfaces *);
struct HistoryServicePinned : public BaseComponent<HistoryServicePinned> {
HistoryServicePinned(Composer*) {
}
MsgId msgId;
HistoryItem *msg;
MsgId msgId = 0;
HistoryItem *msg = nullptr;
TextLinkPtr lnk;
};
class HistoryServiceMessage : public HistoryItem, private HistoryItemInstantiated<HistoryServiceMessage> {
class HistoryService : public HistoryItem, private HistoryItemInstantiated<HistoryService> {
public:
static HistoryServiceMessage *create(History *history, const MTPDmessageService &msg) {
static HistoryService *create(History *history, const MTPDmessageService &msg) {
return _create(history, msg);
}
static HistoryServiceMessage *create(History *history, MsgId msgId, QDateTime date, const QString &msg, MTPDmessage::Flags flags = 0, HistoryMedia *media = 0, int32 from = 0) {
static HistoryService *create(History *history, MsgId msgId, QDateTime date, const QString &msg, MTPDmessage::Flags flags = 0, HistoryMedia *media = 0, int32 from = 0) {
return _create(history, msgId, date, msg, flags, media, from);
}
@ -2710,13 +2717,13 @@ public:
void setServiceText(const QString &text);
~HistoryServiceMessage();
~HistoryService();
protected:
HistoryServiceMessage(History *history, const MTPDmessageService &msg);
HistoryServiceMessage(History *history, MsgId msgId, QDateTime date, const QString &msg, MTPDmessage::Flags flags = 0, HistoryMedia *media = 0, int32 from = 0);
friend class HistoryItemInstantiated<HistoryServiceMessage>;
HistoryService(History *history, const MTPDmessageService &msg);
HistoryService(History *history, MsgId msgId, QDateTime date, const QString &msg, MTPDmessage::Flags flags = 0, HistoryMedia *media = 0, int32 from = 0);
friend class HistoryItemInstantiated<HistoryService>;
void initDimensions() override;
int resizeGetHeight_(int width) override;
@ -2731,7 +2738,7 @@ protected:
int32 _textWidth, _textHeight;
};
class HistoryGroup : public HistoryServiceMessage, private HistoryItemInstantiated<HistoryGroup> {
class HistoryGroup : public HistoryService, private HistoryItemInstantiated<HistoryGroup> {
public:
static HistoryGroup *create(History *history, const MTPDmessageGroup &group, const QDateTime &date) {
@ -2787,7 +2794,7 @@ private:
};
class HistoryCollapse : public HistoryServiceMessage, private HistoryItemInstantiated<HistoryCollapse> {
class HistoryCollapse : public HistoryService, private HistoryItemInstantiated<HistoryCollapse> {
public:
static HistoryCollapse *create(History *history, MsgId wasMinId, const QDateTime &date) {
@ -2822,7 +2829,7 @@ private:
};
class HistoryJoined : public HistoryServiceMessage, private HistoryItemInstantiated<HistoryJoined> {
class HistoryJoined : public HistoryService, private HistoryItemInstantiated<HistoryJoined> {
public:
static HistoryJoined *create(History *history, const QDateTime &date, UserData *from, MTPDmessage::Flags flags) {

View file

@ -948,7 +948,8 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
PhotoLink *lnkPhoto = dynamic_cast<PhotoLink*>(_contextMenuLnk.data());
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
bool lnkIsVideo = lnkDocument ? lnkDocument->document()->isVideo() : false;
bool lnkIsAudio = lnkDocument ? (lnkDocument->document()->voice() != 0) : false;
bool lnkIsAudio = lnkDocument ? (lnkDocument->document()->voice() != nullptr) : false;
bool lnkIsSong = lnkDocument ? (lnkDocument->document()->song() != nullptr) : false;
if (lnkPhoto || lnkDocument) {
if (isUponSelected > 0) {
_menu->addAction(lang(lng_context_copy_selected), this, SLOT(copySelectedText()))->setEnabled(true);
@ -978,7 +979,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
if (lnkDocument && !lnkDocument->document()->filepath(DocumentData::FilePathResolveChecked).isEmpty()) {
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), this, SLOT(showContextInFolder()))->setEnabled(true);
}
_menu->addAction(lang(lnkIsVideo ? lng_context_save_video : (lnkIsAudio ? lng_context_save_audio : lng_context_save_file)), this, SLOT(saveContextFile()))->setEnabled(true);
_menu->addAction(lang(lnkIsVideo ? lng_context_save_video : (lnkIsAudio ? lng_context_save_audio : (lnkIsSong ? lng_context_save_audio_file : lng_context_save_file))), this, SLOT(saveContextFile()))->setEnabled(true);
}
}
if (item && item->hasDirectLink() && isUponSelected != 2 && isUponSelected != -2) {
@ -5996,7 +5997,7 @@ void HistoryWidget::onPhotoUploaded(const FullMsgId &newId, bool silent, const M
uint64 randomId = rand_value<uint64>();
App::historyRegRandom(randomId, newId);
History *hist = item->history();
MsgId replyTo = item->toHistoryReply() ? item->toHistoryReply()->replyToId() : 0;
MsgId replyTo = item->replyToId();
MTPmessages_SendMedia::Flags sendFlags = 0;
if (replyTo) {
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
@ -6048,7 +6049,7 @@ void HistoryWidget::onDocumentUploaded(const FullMsgId &newId, bool silent, cons
uint64 randomId = rand_value<uint64>();
App::historyRegRandom(randomId, newId);
History *hist = item->history();
MsgId replyTo = item->toHistoryReply() ? item->toHistoryReply()->replyToId() : 0;
MsgId replyTo = item->replyToId();
MTPmessages_SendMedia::Flags sendFlags = 0;
if (replyTo) {
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
@ -6077,7 +6078,7 @@ void HistoryWidget::onThumbDocumentUploaded(const FullMsgId &newId, bool silent,
uint64 randomId = rand_value<uint64>();
App::historyRegRandom(randomId, newId);
History *hist = item->history();
MsgId replyTo = item->toHistoryReply() ? item->toHistoryReply()->replyToId() : 0;
MsgId replyTo = item->replyToId();
MTPmessages_SendMedia::Flags sendFlags = 0;
if (replyTo) {
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
@ -6986,7 +6987,7 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() {
} else if (_pinnedBar->msgId != pinnedMsgId) {
_pinnedBar->msgId = pinnedMsgId;
_pinnedBar->msg = 0;
_pinnedBar->text.clean();
_pinnedBar->text.clear();
updatePinnedBar();
update();
}

View file

@ -293,9 +293,10 @@ void LayoutAbstractFileItem::setStatusSize(int32 newSize, int32 fullSize, int32
}
}
LayoutOverviewDate::LayoutOverviewDate(const QDate &date, bool month) : LayoutItem(OverviewItemInfo::Bit())
LayoutOverviewDate::LayoutOverviewDate(const QDate &date, bool month) : LayoutItem()
, _date(date)
, _text(month ? langMonthFull(date) : langDayOfMonthFull(date)) {
AddComponents(OverviewItemInfo::Bit());
}
void LayoutOverviewDate::initDimensions() {
@ -311,7 +312,7 @@ void LayoutOverviewDate::paint(Painter &p, const QRect &clip, uint32 selection,
}
}
LayoutOverviewPhoto::LayoutOverviewPhoto(PhotoData *photo, HistoryItem *parent) : LayoutMediaItem(0, parent)
LayoutOverviewPhoto::LayoutOverviewPhoto(PhotoData *photo, HistoryItem *parent) : LayoutMediaItem(parent)
, _data(photo)
, _link(new PhotoLink(photo))
, _goodLoaded(false) {
@ -385,7 +386,7 @@ void LayoutOverviewPhoto::getState(TextLinkPtr &link, HistoryCursorState &cursor
}
}
LayoutOverviewVideo::LayoutOverviewVideo(DocumentData *video, HistoryItem *parent) : LayoutAbstractFileItem(0, parent)
LayoutOverviewVideo::LayoutOverviewVideo(DocumentData *video, HistoryItem *parent) : LayoutAbstractFileItem(parent)
, _data(video)
, _duration(formatDurationText(_data->duration()))
, _thumbLoaded(false) {
@ -549,9 +550,11 @@ void LayoutOverviewVideo::updateStatusText() const {
}
}
LayoutOverviewVoice::LayoutOverviewVoice(DocumentData *voice, HistoryItem *parent) : LayoutAbstractFileItem(OverviewItemInfo::Bit(), parent)
LayoutOverviewVoice::LayoutOverviewVoice(DocumentData *voice, HistoryItem *parent) : LayoutAbstractFileItem(parent)
, _data(voice)
, _namel(new DocumentOpenLink(_data)) {
AddComponents(OverviewItemInfo::Bit());
t_assert(_data->voice() != 0);
setLinks(new DocumentOpenLink(_data), new DocumentOpenLink(_data), new DocumentCancelLink(_data));
@ -741,7 +744,7 @@ bool LayoutOverviewVoice::updateStatusText() const {
return showPause;
}
LayoutOverviewDocument::LayoutOverviewDocument(DocumentData *document, HistoryItem *parent) : LayoutAbstractFileItem(OverviewItemInfo::Bit(), parent)
LayoutOverviewDocument::LayoutOverviewDocument(DocumentData *document, HistoryItem *parent) : LayoutAbstractFileItem(parent)
, _data(document)
, _msgl(new MessageLink(parent))
, _namel(new DocumentOpenLink(_data))
@ -751,6 +754,8 @@ LayoutOverviewDocument::LayoutOverviewDocument(DocumentData *document, HistoryIt
, _namew(st::semiboldFont->width(_name))
, _datew(st::normalFont->width(_date))
, _colorIndex(documentColorIndex(_data, _ext)) {
AddComponents(OverviewItemInfo::Bit());
setLinks(new DocumentOpenLink(_data), new DocumentSaveLink(_data), new DocumentCancelLink(_data));
setStatusSize(FileStatusSizeReady, _data->size, _data->song() ? _data->song()->duration : -1, 0);
@ -1066,7 +1071,9 @@ namespace {
}
}
LayoutOverviewLink::LayoutOverviewLink(HistoryMedia *media, HistoryItem *parent) : LayoutMediaItem(OverviewItemInfo::Bit(), parent) {
LayoutOverviewLink::LayoutOverviewLink(HistoryMedia *media, HistoryItem *parent) : LayoutMediaItem(parent) {
AddComponents(OverviewItemInfo::Bit());
QString text = _parent->originalText();
EntitiesInText entities = _parent->originalEntities();
@ -1319,7 +1326,7 @@ LayoutOverviewLink::Link::Link(const QString &url, const QString &text)
, lnk(linkFromUrl(url)) {
}
LayoutInlineItem::LayoutInlineItem(InlineResult *result, DocumentData *doc, PhotoData *photo) : LayoutItem(0)
LayoutInlineItem::LayoutInlineItem(InlineResult *result, DocumentData *doc, PhotoData *photo) : LayoutItem()
, _result(result)
, _doc(doc)
, _photo(photo)

View file

@ -101,10 +101,11 @@ public:
};
class LayoutMediaItem;
class LayoutItem : public Interfaces {
class LayoutItem : public Composer {
public:
LayoutItem(uint64 i_mask) : Interfaces(i_mask), _maxw(0), _minh(0) {
LayoutItem() {
}
LayoutItem &operator=(const LayoutItem &) = delete;
int32 maxWidth() const {
return _maxw;
@ -167,14 +168,16 @@ public:
}
protected:
int32 _width, _height, _maxw, _minh;
LayoutItem &operator=(const LayoutItem &);
int _width = 0;
int _height = 0;
int _maxw = 0;
int _minh = 0;
};
class LayoutMediaItem : public LayoutItem {
public:
LayoutMediaItem(uint64 i_mask, HistoryItem *parent) : LayoutItem(i_mask), _parent(parent) {
LayoutMediaItem(HistoryItem *parent) : _parent(parent) {
}
virtual LayoutMediaItem *toLayoutMediaItem() {
@ -194,7 +197,7 @@ protected:
class LayoutRadialProgressItem : public LayoutMediaItem {
public:
LayoutRadialProgressItem(uint64 i_mask, HistoryItem *parent) : LayoutMediaItem(i_mask, parent)
LayoutRadialProgressItem(HistoryItem *parent) : LayoutMediaItem(parent)
, _radial(0)
, a_iconOver(0, 0)
, _a_iconOver(animation(this, &LayoutRadialProgressItem::step_iconOver)) {
@ -240,7 +243,7 @@ private:
class LayoutAbstractFileItem : public LayoutRadialProgressItem {
public:
LayoutAbstractFileItem(uint64 i_mask, HistoryItem *parent) : LayoutRadialProgressItem(i_mask, parent) {
LayoutAbstractFileItem(HistoryItem *parent) : LayoutRadialProgressItem(parent) {
}
protected:
@ -268,19 +271,19 @@ public:
};
class OverviewItemInfo : public BasicInterface<OverviewItemInfo> {
class OverviewItemInfo : public BaseComponent<OverviewItemInfo> {
public:
OverviewItemInfo(Interfaces *) : _top(0) {
OverviewItemInfo(Composer*) {
}
int32 top() const {
int top() const {
return _top;
}
void setTop(int32 top) {
void setTop(int top) {
_top = top;
}
private:
int32 _top;
int _top = 0;
};

View file

@ -3550,7 +3550,7 @@ namespace Local {
return result;
}
void _writePeer(QDataStream &stream, PeerData *peer, int32 fileVersion = AppVersion) {
void _writePeer(QDataStream &stream, PeerData *peer) {
stream << quint64(peer->id) << quint64(peer->photoId);
_writeStorageImageLocation(stream, peer->photoLoc);
if (peer->isUser()) {
@ -3560,7 +3560,7 @@ namespace Local {
if (AppVersion >= 9012) {
stream << qint32(user->flags);
}
if (AppVersion >= 9016 || fileVersion >= 9016) {
if (AppVersion >= 9016) {
stream << (user->botInfo ? user->botInfo->inlinePlaceholder : QString());
}
stream << qint32(user->onlineTill) << qint32(user->contact) << qint32(user->botInfo ? user->botInfo->version : -1);
@ -3580,18 +3580,16 @@ namespace Local {
}
PeerData *_readPeer(FileReadDescriptor &from, int32 fileVersion = 0) {
PeerData *result = 0;
quint64 peerId = 0, photoId = 0;
from.stream >> peerId >> photoId;
StorageImageLocation photoLoc(_readStorageImageLocation(from));
result = App::peerLoaded(peerId);
bool wasLoaded = (result && result->loaded);
PeerData *result = App::peerLoaded(peerId);
bool wasLoaded = (result != nullptr);
if (!wasLoaded) {
result = App::peer(peerId);
result->loaded = true;
result->loadedStatus = PeerData::FullLoaded;
}
if (result->isUser()) {
UserData *user = result->asUser();
@ -3737,7 +3735,7 @@ namespace Local {
}
data.stream << quint32(botsCnt);
for (RecentInlineBots::const_iterator i = bots.cbegin(), e = bots.cend(); i != e; ++i) {
_writePeer(data.stream, *i, 9016);
_writePeer(data.stream, *i);
}
FileWriteDescriptor file(_recentHashtagsAndBotsKey);
file.writeEncrypted(data);

View file

@ -4099,17 +4099,17 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
case mtpc_updateShortMessage: {
const MTPDupdateShortMessage &d(updates.c_updateShortMessage());
if (!App::userLoaded(d.vuser_id.v) || (d.has_via_bot_id() && !App::peerLoaded(peerFromUser(d.vvia_bot_id)))) {
if (!App::userLoaded(d.vuser_id.v) || (d.has_via_bot_id() && !App::userLoaded(d.vvia_bot_id.v))) {
MTP_LOG(0, ("getDifference { good - getting user for updateShortMessage }%1").arg(cTestMode() ? " TESTMODE" : ""));
return getDifference();
}
if (d.has_fwd_from() && d.vfwd_from.type() == mtpc_messageFwdHeader) {
const MTPDmessageFwdHeader &f(d.vfwd_from.c_messageFwdHeader());
if (f.has_from_id() && !App::peerLoaded(peerFromUser(f.vfrom_id))) {
if (f.has_from_id() && !App::userLoaded(f.vfrom_id.v)) {
MTP_LOG(0, ("getDifference { good - getting user for updateShortMessage }%1").arg(cTestMode() ? " TESTMODE" : ""));
return getDifference();
}
if (f.has_channel_id() && !App::peerLoaded(peerFromChannel(f.vchannel_id))) {
if (f.has_channel_id() && !App::channelLoaded(f.vchannel_id.v)) {
MTP_LOG(0, ("getDifference { good - getting user for updateShortMessage }%1").arg(cTestMode() ? " TESTMODE" : ""));
return getDifference();
}
@ -4133,18 +4133,18 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
case mtpc_updateShortChatMessage: {
const MTPDupdateShortChatMessage &d(updates.c_updateShortChatMessage());
bool noFrom = !App::userLoaded(d.vfrom_id.v);
if (!App::chatLoaded(d.vchat_id.v) || noFrom || (d.has_via_bot_id() && !App::peerLoaded(peerFromUser(d.vvia_bot_id)))) {
if (!App::chatLoaded(d.vchat_id.v) || noFrom || (d.has_via_bot_id() && !App::userLoaded(d.vvia_bot_id.v))) {
MTP_LOG(0, ("getDifference { good - getting user for updateShortChatMessage }%1").arg(cTestMode() ? " TESTMODE" : ""));
if (noFrom && App::api()) App::api()->requestFullPeer(App::chatLoaded(d.vchat_id.v));
return getDifference();
}
if (d.has_fwd_from() && d.vfwd_from.type() == mtpc_messageFwdHeader) {
const MTPDmessageFwdHeader &f(d.vfwd_from.c_messageFwdHeader());
if (f.has_from_id() && !App::peerLoaded(peerFromUser(f.vfrom_id))) {
if (f.has_from_id() && !App::userLoaded(f.vfrom_id.v)) {
MTP_LOG(0, ("getDifference { good - getting user for updateShortChatMessage }%1").arg(cTestMode() ? " TESTMODE" : ""));
return getDifference();
}
if (f.has_channel_id() && !App::peerLoaded(peerFromChannel(f.vchannel_id))) {
if (f.has_channel_id() && !App::channelLoaded(f.vchannel_id.v)) {
MTP_LOG(0, ("getDifference { good - getting user for updateShortChatMessage }%1").arg(cTestMode() ? " TESTMODE" : ""));
return getDifference();
}
@ -4357,9 +4357,9 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateChatUserTyping: {
const MTPDupdateChatUserTyping &d(update.c_updateChatUserTyping());
History *history = 0;
if (PeerData *chat = App::peerLoaded(peerFromChat(d.vchat_id.v))) {
if (PeerData *chat = App::chatLoaded(d.vchat_id.v)) {
history = App::historyLoaded(chat->id);
} else if (PeerData *channel = App::peerLoaded(peerFromChannel(d.vchat_id.v))) {
} else if (PeerData *channel = App::channelLoaded(d.vchat_id.v)) {
history = App::historyLoaded(channel->id);
}
UserData *user = (d.vuser_id.v == MTP::authedId()) ? 0 : App::userLoaded(d.vuser_id.v);

View file

@ -1267,8 +1267,9 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_contextMenuLnk = textlnkOver();
PhotoLink *lnkPhoto = dynamic_cast<PhotoLink*>(_contextMenuLnk.data());
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
bool lnkIsAudio = lnkDocument ? (lnkDocument->document()->voice() != 0) : false;
bool lnkIsVideo = lnkDocument ? lnkDocument->document()->isVideo() : false;
bool lnkIsAudio = lnkDocument ? (lnkDocument->document()->voice() != nullptr) : false;
bool lnkIsSong = lnkDocument ? (lnkDocument->document()->song() != nullptr) : false;
if (lnkPhoto || lnkDocument) {
_menu = new PopupMenu();
if (App::hoveredLinkItem()) {
@ -1282,7 +1283,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
if (lnkDocument && !lnkDocument->document()->filepath(DocumentData::FilePathResolveChecked).isEmpty()) {
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), this, SLOT(showContextInFolder()))->setEnabled(true);
}
_menu->addAction(lang(lnkIsVideo ? lng_context_save_video : (lnkIsAudio ? lng_context_save_audio : lng_context_save_file)), this, SLOT(saveContextFile()))->setEnabled(true);
_menu->addAction(lang(lnkIsVideo ? lng_context_save_video : (lnkIsAudio ? lng_context_save_audio : (lnkIsSong ? lng_context_save_audio_file : lng_context_save_file))), this, SLOT(saveContextFile()))->setEnabled(true);
}
}
if (isUponSelected > 1) {

View file

@ -35,8 +35,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "localstorage.h"
namespace {
int32 peerColorIndex(const PeerId &peer) {
int32 myId(MTP::authedId()), peerId(peerToBareInt(peer));
int peerColorIndex(const PeerId &peer) {
UserId myId(MTP::authedId()), peerId(peerToBareInt(peer));
QByteArray both(qsl("%1%2").arg(peerId).arg(myId).toUtf8());
if (both.size() > 15) {
both = both.mid(0, 15);
@ -47,7 +47,7 @@ namespace {
}
}
style::color peerColor(int32 index) {
style::color peerColor(int index) {
static const style::color peerColors[8] = {
style::color(st::color1),
style::color(st::color2),
@ -61,7 +61,7 @@ style::color peerColor(int32 index) {
return peerColors[index];
}
ImagePtr userDefPhoto(int32 index) {
ImagePtr userDefPhoto(int index) {
static const ImagePtr userDefPhotos[UserColorsCount] = {
ImagePtr(qsl(":/ava/art/usercolor1.png"), "PNG"),
ImagePtr(qsl(":/ava/art/usercolor2.png"), "PNG"),
@ -75,7 +75,7 @@ ImagePtr userDefPhoto(int32 index) {
return userDefPhotos[index];
}
ImagePtr chatDefPhoto(int32 index) {
ImagePtr chatDefPhoto(int index) {
static const ImagePtr chatDefPhotos[4] = {
ImagePtr(qsl(":/ava/art/chatcolor1.png"), "PNG"),
ImagePtr(qsl(":/ava/art/chatcolor2.png"), "PNG"),
@ -85,7 +85,7 @@ ImagePtr chatDefPhoto(int32 index) {
return chatDefPhotos[index];
}
ImagePtr channelDefPhoto(int32 index) {
ImagePtr channelDefPhoto(int index) {
static const ImagePtr channelDefPhotos[4] = {
ImagePtr(qsl(":/ava/art/channelcolor1.png"), "PNG"),
ImagePtr(qsl(":/ava/art/channelcolor2.png"), "PNG"),
@ -100,7 +100,7 @@ NotifySettingsPtr globalNotifyAllPtr = UnknownNotifySettings, globalNotifyUsersP
PeerData::PeerData(const PeerId &id) : id(id)
, lnk(new PeerLink(this))
, loaded(false)
, loadedStatus(NotLoaded)
, colorIndex(peerColorIndex(id))
, color(peerColor(colorIndex))
, photoId(UnknownPeerPhotoId)
@ -279,7 +279,7 @@ void UserData::setPhone(const QString &newPhone) {
phone = newPhone;
}
void UserData::setBotInfoVersion(int32 version) {
void UserData::setBotInfoVersion(int version) {
if (version < 0) {
if (botInfo) {
if (!botInfo->commands.isEmpty()) {
@ -850,7 +850,7 @@ QString documentSaveFilename(const DocumentData *data, bool forceSavingAs = fals
} else {
filter = mimeType.filterString() + qsl(";;All files (*.*)");
}
caption = lang(lng_save_file);
caption = lang(data->song() ? lng_save_audio_file : lng_save_file);
prefix = qsl("doc");
}

View file

@ -20,9 +20,21 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
typedef int32 UserId;
typedef int32 ChatId;
typedef int32 ChannelId;
static const ChannelId NoChannel = 0;
typedef int32 MsgId;
struct FullMsgId {
FullMsgId() : channel(NoChannel), msg(0) {
}
FullMsgId(ChannelId channel, MsgId msg) : channel(channel), msg(msg) {
}
ChannelId channel;
MsgId msg;
};
typedef uint64 PeerId;
static const uint64 PeerIdMask = 0xFFFFFFFFULL;
static const uint64 PeerIdTypeMask = 0x300000000ULL;
@ -38,10 +50,10 @@ inline bool peerIsChat(const PeerId &id) {
inline bool peerIsChannel(const PeerId &id) {
return (id & PeerIdTypeMask) == PeerIdChannelShift;
}
inline PeerId peerFromUser(int32 user_id) {
inline PeerId peerFromUser(UserId user_id) {
return PeerIdUserShift | uint64(uint32(user_id));
}
inline PeerId peerFromChat(int32 chat_id) {
inline PeerId peerFromChat(ChatId chat_id) {
return PeerIdChatShift | uint64(uint32(chat_id));
}
inline PeerId peerFromChannel(ChannelId channel_id) {
@ -59,10 +71,10 @@ inline PeerId peerFromChannel(const MTPint &channel_id) {
inline int32 peerToBareInt(const PeerId &id) {
return int32(uint32(id & PeerIdMask));
}
inline int32 peerToUser(const PeerId &id) {
inline UserId peerToUser(const PeerId &id) {
return peerIsUser(id) ? peerToBareInt(id) : 0;
}
inline int32 peerToChat(const PeerId &id) {
inline ChatId peerToChat(const PeerId &id) {
return peerIsChat(id) ? peerToBareInt(id) : 0;
}
inline ChannelId peerToChannel(const PeerId &id) {
@ -112,7 +124,7 @@ inline MTPDmessage::Flags flagsFromMessage(const MTPmessage &msg) {
}
return 0;
}
inline int32 idFromMessage(const MTPmessage &msg) {
inline MsgId idFromMessage(const MTPmessage &msg) {
switch (msg.type()) {
case mtpc_messageEmpty: return msg.c_messageEmpty().vid.v;
case mtpc_message: return msg.c_message().vid.v;
@ -120,7 +132,7 @@ inline int32 idFromMessage(const MTPmessage &msg) {
}
return 0;
}
inline int32 dateFromMessage(const MTPmessage &msg) {
inline TimeId dateFromMessage(const MTPmessage &msg) {
switch (msg.type()) {
case mtpc_message: return msg.c_message().vdate.v;
case mtpc_messageService: return msg.c_messageService().vdate.v;
@ -135,15 +147,6 @@ typedef uint64 DocumentId;
typedef uint64 WebPageId;
static const WebPageId CancelledWebPageId = 0xFFFFFFFFFFFFFFFFULL;
typedef int32 MsgId;
struct FullMsgId {
FullMsgId() : channel(NoChannel), msg(0) {
}
FullMsgId(ChannelId channel, MsgId msg) : channel(channel), msg(msg) {
}
ChannelId channel;
MsgId msg;
};
inline bool operator==(const FullMsgId &a, const FullMsgId &b) {
return (a.channel == b.channel) && (a.msg == b.msg);
}
@ -168,7 +171,7 @@ struct NotifySettings {
NotifySettings() : flags(MTPDpeerNotifySettings::Flag::f_show_previews), mute(0), sound("default") {
}
MTPDpeerNotifySettings::Flags flags;
int32 mute;
TimeId mute;
string sound;
bool previews() const {
return flags & MTPDpeerNotifySettings::Flag::f_show_previews;
@ -184,9 +187,9 @@ static const NotifySettingsPtr EmptyNotifySettings = NotifySettingsPtr(1);
extern NotifySettings globalNotifyAll, globalNotifyUsers, globalNotifyChats;
extern NotifySettingsPtr globalNotifyAllPtr, globalNotifyUsersPtr, globalNotifyChatsPtr;
inline bool isNotifyMuted(NotifySettingsPtr settings, int32 *changeIn = 0) {
inline bool isNotifyMuted(NotifySettingsPtr settings, TimeId *changeIn = 0) {
if (settings != UnknownNotifySettings && settings != EmptyNotifySettings) {
int32 t = unixtime();
TimeId t = unixtime();
if (settings->mute > t) {
if (changeIn) *changeIn = settings->mute - t + 1;
return true;
@ -196,12 +199,12 @@ inline bool isNotifyMuted(NotifySettingsPtr settings, int32 *changeIn = 0) {
return false;
}
static const int32 UserColorsCount = 8;
static const int UserColorsCount = 8;
style::color peerColor(int32 index);
ImagePtr userDefPhoto(int32 index);
ImagePtr chatDefPhoto(int32 index);
ImagePtr channelDefPhoto(int32 index);
style::color peerColor(int index);
ImagePtr userDefPhoto(int index);
ImagePtr chatDefPhoto(int index);
ImagePtr channelDefPhoto(int index);
static const PhotoId UnknownPeerPhotoId = 0xFFFFFFFFFFFFFFFFULL;
@ -276,10 +279,15 @@ public:
typedef QSet<QChar> NameFirstChars;
NameFirstChars chars;
bool loaded;
enum LoadedStatus {
NotLoaded = 0x00,
MinimalLoaded = 0x01,
FullLoaded = 0x02,
};
LoadedStatus loadedStatus;
MTPinputPeer input;
int32 colorIndex;
int colorIndex;
style::color color;
void setUserpic(ImagePtr userpic);
@ -297,7 +305,7 @@ public:
PhotoId photoId;
StorageImageLocation photoLoc;
int32 nameVersion;
int nameVersion;
NotifySettingsPtr notify;
@ -358,7 +366,7 @@ struct BotInfo {
}
bool inited;
bool readsAllHistory, cantJoinGroups;
int32 version;
int version;
QString description, inlinePlaceholder;
QList<BotCommand> commands;
Text text; // description
@ -382,7 +390,7 @@ public:
void setPhoto(const MTPUserProfilePhoto &photo);
void setName(const QString &first, const QString &last, const QString &phoneName, const QString &username);
void setPhone(const QString &newPhone);
void setBotInfoVersion(int32 version);
void setBotInfoVersion(int version);
void setBotInfo(const MTPBotInfo &info);
void setNameOrPhone(const QString &newNameOrPhone);
@ -407,13 +415,13 @@ public:
QString phone;
QString nameOrPhone;
Text phoneText;
int32 onlineTill = 0;
TimeId onlineTill = 0;
int32 contact = -1; // -1 - not contact, cant add (self, empty, deleted, foreign), 0 - not contact, can add (request), 1 - contact
UserBlockedStatus blocked = UserBlockUnknown;
typedef QList<PhotoData*> Photos;
Photos photos;
int32 photosCount = -1; // -1 not loaded, 0 all loaded
int photosCount = -1; // -1 not loaded, 0 all loaded
QString about;
@ -462,10 +470,10 @@ public:
ChannelData *migrateToPtr;
int32 count;
int32 date;
int32 version;
int32 creator;
int count;
TimeId date;
int version;
UserId creator;
MTPDchat::Flags flags;
bool isForbidden;
@ -499,7 +507,7 @@ public:
bool isMigrated() const {
return flags & MTPDchat::Flag::f_migrated_to;
}
typedef QMap<UserData*, int32> Participants;
typedef QMap<UserData*, int> Participants;
Participants participants;
typedef OrderedSet<UserData*> InvitedByMe;
InvitedByMe invitedByMe;
@ -753,29 +761,59 @@ private:
};
inline bool isUser(const PeerData *peer) {
return peer ? peer->isUser() : false;
}
inline UserData *PeerData::asUser() {
return isUser() ? static_cast<UserData*>(this) : 0;
return isUser() ? static_cast<UserData*>(this) : nullptr;
}
inline UserData *asUser(PeerData *peer) {
return peer ? peer->asUser() : nullptr;
}
inline const UserData *PeerData::asUser() const {
return isUser() ? static_cast<const UserData*>(this) : 0;
return isUser() ? static_cast<const UserData*>(this) : nullptr;
}
inline const UserData *asUser(const PeerData *peer) {
return peer ? peer->asUser() : nullptr;
}
inline bool isChat(const PeerData *peer) {
return peer ? peer->isChat() : false;
}
inline ChatData *PeerData::asChat() {
return isChat() ? static_cast<ChatData*>(this) : 0;
return isChat() ? static_cast<ChatData*>(this) : nullptr;
}
inline ChatData *asChat(PeerData *peer) {
return peer ? peer->asChat() : nullptr;
}
inline const ChatData *PeerData::asChat() const {
return isChat() ? static_cast<const ChatData*>(this) : 0;
return isChat() ? static_cast<const ChatData*>(this) : nullptr;
}
inline const ChatData *asChat(const PeerData *peer) {
return peer ? peer->asChat() : nullptr;
}
inline bool isChannel(const PeerData *peer) {
return peer ? peer->isChannel() : false;
}
inline ChannelData *PeerData::asChannel() {
return isChannel() ? static_cast<ChannelData*>(this) : 0;
return isChannel() ? static_cast<ChannelData*>(this) : nullptr;
}
inline ChannelData *asChannel(PeerData *peer) {
return peer ? peer->asChannel() : nullptr;
}
inline const ChannelData *PeerData::asChannel() const {
return isChannel() ? static_cast<const ChannelData*>(this) : 0;
return isChannel() ? static_cast<const ChannelData*>(this) : nullptr;
}
inline const ChannelData *asChannel(const PeerData *peer) {
return peer ? peer->asChannel() : nullptr;
}
inline bool isMegagroup(const PeerData *peer) {
return peer ? peer->isMegagroup() : false;
}
inline ChatData *PeerData::migrateFrom() const {
return (isMegagroup() && asChannel()->amIn()) ? asChannel()->mgInfo->migrateFromPtr : 0;
return (isMegagroup() && asChannel()->amIn()) ? asChannel()->mgInfo->migrateFromPtr : nullptr;
}
inline ChannelData *PeerData::migrateTo() const {
return (isChat() && asChat()->migrateToPtr && asChat()->migrateToPtr->amIn()) ? asChat()->migrateToPtr : 0;
return (isChat() && asChat()->migrateToPtr && asChat()->migrateToPtr->amIn()) ? asChat()->migrateToPtr : nullptr;
}
inline const Text &PeerData::dialogName() const {
return migrateTo() ? migrateTo()->dialogName() : ((isUser() && !asUser()->phoneText.isEmpty()) ? asUser()->phoneText : nameText);
@ -998,11 +1036,14 @@ public:
SongData *song() {
return (type == SongDocument) ? static_cast<SongData*>(_additional) : 0;
}
const SongData *song() const {
return (type == SongDocument) ? static_cast<const SongData*>(_additional) : 0;
}
VoiceData *voice() {
return (type == VoiceDocument) ? static_cast<VoiceData*>(_additional) : 0;
}
const VoiceData *voice() const {
return (type == VoiceDocument) ? static_cast<VoiceData*>(_additional) : 0;
return (type == VoiceDocument) ? static_cast<const VoiceData*>(_additional) : 0;
}
bool isAnimation() const {
return (type == AnimatedDocument) || !mime.compare(qstr("image/gif"), Qt::CaseInsensitive);

View file

@ -120,8 +120,8 @@ namespace {
}
}
int32 myunixtime() {
return (int32)time(NULL);
TimeId myunixtime() {
return (TimeId)time(NULL);
}
void unixtimeInit() {
@ -149,19 +149,19 @@ void unixtimeSet(int32 serverTime, bool force) {
_initMsgIdConstants();
}
int32 unixtime() {
int32 result = myunixtime();
TimeId unixtime() {
TimeId result = myunixtime();
QReadLocker locker(&unixtimeLock);
return result + unixtimeDelta;
}
int32 fromServerTime(const MTPint &serverTime) {
TimeId fromServerTime(const MTPint &serverTime) {
QReadLocker locker(&unixtimeLock);
return serverTime.v - unixtimeDelta;
}
MTPint toServerTime(const int32 &clientTime) {
MTPint toServerTime(const TimeId &clientTime) {
QReadLocker locker(&unixtimeLock);
return MTP_int(clientTime + unixtimeDelta);
}
@ -1034,35 +1034,32 @@ MimeType mimeTypeForData(const QByteArray &data) {
return MimeType(QMimeDatabase().mimeTypeForData(data));
}
class InterfacesMetadatasMap : public QMap<uint64, InterfacesMetadata*> {
public:
~InterfacesMetadatasMap() {
for (const_iterator i = cbegin(), e = cend(); i != e; ++i) {
delete i.value();
struct ComposerMetadatasMap {
QMap<uint64, ComposerMetadata*> data;
~ComposerMetadatasMap() {
for_const (const ComposerMetadata *p, data) {
delete p;
}
}
};
const InterfacesMetadata *GetInterfacesMetadata(uint64 mask) {
typedef QMap<uint64, InterfacesMetadata*> InterfacesMetadatasMap;
static InterfacesMetadatasMap InterfacesMetadatas;
static QMutex InterfacesMetadatasMutex;
const ComposerMetadata *GetComposerMetadata(uint64 mask) {
static ComposerMetadatasMap ComposerMetadatas;
static QMutex ComposerMetadatasMutex;
QMutexLocker lock(&InterfacesMetadatasMutex);
InterfacesMetadatasMap::const_iterator i = InterfacesMetadatas.constFind(mask);
if (i == InterfacesMetadatas.cend()) {
InterfacesMetadata *meta = new InterfacesMetadata(mask);
if (!meta) { // terminate if we can't allocate memory
throw "Can't allocate memory!";
}
QMutexLocker lock(&ComposerMetadatasMutex);
auto i = ComposerMetadatas.data.constFind(mask);
if (i == ComposerMetadatas.data.cend()) {
ComposerMetadata *meta = new ComposerMetadata(mask);
t_assert(meta != nullptr);
i = InterfacesMetadatas.insert(mask, meta);
i = ComposerMetadatas.data.insert(mask, meta);
}
return i.value();
}
const InterfacesMetadata *Interfaces::ZeroInterfacesMetadata = GetInterfacesMetadata(0);
const ComposerMetadata *Composer::ZeroComposerMetadata = GetComposerMetadata(0);
InterfaceWrapStruct InterfaceWraps[64];
ComponentWrapStruct ComponentWraps[64];
QAtomicInt InterfaceIndexLast(0);
QAtomicInt ComponentIndexLast;

View file

@ -104,6 +104,30 @@ using std::string;
using std::exception;
using std::swap;
// we copy some parts of C++11 std:: library, because on OS X 10.6+
// version we can use C++11, but we can't use its library :(
namespace std11 {
template <typename T>
struct remove_reference {
typedef T type;
};
template <typename T>
struct remove_reference<T&> {
typedef T type;
};
template <typename T>
struct remove_reference<T&&> {
typedef T type;
};
template <typename T>
inline typename remove_reference<T>::type &&move(T &&value) {
return static_cast<typename remove_reference<T>::type&&>(value);
}
} // namespace std11
#include "logs.h"
static volatile int *t_assert_nullptr = 0;
@ -140,12 +164,12 @@ private:
};
class MTPint;
int32 myunixtime();
typedef int32 TimeId;
TimeId myunixtime();
void unixtimeInit();
void unixtimeSet(int32 servertime, bool force = false);
int32 unixtime();
int32 fromServerTime(const MTPint &serverTime);
void unixtimeSet(TimeId servertime, bool force = false);
TimeId unixtime();
TimeId fromServerTime(const MTPint &serverTime);
uint64 msgid();
int32 reqid();
@ -541,24 +565,26 @@ inline void destroyImplementation(I *&ptr) {
deleteAndMark(ptr);
}
class Interfaces;
typedef void(*InterfaceConstruct)(void *location, Interfaces *interfaces);
typedef void(*InterfaceDestruct)(void *location);
typedef void(*InterfaceMove)(void *location, void *waslocation);
class Composer;
typedef void(*ComponentConstruct)(void *location, Composer *composer);
typedef void(*ComponentDestruct)(void *location);
typedef void(*ComponentMove)(void *location, void *waslocation);
struct InterfaceWrapStruct {
InterfaceWrapStruct() : Size(0), Construct(0), Destruct(0) {
struct ComponentWrapStruct {
// don't init any fields, because it is only created in
// global scope, so it will be filled by zeros from the start
ComponentWrapStruct() {
}
InterfaceWrapStruct(int size, InterfaceConstruct construct, InterfaceDestruct destruct, InterfaceMove move)
ComponentWrapStruct(int size, ComponentConstruct construct, ComponentDestruct destruct, ComponentMove move)
: Size(size)
, Construct(construct)
, Destruct(destruct)
, Move(move) {
}
int Size;
InterfaceConstruct Construct;
InterfaceDestruct Destruct;
InterfaceMove Move;
ComponentConstruct Construct;
ComponentDestruct Destruct;
ComponentMove Move;
};
template <int Value, int Denominator>
@ -567,36 +593,43 @@ struct CeilDivideMinimumOne {
};
template <typename Type>
struct InterfaceWrapTemplate {
struct ComponentWrapTemplate {
static const int Size = CeilDivideMinimumOne<sizeof(Type), sizeof(uint64)>::Result * sizeof(uint64);
static void Construct(void *location, Interfaces *interfaces) {
new (location) Type(interfaces);
static void Construct(void *location, Composer *composer) {
new (location) Type(composer);
}
static void Destruct(void *location) {
((Type*)location)->~Type();
}
static void Move(void *location, void *waslocation) {
*(Type*)location = *(Type*)waslocation;
*(Type*)location = std11::move(*(Type*)waslocation);
}
};
extern InterfaceWrapStruct InterfaceWraps[64];
extern QAtomicInt InterfaceIndexLast;
extern ComponentWrapStruct ComponentWraps[64];
extern QAtomicInt ComponentIndexLast;
template <typename Type>
class BasicInterface {
class BaseComponent {
public:
BaseComponent() {
}
BaseComponent(const BaseComponent &other) = delete;
BaseComponent &operator=(const BaseComponent &other) = delete;
BaseComponent(BaseComponent &&other) = delete;
BaseComponent &operator=(BaseComponent &&other) = default;
static int Index() {
static QAtomicInt _index(0);
if (int index = _index.loadAcquire()) {
return index - 1;
}
while (true) {
int last = InterfaceIndexLast.loadAcquire();
if (InterfaceIndexLast.testAndSetOrdered(last, last + 1)) {
int last = ComponentIndexLast.loadAcquire();
if (ComponentIndexLast.testAndSetOrdered(last, last + 1)) {
t_assert(last < 64);
if (_index.testAndSetOrdered(0, last + 1)) {
InterfaceWraps[last] = InterfaceWrapStruct(InterfaceWrapTemplate<Type>::Size, InterfaceWrapTemplate<Type>::Construct, InterfaceWrapTemplate<Type>::Destruct, InterfaceWrapTemplate<Type>::Move);
ComponentWraps[last] = ComponentWrapStruct(ComponentWrapTemplate<Type>::Size, ComponentWrapTemplate<Type>::Construct, ComponentWrapTemplate<Type>::Destruct, ComponentWrapTemplate<Type>::Move);
}
break;
}
@ -609,22 +642,14 @@ public:
};
template <typename Type>
class BasicInterfaceWithPointer : public BasicInterface<Type> {
public:
BasicInterfaceWithPointer(Interfaces *interfaces) : interfaces(interfaces) {
}
Interfaces *interfaces = 0;
};
class InterfacesMetadata {
class ComposerMetadata {
public:
InterfacesMetadata(uint64 mask) : size(0), last(64), _mask(mask) {
ComposerMetadata(uint64 mask) : size(0), last(64), _mask(mask) {
for (int i = 0; i < 64; ++i) {
uint64 m = (1 << i);
if (_mask & m) {
int s = InterfaceWraps[i].Size;
int s = ComponentWraps[i].Size;
if (s) {
offsets[i] = size;
size += s;
@ -660,15 +685,15 @@ private:
};
const InterfacesMetadata *GetInterfacesMetadata(uint64 mask);
const ComposerMetadata *GetComposerMetadata(uint64 mask);
class Interfaces {
class Composer {
public:
Interfaces(uint64 mask = 0) : _data(zerodata()) {
Composer(uint64 mask = 0) : _data(zerodata()) {
if (mask) {
const InterfacesMetadata *meta = GetInterfacesMetadata(mask);
int32 size = sizeof(const InterfacesMetadata *) + meta->size;
const ComposerMetadata *meta = GetComposerMetadata(mask);
int size = sizeof(meta) + meta->size;
void *data = operator new(size);
if (!data) { // terminate if we can't allocate memory
throw "Can't allocate memory!";
@ -680,13 +705,13 @@ public:
int offset = meta->offsets[i];
if (offset >= 0) {
try {
InterfaceWraps[i].Construct(_dataptrunsafe(offset), this);
ComponentWraps[i].Construct(_dataptrunsafe(offset), this);
} catch (...) {
while (i > 0) {
--i;
offset = meta->offsets[--i];
if (offset >= 0) {
InterfaceWraps[i].Destruct(_dataptrunsafe(offset));
ComponentWraps[i].Destruct(_dataptrunsafe(offset));
}
}
throw;
@ -695,38 +720,41 @@ public:
}
}
}
void UpdateInterfaces(uint64 mask = 0) {
Composer(const Composer &other) = delete;
Composer &operator=(const Composer &other) = delete;
~Composer() {
if (_data != zerodata()) {
const ComposerMetadata *meta = _meta();
for (int i = 0; i < meta->last; ++i) {
int offset = meta->offsets[i];
if (offset >= 0) {
ComponentWraps[i].Destruct(_dataptrunsafe(offset));
}
}
operator delete(_data);
}
}
void UpdateComponents(uint64 mask = 0) {
if (!_meta()->equals(mask)) {
Interfaces tmp(mask);
Composer tmp(mask);
tmp.swap(*this);
if (_data != zerodata() && tmp._data != zerodata()) {
const InterfacesMetadata *meta = _meta(), *wasmeta = tmp._meta();
const ComposerMetadata *meta = _meta(), *wasmeta = tmp._meta();
for (int i = 0; i < meta->last; ++i) {
int offset = meta->offsets[i], wasoffset = wasmeta->offsets[i];
if (offset >= 0 && wasoffset >= 0) {
InterfaceWraps[i].Move(_dataptrunsafe(offset), tmp._dataptrunsafe(wasoffset));
ComponentWraps[i].Move(_dataptrunsafe(offset), tmp._dataptrunsafe(wasoffset));
}
}
}
}
}
void AddInterfaces(uint64 mask = 0) {
UpdateInterfaces(_meta()->maskadd(mask));
void AddComponents(uint64 mask = 0) {
UpdateComponents(_meta()->maskadd(mask));
}
void RemoveInterfaces(uint64 mask = 0) {
UpdateInterfaces(_meta()->maskremove(mask));
}
~Interfaces() {
if (_data != zerodata()) {
const InterfacesMetadata *meta = _meta();
for (int i = 0; i < meta->last; ++i) {
int offset = meta->offsets[i];
if (offset >= 0) {
InterfaceWraps[i].Destruct(_dataptrunsafe(offset));
}
}
operator delete(_data);
}
void RemoveComponents(uint64 mask = 0) {
UpdateComponents(_meta()->maskremove(mask));
}
template <typename Type>
@ -738,31 +766,28 @@ public:
return static_cast<const Type*>(_dataptr(_meta()->offsets[Type::Index()]));
}
template <typename Type>
bool Is() const {
bool Has() const {
return (_meta()->offsets[Type::Index()] >= 0);
}
private:
static const InterfacesMetadata *ZeroInterfacesMetadata;
static const ComposerMetadata *ZeroComposerMetadata;
static void *zerodata() {
return &ZeroInterfacesMetadata;
return &ZeroComposerMetadata;
}
void *_dataptrunsafe(int skip) const {
return (char*)_data + sizeof(const InterfacesMetadata*) + skip;
return (char*)_data + sizeof(_meta()) + skip;
}
void *_dataptr(int skip) const {
return (skip >= 0) ? _dataptrunsafe(skip) : 0;
}
const InterfacesMetadata *&_meta() const {
return *static_cast<const InterfacesMetadata**>(_data);
const ComposerMetadata *&_meta() const {
return *static_cast<const ComposerMetadata**>(_data);
}
void *_data;
Interfaces(const Interfaces &other);
Interfaces &operator=(const Interfaces &other);
void swap(Interfaces &other) {
void swap(Composer &other) {
std::swap(_data, other._data);
}

View file

@ -1410,7 +1410,7 @@ void Window::notifySchedule(History *history, HistoryItem *item) {
haveSetting = false;
}
int delay = item->Is<HistoryMessageForwarded>() ? 500 : 100, t = unixtime();
int delay = item->Has<HistoryMessageForwarded>() ? 500 : 100, t = unixtime();
uint64 ms = getms(true);
bool isOnline = main->lastWasOnline(), otherNotOld = ((cOtherOnline() * uint64(1000)) + Global::OnlineCloudTimeout() > t * uint64(1000));
bool otherLaterThanMe = (cOtherOnline() * uint64(1000) + (ms - main->lastSetOnline()) > t * uint64(1000));
@ -1629,7 +1629,7 @@ void Window::notifyShowNext(NotifyWindow *remove) {
notifyWaitTimer.start(next - ms);
break;
} else {
HistoryItem *fwd = notifyItem->Is<HistoryMessageForwarded>() ? notifyItem : 0; // forwarded notify grouping
HistoryItem *fwd = notifyItem->Has<HistoryMessageForwarded>() ? notifyItem : nullptr; // forwarded notify grouping
int32 fwdCount = 1;
uint64 ms = getms(true);
@ -1657,7 +1657,7 @@ void Window::notifyShowNext(NotifyWindow *remove) {
} while (history->hasNotification());
if (nextNotify) {
if (fwd) {
HistoryItem *nextFwd = nextNotify->Is<HistoryMessageForwarded>() ? nextNotify : 0;
HistoryItem *nextFwd = nextNotify->Has<HistoryMessageForwarded>() ? nextNotify : nullptr;
if (nextFwd && fwd->author() == nextFwd->author() && qAbs(int64(nextFwd->date.toTime_t()) - int64(fwd->date.toTime_t())) < 2) {
fwd = nextFwd;
++fwdCount;

View file

@ -34,8 +34,8 @@ IDI_ICON1 ICON "SourceFiles\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,9,34,3
PRODUCTVERSION 0,9,34,3
FILEVERSION 0,9,34,4
PRODUCTVERSION 0,9,34,4
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -51,10 +51,10 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileVersion", "0.9.34.3"
VALUE "FileVersion", "0.9.34.4"
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.9.34.3"
VALUE "ProductVersion", "0.9.34.4"
END
END
BLOCK "VarFileInfo"

View file

@ -3,4 +3,4 @@ AppVersionStrMajor 0.9
AppVersionStrSmall 0.9.34
AppVersionStr 0.9.34
DevChannel 0
BetaVersion 9034003
BetaVersion 9034004