From d93c1ccbaa0dc4ad07a3260b6162e67e6b165f5a Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 21 Nov 2017 13:20:56 +0400 Subject: [PATCH] Improve compile time. --- Telegram/SourceFiles/auth_session.cpp | 132 ++++ Telegram/SourceFiles/auth_session.h | 136 +---- Telegram/SourceFiles/base/observer.cpp | 11 + Telegram/SourceFiles/base/observer.h | 12 +- Telegram/SourceFiles/boxes/photo_crop_box.cpp | 4 + Telegram/SourceFiles/boxes/photo_crop_box.h | 4 +- .../SourceFiles/data/data_peer_values.cpp | 126 ++++ Telegram/SourceFiles/data/data_peer_values.h | 108 +--- .../info_common_groups_inner_widget.cpp | 4 + .../info_common_groups_inner_widget.h | 4 +- Telegram/SourceFiles/info/info_controller.cpp | 8 + Telegram/SourceFiles/info/info_controller.h | 8 +- .../SourceFiles/info/info_wrap_widget.cpp | 4 + Telegram/SourceFiles/info/info_wrap_widget.h | 4 +- .../info/media/info_media_inner_widget.cpp | 4 + .../info/media/info_media_inner_widget.h | 4 +- .../info/media/info_media_list_widget.cpp | 9 + .../info/media/info_media_list_widget.h | 9 +- .../info/profile/info_profile_cover.cpp | 5 + .../info/profile/info_profile_cover.h | 5 +- .../profile/info_profile_inner_widget.cpp | 8 + .../info/profile/info_profile_inner_widget.h | 9 +- .../info/profile/info_profile_members.cpp | 4 + .../info/profile/info_profile_members.h | 4 +- Telegram/SourceFiles/observer_peer.cpp | 31 + Telegram/SourceFiles/observer_peer.h | 37 +- .../profile/profile_block_actions.cpp | 377 ------------ .../profile/profile_block_actions.h | 98 --- .../profile/profile_block_channel_members.cpp | 174 ------ .../profile/profile_block_channel_members.h | 67 -- .../profile/profile_block_info.cpp | 265 -------- .../SourceFiles/profile/profile_block_info.h | 80 --- .../profile/profile_block_invite_link.cpp | 118 ---- .../profile/profile_block_invite_link.h | 55 -- .../profile/profile_block_settings.cpp | 270 --------- .../profile/profile_block_settings.h | 73 --- .../profile/profile_block_shared_media.cpp | 211 ------- .../profile/profile_block_shared_media.h | 71 --- .../profile/profile_channel_controllers.cpp | 4 + .../profile/profile_channel_controllers.h | 4 +- .../profile/profile_common_groups_section.cpp | 470 --------------- .../profile/profile_common_groups_section.h | 225 ------- .../SourceFiles/profile/profile_cover.cpp | 570 ------------------ Telegram/SourceFiles/profile/profile_cover.h | 143 ----- .../SourceFiles/profile/profile_fixed_bar.cpp | 262 -------- .../SourceFiles/profile/profile_fixed_bar.h | 111 ---- .../profile/profile_inner_widget.cpp | 272 --------- .../profile/profile_inner_widget.h | 116 ---- .../profile/profile_section_memento.cpp | 37 -- .../profile/profile_section_memento.h | 56 -- .../profile/profile_userpic_button.cpp | 122 ---- .../profile/profile_userpic_button.h | 61 -- .../SourceFiles/profile/profile_widget.cpp | 169 ------ Telegram/SourceFiles/profile/profile_widget.h | 85 --- Telegram/SourceFiles/rpl/consumer.h | 16 +- Telegram/SourceFiles/rpl/producer.h | 8 + Telegram/SourceFiles/stdafx.h | 3 - .../storage/storage_shared_media.cpp | 12 + .../storage/storage_shared_media.h | 13 +- .../storage/storage_sparse_ids_list.cpp | 4 + .../storage/storage_sparse_ids_list.h | 5 +- .../storage/storage_user_photos.cpp | 11 +- .../SourceFiles/storage/storage_user_photos.h | 9 +- Telegram/SourceFiles/ui/rp_widget.cpp | 134 ++++ Telegram/SourceFiles/ui/rp_widget.h | 185 +++--- .../ui/search_field_controller.cpp | 12 + .../SourceFiles/ui/search_field_controller.h | 12 +- Telegram/SourceFiles/ui/wrap/wrap.h | 4 +- Telegram/gyp/telegram_sources.txt | 28 +- 69 files changed, 693 insertions(+), 5023 deletions(-) create mode 100644 Telegram/SourceFiles/data/data_peer_values.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_block_actions.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_block_actions.h delete mode 100644 Telegram/SourceFiles/profile/profile_block_channel_members.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_block_channel_members.h delete mode 100644 Telegram/SourceFiles/profile/profile_block_info.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_block_info.h delete mode 100644 Telegram/SourceFiles/profile/profile_block_invite_link.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_block_invite_link.h delete mode 100644 Telegram/SourceFiles/profile/profile_block_settings.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_block_settings.h delete mode 100644 Telegram/SourceFiles/profile/profile_block_shared_media.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_block_shared_media.h delete mode 100644 Telegram/SourceFiles/profile/profile_common_groups_section.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_common_groups_section.h delete mode 100644 Telegram/SourceFiles/profile/profile_cover.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_cover.h delete mode 100644 Telegram/SourceFiles/profile/profile_fixed_bar.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_fixed_bar.h delete mode 100644 Telegram/SourceFiles/profile/profile_inner_widget.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_inner_widget.h delete mode 100644 Telegram/SourceFiles/profile/profile_section_memento.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_section_memento.h delete mode 100644 Telegram/SourceFiles/profile/profile_userpic_button.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_userpic_button.h delete mode 100644 Telegram/SourceFiles/profile/profile_widget.cpp delete mode 100644 Telegram/SourceFiles/profile/profile_widget.h create mode 100644 Telegram/SourceFiles/ui/rp_widget.cpp diff --git a/Telegram/SourceFiles/auth_session.cpp b/Telegram/SourceFiles/auth_session.cpp index c0a8f23dd78b7a..2c130b283e27c1 100644 --- a/Telegram/SourceFiles/auth_session.cpp +++ b/Telegram/SourceFiles/auth_session.cpp @@ -190,6 +190,88 @@ void AuthSessionData::constructFromSerialized(const QByteArray &serialized) { } } +void AuthSessionData::markItemLayoutChanged(not_null item) { + _itemLayoutChanged.fire_copy(item); +} + +rpl::producer> AuthSessionData::itemLayoutChanged() const { + return _itemLayoutChanged.events(); +} + +void AuthSessionData::requestItemRepaint(not_null item) { + _itemRepaintRequest.fire_copy(item); +} + +rpl::producer> AuthSessionData::itemRepaintRequest() const { + return _itemRepaintRequest.events(); +} + +void AuthSessionData::markItemRemoved(not_null item) { + _itemRemoved.fire_copy(item); +} + +rpl::producer> AuthSessionData::itemRemoved() const { + return _itemRemoved.events(); +} + +void AuthSessionData::markHistoryUnloaded(not_null history) { + _historyUnloaded.fire_copy(history); +} + +rpl::producer> AuthSessionData::historyUnloaded() const { + return _historyUnloaded.events(); +} + +void AuthSessionData::markHistoryCleared(not_null history) { + _historyCleared.fire_copy(history); +} + +rpl::producer> AuthSessionData::historyCleared() const { + return _historyCleared.events(); +} + +void AuthSessionData::removeMegagroupParticipant( + not_null channel, + not_null user) { + _megagroupParticipantRemoved.fire({ channel, user }); +} + +auto AuthSessionData::megagroupParticipantRemoved() const -> rpl::producer { + return _megagroupParticipantRemoved.events(); +} + +rpl::producer> AuthSessionData::megagroupParticipantRemoved( + not_null channel) const { + return megagroupParticipantRemoved() + | rpl::filter([channel](auto updateChannel, auto user) { + return (updateChannel == channel); + }) + | rpl::map([](auto updateChannel, auto user) { + return user; + }); +} + +void AuthSessionData::addNewMegagroupParticipant( + not_null channel, + not_null user) { + _megagroupParticipantAdded.fire({ channel, user }); +} + +auto AuthSessionData::megagroupParticipantAdded() const -> rpl::producer { + return _megagroupParticipantAdded.events(); +} + +rpl::producer> AuthSessionData::megagroupParticipantAdded( + not_null channel) const { + return megagroupParticipantAdded() + | rpl::filter([channel](auto updateChannel, auto user) { + return (updateChannel == channel); + }) + | rpl::map([](auto updateChannel, auto user) { + return user; + }); +} + void AuthSessionData::setTabbedSelectorSectionEnabled(bool enabled) { _variables.tabbedSelectorSectionEnabled = enabled; if (enabled) { @@ -198,6 +280,11 @@ void AuthSessionData::setTabbedSelectorSectionEnabled(bool enabled) { setTabbedReplacedWithInfo(false); } +rpl::producer AuthSessionData::tabbedReplacedWithInfoValue() const { + return _tabbedReplacedWithInfoValue.events_starting_with( + tabbedReplacedWithInfo()); +} + void AuthSessionData::setThirdSectionInfoEnabled(bool enabled) { if (_variables.thirdSectionInfoEnabled != enabled) { _variables.thirdSectionInfoEnabled = enabled; @@ -209,6 +296,11 @@ void AuthSessionData::setThirdSectionInfoEnabled(bool enabled) { } } +rpl::producer AuthSessionData::thirdSectionInfoEnabledValue() const { + return _thirdSectionInfoEnabledValue.events_starting_with( + thirdSectionInfoEnabled()); +} + void AuthSessionData::setTabbedReplacedWithInfo(bool enabled) { if (_tabbedReplacedWithInfo != enabled) { _tabbedReplacedWithInfo = enabled; @@ -224,6 +316,46 @@ QString AuthSessionData::getSoundPath(const QString &key) const { return qsl(":/sounds/") + key + qsl(".mp3"); } +void AuthSessionData::setDialogsWidthRatio(float64 ratio) { + _variables.dialogsWidthRatio = ratio; +} + +float64 AuthSessionData::dialogsWidthRatio() const { + return _variables.dialogsWidthRatio.current(); +} + +rpl::producer AuthSessionData::dialogsWidthRatioChanges() const { + return _variables.dialogsWidthRatio.changes(); +} + +void AuthSessionData::setThirdColumnWidth(int width) { + _variables.thirdColumnWidth = width; +} + +int AuthSessionData::thirdColumnWidth() const { + return _variables.thirdColumnWidth.current(); +} + +rpl::producer AuthSessionData::thirdColumnWidthChanges() const { + return _variables.thirdColumnWidth.changes(); +} + +void AuthSessionData::markStickersUpdated() { + _stickersUpdated.fire({}); +} + +rpl::producer<> AuthSessionData::stickersUpdated() const { + return _stickersUpdated.events(); +} + +void AuthSessionData::markSavedGifsUpdated() { + _savedGifsUpdated.fire({}); +} + +rpl::producer<> AuthSessionData::savedGifsUpdated() const { + return _savedGifsUpdated.events(); +} + AuthSession &Auth() { auto result = Messenger::Instance().authSession(); Assert(result != nullptr); diff --git a/Telegram/SourceFiles/auth_session.h b/Telegram/SourceFiles/auth_session.h index e5286714956151..4f826b3a650aeb 100644 --- a/Telegram/SourceFiles/auth_session.h +++ b/Telegram/SourceFiles/auth_session.h @@ -70,75 +70,31 @@ class AuthSessionData final { base::Observable &queryItemVisibility() { return _queryItemVisibility; } - void markItemLayoutChanged(not_null item) { - _itemLayoutChanged.fire_copy(item); - } - rpl::producer> itemLayoutChanged() const { - return _itemLayoutChanged.events(); - } - void requestItemRepaint(not_null item) { - _itemRepaintRequest.fire_copy(item); - } - rpl::producer> itemRepaintRequest() const { - return _itemRepaintRequest.events(); - } - void markItemRemoved(not_null item) { - _itemRemoved.fire_copy(item); - } - rpl::producer> itemRemoved() const { - return _itemRemoved.events(); - } - void markHistoryUnloaded(not_null history) { - _historyUnloaded.fire_copy(history); - } - rpl::producer> historyUnloaded() const { - return _historyUnloaded.events(); - } - void markHistoryCleared(not_null history) { - _historyCleared.fire_copy(history); - } - rpl::producer> historyCleared() const { - return _historyCleared.events(); - } + void markItemLayoutChanged(not_null item); + rpl::producer> itemLayoutChanged() const; + void requestItemRepaint(not_null item); + rpl::producer> itemRepaintRequest() const; + void markItemRemoved(not_null item); + rpl::producer> itemRemoved() const; + void markHistoryUnloaded(not_null history); + rpl::producer> historyUnloaded() const; + void markHistoryCleared(not_null history); + rpl::producer> historyCleared() const; using MegagroupParticipant = std::tuple< not_null, not_null>; void removeMegagroupParticipant( - not_null channel, - not_null user) { - _megagroupParticipantRemoved.fire({ channel, user }); - } - auto megagroupParticipantRemoved() const { - return _megagroupParticipantRemoved.events(); - } - auto megagroupParticipantRemoved( - not_null channel) const { - return megagroupParticipantRemoved() - | rpl::filter([channel](auto updateChannel, auto user) { - return (updateChannel == channel); - }) - | rpl::map([](auto updateChannel, auto user) { - return user; - }); - } + not_null channel, + not_null user); + rpl::producer megagroupParticipantRemoved() const; + rpl::producer> megagroupParticipantRemoved( + not_null channel) const; void addNewMegagroupParticipant( - not_null channel, - not_null user) { - _megagroupParticipantAdded.fire({ channel, user }); - } - auto megagroupParticipantAdded() const { - return _megagroupParticipantAdded.events(); - } - auto megagroupParticipantAdded( - not_null channel) const { - return megagroupParticipantAdded() - | rpl::filter([channel](auto updateChannel, auto user) { - return (updateChannel == channel); - }) - | rpl::map([](auto updateChannel, auto user) { - return user; - }); - } + not_null channel, + not_null user); + rpl::producer megagroupParticipantAdded() const; + rpl::producer> megagroupParticipantAdded( + not_null channel) const; void moveFrom(AuthSessionData &&other) { _variables = std::move(other._variables); @@ -166,10 +122,7 @@ class AuthSessionData final { return _variables.thirdSectionInfoEnabled; } void setThirdSectionInfoEnabled(bool enabled); - auto thirdSectionInfoEnabledValue() const { - return _thirdSectionInfoEnabledValue.events_starting_with( - thirdSectionInfoEnabled()); - } + rpl::producer thirdSectionInfoEnabledValue() const; int thirdSectionExtendedBy() const { return _variables.thirdSectionExtendedBy; } @@ -180,10 +133,7 @@ class AuthSessionData final { return _tabbedReplacedWithInfo; } void setTabbedReplacedWithInfo(bool enabled); - auto tabbedReplacedWithInfoValue() const { - return _tabbedReplacedWithInfoValue.events_starting_with( - tabbedReplacedWithInfo()); - } + rpl::producer tabbedReplacedWithInfoValue() const; void setSmallDialogsList(bool enabled) { _variables.smallDialogsList = enabled; } @@ -221,37 +171,17 @@ class AuthSessionData final { RectPart floatPlayerCorner() const { return _variables.floatPlayerCorner; } - void setDialogsWidthRatio(float64 ratio) { - _variables.dialogsWidthRatio = ratio; - } - float64 dialogsWidthRatio() const { - return _variables.dialogsWidthRatio.current(); - } - rpl::producer dialogsWidthRatioChanges() const { - return _variables.dialogsWidthRatio.changes(); - } - void setThirdColumnWidth(int width) { - _variables.thirdColumnWidth = width; - } - int thirdColumnWidth() const { - return _variables.thirdColumnWidth.current(); - } - rpl::producer thirdColumnWidthChanges() const { - return _variables.thirdColumnWidth.changes(); - } - - void markStickersUpdated() { - _stickersUpdated.fire({}); - } - rpl::producer<> stickersUpdated() const { - return _stickersUpdated.events(); - } - void markSavedGifsUpdated() { - _savedGifsUpdated.fire({}); - } - rpl::producer<> savedGifsUpdated() const { - return _savedGifsUpdated.events(); - } + void setDialogsWidthRatio(float64 ratio); + float64 dialogsWidthRatio() const; + rpl::producer dialogsWidthRatioChanges() const; + void setThirdColumnWidth(int width); + int thirdColumnWidth() const; + rpl::producer thirdColumnWidthChanges() const; + + void markStickersUpdated(); + rpl::producer<> stickersUpdated() const; + void markSavedGifsUpdated(); + rpl::producer<> savedGifsUpdated() const; void setGroupStickersSectionHidden(PeerId peerId) { _variables.groupStickersSectionHidden.insert(peerId); } diff --git a/Telegram/SourceFiles/base/observer.cpp b/Telegram/SourceFiles/base/observer.cpp index 071470da6dc105..751be90984d7cb 100644 --- a/Telegram/SourceFiles/base/observer.cpp +++ b/Telegram/SourceFiles/base/observer.cpp @@ -77,4 +77,15 @@ void HandleObservables() { } } +rpl::producer<> ObservableViewer(base::Observable &observable) { + return [&observable](const auto &consumer) { + auto lifetime = rpl::lifetime(); + lifetime.make_state( + observable.add_subscription([consumer]() { + consumer.put_next({}); + })); + return lifetime; + }; +} + } // namespace base diff --git a/Telegram/SourceFiles/base/observer.h b/Telegram/SourceFiles/base/observer.h index 81a394a13bd25c..d22c37498d6361 100644 --- a/Telegram/SourceFiles/base/observer.h +++ b/Telegram/SourceFiles/base/observer.h @@ -477,16 +477,6 @@ inline auto ObservableViewer(base::Observable &observable) { }); } -inline auto ObservableViewer(base::Observable &observable) { - return rpl::make_producer<>([&observable]( - const auto &consumer) { - auto lifetime = rpl::lifetime(); - lifetime.make_state( - observable.add_subscription([consumer]() { - consumer.put_next({}); - })); - return lifetime; - }); -} +rpl::producer<> ObservableViewer(base::Observable &observable); } // namespace base diff --git a/Telegram/SourceFiles/boxes/photo_crop_box.cpp b/Telegram/SourceFiles/boxes/photo_crop_box.cpp index 80e220c7d09748..6b540328c8326c 100644 --- a/Telegram/SourceFiles/boxes/photo_crop_box.cpp +++ b/Telegram/SourceFiles/boxes/photo_crop_box.cpp @@ -103,6 +103,10 @@ int PhotoCropBox::mouseState(QPoint p) { return 0; } +rpl::producer PhotoCropBox::ready() const { + return _readyImages.events(); +} + void PhotoCropBox::mouseReleaseEvent(QMouseEvent *e) { if (_downState) { _downState = 0; diff --git a/Telegram/SourceFiles/boxes/photo_crop_box.h b/Telegram/SourceFiles/boxes/photo_crop_box.h index 78e8b3e031b17b..a46248d4a33a7b 100644 --- a/Telegram/SourceFiles/boxes/photo_crop_box.h +++ b/Telegram/SourceFiles/boxes/photo_crop_box.h @@ -29,9 +29,7 @@ class PhotoCropBox : public BoxContent { int32 mouseState(QPoint p); - rpl::producer ready() const { - return _readyImages.events(); - } + rpl::producer ready() const; protected: void prepare() override; diff --git a/Telegram/SourceFiles/data/data_peer_values.cpp b/Telegram/SourceFiles/data/data_peer_values.cpp new file mode 100644 index 00000000000000..acef47a0dbf31f --- /dev/null +++ b/Telegram/SourceFiles/data/data_peer_values.cpp @@ -0,0 +1,126 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "data/data_peer_values.h" + +namespace Data { + +inline auto AdminRightsValue(not_null channel) { + return channel->adminRightsValue(); +} + +inline auto AdminRightsValue( + not_null channel, + MTPDchannelAdminRights::Flags mask) { + return FlagsValueWithMask(AdminRightsValue(channel), mask); +} + +inline auto AdminRightValue( + not_null channel, + MTPDchannelAdminRights::Flag flag) { + return SingleFlagValue(AdminRightsValue(channel), flag); +} + +inline auto RestrictionsValue(not_null channel) { + return channel->restrictionsValue(); +} + +inline auto RestrictionsValue( + not_null channel, + MTPDchannelBannedRights::Flags mask) { + return FlagsValueWithMask(RestrictionsValue(channel), mask); +} + +inline auto RestrictionValue( + not_null channel, + MTPDchannelBannedRights::Flag flag) { + return SingleFlagValue(RestrictionsValue(channel), flag); +} + +rpl::producer PeerFlagValue( + ChatData *chat, + MTPDchat_ClientFlag flag) { + return PeerFlagValue(chat, static_cast(flag)); +} + +rpl::producer PeerFlagValue( + ChannelData *channel, + MTPDchannel_ClientFlag flag) { + return PeerFlagValue(channel, static_cast(flag)); +} + +rpl::producer CanWriteValue(UserData *user) { + using namespace rpl::mappers; + return PeerFlagValue(user, MTPDuser::Flag::f_deleted) + | rpl::map(!_1); +} + +rpl::producer CanWriteValue(ChatData *chat) { + using namespace rpl::mappers; + auto mask = 0 + | MTPDchat::Flag::f_deactivated + | MTPDchat_ClientFlag::f_forbidden + | MTPDchat::Flag::f_left + | MTPDchat::Flag::f_kicked; + return PeerFlagsValue(chat, mask) + | rpl::map(!_1); +} + +rpl::producer CanWriteValue(ChannelData *channel) { + auto mask = 0 + | MTPDchannel::Flag::f_left + | MTPDchannel_ClientFlag::f_forbidden + | MTPDchannel::Flag::f_creator + | MTPDchannel::Flag::f_broadcast; + return rpl::combine( + PeerFlagsValue(channel, mask), + AdminRightValue( + channel, + MTPDchannelAdminRights::Flag::f_post_messages), + RestrictionValue( + channel, + MTPDchannelBannedRights::Flag::f_send_messages), + []( + MTPDchannel::Flags flags, + bool postMessagesRight, + bool sendMessagesRestriction) { + auto notAmInFlags = 0 + | MTPDchannel::Flag::f_left + | MTPDchannel_ClientFlag::f_forbidden; + return !(flags & notAmInFlags) + && (postMessagesRight + || (flags & MTPDchannel::Flag::f_creator) + || (!(flags & MTPDchannel::Flag::f_broadcast) + && !sendMessagesRestriction)); + }); +} + +rpl::producer CanWriteValue(not_null peer) { + if (auto user = peer->asUser()) { + return CanWriteValue(user); + } else if (auto chat = peer->asChat()) { + return CanWriteValue(chat); + } else if (auto channel = peer->asChannel()) { + return CanWriteValue(channel); + } + Unexpected("Bad peer value in CanWriteValue()"); +} + +} // namespace Data diff --git a/Telegram/SourceFiles/data/data_peer_values.h b/Telegram/SourceFiles/data/data_peer_values.h index 904a3771f75494..8fc6b127230c88 100644 --- a/Telegram/SourceFiles/data/data_peer_values.h +++ b/Telegram/SourceFiles/data/data_peer_values.h @@ -82,17 +82,13 @@ inline auto PeerFlagValue( // return PeerFlagValue(user, static_cast(flag)); //} -inline auto PeerFlagValue( - ChatData *chat, - MTPDchat_ClientFlag flag) { - return PeerFlagValue(chat, static_cast(flag)); -} +rpl::producer PeerFlagValue( + ChatData *chat, + MTPDchat_ClientFlag flag); -inline auto PeerFlagValue( - ChannelData *channel, - MTPDchannel_ClientFlag flag) { - return PeerFlagValue(channel, static_cast(flag)); -} +rpl::producer PeerFlagValue( + ChannelData *channel, + MTPDchannel_ClientFlag flag); template < typename PeerType, @@ -120,93 +116,9 @@ inline auto PeerFullFlagValue( return SingleFlagValue(PeerFullFlagsValue(peer), flag); } -inline auto AdminRightsValue(not_null channel) { - return channel->adminRightsValue(); -} - -inline auto AdminRightsValue( - not_null channel, - MTPDchannelAdminRights::Flags mask) { - return FlagsValueWithMask(AdminRightsValue(channel), mask); -} - -inline auto AdminRightValue( - not_null channel, - MTPDchannelAdminRights::Flag flag) { - return SingleFlagValue(AdminRightsValue(channel), flag); -} - -inline auto RestrictionsValue(not_null channel) { - return channel->restrictionsValue(); -} - -inline auto RestrictionsValue( - not_null channel, - MTPDchannelBannedRights::Flags mask) { - return FlagsValueWithMask(RestrictionsValue(channel), mask); -} - -inline auto RestrictionValue( - not_null channel, - MTPDchannelBannedRights::Flag flag) { - return SingleFlagValue(RestrictionsValue(channel), flag); -} - -inline auto CanWriteValue(UserData *user) { - using namespace rpl::mappers; - return PeerFlagValue(user, MTPDuser::Flag::f_deleted) - | rpl::map(!_1); -} - -inline auto CanWriteValue(ChatData *chat) { - using namespace rpl::mappers; - auto mask = 0 - | MTPDchat::Flag::f_deactivated - | MTPDchat_ClientFlag::f_forbidden - | MTPDchat::Flag::f_left - | MTPDchat::Flag::f_kicked; - return PeerFlagsValue(chat, mask) - | rpl::map(!_1); -} - -inline auto CanWriteValue(ChannelData *channel) { - auto flagsMask = 0 - | MTPDchannel::Flag::f_left - | MTPDchannel_ClientFlag::f_forbidden - | MTPDchannel::Flag::f_creator - | MTPDchannel::Flag::f_broadcast; - return rpl::combine( - PeerFlagsValue(channel, flagsMask), - AdminRightValue( - channel, - MTPDchannelAdminRights::Flag::f_post_messages), - RestrictionValue( - channel, - MTPDchannelBannedRights::Flag::f_send_messages), - []( - MTPDchannel::Flags flags, - bool postMessagesRight, - bool sendMessagesRestriction) { - auto notAmInFlags = 0 - | MTPDchannel::Flag::f_left - | MTPDchannel_ClientFlag::f_forbidden; - return !(flags & notAmInFlags) - && (postMessagesRight - || (flags & MTPDchannel::Flag::f_creator) - || (!(flags & MTPDchannel::Flag::f_broadcast) - && !sendMessagesRestriction)); - }); -} - -inline rpl::producer CanWriteValue(not_null peer) { - if (auto user = peer->asUser()) { - return CanWriteValue(user); - } else if (auto chat = peer->asChat()) { - return CanWriteValue(chat); - } else if (auto channel = peer->asChannel()) { - return CanWriteValue(channel); - } - Unexpected("Bad peer value in CanWriteValue()"); -} +rpl::producer CanWriteValue(UserData *user); +rpl::producer CanWriteValue(ChatData *chat); +rpl::producer CanWriteValue(ChannelData *channel); +rpl::producer CanWriteValue(not_null peer); } // namespace Data diff --git a/Telegram/SourceFiles/info/common_groups/info_common_groups_inner_widget.cpp b/Telegram/SourceFiles/info/common_groups/info_common_groups_inner_widget.cpp index 155c670e809cc4..d4d30687f427af 100644 --- a/Telegram/SourceFiles/info/common_groups/info_common_groups_inner_widget.cpp +++ b/Telegram/SourceFiles/info/common_groups/info_common_groups_inner_widget.cpp @@ -208,6 +208,10 @@ void InnerWidget::restoreState(not_null memento) { _listController->restoreState(memento->listState()); } +rpl::producer InnerWidget::scrollToRequests() const { + return _scrollToRequests.events(); +} + int InnerWidget::desiredHeight() const { auto desired = 0; auto count = qMax(_user->commonChatsCount(), 1); diff --git a/Telegram/SourceFiles/info/common_groups/info_common_groups_inner_widget.h b/Telegram/SourceFiles/info/common_groups/info_common_groups_inner_widget.h index dbd3573f19a490..0d55a62833b575 100644 --- a/Telegram/SourceFiles/info/common_groups/info_common_groups_inner_widget.h +++ b/Telegram/SourceFiles/info/common_groups/info_common_groups_inner_widget.h @@ -45,9 +45,7 @@ class InnerWidget final return _user; } - rpl::producer scrollToRequests() const { - return _scrollToRequests.events(); - } + rpl::producer scrollToRequests() const; int desiredHeight() const; diff --git a/Telegram/SourceFiles/info/info_controller.cpp b/Telegram/SourceFiles/info/info_controller.cpp index 6699ae788013b2..3da0ac88fe34ae 100644 --- a/Telegram/SourceFiles/info/info_controller.cpp +++ b/Telegram/SourceFiles/info/info_controller.cpp @@ -167,6 +167,14 @@ auto Controller::produceSearchQuery( return result; } +rpl::producer Controller::searchEnabledByContent() const { + return _seachEnabledByContent.value(); +} + +rpl::producer Controller::mediaSourceQueryValue() const { + return _searchController->currentQueryValue(); +} + rpl::producer Controller::mediaSource( SparseIdsMergedSlice::UniversalMsgId aroundId, int limitBefore, diff --git a/Telegram/SourceFiles/info/info_controller.h b/Telegram/SourceFiles/info/info_controller.h index a16e34379cba32..2127d72afed395 100644 --- a/Telegram/SourceFiles/info/info_controller.h +++ b/Telegram/SourceFiles/info/info_controller.h @@ -109,16 +109,12 @@ class Controller { void setSearchEnabledByContent(bool enabled) { _seachEnabledByContent = enabled; } - rpl::producer searchEnabledByContent() const { - return _seachEnabledByContent.value(); - } + rpl::producer searchEnabledByContent() const; rpl::producer mediaSource( SparseIdsMergedSlice::UniversalMsgId aroundId, int limitBefore, int limitAfter) const; - rpl::producer mediaSourceQueryValue() const { - return _searchController->currentQueryValue(); - } + rpl::producer mediaSourceQueryValue() const; void saveSearchState(not_null memento); diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index d9c75c99dc4942..ffc61760e698a5 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -623,6 +623,10 @@ object_ptr WrapWidget::createContent( // _historyStack.erase(_historyStack.begin()); //} +rpl::producer WrapWidget::wrapValue() const { + return _wrap.value(); +} + void WrapWidget::setWrap(Wrap wrap) { // Was done for top level tabs support. // diff --git a/Telegram/SourceFiles/info/info_wrap_widget.h b/Telegram/SourceFiles/info/info_wrap_widget.h index 8abd07ee21df25..3969474bc9010a 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.h +++ b/Telegram/SourceFiles/info/info_wrap_widget.h @@ -94,9 +94,7 @@ class WrapWidget final : public Window::SectionWidget { Wrap wrap() const { return _wrap.current(); } - rpl::producer wrapValue() const { - return _wrap.value(); - } + rpl::producer wrapValue() const; void setWrap(Wrap wrap); not_null controller() { diff --git a/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp b/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp index debbf62df0521a..ab435909dfb4bc 100644 --- a/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp @@ -360,5 +360,9 @@ void InnerWidget::setScrollHeightValue(rpl::producer value) { _1 - _2)); } +rpl::producer InnerWidget::scrollToRequests() const { + return _scrollToRequests.events(); +} + } // namespace Media } // namespace Info diff --git a/Telegram/SourceFiles/info/media/info_media_inner_widget.h b/Telegram/SourceFiles/info/media/info_media_inner_widget.h index d154f29eb6f2f6..d6f392ffbb33ed 100644 --- a/Telegram/SourceFiles/info/media/info_media_inner_widget.h +++ b/Telegram/SourceFiles/info/media/info_media_inner_widget.h @@ -55,9 +55,7 @@ class InnerWidget final : public Ui::RpWidget { void setScrollHeightValue(rpl::producer value); - rpl::producer scrollToRequests() const { - return _scrollToRequests.events(); - } + rpl::producer scrollToRequests() const; rpl::producer selectedListValue() const; void cancelSelection(); diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index d214a7b53e4e85..c9b9ec1b1cd53d 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -585,6 +585,15 @@ void ListWidget::start() { }, lifetime()); } +rpl::producer ListWidget::scrollToRequests() const { + return _scrollToRequests.events(); +} + +rpl::producer ListWidget::selectedListValue() const { + return _selectedListStream.events_starting_with( + collectSelectedItems()); +} + void ListWidget::restart() { mouseActionCancel(); diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.h b/Telegram/SourceFiles/info/media/info_media_list_widget.h index d8ba8b860f14b2..9ac20bba727f50 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.h +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.h @@ -55,13 +55,8 @@ class ListWidget : public Ui::RpWidget { void restart(); - rpl::producer scrollToRequests() const { - return _scrollToRequests.events(); - } - rpl::producer selectedListValue() const { - return _selectedListStream.events_starting_with( - collectSelectedItems()); - } + rpl::producer scrollToRequests() const; + rpl::producer selectedListValue() const; void cancelSelection() { clearSelected(); } diff --git a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp index e3d93b075f75da..292850e8a3cbd0 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp @@ -431,6 +431,11 @@ SharedMediaCover::SharedMediaCover(QWidget *parent) createLabel(); } +SharedMediaCover *SharedMediaCover::setToggleShown(rpl::producer &&shown) { + return static_cast( + SectionWithToggle::setToggleShown(std::move(shown))); +} + void SharedMediaCover::createLabel() { using namespace rpl::mappers; auto label = object_ptr( diff --git a/Telegram/SourceFiles/info/profile/info_profile_cover.h b/Telegram/SourceFiles/info/profile/info_profile_cover.h index 10921ccaf2b785..265ada5dbf0cad 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_cover.h +++ b/Telegram/SourceFiles/info/profile/info_profile_cover.h @@ -102,10 +102,7 @@ class SharedMediaCover : public SectionWithToggle { public: SharedMediaCover(QWidget *parent); - SharedMediaCover *setToggleShown(rpl::producer &&shown) { - return static_cast( - SectionWithToggle::setToggleShown(std::move(shown))); - } + SharedMediaCover *setToggleShown(rpl::producer &&shown); QMargins getMargins() const override; diff --git a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp index c214fa187f26a2..5a9212c7987ef3 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp @@ -274,6 +274,14 @@ void InnerWidget::restoreState(not_null memento) { } } +rpl::producer InnerWidget::scrollToRequests() const { + return _scrollToRequests.events(); +} + +rpl::producer InnerWidget::desiredHeightValue() const { + return _desiredHeight.events_starting_with(countDesiredHeight()); +} + int InnerWidget::resizeGetHeight(int newWidth) { _inResize = true; auto guard = gsl::finally([&] { _inResize = false; }); diff --git a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.h b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.h index d1f4769cee5aa4..43336900aaac27 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.h +++ b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.h @@ -58,13 +58,8 @@ class InnerWidget final : public Ui::RpWidget { void setIsStackBottom(bool isStackBottom) { _isStackBottom = isStackBottom; } - rpl::producer scrollToRequests() const { - return _scrollToRequests.events(); - } - - rpl::producer desiredHeightValue() const override { - return _desiredHeight.events_starting_with(countDesiredHeight()); - } + rpl::producer scrollToRequests() const; + rpl::producer desiredHeightValue() const override; protected: int resizeGetHeight(int newWidth) override; diff --git a/Telegram/SourceFiles/info/profile/info_profile_members.cpp b/Telegram/SourceFiles/info/profile/info_profile_members.cpp index 1d2d746d43aabd..7e7eee4dd8f763 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_members.cpp @@ -90,6 +90,10 @@ rpl::producer Members::onlineCountValue() const { return _listController->onlineCountValue(); } +rpl::producer Members::scrollToRequests() const { + return _scrollToRequests.events(); +} + std::unique_ptr Members::saveState() { auto result = std::make_unique(); result->list = _listController->saveState(); diff --git a/Telegram/SourceFiles/info/profile/info_profile_members.h b/Telegram/SourceFiles/info/profile/info_profile_members.h index 0683b6f1959720..197f2eaa5617ff 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members.h +++ b/Telegram/SourceFiles/info/profile/info_profile_members.h @@ -60,9 +60,7 @@ class Members not_null controller, not_null peer); - rpl::producer scrollToRequests() const { - return _scrollToRequests.events(); - } + rpl::producer scrollToRequests() const; std::unique_ptr saveState(); void restoreState(std::unique_ptr state); diff --git a/Telegram/SourceFiles/observer_peer.cpp b/Telegram/SourceFiles/observer_peer.cpp index 0ba226a2988f91..2d5a0b53419a4c 100644 --- a/Telegram/SourceFiles/observer_peer.cpp +++ b/Telegram/SourceFiles/observer_peer.cpp @@ -108,4 +108,35 @@ base::Observable &PeerUpdated() { return PeerUpdatedObservable; } +rpl::producer PeerUpdateViewer( + PeerUpdate::Flags flags) { + return [=](const auto &consumer) { + auto lifetime = rpl::lifetime(); + lifetime.make_state( + PeerUpdated().add_subscription({ flags, [=]( + const PeerUpdate &update) { + consumer.put_next_copy(update); + }})); + return lifetime; + }; +} + +rpl::producer PeerUpdateViewer( + not_null peer, + PeerUpdate::Flags flags) { + return PeerUpdateViewer(flags) + | rpl::filter([=](const PeerUpdate &update) { + return (update.peer == peer); + }); +} + +rpl::producer PeerUpdateValue( + not_null peer, + PeerUpdate::Flags flags) { + auto initial = PeerUpdate(peer); + initial.flags = flags; + return rpl::single(initial) + | rpl::then(PeerUpdateViewer(peer, flags)); +} + } // namespace Notify diff --git a/Telegram/SourceFiles/observer_peer.h b/Telegram/SourceFiles/observer_peer.h index ea94fc294568e9..35ab5cd28346d7 100644 --- a/Telegram/SourceFiles/observer_peer.h +++ b/Telegram/SourceFiles/observer_peer.h @@ -125,36 +125,15 @@ class PeerUpdatedHandler { }; base::Observable &PeerUpdated(); -inline auto PeerUpdateViewer( - PeerUpdate::Flags flags) { - return rpl::make_producer([=]( - const auto &consumer) { - auto lifetime = rpl::lifetime(); - lifetime.make_state( - PeerUpdated().add_subscription({ flags, [=]( - const PeerUpdate &update) { - consumer.put_next_copy(update); - }})); - return lifetime; - }); -} +rpl::producer PeerUpdateViewer( + PeerUpdate::Flags flags); -inline auto PeerUpdateViewer( - not_null peer, - PeerUpdate::Flags flags) { - return PeerUpdateViewer(flags) - | rpl::filter([=](const PeerUpdate &update) { - return (update.peer == peer); - }); -} +rpl::producer PeerUpdateViewer( + not_null peer, + PeerUpdate::Flags flags); -inline auto PeerUpdateValue( - not_null peer, - PeerUpdate::Flags flags) { - auto initial = PeerUpdate(peer); - initial.flags = flags; - return rpl::single(initial) - | rpl::then(PeerUpdateViewer(peer, flags)); -} +rpl::producer PeerUpdateValue( + not_null peer, + PeerUpdate::Flags flags); } // namespace Notify diff --git a/Telegram/SourceFiles/profile/profile_block_actions.cpp b/Telegram/SourceFiles/profile/profile_block_actions.cpp deleted file mode 100644 index 811f50f708dfce..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_actions.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#include "profile/profile_block_actions.h" - -#include "styles/style_profile.h" -#include "styles/style_boxes.h" -#include "ui/widgets/buttons.h" -#include "boxes/confirm_box.h" -#include "boxes/report_box.h" -#include "mainwidget.h" -#include "observer_peer.h" -#include "apiwrap.h" -#include "auth_session.h" -#include "lang/lang_keys.h" -#include "profile/profile_channel_controllers.h" -#include "mainwindow.h" - -namespace Profile { - -constexpr auto kEnableSearchMembersAfterCount = 50; -constexpr auto kMaxChannelMembersDeleteAllowed = 1000; - -using UpdateFlag = Notify::PeerUpdate::Flag; - -ActionsWidget::ActionsWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_actions_section)) { - auto observeEvents = UpdateFlag::ChannelAmIn - | UpdateFlag::UserIsBlocked - | UpdateFlag::BotCommandsChanged - | UpdateFlag::MembersChanged; - subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) { - notifyPeerUpdated(update); - })); - - validateBlockStatus(); - refreshButtons(); -} - -void ActionsWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { - if (update.peer != peer()) { - return; - } - - auto needFullRefresh = [&update, this]() { - if (update.flags & UpdateFlag::BotCommandsChanged) { - if (_hasBotHelp != hasBotCommand(qsl("help")) || _hasBotSettings != hasBotCommand(qsl("settings"))) { - return true; - } - } - if (update.flags & UpdateFlag::MembersChanged) { - if (peer()->isMegagroup()) { - // Search members button could change. - return true; - } - } - return false; - }; - if (needFullRefresh()) { - refreshButtons(); - } else { - if (update.flags & UpdateFlag::MembersChanged) { - refreshDeleteChannel(); - } - if (update.flags & UpdateFlag::ChannelAmIn) { - refreshLeaveChannel(); - } - if (update.flags & UpdateFlag::UserIsBlocked) { - refreshBlockUser(); - } - refreshVisibility(); - } - - contentSizeUpdated(); -} - -void ActionsWidget::validateBlockStatus() const { - auto needFullPeer = [this]() { - if (auto user = peer()->asUser()) { - if (user->blockStatus() == UserData::BlockStatus::Unknown) { - return true; - } else if (user->botInfo && !user->botInfo->inited) { - return true; - } - } - return false; - }; - if (needFullPeer()) { - Auth().api().requestFullPeer(peer()); - } -} - -Ui::LeftOutlineButton *ActionsWidget::addButton(const QString &text, const char *slot, const style::OutlineButton &st, int skipHeight) { - auto result = new Ui::LeftOutlineButton(this, text, st); - connect(result, SIGNAL(clicked()), this, slot); - result->show(); - - int top = buttonsBottom() + skipHeight; - resizeButton(result, width(), top); - - _buttons.push_back(result); - return result; -}; - -void ActionsWidget::resizeButton(Ui::LeftOutlineButton *button, int newWidth, int top) { - int left = defaultOutlineButtonLeft(); - int availableWidth = newWidth - left - st::profileBlockMarginRight; - accumulate_min(availableWidth, st::profileBlockOneLineWidthMax); - button->resizeToWidth(availableWidth); - button->moveToLeft(left, top); -} - -void ActionsWidget::refreshButtons() { - auto buttons = base::take(_buttons); - for_const (auto &button, buttons) { - delete button; - } - _blockUser = _leaveChannel = nullptr; - - if (auto user = peer()->asUser()) { - if ((_hasBotHelp = hasBotCommand(qsl("help")))) { - addButton(lang(lng_profile_bot_help), SLOT(onBotHelp())); - } - if ((_hasBotSettings = hasBotCommand(qsl("settings")))) { - addButton(lang(lng_profile_bot_settings), SLOT(onBotSettings())); - } - addButton(lang(lng_profile_clear_history), SLOT(onClearHistory())); - addButton(lang(lng_profile_delete_conversation), SLOT(onDeleteConversation())); - if (user->botInfo) { - addButton(lang(lng_profile_report), SLOT(onReport()), st::defaultLeftOutlineButton, st::profileBlockOneLineSkip); - } - refreshBlockUser(); - } else if (auto chat = peer()->asChat()) { - if (chat->amCreator()) { - addButton(lang(lng_profile_migrate_button), SLOT(onUpgradeToSupergroup())); - } - addButton(lang(lng_profile_clear_history), SLOT(onClearHistory())); - addButton(lang(lng_profile_clear_and_exit), SLOT(onDeleteConversation())); - } else if (auto channel = peer()->asChannel()) { - if (channel->isMegagroup() && channel->membersCount() > kEnableSearchMembersAfterCount) { - addButton(lang(lng_profile_search_members), SLOT(onSearchMembers())); - } - if (!channel->amCreator() && (!channel->isMegagroup() || channel->isPublic())) { - addButton(lang(lng_profile_report), SLOT(onReport())); - } - refreshDeleteChannel(); - refreshLeaveChannel(); - } - - refreshVisibility(); -} - -void ActionsWidget::refreshVisibility() { - setVisible(!_buttons.isEmpty()); -} - -QString ActionsWidget::getBlockButtonText() const { - auto user = peer()->asUser(); - if (!user || (user->id == Auth().userPeerId())) return QString(); - if (user->blockStatus() == UserData::BlockStatus::Unknown) return QString(); - - if (user->isBlocked()) { - if (user->botInfo) { - return lang(lng_profile_unblock_bot); - } - return lang(lng_profile_unblock_user); - } else if (user->botInfo) { - return lang(lng_profile_block_bot); - } - return lang(lng_profile_block_user); -} - -bool ActionsWidget::hasBotCommand(const QString &command) const { - auto user = peer()->asUser(); - if (!user || !user->botInfo || user->botInfo->commands.isEmpty()) { - return false; - } - - for_const (auto &cmd, user->botInfo->commands) { - if (!cmd.command.compare(command, Qt::CaseInsensitive)) { - return true; - } - } - return false; -} - -void ActionsWidget::sendBotCommand(const QString &command) { - auto user = peer()->asUser(); - if (user && user->botInfo && !user->botInfo->commands.isEmpty()) { - for_const (auto &cmd, user->botInfo->commands) { - if (!cmd.command.compare(command, Qt::CaseInsensitive)) { - Ui::showPeerHistory(user, ShowAtTheEndMsgId); - App::sendBotCommand(user, user, '/' + cmd.command); - return; - } - } - } - - // Command was not found. - refreshButtons(); - contentSizeUpdated(); -} - -void ActionsWidget::refreshBlockUser() { - if (auto user = peer()->asUser()) { - auto blockText = getBlockButtonText(); - if (_blockUser) { - if (blockText.isEmpty()) { - _buttons.removeOne(_blockUser); - delete _blockUser; - _blockUser = nullptr; - } else { - _blockUser->setText(blockText); - } - } else if (!blockText.isEmpty()) { - _blockUser = addButton(blockText, SLOT(onBlockUser()), st::attentionLeftOutlineButton, st::profileBlockOneLineSkip); - } - } -} - -void ActionsWidget::refreshDeleteChannel() { - if (auto channel = peer()->asChannel()) { - if (channel->canDelete() && !_deleteChannel) { - _deleteChannel = addButton(lang(channel->isMegagroup() ? lng_profile_delete_group : lng_profile_delete_channel), SLOT(onDeleteChannel()), st::attentionLeftOutlineButton); - } else if (!channel->canDelete() && _deleteChannel) { - _buttons.removeOne(_deleteChannel); - delete _deleteChannel; - _deleteChannel = nullptr; - } - } -} - -void ActionsWidget::refreshLeaveChannel() { - if (auto channel = peer()->asChannel()) { - if (!channel->amCreator()) { - if (channel->amIn() && !_leaveChannel) { - _leaveChannel = addButton(lang(channel->isMegagroup() ? lng_profile_leave_group : lng_profile_leave_channel), SLOT(onLeaveChannel())); - } else if (!channel->amIn() && _leaveChannel) { - _buttons.removeOne(_leaveChannel); - delete _leaveChannel; - _leaveChannel = nullptr; - } - } - } -} - -int ActionsWidget::resizeGetHeight(int newWidth) { - for_const (auto button, _buttons) { - resizeButton(button, newWidth, button->y()); - } - return buttonsBottom(); -} - -int ActionsWidget::buttonsBottom() const { - if (_buttons.isEmpty()) { - return contentTop(); - } - auto lastButton = _buttons.back(); - return lastButton->y() + lastButton->height(); -} - -void ActionsWidget::onBotHelp() { - sendBotCommand(qsl("help")); -} - -void ActionsWidget::onBotSettings() { - sendBotCommand(qsl("settings")); -} - -void ActionsWidget::onClearHistory() { - QString confirmation; - if (auto user = peer()->asUser()) { - confirmation = lng_sure_delete_history(lt_contact, App::peerName(peer())); - } else if (auto chat = peer()->asChat()) { - confirmation = lng_sure_delete_group_history(lt_group, App::peerName(peer())); - } - if (!confirmation.isEmpty()) { - Ui::show(Box(confirmation, lang(lng_box_delete), st::attentionBoxButton, base::lambda_guarded(this, [this] { - Ui::hideLayer(); - App::main()->clearHistory(peer()); - Ui::showPeerHistory(peer(), ShowAtUnreadMsgId); - }))); - } -} - -void ActionsWidget::onDeleteConversation() { - QString confirmation, confirmButton; - if (auto user = peer()->asUser()) { - confirmation = lng_sure_delete_history(lt_contact, App::peerName(peer())); - confirmButton = lang(lng_box_delete); - } else if (auto chat = peer()->asChat()) { - confirmation = lng_sure_delete_and_exit(lt_group, App::peerName(peer())); - confirmButton = lang(lng_box_leave); - } - if (!confirmation.isEmpty()) { - Ui::show(Box(confirmation, confirmButton, st::attentionBoxButton, base::lambda_guarded(this, [this] { - Ui::hideLayer(); - Ui::showChatsList(); - if (auto user = peer()->asUser()) { - App::main()->deleteConversation(peer()); - } else if (auto chat = peer()->asChat()) { - App::main()->deleteAndExit(chat); - } - }))); - } -} - -void ActionsWidget::onBlockUser() { - if (auto user = peer()->asUser()) { - if (user->isBlocked()) { - Auth().api().unblockUser(user); - } else { - Auth().api().blockUser(user); - } - } -} - -void ActionsWidget::onUpgradeToSupergroup() { - if (auto chat = peer()->asChat()) { - Ui::show(Box(chat)); - } -} - -void ActionsWidget::onDeleteChannel() { - auto text = lang(peer()->isMegagroup() ? lng_sure_delete_group : lng_sure_delete_channel); - Ui::show(Box(text, lang(lng_box_delete), st::attentionBoxButton, base::lambda_guarded(this, [this] { - Ui::hideLayer(); - Ui::showChatsList(); - if (auto chat = peer()->migrateFrom()) { - App::main()->deleteAndExit(chat); - } - if (auto channel = peer()->asChannel()) { - MTP::send(MTPchannels_DeleteChannel(channel->inputChannel), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::deleteChannelFailed)); - } - }))); -} - -void ActionsWidget::onLeaveChannel() { - auto channel = peer()->asChannel(); - if (!channel) return; - - auto text = lang(channel->isMegagroup() ? lng_sure_leave_group : lng_sure_leave_channel); - Ui::show(Box(text, lang(lng_box_leave), base::lambda_guarded(this, [this] { - Auth().api().leaveChannel(peer()->asChannel()); - }))); -} - -void ActionsWidget::onSearchMembers() { - if (auto channel = peer()->asChannel()) { - ParticipantsBoxController::Start( - App::wnd()->controller(), - channel, - ParticipantsBoxController::Role::Members); - } -} - -void ActionsWidget::onReport() { - Ui::show(Box(peer())); -} - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_actions.h b/Telegram/SourceFiles/profile/profile_block_actions.h deleted file mode 100644 index a97aa510224ac5..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_actions.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "profile/profile_block_widget.h" - -namespace style { -struct OutlineButton; -} // namespace style - -namespace st { -extern const style::OutlineButton &defaultLeftOutlineButton; -} // namespace st - -namespace Ui { -class LeftOutlineButton; -} // namespace Ui - -namespace Notify { -struct PeerUpdate; -} // namespace Notify - -namespace Profile { - -class ActionsWidget : public BlockWidget { - Q_OBJECT - -public: - ActionsWidget(QWidget *parent, PeerData *peer); - -protected: - // Resizes content and counts natural widget height for the desired width. - int resizeGetHeight(int newWidth) override; - -private slots: - void onBotHelp(); - void onBotSettings(); - void onClearHistory(); - void onDeleteConversation(); - void onBlockUser(); - void onUpgradeToSupergroup(); - void onSearchMembers(); - void onDeleteChannel(); - void onLeaveChannel(); - void onReport(); - -private: - // Observed notifications. - void notifyPeerUpdated(const Notify::PeerUpdate &update); - - void validateBlockStatus() const; - - int buttonsBottom() const; - - void refreshButtons(); - void refreshBlockUser(); - void refreshDeleteChannel(); - void refreshLeaveChannel(); - void refreshVisibility(); - - Ui::LeftOutlineButton *addButton(const QString &text, const char *slot - , const style::OutlineButton &st = st::defaultLeftOutlineButton, int skipHeight = 0); - void resizeButton(Ui::LeftOutlineButton *button, int newWidth, int top); - - QString getBlockButtonText() const; - bool hasBotCommand(const QString &command) const; - void sendBotCommand(const QString &command); - - QList _buttons; - - // Hold some button pointers to update / toggle them. - bool _hasBotHelp = false; - bool _hasBotSettings = false; - Ui::LeftOutlineButton *_blockUser = nullptr; - Ui::LeftOutlineButton *_deleteChannel = nullptr; - Ui::LeftOutlineButton *_leaveChannel = nullptr; - -}; - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_channel_members.cpp b/Telegram/SourceFiles/profile/profile_block_channel_members.cpp deleted file mode 100644 index a7b40062ff1d4b..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_channel_members.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#include "profile/profile_block_channel_members.h" - -#include "profile/profile_channel_controllers.h" -#include "styles/style_profile.h" -#include "ui/widgets/buttons.h" -#include "observer_peer.h" -#include "mainwidget.h" -#include "history/history_admin_log_section.h" -#include "lang/lang_keys.h" -#include "mainwindow.h" -#include "window/window_controller.h" - -namespace Profile { - -using UpdateFlag = Notify::PeerUpdate::Flag; - -ChannelMembersWidget::ChannelMembersWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_participants_section)) { - auto observeEvents = UpdateFlag::ChannelRightsChanged - | UpdateFlag::AdminsChanged - | UpdateFlag::MembersChanged; - subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) { - notifyPeerUpdated(update); - })); - - refreshButtons(); -} - -void ChannelMembersWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { - if (update.peer != peer()) { - return; - } - - if (update.flags & (UpdateFlag::ChannelRightsChanged | UpdateFlag::AdminsChanged)) { - refreshAdmins(); - } - if (update.flags & (UpdateFlag::ChannelRightsChanged | UpdateFlag::MembersChanged)) { - refreshMembers(); - } - refreshVisibility(); - - contentSizeUpdated(); -} - -void ChannelMembersWidget::addButton(const QString &text, object_ptr *button, const char *slot) { - if (text.isEmpty()) { - button->destroy(); - } else if (*button) { - (*button)->setText(text); - } else { - button->create(this, text, st::defaultLeftOutlineButton); - (*button)->show(); - connect(*button, SIGNAL(clicked()), this, slot); - } -} - -void ChannelMembersWidget::refreshButtons() { - refreshMembers(); - refreshAdmins(); - - refreshVisibility(); -} - -void ChannelMembersWidget::refreshAdmins() { - auto getAdminsText = [this] { - if (auto channel = peer()->asChannel()) { - if (!channel->isMegagroup() && channel->canViewAdmins()) { - auto adminsCount = qMax(channel->adminsCount(), 1); - return lng_channel_admins_link(lt_count, adminsCount); - } - } - return QString(); - }; - addButton(getAdminsText(), &_admins, SLOT(onAdmins())); - - auto getRecentActionsText = [this] { - if (auto channel = peer()->asChannel()) { - if (!channel->isMegagroup() && (channel->hasAdminRights() || channel->amCreator())) { - return lang(lng_profile_recent_actions); - } - } - return QString(); - }; - addButton(getRecentActionsText(), &_recentActions, SLOT(onRecentActions())); -} - -void ChannelMembersWidget::refreshMembers() { - auto getMembersText = [this]() -> QString { - if (auto channel = peer()->asChannel()) { - if (!channel->isMegagroup() && channel->canViewMembers()) { - int membersCount = qMax(channel->membersCount(), 1); - return lng_channel_members_link(lt_count, membersCount); - } - } - return QString(); - }; - addButton(getMembersText(), &_members, SLOT(onMembers())); -} - -void ChannelMembersWidget::refreshVisibility() { - setVisible(_admins || _members); -} - -int ChannelMembersWidget::resizeGetHeight(int newWidth) { - int newHeight = contentTop(); - - auto resizeButton = [this, &newHeight, newWidth](object_ptr &button) { - if (!button) { - return; - } - - int left = defaultOutlineButtonLeft(); - int availableWidth = newWidth - left - st::profileBlockMarginRight; - accumulate_min(availableWidth, st::profileBlockOneLineWidthMax); - button->resizeToWidth(availableWidth); - button->moveToLeft(left, newHeight); - newHeight += button->height(); - }; - - resizeButton(_members); - resizeButton(_admins); - resizeButton(_recentActions); - - return newHeight; -} - -void ChannelMembersWidget::onMembers() { - if (auto channel = peer()->asChannel()) { - ParticipantsBoxController::Start( - App::wnd()->controller(), - channel, - ParticipantsBoxController::Role::Members); - } -} - -void ChannelMembersWidget::onAdmins() { - if (auto channel = peer()->asChannel()) { - ParticipantsBoxController::Start( - App::wnd()->controller(), - channel, - ParticipantsBoxController::Role::Admins); - } -} - -void ChannelMembersWidget::onRecentActions() { - if (auto channel = peer()->asChannel()) { - if (auto main = App::main()) { - main->showSection( - AdminLog::SectionMemento(channel), - Window::SectionShow()); - } - } -} - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_channel_members.h b/Telegram/SourceFiles/profile/profile_block_channel_members.h deleted file mode 100644 index 0bc23187b9b11e..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_channel_members.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "profile/profile_block_widget.h" - -namespace Ui { -class LeftOutlineButton; -} // namespace Ui - -namespace Notify { -struct PeerUpdate; -} // namespace Notify - -namespace Profile { - -class ChannelMembersWidget : public BlockWidget { - Q_OBJECT - -public: - ChannelMembersWidget(QWidget *parent, PeerData *peer); - -protected: - // Resizes content and counts natural widget height for the desired width. - int resizeGetHeight(int newWidth) override; - -private slots: - void onMembers(); - void onAdmins(); - void onRecentActions(); - -private: - // Observed notifications. - void notifyPeerUpdated(const Notify::PeerUpdate &update); - - void refreshButtons(); - void refreshAdmins(); - void refreshMembers(); - void refreshVisibility(); - - void addButton(const QString &text, object_ptr *button, const char *slot); - - object_ptr _members = { nullptr }; - object_ptr _admins = { nullptr }; - object_ptr _recentActions = { nullptr }; - -}; - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_info.cpp b/Telegram/SourceFiles/profile/profile_block_info.cpp deleted file mode 100644 index ea521500d97844..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_info.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#include "profile/profile_block_info.h" - -#include "styles/style_profile.h" -#include "ui/widgets/labels.h" -#include "ui/widgets/buttons.h" -#include "ui/wrap/slide_wrap.h" -#include "core/click_handler_types.h" -#include "mainwidget.h" -#include "observer_peer.h" -#include "apiwrap.h" -#include "lang/lang_keys.h" -#include "ui/toast/toast.h" -#include "messenger.h" - -namespace Profile { - -constexpr int kCommonGroupsLimit = 20; - -using UpdateFlag = Notify::PeerUpdate::Flag; - -InfoWidget::InfoWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_info_section)) { - auto observeEvents = UpdateFlag::AboutChanged - | UpdateFlag::UsernameChanged - | UpdateFlag::UserPhoneChanged - | UpdateFlag::UserCanShareContact; - subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) { - notifyPeerUpdated(update); - })); - - refreshLabels(); -} - -void InfoWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { - if (update.peer != peer()) { - return; - } - - if (update.flags & UpdateFlag::AboutChanged) { - refreshAbout(); - } - if (update.flags & UpdateFlag::UsernameChanged) { - refreshUsername(); - refreshChannelLink(); - } - if (update.flags & (UpdateFlag::UserPhoneChanged | UpdateFlag::UserCanShareContact)) { - refreshMobileNumber(); - } - refreshVisibility(); - - contentSizeUpdated(); -} - -int InfoWidget::resizeGetHeight(int newWidth) { - int initialHeight = contentTop(); - int newHeight = initialHeight; - - int marginLeft = st::profileBlockTextPart.margin.left(); - int marginRight = st::profileBlockTextPart.margin.right(); - int left = st::profileBlockTitlePosition.x(); - if (_about) { - int textWidth = _about->naturalWidth(); - int availableWidth = newWidth - left - st::profileBlockMarginRight; - int maxWidth = st::msgMaxWidth; - accumulate_min(textWidth, availableWidth); - accumulate_min(textWidth, st::msgMaxWidth); - _about->resizeToWidth(textWidth + marginLeft + marginRight); - _about->moveToLeft(left - marginLeft, newHeight - st::profileBlockTextPart.margin.top()); - newHeight += _about->height(); - } - - auto moveLabeledText = [&newHeight, left, newWidth, marginLeft, marginRight](Ui::FlatLabel *label, Ui::FlatLabel *text, Ui::FlatLabel *shortText) { - if (!label) return; - - label->moveToLeft(left, newHeight); - int textLeft = left + label->width() + st::normalFont->spacew; - int textWidth = text->naturalWidth(); - int availableWidth = newWidth - textLeft - st::profileBlockMarginRight; - bool doesNotFit = (textWidth > availableWidth); - accumulate_min(textWidth, availableWidth); - accumulate_min(textWidth, st::msgMaxWidth); - text->resizeToWidth(textWidth + marginLeft + marginRight); - text->moveToLeft(textLeft - marginLeft, newHeight - st::profileBlockOneLineTextPart.margin.top()); - if (shortText) { - shortText->resizeToWidth(textWidth + marginLeft + marginRight); - shortText->moveToLeft(textLeft - marginLeft, newHeight - st::profileBlockOneLineTextPart.margin.top()); - if (doesNotFit) { - shortText->show(); - text->hide(); - } else { - shortText->hide(); - text->show(); - } - } - newHeight += qMax(label->height(), text->height() - st::profileBlockTextPart.margin.top() - st::profileBlockTextPart.margin.bottom()) + st::profileBlockOneLineSkip; - }; - moveLabeledText(_channelLinkLabel, _channelLink, _channelLinkShort); - moveLabeledText(_mobileNumberLabel, _mobileNumber, nullptr); - moveLabeledText(_bioLabel, _bio, nullptr); - moveLabeledText(_usernameLabel, _username, nullptr); - - newHeight += st::profileBlockMarginBottom; - return newHeight; -} - -void InfoWidget::leaveEventHook(QEvent *e) { - BotCommandClickHandler::setPeerForCommand(nullptr); - BotCommandClickHandler::setBotForCommand(nullptr); -} - -void InfoWidget::refreshLabels() { - refreshAbout(); - refreshMobileNumber(); - refreshUsername(); - refreshChannelLink(); - - refreshVisibility(); -} - -void InfoWidget::refreshVisibility() { - setVisible(_about || _mobileNumber || _username || _bio || _channelLink); -} - -void InfoWidget::refreshAbout() { - auto getAboutText = [this]() -> QString { - if (auto user = peer()->asUser()) { - return user->about(); - } else if (auto channel = peer()->asChannel()) { - return channel->about(); - } - return QString(); - }; - - _about.destroy(); - _bioLabel.destroy(); - _bio.destroy(); - auto aboutText = TextWithEntities { TextUtilities::Clean(getAboutText()) }; - auto displayAsBio = false; - if (auto user = peer()->asUser()) { - if (!user->botInfo) { - displayAsBio = true; - } - } - if (displayAsBio) { - aboutText.text = TextUtilities::SingleLine(aboutText.text); - } - if (!aboutText.text.isEmpty()) { - if (displayAsBio) { - setLabeledText(&_bioLabel, lang(lng_profile_bio), &_bio, aboutText, st::profileBioLabel, QString()); - } else { - _about.create(this, st::profileBlockTextPart); - _about->show(); - - TextUtilities::ParseEntities(aboutText, TextParseLinks | TextParseMentions | TextParseHashtags | TextParseBotCommands); - _about->setMarkedText(aboutText); - _about->setSelectable(true); - _about->setClickHandlerHook([this](const ClickHandlerPtr &handler, Qt::MouseButton button) { - BotCommandClickHandler::setPeerForCommand(peer()); - return true; - }); - } - } -} - -void InfoWidget::refreshMobileNumber() { - TextWithEntities phoneText; - if (auto user = peer()->asUser()) { - if (!user->phone().isEmpty()) { - phoneText.text = App::formatPhone(user->phone()); - } else { - phoneText.text = App::phoneFromSharedContact(peerToUser(user->id)); - } - } - setSingleLineLabeledText(&_mobileNumberLabel, lang(lng_profile_mobile_number), &_mobileNumber, phoneText, lang(lng_profile_copy_phone)); -} - -void InfoWidget::refreshUsername() { - TextWithEntities usernameText; - if (auto user = peer()->asUser()) { - if (!user->username.isEmpty()) { - usernameText.text = '@' + user->username; - } - } - setSingleLineLabeledText(&_usernameLabel, lang(lng_profile_username), &_username, usernameText, lang(lng_context_copy_mention)); -} - -void InfoWidget::refreshChannelLink() { - TextWithEntities channelLinkText; - TextWithEntities channelLinkTextShort; - if (auto channel = peer()->asChannel()) { - if (!channel->username.isEmpty()) { - channelLinkText.text = Messenger::Instance().createInternalLinkFull(channel->username); - channelLinkText.entities.push_back(EntityInText(EntityInTextUrl, 0, channelLinkText.text.size())); - channelLinkTextShort.text = Messenger::Instance().createInternalLink(channel->username); - channelLinkTextShort.entities.push_back(EntityInText(EntityInTextCustomUrl, 0, channelLinkTextShort.text.size(), Messenger::Instance().createInternalLinkFull(channel->username))); - } - } - setSingleLineLabeledText(nullptr, lang(lng_profile_link), &_channelLink, channelLinkText, QString()); - setSingleLineLabeledText(&_channelLinkLabel, lang(lng_profile_link), &_channelLinkShort, channelLinkTextShort, QString()); - auto copyLinkHandlerHook = [this](const ClickHandlerPtr &handler, Qt::MouseButton button) { - if (auto channel = peer()->asChannel()) { - auto link = Messenger::Instance().createInternalLinkFull(channel->username); - QGuiApplication::clipboard()->setText(link); - Ui::Toast::Show(lang(lng_create_channel_link_copied)); - return false; - } - return true; - }; - if (_channelLink) { - _channelLink->setClickHandlerHook(copyLinkHandlerHook); - } - if (_channelLinkShort) { - _channelLinkShort->setExpandLinksMode(ExpandLinksUrlOnly); - _channelLinkShort->setClickHandlerHook(copyLinkHandlerHook); - } -} - -void InfoWidget::setLabeledText(object_ptr *labelWidget, const QString &label, - object_ptr *textWidget, const TextWithEntities &textWithEntities, - const style::FlatLabel &st, const QString ©Text) { - if (labelWidget) labelWidget->destroy(); - textWidget->destroy(); - if (textWithEntities.text.isEmpty()) { - return; - } - - if (labelWidget) { - labelWidget->create(this, label, Ui::FlatLabel::InitType::Simple, st::profileBlockLabel); - (*labelWidget)->show(); - } - textWidget->create(this, QString(), Ui::FlatLabel::InitType::Simple, st); - (*textWidget)->show(); - (*textWidget)->setMarkedText(textWithEntities); - (*textWidget)->setContextCopyText(copyText); - (*textWidget)->setSelectable(true); -} - -void InfoWidget::setSingleLineLabeledText(object_ptr *labelWidget, const QString &label, - object_ptr *textWidget, const TextWithEntities &textWithEntities, const QString ©Text) { - setLabeledText(labelWidget, label, textWidget, textWithEntities, st::profileBlockOneLineTextPart, copyText); - if (*textWidget) { - (*textWidget)->setDoubleClickSelectsParagraph(true); - } -} - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_info.h b/Telegram/SourceFiles/profile/profile_block_info.h deleted file mode 100644 index 8873c13d5373b1..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_info.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "profile/profile_block_widget.h" - -namespace style { -struct FlatLabel; -} // namespace style - -namespace Ui { -class FlatLabel; -} // namespace Ui - -namespace Notify { -struct PeerUpdate; -} // namespace Notify - -namespace Profile { - -class InfoWidget : public BlockWidget, public RPCSender { -public: - InfoWidget(QWidget *parent, PeerData *peer); - -protected: - // Resizes content and counts natural widget height for the desired width. - int resizeGetHeight(int newWidth) override; - - void leaveEventHook(QEvent *e) override; - -private: - // Observed notifications. - void notifyPeerUpdated(const Notify::PeerUpdate &update); - - void refreshLabels(); - void refreshAbout(); - void refreshMobileNumber(); - void refreshUsername(); - void refreshChannelLink(); - void refreshVisibility(); - - // labelWidget may be nullptr. - void setLabeledText(object_ptr *labelWidget, const QString &label, - object_ptr *textWidget, const TextWithEntities &textWithEntities, - const style::FlatLabel &st, const QString ©Text); - void setSingleLineLabeledText(object_ptr *labelWidget, const QString &label, - object_ptr *textWidget, const TextWithEntities &textWithEntities, const QString ©Text); - - object_ptr _about = { nullptr }; - object_ptr _channelLinkLabel = { nullptr }; - object_ptr _channelLink = { nullptr }; - object_ptr _channelLinkShort = { nullptr }; - object_ptr _mobileNumberLabel = { nullptr }; - object_ptr _mobileNumber = { nullptr }; - object_ptr _bioLabel = { nullptr }; - object_ptr _bio = { nullptr }; - object_ptr _usernameLabel = { nullptr }; - object_ptr _username = { nullptr }; - -}; - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_invite_link.cpp b/Telegram/SourceFiles/profile/profile_block_invite_link.cpp deleted file mode 100644 index 12bc7a20bfbe85..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_invite_link.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#include "profile/profile_block_invite_link.h" - -#include "styles/style_profile.h" -#include "ui/widgets/labels.h" -#include "ui/toast/toast.h" -#include "boxes/confirm_box.h" -#include "observer_peer.h" -#include "mainwindow.h" -#include "lang/lang_keys.h" - -namespace Profile { - -using UpdateFlag = Notify::PeerUpdate::Flag; - -InviteLinkWidget::InviteLinkWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_invite_link_section)) { - auto observeEvents = UpdateFlag::InviteLinkChanged | UpdateFlag::UsernameChanged; - subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) { - notifyPeerUpdated(update); - })); - - refreshLink(); - refreshVisibility(); -} - -void InviteLinkWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { - if (update.peer != peer()) { - return; - } - - if (update.flags & (UpdateFlag::InviteLinkChanged | UpdateFlag::UsernameChanged)) { - refreshLink(); - refreshVisibility(); - - contentSizeUpdated(); - } -} - -int InviteLinkWidget::resizeGetHeight(int newWidth) { - int newHeight = contentTop(); - - int marginLeft = st::profileBlockTextPart.margin.left(); - int marginRight = st::profileBlockTextPart.margin.right(); - int left = st::profileBlockTitlePosition.x(); - if (_link) { - int textWidth = _link->naturalWidth(); - int availableWidth = newWidth - left - st::profileBlockMarginRight; - int maxWidth = st::msgMaxWidth; - accumulate_min(textWidth, availableWidth); - accumulate_min(textWidth, st::msgMaxWidth); - _link->resizeToWidth(textWidth + marginLeft + marginRight); - _link->moveToLeft(left - marginLeft, newHeight - st::profileBlockTextPart.margin.top()); - newHeight += _link->height(); - } - - newHeight += st::profileBlockMarginBottom; - return newHeight; -} - -void InviteLinkWidget::refreshVisibility() { - setVisible(_link != nullptr); -} - -QString InviteLinkWidget::getInviteLink() const { - if (auto chat = peer()->asChat()) { - return chat->inviteLink(); - } else if (auto channel = peer()->asChannel()) { - return channel->isPublic() ? QString() : channel->inviteLink(); - } - return QString(); -}; - -void InviteLinkWidget::refreshLink() { - _link.destroy(); - TextWithEntities linkData = { getInviteLink(), EntitiesInText() }; - if (linkData.text.isEmpty()) { - _link.destroy(); - } else { - _link.create(this, QString(), Ui::FlatLabel::InitType::Simple, st::profileInviteLinkText); - _link->show(); - - linkData.entities.push_back(EntityInText(EntityInTextUrl, 0, linkData.text.size())); - _link->setMarkedText(linkData); - _link->setSelectable(true); - _link->setContextCopyText(QString()); - _link->setClickHandlerHook([this](const ClickHandlerPtr &handler, Qt::MouseButton button) { - auto link = getInviteLink(); - if (link.isEmpty()) { - return true; - } - - QApplication::clipboard()->setText(link); - Ui::Toast::Show(lang(lng_group_invite_copied)); - return false; - }); - } -} - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_invite_link.h b/Telegram/SourceFiles/profile/profile_block_invite_link.h deleted file mode 100644 index 0e0363164a5918..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_invite_link.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "profile/profile_block_widget.h" - -namespace Ui { -class FlatLabel; -} // namespace Ui - -namespace Notify { -struct PeerUpdate; -} // namespace Notify - -namespace Profile { - -class InviteLinkWidget : public BlockWidget { -public: - InviteLinkWidget(QWidget *parent, PeerData *peer); - -protected: - // Resizes content and counts natural widget height for the desired width. - int resizeGetHeight(int newWidth) override; - -private: - // Observed notifications. - void notifyPeerUpdated(const Notify::PeerUpdate &update); - - QString getInviteLink() const; - void refreshLink(); - void refreshVisibility(); - - object_ptr _link = { nullptr }; - -}; - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_settings.cpp b/Telegram/SourceFiles/profile/profile_block_settings.cpp deleted file mode 100644 index 6f87292de01063..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_settings.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#include "profile/profile_block_settings.h" - -#include "profile/profile_channel_controllers.h" -#include "history/history_admin_log_section.h" -#include "styles/style_profile.h" -#include "ui/widgets/buttons.h" -#include "ui/widgets/checkbox.h" -#include "boxes/peer_list_controllers.h" -#include "boxes/confirm_box.h" -#include "observer_peer.h" -#include "auth_session.h" -#include "mainwidget.h" -#include "mainwindow.h" -#include "window/window_controller.h" -#include "apiwrap.h" -#include "lang/lang_keys.h" - -namespace Profile { - -using UpdateFlag = Notify::PeerUpdate::Flag; - -SettingsWidget::SettingsWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_settings_section)) -, _enableNotifications(this, lang(lng_profile_enable_notifications), true, st::defaultCheckbox) { - subscribe(_enableNotifications->checkedChanged, [this](bool checked) { onNotificationsChange(); }); - - Notify::PeerUpdate::Flags observeEvents = UpdateFlag::NotificationsEnabled; - if (auto chat = peer->asChat()) { - if (chat->amCreator()) { - observeEvents |= UpdateFlag::ChatCanEdit | UpdateFlag::InviteLinkChanged; - } - } else if (auto channel = peer->asChannel()) { - observeEvents |= UpdateFlag::ChannelRightsChanged | UpdateFlag::BannedUsersChanged | UpdateFlag::UsernameChanged | UpdateFlag::InviteLinkChanged; - } - subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) { - notifyPeerUpdated(update); - })); - - refreshButtons(); - _enableNotifications->finishAnimating(); - - show(); -} - -void SettingsWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { - if (update.peer != peer()) { - return; - } - - if (update.flags & UpdateFlag::NotificationsEnabled) { - refreshEnableNotifications(); - } - if (update.flags & (UpdateFlag::ChannelRightsChanged | UpdateFlag::ChatCanEdit | UpdateFlag::UsernameChanged | UpdateFlag::InviteLinkChanged)) { - refreshInviteLinkButton(); - } - if (update.flags & (UpdateFlag::ChannelRightsChanged | UpdateFlag::ChatCanEdit)) { - refreshManageAdminsButton(); - } - if (update.flags & (UpdateFlag::ChannelRightsChanged | UpdateFlag::BannedUsersChanged)) { - refreshManageBannedUsersButton(); - } - - contentSizeUpdated(); -} - -int SettingsWidget::resizeGetHeight(int newWidth) { - int newHeight = contentTop() + st::profileEnableNotificationsTop; - - _enableNotifications->moveToLeft(st::profileBlockTitlePosition.x(), newHeight); - newHeight += _enableNotifications->heightNoMargins() + st::profileSettingsBlockSkip; - - auto moveLink = [&newHeight, newWidth](Ui::LeftOutlineButton *button) { - if (!button) return; - - int left = defaultOutlineButtonLeft(); - int availableWidth = newWidth - left - st::profileBlockMarginRight; - accumulate_min(availableWidth, st::profileBlockOneLineWidthMax); - button->resizeToWidth(availableWidth); - button->moveToLeft(left, newHeight); - newHeight += button->height(); - }; - moveLink(_manageAdmins); - moveLink(_recentActions); - moveLink(_manageBannedUsers); - moveLink(_manageRestrictedUsers); - moveLink(_inviteLink); - - newHeight += st::profileBlockMarginBottom; - return newHeight; -} - -void SettingsWidget::refreshButtons() { - refreshEnableNotifications(); - refreshManageAdminsButton(); - refreshManageBannedUsersButton(); - refreshInviteLinkButton(); -} - -void SettingsWidget::refreshEnableNotifications() { - if (peer()->notify == UnknownNotifySettings) { - Auth().api().requestNotifySetting(peer()); - } else { - auto ¬ifySettings = peer()->notify; - bool enabled = (notifySettings == EmptyNotifySettings || notifySettings->mute < unixtime()); - _enableNotifications->setChecked(enabled, Ui::Checkbox::NotifyAboutChange::DontNotify); - } -} - -void SettingsWidget::refreshManageAdminsButton() { - auto hasManageAdmins = [this] { - if (auto chat = peer()->asChat()) { - return (chat->amCreator() && chat->canEdit()); - } else if (auto channel = peer()->asMegagroup()) { - return channel->hasAdminRights() || channel->amCreator(); - } - return false; - }; - _manageAdmins.destroy(); - if (hasManageAdmins()) { - _manageAdmins.create(this, lang(lng_profile_manage_admins), st::defaultLeftOutlineButton); - _manageAdmins->show(); - connect(_manageAdmins, SIGNAL(clicked()), this, SLOT(onManageAdmins())); - } - - auto hasRecentActions = [this] { - if (auto channel = peer()->asMegagroup()) { - return channel->hasAdminRights() || channel->amCreator(); - } - return false; - }; - _recentActions.destroy(); - if (hasRecentActions()) { - _recentActions.create(this, lang(lng_profile_recent_actions), st::defaultLeftOutlineButton); - _recentActions->show(); - connect(_recentActions, SIGNAL(clicked()), this, SLOT(onRecentActions())); - } -} - -void SettingsWidget::refreshManageBannedUsersButton() { - auto hasManageBannedUsers = [this] { - if (auto channel = peer()->asMegagroup()) { - return channel->canViewBanned() && (channel->kickedCount() > 0); - } - return false; - }; - _manageBannedUsers.destroy(); - if (hasManageBannedUsers()) { - _manageBannedUsers.create(this, lang(lng_profile_manage_blocklist), st::defaultLeftOutlineButton); - _manageBannedUsers->show(); - connect(_manageBannedUsers, SIGNAL(clicked()), this, SLOT(onManageBannedUsers())); - } - - auto hasManageRestrictedUsers = [this] { - if (auto channel = peer()->asMegagroup()) { - return channel->canViewBanned() && (channel->restrictedCount() > 0); - } - return false; - }; - _manageRestrictedUsers.destroy(); - if (hasManageRestrictedUsers()) { - _manageRestrictedUsers.create(this, lang(lng_profile_manage_restrictedlist), st::defaultLeftOutlineButton); - _manageRestrictedUsers->show(); - connect(_manageRestrictedUsers, SIGNAL(clicked()), this, SLOT(onManageRestrictedUsers())); - } -} - -void SettingsWidget::refreshInviteLinkButton() { - auto getInviteLinkText = [this]() -> QString { - if (auto chat = peer()->asChat()) { - if (chat->amCreator() && chat->canEdit()) { - return lang(chat->inviteLink().isEmpty() ? lng_group_invite_create : lng_group_invite_create_new); - } - } else if (auto channel = peer()->asChannel()) { - if (channel->canHaveInviteLink() && !channel->isPublic()) { - return lang(channel->inviteLink().isEmpty() ? lng_group_invite_create : lng_group_invite_create_new); - } - } - return QString(); - }; - auto inviteLinkText = getInviteLinkText(); - if (inviteLinkText.isEmpty()) { - _inviteLink.destroy(); - } else { - _inviteLink.create(this, inviteLinkText, st::defaultLeftOutlineButton); - _inviteLink->show(); - connect(_inviteLink, SIGNAL(clicked()), this, SLOT(onInviteLink())); - } -} - -void SettingsWidget::onNotificationsChange() { - App::main()->updateNotifySetting(peer(), _enableNotifications->checked() ? NotifySettingSetNotify : NotifySettingSetMuted); -} - -void SettingsWidget::onManageAdmins() { - if (auto chat = peer()->asChat()) { - EditChatAdminsBoxController::Start(chat); - } else if (auto channel = peer()->asChannel()) { - ParticipantsBoxController::Start( - App::wnd()->controller(), - channel, - ParticipantsBoxController::Role::Admins); - } -} - -void SettingsWidget::onRecentActions() { - if (auto channel = peer()->asChannel()) { - if (auto main = App::main()) { - main->showSection( - AdminLog::SectionMemento(channel), - Window::SectionShow()); - } - } -} - -void SettingsWidget::onManageBannedUsers() { - if (auto channel = peer()->asMegagroup()) { - ParticipantsBoxController::Start( - App::wnd()->controller(), - channel, - ParticipantsBoxController::Role::Kicked); - } -} - -void SettingsWidget::onManageRestrictedUsers() { - if (auto channel = peer()->asMegagroup()) { - ParticipantsBoxController::Start( - App::wnd()->controller(), - channel, - ParticipantsBoxController::Role::Restricted); - } -} - -void SettingsWidget::onInviteLink() { - auto getInviteLink = [this]() { - if (auto chat = peer()->asChat()) { - return chat->inviteLink(); - } else if (auto channel = peer()->asChannel()) { - return channel->inviteLink(); - } - return QString(); - }; - auto link = getInviteLink(); - - auto text = lang(link.isEmpty() ? lng_group_invite_about : lng_group_invite_about_new); - Ui::show(Box(text, base::lambda_guarded(this, [this] { - Ui::hideLayer(); - Auth().api().exportInviteLink(peer()); - }))); -} - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_settings.h b/Telegram/SourceFiles/profile/profile_block_settings.h deleted file mode 100644 index 35dd865131fb4f..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_settings.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "profile/profile_block_widget.h" - -namespace Ui { -class Checkbox; -class LeftOutlineButton; -} // namespace Ui - -namespace Notify { -struct PeerUpdate; -} // namespace Notify - -namespace Profile { - -class SettingsWidget : public BlockWidget { - Q_OBJECT - -public: - SettingsWidget(QWidget *parent, PeerData *peer); - -protected: - // Resizes content and counts natural widget height for the desired width. - int resizeGetHeight(int newWidth) override; - -private slots: - void onNotificationsChange(); - void onManageAdmins(); - void onRecentActions(); - void onManageBannedUsers(); - void onManageRestrictedUsers(); - void onInviteLink(); - -private: - // Observed notifications. - void notifyPeerUpdated(const Notify::PeerUpdate &update); - - void refreshButtons(); - void refreshEnableNotifications(); - void refreshManageAdminsButton(); - void refreshManageBannedUsersButton(); - void refreshInviteLinkButton(); - - object_ptr _enableNotifications; - object_ptr _manageAdmins = { nullptr }; - object_ptr _recentActions = { nullptr }; - object_ptr _manageBannedUsers = { nullptr }; - object_ptr _manageRestrictedUsers = { nullptr }; - object_ptr _inviteLink = { nullptr }; - -}; - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_shared_media.cpp b/Telegram/SourceFiles/profile/profile_block_shared_media.cpp deleted file mode 100644 index 41249f57c83c6e..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_shared_media.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#include "profile/profile_block_shared_media.h" - -#include "profile/profile_common_groups_section.h" -#include "profile/profile_section_memento.h" -#include "styles/style_profile.h" -#include "observer_peer.h" -#include "ui/widgets/buttons.h" -#include "mainwidget.h" -#include "lang/lang_keys.h" -#include "window/window_controller.h" - -namespace Profile { -namespace { - -QString getButtonText(MediaOverviewType type, int count) { - if (count <= 0) { - return QString(); - } - - switch (type) { - case OverviewPhotos: return lng_profile_photos(lt_count, count); - case OverviewVideos: return lng_profile_videos(lt_count, count); - case OverviewMusicFiles: return lng_profile_songs(lt_count, count); - case OverviewFiles: return lng_profile_files(lt_count, count); - case OverviewVoiceFiles: return lng_profile_audios(lt_count, count); - case OverviewLinks: return lng_profile_shared_links(lt_count, count); - } - return QString(); -} - -} // namespace - -SharedMediaWidget::SharedMediaWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_shared_media)) -, _history(App::history(peer)) -, _migrated(_history->migrateFrom()) { - auto observeEvents = Notify::PeerUpdate::Flag::SharedMediaChanged - | Notify::PeerUpdate::Flag::UserCommonChatsChanged; - subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) { - notifyPeerUpdated(update); - })); - - for (auto i = 0; i != OverviewCount; ++i) { - auto type = static_cast(i); - if (!getButtonText(type, 1).isEmpty()) { - App::main()->preloadOverview(peer, type); - if (_migrated) { - App::main()->preloadOverview(_migrated->peer, type); - } - } - } - - refreshButtons(); - refreshVisibility(); -} - -void SharedMediaWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { - if (update.peer != peer() && (!_migrated || update.peer != _migrated->peer)) { - return; - } - - auto updated = false; - for (auto i = 0; i != OverviewCount; ++i) { - if (update.mediaTypesMask & (1 << i)) { - refreshButton(static_cast(i)); - updated = true; - } - } - if (update.flags & Notify::PeerUpdate::Flag::UserCommonChatsChanged) { - refreshCommonGroups(); - updated = true; - } - if (updated) { - refreshVisibility(); - - contentSizeUpdated(); - } -} - -int SharedMediaWidget::resizeGetHeight(int newWidth) { - int newHeight = contentTop(); - - resizeButtons(newWidth, &newHeight); - - return newHeight; -} - -void SharedMediaWidget::refreshButtons() { - for (int typeIndex = 0; typeIndex < OverviewCount; ++typeIndex) { - refreshButton(static_cast(typeIndex)); - } - refreshCommonGroups(); -} - -void SharedMediaWidget::refreshButton(MediaOverviewType type) { - int count = _history->overviewCount(type), migrated = _migrated ? _migrated->overviewCount(type) : 0; - int finalCount = (count >= 0 && migrated >= 0) ? (count + migrated) : -1; - auto text = getButtonText(type, finalCount); - if (text.isEmpty()) { - if (_mediaButtons[type]) { - delete _mediaButtons[type]; - _mediaButtons[type] = nullptr; - } - } else { - if (_mediaButtons[type]) { - _mediaButtons[type]->setText(text); - } else { - _mediaButtons[type] = new Ui::LeftOutlineButton(this, text, st::defaultLeftOutlineButton); - _mediaButtons[type]->show(); - connect(_mediaButtons[type], SIGNAL(clicked()), this, SLOT(onMediaChosen())); - } - } -} - -void SharedMediaWidget::refreshVisibility() { - for_const (auto button, _mediaButtons) { - if (button) { - show(); - return; - } - } - setVisible(_commonGroups != nullptr); -} - -void SharedMediaWidget::onMediaChosen() { - for (int i = 0; i < OverviewCount; ++i) { - auto button = _mediaButtons[i]; - if (button && button == sender()) { - // SharedMediaShowOverview(); - return; - } - } -} - -void SharedMediaWidget::resizeButtons(int newWidth, int *top) { - Assert(top != nullptr); - - int left = defaultOutlineButtonLeft(); - int availableWidth = newWidth - left - st::profileBlockMarginRight; - accumulate_min(availableWidth, st::profileBlockOneLineWidthMax); - for_const (auto button, _mediaButtons) { - if (!button) continue; - - button->resizeToWidth(availableWidth); - button->moveToLeft(left, *top); - *top += button->height(); - } - - if (_commonGroups) { - _commonGroups->resizeToWidth(availableWidth); - _commonGroups->moveToLeft(left, *top); - *top += _commonGroups->height(); - } - -} - -int SharedMediaWidget::getCommonGroupsCount() const { - if (auto user = peer()->asUser()) { - return user->commonChatsCount(); - } - return 0; -} - -void SharedMediaWidget::refreshCommonGroups() { - if (auto count = getCommonGroupsCount()) { - auto text = lng_profile_common_groups(lt_count, count); - if (_commonGroups) { - _commonGroups->setText(text); - } else { - _commonGroups.create(this, text, st::defaultLeftOutlineButton); - _commonGroups->setClickedCallback([this] { onShowCommonGroups(); }); - _commonGroups->show(); - } - } else if (_commonGroups) { - _commonGroups.destroyDelayed(); - } -} - -void SharedMediaWidget::onShowCommonGroups() { - auto count = getCommonGroupsCount(); - if (count <= 0) { - refreshCommonGroups(); - return; - } - if (auto main = App::main()) { - main->showSection( - Profile::CommonGroups::SectionMemento(peer()->asUser()), - Window::SectionShow()); - } -} - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_shared_media.h b/Telegram/SourceFiles/profile/profile_block_shared_media.h deleted file mode 100644 index f9a28c8feb8d76..00000000000000 --- a/Telegram/SourceFiles/profile/profile_block_shared_media.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "profile/profile_block_widget.h" - -namespace Ui { -class LeftOutlineButton; -} // namespace Ui - -namespace Notify { -struct PeerUpdate; -} // namespace Notify - -namespace Profile { - -class SharedMediaWidget : public BlockWidget { - Q_OBJECT - -public: - SharedMediaWidget(QWidget *parent, PeerData *peer); - -protected: - // Resizes content and counts natural widget height for the desired width. - int resizeGetHeight(int newWidth) override; - -private slots: - void onMediaChosen(); - -private: - // Observed notifications. - void notifyPeerUpdated(const Notify::PeerUpdate &update); - - void refreshButtons(); - void refreshButton(MediaOverviewType type); - void refreshCommonGroups(); - void refreshVisibility(); - - int getCommonGroupsCount() const; - void onShowCommonGroups(); - void slideCommonGroupsDown(); - - void resizeButtons(int newWidth, int *top); - - Ui::LeftOutlineButton *_mediaButtons[OverviewCount] = { nullptr }; - object_ptr _commonGroups = { nullptr }; - - History *_history; - History *_migrated; - -}; - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp index ac18bb556a0ffa..5b2b21a1882f75 100644 --- a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp +++ b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp @@ -331,6 +331,10 @@ void ParticipantsBoxController::restoreState( } } +rpl::producer ParticipantsBoxController::onlineCountValue() const { + return _onlineCount.value(); +} + template void ParticipantsBoxController::HandleParticipant(const MTPChannelParticipant &participant, Role role, not_null additional, Callback callback) { if ((role == Role::Profile diff --git a/Telegram/SourceFiles/profile/profile_channel_controllers.h b/Telegram/SourceFiles/profile/profile_channel_controllers.h index d0e4417e67b34a..4f3ea6c2a6a97b 100644 --- a/Telegram/SourceFiles/profile/profile_channel_controllers.h +++ b/Telegram/SourceFiles/profile/profile_channel_controllers.h @@ -95,9 +95,7 @@ class ParticipantsBoxController not_null additional, Callback callback); - rpl::producer onlineCountValue() const override { - return _onlineCount.value(); - } + rpl::producer onlineCountValue() const override; protected: virtual std::unique_ptr createRow(not_null user) const; diff --git a/Telegram/SourceFiles/profile/profile_common_groups_section.cpp b/Telegram/SourceFiles/profile/profile_common_groups_section.cpp deleted file mode 100644 index 04020254128027..00000000000000 --- a/Telegram/SourceFiles/profile/profile_common_groups_section.cpp +++ /dev/null @@ -1,470 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#include "profile/profile_common_groups_section.h" - -#include "profile/profile_section_memento.h" -#include "profile/profile_back_button.h" -#include "styles/style_widgets.h" -#include "styles/style_profile.h" -#include "styles/style_window.h" -#include "styles/style_settings.h" -#include "ui/effects/ripple_animation.h" -#include "ui/widgets/scroll_area.h" -#include "ui/widgets/shadow.h" -#include "mainwidget.h" -#include "observer_peer.h" -#include "apiwrap.h" -#include "lang/lang_keys.h" -#include "mainwindow.h" -#include "window/window_controller.h" - -namespace Profile { -namespace CommonGroups { -namespace { - -constexpr int kCommonGroupsPerPage = 40; - -} // namespace - -object_ptr SectionMemento::createWidget( - QWidget *parent, - not_null controller, - Window::Column column, - const QRect &geometry) { - auto result = object_ptr(parent, controller, _user); - result->setInternalState(geometry, this); - return std::move(result); -} - -FixedBar::FixedBar(QWidget *parent) : TWidget(parent) -, _backButton(this, lang(lng_profile_common_groups_section)) { - _backButton->moveToLeft(0, 0); - connect(_backButton, SIGNAL(clicked()), this, SLOT(onBack())); -} - -void FixedBar::onBack() { - App::main()->showBackFromStack(Window::SectionShow()); -} - -int FixedBar::resizeGetHeight(int newWidth) { - auto newHeight = 0; - - auto buttonLeft = newWidth; - _backButton->resizeToWidth(newWidth); - _backButton->moveToLeft(0, 0); - newHeight += _backButton->height(); - - return newHeight; -} - -void FixedBar::setAnimatingMode(bool enabled) { - if (_animatingMode != enabled) { - _animatingMode = enabled; - setCursor(_animatingMode ? style::cur_pointer : style::cur_default); - if (_animatingMode) { - setAttribute(Qt::WA_OpaquePaintEvent, false); - hideChildren(); - } else { - setAttribute(Qt::WA_OpaquePaintEvent); - showChildren(); - } - show(); - } -} - -void FixedBar::mousePressEvent(QMouseEvent *e) { - if (e->button() == Qt::LeftButton) { - onBack(); - } else { - TWidget::mousePressEvent(e); - } -} - -InnerWidget::Item::Item(PeerData *peer) : peer(peer) { -} - -InnerWidget::Item::~Item() = default; - -InnerWidget::InnerWidget(QWidget *parent, not_null user) : TWidget(parent) -, _user(user) { - setMouseTracking(true); - setAttribute(Qt::WA_OpaquePaintEvent); - _rowHeight = st::profileCommonGroupsPadding.top() + st::profileCommonGroupsPhotoSize + st::profileCommonGroupsPadding.bottom(); - _contentTop = st::profileCommonGroupsSkip; -} - -void InnerWidget::visibleTopBottomUpdated( - int visibleTop, - int visibleBottom) { - _visibleTop = visibleTop; - _visibleBottom = visibleBottom; - - checkPreloadMore(); -} - -void InnerWidget::checkPreloadMore() { - if (_visibleTop + PreloadHeightsCount * (_visibleBottom - _visibleTop) > height()) { - preloadMore(); - } -} - -void InnerWidget::saveState(not_null memento) { - if (auto count = _items.size()) { - QList> groups; - groups.reserve(count); - for_const (auto item, _items) { - groups.push_back(item->peer); - } - memento->setCommonGroups(groups); - } -} - -void InnerWidget::restoreState(not_null memento) { - auto list = memento->getCommonGroups(); - _allLoaded = false; - if (!list.empty()) { - showInitial(list); - } -} - -void InnerWidget::showInitial(const QList> &list) { - for_const (auto group, list) { - if (auto item = computeItem(group)) { - _items.push_back(item); - } - _preloadGroupId = group->bareId(); - } - updateSize(); -} - -void InnerWidget::preloadMore() { - if (_preloadRequestId || _allLoaded) { - return; - } - auto request = MTPmessages_GetCommonChats(user()->inputUser, MTP_int(_preloadGroupId), MTP_int(kCommonGroupsPerPage)); - _preloadRequestId = MTP::send(request, ::rpcDone(base::lambda_guarded(this, [this](const MTPmessages_Chats &result) { - _preloadRequestId = 0; - _preloadGroupId = 0; - _allLoaded = true; - if (auto chats = Api::getChatsFromMessagesChats(result)) { - auto &list = chats->v; - if (!list.empty()) { - _items.reserve(_items.size() + list.size()); - for_const (auto &chatData, list) { - if (auto chat = App::feedChat(chatData)) { - auto found = false; - for_const (auto item, _items) { - if (item->peer == chat) { - found = true; - break; - } - } - if (!found) { - if (auto item = computeItem(chat)) { - _items.push_back(item); - } - } - _preloadGroupId = chat->bareId(); - _allLoaded = false; - } - } - updateSize(); - } - } - }))); -} - -void InnerWidget::updateSize() { - TWidget::resizeToWidth(width()); - checkPreloadMore(); -} - -int InnerWidget::resizeGetHeight(int newWidth) { - update(); - - auto contentLeftMin = st::profileCommonGroupsLeftMin; - auto contentLeftMax = st::profileCommonGroupsLeftMax; - auto widthWithMin = st::columnMinimalWidthMain; - auto widthWithMax = st::profileCommonGroupsWidthMax + 2 * contentLeftMax; - _contentLeft = anim::interpolate(contentLeftMax, contentLeftMin, qMax(widthWithMax - newWidth, 0) / float64(widthWithMax - widthWithMin)); - _contentWidth = qMin(newWidth - 2 * _contentLeft, st::profileCommonGroupsWidthMax); - - auto newHeight = _contentTop; - newHeight += _items.size() * _rowHeight; - newHeight += st::profileCommonGroupsSkip; - return qMax(newHeight, _minHeight); -} - -void InnerWidget::paintEvent(QPaintEvent *e) { - Painter p(this); - - auto ms = getms(); - auto clip = e->rect(); - p.fillRect(clip, st::profileBg); - - auto from = floorclamp(clip.y() - _contentTop, _rowHeight, 0, _items.size()); - auto to = ceilclamp(clip.y() + clip.height() - _contentTop, _rowHeight, 0, _items.size()); - for (auto i = from; i != to; ++i) { - paintRow(p, i, ms); - } -} - -void InnerWidget::paintRow(Painter &p, int index, TimeMs ms) { - auto item = _items[index]; - auto selected = (_pressed >= 0) ? (index == _pressed) : (index == _selected); - - auto x = _contentLeft; - auto y = _contentTop + index * _rowHeight; - if (selected) { - p.fillRect(myrtlrect(x, y, _contentWidth, _rowHeight), st::profileCommonGroupsBgOver); - } - if (auto &ripple = item->ripple) { - ripple->paint(p, x, y, width(), ms); - if (ripple->empty()) { - ripple.reset(); - } - } - - x += st::profileCommonGroupsPadding.left(); - y += st::profileCommonGroupsPadding.top(); - item->peer->paintUserpic(p, rtl() ? (width() - x - st::profileCommonGroupsPhotoSize) : x, y, st::profileCommonGroupsPhotoSize); - - p.setPen(st::profileMemberNameFg); - x += st::profileCommonGroupsPhotoSize + st::profileCommonGroupsNameLeft; - y += st::profileCommonGroupsNameTop; - auto nameWidth = _contentWidth - (x - _contentLeft) - st::profileCommonGroupsPadding.right(); - if (item->name.isEmpty()) { - item->name.setText(st::msgNameStyle, App::peerName(item->peer), _textNameOptions); - } - _items[index]->name.drawLeftElided(p, x, y, nameWidth, width()); -} - -void InnerWidget::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape) { - emit cancelled(); - } -} - -void InnerWidget::updateSelected(QPoint localPos) { - auto selected = -1; - auto selectedKick = false; - - if (rtl()) localPos.setX(width() - localPos.x()); - if (localPos.x() >= _contentLeft && localPos.x() < _contentLeft + _contentWidth && localPos.y() >= _contentTop) { - selected = (localPos.y() - _contentTop) / _rowHeight; - if (selected >= _items.size()) { - selected = -1; - } - } - - if (_selected != selected) { - updateRow(_selected); - _selected = selected; - updateRow(_selected); - if (_pressed < 0) { - setCursor((_selected >= 0) ? style::cur_pointer : style::cur_default); - } - } -} - -void InnerWidget::updateRow(int index) { - rtlupdate(_contentLeft, _contentTop + index * _rowHeight, _contentWidth, _rowHeight); -} - -void InnerWidget::mousePressEvent(QMouseEvent *e) { - _pressed = _selected; - if (_pressed >= 0) { - auto item = _items[_pressed]; - if (!item->ripple) { - auto mask = Ui::RippleAnimation::rectMask(QSize(_contentWidth, _rowHeight)); - item->ripple = std::make_unique(st::profileCommonGroupsRipple, std::move(mask), [this, index = _pressed] { - updateRow(index); - }); - } - auto left = _contentLeft; - auto top = _contentTop + _rowHeight * _pressed; - item->ripple->add(e->pos() - QPoint(left, top)); - } -} - -void InnerWidget::mouseMoveEvent(QMouseEvent *e) { - updateSelected(e->pos()); -} - -void InnerWidget::mouseReleaseEvent(QMouseEvent *e) { - setCursor(_selected ? style::cur_pointer : style::cur_default); - updateRow(_selected); - updateRow(_pressed); - auto pressed = std::exchange(_pressed, -1); - if (pressed >= 0 && pressed < _items.size()) { - if (auto &ripple = _items[pressed]->ripple) { - ripple->lastStop(); - } - if (pressed == _selected) { - App::wnd()->controller()->showPeerHistory( - _items[pressed]->peer, - Window::SectionShow::Way::Forward); - } - } -} - -InnerWidget::Item *InnerWidget::computeItem(PeerData *group) { - // Skip groups that migrated to supergroups. - if (group->migrateTo()) { - return nullptr; - } - - auto it = _dataMap.constFind(group); - if (it == _dataMap.cend()) { - it = _dataMap.insert(group, new Item(group)); - } - return it.value(); -} - -InnerWidget::~InnerWidget() { - for (auto item : base::take(_dataMap)) { - delete item; - } -} - -Widget::Widget(QWidget *parent, not_null controller, not_null user) : Window::SectionWidget(parent, controller) -, _scroll(this, st::settingsScroll) -, _fixedBar(this) -, _fixedBarShadow(this) { - _fixedBar->move(0, 0); - _fixedBar->resizeToWidth(width()); - _fixedBar->show(); - - _fixedBarShadow->raise(); - updateAdaptiveLayout(); - subscribe(Adaptive::Changed(), [this]() { updateAdaptiveLayout(); }); - - _inner = _scroll->setOwnedWidget(object_ptr(this, user)); - _scroll->move(0, _fixedBar->height()); - _scroll->show(); - - connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); - connect(_inner, SIGNAL(cancelled()), _fixedBar, SLOT(onBack())); -} - -void Widget::updateAdaptiveLayout() { - _fixedBarShadow->moveToLeft(Adaptive::OneColumn() ? 0 : st::lineWidth, _fixedBar->height()); -} - -not_null Widget::user() const { - return _inner->user(); -} - -QPixmap Widget::grabForShowAnimation(const Window::SectionSlideParams ¶ms) { - if (params.withTopBarShadow) _fixedBarShadow->hide(); - auto result = myGrab(this); - if (params.withTopBarShadow) _fixedBarShadow->show(); - return result; -} - -void Widget::doSetInnerFocus() { - _inner->setFocus(); -} - -bool Widget::showInternal( - not_null memento, - const Window::SectionShow ¶ms) { - if (auto profileMemento = dynamic_cast(memento.get())) { - if (profileMemento->getUser() == user()) { - restoreState(profileMemento); - return true; - } - } - return false; -} - -void Widget::setInternalState(const QRect &geometry, not_null memento) { - setGeometry(geometry); - myEnsureResized(this); - restoreState(memento); -} - -std::unique_ptr Widget::createMemento() { - auto result = std::make_unique(user()); - saveState(result.get()); - return std::move(result); -} - -void Widget::saveState(not_null memento) { - memento->setScrollTop(_scroll->scrollTop()); - _inner->saveState(memento); -} - -void Widget::restoreState(not_null memento) { - _inner->restoreState(memento); - auto scrollTop = memento->getScrollTop(); - _scroll->scrollToY(scrollTop); - _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); -} - -void Widget::resizeEvent(QResizeEvent *e) { - if (!width() || !height()) { - return; - } - - int newScrollTop = _scroll->scrollTop() + topDelta(); - _fixedBar->resizeToWidth(width()); - _fixedBarShadow->resize(width(), st::lineWidth); - - QSize scrollSize(width(), height() - _fixedBar->height()); - if (_scroll->size() != scrollSize) { - _scroll->resize(scrollSize); - _inner->resizeToWidth(scrollSize.width(), _scroll->height()); - } - - if (!_scroll->isHidden()) { - if (topDelta()) { - _scroll->scrollToY(newScrollTop); - } - int scrollTop = _scroll->scrollTop(); - _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); - } -} - -void Widget::onScroll() { - int scrollTop = _scroll->scrollTop(); - _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); -} - -void Widget::showAnimatedHook( - const Window::SectionSlideParams ¶ms) { - _fixedBar->setAnimatingMode(true); -} - -void Widget::showFinishedHook() { - _fixedBar->setAnimatingMode(false); -} - -bool Widget::wheelEventFromFloatPlayer(QEvent *e) { - return _scroll->viewportEvent(e); -} - -QRect Widget::rectForFloatPlayer() const { - return mapToGlobal(_scroll->geometry()); -} - -} // namespace CommonGroups -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_common_groups_section.h b/Telegram/SourceFiles/profile/profile_common_groups_section.h deleted file mode 100644 index b0734f028669d4..00000000000000 --- a/Telegram/SourceFiles/profile/profile_common_groups_section.h +++ /dev/null @@ -1,225 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "window/section_widget.h" -#include "window/section_memento.h" - -namespace Notify { -struct PeerUpdate; -} // namespace Notify - -namespace Ui { -class ScrollArea; -class PlainShadow; -} // namespace Ui - -namespace Profile { - -class BackButton; - -namespace CommonGroups { - -class SectionMemento : public Window::SectionMemento { -public: - SectionMemento(not_null user) : _user(user) { - } - - object_ptr createWidget( - QWidget *parent, - not_null controller, - Window::Column column, - const QRect &geometry) override; - - not_null getUser() const { - return _user; - } - void setScrollTop(int scrollTop) { - _scrollTop = scrollTop; - } - int getScrollTop() const { - return _scrollTop; - } - void setCommonGroups(const QList> &groups) { - _commonGroups = groups; - } - const QList> &getCommonGroups() const { - return _commonGroups; - } - -private: - not_null _user; - int _scrollTop = 0; - QList> _commonGroups; - -}; - -class FixedBar final : public TWidget, private base::Subscriber { - Q_OBJECT - -public: - FixedBar(QWidget *parent); - - // When animating mode is enabled the content is hidden and the - // whole fixed bar acts like a back button. - void setAnimatingMode(bool enabled); - -protected: - void mousePressEvent(QMouseEvent *e) override; - int resizeGetHeight(int newWidth) override; - -public slots: - void onBack(); - -private: - object_ptr _backButton; - - bool _animatingMode = false; - -}; - -class InnerWidget final : public TWidget { - Q_OBJECT - -public: - InnerWidget(QWidget *parent, not_null user); - - not_null user() const { - return _user; - } - - void resizeToWidth(int newWidth, int minHeight) { - _minHeight = minHeight; - return TWidget::resizeToWidth(newWidth); - } - - void saveState(not_null memento); - void restoreState(not_null memento); - - ~InnerWidget(); - -signals: - void cancelled(); - -protected: - int resizeGetHeight(int newWidth) override; - void visibleTopBottomUpdated( - int visibleTop, - int visibleBottom) override; - - void paintEvent(QPaintEvent *e) override; - void keyPressEvent(QKeyEvent *e) override; - void mousePressEvent(QMouseEvent *e) override; - void mouseMoveEvent(QMouseEvent *e) override; - void mouseReleaseEvent(QMouseEvent *e) override; - -private: - void updateSelected(QPoint localPos); - void updateRow(int index); - void showInitial(const QList> &list); - void checkPreloadMore(); - void preloadMore(); - void updateSize(); - void paintRow(Painter &p, int index, TimeMs ms); - - not_null _user; - - int _minHeight = 0; - int _rowHeight = 0; - int _contentLeft = 0; - int _contentTop = 0; - int _contentWidth = 0; - int _visibleTop = 0; - int _visibleBottom = 0; - - struct Item { - explicit Item(PeerData *peer); - ~Item(); - - PeerData * const peer; - Text name; - std::unique_ptr ripple; - }; - Item *computeItem(PeerData *group); - QMap _dataMap; - QList _items; - int _selected = -1; - int _pressed = -1; - - int32 _preloadGroupId = 0; - mtpRequestId _preloadRequestId = 0; - bool _allLoaded = true; - -}; - -class Widget final : public Window::SectionWidget { - Q_OBJECT - -public: - Widget(QWidget *parent, not_null controller, not_null user); - - not_null user() const; - PeerData *activePeer() const override { - return user(); - } - - bool hasTopBarShadow() const override { - return true; - } - - QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms) override; - - bool showInternal( - not_null memento, - const Window::SectionShow ¶ms) override; - std::unique_ptr createMemento() override; - - void setInternalState(const QRect &geometry, not_null memento); - - // Float player interface. - bool wheelEventFromFloatPlayer(QEvent *e) override; - QRect rectForFloatPlayer() const override; - -protected: - void resizeEvent(QResizeEvent *e) override; - - void showAnimatedHook( - const Window::SectionSlideParams ¶ms) override; - void showFinishedHook() override; - void doSetInnerFocus() override; - -private slots: - void onScroll(); - -private: - void updateAdaptiveLayout(); - void saveState(not_null memento); - void restoreState(not_null memento); - - object_ptr _scroll; - QPointer _inner; - object_ptr _fixedBar; - object_ptr _fixedBarShadow; - -}; - -} // namespace CommonGroups -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_cover.cpp b/Telegram/SourceFiles/profile/profile_cover.cpp deleted file mode 100644 index 6b564aca408520..00000000000000 --- a/Telegram/SourceFiles/profile/profile_cover.cpp +++ /dev/null @@ -1,570 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#include "profile/profile_cover.h" - -#include "data/data_photo.h" -#include "styles/style_profile.h" -#include "styles/style_window.h" -#include "profile/profile_cover_drop_area.h" -#include "profile/profile_userpic_button.h" -#include "ui/widgets/buttons.h" -#include "core/file_utilities.h" -#include "ui/widgets/labels.h" -#include "observer_peer.h" -#include "boxes/confirm_box.h" -#include "boxes/photo_crop_box.h" -#include "boxes/peer_list_controllers.h" -#include "lang/lang_keys.h" -#include "apiwrap.h" -#include "auth_session.h" -#include "mainwidget.h" -#include "mainwindow.h" -#include "messenger.h" -#include "platform/platform_file_utilities.h" -#include "window/main_window.h" -#include "window/window_controller.h" - -namespace Profile { -namespace { - -using UpdateFlag = Notify::PeerUpdate::Flag; -const auto ButtonsUpdateFlags = UpdateFlag::UserCanShareContact - | UpdateFlag::BotCanAddToGroups - | UpdateFlag::ChatCanEdit - | UpdateFlag::ChannelRightsChanged - | UpdateFlag::ChannelAmIn; - -} // namespace - -CoverWidget::CoverWidget(QWidget *parent, PeerData *peer) : TWidget(parent) -, _peer(peer) -, _peerUser(peer->asUser()) -, _peerChat(peer->asChat()) -, _peerChannel(peer->asChannel()) -, _peerMegagroup(peer->isMegagroup() ? _peerChannel : nullptr) -, _userpicButton(this, peer) -, _name(this, st::profileNameLabel) { - _peer->updateFull(); - - subscribe(Lang::Current().updated(), [this] { refreshLang(); }); - - setAttribute(Qt::WA_OpaquePaintEvent); - setAcceptDrops(true); - - _name->setSelectable(true); - _name->setContextCopyText(lang(lng_profile_copy_fullname)); - - auto observeEvents = ButtonsUpdateFlags - | UpdateFlag::NameChanged - | UpdateFlag::UserOnlineChanged - | UpdateFlag::MembersChanged - | UpdateFlag::PhotoChanged; - subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) { - notifyPeerUpdated(update); - })); - - connect(&Messenger::Instance(), SIGNAL(peerPhotoDone(PeerId)), this, SLOT(onPhotoUploadStatusChanged(PeerId))); - connect(&Messenger::Instance(), SIGNAL(peerPhotoFail(PeerId)), this, SLOT(onPhotoUploadStatusChanged(PeerId))); - - connect(_userpicButton, SIGNAL(clicked()), this, SLOT(onPhotoShow())); - validatePhoto(); - - refreshNameText(); - refreshStatusText(); - - refreshButtons(); -} - -void CoverWidget::refreshLang() { - InvokeQueued(this, [this] { moveAndToggleButtons(width()); }); -} - -PhotoData *CoverWidget::validatePhoto() const { - auto photo = (_peer->photoId && _peer->photoId != UnknownPeerPhotoId) ? App::photo(_peer->photoId) : nullptr; - _userpicButton->setPointerCursor(photo != nullptr && photo->date != 0); - if ((_peer->photoId == UnknownPeerPhotoId) || (_peer->photoId && (!photo || !photo->date))) { - Auth().api().requestFullPeer(_peer); - return nullptr; - } - return photo; -} - -void CoverWidget::onPhotoShow() { - if (auto photo = validatePhoto()) { - Messenger::Instance().showPhoto(photo, _peer); - } -} - -void CoverWidget::onCancelPhotoUpload() { - Messenger::Instance().cancelPhotoUpdate(_peer->id); - refreshStatusText(); -} - -int CoverWidget::countPhotoLeft(int newWidth) const { - int result = st::profilePhotoLeftMin; - result += (newWidth - st::columnMinimalWidthMain) / 2; - return qMin(result, st::profilePhotoLeftMax); -} - -int CoverWidget::resizeGetHeight(int newWidth) { - int newHeight = 0; - - newHeight += st::profileMarginTop; - - _photoLeft = countPhotoLeft(newWidth); - _userpicButton->moveToLeft(_photoLeft, newHeight); - - refreshNameGeometry(newWidth); - - int infoLeft = _userpicButton->x() + _userpicButton->width(); - _statusPosition = QPoint(infoLeft + st::profileStatusLeft, _userpicButton->y() + st::profileStatusTop); - if (_cancelPhotoUpload) { - _cancelPhotoUpload->moveToLeft(_statusPosition.x() + st::profileStatusFont->width(_statusText) + st::profileStatusFont->spacew, _statusPosition.y()); - } - - moveAndToggleButtons(newWidth); - - newHeight += st::profilePhotoSize; - newHeight += st::profileMarginBottom; - - _dividerTop = newHeight; - newHeight += st::profileDividerLeft.height(); - - newHeight += st::profileBlocksTop; - - resizeDropArea(newWidth); - return newHeight; -} - -void CoverWidget::refreshNameGeometry(int newWidth) { - int infoLeft = _userpicButton->x() + _userpicButton->width(); - int nameLeft = infoLeft + st::profileNameLeft - st::profileNameLabel.margin.left(); - int nameTop = _userpicButton->y() + st::profileNameTop - st::profileNameLabel.margin.top(); - int nameWidth = newWidth - infoLeft - st::profileNameLeft; - if (_peer->isVerified()) { - nameWidth -= st::profileVerifiedCheckShift + st::profileVerifiedCheck.width(); - } - int marginsAdd = st::profileNameLabel.margin.left() + st::profileNameLabel.margin.right(); - _name->resizeToWidth(qMin(nameWidth - marginsAdd, _name->naturalWidth()) + marginsAdd); - _name->moveToLeft(nameLeft, nameTop); -} - -// A more generic solution would be allowing an optional icon button -// for each text button. But currently we use only one, so it is done easily: -// There can be primary + secondary + icon buttons. If primary + secondary fit, -// then icon is hidden, otherwise secondary is hidden and icon is shown. -void CoverWidget::moveAndToggleButtons(int newWidth) { - int buttonLeft = _userpicButton->x() + _userpicButton->width() + st::profileButtonLeft; - int buttonsRight = newWidth - st::profileButtonSkip; - for (int i = 0, count = _buttons.size(); i < count; ++i) { - auto &button = _buttons.at(i); - button.widget->moveToLeft(buttonLeft, st::profileButtonTop); - if (button.replacement) { - button.replacement->moveToLeft(buttonLeft, st::profileButtonTop); - if (buttonLeft + button.widget->width() > buttonsRight) { - button.widget->hide(); - button.replacement->show(); - buttonLeft += button.replacement->width() + st::profileButtonSkip; - } else { - button.widget->show(); - button.replacement->hide(); - buttonLeft += button.widget->width() + st::profileButtonSkip; - } - } else if (i == 1 && (buttonLeft + button.widget->width() > buttonsRight)) { - // If second button is not fitting. - button.widget->hide(); - } else { - button.widget->show(); - buttonLeft += button.widget->width() + st::profileButtonSkip; - } - } -} - -void CoverWidget::showFinished() { - _userpicButton->showFinished(); -} - -bool CoverWidget::shareContactButtonShown() const { - return _peerUser && (_buttons.size() > 1) && !(_buttons.at(1).widget->isHidden()); -} - -void CoverWidget::paintEvent(QPaintEvent *e) { - Painter p(this); - - p.fillRect(e->rect(), st::profileBg); - - p.setFont(st::profileStatusFont); - p.setPen(_statusTextIsOnline ? st::profileStatusFgActive : st::profileStatusFg); - p.drawTextLeft(_statusPosition.x(), _statusPosition.y(), width(), _statusText); - - if (_peer->isVerified()) { - st::profileVerifiedCheck.paint(p, _name->x() + _name->width() + st::profileVerifiedCheckShift, _name->y(), width()); - } - - paintDivider(p); -} - -void CoverWidget::resizeDropArea(int newWidth) { - if (_dropArea) { - _dropArea->setGeometry(0, 0, newWidth, _dividerTop); - } -} - -void CoverWidget::dropAreaHidden(CoverDropArea *dropArea) { - if (_dropArea == dropArea) { - _dropArea.destroyDelayed(); - } -} - -bool CoverWidget::canEditPhoto() const { - if (_peerChat && _peerChat->canEdit()) { - return true; - } else if (_peerMegagroup && _peerMegagroup->canEditInformation()) { - return true; - } else if (_peerChannel && _peerChannel->canEditInformation()) { - return true; - } - return false; -} - -bool CoverWidget::mimeDataHasImage(const QMimeData *mimeData) const { - if (!mimeData) return false; - - if (mimeData->hasImage()) return true; - - auto uriListFormat = qsl("text/uri-list"); - if (!mimeData->hasFormat(uriListFormat)) return false; - - const auto &urls = mimeData->urls(); - if (urls.size() != 1) return false; - - auto &url = urls.at(0); - if (!url.isLocalFile()) return false; - - auto file = Platform::File::UrlToLocal(url); - - QFileInfo info(file); - if (info.isDir()) return false; - - if (info.size() > App::kImageSizeLimit) return false; - - for (auto &ext : cImgExtensions()) { - if (file.endsWith(ext, Qt::CaseInsensitive)) { - return true; - } - } - return false; -} - -void CoverWidget::dragEnterEvent(QDragEnterEvent *e) { - if (!canEditPhoto() || !mimeDataHasImage(e->mimeData())) { - e->ignore(); - return; - } - if (!_dropArea) { - auto title = lang(lng_profile_drop_area_title); - QString subtitle; - if (_peerChat || _peerMegagroup) { - subtitle = lang(lng_profile_drop_area_subtitle); - } else { - subtitle = lang(lng_profile_drop_area_subtitle_channel); - } - _dropArea.create(this, title, subtitle); - resizeDropArea(width()); - } - _dropArea->showAnimated(); - e->setDropAction(Qt::CopyAction); - e->accept(); -} - -void CoverWidget::dragLeaveEvent(QDragLeaveEvent *e) { - if (_dropArea && !_dropArea->hiding()) { - _dropArea->hideAnimated([this](CoverDropArea *area) { dropAreaHidden(area); }); - } -} - -void CoverWidget::dropEvent(QDropEvent *e) { - auto mimeData = e->mimeData(); - - QImage img; - if (mimeData->hasImage()) { - img = qvariant_cast(mimeData->imageData()); - } else { - const auto &urls = mimeData->urls(); - if (urls.size() == 1) { - auto &url = urls.at(0); - if (url.isLocalFile()) { - img = App::readImage(Platform::File::UrlToLocal(url)); - } - } - } - - if (!_dropArea->hiding()) { - _dropArea->hideAnimated([this](CoverDropArea *area) { dropAreaHidden(area); }); - } - e->acceptProposedAction(); - - showSetPhotoBox(img); -} - -void CoverWidget::paintDivider(Painter &p) { - auto dividerHeight = st::profileDividerLeft.height(); - auto dividerLeft = Adaptive::OneColumn() ? 0 : st::lineWidth; - auto divider = rtlrect(dividerLeft, _dividerTop, width() - dividerLeft, dividerHeight, width()); - p.fillRect(divider, st::profileDividerBg); - if (!Adaptive::OneColumn()) { - st::profileDividerLeft.paint(p, QPoint(dividerLeft, _dividerTop), width()); - } - auto dividerFillLeft = Adaptive::OneColumn() ? 0 : (st::lineWidth + st::profileDividerLeft.width()); - auto dividerFillTop = rtlrect(dividerFillLeft, _dividerTop, width() - dividerFillLeft, st::profileDividerTop.height(), width()); - st::profileDividerTop.fill(p, dividerFillTop); - auto dividerFillBottom = rtlrect(dividerFillLeft, _dividerTop + dividerHeight - st::profileDividerBottom.height(), width() - dividerFillLeft, st::profileDividerBottom.height(), width()); - st::profileDividerBottom.fill(p, dividerFillBottom); -} - -void CoverWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { - if (update.peer != _peer) { - return; - } - if ((update.flags & ButtonsUpdateFlags) != 0) { - refreshButtons(); - } - if (update.flags & UpdateFlag::NameChanged) { - refreshNameText(); - } - if (update.flags & UpdateFlag::PhotoChanged) { - validatePhoto(); - } - if (update.flags & (UpdateFlag::UserOnlineChanged | UpdateFlag::MembersChanged)) { - refreshStatusText(); - } -} - -void CoverWidget::refreshNameText() { - _name->setText(App::peerName(_peer)); - refreshNameGeometry(width()); -} - -void CoverWidget::refreshStatusText() { - if (Messenger::Instance().isPhotoUpdating(_peer->id)) { - _statusText = lang(lng_settings_uploading_photo); - _statusTextIsOnline = false; - if (!_cancelPhotoUpload) { - _cancelPhotoUpload.create(this, lang(lng_cancel), st::defaultLinkButton); - connect(_cancelPhotoUpload, SIGNAL(clicked()), this, SLOT(onCancelPhotoUpload())); - _cancelPhotoUpload->show(); - _cancelPhotoUpload->moveToLeft(_statusPosition.x() + st::profileStatusFont->width(_statusText) + st::profileStatusFont->spacew, _statusPosition.y()); - } - update(); - return; - } - - _cancelPhotoUpload.destroy(); - auto currentTime = unixtime(); - if (_peerUser) { - _statusText = App::onlineText(_peerUser, currentTime, true); - _statusTextIsOnline = App::onlineColorUse(_peerUser, currentTime); - } else if (_peerChat && _peerChat->amIn()) { - auto fullCount = qMax(_peerChat->count, _peerChat->participants.size()); - if (_onlineCount > 0 && _onlineCount <= fullCount) { - auto membersCount = lng_chat_status_members(lt_count, fullCount); - auto onlineCount = lng_chat_status_online(lt_count, _onlineCount); - _statusText = lng_chat_status_members_online(lt_members_count, membersCount, lt_online_count, onlineCount); - } else if (_peerChat->count > 0) { - _statusText = lng_chat_status_members(lt_count, _peerChat->count); - } else { - _statusText = lang(lng_group_status); - } - } else if (_peerChannel) { - auto fullCount = _peerChannel->membersCount(); - if (_onlineCount > 0 && _onlineCount <= fullCount) { - auto membersCount = lng_chat_status_members(lt_count, fullCount); - auto onlineCount = lng_chat_status_online(lt_count, _onlineCount); - _statusText = lng_chat_status_members_online(lt_members_count, membersCount, lt_online_count, onlineCount); - } else if (fullCount > 0) { - _statusText = lng_chat_status_members(lt_count, fullCount); - } else { - _statusText = lang(_peerChannel->isMegagroup() ? lng_group_status : lng_channel_status); - } - } else { - _statusText = lang(lng_chat_status_unaccessible); - } - update(); -} - -void CoverWidget::refreshButtons() { - clearButtons(); - if (_peerUser) { - setUserButtons(); - } else if (_peerChat) { - setChatButtons(); - } else if (_peerMegagroup) { - setMegagroupButtons(); - } else if (_peerChannel) { - setChannelButtons(); - } - resizeToWidth(width()); -} - -void CoverWidget::setUserButtons() { - addButton(langFactory(lng_profile_send_message), SLOT(onSendMessage())); - if (_peerUser->botInfo && !_peerUser->botInfo->cantJoinGroups) { - addButton(langFactory(lng_profile_invite_to_group), SLOT(onAddBotToGroup()), &st::profileAddMemberButton); - } else if (_peerUser->canShareThisContact()) { - addButton(langFactory(lng_profile_share_contact), SLOT(onShareContact())); - } -} - -void CoverWidget::setChatButtons() { - if (_peerChat->canEdit()) { - addButton(langFactory(lng_profile_set_group_photo), SLOT(onSetPhoto())); - addButton(langFactory(lng_profile_add_participant), SLOT(onAddMember()), &st::profileAddMemberButton); - } -} - -void CoverWidget::setMegagroupButtons() { - if (_peerMegagroup->amIn()) { - if (canEditPhoto()) { - addButton(langFactory(lng_profile_set_group_photo), SLOT(onSetPhoto())); - } - } else { - addButton(langFactory(lng_profile_join_channel), SLOT(onJoin())); - } - if (_peerMegagroup->canAddMembers()) { - addButton(langFactory(lng_profile_add_participant), SLOT(onAddMember()), &st::profileAddMemberButton); - } -} - -void CoverWidget::setChannelButtons() { - if (canEditPhoto()) { - addButton(langFactory(lng_profile_set_group_photo), SLOT(onSetPhoto())); - } else if (_peerChannel->amIn()) { - addButton(langFactory(lng_profile_view_channel), SLOT(onViewChannel())); - } else { - addButton(langFactory(lng_profile_join_channel), SLOT(onJoin())); - } -} - -void CoverWidget::clearButtons() { - auto buttons = base::take(_buttons); - for_const (auto button, buttons) { - delete button.widget; - delete button.replacement; - } -} - -void CoverWidget::addButton(base::lambda textFactory, const char *slot, const style::RoundButton *replacementStyle) { - auto &buttonStyle = _buttons.isEmpty() ? st::profilePrimaryButton : st::profileSecondaryButton; - auto button = new Ui::RoundButton(this, std::move(textFactory), buttonStyle); - connect(button, SIGNAL(clicked()), this, slot); - button->show(); - - auto replacement = replacementStyle ? new Ui::RoundButton(this, base::lambda(), *replacementStyle) : nullptr; - if (replacement) { - connect(replacement, SIGNAL(clicked()), this, slot); - replacement->hide(); - } - - _buttons.push_back({ button, replacement }); -} - -void CoverWidget::onOnlineCountUpdated(int onlineCount) { - _onlineCount = onlineCount; - refreshStatusText(); -} - -void CoverWidget::onSendMessage() { - App::wnd()->controller()->showPeerHistory( - _peer, - Window::SectionShow::Way::Forward); -} - -void CoverWidget::onShareContact() { - App::main()->shareContactLayer(_peerUser); -} - -void CoverWidget::onSetPhoto() { - App::CallDelayed(st::profilePrimaryButton.ripple.hideDuration, this, [this] { - auto imgExtensions = cImgExtensions(); - auto filter = qsl("Image files (*") + imgExtensions.join(qsl(" *")) + qsl(");;") + FileDialog::AllFilesFilter(); - FileDialog::GetOpenPath(lang(lng_choose_image), filter, base::lambda_guarded(this, [this](const FileDialog::OpenResult &result) { - if (result.paths.isEmpty() && result.remoteContent.isEmpty()) { - return; - } - - QImage img; - if (!result.remoteContent.isEmpty()) { - img = App::readImage(result.remoteContent); - } else { - img = App::readImage(result.paths.front()); - } - - showSetPhotoBox(img); - })); - }); -} - -void CoverWidget::showSetPhotoBox(const QImage &img) { - if (img.isNull() || img.width() > 10 * img.height() || img.height() > 10 * img.width()) { - Ui::show(Box(lang(lng_bad_photo))); - return; - } - - auto box = Ui::show(Box(img, _peer)); - subscribe(box->boxClosing, [this] { onPhotoUploadStatusChanged(); }); -} - -void CoverWidget::onPhotoUploadStatusChanged(PeerId peerId) { - if (!peerId || peerId == _peer->id) { - refreshStatusText(); - } -} - -void CoverWidget::onAddMember() { - if (_peerChat) { - if (_peerChat->count >= Global::ChatSizeMax() && _peerChat->amCreator()) { - Ui::show(Box(_peerChat)); - } else { - AddParticipantsBoxController::Start(_peerChat); - } - } else if (_peerChannel && _peerChannel->mgInfo) { - auto &participants = _peerChannel->mgInfo->lastParticipants; - AddParticipantsBoxController::Start(_peerChannel, { participants.cbegin(), participants.cend() }); - } -} - -void CoverWidget::onAddBotToGroup() { - if (_peerUser && _peerUser->botInfo) { - AddBotToGroupBoxController::Start(_peerUser); - } -} - -void CoverWidget::onJoin() { - if (!_peerChannel) return; - - Auth().api().joinChannel(_peerChannel); -} - -void CoverWidget::onViewChannel() { - Ui::showPeerHistory(_peer, ShowAtUnreadMsgId); -} - -} // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_cover.h b/Telegram/SourceFiles/profile/profile_cover.h deleted file mode 100644 index 8f1c3b6b28da49..00000000000000 --- a/Telegram/SourceFiles/profile/profile_cover.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "base/observer.h" - -namespace style { -struct RoundButton; -} // namespace style - -namespace Ui { -class FlatLabel; -class RoundButton; -class LinkButton; -} // namespace Ui - -namespace Notify { -struct PeerUpdate; -} // namespace Notify - -namespace Profile { - -class BackButton; -class UserpicButton; -class CoverDropArea; - -class CoverWidget final : public TWidget, private base::Subscriber { - Q_OBJECT - -public: - CoverWidget(QWidget *parent, PeerData *peer); - - void showFinished(); - - // Profile fixed top bar should use this flag to decide - // if it shows "Share contact" button or not. - // It should show it only if it is hidden in the cover. - bool shareContactButtonShown() const; - -public slots: - void onOnlineCountUpdated(int onlineCount); - -private slots: - void onPhotoShow(); - void onPhotoUploadStatusChanged(PeerId peerId = 0); - void onCancelPhotoUpload(); - - void onSendMessage(); - void onShareContact(); - void onSetPhoto(); - void onAddMember(); - void onAddBotToGroup(); - void onJoin(); - void onViewChannel(); - -protected: - void paintEvent(QPaintEvent *e) override; - void dragEnterEvent(QDragEnterEvent *e) override; - void dragLeaveEvent(QDragLeaveEvent *e) override; - void dropEvent(QDropEvent *e) override; - - int resizeGetHeight(int newWidth) override; - -private: - void refreshLang(); - - // Observed notifications. - void notifyPeerUpdated(const Notify::PeerUpdate &update); - - // Counts userpic button left offset for a new widget width. - int countPhotoLeft(int newWidth) const; - PhotoData *validatePhoto() const; - - void refreshNameGeometry(int newWidth); - void moveAndToggleButtons(int newWidth); - void refreshNameText(); - void refreshStatusText(); - - void refreshButtons(); - void setUserButtons(); - void setChatButtons(); - void setMegagroupButtons(); - void setChannelButtons(); - - void clearButtons(); - void addButton(base::lambda textFactory, const char *slot, const style::RoundButton *replacementStyle = nullptr); - - void paintDivider(Painter &p); - - bool canEditPhoto() const; - void showSetPhotoBox(const QImage &img); - void resizeDropArea(int newWidth); - void dropAreaHidden(CoverDropArea *dropArea); - bool mimeDataHasImage(const QMimeData *mimeData) const; - - PeerData *_peer; - UserData *_peerUser; - ChatData *_peerChat; - ChannelData *_peerChannel; - ChannelData *_peerMegagroup; - - object_ptr _userpicButton; - object_ptr _dropArea = { nullptr }; - - object_ptr _name; - object_ptr _cancelPhotoUpload = { nullptr }; - - QPoint _statusPosition; - QString _statusText; - bool _statusTextIsOnline = false; - - struct Button { - Ui::RoundButton *widget; - Ui::RoundButton *replacement; - }; - QList