Add call top bar above the media player.

This commit is contained in:
John Preston 2017-04-25 23:36:04 +03:00
parent 60ac7572af
commit f6eb2c5205
17 changed files with 413 additions and 30 deletions

View File

@ -229,6 +229,9 @@ dialogsUnreadBgActive: dialogsTextFgActive; // chat list unread badge background
dialogsUnreadBgMutedActive: dialogsDraftFgActive; // chat list unread badge background for muted chat for current (active) chat
dialogsUnreadFgActive: dialogsBgActive; // chat list unread badge text for current (active) chat
dialogsRippleBg: windowBgRipple;
dialogsRippleBgActive: activeButtonBgRipple;
dialogsForwardBg: dialogsBgActive; // forwarding panel background (when forwarding messages in the smallest window size)
dialogsForwardFg: dialogsNameFgActive; // forwarding panel text (when forwarding messages in the smallest window size)
@ -519,3 +522,9 @@ callAnswerRipple: #52b149;
callHangupBg: #d75a5a;
callHangupRipple: #c04646;
callMuteRipple: #ffffff12;
callBarBg: dialogsBgActive;
callBarMuteRipple: dialogsRippleBgActive;
callBarBgMuted: #8f8f8f | dialogsUnreadBgMuted;
callBarUnmuteRipple: #7f7f7f | shadowFg;
callBarFg: dialogsNameFgActive;

View File

@ -1134,6 +1134,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_call_status_ringing" = "ringing...";
"lng_call_status_busy" = "line busy";
"lng_call_bar_info" = "Show call info";
"lng_call_bar_hangup" = "End call";
// Not used
"lng_topbar_info" = "Info";

View File

@ -85,6 +85,26 @@ private:
};
template <typename T>
inline bool operator==(const weak_unique_ptr<T> &pointer, std::nullptr_t) {
return (pointer.get() == nullptr);
}
template <typename T>
inline bool operator==(std::nullptr_t, const weak_unique_ptr<T> &pointer) {
return (pointer == nullptr);
}
template <typename T>
inline bool operator!=(const weak_unique_ptr<T> &pointer, std::nullptr_t) {
return !(pointer == nullptr);
}
template <typename T>
inline bool operator!=(std::nullptr_t, const weak_unique_ptr<T> &pointer) {
return !(pointer == nullptr);
}
} // namespace base
#ifdef QT_VERSION

View File

