Add Info::Channels section + feed channels search.

This commit is contained in:
John Preston 2018-02-22 20:38:00 +03:00
parent c3c9ba7e51
commit 027db285bc
13 changed files with 231 additions and 61 deletions

View File

@ -1438,6 +1438,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_feed_select_more_channels#one" = "Select {count} channel or more.";
"lng_feed_select_more_channels#other" = "Select {count} channels or more.";
"lng_feed_create" = "Create";
"lng_feed_edit_title" = "Edit feed";
"lng_feed_channels_not_found" = "No channels found";
"lng_info_feed_title" = "Feed Info";
"lng_info_feed_is_default" = "Group new channels";

View File

@ -0,0 +1,97 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "info/channels/info_channels_widget.h"
#include "info/feed/info_feed_channels.h"
#include "info/info_controller.h"
#include "ui/widgets/scroll_area.h"
#include "styles/style_info.h"
namespace Info {
namespace Channels {
Memento::Memento(not_null<Controller*> controller)
: Memento(controller->feed()) {
}
Memento::Memento(not_null<Data::Feed*> feed)
: ContentMemento(feed) {
}
Section Memento::section() const {
return Section(Section::Type::Channels);
}
object_ptr<ContentWidget> Memento::createWidget(
QWidget *parent,
not_null<Controller*> controller,
const QRect &geometry) {
auto result = object_ptr<Widget>(
parent,
controller);
result->setInternalState(geometry, this);
return std::move(result);
}
void Memento::setState(std::unique_ptr<SavedState> state) {
_state = std::move(state);
}
std::unique_ptr<SavedState> Memento::state() {
return std::move(_state);
}
Memento::~Memento() = default;
Widget::Widget(
QWidget *parent,
not_null<Controller*> controller)
: ContentWidget(parent, controller) {
_inner = setInnerWidget(object_ptr<FeedProfile::Channels>(
this,
controller));
}
bool Widget::showInternal(not_null<ContentMemento*> memento) {
if (!controller()->validateMementoPeer(memento)) {
return false;
}
if (auto membersMemento = dynamic_cast<Memento*>(memento.get())) {
restoreState(membersMemento);
return true;
}
return false;
}
void Widget::setInternalState(
const QRect &geometry,
not_null<Memento*> memento) {
setGeometry(geometry);
Ui::SendPendingMoveResizeEvents(this);
restoreState(memento);
}
std::unique_ptr<ContentMemento> Widget::doCreateMemento() {
auto result = std::make_unique<Memento>(controller());
saveState(result.get());
return std::move(result);
}
void Widget::saveState(not_null<Memento*> memento) {
memento->setScrollTop(scrollTopSave());
memento->setState(_inner->saveState());
}
void Widget::restoreState(not_null<Memento*> memento) {
_inner->restoreState(memento->state());
auto scrollTop = memento->scrollTop();
scrollTopRestore(memento->scrollTop());
}
} // namespace Channels
} // namespace Info

View File

@ -0,0 +1,74 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "info/info_content_widget.h"
struct PeerListState;
namespace Data {
class Feed;
} // namespace Data
namespace Info {
namespace FeedProfile {
class Channels;
struct ChannelsState;
} // namespace FeedProfile
namespace Channels {
using SavedState = FeedProfile::ChannelsState;
class Memento final : public ContentMemento {
public:
explicit Memento(not_null<Controller*> controller);
explicit Memento(not_null<Data::Feed*> feed);
object_ptr<ContentWidget> createWidget(
QWidget *parent,
not_null<Controller*> controller,
const QRect &geometry) override;
Section section() const override;
void setState(std::unique_ptr<SavedState> state);
std::unique_ptr<SavedState> state();
~Memento();
private:
std::unique_ptr<SavedState> _state;
};
class Widget final : public ContentWidget {
public:
Widget(
QWidget *parent,
not_null<Controller*> controller);
bool showInternal(
not_null<ContentMemento*> memento) override;
void setInternalState(
const QRect &geometry,
not_null<Memento*> memento);
private:
void saveState(not_null<Memento*> memento);
void restoreState(not_null<Memento*> memento);
std::unique_ptr<ContentMemento> doCreateMemento() override;
FeedProfile::Channels *_inner = nullptr;
};
} // namespace Channels
} // namespace Info

View File

