1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4 
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #include "passport/passport_panel_form.h"
9 
10 #include "passport/passport_panel_controller.h"
11 #include "passport/ui/passport_form_row.h"
12 #include "lang/lang_keys.h"
13 #include "boxes/abstract_box.h"
14 #include "core/click_handler_types.h"
15 #include "data/data_user.h"
16 #include "ui/effects/animations.h"
17 #include "ui/widgets/shadow.h"
18 #include "ui/widgets/buttons.h"
19 #include "ui/widgets/scroll_area.h"
20 #include "ui/widgets/labels.h"
21 #include "ui/widgets/box_content_divider.h"
22 #include "ui/wrap/vertical_layout.h"
23 #include "ui/wrap/fade_wrap.h"
24 #include "ui/wrap/padding_wrap.h"
25 #include "ui/text/text_utilities.h"
26 #include "ui/text/text_options.h"
27 #include "ui/special_buttons.h"
28 #include "styles/style_passport.h"
29 #include "styles/style_layers.h"
30 #include "styles/style_boxes.h"
31 
32 namespace Passport {
33 
PanelForm(QWidget * parent,not_null<PanelController * > controller)34 PanelForm::PanelForm(
35 	QWidget *parent,
36 	not_null<PanelController*> controller)
37 : RpWidget(parent)
38 , _controller(controller)
39 , _scroll(this, st::passportPanelScroll)
40 , _topShadow(this)
41 , _bottomShadow(this)
42 , _submit(
43 		this,
44 		tr::lng_passport_authorize(),
45 		st::passportPanelAuthorize) {
46 	setupControls();
47 }
48 
setupControls()49 void PanelForm::setupControls() {
50 	const auto inner = setupContent();
51 
52 	_submit->addClickHandler([=] {
53 		_controller->submitForm();
54 	});
55 
56 	using namespace rpl::mappers;
57 
58 	_topShadow->toggleOn(
59 		_scroll->scrollTopValue() | rpl::map(_1 > 0));
60 	_bottomShadow->toggleOn(rpl::combine(
61 		_scroll->scrollTopValue(),
62 		_scroll->heightValue(),
63 		inner->heightValue(),
64 		_1 + _2 < _3));
65 }
66 
setupContent()67 not_null<Ui::RpWidget*> PanelForm::setupContent() {
68 	const auto bot = _controller->bot();
69 
70 	const auto inner = _scroll->setOwnedWidget(
71 		object_ptr<Ui::VerticalLayout>(this));
72 	_scroll->widthValue(
73 	) | rpl::start_with_next([=](int width) {
74 		inner->resizeToWidth(width);
75 	}, inner->lifetime());
76 
77 	const auto userpicWrap = inner->add(
78 		object_ptr<Ui::FixedHeightWidget>(
79 			inner,
80 			st::passportFormUserpic.size.height()),
81 		st::passportFormUserpicPadding);
82 	_userpic = Ui::AttachParentChild(
83 		userpicWrap,
84 		object_ptr<Ui::UserpicButton>(
85 			userpicWrap,
86 			bot,
87 			Ui::UserpicButton::Role::Custom,
88 			st::passportFormUserpic));
89 	userpicWrap->widthValue(
90 	) | rpl::start_with_next([=](int width) {
91 		_userpic->move((width - _userpic->width()) / 2, _userpic->y());
92 	}, _userpic->lifetime());
93 
94 	_about1 = inner->add(
95 		object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
96 			inner,
97 			object_ptr<Ui::FlatLabel>(
98 				inner,
99 				tr::lng_passport_request1(tr::now, lt_bot, bot->name),
100 				st::passportPasswordLabelBold)),
101 		st::passportFormAbout1Padding)->entity();
102 
103 	_about2 = inner->add(
104 		object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
105 			inner,
106 			object_ptr<Ui::FlatLabel>(
107 				inner,
108 				tr::lng_passport_request2(tr::now),
109 				st::passportPasswordLabel)),
110 		st::passportFormAbout2Padding)->entity();
111 
112 	inner->add(object_ptr<Ui::BoxContentDivider>(
113 		inner,
114 		st::passportFormDividerHeight));
115 	inner->add(
116 		object_ptr<Ui::FlatLabel>(
117 			inner,
118 			tr::lng_passport_header(tr::now),
119 			st::passportFormHeader),
120 		st::passportFormHeaderPadding);
121 
122 	auto index = 0;
123 	_controller->fillRows([&](
124 			QString title,
125 			QString description,
126 			bool ready,
127 			bool error) {
128 		_rows.push_back(inner->add(object_ptr<Row>(this)));
129 		_rows.back()->addClickHandler([=] {
130 			_controller->editScope(index);
131 		});
132 		_rows.back()->updateContent(
133 			title,
134 			description,
135 			ready,
136 			error,
137 			anim::type::instant);
138 		++index;
139 	});
140 	_controller->refillRows(
141 	) | rpl::start_with_next([=] {
142 		auto index = 0;
143 		_controller->fillRows([&](
144 				QString title,
145 				QString description,
146 				bool ready,
147 				bool error) {
148 			Expects(index < _rows.size());
149 
150 			_rows[index++]->updateContent(
151 				title,
152 				description,
153 				ready,
154 				error,
155 				anim::type::normal);
156 		});
157 	}, lifetime());
158 	const auto policyUrl = _controller->privacyPolicyUrl();
159 	auto text = policyUrl.isEmpty()
160 		? tr::lng_passport_allow(
161 			lt_bot,
162 			rpl::single('@' + bot->username)
163 		) | Ui::Text::ToWithEntities()
164 		: tr::lng_passport_accept_allow(
165 			lt_policy,
166 			tr::lng_passport_policy(
167 				lt_bot,
168 				rpl::single(bot->name)
169 			) | Ui::Text::ToLink(policyUrl),
170 			lt_bot,
171 			rpl::single('@' + bot->username) | Ui::Text::ToWithEntities(),
172 			Ui::Text::WithEntities);
173 	const auto policy = inner->add(
174 		object_ptr<Ui::FlatLabel>(
175 			inner,
176 			std::move(text),
177 			st::passportFormPolicy),
178 		st::passportFormPolicyPadding);
179 	policy->setLinksTrusted();
180 
181 	return inner;
182 }
183 
resizeEvent(QResizeEvent * e)184 void PanelForm::resizeEvent(QResizeEvent *e) {
185 	updateControlsGeometry();
186 }
187 
updateControlsGeometry()188 void PanelForm::updateControlsGeometry() {
189 	const auto submitTop = height() - _submit->height();
190 	_scroll->setGeometry(0, 0, width(), submitTop);
191 	_topShadow->resizeToWidth(width());
192 	_topShadow->moveToLeft(0, 0);
193 	_bottomShadow->resizeToWidth(width());
194 	_bottomShadow->moveToLeft(0, submitTop - st::lineWidth);
195 	_submit->setFullWidth(width());
196 	_submit->moveToLeft(0, submitTop);
197 
198 	_scroll->updateBars();
199 }
200 
201 } // namespace Passport
202