Skip to content

Commit c93e4e2

Browse files
committed
version 0.5.8 prepared, hashtag search support, clearhistory crash fix
1 parent 54095eb commit c93e4e2

18 files changed

Lines changed: 177 additions & 78 deletions

Telegram/Prepare.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
AppVersionStr=0.5.7
2-
AppVersion=5007
1+
AppVersionStr=0.5.8
2+
AppVersion=5008
33

44
if [ -d "./../Mac/Release/deploy/$AppVersionStr" ]; then
55
echo "Deploy folder for version $AppVersionStr already exists!"

Telegram/PrepareUbuntu.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
AppVersionStr=0.5.7
2-
AppVersion=5007
1+
AppVersionStr=0.5.8
2+
AppVersion=5008
33

44
if [ -d "./../Linux/Release/deploy/$AppVersionStr" ]; then
55
echo "Deploy folder for version $AppVersionStr already exists!"

Telegram/Resources/lang.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ lng_context_open_link: "Open Link";
308308
lng_context_copy_link: "Copy Link";
309309
lng_context_open_email: "Write to this address";
310310
lng_context_copy_email: "Copy email address";
311+
lng_context_open_hashtag: "Search by hashtag";
312+
lng_context_copy_hashtag: "Copy hashtag";
311313
lng_context_open_image: "Open Image";
312314
lng_context_save_image: "Save Image As...";
313315
lng_context_forward_image: "Forward Image";

Telegram/Setup.iss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
#define MyAppShortName "Telegram"
55
#define MyAppName "Telegram Win (Unofficial)"
6-
#define MyAppVersion "0.5.7"
7-
#define MyAppVersionZero "0.5.7"
8-
#define MyAppFullVersion "0.5.7.0"
6+
#define MyAppVersion "0.5.8"
7+
#define MyAppVersionZero "0.5.8"
8+
#define MyAppFullVersion "0.5.8.0"
99
#define MyAppPublisher "Telegram (Unofficial)"
1010
#define MyAppURL "https://tdesktop.com"
1111
#define MyAppExeName "Telegram.exe"

Telegram/SourceFiles/app.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,4 +1955,10 @@ namespace App {
19551955
}
19561956
}
19571957

1958+
void searchByHashtag(const QString &tag) {
1959+
if (App::main()) {
1960+
App::main()->searchMessages(tag);
1961+
}
1962+
}
1963+
19581964
}

Telegram/SourceFiles/app.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,6 @@ namespace App {
187187
void setProxySettings(QNetworkAccessManager &manager);
188188
void setProxySettings(QTcpSocket &socket);
189189

190+
void searchByHashtag(const QString &tag);
191+
190192
};

Telegram/SourceFiles/config.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
1717
*/
1818
#pragma once
1919

20-
static const int32 AppVersion = 5007;
21-
static const wchar_t *AppVersionStr = L"0.5.7";
20+
static const int32 AppVersion = 5008;
21+
static const wchar_t *AppVersionStr = L"0.5.8";
2222
#ifdef Q_OS_WIN
2323
static const wchar_t *AppName = L"Telegram Win (Unofficial)";
2424
#else

Telegram/SourceFiles/dialogswidget.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,16 @@ void DialogsWidget::onNeedSearchMessages() {
11181118
}
11191119
}
11201120

