Send from scheduled messages section.

This commit is contained in:
John Preston 2019-08-16 18:08:51 +03:00
parent 3e895d0e85
commit 77ebdd3576
13 changed files with 224 additions and 8 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -543,10 +543,11 @@ void DeleteMessagesBox::prepare() {
: tr::lng_selected_delete_sure(tr::now, lt_count, _ids.size());
if (const auto peer = checkFromSinglePeer()) {
auto count = int(_ids.size());
if (auto revoke = revokeText(peer)) {
if (hasScheduledMessages()) {
} else if (auto revoke = revokeText(peer)) {
_revoke.create(this, revoke->checkbox, false, st::defaultBoxCheckbox);
appendDetails(std::move(revoke->description));
} else if (peer && peer->isChannel()) {
} else if (peer->isChannel()) {
if (peer->isMegagroup()) {
appendDetails({ tr::lng_delete_for_everyone_hint(tr::now, lt_count, count) });
}
@ -581,6 +582,17 @@ void DeleteMessagesBox::prepare() {
setDimensions(st::boxWidth, fullHeight);
}
bool DeleteMessagesBox::hasScheduledMessages() const {
for (const auto fullId : std::as_const(_ids)) {
if (const auto item = _session->data().message(fullId)) {
if (item->isScheduled()) {
return true;
}
}
}
return false;
}
PeerData *DeleteMessagesBox::checkFromSinglePeer() const {
auto result = (PeerData*)nullptr;
for (const auto fullId : std::as_const(_ids)) {

View File

@ -176,8 +176,10 @@ private:
TextWithEntities description;
};
void deleteAndClear();
PeerData *checkFromSinglePeer() const;
std::optional<RevokeConfig> revokeText(not_null<PeerData*> peer) const;
[[nodiscard]] PeerData *checkFromSinglePeer() const;
[[nodiscard]] bool hasScheduledMessages() const;
[[nodiscard]] std::optional<RevokeConfig> revokeText(
not_null<PeerData*> peer) const;
const not_null<Main::Session*> _session;

View File

@ -220,6 +220,8 @@ historySendIcon: icon {{ "send_control_send", historySendIconFg }};
historySendIconOver: icon {{ "send_control_send", historySendIconFgOver }};
historySendIconPosition: point(11px, 11px);
historySendSize: size(46px, 46px);
historyScheduleIcon: icon {{ "send_control_schedule", historyComposeAreaBg }};
historyScheduleIconPosition: point(8px, 8px);
historyEditSaveIcon: icon {{ "send_control_save", historySendIconFg, point(3px, 7px) }};
historyEditSaveIconOver: icon {{ "send_control_save", historySendIconFgOver, point(3px, 7px) }};

View File

@ -79,6 +79,10 @@ rpl::producer<> ComposeControls::cancelRequests() const {
return _cancelRequests.events();
}
rpl::producer<> ComposeControls::sendRequests() const {
return _send->clicks() | rpl::map([] { return rpl::empty_value(); });
}
void ComposeControls::showStarted() {
if (_inlineResults) {
_inlineResults->hideFast();
@ -103,9 +107,41 @@ void ComposeControls::showForGrab() {
showFinished();
}
TextWithTags ComposeControls::getTextWithAppliedMarkdown() const {
return _field->getTextWithAppliedMarkdown();
}
void ComposeControls::clear() {
setText(TextWithTags());
}
void ComposeControls::setText(const TextWithTags &textWithTags) {
//_textUpdateEvents = events;
_field->setTextWithTags(textWithTags, Ui::InputField::HistoryAction::Clear/*fieldHistoryAction*/);
auto cursor = _field->textCursor();
cursor.movePosition(QTextCursor::End);
_field->setTextCursor(cursor);
//_textUpdateEvents = TextUpdateEvent::SaveDraft
// | TextUpdateEvent::SendTyping;
//previewCancel();
//_previewCancelled = false;
}
void ComposeControls::hidePanelsAnimated() {
//_fieldAutocomplete->hideAnimated();
if (_tabbedPanel) {
_tabbedPanel->hideAnimated();
}
if (_inlineResults) {
_inlineResults->hideAnimated();
}
}
void ComposeControls::init() {
initField();
initTabbedSelector();
initSendButton();
_wrap->sizeValue(
) | rpl::start_with_next([=](QSize size) {
@ -182,6 +218,44 @@ void ComposeControls::initTabbedSelector() {
}, wrap->lifetime());
}
void ComposeControls::initSendButton() {
updateSendButtonType();
_send->finishAnimating();
}
void ComposeControls::updateSendButtonType() {
using Type = Ui::SendButton::Type;
const auto type = [&] {
//if (_editMsgId) {
// return Type::Save;
//} else if (_isInlineBot) {
// return Type::Cancel;
//} else if (showRecordButton()) {
// return Type::Record;
//}
return Type::Schedule;
}();
_send->setType(type);
const auto delay = [&] {
return /*(type != Type::Cancel && type != Type::Save && _peer)
? _peer->slowmodeSecondsLeft()
: */0;
}();
_send->setSlowmodeDelay(delay);
//_send->setDisabled(_peer
// && _peer->slowmodeApplied()
// && (_history->latestSendingMessage() != nullptr)
// && (type == Type::Send || type == Type::Record));
//if (delay != 0) {
// App::CallDelayed(
// kRefreshSlowmodeLabelTimeout,
// this,
// [=] { updateSendButtonType(); });
//}
}
void ComposeControls::updateControlsGeometry(QSize size) {
// _attachToggle -- _inlineResults ------ _tabbedPanel -- _fieldBarCancel
// (_attachDocument|_attachPhoto) _field _tabbedSelectorToggle _send

View File

@ -64,6 +64,7 @@ public:
void focus();
[[nodiscard]] rpl::producer<> cancelRequests() const;
[[nodiscard]] rpl::producer<> sendRequests() const;
void pushTabbedSelectorToThirdSection(const Window::SectionShow &params);
bool returnTabbedSelector();
@ -72,10 +73,16 @@ public:
void showStarted();
void showFinished();
[[nodiscard]] TextWithTags getTextWithAppliedMarkdown() const;
void clear();
void hidePanelsAnimated();
private:
void init();
void initField();
void initTabbedSelector();
void initSendButton();
void updateSendButtonType();
void updateHeight();
void updateControlsGeometry(QSize size);
void updateOuterGeometry(QRect rect);
@ -85,6 +92,7 @@ private:
void toggleTabbedSelectorMode();
void createTabbedPanel();
void setTabbedPanel(std::unique_ptr<ChatHelpers::TabbedPanel> panel);
void setText(const TextWithTags &text);
const not_null<QWidget*> _parent;
const not_null<Window::SessionController*> _window;

View File

@ -507,9 +507,7 @@ void TimeInput::startBorderAnimation() {
} // namespace
TimeId DefaultScheduleTime() {
const auto result = base::unixtime::now() + 3600;
const auto time = base::unixtime::parse(result).time();
return result - (time.minute() % 5) * 60 - time.second();
return base::unixtime::now() + 600;
}
void ScheduleBox(
@ -597,7 +595,8 @@ void ScheduleBox(
timeInput->showError();
return;
}
result.scheduled = QDateTime(date->current(), time).toTime_t();
result.scheduled = base::unixtime::serialize(
QDateTime(date->current(), time));
if (result.scheduled <= base::unixtime::now() + kMinimalSchedule) {
timeInput->showError();
return;

View File

@ -10,11 +10,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_compose_controls.h"
#include "history/view/history_view_top_bar_widget.h"
#include "history/view/history_view_list_widget.h"
#include "history/view/history_view_schedule_box.h"
#include "history/history.h"
#include "history/history_item.h"
#include "ui/widgets/scroll_area.h"
#include "ui/widgets/shadow.h"
#include "ui/special_buttons.h"
#include "api/api_common.h"
#include "apiwrap.h"
#include "boxes/confirm_box.h"
#include "window/window_session_controller.h"
#include "window/window_peer_menu.h"
@ -103,6 +106,58 @@ void ScheduledWidget::setupComposeControls() {
) | rpl::start_with_next([=] {
controller()->showBackFromStack();
}, lifetime());
_composeControls->sendRequests(
) | rpl::start_with_next([=] {
send();
}, lifetime());
}
void ScheduledWidget::send() {
if (_composeControls->getTextWithAppliedMarkdown().text.isEmpty()) {
return;
}
const auto callback = crl::guard(this, [=](Api::SendOptions options) {
send(options);
});
Ui::show(
Box(ScheduleBox, callback, DefaultScheduleTime()),
LayerOption::KeepOther);
}
void ScheduledWidget::send(Api::SendOptions options) {
const auto webPageId = 0;/* _previewCancelled
? CancelledWebPageId
: ((_previewData && _previewData->pendingTill >= 0)
? _previewData->id
: WebPageId(0));*/
auto message = ApiWrap::MessageToSend(_history);
message.textWithTags = _composeControls->getTextWithAppliedMarkdown();
message.action.options = options;
//message.action.replyTo = replyToId();
message.webPageId = webPageId;
//const auto error = GetErrorTextForForward(
// _peer,
// _toForward,
// message.textWithTags);
//if (!error.isEmpty()) {
// ShowErrorToast(error);
// return;
//}
session().api().sendMessage(std::move(message));
_composeControls->clear();
//_saveDraftText = true;
//_saveDraftStart = crl::now();
//onDraftSave();
_composeControls->hidePanelsAnimated();
//if (_previewData && _previewData->pendingTill) previewCancel();
_composeControls->focus();
}
void ScheduledWidget::setupScrollDownButton() {
@ -402,9 +457,42 @@ rpl::producer<Data::MessagesSlice> ScheduledWidget::listSource(
data->scheduledMessages().updates(_history)
) | rpl::map([=] {
return data->scheduledMessages().list(_history);
}) | rpl::after_next([=](const Data::MessagesSlice &slice) {
highlightSingleNewMessage(slice);
});
}
void ScheduledWidget::highlightSingleNewMessage(
const Data::MessagesSlice &slice) {
const auto guard = gsl::finally([&] { _lastSlice = slice; });
if (_lastSlice.ids.empty()
|| (slice.ids.size() != _lastSlice.ids.size() + 1)) {
return;
}
auto firstDifferent = 0;
for (; firstDifferent != _lastSlice.ids.size(); ++firstDifferent) {
if (slice.ids[firstDifferent] != _lastSlice.ids[firstDifferent]) {
break;
}
++firstDifferent;
}
auto lastDifferent = slice.ids.size() - 1;
for (; lastDifferent != firstDifferent;) {
if (slice.ids[lastDifferent] != _lastSlice.ids[lastDifferent - 1]) {
break;
}
--lastDifferent;
}
if (firstDifferent != lastDifferent) {
return;
}
const auto newId = slice.ids[firstDifferent];
if (const auto item = session().data().message(newId)) {
// _highlightMessageId = newId;
showAtPosition(item->position());
}
}
bool ScheduledWidget::listAllowsMultiSelect() {
return true;
}

View File

@ -10,9 +10,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/section_widget.h"
#include "window/section_memento.h"
#include "history/view/history_view_list_widget.h"
#include "data/data_messages.h"
class History;
namespace Api {
struct SendOptions;
} // namespace Api
namespace Notify {
struct PeerUpdate;
} // namespace Notify
@ -125,6 +130,10 @@ private:
void confirmDeleteSelected();
void clearSelected();
void send();
void send(Api::SendOptions options);
void highlightSingleNewMessage(const Data::MessagesSlice &slice);
const not_null<History*> _history;
object_ptr<Ui::ScrollArea> _scroll;
QPointer<ListWidget> _inner;
@ -141,6 +150,8 @@ private:
bool _scrollDownIsShown = false;
object_ptr<Ui::HistoryDownButton> _scrollDown;
Data::MessagesSlice _lastSlice;
};
class ScheduledMemento : public Window::SectionMemento {

View File

@ -369,6 +369,7 @@ void SendButton::paintEvent(QPaintEvent *e) {
case Type::Save: paintSave(p, over); break;
case Type::Cancel: paintCancel(p, over); break;
case Type::Send: paintSend(p, over); break;
case Type::Schedule: paintSchedule(p, over); break;
case Type::Slowmode: paintSlowmode(p); break;
}
}
@ -426,6 +427,23 @@ void SendButton::paintSend(Painter &p, bool over) {
}
}
void SendButton::paintSchedule(Painter &p, bool over) {
{
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
p.setBrush(over ? st::historySendIconFgOver : st::historySendIconFg);
p.drawEllipse(
st::historyScheduleIconPosition.x(),
st::historyScheduleIconPosition.y(),
st::historyScheduleIcon.width(),
st::historyScheduleIcon.height());
}
st::historyScheduleIcon.paint(
p,
st::historyScheduleIconPosition,
width());
}
void SendButton::paintSlowmode(Painter &p) {
p.setFont(st::normalFont);
p.setPen(st::windowSubTextFg);

View File

@ -82,6 +82,7 @@ public:
enum class Type {
Send,
Schedule,
Save,
Record,
Cancel,
@ -129,6 +130,7 @@ private:
void paintSave(Painter &p, bool over);
void paintCancel(Painter &p, bool over);
void paintSend(Painter &p, bool over);
void paintSchedule(Painter &p, bool over);
void paintSlowmode(Painter &p);
Type _type = Type::Send;