init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
This commit is contained in:
145
Telegram/SourceFiles/ui/boxes/choose_time.cpp
Normal file
145
Telegram/SourceFiles/ui/boxes/choose_time.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
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<RpWidget*> parent,
|
||||
TimeId startSeconds,
|
||||
bool hiddenDaysInput) {
|
||||
using TimeField = Ui::TimePartWithPlaceholder;
|
||||
const auto putNext = [](not_null<TimeField*> 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<TimeField*> 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<TimeField*> day;
|
||||
not_null<TimeField*> hour;
|
||||
not_null<TimeField*> minute;
|
||||
|
||||
rpl::variable<int> valueInSeconds = 0;
|
||||
};
|
||||
|
||||
auto content = object_ptr<Ui::FixedHeightWidget>(
|
||||
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>(State{
|
||||
.day = Ui::CreateChild<TimeField>(
|
||||
content.data(),
|
||||
st::muteBoxTimeField,
|
||||
rpl::never<QString>(),
|
||||
QString::number(startDays)),
|
||||
.hour = Ui::CreateChild<TimeField>(
|
||||
content.data(),
|
||||
st::muteBoxTimeField,
|
||||
rpl::never<QString>(),
|
||||
QString::number(startHours)),
|
||||
.minute = Ui::CreateChild<TimeField>(
|
||||
content.data(),
|
||||
st::muteBoxTimeField,
|
||||
rpl::never<QString>(),
|
||||
QString::number(startMinutes)),
|
||||
});
|
||||
|
||||
const auto day = base::make_weak(state->day);
|
||||
const auto hour = base::make_weak(state->hour);
|
||||
const auto minute = base::make_weak(state->minute);
|
||||
|
||||
if (hiddenDaysInput) {
|
||||
day->setVisible(false);
|
||||
}
|
||||
|
||||
day->setPhrase(tr::lng_days);
|
||||
day->setMaxValue(31);
|
||||
day->setWheelStep(1);
|
||||
day->putNext() | rpl::on_next([=](QChar ch) {
|
||||
putNext(hour.get(), ch);
|
||||
}, content->lifetime());
|
||||
|
||||
hour->setPhrase(tr::lng_hours);
|
||||
hour->setMaxValue(23);
|
||||
hour->setWheelStep(1);
|
||||
hour->putNext() | rpl::on_next([=](QChar ch) {
|
||||
putNext(minute.get(), ch);
|
||||
}, content->lifetime());
|
||||
hour->erasePrevious() | rpl::on_next([=] {
|
||||
erasePrevious(day.get());
|
||||
}, content->lifetime());
|
||||
|
||||
minute->setPhrase(tr::lng_minutes);
|
||||
minute->setMaxValue(59);
|
||||
minute->setWheelStep(10);
|
||||
minute->erasePrevious() | rpl::on_next([=] {
|
||||
erasePrevious(hour.get());
|
||||
}, content->lifetime());
|
||||
|
||||
content->sizeValue(
|
||||
) | rpl::on_next([=](const QSize &s) {
|
||||
const auto inputWidth = s.width() / (hiddenDaysInput ? 2 : 3);
|
||||
auto rect = QRect(
|
||||
0,
|
||||
(s.height() - day->height()) / 2,
|
||||
inputWidth,
|
||||
day->height());
|
||||
for (const auto &input : { day, hour, minute }) {
|
||||
if (input->isHidden()) {
|
||||
continue;
|
||||
}
|
||||
input->setGeometry(rect - st::muteBoxTimeFieldPadding);
|
||||
rect.translate(inputWidth, 0);
|
||||
}
|
||||
}, content->lifetime());
|
||||
|
||||
rpl::merge(
|
||||
rpl::single(rpl::empty),
|
||||
base::qt_signal_producer(day.get(), &MaskedInputField::changed),
|
||||
base::qt_signal_producer(hour.get(), &MaskedInputField::changed),
|
||||
base::qt_signal_producer(minute.get(), &MaskedInputField::changed)
|
||||
) | rpl::on_next([=] {
|
||||
state->valueInSeconds = 0
|
||||
+ day->getLastText().toUInt() * 3600 * 24
|
||||
+ hour->getLastText().toUInt() * 3600
|
||||
+ minute->getLastText().toUInt() * 60;
|
||||
}, content->lifetime());
|
||||
return {
|
||||
object_ptr<Ui::RpWidget>::fromRaw(content.release()),
|
||||
state->valueInSeconds.value(),
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
Reference in New Issue
Block a user