Added ability to fill send context menu in ComposeControls.

This commit is contained in:
23rd 2020-11-16 19:01:37 +03:00 committed by John Preston
parent 79cc4da626
commit ab38ddc21d
5 changed files with 92 additions and 27 deletions

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unixtime.h" #include "base/unixtime.h"
#include "chat_helpers/emoji_suggestions_widget.h" #include "chat_helpers/emoji_suggestions_widget.h"
#include "chat_helpers/message_field.h" #include "chat_helpers/message_field.h"
#include "chat_helpers/send_context_menu.h"
#include "chat_helpers/tabbed_panel.h" #include "chat_helpers/tabbed_panel.h"
#include "chat_helpers/tabbed_section.h" #include "chat_helpers/tabbed_section.h"
#include "chat_helpers/tabbed_selector.h" #include "chat_helpers/tabbed_selector.h"
@ -34,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "history/view/controls/history_view_voice_record_bar.h" #include "history/view/controls/history_view_voice_record_bar.h"
#include "history/view/history_view_schedule_box.h" // HistoryView::PrepareScheduleBox
#include "history/view/history_view_webpage_preview.h" #include "history/view/history_view_webpage_preview.h"
#include "inline_bots/inline_results_widget.h" #include "inline_bots/inline_results_widget.h"
#include "inline_bots/inline_bot_result.h" #include "inline_bots/inline_bot_result.h"
@ -575,7 +577,8 @@ MessageToEdit FieldHeader::queryToEdit() {
ComposeControls::ComposeControls( ComposeControls::ComposeControls(
not_null<Ui::RpWidget*> parent, not_null<Ui::RpWidget*> parent,
not_null<Window::SessionController*> window, not_null<Window::SessionController*> window,
Mode mode) Mode mode,
SendMenu::Type sendMenuType)
: _parent(parent) : _parent(parent)
, _window(window) , _window(window)
, _mode(mode) , _mode(mode)
@ -609,6 +612,7 @@ ComposeControls::ComposeControls(
window, window,
_send, _send,
st::historySendSize.height())) st::historySendSize.height()))
, _sendMenuType(sendMenuType)
, _saveDraftTimer([=] { saveDraft(); }) { , _saveDraftTimer([=] { saveDraft(); }) {
init(); init();
} }
@ -717,19 +721,21 @@ rpl::producer<not_null<QKeyEvent*>> ComposeControls::keyEvents() const {
}); });
} }
rpl::producer<> ComposeControls::sendRequests() const { rpl::producer<Api::SendOptions> ComposeControls::sendRequests() const {
auto filter = rpl::filter([=] { auto filter = rpl::filter([=] {
const auto type = (_mode == Mode::Normal) const auto type = (_mode == Mode::Normal)
? Ui::SendButton::Type::Send ? Ui::SendButton::Type::Send
: Ui::SendButton::Type::Schedule; : Ui::SendButton::Type::Schedule;
return (_send->type() == type); return (_send->type() == type);
}); });
auto map = rpl::map_to(Api::SendOptions());
auto submits = base::qt_signal_producer( auto submits = base::qt_signal_producer(
_field.get(), _field.get(),
&Ui::InputField::submitted); &Ui::InputField::submitted);
return rpl::merge( return rpl::merge(
_send->clicks() | filter | rpl::to_empty, _send->clicks() | filter | map,
std::move(submits) | filter | rpl::to_empty); std::move(submits) | filter | map,
_sendCustomRequests.events());
} }
rpl::producer<VoiceToSend> ComposeControls::sendVoiceRequests() const { rpl::producer<VoiceToSend> ComposeControls::sendVoiceRequests() const {
@ -1395,6 +1401,12 @@ void ComposeControls::initSendButton() {
}) | rpl::start_with_next([=] { }) | rpl::start_with_next([=] {
cancelInlineBot(); cancelInlineBot();
}, _send->lifetime()); }, _send->lifetime());
SendMenu::SetupMenuAndShortcuts(
_send.get(),
[=] { return sendButtonMenuType(); },
[=] { sendSilent(); },
[=] { sendScheduled(); });
} }
void ComposeControls::inlineBotResolveDone( void ComposeControls::inlineBotResolveDone(
@ -1550,18 +1562,32 @@ void ComposeControls::updateWrappingVisibility() {
} }
} }
auto ComposeControls::computeSendButtonType() const {
using Type = Ui::SendButton::Type;
if (_header->isEditingMessage()) {
return Type::Save;
} else if (_isInlineBot) {
return Type::Cancel;
} else if (showRecordButton()) {
return Type::Record;
}
return (_mode == Mode::Normal) ? Type::Send : Type::Schedule;
}
SendMenu::Type ComposeControls::sendMenuType() const {
return !_history ? SendMenu::Type::Disabled : _sendMenuType;
}
SendMenu::Type ComposeControls::sendButtonMenuType() const {
return (computeSendButtonType() == Ui::SendButton::Type::Send)
? sendMenuType()
: SendMenu::Type::Disabled;
}
void ComposeControls::updateSendButtonType() { void ComposeControls::updateSendButtonType() {
using Type = Ui::SendButton::Type; using Type = Ui::SendButton::Type;
const auto type = [&] { const auto type = computeSendButtonType();
if (_header->isEditingMessage()) {
return Type::Save;
} else if (_isInlineBot) {
return Type::Cancel;
} else if (showRecordButton()) {
return Type::Record;
}
return (_mode == Mode::Normal) ? Type::Send : Type::Schedule;
}();
_send->setType(type); _send->setType(type);
const auto delay = [&] { const auto delay = [&] {
@ -2076,6 +2102,22 @@ bool ComposeControls::isRecording() const {
return _voiceRecordBar->isRecording(); return _voiceRecordBar->isRecording();
} }
void ComposeControls::sendSilent() {
_sendCustomRequests.fire({ .silent = true });
}
void ComposeControls::sendScheduled() {
auto callback = [=](Api::SendOptions options) {
_sendCustomRequests.fire(std::move(options));
};
Ui::show(
HistoryView::PrepareScheduleBox(
_wrap.get(),
sendMenuType(),
std::move(callback)),
Ui::LayerOption::KeepOther);
}
void ComposeControls::updateInlineBotQuery() { void ComposeControls::updateInlineBotQuery() {
if (!_history) { if (!_history) {
return; return;

View file

@ -21,6 +21,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class History; class History;
class FieldAutocomplete; class FieldAutocomplete;
namespace SendMenu {
enum class Type;
} // namespace SendMenu
namespace ChatHelpers { namespace ChatHelpers {
class TabbedPanel; class TabbedPanel;
class TabbedSelector; class TabbedSelector;
@ -87,7 +91,8 @@ public:
ComposeControls( ComposeControls(
not_null<Ui::RpWidget*> parent, not_null<Ui::RpWidget*> parent,
not_null<Window::SessionController*> window, not_null<Window::SessionController*> window,
Mode mode); Mode mode,
SendMenu::Type sendMenuType);
~ComposeControls(); ~ComposeControls();
[[nodiscard]] Main::Session &session() const; [[nodiscard]] Main::Session &session() const;
@ -104,7 +109,7 @@ public:
bool focus(); bool focus();
[[nodiscard]] rpl::producer<> cancelRequests() const; [[nodiscard]] rpl::producer<> cancelRequests() const;
[[nodiscard]] rpl::producer<> sendRequests() const; [[nodiscard]] rpl::producer<Api::SendOptions> sendRequests() const;
[[nodiscard]] rpl::producer<VoiceToSend> sendVoiceRequests() const; [[nodiscard]] rpl::producer<VoiceToSend> sendVoiceRequests() const;
[[nodiscard]] rpl::producer<QString> sendCommandRequests() const; [[nodiscard]] rpl::producer<QString> sendCommandRequests() const;
[[nodiscard]] rpl::producer<MessageToEdit> editRequests() const; [[nodiscard]] rpl::producer<MessageToEdit> editRequests() const;
@ -184,6 +189,13 @@ private:
void updateOuterGeometry(QRect rect); void updateOuterGeometry(QRect rect);
void paintBackground(QRect clip); void paintBackground(QRect clip);
[[nodiscard]] auto computeSendButtonType() const;
[[nodiscard]] SendMenu::Type sendMenuType() const;
[[nodiscard]] SendMenu::Type sendButtonMenuType() const;
void sendSilent();
void sendScheduled();
void orderControls(); void orderControls();
void checkAutocomplete(); void checkAutocomplete();
void updateStickersByEmoji(); void updateStickersByEmoji();
@ -258,6 +270,9 @@ private:
const std::unique_ptr<FieldHeader> _header; const std::unique_ptr<FieldHeader> _header;
const std::unique_ptr<Controls::VoiceRecordBar> _voiceRecordBar; const std::unique_ptr<Controls::VoiceRecordBar> _voiceRecordBar;
const SendMenu::Type _sendMenuType;
rpl::event_stream<Api::SendOptions> _sendCustomRequests;
rpl::event_stream<> _cancelRequests; rpl::event_stream<> _cancelRequests;
rpl::event_stream<FileChosen> _fileChosen; rpl::event_stream<FileChosen> _fileChosen;
rpl::event_stream<PhotoChosen> _photoChosen; rpl::event_stream<PhotoChosen> _photoChosen;

View file

@ -158,7 +158,8 @@ RepliesWidget::RepliesWidget(
, _composeControls(std::make_unique<ComposeControls>( , _composeControls(std::make_unique<ComposeControls>(
this, this,
controller, controller,
ComposeControls::Mode::Normal)) ComposeControls::Mode::Normal,
SendMenu::Type::SilentOnly))
, _scroll(std::make_unique<Ui::ScrollArea>(this, st::historyScroll, false)) , _scroll(std::make_unique<Ui::ScrollArea>(this, st::historyScroll, false))
, _scrollDown(_scroll.get(), st::historyToDown) , _scrollDown(_scroll.get(), st::historyToDown)
, _readRequestTimer([=] { sendReadTillRequest(); }) { , _readRequestTimer([=] { sendReadTillRequest(); }) {
@ -429,13 +430,13 @@ void RepliesWidget::setupComposeControls() {
}, lifetime()); }, lifetime());
_composeControls->sendRequests( _composeControls->sendRequests(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=](Api::SendOptions options) {
send(); send(options);
}, lifetime()); }, lifetime());
_composeControls->sendVoiceRequests( _composeControls->sendVoiceRequests(
) | rpl::start_with_next([=](ComposeControls::VoiceToSend &&data) { ) | rpl::start_with_next([=](ComposeControls::VoiceToSend &&data) {
sendVoice(data.bytes, data.waveform, data.duration); sendVoice(std::move(data));
}, lifetime()); }, lifetime());
_composeControls->sendCommandRequests( _composeControls->sendCommandRequests(
@ -878,13 +879,15 @@ void RepliesWidget::send() {
// Ui::LayerOption::KeepOther); // Ui::LayerOption::KeepOther);
} }
void RepliesWidget::sendVoice( void RepliesWidget::sendVoice(ComposeControls::VoiceToSend &&data) {
QByteArray bytes,
VoiceWaveform waveform,
int duration) {
auto action = Api::SendAction(_history); auto action = Api::SendAction(_history);
action.replyTo = replyToId(); action.replyTo = replyToId();
session().api().sendVoiceMessage(bytes, waveform, duration, action); action.options = data.options;
session().api().sendVoiceMessage(
data.bytes,
data.waveform,
data.duration,
std::move(action));
} }
void RepliesWidget::send(Api::SendOptions options) { void RepliesWidget::send(Api::SendOptions options) {

View file

@ -52,6 +52,10 @@ class RepliesList;
namespace HistoryView { namespace HistoryView {
namespace Controls {
struct VoiceToSend;
} // namespace Controls
class Element; class Element;
class TopBarWidget; class TopBarWidget;
class RepliesMemento; class RepliesMemento;
@ -180,7 +184,7 @@ private:
void send(); void send();
void send(Api::SendOptions options); void send(Api::SendOptions options);
void sendVoice(QByteArray bytes, VoiceWaveform waveform, int duration); void sendVoice(Controls::VoiceToSend &&data);
void edit( void edit(
not_null<HistoryItem*> item, not_null<HistoryItem*> item,
Api::SendOptions options, Api::SendOptions options,

View file

@ -97,7 +97,8 @@ ScheduledWidget::ScheduledWidget(
, _composeControls(std::make_unique<ComposeControls>( , _composeControls(std::make_unique<ComposeControls>(
this, this,
controller, controller,
ComposeControls::Mode::Scheduled)) ComposeControls::Mode::Scheduled,
SendMenu::Type::Disabled))
, _scrollDown(_scroll, st::historyToDown) { , _scrollDown(_scroll, st::historyToDown) {
const auto state = Dialogs::EntryState{ const auto state = Dialogs::EntryState{
.key = _history, .key = _history,