@ -11,7 +11,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/profile/info_profile_icon.h"
#include "info/profile/info_profile_button.h"
#include "info/profile/info_profile_values.h"
#include "info/channels/info_channels_widget.h"
#include "info/info_controller.h"
#include "info/info_memento.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/scroll_area.h"
@ -58,7 +60,7 @@ Channels::Channels(
int Channels::desiredHeight() const {
auto desired = _header ? _header->height() : 0;
desired += st::infoMembersList.item.height
desired += st::infoChannelsList.item.height
* std::max(int(_feed->channels().size()), _list->fullRowsCount());
return qMax(height(), desired);
}
@ -81,7 +83,7 @@ void Channels::restoreState(std::unique_ptr<ChannelsState> state) {
}
void Channels::setupHeader() {
if (_controller->section().type() == Section::Type::Members) {
if (_controller->section().type() == Section::Type::Channels) {
return;
}
_header = object_ptr<Ui::FixedHeightWidget>(
@ -135,28 +137,24 @@ void Channels::setupButtons() {
showChannelsWithSearch(false);
});
//auto addMemberShown = CanAddMemberValue(_peer)
// | rpl::start_spawning(lifetime());
//_addChannel->showOn(rpl::duplicate(addMemberShown));
//_addChannel->addClickHandler([this] { // TODO throttle(ripple duration)
// this->addMember();
//});
_addChannel->addClickHandler([this] { // TODO throttle(ripple duration)
this->addChannel();
});
//auto searchShown = MembersCountValue(_peer)
// | rpl::map(_1 >= kEnableSearchMembersAfterCount)
// | rpl::distinct_until_changed()
// | rpl::start_spawning(lifetime());
//_search->showOn(rpl::duplicate(searchShown));
//_search->addClickHandler([this] { // TODO throttle(ripple duration)
// this->showMembersWithSearch(true);
//});
auto searchShown = Profile::FeedChannelsCountValue(_feed)
| rpl::map(_1 >= kEnableSearchChannelsAfterCount)
| rpl::distinct_until_changed()
| rpl::start_spawning(lifetime());
_search->showOn(rpl::duplicate(searchShown));
_search->addClickHandler([this] { // TODO throttle(ripple duration)
this->showChannelsWithSearch(true);
});
//rpl::combine(
// std::move(addMemberShown),
// std::move(searchShown)
//) | rpl::start_with_next([this] {
// updateHeaderControlsGeometry(width());
//}, lifetime());
std::move(
searchShown
) | rpl::start_with_next([this] {
updateHeaderControlsGeometry(width());
}, lifetime());
}
void Channels::setupList() {
@ -164,7 +162,7 @@ void Channels::setupList() {
_list = object_ptr<ListWidget>(
this,
_listController.get(),
st::infoCommonGroupsList);
st::infoChannelsList);
_list->scrollToRequests(
) | rpl::start_with_next([this](Ui::ScrollToRequest request) {
auto addmin = (request.ymin < 0 || !_header)
@ -271,34 +269,18 @@ void Channels::updateHeaderControlsGeometry(int newWidth) {
}
void Channels::addChannel() {
//if (const auto chat = _peer->asChat()) {
// if (chat->count >= Global::ChatSizeMax() && chat->amCreator()) {
// Ui::show(Box<ConvertToSupergroupBox>(chat));
// } else {
// AddParticipantsBoxController::Start(chat);
// }
//} else if (const auto channel = _peer->asChannel()) {
// const auto state = _listController->saveState();
// const auto users = ranges::view::all(
// state->list
// ) | ranges::view::transform([](not_null<PeerData*> peer) {
// return peer->asUser();
// }) | ranges::to_vector;
// AddParticipantsBoxController::Start(
// channel,
// { users.begin(), users.end() });
//}
EditController::Start(_feed);
}
void Channels::showChannelsWithSearch(bool withSearch) {
//auto contentMemento = std::make_unique<Info::Members::Memento>(
// _controller);
//contentMemento->setState(saveState());
//contentMemento->setSearchStartsFocused(withSearch);
//auto mementoStack = std::vector<std::unique_ptr<ContentMemento>>();
//mementoStack.push_back(std::move(contentMemento));
//_controller->showSection(
// Info::Memento(std::move(mementoStack)));
auto contentMemento = std::make_unique<Info::Channels::Memento>(
_controller);
contentMemento->setState(saveState());
contentMemento->setSearchStartsFocused(withSearch);
auto mementoStack = std::vector<std::unique_ptr<ContentMemento>>();
mementoStack.push_back(std::move(contentMemento));
_controller->showSection(
Info::Memento(std::move(mementoStack)));
}
void Channels::visibleTopBottomUpdated(

View File

@ -114,7 +114,7 @@ std::unique_ptr<PeerListRow> ChannelsController::createRestoredRow(
}
void ChannelsController::prepare() {
setSearchNoResultsText(lang(lng_bot_groups_not_found));
setSearchNoResultsText(lang(lng_feed_channels_not_found));
delegate()->peerListSetSearchMode(PeerListSearchMode::Enabled);
delegate()->peerListSetTitle(langFactory(lng_info_feed_channels));
@ -241,7 +241,7 @@ NotificationsController::NotificationsController(
}
void NotificationsController::prepare() {
setSearchNoResultsText(lang(lng_blocked_list_not_found));
setSearchNoResultsText(lang(lng_feed_channels_not_found));
delegate()->peerListSetSearchMode(PeerListSearchMode::Enabled);
delegate()->peerListSetTitle(langFactory(lng_feed_notifications));
@ -377,9 +377,12 @@ EditController::EditController(
}
void EditController::prepare() {
setSearchNoResultsText(lang(lng_blocked_list_not_found));
setSearchNoResultsText(lang(lng_feed_channels_not_found));
delegate()->peerListSetSearchMode(PeerListSearchMode::Enabled);
delegate()->peerListSetTitle(langFactory(lng_feed_create_new));
delegate()->peerListSetTitle(langFactory(
(_feed->channels().size() < kChannelsInFeedMin
? lng_feed_create_new
: lng_feed_edit_title)));
loadMoreRows();
}
@ -429,6 +432,7 @@ void EditController::applyFeedSources(
setDescriptionText(lng_feed_too_few_channels(
lt_count,
kChannelsInFeedMin));
delegate()->peerListSetSearchMode(PeerListSearchMode::Disabled);
} else {
auto alreadyInFeed = ranges::view::all(
channels

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_feed.h"
#include "data/data_session.h"
#include "info/info_controller.h"
#include "info/info_memento.h"
#include "lang/lang_keys.h"
#include "ui/widgets/labels.h"
#include "ui/special_buttons.h"
@ -81,12 +82,12 @@ void Cover::refreshStatusText() {
}
return lng_feed_channels(lt_count, _feed->channels().size());
}();
_status->setRichText(statusText);
//_status->setLink(1, std::make_shared<LambdaClickHandler>([=] {
// _controller->showSection(Info::Memento(
// _feed,
// Section::Type::Channels));
//})); // #TODO channels list
_status->setRichText(textcmdLink(1, statusText));
_status->setLink(1, std::make_shared<LambdaClickHandler>([=] {
_controller->showSection(Info::Memento(
_feed,
Section::Type::Channels));
}));
refreshStatusGeometry(width());
}

View File

@ -119,7 +119,7 @@ public:
: _peerId(peerId)
, _migratedPeerId(migratedPeerId) {
}
ContentMemento(not_null<Data::Feed*> feed)
explicit ContentMemento(not_null<Data::Feed*> feed)
: _feed(feed) {
}

View File

@ -156,7 +156,9 @@ void Controller::updateSearchControllers(
auto hasCommonGroupsSearch
= (type == Type::CommonGroups);
auto hasMembersSearch
= (type == Type::Members || type == Type::Profile);
= (type == Type::Members
|| type == Type::Profile
|| type == Type::Channels);
auto searchQuery = memento->searchFieldQuery();
if (isMedia) {
_searchController

View File

@ -42,6 +42,7 @@ public:
Media,
CommonGroups,
Members,
Channels,
};
using MediaType = Storage::SharedMediaType;

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/profile/info_profile_widget.h"
#include "info/media/info_media_widget.h"
#include "info/members/info_members_widget.h"
#include "info/channels/info_channels_widget.h"
#include "info/common_groups/info_common_groups_widget.h"
#include "info/feed/info_feed_profile_widget.h"
#include "info/info_section_widget.h"
@ -108,6 +109,8 @@ std::unique_ptr<ContentMemento> Memento::DefaultContent(
switch (section.type()) {
case Section::Type::Profile:
return std::make_unique<FeedProfile::Memento>(feed);
case Section::Type::Channels:
return std::make_unique<Channels::Memento>(feed);
}
Unexpected("Wrong feed section in Info::Memento::DefaultContent()");
}

View File

@ -584,6 +584,9 @@ rpl::producer<QString> TitleValue(
case Section::Type::Members:
return lng_profile_participants_section;
case Section::Type::Channels:
return lng_info_feed_channels;
}
Unexpected("Bad section type in Info::TitleValue()");
}());

View File

@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include <rpl/producer.h>
#include "info/info_content_widget.h"
struct PeerListState;

View File

@ -286,6 +286,8 @@
<(src_loc)/info/info_top_bar.h
<(src_loc)/info/info_wrap_widget.cpp
<(src_loc)/info/info_wrap_widget.h
<(src_loc)/info/channels/info_channels_widget.cpp
<(src_loc)/info/channels/info_channels_widget.h
<(src_loc)/info/common_groups/info_common_groups_inner_widget.cpp
<(src_loc)/info/common_groups/info_common_groups_inner_widget.h
<(src_loc)/info/common_groups/info_common_groups_widget.cpp