Allow searching in link group to channel box.
This commit is contained in:
parent
a5ea13f248
commit
33ea5ad297
|
@ -134,6 +134,8 @@ void ShowAddParticipantsError(
|
|||
return lang(lng_failed_add_not_mutual);
|
||||
} else if (error == qstr("USER_ALREADY_PARTICIPANT") && hasBot) {
|
||||
return lang(lng_bot_already_in_group);
|
||||
} else if (error == qstr("BOT_GROUPS_BLOCKED")) {
|
||||
return lang(lng_error_cant_add_bot);
|
||||
} else if (error == qstr("PEER_FLOOD")) {
|
||||
const auto isGroup = (chat->isChat() || chat->isMegagroup());
|
||||
return PeerFloodErrorText(isGroup
|
||||
|
|
|
@ -73,7 +73,7 @@ void PeerListBox::createMultiSelect() {
|
|||
_controller->itemDeselectedHook(peer);
|
||||
}
|
||||
});
|
||||
_select->resizeToWidth(st::boxWideWidth);
|
||||
_select->resizeToWidth(_controller->contentWidth());
|
||||
_select->moveToLeft(0, 0);
|
||||
}
|
||||
|
||||
|
@ -101,11 +101,11 @@ void PeerListBox::prepare() {
|
|||
_controller.get(),
|
||||
st::peerListBox),
|
||||
st::boxLayerScroll));
|
||||
content()->resizeToWidth(st::boxWideWidth);
|
||||
content()->resizeToWidth(_controller->contentWidth());
|
||||
|
||||
_controller->setDelegate(this);
|
||||
|
||||
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
|
||||
setDimensions(_controller->contentWidth(), st::boxMaxListHeight);
|
||||
if (_select) {
|
||||
_select->finishAnimating();
|
||||
Ui::SendPendingMoveResizeEvents(_select);
|
||||
|
@ -281,6 +281,10 @@ void PeerListController::restoreState(
|
|||
delegate()->peerListRestoreState(std::move(state));
|
||||
}
|
||||
|
||||
int PeerListController::contentWidth() const {
|
||||
return st::boxWideWidth;
|
||||
}
|
||||
|
||||
void PeerListBox::addSelectItem(not_null<PeerData*> peer, PeerListRow::SetStyle style) {
|
||||
if (!_select) {
|
||||
createMultiSelect();
|
||||
|
@ -825,13 +829,20 @@ void PeerListContent::setSearchNoResults(object_ptr<Ui::FlatLabel> noResults) {
|
|||
}
|
||||
}
|
||||
|
||||
void PeerListContent::setAboveWidget(object_ptr<TWidget> aboveWidget) {
|
||||
_aboveWidget = std::move(aboveWidget);
|
||||
void PeerListContent::setAboveWidget(object_ptr<TWidget> widget) {
|
||||
_aboveWidget = std::move(widget);
|
||||
if (_aboveWidget) {
|
||||
_aboveWidget->setParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListContent::setBelowWidget(object_ptr<TWidget> widget) {
|
||||
_belowWidget = std::move(widget);
|
||||
if (_belowWidget) {
|
||||
_belowWidget->setParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
int PeerListContent::labelHeight() const {
|
||||
auto computeLabelHeight = [](auto &label) {
|
||||
if (!label) {
|
||||
|
@ -937,9 +948,9 @@ int PeerListContent::resizeGetHeight(int newWidth) {
|
|||
_aboveHeight = _aboveWidget->height();
|
||||
}
|
||||
}
|
||||
auto rowsCount = shownRowsCount();
|
||||
auto labelTop = rowsTop() + qMax(1, shownRowsCount()) * _rowHeight;
|
||||
auto labelWidth = newWidth - 2 * st::contactsPadding.left();
|
||||
const auto rowsCount = shownRowsCount();
|
||||
const auto labelTop = rowsTop() + qMax(1, shownRowsCount()) * _rowHeight;
|
||||
const auto labelWidth = newWidth - 2 * st::contactsPadding.left();
|
||||
if (_description) {
|
||||
_description->resizeToWidth(labelWidth);
|
||||
_description->moveToLeft(st::contactsPadding.left(), labelTop + st::membersAboutLimitPadding.top(), newWidth);
|
||||
|
@ -955,9 +966,22 @@ int PeerListContent::resizeGetHeight(int newWidth) {
|
|||
_searchLoading->moveToLeft(st::contactsPadding.left(), labelTop + st::membersAboutLimitPadding.top(), newWidth);
|
||||
_searchLoading->setVisible(showingSearch() && _filterResults.empty() && _controller->isSearchLoading());
|
||||
}
|
||||
auto label = labelHeight();
|
||||
return ((label > 0 || rowsCount > 0) ? (labelTop + label) : 0)
|
||||
+ _st.padding.bottom();
|
||||
const auto label = labelHeight();
|
||||
const auto belowTop = (label > 0 || rowsCount > 0)
|
||||
? (labelTop + label + _st.padding.bottom())
|
||||
: _aboveHeight;
|
||||
_belowHeight = 0;
|
||||
if (_belowWidget) {
|
||||
_belowWidget->resizeToWidth(newWidth);
|
||||
_belowWidget->moveToLeft(0, belowTop, newWidth);
|
||||
if (showingSearch()) {
|
||||
_belowWidget->hide();
|
||||
} else {
|
||||
_belowWidget->show();
|
||||
_belowHeight = _belowWidget->height();
|
||||
}
|
||||
}
|
||||
return belowTop + _belowHeight;
|
||||
}
|
||||
|
||||
void PeerListContent::enterEventHook(QEvent *e) {
|
||||
|
|
|
@ -231,6 +231,7 @@ public:
|
|||
virtual void peerListSetSearchLoading(object_ptr<Ui::FlatLabel> loading) = 0;
|
||||
virtual void peerListSetSearchNoResults(object_ptr<Ui::FlatLabel> noResults) = 0;
|
||||
virtual void peerListSetAboveWidget(object_ptr<TWidget> aboveWidget) = 0;
|
||||
virtual void peerListSetBelowWidget(object_ptr<TWidget> belowWidget) = 0;
|
||||
virtual void peerListSetSearchMode(PeerListSearchMode mode) = 0;
|
||||
virtual void peerListAppendRow(std::unique_ptr<PeerListRow> row) = 0;
|
||||
virtual void peerListAppendSearchRow(std::unique_ptr<PeerListRow> row) = 0;
|
||||
|
@ -358,6 +359,8 @@ public:
|
|||
virtual void restoreState(
|
||||
std::unique_ptr<PeerListState> state);
|
||||
|
||||
virtual int contentWidth() const;
|
||||
|
||||
bool isRowSelected(not_null<PeerData*> peer) {
|
||||
return delegate()->peerListIsRowSelected(peer);
|
||||
}
|
||||
|
@ -457,7 +460,8 @@ public:
|
|||
void setDescription(object_ptr<Ui::FlatLabel> description);
|
||||
void setSearchLoading(object_ptr<Ui::FlatLabel> loading);
|
||||
void setSearchNoResults(object_ptr<Ui::FlatLabel> noResults);
|
||||
void setAboveWidget(object_ptr<TWidget> aboveWidget);
|
||||
void setAboveWidget(object_ptr<TWidget> widget);
|
||||
void setBelowWidget(object_ptr<TWidget> width);
|
||||
void refreshRows();
|
||||
|
||||
void setSearchMode(PeerListSearchMode mode);
|
||||
|
@ -613,7 +617,9 @@ private:
|
|||
std::vector<not_null<PeerListRow*>> _filterResults;
|
||||
|
||||
int _aboveHeight = 0;
|
||||
int _belowHeight = 0;
|
||||
object_ptr<TWidget> _aboveWidget = { nullptr };
|
||||
object_ptr<TWidget> _belowWidget = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _description = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _searchNoResults = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _searchLoading = { nullptr };
|
||||
|
@ -692,6 +698,9 @@ public:
|
|||
void peerListSetAboveWidget(object_ptr<TWidget> aboveWidget) override {
|
||||
_content->setAboveWidget(std::move(aboveWidget));
|
||||
}
|
||||
void peerListSetBelowWidget(object_ptr<TWidget> belowWidget) override {
|
||||
_content->setBelowWidget(std::move(belowWidget));
|
||||
}
|
||||
void peerListSetSearchMode(PeerListSearchMode mode) override {
|
||||
_content->setSearchMode(mode);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace {
|
||||
|
||||
constexpr auto kEnableSearchRowsCount = 10;
|
||||
|
||||
TextWithEntities BoldText(const QString &text) {
|
||||
auto result = TextWithEntities{ text };
|
||||
result.entities.push_back(
|
||||
|
@ -28,68 +30,78 @@ TextWithEntities BoldText(const QString &text) {
|
|||
return result;
|
||||
}
|
||||
|
||||
class ListController
|
||||
: public PeerListController
|
||||
, public PeerListContentDelegate {
|
||||
class Controller : public PeerListController {
|
||||
public:
|
||||
ListController(Fn<void(not_null<ChannelData*>)> callback)
|
||||
: _callback(std::move(callback)) {
|
||||
}
|
||||
void prepare() override {
|
||||
}
|
||||
void rowClicked(not_null<PeerListRow*> row) override {
|
||||
const auto onstack = _callback;
|
||||
onstack(row->peer()->asChannel());
|
||||
}
|
||||
void peerListSetTitle(Fn<QString()> title) override {
|
||||
}
|
||||
void peerListSetAdditionalTitle(Fn<QString()> title) override {
|
||||
}
|
||||
bool peerListIsRowSelected(not_null<PeerData*> peer) override {
|
||||
return false;
|
||||
}
|
||||
int peerListSelectedRowsCount() override {
|
||||
return 0;
|
||||
}
|
||||
auto peerListCollectSelectedRows()
|
||||
-> std::vector<not_null<PeerData*>> override {
|
||||
return {};
|
||||
}
|
||||
void peerListScrollToTop() override {
|
||||
}
|
||||
void peerListAddSelectedRowInBunch(
|
||||
not_null<PeerData*> peer) override {
|
||||
}
|
||||
void peerListFinishSelectedRowsBunch() override {
|
||||
}
|
||||
void peerListSetDescription(
|
||||
object_ptr<Ui::FlatLabel> description) override {
|
||||
}
|
||||
|
||||
private:
|
||||
Fn<void(not_null<ChannelData*>)> _callback;
|
||||
|
||||
};
|
||||
|
||||
object_ptr<Ui::RpWidget> SetupList(
|
||||
not_null<QWidget*> parent,
|
||||
Controller(
|
||||
not_null<ChannelData*> channel,
|
||||
ChannelData *chat,
|
||||
const std::vector<not_null<ChannelData*>> &chats,
|
||||
Fn<void(ChannelData*)> callback) {
|
||||
const auto already = (chat != nullptr);
|
||||
const auto selected = [=](not_null<ChannelData*> chat) {
|
||||
if (already) {
|
||||
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
|
||||
Fn<void(ChannelData*)> callback);
|
||||
|
||||
void prepare() override;
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
int contentWidth() const override;
|
||||
|
||||
private:
|
||||
not_null<ChannelData*> _channel;
|
||||
ChannelData *_chat = nullptr;
|
||||
std::vector<not_null<ChannelData*>> _chats;
|
||||
Fn<void(ChannelData*)> _callback;
|
||||
|
||||
};
|
||||
|
||||
Controller::Controller(
|
||||
not_null<ChannelData*> channel,
|
||||
ChannelData *chat,
|
||||
const std::vector<not_null<ChannelData*>> &chats,
|
||||
Fn<void(ChannelData*)> callback)
|
||||
: _channel(channel)
|
||||
, _chat(chat)
|
||||
, _chats(std::move(chats))
|
||||
, _callback(std::move(callback)) {
|
||||
}
|
||||
|
||||
int Controller::contentWidth() const {
|
||||
return st::boxWidth;
|
||||
}
|
||||
|
||||
void Controller::prepare() {
|
||||
const auto appendRow = [&](not_null<ChannelData*> chat) {
|
||||
if (delegate()->peerListFindRow(chat->id)) {
|
||||
return;
|
||||
}
|
||||
auto row = std::make_unique<PeerListRow>(chat);
|
||||
row->setCustomStatus(chat->isPublic()
|
||||
? ('@' + chat->username)
|
||||
: lang(lng_manage_discussion_group_private));
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
};
|
||||
if (_chat) {
|
||||
appendRow(_chat);
|
||||
} else {
|
||||
for (const auto chat : _chats) {
|
||||
appendRow(chat);
|
||||
}
|
||||
if (_chats.size() >= kEnableSearchRowsCount) {
|
||||
delegate()->peerListSetSearchMode(PeerListSearchMode::Enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::rowClicked(not_null<PeerListRow*> row) {
|
||||
if (_chat != nullptr) {
|
||||
Ui::showPeerHistory(_chat, ShowAtUnreadMsgId);
|
||||
return;
|
||||
}
|
||||
const auto chat = row->peer()->asChannel();
|
||||
auto text = lng_manage_discussion_group_sure__generic<
|
||||
TextWithEntities
|
||||
>(
|
||||
lt_group,
|
||||
BoldText(chat->name),
|
||||
lt_channel,
|
||||
BoldText(channel->name));
|
||||
if (!channel->isPublic()) {
|
||||
BoldText(_channel->name));
|
||||
if (!_channel->isPublic()) {
|
||||
text.append(
|
||||
"\n\n" + lang(lng_manage_linked_channel_private));
|
||||
}
|
||||
|
@ -98,7 +110,8 @@ object_ptr<Ui::RpWidget> SetupList(
|
|||
if (*box) {
|
||||
(*box)->closeBox();
|
||||
}
|
||||
callback(chat);
|
||||
const auto onstack = _callback;
|
||||
onstack(chat);
|
||||
};
|
||||
*box = Ui::show(
|
||||
Box<ConfirmBox>(
|
||||
|
@ -106,31 +119,6 @@ object_ptr<Ui::RpWidget> SetupList(
|
|||
lang(lng_manage_discussion_group_link),
|
||||
sure),
|
||||
LayerOption::KeepOther);
|
||||
}
|
||||
};
|
||||
const auto controller = Ui::CreateChild<ListController>(
|
||||
parent.get(),
|
||||
selected);
|
||||
controller->setDelegate(controller);
|
||||
auto list = object_ptr<PeerListContent>(
|
||||
parent,
|
||||
controller,
|
||||
st::peerListBox);
|
||||
const auto createRow = [](not_null<ChannelData*> chat) {
|
||||
auto result = std::make_unique<PeerListRow>(chat);
|
||||
result->setCustomStatus(chat->isPublic()
|
||||
? ('@' + chat->username)
|
||||
: lang(lng_manage_discussion_group_private));
|
||||
return result;
|
||||
};
|
||||
if (chat) {
|
||||
list->appendRow(createRow(chat));
|
||||
} else {
|
||||
for (const auto chat : chats) {
|
||||
list->appendRow(createRow(chat));
|
||||
}
|
||||
}
|
||||
return std::move(list);
|
||||
}
|
||||
|
||||
object_ptr<Ui::RpWidget> SetupAbout(
|
||||
|
@ -211,58 +199,57 @@ object_ptr<Ui::RpWidget> SetupUnlink(
|
|||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EditLinkedChatBox::EditLinkedChatBox(
|
||||
QWidget*,
|
||||
not_null<ChannelData*> channel,
|
||||
const std::vector<not_null<ChannelData*>> &chats,
|
||||
Fn<void(ChannelData*)> callback)
|
||||
: _channel(channel)
|
||||
, _content(setupContent(channel, nullptr, chats, callback)) {
|
||||
}
|
||||
|
||||
EditLinkedChatBox::EditLinkedChatBox(
|
||||
QWidget*,
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<ChannelData*> chat,
|
||||
Fn<void(ChannelData*)> callback)
|
||||
: _channel(channel)
|
||||
, _content(setupContent(channel, chat, {}, callback)) {
|
||||
}
|
||||
|
||||
object_ptr<Ui::RpWidget> EditLinkedChatBox::setupContent(
|
||||
object_ptr<BoxContent> EditLinkedChatBox(
|
||||
not_null<ChannelData*> channel,
|
||||
ChannelData *chat,
|
||||
const std::vector<not_null<ChannelData*>> &chats,
|
||||
std::vector<not_null<ChannelData*>> &&chats,
|
||||
Fn<void(ChannelData*)> callback) {
|
||||
Expects(channel->isBroadcast() || (chat != nullptr));
|
||||
|
||||
auto result = object_ptr<Ui::VerticalLayout>(this);
|
||||
result->add(
|
||||
SetupAbout(result, channel, chat),
|
||||
const auto init = [=](not_null<PeerListBox*> box) {
|
||||
auto above = object_ptr<Ui::VerticalLayout>(box);
|
||||
above->add(
|
||||
SetupAbout(above, channel, chat),
|
||||
st::linkedChatAboutPadding);
|
||||
if (!chat) {
|
||||
result->add(SetupCreateGroup(result, channel, callback));
|
||||
above->add(SetupCreateGroup(above, channel, callback));
|
||||
}
|
||||
result->add(SetupList(result, channel, chat, chats, callback));
|
||||
if (chat) {
|
||||
result->add(SetupUnlink(result, channel, callback));
|
||||
}
|
||||
result->add(
|
||||
SetupFooter(result, channel),
|
||||
st::linkedChatAboutPadding);
|
||||
return result;
|
||||
}
|
||||
box->peerListSetAboveWidget(std::move(above));
|
||||
|
||||
void EditLinkedChatBox::prepare() {
|
||||
setTitle(langFactory(_channel->isBroadcast()
|
||||
auto below = object_ptr<Ui::VerticalLayout>(box);
|
||||
if (chat) {
|
||||
below->add(SetupUnlink(below, channel, callback));
|
||||
}
|
||||
below->add(
|
||||
SetupFooter(below, channel),
|
||||
st::linkedChatAboutPadding);
|
||||
box->peerListSetBelowWidget(std::move(below));
|
||||
|
||||
box->setTitle(langFactory(channel->isBroadcast()
|
||||
? lng_manage_discussion_group
|
||||
: lng_manage_linked_channel));
|
||||
|
||||
setDimensionsToContent(
|
||||
st::boxWidth,
|
||||
setInnerWidget(std::move(_content)));
|
||||
|
||||
addButton(langFactory(lng_close), [=] { closeBox(); });
|
||||
box->addButton(langFactory(lng_close), [=] { box->closeBox(); });
|
||||
};
|
||||
auto controller = std::make_unique<Controller>(
|
||||
channel,
|
||||
chat,
|
||||
std::move(chats),
|
||||
std::move(callback));
|
||||
return Box<PeerListBox>(std::move(controller), init);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
object_ptr<BoxContent> EditLinkedChatBox(
|
||||
not_null<ChannelData*> channel,
|
||||
std::vector<not_null<ChannelData*>> &&chats,
|
||||
Fn<void(ChannelData*)> callback) {
|
||||
return EditLinkedChatBox(channel, nullptr, std::move(chats), callback);
|
||||
}
|
||||
|
||||
object_ptr<BoxContent> EditLinkedChatBox(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<ChannelData*> chat,
|
||||
Fn<void(ChannelData*)> callback) {
|
||||
return EditLinkedChatBox(channel, chat, {}, callback);
|
||||
}
|
||||
|
|
|
@ -9,30 +9,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "boxes/abstract_box.h"
|
||||
|
||||
class EditLinkedChatBox : public BoxContent {
|
||||
public:
|
||||
EditLinkedChatBox(
|
||||
QWidget*,
|
||||
object_ptr<BoxContent> EditLinkedChatBox(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<ChannelData*> chat,
|
||||
Fn<void(ChannelData*)> callback);
|
||||
EditLinkedChatBox(
|
||||
QWidget*,
|
||||
|
||||
object_ptr<BoxContent> EditLinkedChatBox(
|
||||
not_null<ChannelData*> channel,
|
||||
const std::vector<not_null<ChannelData*>> &chats,
|
||||
std::vector<not_null<ChannelData*>> &&chats,
|
||||
Fn<void(ChannelData*)> callback);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
private:
|
||||
object_ptr<Ui::RpWidget> setupContent(
|
||||
not_null<ChannelData*> channel,
|
||||
ChannelData *chat,
|
||||
const std::vector<not_null<ChannelData*>> &chats,
|
||||
Fn<void(ChannelData*)> callback);
|
||||
|
||||
not_null<ChannelData*> _channel;
|
||||
object_ptr<Ui::RpWidget> _content;
|
||||
|
||||
};
|
|
@ -518,7 +518,7 @@ void Controller::showEditLinkedChatBox() {
|
|||
};
|
||||
if (const auto chat = *_linkedChatSavedValue) {
|
||||
*box = Ui::show(
|
||||
Box<EditLinkedChatBox>(channel, chat, callback),
|
||||
EditLinkedChatBox(channel, chat, callback),
|
||||
LayerOption::KeepOther);
|
||||
return;
|
||||
} else if (_linkedChatsRequestId) {
|
||||
|
@ -541,10 +541,11 @@ void Controller::showEditLinkedChatBox() {
|
|||
const auto chat = _peer->owner().processChat(item);
|
||||
if (chat->isChannel()) {
|
||||
chats.emplace_back(chat->asChannel());
|
||||
} else if (chat->isChat()) {
|
||||
}
|
||||
}
|
||||
*box = Ui::show(
|
||||
Box<EditLinkedChatBox>(channel, chats, callback),
|
||||
EditLinkedChatBox(channel, std::move(chats), callback),
|
||||
LayerOption::KeepOther);
|
||||
}).fail([=](const RPCError &error) {
|
||||
_linkedChatsRequestId = 0;
|
||||
|
@ -779,7 +780,7 @@ void Controller::fillManageSection() {
|
|||
return !isChannel
|
||||
? false
|
||||
: channel->isBroadcast()
|
||||
? (channel->linkedChat() && channel->canEditInformation())
|
||||
? channel->canEditInformation()
|
||||
: (channel->linkedChat()
|
||||
&& channel->canPinMessages()
|
||||
&& channel->adminRights() != 0);
|
||||
|
|
|
@ -436,7 +436,7 @@ infoBlockButton: InfoProfileButton(infoProfileButton) {
|
|||
textFgOver: attentionButtonFgOver;
|
||||
}
|
||||
infoCreateLinkedChatButton: InfoProfileButton(infoMainButton) {
|
||||
padding: margins(73px, 10px, 8px, 8px);
|
||||
padding: margins(74px, 10px, 8px, 8px);
|
||||
}
|
||||
infoUnlinkChatButton: InfoProfileButton(infoCreateLinkedChatButton) {
|
||||
textFg: attentionButtonFg;
|
||||
|
|
Loading…
Reference in New Issue