diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 3a40020ab..e34a738d3 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1296,6 +1296,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_reminder_messages" = "Reminders"; "lng_scheduled_date" = "Scheduled for {date}"; "lng_scheduled_date_until_online" = "Scheduled until online"; +"lng_scheduled_send_until_online" = "Send when online"; "lng_scheduled_send_now" = "Send message now?"; "lng_scheduled_send_now_many#one" = "Send {count} message now?"; "lng_scheduled_send_now_many#other" = "Send {count} messages now?"; diff --git a/Telegram/SourceFiles/api/api_common.h b/Telegram/SourceFiles/api/api_common.h index 25e737d14..beb73081f 100644 --- a/Telegram/SourceFiles/api/api_common.h +++ b/Telegram/SourceFiles/api/api_common.h @@ -21,6 +21,7 @@ struct SendOptions { enum class SendType { Normal, Scheduled, + ScheduledToUser, // For "Send when online". }; struct SendAction { diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 3bbd168da..15d82a847 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -1937,7 +1937,9 @@ void SendFilesBox::setInnerFocus() { void SendFilesBox::send( Api::SendOptions options, bool ctrlShiftEnter) { - if (_sendType == Api::SendType::Scheduled && !options.scheduled) { + if ((_sendType == Api::SendType::Scheduled + || _sendType == Api::SendType::ScheduledToUser) + && !options.scheduled) { return sendScheduled(); } @@ -1982,9 +1984,12 @@ void SendFilesBox::sendSilent() { } void SendFilesBox::sendScheduled() { + const auto type = (_sendType == Api::SendType::ScheduledToUser) + ? SendMenuType::ScheduledToUser + : _sendMenuType; const auto callback = [=](Api::SendOptions options) { send(options); }; Ui::show( - HistoryView::PrepareScheduleBox(this, _sendMenuType, callback), + HistoryView::PrepareScheduleBox(this, type, callback), Ui::LayerOption::KeepOther); } diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 49c2b32ee..2ff338970 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -413,7 +413,9 @@ void ShareBox::keyPressEvent(QKeyEvent *e) { SendMenuType ShareBox::sendMenuType() const { const auto selected = _inner->selected(); - return (selected.size() == 1 && selected.front()->isSelf()) + return ranges::all_of(selected, HistoryView::CanScheduleUntilOnline) + ? SendMenuType::ScheduledToUser + : (selected.size() == 1 && selected.front()->isSelf()) ? SendMenuType::Reminder : SendMenuType::Scheduled; } diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp index c2f3983a5..87012d32f 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.cpp +++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp @@ -688,9 +688,9 @@ void SetupSendMenu( } if (schedule && now != SendMenuType::SilentOnly) { (*menu)->addAction( - (now == SendMenuType::Scheduled - ? tr::lng_schedule_message(tr::now) - : tr::lng_reminder_message(tr::now)), + (now == SendMenuType::Reminder + ? tr::lng_reminder_message(tr::now) + : tr::lng_schedule_message(tr::now)), schedule); } (*menu)->popup(QCursor::pos()); diff --git a/Telegram/SourceFiles/chat_helpers/message_field.h b/Telegram/SourceFiles/chat_helpers/message_field.h index 874e15b8e..f6bfd80b9 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.h +++ b/Telegram/SourceFiles/chat_helpers/message_field.h @@ -99,6 +99,7 @@ enum class SendMenuType { Disabled, SilentOnly, Scheduled, + ScheduledToUser, // For "Send when online". Reminder, }; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index f25f3b113..80b599f93 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -3019,6 +3019,8 @@ SendMenuType HistoryWidget::sendMenuType() const { ? SendMenuType::Disabled : _peer->isSelf() ? SendMenuType::Reminder + : HistoryView::CanScheduleUntilOnline(_peer) + ? SendMenuType::ScheduledToUser : SendMenuType::Scheduled; } diff --git a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp index 64ef33a53..405b9f52f 100644 --- a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp +++ b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp @@ -8,17 +8,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_schedule_box.h" #include "api/api_common.h" +#include "data/data_peer.h" +#include "data/data_user.h" +#include "data/data_scheduled_messages.h" // kScheduledUntilOnlineTimestamp #include "lang/lang_keys.h" #include "base/unixtime.h" #include "boxes/calendar_box.h" #include "ui/widgets/input_fields.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/popup_menu.h" #include "ui/wrap/padding_wrap.h" #include "chat_helpers/message_field.h" +#include "styles/style_info.h" #include "styles/style_layers.h" #include "styles/style_history.h" +#include + namespace HistoryView { namespace { @@ -535,20 +542,38 @@ void TimeInput::startBorderAnimation() { } } +void FillSendUntilOnlineMenu( + not_null button, + Fn callback) { + const auto menu = std::make_shared>(); + button->setClickedCallback([=] { + *menu = base::make_unique_q(button); + (*menu)->addAction( + tr::lng_scheduled_send_until_online(tr::now), + std::move(callback)); + (*menu)->popup(QCursor::pos()); + return true; + }); +} + } // namespace TimeId DefaultScheduleTime() { return base::unixtime::now() + 600; } +bool CanScheduleUntilOnline(not_null peer) { + return !peer->isSelf() && peer->isUser() && !peer->asUser()->isBot(); +} + void ScheduleBox( not_null box, SendMenuType type, FnMut done, TimeId time) { - box->setTitle((type == SendMenuType::Scheduled) - ? tr::lng_schedule_title() - : tr::lng_remind_title()); + box->setTitle((type == SendMenuType::Reminder) + ? tr::lng_remind_title() + : tr::lng_schedule_title()); box->setWidth(st::boxWideWidth); const auto date = Ui::CreateChild>( @@ -637,10 +662,15 @@ void ScheduleBox( } return result; }; - const auto save = [=](bool silent) { + const auto save = [=](bool silent, bool untilOnline = false) { + // Pro tip: Hold Ctrl key to send a silent scheduled message! + auto ctrl = + (QGuiApplication::keyboardModifiers() == Qt::ControlModifier); auto result = Api::SendOptions(); - result.silent = silent; - result.scheduled = collect(); + result.silent = silent || ctrl; + result.scheduled = untilOnline + ? Data::ScheduledMessages::kScheduledUntilOnlineTimestamp + : collect(); if (!result.scheduled) { return; } @@ -664,6 +694,14 @@ void ScheduleBox( [=] { save(true); }, nullptr); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); + + if (type == SendMenuType::ScheduledToUser) { + const auto sendUntilOnline = box->addTopButton(st::infoTopBarMenu); + FillSendUntilOnlineMenu( + sendUntilOnline.data(), + [=] { save(false, true); }); + } + } } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/history_view_schedule_box.h b/Telegram/SourceFiles/history/view/history_view_schedule_box.h index 387ee8c3c..6e4e9c3c2 100644 --- a/Telegram/SourceFiles/history/view/history_view_schedule_box.h +++ b/Telegram/SourceFiles/history/view/history_view_schedule_box.h @@ -18,6 +18,7 @@ enum class SendMenuType; namespace HistoryView { [[nodiscard]] TimeId DefaultScheduleTime(); +[[nodiscard]] bool CanScheduleUntilOnline(not_null peer); void ScheduleBox( not_null box, SendMenuType type, diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 0730b1869..ce6158100 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -240,7 +240,9 @@ bool ScheduledWidget::confirmSendingFiles( text, boxCompressConfirm, _history->peer->slowmodeApplied() ? SendLimit::One : SendLimit::Many, - Api::SendType::Scheduled, + CanScheduleUntilOnline(_history->peer) + ? Api::SendType::ScheduledToUser + : Api::SendType::Scheduled, SendMenuType::Disabled); //_field->setTextWithTags({}); @@ -545,6 +547,8 @@ void ScheduledWidget::sendInlineResult( SendMenuType ScheduledWidget::sendMenuType() const { return _history->peer->isSelf() ? SendMenuType::Reminder + : HistoryView::CanScheduleUntilOnline(_history->peer) + ? SendMenuType::ScheduledToUser : SendMenuType::Scheduled; }