diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index e993e9bcd..13c63fd49 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -79,7 +79,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_month_day" = "{month} {day}"; "lng_month_day_year" = "{month} {day}, {year}"; -"lng_month_year" = "{month}, {year}"; +"lng_month_year" = "{month} {year}"; "lng_box_ok" = "OK"; diff --git a/Telegram/SourceFiles/boxes/backgroundbox.cpp b/Telegram/SourceFiles/boxes/backgroundbox.cpp index d4df90ffe..5a128ee7f 100644 --- a/Telegram/SourceFiles/boxes/backgroundbox.cpp +++ b/Telegram/SourceFiles/boxes/backgroundbox.cpp @@ -29,6 +29,36 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "ui/effects/round_checkbox.h" #include "auth_session.h" +class BackgroundBox::Inner : public TWidget, public RPCSender, private base::Subscriber { +public: + Inner(QWidget *parent); + + void setBackgroundChosenCallback(base::lambda callback) { + _backgroundChosenCallback = std::move(callback); + } + + ~Inner(); + +protected: + void paintEvent(QPaintEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + +private: + void gotWallpapers(const MTPVector &result); + void updateWallpapers(); + + base::lambda _backgroundChosenCallback; + + int _bgCount = 0; + int _rows = 0; + int _over = -1; + int _overDown = -1; + std::unique_ptr _check; // this is not a widget + +}; + BackgroundBox::BackgroundBox(QWidget*) { } diff --git a/Telegram/SourceFiles/boxes/backgroundbox.h b/Telegram/SourceFiles/boxes/backgroundbox.h index 9758a0f28..b5ebbcbde 100644 --- a/Telegram/SourceFiles/boxes/backgroundbox.h +++ b/Telegram/SourceFiles/boxes/backgroundbox.h @@ -40,34 +40,3 @@ private: QPointer _inner; }; - -// This class is hold in header because it requires Qt preprocessing. -class BackgroundBox::Inner : public TWidget, public RPCSender, private base::Subscriber { -public: - Inner(QWidget *parent); - - void setBackgroundChosenCallback(base::lambda callback) { - _backgroundChosenCallback = std::move(callback); - } - - ~Inner(); - -protected: - void paintEvent(QPaintEvent *e) override; - void mouseMoveEvent(QMouseEvent *e) override; - void mousePressEvent(QMouseEvent *e) override; - void mouseReleaseEvent(QMouseEvent *e) override; - -private: - void gotWallpapers(const MTPVector &result); - void updateWallpapers(); - - base::lambda _backgroundChosenCallback; - - int _bgCount = 0; - int _rows = 0; - int _over = -1; - int _overDown = -1; - std::unique_ptr _check; // this is not a widget - -}; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 877b33a11..876f26827 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -516,6 +516,32 @@ backgroundScroll: ScrollArea(boxLayerScroll) { deltab: 10px; } +calendarTitleHeight: boxTitleHeight; +calendarLeft: IconButton { + width: calendarTitleHeight; + height: calendarTitleHeight; + + icon: icon {{ "title_back", boxTitleFg }}; + iconPosition: point(20px, 20px); + + rippleAreaPosition: point(6px, 6px); + rippleAreaSize: 44px; + ripple: RippleAnimation(defaultRippleAnimation) { + color: windowBgOver; + } +} +calendarRight: IconButton(calendarLeft) { + icon: icon {{ "title_back-flip_horizontal", boxTitleFg }}; +} +calendarTitleFont: boxTitleFont; +calendarDaysFont: normalFont; +calendarDaysFg: boxTitleAdditionalFg; +calendarDaysHeight: 32px; +calendarCellSize: size(48px, 40px); +calendarCellInner: 34px; +calendarPadding: margins(14px, 15px, 14px, 10px); +calendarScroll: backgroundScroll; + passcodeTextStyle: TextStyle(defaultTextStyle) { lineHeight: 20px; } diff --git a/Telegram/SourceFiles/boxes/calendarbox.cpp b/Telegram/SourceFiles/boxes/calendarbox.cpp new file mode 100644 index 000000000..3841e8610 --- /dev/null +++ b/Telegram/SourceFiles/boxes/calendarbox.cpp @@ -0,0 +1,393 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "boxes/calendarbox.h" + +#include "ui/widgets/buttons.h" +#include "styles/style_boxes.h" +#include "styles/style_dialogs.h" +#include "lang.h" + +namespace { + +constexpr auto kDaysInWeek = 7; + +} // namespace + +class CalendarBox::Context { +public: + Context(QDate month, QDate highlighted); + + void start() { + _month.setForced(_month.value(), true); + } + + void skipMonth(int skip); + void showMonth(QDate month); + + int highlightedIndex() const { + return _highlightedIndex; + } + int rowsCount() const { + return _rowsCount; + } + int daysShift() const { + return _daysShift; + } + int daysCount() const { + return _daysCount; + } + bool isEnabled(int index) const { + return (_currentDayIndex < 0) || (index <= _currentDayIndex); + } + + const base::Variable &month() { + return _month; + } + + QDate dateFromIndex(int index) const; + QString labelFromIndex(int index) const; + +private: + static int daysShiftForMonth(QDate month); + static int rowsCountForMonth(QDate month); + + base::Variable _month; + QDate _highlighted; + + int _highlightedIndex = 0; + int _currentDayIndex = 0; + int _daysCount = 0; + int _daysShift = 0; + int _rowsCount = 0; + +}; + +CalendarBox::Context::Context(QDate month, QDate highlighted) : _highlighted(highlighted) { + showMonth(month); +} + +void CalendarBox::Context::showMonth(QDate month) { + if (month.day() != 1) { + month = QDate(month.year(), month.month(), 1); + } + _month.set(month); + _daysCount = month.daysInMonth(); + _daysShift = daysShiftForMonth(month); + _rowsCount = rowsCountForMonth(month); + auto yearIndex = month.year(); + auto monthIndex = month.month(); + _highlightedIndex = month.daysTo(_highlighted); + _currentDayIndex = month.daysTo(QDate::currentDate()); +} + +void CalendarBox::Context::skipMonth(int skip) { + auto year = _month.value().year(); + auto month = _month.value().month(); + month += skip; + while (month < 1) { + --year; + month += 12; + } + while (month > 12) { + ++year; + month -= 12; + } + showMonth(QDate(year, month, 1)); +} + +int CalendarBox::Context::daysShiftForMonth(QDate month) { + t_assert(!month.isNull()); + constexpr auto kMaxRows = 6; + auto inMonthIndex = month.day() - 1; + auto inWeekIndex = month.dayOfWeek() - 1; + return ((kMaxRows * kDaysInWeek) + inWeekIndex - inMonthIndex) % kDaysInWeek; +} + +int CalendarBox::Context::rowsCountForMonth(QDate month) { + t_assert(!month.isNull()); + auto daysShift = daysShiftForMonth(month); + auto daysCount = month.daysInMonth(); + auto cellsCount = daysShift + daysCount; + auto result = (cellsCount / kDaysInWeek); + if (cellsCount % kDaysInWeek) ++result; + return result; +} + +QDate CalendarBox::Context::dateFromIndex(int index) const { + constexpr auto kMonthsCount = 12; + auto month = _month.value().month(); + auto year = _month.value().year(); + while (index < 0) { + if (!--month) { + month += kMonthsCount; + --year; + } + index += QDate(year, month, 1).daysInMonth(); + } + for (auto maxIndex = QDate(year, month, 1).daysInMonth(); index >= maxIndex; maxIndex = QDate(year, month, 1).daysInMonth()) { + index -= maxIndex; + if (month++ == kMonthsCount) { + month -= kMonthsCount; + ++year; + } + } + return QDate(year, month, index + 1); +} + +QString CalendarBox::Context::labelFromIndex(int index) const { + auto day = [this, index] { + if (index >= 0 && index < daysCount()) { + return index + 1; + } + return dateFromIndex(index).day(); + }; + return QString::number(day()); +} + +class CalendarBox::Inner : public TWidget, public RPCSender, private base::Subscriber { +public: + Inner(QWidget *parent, Context *context); + + int countHeight() { + auto innerHeight = st::calendarDaysHeight + _context->rowsCount() * st::calendarCellSize.height(); + return st::calendarPadding.top() + innerHeight + st::calendarPadding.bottom(); + } + + void setDateChosenCallback(base::lambda callback) { + _dateChosenCallback = std::move(callback); + } + + ~Inner(); + +protected: + void paintEvent(QPaintEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + +private: + void monthChanged(QDate month); + + int rowsLeft() const; + int rowsTop() const; + void resizeToCurrent(); + void paintDayNames(Painter &p, QRect clip); + void paintRows(Painter &p, QRect clip); + + Context *_context = nullptr; + + base::lambda _dateChosenCallback; + + static constexpr auto kEmptySelection = -kDaysInWeek; + int _selected = kEmptySelection; + int _pressed = kEmptySelection; + +}; + +CalendarBox::Inner::Inner(QWidget *parent, Context *context) : TWidget(parent) +, _context(context) { + setMouseTracking(true); + subscribe(context->month(), [this](QDate month) { monthChanged(month); }); +} + +void CalendarBox::Inner::monthChanged(QDate month) { + resizeToCurrent(); + update(); +} + +void CalendarBox::Inner::resizeToCurrent() { + resize(st::boxWideWidth, countHeight()); +} + +void CalendarBox::Inner::paintEvent(QPaintEvent *e) { + Painter p(this); + + auto clip = e->rect(); + + paintDayNames(p, clip); + paintRows(p, clip); +} + +void CalendarBox::Inner::paintDayNames(Painter &p, QRect clip) { + p.setFont(st::calendarDaysFont); + p.setPen(st::calendarDaysFg); + auto y = st::calendarPadding.top(); + auto x = st::calendarPadding.left(); + if (!myrtlrect(x, y, st::calendarCellSize.width() * kDaysInWeek, st::calendarDaysHeight).intersects(clip)) { + return; + } + for (auto i = 0; i != kDaysInWeek; ++i, x += st::calendarCellSize.width()) { + auto rect = myrtlrect(x, y, st::calendarCellSize.width(), st::calendarDaysHeight); + if (!rect.intersects(clip)) { + continue; + } + p.drawText(rect, langDayOfWeek(i + 1), style::al_top); + } +} + +int CalendarBox::Inner::rowsLeft() const { + return st::calendarPadding.left(); +} + +int CalendarBox::Inner::rowsTop() const { + return st::calendarPadding.top() + st::calendarDaysHeight; +} + +void CalendarBox::Inner::paintRows(Painter &p, QRect clip) { + p.setFont(st::calendarDaysFont); + auto y = rowsTop(); + auto index = -_context->daysShift(); + auto highlightedIndex = _context->highlightedIndex(); + for (auto row = 0, rowsCount = _context->rowsCount(), daysCount = _context->daysCount() + ; row != rowsCount + ; ++row, y += st::calendarCellSize.height()) { + auto x = rowsLeft(); + if (!myrtlrect(x, y, st::calendarCellSize.width() * kDaysInWeek, st::calendarCellSize.height()).intersects(clip)) { + index += kDaysInWeek; + continue; + } + for (auto col = 0; col != kDaysInWeek; ++col, ++index, x += st::calendarCellSize.width()) { + auto rect = myrtlrect(x, y, st::calendarCellSize.width(), st::calendarCellSize.height()); + auto grayedOut = (index < 0 || index >= daysCount || !rect.intersects(clip)); + auto highlighted = (index == highlightedIndex); + auto enabled = _context->isEnabled(index); + if (highlighted) { + PainterHighQualityEnabler hq(p); + p.setPen(Qt::NoPen); + p.setBrush(grayedOut ? st::dialogsUnreadBgMuted : st::dialogsBgActive); + p.drawEllipse(myrtlrect(x + (st::calendarCellSize.width() - st::calendarCellInner) / 2, y + (st::calendarCellSize.height() - st::calendarCellInner) / 2, st::calendarCellInner, st::calendarCellInner)); + p.setBrush(Qt::NoBrush); + } + //if (index == _rippleIndex) { + // _ripple + //} + if (highlighted) { + p.setPen(grayedOut ? st::dialogsUnreadFg : st::dialogsNameFgActive); + } else if (enabled) { + p.setPen(grayedOut ? st::windowSubTextFg : st::boxTextFg); + } else { + p.setPen(st::windowSubTextFg); + } + p.drawText(rect, _context->labelFromIndex(index), style::al_center); + } + } +} + +void CalendarBox::Inner::mouseMoveEvent(QMouseEvent *e) { + auto point = e->pos(); + auto row = floorclamp(point.y() - rowsTop(), st::calendarCellSize.height(), 0, _context->rowsCount()); + auto col = floorclamp(point.x() - rowsLeft(), st::calendarCellSize.width(), 0, kDaysInWeek); + auto index = row * kDaysInWeek + col - _context->daysShift(); + if (_context->isEnabled(index)) { + _selected = index; + setCursor(style::cur_pointer); + } else { + _selected = kEmptySelection; + setCursor(style::cur_default); + } +} + +void CalendarBox::Inner::mousePressEvent(QMouseEvent *e) { + _pressed = _selected; +} + +void CalendarBox::Inner::mouseReleaseEvent(QMouseEvent *e) { + auto pressed = std::exchange(_pressed, kEmptySelection); + if (pressed != kEmptySelection && pressed == _selected) { + _dateChosenCallback(_context->dateFromIndex(pressed)); + } +} + +CalendarBox::Inner::~Inner() = default; + +class CalendarBox::Title : public TWidget, private base::Subscriber { +public: + Title(QWidget *parent, Context *context) : TWidget(parent), _context(context) { + subscribe(_context->month(), [this](QDate date) { monthChanged(date); }); + } + +protected: + void paintEvent(QPaintEvent *e); + +private: + void monthChanged(QDate month); + + Context *_context = nullptr; + + QString _text; + int _textWidth = 0; + +}; + +void CalendarBox::Title::monthChanged(QDate month) { + _text = langMonthOfYearFull(month.month(), month.year()); + _textWidth = st::calendarTitleFont->width(_text); + update(); +} + +void CalendarBox::Title::paintEvent(QPaintEvent *e) { + Painter p(this); + + p.setFont(st::calendarTitleFont); + p.setPen(st::boxTitleFg); + p.drawTextLeft((width() - _textWidth) / 2, (height() - st::calendarTitleFont->height) / 2, width(), _text, _textWidth); +} + +CalendarBox::CalendarBox(QWidget*, QDate month, QDate highlighted, base::lambda callback) +: _context(std::make_unique(month, highlighted.addDays(-5))) +, _inner(this, _context.get()) +, _title(this, _context.get()) +, _left(this, st::calendarLeft) +, _right(this, st::calendarRight) +, _callback(std::move(callback)) { +} + +void CalendarBox::prepare() { + _left->setClickedCallback([this] { + _context->skipMonth(-1); + }); + _right->setClickedCallback([this] { + _context->skipMonth(1); + }); + +// _inner = setInnerWidget(object_ptr(this, _context.get()), st::calendarScroll, st::calendarTitleHeight); + _inner->setDateChosenCallback(std::move(_callback)); + + addButton(lang(lng_close), [this] { closeBox(); }); + + subscribe(_context->month(), [this](QDate month) { monthChanged(month); }); + + _context->start(); +} + +void CalendarBox::monthChanged(QDate month) { + setDimensions(st::boxWideWidth, st::calendarTitleHeight + _inner->countHeight()); +} + +void CalendarBox::resizeEvent(QResizeEvent *e) { + _left->moveToLeft(0, 0); + _right->moveToRight(0, 0); + _title->setGeometryToLeft(_left->width(), 0, width() - _left->width() - _right->width(), st::calendarTitleHeight); + _inner->setGeometryToLeft(0, st::calendarTitleHeight, width(), height() - st::calendarTitleHeight); + BoxContent::resizeEvent(e); +} + +CalendarBox::~CalendarBox() = default; diff --git a/Telegram/SourceFiles/boxes/calendarbox.h b/Telegram/SourceFiles/boxes/calendarbox.h new file mode 100644 index 000000000..ee488421e --- /dev/null +++ b/Telegram/SourceFiles/boxes/calendarbox.h @@ -0,0 +1,55 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "abstractbox.h" + +namespace Ui { +class IconButton; +} // namespace Ui + +class CalendarBox : public BoxContent { +public: + CalendarBox(QWidget*, QDate month, QDate highlighted, base::lambda callback); + ~CalendarBox(); + +protected: + void prepare() override; + + void resizeEvent(QResizeEvent *e) override; + +private: + void monthChanged(QDate month); + + class Context; + std::unique_ptr _context; + + class Inner; + object_ptr _inner; + + class Title; + object_ptr _title; + object_ptr<Ui::IconButton> _left; + object_ptr<Ui::IconButton> _right; + + base::lambda<void(QDate date)> _callback; + +}; diff --git a/Telegram/SourceFiles/core/observer.h b/Telegram/SourceFiles/core/observer.h index b83400544..fc4eb788d 100644 --- a/Telegram/SourceFiles/core/observer.h +++ b/Telegram/SourceFiles/core/observer.h @@ -391,13 +391,13 @@ public: changed().notify(_value, sync); } - Observable<Type> &changed() { + Observable<Type> &changed() const { return _changed; } private: Type _value; - Observable<Type> _changed; + mutable Observable<Type> _changed; }; @@ -415,12 +415,12 @@ protected: } template <typename Type, typename Lambda> - int subscribe(base::Variable<Type> &variable, Lambda &&handler) { + int subscribe(const base::Variable<Type> &variable, Lambda &&handler) { return subscribe(variable.changed(), std::forward<Lambda>(handler)); } template <typename Type, typename Lambda> - int subscribe(base::Variable<Type> *variable, Lambda &&handler) { + int subscribe(const base::Variable<Type> *variable, Lambda &&handler) { return subscribe(variable->changed(), std::forward<Lambda>(handler)); } diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 335e59480..adbc122f9 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -2293,7 +2293,7 @@ DialogsWidget::DialogsWidget(QWidget *parent) : TWidget(parent) subscribe(Adaptive::Changed(), [this] { updateForwardBar(); }); _cancelSearch->setClickedCallback([this] { onCancelSearch(); }); - _jumpToDate->entity()->setClickedCallback([this] { jumpToDate(); }); + _jumpToDate->entity()->setClickedCallback([this] { if (_searchInPeer) App::main()->showJumpToDate(_searchInPeer); }); _lockUnlock->setVisible(Global::LocalPasscode()); subscribe(Global::RefLocalPasscodeChanged(), [this] { updateLockUnlockVisibility(); }); _lockUnlock->setClickedCallback([this] { @@ -2348,10 +2348,6 @@ void DialogsWidget::activate() { _inner->activate(); } -void DialogsWidget::jumpToDate() { - Ui::show(Box<InformBox>("not implemented")); -} - void DialogsWidget::createDialog(History *history) { auto creating = !history->inChatList(Dialogs::Mode::All); _inner->createDialog(history); diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index f97f08e4a..8c8b8bd0b 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -393,8 +393,6 @@ private: void searchReceived(DialogsSearchRequestType type, const MTPmessages_Messages &result, mtpRequestId requestId); void peerSearchReceived(const MTPcontacts_Found &result, mtpRequestId requestId); - void jumpToDate(); - void setSearchInPeer(PeerData *peer); void showMainMenu(); void updateLockUnlockVisibility(); diff --git a/Telegram/SourceFiles/lang.h b/Telegram/SourceFiles/lang.h index 6c129cfa9..7d992f406 100644 --- a/Telegram/SourceFiles/lang.h +++ b/Telegram/SourceFiles/lang.h @@ -80,58 +80,90 @@ LangString langCounted(ushort key0, ushort tag, float64 value); const char *langKeyName(LangKey key); -inline LangString langDayOfMonth(const QDate &date) { - QDate c(QDate::currentDate()); - int32 month = date.month(), day = date.day(), year = date.year(), cyear = c.year(), cmonth = c.month(); - if (year != cyear) { - if (year > cyear + 1 || cyear > year + 1 || (year == cyear + 1 && month + 12 > cmonth + 3) || (cyear == year + 1 && cmonth + 12 > month + 3)) { - return (month > 0 && month <= 12) ? lng_month_day_year(lt_month, lang(LangKey(lng_month1_small + month - 1)), lt_day, QString::number(day), lt_year, QString::number(year)) : qsl("MONTH_ERR"); +template <typename WithYear, typename WithoutYear> +inline LangString langDateMaybeWithYear(QDate date, WithYear withYear, WithoutYear withoutYear) { + auto month = date.month(); + if (month <= 0 || month > 12) { + return qsl("MONTH_ERR"); + }; + auto year = date.year(); + auto current = QDate::currentDate(); + auto currentYear = current.year(); + auto currentMonth = current.month(); + if (year != currentYear) { + auto yearIsMuchGreater = [](int year, int otherYear) { + return (year > otherYear + 1); + }; + auto monthIsMuchGreater = [](int year, int month, int otherYear, int otherMonth) { + return (year == otherYear + 1) && (month + 12 > otherMonth + 3); + }; + if (false + || yearIsMuchGreater(year, currentYear) + || yearIsMuchGreater(currentYear, year) + || monthIsMuchGreater(year, month, currentYear, currentMonth) + || monthIsMuchGreater(currentYear, currentMonth, year, month)) { + return withYear(month, year); } } - return (month > 0 && month <= 12) ? lng_month_day(lt_month, lang(LangKey(lng_month1_small + month - 1)), lt_day, QString::number(day)) : qsl("MONTH_ERR"); + return withoutYear(month, year); +} + +inline LangString langDayOfMonth(const QDate &date) { + auto day = date.day(); + return langDateMaybeWithYear(date, [day](int month, int year) { + return lng_month_day_year(lt_month, lang(LangKey(lng_month1_small + month - 1)), lt_day, QString::number(day), lt_year, QString::number(year)); + }, [day](int month, int year) { + return lng_month_day(lt_month, lang(LangKey(lng_month1_small + month - 1)), lt_day, QString::number(day)); + }); } inline LangString langDayOfMonthFull(const QDate &date) { - QDate c(QDate::currentDate()); - int32 month = date.month(), day = date.day(), year = date.year(), cyear = c.year(), cmonth = c.month(); - if (year != cyear) { - if (year > cyear + 1 || cyear > year + 1 || (year == cyear + 1 && month + 12 > cmonth + 3) || (cyear == year + 1 && cmonth + 12 > month + 3)) { - return (month > 0 && month <= 12) ? lng_month_day_year(lt_month, lang(LangKey(lng_month1 + month - 1)), lt_day, QString::number(day), lt_year, QString::number(year)) : qsl("MONTH_ERR"); - } - } - return (month > 0 && month <= 12) ? lng_month_day(lt_month, lang(LangKey(lng_month1 + month - 1)), lt_day, QString::number(day)) : qsl("MONTH_ERR"); + auto day = date.day(); + return langDateMaybeWithYear(date, [day](int month, int year) { + return lng_month_day_year(lt_month, lang(LangKey(lng_month1 + month - 1)), lt_day, QString::number(day), lt_year, QString::number(year)); + }, [day](int month, int year) { + return lng_month_day(lt_month, lang(LangKey(lng_month1 + month - 1)), lt_day, QString::number(day)); + }); +} + +inline LangString langMonthOfYear(int month, int year) { + return (month > 0 && month <= 12) ? lng_month_year(lt_month, lang(LangKey(lng_month1_small + month - 1)), lt_year, QString::number(year)) : qsl("MONTH_ERR"); } inline LangString langMonth(const QDate &date) { - QDate c(QDate::currentDate()); - int32 month = date.month(), day = date.day(), year = date.year(), cyear = c.year(), cmonth = c.month(); - if (year != cyear) { - if (year > cyear + 1 || cyear > year + 1 || (year == cyear + 1 && month + 12 > cmonth + 3) || (cyear == year + 1 && cmonth + 12 > month + 3)) { - return (month > 0 && month <= 12) ? lng_month_year(lt_month, lang(LangKey(lng_month1_small + month - 1)), lt_year, QString::number(year)) : qsl("MONTH_ERR"); - } - } - return (month > 0 && month <= 12) ? lang(LangKey(lng_month1_small + month - 1)) : qsl("MONTH_ERR"); + return langDateMaybeWithYear(date, [](int month, int year) { + return langMonthOfYear(month, year); + }, [](int month, int year) { + return lang(LangKey(lng_month1_small + month - 1)); + }); +} + +inline LangString langMonthOfYearFull(int month, int year) { + return (month > 0 && month <= 12) ? lng_month_year(lt_month, lang(LangKey(lng_month1 + month - 1)), lt_year, QString::number(year)) : qsl("MONTH_ERR"); } inline LangString langMonthFull(const QDate &date) { - QDate c(QDate::currentDate()); - int32 month = date.month(), day = date.day(), year = date.year(), cyear = c.year(), cmonth = c.month(); - if (year != cyear) { - if (year > cyear + 1 || cyear > year + 1 || (year == cyear + 1 && month + 12 > cmonth + 3) || (cyear == year + 1 && cmonth + 12 > month + 3)) { - return (month > 0 && month <= 12) ? lng_month_year(lt_month, lang(LangKey(lng_month1 + month - 1)), lt_year, QString::number(year)) : qsl("MONTH_ERR"); - } - } - return (month > 0 && month <= 12) ? lang(LangKey(lng_month1 + month - 1)) : qsl("MONTH_ERR"); + return langDateMaybeWithYear(date, [](int month, int year) { + return langMonthOfYearFull(month, year); + }, [](int month, int year) { + return lang(LangKey(lng_month1 + month - 1)); + }); +} + +inline LangString langDayOfWeek(int index) { + return (index > 0 && index <= 7) ? lang(LangKey(lng_weekday1 + index - 1)) : qsl("DAY_ERR"); } inline LangString langDayOfWeek(const QDate &date) { - int32 day = date.dayOfWeek(); - return (day > 0 && day <= 7) ? lang(LangKey(lng_weekday1 + day - 1)) : qsl("DAY_ERR"); + return langDayOfWeek(date.dayOfWeek()); +} + +inline LangString langDayOfWeekFull(int index) { + return (index > 0 && index <= 7) ? lang(LangKey(lng_weekday1_full + index - 1)) : qsl("DAY_ERR"); } inline LangString langDayOfWeekFull(const QDate &date) { - int32 day = date.dayOfWeek(); - return (day > 0 && day <= 7) ? lang(LangKey(lng_weekday1_full + day - 1)) : qsl("DAY_ERR"); + return langDayOfWeekFull(date.dayOfWeek()); } inline LangString langDateTime(const QDateTime &date) { diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 464733861..fdf8946b0 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -62,6 +62,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "styles/style_boxes.h" #include "mtproto/dc_options.h" #include "core/file_utilities.h" +#include "boxes/calendarbox.h" #include "auth_session.h" #include "window/notifications_manager.h" @@ -2758,6 +2759,24 @@ void MainWidget::dlgUpdated(PeerData *peer, MsgId msgId) { } } +void MainWidget::showJumpToDate(PeerData *peer) { + t_assert(peer != nullptr); + auto shown = ([peer] { + if (auto history = App::historyLoaded(peer)) { + if (history->scrollTopItem) { + return history->scrollTopItem->date.date(); + } else if (!history->lastMsgDate.isNull()) { + return history->lastMsgDate.date(); + } + } + return QDate::currentDate(); + })(); + auto highlighted = shown; + Ui::show(Box<CalendarBox>(shown, highlighted, [peer](QDate date) { + Ui::show(Box<InformBox>("not implemented " + langDayOfMonthFull(date))); + })); +} + void MainWidget::windowShown() { _history->windowShown(); } diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index b70c6bb1e..099573c4a 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -180,6 +180,8 @@ public: void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row); void dlgUpdated(PeerData *peer, MsgId msgId); + void showJumpToDate(PeerData *peer); + void windowShown(); void sentUpdatesReceived(uint64 randomId, const MTPUpdates &updates); diff --git a/Telegram/gyp/Telegram.gyp b/Telegram/gyp/Telegram.gyp index 863ee00de..636b6842a 100644 --- a/Telegram/gyp/Telegram.gyp +++ b/Telegram/gyp/Telegram.gyp @@ -109,6 +109,8 @@ '<(src_loc)/boxes/autolockbox.h', '<(src_loc)/boxes/backgroundbox.cpp', '<(src_loc)/boxes/backgroundbox.h', + '<(src_loc)/boxes/calendarbox.cpp', + '<(src_loc)/boxes/calendarbox.h', '<(src_loc)/boxes/confirmbox.cpp', '<(src_loc)/boxes/confirmbox.h', '<(src_loc)/boxes/confirmphonebox.cpp',