@ -107,3 +107,30 @@ callStatus: FlatLabel(defaultFlatLabel) {
callFingerprintPadding: margins(9px, 4px, 9px, 5px);
callFingerprintSkip: 3px;
callFingerprintBottom: 8px;
callBarHeight: 38px;
callBarMuteToggle: IconButton {
width: 41px;
height: 38px;
icon: icon {{ "call_record_active", callBarFg }};
iconPosition: point(9px, 8px);
ripple: RippleAnimation(defaultRippleAnimation) {
color: callBarMuteRipple;
}
rippleAreaPosition: point(5px, 3px);
rippleAreaSize: 32px;
}
callBarUnmuteIcon: icon {{ "call_record_muted", callBarFg }};
callBarRightSkip: 12px;
callBarSkip: 10px;
callBarHangup: IconButton(callBarMuteToggle) {
icon: icon {{ "call_discard", callBarFg }};
iconPosition: point(9px, 11px);
}
callBarLabel: LabelSimple(defaultLabelSimple) {
font: semiboldFont;
textFg: callBarFg;
}
callBarLabelTop: 10px;

View File

@ -148,9 +148,12 @@ void Call::startOutgoing() {
void Call::startIncoming() {
Expects(_type == Type::Incoming);
Expects(_state == State::Starting);
request(MTPphone_ReceivedCall(MTP_inputPhoneCall(MTP_long(_id), MTP_long(_accessHash)))).done([this](const MTPBool &result) {
setState(State::WaitingIncoming);
if (_state == State::Starting) {
setState(State::WaitingIncoming);
}
}).fail([this](const RPCError &error) {
setState(State::Failed);
}).send();
@ -159,6 +162,9 @@ void Call::startIncoming() {
void Call::answer() {
Expects(_type == Type::Incoming);
if (_state != State::Starting && _state != State::WaitingIncoming) {
return;
}
setState(State::ExchangingKeys);
request(MTPphone_AcceptCall(MTP_inputPhoneCall(MTP_long(_id), MTP_long(_accessHash)), MTP_bytes(_gb), _protocol)).done([this](const MTPphone_PhoneCall &result) {
Expects(result.type() == mtpc_phone_phoneCall);
@ -360,8 +366,6 @@ void Call::createAndStartController(const MTPDphoneCall &call) {
return;
}
setState(State::Established);
voip_config_t config;
config.data_saving = DATA_SAVING_NEVER;
config.enableAEC = true;

View File

@ -67,6 +67,7 @@ public:
bool handleUpdate(const MTPPhoneCall &call);
enum State {
Starting,
WaitingInit,
WaitingInitAck,
Established,
@ -127,7 +128,7 @@ private:
gsl::not_null<Delegate*> _delegate;
gsl::not_null<UserData*> _user;
Type _type = Type::Outgoing;
State _state = State::WaitingInit;
State _state = State::Starting;
bool _finishAfterRequestingCall = false;
base::Observable<State> _stateChanged;
TimeMs _startTime = 0;

View File

@ -37,22 +37,25 @@ void Instance::startOutgoingCall(gsl::not_null<UserData*> user) {
}
void Instance::callFinished(gsl::not_null<Call*> call) {
if (_currentCall.get() == call) {
_currentCallPanel.reset();
_currentCall.reset();
}
destroyCall(call);
}
void Instance::callFailed(gsl::not_null<Call*> call) {
destroyCall(call);
}
void Instance::destroyCall(gsl::not_null<Call*> call) {
if (_currentCall.get() == call) {
_currentCallPanel.reset();
_currentCall.reset();
_currentCallChanged.notify(nullptr, true);
}
}
void Instance::createCall(gsl::not_null<UserData*> user, Call::Type type) {
_currentCall = std::make_unique<Call>(getCallDelegate(), user, type);
_currentCallPanel = std::make_unique<Panel>(_currentCall.get());
_currentCallChanged.notify(_currentCall.get(), true);
refreshDhConfig();
}
@ -108,6 +111,12 @@ void Instance::handleUpdate(const MTPDupdatePhoneCall& update) {
handleCallUpdate(update.vphone_call);
}
void Instance::showInfoPanel(gsl::not_null<Call*> call) {
if (_currentCall.get() == call) {
_currentCallPanel->showAndActivate();
}
}
void Instance::handleCallUpdate(const MTPPhoneCall &call) {
if (call.type() == mtpc_phoneCallRequested) {
auto &phoneCall = call.c_phoneCallRequested();

View File

@ -32,8 +32,12 @@ public:
Instance();
void startOutgoingCall(gsl::not_null<UserData*> user);
void handleUpdate(const MTPDupdatePhoneCall &update);
void showInfoPanel(gsl::not_null<Call*> call);
base::Observable<Call*> &currentCallChanged() {
return _currentCallChanged;
}
~Instance();
@ -48,6 +52,7 @@ private:
void callFailed(gsl::not_null<Call*> call) override;
void createCall(gsl::not_null<UserData*> user, Call::Type type);
void refreshDhConfig();
void destroyCall(gsl::not_null<Call*> call);
void handleCallUpdate(const MTPPhoneCall &call);
@ -55,6 +60,7 @@ private:
std::unique_ptr<Call> _currentCall;
std::unique_ptr<Panel> _currentCallPanel;
base::Observable<Call*> _currentCallChanged;
};

View File

@ -101,7 +101,28 @@ Panel::Panel(gsl::not_null<Call*> call)
, _status(this, st::callStatus) {
initControls();
initLayout();
showAndActivate();
}
void Panel::showAndActivate() {
show();
raise();
setWindowState(windowState() | Qt::WindowActive);
activateWindow();
setFocus();
}
bool Panel::event(QEvent *e) {
if (e->type() == QEvent::WindowDeactivate) {
if (_call && _call->state() == State::Established) {
hideDeactivated();
}
}
return TWidget::event(e);
}
void Panel::hideDeactivated() {
hide();
}
void Panel::initControls() {
@ -144,7 +165,7 @@ void Panel::initControls() {
void Panel::initLayout() {
hide();
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | /*Qt::WindowStaysOnTopHint | */Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::Tool);
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::WindowStaysOnTopHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::Tool);
setAttribute(Qt::WA_MacAlwaysShowToolWindow);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_TranslucentBackground, true);
@ -362,9 +383,8 @@ void Panel::mouseReleaseEvent(QMouseEvent *e) {
void Panel::stateChanged(State state) {
updateStatusText(state);
if (_answer
&& state != State::WaitingIncoming
&& state != State::WaitingInit
&& state != State::WaitingInitAck) {
&& state != State::Starting
&& state != State::WaitingIncoming) {
_answer.destroy();
updateControlsGeometry();
}
@ -372,11 +392,15 @@ void Panel::stateChanged(State state) {
_fingerprint = ComputeEmojiFingerprint(_call.get());
update();
}
if (state == State::Established && !isActiveWindow()) {
hideDeactivated();
}
}
void Panel::updateStatusText(State state) {
auto statusText = [this, state]() -> QString {
switch (state) {
case State::Starting:
case State::WaitingInit:
case State::WaitingInitAck: return lang(lng_call_status_connecting);
case State::Established: {

View File

@ -35,12 +35,15 @@ class Panel : public TWidget, private base::Subscriber {
public:
Panel(gsl::not_null<Call*> call);
void showAndActivate();
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
bool event(QEvent *e) override;
private:
using State = Call::State;
@ -49,6 +52,7 @@ private:
void initControls();
void initLayout();
void initGeometry();
void hideDeactivated();
void createBottomImage();
void createDefaultCacheImage();
void refreshCacheImageUserPhoto();

View File

@ -0,0 +1,119 @@
/*
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 "calls/calls_top_bar.h"
#include "styles/style_calls.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "lang.h"
#include "calls/calls_call.h"
#include "calls/calls_instance.h"
namespace Calls {
TopBar::TopBar(QWidget *parent, const base::weak_unique_ptr<Call> &call) : TWidget(parent)
, _call(call)
, _durationLabel(this, st::callBarLabel)
, _infoLabel(this, st::callBarLabel, lang(lng_call_bar_info).toUpper())
, _hangupLabel(this, st::callBarLabel, lang(lng_call_bar_hangup).toUpper())
, _mute(this, st::callBarMuteToggle)
, _info(this)
, _hangup(this, st::callBarHangup) {
initControls();
resize(width(), st::callBarHeight);
}
void TopBar::initControls() {
_mute->setClickedCallback([this] {
_call->setMute(!_call->isMute());
});
subscribe(_call->muteChanged(), [this](bool mute) {
_mute->setIconOverride(mute ? &st::callBarUnmuteIcon : nullptr);
_mute->setRippleColorOverride(mute ? &st::callBarUnmuteRipple : nullptr);
_hangup->setRippleColorOverride(mute ? &st::callBarUnmuteRipple : nullptr);
_muted = mute;
update();
});
_info->setClickedCallback([this] {
if (auto call = _call.get()) {
Current().showInfoPanel(call);
}
});
_hangup->setClickedCallback([this] {
if (_call) {
_call->hangup();
}
});
_updateDurationTimer.setCallback([this] { updateDurationText(); });
updateDurationText();
}
void TopBar::updateDurationText() {
if (!_call) {
return;
}
auto wasWidth = _durationLabel->width();
auto durationMs = _call->getDurationMs();
auto durationSeconds = durationMs / 1000;
startDurationUpdateTimer(durationMs);
_durationLabel->setText(formatDurationText(durationSeconds));
if (_durationLabel->width() != wasWidth) {
updateControlsGeometry();
}
}
void TopBar::startDurationUpdateTimer(TimeMs currentDuration) {
auto msTillNextSecond = 1000 - (currentDuration % 1000);
_updateDurationTimer.callOnce(msTillNextSecond + 5);
}
void TopBar::resizeEvent(QResizeEvent *e) {
updateControlsGeometry();
}
void TopBar::updateControlsGeometry() {
auto left = 0;
_mute->moveToLeft(left, 0); left += _mute->width();
_durationLabel->moveToLeft(left, st::callBarLabelTop); left += _durationLabel->width() + st::callBarSkip;
auto right = st::callBarRightSkip;
_hangupLabel->moveToRight(right, st::callBarLabelTop); right += _hangupLabel->width();
right += st::callBarHangup.width;
_hangup->setGeometryToRight(0, 0, right, height());
_info->setGeometryToLeft(_mute->width(), 0, width() - _mute->width() - _hangup->width(), height());
auto minPadding = qMax(left, right);
auto infoLeft = (width() - _infoLabel->width()) / 2;
if (infoLeft < minPadding) {
infoLeft = left + (width() - left - right - _infoLabel->width()) / 2;
}
_infoLabel->moveToLeft(infoLeft, st::callBarLabelTop);
}
void TopBar::paintEvent(QPaintEvent *e) {
Painter p(this);
p.fillRect(e->rect(), _muted ? st::callBarBgMuted : st::callBarBg);
}
TopBar::~TopBar() = default;
} // namespace Calls

View File

@ -0,0 +1,66 @@
/*
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 "base/weak_unique_ptr.h"
#include "base/timer.h"
namespace Ui {
class IconButton;
class AbstractButton;
class LabelSimple;
} // namespace Ui
namespace Calls {
class Call;
class TopBar : public TWidget, private base::Subscriber {
public:
TopBar(QWidget *parent, const base::weak_unique_ptr<Call> &call);
~TopBar();
protected:
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
private:
void initControls();
void updateDurationText();
void updateControlsGeometry();
void startDurationUpdateTimer(TimeMs currentDuration);
base::weak_unique_ptr<Call> _call;
bool _muted = false;
object_ptr<Ui::LabelSimple> _durationLabel;
object_ptr<Ui::LabelSimple> _infoLabel;
object_ptr<Ui::LabelSimple> _hangupLabel;
object_ptr<Ui::IconButton> _mute;
object_ptr<Ui::AbstractButton> _info;
object_ptr<Ui::IconButton> _hangup;
base::Timer _updateDurationTimer;
};
} // namespace Calls

View File

@ -26,9 +26,9 @@ dialogsUnreadFont: font(12px bold);
dialogsUnreadHeight: 19px;
dialogsUnreadPadding: 5px;
dialogsRipple: defaultRippleAnimation;
dialogsRippleBg: windowBgRipple;
dialogsRippleBgActive: activeButtonBgRipple;
dialogsRipple: RippleAnimation(defaultRippleAnimation) {
color: dialogsRippleBg;
}
dialogsTextFont: font(fsize);
dialogsTextStyle: TextStyle(defaultTextStyle) {

View File

@ -68,6 +68,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "window/notifications_manager.h"
#include "window/window_controller.h"
#include "calls/calls_instance.h"
#include "calls/calls_top_bar.h"
StackItemSection::StackItemSection(std::unique_ptr<Window::SectionMemento> &&memento) : StackItem(nullptr)
, _memento(std::move(memento)) {
@ -111,6 +112,7 @@ MainWidget::MainWidget(QWidget *parent, gsl::not_null<Window::Controller*> contr
handleAudioUpdate(audioId);
}
});
subscribe(AuthSession::Current().calls().currentCallChanged(), [this](Calls::Call *call) { setCurrentCall(call); });
subscribe(AuthSession::Current().api().fullPeerUpdated(), [this](PeerData *peer) {
emit peerUpdated(peer);
});
@ -1631,6 +1633,55 @@ void MainWidget::playerHeightUpdated() {
}
}
void MainWidget::setCurrentCall(Calls::Call *call) {
_currentCall = call;
if (_currentCall) {
subscribe(_currentCall->stateChanged(), [this](Calls::Call::State state) {
using State = Calls::Call::State;
if (state == State::Established) {
createCallTopBar();
} else {
destroyCallTopBar();
}
});
} else {
destroyCallTopBar();
}
}
void MainWidget::createCallTopBar() {
Expects(_currentCall != nullptr);
_callTopBar.create(this, object_ptr<Calls::TopBar>(this, _currentCall), style::margins(0, 0, 0, 0), [this] { callTopBarHeightUpdated(); });
orderWidgets();
if (_a_show.animating()) {
_callTopBar->showFast();
_callTopBar->hide();
} else {
_callTopBar->hideFast();
_callTopBar->showAnimated();
_callTopBarHeight = _contentScrollAddToY = _callTopBar->height();
updateControlsGeometry();
}
}
void MainWidget::destroyCallTopBar() {
if (_callTopBar) {
_callTopBar->hideAnimated();
}
}
void MainWidget::callTopBarHeightUpdated() {
auto callTopBarHeight = _callTopBar ? _callTopBar->height() : 0;
if (!callTopBarHeight && !_currentCall) {
_callTopBar.destroyDelayed();
}
if (callTopBarHeight != _callTopBarHeight) {
_contentScrollAddToY += callTopBarHeight - _callTopBarHeight;
_callTopBarHeight = callTopBarHeight;
updateControlsGeometry();
}
}
void MainWidget::documentLoadProgress(FileLoader *loader) {
if (auto documentId = loader ? loader->objId() : 0) {
documentLoadProgress(App::document(documentId));
@ -2467,8 +2518,9 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarS
_playerPlaylist->hide();
}
auto sectionTop = getSectionTop();
if (selectingPeer() && Adaptive::OneColumn()) {
result.oldContentCache = myGrab(this, QRect(0, _playerHeight, _dialogsWidth, height() - _playerHeight));
result.oldContentCache = myGrab(this, QRect(0, sectionTop, _dialogsWidth, height() - sectionTop));
} else if (_wideSection) {
result.oldContentCache = _wideSection->grabForShowAnimation(result);
} else {
@ -2480,10 +2532,10 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarS
_history->grabStart();
}
if (Adaptive::OneColumn()) {
result.oldContentCache = myGrab(this, QRect(0, _playerHeight, _dialogsWidth, height() - _playerHeight));
result.oldContentCache = myGrab(this, QRect(0, sectionTop, _dialogsWidth, height() - sectionTop));
} else {
_sideShadow->hide();
result.oldContentCache = myGrab(this, QRect(_dialogsWidth, _playerHeight, width() - _dialogsWidth, height() - _playerHeight));
result.oldContentCache = myGrab(this, QRect(_dialogsWidth, sectionTop, width() - _dialogsWidth, height() - sectionTop));
_sideShadow->show();
}
if (_overview) _overview->grabFinish();
@ -2528,7 +2580,8 @@ void MainWidget::showNewWideSection(const Window::SectionMemento *memento, bool
_controller->dialogsListFocused().set(false, true);
_a_dialogsWidth.finish();
auto newWideGeometry = QRect(_history->x(), _playerHeight, _history->width(), height() - _playerHeight);
auto sectionTop = getSectionTop();
auto newWideGeometry = QRect(_history->x(), sectionTop, _history->width(), height() - sectionTop);
auto newWideSection = memento->createWidget(this, newWideGeometry);
auto animatedShow = [this] {
if (_a_show.animating() || App::passcoded()) {
@ -2622,6 +2675,9 @@ void MainWidget::showBackFromStack() {
void MainWidget::orderWidgets() {
_dialogs->raise();
if (_callTopBar) {
_callTopBar->raise();
}
if (_player) {
_player->raise();
}
@ -2660,11 +2716,12 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams &param
_playerPlaylist->hide();
}
auto sectionTop = getSectionTop();
if (Adaptive::OneColumn()) {
result = myGrab(this, QRect(0, _playerHeight, _dialogsWidth, height() - _playerHeight));
result = myGrab(this, QRect(0, sectionTop, _dialogsWidth, height() - sectionTop));
} else {
_sideShadow->hide();
result = myGrab(this, QRect(_dialogsWidth, _playerHeight, width() - _dialogsWidth, height() - _playerHeight));
result = myGrab(this, QRect(_dialogsWidth, sectionTop, width() - _dialogsWidth, height() - sectionTop));
_sideShadow->show();
}
if (playerVolumeVisible) {
@ -2884,6 +2941,10 @@ void MainWidget::paintEvent(QPaintEvent *e) {
}
}
int MainWidget::getSectionTop() const {
return _callTopBarHeight + _playerHeight;
}
void MainWidget::hideAll() {
_dialogs->hide();
_history->hide();
@ -2985,14 +3046,19 @@ void MainWidget::updateControlsGeometry() {
if (!_a_dialogsWidth.animating()) {
_dialogs->stopWidthAnimation();
}
auto sectionTop = getSectionTop();
auto dialogsWidth = qRound(_a_dialogsWidth.current(_dialogsWidth));
if (Adaptive::OneColumn()) {
if (_callTopBar) {
_callTopBar->resizeToWidth(dialogsWidth);
_callTopBar->moveToLeft(0, 0);
}
if (_player) {
_player->resizeToWidth(dialogsWidth);
_player->moveToLeft(0, 0);
_player->moveToLeft(0, _callTopBarHeight);
}
_dialogs->setGeometry(0, _playerHeight, dialogsWidth, height() - _playerHeight);
_history->setGeometry(0, _playerHeight, dialogsWidth, height() - _playerHeight);
_dialogs->setGeometry(0, sectionTop, dialogsWidth, height() - sectionTop);
_history->setGeometry(0, sectionTop, dialogsWidth, height() - sectionTop);
if (_hider) _hider->setGeometry(0, 0, dialogsWidth, height());
} else {
accumulate_min(dialogsWidth, width() - st::windowMinWidth);
@ -3000,11 +3066,15 @@ void MainWidget::updateControlsGeometry() {
_dialogs->setGeometryToLeft(0, 0, dialogsWidth, height());
_sideShadow->setGeometryToLeft(dialogsWidth, 0, st::lineWidth, height());
if (_callTopBar) {
_callTopBar->resizeToWidth(sectionWidth);
_callTopBar->moveToLeft(dialogsWidth, 0);
}
if (_player) {
_player->resizeToWidth(sectionWidth);
_player->moveToLeft(dialogsWidth, 0);
_player->moveToLeft(dialogsWidth, _callTopBarHeight);
}
_history->setGeometryToLeft(dialogsWidth, _playerHeight, sectionWidth, height() - _playerHeight);
_history->setGeometryToLeft(dialogsWidth, sectionTop, sectionWidth, height() - sectionTop);
if (_hider) {
_hider->setGeometryToLeft(dialogsWidth, 0, sectionWidth, height());
}
@ -3021,7 +3091,7 @@ void MainWidget::updateControlsGeometry() {
};
_sideResizeArea->setVisible(isSideResizeAreaVisible());
if (_wideSection) {
auto wideSectionGeometry = QRect(_history->x(), _playerHeight, _history->width(), height() - _playerHeight);
auto wideSectionGeometry = QRect(_history->x(), sectionTop, _history->width(), height() - sectionTop);
_wideSection->setGeometryWithTopMoved(wideSectionGeometry, _contentScrollAddToY);
}
if (_overview) _overview->setGeometry(_history->geometry());
@ -3151,7 +3221,7 @@ void MainWidget::setMembersShowAreaActive(bool active) {
}
int MainWidget::backgroundFromY() const {
return -_playerHeight;
return -getSectionTop();
}
void MainWidget::onHistoryShown(History *history, MsgId atMsgId) {

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "storage/localimageloader.h"
#include "history/history_common.h"
#include "core/single_timer.h"
#include "base/weak_unique_ptr.h"
namespace Notify {
struct PeerUpdate;
@ -43,6 +44,8 @@ class Panel;
namespace Ui {
class PlainShadow;
class DropdownMenu;
template <typename Widget>
class WidgetSlideWrap;
} // namespace Ui
namespace Window {
@ -54,6 +57,11 @@ class SectionWidget;
struct SectionSlideParams;
} // namespace Window
namespace Calls {
class Call;
class TopBar;
} // namespace Calls
class MainWindow;
class ConfirmBox;
class DialogsWidget;
@ -471,6 +479,11 @@ private:
void closeBothPlayers();
void playerHeightUpdated();
void setCurrentCall(Calls::Call *call);
void createCallTopBar();
void destroyCallTopBar();
void callTopBarHeightUpdated();
void sendReadRequest(PeerData *peer, MsgId upTo);
void channelReadDone(PeerData *peer, const MTPBool &result);
void historyReadDone(PeerData *peer, const MTPmessages_AffectedMessages &result);
@ -549,6 +562,8 @@ private:
void inviteImportDone(const MTPUpdates &result);
bool inviteImportFail(const RPCError &error);
int getSectionTop() const;
void hideAll();
void showAll();
@ -572,6 +587,9 @@ private:
object_ptr<Window::SectionWidget> _thirdSection = { nullptr };
object_ptr<OverviewWidget> _overview = { nullptr };
base::weak_unique_ptr<Calls::Call> _currentCall;
object_ptr<Ui::WidgetSlideWrap<Calls::TopBar>> _callTopBar = { nullptr };
object_ptr<Window::PlayerWrapWidget> _player = { nullptr };
object_ptr<Media::Player::VolumeWidget> _playerVolume = { nullptr };
object_ptr<Media::Player::Panel> _playerPlaylist;
@ -585,6 +603,7 @@ private:
MsgId _msgIdInStack = 0;
int _playerHeight = 0;
int _callTopBarHeight = 0;
int _contentScrollAddToY = 0;
int32 updDate = 0;

View File

@ -481,7 +481,7 @@ void RoundButton::paintEvent(QPaintEvent *e) {
p.setPen((over || down) ? _st.numbersTextFgOver : _st.numbersTextFg);
_numbers->paint(p, textLeft, textTop, width());
}
_st.icon.paint(p, QPoint(_st.padding.left(), _st.padding.right()), width());
_st.icon.paint(p, QPoint(_st.padding.left(), _st.padding.top()), width());
}
QImage RoundButton::prepareRippleMask() const {

View File

@ -88,6 +88,8 @@
<(src_loc)/calls/calls_instance.h
<(src_loc)/calls/calls_panel.cpp
<(src_loc)/calls/calls_panel.h
<(src_loc)/calls/calls_top_bar.cpp
<(src_loc)/calls/calls_top_bar.h
<(src_loc)/chat_helpers/bot_keyboard.cpp
<(src_loc)/chat_helpers/bot_keyboard.h
<(src_loc)/chat_helpers/emoji_list_widget.cpp