Add labels to call buttons.

This commit is contained in:
John Preston 2020-08-14 14:54:15 +04:00
parent 1b60829da8
commit 1aaf7df54a
8 changed files with 96 additions and 21 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 B

View file

@ -84,15 +84,15 @@ callFingerprintTop: 11px;
callFingerprintSkip: 3px; callFingerprintSkip: 3px;
callFingerprintBottom: -16px; callFingerprintBottom: -16px;
callTooltipMutedIcon: icon{{ "calls_mute_tooltip", toastFg }}; callTooltipMutedIcon: icon{{ "calls_mute_tooltip", videoPlayIconFg }};
callTooltipMutedIconPosition: point(8px, 4px); callTooltipMutedIconPosition: point(10px, 5px);
callTooltipPadding: margins(41px, 6px, 15px, 7px); callTooltipPadding: margins(41px, 7px, 15px, 8px);
callButton: IconButton { callButton: IconButton {
width: 68px; width: 68px;
height: 68px; height: 79px;
iconPosition: point(-1px, -1px); iconPosition: point(-1px, 16px);
rippleAreaPosition: point(12px, 12px); rippleAreaPosition: point(12px, 12px);
rippleAreaSize: 44px; rippleAreaSize: 44px;
@ -100,6 +100,11 @@ callButton: IconButton {
} }
callButtonLabel: FlatLabel(defaultFlatLabel) { callButtonLabel: FlatLabel(defaultFlatLabel) {
textFg: callNameFg; textFg: callNameFg;
style: TextStyle(defaultTextStyle) {
font: font(11px);
linkFont: font(11px);
linkFontOver: font(11px underline);
}
} }
callAnswer: CallButton { callAnswer: CallButton {
@ -128,7 +133,7 @@ callHangup: CallButton {
} }
callCancel: CallButton { callCancel: CallButton {
button: IconButton(callButton) { button: IconButton(callButton) {
icon: icon {{ "box_button_close", callIconFgActive }}; icon: icon {{ "call_cancel", callIconFgActive }};
ripple: RippleAnimation(defaultRippleAnimation) { ripple: RippleAnimation(defaultRippleAnimation) {
color: callIconActiveRipple; color: callIconActiveRipple;
} }
@ -199,7 +204,12 @@ callStatus: FlatLabel(defaultFlatLabel) {
} }
callRemoteAudioMute: FlatLabel(callStatus) { callRemoteAudioMute: FlatLabel(callStatus) {
minWidth: 0px; minWidth: 0px;
textFg: toastFg; textFg: videoPlayIconFg;
style: TextStyle(defaultTextStyle) {
font: font(12px);
linkFont: font(12px);
linkFontOver: font(12px underline);
}
} }
callRemoteAudioMuteSkip: 12px; callRemoteAudioMuteSkip: 12px;

View file

@ -60,12 +60,14 @@ constexpr auto kTooltipShowTimeoutMs = 1000;
class Panel::Button final : public Ui::RippleButton { class Panel::Button final : public Ui::RippleButton {
public: 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 setProgress(float64 progress);
void setOuterValue(float64 value); void setOuterValue(float64 value);
void setText(rpl::producer<QString> text);
void setIconOverride(const style::icon *iconOverride);
protected: protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
@ -83,7 +85,7 @@ private:
const style::CallButton *_stTo = nullptr; const style::CallButton *_stTo = nullptr;
float64 _progress = 0.; float64 _progress = 0.;
const style::icon *_iconOverride = nullptr; object_ptr<Ui::FlatLabel> _label = { nullptr };
QImage _bgMask, _bg; QImage _bgMask, _bg;
QPixmap _bgFrom, _bgTo; 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) : Ui::RippleButton(parent, stFrom.button.ripple)
, _stFrom(&stFrom) , _stFrom(&stFrom)
, _stTo(stTo) { , _stTo(stTo) {
@ -143,9 +148,18 @@ void Panel::Button::setOuterValue(float64 value) {
} }
} }
void Panel::Button::setIconOverride(const style::icon *iconOverride) { void Panel::Button::setText(rpl::producer<QString> text) {
_iconOverride = iconOverride; _label.create(this, std::move(text), _stFrom->label);
update(); _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) { void Panel::Button::setProgress(float64 progress) {
@ -201,7 +215,7 @@ void Panel::Button::paintEvent(QPaintEvent *e) {
auto positionFrom = iconPosition(_stFrom); auto positionFrom = iconPosition(_stFrom);
if (paintFrom) { if (paintFrom) {
const auto icon = _iconOverride ? _iconOverride : &_stFrom->button.icon; const auto icon = &_stFrom->button.icon;
icon->paint(p, positionFrom, width()); icon->paint(p, positionFrom, width());
} else { } else {
auto positionTo = iconPosition(_stTo); auto positionTo = iconPosition(_stTo);
@ -282,7 +296,9 @@ Panel::Panel(not_null<Call*> call)
, _name(widget(), st::callName) , _name(widget(), st::callName)
, _status(widget(), st::callStatus) { , _status(widget(), st::callStatus) {
_decline->setDuration(st::callPanelDuration); _decline->setDuration(st::callPanelDuration);
_decline->entity()->setText(tr::lng_call_decline());
_cancel->setDuration(st::callPanelDuration); _cancel->setDuration(st::callPanelDuration);
_cancel->entity()->setText(tr::lng_call_cancel());
initWindow(); initWindow();
initWidget(); initWidget();
@ -497,11 +513,18 @@ void Panel::reinitWithCall(Call *call) {
_call->mutedValue( _call->mutedValue(
) | rpl::start_with_next([=](bool mute) { ) | rpl::start_with_next([=](bool mute) {
_mute->setProgress(mute ? 1. : 0.); _mute->setProgress(mute ? 1. : 0.);
_mute->setText(mute
? tr::lng_call_unmute_audio()
: tr::lng_call_mute_audio());
}, _callLifetime); }, _callLifetime);
_call->videoOutgoing()->stateValue( _call->videoOutgoing()->stateValue(
) | rpl::start_with_next([=](Webrtc::VideoState state) { ) | 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); }, _callLifetime);
_call->stateValue( _call->stateValue(
@ -569,7 +592,7 @@ void Panel::createRemoteAudioMute() {
const auto height = _remoteAudioMute->height(); const auto height = _remoteAudioMute->height();
auto hq = PainterHighQualityEnabler(p); auto hq = PainterHighQualityEnabler(p);
p.setBrush(st::toastBg); p.setBrush(st::videoPlayIconBg);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.drawRoundedRect(_remoteAudioMute->rect(), height / 2, height / 2); p.drawRoundedRect(_remoteAudioMute->rect(), height / 2, height / 2);
@ -986,12 +1009,34 @@ void Panel::stateChanged(State state) {
_hangupShown = hangupShown; _hangupShown = hangupShown;
_hangupShownProgress.start([this] { updateHangupGeometry(); }, _hangupShown ? 0. : 1., _hangupShown ? 1. : 0., st::callPanelDuration, anim::sineInOut); _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()) { if (_fingerprint.empty() && _call->isKeyShaForFingerprintReady()) {
fillFingerprint(); 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() { void Panel::fillFingerprint() {
Expects(_call != nullptr); Expects(_call != nullptr);

View file

@ -60,6 +60,11 @@ private:
class Button; class Button;
using State = Call::State; using State = Call::State;
using Type = Call::Type; using Type = Call::Type;
enum class AnswerHangupRedialState : uchar {
Answer,
Hangup,
Redial,
};
[[nodiscard]] not_null<Ui::RpWidget*> widget() const; [[nodiscard]] not_null<Ui::RpWidget*> widget() const;
@ -101,6 +106,7 @@ private:
void refreshOutgoingPreviewInBody(State state); void refreshOutgoingPreviewInBody(State state);
void toggleFullScreen(bool fullscreen); void toggleFullScreen(bool fullscreen);
void createRemoteAudioMute(); void createRemoteAudioMute();
void refreshAnswerHangupRedialLabel();
[[nodiscard]] QRect incomingFrameGeometry() const; [[nodiscard]] QRect incomingFrameGeometry() const;
[[nodiscard]] QRect outgoingFrameGeometry() const; [[nodiscard]] QRect outgoingFrameGeometry() const;
@ -124,6 +130,7 @@ private:
object_ptr<Ui::FadeWrap<Button>> _cancel; object_ptr<Ui::FadeWrap<Button>> _cancel;
bool _hangupShown = false; bool _hangupShown = false;
bool _outgoingPreviewInBody = false; bool _outgoingPreviewInBody = false;
std::optional<AnswerHangupRedialState> _answerHangupRedialState;
Ui::Animations::Simple _hangupShownProgress; Ui::Animations::Simple _hangupShownProgress;
object_ptr<Button> _camera; object_ptr<Button> _camera;
object_ptr<Button> _mute; object_ptr<Button> _mute;

View file

@ -107,6 +107,19 @@ void WrapInvokeAfter(
} }
} }
[[nodiscard]] bool ConstTimeIsDifferent(
const void *a,
const void *b,
size_t size) {
auto ca = reinterpret_cast<const char*>(a);
auto cb = reinterpret_cast<const char*>(b);
volatile auto different = false;
for (const auto ce = ca + size; ca != ce; ++ca, ++cb) {
different |= (*ca != *cb);
}
return different;
}
} // namespace } // namespace
SessionPrivate::SessionPrivate( SessionPrivate::SessionPrivate(
@ -1247,7 +1260,7 @@ void SessionPrivate::handleReceived() {
auto sha1ForMsgKeyCheck = hashSha1(decryptedInts, hashedDataLength); auto sha1ForMsgKeyCheck = hashSha1(decryptedInts, hashedDataLength);
constexpr auto kMsgKeyShift_oldmtp = 4U; constexpr auto kMsgKeyShift_oldmtp = 4U;
if (memcmp(&msgKey, sha1ForMsgKeyCheck.data() + kMsgKeyShift_oldmtp, sizeof(msgKey)) != 0) { if (ConstTimeIsDifferent(&msgKey, sha1ForMsgKeyCheck.data() + kMsgKeyShift_oldmtp, sizeof(msgKey))) {
LOG(("TCP Error: bad SHA1 hash after aesDecrypt in message.")); LOG(("TCP Error: bad SHA1 hash after aesDecrypt in message."));
TCP_LOG(("TCP Error: bad message %1").arg(Logs::mb(encryptedInts, encryptedBytesCount).str())); TCP_LOG(("TCP Error: bad message %1").arg(Logs::mb(encryptedInts, encryptedBytesCount).str()));
@ -1267,7 +1280,7 @@ void SessionPrivate::handleReceived() {
SHA256_Final(sha256Buffer.data(), &msgKeyLargeContext); SHA256_Final(sha256Buffer.data(), &msgKeyLargeContext);
constexpr auto kMsgKeyShift = 8U; constexpr auto kMsgKeyShift = 8U;
if (memcmp(&msgKey, sha256Buffer.data() + kMsgKeyShift, sizeof(msgKey)) != 0) { if (ConstTimeIsDifferent(&msgKey, sha256Buffer.data() + kMsgKeyShift, sizeof(msgKey))) {
LOG(("TCP Error: bad SHA256 hash after aesDecrypt in message")); LOG(("TCP Error: bad SHA256 hash after aesDecrypt in message"));
TCP_LOG(("TCP Error: bad message %1").arg(Logs::mb(encryptedInts, encryptedBytesCount).str())); TCP_LOG(("TCP Error: bad message %1").arg(Logs::mb(encryptedInts, encryptedBytesCount).str()));

@ -1 +1 @@
Subproject commit 2850efa0015dc4e6bbd541c0a072497477d75940 Subproject commit 160c1046c18bcf91fc212d9ea042889437189bac