/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. This code is in Public Domain, see license terms in .github/CONTRIBUTING.md Copyright (C) 2017, Nicholas Guriev */ #include "boxes/mute_settings_box.h" #include "kotato/kotato_lang.h" #include "lang/lang_keys.h" #include "base/event_filter.h" #include "main/main_session.h" #include "data/data_session.h" #include "data/data_peer.h" #include "ui/special_buttons.h" #include "ui/widgets/dropdown_menu.h" #include "ui/widgets/input_fields.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/labels.h" #include "styles/style_layers.h" #include "styles/style_boxes.h" namespace { constexpr auto kForeverHours = 24 * 365; constexpr auto kForeverSeconds = kForeverHours * 3600; constexpr auto kCustomFor = kForeverHours - 1; } // namespace MuteSettingsBox::MuteSettingsBox(QWidget *parent, not_null peer) : _peer(peer) , _forNumberInput(this, st::scheduleDateField) , _forPeriodInput(this, st::scheduleDateField) { } void MuteSettingsBox::prepare() { setTitle(tr::lng_disable_notifications_from_tray()); auto y = 0; object_ptr info(this, st::boxLabel); info->setText(tr::lng_mute_box_tip(tr::now)); info->moveToLeft(st::boxPadding.left(), y); y += info->height() + st::boxLittleSkip; const auto icon = object_ptr( this, _peer, Ui::UserpicButton::Role::Custom, st::mutePhotoButton); icon->setPointerCursor(false); icon->moveToLeft(st::boxPadding.left(), y); object_ptr title(this, st::muteChatTitle); title->setText(_peer->name); title->moveToLeft( st::boxPadding.left() + st::muteChatTitleLeft, y + (icon->height() / 2) - (title->height() / 2)); // the icon is always higher than this chat title y += icon->height() + st::boxMediumSkip; // in fact, this is mute only for 1 year const auto group = std::make_shared(kForeverHours); y += st::boxOptionListPadding.top(); const auto makePeriodText = [=, this] (Period period) { const auto currentValue = _forNumberInput->getLastText().toInt(); switch (period) { case Period::Second: return ktr("ktg_notifications_mute_seconds", currentValue); case Period::Minute: return ktr("ktg_notifications_mute_minutes", currentValue); case Period::Hour: return ktr("ktg_notifications_mute_hours", currentValue); case Period::Day: return ktr("ktg_notifications_mute_days", currentValue); default: return QString(); } }; // Prefill input values, default is 1 hour _forNumberInput->setText("1"); _forPeriodInput->setText(makePeriodText(_period)); for (const auto hours : { kCustomFor, kForeverHours }) { const auto text = [&] { if (hours == kCustomFor) { return ktr("ktg_mute_for_selected_time"); } else { return tr::lng_mute_duration_forever(tr::now); } }(); object_ptr option(this, group, hours, text); option->moveToLeft(st::boxPadding.left(), y); y += option->heightNoMargins() + st::boxOptionListSkip; if (hours == kCustomFor) { const auto fieldLeft = st::boxPadding.left() + st::autolockButton.margin.left() + st::autolockButton.margin.right() + st::defaultToggle.width + st::defaultToggle.border * 2; _forNumberInput->resizeToWidth(st::scheduleTimeWidth); _forNumberInput->moveToLeft(fieldLeft, y); _forPeriodInput->resizeToWidth(st::scheduleDateWidth); _forPeriodInput->moveToLeft(fieldLeft + st::scheduleTimeWidth + st::scheduleAtSkip, y); y += _forNumberInput->heightNoMargins() + st::boxOptionListSkip; } } group->setChangedCallback([this] (int hours) { if (hours == kCustomFor) { _forNumberInput->setFocus(); } else { _forNumberInput->clearFocus(); } }); y += st::boxOptionListPadding.bottom() - st::boxOptionListSkip + st::defaultCheckbox.margin.bottom(); _forNumberInput->customTab(true); _forNumberInput->documentContentsChanges( ) | rpl::start_with_next([=](const auto &value) { _forNumberInput->hideError(); _forPeriodInput->setText(makePeriodText(_period)); }, _lifetime); QObject::connect(_forNumberInput, &Ui::InputField::focused, [=] { if (group->value() != kCustomFor) { group->setValue(kCustomFor); } }); _forPeriodInput->rawTextEdit()->setTextInteractionFlags(Qt::NoTextInteraction); const auto &forPeriodViewport = _forPeriodInput->rawTextEdit()->viewport(); base::install_event_filter(forPeriodViewport, [=](not_null event) { switch (event->type()) { case QEvent::Leave: if (_menu) { _menu->hideAnimated(); } return base::EventFilterResult::Cancel; case QEvent::ContextMenu: case QEvent::MouseButtonDblClick: return base::EventFilterResult::Cancel; case QEvent::MouseButtonPress: if (group->value() != kCustomFor) { group->setValue(kCustomFor); } _forNumberInput->setFocus(); if (_menu) { _menu->hideAnimated(Ui::InnerDropdown::HideOption::IgnoreShow); return base::EventFilterResult::Cancel; } _menu = base::make_unique_q(window()); const auto weak = _menu.get(); _menu->setHiddenCallback([=] { weak->deleteLater(); }); for (const auto period : { Period::Second, Period::Minute, Period::Hour, Period::Day }) { const auto periodStr = makePeriodText(period); _menu->addAction(periodStr, [=] { _period = period; _forPeriodInput->setText(periodStr); }); } const auto parentTopLeft = window()->mapToGlobal(QPoint()); const auto inputTopLeft = _forPeriodInput->mapToGlobal(QPoint()); const auto parentRect = QRect(parentTopLeft, window()->size()); const auto inputRect = QRect(inputTopLeft, _forPeriodInput->size()); _menu->move( inputRect.x() + inputRect.width() + st::boxPadding.left() - _menu->width() - parentRect.x(), inputRect.y() + inputRect.height() - parentRect.y()); _menu->showAnimated(Ui::PanelAnimation::Origin::TopRight); return base::EventFilterResult::Cancel; } return base::EventFilterResult::Continue; }); _save = [=] { const auto muteForSeconds = (group->value() == kCustomFor) ? _forNumberInput->getLastText().toInt() * int(_period) : group->value() * 3600; if (muteForSeconds <= 0 || muteForSeconds > kForeverSeconds) { _forNumberInput->showError(); } else { _peer->owner().updateNotifySettings( _peer, muteForSeconds); closeBox(); } }; addButton(tr::lng_box_ok(), _save); addButton(tr::lng_cancel(), [this] { closeBox(); }); setDimensions(st::boxWidth, y); } void MuteSettingsBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { if (_save) { _save(); } } } // vi: ts=4 tw=80