From b520cf0f780dce2a4db107d4dd2fd8f7fcadc189 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 28 Aug 2016 13:16:23 -0600 Subject: [PATCH] First version of the new Settings page is finished. Added LocalStorageBox for watching info and clearing local storage. Local passcode and cloud password state display and editing done. Temporary download location clearing link added. Crash fixed in local storage clear + app close, now waiting for the clearing thread to quit. Some design improvements and testing. --- Telegram/Resources/langs/lang.strings | 1 + Telegram/SourceFiles/app.cpp | 5 +- Telegram/SourceFiles/application.cpp | 7 +- Telegram/SourceFiles/autoupdater.h | 4 +- Telegram/SourceFiles/boxes/autolockbox.cpp | 5 +- Telegram/SourceFiles/boxes/boxes.style | 2 + .../SourceFiles/boxes/localstoragebox.cpp | 131 +++++++++++++ Telegram/SourceFiles/boxes/localstoragebox.h | 62 ++++++ Telegram/SourceFiles/boxes/passcodebox.cpp | 15 +- Telegram/SourceFiles/facades.cpp | 8 + Telegram/SourceFiles/facades.h | 4 + Telegram/SourceFiles/localstorage.cpp | 29 ++- Telegram/SourceFiles/localstorage.h | 10 +- Telegram/SourceFiles/mainwindow.cpp | 22 ++- Telegram/SourceFiles/settings.cpp | 3 - Telegram/SourceFiles/settings.h | 3 - Telegram/SourceFiles/settings/settings.style | 13 +- .../settings/settings_advanced_widget.cpp | 23 ++- .../settings/settings_background_widget.cpp | 8 +- .../settings/settings_block_widget.cpp | 14 +- .../settings/settings_block_widget.h | 2 +- .../settings_chat_settings_widget.cpp | 178 +++++++++++++----- .../settings/settings_chat_settings_widget.h | 46 ++++- .../SourceFiles/settings/settings_cover.cpp | 12 +- .../settings/settings_general_widget.cpp | 17 +- .../settings/settings_info_widget.cpp | 21 ++- .../settings/settings_inner_widget.cpp | 8 +- .../settings/settings_inner_widget.h | 2 +- .../settings_notifications_widget.cpp | 2 +- .../settings/settings_privacy_widget.cpp | 167 +++++++++++++++- .../settings/settings_privacy_widget.h | 66 ++++++- Telegram/SourceFiles/settingswidget.cpp | 14 +- Telegram/SourceFiles/shortcuts.cpp | 2 +- Telegram/SourceFiles/title.cpp | 4 +- Telegram/SourceFiles/ui/flatbutton.cpp | 26 ++- Telegram/SourceFiles/ui/flatbutton.h | 1 + Telegram/gyp/Telegram.gyp | 2 + 37 files changed, 751 insertions(+), 188 deletions(-) create mode 100644 Telegram/SourceFiles/boxes/localstoragebox.cpp create mode 100644 Telegram/SourceFiles/boxes/localstoragebox.h diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 4e93f0dcb..c06c6e297 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -306,6 +306,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_settings_section_privacy" = "Privacy and Security"; +"lng_local_storage_title" = "Local storage"; "lng_settings_no_data_cached" = "No cached data found!"; "lng_settings_images_cached" = "{count:_not_used_|# image|# images}, {size}"; "lng_settings_audios_cached" = "{count:_not_used_|# voice message|# voice messages}, {size}"; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 90e864638..7bdfb5c8c 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -188,8 +188,9 @@ namespace App { namespace { bool loggedOut() { - if (cHasPasscode()) { - cSetHasPasscode(false); + if (Global::LocalPasscode()) { + Global::SetLocalPasscode(false); + Global::RefLocalPasscodeChanged().notify(); } if (audioPlayer()) { audioPlayer()->stopAndClear(); diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index 61d2fc6c9..04422b048 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -339,7 +339,9 @@ void Application::closeApplication() { _updateReply = 0; if (_updateChecker) _updateChecker->deleteLater(); _updateChecker = 0; - if (_updateThread) _updateThread->quit(); + if (_updateThread) { + _updateThread->quit(); + } _updateThread = 0; #endif @@ -738,7 +740,8 @@ AppClass::AppClass() : QObject() Local::ReadMapState state = Local::readMap(QByteArray()); if (state == Local::ReadMapPassNeeded) { - cSetHasPasscode(true); + Global::SetLocalPasscode(true); + Global::RefLocalPasscodeChanged().notify(); DEBUG_LOG(("Application Info: passcode needed...")); } else { DEBUG_LOG(("Application Info: local map read...")); diff --git a/Telegram/SourceFiles/autoupdater.h b/Telegram/SourceFiles/autoupdater.h index 3687a405d..a7f27a539 100644 --- a/Telegram/SourceFiles/autoupdater.h +++ b/Telegram/SourceFiles/autoupdater.h @@ -66,11 +66,11 @@ private: bool checkReadyUpdate(); -#else +#else // TDESKTOP_DISABLE_AUTOUPDATE class UpdateChecker : public QObject { Q_OBJECT }; -#endif +#endif // TDESKTOP_DISABLE_AUTOUPDATE QString countBetaVersionSignature(uint64 version); diff --git a/Telegram/SourceFiles/boxes/autolockbox.cpp b/Telegram/SourceFiles/boxes/autolockbox.cpp index acb20f47d..238941a3a 100644 --- a/Telegram/SourceFiles/boxes/autolockbox.cpp +++ b/Telegram/SourceFiles/boxes/autolockbox.cpp @@ -41,7 +41,7 @@ _close(this, lang(lng_box_ok), st::defaultBoxButton) { _options.reserve(cnt); for (int32 i = 0; i < cnt; ++i) { int32 v = opts[i]; - _options.push_back(new Radiobutton(this, qsl("autolock"), v, (v % 3600) ? lng_passcode_autolock_minutes(lt_count, v / 60) : lng_passcode_autolock_hours(lt_count, v / 3600), (cAutoLock() == v), st::langsButton)); + _options.push_back(new Radiobutton(this, qsl("autolock"), v, (v % 3600) ? lng_passcode_autolock_minutes(lt_count, v / 60) : lng_passcode_autolock_hours(lt_count, v / 3600), (Global::AutoLock() == v), st::langsButton)); _options.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y); y += _options.back()->height() + st::boxOptionListPadding.top(); connect(_options.back(), SIGNAL(changed()), this, SLOT(onChange())); @@ -73,8 +73,9 @@ void AutoLockBox::onChange() { for (int32 i = 0, l = _options.size(); i < l; ++i) { int32 v = _options[i]->val(); if (_options[i]->checked()) { - cSetAutoLock(v); + Global::SetAutoLock(v); Local::writeUserSettings(); + Global::RefLocalPasscodeChanged().notify(); } } App::wnd()->checkAutoLock(); diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 69dfca7de..dfeb7adff 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -85,3 +85,5 @@ aboutRevokePublicLabel: flatLabel(labelDefFlat) { width: 320px; textFg: windowTextFg; } + +localStorageBoxSkip: 10px; diff --git a/Telegram/SourceFiles/boxes/localstoragebox.cpp b/Telegram/SourceFiles/boxes/localstoragebox.cpp new file mode 100644 index 000000000..29b3e6279 --- /dev/null +++ b/Telegram/SourceFiles/boxes/localstoragebox.cpp @@ -0,0 +1,131 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "boxes/localstoragebox.h" + +#include "localstorage.h" +#include "ui/flatbutton.h" +#include "lang.h" +#include "styles/style_boxes.h" +#include "mainwindow.h" + +LocalStorageBox::LocalStorageBox() : AbstractBox() +, _clear(this, lang(lng_local_storage_clear), st::defaultBoxLinkButton) +, _close(this, lang(lng_box_ok), st::defaultBoxButton) { + connect(_clear, SIGNAL(clicked()), this, SLOT(onClear())); + connect(_close, SIGNAL(clicked()), this, SLOT(onClose())); + + connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); + connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int))); + connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int))); + + checkLocalStoredCounts(); + prepare(); +} + +void LocalStorageBox::updateControls() { + int rowsHeight = 0; + if (_imagesCount > 0 && _audiosCount > 0) { + rowsHeight = 2 * (st::linkFont->height + st::localStorageBoxSkip); + } else { + rowsHeight = st::linkFont->height + st::localStorageBoxSkip; + } + _clear->setVisible(_imagesCount > 0 || _audiosCount > 0); + setMaxHeight(st::boxTitleHeight + st::localStorageBoxSkip + rowsHeight + _clear->height() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom()); + _clear->moveToLeft(st::boxPadding.left(), st::boxTitleHeight + st::localStorageBoxSkip + rowsHeight); + _close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height()); + update(); +} + +void LocalStorageBox::showAll() { + showChildren(); + _clear->setVisible(_imagesCount > 0 || _audiosCount > 0); +} + +void LocalStorageBox::checkLocalStoredCounts() { + int imagesCount = Local::hasImages() + Local::hasStickers() + Local::hasWebFiles(); + int audiosCount = Local::hasAudios(); + if (imagesCount != _imagesCount || audiosCount != _audiosCount) { + _imagesCount = imagesCount; + _audiosCount = audiosCount; + if (_imagesCount > 0 || _audiosCount > 0) { + _state = State::Normal; + } + updateControls(); + } +} + +void LocalStorageBox::paintEvent(QPaintEvent *e) { + Painter p(this); + if (paint(p)) return; + + paintTitle(p, lang(lng_local_storage_title)); + + p.setFont(st::boxTextFont); + p.setPen(st::windowTextFg); + checkLocalStoredCounts(); + int top = st::boxTitleHeight + st::localStorageBoxSkip; + if (_imagesCount > 0) { + auto text = lng_settings_images_cached(lt_count, _imagesCount, lt_size, formatSizeText(Local::storageImagesSize() + Local::storageStickersSize() + Local::storageWebFilesSize())); + p.drawTextLeft(st::boxPadding.left(), top, width(), text); + top += st::boxTextFont->height + st::localStorageBoxSkip; + } + if (_audiosCount > 0) { + auto text = lng_settings_audios_cached(lt_count, _audiosCount, lt_size, formatSizeText(Local::storageAudiosSize())); + p.drawTextLeft(st::boxPadding.left(), top, width(), text); + top += st::boxTextFont->height + st::localStorageBoxSkip; + } else if (_imagesCount <= 0) { + p.drawTextLeft(st::boxPadding.left(), top, width(), lang(lng_settings_no_data_cached)); + top += st::boxTextFont->height + st::localStorageBoxSkip; + } + auto text = ([this]() -> QString { + switch (_state) { + case State::Clearing: return lang(lng_local_storage_clearing); + case State::Cleared: return lang(lng_local_storage_cleared); + case State::ClearFailed: return lang(lng_local_storage_clear_failed); + } + return QString(); + })(); + if (!text.isEmpty()) { + p.drawTextLeft(st::boxPadding.left(), top, width(), text); + top += st::boxTextFont->height + st::localStorageBoxSkip; + } +} + +void LocalStorageBox::onClear() { + App::wnd()->tempDirDelete(Local::ClearManagerStorage); + _state = State::Clearing; + updateControls(); +} + +void LocalStorageBox::onTempDirCleared(int task) { + if (task & Local::ClearManagerStorage) { + _state = State::Cleared; + } + updateControls(); +} + +void LocalStorageBox::onTempDirClearFailed(int task) { + if (task & Local::ClearManagerStorage) { + _state = State::ClearFailed; + } + updateControls(); +} diff --git a/Telegram/SourceFiles/boxes/localstoragebox.h b/Telegram/SourceFiles/boxes/localstoragebox.h new file mode 100644 index 000000000..ef175bfec --- /dev/null +++ b/Telegram/SourceFiles/boxes/localstoragebox.h @@ -0,0 +1,62 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "abstractbox.h" + +class BoxButton; +class LinkButton; + +class LocalStorageBox : public AbstractBox { + Q_OBJECT + +public: + LocalStorageBox(); + +private slots: + void onClear(); + void onTempDirCleared(int task); + void onTempDirClearFailed(int task); + +protected: + void paintEvent(QPaintEvent *e) override; + + void showAll() override; + +private: + void updateControls(); + void checkLocalStoredCounts(); + + enum class State { + Normal, + Clearing, + Cleared, + ClearFailed, + }; + State _state = State::Normal; + + ChildWidget _clear; + ChildWidget _close; + + int _imagesCount = -1; + int _audiosCount = -1; + +}; diff --git a/Telegram/SourceFiles/boxes/passcodebox.cpp b/Telegram/SourceFiles/boxes/passcodebox.cpp index 49ffdf9a1..32ccd9e8a 100644 --- a/Telegram/SourceFiles/boxes/passcodebox.cpp +++ b/Telegram/SourceFiles/boxes/passcodebox.cpp @@ -39,7 +39,7 @@ PasscodeBox::PasscodeBox(bool turningOff) : AbstractBox(st::boxWidth) , _saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::defaultBoxButton) , _cancelButton(this, lang(lng_cancel), st::cancelBoxButton) , _oldPasscode(this, st::defaultInputField, lang(lng_passcode_enter_old)) -, _newPasscode(this, st::defaultInputField, lang(cHasPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first)) +, _newPasscode(this, st::defaultInputField, lang(Global::LocalPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first)) , _reenterPasscode(this, st::defaultInputField, lang(lng_passcode_confirm_new)) , _passwordHint(this, st::defaultInputField, lang(lng_cloud_password_hint)) , _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email)) @@ -86,7 +86,7 @@ void PasscodeBox::init() { _boxTitle = lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove); setMaxHeight(st::boxTitleHeight + st::passcodePadding.top() + _oldPasscode.height() + st::passcodeSkip + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeSkip : 0) + _aboutHeight + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton.height() + st::boxButtonPadding.bottom()); } else { - bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode(); + bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode(); if (has) { _oldPasscode.show(); _boxTitle = lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change); @@ -117,7 +117,7 @@ void PasscodeBox::init() { } void PasscodeBox::showAll() { - bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode(); + bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode(); if (_turningOff) { _oldPasscode.show(); if (_cloudPwd && _hasRecovery) { @@ -125,9 +125,10 @@ void PasscodeBox::showAll() { } else { _recover.hide(); } - _passwordHint.hide(); _newPasscode.hide(); _reenterPasscode.hide(); + _passwordHint.hide(); + _recoverEmail.hide(); } else { if (has) { _oldPasscode.show(); @@ -159,7 +160,7 @@ void PasscodeBox::showAll() { } void PasscodeBox::onSubmit() { - bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode(); + bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode(); if (_oldPasscode.hasFocus()) { if (_turningOff) { onSave(); @@ -230,7 +231,7 @@ void PasscodeBox::paintEvent(QPaintEvent *e) { } void PasscodeBox::resizeEvent(QResizeEvent *e) { - bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode(); + bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode(); int32 w = st::boxWidth - st::boxPadding.left() - st::boxPadding.right(); _oldPasscode.resize(w, _oldPasscode.height()); _oldPasscode.moveToLeft(st::boxPadding.left(), st::boxTitleHeight + st::passcodePadding.top()); @@ -323,7 +324,7 @@ void PasscodeBox::onSave(bool force) { if (_setRequest) return; QString old = _oldPasscode.text(), pwd = _newPasscode.text(), conf = _reenterPasscode.text(); - bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode(); + bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode(); if (!_cloudPwd && (_turningOff || has)) { if (!passcodeCanTry()) { _oldError = lang(lng_flood_error); diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 567389058..f64038d52 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -653,6 +653,10 @@ struct Data { base::Observable ChooseCustomLang; + int AutoLock = 3600; + bool LocalPasscode = false; + base::Observable LocalPasscodeChanged; + }; } // namespace internal @@ -757,4 +761,8 @@ DefineRefVar(Global, base::Observable, ConnectionTypeChanged); DefineRefVar(Global, base::Observable, ChooseCustomLang); +DefineVar(Global, int, AutoLock); +DefineVar(Global, bool, LocalPasscode); +DefineRefVar(Global, base::Observable, LocalPasscodeChanged); + } // namespace Global diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index 217389402..3150fd647 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -318,6 +318,10 @@ DeclareRefVar(base::Observable, ConnectionTypeChanged); DeclareRefVar(base::Observable, ChooseCustomLang); +DeclareVar(int, AutoLock); +DeclareVar(bool, LocalPasscode); +DeclareRefVar(base::Observable, LocalPasscodeChanged); + } // namespace Global namespace Adaptive { diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index fc0121fa2..7dc2cf020 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -1165,7 +1165,8 @@ namespace { stream >> v; if (!_checkStreamStatus(stream)) return false; - cSetAutoLock(v); + Global::SetAutoLock(v); + Global::RefLocalPasscodeChanged().notify(); } break; case dbiReplaceEmojis: { @@ -1569,7 +1570,7 @@ namespace { data.stream << quint32(dbiSendKey) << qint32(cCtrlEnter() ? dbiskCtrlEnter : dbiskEnter); data.stream << quint32(dbiTileBackground) << qint32(Window::chatBackground()->tile() ? 1 : 0); data.stream << quint32(dbiAdaptiveForWide) << qint32(Global::AdaptiveForWide() ? 1 : 0); - data.stream << quint32(dbiAutoLock) << qint32(cAutoLock()); + data.stream << quint32(dbiAutoLock) << qint32(Global::AutoLock()); data.stream << quint32(dbiReplaceEmojis) << qint32(cReplaceEmojis() ? 1 : 0); data.stream << quint32(dbiDefaultAttach) << qint32(cDefaultAttach()); data.stream << quint32(dbiSoundNotify) << qint32(Global::SoundNotify()); @@ -2298,7 +2299,8 @@ namespace Local { _mapChanged = true; _writeMap(WriteMapNow); - cSetHasPasscode(!passcode.isEmpty()); + Global::SetLocalPasscode(!passcode.isEmpty()); + Global::RefLocalPasscodeChanged().notify(); } ReadMapState readMap(const QByteArray &pass) { @@ -4167,11 +4169,22 @@ namespace Local { void ClearManager::start() { moveToThread(data->thread); connect(data->thread, SIGNAL(started()), this, SLOT(onStart())); + connect(data->thread, SIGNAL(finished()), data->thread, SLOT(deleteLater())); + connect(data->thread, SIGNAL(finished()), this, SLOT(deleteLater())); data->thread->start(); } + void ClearManager::stop() { + { + QMutexLocker lock(&data->mutex); + data->tasks.clear(); + } + auto thread = data->thread; + thread->quit(); + thread->wait(); + } + ClearManager::~ClearManager() { - data->thread->deleteLater(); delete data; } @@ -4231,11 +4244,11 @@ namespace Local { } { QMutexLocker lock(&data->mutex); - if (data->tasks.at(0) == task) { + if (!data->tasks.isEmpty() && data->tasks.at(0) == task) { data->tasks.pop_front(); - if (data->tasks.isEmpty()) { - data->working = false; - } + } + if (data->tasks.isEmpty()) { + data->working = false; } if (result) { emit succeed(task, data->working ? 0 : this); diff --git a/Telegram/SourceFiles/localstorage.h b/Telegram/SourceFiles/localstorage.h index ca59fe65b..46a53a177 100644 --- a/Telegram/SourceFiles/localstorage.h +++ b/Telegram/SourceFiles/localstorage.h @@ -81,16 +81,18 @@ namespace Local { bool addTask(int task); bool hasTask(ClearManagerTask task); void start(); - ~ClearManager(); - - public slots: - void onStart(); + void stop(); signals: void succeed(int task, void *manager); void failed(int task, void *manager); + private slots: + void onStart(); + private: + ~ClearManager(); + ClearManagerData *data; }; diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index d84ee853e..99a5e89b1 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -588,10 +588,10 @@ void MainWindow::checkAutoLockIn(int msec) { } void MainWindow::checkAutoLock() { - if (!cHasPasscode() || App::passcoded()) return; + if (!Global::LocalPasscode() || App::passcoded()) return; App::app()->checkLocalTime(); - uint64 ms = getms(true), idle = psIdleTime(), should = cAutoLock() * 1000ULL; + uint64 ms = getms(true), idle = psIdleTime(), should = Global::AutoLock() * 1000ULL; if (idle >= should || (_shouldLockAt > 0 && ms > _shouldLockAt + 3000ULL)) { setupPasscode(true); } else { @@ -608,6 +608,7 @@ void MainWindow::setupIntro(bool anim) { if (_mediaView) { _mediaView->clearData(); } + Ui::hideSettingsAndLayer(true); QPixmap bg = anim ? grabInner() : QPixmap(); @@ -1350,8 +1351,8 @@ void MainWindow::tempDirDelete(int task) { if (_clearManager->addTask(task)) { return; } else { - _clearManager->deleteLater(); - _clearManager = 0; + _clearManager->stop(); + _clearManager = nullptr; } } _clearManager = new Local::ClearManager(); @@ -1363,16 +1364,16 @@ void MainWindow::tempDirDelete(int task) { void MainWindow::onClearFinished(int task, void *manager) { if (manager && manager == _clearManager) { - _clearManager->deleteLater(); - _clearManager = 0; + _clearManager->stop(); + _clearManager = nullptr; } emit tempDirCleared(task); } void MainWindow::onClearFailed(int task, void *manager) { if (manager && manager == _clearManager) { - _clearManager->deleteLater(); - _clearManager = 0; + _clearManager->stop(); + _clearManager = nullptr; } emit tempDirClearFailed(task); } @@ -1918,7 +1919,10 @@ void MainWindow::updateIsActive(int timeout) { MainWindow::~MainWindow() { notifyClearFast(); - delete _clearManager; + if (_clearManager) { + _clearManager->stop(); + _clearManager = nullptr; + } delete _connecting; delete _mediaView; delete trayIcon; diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index 3196e7e8a..8b1e9ff71 100644 --- a/Telegram/SourceFiles/settings.cpp +++ b/Telegram/SourceFiles/settings.cpp @@ -75,9 +75,6 @@ bool gCompressPastedImage = true; QString gTimeFormat = qsl("hh:mm"); -int32 gAutoLock = 3600; -bool gHasPasscode = false; - bool gHasAudioPlayer = true; bool gHasAudioCapture = true; diff --git a/Telegram/SourceFiles/settings.h b/Telegram/SourceFiles/settings.h index a1edfbe3c..d36815245 100644 --- a/Telegram/SourceFiles/settings.h +++ b/Telegram/SourceFiles/settings.h @@ -121,9 +121,6 @@ DeclareSetting(DBIScale, ConfigScale); DeclareSetting(bool, CompressPastedImage); DeclareSetting(QString, TimeFormat); -DeclareSetting(int32, AutoLock); -DeclareSetting(bool, HasPasscode); - DeclareSetting(bool, HasAudioPlayer); DeclareSetting(bool, HasAudioCapture); diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style index 90178514f..db2d6d930 100644 --- a/Telegram/SourceFiles/settings/settings.style +++ b/Telegram/SourceFiles/settings/settings.style @@ -104,22 +104,25 @@ settingsBlocksTop: 7px; settingsBlocksBottom: 20px; settingsBlockMarginTop: 14px; settingsBlockMarginRight: 10px; -settingsBlockMarginBottom: 16px; +settingsBlockMarginBottom: 10px; settingsBlockTitleHeight: 31px; -settingsBlockTitleFont: font(14px semibold); +settingsBlockTitleFont: font(15px semibold); settingsBlockTitleFg: #333333; settingsBlockTitleTop: 0px; -settingsBlockLabel: flatLabel(labelDefFlat) { +settingsPrimaryLabel: flatLabel(labelDefFlat) { + font: boxTextFont; +} +settingsBlockLabel: flatLabel(settingsPrimaryLabel) { textFg: windowSubTextFg; } -settingsBlockOneLineTextPart: flatLabel(labelDefFlat) { +settingsBlockOneLineTextPart: flatLabel(settingsPrimaryLabel) { width: 0px; // No need to set minWidth in one-line text. margin: margins(5px, 5px, 5px, 5px); maxHeight: 20px; } settingsSubSkip: 4px; settingsSmallSkip: 10px; -settingsSkip: 15px; +settingsSkip: 14px; settingsLargeSkip: 23px; settingsActionPadding: margins(0px, 4px, 0px, 5px); diff --git a/Telegram/SourceFiles/settings/settings_advanced_widget.cpp b/Telegram/SourceFiles/settings/settings_advanced_widget.cpp index 34835e522..e95e5b560 100644 --- a/Telegram/SourceFiles/settings/settings_advanced_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_advanced_widget.cpp @@ -26,6 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "boxes/connectionbox.h" #include "boxes/confirmbox.h" #include "boxes/aboutbox.h" +#include "boxes/localstoragebox.h" #include "mainwindow.h" namespace Settings { @@ -43,14 +44,22 @@ void AdvancedWidget::createControls() { style::margins marginSmall(0, 0, 0, st::settingsSmallSkip); style::margins marginLarge(0, 0, 0, st::settingsLargeSkip); - if (self()) { - addChildRow(_manageLocalStorage, marginSmall, lang(lng_settings_manage_local_storage), SLOT(onManageLocalStorage())); - } + style::margins marginLocalStorage = ([&marginSmall, &marginLarge]() { #ifndef TDESKTOP_DISABLE_NETWORK_PROXY - addChildRow(_connectionType, marginLarge, lang(lng_connection_type), lang(lng_connection_auto_connecting)); - connectionTypeUpdated(); - connect(_connectionType->link(), SIGNAL(clicked()), this, SLOT(onConnectionType())); + return marginSmall; +#else // TDESKTOP_DISABLE_NETWORK_PROXY + return marginLarge; #endif // TDESKTOP_DISABLE_NETWORK_PROXY + })(); + if (self()) { + addChildRow(_manageLocalStorage, marginLocalStorage, lang(lng_settings_manage_local_storage), SLOT(onManageLocalStorage())); + } + +#ifndef TDESKTOP_DISABLE_NETWORK_PROXY + addChildRow(_connectionType, marginLarge, lang(lng_connection_type), lang(lng_connection_auto_connecting), LabeledLink::Type::Primary, SLOT(onConnectionType())); + connectionTypeUpdated(); +#endif // TDESKTOP_DISABLE_NETWORK_PROXY + if (self()) { addChildRow(_askQuestion, marginSmall, lang(lng_settings_ask_question), SLOT(onAskQuestion())); } @@ -61,7 +70,7 @@ void AdvancedWidget::createControls() { } void AdvancedWidget::onManageLocalStorage() { - + Ui::showLayer(new LocalStorageBox()); } #ifndef TDESKTOP_DISABLE_NETWORK_PROXY diff --git a/Telegram/SourceFiles/settings/settings_background_widget.cpp b/Telegram/SourceFiles/settings/settings_background_widget.cpp index 22d7d27a2..61c7cf27f 100644 --- a/Telegram/SourceFiles/settings/settings_background_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_background_widget.cpp @@ -33,8 +33,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Settings { BackgroundRow::BackgroundRow(QWidget *parent) : TWidget(parent) -, _chooseFromGallery(this, lang(lng_settings_bg_from_gallery)) -, _chooseFromFile(this, lang(lng_settings_bg_from_file)) +, _chooseFromGallery(this, lang(lng_settings_bg_from_gallery), st::defaultBoxLinkButton) +, _chooseFromFile(this, lang(lng_settings_bg_from_file), st::defaultBoxLinkButton) , _radial(animation(this, &BackgroundRow::step_radial)) { Window::chatBackground()->initIfEmpty(); @@ -87,8 +87,8 @@ int BackgroundRow::resizeGetHeight(int newWidth) { _chooseFromGallery->resizeToWidth(qMin(linkWidth, _chooseFromGallery->naturalWidth())); _chooseFromFile->resizeToWidth(qMin(linkWidth, _chooseFromFile->naturalWidth())); - _chooseFromGallery->moveToLeft(linkLeft, 0); - _chooseFromFile->moveToLeft(linkLeft, _chooseFromGallery->height() + st::settingsSmallSkip); + _chooseFromGallery->moveToLeft(linkLeft, 0, newWidth); + _chooseFromFile->moveToLeft(linkLeft, _chooseFromGallery->height() + st::settingsSmallSkip, newWidth); return st::settingsBackgroundSize; } diff --git a/Telegram/SourceFiles/settings/settings_block_widget.cpp b/Telegram/SourceFiles/settings/settings_block_widget.cpp index 5dfaab86c..2d143ac84 100644 --- a/Telegram/SourceFiles/settings/settings_block_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_block_widget.cpp @@ -43,10 +43,10 @@ int BlockWidget::resizeGetHeight(int newWidth) { int x = contentLeft(), result = contentTop(); int availw = newWidth - x; for_const (auto &row, _rows) { - row.child->moveToLeft(x + row.margin.left(), result + row.margin.top()); - auto availRowWidth = availw - row.margin.left() - row.margin.right(); + row.child->moveToLeft(x + row.margin.left(), result + row.margin.top(), newWidth); + auto availRowWidth = availw - row.margin.left() - row.margin.right() - x; auto natural = row.child->naturalWidth(); - auto rowWidth = (natural < 0) ? (availRowWidth - x) : qMin(natural, availRowWidth); + auto rowWidth = (natural < 0) ? availRowWidth : qMin(natural, availRowWidth); if (row.child->width() != rowWidth) { row.child->resizeToWidth(rowWidth); } @@ -85,17 +85,17 @@ void BlockWidget::rowHeightUpdated() { } void BlockWidget::createChildRow(ChildWidget &child, style::margins &margin, const QString &text, const char *slot, bool checked) { - child = new Checkbox(this, text, checked); + child = new Checkbox(this, text, checked, st::defaultBoxCheckbox); connect(child, SIGNAL(changed()), this, slot); } void BlockWidget::createChildRow(ChildWidget &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked) { - child = new Radiobutton(this, group, value, text, checked); + child = new Radiobutton(this, group, value, text, checked, st::defaultRadiobutton); connect(child, SIGNAL(changed()), this, slot); } -void BlockWidget::createChildRow(ChildWidget &child, style::margins &margin, const QString &text, const char *slot) { - child = new LinkButton(this, text); +void BlockWidget::createChildRow(ChildWidget &child, style::margins &margin, const QString &text, const char *slot, const style::linkButton &st) { + child = new LinkButton(this, text, st); connect(child, SIGNAL(clicked()), this, slot); } diff --git a/Telegram/SourceFiles/settings/settings_block_widget.h b/Telegram/SourceFiles/settings/settings_block_widget.h index f7c949b00..2118db484 100644 --- a/Telegram/SourceFiles/settings/settings_block_widget.h +++ b/Telegram/SourceFiles/settings/settings_block_widget.h @@ -89,7 +89,7 @@ private: } void createChildRow(ChildWidget &child, style::margins &margin, const QString &text, const char *slot, bool checked); void createChildRow(ChildWidget &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked); - void createChildRow(ChildWidget &child, style::margins &margin, const QString &text, const char *slot); + void createChildRow(ChildWidget &child, style::margins &margin, const QString &text, const char *slot, const style::linkButton &st = st::defaultBoxLinkButton); void addCreatedRow(TWidget *child, const style::margins &margin); void rowHeightUpdated(); diff --git a/Telegram/SourceFiles/settings/settings_chat_settings_widget.cpp b/Telegram/SourceFiles/settings/settings_chat_settings_widget.cpp index 31ecab39b..53ae1053a 100644 --- a/Telegram/SourceFiles/settings/settings_chat_settings_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_chat_settings_widget.cpp @@ -27,59 +27,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/flatlabel.h" #include "localstorage.h" #include "mainwidget.h" +#include "mainwindow.h" #include "boxes/emojibox.h" #include "boxes/stickersetbox.h" #include "boxes/downloadpathbox.h" #include "boxes/connectionbox.h" +#include "boxes/confirmbox.h" namespace Settings { -ChatSettingsWidget::ChatSettingsWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_chat_settings)) { - createControls(); - - subscribe(Global::RefDownloadPathChanged(), [this]() { - _downloadPath->entity()->link()->setText(downloadPathText()); - resizeToWidth(width()); - }); -} - -QString ChatSettingsWidget::downloadPathText() const { - if (Global::DownloadPath().isEmpty()) { - return lang(lng_download_path_default); - } else if (Global::DownloadPath() == qsl("tmp")) { - return lang(lng_download_path_temp); - } - return QDir::toNativeSeparators(Global::DownloadPath()); -}; - - -void ChatSettingsWidget::createControls() { - style::margins marginSmall(0, 0, 0, st::settingsSmallSkip); - style::margins marginSkip(0, 0, 0, st::settingsSkip); - style::margins marginSub(0, 0, 0, st::settingsSubSkip); - style::margins slidedPadding(0, marginSub.bottom() / 2, 0, marginSub.bottom() - (marginSub.bottom() / 2)); - - addChildRow(_replaceEmoji, marginSub, lang(lng_settings_replace_emojis), SLOT(onReplaceEmoji()), cReplaceEmojis()); - style::margins marginList(st::defaultCheckbox.textPosition.x(), 0, 0, st::settingsSkip); - addChildRow(_viewList, marginList, slidedPadding, lang(lng_settings_view_emojis), SLOT(onViewList())); - - addChildRow(_dontAskDownloadPath, marginSub, lang(lng_download_path_dont_ask), SLOT(onDontAskDownloadPath()), !Global::AskDownloadPath()); - style::margins marginPath(st::defaultCheckbox.textPosition.x(), 0, 0, st::settingsSkip); - addChildRow(_downloadPath, marginPath, slidedPadding, lang(lng_download_path_label), downloadPathText()); - connect(_downloadPath->entity()->link(), SIGNAL(clicked()), this, SLOT(onDownloadPath())); - if (Global::AskDownloadPath()) { - _downloadPath->hideFast(); - } - - addChildRow(_sendByEnter, marginSmall, qsl("send_key"), 0, lang(lng_settings_send_enter), SLOT(onSendByEnter()), !cCtrlEnter()); - addChildRow(_sendByCtrlEnter, marginSkip, qsl("send_key"), 1, lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter), SLOT(onSendByCtrlEnter()), cCtrlEnter()); - addChildRow(_automaticMediaDownloadSettings, marginSmall, lang(lng_media_auto_settings), SLOT(onAutomaticMediaDownloadSettings())); - addChildRow(_manageStickerSets, marginSmall, lang(lng_stickers_you_have), SLOT(onManageStickerSets())); -} - -LabeledLink::LabeledLink(QWidget *parent, const QString &label, const QString &text) : TWidget(parent) -, _label(this, label, FlatLabel::InitType::Simple) -, _link(this, text) { +LabeledLink::LabeledLink(QWidget *parent, const QString &label, const QString &text, Type type, const char *slot) : TWidget(parent) +, _label(this, label, FlatLabel::InitType::Simple, (type == Type::Primary) ? st::settingsPrimaryLabel : st::labelDefFlat) +, _link(this, text, (type == Type::Primary) ? st::defaultBoxLinkButton : st::btnDefLink) { + connect(_link, SIGNAL(clicked()), parent, slot); } void LabeledLink::setLink(const QString &text) { @@ -92,12 +52,130 @@ int LabeledLink::naturalWidth() const { } int LabeledLink::resizeGetHeight(int newWidth) { - _label->moveToLeft(0, 0); + _label->moveToLeft(0, 0, newWidth); _link->resizeToWidth(newWidth - st::normalFont->spacew - _label->width()); - _link->moveToLeft(_label->width() + st::normalFont->spacew, 0); + _link->moveToLeft(_label->width() + st::normalFont->spacew, 0, newWidth); return _label->height(); } +DownloadPathState::DownloadPathState(QWidget *parent) : TWidget(parent) +, _path(this, lang(lng_download_path_label), downloadPathText(), LabeledLink::Type::Secondary, SLOT(onDownloadPath())) +, _clear(this, lang(lng_download_path_clear)) { + connect(_clear, SIGNAL(clicked()), this, SLOT(onClear())); + connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int))); + connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int))); + subscribe(Global::RefDownloadPathChanged(), [this]() { + _path->link()->setText(downloadPathText()); + resizeToWidth(width()); + }); + switch (App::wnd()->tempDirState()) { + case MainWindow::TempDirEmpty: _state = State::Empty; break; + case MainWindow::TempDirExists: _state = State::Exists; break; + case MainWindow::TempDirRemoving: _state = State::Clearing; break; + } + updateControls(); +} + +int DownloadPathState::resizeGetHeight(int newWidth) { + _path->resizeToWidth(qMin(newWidth, _path->naturalWidth())); + _path->moveToLeft(0, 0, newWidth); + _clear->moveToRight(0, 0, newWidth); + return _path->height(); +} + +void DownloadPathState::paintEvent(QPaintEvent *e) { + Painter p(this); + + auto text = ([this]() -> QString { + switch (_state) { + case State::Clearing: return lang(lng_download_path_clearing); + case State::Cleared: return lang(lng_download_path_cleared); + case State::ClearFailed: return lang(lng_download_path_clear_failed); + } + return QString(); + })(); + if (!text.isEmpty()) { + p.setFont(st::linkFont); + p.setPen(st::windowTextFg); + p.drawTextRight(0, 0, width(), text); + } +} + +void DownloadPathState::updateControls() { + _clear->setVisible(_state == State::Exists); + update(); +} + +QString DownloadPathState::downloadPathText() const { + if (Global::DownloadPath().isEmpty()) { + return lang(lng_download_path_default); + } else if (Global::DownloadPath() == qsl("tmp")) { + return lang(lng_download_path_temp); + } + return QDir::toNativeSeparators(Global::DownloadPath()); +}; + +void DownloadPathState::onDownloadPath() { + Ui::showLayer(new DownloadPathBox()); +} + +void DownloadPathState::onClear() { + ConfirmBox *box = new ConfirmBox(lang(lng_sure_clear_downloads)); + connect(box, SIGNAL(confirmed()), this, SLOT(onClearSure())); + Ui::showLayer(box); +} + +void DownloadPathState::onClearSure() { + Ui::hideLayer(); + App::wnd()->tempDirDelete(Local::ClearManagerDownloads); + _state = State::Clearing; + updateControls(); +} + +void DownloadPathState::onTempDirCleared(int task) { + if (task & Local::ClearManagerDownloads) { + _state = State::Cleared; + } + updateControls(); +} + +void DownloadPathState::onTempDirClearFailed(int task) { + if (task & Local::ClearManagerDownloads) { + _state = State::ClearFailed; + } + updateControls(); +} + +ChatSettingsWidget::ChatSettingsWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_chat_settings)) { + createControls(); +} + +void ChatSettingsWidget::createControls() { + style::margins marginSmall(0, 0, 0, st::settingsSmallSkip); + style::margins marginSkip(0, 0, 0, st::settingsSkip); + style::margins marginSub(0, 0, 0, st::settingsSubSkip); + style::margins slidedPadding(0, marginSub.bottom() / 2, 0, marginSub.bottom() - (marginSub.bottom() / 2)); + + addChildRow(_replaceEmoji, marginSub, lang(lng_settings_replace_emojis), SLOT(onReplaceEmoji()), cReplaceEmojis()); + style::margins marginList(st::defaultBoxCheckbox.textPosition.x(), 0, 0, st::settingsSkip); + addChildRow(_viewList, marginList, slidedPadding, lang(lng_settings_view_emojis), SLOT(onViewList()), st::btnDefLink); + if (!cReplaceEmojis()) { + _viewList->hideFast(); + } + + addChildRow(_dontAskDownloadPath, marginSub, lang(lng_download_path_dont_ask), SLOT(onDontAskDownloadPath()), !Global::AskDownloadPath()); + style::margins marginPath(st::defaultBoxCheckbox.textPosition.x(), 0, 0, st::settingsSkip); + addChildRow(_downloadPath, marginPath, slidedPadding); + if (Global::AskDownloadPath()) { + _downloadPath->hideFast(); + } + + addChildRow(_sendByEnter, marginSmall, qsl("send_key"), 0, lang(lng_settings_send_enter), SLOT(onSendByEnter()), !cCtrlEnter()); + addChildRow(_sendByCtrlEnter, marginSkip, qsl("send_key"), 1, lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter), SLOT(onSendByCtrlEnter()), cCtrlEnter()); + addChildRow(_automaticMediaDownloadSettings, marginSmall, lang(lng_media_auto_settings), SLOT(onAutomaticMediaDownloadSettings())); + addChildRow(_manageStickerSets, marginSmall, lang(lng_stickers_you_have), SLOT(onManageStickerSets())); +} + void ChatSettingsWidget::onReplaceEmoji() { cSetReplaceEmojis(_replaceEmoji->checked()); Local::writeUserSettings(); @@ -123,10 +201,6 @@ void ChatSettingsWidget::onDontAskDownloadPath() { } } -void ChatSettingsWidget::onDownloadPath() { - Ui::showLayer(new DownloadPathBox()); -} - void ChatSettingsWidget::onSendByEnter() { if (_sendByEnter->checked()) { cSetCtrlEnter(false); diff --git a/Telegram/SourceFiles/settings/settings_chat_settings_widget.h b/Telegram/SourceFiles/settings/settings_chat_settings_widget.h index 6656c7811..7b4a1fc9d 100644 --- a/Telegram/SourceFiles/settings/settings_chat_settings_widget.h +++ b/Telegram/SourceFiles/settings/settings_chat_settings_widget.h @@ -28,7 +28,11 @@ namespace Settings { class LabeledLink : public TWidget { public: - LabeledLink(QWidget *parent, const QString &label, const QString &text); + enum class Type { + Primary, + Secondary, + }; + LabeledLink(QWidget *parent, const QString &label, const QString &text, Type type, const char *slot); void setLink(const QString &text); @@ -47,6 +51,42 @@ private: }; +class DownloadPathState : public TWidget, public base::Subscriber { + Q_OBJECT + +public: + DownloadPathState(QWidget *parent); + +protected: + int resizeGetHeight(int newWidth) override; + + void paintEvent(QPaintEvent *e) override; + +private slots: + void onDownloadPath(); + void onClear(); + void onClearSure(); + void onTempDirCleared(int task); + void onTempDirClearFailed(int task); + +private: + QString downloadPathText() const; + void updateControls(); + + enum class State { + Empty, + Exists, + Clearing, + Cleared, + ClearFailed, + }; + State _state = State::Empty; + + ChildWidget _path; + ChildWidget _clear; + +}; + class ChatSettingsWidget : public BlockWidget { Q_OBJECT @@ -57,7 +97,6 @@ private slots: void onReplaceEmoji(); void onViewList(); void onDontAskDownloadPath(); - void onDownloadPath(); void onSendByEnter(); void onSendByCtrlEnter(); void onAutomaticMediaDownloadSettings(); @@ -65,12 +104,11 @@ private slots: private: void createControls(); - QString downloadPathText() const; ChildWidget _replaceEmoji = { nullptr }; ChildWidget> _viewList = { nullptr }; ChildWidget _dontAskDownloadPath = { nullptr }; - ChildWidget> _downloadPath = { nullptr }; + ChildWidget> _downloadPath = { nullptr }; ChildWidget _sendByEnter = { nullptr }; ChildWidget _sendByCtrlEnter = { nullptr }; ChildWidget _automaticMediaDownloadSettings = { nullptr }; diff --git a/Telegram/SourceFiles/settings/settings_cover.cpp b/Telegram/SourceFiles/settings/settings_cover.cpp index d6c689d91..11047c067 100644 --- a/Telegram/SourceFiles/settings/settings_cover.cpp +++ b/Telegram/SourceFiles/settings/settings_cover.cpp @@ -97,19 +97,19 @@ int CoverWidget::resizeGetHeight(int newWidth) { newHeight += st::settingsMarginTop; - _userpicButton->moveToLeft(contentLeft() + st::settingsPhotoLeft, newHeight); + _userpicButton->moveToLeft(contentLeft() + st::settingsPhotoLeft, newHeight, newWidth); int infoLeft = _userpicButton->x() + _userpicButton->width(); _statusPosition = QPoint(infoLeft + st::settingsStatusLeft, _userpicButton->y() + st::settingsStatusTop); if (_cancelPhotoUpload) { - _cancelPhotoUpload->moveToLeft(_statusPosition.x() + st::settingsStatusFont->width(_statusText) + st::settingsStatusFont->spacew, _statusPosition.y()); + _cancelPhotoUpload->moveToLeft(_statusPosition.x() + st::settingsStatusFont->width(_statusText) + st::settingsStatusFont->spacew, _statusPosition.y(), newWidth); } int buttonLeft = _userpicButton->x() + _userpicButton->width() + st::settingsButtonLeft; int buttonsRight = newWidth - st::settingsButtonSkip; - _setPhoto->moveToLeft(buttonLeft, _userpicButton->y() + st::settingsButtonTop); + _setPhoto->moveToLeft(buttonLeft, _userpicButton->y() + st::settingsButtonTop, newWidth); buttonLeft += _setPhoto->width() + st::settingsButtonSkip; - _editName->moveToLeft(buttonLeft, _setPhoto->y()); + _editName->moveToLeft(buttonLeft, _setPhoto->y(), newWidth); _editNameVisible = (buttonLeft + _editName->width() + st::settingsButtonSkip <= newWidth); _editName->setVisible(_editNameVisible); @@ -139,9 +139,9 @@ void CoverWidget::refreshNameGeometry(int newWidth) { int marginsAdd = st::settingsNameLabel.margin.left() + st::settingsNameLabel.margin.right(); _name->resizeToWidth(qMin(nameWidth - marginsAdd, _name->naturalWidth()) + marginsAdd); - _name->moveToLeft(nameLeft, nameTop); + _name->moveToLeft(nameLeft, nameTop, newWidth); - _editNameInline->moveToLeft(nameLeft + _name->width(), nameTop); + _editNameInline->moveToLeft(nameLeft + _name->width(), nameTop, newWidth); _editNameInline->setVisible(editNameInlineVisible); } diff --git a/Telegram/SourceFiles/settings/settings_general_widget.cpp b/Telegram/SourceFiles/settings/settings_general_widget.cpp index 5b799e72c..80516272f 100644 --- a/Telegram/SourceFiles/settings/settings_general_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_general_widget.cpp @@ -45,7 +45,7 @@ QString currentVersion() { result += " alpha"; } if (cBetaVersion()) { - result += qsl(" beta %1").arg(cBetaVersion()); + result += qsl(" beta %1").arg(cBetaVersion() % 1000); } return result; } @@ -83,10 +83,10 @@ int UpdateStateRow::resizeGetHeight(int newWidth) { auto restartLeft = labelWidth(lang(lng_settings_update_ready)); _check->resizeToWidth(qMin(newWidth, _check->naturalWidth())); - _check->moveToLeft(checkLeft, 0); + _check->moveToLeft(checkLeft, 0, newWidth); _restart->resizeToWidth(qMin(newWidth, _restart->naturalWidth())); - _restart->moveToLeft(restartLeft, 0); + _restart->moveToLeft(restartLeft, 0, newWidth); return _check->height(); } @@ -112,6 +112,7 @@ void UpdateStateRow::paintEvent(QPaintEvent *e) { void UpdateStateRow::onCheck() { if (!cAutoUpdate()) return; + setState(State::Check); cSetLastUpdateCheck(0); Sandbox::startUpdateCheck(); } @@ -120,11 +121,11 @@ void UpdateStateRow::setState(State state, bool force) { if (_state != state || force) { _state = state; switch (state) { - case State::None: - case State::Latest: _check->show(); _restart->hide(); break; + case State::None: _check->show(); _restart->hide(); break; case State::Ready: _check->hide(); _restart->show(); break; case State::Check: case State::Download: + case State::Latest: case State::Fail: _check->hide(); _restart->hide(); break; } resizeToWidth(width()); @@ -167,7 +168,7 @@ void UpdateStateRow::onFailed() { #endif // TDESKTOP_DISABLE_AUTOUPDATE GeneralWidget::GeneralWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_general)) -, _changeLanguage(this, lang(lng_settings_change_lang)) { +, _changeLanguage(this, lang(lng_settings_change_lang), st::defaultBoxLinkButton) { connect(_changeLanguage, SIGNAL(clicked()), this, SLOT(onChangeLanguage())); subscribe(Global::RefChooseCustomLang(), [this]() { chooseCustomLang(); }); FileDialog::registerObserver(this, &GeneralWidget::notifyFileQueryUpdated); @@ -175,7 +176,7 @@ GeneralWidget::GeneralWidget(QWidget *parent, UserData *self) : BlockWidget(pare } int GeneralWidget::resizeGetHeight(int newWidth) { - _changeLanguage->moveToRight(contentLeft(), st::settingsBlockMarginTop + st::settingsBlockTitleTop + st::settingsBlockTitleFont->ascent - st::btnDefLink.font->ascent); + _changeLanguage->moveToRight(contentLeft(), st::settingsBlockMarginTop + st::settingsBlockTitleTop + st::settingsBlockTitleFont->ascent - st::btnDefLink.font->ascent, newWidth); return BlockWidget::resizeGetHeight(newWidth); } @@ -187,7 +188,7 @@ void GeneralWidget::refreshControls() { #ifndef TDESKTOP_DISABLE_AUTOUPDATE addChildRow(_updateAutomatically, marginSub, lng_settings_update_automatically(lt_version, currentVersion()), SLOT(onUpdateAutomatically()), cAutoUpdate()); - style::margins marginLink(st::defaultCheckbox.textPosition.x(), 0, 0, st::settingsSkip); + style::margins marginLink(st::defaultBoxCheckbox.textPosition.x(), 0, 0, st::settingsSkip); addChildRow(_updateRow, marginLink, slidedPadding); connect(_updateRow->entity(), SIGNAL(restart()), this, SLOT(onRestart())); #endif // TDESKTOP_DISABLE_AUTOUPDATE diff --git a/Telegram/SourceFiles/settings/settings_info_widget.cpp b/Telegram/SourceFiles/settings/settings_info_widget.cpp index 1510ca6d9..88acf95b4 100644 --- a/Telegram/SourceFiles/settings/settings_info_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_info_widget.cpp @@ -45,6 +45,9 @@ void InfoWidget::createControls() { addChildRow(_mobileNumber, margin, slidedPadding); addChildRow(_username, margin, slidedPadding); addChildRow(_link, margin, slidedPadding); + if (self()->username.isEmpty()) { + _link->hideFast(); + } refreshControls(); } @@ -75,7 +78,7 @@ void InfoWidget::refreshUsername() { usernameText.text = '@' + self()->username; copyText = lang(lng_context_copy_mention); } - usernameText.entities.push_back(EntityInText(EntityInTextCustomUrl, 0, usernameText.text.size())); + usernameText.entities.push_back(EntityInText(EntityInTextCustomUrl, 0, usernameText.text.size(), qsl("https://telegram.me/") + self()->username)); setLabeledText(_username, lang(lng_profile_username), usernameText, TextWithEntities(), copyText); if (auto text = _username->entity()->textLabel()) { text->setClickHandlerHook(func(this, &InfoWidget::usernameClickHandlerHook)); @@ -106,10 +109,6 @@ bool InfoWidget::usernameClickHandlerHook(const ClickHandlerPtr &handler, Qt::Mo return false; } -InfoWidget::LabeledWidget::LabeledWidget(QWidget *parent) : TWidget(parent) { - resize(width(), st::labelDefFlat.font->height); -} - void InfoWidget::setLabeledText(ChildWidget &row, const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString ©Text) { if (textWithEntities.text.isEmpty()) { row->slideUp(); @@ -119,6 +118,9 @@ void InfoWidget::setLabeledText(ChildWidget &row, const QString &la } } +InfoWidget::LabeledWidget::LabeledWidget(QWidget *parent) : TWidget(parent) { +} + void InfoWidget::LabeledWidget::setLabeledText(const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString ©Text) { _label.destroy(); _text.destroy(); @@ -129,6 +131,7 @@ void InfoWidget::LabeledWidget::setLabeledText(const QString &label, const TextW _label->show(); setLabelText(_text, textWithEntities, copyText); setLabelText(_shortText, shortTextWithEntities, copyText); + resizeToWidth(width()); } void InfoWidget::LabeledWidget::setLabelText(ChildWidget &text, const TextWithEntities &textWithEntities, const QString ©Text) { @@ -161,7 +164,7 @@ void InfoWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { int InfoWidget::LabeledWidget::naturalWidth() const { if (!_text) return -1; - return _label->naturalWidth() + st::normalFont->spacew + (_shortText ? _shortText : _text)->naturalWidth(); + return _label->naturalWidth() + st::normalFont->spacew + _text->naturalWidth(); } int InfoWidget::LabeledWidget::resizeGetHeight(int newWidth) { @@ -170,7 +173,7 @@ int InfoWidget::LabeledWidget::resizeGetHeight(int newWidth) { if (!_label) return 0; - _label->moveToLeft(0, st::settingsBlockOneLineTextPart.margin.top()); + _label->moveToLeft(0, st::settingsBlockOneLineTextPart.margin.top(), newWidth); auto labelNatural = _label->naturalWidth(); t_assert(labelNatural >= 0); @@ -186,10 +189,10 @@ int InfoWidget::LabeledWidget::resizeGetHeight(int newWidth) { textWidth = -(marginLeft + marginRight); } _text->resizeToWidth(textWidth + marginLeft + marginRight); - _text->moveToLeft(textLeft - marginLeft, 0); + _text->moveToLeft(textLeft - marginLeft, 0, newWidth); if (_shortText) { _shortText->resizeToWidth(textWidth + marginLeft + marginRight); - _shortText->moveToLeft(textLeft - marginLeft, 0); + _shortText->moveToLeft(textLeft - marginLeft, 0, newWidth); if (doesNotFit) { _shortText->show(); _text->hide(); diff --git a/Telegram/SourceFiles/settings/settings_inner_widget.cpp b/Telegram/SourceFiles/settings/settings_inner_widget.cpp index cab185df3..34fcab0e8 100644 --- a/Telegram/SourceFiles/settings/settings_inner_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_inner_widget.cpp @@ -102,25 +102,25 @@ int InnerWidget::resizeGetHeight(int newWidth) { block->resizeToWidth(newWidth); } - int result = refreshBlocksPositions(); + int result = refreshBlocksPositions(newWidth); return result; } -int InnerWidget::refreshBlocksPositions() { +int InnerWidget::refreshBlocksPositions(int newWidth) { int result = (_cover ? _cover->height() : 0) + st::settingsBlocksTop; for_const (auto block, _blocks) { if (block->isHidden()) { continue; } - block->moveToLeft(0, result); + block->moveToLeft(0, result, newWidth); result += block->height(); } return result; } void InnerWidget::onBlockHeightUpdated() { - int newHeight = refreshBlocksPositions(); + int newHeight = refreshBlocksPositions(width()); if (newHeight != height()) { resize(width(), newHeight); emit heightUpdated(); diff --git a/Telegram/SourceFiles/settings/settings_inner_widget.h b/Telegram/SourceFiles/settings/settings_inner_widget.h index a71d2b20f..570c7958e 100644 --- a/Telegram/SourceFiles/settings/settings_inner_widget.h +++ b/Telegram/SourceFiles/settings/settings_inner_widget.h @@ -57,7 +57,7 @@ private: void refreshBlocks(); // Returns the new height value. - int refreshBlocksPositions(); + int refreshBlocksPositions(int newWidth); ChildWidget _cover = { nullptr }; QList _blocks; diff --git a/Telegram/SourceFiles/settings/settings_notifications_widget.cpp b/Telegram/SourceFiles/settings/settings_notifications_widget.cpp index 4f7b45585..86c34889c 100644 --- a/Telegram/SourceFiles/settings/settings_notifications_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_notifications_widget.cpp @@ -45,7 +45,7 @@ NotificationsWidget::NotificationsWidget(QWidget *parent, UserData *self) : Bloc } void NotificationsWidget::createControls() { - style::margins margin(0, 0, 0, st::settingsSmallSkip); + style::margins margin(0, 0, 0, st::settingsSkip); style::margins slidedPadding(0, margin.bottom() / 2, 0, margin.bottom() - (margin.bottom() / 2)); addChildRow(_desktopNotifications, margin, lang(lng_settings_desktop_notify), SLOT(onDesktopNotifications()), Global::DesktopNotify()); addChildRow(_showSenderName, margin, slidedPadding, lang(lng_settings_show_name), SLOT(onShowSenderName()), Global::NotifyView() <= dbinvShowName); diff --git a/Telegram/SourceFiles/settings/settings_privacy_widget.cpp b/Telegram/SourceFiles/settings/settings_privacy_widget.cpp index 972ea269d..03c08e540 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_widget.cpp @@ -21,32 +21,181 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "settings/settings_privacy_widget.h" +#include "ui/widgets/widget_slide_wrap.h" #include "styles/style_settings.h" #include "lang.h" +#include "application.h" #include "boxes/sessionsbox.h" +#include "boxes/passcodebox.h" +#include "boxes/autolockbox.h" +#include "pspecific.h" namespace Settings { -PrivacyWidget::PrivacyWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_privacy)) { - refreshControls(); +LocalPasscodeState::LocalPasscodeState(QWidget *parent) : TWidget(parent) +, _edit(this, lang(Global::LocalPasscode() ? lng_passcode_change : lng_passcode_turn_on), st::defaultBoxLinkButton) +, _turnOff(this, lang(lng_passcode_turn_off), st::defaultBoxLinkButton) { + updateControls(); + connect(_edit, SIGNAL(clicked()), this, SLOT(onEdit())); + connect(_turnOff, SIGNAL(clicked()), this, SLOT(onTurnOff())); + subscribe(Global::RefLocalPasscodeChanged(), [this]() { updateControls(); }); } -void PrivacyWidget::refreshControls() { +int LocalPasscodeState::resizeGetHeight(int newWidth) { + _edit->moveToLeft(0, 0, newWidth); + _turnOff->moveToRight(0, 0, newWidth); + return _edit->height(); +} + +void LocalPasscodeState::onEdit() { + Ui::showLayer(new PasscodeBox()); +} + +void LocalPasscodeState::onTurnOff() { + Ui::showLayer(new PasscodeBox(true)); +} + +void LocalPasscodeState::updateControls() { + _edit->setText(lang(Global::LocalPasscode() ? lng_passcode_change : lng_passcode_turn_on)); + _edit->moveToLeft(0, 0); + _turnOff->setVisible(Global::LocalPasscode()); +} + +CloudPasswordState::CloudPasswordState(QWidget *parent) : TWidget(parent) +, _edit(this, lang(lng_cloud_password_set), st::defaultBoxLinkButton) +, _turnOff(this, lang(lng_passcode_turn_off), st::defaultBoxLinkButton) { + _turnOff->hide(); + connect(_edit, SIGNAL(clicked()), this, SLOT(onEdit())); + connect(_turnOff, SIGNAL(clicked()), this, SLOT(onTurnOff())); + Sandbox::connect(SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(onReloadPassword(Qt::ApplicationState))); + onReloadPassword(); +} + +int CloudPasswordState::resizeGetHeight(int newWidth) { + _edit->moveToLeft(0, 0, newWidth); + _turnOff->moveToRight(0, 0, newWidth); + return _edit->height(); +} + +void CloudPasswordState::onEdit() { + PasscodeBox *box = new PasscodeBox(_newPasswordSalt, _curPasswordSalt, _hasPasswordRecovery, _curPasswordHint); + connect(box, SIGNAL(reloadPassword()), this, SLOT(onReloadPassword())); + Ui::showLayer(box); +} + +void CloudPasswordState::onTurnOff() { + if (_curPasswordSalt.isEmpty()) { + _turnOff->hide(); + + MTPDaccount_passwordInputSettings::Flags flags = MTPDaccount_passwordInputSettings::Flag::f_email; + MTPaccount_PasswordInputSettings settings(MTP_account_passwordInputSettings(MTP_flags(flags), MTP_bytes(QByteArray()), MTP_bytes(QByteArray()), MTP_string(QString()), MTP_string(QString()))); + MTP::send(MTPaccount_UpdatePasswordSettings(MTP_bytes(QByteArray()), settings), rpcDone(&CloudPasswordState::offPasswordDone), rpcFail(&CloudPasswordState::offPasswordFail)); + } else { + PasscodeBox *box = new PasscodeBox(_newPasswordSalt, _curPasswordSalt, _hasPasswordRecovery, _curPasswordHint, true); + connect(box, SIGNAL(reloadPassword()), this, SLOT(onReloadPassword())); + Ui::showLayer(box); + } +} + +void CloudPasswordState::onReloadPassword(Qt::ApplicationState state) { + if (state == Qt::ApplicationActive) { + MTP::send(MTPaccount_GetPassword(), rpcDone(&CloudPasswordState::getPasswordDone)); + } +} + +void CloudPasswordState::getPasswordDone(const MTPaccount_Password &result) { + _waitingConfirm = QString(); + + switch (result.type()) { + case mtpc_account_noPassword: { + auto &d = result.c_account_noPassword(); + _curPasswordSalt = QByteArray(); + _hasPasswordRecovery = false; + _curPasswordHint = QString(); + _newPasswordSalt = qba(d.vnew_salt); + auto pattern = qs(d.vemail_unconfirmed_pattern); + if (!pattern.isEmpty()) { + _waitingConfirm = lng_cloud_password_waiting(lt_email, pattern); + } + } break; + + case mtpc_account_password: { + auto &d = result.c_account_password(); + _curPasswordSalt = qba(d.vcurrent_salt); + _hasPasswordRecovery = mtpIsTrue(d.vhas_recovery); + _curPasswordHint = qs(d.vhint); + _newPasswordSalt = qba(d.vnew_salt); + auto pattern = qs(d.vemail_unconfirmed_pattern); + if (!pattern.isEmpty()) { + _waitingConfirm = lng_cloud_password_waiting(lt_email, pattern); + } + } break; + } + _edit->setText(lang(_curPasswordSalt.isEmpty() ? lng_cloud_password_set : lng_cloud_password_edit)); + _edit->setVisible(_waitingConfirm.isEmpty()); + _turnOff->setVisible(!_waitingConfirm.isEmpty() || !_curPasswordSalt.isEmpty()); + update(); + + _newPasswordSalt.resize(_newPasswordSalt.size() + 8); + memset_rand(_newPasswordSalt.data() + _newPasswordSalt.size() - 8, 8); +} + +void CloudPasswordState::paintEvent(QPaintEvent *e) { + Painter p(this); + + auto text = st::linkFont->elided(_waitingConfirm, width() - _turnOff->width()); + if (!text.isEmpty()) { + p.setPen(st::windowTextFg); + p.setFont(st::boxTextFont); + p.drawTextLeft(0, 0, width(), text); + } +} + +void CloudPasswordState::offPasswordDone(const MTPBool &result) { + onReloadPassword(); +} + +bool CloudPasswordState::offPasswordFail(const RPCError &error) { + if (MTP::isDefaultHandledError(error)) return false; + + onReloadPassword(); + return true; +} + +PrivacyWidget::PrivacyWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_privacy)) { + createControls(); + subscribe(Global::RefLocalPasscodeChanged(), [this]() { autoLockUpdated(); }); +} + +void PrivacyWidget::createControls() { style::margins marginSmall(0, 0, 0, st::settingsSmallSkip); style::margins marginSkip(0, 0, 0, st::settingsSkip); style::margins slidedPadding(0, marginSmall.bottom() / 2, 0, marginSmall.bottom() - (marginSmall.bottom() / 2)); - addChildRow(_editPasscode, marginSmall, lang(lng_passcode_turn_on), SLOT(onEditPasscode())); - addChildRow(_editPassword, marginSmall, lang(lng_cloud_password_set), SLOT(onEditPassword())); + addChildRow(_localPasscodeState, marginSmall); + auto label = lang(psIdleSupported() ? lng_passcode_autolock_away : lng_passcode_autolock_inactive); + auto value = (Global::AutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, Global::AutoLock() / 60) : lng_passcode_autolock_hours(lt_count, Global::AutoLock() / 3600); + addChildRow(_autoLock, marginSmall, slidedPadding, label, value, LabeledLink::Type::Primary, SLOT(onAutoLock())); + if (!Global::LocalPasscode()) { + _autoLock->hideFast(); + } + addChildRow(_cloudPasswordState, marginSmall); addChildRow(_showAllSessions, marginSmall, lang(lng_settings_show_sessions), SLOT(onShowSessions())); } -void PrivacyWidget::onEditPasscode() { - +void PrivacyWidget::autoLockUpdated() { + if (Global::LocalPasscode()) { + auto value = (Global::AutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, Global::AutoLock() / 60) : lng_passcode_autolock_hours(lt_count, Global::AutoLock() / 3600); + _autoLock->entity()->link()->setText(value); + resizeToWidth(width()); + _autoLock->slideDown(); + } else { + _autoLock->slideUp(); + } } -void PrivacyWidget::onEditPassword() { - +void PrivacyWidget::onAutoLock() { + Ui::showLayer(new AutoLockBox()); } void PrivacyWidget::onShowSessions() { diff --git a/Telegram/SourceFiles/settings/settings_privacy_widget.h b/Telegram/SourceFiles/settings/settings_privacy_widget.h index cce92d5de..eec2ff87d 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_widget.h +++ b/Telegram/SourceFiles/settings/settings_privacy_widget.h @@ -21,13 +21,61 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "settings/settings_block_widget.h" +#include "settings/settings_chat_settings_widget.h" namespace Settings { -class LocalPasscodeState : public TWidget { +class LocalPasscodeState : public TWidget, public base::Subscriber { + Q_OBJECT + +public: + LocalPasscodeState(QWidget *parent); + +protected: + int resizeGetHeight(int newWidth) override; + +private slots: + void onEdit(); + void onTurnOff(); + +private: + void updateControls(); + + ChildWidget _edit; + ChildWidget _turnOff; + }; -class CloudPasswordState : public TWidget { +class CloudPasswordState : public TWidget, private base::Subscriber, public RPCSender { + Q_OBJECT + +public: + CloudPasswordState(QWidget *parent); + +protected: + int resizeGetHeight(int newWidth) override; + + void paintEvent(QPaintEvent *e) override; + +private slots: + void onEdit(); + void onTurnOff(); + void onReloadPassword(Qt::ApplicationState state = Qt::ApplicationActive); + +private: + void getPasswordDone(const MTPaccount_Password &result); + void offPasswordDone(const MTPBool &result); + bool offPasswordFail(const RPCError &error); + + ChildWidget _edit; + ChildWidget _turnOff; + + QString _waitingConfirm; + QByteArray _curPasswordSalt; + bool _hasPasswordRecovery = false; + QString _curPasswordHint; + QByteArray _newPasswordSalt; + }; class PrivacyWidget : public BlockWidget { @@ -37,18 +85,16 @@ public: PrivacyWidget(QWidget *parent, UserData *self); private slots: - void onEditPasscode(); - void onEditPassword(); + void onAutoLock(); void onShowSessions(); private: - void refreshControls(); + void createControls(); + void autoLockUpdated(); - //ChildWidget _localPasscodeState = { nullptr }; - //ChildWidget> _autoLock = { nullptr }; - //ChildWidget _cloudPasswordState = { nullptr }; - ChildWidget _editPasscode = { nullptr }; - ChildWidget _editPassword = { nullptr }; + ChildWidget _localPasscodeState = { nullptr }; + ChildWidget> _autoLock = { nullptr }; + ChildWidget _cloudPasswordState = { nullptr }; ChildWidget _showAllSessions = { nullptr }; }; diff --git a/Telegram/SourceFiles/settingswidget.cpp b/Telegram/SourceFiles/settingswidget.cpp index ff8220b81..e6e02552f 100644 --- a/Telegram/SourceFiles/settingswidget.cpp +++ b/Telegram/SourceFiles/settingswidget.cpp @@ -191,9 +191,9 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent) , _radial(animation(this, &SettingsInner::step_radial)) // advanced -, _passcodeEdit(this, lang(cHasPasscode() ? lng_passcode_change : lng_passcode_turn_on)) +, _passcodeEdit(this, lang(Global::LocalPasscode() ? lng_passcode_change : lng_passcode_turn_on)) , _passcodeTurnOff(this, lang(lng_passcode_turn_off)) -, _autoLock(this, (cAutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, cAutoLock() / 60) : lng_passcode_autolock_hours(lt_count, cAutoLock() / 3600)) +, _autoLock(this, /*(cAutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, cAutoLock() / 60) : lng_passcode_autolock_hours(lt_count, cAutoLock() / 3600)*/"") , _autoLockText(lang(psIdleSupported() ? lng_passcode_autolock_away : lng_passcode_autolock_inactive) + ' ') , _autoLockWidth(st::linkFont->width(_autoLockText)) , _passwordEdit(this, lang(lng_cloud_password_set)) @@ -665,7 +665,7 @@ void SettingsInner::paintEvent(QPaintEvent *e) { p.setPen(st::black->p); if (self()) { top += _passcodeEdit.height() + st::setLittleSkip; - if (cHasPasscode()) { + if (Global::LocalPasscode()) { p.drawText(_left, top + st::linkFont->ascent, _autoLockText); top += _autoLock.height() + st::setLittleSkip; } @@ -782,7 +782,7 @@ void SettingsInner::resizeEvent(QResizeEvent *e) { if (self()) { _passcodeEdit.move(_left, top); _passcodeTurnOff.move(_left + st::setWidth - _passcodeTurnOff.width(), top); top += _passcodeTurnOff.height() + st::setLittleSkip; - if (cHasPasscode()) { + if (Global::LocalPasscode()) { _autoLock.move(_left + _autoLockWidth, top); top += _autoLock.height() + st::setLittleSkip; } _passwordEdit.move(_left, top); @@ -953,8 +953,8 @@ void SettingsInner::updateConnectionType() { void SettingsInner::passcodeChanged() { resizeEvent(0); - _passcodeEdit.setText(lang(cHasPasscode() ? lng_passcode_change : lng_passcode_turn_on)); - _autoLock.setText((cAutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, cAutoLock() / 60) : lng_passcode_autolock_hours(lt_count, cAutoLock() / 3600)); + //_passcodeEdit.setText(lang(cHasPasscode() ? lng_passcode_change : lng_passcode_turn_on)); + //_autoLock.setText((cAutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, cAutoLock() / 60) : lng_passcode_autolock_hours(lt_count, cAutoLock() / 3600)); // _passwordEdit.setText() showAll(); } @@ -1165,7 +1165,7 @@ void SettingsInner::showAll() { // advanced if (self()) { _passcodeEdit.show(); - if (cHasPasscode()) { + if (Global::LocalPasscode()) { _autoLock.show(); _passcodeTurnOff.show(); } else { diff --git a/Telegram/SourceFiles/shortcuts.cpp b/Telegram/SourceFiles/shortcuts.cpp index 9f782ea35..89b8facc3 100644 --- a/Telegram/SourceFiles/shortcuts.cpp +++ b/Telegram/SourceFiles/shortcuts.cpp @@ -35,7 +35,7 @@ bool lock_telegram() { if (App::passcoded()) { w->passcodeWidget()->onSubmit(); return true; - } else if (cHasPasscode()) { + } else if (Global::LocalPasscode()) { w->setupPasscode(true); return true; } diff --git a/Telegram/SourceFiles/title.cpp b/Telegram/SourceFiles/title.cpp index 170afbd89..f75eb8d58 100644 --- a/Telegram/SourceFiles/title.cpp +++ b/Telegram/SourceFiles/title.cpp @@ -73,7 +73,7 @@ TitleWidget::TitleWidget(MainWindow *window) : TWidget(window) #ifndef TDESKTOP_DISABLE_AUTOUPDATE Sandbox::updatingState() == Application::UpdatingReady || #endif - cHasPasscode() + Global::LocalPasscode() ) { showUpdateBtn(); } @@ -309,7 +309,7 @@ void TitleWidget::showUpdateBtn() { _close.hide(); return; } - if (cHasPasscode()) { + if (Global::LocalPasscode()) { _lock.show(); } else { _lock.hide(); diff --git a/Telegram/SourceFiles/ui/flatbutton.cpp b/Telegram/SourceFiles/ui/flatbutton.cpp index 2fff65d45..3ed82ca7b 100644 --- a/Telegram/SourceFiles/ui/flatbutton.cpp +++ b/Telegram/SourceFiles/ui/flatbutton.cpp @@ -121,26 +121,36 @@ void FlatButton::paintEvent(QPaintEvent *e) { p.drawText(r, _text, style::al_top); } -LinkButton::LinkButton(QWidget *parent, const QString &text, const style::linkButton &st) : Button(parent), _text(text), _st(st) { +LinkButton::LinkButton(QWidget *parent, const QString &text, const style::linkButton &st) : Button(parent) +, _text(text) +, _textWidth(st.font->width(_text)) +, _st(st) { connect(this, SIGNAL(stateChanged(int, ButtonStateChangeSource)), this, SLOT(onStateChange(int, ButtonStateChangeSource))); - resize(_st.font->width(_text), _st.font->height); + resize(_textWidth, _st.font->height); setCursor(style::cur_pointer); } int LinkButton::naturalWidth() const { - return _st.font->width(_text); + return _textWidth; } void LinkButton::paintEvent(QPaintEvent *e) { - QPainter p(this); - p.setFont(((_state & StateOver) ? _st.overFont : _st.font)->f); - p.setPen(((_state & StateDown) ? _st.downColor : ((_state & StateOver) ? _st.overColor : _st.color))->p); - p.drawText(0, ((_state & StateOver) ? _st.overFont : _st.font)->ascent, _text); + Painter p(this); + auto &font = ((_state & StateOver) ? _st.overFont : _st.font); + auto &pen = ((_state & StateDown) ? _st.downColor : ((_state & StateOver) ? _st.overColor : _st.color)); + p.setFont(font); + p.setPen(pen); + if (_textWidth > width()) { + p.drawText(0, font->ascent, font->elided(_text, width())); + } else { + p.drawText(0, font->ascent, _text); + } } void LinkButton::setText(const QString &text) { _text = text; - resize(_st.font->width(_text), _st.font->height); + _textWidth = _st.font->width(_text); + resize(_textWidth, _st.font->height); update(); } diff --git a/Telegram/SourceFiles/ui/flatbutton.h b/Telegram/SourceFiles/ui/flatbutton.h index aada3d54c..83d725615 100644 --- a/Telegram/SourceFiles/ui/flatbutton.h +++ b/Telegram/SourceFiles/ui/flatbutton.h @@ -82,6 +82,7 @@ public slots: private: QString _text; + int _textWidth = 0; style::linkButton _st; }; diff --git a/Telegram/gyp/Telegram.gyp b/Telegram/gyp/Telegram.gyp index 3798112ea..a69901236 100644 --- a/Telegram/gyp/Telegram.gyp +++ b/Telegram/gyp/Telegram.gyp @@ -163,6 +163,8 @@ '<(src_loc)/boxes/emojibox.h', '<(src_loc)/boxes/languagebox.cpp', '<(src_loc)/boxes/languagebox.h', + '<(src_loc)/boxes/localstoragebox.cpp', + '<(src_loc)/boxes/localstoragebox.h', '<(src_loc)/boxes/passcodebox.cpp', '<(src_loc)/boxes/passcodebox.h', '<(src_loc)/boxes/photocropbox.cpp',