diff --git a/Telegram/Resources/icons/call_cancel.png b/Telegram/Resources/icons/call_cancel.png new file mode 100644 index 000000000..607033d0f Binary files /dev/null and b/Telegram/Resources/icons/call_cancel.png differ diff --git a/Telegram/Resources/icons/call_cancel@2x.png b/Telegram/Resources/icons/call_cancel@2x.png new file mode 100644 index 000000000..611f89d36 Binary files /dev/null and b/Telegram/Resources/icons/call_cancel@2x.png differ diff --git a/Telegram/Resources/icons/call_cancel@3x.png b/Telegram/Resources/icons/call_cancel@3x.png new file mode 100644 index 000000000..006886953 Binary files /dev/null and b/Telegram/Resources/icons/call_cancel@3x.png differ diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index 948025114..0af42ccbc 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -84,15 +84,15 @@ callFingerprintTop: 11px; callFingerprintSkip: 3px; callFingerprintBottom: -16px; -callTooltipMutedIcon: icon{{ "calls_mute_tooltip", toastFg }}; -callTooltipMutedIconPosition: point(8px, 4px); -callTooltipPadding: margins(41px, 6px, 15px, 7px); +callTooltipMutedIcon: icon{{ "calls_mute_tooltip", videoPlayIconFg }}; +callTooltipMutedIconPosition: point(10px, 5px); +callTooltipPadding: margins(41px, 7px, 15px, 8px); callButton: IconButton { width: 68px; - height: 68px; + height: 79px; - iconPosition: point(-1px, -1px); + iconPosition: point(-1px, 16px); rippleAreaPosition: point(12px, 12px); rippleAreaSize: 44px; @@ -100,6 +100,11 @@ callButton: IconButton { } callButtonLabel: FlatLabel(defaultFlatLabel) { textFg: callNameFg; + style: TextStyle(defaultTextStyle) { + font: font(11px); + linkFont: font(11px); + linkFontOver: font(11px underline); + } } callAnswer: CallButton { @@ -128,7 +133,7 @@ callHangup: CallButton { } callCancel: CallButton { button: IconButton(callButton) { - icon: icon {{ "box_button_close", callIconFgActive }}; + icon: icon {{ "call_cancel", callIconFgActive }}; ripple: RippleAnimation(defaultRippleAnimation) { color: callIconActiveRipple; } @@ -199,7 +204,12 @@ callStatus: FlatLabel(defaultFlatLabel) { } callRemoteAudioMute: FlatLabel(callStatus) { minWidth: 0px; - textFg: toastFg; + textFg: videoPlayIconFg; + style: TextStyle(defaultTextStyle) { + font: font(12px); + linkFont: font(12px); + linkFontOver: font(12px underline); + } } callRemoteAudioMuteSkip: 12px; diff --git a/Telegram/SourceFiles/calls/calls_panel.cpp b/Telegram/SourceFiles/calls/calls_panel.cpp index 34b7950c8..490040f3c 100644 --- a/Telegram/SourceFiles/calls/calls_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_panel.cpp @@ -60,12 +60,14 @@ constexpr auto kTooltipShowTimeoutMs = 1000; class Panel::Button final : public Ui::RippleButton { public: - Button(QWidget *parent, const style::CallButton &stFrom, const style::CallButton *stTo = nullptr); + Button( + QWidget *parent, + const style::CallButton &stFrom, + const style::CallButton *stTo = nullptr); void setProgress(float64 progress); void setOuterValue(float64 value); - - void setIconOverride(const style::icon *iconOverride); + void setText(rpl::producer text); protected: void paintEvent(QPaintEvent *e) override; @@ -83,7 +85,7 @@ private: const style::CallButton *_stTo = nullptr; float64 _progress = 0.; - const style::icon *_iconOverride = nullptr; + object_ptr _label = { nullptr }; QImage _bgMask, _bg; QPixmap _bgFrom, _bgTo; @@ -94,7 +96,10 @@ private: }; -Panel::Button::Button(QWidget *parent, const style::CallButton &stFrom, const style::CallButton *stTo) +Panel::Button::Button( + QWidget *parent, + const style::CallButton &stFrom, + const style::CallButton *stTo) : Ui::RippleButton(parent, stFrom.button.ripple) , _stFrom(&stFrom) , _stTo(stTo) { @@ -143,9 +148,18 @@ void Panel::Button::setOuterValue(float64 value) { } } -void Panel::Button::setIconOverride(const style::icon *iconOverride) { - _iconOverride = iconOverride; - update(); +void Panel::Button::setText(rpl::producer text) { + _label.create(this, std::move(text), _stFrom->label); + _label->show(); + rpl::combine( + sizeValue(), + _label->sizeValue() + ) | rpl::start_with_next([=](QSize my, QSize label) { + _label->moveToLeft( + (my.width() - label.width()) / 2, + my.height() - label.height(), + my.width()); + }, _label->lifetime()); } void Panel::Button::setProgress(float64 progress) { @@ -201,7 +215,7 @@ void Panel::Button::paintEvent(QPaintEvent *e) { auto positionFrom = iconPosition(_stFrom); if (paintFrom) { - const auto icon = _iconOverride ? _iconOverride : &_stFrom->button.icon; + const auto icon = &_stFrom->button.icon; icon->paint(p, positionFrom, width()); } else { auto positionTo = iconPosition(_stTo); @@ -282,7 +296,9 @@ Panel::Panel(not_null call) , _name(widget(), st::callName) , _status(widget(), st::callStatus) { _decline->setDuration(st::callPanelDuration); + _decline->entity()->setText(tr::lng_call_decline()); _cancel->setDuration(st::callPanelDuration); + _cancel->entity()->setText(tr::lng_call_cancel()); initWindow(); initWidget(); @@ -497,11 +513,18 @@ void Panel::reinitWithCall(Call *call) { _call->mutedValue( ) | rpl::start_with_next([=](bool mute) { _mute->setProgress(mute ? 1. : 0.); + _mute->setText(mute + ? tr::lng_call_unmute_audio() + : tr::lng_call_mute_audio()); }, _callLifetime); _call->videoOutgoing()->stateValue( ) | rpl::start_with_next([=](Webrtc::VideoState state) { - _camera->setProgress((state == Webrtc::VideoState::Active) ? 0. : 1.); + const auto active = (state == Webrtc::VideoState::Active); + _camera->setProgress(active ? 0. : 1.); + _camera->setText(active + ? tr::lng_call_stop_video() + : tr::lng_call_start_video()); }, _callLifetime); _call->stateValue( @@ -569,7 +592,7 @@ void Panel::createRemoteAudioMute() { const auto height = _remoteAudioMute->height(); auto hq = PainterHighQualityEnabler(p); - p.setBrush(st::toastBg); + p.setBrush(st::videoPlayIconBg); p.setPen(Qt::NoPen); p.drawRoundedRect(_remoteAudioMute->rect(), height / 2, height / 2); @@ -986,12 +1009,34 @@ void Panel::stateChanged(State state) { _hangupShown = hangupShown; _hangupShownProgress.start([this] { updateHangupGeometry(); }, _hangupShown ? 0. : 1., _hangupShown ? 1. : 0., st::callPanelDuration, anim::sineInOut); } + const auto answerHangupRedialState = incomingWaiting + ? AnswerHangupRedialState::Answer + : (state == State::Busy) + ? AnswerHangupRedialState::Redial + : AnswerHangupRedialState::Hangup; + if (_answerHangupRedialState != answerHangupRedialState) { + _answerHangupRedialState = answerHangupRedialState; + refreshAnswerHangupRedialLabel(); + } if (_fingerprint.empty() && _call->isKeyShaForFingerprintReady()) { fillFingerprint(); } } } +void Panel::refreshAnswerHangupRedialLabel() { + Expects(_answerHangupRedialState.has_value()); + + _answerHangupRedial->setText([&] { + switch (*_answerHangupRedialState) { + case AnswerHangupRedialState::Answer: return tr::lng_call_accept(); + case AnswerHangupRedialState::Hangup: return tr::lng_call_end_call(); + case AnswerHangupRedialState::Redial: return tr::lng_call_redial(); + } + Unexpected("AnswerHangupRedialState value."); + }()); +} + void Panel::fillFingerprint() { Expects(_call != nullptr); diff --git a/Telegram/SourceFiles/calls/calls_panel.h b/Telegram/SourceFiles/calls/calls_panel.h index c57ca6070..ccdff5791 100644 --- a/Telegram/SourceFiles/calls/calls_panel.h +++ b/Telegram/SourceFiles/calls/calls_panel.h @@ -60,6 +60,11 @@ private: class Button; using State = Call::State; using Type = Call::Type; + enum class AnswerHangupRedialState : uchar { + Answer, + Hangup, + Redial, + }; [[nodiscard]] not_null widget() const; @@ -101,6 +106,7 @@ private: void refreshOutgoingPreviewInBody(State state); void toggleFullScreen(bool fullscreen); void createRemoteAudioMute(); + void refreshAnswerHangupRedialLabel(); [[nodiscard]] QRect incomingFrameGeometry() const; [[nodiscard]] QRect outgoingFrameGeometry() const; @@ -124,6 +130,7 @@ private: object_ptr> _cancel; bool _hangupShown = false; bool _outgoingPreviewInBody = false; + std::optional _answerHangupRedialState; Ui::Animations::Simple _hangupShownProgress; object_ptr