diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings index 3cd50617cb..e633a506ee 100644 --- a/Telegram/Resources/lang.strings +++ b/Telegram/Resources/lang.strings @@ -686,6 +686,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org "lng_forwarding_from" = "{user} and {count:_not_used_|# other|# others}"; "lng_forwarding_from_two" = "{user} and {second_user}"; +"lng_share_cant" = "Sorry, no way to share here :("; + "lng_contact_phone" = "Phone number"; "lng_enter_contact_data" = "New Contact"; "lng_edit_group_title" = "Edit group name"; diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 7dc5d751ee..83ac51c8b0 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -2294,7 +2294,7 @@ void DialogsWidget::onCancelSearchInPeer() { _searchRequest = 0; } if (_searchInPeer) { - if (!cWideMode()) { + if (!cWideMode() && !App::main()->selectingPeer()) { App::main()->showPeerHistory(_searchInPeer->id, ShowAtUnreadMsgId); } _searchInPeer = 0; @@ -2304,7 +2304,7 @@ void DialogsWidget::onCancelSearchInPeer() { _filter.clear(); _filter.updatePlaceholder(); onFilterUpdate(); - if (cWideMode()) { + if (cWideMode() && !App::main()->selectingPeer()) { emit cancelled(); } } diff --git a/Telegram/SourceFiles/gui/text.cpp b/Telegram/SourceFiles/gui/text.cpp index 1b2bfb2b97..d25b7f36b7 100644 --- a/Telegram/SourceFiles/gui/text.cpp +++ b/Telegram/SourceFiles/gui/text.cpp @@ -798,7 +798,6 @@ namespace { ++stop; start = stop; } - } void TextLink::onClick(Qt::MouseButton button) const { @@ -807,21 +806,19 @@ void TextLink::onClick(Qt::MouseButton button) const { QRegularExpressionMatch telegramMeUser = QRegularExpression(qsl("^https?://telegram\\.me/([a-zA-Z0-9\\.\\_]+)/?(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url); QRegularExpressionMatch telegramMeGroup = QRegularExpression(qsl("^https?://telegram\\.me/joinchat/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url); QRegularExpressionMatch telegramMeStickers = QRegularExpression(qsl("^https?://telegram\\.me/addstickers/([a-zA-Z0-9\\.\\_]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url); + QRegularExpressionMatch telegramMeShareUrl = QRegularExpression(qsl("^https?://telegram\\.me/share/url\\?(.+)$"), QRegularExpression::CaseInsensitiveOption).match(url); if (telegramMeUser.hasMatch()) { - QString params = url.mid(telegramMeUser.captured(0).size()), start, startToken; - if (!params.isEmpty()) { - QRegularExpressionMatch startParams = QRegularExpression(qsl("(^|&)(start|startgroup)=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"), QRegularExpression::CaseInsensitiveOption).match(params); - if (startParams.hasMatch()) { - start = startParams.captured(2); - startToken = startParams.captured(3); - } - } - App::openPeerByName(telegramMeUser.captured(1), start == qsl("startgroup"), startToken); + QString params = url.mid(telegramMeUser.captured(0).size()); + url = qsl("tg://resolve/?domain=") + myUrlEncode(telegramMeUser.captured(1)) + (params.isEmpty() ? QString() : '&' + params); } else if (telegramMeGroup.hasMatch()) { - App::joinGroupByHash(telegramMeGroup.captured(1)); + url = qsl("tg://join?invite=") + myUrlEncode(telegramMeGroup.captured(1)); } else if (telegramMeStickers.hasMatch()) { - App::stickersBox(telegramMeStickers.captured(1)); - } else if (QRegularExpression(qsl("^tg://[a-zA-Z0-9]+"), QRegularExpression::CaseInsensitiveOption).match(url).hasMatch()) { + url = qsl("tg://addstickers?set=") + myUrlEncode(telegramMeStickers.captured(1)); + } else if (telegramMeShareUrl.hasMatch()) { + url = qsl("tg://msg_url?") + telegramMeShareUrl.captured(1); + } + + if (QRegularExpression(qsl("^tg://[a-zA-Z0-9]+"), QRegularExpression::CaseInsensitiveOption).match(url).hasMatch()) { App::openLocalUrl(url); } else { QDesktopServices::openUrl(url); diff --git a/Telegram/SourceFiles/gui/text.h b/Telegram/SourceFiles/gui/text.h index 14c9f1fabf..ef0b81d823 100644 --- a/Telegram/SourceFiles/gui/text.h +++ b/Telegram/SourceFiles/gui/text.h @@ -773,3 +773,10 @@ inline bool chIsParagraphSeparator(QChar ch) { } return false; } + +inline QString myUrlEncode(const QString &str) { + return QString::fromLatin1(QUrl::toPercentEncoding(str)); +} +inline QString myUrlDecode(const QString &enc) { + return QUrl::fromPercentEncoding(enc.toUtf8()); +} diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 895371ec3d..1f85e0bbcf 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -2104,6 +2104,24 @@ HistoryHider::HistoryHider(MainWidget *parent) : TWidget(parent) init(); } +HistoryHider::HistoryHider(MainWidget *parent, const QString &url, const QString &text) : TWidget(parent) +, _sharedContact(0) +, _forwardSelected(false) +, _sendPath(false) +, _shareUrl(url) +, _shareText(text) +, _send(this, lang(lng_forward_send), st::defaultBoxButton) +, _cancel(this, lang(lng_cancel), st::cancelBoxButton) +, offered(0) +, a_opacity(0, 1) +, hiding(false) +, _forwardRequest(0) +, toTextWidth(0) +, shadow(st::boxShadow) +{ + init(); +} + void HistoryHider::init() { connect(&_send, SIGNAL(clicked()), this, SLOT(forward())); connect(&_cancel, SIGNAL(clicked()), this, SLOT(startHide())); @@ -2211,6 +2229,8 @@ void HistoryHider::forward() { parent()->onShareContact(offered->id, _sharedContact); } else if (_sendPath) { parent()->onSendPaths(offered->id); + } else if (!_shareUrl.isEmpty()) { + parent()->onShareUrl(offered->id, _shareUrl, _shareText); } else { parent()->onForward(offered->id, _forwardSelected ? ForwardSelectedMessages : ForwardContextMessage); } @@ -2268,6 +2288,13 @@ bool HistoryHider::offerPeer(PeerId peer) { } phrase = lng_forward_send_file_confirm(lt_name, name, lt_recipient, recipient); } + } else if (!_shareUrl.isEmpty()) { + PeerId to = offered->id; + offered = 0; + if (parent()->onShareUrl(to, _shareUrl, _shareText)) { + startHide(); + } + return false; } else { PeerId to = offered->id; offered = 0; @@ -2880,6 +2907,17 @@ void HistoryWidget::fastShowAtEnd(History *h) { } } +void HistoryWidget::applyDraft(bool parseLinks) { + if (!_history) return; + setFieldText(_history->draft); + _field.setFocus(); + _history->draftCursor.applyTo(_field, &_synthedTextUpdate); + _previewCancelled = _history->draftPreviewCancelled; + if (parseLinks) { + onPreviewParse(); + } +} + void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) { MsgId wasMsgId = _showAtMsgId; History *wasHistory = _history; @@ -3028,13 +3066,8 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) { App::main()->peerUpdated(_peer); if (_history->draftToId > 0 || !_history->draft.isEmpty()) { - setFieldText(_history->draft); - _field.setFocus(); - _history->draftCursor.applyTo(_field, &_synthedTextUpdate); + applyDraft(false); _replyToId = readyToForward() ? 0 : _history->draftToId; - if (_history->draftPreviewCancelled) { - _previewCancelled = true; - } } else { Local::MessageDraft draft = Local::readDraft(_peer->id); setFieldText(draft.text); @@ -3044,9 +3077,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) { cur.applyTo(_field, &_synthedTextUpdate); } _replyToId = readyToForward() ? 0 : draft.replyTo; - if (draft.previewCancelled) { - _previewCancelled = true; - } + _previewCancelled = draft.previewCancelled; } if (_replyToId) { updateReplyTo(); diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index 7a629936ff..b17f72e00a 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -319,6 +319,7 @@ public: HistoryHider(MainWidget *parent, bool forwardSelected); // forward messages HistoryHider(MainWidget *parent, UserData *sharedContact); // share contact HistoryHider(MainWidget *parent); // send path from command line argument + HistoryHider(MainWidget *parent, const QString &url, const QString &text); // share url bool animStep(float64 ms); bool withConfirm() const; @@ -354,6 +355,8 @@ private: UserData *_sharedContact; bool _forwardSelected, _sendPath; + QString _shareUrl, _shareText; + BoxButton _send, _cancel; PeerData *offered; anim::fvalue a_opacity; @@ -520,6 +523,7 @@ public: DragState getDragState(const QMimeData *d); void fastShowAtEnd(History *h); + void applyDraft(bool parseLinks = true); void showPeerHistory(const PeerId &peer, MsgId showAtMsgId); void clearDelayedShowAt(); void clearAllLoadRequests(); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index e82e69aea7..6eb65f6674 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -509,6 +509,26 @@ bool MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) { return true; } +bool MainWidget::onShareUrl(const PeerId &peer, const QString &url, const QString &text) { + PeerData *p = App::peer(peer); + if (!peer || (p->isChannel() && !p->asChannel()->canPublish() && p->asChannel()->isBroadcast()) || (p->isChat() && (p->asChat()->haveLeft || p->asChat()->isForbidden)) || (p->isUser() && p->asUser()->access == UserNoAccess)) { + App::wnd()->showLayer(new InformBox(lang(lng_share_cant))); + return false; + } + History *h = App::history(peer); + h->draft = url + '\n' + text; + h->draftCursor.anchor = url.size() + 1; + h->draftCursor.position = h->draftCursor.anchor + text.size(); + h->draftPreviewCancelled = false; + bool opened = history.peer() && (history.peer()->id == peer); + if (opened) { + history.applyDraft(); + } else { + showPeerHistory(peer, ShowAtUnreadMsgId); + } + return true; +} + bool MainWidget::hasForwardingItems() { return !_toForward.isEmpty(); } @@ -785,6 +805,10 @@ void MainWidget::shareContactLayer(UserData *contact) { hiderLayer(new HistoryHider(this, contact)); } +void MainWidget::shareUrlLayer(const QString &url, const QString &text) { + hiderLayer(new HistoryHider(this, url, text)); +} + bool MainWidget::selectingPeer(bool withConfirm) { return _hider ? (withConfirm ? _hider->withConfirm() : true) : false; } @@ -3578,6 +3602,22 @@ void MainWidget::openLocalUrl(const QString &url) { if (m.hasMatch()) { stickersBox(MTP_inputStickerSetShortName(MTP_string(m.captured(1)))); } + } else if (u.startsWith(qstr("tg://msg_url"), Qt::CaseInsensitive)) { + QRegularExpressionMatch m = QRegularExpression(qsl("^tg://msg_url/?\\?(.+)(#|$)"), QRegularExpression::CaseInsensitiveOption).match(u); + if (m.hasMatch()) { + QStringList params = m.captured(1).split('&'); + QString url, text; + for (int32 i = 0, l = params.size(); i < l; ++i) { + if (params.at(i).startsWith(qstr("url="), Qt::CaseInsensitive)) { + url = myUrlDecode(params.at(i).mid(4)); + } else if (params.at(i).startsWith(qstr("text="), Qt::CaseInsensitive)) { + text = myUrlDecode(params.at(i).mid(5)); + } + } + if (!url.isEmpty()) { + shareUrlLayer(url, text); + } + } } } diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 2993750ac1..6c85bb2ac4 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -285,9 +285,11 @@ public: void forwardLayer(int32 forwardSelected = 0); // -1 - send paths void deleteLayer(int32 selectedCount = -1); // -1 - context item, else selected, -2 - cancel upload void shareContactLayer(UserData *contact); + void shareUrlLayer(const QString &url, const QString &text); void hiderLayer(HistoryHider *h); void noHider(HistoryHider *destroyed); bool onForward(const PeerId &peer, ForwardWhatMessages what); + bool onShareUrl(const PeerId &peer, const QString &url, const QString &text); void onShareContact(const PeerId &peer, UserData *contact); void onSendPaths(const PeerId &peer); void onFilesOrForwardDrop(const PeerId &peer, const QMimeData *data);