Add TabbedSection which uses the TabbedSelector.

This commit is contained in:
John Preston 2017-04-09 21:06:06 +03:00
parent 647ea44881
commit 891d200e2d
33 changed files with 713 additions and 405 deletions

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "apiwrap.h" #include "apiwrap.h"
#include "messenger.h" #include "messenger.h"
#include "storage/file_download.h" #include "storage/file_download.h"
#include "storage/localstorage.h"
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
QByteArray AuthSessionData::serialize() const { QByteArray AuthSessionData::serialize() const {
@ -40,6 +41,7 @@ QByteArray AuthSessionData::serialize() const {
stream.setVersion(QDataStream::Qt_5_1); stream.setVersion(QDataStream::Qt_5_1);
stream << static_cast<qint32>(_variables.emojiPanelTab); stream << static_cast<qint32>(_variables.emojiPanelTab);
stream << qint32(_variables.lastSeenWarningSeen ? 1 : 0); stream << qint32(_variables.lastSeenWarningSeen ? 1 : 0);
stream << qint32(_variables.tabbedSelectorSectionEnabled ? 1 : 0);
} }
return result; return result;
} }
@ -58,8 +60,12 @@ void AuthSessionData::constructFromSerialized(const QByteArray &serialized) {
stream.setVersion(QDataStream::Qt_5_1); stream.setVersion(QDataStream::Qt_5_1);
qint32 emojiPanTab = static_cast<qint32>(EmojiPanelTab::Emoji); qint32 emojiPanTab = static_cast<qint32>(EmojiPanelTab::Emoji);
qint32 lastSeenWarningSeen = 0; qint32 lastSeenWarningSeen = 0;
qint32 tabbedSelectorSectionEnabled = 1;
stream >> emojiPanTab; stream >> emojiPanTab;
stream >> lastSeenWarningSeen; stream >> lastSeenWarningSeen;
if (!stream.atEnd()) {
stream >> tabbedSelectorSectionEnabled;
}
if (stream.status() != QDataStream::Ok) { if (stream.status() != QDataStream::Ok) {
LOG(("App Error: Bad data for AuthSessionData::constructFromSerialized()")); LOG(("App Error: Bad data for AuthSessionData::constructFromSerialized()"));
return; return;
@ -72,6 +78,7 @@ void AuthSessionData::constructFromSerialized(const QByteArray &serialized) {
case EmojiPanelTab::Gifs: _variables.emojiPanelTab = uncheckedTab; break; case EmojiPanelTab::Gifs: _variables.emojiPanelTab = uncheckedTab; break;
} }
_variables.lastSeenWarningSeen = (lastSeenWarningSeen == 1); _variables.lastSeenWarningSeen = (lastSeenWarningSeen == 1);
_variables.tabbedSelectorSectionEnabled = (tabbedSelectorSectionEnabled == 1);
} }
AuthSession::AuthSession(UserId userId) AuthSession::AuthSession(UserId userId)
@ -80,6 +87,9 @@ AuthSession::AuthSession(UserId userId)
, _downloader(std::make_unique<Storage::Downloader>()) , _downloader(std::make_unique<Storage::Downloader>())
, _notifications(std::make_unique<Window::Notifications::System>(this)) { , _notifications(std::make_unique<Window::Notifications::System>(this)) {
Expects(_userId != 0); Expects(_userId != 0);
_saveDataTimer.setCallback([this] {
Local::writeUserSettings();
});
} }
bool AuthSession::Exists() { bool AuthSession::Exists() {
@ -109,4 +119,9 @@ bool AuthSession::validateSelf(const MTPUser &user) {
return true; return true;
} }
void AuthSession::saveDataDelayed(TimeMs delay) {
Expects(this == &AuthSession::Current());
_saveDataTimer.callOnce(delay);
}
AuthSession::~AuthSession() = default; AuthSession::~AuthSession() = default;

View File

@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
#include "base/timer.h"
namespace Storage { namespace Storage {
class Downloader; class Downloader;
} // namespace Storage } // namespace Storage
@ -71,11 +73,18 @@ public:
void setEmojiPanelTab(EmojiPanelTab tab) { void setEmojiPanelTab(EmojiPanelTab tab) {
_variables.emojiPanelTab = tab; _variables.emojiPanelTab = tab;
} }
bool tabbedSelectorSectionEnabled() const {
return _variables.tabbedSelectorSectionEnabled;
}
void setTabbedSelectorSectionEnabled(bool enabled) {
_variables.tabbedSelectorSectionEnabled = enabled;
}
private: private:
struct Variables { struct Variables {
bool lastSeenWarningSeen = false; bool lastSeenWarningSeen = false;
EmojiPanelTab emojiPanelTab = EmojiPanelTab::Emoji; EmojiPanelTab emojiPanelTab = EmojiPanelTab::Emoji;
bool tabbedSelectorSectionEnabled = true;
}; };
base::Variable<bool> _contactsLoaded = { false }; base::Variable<bool> _contactsLoaded = { false };
@ -122,6 +131,7 @@ public:
AuthSessionData &data() { AuthSessionData &data() {
return _data; return _data;
} }
void saveDataDelayed(TimeMs delay);
ApiWrap &api() { ApiWrap &api() {
return *_api; return *_api;
@ -132,6 +142,7 @@ public:
private: private:
const UserId _userId = 0; const UserId _userId = 0;
AuthSessionData _data; AuthSessionData _data;
base::Timer _saveDataTimer;
const std::unique_ptr<ApiWrap> _api; const std::unique_ptr<ApiWrap> _api;
const std::unique_ptr<Storage::Downloader> _downloader; const std::unique_ptr<Storage::Downloader> _downloader;

View File

@ -107,7 +107,11 @@ stickersSettingsUnreadPosition: point(4px, 5px);
emojiPanMargins: margins(10px, 10px, 10px, 10px); emojiPanMargins: margins(10px, 10px, 10px, 10px);
emojiTabs: defaultTabsSlider; emojiTabs: SettingsSlider(defaultTabsSlider) {
height: 55px;
barTop: 52px;
labelTop: 19px;
}
emojiScroll: defaultSolidScroll; emojiScroll: defaultSolidScroll;
emojiRecent: icon {{ "emoji_recent", emojiIconFg }}; emojiRecent: icon {{ "emoji_recent", emojiIconFg }};
emojiRecentActive: icon {{ "emoji_recent", emojiIconFgActive }}; emojiRecentActive: icon {{ "emoji_recent", emojiIconFgActive }};

View File

@ -103,7 +103,10 @@ void GifsListWidget::Footer::stealFocus() {
void GifsListWidget::Footer::returnFocus() { void GifsListWidget::Footer::returnFocus() {
if (_focusTakenFrom) { if (_focusTakenFrom) {
_focusTakenFrom->setFocus(); if (_field->hasFocus()) {
_focusTakenFrom->setFocus();
}
_focusTakenFrom = nullptr;
} }
} }

View File

@ -54,7 +54,7 @@ struct StickerIcon {
}; };
class StickersListWidget::Footer : public TabbedSelector::InnerFooter { class StickersListWidget::Footer : public TabbedSelector::InnerFooter, private base::Subscriber {
public: public:
Footer(gsl::not_null<StickersListWidget*> parent); Footer(gsl::not_null<StickersListWidget*> parent);
@ -112,6 +112,10 @@ StickersListWidget::Footer::Footer(gsl::not_null<StickersListWidget*> parent) :
setMouseTracking(true); setMouseTracking(true);
_iconsLeft = (st::emojiPanWidth - kVisibleIconsCount * st::emojiCategory.width) / 2; _iconsLeft = (st::emojiPanWidth - kVisibleIconsCount * st::emojiCategory.width) / 2;
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] {
update();
});
} }
template <typename Callback> template <typename Callback>
@ -905,13 +909,13 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
emit selected(set.pack[sticker->index]); emit selected(set.pack[sticker->index]);
} else if (auto set = base::get_if<OverSet>(&pressed)) { } else if (auto set = base::get_if<OverSet>(&pressed)) {
t_assert(set->section >= 0 && set->section < sets.size()); t_assert(set->section >= 0 && set->section < sets.size());
emit displaySet(sets[set->section].id); displaySet(sets[set->section].id);
} else if (auto button = base::get_if<OverButton>(&pressed)) { } else if (auto button = base::get_if<OverButton>(&pressed)) {
t_assert(button->section >= 0 && button->section < sets.size()); t_assert(button->section >= 0 && button->section < sets.size());
if (_section == Section::Featured) { if (_section == Section::Featured) {
emit installSet(sets[button->section].id); installSet(sets[button->section].id);
} else { } else {
emit removeSet(sets[button->section].id); removeSet(sets[button->section].id);
} }
} }
} }
@ -1385,22 +1389,22 @@ void StickersListWidget::installSet(quint64 setId) {
void StickersListWidget::removeSet(quint64 setId) { void StickersListWidget::removeSet(quint64 setId) {
auto &sets = Global::StickerSets(); auto &sets = Global::StickerSets();
auto it = sets.constFind(setId); auto it = sets.constFind(setId);
if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) { if (it != sets.cend()) {
_removingSetId = it->id; _removingSetId = it->id;
auto text = lng_stickers_remove_pack(lt_sticker_pack, it->title); auto text = lng_stickers_remove_pack(lt_sticker_pack, it->title);
Ui::show(Box<ConfirmBox>(text, lang(lng_box_remove), base::lambda_guarded(this, [this] { Ui::show(Box<ConfirmBox>(text, lang(lng_box_remove), base::lambda_guarded(this, [this] {
Ui::hideLayer(); Ui::hideLayer();
auto &sets = Global::RefStickerSets(); auto &sets = Global::RefStickerSets();
auto it = sets.find(_removingSetId); auto it = sets.find(_removingSetId);
if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) { if (it != sets.cend()) {
if (it->id && it->access) { if (it->id && it->access) {
request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)))).send(); request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)))).send();
} else if (!it->shortName.isEmpty()) { } else if (!it->shortName.isEmpty()) {
request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetShortName(MTP_string(it->shortName)))).send(); request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetShortName(MTP_string(it->shortName)))).send();
} }
bool writeRecent = false; auto writeRecent = false;
RecentStickerPack &recent(cGetRecentStickers()); auto &recent = cGetRecentStickers();
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) { for (auto i = recent.begin(); i != recent.cend();) {
if (it->stickers.indexOf(i->first) >= 0) { if (it->stickers.indexOf(i->first) >= 0) {
i = recent.erase(i); i = recent.erase(i);
writeRecent = true; writeRecent = true;

View File

@ -33,8 +33,12 @@ constexpr auto kDelayedHideTimeoutMs = 3000;
} // namespace } // namespace
TabbedPanel::TabbedPanel(QWidget *parent, gsl::not_null<Window::Controller*> controller) : TWidget(parent) TabbedPanel::TabbedPanel(QWidget *parent, gsl::not_null<Window::Controller*> controller) : TabbedPanel(parent, controller, object_ptr<TabbedSelector>(nullptr, controller)) {
, _selector(this, controller) { }
TabbedPanel::TabbedPanel(QWidget *parent, gsl::not_null<Window::Controller*> controller, object_ptr<TabbedSelector> selector) : TWidget(parent)
, _selector(std::move(selector)) {
_selector->setParent(this);
_selector->setRoundRadius(st::buttonRadius); _selector->setRoundRadius(st::buttonRadius);
resize(QRect(0, 0, st::emojiPanWidth, st::emojiPanMaxHeight).marginsAdded(innerPadding()).size()); resize(QRect(0, 0, st::emojiPanWidth, st::emojiPanMaxHeight).marginsAdded(innerPadding()).size());
@ -47,11 +51,11 @@ TabbedPanel::TabbedPanel(QWidget *parent, gsl::not_null<Window::Controller*> con
_hideTimer.setCallback([this] { hideByTimerOrLeave(); }); _hideTimer.setCallback([this] { hideByTimerOrLeave(); });
connect(_selector, SIGNAL(checkForHide()), this, SLOT(onCheckForHide())); connect(_selector, &TabbedSelector::checkForHide, this, [this] {
connect(_selector, SIGNAL(emojiSelected(EmojiPtr)), this, SIGNAL(emojiSelected(EmojiPtr))); if (!rect().contains(mapFromGlobal(QCursor::pos()))) {
connect(_selector, SIGNAL(stickerSelected(DocumentData*)), this, SIGNAL(stickerSelected(DocumentData*))); _hideTimer.callOnce(kDelayedHideTimeoutMs);
connect(_selector, SIGNAL(photoSelected(PhotoData*)), this, SIGNAL(photoSelected(PhotoData*))); }
connect(_selector, SIGNAL(inlineResultSelected(InlineBots::Result*,UserData*)), this, SIGNAL(inlineResultSelected(InlineBots::Result*,UserData*))); });
connect(_selector, &TabbedSelector::cancelled, this, [this] { connect(_selector, &TabbedSelector::cancelled, this, [this] {
hideAnimated(); hideAnimated();
}); });
@ -77,6 +81,10 @@ void TabbedPanel::moveBottom(int bottom) {
} }
void TabbedPanel::updateContentHeight() { void TabbedPanel::updateContentHeight() {
if (isDestroying()) {
return;
}
auto addedHeight = innerPadding().top() + innerPadding().bottom(); auto addedHeight = innerPadding().top() + innerPadding().bottom();
auto wantedContentHeight = qRound(st::emojiPanHeightRatio * _bottom) - addedHeight; auto wantedContentHeight = qRound(st::emojiPanHeightRatio * _bottom) - addedHeight;
auto contentHeight = snap(wantedContentHeight, st::emojiPanMinHeight, st::emojiPanMaxHeight); auto contentHeight = snap(wantedContentHeight, st::emojiPanMinHeight, st::emojiPanMaxHeight);
@ -98,8 +106,8 @@ void TabbedPanel::updateContentHeight() {
} }
void TabbedPanel::onWndActiveChanged() { void TabbedPanel::onWndActiveChanged() {
if (!App::wnd()->windowHandle()->isActive() && !isHidden()) { if (!App::wnd()->windowHandle()->isActive() && !isHidden() && !preventAutoHide()) {
leaveEvent(0); hideAnimated();
} }
} }
@ -114,7 +122,7 @@ void TabbedPanel::paintEvent(QPaintEvent *e) {
auto showAnimating = _a_show.animating(ms); auto showAnimating = _a_show.animating(ms);
if (_showAnimation && !showAnimating) { if (_showAnimation && !showAnimating) {
_showAnimation.reset(); _showAnimation.reset();
if (!opacityAnimating) { if (!opacityAnimating && !isDestroying()) {
showChildren(); showChildren();
_selector->afterShown(); _selector->afterShown();
} }
@ -146,6 +154,9 @@ void TabbedPanel::enterEventHook(QEvent *e) {
} }
bool TabbedPanel::preventAutoHide() const { bool TabbedPanel::preventAutoHide() const {
if (isDestroying()) {
return false;
}
return _selector->preventAutoHide(); return _selector->preventAutoHide();
} }
@ -188,14 +199,10 @@ void TabbedPanel::hideFast() {
hideFinished(); hideFinished();
} }
void TabbedPanel::refreshStickers() {
_selector->refreshStickers();
}
void TabbedPanel::opacityAnimationCallback() { void TabbedPanel::opacityAnimationCallback() {
update(); update();
if (!_a_opacity.animating()) { if (!_a_opacity.animating()) {
if (_hiding) { if (_hiding || isDestroying()) {
_hiding = false; _hiding = false;
hideFinished(); hideFinished();
} else if (!_a_show.animating()) { } else if (!_a_show.animating()) {
@ -226,7 +233,7 @@ void TabbedPanel::prepareCache() {
} }
void TabbedPanel::startOpacityAnimation(bool hiding) { void TabbedPanel::startOpacityAnimation(bool hiding) {
if (!_selector->isHidden()) { if (_selector && !_selector->isHidden()) {
_selector->beforeHiding(); _selector->beforeHiding();
} }
_hiding = false; _hiding = false;
@ -259,12 +266,13 @@ QImage TabbedPanel::grabForAnimation() {
showChildren(); showChildren();
myEnsureResized(this); myEnsureResized(this);
myEnsureResized(_selector);
auto result = QImage(size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); auto result = QImage(size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
result.setDevicePixelRatio(cRetinaFactor()); result.setDevicePixelRatio(cRetinaFactor());
result.fill(Qt::transparent); result.fill(Qt::transparent);
_selector->render(&result, _selector->geometry().topLeft()); if (_selector) {
_selector->render(&result, _selector->geometry().topLeft());
}
_a_show = base::take(showAnimation); _a_show = base::take(showAnimation);
_showAnimation = base::take(showAnimationData); _showAnimation = base::take(showAnimationData);
@ -275,26 +283,50 @@ QImage TabbedPanel::grabForAnimation() {
} }
void TabbedPanel::hideAnimated() { void TabbedPanel::hideAnimated() {
if (isHidden()) return; if (isHidden() || _hiding) {
if (_hiding) return; return;
}
_hideTimer.cancel(); _hideTimer.cancel();
if (_selector->isSliding()) { if (!isDestroying() && _selector->isSliding()) {
_hideAfterSlide = true; _hideAfterSlide = true;
} else { } else {
startOpacityAnimation(true); startOpacityAnimation(true);
} }
} }
TabbedPanel::~TabbedPanel() = default; void TabbedPanel::toggleAnimated() {
if (isDestroying()) {
return;
}
if (isHidden() || _hiding || _hideAfterSlide) {
showAnimated();
} else {
hideAnimated();
}
}
object_ptr<TabbedSelector> TabbedPanel::takeSelector() {
auto result = std::move(_selector);
hideAnimated();
return result;
}
QPointer<TabbedSelector> TabbedPanel::getSelector() const {
return _selector.data();
}
void TabbedPanel::hideFinished() { void TabbedPanel::hideFinished() {
hide(); hide();
_selector->hideFinished();
_a_show.finish(); _a_show.finish();
_showAnimation.reset(); _showAnimation.reset();
_cache = QPixmap(); _cache = QPixmap();
_hiding = false; _hiding = false;
if (isDestroying()) {
deleteLater();
} else {
_selector->hideFinished();
}
} }
void TabbedPanel::showAnimated() { void TabbedPanel::showAnimated() {
@ -304,6 +336,9 @@ void TabbedPanel::showAnimated() {
} }
void TabbedPanel::showStarted() { void TabbedPanel::showStarted() {
if (isDestroying()) {
return;
}
if (isHidden()) { if (isHidden()) {
_selector->showStarted(); _selector->showStarted();
moveByBottom(); moveByBottom();
@ -315,21 +350,21 @@ void TabbedPanel::showStarted() {
} }
bool TabbedPanel::eventFilter(QObject *obj, QEvent *e) { bool TabbedPanel::eventFilter(QObject *obj, QEvent *e) {
if (isDestroying()) {
return false;
}
if (e->type() == QEvent::Enter) { if (e->type() == QEvent::Enter) {
otherEnter(); otherEnter();
} else if (e->type() == QEvent::Leave) { } else if (e->type() == QEvent::Leave) {
otherLeave(); otherLeave();
} else if (e->type() == QEvent::MouseButtonPress && static_cast<QMouseEvent*>(e)->button() == Qt::LeftButton/* && !dynamic_cast<StickerPan*>(obj)*/) {
if (isHidden() || _hiding || _hideAfterSlide) {
showAnimated();
} else {
hideAnimated();
}
} }
return false; return false;
} }
void TabbedPanel::stickersInstalled(uint64 setId) { void TabbedPanel::stickersInstalled(uint64 setId) {
if (isDestroying()) {
return;
}
_selector->stickersInstalled(setId); _selector->stickersInstalled(setId);
if (isHidden()) { if (isHidden()) {
moveByBottom(); moveByBottom();
@ -340,10 +375,6 @@ void TabbedPanel::stickersInstalled(uint64 setId) {
showAnimated(); showAnimated();
} }
void TabbedPanel::setInlineQueryPeer(PeerData *peer) {
_selector->setInlineQueryPeer(peer);
}
style::margins TabbedPanel::innerPadding() const { style::margins TabbedPanel::innerPadding() const {
return st::emojiPanMargins; return st::emojiPanMargins;
} }
@ -360,12 +391,6 @@ QRect TabbedPanel::verticalRect() const {
return innerRect().marginsRemoved(style::margins(st::buttonRadius, 0, st::buttonRadius, 0)); return innerRect().marginsRemoved(style::margins(st::buttonRadius, 0, st::buttonRadius, 0));
} }
void TabbedPanel::onCheckForHide() {
if (!rect().contains(mapFromGlobal(QCursor::pos()))) {
_hideTimer.callOnce(kDelayedHideTimeoutMs);
}
}
bool TabbedPanel::overlaps(const QRect &globalRect) const { bool TabbedPanel::overlaps(const QRect &globalRect) const {
if (isHidden() || !_cache.isNull()) return false; if (isHidden() || !_cache.isNull()) return false;
@ -375,4 +400,6 @@ bool TabbedPanel::overlaps(const QRect &globalRect) const {
|| inner.marginsRemoved(QMargins(0, st::buttonRadius, 0, st::buttonRadius)).contains(testRect); || inner.marginsRemoved(QMargins(0, st::buttonRadius, 0, st::buttonRadius)).contains(testRect);
} }
TabbedPanel::~TabbedPanel() = default;
} // namespace ChatHelpers } // namespace ChatHelpers

View File

@ -21,19 +21,16 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once #pragma once
#include "ui/twidget.h" #include "ui/twidget.h"
#include "ui/effects/panel_animation.h"
#include "mtproto/sender.h"
#include "auth_session.h"
#include "base/timer.h" #include "base/timer.h"
namespace InlineBots {
class Result;
} // namespace InlineBots
namespace Window { namespace Window {
class Controller; class Controller;
} // namespace Window } // namespace Window
namespace Ui {
class PanelAnimation;
} // namespace Ui
namespace ChatHelpers { namespace ChatHelpers {
class TabbedSelector; class TabbedSelector;
@ -43,7 +40,10 @@ class TabbedPanel : public TWidget {
public: public:
TabbedPanel(QWidget *parent, gsl::not_null<Window::Controller*> controller); TabbedPanel(QWidget *parent, gsl::not_null<Window::Controller*> controller);
TabbedPanel(QWidget *parent, gsl::not_null<Window::Controller*> controller, object_ptr<TabbedSelector> selector);
object_ptr<TabbedSelector> takeSelector();
QPointer<TabbedSelector> getSelector() const;
void moveBottom(int bottom); void moveBottom(int bottom);
void hideFast(); void hideFast();
@ -54,12 +54,10 @@ public:
void stickersInstalled(uint64 setId); void stickersInstalled(uint64 setId);
bool overlaps(const QRect &globalRect) const; bool overlaps(const QRect &globalRect) const;
void setInlineQueryPeer(PeerData *peer);
void showAnimated(); void showAnimated();
void hideAnimated(); void hideAnimated();
void toggleAnimated();
void refreshStickers();
~TabbedPanel(); ~TabbedPanel();
@ -74,19 +72,13 @@ protected:
private slots: private slots:
void onWndActiveChanged(); void onWndActiveChanged();
void onCheckForHide();
signals:
void emojiSelected(EmojiPtr emoji);
void stickerSelected(DocumentData *sticker);
void photoSelected(PhotoData *photo);
void inlineResultSelected(InlineBots::Result *result, UserData *bot);
void updateStickers();
private: private:
void hideByTimerOrLeave(); void hideByTimerOrLeave();
void moveByBottom(); void moveByBottom();
bool isDestroying() const {
return !_selector;
}
style::margins innerPadding() const; style::margins innerPadding() const;

View File

@ -20,3 +20,54 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/ */
#include "chat_helpers/tabbed_section.h" #include "chat_helpers/tabbed_section.h"
#include "styles/style_chat_helpers.h"
#include "chat_helpers/tabbed_selector.h"
namespace ChatHelpers {
TabbedSection::TabbedSection(QWidget *parent, gsl::not_null<Window::Controller*> controller) : TabbedSection(parent, controller, object_ptr<TabbedSelector>(this, controller)) {
}
TabbedSection::TabbedSection(QWidget *parent, gsl::not_null<Window::Controller*> controller, object_ptr<TabbedSelector> selector) : TWidget(parent)
, _selector(std::move(selector)) {
resize(st::emojiPanWidth, st::emojiPanMaxHeight);
_selector->setParent(this);
_selector->setRoundRadius(0);
_selector->setGeometry(rect());
_selector->showStarted();
_selector->show();
connect(_selector, &TabbedSelector::cancelled, this, [this] {
if (_cancelledCallback) {
_cancelledCallback();
}
});
setAttribute(Qt::WA_OpaquePaintEvent, true);
}
void TabbedSection::beforeHiding() {
_selector->beforeHiding();
}
void TabbedSection::afterShown() {
_selector->afterShown();
}
void TabbedSection::resizeEvent(QResizeEvent *e) {
_selector->setGeometry(rect());
}
object_ptr<TabbedSelector> TabbedSection::takeSelector() {
return std::move(_selector);
}
QPointer<TabbedSelector> TabbedSection::getSelector() const {
return _selector.data();
}
void TabbedSection::stickersInstalled(uint64 setId) {
_selector->stickersInstalled(setId);
}
} // namespace ChatHelpers

View File

@ -19,3 +19,40 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
#include "ui/twidget.h"
namespace Window {
class Controller;
} // namespace Window
namespace ChatHelpers {
class TabbedSelector;
class TabbedSection : public TWidget {
public:
TabbedSection(QWidget *parent, gsl::not_null<Window::Controller*> controller);
TabbedSection(QWidget *parent, gsl::not_null<Window::Controller*> controller, object_ptr<TabbedSelector> selector);
void beforeHiding();
void afterShown();
void setCancelledCallback(base::lambda<void()> callback) {
_cancelledCallback = std::move(callback);
}
object_ptr<TabbedSelector> takeSelector();
QPointer<TabbedSelector> getSelector() const;
void stickersInstalled(uint64 setId);
protected:
void resizeEvent(QResizeEvent *e) override;
private:
object_ptr<TabbedSelector> _selector;
base::lambda<void()> _cancelledCallback;
};
} // namespace ChatHelpers

View File

@ -292,28 +292,35 @@ TabbedSelector::TabbedSelector(QWidget *parent, gsl::not_null<Window::Controller
, _currentTabType(AuthSession::Current().data().emojiPanelTab()) { , _currentTabType(AuthSession::Current().data().emojiPanelTab()) {
resize(st::emojiPanWidth, st::emojiPanMaxHeight); resize(st::emojiPanWidth, st::emojiPanMaxHeight);
for (auto &tab : _tabs) {
tab.footer()->hide();
tab.widget()->hide();
}
createTabsSlider(); createTabsSlider();
_scroll->resize(st::emojiPanWidth - st::buttonRadius, height() - marginTop() - marginBottom()); _scroll->setGeometryToLeft(st::buttonRadius, marginTop(), st::emojiPanWidth - st::buttonRadius, height() - marginTop() - marginBottom());
_scroll->move(st::buttonRadius, marginTop());
setWidgetToScrollArea(); setWidgetToScrollArea();
_bottomShadow->setGeometry(_tabsSlider->x(), _scroll->y() + _scroll->height() - st::lineWidth, _tabsSlider->width(), st::lineWidth); _bottomShadow->setGeometry(_tabsSlider->x(), _scroll->y() + _scroll->height() - st::lineWidth, _tabsSlider->width(), st::lineWidth);
for (auto &tab : _tabs) { for (auto &tab : _tabs) {
connect(tab.widget(), &Inner::scrollToY, this, [this, tab = &tab](int y) { auto widget = tab.widget();
connect(widget, &Inner::scrollToY, this, [this, tab = &tab](int y) {
if (tab == currentTab()) { if (tab == currentTab()) {
scrollToY(y); scrollToY(y);
} else { } else {
tab->saveScrollTop(y); tab->saveScrollTop(y);
} }
}); });
connect(tab.widget(), &Inner::disableScroll, this, [this, tab = &tab](bool disabled) { connect(widget, &Inner::disableScroll, this, [this, tab = &tab](bool disabled) {
if (tab == currentTab()) { if (tab == currentTab()) {
_scroll->disableScroll(disabled); _scroll->disableScroll(disabled);
} }
}); });
connect(tab.widget(), SIGNAL(saveConfigDelayed(int)), this, SLOT(onSaveConfigDelayed(int))); connect(widget, &Inner::saveConfigDelayed, this, [this](int delay) {
AuthSession::Current().saveDataDelayed(delay);
});
} }
connect(stickers(), SIGNAL(scrollUpdated()), this, SLOT(onScroll())); connect(stickers(), SIGNAL(scrollUpdated()), this, SLOT(onScroll()));
@ -326,8 +333,6 @@ TabbedSelector::TabbedSelector(QWidget *parent, gsl::not_null<Window::Controller
connect(gifs(), SIGNAL(selected(InlineBots::Result*, UserData*)), this, SIGNAL(inlineResultSelected(InlineBots::Result*, UserData*))); connect(gifs(), SIGNAL(selected(InlineBots::Result*, UserData*)), this, SIGNAL(inlineResultSelected(InlineBots::Result*, UserData*)));
connect(gifs(), SIGNAL(cancelled()), this, SIGNAL(cancelled())); connect(gifs(), SIGNAL(cancelled()), this, SIGNAL(cancelled()));
_saveConfigTimer.setCallback([this] { Local::writeUserSettings(); });
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWndActiveChanged())); connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWndActiveChanged()));
} }
@ -338,8 +343,7 @@ TabbedSelector::TabbedSelector(QWidget *parent, gsl::not_null<Window::Controller
// setAttribute(Qt::WA_AcceptTouchEvents); // setAttribute(Qt::WA_AcceptTouchEvents);
setAttribute(Qt::WA_OpaquePaintEvent, false); setAttribute(Qt::WA_OpaquePaintEvent, false);
showAll();
hideChildren();
} }
void TabbedSelector::resizeEvent(QResizeEvent *e) { void TabbedSelector::resizeEvent(QResizeEvent *e) {
@ -363,10 +367,6 @@ void TabbedSelector::resizeEvent(QResizeEvent *e) {
update(); update();
} }
void TabbedSelector::onSaveConfigDelayed(int delay) {
_saveConfigTimer.callOnce(delay);
}
void TabbedSelector::paintEvent(QPaintEvent *e) { void TabbedSelector::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
@ -593,7 +593,7 @@ void TabbedSelector::switchTab() {
update(); update();
AuthSession::Current().data().setEmojiPanelTab(_currentTabType); AuthSession::Current().data().setEmojiPanelTab(_currentTabType);
onSaveConfigDelayed(kSaveChosenTabTimeout); AuthSession::Current().saveDataDelayed(kSaveChosenTabTimeout);
} }
gsl::not_null<EmojiListWidget*> TabbedSelector::emoji() const { gsl::not_null<EmojiListWidget*> TabbedSelector::emoji() const {

View File

@ -24,7 +24,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/effects/panel_animation.h" #include "ui/effects/panel_animation.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "auth_session.h" #include "auth_session.h"
#include "base/timer.h"
namespace InlineBots { namespace InlineBots {
class Result; class Result;
@ -79,8 +78,6 @@ protected:
private slots: private slots:
void onScroll(); void onScroll();
void onSaveConfigDelayed(int delay);
signals: signals:
void emojiSelected(EmojiPtr emoji); void emojiSelected(EmojiPtr emoji);
void stickerSelected(DocumentData *sticker); void stickerSelected(DocumentData *sticker);
@ -176,8 +173,6 @@ private:
std::array<Tab, Tab::kCount> _tabs; std::array<Tab, Tab::kCount> _tabs;
TabType _currentTabType = TabType::Emoji; TabType _currentTabType = TabType::Emoji;
base::Timer _saveConfigTimer;
}; };
class TabbedSelector::Inner : public TWidget { class TabbedSelector::Inner : public TWidget {

View File

@ -74,7 +74,8 @@ struct DialogsInner::PeerSearchResult {
Dialogs::RippleRow row; Dialogs::RippleRow row;
}; };
DialogsInner::DialogsInner(QWidget *parent, QWidget *main) : SplittedWidget(parent) DialogsInner::DialogsInner(QWidget *parent, gsl::not_null<Window::Controller*> controller, QWidget *main) : SplittedWidget(parent)
, _controller(controller)
, _dialogs(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date)) , _dialogs(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date))
, _contactsNoDialogs(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name)) , _contactsNoDialogs(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
, _contacts(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name)) , _contacts(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
@ -1674,7 +1675,7 @@ void DialogsInner::refresh(bool toTop) {
emit mustScrollTo(0, 0); emit mustScrollTo(0, 0);
loadPeerPhotos(); loadPeerPhotos();
} }
Global::RefDialogsListDisplayForced().set(_searchInPeer || !_filter.isEmpty(), true); _controller->dialogsListDisplayForced().set(_searchInPeer || !_filter.isEmpty(), true);
update(); update();
} }
@ -1722,7 +1723,7 @@ void DialogsInner::searchInPeer(PeerData *peer) {
} else { } else {
_cancelSearchInPeer->hide(); _cancelSearchInPeer->hide();
} }
Global::RefDialogsListDisplayForced().set(_searchInPeer || !_filter.isEmpty(), true); _controller->dialogsListDisplayForced().set(_searchInPeer || !_filter.isEmpty(), true);
} }
void DialogsInner::clearFilter() { void DialogsInner::clearFilter() {
@ -2274,7 +2275,7 @@ DialogsWidget::DialogsWidget(QWidget *parent, gsl::not_null<Window::Controller*>
, _cancelSearch(this, st::dialogsCancelSearch) , _cancelSearch(this, st::dialogsCancelSearch)
, _lockUnlock(this, st::dialogsLock) , _lockUnlock(this, st::dialogsLock)
, _scroll(this, st::dialogsScroll) { , _scroll(this, st::dialogsScroll) {
_inner = _scroll->setOwnedWidget(object_ptr<DialogsInner>(this, parent)); _inner = _scroll->setOwnedWidget(object_ptr<DialogsInner>(this, _controller, parent));
connect(_inner, SIGNAL(draggingScrollDelta(int)), this, SLOT(onDraggingScrollDelta(int))); connect(_inner, SIGNAL(draggingScrollDelta(int)), this, SLOT(onDraggingScrollDelta(int)));
connect(_inner, SIGNAL(mustScrollTo(int,int)), _scroll, SLOT(scrollToY(int,int))); connect(_inner, SIGNAL(mustScrollTo(int,int)), _scroll, SLOT(scrollToY(int,int)));
connect(_inner, SIGNAL(dialogMoved(int,int)), this, SLOT(onDialogMoved(int,int))); connect(_inner, SIGNAL(dialogMoved(int,int)), this, SLOT(onDialogMoved(int,int)));

View File

@ -58,7 +58,7 @@ class DialogsInner : public Ui::SplittedWidget, public RPCSender, private base::
Q_OBJECT Q_OBJECT
public: public:
DialogsInner(QWidget *parent, QWidget *main); DialogsInner(QWidget *parent, gsl::not_null<Window::Controller*> controller, QWidget *main);
void dialogsReceived(const QVector<MTPDialog> &dialogs); void dialogsReceived(const QVector<MTPDialog> &dialogs);
void addSavedPeersAfter(const QDateTime &date); void addSavedPeersAfter(const QDateTime &date);
@ -226,6 +226,8 @@ private:
void savePinnedOrder(); void savePinnedOrder();
void step_pinnedShifting(TimeMs ms, bool timer); void step_pinnedShifting(TimeMs ms, bool timer);
gsl::not_null<Window::Controller*> _controller;
DialogsList _dialogs; DialogsList _dialogs;
DialogsList _dialogsImportant; DialogsList _dialogsImportant;

View File

@ -682,10 +682,6 @@ struct Data {
base::Observable<void> UnreadCounterUpdate; base::Observable<void> UnreadCounterUpdate;
base::Observable<void> PeerChooseCancel; base::Observable<void> PeerChooseCancel;
float64 DialogsWidthRatio = 5. / 14;
base::Variable<bool> DialogsListFocused = { false };
base::Variable<bool> DialogsListDisplayForced = { false };
}; };
} // namespace internal } // namespace internal
@ -805,8 +801,4 @@ DefineRefVar(Global, base::Observable<HistoryItem*>, ItemRemoved);
DefineRefVar(Global, base::Observable<void>, UnreadCounterUpdate); DefineRefVar(Global, base::Observable<void>, UnreadCounterUpdate);
DefineRefVar(Global, base::Observable<void>, PeerChooseCancel); DefineRefVar(Global, base::Observable<void>, PeerChooseCancel);
DefineVar(Global, float64, DialogsWidthRatio);
DefineRefVar(Global, base::Variable<bool>, DialogsListFocused);
DefineRefVar(Global, base::Variable<bool>, DialogsListDisplayForced);
} // namespace Global } // namespace Global

View File

@ -391,10 +391,6 @@ DeclareRefVar(base::Observable<HistoryItem*>, ItemRemoved);
DeclareRefVar(base::Observable<void>, UnreadCounterUpdate); DeclareRefVar(base::Observable<void>, UnreadCounterUpdate);
DeclareRefVar(base::Observable<void>, PeerChooseCancel); DeclareRefVar(base::Observable<void>, PeerChooseCancel);
DeclareVar(float64, DialogsWidthRatio);
DeclareRefVar(base::Variable<bool>, DialogsListFocused);
DeclareRefVar(base::Variable<bool>, DialogsListDisplayForced);
} // namespace Global } // namespace Global
namespace Adaptive { namespace Adaptive {

File diff suppressed because it is too large Load Diff

View File

@ -58,6 +58,8 @@ class TopBarWidget;
namespace ChatHelpers { namespace ChatHelpers {
class TabbedPanel; class TabbedPanel;
class TabbedSection;
class TabbedSelector;
} // namespace ChatHelpers } // namespace ChatHelpers
class DragArea; class DragArea;
@ -476,6 +478,11 @@ private:
void fullPeerUpdated(PeerData *peer); void fullPeerUpdated(PeerData *peer);
void topBarClick(); void topBarClick();
void toggleTabbedSelectorMode();
void updateTabbedSelectorSectionShown();
void recountChatWidth();
int minimalWidthForTabbedSelectorSection() const;
void setReportSpamStatus(DBIPeerReportSpamStatus status);
void animationCallback(); void animationCallback();
void updateOverStates(QPoint pos); void updateOverStates(QPoint pos);
@ -529,6 +536,7 @@ private:
int _replyToNameVersion = 0; int _replyToNameVersion = 0;
void updateReplyToName(); void updateReplyToName();
int _chatWidth = 0;
MsgId _editMsgId = 0; MsgId _editMsgId = 0;
HistoryItem *_replyEditMsg = nullptr; HistoryItem *_replyEditMsg = nullptr;
@ -739,7 +747,7 @@ private:
bool showRecordButton() const; bool showRecordButton() const;
bool showInlineBotCancel() const; bool showInlineBotCancel() const;
object_ptr<ReportSpamPanel> _reportSpamPanel; object_ptr<ReportSpamPanel> _reportSpamPanel = { nullptr };
object_ptr<Ui::SendButton> _send; object_ptr<Ui::SendButton> _send;
object_ptr<Ui::FlatButton> _unblock; object_ptr<Ui::FlatButton> _unblock;
@ -749,7 +757,7 @@ private:
mtpRequestId _unblockRequest = 0; mtpRequestId _unblockRequest = 0;
mtpRequestId _reportSpamRequest = 0; mtpRequestId _reportSpamRequest = 0;
object_ptr<Ui::IconButton> _attachToggle; object_ptr<Ui::IconButton> _attachToggle;
object_ptr<Ui::EmojiButton> _attachEmoji; object_ptr<Ui::EmojiButton> _tabbedSelectorToggle;
object_ptr<Ui::IconButton> _botKeyboardShow; object_ptr<Ui::IconButton> _botKeyboardShow;
object_ptr<Ui::IconButton> _botKeyboardHide; object_ptr<Ui::IconButton> _botKeyboardHide;
object_ptr<Ui::IconButton> _botCommandStart; object_ptr<Ui::IconButton> _botCommandStart;
@ -781,6 +789,8 @@ private:
object_ptr<InlineBots::Layout::Widget> _inlineResults = { nullptr }; object_ptr<InlineBots::Layout::Widget> _inlineResults = { nullptr };
object_ptr<ChatHelpers::TabbedPanel> _tabbedPanel; object_ptr<ChatHelpers::TabbedPanel> _tabbedPanel;
object_ptr<ChatHelpers::TabbedSection> _tabbedSection = { nullptr };
QPointer<ChatHelpers::TabbedSelector> _tabbedSelector;
DragState _attachDrag = DragStateNone; DragState _attachDrag = DragStateNone;
object_ptr<DragArea> _attachDragDocument, _attachDragPhoto; object_ptr<DragArea> _attachDragDocument, _attachDragPhoto;
@ -814,6 +824,7 @@ private:
QTimer _saveDraftTimer, _saveCloudDraftTimer; QTimer _saveDraftTimer, _saveCloudDraftTimer;
object_ptr<Ui::PlainShadow> _topShadow; object_ptr<Ui::PlainShadow> _topShadow;
object_ptr<Ui::PlainShadow> _rightShadow = { nullptr };
bool _inGrab = false; bool _inGrab = false;
}; };

View File

@ -121,7 +121,6 @@ void Widget::changeLanguage(int32 languageId) {
} }
void Widget::setInnerFocus() { void Widget::setInnerFocus() {
Global::RefDialogsListFocused().set(false, true);
if (getStep()->animating()) { if (getStep()->animating()) {
setFocus(); setFocus();
} else { } else {

View File

@ -113,12 +113,15 @@ MainWidget::MainWidget(QWidget *parent, gsl::not_null<Window::Controller*> contr
subscribe(AuthSession::Current().api().fullPeerUpdated(), [this](PeerData *peer) { subscribe(AuthSession::Current().api().fullPeerUpdated(), [this](PeerData *peer) {
emit peerUpdated(peer); emit peerUpdated(peer);
}); });
subscribe(Global::RefDialogsListFocused(), [this](bool) { subscribe(_controller->dialogsListFocused(), [this](bool) {
updateDialogsWidthAnimated(); updateDialogsWidthAnimated();
}); });
subscribe(Global::RefDialogsListDisplayForced(), [this](bool) { subscribe(_controller->dialogsListDisplayForced(), [this](bool) {
updateDialogsWidthAnimated(); updateDialogsWidthAnimated();
}); });
subscribe(_controller->dialogsWidthRatio(), [this](float64) {
updateControlsGeometry();
});
QCoreApplication::instance()->installEventFilter(this); QCoreApplication::instance()->installEventFilter(this);
@ -2141,7 +2144,7 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, Ui::Show
} }
} }
Global::RefDialogsListFocused().set(false, true); _controller->dialogsListFocused().set(false, true);
_a_dialogsWidth.finish(); _a_dialogsWidth.finish();
bool back = (way == Ui::ShowWay::Backward || !peerId); bool back = (way == Ui::ShowWay::Backward || !peerId);
@ -2348,7 +2351,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
return; return;
} }
Global::RefDialogsListFocused().set(false, true); _controller->dialogsListFocused().set(false, true);
_a_dialogsWidth.finish(); _a_dialogsWidth.finish();
auto animatedShow = [this] { auto animatedShow = [this] {
@ -2411,9 +2414,10 @@ void MainWidget::showWideSection(const Window::SectionMemento &memento) {
showNewWideSection(&memento, false, true); showNewWideSection(&memento, false, true);
} }
Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarShadow) { Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarShadow, bool willHaveTabbedSection) {
Window::SectionSlideParams result; Window::SectionSlideParams result;
result.withTopBarShadow = willHaveTopBarShadow; result.withTopBarShadow = willHaveTopBarShadow;
result.withTabbedSection = willHaveTabbedSection;
if (selectingPeer() && Adaptive::OneColumn()) { if (selectingPeer() && Adaptive::OneColumn()) {
result.withTopBarShadow = false; result.withTopBarShadow = false;
} else if (_wideSection) { } else if (_wideSection) {
@ -2423,6 +2427,9 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarS
} else if (!_overview && !_history->peer()) { } else if (!_overview && !_history->peer()) {
result.withTopBarShadow = false; result.withTopBarShadow = false;
} }
if ((selectingPeer() && Adaptive::OneColumn()) || !_history->peer()) {
result.withTabbedSection = false;
}
if (_player) { if (_player) {
_player->hideShadow(); _player->hideShadow();
@ -2480,25 +2487,25 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarS
} }
Window::SectionSlideParams MainWidget::prepareWideSectionAnimation(Window::SectionWidget *section) { Window::SectionSlideParams MainWidget::prepareWideSectionAnimation(Window::SectionWidget *section) {
return prepareShowAnimation(section->hasTopBarShadow()); return prepareShowAnimation(section->hasTopBarShadow(), false);
} }
Window::SectionSlideParams MainWidget::prepareHistoryAnimation(PeerId historyPeerId) { Window::SectionSlideParams MainWidget::prepareHistoryAnimation(PeerId historyPeerId) {
return prepareShowAnimation(historyPeerId != 0); return prepareShowAnimation(historyPeerId != 0, historyPeerId != 0);
} }
Window::SectionSlideParams MainWidget::prepareOverviewAnimation() { Window::SectionSlideParams MainWidget::prepareOverviewAnimation() {
return prepareShowAnimation(true); return prepareShowAnimation(true, false);
} }
Window::SectionSlideParams MainWidget::prepareDialogsAnimation() { Window::SectionSlideParams MainWidget::prepareDialogsAnimation() {
return prepareShowAnimation(false); return prepareShowAnimation(false, false);
} }
void MainWidget::showNewWideSection(const Window::SectionMemento *memento, bool back, bool saveInStack) { void MainWidget::showNewWideSection(const Window::SectionMemento *memento, bool back, bool saveInStack) {
QPixmap animCache; QPixmap animCache;
Global::RefDialogsListFocused().set(false, true); _controller->dialogsListFocused().set(false, true);
_a_dialogsWidth.finish(); _a_dialogsWidth.finish();
auto newWideGeometry = QRect(_history->x(), _playerHeight, _history->width(), height() - _playerHeight); auto newWideGeometry = QRect(_history->x(), _playerHeight, _history->width(), height() - _playerHeight);
@ -3058,22 +3065,21 @@ bool MainWidget::eventFilter(QObject *o, QEvent *e) {
} else if (e->type() == QEvent::MouseButtonRelease) { } else if (e->type() == QEvent::MouseButtonRelease) {
_resizingSide = false; _resizingSide = false;
if (!Adaptive::OneColumn()) { if (!Adaptive::OneColumn()) {
Global::SetDialogsWidthRatio(float64(_dialogsWidth) / width()); _controller->dialogsWidthRatio().set(float64(_dialogsWidth) / width(), true);
} }
Local::writeUserSettings(); Local::writeUserSettings();
} else if (e->type() == QEvent::MouseMove && _resizingSide) { } else if (e->type() == QEvent::MouseMove && _resizingSide) {
auto newWidth = mouseLeft() - _resizingSideShift; auto newWidth = mouseLeft() - _resizingSideShift;
Global::SetDialogsWidthRatio(float64(newWidth) / width()); _controller->dialogsWidthRatio().set(float64(newWidth) / width(), true);
updateControlsGeometry();
} }
} else if (e->type() == QEvent::FocusIn) { } else if (e->type() == QEvent::FocusIn) {
if (auto widget = qobject_cast<QWidget*>(o)) { if (auto widget = qobject_cast<QWidget*>(o)) {
if (_history == widget || _history->isAncestorOf(widget) if (_history == widget || _history->isAncestorOf(widget)
|| (_overview && (_overview == widget || _overview->isAncestorOf(widget))) || (_overview && (_overview == widget || _overview->isAncestorOf(widget)))
|| (_wideSection && (_wideSection == widget || _wideSection->isAncestorOf(widget)))) { || (_wideSection && (_wideSection == widget || _wideSection->isAncestorOf(widget)))) {
Global::RefDialogsListFocused().set(false, false); _controller->dialogsListFocused().set(false);
} else if (_dialogs == widget || _dialogs->isAncestorOf(widget)) { } else if (_dialogs == widget || _dialogs->isAncestorOf(widget)) {
Global::RefDialogsListFocused().set(true, false); _controller->dialogsListFocused().set(true);
} }
} }
} else if (e->type() == QEvent::MouseButtonPress) { } else if (e->type() == QEvent::MouseButtonPress) {
@ -3094,62 +3100,14 @@ void MainWidget::handleAdaptiveLayoutUpdate() {
} }
void MainWidget::updateWindowAdaptiveLayout() { void MainWidget::updateWindowAdaptiveLayout() {
auto layout = Adaptive::WindowLayout::OneColumn; auto layout = _controller->computeColumnLayout();
_dialogsWidth = layout.dialogsWidth;
auto dialogsWidth = qRound(width() * Global::DialogsWidthRatio()); if (layout.windowLayout != Global::AdaptiveWindowLayout()) {
auto historyWidth = width() - dialogsWidth; Global::SetAdaptiveWindowLayout(layout.windowLayout);
accumulate_max(historyWidth, st::windowMinWidth);
dialogsWidth = width() - historyWidth;
auto useOneColumnLayout = [this, dialogsWidth] {
auto someSectionShown = !selectingPeer() && isSectionShown();
if (dialogsWidth < st::dialogsPadding.x() && (Adaptive::OneColumn() || someSectionShown)) {
return true;
}
if (width() < st::windowMinWidth + st::dialogsWidthMin) {
return true;
}
return false;
};
auto useSmallColumnLayout = [this, dialogsWidth] {
// used if useOneColumnLayout() == false.
if (dialogsWidth < st::dialogsWidthMin / 2) {
return true;
}
return false;
};
if (useOneColumnLayout()) {
dialogsWidth = width();
} else if (useSmallColumnLayout()) {
layout = Adaptive::WindowLayout::SmallColumn;
auto forceWideDialogs = [this] {
if (Global::DialogsListDisplayForced().value()) {
return true;
} else if (Global::DialogsListFocused().value()) {
return true;
}
return !isSectionShown();
};
if (forceWideDialogs()) {
dialogsWidth = st::dialogsWidthMin;
} else {
dialogsWidth = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPadding.x();
}
} else {
layout = Adaptive::WindowLayout::Normal;
accumulate_max(dialogsWidth, st::dialogsWidthMin);
}
_dialogsWidth = dialogsWidth;
if (layout != Global::AdaptiveWindowLayout()) {
Global::SetAdaptiveWindowLayout(layout);
Adaptive::Changed().notify(true); Adaptive::Changed().notify(true);
} }
} }
bool MainWidget::needBackButton() {
return isSectionShown();
}
bool MainWidget::paintTopBar(Painter &p, int decreaseWidth, TimeMs ms) { bool MainWidget::paintTopBar(Painter &p, int decreaseWidth, TimeMs ms) {
if (_overview) { if (_overview) {
return _overview->paintTopBar(p, decreaseWidth); return _overview->paintTopBar(p, decreaseWidth);

View File

@ -144,7 +144,7 @@ class MainWidget : public TWidget, public RPCSender, private base::Subscriber {
public: public:
MainWidget(QWidget *parent, gsl::not_null<Window::Controller*> controller); MainWidget(QWidget *parent, gsl::not_null<Window::Controller*> controller);
bool needBackButton(); bool isSectionShown() const;
// Temporary methods, while top bar was not done inside HistoryWidget / OverviewWidget. // Temporary methods, while top bar was not done inside HistoryWidget / OverviewWidget.
bool paintTopBar(Painter &, int decreaseWidth, TimeMs ms); bool paintTopBar(Painter &, int decreaseWidth, TimeMs ms);
@ -481,9 +481,8 @@ private:
void overviewLoaded(History *history, const MTPmessages_Messages &result, mtpRequestId req); void overviewLoaded(History *history, const MTPmessages_Messages &result, mtpRequestId req);
void mediaOverviewUpdated(const Notify::PeerUpdate &update); void mediaOverviewUpdated(const Notify::PeerUpdate &update);
Window::SectionSlideParams prepareShowAnimation(bool willHaveTopBarShadow); Window::SectionSlideParams prepareShowAnimation(bool willHaveTopBarShadow, bool willHaveTabbedSection);
void showNewWideSection(const Window::SectionMemento *memento, bool back, bool saveInStack); void showNewWideSection(const Window::SectionMemento *memento, bool back, bool saveInStack);
bool isSectionShown() const;
// All this methods use the prepareShowAnimation(). // All this methods use the prepareShowAnimation().
Window::SectionSlideParams prepareWideSectionAnimation(Window::SectionWidget *section); Window::SectionSlideParams prepareWideSectionAnimation(Window::SectionWidget *section);

View File

@ -110,15 +110,25 @@ MainWindow::MainWindow() {
connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock())); connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock()));
subscribe(Global::RefSelfChanged(), [this]() { updateGlobalMenu(); }); subscribe(Global::RefSelfChanged(), [this] { updateGlobalMenu(); });
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &data) { subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &data) {
themeUpdated(data); themeUpdated(data);
}); });
subscribe(Messenger::Instance().authSessionChanged(), [this] { checkAuthSession(); });
checkAuthSession();
setAttribute(Qt::WA_NoSystemBackground); setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_OpaquePaintEvent);
} }
void MainWindow::checkAuthSession() {
if (AuthSession::Exists()) {
_controller = std::make_unique<Window::Controller>(this);
} else {
_controller = nullptr;
}
}
void MainWindow::inactivePress(bool inactive) { void MainWindow::inactivePress(bool inactive) {
_inactivePress = inactive; _inactivePress = inactive;
if (_inactivePress) { if (_inactivePress) {
@ -200,7 +210,6 @@ void MainWindow::clearWidgetsHook() {
auto wasMain = (_main != nullptr); auto wasMain = (_main != nullptr);
_passcode.destroyDelayed(); _passcode.destroyDelayed();
_main.destroy(); _main.destroy();
_controller.reset();
_intro.destroy(); _intro.destroy();
if (wasMain) { if (wasMain) {
App::clearHistories(); App::clearHistories();
@ -352,7 +361,7 @@ void MainWindow::setupMain(const MTPUser *self) {
t_assert(AuthSession::Exists()); t_assert(AuthSession::Exists());
_controller = std::make_unique<Window::Controller>(this);
_main.create(bodyWidget(), controller()); _main.create(bodyWidget(), controller());
_main->show(); _main->show();
updateControlsGeometry(); updateControlsGeometry();

View File

@ -199,6 +199,7 @@ private slots:
void onWindowActiveChanged(); void onWindowActiveChanged();
private: private:
void checkAuthSession();
void showConnecting(const QString &text, const QString &reconnect = QString()); void showConnecting(const QString &text, const QString &reconnect = QString());
void hideConnecting(); void hideConnecting();

View File

@ -99,7 +99,7 @@ MediaView::MediaView(QWidget*) : TWidget(nullptr)
}); });
} }
}; };
subscribe(Messenger::Instance().authSessionChanged(), [this, subscribeToDownloadFinished] { subscribe(Messenger::Instance().authSessionChanged(), [subscribeToDownloadFinished] {
subscribeToDownloadFinished(); subscribeToDownloadFinished();
}); });
subscribeToDownloadFinished(); subscribeToDownloadFinished();

View File

@ -38,6 +38,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "history/history_location_manager.h" #include "history/history_location_manager.h"
#include "ui/widgets/tooltip.h" #include "ui/widgets/tooltip.h"
#include "storage/serialize_common.h" #include "storage/serialize_common.h"
#include "window/window_controller.h"
namespace { namespace {
@ -51,7 +52,7 @@ Messenger *Messenger::InstancePointer() {
struct Messenger::Private { struct Messenger::Private {
UserId authSessionUserId = 0; UserId authSessionUserId = 0;
std::unique_ptr<AuthSessionData> authSessionData; std::unique_ptr<Local::StoredAuthSession> storedAuthSession;
MTP::Instance::Config mtpConfig; MTP::Instance::Config mtpConfig;
MTP::AuthKeysList mtpKeysToDestroy; MTP::AuthKeysList mtpKeysToDestroy;
}; };
@ -220,14 +221,14 @@ void Messenger::setAuthSessionUserId(UserId userId) {
_private->authSessionUserId = userId; _private->authSessionUserId = userId;
} }
void Messenger::setAuthSessionData(std::unique_ptr<AuthSessionData> data) { void Messenger::setAuthSessionFromStorage(std::unique_ptr<Local::StoredAuthSession> data) {
Expects(!authSession()); Expects(!authSession());
_private->authSessionData = std::move(data); _private->storedAuthSession = std::move(data);
} }
AuthSessionData *Messenger::getAuthSessionData() { AuthSessionData *Messenger::getAuthSessionData() {
if (_private->authSessionUserId) { if (_private->authSessionUserId) {
return _private->authSessionData.get(); return _private->storedAuthSession ? &_private->storedAuthSession->data : nullptr;
} else if (AuthSession::Exists()) { } else if (AuthSession::Exists()) {
return &AuthSession::Current().data(); return &AuthSession::Current().data();
} }
@ -301,11 +302,15 @@ void Messenger::startMtp() {
if (_private->authSessionUserId) { if (_private->authSessionUserId) {
authSessionCreate(base::take(_private->authSessionUserId)); authSessionCreate(base::take(_private->authSessionUserId));
} }
if (_private->authSessionData) { if (_private->storedAuthSession) {
if (_authSession) { if (_authSession) {
_authSession->data().copyFrom(*_private->authSessionData); _authSession->data().copyFrom(_private->storedAuthSession->data);
if (auto window = App::wnd()) {
t_assert(window->controller() != nullptr);
window->controller()->dialogsWidthRatio().set(_private->storedAuthSession->dialogsWidthRatio);
}
} }
_private->authSessionData.reset(); _private->storedAuthSession.reset();
} }
} }
@ -613,14 +618,14 @@ void Messenger::onSwitchTestMode() {
void Messenger::authSessionCreate(UserId userId) { void Messenger::authSessionCreate(UserId userId) {
Expects(_mtproto != nullptr); Expects(_mtproto != nullptr);
_authSession = std::make_unique<AuthSession>(userId); _authSession = std::make_unique<AuthSession>(userId);
authSessionChanged().notify(); authSessionChanged().notify(true);
} }
void Messenger::authSessionDestroy() { void Messenger::authSessionDestroy() {
_authSession.reset(); _authSession.reset();
_private->authSessionData.reset(); _private->storedAuthSession.reset();
_private->authSessionUserId = 0; _private->authSessionUserId = 0;
authSessionChanged().notify(); authSessionChanged().notify(true);
} }
void Messenger::setInternalLinkDomain(const QString &domain) const { void Messenger::setInternalLinkDomain(const QString &domain) const {

View File

@ -33,6 +33,10 @@ class MainWidget;
class FileUploader; class FileUploader;
class Translator; class Translator;
namespace Local {
struct StoredAuthSession;
} // namespace Local
class Messenger final : public QObject, public RPCSender, private base::Subscriber { class Messenger final : public QObject, public RPCSender, private base::Subscriber {
Q_OBJECT Q_OBJECT
@ -62,7 +66,7 @@ public:
void setMtpMainDcId(MTP::DcId mainDcId); void setMtpMainDcId(MTP::DcId mainDcId);
void setMtpKey(MTP::DcId dcId, const MTP::AuthKey::Data &keyData); void setMtpKey(MTP::DcId dcId, const MTP::AuthKey::Data &keyData);
void setAuthSessionUserId(UserId userId); void setAuthSessionUserId(UserId userId);
void setAuthSessionData(std::unique_ptr<AuthSessionData> data); void setAuthSessionFromStorage(std::unique_ptr<Local::StoredAuthSession> data);
AuthSessionData *getAuthSessionData(); AuthSessionData *getAuthSessionData();
// Serialization. // Serialization.

View File

@ -29,6 +29,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "window/window_slide_animation.h" #include "window/window_slide_animation.h"
#include "window/window_controller.h"
#include "auth_session.h" #include "auth_session.h"
PasscodeWidget::PasscodeWidget(QWidget *parent) : TWidget(parent) PasscodeWidget::PasscodeWidget(QWidget *parent) : TWidget(parent)
@ -187,6 +188,8 @@ void PasscodeWidget::resizeEvent(QResizeEvent *e) {
} }
void PasscodeWidget::setInnerFocus() { void PasscodeWidget::setInnerFocus() {
Global::RefDialogsListFocused().set(false, true); if (auto controller = App::wnd()->controller()) {
controller->dialogsListFocused().set(false, true);
}
_passcode->setFocusFast(); _passcode->setFocusFast();
} }

View File

@ -35,6 +35,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "application.h" #include "application.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "auth_session.h" #include "auth_session.h"
#include "window/window_controller.h"
#include <openssl/evp.h> #include <openssl/evp.h>
@ -638,12 +639,12 @@ enum class WriteMapWhen {
Soon, Soon,
}; };
std::unique_ptr<AuthSessionData> AuthSessionDataCache; std::unique_ptr<StoredAuthSession> StoredAuthSessionCache;
AuthSessionData &GetAuthSessionDataCache() { StoredAuthSession &GetStoredAuthSessionCache() {
if (!AuthSessionDataCache) { if (!StoredAuthSessionCache) {
AuthSessionDataCache = std::make_unique<AuthSessionData>(); StoredAuthSessionCache = std::make_unique<StoredAuthSession>();
} }
return *AuthSessionDataCache; return *StoredAuthSessionCache;
} }
void _writeMap(WriteMapWhen when = WriteMapWhen::Soon); void _writeMap(WriteMapWhen when = WriteMapWhen::Soon);
@ -1010,7 +1011,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
if (!_checkStreamStatus(stream)) return false; if (!_checkStreamStatus(stream)) return false;
Global::SetDialogsModeEnabled(enabled == 1); Global::SetDialogsModeEnabled(enabled == 1);
Dialogs::Mode mode = Dialogs::Mode::All; auto mode = Dialogs::Mode::All;
if (enabled) { if (enabled) {
mode = static_cast<Dialogs::Mode>(modeInt); mode = static_cast<Dialogs::Mode>(modeInt);
if (mode != Dialogs::Mode::All && mode != Dialogs::Mode::Important) { if (mode != Dialogs::Mode::All && mode != Dialogs::Mode::Important) {
@ -1086,7 +1087,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
stream >> v; stream >> v;
if (!_checkStreamStatus(stream)) return false; if (!_checkStreamStatus(stream)) return false;
Global::SetDialogsWidthRatio(v / 1000000.); GetStoredAuthSessionCache().dialogsWidthRatio = v / 1000000.;
} break; } break;
case dbiLastSeenWarningSeenOld: { case dbiLastSeenWarningSeenOld: {
@ -1094,7 +1095,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
stream >> v; stream >> v;
if (!_checkStreamStatus(stream)) return false; if (!_checkStreamStatus(stream)) return false;
GetAuthSessionDataCache().setLastSeenWarningSeen(v == 1); GetStoredAuthSessionCache().data.setLastSeenWarningSeen(v == 1);
} break; } break;
case dbiAuthSessionData: { case dbiAuthSessionData: {
@ -1102,7 +1103,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
stream >> v; stream >> v;
if (!_checkStreamStatus(stream)) return false; if (!_checkStreamStatus(stream)) return false;
GetAuthSessionDataCache().constructFromSerialized(v); GetStoredAuthSessionCache().data.constructFromSerialized(v);
} break; } break;
case dbiWorkMode: { case dbiWorkMode: {
@ -1707,8 +1708,9 @@ void _writeUserSettings() {
recentEmojiPreloadData.push_back(qMakePair(item.first->id(), item.second)); recentEmojiPreloadData.push_back(qMakePair(item.first->id(), item.second));
} }
} }
auto userDataInstance = AuthSessionDataCache ? AuthSessionDataCache.get() : Messenger::Instance().getAuthSessionData(); auto userDataInstance = StoredAuthSessionCache ? &StoredAuthSessionCache->data : Messenger::Instance().getAuthSessionData();
auto userData = userDataInstance ? userDataInstance->serialize() : QByteArray(); auto userData = userDataInstance ? userDataInstance->serialize() : QByteArray();
auto dialogsWidthRatio = StoredAuthSessionCache ? StoredAuthSessionCache->dialogsWidthRatio : (App::wnd() ? App::wnd()->controller()->dialogsWidthRatio().value() : Window::Controller::kDefaultDialogsWidthRatio);
uint32 size = 21 * (sizeof(quint32) + sizeof(qint32)); uint32 size = 21 * (sizeof(quint32) + sizeof(qint32));
size += sizeof(quint32) + Serialize::stringSize(Global::AskDownloadPath() ? QString() : Global::DownloadPath()) + Serialize::bytearraySize(Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark()); size += sizeof(quint32) + Serialize::stringSize(Global::AskDownloadPath() ? QString() : Global::DownloadPath()) + Serialize::bytearraySize(Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark());
@ -1753,7 +1755,7 @@ void _writeUserSettings() {
data.stream << quint32(dbiDialogsMode) << qint32(Global::DialogsModeEnabled() ? 1 : 0) << static_cast<qint32>(Global::DialogsMode()); data.stream << quint32(dbiDialogsMode) << qint32(Global::DialogsModeEnabled() ? 1 : 0) << static_cast<qint32>(Global::DialogsMode());
data.stream << quint32(dbiModerateMode) << qint32(Global::ModerateModeEnabled() ? 1 : 0); data.stream << quint32(dbiModerateMode) << qint32(Global::ModerateModeEnabled() ? 1 : 0);
data.stream << quint32(dbiAutoPlay) << qint32(cAutoPlayGif() ? 1 : 0); data.stream << quint32(dbiAutoPlay) << qint32(cAutoPlayGif() ? 1 : 0);
data.stream << quint32(dbiDialogsWidthRatio) << qint32(snap(qRound(Global::DialogsWidthRatio() * 1000000), 0, 1000000)); data.stream << quint32(dbiDialogsWidthRatio) << qint32(snap(qRound(dialogsWidthRatio * 1000000), 0, 1000000));
data.stream << quint32(dbiUseExternalVideoPlayer) << qint32(cUseExternalVideoPlayer()); data.stream << quint32(dbiUseExternalVideoPlayer) << qint32(cUseExternalVideoPlayer());
if (!userData.isEmpty()) { if (!userData.isEmpty()) {
data.stream << quint32(dbiAuthSessionData) << userData; data.stream << quint32(dbiAuthSessionData) << userData;
@ -2063,7 +2065,7 @@ ReadMapState _readMap(const QByteArray &pass) {
_readUserSettings(); _readUserSettings();
_readMtpData(); _readMtpData();
Messenger::Instance().setAuthSessionData(std::move(AuthSessionDataCache)); Messenger::Instance().setAuthSessionFromStorage(std::move(StoredAuthSessionCache));
LOG(("Map read time: %1").arg(getms() - ms)); LOG(("Map read time: %1").arg(getms() - ms));
if (_oldSettingsVersion < AppVersion) { if (_oldSettingsVersion < AppVersion) {
@ -2360,7 +2362,7 @@ void reset() {
_savedGifsKey = 0; _savedGifsKey = 0;
_backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = 0; _backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = 0;
_oldMapVersion = _oldSettingsVersion = 0; _oldMapVersion = _oldSettingsVersion = 0;
AuthSessionDataCache.reset(); StoredAuthSessionCache.reset();
_mapChanged = true; _mapChanged = true;
_writeMap(WriteMapWhen::Now); _writeMap(WriteMapWhen::Now);

View File

@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "core/basic_types.h" #include "core/basic_types.h"
#include "storage/file_download.h" #include "storage/file_download.h"
#include "auth_session.h"
namespace Window { namespace Window {
namespace Theme { namespace Theme {
@ -31,6 +32,11 @@ struct Cached;
namespace Local { namespace Local {
struct StoredAuthSession {
AuthSessionData data;
float64 dialogsWidthRatio;
};
void start(); void start();
void finish(); void finish();

View File

@ -339,17 +339,24 @@ void MainWindow::showRightColumn(object_ptr<TWidget> widget) {
} }
auto nowRightWidth = _rightColumn ? _rightColumn->width() : 0; auto nowRightWidth = _rightColumn ? _rightColumn->width() : 0;
setMinimumWidth(st::windowMinWidth + nowRightWidth); setMinimumWidth(st::windowMinWidth + nowRightWidth);
auto nowWidth = width();
if (!isMaximized()) { if (!isMaximized()) {
auto desktop = QDesktopWidget().availableGeometry(this); tryToExtendWidthBy(wasWidth + nowRightWidth - wasRightWidth - width());
auto newWidth = qMin(wasWidth + nowRightWidth - wasRightWidth, desktop.width()); } else {
auto newLeft = qMin(x(), desktop.x() + desktop.width() - newWidth); updateControlsGeometry();
if (x() != newLeft || width() != newWidth) { }
setGeometry(newLeft, y(), newWidth, height()); }
} else {
updateControlsGeometry(); bool MainWindow::canExtendWidthBy(int addToWidth) {
} auto desktop = QDesktopWidget().availableGeometry(this);
return (width() + addToWidth) <= desktop.width();
}
void MainWindow::tryToExtendWidthBy(int addToWidth) {
auto desktop = QDesktopWidget().availableGeometry(this);
auto newWidth = qMin(width() + addToWidth, desktop.width());
auto newLeft = qMin(x(), desktop.x() + desktop.width() - newWidth);
if (x() != newLeft || width() != newWidth) {
setGeometry(newLeft, y(), newWidth, height());
} else { } else {
updateControlsGeometry(); updateControlsGeometry();
} }

View File

@ -69,6 +69,8 @@ public:
QWidget *filedialogParent(); QWidget *filedialogParent();
void showRightColumn(object_ptr<TWidget> widget); void showRightColumn(object_ptr<TWidget> widget);
bool canExtendWidthBy(int addToWidth);
void tryToExtendWidthBy(int addToWidth);
virtual void updateTrayMenu(bool force = false) { virtual void updateTrayMenu(bool force = false) {
} }

View File

@ -30,6 +30,7 @@ class SectionMemento;
struct SectionSlideParams { struct SectionSlideParams {
QPixmap oldContentCache; QPixmap oldContentCache;
bool withTopBarShadow = false; bool withTopBarShadow = false;
bool withTabbedSection = false;
explicit operator bool() const { explicit operator bool() const {
return !oldContentCache.isNull(); return !oldContentCache.isNull();

View File

@ -21,6 +21,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "window/window_controller.h" #include "window/window_controller.h"
#include "window/main_window.h" #include "window/main_window.h"
#include "mainwidget.h"
#include "styles/style_window.h"
#include "styles/style_dialogs.h"
namespace Window { namespace Window {
@ -50,4 +53,74 @@ bool Controller::isGifPausedAtLeastFor(GifPauseReason reason) const {
return (static_cast<int>(_gifPauseReasons) >= 2 * static_cast<int>(reason)) || !window()->isActive(); return (static_cast<int>(_gifPauseReasons) >= 2 * static_cast<int>(reason)) || !window()->isActive();
} }
Controller::ColumnLayout Controller::computeColumnLayout() {
auto layout = Adaptive::WindowLayout::OneColumn;
auto bodyWidth = window()->bodyWidget()->width();
auto dialogsWidth = qRound(bodyWidth * dialogsWidthRatio().value());
auto historyWidth = bodyWidth - dialogsWidth;
accumulate_max(historyWidth, st::windowMinWidth);
dialogsWidth = bodyWidth - historyWidth;
auto useOneColumnLayout = [this, bodyWidth, dialogsWidth] {
auto someSectionShown = !App::main()->selectingPeer() && App::main()->isSectionShown();
if (dialogsWidth < st::dialogsPadding.x() && (Adaptive::OneColumn() || someSectionShown)) {
return true;
}
if (bodyWidth < st::windowMinWidth + st::dialogsWidthMin) {
return true;
}
return false;
};
auto useSmallColumnLayout = [this, dialogsWidth] {
// used if useOneColumnLayout() == false.
if (dialogsWidth < st::dialogsWidthMin / 2) {
return true;
}
return false;
};
if (useOneColumnLayout()) {
dialogsWidth = bodyWidth;
} else if (useSmallColumnLayout()) {
layout = Adaptive::WindowLayout::SmallColumn;
auto forceWideDialogs = [this] {
if (dialogsListDisplayForced().value()) {
return true;
} else if (dialogsListFocused().value()) {
return true;
}
return !App::main()->isSectionShown();
};
if (forceWideDialogs()) {
dialogsWidth = st::dialogsWidthMin;
} else {
dialogsWidth = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPadding.x();
}
} else {
layout = Adaptive::WindowLayout::Normal;
accumulate_max(dialogsWidth, st::dialogsWidthMin);
}
return { bodyWidth, dialogsWidth, layout };
}
bool Controller::provideChatWidth(int requestedWidth) {
auto currentLayout = computeColumnLayout();
auto chatWidth = currentLayout.bodyWidth - currentLayout.dialogsWidth;
if (currentLayout.windowLayout == Adaptive::WindowLayout::OneColumn) {
chatWidth = currentLayout.bodyWidth;
}
if (chatWidth >= requestedWidth) {
return true;
}
if (!window()->canExtendWidthBy(requestedWidth - chatWidth)) {
return false;
}
window()->tryToExtendWidthBy(requestedWidth - chatWidth);
auto newLayout = computeColumnLayout();
if (newLayout.windowLayout != Adaptive::WindowLayout::OneColumn) {
dialogsWidthRatio().set(float64(newLayout.bodyWidth - requestedWidth) / newLayout.bodyWidth, true);
}
return true;
}
} // namespace Window } // namespace Window

View File

@ -36,6 +36,8 @@ class MainWindow;
class Controller { class Controller {
public: public:
static constexpr auto kDefaultDialogsWidthRatio = 5. / 14;
Controller(gsl::not_null<MainWindow*> window) : _window(window) { Controller(gsl::not_null<MainWindow*> window) : _window(window) {
} }
@ -63,6 +65,24 @@ public:
} }
bool isGifPausedAtLeastFor(GifPauseReason reason) const; bool isGifPausedAtLeastFor(GifPauseReason reason) const;
struct ColumnLayout {
int bodyWidth;
int dialogsWidth;
Adaptive::WindowLayout windowLayout;
};
ColumnLayout computeColumnLayout();
bool provideChatWidth(int requestedWidth);
base::Variable<float64> &dialogsWidthRatio() {
return _dialogsWidthRatio;
}
base::Variable<bool> &dialogsListFocused() {
return _dialogsListFocused;
}
base::Variable<bool> &dialogsListDisplayForced() {
return _dialogsListDisplayForced;
}
private: private:
gsl::not_null<MainWindow*> _window; gsl::not_null<MainWindow*> _window;
@ -72,6 +92,10 @@ private:
GifPauseReasons _gifPauseReasons = { 0 }; GifPauseReasons _gifPauseReasons = { 0 };
base::Observable<void> _gifPauseLevelChanged; base::Observable<void> _gifPauseLevelChanged;
base::Variable<float64> _dialogsWidthRatio = { kDefaultDialogsWidthRatio };
base::Variable<bool> _dialogsListFocused = { false };
base::Variable<bool> _dialogsListDisplayForced = { false };
}; };
} // namespace Window } // namespace Window