diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 57671b9d92..e868a3bea7 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -519,7 +519,7 @@ defaultCalendarSizes: CalendarSizes { daysHeight: 40px; cellSize: size(48px, 40px); cellInner: 34px; - padding: margins(14px, 7px, 14px, 10px); + padding: margins(14px, 0px, 14px, 0px); } calendarDaysFont: normalFont; calendarDaysFg: boxTitleAdditionalFg; diff --git a/Telegram/SourceFiles/export/view/export.style b/Telegram/SourceFiles/export/view/export.style index f45c48e980..5091de896c 100644 --- a/Telegram/SourceFiles/export/view/export.style +++ b/Telegram/SourceFiles/export/view/export.style @@ -100,5 +100,5 @@ exportCalendarSizes: CalendarSizes(defaultCalendarSizes) { daysHeight: 40px; cellSize: size(42px, 38px); cellInner: 32px; - padding: margins(14px, 7px, 14px, 10px); + padding: margins(14px, 0px, 14px, 0px); } diff --git a/Telegram/SourceFiles/ui/boxes/calendar_box.cpp b/Telegram/SourceFiles/ui/boxes/calendar_box.cpp index cc5c0be5e6..485f62f0e6 100644 --- a/Telegram/SourceFiles/ui/boxes/calendar_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/calendar_box.cpp @@ -43,6 +43,7 @@ public: void skipMonth(int skip); void showMonth(QDate month); + [[nodiscard]] bool showsMonthOf(QDate date) const; [[nodiscard]] int highlightedIndex() const { return _highlightedIndex; @@ -122,6 +123,11 @@ void CalendarBox::Context::showMonth(QDate month) { applyMonth(month); } +bool CalendarBox::Context::showsMonthOf(QDate date) const { + const auto shown = _month.current(); + return (shown.year() == date.year()) && (shown.month() == date.month()); +} + void CalendarBox::Context::applyMonth(const QDate &month, bool forced) { _daysCount = month.daysInMonth(); _daysShift = DaysShiftForMonth(month, _min); @@ -167,7 +173,7 @@ int CalendarBox::Context::DaysShiftForMonth(QDate month, QDate min) { if (min.day() != 1) { min = QDate(min.year(), min.month(), 1); } - const auto add = min.daysTo(month) + inWeekIndex + (min.dayOfWeek() - 1); + const auto add = min.daysTo(month) - inWeekIndex + (min.dayOfWeek() - 1); return from + add; } @@ -565,6 +571,13 @@ CalendarBox::CalendarBox(QWidget*, CalendarBoxArgs &&args) _context->setBeginningButton(args.hasBeginningButton); _context->setMinDate(args.minDate); _context->setMaxDate(args.maxDate); + + _scroll->scrolls( + ) | rpl::filter([=] { + return _watchScroll; + }) | rpl::start_with_next([=] { + processScroll(); + }, lifetime()); } void CalendarBox::prepare() { @@ -579,6 +592,7 @@ void CalendarBox::prepare() { ) | rpl::start_with_next([=](QDate month) { monthChanged(month); }, lifetime()); + setExactScroll(); if (_finalize) { _finalize(this); @@ -601,15 +615,46 @@ bool CalendarBox::isNextEnabled() const { void CalendarBox::goPreviousMonth() { if (isPreviousEnabled()) { _context->skipMonth(-1); + setExactScroll(); } } void CalendarBox::goNextMonth() { if (isNextEnabled()) { _context->skipMonth(1); + setExactScroll(); } } +void CalendarBox::setExactScroll() { + const auto top = _st.padding.top() + + (_context->daysShift() / kDaysInWeek) * _st.cellSize.height(); + _scroll->scrollToY(top); + _watchScroll = true; +} + +void CalendarBox::processScroll() { + const auto wasTop = _scroll->scrollTop(); + const auto wasShift = _context->daysShift(); + const auto point = _scroll->rect().center() + QPoint(0, wasTop); + const auto row = (point.y() - _st.padding.top()) / _st.cellSize.height(); + const auto col = (point.x() - _st.padding.left()) / _st.cellSize.width(); + const auto index = row * kDaysInWeek + col; + const auto date = _context->dateFromIndex(index - wasShift); + if (_context->showsMonthOf(date)) { + return; + } + const auto wasFirst = _context->dateFromIndex(-wasShift); + const auto month = QDate(date.year(), date.month(), 1); + _watchScroll = false; + _context->showMonth(month); + const auto nowShift = _context->daysShift(); + const auto nowFirst = _context->dateFromIndex(-nowShift); + const auto delta = nowFirst.daysTo(wasFirst) / kDaysInWeek; + _scroll->scrollToY(wasTop + delta * _st.cellSize.height()); + _watchScroll = true; +} + void CalendarBox::monthChanged(QDate month) { setDimensions(_st.width, st::calendarTitleHeight + _st.daysHeight + _inner->countMaxHeight()); auto previousEnabled = isPreviousEnabled(); diff --git a/Telegram/SourceFiles/ui/boxes/calendar_box.h b/Telegram/SourceFiles/ui/boxes/calendar_box.h index 830dcebb56..b3952dc872 100644 --- a/Telegram/SourceFiles/ui/boxes/calendar_box.h +++ b/Telegram/SourceFiles/ui/boxes/calendar_box.h @@ -58,6 +58,8 @@ private: void goPreviousMonth(); void goNextMonth(); + void setExactScroll(); + void processScroll(); const style::CalendarSizes &_st; @@ -76,6 +78,7 @@ private: Fn _callback; FnMut)> _finalize; + bool _watchScroll = false; };