diff --git a/Telegram/Resources/icons/call_rating.png b/Telegram/Resources/icons/call_rating.png new file mode 100644 index 000000000..6e0fdd9aa Binary files /dev/null and b/Telegram/Resources/icons/call_rating.png differ diff --git a/Telegram/Resources/icons/call_rating@2x.png b/Telegram/Resources/icons/call_rating@2x.png new file mode 100644 index 000000000..8a93de55d Binary files /dev/null and b/Telegram/Resources/icons/call_rating@2x.png differ diff --git a/Telegram/Resources/icons/call_rating_filled.png b/Telegram/Resources/icons/call_rating_filled.png new file mode 100644 index 000000000..a7be4cf5d Binary files /dev/null and b/Telegram/Resources/icons/call_rating_filled.png differ diff --git a/Telegram/Resources/icons/call_rating_filled@2x.png b/Telegram/Resources/icons/call_rating_filled@2x.png new file mode 100644 index 000000000..78f2869ea Binary files /dev/null and b/Telegram/Resources/icons/call_rating_filled@2x.png differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 871c9b2e4..084df253e 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1160,6 +1160,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_call_duration_info" = "{time}, {duration}"; "lng_call_type_and_duration" = "{type} ({duration})"; +"lng_call_rate_label" = "Please rate the quality of your call"; +"lng_call_rate_comment" = "Comment (optional)"; + // Not used "lng_topbar_info" = "Info"; diff --git a/Telegram/SourceFiles/boxes/rate_call_box.cpp b/Telegram/SourceFiles/boxes/rate_call_box.cpp new file mode 100644 index 000000000..ac3021cc0 --- /dev/null +++ b/Telegram/SourceFiles/boxes/rate_call_box.cpp @@ -0,0 +1,136 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "boxes/rate_call_box.h" + +#include "lang.h" +#include "styles/style_boxes.h" +#include "styles/style_calls.h" +#include "boxes/confirm_box.h" +#include "ui/widgets/labels.h" +#include "ui/widgets/buttons.h" +#include "ui/widgets/input_fields.h" +#include "mainwindow.h" +#include "mainwidget.h" + +namespace { + +constexpr auto kMaxRating = 5; + +} // namespace + +RateCallBox::RateCallBox(QWidget*, uint64 callId, uint64 callAccessHash) +: _callId(callId) +, _callAccessHash(callAccessHash) +, _label(this, lang(lng_call_rate_label), Ui::FlatLabel::InitType::Simple, st::boxLabel) { +} + +void RateCallBox::prepare() { + addButton(lang(lng_cancel), [this] { closeBox(); }); + + for (auto i = 0; i < kMaxRating; ++i) { + _stars.push_back(object_ptr(this, st::callRatingStar)); + _stars.back()->setClickedCallback([this, value = i + 1] { ratingChanged(value); }); + _stars.back()->show(); + } + + updateMaxHeight(); +} + +void RateCallBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); + + _label->moveToLeft(st::callRatingPadding.left(), st::callRatingPadding.top()); + auto starLeft = st::callRatingPadding.left() + st::callRatingStarLeft; + auto starTop = _label->bottomNoMargins() + st::callRatingStarTop; + for (auto &star : _stars) { + star->moveToLeft(starLeft, starTop); + starLeft += star->width(); + } + if (_comment) { + _comment->moveToLeft(st::callRatingPadding.left(), _stars.back()->bottomNoMargins() + st::callRatingCommentTop); + } +} + +void RateCallBox::ratingChanged(int value) { + Expects(value > 0 && value <= kMaxRating); + if (!_rating) { + clearButtons(); + addButton(lang(lng_send_button), [this] { onSend(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); + } + _rating = value; + + for (auto i = 0; i < kMaxRating; ++i) { + _stars[i]->setIconOverride((i < value) ? &st::callRatingStarFilled : nullptr); + _stars[i]->setRippleColorOverride((i < value) ? &st::lightButtonBgOver : nullptr); + } + if (value < kMaxRating) { + if (!_comment) { + _comment.create(this, st::callRatingComment, lang(lng_call_rate_comment)); + _comment->show(); + _comment->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both); + _comment->setMaxLength(MaxPhotoCaption); + _comment->resize(width() - (st::callRatingPadding.left() + st::callRatingPadding.right()), _comment->height()); + + updateMaxHeight(); + connect(_comment, SIGNAL(resized()), this, SLOT(onCommentResized())); + connect(_comment, SIGNAL(submitted(bool)), this, SLOT(onSend())); + connect(_comment, SIGNAL(cancelled()), this, SLOT(onClose())); + } + _comment->setFocusFast(); + } else if (_comment) { + _comment.destroy(); + updateMaxHeight(); + } +} + +void RateCallBox::setInnerFocus() { + if (_comment) { + _comment->setFocusFast(); + } else { + setFocus(); + } +} + +void RateCallBox::onCommentResized() { + updateMaxHeight(); + update(); +} + +void RateCallBox::onSend() { + Expects(_rating > 0 && _rating <= kMaxRating); + if (_requestId) { + return; + } + auto comment = _comment ? _comment->getLastText().trimmed() : QString(); + _requestId = request(MTPphone_SetCallRating(MTP_inputPhoneCall(MTP_long(_callId), MTP_long(_callAccessHash)), MTP_int(_rating), MTP_string(comment))).done([this](const MTPUpdates &updates) { + App::main()->sentUpdatesReceived(updates); + closeBox(); + }).fail([this](const RPCError &error) { closeBox(); }).send(); +} + +void RateCallBox::updateMaxHeight() { + auto newHeight = st::callRatingPadding.top() + _label->heightNoMargins() + st::callRatingStarTop + _stars.back()->heightNoMargins() + st::callRatingPadding.bottom(); + if (_comment) { + newHeight += st::callRatingCommentTop + _comment->height(); + } + setDimensions(st::boxWidth, newHeight); +} diff --git a/Telegram/SourceFiles/boxes/rate_call_box.h b/Telegram/SourceFiles/boxes/rate_call_box.h new file mode 100644 index 000000000..679ae044d --- /dev/null +++ b/Telegram/SourceFiles/boxes/rate_call_box.h @@ -0,0 +1,65 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "boxes/abstract_box.h" +#include "mtproto/sender.h" + +namespace Ui { +class InputArea; +class FlatLabel; +class IconButton; +} // namespace Ui + +class RateCallBox : public BoxContent, private MTP::Sender { + Q_OBJECT + +public: + RateCallBox(QWidget*, uint64 callId, uint64 callAccessHash); + +private slots: + void onSend(); + void onCommentResized(); + void onClose() { + closeBox(); + } + +protected: + void prepare() override; + void setInnerFocus() override; + + void resizeEvent(QResizeEvent *e) override; + +private: + void updateMaxHeight(); + void ratingChanged(int value); + + uint64 _callId = 0; + uint64 _callAccessHash = 0; + int _rating = 0; + + object_ptr _label; + std::vector> _stars; + object_ptr _comment = { nullptr }; + + mtpRequestId _requestId = 0; + +}; diff --git a/Telegram/SourceFiles/boxes/report_box.cpp b/Telegram/SourceFiles/boxes/report_box.cpp index 8f7d45625..b8eb15f1e 100644 --- a/Telegram/SourceFiles/boxes/report_box.cpp +++ b/Telegram/SourceFiles/boxes/report_box.cpp @@ -71,7 +71,7 @@ void ReportBox::reasonChanged(Reason reason) { _reasonOtherText->resize(width() - (st::boxPadding.left() + st::boxOptionListPadding.left() + st::boxPadding.right()), _reasonOtherText->height()); updateMaxHeight(); - connect(_reasonOtherText, SIGNAL(resized()), this, SLOT(onDescriptionResized())); + connect(_reasonOtherText, SIGNAL(resized()), this, SLOT(onReasonResized())); connect(_reasonOtherText, SIGNAL(submitted(bool)), this, SLOT(onReport())); connect(_reasonOtherText, SIGNAL(cancelled()), this, SLOT(onClose())); } @@ -90,7 +90,7 @@ void ReportBox::setInnerFocus() { } } -void ReportBox::onDescriptionResized() { +void ReportBox::onReasonResized() { updateMaxHeight(); update(); } diff --git a/Telegram/SourceFiles/boxes/report_box.h b/Telegram/SourceFiles/boxes/report_box.h index 7f224a737..9d588179a 100644 --- a/Telegram/SourceFiles/boxes/report_box.h +++ b/Telegram/SourceFiles/boxes/report_box.h @@ -38,7 +38,7 @@ public: private slots: void onReport(); - void onDescriptionResized(); + void onReasonResized(); void onClose() { closeBox(); } diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index e29a08c4e..a3b027629 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -161,3 +161,26 @@ callReDial: IconButton { rippleAreaPosition: point(0px, 8px); rippleAreaSize: 40px; } + +callRatingPadding: margins(24px, 26px, 24px, 8px); +callRatingStar: IconButton { + width: 36px; + height: 36px; + + icon: icon {{ "call_rating", windowSubTextFg }}; + iconPosition: point(-1px, -1px); + + ripple: RippleAnimation(defaultRippleAnimation) { + color: windowBgOver; + } + rippleAreaPosition: point(0px, 0px); + rippleAreaSize: 36px; +} +callRatingStarFilled: icon {{ "call_rating_filled", lightButtonFg }}; +callRatingStarLeft: -7px; +callRatingStarTop: 6px; +callRatingComment: InputField(defaultInputField) { + textMargins: margins(1px, 26px, 1px, 4px); + heightMax: 135px; +} +callRatingCommentTop: 2px; diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp index 08d2f098e..6c94e154b 100644 --- a/Telegram/SourceFiles/calls/calls_call.cpp +++ b/Telegram/SourceFiles/calls/calls_call.cpp @@ -24,6 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "mainwidget.h" #include "lang.h" #include "boxes/confirm_box.h" +#include "boxes/rate_call_box.h" #include "calls/calls_instance.h" #include "base/openssl_help.h" #include "mtproto/connection.h" @@ -301,6 +302,9 @@ bool Call::handleUpdate(const MTPPhoneCall &call) { MTP::send(MTPphone_SaveCallDebug(MTP_inputPhoneCall(MTP_long(_id), MTP_long(_accessHash)), MTP_dataJSON(MTP_string(debugLog)))); } } + if (data.is_need_rating() && _id && _accessHash) { + Ui::show(Box(_id, _accessHash)); + } if (data.has_reason() && data.vreason.type() == mtpc_phoneCallDiscardReasonDisconnect) { LOG(("Call Info: Discarded with DISCONNECT reason.")); } diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index 220434176..b453b2d79 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -29,6 +29,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "calls/calls_call.h" #include "calls/calls_panel.h" + +#include "boxes/rate_call_box.h" namespace Calls { namespace { diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 2bf7463b2..fed4836d7 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -64,6 +64,8 @@ <(src_loc)/boxes/passcode_box.h <(src_loc)/boxes/photo_crop_box.cpp <(src_loc)/boxes/photo_crop_box.h +<(src_loc)/boxes/rate_call_box.cpp +<(src_loc)/boxes/rate_call_box.h <(src_loc)/boxes/report_box.cpp <(src_loc)/boxes/report_box.h <(src_loc)/boxes/self_destruction_box.cpp