diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index f6e24d9c2f..8dc0ed77ce 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -127,6 +127,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_join_channel_error" = "Sorry, you have joined too many channels and supergroups. Please leave some before joining."; "lng_error_phone_flood" = "Sorry, you have deleted and re-created your account too many times recently. Please wait for a few days before signing up again."; "lng_error_start_minimized_passcoded" = "You have set a local passcode, so the app can't be launched minimized. App will ask you to enter the passcode before it can start working."; +"lng_error_pinned_max" = "Sorry, you can pin no more than {count:_not_used_|# chat|# chats} to the top."; "lng_edit_deleted" = "This message was deleted"; "lng_edit_too_long" = "Your message text is too long"; @@ -157,7 +158,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_phone_notreg" = "If you don't have a Telegram account yet,\nplease [b]sign up[/b] with {link_start}Android / iPhone{link_end} or {signup_start}here{signup_end}"; "lng_country_code" = "Country Code"; "lng_bad_country_code" = "Invalid Country Code"; -"lng_country_fake_ph" = "Your country"; "lng_country_ph" = "Search"; "lng_country_done" = "Done"; "lng_country_none" = "Country not found"; @@ -754,8 +754,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_report_spam_sure_group" = "Are you sure you want to report spam in this group?"; "lng_report_spam_sure_channel" = "Are you sure you want to report spam in this channel?"; "lng_report_spam_ok" = "Report"; -"lng_cant_send_to_not_contact" = "You have contacted too many non-contacts today, please try again tomorrow. You will be able to reply today if this user messages you first. {more_info}"; -"lng_cant_invite_not_contact" = "You can't add this user because you have contacted too many non-contacts today. Please try again tomorrow. You can ask another member to add this user to the group. {more_info}"; +"lng_cant_send_to_not_contact" = "Sorry, you can only send messages to\nmutual contacts at the moment.\n{more_info}"; +"lng_cant_invite_not_contact" = "Sorry, you can only add mutual contacts\nto groups at the moment.\n{more_info}"; +"lng_cant_send_to_not_contact_flood" = "You have contacted too many non-contacts today, please try again tomorrow. You will be able to reply today if this user messages you first."; +"lng_cant_invite_not_contact_flood" = "You can't add this user because you have contacted too many non-contacts today. Please try again tomorrow. You can ask another member to add this user to the group."; "lng_cant_more_info" = "More info ยป"; "lng_cant_invite_banned" = "Sorry, only admin can add this user."; "lng_cant_invite_privacy" = "Sorry, you cannot add this user to groups because of their privacy settings."; @@ -959,11 +961,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_selected_delete_sure_this" = "Do you want to delete this message?"; "lng_selected_delete_sure" = "Do you want to delete {count:_not_used_|# message|# messages}?"; "lng_delete_photo_sure" = "Do you want to delete this photo?"; -"lng_delete_for_everyone_this_hint" = "This will delete it for everyone in this chat."; "lng_delete_for_everyone_hint" = "This will delete {count:_not_used_|it|them} for everyone in this chat."; -"lng_delete_for_me_chat_this_hint" = "This will delete it just for you, not for other participants of the chat."; "lng_delete_for_me_chat_hint" = "This will delete {count:_not_used_|it|them} just for you, not for other participants of the chat."; -"lng_delete_for_me_this_hint" = "This will delete it just for you."; "lng_delete_for_me_hint" = "This will delete {count:_not_used_|it|them} just for you."; "lng_delete_for_everyone_check" = "Delete for everyone"; "lng_delete_for_other_check" = "Delete for {user}"; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index dcac4225e7..d893201d53 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -416,9 +416,10 @@ passcodeSubmit: RoundButton(introNextButton) { width: 225px; } passcodeSubmitSkip: 40px; -passcodePadding: margins(0px, 0px, 0px, 12px); +passcodePadding: margins(0px, 0px, 0px, 5px); passcodeTextLine: 28px; passcodeLittleSkip: 5px; +passcodeAboutSkip: 7px; passcodeSkip: 20px; newGroupAboutFg: windowSubTextFg; diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp index 14e31f6473..d001e814e2 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.cpp +++ b/Telegram/SourceFiles/boxes/confirmbox.cpp @@ -371,8 +371,6 @@ PinMessageBox::PinMessageBox(QWidget*, ChannelData *channel, MsgId msgId) } void PinMessageBox::prepare() { - _text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); - addButton(lang(lng_pinned_pin), [this] { pinMessage(); }); addButton(lang(lng_cancel), [this] { closeBox(); }); @@ -385,6 +383,14 @@ void PinMessageBox::resizeEvent(QResizeEvent *e) { _notify->moveToLeft(st::boxPadding.left(), _text->y() + _text->height() + st::boxMediumSkip); } +void PinMessageBox::keyPressEvent(QKeyEvent *e) { + if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { + pinMessage(); + } else { + BoxContent::keyPressEvent(e); + } +} + void PinMessageBox::pinMessage() { if (_requestId) return; @@ -458,16 +464,17 @@ void DeleteMessagesBox::prepare() { canDeleteAllForEveryone = false; } } + auto count = qMax(1, _ids.size()); if (canDeleteAllForEveryone) { _forEveryone.create(this, forEveryoneText, false, st::defaultBoxCheckbox); } else if (peer && peer->isChannel()) { if (peer->isMegagroup()) { - text += qsl("\n\n") + (_singleItem ? lang(lng_delete_for_everyone_this_hint) : lng_delete_for_everyone_hint(lt_count, _ids.size())); + text += qsl("\n\n") + lng_delete_for_everyone_hint(lt_count, count); } } else if (peer->isChat()) { - text += qsl("\n\n") + (_singleItem ? lang(lng_delete_for_me_chat_this_hint) : lng_delete_for_me_chat_hint(lt_count, _ids.size())); - } else { - text += qsl("\n\n") + (_singleItem ? lang(lng_delete_for_me_this_hint) : lng_delete_for_me_hint(lt_count, _ids.size())); + text += qsl("\n\n") + lng_delete_for_me_chat_hint(lt_count, count); + } else if (!peer->isSelf()) { + text += qsl("\n\n") + lng_delete_for_me_hint(lt_count, count); } } _text.create(this, text, Ui::FlatLabel::InitType::Simple, st::boxLabel); @@ -475,7 +482,6 @@ void DeleteMessagesBox::prepare() { addButton(lang(lng_box_delete), [this] { deleteAndClear(); }); addButton(lang(lng_cancel), [this] { closeBox(); }); - _text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); auto fullHeight = st::boxPadding.top() + _text->height() + st::boxPadding.bottom(); if (_moderateFrom) { fullHeight += st::boxMediumSkip + _banUser->heightNoMargins() + st::boxLittleSkip + _reportSpam->heightNoMargins() + st::boxLittleSkip + _deleteAll->heightNoMargins(); @@ -497,6 +503,14 @@ void DeleteMessagesBox::resizeEvent(QResizeEvent *e) { } } +void DeleteMessagesBox::keyPressEvent(QKeyEvent *e) { + if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { + deleteAndClear(); + } else { + BoxContent::keyPressEvent(e); + } +} + void DeleteMessagesBox::deleteAndClear() { if (!App::main()) { return; diff --git a/Telegram/SourceFiles/boxes/confirmbox.h b/Telegram/SourceFiles/boxes/confirmbox.h index 11748b0913..d2762e4da4 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.h +++ b/Telegram/SourceFiles/boxes/confirmbox.h @@ -154,6 +154,7 @@ protected: void prepare() override; void resizeEvent(QResizeEvent *e) override; + void keyPressEvent(QKeyEvent *e) override; private: void pinMessage(); @@ -179,6 +180,7 @@ protected: void prepare() override; void resizeEvent(QResizeEvent *e) override; + void keyPressEvent(QKeyEvent *e) override; private: void deleteAndClear(); diff --git a/Telegram/SourceFiles/boxes/passcodebox.cpp b/Telegram/SourceFiles/boxes/passcodebox.cpp index 0773a89790..7676123490 100644 --- a/Telegram/SourceFiles/boxes/passcodebox.cpp +++ b/Telegram/SourceFiles/boxes/passcodebox.cpp @@ -65,17 +65,17 @@ void PasscodeBox::prepare() { if (_turningOff) { _oldPasscode->show(); setTitle(lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove)); - setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _aboutHeight + st::passcodePadding.bottom()); + setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + st::passcodeAboutSkip + _aboutHeight + st::passcodePadding.bottom()); } else { auto has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode(); if (has) { _oldPasscode->show(); setTitle(lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change)); - setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + _aboutHeight + st::passcodePadding.bottom()); + setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + st::passcodeAboutSkip + _aboutHeight + st::passcodePadding.bottom()); } else { _oldPasscode->hide(); setTitle(lang(_cloudPwd ? lng_cloud_password_create : lng_passcode_create)); - setDimensions(st::boxWidth, st::passcodePadding.top() + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + _aboutHeight + (_cloudPwd ? st::passcodeLittleSkip + _recoverEmail->height() + st::passcodeSkip : st::passcodePadding.bottom())); + setDimensions(st::boxWidth, st::passcodePadding.top() + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + st::passcodeAboutSkip + _aboutHeight + (_cloudPwd ? (st::passcodeLittleSkip + _recoverEmail->height() + st::passcodeSkip) : st::passcodePadding.bottom())); } } @@ -143,7 +143,7 @@ void PasscodeBox::paintEvent(QPaintEvent *e) { Painter p(this); int32 w = st::boxWidth - st::boxPadding.left() * 1.5; - int32 abouty = (_passwordHint->isHidden() ? (_reenterPasscode->isHidden() ? (_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) : _reenterPasscode->y()) + st::passcodeSkip : _passwordHint->y() + st::passcodeLittleSkip) + _oldPasscode->height() + st::passcodePadding.bottom(); + int32 abouty = (_passwordHint->isHidden() ? ((_reenterPasscode->isHidden() ? (_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) : _reenterPasscode->y()) + st::passcodeSkip) : (_passwordHint->y() + st::passcodeLittleSkip)) + _oldPasscode->height() + st::passcodeLittleSkip + st::passcodeAboutSkip; p.setPen(st::boxTextFg); _about.drawLeft(p, st::boxPadding.left(), abouty, w, width()); diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp index ddc40606cc..2cf41f060c 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp @@ -81,9 +81,16 @@ void paintRow(Painter &p, const RippleRow *row, History *history, HistoryItem *i if (draft) { paintRowDate(p, date, rectForName, active, selected); + auto availableWidth = namewidth; + if (history->isPinnedDialog()) { + auto &icon = (active ? st::dialogsPinnedIconActive : (selected ? st::dialogsPinnedIconOver : st::dialogsPinnedIcon)); + icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), texttop, fullWidth); + availableWidth -= icon.width() + st::dialogsUnreadPadding; + } + p.setFont(st::dialogsTextFont); auto &color = active ? st::dialogsTextFgServiceActive : (selected ? st::dialogsTextFgServiceOver : st::dialogsTextFgService); - if (!history->paintSendAction(p, nameleft, texttop, namewidth, fullWidth, color, ms)) { + if (!history->paintSendAction(p, nameleft, texttop, availableWidth, fullWidth, color, ms)) { if (history->cloudDraftTextCache.isEmpty()) { auto draftWrapped = textcmdLink(1, lng_dialogs_text_from_wrapped(lt_from, lang(lng_from_draft))); auto draftText = lng_dialogs_text_with_from(lt_from_part, draftWrapped, lt_message, textClean(draft->textWithTags.text)); @@ -91,7 +98,7 @@ void paintRow(Painter &p, const RippleRow *row, History *history, HistoryItem *i } p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg)); p.setTextPalette(active ? st::dialogsTextPaletteDraftActive : (selected ? st::dialogsTextPaletteDraftOver : st::dialogsTextPaletteDraft)); - history->cloudDraftTextCache.drawElided(p, nameleft, texttop, namewidth, 1); + history->cloudDraftTextCache.drawElided(p, nameleft, texttop, availableWidth, 1); p.restoreTextPalette(); } } else if (!item) { diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 3f05e0a3e1..ed096cb79d 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -748,6 +748,10 @@ void Histories::clearPinned() { } } +int Histories::pinnedCount() const { + return _pinnedDialogs.size(); +} + HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction, bool detachExistingItem) { auto msgId = MsgId(0); switch (msg.type()) { diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index c1207ca25d..29d88a1b8f 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -84,6 +84,7 @@ public: void setIsPinned(History *history, bool isPinned); void clearPinned(); + int pinnedCount() const; struct SendActionAnimationUpdate { History *history; diff --git a/Telegram/SourceFiles/history/history_media_types.cpp b/Telegram/SourceFiles/history/history_media_types.cpp index 9da212d63b..7a2e3f71dc 100644 --- a/Telegram/SourceFiles/history/history_media_types.cpp +++ b/Telegram/SourceFiles/history/history_media_types.cpp @@ -1737,7 +1737,8 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM auto roundCorners = inWebPage ? ImageRoundCorner::All : ((isBubbleTop() ? (ImageRoundCorner::TopLeft | ImageRoundCorner::TopRight) : ImageRoundCorner::None) | ((isBubbleBottom() && _caption.isEmpty()) ? (ImageRoundCorner::BottomLeft | ImageRoundCorner::BottomRight) : ImageRoundCorner::None)); if (animating) { - p.drawPixmap(rthumb.topLeft(), _gif->current(_thumbw, _thumbh, width, height, roundRadius, roundCorners, (Ui::isLayerShown() || Ui::isMediaViewShown() || Ui::isInlineItemBeingChosen()) ? 0 : ms)); + auto pauseGif = (Ui::isLayerShown() || Ui::isMediaViewShown() || Ui::isInlineItemBeingChosen() || !App::wnd()->isActive()); + p.drawPixmap(rthumb.topLeft(), _gif->current(_thumbw, _thumbh, width, height, roundRadius, roundCorners, pauseGif ? 0 : ms)); } else { p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(_thumbw, _thumbh, width, height, roundRadius, roundCorners)); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 0c4c0928b0..543bbcb254 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1977,6 +1977,11 @@ void MainWidget::fillPeerMenu(PeerData *peer, base::lambdaisPinnedDialog(); + if (isPinned && App::histories().pinnedCount() >= Global::PinnedDialogsCountMax()) { + Ui::show(Box(lng_error_pinned_max(lt_count, Global::PinnedDialogsCountMax()))); + return; + } + history->setPinnedDialog(isPinned); auto flags = MTPmessages_ToggleDialogPin::Flags(0); if (isPinned) { diff --git a/Telegram/SourceFiles/stickers/emoji_pan.cpp b/Telegram/SourceFiles/stickers/emoji_pan.cpp index 1f9bde042f..58c2f7e372 100644 --- a/Telegram/SourceFiles/stickers/emoji_pan.cpp +++ b/Telegram/SourceFiles/stickers/emoji_pan.cpp @@ -867,7 +867,8 @@ void StickerPanInner::paintInlineItems(Painter &p, const QRect &r) { p.drawText(QRect(0, 0, width(), (height() / 3) * 2 + st::normalFont->height), lang(lng_inline_bot_no_results), style::al_center); return; } - InlineBots::Layout::PaintContext context(getms(), false, Ui::isLayerShown() || Ui::isMediaViewShown() || _previewShown, false); + auto gifPaused = Ui::isLayerShown() || Ui::isMediaViewShown() || _previewShown || !App::wnd()->isActive(); + InlineBots::Layout::PaintContext context(getms(), false, gifPaused, false); int top = st::emojiPanHeader; if (_switchPmButton) { diff --git a/Telegram/SourceFiles/ui/widgets/labels.cpp b/Telegram/SourceFiles/ui/widgets/labels.cpp index 9d93f4aa02..75a099573d 100644 --- a/Telegram/SourceFiles/ui/widgets/labels.cpp +++ b/Telegram/SourceFiles/ui/widgets/labels.cpp @@ -159,30 +159,25 @@ void FlatLabel::init() { connect(&_touchSelectTimer, SIGNAL(timeout()), this, SLOT(onTouchSelect())); } -template -void FlatLabel::setTextByCallback(SetCallback callback) { - callback(); +void FlatLabel::textUpdated() { refreshSize(); setMouseTracking(_selectable || _text.hasLinks()); update(); } void FlatLabel::setText(const QString &text) { - setTextByCallback([this, &text]() { - _text.setText(_st.style, text, _labelOptions); - }); + _text.setText(_st.style, text, _labelOptions); + textUpdated(); } void FlatLabel::setRichText(const QString &text) { - setTextByCallback([this, &text]() { - _text.setRichText(_st.style, text, _labelOptions); - }); + _text.setRichText(_st.style, text, _labelOptions); + textUpdated(); } void FlatLabel::setMarkedText(const TextWithEntities &textWithEntities) { - setTextByCallback([this, &textWithEntities]() { - _text.setMarkedText(_st.style, textWithEntities, _labelMarkedOptions); - }); + _text.setMarkedText(_st.style, textWithEntities, _labelMarkedOptions); + textUpdated(); } void FlatLabel::setSelectable(bool selectable) { diff --git a/Telegram/SourceFiles/ui/widgets/labels.h b/Telegram/SourceFiles/ui/widgets/labels.h index c1726f8bda..0b24db9dd3 100644 --- a/Telegram/SourceFiles/ui/widgets/labels.h +++ b/Telegram/SourceFiles/ui/widgets/labels.h @@ -143,9 +143,7 @@ private slots: private: void init(); - - template - void setTextByCallback(SetCallback callback); + void textUpdated(); Text::StateResult dragActionUpdate(); Text::StateResult dragActionStart(const QPoint &p, Qt::MouseButton button); diff --git a/Telegram/SourceFiles/ui/widgets/popup_menu.cpp b/Telegram/SourceFiles/ui/widgets/popup_menu.cpp index 927c29934b..467ca31fc4 100644 --- a/Telegram/SourceFiles/ui/widgets/popup_menu.cpp +++ b/Telegram/SourceFiles/ui/widgets/popup_menu.cpp @@ -151,8 +151,8 @@ void PopupMenu::handleActivated(QAction *action, int actionTop, TriggeredSource void PopupMenu::handleTriggered(QAction *action, int actionTop, TriggeredSource source) { if (!popupSubmenuFromAction(action, actionTop, source)) { - hideMenu(); _triggering = true; + hideMenu(); emit action->trigger(); _triggering = false; if (_deleteLater) {