From eff90395b66a73abbdf2c2041ebc6a05ce4a8338 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 8 Jan 2019 14:54:18 +0400 Subject: [PATCH] Add EditPeerPermissionsBox. --- Telegram/Resources/icons/info_permissions.png | Bin 0 -> 672 bytes .../Resources/icons/info_permissions@2x.png | Bin 0 -> 1390 bytes .../Resources/icons/info_permissions@3x.png | Bin 0 -> 2133 bytes Telegram/Resources/langs/lang.strings | 10 +- Telegram/SourceFiles/apiwrap.cpp | 33 ++++ Telegram/SourceFiles/apiwrap.h | 8 + Telegram/SourceFiles/boxes/abstract_box.h | 9 +- Telegram/SourceFiles/boxes/boxes.style | 5 +- .../boxes/peers/edit_participant_box.cpp | 128 +++++--------- .../boxes/peers/edit_participant_box.h | 9 +- .../boxes/peers/edit_peer_permissions_box.cpp | 163 +++++++++++++++++- .../boxes/peers/edit_peer_permissions_box.h | 25 +++ .../boxes/peers/manage_peer_box.cpp | 130 ++++++++++---- .../SourceFiles/boxes/peers/manage_peer_box.h | 22 +++ Telegram/SourceFiles/data/data_channel.cpp | 2 +- Telegram/SourceFiles/data/data_session.cpp | 7 +- Telegram/SourceFiles/info/info.style | 23 ++- Telegram/SourceFiles/mainwidget.cpp | 23 ++- Telegram/SourceFiles/ui/widgets/widgets.style | 8 + .../SourceFiles/ui/wrap/vertical_layout.cpp | 6 +- 20 files changed, 469 insertions(+), 142 deletions(-) create mode 100644 Telegram/Resources/icons/info_permissions.png create mode 100644 Telegram/Resources/icons/info_permissions@2x.png create mode 100644 Telegram/Resources/icons/info_permissions@3x.png diff --git a/Telegram/Resources/icons/info_permissions.png b/Telegram/Resources/icons/info_permissions.png new file mode 100644 index 0000000000000000000000000000000000000000..37d5e44d0dd59d2e67dd43879e5dd8afc4d6e62a GIT binary patch literal 672 zcmV;R0$=@!P)9DlWwz=-?p!fLiEK5J3kKL_|dg-Te!sWDGcW zQ$ZI+(JeYzWhGPVW6g3LymO7vs-w78m0z;NKRY(P&UC z7DGJGqxE`?Hk%FV_xmUwkK=pC2K;1%LLrcgWHNaSw{ii2K!B94)oNh3+d-?9 z*laeaR4U|tB9Ty608P_`{Pp$q+q{>T7m}yZXw(xBi9|4ItJRXt6}uxwEEZEw0LO8d z^#1;yU@n&nR;v{(mrHQF-2@jujTk)7t0!QwSYT44(MT|{xD@mGoZvd04x@q~e9Nc! z7y|tL>7XczU>_eJWWC*P$y&;hp4k_Q1qgzGXT4reu*b(oG#Cu<2#3Q2XIU1{@9*!2 zU+UOVE|*EGDTgoy{4hM8P9g-gm2Icq<7x#EPgiI77;eNkg){4K1{gD8x)k?^6xg5d2x?!PE zfL^Z$)9Dmuvl+a-z2U+#Z9h(cD$A3z$qMnBM2};p>Zw3p`sa7K{&vLp)cjRk*&s zK1l$*&zU3(Wf%qpgF)18w^6s-MI6Ur++Z*unx@fiw^M4Q$2sBi^Yg*umCxr-ZM*y? ze0q9<@pz2eol2#^>-9pT(Ez8@sb+CF|1&xZ_|F9(ggybhx15w(RHq>T0000npoa96v-XigH`cFu9M3&9z*XcakV6mz2CxUdS7l|G-->+@f3~ccTeqvA3kA<%Rnu zq1=k5QRmn9DcbWqXS3PmdGy<-PIjJs&v)PN=bZCB=lgx)gAl^#KZfuB>^#6r01s^7 z6kY;&U<0S{62Jo+IE9x09@xMs{PniNYinzEJI=($#s-dyi~E}d zq^73g>+9=ZJO72Jrzf0~lk>L-0O!qSGtr@$nHgMFRfUt2lW}lxFb)a|!ikBAxV*d^ zPfSc$CBg+Hc*c35P>8Rtu2>Gt&CTJ2goGc*i$o$kJv~ia2~KVY&k(S@yv#CwXlTe` zJp%&+EIkktcuhcEU7bsuw?#s0Yb$>V*xK5n8N0Hw;ctX zu)n`gGg6^Y5al*EH(AbqVRdztI7T9o(B#g~&-q6H^X!McOOi90OjZeaetss72?+_I z$-TV1IBcKC(_tSUAL8@R&rhpk%x1IO>~T8*x3{;nzECJ6%Bj_At2#C}H;K<9BO_`3 z`}=!`?Q=T;dcB_3mrA8Xx$f?6ba!{hdJZ*#o}M1!7==PX>mMB*Ic%R>2@s3LsIah* z_DmoU5M|HLZ@baWJ5TwI{Dvoka}I7m5ZG#ZIxYHDg|{ofW$+!FjkLqoAvt7QeW z%*;%e=!c_`iJvZ59z6w?mX=rsj*N`BOg~(wEwR15{aanGcYbVajO9Gs-Cd<0h-3m1 zE?y7-SsoKAmC9xMhlht*`WF@!oYCnz=j-e1S;ie49N_TqaI0g)Vlj20`AK&{K>@Lj zcye-rBO)TWCx8@`p!OFZA5WBzjg7@>wfb8YuEJeiU0A79;ezm&yOWPIXOuML0B>U{ryyF zORv{cOB~(=0hx`Bjm`!-*Avjx)WmWI0@+XFNGrfvtng5C{D4`RBrI~jCo&JUtj+_1Tah7fSQ^bqO9fV zU@#cI>w(3^#kBEzdwYL_0A_&`+lcru^CUo#lZoEmUj7pRk(dd1p=nJX&S`rATZH!n zFw;+1wt<0xHpf7c@)IC)ette}jAey*XJ-eux3_cc zy!`|~;$e*d$ORyhe?|1Kpvb)Ve13jX@BRY<0{Gy#V+6p<2}{5WkM#6(oRyVDyxT(> z3^zGT93CF>$#KUBAO%53(bw1acL_jNjzN0?tAvNnJ4OIBNM5XAe0&@)E-tdZg#xL) z*JR!k0Ii{+fy(+IszZa%wY9b1-$U?&d;uyt5cGKJIMuxWGsFWMIE9x09@xMsyae#T w22SB6fCn~k3NHaXuz^!}3E+VZ+yNo<56zY5SZZ(XHUIzs07*qoM6N<$f|GERNdN!< literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/info_permissions@3x.png b/Telegram/Resources/icons/info_permissions@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e6929d15478602ee282d0799b1f0794beaff4549 GIT binary patch literal 2133 zcmaKuX*3&(62}w7QhP&62p6@qf}~MeOQP1M6>F=u+G>rZvDMP1a+SEqL+P~?p>e6D zT(tzPR*R}?Eze$SYAL05(h$qb{rt{*A7{U}c zPW1T4_<1>gE;s5D0KhMcHNA2px?t^gz*UH~tlVPb1zbmp=6RIQ-f)dXp0H4y2^vxlfJC$6tI*85&< z7$ErBeTTlx7~iGCUa17J_Nyk+@fY{-&p?QX}E6?;FukS>kly>;_uD7LbyN+~$X(J@zHG9Vy;wX@W3JgF1aw+>+( zAFgwp&VM)?e z)B8mRF`4I#XWtUvXaO3U;O}e(*AMUiTJH@yX8!y-PXtm8VvLFVCP^aFbdbqVU!lH? z6(7t%xORCd0NCEqk=Gc{lTcLOS;T-Jd^$%l<{7 zm~zs}GRS}GX@O%k&jto;p1pbT0&e1?%{?Z7@a`5{+1cI>^PHeigd|`v4T^5Wvdxq1 zY!%AKo~)bZC_*9N=wPn|owQ~u4$*W~E40SrD-j~<)(+CW?;^Ppl9KF;#zsa2hPpaC zuP!Osr+Uig@s9h^Pf@p1{PFnAw8`;tH41nBzP7fmF5CV~+)nM6OtbQeif7Q3iN-1f zx00L4g;1x9g?m1^zpwI?S60%{8?$X~2#vsD;||We389X#STnQ42()6e6{)W7!phEL zC5ux-Tos%HmF#*QxeDp&>w|Qqrlz89nAa0VOeu}fn2j03id}@@TOwO0T=Cw~L8Pp> zxPs5>`$v2?WGX5u9NyO7@3zKbJx}N4=c@;+s;T`k&gs(CPc`hYE<%4eqvh6F@7JGA z2UbzxBvkGa52^RAoKDaB1k(_$8VUwBcaJ}5+F9t&*G*^F zv43sodW(_^eLr&@UB_YtnhXXkC%TjB7gEXjOMQh|bkO`kHk#)+O&;T>rx9^XJLcQ` z-Yau@OcO2p2C0rlQ{j>ciHWvxTIbGP0jpSM)csjhl>Yro-cH+6ZF1QDwojd_jgwO{ zJ}~f8csF=->)WzjSXkZgpm}8E#cNos!eSjbZRBBg6E~p1+Y|lU9aRj*-7)+KWZCTf zdESpee&FvMovR&?8Q7gv_NmYJIj$B1o*9SANQF$`(6RvFiOuu#%3;PNkRXKM4t2oz z{4`1mJj2*b%G&|eoH5d#yG&q^8mftGCUUI+6GvrHpdcYk_3joD9Hd_^tVErfa{azx zW@hHUI$Ax*G&VLa@0Wo>ZG3%IV%bcM?fnO8NaSPI8bt~j&*F>xF__rN-kRsz3X9&F z16}^>wyP^;Wpx$TnzvVL<}~WddyJx!ODxQPDyyoZ)?nxdjsY4>l;d4(b@f!NLwGpq z@|J&>=4!JYk@yButQ<7cnm2h`RarTYF6@poG2tH3WIf?+1<;hxg!8uEC4T+XPLadX zqldf8ww1xnT8hOWQnG~T$21stV*KTuj~IxD_Yl*FH_-9^xAw$$l7OeY)a#cTrWIvS zzF&&Vj&^?xVR}btW~t>{6!=_>6=23`rl;pxg?K-QaxLy+t}sA}D#W4MSu&Sv^WNjy z1*oX25<@FU&v+#S_$q3nue7)ORm!p;0~n$k@O*)-YQ)(~R}XlhXK>nWNTdtYT11H|L;<(+?w4)Tf0SrX-7FkIupSQO+ zLj2`F&(bWA=G(wfw3X%~ordN2h=Y>`N0v;A``x8J6rz>t|%tTJVk=XOh2 zB1bsZ%5eGScubW%YkM(u>}r!aX>GE}UZA6zzW1Ve8lk0SEodZ2P|gKAzVu3jkR(mP z$T-iAX`z|ZfcDbsIYD5L(HBn6fV_;XEG69eDd%pNR_@k^M^7Vqr*WzPoHv_@!()LU``(j=*;qH3G}*gL*kmXwW`d#fPlb)4XT;>-keoo z{~T_3XBD)3QdTK-Ab;t9itGQ;-2tw09^+-*c~ZQ?&G?hYoOc0$HM26UG4_c64{hc0 A>Hq)$ literal 0 HcmV?d00001 diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 39429cab79..062cd87a66 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -789,6 +789,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_manage_peer_administrators" = "Administrators"; "lng_manage_peer_banned_users" = "Banned users"; "lng_manage_peer_restricted_users" = "Restricted users"; +"lng_manage_peer_exceptions" = "Exceptions"; +"lng_manage_peer_removed_users" = "Removed users"; +"lng_manage_peer_permissions" = "Permissions"; "lng_manage_history_visibility_title" = "Chat history for new members"; "lng_manage_history_visibility_shown" = "Visible"; "lng_manage_history_visibility_shown_about" = "New members will see messages that were sent before they joined."; @@ -1472,7 +1475,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_rights_about_add_admins_no" = "This admin will not be able to add new admins."; "lng_rights_about_admin_cant_edit" = "You cannot edit rights of this admin."; "lng_rights_user_restrictions" = "User restrictions"; -"lng_rights_user_restrictions_header" = "What can this user do?"; +"lng_rights_user_restrictions_header" = "What can this member do?"; +"lng_rights_default_restrictions_header" = "What can members of this group do?"; "lng_rights_channel_info" = "Change channel info"; "lng_rights_channel_post" = "Post messages"; @@ -1490,6 +1494,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_rights_chat_send_media" = "Send media"; "lng_rights_chat_send_stickers" = "Send stickers & GIFs"; "lng_rights_chat_send_links" = "Embed links"; +"lng_rights_chat_send_polls" = "Send polls"; +"lng_rights_chat_add_members" = "Add members"; "lng_rights_chat_banned_until_header" = "Restricted until"; "lng_rights_chat_banned_forever" = "Forever"; "lng_rights_chat_banned_day#one" = "For {count} day"; @@ -1586,7 +1592,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_admin_log_admin_edit_messages" = "Edit messages"; "lng_admin_log_admin_delete_messages" = "Delete messages"; "lng_admin_log_admin_ban_users" = "Ban users"; -"lng_admin_log_admin_invite_users" = "Add users"; +"lng_admin_log_admin_invite_users" = "Add members"; "lng_admin_log_admin_invite_link" = "Invite users via link"; "lng_admin_log_admin_pin_messages" = "Pin messages"; "lng_admin_log_admin_add_admins" = "Add new admins"; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index bc22e6ed07..9cdc5dc837 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -1636,6 +1636,39 @@ void ApiWrap::unblockParticipant( _kickRequests.emplace(kick, requestId); } +void ApiWrap::saveDefaultRestrictions( + not_null peer, + const MTPChatBannedRights &rights, + Fn callback) { + if (_defaultRestrictionsRequests.contains(peer)) { + return; + } + const auto requestId = request(MTPmessages_EditChatDefaultBannedRights( + peer->input, + rights + )).done([=](const MTPUpdates &result) { + _defaultRestrictionsRequests.erase(peer); + applyUpdates(result); + if (callback) { + callback(true); + } + }).fail([=](const RPCError &error) { + _defaultRestrictionsRequests.erase(peer); + if (error.type() == qstr("CHAT_NOT_MODIFIED")) { + if (const auto chat = peer->asChat()) { + chat->setDefaultRestrictions(rights); + if (callback) { + callback(true); + } + return; + } + } + if (callback) { + callback(false); + } + }).send(); +} + void ApiWrap::deleteAllFromUser( not_null channel, not_null from) { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 220a091141..9aa727b4b8 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -156,6 +156,10 @@ public: void deleteAllFromUser( not_null channel, not_null from); + void saveDefaultRestrictions( + not_null peer, + const MTPChatBannedRights &rights, + Fn callback = nullptr); void requestWebPageDelayed(WebPageData *page); void clearWebPageRequest(WebPageData *page); @@ -610,6 +614,10 @@ private: not_null>; base::flat_map _kickRequests; + base::flat_map< + not_null, + mtpRequestId> _defaultRestrictionsRequests; + QMap _selfParticipantRequests; base::flat_map< diff --git a/Telegram/SourceFiles/boxes/abstract_box.h b/Telegram/SourceFiles/boxes/abstract_box.h index 45561451d0..9bef60992f 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.h +++ b/Telegram/SourceFiles/boxes/abstract_box.h @@ -103,11 +103,14 @@ public: void clearButtons() { getDelegate()->clearButtons(); } - QPointer addButton(Fn textFactory, Fn clickCallback); - QPointer addLeftButton(Fn textFactory, Fn clickCallback); - QPointer addTopButton(const style::IconButton &st, Fn clickCallback) { + QPointer addButton(Fn textFactory, Fn clickCallback = nullptr); + QPointer addLeftButton(Fn textFactory, Fn clickCallback = nullptr); + QPointer addTopButton(const style::IconButton &st, Fn clickCallback = nullptr) { return getDelegate()->addTopButton(st, std::move(clickCallback)); } + QPointer addButton(Fn textFactory, const style::RoundButton &st) { + return getDelegate()->addButton(std::move(textFactory), nullptr, st); + } QPointer addButton(Fn textFactory, Fn clickCallback, const style::RoundButton &st) { return getDelegate()->addButton(std::move(textFactory), std::move(clickCallback), st); } diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index fa5bcf3246..6fdf278683 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -699,7 +699,8 @@ rightsToggle: Toggle(defaultToggle) { duration: 120; } rightsDividerHeight: 10px; -rightsHeaderMargin: margins(23px, 20px, 23px, 8px); +rightsDividerMargin: margins(0px, 0px, 0px, 20px); +rightsHeaderMargin: margins(23px, 0px, 23px, 8px); rightsToggleMargin: margins(23px, 8px, 23px, 8px); rightsAboutMargin: margins(23px, 8px, 23px, 8px); rightsPhotoButton: UserpicButton(defaultUserpicButton) { @@ -722,7 +723,7 @@ rightsHeaderLabel: FlatLabel(boxLabel) { } textFg: windowActiveTextFg; } -rightsUntilMargin: margins(0px, 8px, 0px, 0px); +rightsUntilMargin: margins(0px, 8px, 0px, 20px); mutePhotoButton: UserpicButton(defaultUserpicButton) { size: size(40px, 40px); diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp index b33669d9c6..7f0e09ba00 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp @@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/peers/edit_participant_box.h" #include "lang/lang_keys.h" +#include "ui/wrap/vertical_layout.h" +#include "ui/wrap/padding_wrap.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" @@ -28,7 +30,7 @@ constexpr auto kSecondsInWeek = 7 * kSecondsInDay; } // namespace -class EditParticipantBox::Inner : public TWidget { +class EditParticipantBox::Inner : public Ui::RpWidget { public: Inner( QWidget *parent, @@ -37,27 +39,19 @@ public: bool hasAdminRights); template - QPointer addControl(object_ptr widget, QMargins margin); - - void removeControl(QPointer widget); + Widget *addControl(object_ptr widget, QMargins margin); protected: int resizeGetHeight(int newWidth) override; void paintEvent(QPaintEvent *e) override; private: - void doAddControl(object_ptr widget, QMargins margin); - not_null _channel; not_null _user; object_ptr _userPhoto; Text _userName; bool _hasAdminRights = false; - struct Control { - object_ptr widget; - QMargins margin; - }; - std::vector _rows; + object_ptr _rows; }; @@ -66,7 +60,7 @@ EditParticipantBox::Inner::Inner( not_null channel, not_null user, bool hasAdminRights) -: TWidget(parent) +: RpWidget(parent) , _channel(channel) , _user(user) , _userPhoto( @@ -74,7 +68,13 @@ EditParticipantBox::Inner::Inner( _user, Ui::UserpicButton::Role::Custom, st::rightsPhotoButton) -, _hasAdminRights(hasAdminRights) { +, _hasAdminRights(hasAdminRights) +, _rows(this) { + _rows->heightValue( + ) | rpl::start_with_next([=] { + resizeToWidth(width()); + }, lifetime()); + _userPhoto->setPointerCursor(false); _userName.setText( st::rightsNameStyle, @@ -82,44 +82,23 @@ EditParticipantBox::Inner::Inner( Ui::NameTextOptions()); } -void EditParticipantBox::Inner::removeControl(QPointer widget) { - auto row = ranges::find(_rows, widget, &Control::widget); - Assert(row != _rows.end()); - row->widget.destroy(); - _rows.erase(row); -} - template -QPointer EditParticipantBox::Inner::addControl( +Widget *EditParticipantBox::Inner::addControl( object_ptr widget, QMargins margin) { - doAddControl(std::move(widget), margin); - return static_cast(_rows.back().widget.data()); -} - -void EditParticipantBox::Inner::doAddControl( - object_ptr widget, - QMargins margin) { - widget->setParent(this); - _rows.push_back({ std::move(widget), margin }); - _rows.back().widget->show(); + return _rows->add(std::move(widget), margin); } int EditParticipantBox::Inner::resizeGetHeight(int newWidth) { _userPhoto->moveToLeft( st::rightsPhotoMargin.left(), st::rightsPhotoMargin.top()); - auto newHeight = st::rightsPhotoMargin.top() + const auto rowsTop = st::rightsPhotoMargin.top() + st::rightsPhotoButton.size.height() + st::rightsPhotoMargin.bottom(); - for (auto &&row : _rows) { - auto rowWidth = newWidth - row.margin.left() - row.margin.right(); - newHeight += row.margin.top(); - row.widget->resizeToNaturalWidth(rowWidth); - row.widget->moveToLeft(row.margin.left(), newHeight); - newHeight += row.widget->heightNoMargins() + row.margin.bottom(); - } - return newHeight; + _rows->resizeToWidth(newWidth); + _rows->moveToLeft(0, rowsTop, newWidth); + return rowsTop + _rows->heightNoMargins(); } void EditParticipantBox::Inner::paintEvent(QPaintEvent *e) { @@ -173,10 +152,11 @@ void EditParticipantBox::prepare() { _channel, _user, hasAdminRights())); + setDimensionsToContent(st::boxWideWidth, _inner); } template -QPointer EditParticipantBox::addControl( +Widget *EditParticipantBox::addControl( object_ptr widget, QMargins margin) { Expects(_inner != nullptr); @@ -184,19 +164,6 @@ QPointer EditParticipantBox::addControl( return _inner->addControl(std::move(widget), margin); } -void EditParticipantBox::removeControl(QPointer widget) { - Expects(_inner != nullptr); - - return _inner->removeControl(widget); -} - -void EditParticipantBox::resizeToContent() { - _inner->resizeToWidth(st::boxWideWidth); - setDimensions( - _inner->width(), - qMin(_inner->height(), st::boxMaxListHeight)); -} - EditAdminBox::EditAdminBox( QWidget*, not_null channel, @@ -235,7 +202,9 @@ void EditAdminBox::prepare() { ? lng_rights_edit_admin : lng_channel_add_admin)); - addControl(object_ptr(this), QMargins()); + addControl( + object_ptr(this), + st::rightsDividerMargin); const auto prepareRights = hadRights ? _oldRights : Defaults(channel()); const auto filterByMyRights = canSave() @@ -290,8 +259,6 @@ void EditAdminBox::prepare() { } else { addButton(langFactory(lng_box_ok), [this] { closeBox(); }); } - - resizeToContent(); } void EditAdminBox::refreshAboutAddAdminsText(bool canAddAdmins) { @@ -303,7 +270,6 @@ void EditAdminBox::refreshAboutAddAdminsText(bool canAddAdmins) { } return lang(lng_rights_about_add_admins_no); }()); - resizeToContent(); } EditRestrictedBox::EditRestrictedBox( @@ -321,14 +287,21 @@ void EditRestrictedBox::prepare() { setTitle(langFactory(lng_rights_user_restrictions)); - addControl(object_ptr(this), QMargins()); + addControl( + object_ptr(this), + st::rightsDividerMargin); const auto prepareRights = _oldRights.c_chatBannedRights().vflags.v ? _oldRights : Defaults(channel()); - const auto disabledFlags = canSave() ? Flags(0) : ~Flags(0); + const auto disabledFlags = canSave() + ? (channel()->defaultRestrictions() + /*| (channel()->isPublic() + ? (Flag::f_change_info | Flag::f_pin_messages) + : Flags(0))*/) // #TODO groups + : ~Flags(0); - auto [checkboxes, getChecked, changes] = CreateEditRestrictions( + auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions( this, lng_rights_user_restrictions_header, prepareRights.c_chatBannedRights().vflags.v, @@ -353,7 +326,7 @@ void EditRestrictedBox::prepare() { // st::boxLinkButton)); if (canSave()) { - addButton(langFactory(lng_settings_save), [=, value = getChecked] { + const auto save = [=, value = getRestrictions] { if (!_saveCallback) { return; } @@ -362,13 +335,12 @@ void EditRestrictedBox::prepare() { MTP_chatBannedRights( MTP_flags(value()), MTP_int(getRealUntilValue()))); - }); + }; + addButton(langFactory(lng_settings_save), save); addButton(langFactory(lng_cancel), [=] { closeBox(); }); } else { addButton(langFactory(lng_box_ok), [=] { closeBox(); }); } - - resizeToContent(); } MTPChatBannedRights EditRestrictedBox::Defaults( @@ -411,22 +383,15 @@ void EditRestrictedBox::setRestrictUntil(TimeId until) { if (_restrictUntilBox) { _restrictUntilBox->closeBox(); } - clearVariants(); + _untilVariants.clear(); createUntilGroup(); createUntilVariants(); - resizeToContent(); } bool EditRestrictedBox::isUntilForever() const { return ChannelData::IsRestrictedForever(_until); } -void EditRestrictedBox::clearVariants() { - for (auto &&widget : base::take(_untilVariants)) { - removeControl(widget.data()); - } -} - void EditRestrictedBox::createUntilGroup() { _untilGroup = std::make_shared( isUntilForever() ? 0 : _until); @@ -445,14 +410,15 @@ void EditRestrictedBox::createUntilVariants() { if (!canSave() && _untilGroup->value() != value) { return; } - _untilVariants.push_back(addControl( - object_ptr( - this, - _untilGroup, - value, - text, - st::defaultBoxCheckbox), - st::rightsToggleMargin)); + _untilVariants.push_back(base::unique_qptr( + addControl( + object_ptr( + this, + _untilGroup, + value, + text, + st::defaultBoxCheckbox), + st::rightsToggleMargin))); if (!canSave()) { _untilVariants.back()->setDisabled(true); } diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.h b/Telegram/SourceFiles/boxes/peers/edit_participant_box.h index 400af983d0..b3235a7882 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "boxes/abstract_box.h" +#include "base/unique_qptr.h" namespace Ui { class FlatLabel; @@ -30,8 +31,6 @@ public: protected: void prepare() override; - void resizeToContent(); - not_null user() const { return _user; } @@ -40,9 +39,7 @@ protected: } template - QPointer addControl(object_ptr widget, QMargins margin); - - void removeControl(QPointer widget); + Widget *addControl(object_ptr widget, QMargins margin = {}); bool hasAdminRights() const { return _hasAdminRights; @@ -134,7 +131,7 @@ private: Fn _saveCallback; std::shared_ptr _untilGroup; - QVector> _untilVariants; + std::vector> _untilVariants; QPointer _restrictUntilBox; static constexpr auto kUntilOneDay = -1; diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp index 0e70da5125..f0a2e06594 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp @@ -8,10 +8,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/peers/edit_peer_permissions_box.h" #include "lang/lang_keys.h" +#include "data/data_channel.h" +#include "data/data_chat.h" #include "ui/wrap/vertical_layout.h" #include "ui/widgets/labels.h" #include "ui/widgets/checkbox.h" +#include "info/profile/info_profile_button.h" +#include "info/profile/info_profile_icon.h" +#include "info/profile/info_profile_values.h" +#include "profile/profile_channel_controllers.h" +#include "boxes/peers/manage_peer_box.h" +#include "window/window_controller.h" +#include "mainwindow.h" #include "styles/style_boxes.h" +#include "styles/style_info.h" namespace { @@ -71,7 +81,6 @@ std::vector> RestrictionLabels() { using Flag = ChatRestriction; return { - { Flag::f_view_messages, lng_rights_chat_read }, { Flag::f_send_messages, lng_rights_chat_send_text }, { Flag::f_send_media, lng_rights_chat_send_media }, { Flag::f_send_stickers @@ -79,6 +88,10 @@ std::vector> RestrictionLabels() { | Flag::f_send_games | Flag::f_send_inline, lng_rights_chat_send_stickers }, { Flag::f_embed_links, lng_rights_chat_send_links }, + { Flag::f_send_polls, lng_rights_chat_send_polls }, + { Flag::f_invite_users, lng_rights_chat_add_members }, + { Flag::f_pin_messages, lng_rights_group_pin }, + { Flag::f_change_info, lng_rights_group_info }, }; } @@ -133,9 +146,12 @@ auto Dependencies(ChatRestrictions) // embed_links -> send_media { Flag::f_embed_links, Flag::f_send_media }, - // send_media- > send_messages + // send_media -> send_messages { Flag::f_send_media, Flag::f_send_messages }, + // send_polls -> send_messages + { Flag::f_send_polls, Flag::f_send_messages }, + // send_messages -> view_messages { Flag::f_send_messages, Flag::f_view_messages }, }; @@ -145,6 +161,8 @@ ChatRestrictions NegateRestrictions(ChatRestrictions value) { using Flag = ChatRestriction; return (~value) & (Flag(0) + // view_messages is always allowed, so it is never in restrictions. + //| Flag::f_view_messages | Flag::f_change_info | Flag::f_embed_links | Flag::f_invite_users @@ -155,8 +173,7 @@ ChatRestrictions NegateRestrictions(ChatRestrictions value) { | Flag::f_send_media | Flag::f_send_messages | Flag::f_send_polls - | Flag::f_send_stickers - | Flag::f_view_messages); + | Flag::f_send_stickers); } auto Dependencies(ChatAdminRights) @@ -164,8 +181,146 @@ auto Dependencies(ChatAdminRights) return {}; } +auto ToPositiveNumberString() { + return rpl::map([](int count) { + return count ? QString::number(count) : QString(); + }); +} + +ChatRestrictions DisabledByAdminRights(not_null peer) { + using Flag = ChatRestriction; + using Flags = ChatRestrictions; + using Admin = ChatAdminRight; + using Admins = ChatAdminRights; + + const auto adminRights = [&] { + const auto full = ~Admins(0); + if (const auto chat = peer->asChat()) { + return chat->amCreator() ? full : chat->adminRights(); + } else if (const auto channel = peer->asChannel()) { + return channel->amCreator() ? full : channel->adminRights(); + } + Unexpected("User in DisabledByAdminRights."); + }(); + return Flag(0) + | ((adminRights & Admin::f_pin_messages) + ? Flag(0) + : Flag::f_pin_messages) + | ((adminRights & Admin::f_invite_users) + ? Flag(0) + : Flag::f_invite_users) + | ((adminRights & Admin::f_change_info) + ? Flag(0) + : Flag::f_change_info); +} + } // namespace +EditPeerPermissionsBox::EditPeerPermissionsBox( + QWidget*, + not_null peer) +: _peer(peer) { +} + +auto EditPeerPermissionsBox::saveEvents() const +-> rpl::producer { + Expects(_save != nullptr); + + return _save->clicks() | rpl::map(_value); +} + +void EditPeerPermissionsBox::prepare() { + setTitle(langFactory(lng_manage_peer_permissions)); + + const auto inner = setInnerWidget(object_ptr(this)); + + using Flag = ChatRestriction; + using Flags = ChatRestrictions; + + const auto disabledByAdminRights = DisabledByAdminRights(_peer); + const auto restrictions = [&] { + if (const auto chat = _peer->asChat()) { + return chat->defaultRestrictions() + /*| disabledByAdminRights*/; // #TODO groups + } else if (const auto channel = _peer->asChannel()) { + return (channel->defaultRestrictions() + /*| (channel->isPublic() + ? (Flag::f_change_info | Flag::f_pin_messages) + : Flags(0)) + | disabledByAdminRights*/); // #TODO groups + } + Unexpected("User in EditPeerPermissionsBox."); + }(); + const auto disabledFlags = [&] { + if (const auto chat = _peer->asChat()) { + return Flags(0) + | disabledByAdminRights; + } else if (const auto channel = _peer->asChannel()) { + return (channel->isPublic() + ? (Flag::f_change_info | Flag::f_pin_messages) + : Flags(0)) + | disabledByAdminRights; + } + Unexpected("User in EditPeerPermissionsBox."); + }(); + + auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions( + this, + lng_rights_default_restrictions_header, + restrictions, + disabledFlags); + + inner->add(std::move(checkboxes)); + + if (const auto channel = _peer->asChannel()) { + addBannedButtons(inner, channel); + } + + _value = getRestrictions; + _save = addButton(langFactory(lng_settings_save)); + addButton(langFactory(lng_cancel), [=] { closeBox(); }); + + setDimensionsToContent(st::boxWidth, inner); +} + +void EditPeerPermissionsBox::addBannedButtons( + not_null container, + not_null channel) { + using Profile::ParticipantsBoxController; + + container->add( + object_ptr(container), + { 0, st::infoProfileSkip, 0, st::infoProfileSkip }); + + const auto navigation = App::wnd()->controller(); + ManagePeerBox::CreateButton( + container, + Lang::Viewer(lng_manage_peer_exceptions), + Info::Profile::RestrictedCountValue(channel) + | ToPositiveNumberString(), + [=] { + ParticipantsBoxController::Start( + navigation, + channel, + ParticipantsBoxController::Role::Restricted); + }, + st::peerPermissionsButton, + st::infoIconRestrictedUsers); + ManagePeerBox::CreateButton( + container, + Lang::Viewer(lng_manage_peer_removed_users), + Info::Profile::KickedCountValue(channel) + | ToPositiveNumberString(), + [=] { + ParticipantsBoxController::Start( + navigation, + channel, + ParticipantsBoxController::Role::Kicked); + }, + st::peerPermissionsButton, + st::infoIconBlacklist); +} + template EditFlagsControl CreateEditFlags( QWidget *parent, diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h index 100ded2690..488c100a4f 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h @@ -10,8 +10,33 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/abstract_box.h" #include "data/data_peer.h" +namespace Ui { +class RoundButton; +class VerticalLayout; +} // namespace Ui + enum LangKey : int; +class EditPeerPermissionsBox : public BoxContent { +public: + EditPeerPermissionsBox(QWidget*, not_null peer); + + rpl::producer saveEvents() const; + +protected: + void prepare() override; + +private: + void addBannedButtons( + not_null container, + not_null channel); + + not_null _peer; + Ui::RoundButton *_save = nullptr; + Fn _value; + +}; + template struct EditFlagsControl { object_ptr widget; diff --git a/Telegram/SourceFiles/boxes/peers/manage_peer_box.cpp b/Telegram/SourceFiles/boxes/peers/manage_peer_box.cpp index d0d1d04242..fd587a1c72 100644 --- a/Telegram/SourceFiles/boxes/peers/manage_peer_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/manage_peer_box.cpp @@ -15,13 +15,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "history/admin_log/history_admin_log_section.h" #include "window/window_controller.h" -#include "mainwindow.h" #include "profile/profile_channel_controllers.h" #include "info/profile/info_profile_button.h" #include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_values.h" #include "data/data_channel.h" #include "data/data_chat.h" +#include "mainwindow.h" +#include "auth_session.h" +#include "apiwrap.h" #include "styles/style_boxes.h" #include "styles/style_info.h" @@ -39,51 +41,33 @@ auto ToPositiveNumberString() { }); } -template Info::Profile::Button *AddButton( not_null parent, rpl::producer &&text, - Callback callback, + Fn callback, const style::icon &icon) { - auto button = parent->add( - object_ptr( - parent, - std::move(text), - st::managePeerButton)); - button->addClickHandler(std::forward(callback)); - Ui::CreateChild( - button, - icon, - st::managePeerButtonIconPosition); - return button; + return ManagePeerBox::CreateButton( + parent, + std::move(text), + rpl::single(QString()), + std::move(callback), + st::managePeerButton, + icon); } -template void AddButtonWithCount( not_null parent, rpl::producer &&text, rpl::producer &&count, - Callback callback, + Fn callback, const style::icon &icon) { - auto button = AddButton( + ManagePeerBox::CreateButton( parent, std::move(text), - std::forward(callback), - icon); - auto label = Ui::CreateChild( - button, std::move(count), - st::managePeerButtonLabel); - label->setAttribute(Qt::WA_TransparentForMouseEvents); - rpl::combine( - button->widthValue(), - label->widthValue() - ) | rpl::start_with_next([label](int outerWidth, int width) { - label->moveToRight( - st::managePeerButtonLabelPosition.x(), - st::managePeerButtonLabelPosition.y(), - outerWidth); - }, label->lifetime()); + std::move(callback), + st::managePeerButton, + icon); } bool HasRecentActions(not_null channel) { @@ -112,6 +96,24 @@ bool HasEditInfoBox(not_null peer) { return false; } +void ShowEditPermissions(not_null peer) { + const auto box = Ui::show( + Box(peer), + LayerOption::KeepOther); + box->saveEvents( + ) | rpl::start_with_next([=](MTPDchatBannedRights::Flags restrictions) { + const auto callback = crl::guard(box, [=](bool success) { + if (success) { + box->closeBox(); + } + }); + Auth().api().saveDefaultRestrictions( + peer, + MTP_chatBannedRights(MTP_flags(restrictions), MTP_int(0)), + callback); + }, box->lifetime()); +} + void FillManageChatBox( not_null navigation, not_null chat, @@ -123,6 +125,13 @@ void FillManageChatBox( [=] { Ui::show(Box(chat)); }, st::infoIconInformation); } + if (chat->canEditPermissions()) { + AddButton( + content, + Lang::Viewer(lng_manage_peer_permissions), + [=] { ShowEditPermissions(chat); }, + st::infoIconPermissions); + } if (chat->amIn()) { AddButtonWithCount( content, @@ -174,6 +183,13 @@ void FillManageChannelBox( [=] { ShowRecentActions(navigation, channel); }, st::infoIconRecentActions); } + if (channel->canEditPermissions()) { + AddButton( + content, + Lang::Viewer(lng_manage_peer_permissions), + [=] { ShowEditPermissions(channel); }, + st::infoIconPermissions); + } if (channel->canViewAdmins()) { AddButtonWithCount( content, @@ -202,6 +218,20 @@ void FillManageChannelBox( }, st::infoIconMembers); } + if (!channel->isMegagroup()) { + AddButtonWithCount( + content, + Lang::Viewer(lng_manage_peer_removed_users), + Info::Profile::KickedCountValue(channel) + | ToPositiveNumberString(), + [=] { + ParticipantsBoxController::Start( + navigation, + channel, + ParticipantsBoxController::Role::Kicked); + }, + st::infoIconBlacklist); + } } } // namespace @@ -236,6 +266,42 @@ bool ManagePeerBox::Available(not_null peer) { } } +Info::Profile::Button *ManagePeerBox::CreateButton( + not_null parent, + rpl::producer &&text, + rpl::producer &&count, + Fn callback, + const style::InfoProfileCountButton &st, + const style::icon &icon) { + const auto button = parent->add( + object_ptr( + parent, + std::move(text), + st.button)); + button->addClickHandler(callback); + Ui::CreateChild( + button, + icon, + st.iconPosition); + const auto label = Ui::CreateChild( + button, + std::move(count), + st.label); + label->setAttribute(Qt::WA_TransparentForMouseEvents); + + rpl::combine( + button->widthValue(), + label->widthValue() + ) | rpl::start_with_next([=, &st](int outerWidth, int width) { + label->moveToRight( + st.labelPosition.x(), + st.labelPosition.y(), + outerWidth); + }, label->lifetime()); + + return button; +} + void ManagePeerBox::prepare() { _peer->updateFull(); diff --git a/Telegram/SourceFiles/boxes/peers/manage_peer_box.h b/Telegram/SourceFiles/boxes/peers/manage_peer_box.h index 37ee7722cf..93cecc5353 100644 --- a/Telegram/SourceFiles/boxes/peers/manage_peer_box.h +++ b/Telegram/SourceFiles/boxes/peers/manage_peer_box.h @@ -9,12 +9,34 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/abstract_box.h" +namespace style { +struct InfoProfileCountButton; +} // namespace style + +namespace Ui { +class VerticalLayout; +} // namespace Ui + +namespace Info { +namespace Profile { +class Button; +} // namespace Profile +} // namespace Info + class ManagePeerBox : public BoxContent { public: ManagePeerBox(QWidget*, not_null peer); static bool Available(not_null peer); + static Info::Profile::Button *CreateButton( + not_null parent, + rpl::producer &&text, + rpl::producer &&count, + Fn callback, + const style::InfoProfileCountButton &st, + const style::icon &icon); + protected: void prepare() override; diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index 5816e3249a..2d6cecee56 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -357,7 +357,7 @@ bool ChannelData::canEditInformation() const { } bool ChannelData::canEditPermissions() const { - return (hasAdminRights() || amCreator()); + return isMegagroup() && (hasAdminRights() || amCreator()); } bool ChannelData::canEditSignatures() const { diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 65bf500005..b555d36160 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -446,7 +446,8 @@ not_null Session::chat(const MTPChat &data) { : MTPChatAdminRights(MTP_chatAdminRights(MTP_flags(0)))); chat->setDefaultRestrictions(data.has_default_banned_rights() ? data.vdefault_banned_rights - : MTPChatBannedRights(MTP_chatBannedRights(MTP_flags(0), MTP_int(0)))); + : MTPChatBannedRights( + MTP_chatBannedRights(MTP_flags(0), MTP_int(0)))); const auto &migratedTo = data.has_migrated_to() ? data.vmigrated_to @@ -535,6 +536,10 @@ not_null Session::chat(const MTPChat &data) { if (data.has_participants_count()) { channel->setMembersCount(data.vparticipants_count.v); } + channel->setDefaultRestrictions(data.has_default_banned_rights() + ? data.vdefault_banned_rights + : MTPChatBannedRights( + MTP_chatBannedRights(MTP_flags(0), MTP_int(0)))); if (minimal) { auto mask = 0 | MTPDchannel::Flag::f_broadcast diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index 8521c30a7e..fd88ed4fae 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -362,6 +362,7 @@ infoIconRecentActions: icon {{ "info_recent_actions", infoIconFg }}; infoIconAdministrators: icon {{ "info_administrators", infoIconFg }}; infoIconBlacklist: icon {{ "info_blacklist", infoIconFg }}; infoIconRestrictedUsers: icon {{ "info_restricted_users", infoIconFg }}; +infoIconPermissions: icon {{ "info_permissions", infoIconFg }}; infoInformationIconPosition: point(25px, 12px); infoNotificationsIconPosition: point(20px, 5px); infoSharedMediaIconPosition: point(20px, 24px); @@ -578,15 +579,23 @@ infoChannelsList: PeerList(infoCommonGroupsList) { } } -managePeerButton: InfoProfileButton(infoProfileButton) { - padding: margins(76px, 12px, 76px, 10px); +managePeerButton: InfoProfileCountButton { + button: InfoProfileButton(infoProfileButton) { + padding: margins(76px, 12px, 76px, 10px); + } + iconPosition: point(20px, 5px); + label: FlatLabel(defaultFlatLabel) { + textFg: windowActiveTextFg; + style: semiboldTextStyle; + } + labelPosition: point(25px, 12px); } -managePeerButtonIconPosition: point(20px, 5px); -managePeerButtonLabel: FlatLabel(defaultFlatLabel) { - textFg: windowActiveTextFg; - style: semiboldTextStyle; +peerPermissionsButton: InfoProfileCountButton(managePeerButton) { + button: InfoProfileButton(infoProfileButton) { + padding: margins(67px, 12px, 67px, 10px); + } + iconPosition: point(24px, 5px); } -managePeerButtonLabelPosition: point(25px, 11px); terminateSessionsButton: InfoProfileButton(infoBlockButton) { padding: margins(23px, 12px, 23px, 10px); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 57ac62f45e..ba57a13831 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -4226,7 +4226,28 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { App::feedParticipantDelete(update.c_updateChatParticipantDelete()); } break; - // #TODO groups new update + case mtpc_updateChatDefaultBannedRights: { + const auto &data = update.c_updateChatDefaultBannedRights(); + const auto peerId = peerFromMTP(data.vpeer); + if (const auto peer = Auth().data().peerLoaded(peerId)) { + if (const auto chat = peer->asChat()) { + if (data.vversion.v == chat->version + 1) { + chat->setDefaultRestrictions( + data.vdefault_banned_rights); + } else { + chat->version = data.vversion.v; + chat->invalidateParticipants(); + Auth().api().requestPeer(chat); + } + } else if (const auto channel = peer->asChannel()) { + channel->setDefaultRestrictions( + data.vdefault_banned_rights); + } else { + LOG(("API Error: " + "User received in updateChatDefaultBannedRights.")); + } + } + } break; case mtpc_updateChatParticipantAdmin: { App::feedParticipantAdmin(update.c_updateChatParticipantAdmin()); diff --git a/Telegram/SourceFiles/ui/widgets/widgets.style b/Telegram/SourceFiles/ui/widgets/widgets.style index a22acdc96a..b9511979ac 100644 --- a/Telegram/SourceFiles/ui/widgets/widgets.style +++ b/Telegram/SourceFiles/ui/widgets/widgets.style @@ -527,6 +527,14 @@ InfoProfileButton { ripple: RippleAnimation; } +InfoProfileCountButton { + button: InfoProfileButton; + icon: icon; + iconPosition: point; + label: FlatLabel; + labelPosition: point; +} + PassportScanRow { padding: margins; size: pixels; diff --git a/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp b/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp index c44786ccac..bda6e224be 100644 --- a/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp +++ b/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp @@ -36,11 +36,13 @@ QMargins VerticalLayout::getMargins() const { int VerticalLayout::naturalWidth() const { auto result = 0; for (auto &row : _rows) { - auto natural = row.widget->naturalWidth(); + const auto natural = row.widget->naturalWidth(); if (natural < 0) { return natural; } - accumulate_max(result, natural); + accumulate_max( + result, + row.margin.left() + natural + row.margin.right()); } return result; }