mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Introduce fast-buttons-bots for support mode.
This commit is contained in:
parent
3cebd6d923
commit
da426ae03b
10 changed files with 238 additions and 24 deletions
|
@ -50,6 +50,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "api/api_bot.h"
|
#include "api/api_bot.h"
|
||||||
|
#include "support/support_helper.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
#include "styles/style_dialogs.h" // dialogsMiniReplyStory.
|
#include "styles/style_dialogs.h" // dialogsMiniReplyStory.
|
||||||
|
@ -880,12 +881,17 @@ void ReplyKeyboard::paint(
|
||||||
Assert(_width > 0);
|
Assert(_width > 0);
|
||||||
|
|
||||||
_st->startPaint(p, st);
|
_st->startPaint(p, st);
|
||||||
|
auto number = hasFastButtonMode() ? 1 : 0;
|
||||||
for (auto y = 0, rowsCount = int(_rows.size()); y != rowsCount; ++y) {
|
for (auto y = 0, rowsCount = int(_rows.size()); y != rowsCount; ++y) {
|
||||||
for (auto x = 0, count = int(_rows[y].size()); x != count; ++x) {
|
for (auto x = 0, count = int(_rows[y].size()); x != count; ++x) {
|
||||||
|
const auto guard = gsl::finally([&] { if (number) ++number; });
|
||||||
const auto &button = _rows[y][x];
|
const auto &button = _rows[y][x];
|
||||||
const auto rect = button.rect;
|
const auto rect = button.rect;
|
||||||
if (rect.y() >= clip.y() + clip.height()) return;
|
if (rect.y() >= clip.y() + clip.height()) {
|
||||||
if (rect.y() + rect.height() < clip.y()) continue;
|
return;
|
||||||
|
} else if (rect.y() + rect.height() < clip.y()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// just ignore the buttons that didn't layout well
|
// just ignore the buttons that didn't layout well
|
||||||
if (rect.x() + rect.width() > _width) break;
|
if (rect.x() + rect.width() > _width) break;
|
||||||
|
@ -904,10 +910,27 @@ void ReplyKeyboard::paint(
|
||||||
? Corner::Large
|
? Corner::Large
|
||||||
: Corner::Small;
|
: Corner::Small;
|
||||||
_st->paintButton(p, st, outerWidth, button, buttonRounding);
|
_st->paintButton(p, st, outerWidth, button, buttonRounding);
|
||||||
|
|
||||||
|
if (number) {
|
||||||
|
p.setFont(st::dialogsUnreadFont);
|
||||||
|
p.setPen(st->msgServiceFg());
|
||||||
|
p.drawText(
|
||||||
|
rect.x() + st::msgBotKbIconPadding,
|
||||||
|
rect.y() + st::dialogsUnreadFont->ascent,
|
||||||
|
QString::number(number));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ReplyKeyboard::hasFastButtonMode() const {
|
||||||
|
return _item->inlineReplyKeyboard()
|
||||||
|
&& (_item == _item->history()->lastMessage())
|
||||||
|
&& _item->history()->session().supportMode()
|
||||||
|
&& _item->history()->session().supportHelper().fastButtonMode(
|
||||||
|
_item->history()->peer);
|
||||||
|
}
|
||||||
|
|
||||||
ClickHandlerPtr ReplyKeyboard::getLink(QPoint point) const {
|
ClickHandlerPtr ReplyKeyboard::getLink(QPoint point) const {
|
||||||
Assert(_width > 0);
|
Assert(_width > 0);
|
||||||
|
|
||||||
|
@ -927,6 +950,19 @@ ClickHandlerPtr ReplyKeyboard::getLink(QPoint point) const {
|
||||||
return ClickHandlerPtr();
|
return ClickHandlerPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClickHandlerPtr ReplyKeyboard::getLinkByIndex(int index) const {
|
||||||
|
auto number = 1;
|
||||||
|
for (const auto &row : _rows) {
|
||||||
|
for (const auto &button : row) {
|
||||||
|
if (number == index + 1) {
|
||||||
|
return button.link;
|
||||||
|
}
|
||||||
|
++number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ClickHandlerPtr();
|
||||||
|
}
|
||||||
|
|
||||||
void ReplyKeyboard::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
void ReplyKeyboard::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
||||||
if (!p) return;
|
if (!p) return;
|
||||||
|
|
||||||
|
|
|
@ -504,6 +504,7 @@ public:
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
const QRect &clip) const;
|
const QRect &clip) const;
|
||||||
ClickHandlerPtr getLink(QPoint point) const;
|
ClickHandlerPtr getLink(QPoint point) const;
|
||||||
|
ClickHandlerPtr getLinkByIndex(int index) const;
|
||||||
|
|
||||||
void clickHandlerActiveChanged(
|
void clickHandlerActiveChanged(
|
||||||
const ClickHandlerPtr &p,
|
const ClickHandlerPtr &p,
|
||||||
|
@ -537,6 +538,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
void startAnimation(int i, int j, int direction);
|
void startAnimation(int i, int j, int direction);
|
||||||
|
[[nodiscard]] bool hasFastButtonMode() const;
|
||||||
|
|
||||||
ButtonCoords findButtonCoordsByClickHandler(const ClickHandlerPtr &p);
|
ButtonCoords findButtonCoordsByClickHandler(const ClickHandlerPtr &p);
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "core/ui_integration.h"
|
#include "core/ui_integration.h"
|
||||||
#include "support/support_common.h"
|
#include "support/support_common.h"
|
||||||
#include "support/support_autocomplete.h"
|
#include "support/support_autocomplete.h"
|
||||||
|
#include "support/support_helper.h"
|
||||||
#include "support/support_preload.h"
|
#include "support/support_preload.h"
|
||||||
#include "dialogs/dialogs_key.h"
|
#include "dialogs/dialogs_key.h"
|
||||||
#include "calls/calls_instance.h"
|
#include "calls/calls_instance.h"
|
||||||
|
@ -467,6 +468,8 @@ HistoryWidget::HistoryWidget(
|
||||||
});
|
});
|
||||||
InitMessageFieldFade(_field, st::historyComposeField.textBg);
|
InitMessageFieldFade(_field, st::historyComposeField.textBg);
|
||||||
|
|
||||||
|
setupFastButtonMode();
|
||||||
|
|
||||||
_fieldCharsCountManager.limitExceeds(
|
_fieldCharsCountManager.limitExceeds(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
const auto hide = _fieldCharsCountManager.isLimitExceeded();
|
const auto hide = _fieldCharsCountManager.isLimitExceeded();
|
||||||
|
@ -2888,6 +2891,43 @@ void HistoryWidget::refreshSilentToggle() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryWidget::setupFastButtonMode() {
|
||||||
|
if (!session().supportMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto field = _field->rawTextEdit();
|
||||||
|
base::install_event_filter(field, [=](not_null<QEvent*> e) {
|
||||||
|
if (e->type() != QEvent::KeyPress
|
||||||
|
|| !_history
|
||||||
|
|| !session().supportHelper().fastButtonMode(_history->peer)
|
||||||
|
|| !_field->getLastText().isEmpty()) {
|
||||||
|
return base::EventFilterResult::Continue;
|
||||||
|
}
|
||||||
|
const auto k = static_cast<QKeyEvent*>(e.get());
|
||||||
|
const auto key = k->key();
|
||||||
|
if (key < Qt::Key_1 || key > Qt::Key_9 || k->modifiers()) {
|
||||||
|
return base::EventFilterResult::Continue;
|
||||||
|
}
|
||||||
|
const auto item = _history ? _history->lastMessage() : nullptr;
|
||||||
|
const auto markup = item ? item->inlineReplyKeyboard() : nullptr;
|
||||||
|
const auto link = markup
|
||||||
|
? markup->getLinkByIndex(key - Qt::Key_1)
|
||||||
|
: nullptr;
|
||||||
|
if (!link) {
|
||||||
|
return base::EventFilterResult::Continue;
|
||||||
|
}
|
||||||
|
const auto id = item->fullId();
|
||||||
|
ActivateClickHandler(window(), link, {
|
||||||
|
Qt::LeftButton,
|
||||||
|
QVariant::fromValue(ClickHandlerContext{
|
||||||
|
.itemId = item->fullId(),
|
||||||
|
.sessionWindow = base::make_weak(controller()),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
return base::EventFilterResult::Cancel;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryWidget::setupScheduledToggle() {
|
void HistoryWidget::setupScheduledToggle() {
|
||||||
controller()->activeChatValue(
|
controller()->activeChatValue(
|
||||||
) | rpl::map([=](Dialogs::Key key) -> rpl::producer<> {
|
) | rpl::map([=](Dialogs::Key key) -> rpl::producer<> {
|
||||||
|
|
|
@ -653,6 +653,7 @@ private:
|
||||||
[[nodiscard]] bool showRecordButton() const;
|
[[nodiscard]] bool showRecordButton() const;
|
||||||
[[nodiscard]] bool showInlineBotCancel() const;
|
[[nodiscard]] bool showInlineBotCancel() const;
|
||||||
void refreshSilentToggle();
|
void refreshSilentToggle();
|
||||||
|
void setupFastButtonMode();
|
||||||
|
|
||||||
[[nodiscard]] bool isChoosingTheme() const;
|
[[nodiscard]] bool isChoosingTheme() const;
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ const auto kPsaTooltipPrefix = "cloud_lng_tooltip_psa_";
|
||||||
|
|
||||||
class KeyboardStyle : public ReplyKeyboard::Style {
|
class KeyboardStyle : public ReplyKeyboard::Style {
|
||||||
public:
|
public:
|
||||||
KeyboardStyle(const style::BotKeyboardButton &st);
|
KeyboardStyle(const style::BotKeyboardButton &st, Fn<void()> repaint);
|
||||||
|
|
||||||
Images::CornersMaskRef buttonRounding(
|
Images::CornersMaskRef buttonRounding(
|
||||||
Ui::BubbleRounding outer,
|
Ui::BubbleRounding outer,
|
||||||
|
@ -93,12 +93,16 @@ private:
|
||||||
mutable base::flat_map<BubbleRoundingKey, QImage> _cachedBg;
|
mutable base::flat_map<BubbleRoundingKey, QImage> _cachedBg;
|
||||||
mutable base::flat_map<BubbleRoundingKey, QPainterPath> _cachedOutline;
|
mutable base::flat_map<BubbleRoundingKey, QPainterPath> _cachedOutline;
|
||||||
mutable std::unique_ptr<Ui::GlareEffect> _glare;
|
mutable std::unique_ptr<Ui::GlareEffect> _glare;
|
||||||
|
Fn<void()> _repaint;
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
KeyboardStyle::KeyboardStyle(const style::BotKeyboardButton &st)
|
KeyboardStyle::KeyboardStyle(
|
||||||
: ReplyKeyboard::Style(st) {
|
const style::BotKeyboardButton &st,
|
||||||
|
Fn<void()> repaint)
|
||||||
|
: ReplyKeyboard::Style(st)
|
||||||
|
, _repaint(std::move(repaint)) {
|
||||||
style::PaletteChanged(
|
style::PaletteChanged(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
_cachedBg = {};
|
_cachedBg = {};
|
||||||
|
@ -120,15 +124,6 @@ const style::TextStyle &KeyboardStyle::textStyle() const {
|
||||||
|
|
||||||
void KeyboardStyle::repaint(not_null<const HistoryItem*> item) const {
|
void KeyboardStyle::repaint(not_null<const HistoryItem*> item) const {
|
||||||
item->history()->owner().requestItemRepaint(item);
|
item->history()->owner().requestItemRepaint(item);
|
||||||
if (_glare && !_glare->glare.birthTime) {
|
|
||||||
constexpr auto kTimeout = crl::time(0);
|
|
||||||
constexpr auto kDuration = crl::time(1100);
|
|
||||||
_glare->validate(
|
|
||||||
st::premiumButtonFg->c,
|
|
||||||
[=] { repaint(item); },
|
|
||||||
kTimeout,
|
|
||||||
kDuration);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Images::CornersMaskRef KeyboardStyle::buttonRounding(
|
Images::CornersMaskRef KeyboardStyle::buttonRounding(
|
||||||
|
@ -306,6 +301,11 @@ void KeyboardStyle::paintButtonLoading(
|
||||||
} else {
|
} else {
|
||||||
_glare = std::make_unique<Ui::GlareEffect>();
|
_glare = std::make_unique<Ui::GlareEffect>();
|
||||||
_glare->width = outerWidth;
|
_glare->width = outerWidth;
|
||||||
|
|
||||||
|
constexpr auto kTimeout = crl::time(0);
|
||||||
|
constexpr auto kDuration = crl::time(1100);
|
||||||
|
const auto color = st::premiumButtonFg->c;
|
||||||
|
_glare->validate(color, _repaint, kTimeout, kDuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3400,9 +3400,12 @@ void Message::validateInlineKeyboard(HistoryMessageReplyMarkup *markup) {
|
||||||
|| markup->hiddenBy(data()->media())) {
|
|| markup->hiddenBy(data()->media())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const auto item = data();
|
||||||
markup->inlineKeyboard = std::make_unique<ReplyKeyboard>(
|
markup->inlineKeyboard = std::make_unique<ReplyKeyboard>(
|
||||||
data(),
|
item,
|
||||||
std::make_unique<KeyboardStyle>(st::msgBotKbButton));
|
std::make_unique<KeyboardStyle>(
|
||||||
|
st::msgBotKbButton,
|
||||||
|
[=] { item->history()->owner().requestItemRepaint(item); }));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Message::validateFromNameText(PeerData *from) const {
|
void Message::validateFromNameText(PeerData *from) const {
|
||||||
|
|
|
@ -740,8 +740,7 @@ auto AddActionButton(
|
||||||
ToggleOn &&toggleOn,
|
ToggleOn &&toggleOn,
|
||||||
Callback &&callback,
|
Callback &&callback,
|
||||||
const style::icon *icon,
|
const style::icon *icon,
|
||||||
const style::SettingsButton &st
|
const style::SettingsButton &st = st::infoSharedMediaButton) {
|
||||||
= st::infoSharedMediaButton) {
|
|
||||||
auto result = parent->add(object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
|
auto result = parent->add(object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
|
||||||
parent,
|
parent,
|
||||||
object_ptr<Ui::SettingsButton>(
|
object_ptr<Ui::SettingsButton>(
|
||||||
|
@ -1018,6 +1017,7 @@ private:
|
||||||
void addEditContactAction(not_null<UserData*> user);
|
void addEditContactAction(not_null<UserData*> user);
|
||||||
void addDeleteContactAction(not_null<UserData*> user);
|
void addDeleteContactAction(not_null<UserData*> user);
|
||||||
void addBotCommandActions(not_null<UserData*> user);
|
void addBotCommandActions(not_null<UserData*> user);
|
||||||
|
void addFastButtonsMode(not_null<UserData*> user);
|
||||||
void addReportAction();
|
void addReportAction();
|
||||||
void addBlockAction(not_null<UserData*> user);
|
void addBlockAction(not_null<UserData*> user);
|
||||||
void addLeaveChannelAction(not_null<ChannelData*> channel);
|
void addLeaveChannelAction(not_null<ChannelData*> channel);
|
||||||
|
@ -2320,7 +2320,36 @@ void ActionsFiller::addDeleteContactAction(not_null<UserData*> user) {
|
||||||
&st::infoIconDelete);
|
&st::infoIconDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ActionsFiller::addFastButtonsMode(not_null<UserData*> user) {
|
||||||
|
Expects(user->isBot());
|
||||||
|
|
||||||
|
const auto helper = &user->session().supportHelper();
|
||||||
|
const auto button = _wrap->add(object_ptr<Ui::SettingsButton>(
|
||||||
|
_wrap,
|
||||||
|
rpl::single(u"Fast buttons mode"_q),
|
||||||
|
st::infoSharedMediaButton));
|
||||||
|
object_ptr<Info::Profile::FloatingIcon>(
|
||||||
|
button,
|
||||||
|
st::infoIconMediaBot,
|
||||||
|
st::infoSharedMediaButtonIconPosition);
|
||||||
|
|
||||||
|
AddSkip(_wrap);
|
||||||
|
AddDivider(_wrap);
|
||||||
|
AddSkip(_wrap);
|
||||||
|
|
||||||
|
button->toggleOn(helper->fastButtonModeValue(user));
|
||||||
|
button->toggledValue(
|
||||||
|
) | rpl::filter([=](bool value) {
|
||||||
|
return value != helper->fastButtonMode(user);
|
||||||
|
}) | rpl::start_with_next([=](bool value) {
|
||||||
|
helper->setFastButtonMode(user, value);
|
||||||
|
}, button->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
void ActionsFiller::addBotCommandActions(not_null<UserData*> user) {
|
void ActionsFiller::addBotCommandActions(not_null<UserData*> user) {
|
||||||
|
if (user->session().supportMode()) {
|
||||||
|
addFastButtonsMode(user);
|
||||||
|
}
|
||||||
const auto window = _controller->parentController();
|
const auto window = _controller->parentController();
|
||||||
const auto findBotCommand = [user](const QString &command) {
|
const auto findBotCommand = [user](const QString &command) {
|
||||||
if (!user->isBot()) {
|
if (!user->isBot()) {
|
||||||
|
|
|
@ -162,6 +162,10 @@ QString Account::tempDirectory() const {
|
||||||
return _tempPath;
|
return _tempPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Account::supportModePath() const {
|
||||||
|
return _databasePath + u"support"_q;
|
||||||
|
}
|
||||||
|
|
||||||
StartResult Account::legacyStart(const QByteArray &passcode) {
|
StartResult Account::legacyStart(const QByteArray &passcode) {
|
||||||
const auto result = readMapWith(MTP::AuthKeyPtr(), passcode);
|
const auto result = readMapWith(MTP::AuthKeyPtr(), passcode);
|
||||||
if (result == ReadMapResult::Failed) {
|
if (result == ReadMapResult::Failed) {
|
||||||
|
|
|
@ -76,6 +76,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] QString tempDirectory() const;
|
[[nodiscard]] QString tempDirectory() const;
|
||||||
|
[[nodiscard]] QString supportModePath() const;
|
||||||
|
|
||||||
[[nodiscard]] MTP::AuthKeyPtr peekLegacyLocalKey() const {
|
[[nodiscard]] MTP::AuthKeyPtr peekLegacyLocalKey() const {
|
||||||
return _localKey;
|
return _localKey;
|
||||||
|
|
|
@ -28,16 +28,21 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
|
#include "storage/storage_account.h"
|
||||||
#include "storage/storage_media_prepare.h"
|
#include "storage/storage_media_prepare.h"
|
||||||
#include "storage/localimageloader.h"
|
#include "storage/localimageloader.h"
|
||||||
#include "core/launcher.h"
|
#include "core/launcher.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "core/core_settings.h"
|
#include "core/core_settings.h"
|
||||||
|
#include "main/main_account.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
|
|
||||||
|
#include <QtCore/QJsonDocument>
|
||||||
|
#include <QtCore/QJsonArray>
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
class Session;
|
class Session;
|
||||||
} // namespace Main
|
} // namespace Main
|
||||||
|
@ -256,6 +261,12 @@ TimeId OccupiedBySomeoneTill(History *history) {
|
||||||
return valid ? result : 0;
|
return valid ? result : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString FastButtonModeIdsPath(not_null<Main::Session*> session) {
|
||||||
|
const auto base = session->account().local().supportModePath();
|
||||||
|
QDir().mkpath(base);
|
||||||
|
return base + u"/fast_button_mode_ids.json"_q;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Helper::Helper(not_null<Main::Session*> session)
|
Helper::Helper(not_null<Main::Session*> session)
|
||||||
|
@ -472,6 +483,79 @@ UserInfo Helper::infoCurrent(not_null<UserData*> user) const {
|
||||||
return (i != end(_userInformation)) ? i->second : UserInfo();
|
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<PeerData*> peer) const {
|
||||||
|
if (!_readFastButtonModeBots) {
|
||||||
|
const_cast<Helper*>(this)->readFastButtonModeBots();
|
||||||
|
}
|
||||||
|
return _fastButtonModeBots.contains(peer->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<bool> Helper::fastButtonModeValue(
|
||||||
|
not_null<PeerData*> 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<PeerData*> 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(
|
void Helper::editInfo(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<UserData*> user) {
|
not_null<UserData*> user) {
|
||||||
|
|
|
@ -50,19 +50,26 @@ public:
|
||||||
|
|
||||||
void chatOccupiedUpdated(not_null<History*> history);
|
void chatOccupiedUpdated(not_null<History*> history);
|
||||||
|
|
||||||
bool isOccupiedByMe(History *history) const;
|
[[nodiscard]] bool isOccupiedByMe(History *history) const;
|
||||||
bool isOccupiedBySomeone(History *history) const;
|
[[nodiscard]] bool isOccupiedBySomeone(History *history) const;
|
||||||
|
|
||||||
void refreshInfo(not_null<UserData*> user);
|
void refreshInfo(not_null<UserData*> user);
|
||||||
rpl::producer<UserInfo> infoValue(not_null<UserData*> user) const;
|
[[nodiscard]] rpl::producer<UserInfo> infoValue(
|
||||||
rpl::producer<QString> infoLabelValue(not_null<UserData*> user) const;
|
|
||||||
rpl::producer<TextWithEntities> infoTextValue(
|
|
||||||
not_null<UserData*> user) const;
|
not_null<UserData*> user) const;
|
||||||
UserInfo infoCurrent(not_null<UserData*> user) const;
|
[[nodiscard]] rpl::producer<QString> infoLabelValue(
|
||||||
|
not_null<UserData*> user) const;
|
||||||
|
[[nodiscard]] rpl::producer<TextWithEntities> infoTextValue(
|
||||||
|
not_null<UserData*> user) const;
|
||||||
|
[[nodiscard]] UserInfo infoCurrent(not_null<UserData*> user) const;
|
||||||
void editInfo(
|
void editInfo(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<UserData*> user);
|
not_null<UserData*> user);
|
||||||
|
|
||||||
|
[[nodiscard]] bool fastButtonMode(not_null<PeerData*> peer) const;
|
||||||
|
[[nodiscard]] rpl::producer<bool> fastButtonModeValue(
|
||||||
|
not_null<PeerData*> peer) const;
|
||||||
|
void setFastButtonMode(not_null<PeerData*> peer, bool fast);
|
||||||
|
|
||||||
Templates &templates();
|
Templates &templates();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -90,6 +97,9 @@ private:
|
||||||
TextWithEntities text,
|
TextWithEntities text,
|
||||||
Fn<void(bool success)> done);
|
Fn<void(bool success)> done);
|
||||||
|
|
||||||
|
void writeFastButtonModeBots();
|
||||||
|
void readFastButtonModeBots();
|
||||||
|
|
||||||
not_null<Main::Session*> _session;
|
not_null<Main::Session*> _session;
|
||||||
MTP::Sender _api;
|
MTP::Sender _api;
|
||||||
Templates _templates;
|
Templates _templates;
|
||||||
|
@ -107,6 +117,10 @@ private:
|
||||||
base::weak_ptr<Window::SessionController>> _userInfoEditPending;
|
base::weak_ptr<Window::SessionController>> _userInfoEditPending;
|
||||||
base::flat_map<not_null<UserData*>, SavingInfo> _userInfoSaving;
|
base::flat_map<not_null<UserData*>, SavingInfo> _userInfoSaving;
|
||||||
|
|
||||||
|
base::flat_set<PeerId> _fastButtonModeBots;
|
||||||
|
rpl::event_stream<PeerId> _fastButtonModeBotsChanges;
|
||||||
|
bool _readFastButtonModeBots = false;
|
||||||
|
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue