Move third column from HistoryWidget to MainWidget.

This commit is contained in:
John Preston 2017-09-16 19:53:41 +03:00
parent f162462111
commit 5e7aa4ff81
63 changed files with 1187 additions and 752 deletions

View File

@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <rpl/event_stream.h>
#include "base/timer.h"
#include "core/single_timer.h"
#include "mtproto/sender.h"
@ -132,6 +133,13 @@ public:
not_null<UserData*> user,
PhotoId afterId);
void stickerSetInstalled(uint64 setId) {
_stickerSetInstalled.fire_copy(setId);
}
rpl::producer<uint64> stickerSetInstalled() const {
return _stickerSetInstalled.events();
}
~ApiWrap();
private:
@ -262,4 +270,6 @@ private:
base::Observable<PeerData*> _fullPeerUpdated;
rpl::event_stream<uint64> _stickerSetInstalled;
};

View File

@ -71,6 +71,7 @@ QByteArray AuthSessionData::serialize() const {
for (auto peerId : _variables.groupStickersSectionHidden) {
stream << quint64(peerId);
}
stream << qint32(_variables.thirdSectionInfoEnabled ? 1 : 0);
}
return result;
}
@ -89,7 +90,8 @@ void AuthSessionData::constructFromSerialized(const QByteArray &serialized) {
qint32 floatPlayerColumn = static_cast<qint32>(Window::Column::Second);
qint32 floatPlayerCorner = static_cast<qint32>(RectPart::TopRight);
QMap<QString, QString> soundOverrides;
OrderedSet<PeerId> groupStickersSectionHidden;
base::flat_set<PeerId> groupStickersSectionHidden;
qint32 thirdSectionInfoEnabled = 0;
stream >> selectorTab;
stream >> lastSeenWarningSeen;
if (!stream.atEnd()) {
@ -123,6 +125,9 @@ void AuthSessionData::constructFromSerialized(const QByteArray &serialized) {
}
}
}
if (!stream.atEnd()) {
stream >> thirdSectionInfoEnabled;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: Bad data for AuthSessionData::constructFromSerialized()"));
return;
@ -152,6 +157,24 @@ void AuthSessionData::constructFromSerialized(const QByteArray &serialized) {
case RectPart::BottomRight: _variables.floatPlayerCorner = uncheckedCorner; break;
}
_variables.groupStickersSectionHidden = std::move(groupStickersSectionHidden);
_variables.thirdSectionInfoEnabled = thirdSectionInfoEnabled;
}
void AuthSessionData::setTabbedSelectorSectionEnabled(bool enabled) {
_variables.tabbedSelectorSectionEnabled = enabled;
if (enabled) {
setThirdSectionInfoEnabled(false);
}
}
void AuthSessionData::setThirdSectionInfoEnabled(bool enabled) {
if (_variables.thirdSectionInfoEnabled != enabled) {
_variables.thirdSectionInfoEnabled = enabled;
if (enabled) {
setTabbedSelectorSectionEnabled(false);
}
_thirdSectionInfoEnabledValue.fire_copy(enabled);
}
}
QString AuthSessionData::getSoundPath(const QString &key) const {

View File

@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <rpl/event_stream.h>
#include "base/timer.h"
namespace Storage {
@ -100,8 +101,14 @@ public:
bool tabbedSelectorSectionEnabled() const {
return _variables.tabbedSelectorSectionEnabled;
}
void setTabbedSelectorSectionEnabled(bool enabled) {
_variables.tabbedSelectorSectionEnabled = enabled;
void setTabbedSelectorSectionEnabled(bool enabled);
bool thirdSectionInfoEnabled() const {
return _variables.thirdSectionInfoEnabled;
}
void setThirdSectionInfoEnabled(bool enabled);
rpl::producer<bool> thirdSectionInfoEnabledValue() const {
return _thirdSectionInfoEnabledValue.events_starting_with(
thirdSectionInfoEnabled());
}
void setLastTimeVideoPlayedAt(TimeMs time) {
_lastTimeVideoPlayedAt = time;
@ -155,7 +162,8 @@ private:
QMap<QString, QString> soundOverrides;
Window::Column floatPlayerColumn;
RectPart floatPlayerCorner;
OrderedSet<PeerId> groupStickersSectionHidden;
base::flat_set<PeerId> groupStickersSectionHidden;
bool thirdSectionInfoEnabled = false;
};
base::Variable<bool> _contactsLoaded = { false };
@ -167,6 +175,8 @@ private:
base::Observable<not_null<const HistoryItem*>> _repaintLogEntry;
base::Observable<void> _pendingHistoryResize;
base::Observable<ItemVisibilityQuery> _queryItemVisibility;
rpl::event_stream<bool> _thirdSectionInfoEnabledValue;
Variables _variables;
TimeMs _lastTimeVideoPlayedAt = 0;

View File

@ -56,12 +56,12 @@ void StickerSetBox::prepare() {
onUpdateButtons();
connect(_inner, SIGNAL(updateButtons()), this, SLOT(onUpdateButtons()));
connect(_inner, SIGNAL(installed(uint64)), this, SLOT(onInstalled(uint64)));
}
void StickerSetBox::onInstalled(uint64 setId) {
emit installed(setId);
closeBox();
_inner->setInstalled()
| rpl::on_next([this](auto &&setId) {
Auth().api().stickerSetInstalled(setId);
closeBox();
})
| rpl::start(lifetime());
}
void StickerSetBox::onAddStickers() {
@ -250,7 +250,7 @@ void StickerSetBox::Inner::installDone(const MTPmessages_StickerSetInstallResult
Local::writeInstalledStickers();
Auth().data().stickersUpdated().notify(true);
}
emit installed(_setId);
_setInstalled.fire_copy(_setId);
}
bool StickerSetBox::Inner::installFail(const RPCError &error) {

View File

@ -35,9 +35,6 @@ class StickerSetBox : public BoxContent, public RPCSender {
public:
StickerSetBox(QWidget*, const MTPInputStickerSet &set);
signals:
void installed(uint64 id);
protected:
void prepare() override;
@ -48,8 +45,6 @@ private slots:
void onShareStickers();
void onUpdateButtons();
void onInstalled(uint64 id);
private:
void updateButtons();
@ -74,6 +69,9 @@ public:
QString shortName() const;
void install();
rpl::producer<uint64> setInstalled() const {
return _setInstalled.events();
}
~Inner();
@ -89,7 +87,6 @@ private slots:
signals:
void updateButtons();
void installed(uint64 id);
private:
void updateSelected();
@ -127,4 +124,6 @@ private:
QTimer _previewTimer;
int _previewShown = -1;
rpl::event_stream<uint64> _setInstalled;
};

View File

@ -1094,7 +1094,7 @@ void StickersBox::Inner::saveGroupSet() {
auto newId = (_megagroupSetInput.type() == mtpc_inputStickerSetID) ? _megagroupSetInput.c_inputStickerSetID().vid.v : 0;
if (newId != oldId) {
Auth().api().setGroupStickerSet(_megagroupSet, _megagroupSetInput);
App::main()->onStickersInstalled(Stickers::MegagroupSetId);
Auth().api().stickerSetInstalled(Stickers::MegagroupSetId);
}
}

View File

@ -304,7 +304,7 @@ void EmojiColorPicker::drawVariant(Painter &p, int variant) {
EmojiListWidget::EmojiListWidget(QWidget *parent, not_null<Window::Controller*> controller) : Inner(parent, controller)
, _picker(this) {
resize(st::emojiPanWidth - st::emojiScroll.width - st::buttonRadius, countHeight());
updateSize();
setMouseTracking(true);
setAttribute(Qt::WA_OpaquePaintEvent);
@ -381,7 +381,7 @@ EmojiListWidget::SectionInfo EmojiListWidget::sectionInfoByOffset(int yOffset) c
return result;
}
int EmojiListWidget::countHeight() {
int EmojiListWidget::countDesiredHeight() {
return sectionInfo(kEmojiSectionCount - 1).rowsBottom + st::emojiPanPadding;
}
@ -648,11 +648,7 @@ void EmojiListWidget::refreshRecent() {
clearSelection();
_emoji[0] = Ui::Emoji::GetSection(Section::Recent);
_counts[0] = _emoji[0].size();
auto h = countHeight();
if (h != height()) {
resize(width(), h);
update();
}
updateSize();
}
bool EmojiListWidget::event(QEvent *e) {

View File

@ -126,7 +126,7 @@ protected:
TabbedSelector::InnerFooter *getFooter() const override;
void processHideFinished() override;
int countHeight() override;
int countDesiredHeight() override;
private:
class Footer;

View File

@ -122,7 +122,7 @@ void GifsListWidget::Footer::processPanelHideFinished() {
GifsListWidget::GifsListWidget(QWidget *parent, not_null<Window::Controller*> controller) : Inner(parent, controller)
, _section(Section::Gifs) {
resize(st::emojiPanWidth - st::emojiScroll.width - st::buttonRadius, countHeight());
updateSize();
setMouseTracking(true);
setAttribute(Qt::WA_OpaquePaintEvent);
@ -174,17 +174,12 @@ void GifsListWidget::checkLoadMore() {
}
}
int GifsListWidget::countHeight() {
auto visibleHeight = getVisibleBottom() - getVisibleTop();
if (visibleHeight <= 0) {
visibleHeight = st::emojiPanMaxHeight - st::emojiCategory.height;
}
auto minimalLastHeight = (visibleHeight - st::stickerPanPadding);
int GifsListWidget::countDesiredHeight() {
auto result = st::stickerPanPadding;
for (int i = 0, l = _rows.count(); i < l; ++i) {
result += _rows[i].height;
}
return qMax(minimalLastHeight, result) + st::stickerPanPadding;
return result + st::stickerPanPadding;
}
GifsListWidget::~GifsListWidget() {
@ -475,11 +470,7 @@ void GifsListWidget::refreshSavedGifs() {
}
deleteUnusedGifLayouts();
auto newHeight = countHeight();
if (newHeight != height()) {
resize(width(), newHeight);
}
updateSize();
update();
}
@ -642,8 +633,7 @@ int GifsListWidget::refreshInlineRows(const InlineCacheEntry *entry, bool result
inlineRowFinalize(row, sumWidth, true);
}
int32 h = countHeight();
if (h != height()) resize(width(), h);
updateSize();
update();
_lastMousePos = QCursor::pos();

View File

@ -82,7 +82,7 @@ protected:
TabbedSelector::InnerFooter *getFooter() const override;
void processHideFinished() override;
void processPanelHideFinished() override;
int countHeight() override;
int countDesiredHeight() override;
private slots:
void onPreview();

View File

@ -262,7 +262,7 @@ void SetIsFaved(not_null<DocumentData*> document, base::optional<std::vector<not
}
Local::writeFavedStickers();
Auth().data().stickersUpdated().notify(true);
App::main()->onStickersInstalled(FavedSetId);
Auth().api().stickerSetInstalled(FavedSetId);
}
void RequestSetToPushFaved(not_null<DocumentData*> document) {

View File

@ -440,7 +440,7 @@ StickersListWidget::StickersListWidget(QWidget *parent, not_null<Window::Control
, _addText(lang(lng_stickers_featured_add).toUpper())
, _addWidth(st::stickersTrendingAdd.font->width(_addText))
, _settings(this, lang(lng_stickers_you_have)) {
resize(st::emojiPanWidth - st::emojiScroll.width - st::buttonRadius, countHeight());
updateSize();
setMouseTracking(true);
setAttribute(Qt::WA_OpaquePaintEvent);
@ -559,11 +559,8 @@ StickersListWidget::SectionInfo StickersListWidget::sectionInfoByOffset(int yOff
return result;
}
int StickersListWidget::countHeight() {
auto visibleHeight = getVisibleBottom() - getVisibleTop();
if (visibleHeight <= 0) {
visibleHeight = st::emojiPanMaxHeight - st::emojiCategory.height;
}
int StickersListWidget::countDesiredHeight() {
auto visibleHeight = minimalHeight();
auto minimalLastHeight = (visibleHeight - st::stickerPanPadding);
auto countResult = [this, minimalLastHeight] {
if (_section == Section::Featured) {
@ -1154,10 +1151,7 @@ void StickersListWidget::refreshStickers() {
appendSet(_featuredSets, setId, AppendSkip::Installed);
}
auto newHeight = countHeight();
if (newHeight != height()) {
resize(width(), newHeight);
}
updateSize();
if (_footer) {
_footer->refreshIcons(ValidateIconAnimations::None);
@ -1283,12 +1277,7 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
}
if (performResize && (_section == Section::Stickers || _section == Section::Featured)) {
int32 h = countHeight();
if (h != height()) {
resize(width(), h);
update();
}
updateSize();
updateSelected();
}
}

View File

@ -79,7 +79,7 @@ protected:
TabbedSelector::InnerFooter *getFooter() const override;
void processHideFinished() override;
void processPanelHideFinished() override;
int countHeight() override;
int countDesiredHeight() override;
private slots:
void onSettings();

View File

@ -34,10 +34,20 @@ constexpr auto kDelayedHideTimeoutMs = 3000;
} // namespace
TabbedPanel::TabbedPanel(QWidget *parent, not_null<Window::Controller*> controller) : TabbedPanel(parent, controller, object_ptr<TabbedSelector>(nullptr, controller)) {
TabbedPanel::TabbedPanel(
QWidget *parent,
not_null<Window::Controller*> controller)
: TabbedPanel(
parent,
controller,
object_ptr<TabbedSelector>(nullptr, controller)) {
}
TabbedPanel::TabbedPanel(QWidget *parent, not_null<Window::Controller*> controller, object_ptr<TabbedSelector> selector) : TWidget(parent)
TabbedPanel::TabbedPanel(
QWidget *parent,
not_null<Window::Controller*> controller,
object_ptr<TabbedSelector> selector)
: RpWidget(parent)
, _controller(controller)
, _selector(std::move(selector)) {
_selector->setParent(this);
@ -52,6 +62,9 @@ TabbedPanel::TabbedPanel(QWidget *parent, not_null<Window::Controller*> controll
_controller->disableGifPauseReason(Window::GifPauseReason::SavedGifs);
}
});
_selector->showRequests()
| rpl::on_next([this](auto&&) { showFromSelector(); })
| rpl::start(lifetime());
resize(QRect(0, 0, st::emojiPanWidth, st::emojiPanMaxHeight).marginsAdded(innerPadding()).size());
@ -376,11 +389,7 @@ bool TabbedPanel::eventFilter(QObject *obj, QEvent *e) {
return false;
}
void TabbedPanel::stickersInstalled(uint64 setId) {
if (isDestroying()) {
return;
}
_selector->stickersInstalled(setId);
void TabbedPanel::showFromSelector() {
if (isHidden()) {
moveByBottom();
startShowAnimation();

View File

@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/twidget.h"
#include "ui/rp_widget.h"
#include "base/timer.h"
namespace Window {
@ -35,7 +35,7 @@ namespace ChatHelpers {
class TabbedSelector;
class TabbedPanel : public TWidget {
class TabbedPanel : public Ui::RpWidget{
Q_OBJECT
public:
@ -51,8 +51,6 @@ public:
return _hiding || _hideTimer.isActive();
}
void stickersInstalled(uint64 setId);
bool overlaps(const QRect &globalRect) const;
void showAnimated();
@ -79,6 +77,7 @@ private:
bool isDestroying() const {
return !_selector;
}
void showFromSelector();
style::margins innerPadding() const;

View File

@ -25,11 +25,49 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace ChatHelpers {
TabbedSection::TabbedSection(QWidget *parent, not_null<Window::Controller*> controller) : TabbedSection(parent, controller, object_ptr<TabbedSelector>(this, controller)) {
TabbedMemento::TabbedMemento(
object_ptr<TabbedSelector> selector,
base::lambda<void(object_ptr<TabbedSelector>)> returnMethod)
: _selector(std::move(selector))
, _returnMethod(std::move(returnMethod)) {
}
TabbedSection::TabbedSection(QWidget *parent, not_null<Window::Controller*> controller, object_ptr<TabbedSelector> selector) : Window::AbstractSectionWidget(parent, controller)
, _selector(std::move(selector)) {
object_ptr<Window::SectionWidget> TabbedMemento::createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) {
return object_ptr<TabbedSection>(
parent,
controller,
std::move(_selector),
std::move(_returnMethod));
}
TabbedMemento::~TabbedMemento() {
if (_returnMethod && _selector) {
_returnMethod(std::move(_selector));
}
}
TabbedSection::TabbedSection(
QWidget *parent,
not_null<Window::Controller*> controller)
: TabbedSection(
parent,
controller,
object_ptr<TabbedSelector>(this, controller),
base::lambda<void(object_ptr<TabbedSelector>)>()) {
}
TabbedSection::TabbedSection(
QWidget *parent,
not_null<Window::Controller*> controller,
object_ptr<TabbedSelector> selector,
base::lambda<void(object_ptr<TabbedSelector>)> returnMethod)
: Window::SectionWidget(parent, controller)
, _selector(std::move(selector))
, _returnMethod(std::move(returnMethod)) {
resize(st::emojiPanWidth, st::emojiPanMaxHeight);
_selector->setParent(this);
@ -68,17 +106,24 @@ object_ptr<TabbedSelector> TabbedSection::takeSelector() {
QPointer<TabbedSelector> TabbedSection::getSelector() const {
return _selector.data();
}
void TabbedSection::stickersInstalled(uint64 setId) {
_selector->stickersInstalled(setId);
bool TabbedSection::showInternal(
not_null<Window::SectionMemento*> memento) {
return false;
}
bool TabbedSection::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) {
bool TabbedSection::wheelEventFromFloatPlayer(QEvent *e) {
return _selector->wheelEventFromFloatPlayer(e);
}
QRect TabbedSection::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
QRect TabbedSection::rectForFloatPlayer() const {
return _selector->rectForFloatPlayer();
}
TabbedSection::~TabbedSection() {
beforeHiding();
if (_returnMethod) {
_returnMethod(takeSelector());
}
}
} // namespace ChatHelpers

View File

@ -21,15 +21,42 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "window/section_widget.h"
#include "window/section_memento.h"
namespace ChatHelpers {
class TabbedSelector;
class TabbedSection : public Window::AbstractSectionWidget {
class TabbedMemento : public Window::SectionMemento {
public:
TabbedSection(QWidget *parent, not_null<Window::Controller*> controller);
TabbedSection(QWidget *parent, not_null<Window::Controller*> controller, object_ptr<TabbedSelector> selector);
TabbedMemento(
object_ptr<TabbedSelector> selector,
base::lambda<void(object_ptr<TabbedSelector>)> returnMethod);
object_ptr<Window::SectionWidget> createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) override;
~TabbedMemento();
private:
object_ptr<TabbedSelector> _selector;
base::lambda<void(object_ptr<TabbedSelector>)> _returnMethod;
};
class TabbedSection : public Window::SectionWidget {
public:
TabbedSection(
QWidget *parent,
not_null<Window::Controller*> controller);
TabbedSection(
QWidget *parent,
not_null<Window::Controller*> controller,
object_ptr<TabbedSelector> selector,
base::lambda<void(object_ptr<TabbedSelector>)> returnMethod);
void beforeHiding();
void afterShown();
@ -40,18 +67,28 @@ public:
object_ptr<TabbedSelector> takeSelector();
QPointer<TabbedSelector> getSelector() const;
void stickersInstalled(uint64 setId);
bool showInternal(
not_null<Window::SectionMemento*> memento) override;
bool forceAnimateBack() const override {
return true;
}
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;
~TabbedSection();
protected:
void resizeEvent(QResizeEvent *e) override;
void showFinishedHook() override {
afterShown();
}
private:
object_ptr<TabbedSelector> _selector;
base::lambda<void()> _cancelledCallback;
base::lambda<void(object_ptr<TabbedSelector>)> _returnMethod;
};

View File

@ -346,6 +346,14 @@ TabbedSelector::TabbedSelector(QWidget *parent, not_null<Window::Controller*> co
}
}));
Auth().api().stickerSetInstalled()
| rpl::on_next([this](uint64 setId) {
_tabsSlider->setActiveSection(static_cast<int>(SelectorTab::Stickers));
stickers()->showStickerSet(setId);
_showRequests.fire({});
})
| rpl::start(lifetime());
// setAttribute(Qt::WA_AcceptTouchEvents);
setAttribute(Qt::WA_OpaquePaintEvent, false);
showAll();
@ -356,9 +364,11 @@ void TabbedSelector::resizeEvent(QResizeEvent *e) {
if (e->oldSize().height() > height()) {
_scroll->resize(_scroll->width(), contentHeight);
auto scrollTop = _scroll->scrollTop();
currentTab()->widget()->setMinimalHeight(contentHeight);
currentTab()->widget()->setVisibleTopBottom(scrollTop, scrollTop + contentHeight);
} else {
auto scrollTop = _scroll->scrollTop();
currentTab()->widget()->setMinimalHeight(contentHeight);
currentTab()->widget()->setVisibleTopBottom(scrollTop, scrollTop + contentHeight);
_scroll->resize(_scroll->width(), contentHeight);
}
@ -514,11 +524,6 @@ void TabbedSelector::afterShown() {
}
}
void TabbedSelector::stickersInstalled(uint64 setId) {
_tabsSlider->setActiveSection(static_cast<int>(SelectorTab::Stickers));
stickers()->showStickerSet(setId);
}
void TabbedSelector::showMegagroupSet(ChannelData *megagroup) {
stickers()->showMegagroupSet(megagroup);
}
@ -702,15 +707,36 @@ TabbedSelector::Inner::Inner(QWidget *parent, not_null<Window::Controller*> cont
}
void TabbedSelector::Inner::visibleTopBottomUpdated(int visibleTop, int visibleBottom) {
auto oldVisibleHeight = getVisibleBottom() - getVisibleTop();
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
auto visibleHeight = getVisibleBottom() - getVisibleTop();
if (visibleHeight != oldVisibleHeight) {
resize(st::emojiPanWidth - st::emojiScroll.width - st::buttonRadius, countHeight());
}
void TabbedSelector::Inner::setMinimalHeight(int newMinimalHeight) {
if (_minimalHeight != newMinimalHeight) {
_minimalHeight = newMinimalHeight;
updateSize();
}
}
void TabbedSelector::Inner::updateSize() {
auto width = st::emojiPanWidth
- st::emojiScroll.width
- st::buttonRadius;
auto height = qMax(countDesiredHeight(), minimalHeight());
auto newSize = QSize(width, height);
if (size() != newSize) {
resize(newSize);
update();
}
}
int TabbedSelector::Inner::minimalHeight() const {
auto result = _minimalHeight;
return (_minimalHeight > 0)
? _minimalHeight
: (st::emojiPanMaxHeight - st::emojiCategory.height);
}
void TabbedSelector::Inner::hideFinished() {
processHideFinished();
if (auto footer = getFooter()) {

View File

@ -60,7 +60,6 @@ public:
void setRoundRadius(int radius);
void refreshStickers();
void stickersInstalled(uint64 setId);
void showMegagroupSet(ChannelData *megagroup);
void setCurrentPeer(PeerData *peer);
@ -88,6 +87,10 @@ public:
bool wheelEventFromFloatPlayer(QEvent *e);
QRect rectForFloatPlayer() const;
rpl::producer<> showRequests() const {
return _showRequests.events();
}
~TabbedSelector();
class Inner;
@ -199,6 +202,8 @@ private:
base::lambda<void(SelectorTab)> _afterShownCallback;
base::lambda<void(SelectorTab)> _beforeHidingCallback;
rpl::event_stream<> _showRequests;
};
class TabbedSelector::Inner : public TWidget {
@ -213,6 +218,7 @@ public:
int getVisibleBottom() const {
return _visibleBottom;
}
void setMinimalHeight(int newMinimalHeight);
virtual void refreshRecent() = 0;
virtual void preloadImages() {
@ -236,12 +242,14 @@ protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void updateSize();
int minimalHeight() const;
not_null<Window::Controller*> controller() const {
return _controller;
}
virtual int countHeight() = 0;
virtual int countDesiredHeight() = 0;
virtual InnerFooter *getFooter() const = 0;
virtual void processHideFinished() {
}
@ -253,6 +261,7 @@ private:
int _visibleTop = 0;
int _visibleBottom = 0;
int _minimalHeight = 0;
};

View File

@ -267,11 +267,11 @@ void DialogsWidget::showAnimated(Window::SlideDirection direction, const Window:
_a_show.start([this] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition());
}
bool DialogsWidget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) {
bool DialogsWidget::wheelEventFromFloatPlayer(QEvent *e) {
return _scroll->viewportEvent(e);
}
QRect DialogsWidget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
QRect DialogsWidget::rectForFloatPlayer() const {
return mapToGlobal(_scroll->geometry());
}

View File

@ -98,8 +98,8 @@ public:
void onSearchMore();
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
void notify_historyMuteUpdated(History *history);

View File

@ -262,17 +262,9 @@ void autoplayMediaInlineAsync(const FullMsgId &msgId) {
}
void showPeerProfile(const PeerId &peer) {
//if (auto main = App::main()) {
// main->showWideSection(Profile::SectionMemento(App::peer(peer)));
//}
if (auto window = App::wnd()) {
auto memento = Info::Memento(peer);
if (auto layer = memento.createLayer(window->controller())) {
window->controller()->showSpecialLayer(std::move(layer));
} else {
App::main()->showWideSection(std::move(memento));
}
if (auto main = App::main()) {
// main->showSection(Profile::SectionMemento(App::peer(peer)));
main->showSection(Info::Memento(peer), anim::type::normal);
}
}

View File

@ -238,6 +238,7 @@ enum class WindowLayout {
OneColumn,
SmallColumn,
Normal,
ThreeColumn,
};
enum class ChatLayout {
@ -424,8 +425,13 @@ inline bool Normal() {
return Global::AdaptiveWindowLayout() == WindowLayout::Normal;
}
inline bool ThreeColumn() {
return Global::AdaptiveWindowLayout() == WindowLayout::ThreeColumn;
}
inline bool ChatNormal() {
return !Global::AdaptiveForWide() || (Global::AdaptiveChatLayout() == ChatLayout::Normal);
return !Global::AdaptiveForWide()
|| (Global::AdaptiveChatLayout() == ChatLayout::Normal);
}
inline bool ChatWide() {

View File

@ -22,6 +22,8 @@ using "basic.style";
using "dialogs/dialogs.style";
using "ui/widgets/widgets.style";
historyMinimalWidth: 380px;
historyScroll: ScrollArea(defaultScrollArea) {
bg: historyScrollBg;
bgOver: historyScrollBgOver;

View File

@ -88,7 +88,14 @@ private:
};
object_ptr<Window::SectionWidget> SectionMemento::createWidget(QWidget *parent, not_null<Window::Controller*> controller, const QRect &geometry) {
object_ptr<Window::SectionWidget> SectionMemento::createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) {
if (column == Window::Column::Third) {
return nullptr;
}
auto result = object_ptr<Widget>(parent, controller, _channel);
result->setInternalState(geometry, this);
return std::move(result);
@ -427,11 +434,11 @@ void Widget::showFinishedHook() {
_fixedBar->setAnimatingMode(false);
}
bool Widget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) {
bool Widget::wheelEventFromFloatPlayer(QEvent *e) {
return _scroll->viewportEvent(e);
}
QRect Widget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
QRect Widget::rectForFloatPlayer() const {
return mapToGlobal(_scroll->geometry());
}

View File

@ -101,8 +101,8 @@ public:
void setInternalState(const QRect &geometry, not_null<SectionMemento*> memento);
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;
void applyFilter(FilterValue &&value);
@ -136,7 +136,11 @@ public:
SectionMemento(not_null<ChannelData*> channel) : _channel(channel) {
}
object_ptr<Window::SectionWidget> createWidget(QWidget *parent, not_null<Window::Controller*> controller, const QRect &geometry) override;
object_ptr<Window::SectionWidget> createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) override;
not_null<ChannelData*> getChannel() const {
return _channel;

View File

@ -47,8 +47,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "profile/profile_block_group_members.h"
#include "core/click_handler_types.h"
#include "chat_helpers/tabbed_panel.h"
#include "chat_helpers/tabbed_section.h"
#include "chat_helpers/tabbed_selector.h"
#include "chat_helpers/tabbed_section.h"
#include "chat_helpers/bot_keyboard.h"
#include "chat_helpers/message_field.h"
#include "lang/lang_keys.h"
@ -75,101 +75,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "inline_bots/inline_results_widget.h"
#include "chat_helpers/emoji_suggestions_widget.h"
// Smart pointer for QObject*, has move semantics, destroys object if it doesn't have a parent.
template <typename Object>
class test_ptr {
public:
test_ptr(std::nullptr_t) {
}
// No default constructor, but constructors with at least
// one argument are simply make functions.
template <typename Parent, typename... Args>
explicit test_ptr(Parent &&parent, Args&&... args) : _object(new Object(std::forward<Parent>(parent), std::forward<Args>(args)...)) {
}
test_ptr(const test_ptr &other) = delete;
test_ptr &operator=(const test_ptr &other) = delete;
test_ptr(test_ptr &&other) : _object(base::take(other._object)) {
}
test_ptr &operator=(test_ptr &&other) {
auto temp = std::move(other);
destroy();
std::swap(_object, temp._object);
return *this;
}
template <typename OtherObject, typename = std::enable_if_t<std::is_base_of<Object, OtherObject>::value>>
test_ptr(test_ptr<OtherObject> &&other) : _object(base::take(other._object)) {
}
template <typename OtherObject, typename = std::enable_if_t<std::is_base_of<Object, OtherObject>::value>>
test_ptr &operator=(test_ptr<OtherObject> &&other) {
_object = base::take(other._object);
return *this;
}
test_ptr &operator=(std::nullptr_t) {
_object = nullptr;
return *this;
}
// So we can pass this pointer to methods like connect().
Object *data() const {
return static_cast<Object*>(_object);
}
operator Object*() const {
return data();
}
explicit operator bool() const {
return _object != nullptr;
}
Object *operator->() const {
return data();
}
Object &operator*() const {
return *data();
}
// Use that instead "= new Object(parent, ...)"
template <typename Parent, typename... Args>
void create(Parent &&parent, Args&&... args) {
destroy();
_object = new Object(std::forward<Parent>(parent), std::forward<Args>(args)...);
}
void destroy() {
delete base::take(_object);
}
void destroyDelayed() {
if (_object) {
if (auto widget = base::up_cast<QWidget*>(data())) {
widget->hide();
}
base::take(_object)->deleteLater();
}
}
~test_ptr() {
if (auto pointer = _object) {
if (!pointer->parent()) {
destroy();
}
}
}
private:
template <typename OtherObject>
friend class test_ptr;
QPointer<QObject> _object;
};
class TestClass;
test_ptr<TestClass> tmp = { nullptr };
namespace {
constexpr auto kSaveTabbedSelectorSectionTimeoutMs = 1000;
@ -739,7 +644,9 @@ HistoryWidget::HistoryWidget(QWidget *parent, not_null<Window::Controller*> cont
_botCommandStart->hide();
_tabbedSelectorToggle->installEventFilter(_tabbedPanel);
_tabbedSelectorToggle->setClickedCallback([this] { toggleTabbedSelectorMode(); });
_tabbedSelectorToggle->setClickedCallback([this] {
toggleTabbedSelectorMode();
});
connect(_botKeyboardShow, SIGNAL(clicked()), this, SLOT(onKbToggle()));
connect(_botKeyboardHide, SIGNAL(clicked()), this, SLOT(onKbToggle()));
@ -819,22 +726,6 @@ HistoryWidget::HistoryWidget(QWidget *parent, not_null<Window::Controller*> cont
}
}
}));
subscribe(controller->window()->widgetGrabbed(), [this] {
// Qt bug workaround: QWidget::render() for an arbitrary widget calls
// sendPendingMoveAndResizeEvents(true, true) for the whole window,
// which does something like:
//
// setAttribute(Qt::WA_UpdatesDisabled);
// sendEvent(QResizeEvent);
// setAttribute(Qt::WA_UpdatesDisabled, false);
//
// So if we create TabbedSection widget in HistoryWidget::resizeEvent()
// it will get an enabled Qt::WA_UpdatesDisabled from its parent and it
// will never be rendered, because no one will ever remove that attribute.
//
// So we force HistoryWidget::resizeEvent() here, without WA_UpdatesDisabled.
myEnsureResized(this);
});
subscribe(Auth().data().pendingHistoryResize(), [this] { handlePendingHistoryUpdate(); });
subscribe(Auth().data().queryItemVisibility(), [this](const AuthSessionData::ItemVisibilityQuery &query) {
if (_a_show.animating() || _history != query.item->history() || query.item->detached() || !isVisible()) {
@ -1152,9 +1043,6 @@ void HistoryWidget::orderWidgets() {
_reportSpamPanel->raise();
}
_topShadow->raise();
if (_rightShadow) {
_rightShadow->raise();
}
if (_membersDropdown) {
_membersDropdown->raise();
}
@ -1383,14 +1271,6 @@ void HistoryWidget::updateRecentStickers() {
_tabbedSelector->refreshStickers();
}
void HistoryWidget::stickersInstalled(uint64 setId) {
if (_tabbedPanel) {
_tabbedPanel->stickersInstalled(setId);
} else if (_tabbedSection) {
_tabbedSection->stickersInstalled(setId);
}
}
void HistoryWidget::sendActionDone(const MTPBool &result, mtpRequestId req) {
for (auto i = _sendActionRequests.begin(), e = _sendActionRequests.end(); i != e; ++i) {
if (i.value() == req) {
@ -2108,20 +1988,10 @@ void HistoryWidget::updateControlsVisibility() {
updateHistoryDownVisibility();
updateUnreadMentionsVisibility();
if (!_history || _a_show.animating()) {
if (_tabbedSection && !_tabbedSection->isHidden()) {
_tabbedSection->beforeHiding();
}
hideChildren();
return;
}
if (_tabbedSection) {
if (_tabbedSection->isHidden()) {
_tabbedSection->show();
_tabbedSection->afterShown();
}
_rightShadow->show();
}
if (_pinnedBar) {
_pinnedBar->cancel->show();
_pinnedBar->shadow->show();
@ -2287,7 +2157,7 @@ void HistoryWidget::updateControlsVisibility() {
update();
}
}
checkTabbedSelectorToggleTooltip();
//checkTabbedSelectorToggleTooltip();
updateMouseTracking();
}
@ -2807,7 +2677,16 @@ void HistoryWidget::saveEditMsg() {
if (!sentEntities.v.isEmpty()) {
sendFlags |= MTPmessages_EditMessage::Flag::f_entities;
}
_saveEditMsgRequestId = MTP::send(MTPmessages_EditMessage(MTP_flags(sendFlags), _history->peer->input, MTP_int(_editMsgId), MTP_string(sending.text), MTPnullMarkup, sentEntities), rpcDone(&HistoryWidget::saveEditMsgDone, _history), rpcFail(&HistoryWidget::saveEditMsgFail, _history));
_saveEditMsgRequestId = MTP::send(
MTPmessages_EditMessage(
MTP_flags(sendFlags),
_history->peer->input,
MTP_int(_editMsgId),
MTP_string(sending.text),
MTPnullMarkup,
sentEntities),
rpcDone(&HistoryWidget::saveEditMsgDone, _history),
rpcFail(&HistoryWidget::saveEditMsgFail, _history));
}
void HistoryWidget::saveEditMsgDone(History *history, const MTPUpdates &updates, mtpRequestId req) {
@ -3077,15 +2956,8 @@ void HistoryWidget::showAnimated(Window::SlideDirection direction, const Window:
_topShadow->setVisible(params.withTopBarShadow ? false : true);
_cacheOver = App::main()->grabForShowAnimation(params);
if (_tabbedSection && !_tabbedSection->isHidden()) {
_tabbedSection->beforeHiding();
}
hideChildren();
if (params.withTopBarShadow) _topShadow->show();
if (params.withTabbedSection && _tabbedSection) {
_tabbedSection->show();
_tabbedSection->afterShown();
}
if (_showDirection == Window::SlideDirection::FromLeft) {
std::swap(_cacheUnder, _cacheOver);
@ -3507,19 +3379,11 @@ bool HistoryWidget::eventFilter(QObject *obj, QEvent *e) {
return TWidget::eventFilter(obj, e);
}
bool HistoryWidget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) {
if (playerColumn == Window::Column::Third && _tabbedSection) {
auto tabbedColumn = (myColumn == Window::Column::First) ? Window::Column::Second : Window::Column::Third;
return _tabbedSection->wheelEventFromFloatPlayer(e, tabbedColumn, playerColumn);
}
bool HistoryWidget::wheelEventFromFloatPlayer(QEvent *e) {
return _scroll->viewportEvent(e);
}
QRect HistoryWidget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
if (playerColumn == Window::Column::Third && _tabbedSection) {
auto tabbedColumn = (myColumn == Window::Column::First) ? Window::Column::Second : Window::Column::Third;
return _tabbedSection->rectForFloatPlayer(tabbedColumn, playerColumn);
}
QRect HistoryWidget::rectForFloatPlayer() const {
return mapToGlobal(_scroll->geometry());
}
@ -3827,7 +3691,7 @@ bool HistoryWidget::paintTopBar(Painter &p, int decreaseWidth, TimeMs ms) {
auto nameleft = st::topBarArrowPadding.right() + increaseLeft;
auto nametop = st::topBarArrowPadding.top();
auto statustop = st::topBarHeight - st::topBarArrowPadding.bottom() - st::dialogsTextFont->height;
auto namewidth = _chatWidth - decreaseWidth - nameleft - st::topBarArrowPadding.right();
auto namewidth = width() - decreaseWidth - nameleft - st::topBarArrowPadding.right();
p.setFont(st::dialogsTextFont);
if (!_history->paintSendAction(p, nameleft, statustop, namewidth, width(), st::historyStatusFgTyping, ms)) {
p.setPen(_titlePeerTextOnline ? st::historyStatusFgActive : st::historyStatusFg);
@ -3888,113 +3752,66 @@ void HistoryWidget::onModerateKeyActivate(int index, bool *outHandled) {
void HistoryWidget::topBarClick() {
if (Adaptive::OneColumn() || !App::main()->stackIsEmpty()) {
App::main()->showBackFromStack();
} else {
if (_history) Ui::showPeerProfile(_peer);
} else if (_peer) {
controller()->showPeerInfo(_peer);
}
}
void HistoryWidget::updateTabbedSelectorSectionShown() {
auto tabbedSelectorSectionEnabled = Auth().data().tabbedSelectorSectionEnabled();
auto useTabbedSection = tabbedSelectorSectionEnabled && (width() >= minimalWidthForTabbedSelectorSection());
if (_tabbedSectionUsed == useTabbedSection) {
void HistoryWidget::pushTabbedSelectorToThirdSection() {
if (!_history || !_tabbedPanel) {
return;
}
_tabbedSectionUsed = useTabbedSection;
_tabbedSelectorToggle->setColorOverrides(
&st::historyAttachEmojiActive,
&st::historyRecordVoiceFgActive,
&st::historyRecordVoiceRippleBgActive);
auto destroyingPanel = std::move(_tabbedPanel);
controller()->resizeForThirdSection();
controller()->showSection(ChatHelpers::TabbedMemento(
destroyingPanel->takeSelector(),
base::lambda_guarded(this, [this](
object_ptr<TabbedSelector> selector) {
returnTabbedSelector(std::move(selector));
})));
}
// Use a separate bool flag instead of just (_tabbedSection != nullptr), because
// _tabbedPanel->takeSelector() calls QWidget::render(), which calls
// sendPendingMoveAndResizeEvents() for all widgets in the window, which can lead
// to a new HistoryWidget::resizeEvent() call and an infinite recursion here.
if (_tabbedSectionUsed) {
_tabbedSection.create(this, controller(), _tabbedPanel->takeSelector());
_tabbedSection->setCancelledCallback([this] { setInnerFocus(); });
_tabbedSelectorToggle->setColorOverrides(&st::historyAttachEmojiActive, &st::historyRecordVoiceFgActive, &st::historyRecordVoiceRippleBgActive);
_rightShadow.create(this, st::shadowFg);
auto destroyingPanel = std::move(_tabbedPanel);
updateControlsVisibility();
} else {
_tabbedPanel.create(this, controller(), _tabbedSection->takeSelector());
_tabbedPanel->hide();
_tabbedSelectorToggle->installEventFilter(_tabbedPanel);
_tabbedSection.destroy();
_tabbedSelectorToggle->setColorOverrides(nullptr, nullptr, nullptr);
_rightShadow.destroy();
_tabbedSelectorToggleTooltipShown = false;
void HistoryWidget::pushInfoToThirdSection() {
if (!_peer) {
return;
}
checkTabbedSelectorToggleTooltip();
orderWidgets();
}
void HistoryWidget::checkTabbedSelectorToggleTooltip() {
if (_tabbedSection && !_tabbedSection->isHidden() && !_tabbedSelectorToggle->isHidden()) {
if (!_tabbedSelectorToggleTooltipShown) {
auto shownCount = Auth().data().tabbedSelectorSectionTooltipShown();
if (shownCount < kTabbedSelectorToggleTooltipCount) {
_tabbedSelectorToggleTooltipShown = true;
_tabbedSelectorToggleTooltip.create(this, object_ptr<Ui::FlatLabel>(this, lang(lng_emoji_hide_panel), Ui::FlatLabel::InitType::Simple, st::defaultImportantTooltipLabel), st::defaultImportantTooltip);
_tabbedSelectorToggleTooltip->setHiddenCallback([this] {
_tabbedSelectorToggleTooltip.destroy();
});
InvokeQueued(_tabbedSelectorToggleTooltip, [this, shownCount] {
Auth().data().setTabbedSelectorSectionTooltipShown(shownCount + 1);
Auth().saveDataDelayed(kTabbedSelectorToggleTooltipTimeoutMs);
updateTabbedSelectorToggleTooltipGeometry();
_tabbedSelectorToggleTooltip->hideAfter(kTabbedSelectorToggleTooltipTimeoutMs);
_tabbedSelectorToggleTooltip->toggleAnimated(true);
});
}
}
} else {
_tabbedSelectorToggleTooltip.destroy();
}
}
int HistoryWidget::tabbedSelectorSectionWidth() const {
return st::emojiPanWidth;
}
int HistoryWidget::minimalWidthForTabbedSelectorSection() const {
return st::windowMinWidth + tabbedSelectorSectionWidth();
}
bool HistoryWidget::willSwitchToTabbedSelectorWithWidth(int newWidth) const {
if (!Auth().data().tabbedSelectorSectionEnabled()) {
return false;
} else if (_tabbedSectionUsed) {
return false;
}
return (newWidth >= minimalWidthForTabbedSelectorSection());
controller()->showPeerInfo(_peer);
}
void HistoryWidget::toggleTabbedSelectorMode() {
if (_tabbedSection) {
Auth().data().setTabbedSelectorSectionEnabled(false);
Auth().saveDataDelayed(kSaveTabbedSelectorSectionTimeoutMs);
updateTabbedSelectorSectionShown();
recountChatWidth();
updateControlsGeometry();
} else if (controller()->canProvideChatWidth(minimalWidthForTabbedSelectorSection())) {
if (!Auth().data().tabbedSelectorSectionEnabled()) {
if (_tabbedPanel) {
if (controller()->canShowThirdSection()) {
Auth().data().setTabbedSelectorSectionEnabled(true);
Auth().saveDataDelayed(kSaveTabbedSelectorSectionTimeoutMs);
pushTabbedSelectorToThirdSection();
} else {
_tabbedPanel->toggleAnimated();
}
controller()->provideChatWidth(minimalWidthForTabbedSelectorSection());
updateTabbedSelectorSectionShown();
recountChatWidth();
updateControlsGeometry();
} else {
Assert(_tabbedPanel != nullptr);
_tabbedPanel->toggleAnimated();
controller()->closeThirdSection();
}
}
void HistoryWidget::returnTabbedSelector(
object_ptr<TabbedSelector> selector) {
_tabbedPanel.create(
this,
controller(),
std::move(selector));
_tabbedPanel->hide();
_tabbedSelectorToggle->installEventFilter(_tabbedPanel);
_tabbedSelectorToggle->setColorOverrides(nullptr, nullptr, nullptr);
_tabbedSelectorToggleTooltipShown = false;
}
void HistoryWidget::recountChatWidth() {
_chatWidth = width();
if (_tabbedSection) {
_chatWidth -= _tabbedSection->width();
}
auto layout = (_chatWidth < st::adaptiveChatWideWidth) ? Adaptive::ChatLayout::Normal : Adaptive::ChatLayout::Wide;
auto layout = (width() < st::adaptiveChatWideWidth)
? Adaptive::ChatLayout::Normal
: Adaptive::ChatLayout::Wide;
if (layout != Global::AdaptiveChatLayout()) {
Global::SetAdaptiveChatLayout(layout);
Adaptive::Changed().notify(true);
@ -4106,11 +3923,11 @@ void HistoryWidget::moveFieldControls() {
auto keyboardHeight = 0;
auto bottom = height();
auto maxKeyboardHeight = st::historyComposeFieldMaxHeight - _field->height();
_keyboard->resizeToWidth(_chatWidth, maxKeyboardHeight);
_keyboard->resizeToWidth(width(), maxKeyboardHeight);
if (_kbShown) {
keyboardHeight = qMin(_keyboard->height(), maxKeyboardHeight);
bottom -= keyboardHeight;
_kbScroll->setGeometryToLeft(0, bottom, _chatWidth, keyboardHeight);
_kbScroll->setGeometryToLeft(0, bottom, width(), keyboardHeight);
}
// _attachToggle --------- _inlineResults -------------------------------------- _tabbedPanel --------- _fieldBarCancel
@ -4121,7 +3938,7 @@ void HistoryWidget::moveFieldControls() {
auto left = 0;
_attachToggle->moveToLeft(left, buttonsBottom); left += _attachToggle->width();
_field->moveToLeft(left, bottom - _field->height() - st::historySendPadding);
auto right = (width() - _chatWidth) + st::historySendRight;
auto right = st::historySendRight;
_send->moveToRight(right, buttonsBottom); right += _send->width();
_tabbedSelectorToggle->moveToRight(right, buttonsBottom);
updateTabbedSelectorToggleTooltipGeometry();
@ -4130,7 +3947,7 @@ void HistoryWidget::moveFieldControls() {
_botCommandStart->moveToRight(right, buttonsBottom);
_silent->moveToRight(right, buttonsBottom);
_fieldBarCancel->moveToRight(width() - _chatWidth, _field->y() - st::historySendPadding - _fieldBarCancel->height());
_fieldBarCancel->moveToRight(0, _field->y() - st::historySendPadding - _fieldBarCancel->height());
if (_inlineResults) {
_inlineResults->moveBottom(_field->y() - st::historySendPadding);
}
@ -4138,7 +3955,11 @@ void HistoryWidget::moveFieldControls() {
_tabbedPanel->moveBottom(buttonsBottom);
}
auto fullWidthButtonRect = myrtlrect(0, bottom - _botStart->height(), _chatWidth, _botStart->height());
auto fullWidthButtonRect = myrtlrect(
0,
bottom - _botStart->height(),
width(),
_botStart->height());
_botStart->setGeometry(fullWidthButtonRect);
_unblock->setGeometry(fullWidthButtonRect);
_joinChannel->setGeometry(fullWidthButtonRect);
@ -4156,7 +3977,7 @@ void HistoryWidget::updateTabbedSelectorToggleTooltipGeometry() {
void HistoryWidget::updateFieldSize() {
auto kbShowShown = _history && !_kbShown && _keyboard->hasMarkup();
auto fieldWidth = _chatWidth - _attachToggle->width() - st::historySendRight;
auto fieldWidth = width() - _attachToggle->width() - st::historySendRight;
fieldWidth -= _send->width();
fieldWidth -= _tabbedSelectorToggle->width();
if (kbShowShown) fieldWidth -= _botKeyboardShow->width();
@ -4780,31 +4601,28 @@ void HistoryWidget::handlePendingHistoryUpdate() {
}
void HistoryWidget::resizeEvent(QResizeEvent *e) {
updateTabbedSelectorSectionShown();
//updateTabbedSelectorSectionShown();
recountChatWidth();
updateControlsGeometry();
}
void HistoryWidget::updateControlsGeometry() {
if (_tabbedSection) {
_tabbedSection->setGeometryToRight(0, 0, st::emojiPanWidth, height());
}
_topBar->setGeometryToLeft(0, 0, _chatWidth, st::topBarHeight);
_topBar->setGeometryToLeft(0, 0, width(), st::topBarHeight);
moveFieldControls();
auto scrollAreaTop = _topBar->bottomNoMargins();
if (_pinnedBar) {
_pinnedBar->cancel->moveToLeft(_chatWidth - _pinnedBar->cancel->width(), scrollAreaTop);
_pinnedBar->cancel->moveToLeft(width() - _pinnedBar->cancel->width(), scrollAreaTop);
scrollAreaTop += st::historyReplyHeight;
_pinnedBar->shadow->setGeometryToLeft(0, scrollAreaTop, _chatWidth, st::lineWidth);
_pinnedBar->shadow->setGeometryToLeft(0, scrollAreaTop, width(), st::lineWidth);
}
if (_scroll->y() != scrollAreaTop) {
_scroll->moveToLeft(0, scrollAreaTop);
_fieldAutocomplete->setBoundings(_scroll->geometry());
}
if (_reportSpamPanel) {
_reportSpamPanel->setGeometryToLeft(0, _scroll->y(), _chatWidth, _reportSpamPanel->height());
_reportSpamPanel->setGeometryToLeft(0, _scroll->y(), width(), _reportSpamPanel->height());
}
updateHistoryGeometry(false, false, { ScrollChangeAdd, App::main() ? App::main()->contentScrollAddToY() : 0 });
@ -4834,12 +4652,13 @@ void HistoryWidget::updateControlsGeometry() {
break;
}
if (_rightShadow) {
_rightShadow->setGeometryToLeft(_chatWidth - st::lineWidth, 0, st::lineWidth, height());
}
auto topShadowLeft = (Adaptive::OneColumn() || _inGrab) ? 0 : st::lineWidth;
auto topShadowRight = _rightShadow ? st::lineWidth : 0;
_topShadow->setGeometryToLeft(topShadowLeft, _topBar->bottomNoMargins(), _chatWidth - topShadowLeft - topShadowRight, st::lineWidth);
auto topShadowRight = (Adaptive::ThreeColumn() && !_inGrab && _peer) ? st::lineWidth : 0;
_topShadow->setGeometryToLeft(
topShadowLeft,
_topBar->bottomNoMargins(),
width() - topShadowLeft - topShadowRight,
st::lineWidth);
}
void HistoryWidget::itemRemoved(HistoryItem *item) {
@ -4963,9 +4782,9 @@ void HistoryWidget::updateHistoryGeometry(bool initial, bool loadedDown, const S
auto wasScrollTop = _scroll->scrollTop();
auto wasScrollTopMax = _scroll->scrollTopMax();
auto wasAtBottom = wasScrollTop + 1 > wasScrollTopMax;
auto needResize = (_scroll->width() != _chatWidth) || (_scroll->height() != newScrollHeight);
auto needResize = (_scroll->width() != width()) || (_scroll->height() != newScrollHeight);
if (needResize) {
_scroll->resize(_chatWidth, newScrollHeight);
_scroll->resize(width(), newScrollHeight);
// on initial updateListSize we didn't put the _scroll->scrollTop correctly yet
// so visibleAreaUpdated() call will erase it with the new (undefined) value
if (!initial) {
@ -6379,7 +6198,7 @@ void HistoryWidget::updateReplyToName() {
void HistoryWidget::updateField() {
auto fieldAreaTop = _scroll->y() + _scroll->height();
rtlupdate(0, fieldAreaTop, _chatWidth, height() - fieldAreaTop);
rtlupdate(0, fieldAreaTop, width(), height() - fieldAreaTop);
}
void HistoryWidget::drawField(Painter &p, const QRect &rect) {
@ -6402,7 +6221,7 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
backh += st::historyReplyHeight;
}
auto drawWebPagePreview = (_previewData && _previewData->pendingTill >= 0) && !_replyForwardPressed;
p.fillRect(myrtlrect(0, backy, _chatWidth, backh), st::historyReplyBg);
p.fillRect(myrtlrect(0, backy, width(), backh), st::historyReplyBg);
if (_editMsgId || _replyToId || (!hasForward && _kbReplyTo)) {
auto replyLeft = st::historyReplySkip;
(_editMsgId ? st::historyEditIcon : st::historyReplyIcon).paint(p, st::historyReplyIconPosition + QPoint(0, backy), width());
@ -6420,14 +6239,14 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
if (_editMsgId) {
paintEditHeader(p, rect, replyLeft, backy);
} else {
_replyToName.drawElided(p, replyLeft, backy + st::msgReplyPadding.top(), _chatWidth - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right());
_replyToName.drawElided(p, replyLeft, backy + st::msgReplyPadding.top(), width() - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right());
}
p.setPen(((drawMsgText->toHistoryMessage() && drawMsgText->toHistoryMessage()->emptyText()) || drawMsgText->serviceMsg()) ? st::historyComposeAreaFgService : st::historyComposeAreaFg);
_replyEditMsgText.drawElided(p, replyLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, _chatWidth - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right());
_replyEditMsgText.drawElided(p, replyLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right());
} else {
p.setFont(st::msgDateFont);
p.setPen(st::historyComposeAreaFgService);
p.drawText(replyLeft, backy + st::msgReplyPadding.top() + (st::msgReplyBarSize.height() - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(lang(lng_profile_loading), _chatWidth - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right()));
p.drawText(replyLeft, backy + st::msgReplyPadding.top() + (st::msgReplyBarSize.height() - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(lang(lng_profile_loading), width() - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right()));
}
}
} else if (hasForward) {
@ -6451,7 +6270,7 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
p.setPen(st::historyReplyNameFg);
_toForwardFrom.drawElided(p, forwardLeft, backy + st::msgReplyPadding.top(), width() - forwardLeft - _fieldBarCancel->width() - st::msgReplyPadding.right());
p.setPen(serviceColor ? st::historyComposeAreaFgService : st::historyComposeAreaFg);
_toForwardText.drawElided(p, forwardLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, _chatWidth - forwardLeft - _fieldBarCancel->width() - st::msgReplyPadding.right());
_toForwardText.drawElided(p, forwardLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - forwardLeft - _fieldBarCancel->width() - st::msgReplyPadding.right());
}
}
if (drawWebPagePreview) {
@ -6471,14 +6290,14 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
previewLeft += st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x();
}
p.setPen(st::historyReplyNameFg);
_previewTitle.drawElided(p, previewLeft, backy + st::msgReplyPadding.top(), _chatWidth - previewLeft - _fieldBarCancel->width() - st::msgReplyPadding.right());
_previewTitle.drawElided(p, previewLeft, backy + st::msgReplyPadding.top(), width() - previewLeft - _fieldBarCancel->width() - st::msgReplyPadding.right());
p.setPen(st::historyComposeAreaFg);
_previewDescription.drawElided(p, previewLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, _chatWidth - previewLeft - _fieldBarCancel->width() - st::msgReplyPadding.right());
_previewDescription.drawElided(p, previewLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - previewLeft - _fieldBarCancel->width() - st::msgReplyPadding.right());
}
}
void HistoryWidget::drawRestrictedWrite(Painter &p) {
auto rect = myrtlrect(0, height() - _unblock->height(), _chatWidth, _unblock->height());
auto rect = myrtlrect(0, height() - _unblock->height(), width(), _unblock->height());
p.fillRect(rect, st::historyReplyBg);
p.setFont(st::normalFont);
@ -6487,7 +6306,7 @@ void HistoryWidget::drawRestrictedWrite(Painter &p) {
}
void HistoryWidget::paintEditHeader(Painter &p, const QRect &rect, int left, int top) const {
if (!rect.intersects(myrtlrect(left, top, _chatWidth - left, st::normalFont->height))) {
if (!rect.intersects(myrtlrect(left, top, width() - left, st::normalFont->height))) {
return;
}
@ -6517,7 +6336,7 @@ void HistoryWidget::paintEditHeader(Painter &p, const QRect &rect, int left, int
}
// Restart timer only if we are sure that we've painted the whole timer.
if (rect.contains(myrtlrect(left, top, _chatWidth - left, st::normalFont->height)) && updateIn > 0) {
if (rect.contains(myrtlrect(left, top, width() - left, st::normalFont->height)) && updateIn > 0) {
_updateEditTimeLeftDisplay.start(updateIn);
}
@ -6546,7 +6365,7 @@ void HistoryWidget::drawRecording(Painter &p, float64 recordActive) {
p.drawText(_attachToggle->x() + _tabbedSelectorToggle->width(), _attachToggle->y() + st::historyRecordTextTop + st::historyRecordFont->ascent, duration);
int32 left = _attachToggle->x() + _tabbedSelectorToggle->width() + st::historyRecordFont->width(duration) + ((_send->width() - st::historyRecordVoice.width()) / 2);
int32 right = _chatWidth - _send->width();
int32 right = width() - _send->width();
p.setPen(anim::pen(st::historyRecordCancel, st::historyRecordCancelActive, 1. - recordActive));
p.drawText(left + (right - left - _recordCancelWidth) / 2, _attachToggle->y() + st::historyRecordTextTop + st::historyRecordFont->ascent, lang(lng_record_cancel));
@ -6559,7 +6378,7 @@ void HistoryWidget::drawPinnedBar(Painter &p) {
Text *from = 0, *text = 0;
bool serviceColor = false, hasForward = readyToForward();
ImagePtr preview;
p.fillRect(myrtlrect(0, top, _chatWidth, st::historyReplyHeight), st::historyPinnedBg);
p.fillRect(myrtlrect(0, top, width(), st::historyReplyHeight), st::historyPinnedBg);
top += st::msgReplyPadding.top();
QRect rbar(myrtlrect(st::msgReplyBarSkip + st::msgReplyBarPos.x(), top + st::msgReplyBarPos.y(), st::msgReplyBarSize.width(), st::msgReplyBarSize.height()));
@ -6580,11 +6399,11 @@ void HistoryWidget::drawPinnedBar(Painter &p) {
p.drawText(left, top + st::msgServiceNameFont->ascent, lang(lng_pinned_message));
p.setPen(((_pinnedBar->msg->toHistoryMessage() && _pinnedBar->msg->toHistoryMessage()->emptyText()) || _pinnedBar->msg->serviceMsg()) ? st::historyComposeAreaFgService : st::historyComposeAreaFg);
_pinnedBar->text.drawElided(p, left, top + st::msgServiceNameFont->height, _chatWidth - left - _pinnedBar->cancel->width() - st::msgReplyPadding.right());
_pinnedBar->text.drawElided(p, left, top + st::msgServiceNameFont->height, width() - left - _pinnedBar->cancel->width() - st::msgReplyPadding.right());
} else {
p.setFont(st::msgDateFont);
p.setPen(st::historyComposeAreaFgService);
p.drawText(left, top + (st::msgReplyBarSize.height() - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(lang(lng_profile_loading), _chatWidth - left - _pinnedBar->cancel->width() - st::msgReplyPadding.right()));
p.drawText(left, top + (st::msgReplyBarSize.height() - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(lang(lng_profile_loading), width() - left - _pinnedBar->cancel->width() - st::msgReplyPadding.right()));
}
}
@ -6607,7 +6426,7 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
_unreadMentionsShown.step(ms);
auto progress = _a_show.current(ms, 1.);
if (_a_show.animating()) {
auto animationWidth = (!_tabbedSection || _tabbedSection->isHidden()) ? width() : _chatWidth;
auto animationWidth = width();
auto retina = cIntRetinaFactor();
auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft);
auto coordUnder = fromLeft ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress);
@ -6625,7 +6444,7 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
return;
}
QRect fill(0, 0, _history ? _chatWidth : width(), App::main()->height());
QRect fill(0, 0, width(), App::main()->height());
auto fromy = App::main()->backgroundFromY();
auto x = 0, y = 0;
QPixmap cached = App::main()->cachedBackground(fill, x, y);

View File

@ -207,15 +207,13 @@ public:
void unreadCountChanged(History *history);
QRect historyRect() const;
int tabbedSelectorSectionWidth() const;
int minimalWidthForTabbedSelectorSection() const;
bool willSwitchToTabbedSelectorWithWidth(int newWidth) const;
void pushTabbedSelectorToThirdSection();
void pushInfoToThirdSection();
void updateSendAction(History *history, SendAction::Type type, int32 progress = 0);
void cancelSendAction(History *history, SendAction::Type type);
void updateRecentStickers();
void stickersInstalled(uint64 setId);
void sendActionDone(const MTPBool &result, mtpRequestId req);
void destroyData();
@ -347,8 +345,8 @@ public:
void deleteSelectedItems(bool forEveryone);
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;
void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, not_null<const HistoryItem*> msg, int row, int col);
@ -479,12 +477,14 @@ private:
QStringList filesToSend;
bool allFilesForCompress = true;
};
using TabbedPanel = ChatHelpers::TabbedPanel;
using TabbedSelector = ChatHelpers::TabbedSelector;
void handlePendingHistoryUpdate();
void fullPeerUpdated(PeerData *peer);
void topBarClick();
void toggleTabbedSelectorMode();
void updateTabbedSelectorSectionShown();
void returnTabbedSelector(object_ptr<TabbedSelector> selector);
void recountChatWidth();
void setReportSpamStatus(DBIPeerReportSpamStatus status);
void historyDownClicked();
@ -562,7 +562,6 @@ private:
int _toForwardNameVersion = 0;
int _forwardingItemRemovedSubscription = 0;
int _chatWidth = 0;
MsgId _editMsgId = 0;
HistoryItem *_replyEditMsg = nullptr;
@ -822,10 +821,8 @@ private:
QTimer _membersDropdownShowTimer;
object_ptr<InlineBots::Layout::Widget> _inlineResults = { nullptr };
object_ptr<ChatHelpers::TabbedPanel> _tabbedPanel;
object_ptr<ChatHelpers::TabbedSection> _tabbedSection = { nullptr };
QPointer<ChatHelpers::TabbedSelector> _tabbedSelector;
bool _tabbedSectionUsed = false;
object_ptr<TabbedPanel> _tabbedPanel;
QPointer<TabbedSelector> _tabbedSelector;
DragState _attachDrag = DragStateNone;
object_ptr<DragArea> _attachDragDocument, _attachDragPhoto;
@ -863,7 +860,6 @@ private:
QTimer _saveDraftTimer, _saveCloudDraftTimer;
object_ptr<Ui::PlainShadow> _topShadow;
object_ptr<Ui::PlainShadow> _rightShadow = { nullptr };
bool _inGrab = false;
};

View File

@ -106,7 +106,7 @@ void LayerWrap::parentResized() {
hide();
setParent(nullptr);
auto localCopy = _controller;
localCopy->showWideSection(
localCopy->showSection(
MoveMemento(std::move(_content), Wrap::Narrow));
localCopy->hideSpecialLayer(LayerOption::ForceFast);
} else {

View File

@ -30,14 +30,6 @@ InnerWidget::InnerWidget(
: RpWidget(parent)
, _peer(peer)
, _type(type) {
base::lambda<void(int)> launch = [this, &launch](int counter) {
QTimer::singleShot(500, this, [this, launch, counter] {
_rowsHeightFake += 300;
resizeToWidth(width(), _minHeight);
launch(counter - 1);
});
};
launch(10);
}
void InnerWidget::visibleTopBottomUpdated(

View File

@ -165,7 +165,14 @@ std::unique_ptr<ContentMemento> Memento::Default(
object_ptr<Window::SectionWidget> Memento::createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) {
if (column == Window::Column::Third) {
return object_ptr<SideWrap>(
parent,
controller,
this);
}
return object_ptr<NarrowWrap>(
parent,
controller,
@ -193,21 +200,24 @@ MoveMemento::MoveMemento(
object_ptr<Window::SectionWidget> MoveMemento::createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) {
if (_wrap == Wrap::Narrow) {
if (_wrap == Wrap::Narrow && column != Window::Column::Third) {
auto result = object_ptr<NarrowWrap>(
parent,
controller,
this);
result->setGeometry(geometry);
return result;
} else if (_wrap == Wrap::Side && column == Window::Column::Third) {
auto result = object_ptr<SideWrap>(
parent,
controller,
this);
result->setGeometry(geometry);
return result;
}
auto result = object_ptr<SideWrap>(
parent,
controller,
this);
result->setGeometry(geometry);
return result;
return nullptr;
}
object_ptr<LayerWidget> MoveMemento::createLayer(

View File

@ -195,6 +195,7 @@ public:
object_ptr<Window::SectionWidget> createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) override;
object_ptr<LayerWidget> createLayer(
@ -232,6 +233,7 @@ public:
object_ptr<Window::SectionWidget> createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) override;
object_ptr<LayerWidget> createLayer(

View File

@ -176,20 +176,20 @@ void NarrowWrap::resizeEvent(QResizeEvent *e) {
}
void NarrowWrap::paintEvent(QPaintEvent *e) {
SectionWidget::paintEvent(e);
if (animating()) {
return;
}
Painter p(this);
p.fillRect(e->rect(), st::profileBg);
}
bool NarrowWrap::wheelEventFromFloatPlayer(
QEvent *e,
Window::Column myColumn,
Window::Column playerColumn) {
bool NarrowWrap::wheelEventFromFloatPlayer(QEvent *e) {
return _content->wheelEventFromFloatPlayer(e);
}
QRect NarrowWrap::rectForFloatPlayer(
Window::Column myColumn,
Window::Column playerColumn) const {
QRect NarrowWrap::rectForFloatPlayer() const {
return _content->rectForFloatPlayer();
}

View File

@ -79,13 +79,8 @@ public:
not_null<Memento*> memento);
// Float player interface.
bool wheelEventFromFloatPlayer(
QEvent *e,
Window::Column myColumn,
Window::Column playerColumn) override;
QRect rectForFloatPlayer(
Window::Column myColumn,
Window::Column playerColumn) const override;
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;
protected:
void resizeEvent(QResizeEvent *e) override;

View File

@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "info/info_media_widget.h"
#include "info/info_memento.h"
#include "ui/widgets/discrete_sliders.h"
#include "auth_session.h"
#include "ui/widgets/shadow.h"
#include "lang/lang_keys.h"
#include "styles/style_info.h"
@ -80,8 +81,7 @@ void SideWrap::showTab(Tab tab) {
showContent(createContent(tab));
}
void SideWrap::showContent(object_ptr<ContentWidget> content) {
auto section = content->section();
void SideWrap::setSection(const Section &section) {
switch (section.type()) {
case Section::Type::Profile:
setCurrentTab(Tab::Profile);
@ -102,7 +102,9 @@ void SideWrap::showContent(object_ptr<ContentWidget> content) {
setCurrentTab(Tab::None);
break;
}
}
void SideWrap::showContent(object_ptr<ContentWidget> content) {
_content = std::move(content);
_content->setGeometry(contentGeometry());
_content->show();
@ -158,6 +160,9 @@ void SideWrap::doSetInnerFocus() {
_content->setInnerFocus();
}
void SideWrap::showFinishedHook() {
}
bool SideWrap::showInternal(
not_null<Window::SectionMemento*> memento) {
if (auto infoMemento = dynamic_cast<Memento*>(memento.get())) {
@ -203,6 +208,8 @@ QRect SideWrap::contentGeometry() const {
}
void SideWrap::restoreState(not_null<Memento*> memento) {
// Validates contentGeometry().
setSection(memento->section());
showContent(memento->content()->createWidget(
this,
Wrap::Side,
@ -211,7 +218,9 @@ void SideWrap::restoreState(not_null<Memento*> memento) {
}
void SideWrap::restoreState(not_null<MoveMemento*> memento) {
showContent(memento->content(this, Wrap::Side));
auto content = memento->content(this, Wrap::Side);
setSection(content->section());
showContent(std::move(content));
}
void SideWrap::setCurrentTab(Tab tab) {
@ -235,20 +244,20 @@ void SideWrap::resizeEvent(QResizeEvent *e) {
}
void SideWrap::paintEvent(QPaintEvent *e) {
SectionWidget::paintEvent(e);
if (animating()) {
return;
}
Painter p(this);
p.fillRect(e->rect(), st::profileBg);
}
bool SideWrap::wheelEventFromFloatPlayer(
QEvent *e,
Window::Column myColumn,
Window::Column playerColumn) {
bool SideWrap::wheelEventFromFloatPlayer(QEvent *e) {
return _content->wheelEventFromFloatPlayer(e);
}
QRect SideWrap::rectForFloatPlayer(
Window::Column myColumn,
Window::Column playerColumn) const {
QRect SideWrap::rectForFloatPlayer() const {
return _content->rectForFloatPlayer();
}

View File

@ -37,6 +37,7 @@ namespace Media {
class Widget;
} // namespace Media
class Section;
class Memento;
class MoveMemento;
class ContentWidget;
@ -75,19 +76,15 @@ public:
not_null<Memento*> memento);
// Float player interface.
bool wheelEventFromFloatPlayer(
QEvent *e,
Window::Column myColumn,
Window::Column playerColumn) override;
QRect rectForFloatPlayer(
Window::Column myColumn,
Window::Column playerColumn) const override;
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;
protected:
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void doSetInnerFocus() override;
void showFinishedHook() override;
private:
enum class Tab {
@ -105,6 +102,7 @@ private:
void setupTabs();
void showTab(Tab tab);
void setCurrentTab(Tab tab);
void setSection(const Section &section);
void showContent(object_ptr<ContentWidget> content);
object_ptr<ContentWidget> createContent(Tab tab);
object_ptr<Profile::Widget> createProfileWidget();

File diff suppressed because it is too large Load Diff

View File

@ -156,7 +156,8 @@ class MainWidget : public Ui::RpWidget, public RPCSender, private base::Subscrib
public:
MainWidget(QWidget *parent, not_null<Window::Controller*> controller);
bool isSectionShown() const;
bool isMainSectionShown() const;
bool isThirdSectionShown() const;
// Temporary methods, while top bar was not done inside HistoryWidget / OverviewWidget.
bool paintTopBar(Painter &, int decreaseWidth, TimeMs ms);
@ -212,14 +213,17 @@ public:
int backgroundFromY() const;
PeerData *overviewPeer();
bool showMediaTypeSwitch() const;
void showWideSection(Window::SectionMemento &&memento);
void showSection(
Window::SectionMemento &&memento,
anim::type animated);
void updateColumnLayout();
void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1);
bool stackIsEmpty() const;
void showBackFromStack();
void orderWidgets();
QRect historyRect() const;
QPixmap grabForShowAnimation(const Window::SectionSlideParams &params);
void checkWideSectionToLayer();
void checkMainSectionToLayer();
void onSendFileConfirm(const FileLoadResultPtr &file);
bool onSendSticker(DocumentData *sticker);
@ -442,8 +446,6 @@ public slots:
void onUpdateMuted();
void onStickersInstalled(uint64 setId);
void onViewsIncrement();
void ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId, Ui::ShowWay way);
@ -523,12 +525,19 @@ private:
mtpRequestId req);
void mediaOverviewUpdated(const Notify::PeerUpdate &update);
Window::SectionSlideParams prepareShowAnimation(bool willHaveTopBarShadow, bool willHaveTabbedSection);
void showNewWideSection(Window::SectionMemento &&memento, bool back, bool saveInStack);
void dropWideSection(Window::SectionWidget *widget);
Window::SectionSlideParams prepareShowAnimation(
bool willHaveTopBarShadow);
void showNewSection(
Window::SectionMemento &&memento,
bool back,
bool saveInStack,
anim::type animated);
void dropMainSection(Window::SectionWidget *widget);
Window::SectionSlideParams prepareThirdSectionAnimation(Window::SectionWidget *section);
// All this methods use the prepareShowAnimation().
Window::SectionSlideParams prepareWideSectionAnimation(Window::SectionWidget *section);
Window::SectionSlideParams prepareMainSectionAnimation(Window::SectionWidget *section);
Window::SectionSlideParams prepareHistoryAnimation(PeerId historyPeerId);
Window::SectionSlideParams prepareOverviewAnimation();
Window::SectionSlideParams prepareDialogsAnimation();
@ -564,7 +573,8 @@ private:
void inviteImportDone(const MTPUpdates &result);
bool inviteImportFail(const RPCError &error);
int getSectionTop() const;
int getMainSectionTop() const;
int getThirdSectionTop() const;
void hideAll();
void showAll();
@ -581,11 +591,17 @@ private:
Float *currentFloatPlayer() const {
return _playerFloats.empty() ? nullptr : _playerFloats.back().get();
}
Window::AbstractSectionWidget *getFloatPlayerSection(not_null<Window::Column*> column) const;
void finishFloatPlayerDrag(not_null<Float*> instance, bool closed);
Window::AbstractSectionWidget *getFloatPlayerSection(
Window::Column column) const;
void finishFloatPlayerDrag(
not_null<Float*> instance,
bool closed);
void updateFloatPlayerColumnCorner(QPoint center);
QPoint getFloatPlayerPosition(not_null<Float*> instance) const;
QPoint getFloatPlayerHiddenPosition(QPoint position, QSize size, RectPart side) const;
QPoint getFloatPlayerHiddenPosition(
QPoint position,
QSize size,
RectPart side) const;
RectPart getFloatPlayerSide(QPoint center) const;
bool ptsUpdateAndApply(int32 pts, int32 ptsCount, const MTPUpdates &updates);
@ -615,10 +631,11 @@ private:
Animation _a_dialogsWidth;
object_ptr<Ui::PlainShadow> _sideShadow;
object_ptr<Ui::PlainShadow> _thirdShadow = { nullptr };
object_ptr<TWidget> _sideResizeArea;
object_ptr<DialogsWidget> _dialogs;
object_ptr<HistoryWidget> _history;
object_ptr<Window::SectionWidget> _wideSection = { nullptr };
object_ptr<Window::SectionWidget> _mainSection = { nullptr };
object_ptr<Window::SectionWidget> _thirdSection = { nullptr };
object_ptr<OverviewWidget> _overview = { nullptr };

View File

@ -812,7 +812,7 @@ void MainWindow::updateControlsGeometry() {
if (_connecting) _connecting->moveToLeft(0, body.height() - _connecting->height());
if (_testingThemeWarning) _testingThemeWarning->setGeometry(body);
if (_main) _main->checkWideSectionToLayer();
if (_main) _main->checkMainSectionToLayer();
}
MainWindow::TempDirState MainWindow::tempDirState() {

View File

@ -62,7 +62,7 @@ OverviewInner::OverviewInner(OverviewWidget *overview, Ui::ScrollArea *scroll, P
, _search(this, st::overviewFilter, langFactory(lng_dlg_filter))
, _cancelSearch(this, st::dialogsCancelSearch)
, _itemsToBeLoaded(LinksOverviewPerPage * 2)
, _width(st::windowMinWidth) {
, _width(st::columnMinimalWidthMain) {
subscribe(Auth().downloader().taskFinished(), [this] { update(); });
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
itemRemoved(item);
@ -1314,7 +1314,7 @@ int32 OverviewInner::resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeigh
contentLeftMin -= st::overviewFileLayout.songPadding.left();
contentLeftMax -= st::overviewFileLayout.songPadding.left();
}
auto widthWithMin = st::windowMinWidth;
auto widthWithMin = st::columnMinimalWidthMain;
auto widthWithMax = st::overviewFileLayout.maxWidth + 2 * contentLeftMax;
_rowsLeft = anim::interpolate(contentLeftMax, contentLeftMin, qMax(widthWithMax - _width, 0) / float64(widthWithMax - widthWithMin));
_rowWidth = qMin(_width - 2 * _rowsLeft, st::overviewFileLayout.maxWidth);
@ -2145,11 +2145,11 @@ int32 OverviewWidget::lastScrollTop() const {
return _scroll->scrollTop();
}
bool OverviewWidget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) {
bool OverviewWidget::wheelEventFromFloatPlayer(QEvent *e) {
return _scroll->viewportEvent(e);
}
QRect OverviewWidget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
QRect OverviewWidget::rectForFloatPlayer() const {
return mapToGlobal(_scroll->geometry());
}

View File

@ -349,8 +349,8 @@ public:
void deleteSelectedItems(bool forEveryone);
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;
void ui_repaintHistoryItem(not_null<const HistoryItem*> item);

View File

@ -156,7 +156,7 @@ void ChannelMembersWidget::onAdmins() {
void ChannelMembersWidget::onRecentActions() {
if (auto channel = peer()->asChannel()) {
if (auto main = App::main()) {
main->showWideSection(AdminLog::SectionMemento(channel));
main->showSection(AdminLog::SectionMemento(channel), anim::type::normal);
}
}
}

View File

@ -219,7 +219,7 @@ void SettingsWidget::onManageAdmins() {
void SettingsWidget::onRecentActions() {
if (auto channel = peer()->asChannel()) {
if (auto main = App::main()) {
main->showWideSection(AdminLog::SectionMemento(channel));
main->showSection(AdminLog::SectionMemento(channel), anim::type::normal);
}
}
}

View File

@ -201,7 +201,7 @@ void SharedMediaWidget::onShowCommonGroups() {
return;
}
if (auto main = App::main()) {
main->showWideSection(Profile::CommonGroups::SectionMemento(peer()->asUser()));
main->showSection(Profile::CommonGroups::SectionMemento(peer()->asUser()), anim::type::normal);
}
}

View File

@ -42,7 +42,11 @@ constexpr int kCommonGroupsPerPage = 40;
} // namespace
object_ptr<Window::SectionWidget> SectionMemento::createWidget(QWidget *parent, not_null<Window::Controller*> controller, const QRect &geometry) {
object_ptr<Window::SectionWidget> SectionMemento::createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) {
auto result = object_ptr<Widget>(parent, controller, _user);
result->setInternalState(geometry, this);
return std::move(result);
@ -196,7 +200,7 @@ int InnerWidget::resizeGetHeight(int newWidth) {
auto contentLeftMin = st::profileCommonGroupsLeftMin;
auto contentLeftMax = st::profileCommonGroupsLeftMax;
auto widthWithMin = st::windowMinWidth;
auto widthWithMin = st::columnMinimalWidthMain;
auto widthWithMax = st::profileCommonGroupsWidthMax + 2 * contentLeftMax;
_contentLeft = anim::interpolate(contentLeftMax, contentLeftMin, qMax(widthWithMax - newWidth, 0) / float64(widthWithMax - widthWithMin));
_contentWidth = qMin(newWidth - 2 * _contentLeft, st::profileCommonGroupsWidthMax);
@ -447,11 +451,11 @@ void Widget::showFinishedHook() {
_fixedBar->setAnimatingMode(false);
}
bool Widget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) {
bool Widget::wheelEventFromFloatPlayer(QEvent *e) {
return _scroll->viewportEvent(e);
}
QRect Widget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
QRect Widget::rectForFloatPlayer() const {
return mapToGlobal(_scroll->geometry());
}

View File

@ -43,7 +43,11 @@ public:
SectionMemento(not_null<UserData*> user) : _user(user) {
}
object_ptr<Window::SectionWidget> createWidget(QWidget *parent, not_null<Window::Controller*> controller, const QRect &geometry) override;
object_ptr<Window::SectionWidget> createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) override;
not_null<UserData*> getUser() const {
return _user;
@ -189,8 +193,8 @@ public:
void setInternalState(const QRect &geometry, not_null<SectionMemento*> memento);
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;
protected:
void resizeEvent(QResizeEvent *e) override;

View File

@ -117,7 +117,7 @@ void CoverWidget::onCancelPhotoUpload() {
int CoverWidget::countPhotoLeft(int newWidth) const {
int result = st::profilePhotoLeftMin;
result += (newWidth - st::windowMinWidth) / 2;
result += (newWidth - st::columnMinimalWidthMain) / 2;
return qMin(result, st::profilePhotoLeftMax);
}

View File

@ -148,7 +148,7 @@ int InnerWidget::countBlocksHeight(RectPart countSide) const {
int InnerWidget::countBlocksLeft(int newWidth) const {
int result = st::profileBlockLeftMin;
result += (newWidth - st::windowMinWidth) / 2;
result += (newWidth - st::columnMinimalWidthMain) / 2;
return qMin(result, st::profileBlockLeftMax);
}

View File

@ -24,7 +24,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Profile {
object_ptr<Window::SectionWidget> SectionMemento::createWidget(QWidget *parent, not_null<Window::Controller*> controller, const QRect &geometry) {
object_ptr<Window::SectionWidget> SectionMemento::createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) {
auto result = object_ptr<Widget>(parent, controller, _peer);
result->setInternalState(geometry, this);
return std::move(result);

View File

@ -31,7 +31,11 @@ public:
SectionMemento(PeerData *peer) : _peer(peer) {
}
object_ptr<Window::SectionWidget> createWidget(QWidget *parent, not_null<Window::Controller*> controller, const QRect &geometry) override;
object_ptr<Window::SectionWidget> createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Window::Column column,
const QRect &geometry) override;
PeerData *getPeer() const {
return _peer;

View File

@ -161,11 +161,11 @@ void Widget::showFinishedHook() {
_inner->showFinished();
}
bool Widget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) {
bool Widget::wheelEventFromFloatPlayer(QEvent *e) {
return _scroll->viewportEvent(e);
}
QRect Widget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
QRect Widget::rectForFloatPlayer() const {
return mapToGlobal(_scroll->geometry());
}

View File

@ -55,8 +55,8 @@ public:
void setInternalState(const QRect &geometry, not_null<SectionMemento*> memento);
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
bool wheelEventFromFloatPlayer(QEvent *e) override;
QRect rectForFloatPlayer() const override;
protected:
void resizeEvent(QResizeEvent *e) override;

View File

@ -93,6 +93,11 @@ enum Notification {
namespace anim {
enum class type {
normal,
instant,
};
using transition = base::lambda<float64(float64 delta, float64 dt)>;
extern transition linear;

View File

@ -191,8 +191,6 @@ QPixmap myGrab(TWidget *target, QRect rect, QColor bg) {
result.fill(bg);
}
App::wnd()->widgetGrabbed().notify(true);
target->grabStart();
target->render(&result, QPoint(0, 0), rect, QWidget::DrawChildren | QWidget::IgnoreMask);
target->grabFinish();

View File

@ -92,9 +92,6 @@ public:
base::Observable<void> &dragFinished() {
return _dragFinished;
}
base::Observable<void> &widgetGrabbed() {
return _widgetGrabbed;
}
public slots:
bool minimizeToTray();
@ -184,8 +181,7 @@ private:
base::Timer _inactivePressTimer;
base::Observable<void> _dragFinished;
base::Observable<void> _widgetGrabbed;
};
} // namespace Window

View File

@ -26,12 +26,14 @@ namespace Window {
class Controller;
class SectionWidget;
enum class Column;
class SectionMemento {
public:
virtual object_ptr<Window::SectionWidget> createWidget(
QWidget *parent,
not_null<Window::Controller*> controller,
Column column,
const QRect &geometry) = 0;
virtual object_ptr<LayerWidget> createLayer(

View File

@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "window/section_widget.h"
#include "application.h"
#include "window/section_memento.h"
#include <rpl/single.h>
namespace Window {
@ -28,7 +29,7 @@ namespace Window {
SectionWidget::SectionWidget(
QWidget *parent,
not_null<Window::Controller*> controller)
: AbstractSectionWidget(parent, controller) {
: AbstractSectionWidget(parent, controller) {
}
void SectionWidget::setGeometryWithTopMoved(
@ -72,6 +73,10 @@ void SectionWidget::showAnimated(
show();
}
std::unique_ptr<SectionMemento> SectionWidget::createMemento() {
return nullptr;
}
void SectionWidget::showFast() {
show();
showFinished();

View File

@ -45,10 +45,10 @@ public:
}
// Float player interface.
virtual bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) {
virtual bool wheelEventFromFloatPlayer(QEvent *e) {
return false;
}
virtual QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
virtual QRect rectForFloatPlayer() const {
return mapToGlobal(rect());
}
@ -67,7 +67,6 @@ class SectionMemento;
struct SectionSlideParams {
QPixmap oldContentCache;
bool withTopBarShadow = false;
bool withTabbedSection = false;
explicit operator bool() const {
return !oldContentCache.isNull();
@ -90,6 +89,9 @@ public:
virtual bool hasTopBarShadow() const {
return false;
}
virtual bool forceAnimateBack() const {
return false;
}
void showAnimated(SlideDirection direction, const SectionSlideParams &params);
void showFast();
@ -109,7 +111,7 @@ public:
// Create a memento of that section to store it in the history stack.
// This method may modify the section ("take" heavy items).
virtual std::unique_ptr<SectionMemento> createMemento() = 0;
virtual std::unique_ptr<SectionMemento> createMemento();
void setInnerFocus() {
doSetInnerFocus();

View File

@ -23,9 +23,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_window.h"
#include "boxes/add_contact_box.h"
#include "boxes/confirm_box.h"
#include "info/info_memento.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "shortcuts.h"
#include "auth_session.h"
#include "lang/lang_keys.h"
#include "ui/special_buttons.h"
#include "ui/widgets/buttons.h"
@ -36,8 +38,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "observer_peer.h"
namespace Window {
namespace {
TopBarWidget::TopBarWidget(QWidget *parent, not_null<Window::Controller*> controller) : TWidget(parent)
constexpr auto kThirdSectionInfoTimeoutMs = 1000;
} // namespace
TopBarWidget::TopBarWidget(QWidget *parent, not_null<Window::Controller*> controller) : RpWidget(parent)
, _controller(controller)
, _clearSelection(this, langFactory(lng_selected_clear), st::topBarClearButton)
, _forward(this, langFactory(lng_selected_forward), st::defaultActiveButton)
@ -46,6 +53,7 @@ TopBarWidget::TopBarWidget(QWidget *parent, not_null<Window::Controller*> contro
, _mediaType(this, langFactory(lng_media_type), st::topBarButton)
, _call(this, st::topBarCall)
, _search(this, st::topBarSearch)
, _infoToggle(this, st::topBarInfo)
, _menuToggle(this, st::topBarMenuToggle) {
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
@ -58,6 +66,7 @@ TopBarWidget::TopBarWidget(QWidget *parent, not_null<Window::Controller*> contro
_call->setClickedCallback([this] { onCall(); });
_search->setClickedCallback([this] { onSearch(); });
_menuToggle->setClickedCallback([this] { showMenu(); });
_infoToggle->setClickedCallback([this] { toggleInfoSection(); });
subscribe(_controller->searchInPeerChanged(), [this](PeerData *peer) {
_searchInPeer = peer;
@ -85,7 +94,12 @@ TopBarWidget::TopBarWidget(QWidget *parent, not_null<Window::Controller*> contro
updateControlsVisibility();
}
}));
subscribe(Global::RefPhoneCallsEnabledChanged(), [this] { updateControlsVisibility(); });
subscribe(Global::RefPhoneCallsEnabledChanged(), [this] {
updateControlsVisibility(); });
Auth().data().thirdSectionInfoEnabledValue()
| rpl::on_next([this](bool) { updateInfoToggleActive(); })
| rpl::start(lifetime());
setCursor(style::cur_pointer);
updateControlsVisibility();
@ -109,7 +123,9 @@ void TopBarWidget::onClearSelection() {
void TopBarWidget::onInfoClicked() {
auto p = App::main() ? App::main()->historyPeer() : nullptr;
if (p) Ui::showPeerProfile(p);
if (p) {
_controller->showPeerInfo(p);
}
}
void TopBarWidget::onSearch() {
@ -163,6 +179,28 @@ void TopBarWidget::showMenu() {
}
}
void TopBarWidget::toggleInfoSection() {
if (Adaptive::ThreeColumn()
&& Auth().data().thirdSectionInfoEnabled()) {
_controller->closeThirdSection();
} else if (auto peer = App::main()->historyPeer()) {
if (_controller->canShowThirdSection()) {
Auth().data().setThirdSectionInfoEnabled(true);
Auth().saveDataDelayed(kThirdSectionInfoTimeoutMs);
if (Adaptive::ThreeColumn()) {
_controller->showSection(Info::Memento(peer->id));
} else {
_controller->resizeForThirdSection();
_controller->updateColumnLayout();
}
} else {
_controller->showSection(Info::Memento(peer->id));
}
} else {
updateControlsVisibility();
}
}
bool TopBarWidget::eventFilter(QObject *obj, QEvent *e) {
if (obj == _membersShowArea) {
switch (e->type()) {
@ -288,10 +326,14 @@ void TopBarWidget::updateControlsGeometry() {
_menuToggle->moveToRight(right, otherButtonsTop);
_mediaType->moveToRight(right, otherButtonsTop);
if (_info->isHidden()) {
right += _menuToggle->width();
right += _menuToggle->width() + st::topBarSkip;
} else {
right += _info->width();
}
_infoToggle->moveToRight(right, otherButtonsTop);
if (!_infoToggle->isHidden()) {
right += _infoToggle->width() + st::topBarSkip;
}
_search->moveToRight(right, otherButtonsTop);
right += _search->width() + st::topBarCallSkip;
_call->moveToRight(right, otherButtonsTop);
@ -322,6 +364,8 @@ void TopBarWidget::updateControlsVisibility() {
_menuToggle->show();
}
_search->show();
_infoToggle->setVisible(!Adaptive::OneColumn()
&& _controller->canShowThirdSection());
auto callsEnabled = false;
if (auto user = historyPeer->asUser()) {
callsEnabled = Global::PhoneCallsEnabled() && user->hasCalls();
@ -421,6 +465,20 @@ void TopBarWidget::updateAdaptiveLayout() {
rtlupdate(0, 0, st::titleUnreadCounterRight, st::titleUnreadCounterTop);
});
}
updateInfoToggleActive();
}
void TopBarWidget::updateInfoToggleActive() {
auto infoThirdActive = Adaptive::ThreeColumn()
&& Auth().data().thirdSectionInfoEnabled();
auto iconOverride = infoThirdActive
? &st::topBarInfoActive
: nullptr;
auto ripplOverride = infoThirdActive
? &st::lightButtonBgOver
: nullptr;
_infoToggle->setIconOverride(iconOverride, iconOverride);
_infoToggle->setRippleColorOverride(ripplOverride);
}
Ui::RoundButton *TopBarWidget::mediaTypeButton() {

View File

@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/twidget.h"
#include "ui/rp_widget.h"
namespace Ui {
class PeerAvatarButton;
@ -33,7 +33,7 @@ namespace Window {
class Controller;
class TopBarWidget : public TWidget, private base::Subscriber {
class TopBarWidget : public Ui::RpWidget, private base::Subscriber {
Q_OBJECT
public:
@ -68,6 +68,7 @@ private:
void refreshLang();
void updateControlsGeometry();
void selectedShowCallback();
void updateInfoToggleActive();
void onForwardSelection();
void onDeleteSelection();
@ -76,6 +77,7 @@ private:
void onCall();
void onSearch();
void showMenu();
void toggleInfoSection();
void updateAdaptiveLayout();
int countSelectedButtonsTop(float64 selectedShown);
@ -97,6 +99,7 @@ private:
object_ptr<Ui::IconButton> _call;
object_ptr<Ui::IconButton> _search;
object_ptr<Ui::IconButton> _infoToggle;
object_ptr<Ui::IconButton> _menuToggle;
object_ptr<Ui::DropdownMenu> _menu = { nullptr };

View File

@ -30,6 +30,10 @@ windowDefaultHeight: 600px;
windowShadow: icon {{ "window_shadow", windowShadowFg }};
windowShadowShift: 1px;
columnMinimalWidthLeft: 260px;
columnMinimalWidthMain: 380px;
columnMinimalWidthThird: 345px;
adaptiveChatWideWidth: 880px;
notifyBorder: windowShadowFgFallback;
@ -257,9 +261,9 @@ topBarSearch: IconButton {
width: 40px;
height: topBarHeight;
icon: icon {{ "title_search-flip_horizontal", menuIconFg }};
iconOver: icon {{ "title_search-flip_horizontal", menuIconFgOver }};
iconPosition: point(11px, 19px);
icon: icon {{ "top_bar_search", menuIconFg }};
iconOver: icon {{ "top_bar_search", menuIconFgOver }};
iconPosition: point(4px, 11px);
rippleAreaPosition: point(0px, 7px);
rippleAreaSize: 40px;
@ -268,10 +272,16 @@ topBarSearch: IconButton {
}
}
topBarCall: IconButton(topBarSearch) {
icon: icon {{ "add_contact_phone", menuIconFg }};
iconOver: icon {{ "add_contact_phone", menuIconFgOver }};
icon: icon {{ "top_bar_call", menuIconFg }};
iconOver: icon {{ "top_bar_call", menuIconFgOver }};
}
topBarCallSkip: 4px;
topBarInfo: IconButton(topBarSearch) {
icon: icon {{ "top_bar_profile", menuIconFg }};
iconOver: icon {{ "top_bar_profile", menuIconFgOver }};
}
topBarInfoActive: icon {{ "top_bar_profile", windowBgActive }};
topBarSkip: -2px;
topBarCallSkip: -1px;
topBarMenuToggle: IconButton(topBarSearch) {
width: 44px;

View File

@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "window/window_controller.h"
#include "window/main_window.h"
#include "info/info_memento.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "styles/style_window.h"
@ -30,6 +31,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "apiwrap.h"
namespace Window {
namespace {
constexpr auto kThirdSectionInfoTimeoutMs = 1000;
} // namespace
void Controller::enableGifPauseReason(GifPauseReason reason) {
if (!(_gifPauseReasons & reason)) {
@ -61,21 +67,29 @@ int Controller::dialogsSmallColumnWidth() const {
return st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPadding.x();
}
int Controller::minimalThreeColumnWidth() const {
return st::columnMinimalWidthLeft
+ st::columnMinimalWidthMain
+ st::columnMinimalWidthThird;
}
Controller::ColumnLayout Controller::computeColumnLayout() const {
auto layout = Adaptive::WindowLayout::OneColumn;
auto bodyWidth = window()->bodyWidget()->width();
auto dialogsWidth = qRound(bodyWidth * dialogsWidthRatio().value());
auto chatWidth = bodyWidth - dialogsWidth;
accumulate_max(chatWidth, st::windowMinWidth);
auto thirdWidth = 0;
accumulate_max(chatWidth, st::columnMinimalWidthMain);
dialogsWidth = bodyWidth - chatWidth;
auto useOneColumnLayout = [this, bodyWidth, dialogsWidth] {
auto someSectionShown = !App::main()->selectingPeer() && App::main()->isSectionShown();
if (dialogsWidth < st::dialogsPadding.x() && (Adaptive::OneColumn() || someSectionShown)) {
if (dialogsWidth < st::dialogsPadding.x() && Adaptive::OneColumn()) {
return true;
}
if (bodyWidth < st::windowMinWidth + st::dialogsWidthMin) {
auto minimalNormal = st::columnMinimalWidthLeft
+ st::columnMinimalWidthMain;
if (bodyWidth < minimalNormal) {
return true;
}
return false;
@ -89,6 +103,18 @@ Controller::ColumnLayout Controller::computeColumnLayout() const {
return false;
};
auto useNormalLayout = [this, bodyWidth] {
// Used if useSmallColumnLayout() == false.
if (bodyWidth < minimalThreeColumnWidth()) {
return true;
}
if (!Auth().data().tabbedSelectorSectionEnabled()
&& !Auth().data().thirdSectionInfoEnabled()) {
return true;
}
return false;
};
if (useOneColumnLayout()) {
dialogsWidth = chatWidth = bodyWidth;
} else if (useSmallColumnLayout()) {
@ -99,7 +125,7 @@ Controller::ColumnLayout Controller::computeColumnLayout() const {
} else if (dialogsListFocused().value()) {
return true;
}
return !App::main()->isSectionShown();
return !App::main()->isMainSectionShown();
};
if (forceWideDialogs()) {
dialogsWidth = st::dialogsWidthMin;
@ -107,33 +133,81 @@ Controller::ColumnLayout Controller::computeColumnLayout() const {
dialogsWidth = dialogsSmallColumnWidth();
}
chatWidth = bodyWidth - dialogsWidth;
} else {
} else if (useNormalLayout()) {
layout = Adaptive::WindowLayout::Normal;
accumulate_max(dialogsWidth, st::dialogsWidthMin);
accumulate_max(dialogsWidth, st::columnMinimalWidthLeft);
chatWidth = bodyWidth - dialogsWidth;
} else {
layout = Adaptive::WindowLayout::ThreeColumn;
accumulate_max(dialogsWidth, st::columnMinimalWidthLeft);
thirdWidth = st::columnMinimalWidthThird;
accumulate_min(
dialogsWidth,
bodyWidth - thirdWidth - st::columnMinimalWidthMain);
chatWidth = bodyWidth - dialogsWidth - thirdWidth;
}
return { bodyWidth, dialogsWidth, chatWidth, layout };
return { bodyWidth, dialogsWidth, chatWidth, thirdWidth, layout };
}
bool Controller::canProvideChatWidth(int requestedWidth) const {
bool Controller::canShowThirdSection() const {
auto currentLayout = computeColumnLayout();
auto extendBy = requestedWidth - currentLayout.chatWidth;
auto extendBy = minimalThreeColumnWidth()
- currentLayout.bodyWidth;
if (extendBy <= 0) {
return true;
}
return window()->canExtendWidthBy(extendBy);
}
void Controller::provideChatWidth(int requestedWidth) {
auto currentLayout = computeColumnLayout();
auto extendBy = requestedWidth - currentLayout.chatWidth;
if (extendBy <= 0) {
void Controller::resizeForThirdSection() {
auto layout = computeColumnLayout();
if (layout.windowLayout == Adaptive::WindowLayout::ThreeColumn) {
return;
}
auto tabbedSelectorSectionEnabled =
Auth().data().tabbedSelectorSectionEnabled();
auto thirdSectionInfoEnabled =
Auth().data().thirdSectionInfoEnabled();
Auth().data().setTabbedSelectorSectionEnabled(false);
Auth().data().setThirdSectionInfoEnabled(false);
auto extendBy = st::columnMinimalWidthThird;
auto newBodyWidth = layout.bodyWidth + extendBy;
dialogsWidthRatio().set(
float64(layout.dialogsWidth) / newBodyWidth,
true);
window()->tryToExtendWidthBy(extendBy);
auto newLayout = computeColumnLayout();
if (newLayout.windowLayout != Adaptive::WindowLayout::OneColumn) {
dialogsWidthRatio().set(float64(newLayout.bodyWidth - requestedWidth) / newLayout.bodyWidth, true);
Auth().data().setTabbedSelectorSectionEnabled(
tabbedSelectorSectionEnabled);
Auth().data().setThirdSectionInfoEnabled(
thirdSectionInfoEnabled);
}
void Controller::closeThirdSection() {
auto newWindowSize = window()->size();
auto layout = computeColumnLayout();
if (layout.windowLayout == Adaptive::WindowLayout::ThreeColumn) {
auto noResize = window()->isFullScreen()
|| window()->isMaximized();
auto newBodyWidth = noResize
? layout.bodyWidth
: (layout.bodyWidth - layout.thirdWidth);
dialogsWidthRatio().set(
float64(layout.dialogsWidth) / newBodyWidth,
true);
newWindowSize = QSize(
window()->width() + (newBodyWidth - layout.bodyWidth),
window()->height());
}
Auth().data().setTabbedSelectorSectionEnabled(false);
Auth().data().setThirdSectionInfoEnabled(false);
Auth().saveDataDelayed(kThirdSectionInfoTimeoutMs);
if (window()->size() != newWindowSize) {
window()->resize(newWindowSize);
} else {
updateColumnLayout();
}
}
@ -184,15 +258,57 @@ void Controller::showJumpToDate(not_null<PeerData*> peer, QDate requestedDate) {
Ui::show(std::move(box));
}
void Controller::updateColumnLayout() {
App::main()->updateColumnLayout();
}
void Controller::showPeerHistory(
PeerId peerId,
Ui::ShowWay way,
MsgId msgId) {
Ui::showPeerHistory(peerId, msgId, way);
}
void Controller::showPeerHistory(
not_null<PeerData*> peer,
Ui::ShowWay way,
MsgId msgId) {
Ui::showPeerHistory(peer, msgId, way);
showPeerHistory(peer->id, way, msgId);
}
void Controller::showWideSection(SectionMemento &&memento) {
App::main()->showWideSection(std::move(memento));
void Controller::showPeerHistory(
not_null<History*> history,
Ui::ShowWay way,
MsgId msgId) {
showPeerHistory(history->peer->id, way, msgId);
}
void Controller::showPeerInfo(
PeerId peerId,
anim::type animated) {
if (Adaptive::ThreeColumn()) {
Auth().data().setThirdSectionInfoEnabled(true);
Auth().saveDataDelayed(kThirdSectionInfoTimeoutMs);
}
showSection(Info::Memento(peerId), animated);
}
void Controller::showPeerInfo(
not_null<PeerData*> peer,
anim::type animated) {
showPeerInfo(peer->id, animated);
}
void Controller::showPeerInfo(
not_null<History*> history,
anim::type animated) {
showPeerInfo(history->peer->id, animated);
}
void Controller::showSection(
SectionMemento &&memento,
anim::type animated) {
App::main()->showSection(std::move(memento), animated);
}
void Controller::showBackFromStack() {

View File

@ -78,12 +78,47 @@ public:
int bodyWidth;
int dialogsWidth;
int chatWidth;
int thirdWidth;
Adaptive::WindowLayout windowLayout;
};
ColumnLayout computeColumnLayout() const;
int dialogsSmallColumnWidth() const;
bool canProvideChatWidth(int requestedWidth) const;
void provideChatWidth(int requestedWidth);
void updateColumnLayout();
bool canShowThirdSection() const;
void resizeForThirdSection();
void closeThirdSection();
void showSection(
SectionMemento &&memento,
anim::type animated = anim::type::normal);
void showBackFromStack();
void showSpecialLayer(
object_ptr<LayerWidget> &&layer,
LayerOptions options = LayerOption::Animated);
void hideSpecialLayer(
LayerOptions options = LayerOption::Animated);
void showPeerHistory(
PeerId peerId,
Ui::ShowWay way = Ui::ShowWay::ClearStack,
MsgId msgId = ShowAtUnreadMsgId);
void showPeerHistory(
not_null<PeerData*> peer,
Ui::ShowWay way = Ui::ShowWay::ClearStack,
MsgId msgId = ShowAtUnreadMsgId);
void showPeerHistory(
not_null<History*> history,
Ui::ShowWay way = Ui::ShowWay::ClearStack,
MsgId msgId = ShowAtUnreadMsgId);
void showPeerInfo(
PeerId peerId,
anim::type animated = anim::type::normal);
void showPeerInfo(
not_null<PeerData*> peer,
anim::type animated = anim::type::normal);
void showPeerInfo(
not_null<History*> history,
anim::type animated = anim::type::normal);
void showJumpToDate(not_null<PeerData*> peer, QDate requestedDate);
@ -106,19 +141,8 @@ public:
return _dialogsListDisplayForced;
}
void showPeerHistory(
not_null<PeerData*> peer,
Ui::ShowWay way = Ui::ShowWay::ClearStack,
MsgId msgId = ShowAtUnreadMsgId);
void showWideSection(SectionMemento &&memento);
void showBackFromStack();
void showSpecialLayer(
object_ptr<LayerWidget> &&layer,
LayerOptions options = LayerOption::Animated);
void hideSpecialLayer(
LayerOptions options = LayerOption::Animated);
private:
int minimalThreeColumnWidth() const;
not_null<MainWidget*> chats() const;
not_null<MainWindow*> _window;