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

View File

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

View File

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

View File

@ -103,7 +103,10 @@ void GifsListWidget::Footer::stealFocus() {
void GifsListWidget::Footer::returnFocus() {
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:
Footer(gsl::not_null<StickersListWidget*> parent);
@ -112,6 +112,10 @@ StickersListWidget::Footer::Footer(gsl::not_null<StickersListWidget*> parent) :
setMouseTracking(true);
_iconsLeft = (st::emojiPanWidth - kVisibleIconsCount * st::emojiCategory.width) / 2;
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] {
update();
});
}
template <typename Callback>
@ -905,13 +909,13 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
emit selected(set.pack[sticker->index]);
} else if (auto set = base::get_if<OverSet>(&pressed)) {
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)) {
t_assert(button->section >= 0 && button->section < sets.size());
if (_section == Section::Featured) {
emit installSet(sets[button->section].id);
installSet(sets[button->section].id);
} 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) {
auto &sets = Global::StickerSets();
auto it = sets.constFind(setId);
if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) {
if (it != sets.cend()) {
_removingSetId = it->id;
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::hideLayer();
auto &sets = Global::RefStickerSets();
auto it = sets.find(_removingSetId);
if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) {
if (it != sets.cend()) {
if (it->id && it->access) {
request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)))).send();
} else if (!it->shortName.isEmpty()) {
request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetShortName(MTP_string(it->shortName)))).send();
}
bool writeRecent = false;
RecentStickerPack &recent(cGetRecentStickers());
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
auto writeRecent = false;
auto &recent = cGetRecentStickers();
for (auto i = recent.begin(); i != recent.cend();) {
if (it->stickers.indexOf(i->first) >= 0) {
i = recent.erase(i);
writeRecent = true;

View File

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

View File

@ -21,19 +21,16 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "ui/twidget.h"
#include "ui/effects/panel_animation.h"
#include "mtproto/sender.h"
#include "auth_session.h"
#include "base/timer.h"
namespace InlineBots {
class Result;
} // namespace InlineBots
namespace Window {
class Controller;
} // namespace Window
namespace Ui {
class PanelAnimation;
} // namespace Ui
namespace ChatHelpers {
class TabbedSelector;
@ -43,7 +40,10 @@ class TabbedPanel : public TWidget {
public:
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 hideFast();
@ -54,12 +54,10 @@ public:
void stickersInstalled(uint64 setId);
bool overlaps(const QRect &globalRect) const;
void setInlineQueryPeer(PeerData *peer);
void showAnimated();
void hideAnimated();
void refreshStickers();
void toggleAnimated();
~TabbedPanel();
@ -74,19 +72,13 @@ protected:
private slots:
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:
void hideByTimerOrLeave();
void moveByBottom();
bool isDestroying() const {
return !_selector;
}
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 "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
*/
#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()) {
resize(st::emojiPanWidth, st::emojiPanMaxHeight);
for (auto &tab : _tabs) {
tab.footer()->hide();
tab.widget()->hide();
}
createTabsSlider();
_scroll->resize(st::emojiPanWidth - st::buttonRadius, height() - marginTop() - marginBottom());
_scroll->move(st::buttonRadius, marginTop());
_scroll->setGeometryToLeft(st::buttonRadius, marginTop(), st::emojiPanWidth - st::buttonRadius, height() - marginTop() - marginBottom());
setWidgetToScrollArea();
_bottomShadow->setGeometry(_tabsSlider->x(), _scroll->y() + _scroll->height() - st::lineWidth, _tabsSlider->width(), st::lineWidth);
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()) {
scrollToY(y);
} else {
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()) {
_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()));
@ -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(cancelled()), this, SIGNAL(cancelled()));
_saveConfigTimer.setCallback([this] { Local::writeUserSettings(); });
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
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_OpaquePaintEvent, false);
hideChildren();
showAll();
}
void TabbedSelector::resizeEvent(QResizeEvent *e) {
@ -363,10 +367,6 @@ void TabbedSelector::resizeEvent(QResizeEvent *e) {
update();
}
void TabbedSelector::onSaveConfigDelayed(int delay) {
_saveConfigTimer.callOnce(delay);
}
void TabbedSelector::paintEvent(QPaintEvent *e) {
Painter p(this);
@ -593,7 +593,7 @@ void TabbedSelector::switchTab() {
update();
AuthSession::Current().data().setEmojiPanelTab(_currentTabType);
onSaveConfigDelayed(kSaveChosenTabTimeout);
AuthSession::Current().saveDataDelayed(kSaveChosenTabTimeout);
}
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 "mtproto/sender.h"
#include "auth_session.h"
#include "base/timer.h"
namespace InlineBots {
class Result;
@ -79,8 +78,6 @@ protected:
private slots:
void onScroll();
void onSaveConfigDelayed(int delay);
signals:
void emojiSelected(EmojiPtr emoji);
void stickerSelected(DocumentData *sticker);
@ -176,8 +173,6 @@ private:
std::array<Tab, Tab::kCount> _tabs;
TabType _currentTabType = TabType::Emoji;
base::Timer _saveConfigTimer;
};
class TabbedSelector::Inner : public TWidget {

View File

@ -74,7 +74,8 @@ struct DialogsInner::PeerSearchResult {
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))
, _contactsNoDialogs(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);
loadPeerPhotos();
}
Global::RefDialogsListDisplayForced().set(_searchInPeer || !_filter.isEmpty(), true);
_controller->dialogsListDisplayForced().set(_searchInPeer || !_filter.isEmpty(), true);
update();
}
@ -1722,7 +1723,7 @@ void DialogsInner::searchInPeer(PeerData *peer) {
} else {
_cancelSearchInPeer->hide();
}
Global::RefDialogsListDisplayForced().set(_searchInPeer || !_filter.isEmpty(), true);
_controller->dialogsListDisplayForced().set(_searchInPeer || !_filter.isEmpty(), true);
}
void DialogsInner::clearFilter() {
@ -2274,7 +2275,7 @@ DialogsWidget::DialogsWidget(QWidget *parent, gsl::not_null<Window::Controller*>
, _cancelSearch(this, st::dialogsCancelSearch)
, _lockUnlock(this, st::dialogsLock)
, _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(mustScrollTo(int,int)), _scroll, SLOT(scrollToY(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
public:
DialogsInner(QWidget *parent, QWidget *main);
DialogsInner(QWidget *parent, gsl::not_null<Window::Controller*> controller, QWidget *main);
void dialogsReceived(const QVector<MTPDialog> &dialogs);
void addSavedPeersAfter(const QDateTime &date);
@ -226,6 +226,8 @@ private:
void savePinnedOrder();
void step_pinnedShifting(TimeMs ms, bool timer);
gsl::not_null<Window::Controller*> _controller;
DialogsList _dialogs;
DialogsList _dialogsImportant;

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -121,7 +121,6 @@ void Widget::changeLanguage(int32 languageId) {
}
void Widget::setInnerFocus() {
Global::RefDialogsListFocused().set(false, true);
if (getStep()->animating()) {
setFocus();
} 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) {
emit peerUpdated(peer);
});
subscribe(Global::RefDialogsListFocused(), [this](bool) {
subscribe(_controller->dialogsListFocused(), [this](bool) {
updateDialogsWidthAnimated();
});
subscribe(Global::RefDialogsListDisplayForced(), [this](bool) {
subscribe(_controller->dialogsListDisplayForced(), [this](bool) {
updateDialogsWidthAnimated();
});
subscribe(_controller->dialogsWidthRatio(), [this](float64) {
updateControlsGeometry();
});
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();
bool back = (way == Ui::ShowWay::Backward || !peerId);
@ -2348,7 +2351,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
return;
}
Global::RefDialogsListFocused().set(false, true);
_controller->dialogsListFocused().set(false, true);
_a_dialogsWidth.finish();
auto animatedShow = [this] {
@ -2411,9 +2414,10 @@ void MainWidget::showWideSection(const Window::SectionMemento &memento) {
showNewWideSection(&memento, false, true);
}
Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarShadow) {
Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarShadow, bool willHaveTabbedSection) {
Window::SectionSlideParams result;
result.withTopBarShadow = willHaveTopBarShadow;
result.withTabbedSection = willHaveTabbedSection;
if (selectingPeer() && Adaptive::OneColumn()) {
result.withTopBarShadow = false;
} else if (_wideSection) {
@ -2423,6 +2427,9 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarS
} else if (!_overview && !_history->peer()) {
result.withTopBarShadow = false;
}
if ((selectingPeer() && Adaptive::OneColumn()) || !_history->peer()) {
result.withTabbedSection = false;
}
if (_player) {
_player->hideShadow();
@ -2480,25 +2487,25 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarS
}
Window::SectionSlideParams MainWidget::prepareWideSectionAnimation(Window::SectionWidget *section) {
return prepareShowAnimation(section->hasTopBarShadow());
return prepareShowAnimation(section->hasTopBarShadow(), false);
}
Window::SectionSlideParams MainWidget::prepareHistoryAnimation(PeerId historyPeerId) {
return prepareShowAnimation(historyPeerId != 0);
return prepareShowAnimation(historyPeerId != 0, historyPeerId != 0);
}
Window::SectionSlideParams MainWidget::prepareOverviewAnimation() {
return prepareShowAnimation(true);
return prepareShowAnimation(true, false);
}
Window::SectionSlideParams MainWidget::prepareDialogsAnimation() {
return prepareShowAnimation(false);
return prepareShowAnimation(false, false);
}
void MainWidget::showNewWideSection(const Window::SectionMemento *memento, bool back, bool saveInStack) {
QPixmap animCache;
Global::RefDialogsListFocused().set(false, true);
_controller->dialogsListFocused().set(false, true);
_a_dialogsWidth.finish();
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) {
_resizingSide = false;
if (!Adaptive::OneColumn()) {
Global::SetDialogsWidthRatio(float64(_dialogsWidth) / width());
_controller->dialogsWidthRatio().set(float64(_dialogsWidth) / width(), true);
}
Local::writeUserSettings();
} else if (e->type() == QEvent::MouseMove && _resizingSide) {
auto newWidth = mouseLeft() - _resizingSideShift;
Global::SetDialogsWidthRatio(float64(newWidth) / width());
updateControlsGeometry();
_controller->dialogsWidthRatio().set(float64(newWidth) / width(), true);
}
} else if (e->type() == QEvent::FocusIn) {
if (auto widget = qobject_cast<QWidget*>(o)) {
if (_history == widget || _history->isAncestorOf(widget)
|| (_overview && (_overview == widget || _overview->isAncestorOf(widget)))
|| (_wideSection && (_wideSection == widget || _wideSection->isAncestorOf(widget)))) {
Global::RefDialogsListFocused().set(false, false);
_controller->dialogsListFocused().set(false);
} else if (_dialogs == widget || _dialogs->isAncestorOf(widget)) {
Global::RefDialogsListFocused().set(true, false);
_controller->dialogsListFocused().set(true);
}
}
} else if (e->type() == QEvent::MouseButtonPress) {
@ -3094,62 +3100,14 @@ void MainWidget::handleAdaptiveLayoutUpdate() {
}
void MainWidget::updateWindowAdaptiveLayout() {
auto layout = Adaptive::WindowLayout::OneColumn;
auto dialogsWidth = qRound(width() * Global::DialogsWidthRatio());
auto historyWidth = width() - dialogsWidth;
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);
auto layout = _controller->computeColumnLayout();
_dialogsWidth = layout.dialogsWidth;
if (layout.windowLayout != Global::AdaptiveWindowLayout()) {
Global::SetAdaptiveWindowLayout(layout.windowLayout);
Adaptive::Changed().notify(true);
}
}
bool MainWidget::needBackButton() {
return isSectionShown();
}
bool MainWidget::paintTopBar(Painter &p, int decreaseWidth, TimeMs ms) {
if (_overview) {
return _overview->paintTopBar(p, decreaseWidth);

View File

@ -144,7 +144,7 @@ class MainWidget : public TWidget, public RPCSender, private base::Subscriber {
public:
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.
bool paintTopBar(Painter &, int decreaseWidth, TimeMs ms);
@ -481,9 +481,8 @@ private:
void overviewLoaded(History *history, const MTPmessages_Messages &result, mtpRequestId req);
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);
bool isSectionShown() const;
// All this methods use the prepareShowAnimation().
Window::SectionSlideParams prepareWideSectionAnimation(Window::SectionWidget *section);

View File

@ -110,15 +110,25 @@ MainWindow::MainWindow() {
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) {
themeUpdated(data);
});
subscribe(Messenger::Instance().authSessionChanged(), [this] { checkAuthSession(); });
checkAuthSession();
setAttribute(Qt::WA_NoSystemBackground);
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) {
_inactivePress = inactive;
if (_inactivePress) {
@ -200,7 +210,6 @@ void MainWindow::clearWidgetsHook() {
auto wasMain = (_main != nullptr);
_passcode.destroyDelayed();
_main.destroy();
_controller.reset();
_intro.destroy();
if (wasMain) {
App::clearHistories();
@ -352,7 +361,7 @@ void MainWindow::setupMain(const MTPUser *self) {
t_assert(AuthSession::Exists());
_controller = std::make_unique<Window::Controller>(this);
_main.create(bodyWidget(), controller());
_main->show();
updateControlsGeometry();

View File

@ -199,6 +199,7 @@ private slots:
void onWindowActiveChanged();
private:
void checkAuthSession();
void showConnecting(const QString &text, const QString &reconnect = QString());
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();

View File

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

View File

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

View File

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

View File

@ -35,6 +35,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "application.h"
#include "apiwrap.h"
#include "auth_session.h"
#include "window/window_controller.h"
#include <openssl/evp.h>
@ -638,12 +639,12 @@ enum class WriteMapWhen {
Soon,
};
std::unique_ptr<AuthSessionData> AuthSessionDataCache;
AuthSessionData &GetAuthSessionDataCache() {
if (!AuthSessionDataCache) {
AuthSessionDataCache = std::make_unique<AuthSessionData>();
std::unique_ptr<StoredAuthSession> StoredAuthSessionCache;
StoredAuthSession &GetStoredAuthSessionCache() {
if (!StoredAuthSessionCache) {
StoredAuthSessionCache = std::make_unique<StoredAuthSession>();
}
return *AuthSessionDataCache;
return *StoredAuthSessionCache;
}
void _writeMap(WriteMapWhen when = WriteMapWhen::Soon);
@ -1010,7 +1011,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
if (!_checkStreamStatus(stream)) return false;
Global::SetDialogsModeEnabled(enabled == 1);
Dialogs::Mode mode = Dialogs::Mode::All;
auto mode = Dialogs::Mode::All;
if (enabled) {
mode = static_cast<Dialogs::Mode>(modeInt);
if (mode != Dialogs::Mode::All && mode != Dialogs::Mode::Important) {
@ -1086,7 +1087,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
stream >> v;
if (!_checkStreamStatus(stream)) return false;
Global::SetDialogsWidthRatio(v / 1000000.);
GetStoredAuthSessionCache().dialogsWidthRatio = v / 1000000.;
} break;
case dbiLastSeenWarningSeenOld: {
@ -1094,7 +1095,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
stream >> v;
if (!_checkStreamStatus(stream)) return false;
GetAuthSessionDataCache().setLastSeenWarningSeen(v == 1);
GetStoredAuthSessionCache().data.setLastSeenWarningSeen(v == 1);
} break;
case dbiAuthSessionData: {
@ -1102,7 +1103,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
stream >> v;
if (!_checkStreamStatus(stream)) return false;
GetAuthSessionDataCache().constructFromSerialized(v);
GetStoredAuthSessionCache().data.constructFromSerialized(v);
} break;
case dbiWorkMode: {
@ -1707,8 +1708,9 @@ void _writeUserSettings() {
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 dialogsWidthRatio = StoredAuthSessionCache ? StoredAuthSessionCache->dialogsWidthRatio : (App::wnd() ? App::wnd()->controller()->dialogsWidthRatio().value() : Window::Controller::kDefaultDialogsWidthRatio);
uint32 size = 21 * (sizeof(quint32) + sizeof(qint32));
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(dbiModerateMode) << qint32(Global::ModerateModeEnabled() ? 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());
if (!userData.isEmpty()) {
data.stream << quint32(dbiAuthSessionData) << userData;
@ -2063,7 +2065,7 @@ ReadMapState _readMap(const QByteArray &pass) {
_readUserSettings();
_readMtpData();
Messenger::Instance().setAuthSessionData(std::move(AuthSessionDataCache));
Messenger::Instance().setAuthSessionFromStorage(std::move(StoredAuthSessionCache));
LOG(("Map read time: %1").arg(getms() - ms));
if (_oldSettingsVersion < AppVersion) {
@ -2360,7 +2362,7 @@ void reset() {
_savedGifsKey = 0;
_backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = 0;
_oldMapVersion = _oldSettingsVersion = 0;
AuthSessionDataCache.reset();
StoredAuthSessionCache.reset();
_mapChanged = true;
_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 "storage/file_download.h"
#include "auth_session.h"
namespace Window {
namespace Theme {
@ -31,6 +32,11 @@ struct Cached;
namespace Local {
struct StoredAuthSession {
AuthSessionData data;
float64 dialogsWidthRatio;
};
void start();
void finish();

View File

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

View File

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

View File

@ -30,6 +30,7 @@ class SectionMemento;
struct SectionSlideParams {
QPixmap oldContentCache;
bool withTopBarShadow = false;
bool withTabbedSection = false;
explicit operator bool() const {
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/main_window.h"
#include "mainwidget.h"
#include "styles/style_window.h"
#include "styles/style_dialogs.h"
namespace Window {
@ -50,4 +53,74 @@ bool Controller::isGifPausedAtLeastFor(GifPauseReason reason) const {
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

View File

@ -36,6 +36,8 @@ class MainWindow;
class Controller {
public:
static constexpr auto kDefaultDialogsWidthRatio = 5. / 14;
Controller(gsl::not_null<MainWindow*> window) : _window(window) {
}
@ -63,6 +65,24 @@ public:
}
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:
gsl::not_null<MainWindow*> _window;
@ -72,6 +92,10 @@ private:
GifPauseReasons _gifPauseReasons = { 0 };
base::Observable<void> _gifPauseLevelChanged;
base::Variable<float64> _dialogsWidthRatio = { kDefaultDialogsWidthRatio };
base::Variable<bool> _dialogsListFocused = { false };
base::Variable<bool> _dialogsListDisplayForced = { false };
};
} // namespace Window