diff --git a/Telegram/SourceFiles/history/history_item_components.cpp b/Telegram/SourceFiles/history/history_item_components.cpp index c57dfc6f3..d71e861f5 100644 --- a/Telegram/SourceFiles/history/history_item_components.cpp +++ b/Telegram/SourceFiles/history/history_item_components.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_text_entities.h" #include "base/qt/qt_key_modifiers.h" +#include "base/options.h" #include "lang/lang_keys.h" #include "ui/effects/ripple_animation.h" #include "ui/effects/spoiler_mess.h" @@ -63,8 +64,20 @@ namespace { const auto kPsaForwardedPrefix = "cloud_lng_forwarded_psa_"; +base::options::toggle FastButtonsModeOption({ + .id = kOptionFastButtonsMode, + .name = "Fast buttons mode", + .description = "Trigger inline keyboard buttons by 1-9 keyboard keys.", +}); + } // namespace +const char kOptionFastButtonsMode[] = "fast-buttons-mode"; + +bool FastButtonsMode() { + return FastButtonsModeOption.value(); +} + void HistoryMessageVia::create( not_null owner, UserId userId) { @@ -924,10 +937,10 @@ void ReplyKeyboard::paint( } bool ReplyKeyboard::hasFastButtonMode() const { - return _item->inlineReplyKeyboard() + return FastButtonsMode() + && _item->inlineReplyKeyboard() && (_item == _item->history()->lastMessage()) - && _item->history()->session().supportMode() - && _item->history()->session().supportHelper().fastButtonMode( + && _item->history()->session().fastButtonsBots().enabled( _item->history()->peer); } diff --git a/Telegram/SourceFiles/history/history_item_components.h b/Telegram/SourceFiles/history/history_item_components.h index c2281496b..331ee24df 100644 --- a/Telegram/SourceFiles/history/history_item_components.h +++ b/Telegram/SourceFiles/history/history_item_components.h @@ -54,6 +54,9 @@ namespace style { struct BotKeyboardButton; } // namespace style +extern const char kOptionFastButtonsMode[]; +[[nodiscard]] bool FastButtonsMode(); + struct HistoryMessageVia : public RuntimeComponent { void create(not_null owner, UserId userId); void resize(int32 availw) const; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 7109b494c..81fe2777f 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -2911,14 +2911,12 @@ void HistoryWidget::refreshSilentToggle() { } void HistoryWidget::setupFastButtonMode() { - if (!session().supportMode()) { - return; - } const auto field = _field->rawTextEdit(); base::install_event_filter(field, [=](not_null e) { if (e->type() != QEvent::KeyPress || !_history - || !session().supportHelper().fastButtonMode(_history->peer) + || !FastButtonsMode() + || !session().fastButtonsBots().enabled(_history->peer) || !_field->getLastText().isEmpty()) { return base::EventFilterResult::Continue; } diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index e8a949450..b313aee0e 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -44,6 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/ui/dialogs_message_view.h" #include "history/history.h" #include "history/history_item.h" +#include "history/history_item_components.h" #include "history/history_item_helpers.h" #include "history/view/history_view_item_preview.h" #include "info/bot/earn/info_bot_earn_widget.h" @@ -2360,7 +2361,7 @@ void ActionsFiller::addDeleteContactAction(not_null user) { void ActionsFiller::addFastButtonsMode(not_null user) { Expects(user->isBot()); - const auto helper = &user->session().supportHelper(); + const auto bots = &user->session().fastButtonsBots(); const auto button = _wrap->add(object_ptr( _wrap, rpl::single(u"Fast buttons mode"_q), @@ -2374,17 +2375,17 @@ void ActionsFiller::addFastButtonsMode(not_null user) { AddDivider(_wrap); AddSkip(_wrap); - button->toggleOn(helper->fastButtonModeValue(user)); + button->toggleOn(bots->enabledValue(user)); button->toggledValue( ) | rpl::filter([=](bool value) { - return value != helper->fastButtonMode(user); + return value != bots->enabled(user); }) | rpl::start_with_next([=](bool value) { - helper->setFastButtonMode(user, value); + bots->setEnabled(user, value); }, button->lifetime()); } void ActionsFiller::addBotCommandActions(not_null user) { - if (user->session().supportMode()) { + if (FastButtonsMode()) { addFastButtonsMode(user); } const auto window = _controller->parentController(); diff --git a/Telegram/SourceFiles/main/main_session.cpp b/Telegram/SourceFiles/main/main_session.cpp index 7f398e0a7..2d846d30a 100644 --- a/Telegram/SourceFiles/main/main_session.cpp +++ b/Telegram/SourceFiles/main/main_session.cpp @@ -119,6 +119,7 @@ Session::Session( , _credits(std::make_unique(this)) , _cachedReactionIconFactory(std::make_unique()) , _supportHelper(Support::Helper::Create(this)) +, _fastButtonsBots(std::make_unique(this)) , _saveSettingsTimer([=] { saveSettings(); }) { Expects(_settings != nullptr); @@ -426,6 +427,10 @@ Support::Templates& Session::supportTemplates() const { return supportHelper().templates(); } +Support::FastButtonsBots &Session::fastButtonsBots() const { + return *_fastButtonsBots; +} + void Session::addWindow(not_null controller) { _windows.emplace(controller); controller->lifetime().add([=] { diff --git a/Telegram/SourceFiles/main/main_session.h b/Telegram/SourceFiles/main/main_session.h index 0a6917f38..677405d28 100644 --- a/Telegram/SourceFiles/main/main_session.h +++ b/Telegram/SourceFiles/main/main_session.h @@ -26,6 +26,7 @@ struct ConfigFields; namespace Support { class Helper; class Templates; +class FastButtonsBots; } // namespace Support namespace Data { @@ -233,6 +234,7 @@ public: [[nodiscard]] bool supportMode() const; [[nodiscard]] Support::Helper &supportHelper() const; [[nodiscard]] Support::Templates &supportTemplates() const; + [[nodiscard]] Support::FastButtonsBots &fastButtonsBots() const; [[nodiscard]] auto colorIndicesValue() -> rpl::producer; @@ -275,6 +277,7 @@ private: const std::unique_ptr _cachedReactionIconFactory; const std::unique_ptr _supportHelper; + const std::unique_ptr _fastButtonsBots; std::shared_ptr _selfUserpicView; rpl::variable _premiumPossible = false; diff --git a/Telegram/SourceFiles/settings/settings_codes.cpp b/Telegram/SourceFiles/settings/settings_codes.cpp index 28f495897..3ac02395a 100644 --- a/Telegram/SourceFiles/settings/settings_codes.cpp +++ b/Telegram/SourceFiles/settings/settings_codes.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwindow.h" #include "data/data_session.h" #include "data/data_cloud_themes.h" +#include "history/history_item_components.h" #include "main/main_session.h" #include "main/main_account.h" #include "main/main_domain.h" @@ -28,9 +29,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_session_controller.h" #include "media/audio/media_audio_track.h" #include "settings/settings_folders.h" +#include "storage/storage_account.h" #include "api/api_updates.h" #include "base/qt/qt_common_adapters.h" #include "base/custom_app_icon.h" +#include "base/options.h" #include "boxes/abstract_box.h" // Ui::show(). #include @@ -165,6 +168,15 @@ auto GenerateCodes() { Core::Application::RegisterUrlScheme(); Ui::Toast::Show("Forced custom scheme register."); }); + codes.emplace(u"numberbuttons"_q, [](SessionController *window) { + using namespace base::options; + auto &option = lookup(kOptionFastButtonsMode); + const auto now = !option.value(); + option.set(now); + Ui::Toast::Show(now + ? u"Fast buttons mode enabled."_q + : u"Fast buttons mode disabled."_q); + }); auto audioFilters = u"Audio files (*.wav *.mp3);;"_q + FileDialog::AllFilesFilter(); auto audioKeys = { diff --git a/Telegram/SourceFiles/settings/settings_experimental.cpp b/Telegram/SourceFiles/settings/settings_experimental.cpp index b1d2a8480..ef67935a6 100644 --- a/Telegram/SourceFiles/settings/settings_experimental.cpp +++ b/Telegram/SourceFiles/settings/settings_experimental.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/launcher.h" #include "chat_helpers/tabbed_panel.h" #include "dialogs/dialogs_widget.h" +#include "history/history_item_components.h" #include "info/profile/info_profile_actions.h" #include "lang/lang_keys.h" #include "mainwindow.h" @@ -158,6 +159,9 @@ void SetupExperimental( addToggle(Data::kOptionExternalVideoPlayer); addToggle(Window::kOptionNewWindowsSizeAsFirst); addToggle(MTP::details::kOptionPreferIPv6); + if (base::options::lookup(kOptionFastButtonsMode).value()) { + addToggle(kOptionFastButtonsMode); + } addToggle(Window::kOptionDisableTouchbar); } diff --git a/Telegram/SourceFiles/support/support_helper.cpp b/Telegram/SourceFiles/support/support_helper.cpp index 87a13da1b..892bda631 100644 --- a/Telegram/SourceFiles/support/support_helper.cpp +++ b/Telegram/SourceFiles/support/support_helper.cpp @@ -483,79 +483,6 @@ UserInfo Helper::infoCurrent(not_null user) const { return (i != end(_userInformation)) ? i->second : UserInfo(); } -void Helper::readFastButtonModeBots() { - _readFastButtonModeBots = true; - - auto f = QFile(FastButtonModeIdsPath(_session)); - if (!f.open(QIODevice::ReadOnly)) { - return; - } - const auto data = f.readAll(); - const auto json = QJsonDocument::fromJson(data); - if (!json.isObject()) { - return; - } - const auto object = json.object(); - const auto array = object.value(u"ids"_q).toArray(); - for (const auto &value : array) { - const auto bareId = value.toString().toULongLong(); - _fastButtonModeBots.emplace(PeerId(bareId)); - } -} - -void Helper::writeFastButtonModeBots() { - auto array = QJsonArray(); - for (const auto &id : _fastButtonModeBots) { - array.append(QString::number(id.value)); - } - auto object = QJsonObject(); - object[u"ids"_q] = array; - auto f = QFile(FastButtonModeIdsPath(_session)); - if (f.open(QIODevice::WriteOnly)) { - f.write(QJsonDocument(object).toJson(QJsonDocument::Indented)); - } -} - -bool Helper::fastButtonMode(not_null peer) const { - if (!_readFastButtonModeBots) { - const_cast(this)->readFastButtonModeBots(); - } - return _fastButtonModeBots.contains(peer->id); -} - -rpl::producer Helper::fastButtonModeValue( - not_null peer) const { - return rpl::single( - fastButtonMode(peer) - ) | rpl::then(_fastButtonModeBotsChanges.events( - ) | rpl::filter([=](PeerId id) { - return (peer->id == id); - }) | rpl::map([=] { - return fastButtonMode(peer); - })); -} - -void Helper::setFastButtonMode(not_null peer, bool fast) { - if (fast == fastButtonMode(peer)) { - return; - } else if (fast) { - _fastButtonModeBots.emplace(peer->id); - } else { - _fastButtonModeBots.remove(peer->id); - } - if (_fastButtonModeBots.empty()) { - QFile(FastButtonModeIdsPath(_session)).remove(); - } else { - writeFastButtonModeBots(); - } - _fastButtonModeBotsChanges.fire_copy(peer->id); - if (const auto history = peer->owner().history(peer)) { - if (const auto item = history->lastMessage()) { - history->owner().requestItemRepaint(item); - } - } -} - void Helper::editInfo( not_null controller, not_null user) { @@ -624,6 +551,83 @@ Templates &Helper::templates() { return _templates; } +FastButtonsBots::FastButtonsBots(not_null session) +: _session(session) { +} + +bool FastButtonsBots::enabled(not_null peer) const { + if (!_read) { + const_cast(this)->read(); + } + return _bots.contains(peer->id); +} + +rpl::producer FastButtonsBots::enabledValue( + not_null peer) const { + return rpl::single( + enabled(peer) + ) | rpl::then(_changes.events( + ) | rpl::filter([=](PeerId id) { + return (peer->id == id); + }) | rpl::map([=] { + return enabled(peer); + })); +} + +void FastButtonsBots::setEnabled(not_null peer, bool value) { + if (value == enabled(peer)) { + return; + } else if (value) { + _bots.emplace(peer->id); + } else { + _bots.remove(peer->id); + } + if (_bots.empty()) { + QFile(FastButtonModeIdsPath(_session)).remove(); + } else { + write(); + } + _changes.fire_copy(peer->id); + if (const auto history = peer->owner().history(peer)) { + if (const auto item = history->lastMessage()) { + history->owner().requestItemRepaint(item); + } + } +} + +void FastButtonsBots::write() { + auto array = QJsonArray(); + for (const auto &id : _bots) { + array.append(QString::number(id.value)); + } + auto object = QJsonObject(); + object[u"ids"_q] = array; + auto f = QFile(FastButtonModeIdsPath(_session)); + if (f.open(QIODevice::WriteOnly)) { + f.write(QJsonDocument(object).toJson(QJsonDocument::Indented)); + } +} + +void FastButtonsBots::read() { + _read = true; + + auto f = QFile(FastButtonModeIdsPath(_session)); + if (!f.open(QIODevice::ReadOnly)) { + return; + } + const auto data = f.readAll(); + const auto json = QJsonDocument::fromJson(data); + if (!json.isObject()) { + return; + } + const auto object = json.object(); + const auto array = object.value(u"ids"_q).toArray(); + for (const auto &value : array) { + const auto bareId = value.toString().toULongLong(); + _bots.emplace(PeerId(bareId)); + } +} + QString ChatOccupiedString(not_null history) { const auto hand = QString::fromUtf8("\xe2\x9c\x8b\xef\xb8\x8f"); const auto name = ParseOccupationName(history); diff --git a/Telegram/SourceFiles/support/support_helper.h b/Telegram/SourceFiles/support/support_helper.h index 55c4f3199..9a0a6b9e3 100644 --- a/Telegram/SourceFiles/support/support_helper.h +++ b/Telegram/SourceFiles/support/support_helper.h @@ -65,11 +65,6 @@ public: not_null controller, not_null user); - [[nodiscard]] bool fastButtonMode(not_null peer) const; - [[nodiscard]] rpl::producer fastButtonModeValue( - not_null peer) const; - void setFastButtonMode(not_null peer, bool fast); - Templates &templates(); private: @@ -97,10 +92,7 @@ private: TextWithEntities text, Fn done); - void writeFastButtonModeBots(); - void readFastButtonModeBots(); - - not_null _session; + const not_null _session; MTP::Sender _api; Templates _templates; QString _supportName; @@ -117,14 +109,31 @@ private: base::weak_ptr> _userInfoEditPending; base::flat_map, SavingInfo> _userInfoSaving; - base::flat_set _fastButtonModeBots; - rpl::event_stream _fastButtonModeBotsChanges; - bool _readFastButtonModeBots = false; - rpl::lifetime _lifetime; }; +class FastButtonsBots final { +public: + explicit FastButtonsBots(not_null session); + + [[nodiscard]] bool enabled(not_null peer) const; + [[nodiscard]] rpl::producer enabledValue( + not_null peer) const; + void setEnabled(not_null peer, bool value); + +private: + void write(); + void read(); + + const not_null _session; + + base::flat_set _bots; + rpl::event_stream _changes; + bool _read = false; + +}; + QString ChatOccupiedString(not_null history); QString InterpretSendPath(