1121+
void DialogsWidget::searchMessages(const QString &query) {
1122+
if (_filter.text() != query) {
1123+
_filter.setText(query);
1124+
_filter.updatePlaceholder();
1125+
onFilterUpdate();
1126+
_searchTimer.stop();
1127+
onSearchMessages();
1128+
}
1129+
}
1130+
11211131
void DialogsWidget::onSearchMore(MsgId minMsgId) {
11221132
if (!_searchRequest && !_searchFull) {
11231133
_searchRequest = MTP::send(MTPmessages_Search(MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minMsgId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, !minMsgId), rpcFail(&DialogsWidget::searchFailed));

Telegram/SourceFiles/dialogswidget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ class DialogsWidget : public QWidget, public Animated, public RPCSender {
170170

171171
void enableShadow(bool enable = true);
172172

173+
void searchMessages(const QString &query);
173174
void onSearchMore(MsgId minMsgId);
174175
void clearFiltered();
175176

Telegram/SourceFiles/gui/text.cpp

Lines changed: 100 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
1919
#include "text.h"
2020

2121
#include "lang.h"
22+
#include "app.h"
2223

2324
#include <private/qharfbuzz_p.h>
2425

@@ -111,8 +112,9 @@ namespace {
111112
}
112113

113114
const QRegularExpression reDomain(QString::fromUtf8("(?<![A-Za-z\\$0-9А-Яа-яёЁ\\-\\_%=])(?:([a-zA-Z]+)://)?((?:[A-Za-zА-яА-ЯёЁ0-9\\-\\_]+\\.){1,5}([A-Za-zрф\\-\\d]{2,22}))"));
114-
const QRegularExpression reMailName(QString::fromUtf8("[a-zA-Z\\-_\\.0-9]{1,256}$"));
115-
const QRegularExpression reMailStart(QString::fromUtf8("^[a-zA-Z\\-_\\.0-9]{1,256}\\@"));
115+
const QRegularExpression reMailName(qsl("[a-zA-Z\\-_\\.0-9]{1,256}$"));
116+
const QRegularExpression reMailStart(qsl("^[a-zA-Z\\-_\\.0-9]{1,256}\\@"));
117+
const QRegularExpression reHashtag(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])#[A-Za-z_\\.0-9]{4,20}([\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10]|$)"));
116118
QSet<int32> validProtocols, validTopDomains;
117119
void initLinkSets();
118120

@@ -298,7 +300,7 @@ class TextParser {
298300
return Qt::LayoutDirectionAuto;
299301
}
300302

301-
void prepareLinks() { // support emails!
303+
void prepareLinks() { // support emails and hashtags!
302304
if (validProtocols.empty()) {
303305
initLinkSets();
304306
}
@@ -313,73 +315,98 @@ class TextParser {
313315
}
314316
}
315317
QRegularExpressionMatch mDomain = reDomain.match(src, offset);
316-
if (!mDomain.hasMatch()) break;
318+
QRegularExpressionMatch mHashtag = reHashtag.match(src, offset);
319+
if (!mDomain.hasMatch() && !mHashtag.hasMatch()) break;
317320

318-
int32 domainOffset = mDomain.capturedStart(), domainEnd = mDomain.capturedEnd();
319-
if (domainOffset > nextCmd) {
320-
const QChar *after = skipCommand(srcData + nextCmd, srcData + len);
321-
if (after > srcData + nextCmd && domainOffset < (after - srcData)) {
322-
nextCmd = offset = after - srcData;
323-
continue;
321+
LinkRange link;
322+
int32 domainOffset = mDomain.hasMatch() ? mDomain.capturedStart() : INT_MAX,
323+
domainEnd = mDomain.hasMatch() ? mDomain.capturedEnd() : INT_MAX,
324+
hashtagOffset = mHashtag.hasMatch() ? mHashtag.capturedStart() : INT_MAX,
325+
hashtagEnd = mHashtag.hasMatch() ? mHashtag.capturedEnd() : INT_MAX;
326+
if (mHashtag.hasMatch()) {
327+
if (!mHashtag.capturedRef(1).isEmpty()) {
328+
++hashtagOffset;
329+
}
330+
if (!mHashtag.capturedRef(2).isEmpty()) {
331+
--hashtagEnd;
324332
}
325333
}
334+
if (hashtagOffset < domainOffset) {
335+
if (hashtagOffset > nextCmd) {
336+
const QChar *after = skipCommand(srcData + nextCmd, srcData + len);
337+
if (after > srcData + nextCmd && hashtagOffset < (after - srcData)) {
338+
nextCmd = offset = after - srcData;
339+
continue;
340+
}
341+
}
342+
343+
link.from = start + hashtagOffset;
344+
link.len = start + hashtagEnd - link.from;
345+
} else {
346+
if (domainOffset > nextCmd) {
347+
const QChar *after = skipCommand(srcData + nextCmd, srcData + len);
348+
if (after > srcData + nextCmd && domainOffset < (after - srcData)) {
349+
nextCmd = offset = after - srcData;
350+
continue;
351+
}
352+
}
326353

327-
QString protocol = mDomain.captured(1).toLower();
328-
QString topDomain = mDomain.captured(3).toLower();
329-
330-
bool isProtocolValid = protocol.isEmpty() || validProtocols.contains(hashCrc32(protocol.constData(), protocol.size() * sizeof(QChar)));
331-
bool isTopDomainValid = validTopDomains.contains(hashCrc32(topDomain.constData(), topDomain.size() * sizeof(QChar)));
354+
QString protocol = mDomain.captured(1).toLower();
355+
QString topDomain = mDomain.captured(3).toLower();
332356

333-
if (!isProtocolValid || !isTopDomainValid) {
334-
offset = domainEnd;
335-
continue;
336-
}
357+
bool isProtocolValid = protocol.isEmpty() || validProtocols.contains(hashCrc32(protocol.constData(), protocol.size() * sizeof(QChar)));
358+
bool isTopDomainValid = validTopDomains.contains(hashCrc32(topDomain.constData(), topDomain.size() * sizeof(QChar)));
337359

338-
LinkRange link;
339-
if (protocol.isEmpty() && domainOffset > offset + 1 && *(start + domainOffset - 1) == QChar('@')) {
340-
QString forMailName = src.mid(offset, domainOffset - offset - 1);
341-
QRegularExpressionMatch mMailName = reMailName.match(forMailName);
342-
if (mMailName.hasMatch()) {
343-
int32 mailOffset = offset + mMailName.capturedStart();
344-
if (mailOffset < offset) {
345-
mailOffset = offset;
346-
}
347-
link.from = start + mailOffset;
348-
link.len = domainEnd - mailOffset;
360+
if (!isProtocolValid || !isTopDomainValid) {
361+
offset = domainEnd;
362+
continue;
349363
}
350-
}
351-
if (!link.from || !link.len) {
352-
link.from = start + domainOffset;
353-
354-
QStack<const QChar*> parenth;
355-
const QChar *p = start + mDomain.capturedEnd();
356-
for (; p < end; ++p) {
357-
QChar ch(*p);
358-
if (chIsLinkEnd(ch)) break; // link finished
359-
if (chIsAlmostLinkEnd(ch)) {
360-
const QChar *endTest = p + 1;
361-
while (endTest < end && chIsAlmostLinkEnd(*endTest)) {
362-
++endTest;
363-
}
364-
if (endTest >= end || chIsLinkEnd(*endTest)) {
365-
break; // link finished at p
364+
365+
if (protocol.isEmpty() && domainOffset > offset + 1 && *(start + domainOffset - 1) == QChar('@')) {
366+
QString forMailName = src.mid(offset, domainOffset - offset - 1);
367+
QRegularExpressionMatch mMailName = reMailName.match(forMailName);
368+
if (mMailName.hasMatch()) {
369+
int32 mailOffset = offset + mMailName.capturedStart();
370+
if (mailOffset < offset) {
371+
mailOffset = offset;
366372
}
367-
p = endTest;
368-
ch = *p;
373+
link.from = start + mailOffset;
374+
link.len = domainEnd - mailOffset;
369375
}
370-
if (ch == '(' || ch == '[' || ch == '{' || ch == '<') {
371-
parenth.push(p);
372-
} else if (ch == ')' || ch == ']' || ch == '}' || ch == '>') {
373-
if (parenth.isEmpty()) break;
374-
const QChar *q = parenth.pop(), open(*q);
375-
if ((ch == ')' && open != '(') || (ch == ']' && open != '[') || (ch == '}' && open != '{') || (ch == '>' && open != '<')) {
376-
p = q;
377-
break;
376+
}
377+
if (!link.from || !link.len) {
378+
link.from = start + domainOffset;
379+
380+
QStack<const QChar*> parenth;
381+
const QChar *p = start + mDomain.capturedEnd();
382+
for (; p < end; ++p) {
383+
QChar ch(*p);
384+
if (chIsLinkEnd(ch)) break; // link finished
385+
if (chIsAlmostLinkEnd(ch)) {
386+
const QChar *endTest = p + 1;
387+
while (endTest < end && chIsAlmostLinkEnd(*endTest)) {
388+
++endTest;
389+
}
390+
if (endTest >= end || chIsLinkEnd(*endTest)) {
391+
break; // link finished at p
392+
}
393+
p = endTest;
394+
ch = *p;
395+
}
396+
if (ch == '(' || ch == '[' || ch == '{' || ch == '<') {
397+
parenth.push(p);
398+
} else if (ch == ')' || ch == ']' || ch == '}' || ch == '>') {
399+
if (parenth.isEmpty()) break;
400+
const QChar *q = parenth.pop(), open(*q);
401+
if ((ch == ')' && open != '(') || (ch == ']' && open != '[') || (ch == '}' && open != '{') || (ch == '>' && open != '<')) {
402+
p = q;
403+
break;
404+
}
378405
}
379406
}
380-
}
381407

382-
link.len = p - link.from;
408+
link.len = p - link.from;
409+
}
383410
}
384411
lnkRanges.push_back(link);
385412

@@ -421,9 +448,12 @@ class TextParser {
421448
}
422449

423450
void getLinkData(const QString &original, QString &result, int32 &fullDisplayed) {
424-
if (reMailStart.match(original).hasMatch()) {
451+
if (!original.isEmpty() && original.at(0) == '#') {
452+
result = original;
453+
fullDisplayed = -2; // hashtag
454+
} else if (reMailStart.match(original).hasMatch()) {
425455
result = original;
426-
fullDisplayed = -1;
456+
fullDisplayed = -1; // email
427457
} else {
428458
QUrl url(original), good(url.isValid() ? url.toEncoded() : "");
429459
QString readable = good.isValid() ? good.toDisplayString() : original;
@@ -725,7 +755,9 @@ class TextParser {
725755
_t->_links.resize(lnkIndex);
726756
const TextLinkData &data(links[lnkIndex - maxLnkIndex - 1]);
727757
TextLinkPtr lnk;
728-
if (data.fullDisplayed < 0) { // email
758+
if (data.fullDisplayed < -1) { // hashtag
759+
lnk = TextLinkPtr(new HashtagLink(data.url));
760+
} else if (data.fullDisplayed < 0) { // email
729761
lnk = TextLinkPtr(new EmailLink(data.url));
730762
} else {
731763
lnk = TextLinkPtr(new TextLink(data.url, data.fullDisplayed > 0));
@@ -755,7 +787,7 @@ class TextParser {
755787
TextLinkData(const QString &url = QString(), int32 fullDisplayed = 1) : url(url), fullDisplayed(fullDisplayed) {
756788
}
757789
QString url;
758-
int32 fullDisplayed; // < 0 - email
790+
int32 fullDisplayed; // -2 - hashtag, -1 - email
759791
};
760792
typedef QVector<TextLinkData> TextLinks;
761793
TextLinks links;
@@ -874,6 +906,12 @@ namespace {
874906

875907
}
876908

909+
void HashtagLink::onClick(Qt::MouseButton button) const {
910+
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
911+
App::searchByHashtag(_tag);
912+
}
913+
}
914+
877915
class TextPainter {
878916
public:
879917

0 commit comments

Comments
 (0)