From af4b3ba023a852de78cefe39185723ad29582aa1 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 21 Jun 2016 18:58:07 +0300 Subject: [PATCH] Shutdown on Linux fix attempt. Draft remove in empty conversation fix. Larger badge of unread messages in history-to-down button. Submit bot-start by Enter. Fix icons show in chat without input field. --- Telegram/SourceFiles/app.cpp | 4 +- Telegram/SourceFiles/data/data_drafts.cpp | 2 - .../SourceFiles/dialogs/dialogs_layout.cpp | 79 ++++++++++++------- Telegram/SourceFiles/dialogs/dialogs_layout.h | 19 ++++- Telegram/SourceFiles/history.cpp | 18 +++-- Telegram/SourceFiles/history/history.style | 2 + Telegram/SourceFiles/historywidget.cpp | 25 ++++-- Telegram/SourceFiles/historywidget.h | 1 + Telegram/SourceFiles/mainwindow.cpp | 9 ++- .../ui/buttons/history_down_button.cpp | 9 ++- Telegram/Telegram.vcxproj | 10 +++ Telegram/Telegram.vcxproj.filters | 6 ++ 12 files changed, 137 insertions(+), 47 deletions(-) diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index b689de5796..be6c451c4d 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -2288,7 +2288,9 @@ namespace { setLaunchState(QuitRequested); if (auto window = wnd()) { - window->hide(); + if (!Sandbox::isSavingSession()) { + window->hide(); + } } if (auto mainwidget = main()) { mainwidget->saveDraftToCloud(); diff --git a/Telegram/SourceFiles/data/data_drafts.cpp b/Telegram/SourceFiles/data/data_drafts.cpp index 8d33956b96..6179e45b25 100644 --- a/Telegram/SourceFiles/data/data_drafts.cpp +++ b/Telegram/SourceFiles/data/data_drafts.cpp @@ -42,7 +42,6 @@ void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) { history->setCloudDraft(std_::move(cloudDraft)); history->createLocalDraftFromCloud(); history->updateChatListSortPosition(); - history->updateChatListEntry(); if (auto main = App::main()) { main->applyCloudDraft(history); @@ -56,7 +55,6 @@ void clearPeerCloudDraft(PeerId peerId) { history->clearLocalDraft(); history->updateChatListSortPosition(); - history->updateChatListEntry(); if (auto main = App::main()) { main->applyCloudDraft(history); diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp index 9577393dec..0d568a8203 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp @@ -140,59 +140,78 @@ void paintRow(Painter &p, History *history, HistoryItem *item, Data::Draft *draf history->peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); } -class UnreadBadgeStyleData : public Data::AbstractStructure { -public: +struct UnreadBadgeSizeData { QImage circle; QPixmap left[4], right[4]; +}; +class UnreadBadgeStyleData : public Data::AbstractStructure { +public: + UnreadBadgeSizeData sizes[UnreadBadgeSizesCount]; style::color bg[4] = { st::dialogsUnreadBg, st::dialogsUnreadBgActive, st::dialogsUnreadBgMuted, st::dialogsUnreadBgMutedActive }; }; Data::GlobalStructurePointer unreadBadgeStyle; -void createCircleMask(int size) { - if (!unreadBadgeStyle->circle.isNull()) return; +void createCircleMask(UnreadBadgeSizeData *data, int size) { + if (!data->circle.isNull()) return; - unreadBadgeStyle->circle = style::createCircleMask(size); + data->circle = style::createCircleMask(size); } -QImage colorizeCircleHalf(int size, int half, int xoffset, style::color color) { - auto result = style::colorizeImage(unreadBadgeStyle->circle, color, QRect(xoffset, 0, half, size)); +QImage colorizeCircleHalf(UnreadBadgeSizeData *data, int size, int half, int xoffset, style::color color) { + auto result = style::colorizeImage(data->circle, color, QRect(xoffset, 0, half, size)); result.setDevicePixelRatio(cRetinaFactor()); return result; } } // namepsace -void paintUnreadBadge(Painter &p, const QRect &rect, bool active, bool muted) { - int index = (active ? 0x01 : 0x00) | (muted ? 0x02 : 0x00); - int size = rect.height(), sizehalf = size / 2; +void paintUnreadBadge(Painter &p, const QRect &rect, const UnreadBadgeStyle &st) { + t_assert(rect.height() == st.size); + + int index = (st.active ? 0x01 : 0x00) | (st.muted ? 0x02 : 0x00); + int size = st.size, sizehalf = size / 2; unreadBadgeStyle.createIfNull(); + auto badgeData = unreadBadgeStyle->sizes; + if (st.sizeId > 0) { + t_assert(st.sizeId < UnreadBadgeSizesCount); + badgeData = &unreadBadgeStyle->sizes[st.sizeId]; + } style::color bg = unreadBadgeStyle->bg[index]; - if (unreadBadgeStyle->left[index].isNull()) { + if (badgeData->left[index].isNull()) { int imgsize = size * cIntRetinaFactor(), imgsizehalf = sizehalf * cIntRetinaFactor(); - createCircleMask(size); - unreadBadgeStyle->left[index] = App::pixmapFromImageInPlace(colorizeCircleHalf(imgsize, imgsizehalf, 0, bg)); - unreadBadgeStyle->right[index] = App::pixmapFromImageInPlace(colorizeCircleHalf(imgsize, imgsizehalf, imgsize - imgsizehalf, bg)); + createCircleMask(badgeData, size); + badgeData->left[index] = App::pixmapFromImageInPlace(colorizeCircleHalf(badgeData, imgsize, imgsizehalf, 0, bg)); + badgeData->right[index] = App::pixmapFromImageInPlace(colorizeCircleHalf(badgeData, imgsize, imgsizehalf, imgsize - imgsizehalf, bg)); } int bar = rect.width() - 2 * sizehalf; - p.drawPixmap(rect.x(), rect.y(), unreadBadgeStyle->left[index]); + p.drawPixmap(rect.x(), rect.y(), badgeData->left[index]); if (bar) { p.fillRect(rect.x() + sizehalf, rect.y(), bar, rect.height(), bg); } - p.drawPixmap(rect.x() + sizehalf + bar, rect.y(), unreadBadgeStyle->right[index]); + p.drawPixmap(rect.x() + sizehalf + bar, rect.y(), badgeData->right[index]); } -void paintUnreadCount(Painter &p, const QString &text, int x, int y, style::align align, bool active, bool muted, int *outUnreadWidth) { - int unreadWidth = st::dialogsUnreadFont->width(text); +UnreadBadgeStyle::UnreadBadgeStyle() +: align(style::al_right) +, active(false) +, muted(false) +, size(st::dialogsUnreadHeight) +, sizeId(UnreadBadgeInDialogs) +, font(st::dialogsUnreadFont) { +} + +void paintUnreadCount(Painter &p, const QString &text, int x, int y, const UnreadBadgeStyle &st, int *outUnreadWidth) { + int unreadWidth = st.font->width(text); int unreadRectWidth = unreadWidth + 2 * st::dialogsUnreadPadding; - int unreadRectHeight = st::dialogsUnreadHeight; + int unreadRectHeight = st.size; accumulate_max(unreadRectWidth, unreadRectHeight); int unreadRectLeft = x; - if ((align & Qt::AlignHorizontal_Mask) & style::al_center) { + if ((st.align & Qt::AlignHorizontal_Mask) & style::al_center) { unreadRectLeft = (x - unreadRectWidth) / 2; - } else if ((align & Qt::AlignHorizontal_Mask) & style::al_right) { + } else if ((st.align & Qt::AlignHorizontal_Mask) & style::al_right) { unreadRectLeft = x - unreadRectWidth; } int unreadRectTop = y; @@ -200,11 +219,11 @@ void paintUnreadCount(Painter &p, const QString &text, int x, int y, style::alig *outUnreadWidth = unreadRectWidth; } - paintUnreadBadge(p, QRect(unreadRectLeft, unreadRectTop, unreadRectWidth, unreadRectHeight), active, muted); + paintUnreadBadge(p, QRect(unreadRectLeft, unreadRectTop, unreadRectWidth, unreadRectHeight), st); - p.setFont(st::dialogsUnreadFont); - p.setPen(active ? st::dialogsUnreadFgActive : st::dialogsUnreadFg); - p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + st::dialogsUnreadTop + st::dialogsUnreadFont->ascent, text); + p.setFont(st.font); + p.setPen(st.active ? st::dialogsUnreadFgActive : st::dialogsUnreadFg); + p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + st::dialogsUnreadTop + st.font->ascent, text); } void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool selected, bool onlyBackground) { @@ -242,7 +261,11 @@ void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool sele int unreadRight = w - st::dialogsPadding.x(); int unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - st::dialogsUnreadTop; int unreadWidth = 0; - paintUnreadCount(p, counter, unreadRight, unreadTop, style::al_right, active, mutedCounter, &unreadWidth); + + UnreadBadgeStyle st; + st.active = active; + st.muted = history->mute(); + paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth); availableWidth -= unreadWidth + st::dialogsUnreadPadding; } if (history->typing.isEmpty() && history->sendActions.isEmpty()) { @@ -281,7 +304,9 @@ void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool o if (mutedHidden) { if (int32 unread = App::histories().unreadMutedCount()) { int unreadRight = w - st::dialogsPadding.x(); - paintUnreadCount(p, QString::number(unread), unreadRight, unreadTop, style::al_right, false, true, nullptr); + UnreadBadgeStyle st; + st.muted = true; + paintUnreadCount(p, QString::number(unread), unreadRight, unreadTop, st, nullptr); } } } diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.h b/Telegram/SourceFiles/dialogs/dialogs_layout.h index 985d0c7d97..b0e5bd8b10 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.h +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.h @@ -35,8 +35,23 @@ public: void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool onlyBackground); -void paintUnreadCount(Painter &p, const QString &text, int x, int y, style::align align, bool active, bool muted, int *outUnreadWidth); -void paintUnreadBadge(Painter &p, const QRect &rect, bool active, bool muted); +enum UnreadBadgeSize { + UnreadBadgeInDialogs = 0, + UnreadBadgeInHistoryToDown, + + UnreadBadgeSizesCount +}; +struct UnreadBadgeStyle { + UnreadBadgeStyle(); + + style::align align; + bool active; + bool muted; + int size; + UnreadBadgeSize sizeId; + style::font font; +}; +void paintUnreadCount(Painter &p, const QString &text, int x, int y, const UnreadBadgeStyle &st, int *outUnreadWidth = nullptr); } // namespace Layout } // namespace Dialogs diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 0dcb4a9f4b..950eab39dc 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -230,7 +230,6 @@ Data::Draft *History::createCloudDraft(Data::Draft *fromDraft) { cloudDraftTextCache.clear(); updateChatListSortPosition(); - updateChatListEntry(); return cloudDraft(); } @@ -248,7 +247,6 @@ void History::clearCloudDraft() { _cloudDraft = nullptr; cloudDraftTextCache.clear(); updateChatListSortPosition(); - updateChatListEntry(); } } @@ -1759,6 +1757,7 @@ namespace { } inline uint64 dialogPosFromDate(const QDateTime &date) { + if (date.isNull()) return 0; return (uint64(date.toTime_t()) << 32) | (++_dialogsPosToTopShift); } @@ -1769,8 +1768,8 @@ void History::setLastMessage(HistoryItem *msg) { setChatsListDate(msg->date); } else { lastMsg = 0; + updateChatListEntry(); } - updateChatListEntry(); } bool History::needUpdateInChatList() const { @@ -1796,7 +1795,7 @@ void History::setChatsListDate(const QDateTime &date) { void History::updateChatListSortPosition() { auto chatListDate = [this]() { if (auto draft = cloudDraft()) { - if (draft->date > lastMsgDate) { + if (!Data::draftIsNull(draft) && draft->date > lastMsgDate) { return draft->date; } } @@ -1804,8 +1803,15 @@ void History::updateChatListSortPosition() { }; _sortKeyInChatList = dialogPosFromDate(chatListDate()); - if (App::main() && needUpdateInChatList()) { - App::main()->createDialog(this); + if (auto m = App::main()) { + if (needUpdateInChatList()) { + if (_sortKeyInChatList) { + m->createDialog(this); + updateChatListEntry(); + } else { + m->deleteConversation(peer, false); + } + } } } diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index 9ab0bd79fd..59a20ef439 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -42,3 +42,5 @@ membersInnerDropdown: InnerDropdown(defaultInnerDropdown) { scrollMargin: margins(0px, 5px, 0px, 5px); scrollPadding: margins(0px, 3px, 8px, 3px); } +historyToDownBadgeFont: semiboldFont; +historyToDownBadgeSize: 22px; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 23b4567a2f..655465aaa2 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -1477,6 +1477,10 @@ void HistoryInner::keyPressEvent(QKeyEvent *e) { if (!_selected.isEmpty() && selectedForDelete == selectedForForward) { _widget->onDeleteSelected(); } + } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { + if (_selected.isEmpty()) { + _widget->onListEnterPressed(); + } } else { e->ignore(); } @@ -5863,10 +5867,13 @@ void HistoryWidget::onFilesDrop(const QMimeData *data) { } void HistoryWidget::onKbToggle(bool manual) { + auto fieldEnabled = canWriteMessage(); if (_kbShown || _kbReplyTo) { _kbHide.hide(); if (_kbShown) { - _kbShow.show(); + if (fieldEnabled) { + _kbShow.show(); + } if (manual && _history) { _history->lastKeyboardHiddenId = _keyboard.forMsgId().msg; } @@ -5890,14 +5897,16 @@ void HistoryWidget::onKbToggle(bool manual) { } else if (!_keyboard.hasMarkup() && _keyboard.forceReply()) { _kbHide.hide(); _kbShow.hide(); - _cmdStart.show(); + if (fieldEnabled) { + _cmdStart.show(); + } _kbScroll.hide(); _kbShown = false; _field.setMaxHeight(st::maxFieldHeight); _kbReplyTo = (_peer->isChat() || _peer->isChannel() || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0; - if (_kbReplyTo && !_editMsgId && !_replyToId) { + if (_kbReplyTo && !_editMsgId && !_replyToId && fieldEnabled) { updateReplyToName(); _replyEditMsgText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions); _fieldBarCancel.show(); @@ -5906,7 +5915,7 @@ void HistoryWidget::onKbToggle(bool manual) { if (manual && _history) { _history->lastKeyboardHiddenId = 0; } - } else { + } else if (fieldEnabled) { _kbHide.show(); _kbShow.hide(); _kbScroll.show(); @@ -5927,7 +5936,7 @@ void HistoryWidget::onKbToggle(bool manual) { } } resizeEvent(0); - if (_kbHide.isHidden()) { + if (_kbHide.isHidden() && canWriteMessage()) { _attachEmoji.show(); } else { _attachEmoji.hide(); @@ -8072,6 +8081,12 @@ void HistoryWidget::onListEscapePressed() { } } +void HistoryWidget::onListEnterPressed() { + if (!_botStart.isHidden()) { + onBotStart(); + } +} + void HistoryWidget::onClearSelected() { if (_list) _list->clearSelectedItems(); } diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index 92f077fa1c..a79a71e52f 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -651,6 +651,7 @@ public: void stopRecording(bool send); void onListEscapePressed(); + void onListEnterPressed(); void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo); bool insertBotCommand(const QString &cmd, bool specialGif); diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 35ed14b870..8f7652acab 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -1285,9 +1285,14 @@ void MainWindow::toggleDisplayNotifyFromTray() { } void MainWindow::closeEvent(QCloseEvent *e) { - e->ignore(); - if (!MTP::authedId() || Sandbox::isSavingSession() || !Ui::hideWindowNoQuit()) { + if (Sandbox::isSavingSession()) { + e->accept(); App::quit(); + } else { + e->ignore(); + if (!MTP::authedId() || !Ui::hideWindowNoQuit()) { + App::quit(); + } } } diff --git a/Telegram/SourceFiles/ui/buttons/history_down_button.cpp b/Telegram/SourceFiles/ui/buttons/history_down_button.cpp index 409091755c..2b1fd86e98 100644 --- a/Telegram/SourceFiles/ui/buttons/history_down_button.cpp +++ b/Telegram/SourceFiles/ui/buttons/history_down_button.cpp @@ -68,12 +68,17 @@ void HistoryDownButton::paintEvent(QPaintEvent *e) { st::historyToDownArrow.paint(p, QPoint(0, st::historyToDownPaddingTop), width()); if (_unreadCount > 0) { p.setOpacity(opacity); - bool active = false, muted = false; auto unreadString = QString::number(_unreadCount); if (unreadString.size() > 4) { unreadString = qsl("..") + unreadString.mid(unreadString.size() - 4); } - Dialogs::Layout::paintUnreadCount(p, unreadString, width(), 0, style::al_center, active, muted, nullptr); + + Dialogs::Layout::UnreadBadgeStyle st; + st.align = style::al_center; + st.font = st::historyToDownBadgeFont; + st.size = st::historyToDownBadgeSize; + st.sizeId = Dialogs::Layout::UnreadBadgeInHistoryToDown; + Dialogs::Layout::paintUnreadCount(p, unreadString, width(), 0, st, nullptr); } } diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj index 9e96d89113..5b8fc9a823 100644 --- a/Telegram/Telegram.vcxproj +++ b/Telegram/Telegram.vcxproj @@ -1268,6 +1268,11 @@ + + true + true + true + true true @@ -1726,6 +1731,11 @@ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/platform/linux/main_window_linux.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore\5.6.0\QtCore" "-I$(QTDIR)\include\QtGui\5.6.0\QtGui" "-I.\..\..\Libraries\breakpad\src" "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\ThirdParty\minizip" "-I.\..\..\Libraries\openssl\Release\include" + + true + true + true + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath) diff --git a/Telegram/Telegram.vcxproj.filters b/Telegram/Telegram.vcxproj.filters index 131db69070..2d1a1f3934 100644 --- a/Telegram/Telegram.vcxproj.filters +++ b/Telegram/Telegram.vcxproj.filters @@ -1341,6 +1341,9 @@ GeneratedFiles\Release + + SourceFiles\platform\linux + @@ -1589,6 +1592,9 @@ SourceFiles\platform\winrt + + SourceFiles\platform\linux +