/* 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 "info/profile/info_profile_inner_widget.h" #include #include "info/profile/info_profile_button.h" #include "info/profile/info_profile_widget.h" #include "info/profile/info_profile_text.h" #include "info/profile/info_profile_values.h" #include "info/profile/info_profile_cover.h" #include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_members.h" #include "boxes/abstract_box.h" #include "boxes/add_contact_box.h" #include "mainwidget.h" #include "window/window_controller.h" #include "storage/storage_shared_media.h" #include "lang/lang_keys.h" #include "styles/style_info.h" #include "ui/widgets/buttons.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/scroll_area.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/vertical_layout.h" namespace Info { namespace Profile { InnerWidget::InnerWidget( QWidget *parent, rpl::producer &&wrapValue, not_null controller, not_null peer) : RpWidget(parent) , _controller(controller) , _peer(peer) , _content(setupContent(this, std::move(wrapValue))) { _content->heightValue() | rpl::start([this](int height) { TWidget::resizeToWidth(width()); _desiredHeight.fire(countDesiredHeight()); }, lifetime()); } bool InnerWidget::canHideDetailsEver() const { return (_peer->isChat() || _peer->isMegagroup()); } rpl::producer InnerWidget::canHideDetails() const { using namespace rpl::mappers; return MembersCountValue(_peer) | rpl::map($1 > 0); } object_ptr InnerWidget::setupContent( RpWidget *parent, rpl::producer &&wrapValue) { auto result = object_ptr(parent); auto cover = result->add(object_ptr( result, _peer) ); cover->setOnlineCount(rpl::single(0)); auto details = setupDetails(parent); if (canHideDetailsEver()) { cover->setToggleShown(canHideDetails()); result->add(object_ptr>( result, std::move(details)) )->toggleOn(cover->toggledValue()); } else { result->add(std::move(details)); } result->add(setupSharedMedia(result)); result->add(object_ptr(result)); if (auto user = _peer->asUser()) { result->add(setupUserActions(result, user)); //} else if (auto channel = _peer->asChannel()) { // if (!channel->isMegagroup()) { // setupChannelActions(result, channel); // } } if (_peer->isChat() || _peer->isMegagroup()) { _members = result->add(object_ptr( result, _controller, std::move(wrapValue), _peer) ); _members->scrollToRequests() | rpl::start([this](Ui::ScrollToRequest request) { auto min = (request.ymin < 0) ? request.ymin : mapFromGlobal(_members->mapToGlobal({ 0, request.ymin })).y(); auto max = (request.ymin < 0) ? mapFromGlobal(_members->mapToGlobal({ 0, 0 })).y() : (request.ymax < 0) ? request.ymax : mapFromGlobal(_members->mapToGlobal({ 0, request.ymax })).y(); _scrollToRequests.fire({ min, max }); }, _members->lifetime()); } return std::move(result); } object_ptr InnerWidget::setupDetails( RpWidget *parent) const { auto result = object_ptr(parent); result->add(object_ptr(result)); result->add(createSkipWidget(result)); result->add(setupInfo(result)); result->add(setupMuteToggle(result)); if (auto user = _peer->asUser()) { setupUserButtons(result, user); //} else if (auto channel = _peer->asChannel()) { // if (!channel->isMegagroup()) { // setupChannelButtons(result, channel); // } } result->add(createSkipWidget(result)); return std::move(result); } object_ptr InnerWidget::setupInfo( RpWidget *parent) const { auto result = object_ptr(parent); auto tracker = MultiLineTracker(); auto addInfoLine = [&]( LangKey label, rpl::producer &&text, bool selectByDoubleClick = false, const style::FlatLabel &textSt = st::infoLabeled) { auto line = result->add(CreateTextWithLabel( result, Lang::Viewer(label) | WithEmptyEntities(), std::move(text), textSt, st::infoProfileLabeledPadding, selectByDoubleClick)); tracker.track(line); return line; }; auto addInfoOneLine = [&]( LangKey label, rpl::producer &&text) { addInfoLine( label, std::move(text), true, st::infoLabeledOneLine); }; if (auto user = _peer->asUser()) { addInfoOneLine(lng_info_mobile_label, PhoneValue(user)); addInfoLine(lng_info_bio_label, BioValue(user)); addInfoOneLine(lng_info_username_label, UsernameValue(user)); } else { addInfoOneLine(lng_info_link_label, LinkValue(_peer)); addInfoLine(lng_info_about_label, AboutValue(_peer)); } result->add(object_ptr>( result, object_ptr(result, st::shadowFg), st::infoProfileSeparatorPadding) )->toggleOn(std::move(tracker).atLeastOneShownValue()); object_ptr( result, st::infoIconInformation, st::infoInformationIconPosition); return std::move(result); } object_ptr InnerWidget::setupMuteToggle( RpWidget *parent) const { auto result = object_ptr