mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Initial add filter / chats / edit filter link.
This commit is contained in:
parent
b7d9d549ff
commit
8a9d13c6e4
9 changed files with 520 additions and 14 deletions
|
@ -7,12 +7,331 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "api/api_chat_filters.h"
|
||||
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "main/main_session.h"
|
||||
#include "apiwrap.h"
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "core/application.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "ui/toasts/common_toasts.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_settings.h"
|
||||
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
enum class ToggleAction {
|
||||
Adding,
|
||||
Removing,
|
||||
};
|
||||
|
||||
enum class HeaderType {
|
||||
AddingFilter,
|
||||
AddingChats,
|
||||
AllAdded,
|
||||
Removing,
|
||||
};
|
||||
|
||||
struct HeaderDescriptor {
|
||||
base::required<HeaderType> type;
|
||||
base::required<QString> title;
|
||||
int badge = 0;
|
||||
};
|
||||
|
||||
class ToggleChatsController final
|
||||
: public PeerListController
|
||||
, public base::has_weak_ptr {
|
||||
public:
|
||||
ToggleChatsController(
|
||||
not_null<Window::SessionController*> window,
|
||||
ToggleAction action,
|
||||
const QString &slug,
|
||||
FilterId filterId,
|
||||
const QString &title,
|
||||
std::vector<not_null<PeerData*>> chats);
|
||||
|
||||
void prepare() override;
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
Main::Session &session() const override;
|
||||
|
||||
[[nodiscard]] auto selectedValue() const
|
||||
-> rpl::producer<base::flat_set<not_null<PeerData*>>>;
|
||||
|
||||
private:
|
||||
void setupAboveWidget();
|
||||
|
||||
const not_null<Window::SessionController*> _window;
|
||||
|
||||
ToggleAction _action = ToggleAction::Adding;
|
||||
QString _slug;
|
||||
FilterId _filterId = 0;
|
||||
QString _filterTitle;
|
||||
std::vector<not_null<PeerData*>> _chats;
|
||||
rpl::variable<base::flat_set<not_null<PeerData*>>> _selected;
|
||||
|
||||
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]] rpl::producer<QString> TitleText(HeaderType type) {
|
||||
// langs
|
||||
switch (type) {
|
||||
case HeaderType::AddingFilter:
|
||||
return rpl::single(u"Add Folder"_q);
|
||||
case HeaderType::AddingChats:
|
||||
return rpl::single(u"Add Chats to Folder"_q);
|
||||
case HeaderType::AllAdded:
|
||||
return rpl::single(u"Folder Already Added"_q);
|
||||
case HeaderType::Removing:
|
||||
return rpl::single(u"Remove Folder"_q);
|
||||
}
|
||||
Unexpected("HeaderType in TitleText.");
|
||||
}
|
||||
|
||||
void FillHeader(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
HeaderDescriptor descriptor) {
|
||||
// langs
|
||||
const auto description = (descriptor.type == HeaderType::AddingFilter)
|
||||
? (u"Do you want to add a new chat folder "_q
|
||||
+ descriptor.title
|
||||
+ u" and join its groups and channels?"_q)
|
||||
: (descriptor.type == HeaderType::AddingChats)
|
||||
? (u"Do you want to join "_q
|
||||
+ QString::number(descriptor.badge)
|
||||
+ u" chats and add them to your folder "_q
|
||||
+ descriptor.title + '?')
|
||||
: (descriptor.type == HeaderType::AllAdded)
|
||||
? (u"You have already added the folder "_q
|
||||
+ descriptor.title
|
||||
+ u" and all its chats."_q)
|
||||
: (u"Do you want to quit the chats you joined "
|
||||
"when adding the folder "_q
|
||||
+ descriptor.title + '?');
|
||||
container->add(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
container,
|
||||
description,
|
||||
st::boxDividerLabel),
|
||||
st::boxRowPadding);
|
||||
}
|
||||
|
||||
void ImportInvite(
|
||||
base::weak_ptr<Window::SessionController> weak,
|
||||
const QString &slug,
|
||||
const base::flat_set<not_null<PeerData*>> &peers) {
|
||||
Expects(!peers.empty());
|
||||
|
||||
const auto peer = peers.front();
|
||||
const auto api = &peer->session().api();
|
||||
const auto callback = [=](const MTPUpdates &result) {
|
||||
api->applyUpdates(result);
|
||||
};
|
||||
const auto error = [=](const MTP::Error &error) {
|
||||
if (const auto strong = weak.get()) {
|
||||
Ui::ShowMultilineToast({
|
||||
.parentOverride = Window::Show(strong).toastParent(),
|
||||
.text = { error.description() },
|
||||
});
|
||||
}
|
||||
};
|
||||
auto inputs = peers | ranges::views::transform([](auto peer) {
|
||||
return MTPInputPeer(peer->input);
|
||||
}) | ranges::to<QVector>();
|
||||
api->request(MTPcommunities_JoinCommunityInvite(
|
||||
MTP_string(slug),
|
||||
MTP_vector<MTPInputPeer>(std::move(inputs))
|
||||
)).done(callback).fail(error).send();
|
||||
}
|
||||
|
||||
ToggleChatsController::ToggleChatsController(
|
||||
not_null<Window::SessionController*> window,
|
||||
ToggleAction action,
|
||||
const QString &slug,
|
||||
FilterId filterId,
|
||||
const QString &title,
|
||||
std::vector<not_null<PeerData*>> chats)
|
||||
: _window(window)
|
||||
, _action(action)
|
||||
, _slug(slug)
|
||||
, _filterId(filterId)
|
||||
, _filterTitle(title)
|
||||
, _chats(std::move(chats)) {
|
||||
}
|
||||
|
||||
void ToggleChatsController::prepare() {
|
||||
setupAboveWidget();
|
||||
auto selected = base::flat_set<not_null<PeerData*>>();
|
||||
for (const auto &peer : _chats) {
|
||||
auto row = std::make_unique<PeerListRow>(peer);
|
||||
const auto raw = row.get();
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
delegate()->peerListSetRowChecked(raw, true);
|
||||
selected.emplace(peer);
|
||||
}
|
||||
delegate()->peerListRefreshRows();
|
||||
_selected = std::move(selected);
|
||||
}
|
||||
|
||||
void ToggleChatsController::rowClicked(not_null<PeerListRow*> row) {
|
||||
const auto peer = row->peer();
|
||||
const auto checked = row->checked();
|
||||
auto selected = _selected.current();
|
||||
delegate()->peerListSetRowChecked(row, !checked);
|
||||
if (checked) {
|
||||
selected.remove(peer);
|
||||
} else {
|
||||
selected.emplace(peer);
|
||||
}
|
||||
_selected = std::move(selected);
|
||||
}
|
||||
|
||||
void ToggleChatsController::setupAboveWidget() {
|
||||
using namespace Settings;
|
||||
|
||||
auto wrap = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
|
||||
const auto container = wrap.data();
|
||||
|
||||
const auto type = !_filterId
|
||||
? HeaderType::AddingFilter
|
||||
: (_action == ToggleAction::Adding)
|
||||
? HeaderType::AddingChats
|
||||
: HeaderType::Removing;
|
||||
delegate()->peerListSetTitle(TitleText(type));
|
||||
FillHeader(container, {
|
||||
.type = type,
|
||||
.title = _filterTitle,
|
||||
.badge = (type == HeaderType::AddingChats) ? int(_chats.size()) : 0,
|
||||
});
|
||||
|
||||
delegate()->peerListSetAboveWidget(std::move(wrap));
|
||||
}
|
||||
|
||||
Main::Session &ToggleChatsController::session() const {
|
||||
return _window->session();
|
||||
}
|
||||
|
||||
auto ToggleChatsController::selectedValue() const
|
||||
-> rpl::producer<base::flat_set<not_null<PeerData*>>> {
|
||||
return _selected.value();
|
||||
}
|
||||
|
||||
[[nodiscard]] void AlreadyFilterBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
const QString &title) {
|
||||
// langs
|
||||
box->setTitle(TitleText(HeaderType::AllAdded));
|
||||
|
||||
FillHeader(box->verticalLayout(), {
|
||||
.type = HeaderType::AllAdded,
|
||||
.title = title,
|
||||
});
|
||||
|
||||
box->addButton(tr::lng_box_ok(), [=] { box->closeBox(); });
|
||||
}
|
||||
|
||||
void ProcessFilterInvite(
|
||||
base::weak_ptr<Window::SessionController> weak,
|
||||
const QString &slug,
|
||||
FilterId filterId,
|
||||
const QString &title,
|
||||
std::vector<not_null<PeerData*>> peers) {
|
||||
const auto strong = weak.get();
|
||||
if (!strong) {
|
||||
return;
|
||||
}
|
||||
Core::App().hideMediaView();
|
||||
if (peers.empty()) {
|
||||
if (filterId) {
|
||||
strong->show(Box(AlreadyFilterBox, title));
|
||||
} else {
|
||||
Ui::ShowMultilineToast({
|
||||
.parentOverride = Window::Show(strong).toastParent(),
|
||||
.text = { tr::lng_group_invite_bad_link(tr::now) },
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto controller = std::make_unique<ToggleChatsController>(
|
||||
strong,
|
||||
ToggleAction::Adding,
|
||||
slug,
|
||||
filterId,
|
||||
title,
|
||||
std::move(peers));
|
||||
const auto raw = controller.get();
|
||||
auto initBox = [=](not_null<Ui::BoxContent*> box) {
|
||||
box->setStyle(st::filterInviteBox);
|
||||
raw->selectedValue(
|
||||
) | rpl::start_with_next([=](
|
||||
base::flat_set<not_null<PeerData*>> &&peers) {
|
||||
const auto count = int(peers.size());
|
||||
|
||||
box->clearButtons();
|
||||
auto button = object_ptr<Ui::RoundButton>(
|
||||
box,
|
||||
rpl::single(count
|
||||
? u"Add %1 Chats"_q.arg(count)
|
||||
: u"Don't add chats"_q),
|
||||
st::defaultActiveButton);
|
||||
const auto raw = button.data();
|
||||
|
||||
box->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
const auto &padding = st::filterInviteBox.buttonPadding;
|
||||
raw->resizeToWidth(width
|
||||
- padding.left()
|
||||
- padding.right());
|
||||
raw->moveToLeft(padding.left(), padding.top());
|
||||
}, raw->lifetime());
|
||||
|
||||
raw->setClickedCallback([=] {
|
||||
if (!count) {
|
||||
box->closeBox();
|
||||
//} else if (count + alreadyInFilter() >= ...) {
|
||||
// #TODO filters
|
||||
} else {
|
||||
ImportInvite(weak, slug, peers);
|
||||
}
|
||||
});
|
||||
|
||||
box->addButton(std::move(button));
|
||||
}, box->lifetime());
|
||||
};
|
||||
strong->show(
|
||||
Box<PeerListBox>(std::move(controller), std::move(initBox)));
|
||||
}
|
||||
|
||||
void ProcessFilterInvite(
|
||||
base::weak_ptr<Window::SessionController> weak,
|
||||
const QString &slug,
|
||||
FilterId filterId,
|
||||
std::vector<not_null<PeerData*>> peers) {
|
||||
const auto strong = weak.get();
|
||||
if (!strong) {
|
||||
return;
|
||||
}
|
||||
Core::App().hideMediaView();
|
||||
const auto &list = strong->session().data().chatsFilters().list();
|
||||
const auto it = ranges::find(list, filterId, &Data::ChatFilter::id);
|
||||
if (it == end(list)) {
|
||||
Ui::ShowMultilineToast({
|
||||
.parentOverride = Window::Show(strong).toastParent(),
|
||||
.text = { u"Filter not found :shrug:"_q },
|
||||
});
|
||||
return;
|
||||
}
|
||||
ProcessFilterInvite(weak, slug, filterId, it->title(), std::move(peers));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void SaveNewFilterPinned(
|
||||
not_null<Main::Session*> session,
|
||||
|
@ -25,7 +344,70 @@ void SaveNewFilterPinned(
|
|||
MTP_int(filterId),
|
||||
filter.tl()
|
||||
)).send();
|
||||
}
|
||||
|
||||
void CheckFilterInvite(
|
||||
not_null<Window::SessionController*> controller,
|
||||
const QString &slug) {
|
||||
const auto session = &controller->session();
|
||||
const auto weak = base::make_weak(controller);
|
||||
session->api().checkFilterInvite(slug, [=](
|
||||
const MTPcommunities_CommunityInvite &result) {
|
||||
const auto strong = weak.get();
|
||||
if (!strong) {
|
||||
return;
|
||||
}
|
||||
auto title = QString();
|
||||
auto filterId = FilterId();
|
||||
auto peers = std::vector<not_null<PeerData*>>();
|
||||
auto already = std::vector<not_null<PeerData*>>();
|
||||
auto &owner = strong->session().data();
|
||||
result.match([&](const auto &data) {
|
||||
owner.processUsers(data.vusers());
|
||||
owner.processChats(data.vchats());
|
||||
});
|
||||
const auto parseList = [&](const MTPVector<MTPPeer> &list) {
|
||||
auto result = std::vector<not_null<PeerData*>>();
|
||||
result.reserve(list.v.size());
|
||||
for (const auto &peer : list.v) {
|
||||
result.push_back(owner.peer(peerFromMTP(peer)));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
result.match([&](const MTPDcommunities_communityInvite &data) {
|
||||
title = qs(data.vtitle());
|
||||
peers = parseList(data.vpeers());
|
||||
}, [&](const MTPDcommunities_communityInviteAlready &data) {
|
||||
filterId = data.vfilter_id().v;
|
||||
peers = parseList(data.vmissing_peers());
|
||||
already = parseList(data.valready_peers());
|
||||
});
|
||||
|
||||
const auto &filters = owner.chatsFilters();
|
||||
const auto notLoaded = filterId
|
||||
&& !ranges::contains(
|
||||
owner.chatsFilters().list(),
|
||||
filterId,
|
||||
&Data::ChatFilter::id);
|
||||
if (notLoaded) {
|
||||
const auto lifetime = std::make_shared<rpl::lifetime>();
|
||||
owner.chatsFilters().changed(
|
||||
) | rpl::start_with_next([=] {
|
||||
lifetime->destroy();
|
||||
ProcessFilterInvite(weak, slug, filterId, std::move(peers));
|
||||
}, *lifetime);
|
||||
owner.chatsFilters().reload();
|
||||
} else if (filterId) {
|
||||
ProcessFilterInvite(weak, slug, filterId, std::move(peers));
|
||||
} else {
|
||||
ProcessFilterInvite(weak, slug, filterId, title, std::move(peers));
|
||||
}
|
||||
}, [=](const MTP::Error &error) {
|
||||
if (error.code() != 400) {
|
||||
return;
|
||||
}
|
||||
ProcessFilterInvite(weak, slug, FilterId(), QString(), {});
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
|
|
|
@ -11,10 +11,18 @@ namespace Main {
|
|||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace Api {
|
||||
|
||||
void SaveNewFilterPinned(
|
||||
not_null<Main::Session*> session,
|
||||
FilterId filterId);
|
||||
|
||||
void CheckFilterInvite(
|
||||
not_null<Window::SessionController*> controller,
|
||||
const QString &slug);
|
||||
|
||||
} // namespace Api
|
||||
|
|
|
@ -380,6 +380,16 @@ void ApiWrap::checkChatInvite(
|
|||
)).done(std::move(done)).fail(std::move(fail)).send();
|
||||
}
|
||||
|
||||
void ApiWrap::checkFilterInvite(
|
||||
const QString &slug,
|
||||
FnMut<void(const MTPcommunities_CommunityInvite &)> done,
|
||||
Fn<void(const MTP::Error &)> fail) {
|
||||
request(base::take(_checkFilterInviteRequestId)).cancel();
|
||||
_checkFilterInviteRequestId = request(
|
||||
MTPcommunities_CheckCommunityInvite(MTP_string(slug))
|
||||
).done(std::move(done)).fail(std::move(fail)).send();
|
||||
}
|
||||
|
||||
void ApiWrap::savePinnedOrder(Data::Folder *folder) {
|
||||
const auto &order = _session->data().pinnedChatsOrder(folder);
|
||||
const auto input = [](Dialogs::Key key) {
|
||||
|
|
|
@ -202,6 +202,10 @@ public:
|
|||
const QString &hash,
|
||||
FnMut<void(const MTPChatInvite &)> done,
|
||||
Fn<void(const MTP::Error &)> fail);
|
||||
void checkFilterInvite(
|
||||
const QString &slug,
|
||||
FnMut<void(const MTPcommunities_CommunityInvite &)> done,
|
||||
Fn<void(const MTP::Error &)> fail);
|
||||
|
||||
void processFullPeer(
|
||||
not_null<PeerData*> peer,
|
||||
|
@ -653,6 +657,7 @@ private:
|
|||
mtpRequestId _termsUpdateRequestId = 0;
|
||||
|
||||
mtpRequestId _checkInviteRequestId = 0;
|
||||
mtpRequestId _checkFilterInviteRequestId = 0;
|
||||
|
||||
struct MigrateCallbacks {
|
||||
FnMut<void(not_null<ChannelData*>)> done;
|
||||
|
|
|
@ -77,6 +77,14 @@ struct InviteLinkAction {
|
|||
}
|
||||
}
|
||||
|
||||
void ShowEmptyLinkError(not_null<Window::SessionController*> window) {
|
||||
// langs
|
||||
Ui::ShowMultilineToast({
|
||||
.parentOverride = Window::Show(window).toastParent(),
|
||||
.text = { u"Link should have at least one chat shared."_q },
|
||||
});
|
||||
}
|
||||
|
||||
void ChatFilterLinkBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
Data::ChatFilterLink data) {
|
||||
|
@ -336,6 +344,7 @@ public:
|
|||
void showFinished() override;
|
||||
|
||||
[[nodiscard]] rpl::producer<bool> hasChangesValue() const;
|
||||
[[nodiscard]] base::flat_set<not_null<PeerData*>> selected() const;
|
||||
|
||||
private:
|
||||
void setupAboveWidget();
|
||||
|
@ -347,14 +356,13 @@ private:
|
|||
|
||||
base::flat_set<not_null<History*>> _filterChats;
|
||||
base::flat_set<not_null<PeerData*>> _allowed;
|
||||
rpl::variable<int> _selected = 0;
|
||||
rpl::variable<base::flat_set<not_null<PeerData*>>> _selected;
|
||||
base::flat_set<not_null<PeerData*>> _initial;
|
||||
|
||||
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||
|
||||
QString _link;
|
||||
|
||||
Ui::RpWidget *_headerWidget = nullptr;
|
||||
rpl::variable<int> _addedHeight;
|
||||
rpl::variable<bool> _hasChanges = false;
|
||||
|
||||
rpl::event_stream<> _showFinished;
|
||||
|
@ -495,7 +503,6 @@ void LinkController::addLinkBlock(not_null<Ui::VerticalLayout*> container) {
|
|||
|
||||
void LinkController::prepare() {
|
||||
setupAboveWidget();
|
||||
auto selected = 0;
|
||||
for (const auto &history : _data.chats) {
|
||||
const auto peer = history->peer;
|
||||
_allowed.emplace(peer);
|
||||
|
@ -503,7 +510,7 @@ void LinkController::prepare() {
|
|||
const auto raw = row.get();
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
delegate()->peerListSetRowChecked(raw, true);
|
||||
++selected;
|
||||
_initial.emplace(peer);
|
||||
}
|
||||
for (const auto &history : _filterChats) {
|
||||
if (delegate()->peerListFindRow(history->peer->id.value)) {
|
||||
|
@ -520,14 +527,23 @@ void LinkController::prepare() {
|
|||
}
|
||||
}
|
||||
delegate()->peerListRefreshRows();
|
||||
_selected = selected;
|
||||
_selected = _initial;
|
||||
}
|
||||
|
||||
void LinkController::rowClicked(not_null<PeerListRow*> row) {
|
||||
if (_allowed.contains(row->peer())) {
|
||||
const auto peer = row->peer();
|
||||
const auto checked = row->checked();
|
||||
auto selected = _selected.current();
|
||||
delegate()->peerListSetRowChecked(row, !checked);
|
||||
_selected = _selected.current() + (checked ? -1 : 1);
|
||||
if (checked) {
|
||||
selected.remove(peer);
|
||||
} else {
|
||||
selected.emplace(peer);
|
||||
}
|
||||
const auto has = (_initial != selected);
|
||||
_selected = std::move(selected);
|
||||
_hasChanges = has;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -546,9 +562,16 @@ void LinkController::setupAboveWidget() {
|
|||
addLinkBlock(container);
|
||||
}
|
||||
|
||||
// langs
|
||||
auto subtitle = _selected.value(
|
||||
) | rpl::map([](const base::flat_set<not_null<PeerData*>> &selected) {
|
||||
return selected.empty()
|
||||
? u"No chats selected"_q
|
||||
: (QString::number(selected.size()) + u" chats selected"_q);
|
||||
});
|
||||
Settings::AddSubsectionTitle(
|
||||
container,
|
||||
rpl::single(u"3 chats selected"_q));
|
||||
std::move(subtitle));
|
||||
|
||||
delegate()->peerListSetAboveWidget(std::move(wrap));
|
||||
}
|
||||
|
@ -561,6 +584,10 @@ rpl::producer<bool> LinkController::hasChangesValue() const {
|
|||
return _hasChanges.value();
|
||||
}
|
||||
|
||||
base::flat_set<not_null<PeerData*>> LinkController::selected() const {
|
||||
return _selected.current();
|
||||
}
|
||||
|
||||
LinksController::LinksController(
|
||||
not_null<Window::SessionController*> window,
|
||||
rpl::producer<std::vector<InviteLinkData>> content,
|
||||
|
@ -804,7 +831,7 @@ void ExportFilterLink(
|
|||
) | ranges::to<QVector>();
|
||||
session->api().request(MTPcommunities_ExportCommunityInvite(
|
||||
MTP_inputCommunityDialogFilter(MTP_int(id)),
|
||||
MTP_string(),
|
||||
MTP_string(), // title
|
||||
MTP_vector<MTPInputPeer>(std::move(mtpPeers))
|
||||
)).done([=](const MTPcommunities_ExportedCommunityInvite &result) {
|
||||
const auto &data = result.data();
|
||||
|
@ -821,6 +848,34 @@ void ExportFilterLink(
|
|||
}).send();
|
||||
}
|
||||
|
||||
void EditLinkChats(
|
||||
const Data::ChatFilterLink &link,
|
||||
base::flat_set<not_null<PeerData*>> peers) {
|
||||
Expects(!peers.empty());
|
||||
Expects(link.id != 0);
|
||||
Expects(!link.url.isEmpty());
|
||||
|
||||
const auto id = link.id;
|
||||
const auto front = peers.front();
|
||||
const auto session = &front->session();
|
||||
auto mtpPeers = peers | ranges::views::transform(
|
||||
[](not_null<PeerData*> peer) { return MTPInputPeer(peer->input); }
|
||||
) | ranges::to<QVector>();
|
||||
session->api().request(MTPcommunities_EditExportedInvite(
|
||||
MTP_flags(MTPcommunities_EditExportedInvite::Flag::f_peers),
|
||||
MTP_inputCommunityDialogFilter(MTP_int(link.id)),
|
||||
MTP_string(link.url),
|
||||
MTPstring(), // title
|
||||
MTP_vector<MTPInputPeer>(std::move(mtpPeers))
|
||||
)).done([=](const MTPExportedCommunityInvite &result) {
|
||||
const auto &data = result.data();
|
||||
const auto link = session->data().chatsFilters().add(id, result);
|
||||
//done(link);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
//done({ .id = id });
|
||||
}).send();
|
||||
}
|
||||
|
||||
object_ptr<Ui::BoxContent> ShowLinkBox(
|
||||
not_null<Window::SessionController*> window,
|
||||
const Data::ChatFilter &filter,
|
||||
|
@ -837,7 +892,12 @@ object_ptr<Ui::BoxContent> ShowLinkBox(
|
|||
box->clearButtons();
|
||||
if (has) {
|
||||
box->addButton(tr::lng_settings_save(), [=] {
|
||||
|
||||
const auto chosen = raw->selected();
|
||||
if (chosen.empty()) {
|
||||
ShowEmptyLinkError(window);
|
||||
} else {
|
||||
EditLinkChats(link, chosen);
|
||||
}
|
||||
});
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
} else {
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_authorizations.h"
|
||||
#include "api/api_confirm_phone.h"
|
||||
#include "api/api_text_entities.h"
|
||||
#include "api/api_chat_filters.h"
|
||||
#include "api/api_chat_invite.h"
|
||||
#include "base/qthelp_regex.h"
|
||||
#include "base/qthelp_url.h"
|
||||
|
@ -78,6 +79,18 @@ bool JoinGroupByHash(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool JoinFilterBySlug(
|
||||
Window::SessionController *controller,
|
||||
const Match &match,
|
||||
const QVariant &context) {
|
||||
if (!controller) {
|
||||
return false;
|
||||
}
|
||||
Api::CheckFilterInvite(controller, match->captured(1));
|
||||
controller->window().activate();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShowStickerSet(
|
||||
Window::SessionController *controller,
|
||||
const Match &match,
|
||||
|
@ -829,6 +842,10 @@ const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
|
|||
u"^join/?\\?invite=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"_q,
|
||||
JoinGroupByHash
|
||||
},
|
||||
{
|
||||
u"^list/?\\?slug=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"_q,
|
||||
JoinFilterBySlug
|
||||
},
|
||||
{
|
||||
u"^(addstickers|addemoji)/?\\?set=([a-zA-Z0-9\\.\\_]+)(&|$)"_q,
|
||||
ShowStickerSet
|
||||
|
@ -953,6 +970,8 @@ QString TryConvertUrlToLocal(QString url) {
|
|||
return u"tg://resolve?phone="_q + phoneMatch->captured(1) + (params.isEmpty() ? QString() : '&' + params);
|
||||
} else if (const auto joinChatMatch = regex_match(u"^(joinchat/|\\+|\\%20)([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"_q, query, matchOptions)) {
|
||||
return u"tg://join?invite="_q + url_encode(joinChatMatch->captured(2));
|
||||
} else if (const auto joinFilterMatch = regex_match(u"^(list/)([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"_q, query, matchOptions)) {
|
||||
return u"tg://list?slug="_q + url_encode(joinFilterMatch->captured(2));
|
||||
} else if (const auto stickerSetMatch = regex_match(u"^(addstickers|addemoji)/([a-zA-Z0-9\\.\\_]+)(\\?|$)"_q, query, matchOptions)) {
|
||||
return u"tg://"_q + stickerSetMatch->captured(1) + "?set=" + url_encode(stickerSetMatch->captured(2));
|
||||
} else if (const auto themeMatch = regex_match(u"^addtheme/([a-zA-Z0-9\\.\\_]+)(\\?|$)"_q, query, matchOptions)) {
|
||||
|
|
|
@ -329,6 +329,11 @@ void ChatFilters::load() {
|
|||
load(false);
|
||||
}
|
||||
|
||||
void ChatFilters::reload() {
|
||||
_reloading = true;
|
||||
load();
|
||||
}
|
||||
|
||||
void ChatFilters::load(bool force) {
|
||||
if (_loadRequestId && !force) {
|
||||
return;
|
||||
|
@ -341,6 +346,10 @@ void ChatFilters::load(bool force) {
|
|||
_loadRequestId = 0;
|
||||
}).fail([=] {
|
||||
_loadRequestId = 0;
|
||||
if (_reloading) {
|
||||
_reloading = false;
|
||||
_listChanged.fire({});
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
||||
|
@ -372,8 +381,9 @@ void ChatFilters::received(const QVector<MTPDialogFilter> &list) {
|
|||
if (!ranges::contains(begin(_list), end(_list), 0, &ChatFilter::id)) {
|
||||
_list.insert(begin(_list), ChatFilter());
|
||||
}
|
||||
if (changed || !_loaded) {
|
||||
if (changed || !_loaded || _reloading) {
|
||||
_loaded = true;
|
||||
_reloading = false;
|
||||
_listChanged.fire({});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@ public:
|
|||
void setPreloaded(const QVector<MTPDialogFilter> &result);
|
||||
|
||||
void load();
|
||||
void reload();
|
||||
void apply(const MTPUpdate &update);
|
||||
void set(ChatFilter filter);
|
||||
void remove(FilterId id);
|
||||
|
@ -175,6 +176,7 @@ private:
|
|||
mtpRequestId _saveOrderRequestId = 0;
|
||||
mtpRequestId _saveOrderAfterId = 0;
|
||||
bool _loaded = false;
|
||||
bool _reloading = false;
|
||||
|
||||
mtpRequestId _suggestedRequestId = 0;
|
||||
std::vector<SuggestedFilter> _suggested;
|
||||
|
|
|
@ -538,3 +538,13 @@ powerSavingButtonNoIcon: SettingsButton(powerSavingButton) {
|
|||
padding: margins(22px, 8px, 22px, 8px);
|
||||
}
|
||||
powerSavingSubtitlePadding: margins(0px, 4px, 0px, -2px);
|
||||
|
||||
filterInviteBox: Box(defaultBox) {
|
||||
buttonPadding: margins(12px, 12px, 12px, 12px);
|
||||
buttonHeight: 44px;
|
||||
button: RoundButton(defaultActiveButton) {
|
||||
height: 44px;
|
||||
textTop: 12px;
|
||||
font: font(13px semibold);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue