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:
218
Telegram/SourceFiles/ui/boxes/edit_birthday_box.cpp
Normal file
218
Telegram/SourceFiles/ui/boxes/edit_birthday_box.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
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/edit_birthday_box.h"
|
||||
|
||||
#include "base/event_filter.h"
|
||||
#include "data/data_birthday.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/widgets/vertical_drum_picker.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_settings.h"
|
||||
|
||||
#include <QtCore/QDate>
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class GenericBox;
|
||||
|
||||
void EditBirthdayBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
Data::Birthday current,
|
||||
Fn<void(Data::Birthday)> save,
|
||||
EditBirthdayType type) {
|
||||
box->setWidth(st::boxWideWidth);
|
||||
const auto content = box->addRow(object_ptr<Ui::FixedHeightWidget>(
|
||||
box,
|
||||
st::settingsWorkingHoursPicker));
|
||||
|
||||
const auto font = st::boxTextFont;
|
||||
const auto itemHeight = st::settingsWorkingHoursPickerItemHeight;
|
||||
const auto picker = [=](
|
||||
int count,
|
||||
int startIndex,
|
||||
Fn<void(QPainter &p, QRectF rect, int index)> paint) {
|
||||
return Ui::CreateChild<Ui::VerticalDrumPicker>(
|
||||
content,
|
||||
Ui::VerticalDrumPicker::DefaultPaintCallback(
|
||||
font,
|
||||
itemHeight,
|
||||
paint),
|
||||
count,
|
||||
itemHeight,
|
||||
startIndex);
|
||||
};
|
||||
|
||||
const auto nowDate = QDate::currentDate();
|
||||
const auto nowYear = nowDate.year();
|
||||
const auto nowMonth = nowDate.month();
|
||||
const auto nowDay = nowDate.day();
|
||||
const auto now = Data::Birthday(nowDay, nowMonth, nowYear);
|
||||
const auto max = current.year() ? std::max(now, current) : now;
|
||||
const auto maxYear = max.year();
|
||||
const auto minYear = Data::Birthday::kYearMin;
|
||||
const auto yearsCount = (maxYear - minYear + 2); // Last - not set.
|
||||
const auto yearsStartIndex = current.year()
|
||||
? (current.year() - minYear)
|
||||
: (yearsCount - 1);
|
||||
const auto yearsPaint = [=](QPainter &p, QRectF rect, int index) {
|
||||
p.drawText(
|
||||
rect,
|
||||
(index < yearsCount - 1
|
||||
? QString::number(minYear + index)
|
||||
: QString::fromUtf8("\xe2\x80\x94")),
|
||||
style::al_center);
|
||||
};
|
||||
const auto years = picker(yearsCount, yearsStartIndex, yearsPaint);
|
||||
|
||||
struct State {
|
||||
rpl::variable<Ui::VerticalDrumPicker*> months;
|
||||
rpl::variable<Ui::VerticalDrumPicker*> days;
|
||||
};
|
||||
const auto state = content->lifetime().make_state<State>();
|
||||
|
||||
// years->value() is valid only after size is set.
|
||||
rpl::combine(
|
||||
content->sizeValue(),
|
||||
state->months.value(),
|
||||
state->days.value()
|
||||
) | rpl::on_next([=](
|
||||
QSize s,
|
||||
Ui::VerticalDrumPicker *months,
|
||||
Ui::VerticalDrumPicker *days) {
|
||||
const auto half = s.width() / 2;
|
||||
years->setGeometry(half * 3 / 2, 0, half / 2, s.height());
|
||||
if (months) {
|
||||
months->setGeometry(half / 2, 0, half, s.height());
|
||||
}
|
||||
if (days) {
|
||||
days->setGeometry(0, 0, half / 2, s.height());
|
||||
}
|
||||
}, content->lifetime());
|
||||
|
||||
Ui::SendPendingMoveResizeEvents(years);
|
||||
|
||||
years->value() | rpl::on_next([=](int yearsIndex) {
|
||||
const auto year = (yearsIndex == yearsCount - 1)
|
||||
? 0
|
||||
: minYear + yearsIndex;
|
||||
const auto monthsCount = (year == maxYear)
|
||||
? max.month()
|
||||
: 12;
|
||||
const auto monthsStartIndex = std::clamp(
|
||||
(state->months.current()
|
||||
? state->months.current()->index()
|
||||
: current.month()
|
||||
? (current.month() - 1)
|
||||
: (now.month() - 1)),
|
||||
0,
|
||||
monthsCount - 1);
|
||||
const auto monthsPaint = [=](QPainter &p, QRectF rect, int index) {
|
||||
p.drawText(
|
||||
rect,
|
||||
Lang::Month(index + 1)(tr::now),
|
||||
style::al_center);
|
||||
};
|
||||
const auto updated = picker(
|
||||
monthsCount,
|
||||
monthsStartIndex,
|
||||
monthsPaint);
|
||||
delete state->months.current();
|
||||
state->months = updated;
|
||||
state->months.current()->show();
|
||||
}, years->lifetime());
|
||||
|
||||
Ui::SendPendingMoveResizeEvents(state->months.current());
|
||||
|
||||
state->months.value() | rpl::map([=](Ui::VerticalDrumPicker *picker) {
|
||||
return picker ? picker->value() : rpl::single(current.month()
|
||||
? (current.month() - 1)
|
||||
: (now.month() - 1));
|
||||
}) | rpl::flatten_latest() | rpl::on_next([=](int monthIndex) {
|
||||
const auto month = monthIndex + 1;
|
||||
const auto yearsIndex = years->index();
|
||||
const auto year = (yearsIndex == yearsCount - 1)
|
||||
? 0
|
||||
: minYear + yearsIndex;
|
||||
const auto daysCount = (year == maxYear && month == max.month())
|
||||
? max.day()
|
||||
: (month == 2)
|
||||
? ((!year || (!(year % 4) && ((year % 100) || !(year % 400))))
|
||||
? 29
|
||||
: 28)
|
||||
: ((month == 4) || (month == 6) || (month == 9) || (month == 11))
|
||||
? 30
|
||||
: 31;
|
||||
const auto daysStartIndex = std::clamp(
|
||||
(state->days.current()
|
||||
? state->days.current()->index()
|
||||
: current.day()
|
||||
? (current.day() - 1)
|
||||
: (now.day() - 1)),
|
||||
0,
|
||||
daysCount - 1);
|
||||
const auto daysPaint = [=](QPainter &p, QRectF rect, int index) {
|
||||
p.drawText(rect, QString::number(index + 1), style::al_center);
|
||||
};
|
||||
const auto updated = picker(
|
||||
daysCount,
|
||||
daysStartIndex,
|
||||
daysPaint);
|
||||
delete state->days.current();
|
||||
state->days = updated;
|
||||
state->days.current()->show();
|
||||
}, years->lifetime());
|
||||
|
||||
content->paintRequest(
|
||||
) | rpl::on_next([=](const QRect &r) {
|
||||
auto p = QPainter(content);
|
||||
|
||||
p.fillRect(r, Qt::transparent);
|
||||
|
||||
const auto lineRect = QRect(
|
||||
0,
|
||||
content->height() / 2,
|
||||
content->width(),
|
||||
st::defaultInputField.borderActive);
|
||||
p.fillRect(lineRect.translated(0, itemHeight / 2), st::activeLineFg);
|
||||
p.fillRect(lineRect.translated(0, -itemHeight / 2), st::activeLineFg);
|
||||
}, content->lifetime());
|
||||
|
||||
base::install_event_filter(box, [=](not_null<QEvent*> e) {
|
||||
if (e->type() == QEvent::KeyPress) {
|
||||
years->handleKeyEvent(static_cast<QKeyEvent*>(e.get()));
|
||||
}
|
||||
return base::EventFilterResult::Continue;
|
||||
});
|
||||
|
||||
auto confirmText = (type == EditBirthdayType::Suggest)
|
||||
? tr::lng_suggest_birthday_box_confirm()
|
||||
: tr::lng_settings_save();
|
||||
box->addButton(std::move(confirmText), [=] {
|
||||
const auto result = Data::Birthday(
|
||||
state->days.current()->index() + 1,
|
||||
state->months.current()->index() + 1,
|
||||
((years->index() == yearsCount - 1)
|
||||
? 0
|
||||
: minYear + years->index()));
|
||||
box->closeBox();
|
||||
save(result);
|
||||
});
|
||||
box->addButton(tr::lng_cancel(), [=] {
|
||||
box->closeBox();
|
||||
});
|
||||
if (current && type == EditBirthdayType::Edit) {
|
||||
box->addLeftButton(tr::lng_settings_birthday_reset(), [=] {
|
||||
box->closeBox();
|
||||
save(Data::Birthday());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
Reference in New Issue
Block a user