2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-09-05 08:55:59 +00:00

Initial frozen accounts support.

This commit is contained in:
John Preston
2025-03-10 17:52:13 +04:00
parent 7f53a19647
commit d9b270b477
29 changed files with 481 additions and 39 deletions

View File

@@ -11,38 +11,48 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h" // History::session
#include "history/history_item.h" // HistoryItem::originalText
#include "history/history_item_helpers.h" // DropDisallowedCustomEmoji
#include "base/unixtime.h"
#include "base/qthelp_regex.h"
#include "base/qthelp_url.h"
#include "base/event_filter.h"
#include "ui/chat/chat_style.h"
#include "ui/layers/generic_box.h"
#include "ui/basic_click_handlers.h"
#include "ui/rect.h"
#include "core/shortcuts.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "core/ui_integration.h"
#include "lottie/lottie_icon.h"
#include "info/profile/info_profile_icon.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h"
#include "ui/widgets/shadow.h"
#include "ui/power_saving.h"
#include "ui/vertical_list.h"
#include "ui/ui_utility.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "data/data_document.h"
#include "data/stickers/data_custom_emoji.h"
#include "chat_helpers/emoji_suggestions_widget.h"
#include "history/view/controls/compose_controls_common.h"
#include "window/window_session_controller.h"
#include "lang/lang_keys.h"
#include "mainwindow.h"
#include "main/main_session.h"
#include "settings/settings_common.h"
#include "settings/settings_premium.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_chat.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_credits.h"
#include "styles/style_dialogs.h"
#include "styles/style_menu_icons.h"
#include "styles/style_settings.h"
#include "base/qt/qt_common_adapters.h"
@@ -1187,10 +1197,10 @@ base::unique_qptr<Ui::RpWidget> CreateDisabledFieldView(
return result;
}
base::unique_qptr<Ui::RpWidget> TextErrorSendRestriction(
std::unique_ptr<Ui::RpWidget> TextErrorSendRestriction(
QWidget *parent,
const QString &text) {
auto result = base::make_unique_q<Ui::RpWidget>(parent);
auto result = std::make_unique<Ui::RpWidget>(parent);
const auto raw = result.get();
const auto label = CreateChild<Ui::FlatLabel>(
result.get(),
@@ -1215,11 +1225,11 @@ base::unique_qptr<Ui::RpWidget> TextErrorSendRestriction(
return result;
}
base::unique_qptr<Ui::RpWidget> PremiumRequiredSendRestriction(
std::unique_ptr<Ui::RpWidget> PremiumRequiredSendRestriction(
QWidget *parent,
not_null<UserData*> user,
not_null<Window::SessionController*> controller) {
auto result = base::make_unique_q<Ui::RpWidget>(parent);
auto result = std::make_unique<Ui::RpWidget>(parent);
const auto raw = result.get();
const auto label = CreateChild<Ui::FlatLabel>(
result.get(),
@@ -1254,6 +1264,196 @@ base::unique_qptr<Ui::RpWidget> PremiumRequiredSendRestriction(
return result;
}
std::unique_ptr<Ui::AbstractButton> BoostsToLiftWriteRestriction(
not_null<QWidget*> parent,
std::shared_ptr<ChatHelpers::Show> show,
not_null<PeerData*> peer,
int boosts) {
auto result = std::make_unique<Ui::FlatButton>(
parent,
tr::lng_restricted_boost_group(tr::now),
st::historyComposeButton);
result->setClickedCallback([=] {
const auto window = show->resolveWindow();
window->resolveBoostState(peer->asChannel(), boosts);
});
return result;
}
std::unique_ptr<Ui::AbstractButton> FrozenWriteRestriction(
not_null<QWidget*> parent,
std::shared_ptr<ChatHelpers::Show> show,
FrozenWriteRestrictionType type,
FreezeInfoStyleOverride st) {
using namespace Ui;
auto result = std::make_unique<FlatButton>(
parent,
QString(),
st::historyComposeButton);
const auto raw = result.get();
const auto bar = (type == FrozenWriteRestrictionType::DialogsList);
const auto title = CreateChild<FlatLabel>(
raw,
(bar ? tr::lng_frozen_bar_title : tr::lng_frozen_restrict_title)(
tr::now),
bar ? st::frozenBarTitle : st::frozenRestrictionTitle);
title->setAttribute(Qt::WA_TransparentForMouseEvents);
title->show();
const auto subtitle = CreateChild<FlatLabel>(
raw,
(bar
? tr::lng_frozen_bar_text(
lt_arrow,
rpl::single(Ui::Text::IconEmoji(&st::textMoreIconEmoji)),
Ui::Text::WithEntities)
: tr::lng_frozen_restrict_text(Ui::Text::WithEntities)),
bar ? st::frozenBarSubtitle : st::frozenRestrictionSubtitle);
subtitle->setAttribute(Qt::WA_TransparentForMouseEvents);
subtitle->show();
const auto shadow = bar ? CreateChild<PlainShadow>(raw) : nullptr;
const auto icon = bar ? CreateChild<RpWidget>(raw) : nullptr;
if (icon) {
icon->paintRequest() | rpl::start_with_next([=] {
auto p = QPainter(icon);
st::menuIconDisableAttention.paintInCenter(p, icon->rect());
}, icon->lifetime());
icon->show();
}
raw->sizeValue() | rpl::start_with_next([=](QSize size) {
if (bar) {
const auto toggle = [&](auto &&widget, bool shown) {
if (widget->isHidden() == shown) {
widget->setVisible(shown);
}
};
const auto small = 2 * st::defaultDialogRow.photoSize;
const auto shown = (size.width() > small);
toggle(icon, !shown);
toggle(title, shown);
toggle(subtitle, shown);
icon->setGeometry(0, 0, size.width(), size.height());
}
const auto skip = bar
? st::defaultDialogRow.padding.left()
: 2 * st::normalFont->spacew;
const auto available = size.width() - skip * 2;
title->resizeToWidth(available);
subtitle->resizeToWidth(available);
const auto height = title->height() + subtitle->height();
const auto top = (size.height() - height) / 2;
title->moveToLeft(skip, top, size.width());
subtitle->moveToLeft(skip, top + title->height(), size.width());
const auto line = st::lineWidth;
if (shadow) {
shadow->setGeometry(0, size.height() - line, size.width(), line);
}
}, title->lifetime());
const auto info = show->session().frozen();
const auto detailsBox = [=](not_null<GenericBox*> box) {
box->setWidth(st::boxWideWidth);
box->setStyle(st::frozenInfoBox);
box->setNoContentMargin(true);
box->addTopButton(st::boxTitleClose, [=] {
box->closeBox();
});
const auto content = box->verticalLayout();
auto icon = Settings::CreateLottieIcon(
content,
{
.name = u"media_forbidden"_q,
.sizeOverride = {
st::changePhoneIconSize,
st::changePhoneIconSize,
},
},
st::settingLocalPasscodeIconPadding);
content->add(std::move(icon.widget));
box->setShowFinishedCallback([animate = std::move(icon.animate)] {
animate(anim::repeat::once);
});
Ui::AddSkip(content);
const auto infoRow = [&](
rpl::producer<QString> title,
rpl::producer<TextWithEntities> text,
not_null<const style::icon*> icon) {
auto raw = content->add(
object_ptr<Ui::VerticalLayout>(content));
raw->add(
object_ptr<Ui::FlatLabel>(
raw,
std::move(title) | Ui::Text::ToBold(),
st.infoTitle ? *st.infoTitle : st::defaultFlatLabel),
st::settingsPremiumRowTitlePadding);
raw->add(
object_ptr<Ui::FlatLabel>(
raw,
std::move(text),
st.infoAbout ? *st.infoAbout : st::upgradeGiftSubtext),
st::settingsPremiumRowAboutPadding);
object_ptr<Info::Profile::FloatingIcon>(
raw,
*icon,
st::starrefInfoIconPosition);
};
content->add(
object_ptr<Ui::FlatLabel>(
content,
tr::lng_frozen_title(),
st.title ? *st.title : st::uniqueGiftTitle),
st::settingsPremiumRowTitlePadding);
Ui::AddSkip(content, st::defaultVerticalListSkip * 3);
infoRow(
tr::lng_frozen_subtitle1(),
tr::lng_frozen_text1(Text::WithEntities),
st.violationIcon ? st.violationIcon : &st::menuIconBlock);
infoRow(
tr::lng_frozen_subtitle2(),
tr::lng_frozen_text2(Text::WithEntities),
st.readOnlyIcon ? st.readOnlyIcon : &st::menuIconLock);
infoRow(
tr::lng_frozen_subtitle3(),
tr::lng_frozen_text3(
lt_link,
rpl::single(Text::Link(u"@SpamBot"_q, info.appealUrl)),
lt_date,
rpl::single(TextWithEntities{
langDayOfMonthFull(
base::unixtime::parse(info.until).date()),
}),
Text::WithEntities),
st.appealIcon ? st.appealIcon : &st::menuIconHourglass);
const auto button = box->addButton(
tr::lng_frozen_appeal_button(),
[url = info.appealUrl] { UrlClickHandler::Open(url); });
const auto buttonPadding = st::frozenInfoBox.buttonPadding;
const auto buttonWidth = st::boxWideWidth
- buttonPadding.left()
- buttonPadding.right();
button->widthValue() | rpl::filter([=] {
return (button->widthNoMargins() != buttonWidth);
}) | rpl::start_with_next([=] {
button->resizeToWidth(buttonWidth);
}, button->lifetime());
};
raw->setClickedCallback([=] {
show->show(Box(detailsBox));
});
return result;
}
void SelectTextInFieldWithMargins(
not_null<Ui::InputField*> field,
const TextSelection &selection) {