mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
serverside links parsing used
This commit is contained in:
parent
8dff205949
commit
4afa1aace0
8 changed files with 345 additions and 151 deletions
|
@ -79,6 +79,9 @@ namespace {
|
|||
typedef QMap<uint64, MsgId> RandomData;
|
||||
RandomData randomData;
|
||||
|
||||
typedef QMap<uint64, QString> SentTextData;
|
||||
SentTextData sentTextData;
|
||||
|
||||
HistoryItem *hoveredItem = 0, *pressedItem = 0, *hoveredLinkItem = 0, *pressedLinkItem = 0, *contextItem = 0, *mousedItem = 0;
|
||||
|
||||
QPixmap *sprite = 0, *emojis = 0, *emojisLarge = 0;
|
||||
|
@ -1681,6 +1684,7 @@ namespace App {
|
|||
void historyClearItems() {
|
||||
historyClearMsgs();
|
||||
randomData.clear();
|
||||
sentTextData.clear();
|
||||
mutedPeers.clear();
|
||||
updatedPeers.clear();
|
||||
cSetSavedPeers(SavedPeers());
|
||||
|
@ -1756,6 +1760,18 @@ namespace App {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void historyRegSentText(uint64 randomId, const QString &text) {
|
||||
sentTextData.insert(randomId, text);
|
||||
}
|
||||
|
||||
void historyUnregSentText(uint64 randomId) {
|
||||
sentTextData.remove(randomId);
|
||||
}
|
||||
|
||||
QString histSentTextByItem(uint64 randomId) {
|
||||
return sentTextData.value(randomId);
|
||||
}
|
||||
|
||||
void prepareCorners(RoundCorners index, int32 radius, const style::color &color, const style::color *shadow = 0, QImage *cors = 0) {
|
||||
int32 r = radius * cIntRetinaFactor(), s = st::msgShadow * cIntRetinaFactor();
|
||||
QImage rect(r * 3, r * 3 + (shadow ? s : 0), QImage::Format_ARGB32_Premultiplied), localCors[4];
|
||||
|
|
|
@ -188,6 +188,9 @@ namespace App {
|
|||
void historyRegRandom(uint64 randomId, MsgId itemId);
|
||||
void historyUnregRandom(uint64 randomId);
|
||||
MsgId histItemByRandom(uint64 randomId);
|
||||
void historyRegSentText(uint64 itemId, const QString &text);
|
||||
void historyUnregSentText(uint64 itemId);
|
||||
QString histSentTextByItem(uint64 itemId);
|
||||
|
||||
void hoveredItem(HistoryItem *item);
|
||||
HistoryItem *hoveredItem();
|
||||
|
|
|
@ -146,8 +146,8 @@ inline bool emojiEdge(const QChar *ch) {
|
|||
|
||||
inline QString replaceEmojis(const QString &text) {
|
||||
QString result;
|
||||
LinkRanges lnkRanges = textParseLinks(text, TextParseLinks | TextParseMentions | TextParseHashtags);
|
||||
int32 currentLink = 0, lnkCount = lnkRanges.size();
|
||||
LinksInText links = textParseLinks(text, TextParseLinks | TextParseMentions | TextParseHashtags);
|
||||
int32 currentLink = 0, lnkCount = links.size();
|
||||
const QChar *emojiStart = text.unicode(), *emojiEnd = emojiStart, *e = text.cend();
|
||||
bool canFindEmoji = true, consumePrevious = false;
|
||||
for (const QChar *ch = emojiEnd; ch != e;) {
|
||||
|
@ -157,14 +157,14 @@ inline QString replaceEmojis(const QString &text) {
|
|||
emojiFind(ch, e, newEmojiEnd, emojiCode);
|
||||
}
|
||||
|
||||
while (currentLink < lnkCount && ch >= lnkRanges[currentLink].from + lnkRanges[currentLink].len) {
|
||||
while (currentLink < lnkCount && ch >= emojiStart + links[currentLink].offset + links[currentLink].length) {
|
||||
++currentLink;
|
||||
}
|
||||
EmojiPtr emoji = emojiCode ? emojiGet(emojiCode) : 0;
|
||||
if (emoji && emoji != TwoSymbolEmoji &&
|
||||
(ch == emojiStart || !ch->isLetterOrNumber() || !(ch - 1)->isLetterOrNumber()) &&
|
||||
(newEmojiEnd == e || !newEmojiEnd->isLetterOrNumber() || newEmojiEnd == emojiStart || !(newEmojiEnd - 1)->isLetterOrNumber()) &&
|
||||
(currentLink >= lnkCount || (ch < lnkRanges[currentLink].from && newEmojiEnd <= lnkRanges[currentLink].from) || (ch >= lnkRanges[currentLink].from + lnkRanges[currentLink].len && newEmojiEnd > lnkRanges[currentLink].from + lnkRanges[currentLink].len))
|
||||
(currentLink >= lnkCount || (ch < emojiStart + links[currentLink].offset && newEmojiEnd <= emojiStart + links[currentLink].offset) || (ch >= emojiStart + links[currentLink].offset + links[currentLink].length && newEmojiEnd > emojiStart + links[currentLink].offset + links[currentLink].length))
|
||||
) {
|
||||
// if (newEmojiEnd < e && newEmojiEnd->unicode() == ' ') ++newEmojiEnd;
|
||||
if (result.isEmpty()) result.reserve(text.size());
|
||||
|
|
|
@ -328,13 +328,13 @@ public:
|
|||
}
|
||||
|
||||
bool checkWaitedLink() {
|
||||
if (waitingLink == linksEnd || ptr < waitingLink->from || links.size() >= 0x7FFF) {
|
||||
if (waitingLink == linksEnd || ptr < start + waitingLink->offset || links.size() >= 0x7FFF) {
|
||||
return true;
|
||||
}
|
||||
|
||||
createBlock();
|
||||
|
||||
QString lnkUrl = QString(waitingLink->from, waitingLink->len), lnkText;
|
||||
QString lnkUrl = QString(start + waitingLink->offset, waitingLink->length), lnkText;
|
||||
int32 fullDisplayed;
|
||||
getLinkData(lnkUrl, lnkText, fullDisplayed);
|
||||
|
||||
|
@ -342,7 +342,7 @@ public:
|
|||
lnkIndex = 0x8000 + links.size();
|
||||
|
||||
_t->_text += lnkText;
|
||||
ptr = waitingLink->from + waitingLink->len;
|
||||
ptr = start + waitingLink->offset + waitingLink->length;
|
||||
|
||||
createBlock();
|
||||
++waitingLink;
|
||||
|
@ -519,8 +519,31 @@ public:
|
|||
emoji = e;
|
||||
}
|
||||
|
||||
TextParser(Text *t, const QString &text, const TextParseOptions &options) : _t(t), src(text),
|
||||
rich(options.flags & TextParseRichText), multiline(options.flags & TextParseMultiline), maxLnkIndex(0), flags(0), lnkIndex(0), stopAfterWidth(QFIXED_MAX) {
|
||||
TextParser(Text *t, const QString &text, const TextParseOptions &options) : _t(t),
|
||||
src(text),
|
||||
rich(options.flags & TextParseRichText),
|
||||
multiline(options.flags & TextParseMultiline),
|
||||
maxLnkIndex(0),
|
||||
flags(0),
|
||||
lnkIndex(0),
|
||||
stopAfterWidth(QFIXED_MAX) {
|
||||
if (options.flags & TextParseLinks) {
|
||||
lnkRanges = textParseLinks(src, options.flags, rich);
|
||||
}
|
||||
parse(options);
|
||||
}
|
||||
TextParser(Text *t, const QString &text, const LinksInText &links, const TextParseOptions &options) : _t(t),
|
||||
src(text),
|
||||
rich(options.flags & TextParseRichText),
|
||||
multiline(options.flags & TextParseMultiline),
|
||||
maxLnkIndex(0),
|
||||
flags(0),
|
||||
lnkIndex(0),
|
||||
stopAfterWidth(QFIXED_MAX) {
|
||||
lnkRanges = links;
|
||||
parse(options);
|
||||
}
|
||||
void parse(const TextParseOptions &options) {
|
||||
int flags = options.flags;
|
||||
if (options.maxw > 0 && options.maxh > 0) {
|
||||
stopAfterWidth = ((options.maxh / _t->_font->height) + 1) * options.maxw;
|
||||
|
@ -529,10 +552,6 @@ public:
|
|||
start = src.constData();
|
||||
end = start + src.size();
|
||||
|
||||
if (options.flags & TextParseLinks) {
|
||||
lnkRanges = textParseLinks(src, options.flags, rich);
|
||||
}
|
||||
|
||||
while (start != end && chIsTrimmed(*start, rich)) {
|
||||
++start;
|
||||
}
|
||||
|
@ -552,8 +571,8 @@ public:
|
|||
ch = chInt = 0;
|
||||
lastSkipped = false;
|
||||
lastSpace = true;
|
||||
waitingLink = lnkRanges.isEmpty() ? 0 : lnkRanges.constData();
|
||||
linksEnd = lnkRanges.isEmpty() ? 0 : waitingLink + lnkRanges.size();
|
||||
waitingLink = lnkRanges.cbegin();
|
||||
linksEnd = lnkRanges.cend();
|
||||
for (ptr = start; ptr <= end; ++ptr) {
|
||||
if (!checkWaitedLink()) {
|
||||
break;
|
||||
|
@ -615,8 +634,8 @@ private:
|
|||
const QChar *start, *end, *ptr;
|
||||
bool rich, multiline;
|
||||
|
||||
LinkRanges lnkRanges;
|
||||
const LinkRange *waitingLink, *linksEnd;
|
||||
LinksInText lnkRanges;
|
||||
LinksInText::const_iterator waitingLink, linksEnd;
|
||||
|
||||
struct TextLinkData {
|
||||
TextLinkData(const QString &url = QString(), int32 fullDisplayed = 1) : url(url), fullDisplayed(fullDisplayed) {
|
||||
|
@ -2305,6 +2324,7 @@ void Text::setText(style::font font, const QString &text, const TextParseOptions
|
|||
void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
|
||||
NewlineBlock *lastNewline = 0;
|
||||
|
||||
_maxWidth = _minHeight = 0;
|
||||
int32 lineHeight = 0;
|
||||
int32 result = 0, lastNewlineStart = 0;
|
||||
QFixed _width = 0, last_rBearing = 0, last_rPadding = 0;
|
||||
|
@ -2369,8 +2389,14 @@ void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
|
|||
}
|
||||
}
|
||||
|
||||
void Text::setMarkedText(style::font font, const QString &text, const LinksInText &links) {
|
||||
|
||||
void Text::setMarkedText(style::font font, const QString &text, const LinksInText &links, const TextParseOptions &options) {
|
||||
if (!_textStyle) _initDefault();
|
||||
_font = font;
|
||||
clean();
|
||||
{
|
||||
TextParser parser(this, text, links, options);
|
||||
}
|
||||
recountNaturalSize(true, options.dir);
|
||||
}
|
||||
|
||||
void Text::setRichText(style::font font, const QString &text, TextParseOptions options, const TextCustomTagsMap &custom) {
|
||||
|
@ -2460,16 +2486,80 @@ bool Text::hasLinks() const {
|
|||
return !_links.isEmpty();
|
||||
}
|
||||
|
||||
void Text::setSkipBlock(int32 width) {
|
||||
|
||||
void Text::setSkipBlock(int32 width, int32 height) {
|
||||
if (!_blocks.isEmpty() && _blocks.back()->type() == TextBlockSkip) {
|
||||
SkipBlock *block = static_cast<SkipBlock*>(_blocks.back());
|
||||
if (block->width() == width && block->height() == height) return;
|
||||
_text.resize(block->from());
|
||||
_blocks.pop_back();
|
||||
}
|
||||
_text.push_back('_');
|
||||
_blocks.push_back(new SkipBlock(_font, _text, _text.size() - 1, width, height, 0));
|
||||
recountNaturalSize(false);
|
||||
}
|
||||
|
||||
void Text::removeSkipBlock() {
|
||||
|
||||
if (!_blocks.isEmpty() && _blocks.back()->type() == TextBlockSkip) {
|
||||
_text.resize(_blocks.back()->from());
|
||||
_blocks.pop_back();
|
||||
recountNaturalSize(false);
|
||||
}
|
||||
}
|
||||
|
||||
LinksInText Text::calcLinksInText() const {
|
||||
return LinksInText();
|
||||
LinksInText result;
|
||||
int32 lnkFrom = 0, lnkIndex = 0, offset = 0;
|
||||
for (TextBlocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); true; ++i) {
|
||||
int32 blockLnkIndex = (i == e) ? 0 : (*i)->lnkIndex();
|
||||
int32 blockFrom = (i == e) ? _text.size() : (*i)->from();
|
||||
if (blockLnkIndex != lnkIndex) {
|
||||
if (lnkIndex) { // write link
|
||||
const TextLinkPtr &lnk(_links.at(lnkIndex - 1));
|
||||
const QString &url(lnk ? lnk->text() : QString());
|
||||
|
||||
int32 rangeFrom = lnkFrom, rangeTo = blockFrom;
|
||||
if (rangeTo > rangeFrom) {
|
||||
QStringRef r = _text.midRef(rangeFrom, rangeTo - rangeFrom);
|
||||
if (url.isEmpty()) {
|
||||
offset += r.size();
|
||||
} else {
|
||||
QUrl u(url);
|
||||
if (r.size() <= 3 || _text.midRef(lnkFrom, r.size() - 3) == (u.isValid() ? u.toDisplayString() : url).midRef(0, r.size() - 3)) { // same link
|
||||
if (url.at(0) == '@') {
|
||||
result.push_back(LinkInText(LinkInTextMention, offset, url.size()));
|
||||
} else if (url.at(0) == '#') {
|
||||
result.push_back(LinkInText(LinkInTextHashtag, offset, url.size()));
|
||||
} else if (url.at(0) == '/') {
|
||||
result.push_back(LinkInText(LinkInTextBotCommand, offset, url.size()));
|
||||
} else if (url.indexOf('@') > 0 && url.indexOf('/') <= 0) {
|
||||
result.push_back(LinkInText(LinkInTextEmail, offset, url.size()));
|
||||
} else {
|
||||
result.push_back(LinkInText(LinkInTextUrl, offset, url.size()));
|
||||
}
|
||||
offset += url.size();
|
||||
} else {
|
||||
result.push_back(LinkInText(LinkInTextCustomUrl, offset, r.size(), url));
|
||||
offset += r.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lnkIndex = blockLnkIndex;
|
||||
lnkFrom = blockFrom;
|
||||
}
|
||||
if (i == e) break;
|
||||
|
||||
TextBlockType type = (*i)->type();
|
||||
if (type == TextBlockSkip) continue;
|
||||
|
||||
if (!blockLnkIndex) {
|
||||
int32 rangeFrom = (*i)->from(), rangeTo = uint16((*i)->from() + TextPainter::_blockLength(this, i, e));
|
||||
if (rangeTo > rangeFrom) {
|
||||
offset += rangeTo - rangeFrom;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int32 Text::countHeight(int32 w) const {
|
||||
|
@ -4058,16 +4148,16 @@ QString textSearchKey(const QString &text) {
|
|||
bool textSplit(QString &sendingText, QString &leftText, int32 limit) {
|
||||
if (leftText.isEmpty() || !limit) return false;
|
||||
|
||||
LinkRanges lnkRanges = textParseLinks(leftText, TextParseLinks | TextParseMentions | TextParseHashtags);
|
||||
int32 currentLink = 0, lnkCount = lnkRanges.size();
|
||||
LinksInText links = textParseLinks(leftText, TextParseLinks | TextParseMentions | TextParseHashtags);
|
||||
int32 currentLink = 0, lnkCount = links.size();
|
||||
|
||||
int32 s = 0, half = limit / 2, goodLevel = 0;
|
||||
for (const QChar *start = leftText.constData(), *ch = start, *end = leftText.constEnd(), *good = ch; ch != end; ++ch, ++s) {
|
||||
while (currentLink < lnkCount && ch >= lnkRanges[currentLink].from + lnkRanges[currentLink].len) {
|
||||
while (currentLink < lnkCount && ch >= start + links[currentLink].offset + links[currentLink].length) {
|
||||
++currentLink;
|
||||
}
|
||||
|
||||
bool inLink = (currentLink < lnkCount) && (ch > lnkRanges[currentLink].from) && (ch < lnkRanges[currentLink].from + lnkRanges[currentLink].len);
|
||||
bool inLink = (currentLink < lnkCount) && (ch > start + links[currentLink].offset) && (ch < start + links[currentLink].offset + links[currentLink].length);
|
||||
if (s > half) {
|
||||
if (inLink) {
|
||||
if (!goodLevel) good = ch;
|
||||
|
@ -4125,8 +4215,8 @@ bool textSplit(QString &sendingText, QString &leftText, int32 limit) {
|
|||
return true;
|
||||
}
|
||||
|
||||
LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some code is duplicated in flattextarea.cpp!
|
||||
LinkRanges lnkRanges;
|
||||
LinksInText textParseLinks(const QString &text, int32 flags, bool rich) { // some code is duplicated in flattextarea.cpp!
|
||||
LinksInText result;
|
||||
|
||||
bool withHashtags = (flags & TextParseHashtags);
|
||||
bool withMentions = (flags & TextParseMentions);
|
||||
|
@ -4149,7 +4239,8 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some
|
|||
QRegularExpressionMatch mMention = withMentions ? _reMention.match(text, qMax(mentionSkip, matchOffset)) : QRegularExpressionMatch();
|
||||
QRegularExpressionMatch mBotCommand = withBotCommands ? _reBotCommand.match(text, matchOffset) : QRegularExpressionMatch();
|
||||
|
||||
LinkRange link;
|
||||
LinkInTextType lnkType = LinkInTextUrl;
|
||||
int32 lnkOffset = 0, lnkLength = 0;
|
||||
int32 domainOffset = mDomain.hasMatch() ? mDomain.capturedStart() : INT_MAX,
|
||||
domainEnd = mDomain.hasMatch() ? mDomain.capturedEnd() : INT_MAX,
|
||||
explicitDomainOffset = mExplicitDomain.hasMatch() ? mExplicitDomain.capturedStart() : INT_MAX,
|
||||
|
@ -4214,9 +4305,9 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
link.from = start + mentionOffset;
|
||||
link.len = start + mentionEnd - link.from;
|
||||
lnkType = LinkInTextMention;
|
||||
lnkOffset = mentionOffset;
|
||||
lnkLength = mentionEnd - mentionOffset;
|
||||
} else if (hashtagOffset < domainOffset && hashtagOffset < botCommandOffset) {
|
||||
if (hashtagOffset > nextCmd) {
|
||||
const QChar *after = textSkipCommand(start + nextCmd, start + len);
|
||||
|
@ -4226,8 +4317,9 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some
|
|||
}
|
||||
}
|
||||
|
||||
link.from = start + hashtagOffset;
|
||||
link.len = start + hashtagEnd - link.from;
|
||||
lnkType = LinkInTextHashtag;
|
||||
lnkOffset = hashtagOffset;
|
||||
lnkLength = hashtagEnd - hashtagOffset;
|
||||
} else if (botCommandOffset < domainOffset) {
|
||||
if (botCommandOffset > nextCmd) {
|
||||
const QChar *after = textSkipCommand(start + nextCmd, start + len);
|
||||
|
@ -4237,8 +4329,9 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some
|
|||
}
|
||||
}
|
||||
|
||||
link.from = start + botCommandOffset;
|
||||
link.len = start + botCommandEnd - link.from;
|
||||
lnkType = LinkInTextBotCommand;
|
||||
lnkOffset = botCommandOffset;
|
||||
lnkLength = botCommandEnd - botCommandOffset;
|
||||
} else {
|
||||
if (domainOffset > nextCmd) {
|
||||
const QChar *after = textSkipCommand(start + nextCmd, start + len);
|
||||
|
@ -4262,16 +4355,17 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some
|
|||
if (mailOffset < offset) {
|
||||
mailOffset = offset;
|
||||
}
|
||||
link.from = start + mailOffset;
|
||||
link.len = domainEnd - mailOffset;
|
||||
lnkType = LinkInTextEmail;
|
||||
lnkOffset = mailOffset;
|
||||
lnkLength = domainEnd - mailOffset;
|
||||
}
|
||||
}
|
||||
if (!link.from || !link.len) {
|
||||
if (lnkType == LinkInTextUrl && !lnkLength) {
|
||||
if (!isProtocolValid || !isTopDomainValid) {
|
||||
matchOffset = domainEnd;
|
||||
continue;
|
||||
}
|
||||
link.from = start + domainOffset;
|
||||
lnkOffset = domainOffset;
|
||||
|
||||
QStack<const QChar*> parenth;
|
||||
const QChar *domainEnd = start + mDomain.capturedEnd(), *p = domainEnd;
|
||||
|
@ -4306,15 +4400,15 @@ LinkRanges textParseLinks(const QString &text, int32 flags, bool rich) { // some
|
|||
continue;
|
||||
}
|
||||
}
|
||||
link.len = p - link.from;
|
||||
lnkLength = (p - start) - lnkOffset;
|
||||
}
|
||||
}
|
||||
lnkRanges.push_back(link);
|
||||
result.push_back(LinkInText(lnkType, lnkOffset, lnkLength));
|
||||
|
||||
offset = matchOffset = (link.from - start) + link.len;
|
||||
offset = matchOffset = lnkOffset + lnkLength;
|
||||
}
|
||||
|
||||
return lnkRanges;
|
||||
return result;
|
||||
}
|
||||
|
||||
void emojiDraw(QPainter &p, EmojiPtr e, int x, int y) {
|
||||
|
|
|
@ -39,14 +39,57 @@ enum {
|
|||
TextInstagramHashtags = 0x200,
|
||||
};
|
||||
|
||||
struct LinkRange {
|
||||
LinkRange() : from(0), len(0) {
|
||||
}
|
||||
const QChar *from;
|
||||
int32 len;
|
||||
enum LinkInTextType {
|
||||
LinkInTextUrl,
|
||||
LinkInTextCustomUrl,
|
||||
LinkInTextEmail,
|
||||
LinkInTextHashtag,
|
||||
LinkInTextMention,
|
||||
LinkInTextBotCommand,
|
||||
};
|
||||
typedef QVector<LinkRange> LinkRanges;
|
||||
LinkRanges textParseLinks(const QString &text, int32 flags, bool rich = false);
|
||||
struct LinkInText {
|
||||
LinkInText(LinkInTextType type, int32 offset, int32 length, const QString &text = QString()) : type(type), offset(offset), length(length), text(text) {
|
||||
}
|
||||
LinkInTextType type;
|
||||
int32 offset, length;
|
||||
QString text;
|
||||
};
|
||||
typedef QList<LinkInText> LinksInText;
|
||||
inline LinksInText linksFromMTP(const QVector<MTPMessageEntity> &entities) {
|
||||
LinksInText result;
|
||||
if (!entities.isEmpty()) {
|
||||
result.reserve(entities.size());
|
||||
for (int32 i = 0, l = entities.size(); i != l; ++i) {
|
||||
const MTPMessageEntity &e(entities.at(i));
|
||||
switch (e.type()) {
|
||||
case mtpc_messageEntityUrl: { const MTPDmessageEntityUrl &d(e.c_messageEntityUrl()); result.push_back(LinkInText(LinkInTextUrl, d.voffset.v, d.vlength.v)); } break;
|
||||
case mtpc_messageEntityTextUrl: { const MTPDmessageEntityTextUrl &d(e.c_messageEntityTextUrl()); result.push_back(LinkInText(LinkInTextCustomUrl, d.voffset.v, d.vlength.v, textClean(qs(d.vurl)))); } break;
|
||||
case mtpc_messageEntityEmail: { const MTPDmessageEntityEmail &d(e.c_messageEntityEmail()); result.push_back(LinkInText(LinkInTextEmail, d.voffset.v, d.vlength.v)); } break;
|
||||
case mtpc_messageEntityHashtag: { const MTPDmessageEntityHashtag &d(e.c_messageEntityHashtag()); result.push_back(LinkInText(LinkInTextHashtag, d.voffset.v, d.vlength.v)); } break;
|
||||
case mtpc_messageEntityMention: { const MTPDmessageEntityMention &d(e.c_messageEntityMention()); result.push_back(LinkInText(LinkInTextMention, d.voffset.v, d.vlength.v)); } break;
|
||||
case mtpc_messageEntityBotCommand: { const MTPDmessageEntityBotCommand &d(e.c_messageEntityBotCommand()); result.push_back(LinkInText(LinkInTextBotCommand, d.voffset.v, d.vlength.v)); } break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
inline MTPVector<MTPMessageEntity> linksToMTP(const LinksInText &links) {
|
||||
MTPVector<MTPMessageEntity> result(MTP_vector<MTPMessageEntity>(0));
|
||||
QVector<MTPMessageEntity> &v(result._vector().v);
|
||||
for (int32 i = 0, s = links.size(); i != s; ++i) {
|
||||
const LinkInText &l(links.at(i));
|
||||
switch (l.type) {
|
||||
case LinkInTextUrl: v.push_back(MTP_messageEntityUrl(MTP_int(l.offset), MTP_int(l.length))); break;
|
||||
case LinkInTextCustomUrl: v.push_back(MTP_messageEntityTextUrl(MTP_int(l.offset), MTP_int(l.length), MTP_string(l.text))); break;
|
||||
case LinkInTextEmail: v.push_back(MTP_messageEntityEmail(MTP_int(l.offset), MTP_int(l.length))); break;
|
||||
case LinkInTextHashtag: v.push_back(MTP_messageEntityHashtag(MTP_int(l.offset), MTP_int(l.length))); break;
|
||||
case LinkInTextMention: v.push_back(MTP_messageEntityMention(MTP_int(l.offset), MTP_int(l.length))); break;
|
||||
case LinkInTextBotCommand: v.push_back(MTP_messageEntityBotCommand(MTP_int(l.offset), MTP_int(l.length))); break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
LinksInText textParseLinks(const QString &text, int32 flags, bool rich = false);
|
||||
|
||||
#include "gui/emoji_config.h"
|
||||
|
||||
|
@ -464,23 +507,6 @@ enum TextSelectType {
|
|||
typedef QPair<QString, QString> TextCustomTag; // open str and close str
|
||||
typedef QMap<QChar, TextCustomTag> TextCustomTagsMap;
|
||||
|
||||
enum LinkInTextType {
|
||||
LinkInTextUrl,
|
||||
LinkInTextCustomUrl,
|
||||
LinkInTextEmail,
|
||||
LinkInTextHashtag,
|
||||
LinkInTextMention,
|
||||
LinkInTextBotCommand,
|
||||
};
|
||||
struct LinkInText {
|
||||
LinkInText(LinkInTextType type, int32 offset, int32 length, const QString &text = QString()) : type(type), offset(offset), length(length), text(text) {
|
||||
}
|
||||
LinkInTextType type;
|
||||
int32 offset, length;
|
||||
QString text;
|
||||
};
|
||||
typedef QList<LinkInText> LinksInText;
|
||||
|
||||
class Text {
|
||||
public:
|
||||
|
||||
|
@ -492,7 +518,7 @@ public:
|
|||
int32 countHeight(int32 width) const;
|
||||
void setText(style::font font, const QString &text, const TextParseOptions &options = _defaultOptions);
|
||||
void setRichText(style::font font, const QString &text, TextParseOptions options = _defaultOptions, const TextCustomTagsMap &custom = TextCustomTagsMap());
|
||||
void setMarkedText(style::font font, const QString &text, const LinksInText &links);
|
||||
void setMarkedText(style::font font, const QString &text, const LinksInText &links, const TextParseOptions &options = _defaultOptions);
|
||||
|
||||
void setLink(uint16 lnkIndex, const TextLinkPtr &lnk);
|
||||
bool hasLinks() const;
|
||||
|
@ -500,7 +526,7 @@ public:
|
|||
bool hasSkipBlock() const {
|
||||
return _blocks.isEmpty() ? false : _blocks.back()->type() == TextBlockSkip;
|
||||
}
|
||||
void setSkipBlock(int32 width);
|
||||
void setSkipBlock(int32 width, int32 height);
|
||||
void removeSkipBlock();
|
||||
LinksInText calcLinksInText() const;
|
||||
|
||||
|
|
|
@ -110,15 +110,17 @@ namespace {
|
|||
return item ? item->toHistoryForwarded() : 0;
|
||||
}
|
||||
inline const TextParseOptions &itemTextParseOptions(HistoryItem *item) {
|
||||
History *h = item->history();
|
||||
UserData *f = item->from();
|
||||
if ((!h->peer->chat && h->peer->asUser()->botInfo) || (!f->chat && f->asUser()->botInfo) || (h->peer->chat && h->peer->asChat()->botStatus >= 0)) {
|
||||
return _historyBotOptions;
|
||||
}
|
||||
return _historyTextOptions;
|
||||
return itemTextParseOptions(item->history(), item->from());
|
||||
}
|
||||
}
|
||||
|
||||
const TextParseOptions &itemTextParseOptions(History *h, UserData *f) {
|
||||
if ((!h->peer->chat && h->peer->asUser()->botInfo) || (!f->chat && f->asUser()->botInfo) || (h->peer->chat && h->peer->asChat()->botStatus >= 0)) {
|
||||
return _historyBotOptions;
|
||||
}
|
||||
return _historyTextOptions;
|
||||
}
|
||||
|
||||
void historyInit() {
|
||||
_initTextOptions();
|
||||
}
|
||||
|
@ -1035,7 +1037,7 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
|
|||
|
||||
int32 addToH = 0, skip = 0;
|
||||
if (!isEmpty()) {
|
||||
addToH = -front()->height;
|
||||
if (width) addToH = -front()->height;
|
||||
pop_front(); // remove date block
|
||||
}
|
||||
HistoryItem *till = isEmpty() ? 0 : front()->front(), *prev = 0;
|
||||
|
@ -1049,12 +1051,16 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
|
|||
if (prev && prev->date.date() != adding->date.date()) {
|
||||
HistoryItem *dayItem = createDayServiceMsg(this, block, adding->date);
|
||||
block->push_back(dayItem);
|
||||
dayItem->y = block->height;
|
||||
block->height += dayItem->resize(width);
|
||||
if (width) {
|
||||
dayItem->y = block->height;
|
||||
block->height += dayItem->resize(width);
|
||||
}
|
||||
}
|
||||
block->push_back(adding);
|
||||
adding->y = block->height;
|
||||
block->height += adding->resize(width);
|
||||
if (width) {
|
||||
adding->y = block->height;
|
||||
block->height += adding->resize(width);
|
||||
}
|
||||
setMsgCount(msgCount + 1);
|
||||
prev = adding;
|
||||
}
|
||||
|
@ -1063,8 +1069,10 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
|
|||
if (till && prev && prev->date.date() != till->date.date()) {
|
||||
HistoryItem *dayItem = createDayServiceMsg(this, block, till->date);
|
||||
block->push_back(dayItem);
|
||||
dayItem->y = block->height;
|
||||
block->height += dayItem->resize(width);
|
||||
if (width) {
|
||||
dayItem->y = block->height;
|
||||
block->height += dayItem->resize(width);
|
||||
}
|
||||
}
|
||||
if (block->size()) {
|
||||
if (loadedAtBottom() && wasMsgCount < unreadCount && msgCount >= unreadCount) {
|
||||
|
@ -1079,8 +1087,10 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
|
|||
}
|
||||
}
|
||||
push_front(block);
|
||||
addToH += block->height;
|
||||
++skip;
|
||||
if (width) {
|
||||
addToH += block->height;
|
||||
++skip;
|
||||
}
|
||||
|
||||
if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors
|
||||
int32 mask = 0;
|
||||
|
@ -1167,16 +1177,18 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
|
|||
HistoryBlock *dateBlock = new HistoryBlock(this);
|
||||
HistoryItem *dayItem = createDayServiceMsg(this, dateBlock, front()->front()->date);
|
||||
dateBlock->push_back(dayItem);
|
||||
int32 dh = dayItem->resize(width);
|
||||
dateBlock->height = dh;
|
||||
if (skip) {
|
||||
front()->y += dh;
|
||||
if (width) {
|
||||
int32 dh = dayItem->resize(width);
|
||||
dateBlock->height = dh;
|
||||
if (skip) {
|
||||
front()->y += dh;
|
||||
}
|
||||
addToH += dh;
|
||||
++skip;
|
||||
}
|
||||
push_front(dateBlock); // date block
|
||||
addToH += dh;
|
||||
++skip;
|
||||
}
|
||||
if (addToH) {
|
||||
if (width && addToH) {
|
||||
for (iterator i = begin(), e = end(); i != e; ++i) {
|
||||
if (skip) {
|
||||
--skip;
|
||||
|
@ -5026,7 +5038,7 @@ HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, const MTPD
|
|||
QString text(textClean(qs(msg.vmessage)));
|
||||
initTime();
|
||||
initMedia(msg.vmedia, text);
|
||||
initDimensions(text, msg.has_entities() ? linksFromMTP(msg.ventities.c_vector().v) : LinksInText());
|
||||
setText(text, msg.has_entities() ? linksFromMTP(msg.ventities.c_vector().v) : LinksInText());
|
||||
}
|
||||
|
||||
HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const LinksInText &links, const MTPMessageMedia &media) :
|
||||
|
@ -5039,7 +5051,7 @@ HistoryItem(history, block, msgId, flags, date, from)
|
|||
QString text(msg);
|
||||
initTime();
|
||||
initMedia(media, text);
|
||||
initDimensions(text, links);
|
||||
setText(text, links);
|
||||
}
|
||||
|
||||
HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, const QString &msg, const LinksInText &links, HistoryMedia *fromMedia) :
|
||||
|
@ -5054,7 +5066,7 @@ HistoryItem(history, block, msgId, flags, date, from)
|
|||
_media = fromMedia->clone();
|
||||
_media->regItem(this);
|
||||
}
|
||||
initDimensions(msg, links);
|
||||
setText(msg, links);
|
||||
}
|
||||
|
||||
HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime date, int32 from, DocumentData *doc) :
|
||||
|
@ -5066,7 +5078,7 @@ HistoryItem(history, block, msgId, flags, date, from)
|
|||
{
|
||||
initTime();
|
||||
initMediaFromDocument(doc);
|
||||
initDimensions(QString(), LinksInText());
|
||||
setText(QString(), LinksInText());
|
||||
}
|
||||
|
||||
void HistoryMessage::initTime() {
|
||||
|
@ -5154,22 +5166,6 @@ void HistoryMessage::initMediaFromDocument(DocumentData *doc) {
|
|||
_media->regItem(this);
|
||||
}
|
||||
|
||||
void HistoryMessage::initDimensions(const QString &text, const LinksInText &links) {
|
||||
if (!_media || !text.isEmpty()) { // !justMedia()
|
||||
if (_media && _media->isDisplayed()) {
|
||||
_text.setMarkedText(st::msgFont, text, links, itemTextParseOptions(this));
|
||||
} else {
|
||||
_text.setMarkedText(st::msgFont, text + textcmdSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()), links, itemTextParseOptions(this));
|
||||
}
|
||||
for (int32 i = 0, l = links.size(); i != l; ++i) {
|
||||
if (links.at(i).type == LinkInTextUrl || links.at(i).type == LinkInTextCustomUrl || links.at(i).type == LinkInTextEmail) {
|
||||
_flags |= MTPDmessage_flag_HAS_TEXT_LINKS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryMessage::initDimensions(const HistoryItem *parent) {
|
||||
if (justMedia()) {
|
||||
_media->initDimensions(this);
|
||||
|
@ -5182,19 +5178,13 @@ void HistoryMessage::initDimensions(const HistoryItem *parent) {
|
|||
if (_media) {
|
||||
_media->initDimensions(this);
|
||||
if (_media->isDisplayed() && _text.hasSkipBlock()) {
|
||||
QString was = HistoryMessage::selectedText(FullItemSel);
|
||||
if (!was.isEmpty()) {
|
||||
_text.setText(st::msgFont, was, itemTextParseOptions(this)); // without date skip
|
||||
_textWidth = 0;
|
||||
_textHeight = 0;
|
||||
}
|
||||
_text.removeSkipBlock();
|
||||
_textWidth = 0;
|
||||
_textHeight = 0;
|
||||
} else if (!_media->isDisplayed() && !_text.hasSkipBlock()) {
|
||||
QString was = HistoryMessage::selectedText(FullItemSel);
|
||||
if (!was.isEmpty()) {
|
||||
_text.setText(st::msgFont, was + textcmdSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()), itemTextParseOptions(this)); // without date skip
|
||||
_textWidth = 0;
|
||||
_textHeight = 0;
|
||||
}
|
||||
_text.setSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y());
|
||||
_textWidth = 0;
|
||||
_textHeight = 0;
|
||||
}
|
||||
if (_media->isDisplayed()) {
|
||||
int32 maxw = _media->maxWidth() + st::msgPadding.left() + st::msgPadding.right();
|
||||
|
@ -5226,6 +5216,10 @@ QString HistoryMessage::selectedText(uint32 selection) const {
|
|||
return _text.original(selectedFrom, selectedTo);
|
||||
}
|
||||
|
||||
LinksInText HistoryMessage::textLinks() const {
|
||||
return _text.calcLinksInText();
|
||||
}
|
||||
|
||||
QString HistoryMessage::inDialogsText() const {
|
||||
QString result = _media ? _media->inDialogsText() : QString();
|
||||
return result.isEmpty() ? _text.original(0, 0xFFFF, false) : result;
|
||||
|
@ -5237,6 +5231,7 @@ HistoryMedia *HistoryMessage::getMedia(bool inOverview) const {
|
|||
|
||||
void HistoryMessage::setMedia(const MTPmessageMedia &media) {
|
||||
if ((!_media || _media->isImageLink()) && media.type() == mtpc_messageMediaEmpty) return;
|
||||
|
||||
bool mediaWasDisplayed = false;
|
||||
if (_media) {
|
||||
mediaWasDisplayed = _media->isDisplayed();
|
||||
|
@ -5246,24 +5241,38 @@ void HistoryMessage::setMedia(const MTPmessageMedia &media) {
|
|||
QString t;
|
||||
initMedia(media, t);
|
||||
if (_media && _media->isDisplayed() && !mediaWasDisplayed) {
|
||||
QString was = HistoryMessage::selectedText(FullItemSel);
|
||||
if (!was.isEmpty()) {
|
||||
_text.setText(st::msgFont, was, itemTextParseOptions(this)); // without date skip
|
||||
_textWidth = 0;
|
||||
_textHeight = 0;
|
||||
}
|
||||
_text.removeSkipBlock();
|
||||
_textWidth = 0;
|
||||
_textHeight = 0;
|
||||
} else if (mediaWasDisplayed && (!_media || !_media->isDisplayed())) {
|
||||
QString was = HistoryMessage::selectedText(FullItemSel);
|
||||
if (!was.isEmpty()) {
|
||||
_text.setText(st::msgFont, was + textcmdSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()), itemTextParseOptions(this)); // without date skip
|
||||
_textWidth = 0;
|
||||
_textHeight = 0;
|
||||
}
|
||||
_text.setSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y());
|
||||
_textWidth = 0;
|
||||
_textHeight = 0;
|
||||
}
|
||||
initDimensions(0);
|
||||
if (App::main()) App::main()->itemResized(this);
|
||||
}
|
||||
|
||||
void HistoryMessage::setText(const QString &text, const LinksInText &links) {
|
||||
if (!_media || !text.isEmpty()) { // !justMedia()
|
||||
if (_media && _media->isDisplayed()) {
|
||||
_text.setMarkedText(st::msgFont, text, links, itemTextParseOptions(this));
|
||||
} else {
|
||||
_text.setMarkedText(st::msgFont, text + textcmdSkipBlock(timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y()), links, itemTextParseOptions(this));
|
||||
}
|
||||
if (id > 0) {
|
||||
for (int32 i = 0, l = links.size(); i != l; ++i) {
|
||||
if (links.at(i).type == LinkInTextUrl || links.at(i).type == LinkInTextCustomUrl || links.at(i).type == LinkInTextEmail) {
|
||||
_flags |= MTPDmessage_flag_HAS_TEXT_LINKS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_textWidth = 0;
|
||||
_textHeight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryMessage::draw(QPainter &p, uint32 selection) const {
|
||||
textstyleSet(&(out() ? st::outTextStyle : st::inTextStyle));
|
||||
|
||||
|
@ -5368,6 +5377,8 @@ void HistoryMessage::drawMessageText(QPainter &p, const QRect &trect, uint32 sel
|
|||
}
|
||||
|
||||
int32 HistoryMessage::resize(int32 width, bool dontRecountText, const HistoryItem *parent) {
|
||||
if (width < st::msgMinWidth) return _height;
|
||||
|
||||
width -= st::msgMargin.left() + st::msgMargin.right();
|
||||
if (justMedia()) {
|
||||
_height = _media->resize(width, dontRecountText, this);
|
||||
|
@ -5573,7 +5584,7 @@ HistoryMessage::~HistoryMessage() {
|
|||
}
|
||||
}
|
||||
|
||||
HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const MTPDmessage &msg) : HistoryMessage(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.vfrom_id.v, textClean(qs(msg.vmessage)), msg.vmedia)
|
||||
HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const MTPDmessage &msg) : HistoryMessage(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.vfrom_id.v, textClean(qs(msg.vmessage)), msg.has_entities() ? linksFromMTP(msg.ventities.c_vector().v) : LinksInText(), msg.vmedia)
|
||||
, fwdDate(::date(msg.vfwd_date))
|
||||
, fwdFrom(App::user(msg.vfwd_from_id.v))
|
||||
, fwdFromVersion(fwdFrom->nameVersion)
|
||||
|
@ -5582,7 +5593,7 @@ HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const
|
|||
fwdNameUpdated();
|
||||
}
|
||||
|
||||
HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId id, HistoryMessage *msg) : HistoryMessage(history, block, id, ((history->peer->input.type() != mtpc_inputPeerSelf) ? (MTPDmessage_flag_out | MTPDmessage_flag_unread) : 0) | (msg->getMedia() && (msg->getMedia()->type() == MediaTypeAudio/* || msg->getMedia()->type() == MediaTypeVideo*/) ? MTPDmessage_flag_media_unread : 0), ::date(unixtime()), MTP::authedId(), msg->justMedia() ? QString() : msg->HistoryMessage::selectedText(FullItemSel), msg->getMedia())
|
||||
HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId id, HistoryMessage *msg) : HistoryMessage(history, block, id, ((history->peer->input.type() != mtpc_inputPeerSelf) ? (MTPDmessage_flag_out | MTPDmessage_flag_unread) : 0) | (msg->getMedia() && (msg->getMedia()->type() == MediaTypeAudio/* || msg->getMedia()->type() == MediaTypeVideo*/) ? MTPDmessage_flag_media_unread : 0), ::date(unixtime()), MTP::authedId(), msg->justMedia() ? QString() : msg->HistoryMessage::selectedText(FullItemSel), msg->HistoryMessage::textLinks(), msg->getMedia())
|
||||
, fwdDate(msg->dateForwarded())
|
||||
, fwdFrom(msg->fromForwarded())
|
||||
, fwdFromVersion(fwdFrom->nameVersion)
|
||||
|
@ -5769,7 +5780,7 @@ void HistoryForwarded::getSymbol(uint16 &symbol, bool &after, bool &upon, int32
|
|||
return HistoryMessage::getSymbol(symbol, after, upon, x, y);
|
||||
}
|
||||
|
||||
HistoryReply::HistoryReply(History *history, HistoryBlock *block, const MTPDmessage &msg) : HistoryMessage(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.vfrom_id.v, textClean(qs(msg.vmessage)), msg.vmedia)
|
||||
HistoryReply::HistoryReply(History *history, HistoryBlock *block, const MTPDmessage &msg) : HistoryMessage(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.vfrom_id.v, textClean(qs(msg.vmessage)), msg.has_entities() ? linksFromMTP(msg.ventities.c_vector().v) : LinksInText(), msg.vmedia)
|
||||
, replyToMsgId(msg.vreply_to_msg_id.v)
|
||||
, replyToMsg(0)
|
||||
, replyToVersion(0)
|
||||
|
|
|
@ -780,6 +780,8 @@ public:
|
|||
}
|
||||
virtual void setMedia(const MTPmessageMedia &media) {
|
||||
}
|
||||
virtual void setText(const QString &text, const LinksInText &links) {
|
||||
}
|
||||
virtual QString time() const {
|
||||
return QString();
|
||||
}
|
||||
|
@ -1288,7 +1290,6 @@ public:
|
|||
void initMediaFromText(QString ¤tText);
|
||||
void initMediaFromDocument(DocumentData *doc);
|
||||
void initDimensions(const HistoryItem *parent = 0);
|
||||
void initDimensions(const QString &text, const LinksInText &links);
|
||||
void fromNameUpdated() const;
|
||||
|
||||
bool justMedia() const {
|
||||
|
@ -1322,9 +1323,11 @@ public:
|
|||
}
|
||||
|
||||
QString selectedText(uint32 selection) const;
|
||||
LinksInText textLinks() const;
|
||||
QString inDialogsText() const;
|
||||
HistoryMedia *getMedia(bool inOverview = false) const;
|
||||
void setMedia(const MTPmessageMedia &media);
|
||||
void setText(const QString &text, const LinksInText &links);
|
||||
|
||||
QString time() const {
|
||||
return _time;
|
||||
|
@ -1559,3 +1562,5 @@ protected:
|
|||
QString text;
|
||||
bool freezed;
|
||||
};
|
||||
|
||||
const TextParseOptions &itemTextParseOptions(History *h, UserData *f);
|
||||
|
|
|
@ -982,6 +982,12 @@ DialogsIndexed &MainWidget::dialogsList() {
|
|||
return dialogs.dialogsList();
|
||||
}
|
||||
|
||||
QString cleanMessage(const QString &text) {
|
||||
QString result = text.trimmed();
|
||||
// clean bad symbols
|
||||
return result;
|
||||
}
|
||||
|
||||
void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId replyTo, WebPageId webPageId) {
|
||||
saveRecentHashtags(text);
|
||||
QString sendingText, leftText = text;
|
||||
|
@ -990,7 +996,10 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl
|
|||
MsgId newId = clientMsgId();
|
||||
uint64 randomId = MTP::nonce<uint64>();
|
||||
|
||||
sendingText = cleanMessage(sendingText);
|
||||
|
||||
App::historyRegRandom(randomId, newId);
|
||||
App::historyRegSentText(randomId, sendingText);
|
||||
|
||||
MTPstring msgText(MTP_string(sendingText));
|
||||
int32 flags = newMessageFlags(hist->peer); // unread, out
|
||||
|
@ -1006,8 +1015,9 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl
|
|||
WebPageData *page = App::webPage(webPageId);
|
||||
media = MTP_messageMediaWebPage(MTP_webPagePending(MTP_long(page->id), MTP_int(page->pendingTill)));
|
||||
}
|
||||
MTPVector<MTPMessageEntity> localEntities = linksToMTP(textParseLinks(sendingText, itemTextParseOptions(hist, App::self()).flags));
|
||||
hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media, MTPnullMarkup, MTPnullEntities));
|
||||
hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup, MTPnullEntities), App::main()->rpcDone(&MainWidget::sentDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId);
|
||||
hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup, localEntities), App::main()->rpcDone(&MainWidget::sentDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId);
|
||||
}
|
||||
|
||||
finishForwarding(hist);
|
||||
|
@ -2221,8 +2231,21 @@ void MainWidget::sentDataReceived(uint64 randomId, const MTPmessages_SentMessage
|
|||
switch (result.type()) {
|
||||
case mtpc_messages_sentMessage: {
|
||||
const MTPDmessages_sentMessage &d(result.c_messages_sentMessage());
|
||||
|
||||
if (randomId) feedUpdate(MTP_updateMessageID(d.vid, MTP_long(randomId))); // ignore real date
|
||||
|
||||
HistoryItem *item = 0;
|
||||
if (randomId) {
|
||||
QString text = App::histSentTextByItem(randomId);
|
||||
feedUpdate(MTP_updateMessageID(d.vid, MTP_long(randomId))); // ignore real date
|
||||
LinksInText links(linksFromMTP(d.ventities.c_vector().v));
|
||||
if (!text.isEmpty() && !links.isEmpty()) {
|
||||
item = App::histItemById(d.vid.v);
|
||||
if (item) {
|
||||
item->setText(text, links);
|
||||
item->initDimensions(0);
|
||||
itemResized(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updInited) {
|
||||
if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) {
|
||||
|
@ -2231,7 +2254,9 @@ void MainWidget::sentDataReceived(uint64 randomId, const MTPmessages_SentMessage
|
|||
}
|
||||
}
|
||||
|
||||
HistoryItem *item = App::histItemById(d.vid.v);
|
||||
if (!item) {
|
||||
item = App::histItemById(d.vid.v);
|
||||
}
|
||||
if (item) {
|
||||
item->setMedia(d.vmedia);
|
||||
}
|
||||
|
@ -2240,7 +2265,20 @@ void MainWidget::sentDataReceived(uint64 randomId, const MTPmessages_SentMessage
|
|||
case mtpc_messages_sentMessageLink: {
|
||||
const MTPDmessages_sentMessageLink &d(result.c_messages_sentMessageLink());
|
||||
|
||||
if (randomId) feedUpdate(MTP_updateMessageID(d.vid, MTP_long(randomId))); // ignore real date
|
||||
HistoryItem *item = 0;
|
||||
if (randomId) {
|
||||
//QString text = App::histSentTextByItem(randomId);
|
||||
feedUpdate(MTP_updateMessageID(d.vid, MTP_long(randomId))); // ignore real date
|
||||
//LinksInText links(linksFromMTP(d.ventities.c_vector().v));
|
||||
//if (!text.isEmpty() && !links.isEmpty()) {
|
||||
// item = App::histItemById(d.vid.v);
|
||||
// if (item) {
|
||||
// item->setText(text, links);
|
||||
// item->initDimensions(0);
|
||||
// itemResized(item);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
if (updInited) {
|
||||
if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) {
|
||||
|
@ -2250,11 +2288,11 @@ void MainWidget::sentDataReceived(uint64 randomId, const MTPmessages_SentMessage
|
|||
}
|
||||
App::feedUserLinks(d.vlinks);
|
||||
|
||||
if (d.vmedia.type() != mtpc_messageMediaEmpty) {
|
||||
HistoryItem *item = App::histItemById(d.vid.v);
|
||||
if (item) {
|
||||
item->setMedia(d.vmedia);
|
||||
}
|
||||
if (!item) {
|
||||
item = App::histItemById(d.vid.v);
|
||||
}
|
||||
if (item) {
|
||||
item->setMedia(d.vmedia);
|
||||
}
|
||||
} break;
|
||||
};
|
||||
|
@ -3434,6 +3472,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
}
|
||||
App::historyUnregRandom(d.vrandom_id.v);
|
||||
}
|
||||
App::historyUnregSentText(d.vrandom_id.v);
|
||||
} break;
|
||||
|
||||
case mtpc_updateReadMessagesContents: {
|
||||
|
|
Loading…
Add table
Reference in a new issue