diff --git a/Telegram/Resources/icons/menu/auto_delete.png b/Telegram/Resources/icons/menu/auto_delete.png new file mode 100644 index 000000000..c1fd7790c Binary files /dev/null and b/Telegram/Resources/icons/menu/auto_delete.png differ diff --git a/Telegram/Resources/icons/menu/auto_delete@2x.png b/Telegram/Resources/icons/menu/auto_delete@2x.png new file mode 100644 index 000000000..72a6c2279 Binary files /dev/null and b/Telegram/Resources/icons/menu/auto_delete@2x.png differ diff --git a/Telegram/Resources/icons/menu/auto_delete@3x.png b/Telegram/Resources/icons/menu/auto_delete@3x.png new file mode 100644 index 000000000..73a58632e Binary files /dev/null and b/Telegram/Resources/icons/menu/auto_delete@3x.png differ diff --git a/Telegram/Resources/icons/menu/auto_delete_plain.png b/Telegram/Resources/icons/menu/auto_delete_plain.png new file mode 100644 index 000000000..a5da8a94a Binary files /dev/null and b/Telegram/Resources/icons/menu/auto_delete_plain.png differ diff --git a/Telegram/Resources/icons/menu/auto_delete_plain@2x.png b/Telegram/Resources/icons/menu/auto_delete_plain@2x.png new file mode 100644 index 000000000..f855a5bcd Binary files /dev/null and b/Telegram/Resources/icons/menu/auto_delete_plain@2x.png differ diff --git a/Telegram/Resources/icons/menu/auto_delete_plain@3x.png b/Telegram/Resources/icons/menu/auto_delete_plain@3x.png new file mode 100644 index 000000000..5d034aec6 Binary files /dev/null and b/Telegram/Resources/icons/menu/auto_delete_plain@3x.png differ diff --git a/Telegram/Resources/icons/menu/customize.png b/Telegram/Resources/icons/menu/customize.png new file mode 100644 index 000000000..ef86a7a98 Binary files /dev/null and b/Telegram/Resources/icons/menu/customize.png differ diff --git a/Telegram/Resources/icons/menu/customize@2x.png b/Telegram/Resources/icons/menu/customize@2x.png new file mode 100644 index 000000000..4ed42cbaa Binary files /dev/null and b/Telegram/Resources/icons/menu/customize@2x.png differ diff --git a/Telegram/Resources/icons/menu/customize@3x.png b/Telegram/Resources/icons/menu/customize@3x.png new file mode 100644 index 000000000..87463e1af Binary files /dev/null and b/Telegram/Resources/icons/menu/customize@3x.png differ diff --git a/Telegram/Resources/icons/menu/disable.png b/Telegram/Resources/icons/menu/disable.png new file mode 100644 index 000000000..2f5f1437d Binary files /dev/null and b/Telegram/Resources/icons/menu/disable.png differ diff --git a/Telegram/Resources/icons/menu/disable@2x.png b/Telegram/Resources/icons/menu/disable@2x.png new file mode 100644 index 000000000..a514806d1 Binary files /dev/null and b/Telegram/Resources/icons/menu/disable@2x.png differ diff --git a/Telegram/Resources/icons/menu/disable@3x.png b/Telegram/Resources/icons/menu/disable@3x.png new file mode 100644 index 000000000..7a903fdb4 Binary files /dev/null and b/Telegram/Resources/icons/menu/disable@3x.png differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index ebc0cc69f..f88ef925b 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1122,11 +1122,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_manage_history_visibility_hidden_about" = "New members won't see earlier messages."; "lng_manage_history_visibility_hidden_legacy" = "New members won't see more than 100 previous messages."; -"lng_manage_messages_ttl_title" = "Auto-delete messages"; -"lng_manage_messages_ttl_never" = "Off"; -"lng_manage_messages_ttl_after1" = "1 day"; -"lng_manage_messages_ttl_after2" = "1 week"; -"lng_manage_messages_ttl_after3" = "1 month"; +"lng_manage_messages_ttl_title" = "Auto-delete after..."; +"lng_manage_messages_ttl_never" = "Disable"; +"lng_manage_messages_ttl_after1" = "1 hour"; +"lng_manage_messages_ttl_after2" = "1 day"; +"lng_manage_messages_ttl_after3" = "1 week"; +"lng_manage_messages_ttl_after4" = "1 month"; +"lng_manage_messages_ttl_after_custom" = "Custom"; +"lng_manage_messages_ttl_menu" = "Auto-Delete"; "lng_ttl_edit_about" = "Automatically delete new messages after a certain period of time for you and {user}."; "lng_ttl_edit_about_group" = "Automatically delete new messages sent in this chat after a certain period of time."; diff --git a/Telegram/SourceFiles/menu/menu_ttl.cpp b/Telegram/SourceFiles/menu/menu_ttl.cpp new file mode 100644 index 000000000..31ec538e4 --- /dev/null +++ b/Telegram/SourceFiles/menu/menu_ttl.cpp @@ -0,0 +1,217 @@ +/* +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 "menu/menu_ttl.h" + +#include "lang/lang_keys.h" +#include "ui/boxes/choose_time.h" +#include "ui/layers/generic_box.h" +#include "ui/text/format_values.h" +#include "ui/widgets/labels.h" +#include "ui/widgets/menu/menu_action.h" +#include "ui/widgets/popup_menu.h" +#include "styles/style_chat.h" +#include "styles/style_dialogs.h" // dialogsScamFont +#include "styles/style_menu_icons.h" + +namespace TTLMenu { + +namespace { + +constexpr auto kTTLDurHours1 = crl::time(1); +constexpr auto kTTLDurSeconds1 = kTTLDurHours1 * 3600; +constexpr auto kTTLDurHours2 = crl::time(24); +constexpr auto kTTLDurSeconds2 = kTTLDurHours2 * 3600; +constexpr auto kTTLDurHours3 = crl::time(24 * 7); +constexpr auto kTTLDurSeconds3 = kTTLDurHours3 * 3600; +constexpr auto kTTLDurHours4 = crl::time(24 * 30); +constexpr auto kTTLDurSeconds4 = kTTLDurHours4 * 3600; + +class IconWithText final : public Ui::Menu::Action { +public: + using Ui::Menu::Action::Action; + + void setData(const QString &text, const QPoint &iconPosition); + +protected: + void paintEvent(QPaintEvent *e) override; + +private: + QPoint _iconPosition; + QString _text; + +}; + +void IconWithText::setData(const QString &text, const QPoint &iconPosition) { + _iconPosition = iconPosition; + _text = text; +} + +void IconWithText::paintEvent(QPaintEvent *e) { + Ui::Menu::Action::paintEvent(e); + + Painter p(this); + p.setFont(st::dialogsScamFont); + p.setPen(st::menuIconColor); + p.drawText(_iconPosition, _text); +} + +class TextItem final : public Ui::Menu::ItemBase { +public: + TextItem( + not_null parent, + const style::Menu &st, + rpl::producer &&text); + + not_null action() const override; + bool isEnabled() const override; + +protected: + int contentHeight() const override; + +private: + const base::unique_qptr _label; + const not_null _dummyAction; + +}; + +TextItem::TextItem( + not_null parent, + const style::Menu &st, + rpl::producer &&text) +: ItemBase(parent, st) +, _label(base::make_unique_q( + this, + std::move(text), + st::historyMessagesTTLLabel)) +, _dummyAction(Ui::CreateChild(parent.get())) { + + setAttribute(Qt::WA_TransparentForMouseEvents); + + setMinWidth(st::historyMessagesTTLLabel.minWidth + + st.itemIconPosition.x()); + + sizeValue( + ) | rpl::start_with_next([=](const QSize &s) { + _label->moveToLeft( + st.itemIconPosition.x(), + (s.height() - _label->height()) / 2); + }, lifetime()); + + initResizeHook(parent->sizeValue()); +} + +not_null TextItem::action() const { + return _dummyAction; +} + +bool TextItem::isEnabled() const { + return false; +} + +int TextItem::contentHeight() const { + return _label->height(); +} + +void TTLBox( + not_null box, + Fn callback, + TimeId startTtlPeriod) { + struct State { + int lastSeconds = 0; + }; + const auto startTtl = startTtlPeriod ? startTtlPeriod : kTTLDurSeconds2; + auto chooseTimeResult = ChooseTimeWidget(box, startTtl); + box->addRow(std::move(chooseTimeResult.widget)); + + const auto state = box->lifetime().make_state(); + + box->setTitle(tr::lng_manage_messages_ttl_title()); + + auto confirmText = std::move( + chooseTimeResult.secondsValue + ) | rpl::map([=](int seconds) { + state->lastSeconds = seconds; + return !seconds + ? tr::lng_manage_messages_ttl_never() + : tr::lng_enable_auto_delete(); + }) | rpl::flatten_latest(); + const auto confirm = box->addButton(std::move(confirmText), [=] { + callback(state->lastSeconds); + box->closeBox(); + }); + box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); +} + +} // namespace + +void FillTTLMenu(not_null menu, Args args) { + const auto &st = menu->st().menu; + const auto iconTextPosition = st.itemIconPosition + + st::menuIconTTLAnyTextPosition; + const auto addAction = [&](const QString &text, TimeId ttl) { + auto item = base::make_unique_q( + menu, + st, + Ui::Menu::CreateAction( + menu->menu().get(), + text, + [=] { args.callback(ttl); }), + &st::menuIconTTLAny, + &st::menuIconTTLAny); + item->setData(Ui::FormatTTLTiny(ttl), iconTextPosition); + menu->addAction(std::move(item)); + }; + addAction(tr::lng_manage_messages_ttl_after1(tr::now), kTTLDurSeconds1); + addAction(tr::lng_manage_messages_ttl_after2(tr::now), kTTLDurSeconds2); + addAction(tr::lng_manage_messages_ttl_after3(tr::now), kTTLDurSeconds3); + addAction(tr::lng_manage_messages_ttl_after4(tr::now), kTTLDurSeconds4); + + menu->addAction( + tr::lng_manage_messages_ttl_after_custom(tr::now), + [a = args] { a.show->showBox(Box(TTLBox, a.callback, a.startTtl)); }, + &st::menuIconCustomize); + + if (args.startTtl) { + const auto disable = menu->addAction( + tr::lng_manage_messages_ttl_never(tr::now), + [=] { args.callback(0); }, + &st::menuIconDisableAttention); + disable->setData(st::menuIconAttentionColor->c); + } + + menu->addSeparator(); + + menu->addAction(base::make_unique_q( + menu, + menu->st().menu, + std::move(args.about))); +} + +void SetupTTLMenu( + not_null parent, + rpl::producer<> triggers, + Args args) { + struct State { + base::unique_qptr menu; + }; + const auto state = parent->lifetime().make_state(); + std::move( + triggers + ) | rpl::start_with_next([=] { + if (state->menu) { + return; + } + state->menu = base::make_unique_q( + parent, + st::popupMenuExpandedSeparator); + FillTTLMenu(state->menu.get(), args); + state->menu->popup(QCursor::pos()); + }, parent->lifetime()); +} + +} // namespace TTLMenu diff --git a/Telegram/SourceFiles/menu/menu_ttl.h b/Telegram/SourceFiles/menu/menu_ttl.h new file mode 100644 index 000000000..a1f5e0f78 --- /dev/null +++ b/Telegram/SourceFiles/menu/menu_ttl.h @@ -0,0 +1,32 @@ +/* +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 + +namespace Ui { +class PopupMenu; +class RpWidget; +class Show; +} // namespace Ui + +namespace TTLMenu { + +struct Args { + std::shared_ptr show; + TimeId startTtl; + rpl::producer about; + Fn callback; +}; + +void FillTTLMenu(not_null menu, Args args); + +void SetupTTLMenu( + not_null parent, + rpl::producer<> triggers, + Args args); + +} // namespace TTLMenu diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index cec6daac7..6987ada8c 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -319,6 +319,12 @@ historyMessagesTTL2Icon: icon {{ "chat/input_autodelete_7d", historyComposeIconF historyMessagesTTL2IconOver: icon {{ "chat/input_autodelete_7d", historyComposeIconFgOver }}; historyMessagesTTL3Icon: icon {{ "chat/input_autodelete_30d", historyComposeIconFg }}; historyMessagesTTL3IconOver: icon {{ "chat/input_autodelete_30d", historyComposeIconFgOver }}; +historyMessagesTTLLabel: FlatLabel(defaultFlatLabel) { + minWidth: 200px; + align: align(topleft); + textFg: windowSubTextFg; +} + historyAttachEmojiFgActive: windowBgActive; historyAttachEmojiActive: icon {{ "chat/input_smile_face", historyAttachEmojiFgActive }}; historyAttachEmojiTooltipDelta: 4px; @@ -881,6 +887,13 @@ ttlDividerLabelPadding: margins(22px, 10px, 22px, 19px); ttlItemPadding: margins(0px, 4px, 0px, 4px); ttlItemTimerFont: font(12px); +popupMenuExpandedSeparator: PopupMenu(popupMenuWithIcons) { + menu: Menu(menuWithIcons) { + separatorPadding: margins(0px, 4px, 0px, 4px); + separatorWidth: 6px; + } +} + WhoRead { userpics: GroupCallUserpics; photoLeft: pixels; @@ -904,13 +917,9 @@ defaultWhoRead: WhoRead { iconPosition: point(15px, 7px); itemPadding: margins(44px, 9px, 17px, 7px); } -whoReadMenu: PopupMenu(popupMenuWithIcons) { +whoReadMenu: PopupMenu(popupMenuExpandedSeparator) { scrollPadding: margins(0px, 6px, 0px, 4px); maxHeight: 400px; - menu: Menu(menuWithIcons) { - separatorPadding: margins(0px, 4px, 0px, 4px); - separatorWidth: 6px; - } } whoReadChecks: icon{{ "menu/read_ticks", windowBoldFg }}; whoReadChecksOver: icon{{ "menu/read_ticks", windowBoldFg }}; diff --git a/Telegram/SourceFiles/ui/menu_icons.style b/Telegram/SourceFiles/ui/menu_icons.style index 2c1a73c37..f2f95e0c8 100644 --- a/Telegram/SourceFiles/ui/menu_icons.style +++ b/Telegram/SourceFiles/ui/menu_icons.style @@ -96,6 +96,11 @@ menuIconPorn: icon {{ "menu/porn", menuIconColor }}; menuIconViolence: icon {{ "menu/violence", menuIconColor }}; menuIconMuteFor: icon {{ "menu/mute_for", menuIconColor }}; menuIconSilent: icon {{ "menu/silent", menuIconColor }}; +menuIconCustomize: icon {{ "menu/customize", menuIconColor }}; + +menuIconTTLAny: icon {{ "menu/auto_delete_plain", menuIconColor }}; +menuIconTTLAnyTextPosition: point(11px, 22px); +menuIconTTL: icon {{ "menu/auto_delete", menuIconColor }}; mediaMenuIconStickers: icon {{ "menu/stickers", mediaviewMenuFg }}; mediaMenuIconCancel: icon {{ "menu/cancel", mediaviewMenuFg }}; @@ -112,3 +117,4 @@ menuIconStartStreamWith: icon {{ "menu/start_stream_with", menuIconColor }}; menuIconDeleteAttention: icon {{ "menu/delete", menuIconAttentionColor }}; menuIconLeaveAttention: icon {{ "menu/leave", menuIconAttentionColor }}; +menuIconDisableAttention: icon {{ "menu/disable", menuIconAttentionColor }}; diff --git a/Telegram/SourceFiles/ui/text/format_values.cpp b/Telegram/SourceFiles/ui/text/format_values.cpp index a34cf46b0..01199b248 100644 --- a/Telegram/SourceFiles/ui/text/format_values.cpp +++ b/Telegram/SourceFiles/ui/text/format_values.cpp @@ -384,4 +384,16 @@ QString FormatPhone(const QString &phone) { return Countries::Instance().format({ .phone = phone }).formatted; } +QString FormatTTLTiny(float64 ttl) { + return (ttl <= 3600 * 9) + ? tr::lng_hours_tiny(tr::now, lt_count, std::ceil(ttl / 3600)) + : (ttl <= (86400) * 6) + ? tr::lng_days_tiny(tr::now, lt_count, std::ceil(ttl / (86400))) + : (ttl <= (86400 * 7) * 3) + ? tr::lng_weeks_tiny(tr::now, lt_count, std::ceil(ttl / (86400 * 7))) + : (ttl <= (86400 * 30) * 11) + ? tr::lng_months_tiny({}, lt_count, std::ceil(ttl / (86400 * 30))) + : tr::lng_years_tiny({}, lt_count, std::ceil(ttl / (86400 * 360))); +} + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/text/format_values.h b/Telegram/SourceFiles/ui/text/format_values.h index 56b0d1c78..6f33b9f8b 100644 --- a/Telegram/SourceFiles/ui/text/format_values.h +++ b/Telegram/SourceFiles/ui/text/format_values.h @@ -27,6 +27,7 @@ inline constexpr auto FileStatusSizeFailed = 0x7FFFFFF2; [[nodiscard]] QString FormatPlayedText(qint64 played, qint64 duration); [[nodiscard]] QString FormatImageSizeText(const QSize &size); [[nodiscard]] QString FormatPhone(const QString &phone); +[[nodiscard]] QString FormatTTLTiny(float64 ttl); struct CurrencyRule { const char *international = ""; diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index 31643282a..eec6b9e76 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -104,6 +104,8 @@ PRIVATE menu/menu_check_item.cpp menu/menu_check_item.h + menu/menu_ttl.cpp + menu/menu_ttl.h passport/ui/passport_details_row.cpp passport/ui/passport_details_row.h