Support topic choosing in ShareBox.

This commit is contained in:
John Preston 2022-11-01 15:17:13 +04:00
parent 7384cd3463
commit e6c2aa8021
14 changed files with 273 additions and 117 deletions

View file

@ -1141,7 +1141,7 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
showToast(tr::lng_group_invite_copied(tr::now));
};
auto submitCallback = [=](
std::vector<not_null<PeerData*>> &&result,
std::vector<not_null<Data::Thread*>> &&result,
TextWithTags &&comment,
Api::SendOptions options,
Data::ForwardOptions) {
@ -1150,12 +1150,12 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
}
const auto error = [&] {
for (const auto peer : result) {
for (const auto thread : result) {
const auto error = GetErrorTextForSending(
peer,
thread,
{ .text = &comment });
if (!error.isEmpty()) {
return std::make_pair(error, peer);
return std::make_pair(error, thread);
}
}
return std::make_pair(QString(), result.front());
@ -1164,7 +1164,7 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
auto text = TextWithEntities();
if (result.size() > 1) {
text.append(
Ui::Text::Bold(error.second->name())
Ui::Text::Bold(error.second->chatListName())
).append("\n\n");
}
text.append(error.first);
@ -1188,10 +1188,9 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
}
const auto owner = &peer->owner();
auto &api = peer->session().api();
for (const auto peer : result) {
const auto history = owner->history(peer);
for (const auto thread : result) {
auto message = Api::MessageToSend(
Api::SendAction(history, options));
Api::SendAction(thread, options));
message.textWithTags = comment;
message.action.clearDraft = false;
api.sendMessage(std::move(message));
@ -1204,8 +1203,8 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
auto object = Box<ShareBox>(ShareBox::Descriptor{
.session = &peer->session(),
.copyCallback = std::move(copyCallback),
.submitCallback = std::move(submitCallback), // #TODO forum share
.filterCallback = [](auto peer) { return peer->canWrite(); },
.submitCallback = std::move(submitCallback),
.filterCallback = [](auto thread) { return thread->canWrite(); },
});
*box = Ui::MakeWeak(object.data());
return object;

View file

@ -35,7 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_context_menu.h" // CopyPostLink.
#include "history/view/history_view_schedule_box.h"
#include "window/window_session_controller.h"
#include "boxes/peer_list_box.h"
#include "boxes/peer_list_controllers.h"
#include "chat_helpers/emoji_suggestions_widget.h"
#include "data/data_channel.h"
#include "data/data_game.h"
@ -43,6 +43,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h"
#include "data/data_session.h"
#include "data/data_folder.h"
#include "data/data_forum.h"
#include "data/data_forum_topic.h"
#include "data/data_changes.h"
#include "main/main_session.h"
#include "core/application.h"
@ -57,14 +59,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class ShareBox::Inner final : public Ui::RpWidget {
public:
Inner(QWidget *parent, const Descriptor &descriptor);
Inner(
QWidget *parent,
const Descriptor &descriptor,
std::shared_ptr<Ui::BoxShow> show);
void setPeerSelectedChangedCallback(
Fn<void(PeerData *peer, bool selected)> callback);
Fn<void(not_null<Data::Thread*> thread, bool selected)> callback);
void peerUnselected(not_null<PeerData*> peer);
std::vector<not_null<PeerData*>> selected() const;
bool hasSelected() const;
[[nodiscard]] std::vector<not_null<Data::Thread*>> selected() const;
[[nodiscard]] bool hasSelected() const;
void peopleReceived(
const QString &query,
@ -95,11 +100,13 @@ protected:
private:
struct Chat {
Chat(
PeerData *peer,
not_null<PeerData*> peer,
const style::PeerListItem &st,
Fn<void()> updateCallback);
PeerData *peer;
not_null<PeerData*> peer;
Data::ForumTopic *topic = nullptr;
rpl::lifetime topicLifetime;
Ui::RoundImageCheckbox checkbox;
Ui::Text::String name;
Ui::Animations::Simple nameActive;
@ -107,11 +114,13 @@ private:
void invalidateCache();
int displayedChatsCount() const;
[[nodiscard]] int displayedChatsCount() const;
[[nodiscard]] not_null<Data::Thread*> chatThread(
not_null<Chat*> chat) const;
void paintChat(Painter &p, not_null<Chat*> chat, int index);
void updateChat(not_null<PeerData*> peer);
void updateChatName(not_null<Chat*> chat, not_null<PeerData*> peer);
void updateChatName(not_null<Chat*> chat);
void repaintChat(not_null<PeerData*> peer);
int chatIndex(not_null<PeerData*> peer) const;
void repaintChatAtIndex(int index);
@ -119,6 +128,7 @@ private:
void loadProfilePhotos(int yFrom);
void changeCheckState(Chat *chat);
void chooseForumTopic(not_null<Data::Forum*> forum);
enum class ChangeStateWay {
Default,
SkipCallback,
@ -135,6 +145,7 @@ private:
void refresh();
const Descriptor &_descriptor;
const std::shared_ptr<Ui::BoxShow> _show;
const style::PeerList &_st;
float64 _columnSkip = 0.;
@ -152,9 +163,9 @@ private:
std::vector<not_null<Dialogs::Row*>> _filtered;
std::map<not_null<PeerData*>, std::unique_ptr<Chat>> _dataMap;
base::flat_set<not_null<PeerData*>> _selected;
base::flat_set<not_null<Data::Thread*>> _selected;
Fn<void(PeerData *peer, bool selected)> _peerSelectedChangedCallback;
Fn<void(not_null<Data::Thread*>, bool)> _peerSelectedChangedCallback;
bool _searching = false;
QString _lastQuery;
@ -247,7 +258,7 @@ void ShareBox::prepare() {
setTitle(tr::lng_share_title());
_inner = setInnerWidget(
object_ptr<Inner>(this, _descriptor),
object_ptr<Inner>(this, _descriptor, _show),
getTopScrollSkip(),
getBottomScrollSkip());
@ -293,8 +304,10 @@ void ShareBox::prepare() {
scrollTo(request);
}, _inner->lifetime());
_inner->setPeerSelectedChangedCallback([=](PeerData *peer, bool checked) {
innerSelectedChanged(peer, checked);
_inner->setPeerSelectedChangedCallback([=](
not_null<Data::Thread*> thread,
bool checked) {
innerSelectedChanged(thread, checked);
});
Ui::Emoji::SuggestionsController::Init(
@ -442,9 +455,11 @@ void ShareBox::keyPressEvent(QKeyEvent *e) {
SendMenu::Type ShareBox::sendMenuType() const {
const auto selected = _inner->selected();
return ranges::all_of(selected, HistoryView::CanScheduleUntilOnline)
return ranges::all_of(
selected | ranges::views::transform(&Data::Thread::peer),
HistoryView::CanScheduleUntilOnline)
? SendMenu::Type::ScheduledToUser
: (selected.size() == 1 && selected.front()->isSelf())
: (selected.size() == 1 && selected.front()->peer()->isSelf())
? SendMenu::Type::Reminder
: SendMenu::Type::Scheduled;
}
@ -522,23 +537,51 @@ void ShareBox::applyFilterUpdate(const QString &query) {
_inner->updateFilter(query);
}
void ShareBox::addPeerToMultiSelect(PeerData *peer, bool skipAnimation) {
using AddItemWay = Ui::MultiSelect::AddItemWay;
auto addItemWay = skipAnimation ? AddItemWay::SkipAnimation : AddItemWay::Default;
PaintRoundImageCallback ForceRoundUserpicCallback(not_null<PeerData*> peer) {
auto userpic = std::shared_ptr<Data::CloudImageView>();
auto cache = std::make_shared<QImage>();
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
const auto ratio = style::DevicePixelRatio();
const auto cacheSize = QSize(size, size) * ratio;
if (cache->size() != cacheSize) {
*cache = QImage(cacheSize, QImage::Format_ARGB32_Premultiplied);
cache->setDevicePixelRatio(ratio);
}
auto q = Painter(cache.get());
peer->paintUserpicLeft(q, userpic, 0, 0, outerWidth, size);
q.end();
*cache = Images::Circle(std::move(*cache));
p.drawImage(x, y, *cache);
};
}
void ShareBox::addPeerToMultiSelect(not_null<Data::Thread*> thread) {
auto addItemWay = Ui::MultiSelect::AddItemWay::Default;
const auto peer = thread->peer();
const auto topic = thread->asTopic();
_select->addItem(
peer->id.value,
peer->isSelf() ? tr::lng_saved_short(tr::now) : peer->shortName(),
(topic
? topic->title()
: peer->isSelf()
? tr::lng_saved_short(tr::now)
: peer->shortName()),
st::activeButtonBg,
PaintUserpicCallback(peer, true),
(topic
? ForceRoundUserpicCallback(peer)
: PaintUserpicCallback(peer, true)),
addItemWay);
}
void ShareBox::innerSelectedChanged(PeerData *peer, bool checked) {
void ShareBox::innerSelectedChanged(
not_null<Data::Thread*> thread,
bool checked) {
if (checked) {
addPeerToMultiSelect(peer);
addPeerToMultiSelect(thread);
_select->clearQuery();
} else {
_select->removeItem(peer->id.value);
_select->removeItem(thread->peer()->id.value);
}
selectedChanged();
update();
@ -612,9 +655,13 @@ void ShareBox::scrollAnimationCallback() {
//scrollArea()->scrollToY(scrollTop);
}
ShareBox::Inner::Inner(QWidget *parent, const Descriptor &descriptor)
ShareBox::Inner::Inner(
QWidget *parent,
const Descriptor &descriptor,
std::shared_ptr<Ui::BoxShow> show)
: RpWidget(parent)
, _descriptor(descriptor)
, _show(std::move(show))
, _st(_descriptor.st ? *_descriptor.st : st::shareBoxList)
, _chatsIndexed(
std::make_unique<Dialogs::IndexedList>(
@ -624,14 +671,16 @@ ShareBox::Inner::Inner(QWidget *parent, const Descriptor &descriptor)
setAttribute(Qt::WA_OpaquePaintEvent);
const auto self = _descriptor.session->user();
if (_descriptor.filterCallback(self)) {
_chatsIndexed->addToEnd(self->owner().history(self));
const auto selfHistory = self->owner().history(self);
if (_descriptor.filterCallback(selfHistory)) {
_chatsIndexed->addToEnd(selfHistory);
}
const auto addList = [&](not_null<Dialogs::IndexedList*> list) {
for (const auto &row : list->all()) {
if (const auto history = row->history()) {
if (!history->peer->isSelf()
&& _descriptor.filterCallback(history->peer)) {
&& (history->asForum()
|| _descriptor.filterCallback(history))) {
_chatsIndexed->addToEnd(history);
}
}
@ -715,15 +764,16 @@ void ShareBox::Inner::activateSkipPage(int pageHeight, int direction) {
void ShareBox::Inner::updateChat(not_null<PeerData*> peer) {
if (const auto i = _dataMap.find(peer); i != end(_dataMap)) {
updateChatName(i->second.get(), peer);
updateChatName(i->second.get());
repaintChat(peer);
}
}
void ShareBox::Inner::updateChatName(
not_null<Chat*> chat,
not_null<PeerData*> peer) {
const auto text = peer->isSelf()
void ShareBox::Inner::updateChatName(not_null<Chat*> chat) {
const auto peer = chat->peer;
const auto text = chat->topic
? chat->topic->title()
: peer->isSelf()
? tr::lng_saved_messages(tr::now)
: peer->isRepliesChat()
? tr::lng_replies_messages(tr::now)
@ -852,7 +902,7 @@ auto ShareBox::Inner::getChat(not_null<Dialogs::Row*> row)
const auto [i, ok] = _dataMap.emplace(
peer,
std::make_unique<Chat>(peer, _st.item, [=] { repaintChat(peer); }));
updateChatName(i->second.get(), peer);
updateChatName(i->second.get());
row->attached = i->second.get();
return i->second.get();
}
@ -896,11 +946,17 @@ void ShareBox::Inner::paintChat(
}
ShareBox::Inner::Chat::Chat(
PeerData *peer,
not_null<PeerData*> peer,
const style::PeerListItem &st,
Fn<void()> updateCallback)
: peer(peer)
, checkbox(st.checkbox, updateCallback, PaintUserpicCallback(peer, true))
, checkbox(
st.checkbox,
updateCallback,
PaintUserpicCallback(peer, true),
[=] { return peer->isForum()
? ImageRoundRadius::Large
: ImageRoundRadius::Ellipse; })
, name(st.checkbox.imageRadius * 2) {
}
@ -1022,9 +1078,9 @@ void ShareBox::Inner::resizeEvent(QResizeEvent *e) {
}
void ShareBox::Inner::changeCheckState(Chat *chat) {
if (!chat) return;
if (!_filter.isEmpty()) {
if (!chat) {
return;
} else if (!_filter.isEmpty()) {
const auto history = chat->peer->owner().history(chat->peer);
auto row = _chatsIndexed->getRow(history);
if (!row) {
@ -1036,7 +1092,60 @@ void ShareBox::Inner::changeCheckState(Chat *chat) {
}
}
changePeerCheckState(chat, !chat->checkbox.checked());
const auto checked = chat->checkbox.checked();
const auto forum = chat->peer->forum();
if (checked || !forum) {
changePeerCheckState(chat, !checked);
} else {
chooseForumTopic(chat->peer->forum());
}
}
void ShareBox::Inner::chooseForumTopic(not_null<Data::Forum*> forum) {
const auto guard = Ui::MakeWeak(this);
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
auto chosen = [=](not_null<Data::ForumTopic*> topic) {
if (const auto strong = *weak) {
strong->closeBox();
}
if (!guard) {
return;
}
const auto row = _chatsIndexed->getRow(topic->owningHistory());
if (!row) {
return;
}
const auto chat = getChat(row);
Assert(!chat->topic);
chat->topic = topic;
chat->topic->destroyed(
) | rpl::start_with_next([=] {
changePeerCheckState(chat, false);
}, chat->topicLifetime);
updateChatName(chat);
changePeerCheckState(chat, true);
};
auto initBox = [](not_null<PeerListBox*> box) {
box->addButton(tr::lng_cancel(), [box] {
box->closeBox();
});
};
auto box = Box<PeerListBox>(
std::make_unique<ChooseTopicBoxController>(
forum,
std::move(chosen)),
[=](not_null<PeerListBox*> box) {
box->addButton(tr::lng_cancel(), [=] {
box->closeBox();
});
forum->destroyed(
) | rpl::start_with_next([=] {
box->closeBox();
}, box->lifetime());
});
*weak = box.data();
_show->showBox(std::move(box));
}
void ShareBox::Inner::peerUnselected(not_null<PeerData*> peer) {
@ -1049,7 +1158,7 @@ void ShareBox::Inner::peerUnselected(not_null<PeerData*> peer) {
}
void ShareBox::Inner::setPeerSelectedChangedCallback(
Fn<void(PeerData *peer, bool selected)> callback) {
Fn<void(not_null<Data::Thread*> thread, bool selected)> callback) {
_peerSelectedChangedCallback = std::move(callback);
}
@ -1058,15 +1167,21 @@ void ShareBox::Inner::changePeerCheckState(
bool checked,
ChangeStateWay useCallback) {
chat->checkbox.setChecked(checked);
const auto thread = chatThread(chat);
if (checked) {
_selected.insert(chat->peer);
_selected.emplace(thread);
setActive(chatIndex(chat->peer));
} else {
_selected.remove(chat->peer);
_selected.remove(thread);
if (chat->topic) {
chat->topicLifetime.destroy();
chat->topic = nullptr;
updateChatName(chat);
}
}
if (useCallback != ChangeStateWay::SkipCallback
&& _peerSelectedChangedCallback) {
_peerSelectedChangedCallback(chat->peer, checked);
_peerSelectedChangedCallback(thread, checked);
}
}
@ -1122,9 +1237,11 @@ void ShareBox::Inner::peopleReceived(
const auto feedList = [&](const QVector<MTPPeer> &list) {
for (const auto &data : list) {
if (const auto peer = _descriptor.session->data().peerLoaded(
peerFromMTP(data))) {
const auto history = _descriptor.session->data().historyLoaded(peer);
if (!_descriptor.filterCallback(peer)) {
peerFromMTP(data))) {
const auto history = _descriptor.session->data().history(
peer);
if (!history->asForum()
&& !_descriptor.filterCallback(history)) {
continue;
} else if (history && _chatsIndexed->getRow(history)) {
continue;
@ -1136,7 +1253,7 @@ void ShareBox::Inner::peopleReceived(
peer,
_st.item,
[=] { repaintChat(peer); }));
updateChatName(d_byUsernameFiltered.back().get(), peer);
updateChatName(d_byUsernameFiltered.back().get());
}
}
};
@ -1158,12 +1275,19 @@ void ShareBox::Inner::refresh() {
update();
}
std::vector<not_null<PeerData*>> ShareBox::Inner::selected() const {
auto result = std::vector<not_null<PeerData*>>();
not_null<Data::Thread*> ShareBox::Inner::chatThread(
not_null<Chat*> chat) const {
return chat->topic
? (Data::Thread*)chat->topic
: chat->peer->owner().history(chat->peer).get();
}
std::vector<not_null<Data::Thread*>> ShareBox::Inner::selected() const {
auto result = std::vector<not_null<Data::Thread*>>();
result.reserve(_dataMap.size());
for (const auto &[peer, chat] : _dataMap) {
if (chat->checkbox.checked()) {
result.push_back(peer);
result.push_back(chatThread(chat.get()));
}
}
return result;
@ -1279,7 +1403,7 @@ void FastShareMessage(
};
auto submitCallback = [=](
std::vector<not_null<PeerData*>> &&result,
std::vector<not_null<Data::Thread*>> &&result,
TextWithTags &&comment,
Api::SendOptions options,
Data::ForwardOptions forwardOptions) {
@ -1292,12 +1416,12 @@ void FastShareMessage(
}
const auto error = [&] {
for (const auto peer : result) { // #TODO forum share
for (const auto thread : result) {
const auto error = GetErrorTextForSending(
peer,
thread,
{ .forward = &items, .text = &comment });
if (!error.isEmpty()) {
return std::make_pair(error, peer);
return std::make_pair(error, thread);
}
}
return std::make_pair(QString(), result.front());
@ -1306,7 +1430,7 @@ void FastShareMessage(
auto text = TextWithEntities();
if (result.size() > 1) {
text.append(
Ui::Text::Bold(error.second->name())
Ui::Text::Bold(error.second->chatListName())
).append("\n\n");
}
text.append(error.first);
@ -1316,17 +1440,16 @@ void FastShareMessage(
return;
}
const auto commonSendFlags = MTPmessages_ForwardMessages::Flag(0)
| MTPmessages_ForwardMessages::Flag::f_with_my_score
| (options.scheduled
? MTPmessages_ForwardMessages::Flag::f_schedule_date
: MTPmessages_ForwardMessages::Flag(0))
using Flag = MTPmessages_ForwardMessages::Flag;
const auto commonSendFlags = Flag(0)
| Flag::f_with_my_score
| (options.scheduled ? Flag::f_schedule_date : Flag(0))
| ((forwardOptions != Data::ForwardOptions::PreserveInfo)
? MTPmessages_ForwardMessages::Flag::f_drop_author
: MTPmessages_ForwardMessages::Flag(0))
? Flag::f_drop_author
: Flag(0))
| ((forwardOptions == Data::ForwardOptions::NoNamesAndCaptions)
? MTPmessages_ForwardMessages::Flag::f_drop_media_captions
: MTPmessages_ForwardMessages::Flag(0));
? Flag::f_drop_media_captions
: Flag(0));
auto msgIds = QVector<MTPint>();
msgIds.reserve(data->msgIds.size());
for (const auto &fullId : data->msgIds) {
@ -1342,21 +1465,23 @@ void FastShareMessage(
auto &api = owner->session().api();
auto &histories = owner->histories();
const auto requestType = Data::Histories::RequestType::Send;
for (const auto peer : result) {
const auto history = owner->history(peer);
for (const auto thread : result) {
if (!comment.text.isEmpty()) {
auto message = Api::MessageToSend(
Api::SendAction(history, options));
Api::SendAction(thread, options));
message.textWithTags = comment;
message.action.clearDraft = false;
api.sendMessage(std::move(message));
}
const auto topicRootId = thread->topicRootId();
const auto peer = thread->peer();
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
auto &api = history->session().api();
const auto sendFlags = commonSendFlags
| (topicRootId ? Flag::f_top_msg_id : Flag(0))
| (ShouldSendSilent(peer, options)
? MTPmessages_ForwardMessages::Flag::f_silent
: MTPmessages_ForwardMessages::Flag(0));
? Flag::f_silent
: Flag(0));
history->sendRequestId = api.request(
MTPmessages_ForwardMessages(
MTP_flags(sendFlags),
@ -1364,7 +1489,7 @@ void FastShareMessage(
MTP_vector<MTPint>(msgIds),
MTP_vector<MTPlong>(generateRandom()),
peer->input,
MTPint(), // top_msg_id
MTP_int(topicRootId),
MTP_int(options.scheduled),
MTP_inputPeerEmpty() // send_as
)).done([=](const MTPUpdates &updates, mtpRequestId reqId) {
@ -1397,14 +1522,9 @@ void FastShareMessage(
data->requests.insert(history->sendRequestId);
}
};
auto filterCallback = [isGame](PeerData *peer) {
if (peer->canWrite()) { // #TODO forum share
if (auto channel = peer->asChannel()) {
return isGame ? (!channel->isBroadcast()) : true;
}
return true;
}
return false;
auto filterCallback = [isGame](not_null<Data::Thread*> thread) {
return thread->canWrite()
&& (!isGame || !thread->peer()->isBroadcast());
};
auto copyLinkCallback = canCopyLink
? Fn<void()>(std::move(copyCallback))

View file

@ -44,6 +44,7 @@ class IndexedList;
namespace Data {
enum class ForwardOptions;
class Thread;
} // namespace Data
namespace Ui {
@ -70,11 +71,11 @@ class ShareBox final : public Ui::BoxContent {
public:
using CopyCallback = Fn<void()>;
using SubmitCallback = Fn<void(
std::vector<not_null<PeerData*>>&&,
std::vector<not_null<Data::Thread*>>&&,
TextWithTags&&,
Api::SendOptions,
Data::ForwardOptions option)>;
using FilterCallback = Fn<bool(PeerData*)>;
using FilterCallback = Fn<bool(not_null<Data::Thread*>)>;
struct Descriptor {
not_null<Main::Session*> session;
@ -125,8 +126,8 @@ private:
int contentHeight() const;
void updateScrollSkips();
void addPeerToMultiSelect(PeerData *peer, bool skipAnimation = false);
void innerSelectedChanged(PeerData *peer, bool checked);
void addPeerToMultiSelect(not_null<Data::Thread*> thread);
void innerSelectedChanged(not_null<Data::Thread*> thread, bool checked);
void peopleDone(
const MTPcontacts_Found &result,

View file

@ -133,7 +133,7 @@ object_ptr<ShareBox> ShareInviteLinkBox(
showToast(tr::lng_group_invite_copied(tr::now));
};
auto submitCallback = [=](
std::vector<not_null<PeerData*>> &&result,
std::vector<not_null<Data::Thread*>> &&result,
TextWithTags &&comment,
Api::SendOptions options,
Data::ForwardOptions) {
@ -142,12 +142,12 @@ object_ptr<ShareBox> ShareInviteLinkBox(
}
const auto error = [&] {
for (const auto peer : result) { // #TODO forum share
for (const auto thread : result) {
const auto error = GetErrorTextForSending(
peer,
thread,
{ .text = &comment });
if (!error.isEmpty()) {
return std::make_pair(error, peer);
return std::make_pair(error, thread);
}
}
return std::make_pair(QString(), result.front());
@ -156,7 +156,7 @@ object_ptr<ShareBox> ShareInviteLinkBox(
auto text = TextWithEntities();
if (result.size() > 1) {
text.append(
Ui::Text::Bold(error.second->name())
Ui::Text::Bold(error.second->chatListName())
).append("\n\n");
}
text.append(error.first);
@ -182,10 +182,9 @@ object_ptr<ShareBox> ShareInviteLinkBox(
}
const auto owner = &peer->owner();
auto &api = peer->session().api();
for (const auto peer : result) {
const auto history = owner->history(peer);
for (const auto thread : result) {
auto message = Api::MessageToSend(
Api::SendAction(history, options));
Api::SendAction(thread, options));
message.textWithTags = comment;
message.action.clearDraft = false;
api.sendMessage(std::move(message));
@ -195,8 +194,8 @@ object_ptr<ShareBox> ShareInviteLinkBox(
}
showToast(tr::lng_share_done(tr::now));
};
auto filterCallback = [](PeerData *peer) {
return peer->canWrite(); // #TODO forum share
auto filterCallback = [](not_null<Data::Thread*> thread) {
return thread->canWrite(); // #TODO forum share
};
const auto scheduleStyle = [&] {

View file

@ -178,6 +178,13 @@ QString GetErrorTextForSending(
return QString();
}
QString GetErrorTextForSending(
not_null<Data::Thread*> thread,
SendingErrorRequest request) {
request.topicRootId = thread->topicRootId();
return GetErrorTextForSending(thread->peer(), std::move(request));
}
void RequestDependentMessageData(
not_null<HistoryItem*> item,
PeerId peerId,

View file

@ -15,6 +15,7 @@ struct SendOptions;
} // namespace Api
namespace Data {
class Thread;
struct SponsoredFrom;
} // namespace Data
@ -50,6 +51,9 @@ struct SendingErrorRequest {
[[nodiscard]] QString GetErrorTextForSending(
not_null<PeerData*> peer,
SendingErrorRequest request);
[[nodiscard]] QString GetErrorTextForSending(
not_null<Data::Thread*> thread,
SendingErrorRequest request);
[[nodiscard]] TextWithEntities DropCustomEmoji(TextWithEntities text);

View file

@ -171,7 +171,7 @@ void ForwardPanel::updateTexts() {
}).text;
const auto history = item->history();
const auto dropCustomEmoji = !history->session().premium()
&& !_to->owningHistory()->peer->isSelf()
&& !_to->peer()->isSelf()
&& (item->computeDropForwardedInfo() || !keepNames);
if (dropCustomEmoji) {
text = DropCustomEmoji(std::move(text));

View file

@ -64,7 +64,7 @@ PinnedMemento::PinnedMemento(
: _thread(thread)
, _highlightId(highlightId) {
_list.setAroundPosition({
.fullId = FullMsgId(_thread->owningHistory()->peer->id, highlightId),
.fullId = FullMsgId(_thread->peer()->id, highlightId),
.date = TimeId(0),
});
}
@ -89,7 +89,7 @@ PinnedWidget::PinnedWidget(
QWidget *parent,
not_null<Window::SessionController*> controller,
not_null<Data::Thread*> thread)
: Window::SectionWidget(parent, controller, thread->owningHistory()->peer)
: Window::SectionWidget(parent, controller, thread->peer())
, _thread(thread->migrateToOrMe())
, _history(thread->owningHistory())
, _migratedPeer(thread->asHistory()
@ -116,7 +116,7 @@ PinnedWidget::PinnedWidget(
Window::ChatThemeValueFromPeer(
controller,
thread->owningHistory()->peer
thread->peer()
) | rpl::start_with_next([=](std::shared_ptr<Ui::ChatTheme> &&theme) {
_theme = std::move(theme);
controller->setChatStyleTheme(_theme);

View file

@ -79,7 +79,7 @@ void PinnedTracker::refreshViewer() {
}
_dataLifetime.destroy();
_viewerAroundId = _aroundId;
const auto peer = _thread->owningHistory()->peer;
const auto peer = _thread->peer();
SharedMediaMergedViewer(
&peer->session(),
SharedMediaMergedKey(

View file

@ -141,7 +141,7 @@ void ShowChooseBox(
callback(thread);
};
auto filter = [=](not_null<Data::Thread*> thread) -> bool {
const auto peer = thread->owningHistory()->peer;
const auto peer = thread->peer();
if (!thread->canWrite()) {
return false;
} else if (const auto user = peer->asUser()) {

View file

@ -607,7 +607,7 @@ bool MainWidget::sendPaths(not_null<Data::Thread*> thread) {
Ui::show(Ui::MakeInformBox(tr::lng_forward_send_files_cant()));
return false;
} else if (const auto error = Data::RestrictionError(
thread->owningHistory()->peer,
thread->peer(),
ChatRestriction::SendMedia)) {
Ui::show(Ui::MakeInformBox(*error));
return false;

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h"
#include "ui/ui_utility.h"
#include "ui/painter.h"
#include "ui/image/image_prepare.h"
#include <QtCore/QCoreApplication>
@ -355,10 +356,15 @@ void RoundCheckbox::prepareInactiveCache() {
_inactiveCacheFg = Ui::PixmapFromImage(std::move(cacheFg));
}
RoundImageCheckbox::RoundImageCheckbox(const style::RoundImageCheckbox &st, Fn<void()> updateCallback, PaintRoundImage &&paintRoundImage)
RoundImageCheckbox::RoundImageCheckbox(
const style::RoundImageCheckbox &st,
Fn<void()> updateCallback,
PaintRoundImage &&paintRoundImage,
Fn<ImageRoundRadius()> roundingRadius)
: _st(st)
, _updateCallback(updateCallback)
, _paintRoundImage(std::move(paintRoundImage))
, _roundingRadius(std::move(roundingRadius))
, _check(_st.check, _updateCallback) {
}
@ -383,6 +389,9 @@ void RoundImageCheckbox::paint(Painter &p, int x, int y, int outerWidth) const {
}
if (selectionLevel > 0) {
const auto radius = _roundingRadius
? _roundingRadius()
: ImageRoundRadius::Ellipse;
PainterHighQualityEnabler hq(p);
p.setOpacity(std::clamp(selectionLevel, 0., 1.));
p.setBrush(Qt::NoBrush);
@ -390,7 +399,18 @@ void RoundImageCheckbox::paint(Painter &p, int x, int y, int outerWidth) const {
_fgOverride ? (*_fgOverride) : _st.selectFg->b,
_st.selectWidth);
p.setPen(pen);
p.drawEllipse(style::rtlrect(x, y, _st.imageRadius * 2, _st.imageRadius * 2, outerWidth));
const auto rect = style::rtlrect(
x,
y,
_st.imageRadius * 2,
_st.imageRadius * 2,
outerWidth);
if (radius == ImageRoundRadius::Ellipse) {
p.drawEllipse(rect);
} else {
const auto pxRadius = st::roundRadiusLarge;
p.drawRoundedRect(rect, pxRadius, pxRadius);
}
p.setOpacity(1.);
}
if (_st.check.size > 0) {

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_widgets.h"
class Painter;
enum class ImageRoundRadius;
namespace Ui {
@ -47,7 +48,11 @@ private:
class RoundImageCheckbox {
public:
using PaintRoundImage = Fn<void(Painter &p, int x, int y, int outerWidth, int size)>;
RoundImageCheckbox(const style::RoundImageCheckbox &st, Fn<void()> updateCallback, PaintRoundImage &&paintRoundImage);
RoundImageCheckbox(
const style::RoundImageCheckbox &st,
Fn<void()> updateCallback,
PaintRoundImage &&paintRoundImage,
Fn<ImageRoundRadius()> roundingRadius = nullptr);
void paint(Painter &p, int x, int y, int outerWidth) const;
float64 checkedAnimationRatio() const;
@ -71,6 +76,7 @@ private:
const style::RoundImageCheckbox &_st;
Fn<void()> _updateCallback;
PaintRoundImage _paintRoundImage;
Fn<ImageRoundRadius()> _roundingRadius;
QPixmap _wideCache;
Ui::Animations::Simple _selection;

View file

@ -1290,7 +1290,7 @@ void PeerMenuShareContactBox(
// There is no async to make weak from controller.
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
auto callback = [=](not_null<Data::Thread*> thread) {
const auto peer = thread->owningHistory()->peer;
const auto peer = thread->peer();
if (!thread->canWrite()) {
navigation->parentController()->show(
Ui::MakeInformBox(tr::lng_forward_share_cant()),
@ -1544,7 +1544,7 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
weak,
navigation
](not_null<Data::Thread*> thread) mutable {
const auto peer = thread->owningHistory()->peer;
const auto peer = thread->peer();
const auto content = navigation->parentController()->content();
if (peer->isSelf()
&& !draft.ids.empty()
@ -1604,7 +1604,7 @@ QPointer<Ui::BoxContent> ShowShareGameBox(
ShowAtUnreadMsgId,
SectionShow::Way::ClearStack);
});
const auto confirmText = thread->owningHistory()->peer->isUser()
const auto confirmText = thread->peer()->isUser()
? tr::lng_bot_sure_share_game(
tr::now,
lt_user,
@ -1621,7 +1621,7 @@ QPointer<Ui::BoxContent> ShowShareGameBox(
Ui::LayerOption::KeepOther);
};
auto filter = [](not_null<Data::Thread*> thread) {
const auto peer = thread->owningHistory()->peer;
const auto peer = thread->peer();
return (thread->canWrite() || thread->asForum())
&& !peer->amRestricted(ChatRestriction::SendGames)
&& !peer->isSelf();