mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 21:27:07 +02:00
Support topic choosing in ShareBox.
This commit is contained in:
parent
7384cd3463
commit
e6c2aa8021
14 changed files with 273 additions and 117 deletions
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 = [&] {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue