From ae25804d83127ea498fe0a76fed5927869c0935f Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 28 Mar 2022 22:21:45 +0300 Subject: [PATCH] Moved widget for time choosing to td_ui. --- Telegram/SourceFiles/menu/menu_mute.cpp | 119 ++------------- Telegram/SourceFiles/ui/boxes/choose_time.cpp | 137 ++++++++++++++++++ Telegram/SourceFiles/ui/boxes/choose_time.h | 25 ++++ Telegram/cmake/td_ui.cmake | 2 + 4 files changed, 178 insertions(+), 105 deletions(-) create mode 100644 Telegram/SourceFiles/ui/boxes/choose_time.cpp create mode 100644 Telegram/SourceFiles/ui/boxes/choose_time.h diff --git a/Telegram/SourceFiles/menu/menu_mute.cpp b/Telegram/SourceFiles/menu/menu_mute.cpp index 480ed4b8f..f8b306f0c 100644 --- a/Telegram/SourceFiles/menu/menu_mute.cpp +++ b/Telegram/SourceFiles/menu/menu_mute.cpp @@ -7,16 +7,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "menu/menu_mute.h" -#include "base/qt_signal_producer.h" #include "data/data_peer.h" #include "data/data_session.h" #include "info/profile/info_profile_values.h" #include "lang/lang_keys.h" #include "menu/menu_check_item.h" +#include "ui/boxes/choose_time.h" #include "ui/effects/animation_value.h" #include "ui/layers/generic_box.h" #include "ui/widgets/checkbox.h" -#include "ui/widgets/fields/time_part_input_with_placeholder.h" #include "ui/widgets/menu/menu_action.h" #include "ui/widgets/popup_menu.h" #include "styles/style_boxes.h" @@ -28,6 +27,8 @@ namespace MuteMenu { namespace { +constexpr auto kMuteDurSecondsDefault = crl::time(8) * 3600; + class MuteItem final : public Ui::Menu::Action { public: MuteItem( @@ -139,101 +140,19 @@ void FillSoundMenu( } void MuteBox(not_null box, not_null peer) { - using TimeField = Ui::TimePartWithPlaceholder; - const auto putNext = [](not_null field, QChar ch) { - field->setCursorPosition(0); - if (ch.unicode()) { - field->setText(ch + field->getLastText()); - field->setCursorPosition(1); - } - field->onTextEdited(); - field->setFocus(); - }; - - const auto erasePrevious = [](not_null field) { - const auto text = field->getLastText(); - if (!text.isEmpty()) { - field->setCursorPosition(text.size() - 1); - field->setText(text.mid(0, text.size() - 1)); - } - field->setFocus(); - }; - struct State { - not_null day; - not_null hour; - not_null minute; - base::unique_qptr menu; - rpl::variable noSoundChanges; - int valueInSeconds = 0; + int lastSeconds = 0; }; - const auto content = box->addRow( - object_ptr(box, st::scheduleHeight)); + auto chooseTimeResult = ChooseTimeWidget(box, kMuteDurSecondsDefault); + box->addRow(std::move(chooseTimeResult.widget)); const auto state = box->lifetime().make_state(State{ - .day = Ui::CreateChild( - content, - st::muteBoxTimeField, - rpl::never(), - QString::number(0)), - .hour = Ui::CreateChild( - content, - st::muteBoxTimeField, - rpl::never(), - QString::number(0)), - .minute = Ui::CreateChild( - content, - st::muteBoxTimeField, - rpl::never(), - QString::number(0)), .noSoundChanges = false, }); - const auto day = Ui::MakeWeak(state->day); - const auto hour = Ui::MakeWeak(state->hour); - const auto minute = Ui::MakeWeak(state->minute); - - day->setPhrase(tr::lng_mute_box_days); - day->setMaxValue(31); - day->setWheelStep(1); - day->putNext() | rpl::start_with_next([=](QChar ch) { - putNext(hour, ch); - }, box->lifetime()); - - hour->setPhrase(tr::lng_mute_box_hours); - hour->setMaxValue(23); - hour->setWheelStep(1); - hour->putNext() | rpl::start_with_next([=](QChar ch) { - putNext(minute, ch); - }, box->lifetime()); - hour->erasePrevious() | rpl::start_with_next([=] { - erasePrevious(day); - }, box->lifetime()); - - minute->setPhrase(tr::lng_mute_box_minutes); - minute->setMaxValue(59); - minute->setWheelStep(10); - minute->erasePrevious() | rpl::start_with_next([=] { - erasePrevious(hour); - }, box->lifetime()); - - content->sizeValue( - ) | rpl::start_with_next([=](const QSize &s) { - const auto inputWidth = s.width() / 3; - auto rect = QRect( - 0, - (s.height() - day->height()) / 2, - inputWidth, - day->height()); - for (const auto &input : { day, hour, minute }) { - input->setGeometry(rect - st::muteBoxTimeFieldPadding); - rect.translate(inputWidth, 0); - } - }, box->lifetime()); - box->setTitle(tr::lng_mute_box_title()); const auto topButton = box->addTopButton(st::infoTopBarMenu); @@ -256,31 +175,21 @@ void MuteBox(not_null box, not_null peer) { return; }); - const auto updateValueInSeconds = [=] { - state->valueInSeconds = 0 - + day->getLastText().toUInt() * 3600 * 24 - + hour->getLastText().toUInt() * 3600 - + minute->getLastText().toUInt() * 60; - }; - - using Field = Ui::MaskedInputField; - auto confirmText = rpl::merge( - base::qt_signal_producer(day.data(), &Field::changed), - base::qt_signal_producer(hour.data(), &Field::changed), - base::qt_signal_producer(minute.data(), &Field::changed), - state->noSoundChanges.value() | rpl::to_empty - ) | rpl::map([=] { - updateValueInSeconds(); - return !state->valueInSeconds + auto confirmText = rpl::combine( + std::move(chooseTimeResult.secondsValue), + state->noSoundChanges.value() + ) | rpl::map([=](int seconds, bool noSound) { + state->lastSeconds = seconds; + return !seconds ? tr::lng_mute_menu_unmute() - : state->noSoundChanges.current() + : noSound ? tr::lng_mute_box_silent_notifications() : tr::lng_mute_menu_mute(); }) | rpl::flatten_latest(); const auto confirm = box->addButton(std::move(confirmText), [=] { peer->owner().updateNotifySettings( peer, - state->valueInSeconds, + state->lastSeconds, std::nullopt, state->noSoundChanges.current()); box->closeBox(); diff --git a/Telegram/SourceFiles/ui/boxes/choose_time.cpp b/Telegram/SourceFiles/ui/boxes/choose_time.cpp new file mode 100644 index 000000000..f094d9ac2 --- /dev/null +++ b/Telegram/SourceFiles/ui/boxes/choose_time.cpp @@ -0,0 +1,137 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "ui/boxes/choose_time.h" + +#include "base/qt_signal_producer.h" +#include "ui/ui_utility.h" +#include "ui/widgets/fields/time_part_input_with_placeholder.h" +#include "ui/wrap/padding_wrap.h" +#include "styles/style_boxes.h" +#include "styles/style_layers.h" + +namespace Ui { + +ChooseTimeResult ChooseTimeWidget( + not_null parent, + TimeId startSeconds) { + using TimeField = Ui::TimePartWithPlaceholder; + const auto putNext = [](not_null field, QChar ch) { + field->setCursorPosition(0); + if (ch.unicode()) { + field->setText(ch + field->getLastText()); + field->setCursorPosition(1); + } + field->onTextEdited(); + field->setFocus(); + }; + + const auto erasePrevious = [](not_null field) { + const auto text = field->getLastText(); + if (!text.isEmpty()) { + field->setCursorPosition(text.size() - 1); + field->setText(text.mid(0, text.size() - 1)); + } + field->setFocus(); + }; + + struct State { + not_null day; + not_null hour; + not_null minute; + + rpl::variable valueInSeconds = 0; + }; + + auto content = object_ptr( + parent, + st::scheduleHeight); + + const auto startDays = startSeconds / 86400; + startSeconds -= startDays * 86400; + const auto startHours = startSeconds / 3600; + startSeconds -= startHours * 3600; + const auto startMinutes = startSeconds / 60; + + const auto state = content->lifetime().make_state(State{ + .day = Ui::CreateChild( + content.data(), + st::muteBoxTimeField, + rpl::never(), + QString::number(startDays)), + .hour = Ui::CreateChild( + content.data(), + st::muteBoxTimeField, + rpl::never(), + QString::number(startHours)), + .minute = Ui::CreateChild( + content.data(), + st::muteBoxTimeField, + rpl::never(), + QString::number(startMinutes)), + }); + + const auto day = Ui::MakeWeak(state->day); + const auto hour = Ui::MakeWeak(state->hour); + const auto minute = Ui::MakeWeak(state->minute); + + day->setPhrase(tr::lng_mute_box_days); + day->setMaxValue(31); + day->setWheelStep(1); + day->putNext() | rpl::start_with_next([=](QChar ch) { + putNext(hour, ch); + }, content->lifetime()); + + hour->setPhrase(tr::lng_mute_box_hours); + hour->setMaxValue(23); + hour->setWheelStep(1); + hour->putNext() | rpl::start_with_next([=](QChar ch) { + putNext(minute, ch); + }, content->lifetime()); + hour->erasePrevious() | rpl::start_with_next([=] { + erasePrevious(day); + }, content->lifetime()); + + minute->setPhrase(tr::lng_mute_box_minutes); + minute->setMaxValue(59); + minute->setWheelStep(10); + minute->erasePrevious() | rpl::start_with_next([=] { + erasePrevious(hour); + }, content->lifetime()); + + content->sizeValue( + ) | rpl::start_with_next([=](const QSize &s) { + const auto inputWidth = s.width() / 3; + auto rect = QRect( + 0, + (s.height() - day->height()) / 2, + inputWidth, + day->height()); + for (const auto &input : { day, hour, minute }) { + input->setGeometry(rect - st::muteBoxTimeFieldPadding); + rect.translate(inputWidth, 0); + } + }, content->lifetime()); + + rpl::merge( + rpl::single(rpl::empty), + base::qt_signal_producer(day.data(), &MaskedInputField::changed), + base::qt_signal_producer(hour.data(), &MaskedInputField::changed), + base::qt_signal_producer(minute.data(), &MaskedInputField::changed) + ) | rpl::start_with_next([=] { + state->valueInSeconds = 0 + + day->getLastText().toUInt() * 3600 * 24 + + hour->getLastText().toUInt() * 3600 + + minute->getLastText().toUInt() * 60; + }, content->lifetime()); + return { + object_ptr::fromRaw(content.release()), + state->valueInSeconds.value(), + }; +} + +} // namespace Ui diff --git a/Telegram/SourceFiles/ui/boxes/choose_time.h b/Telegram/SourceFiles/ui/boxes/choose_time.h new file mode 100644 index 000000000..ca25710cf --- /dev/null +++ b/Telegram/SourceFiles/ui/boxes/choose_time.h @@ -0,0 +1,25 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "base/object_ptr.h" + +namespace Ui { + +class RpWidget; + +struct ChooseTimeResult { + object_ptr widget; + rpl::producer secondsValue; +}; + +ChooseTimeResult ChooseTimeWidget( + not_null parent, + TimeId startSeconds); + +} // namespace Ui diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index 69bbf3d8d..31643282a 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -133,6 +133,8 @@ PRIVATE ui/boxes/calendar_box.h ui/boxes/choose_date_time.cpp ui/boxes/choose_date_time.h + ui/boxes/choose_time.cpp + ui/boxes/choose_time.h ui/boxes/confirm_box.cpp ui/boxes/confirm_box.h ui/boxes/confirm_phone_box.cpp