mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-24 14:33:02 +02:00
Support mark as read/unread in sublists.
This commit is contained in:
parent
abe1962002
commit
3278de9ba1
35 changed files with 497 additions and 91 deletions
|
@ -1373,6 +1373,32 @@ void ApiWrap::deleteAllFromParticipantSend(
|
|||
}).send();
|
||||
}
|
||||
|
||||
void ApiWrap::deleteSublistHistory(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> sublistPeer) {
|
||||
deleteSublistHistorySend(channel, sublistPeer);
|
||||
}
|
||||
|
||||
void ApiWrap::deleteSublistHistorySend(
|
||||
not_null<ChannelData*> parentChat,
|
||||
not_null<PeerData*> sublistPeer) {
|
||||
request(MTPmessages_DeleteSavedHistory(
|
||||
MTP_flags(MTPmessages_DeleteSavedHistory::Flag::f_parent_peer),
|
||||
parentChat->input,
|
||||
sublistPeer->input,
|
||||
MTP_int(0), // max_id
|
||||
MTP_int(0), // min_date
|
||||
MTP_int(0) // max_date
|
||||
)).done([=](const MTPmessages_AffectedHistory &result) {
|
||||
const auto offset = applyAffectedHistory(parentChat, result);
|
||||
if (offset > 0) {
|
||||
deleteSublistHistorySend(parentChat, sublistPeer);
|
||||
} else if (const auto monoforum = parentChat->monoforum()) {
|
||||
monoforum->applySublistDeleted(sublistPeer);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ApiWrap::scheduleStickerSetRequest(uint64 setId, uint64 access) {
|
||||
if (!_stickerSetRequests.contains(setId)) {
|
||||
_stickerSetRequests.emplace(setId, StickerSetRequest{ access });
|
||||
|
|
|
@ -231,6 +231,9 @@ public:
|
|||
void deleteAllFromParticipant(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> from);
|
||||
void deleteSublistHistory(
|
||||
not_null<ChannelData*> parentChat,
|
||||
not_null<PeerData*> sublistPeer);
|
||||
|
||||
void requestWebPageDelayed(not_null<WebPageData*> page);
|
||||
void clearWebPageRequest(not_null<WebPageData*> page);
|
||||
|
@ -539,6 +542,9 @@ private:
|
|||
void deleteAllFromParticipantSend(
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> from);
|
||||
void deleteSublistHistorySend(
|
||||
not_null<ChannelData*> parentChat,
|
||||
not_null<PeerData*> sublistPeer);
|
||||
|
||||
void uploadAlbumMedia(
|
||||
not_null<HistoryItem*> item,
|
||||
|
|
|
@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_chat_participant_status.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_saved_sublist.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
|
@ -565,15 +566,7 @@ bool CanCreateModerateMessagesBox(const HistoryItemsList &items) {
|
|||
&& !options.participants.empty();
|
||||
}
|
||||
|
||||
void DeleteChatBox(not_null<Ui::GenericBox*> box, not_null<PeerData*> peer) {
|
||||
const auto container = box->verticalLayout();
|
||||
|
||||
const auto maybeUser = peer->asUser();
|
||||
const auto isBot = maybeUser && maybeUser->isBot();
|
||||
|
||||
Ui::AddSkip(container);
|
||||
Ui::AddSkip(container);
|
||||
|
||||
void SafeSubmitOnEnter(not_null<Ui::GenericBox*> box) {
|
||||
base::install_event_filter(box, [=](not_null<QEvent*> event) {
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
if (const auto k = static_cast<QKeyEvent*>(event.get())) {
|
||||
|
@ -587,12 +580,24 @@ void DeleteChatBox(not_null<Ui::GenericBox*> box, not_null<PeerData*> peer) {
|
|||
},
|
||||
.confirmText = tr::lng_box_yes(),
|
||||
.cancelText = tr::lng_box_no(),
|
||||
}));
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
return base::EventFilterResult::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
void DeleteChatBox(not_null<Ui::GenericBox*> box, not_null<PeerData*> peer) {
|
||||
const auto container = box->verticalLayout();
|
||||
|
||||
const auto maybeUser = peer->asUser();
|
||||
const auto isBot = maybeUser && maybeUser->isBot();
|
||||
|
||||
Ui::AddSkip(container);
|
||||
Ui::AddSkip(container);
|
||||
|
||||
SafeSubmitOnEnter(box);
|
||||
|
||||
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
|
||||
container,
|
||||
|
@ -754,3 +759,54 @@ void DeleteChatBox(not_null<Ui::GenericBox*> box, not_null<PeerData*> peer) {
|
|||
}, st::attentionBoxButton);
|
||||
box->addButton(tr::lng_cancel(), close);
|
||||
}
|
||||
|
||||
void DeleteSublistBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Data::SavedSublist*> sublist) {
|
||||
const auto container = box->verticalLayout();
|
||||
|
||||
const auto weak = base::make_weak(sublist.get());
|
||||
const auto peer = sublist->sublistPeer();
|
||||
|
||||
Ui::AddSkip(container);
|
||||
Ui::AddSkip(container);
|
||||
|
||||
SafeSubmitOnEnter(box);
|
||||
|
||||
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
|
||||
container,
|
||||
peer,
|
||||
st::mainMenuUserpic);
|
||||
Ui::IconWithTitle(
|
||||
container,
|
||||
userpic,
|
||||
Ui::CreateChild<Ui::FlatLabel>(
|
||||
container,
|
||||
tr::lng_profile_delete_conversation() | Ui::Text::ToBold(),
|
||||
box->getDelegate()->style().title));
|
||||
|
||||
Ui::AddSkip(container);
|
||||
Ui::AddSkip(container);
|
||||
|
||||
box->addRow(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
container,
|
||||
tr::lng_sure_delete_history(
|
||||
lt_contact,
|
||||
rpl::single(peer->name())),
|
||||
st::boxLabel));
|
||||
|
||||
Ui::AddSkip(container);
|
||||
|
||||
const auto close = crl::guard(box, [=] { box->closeBox(); });
|
||||
box->addButton(tr::lng_box_delete(), [=] {
|
||||
const auto strong = weak.get();
|
||||
const auto parentChat = strong ? strong->parentChat() : nullptr;
|
||||
if (!parentChat) {
|
||||
return;
|
||||
}
|
||||
peer->session().api().deleteSublistHistory(parentChat, peer);
|
||||
close();
|
||||
}, st::attentionBoxButton);
|
||||
box->addButton(tr::lng_cancel(), close);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
class PeerData;
|
||||
|
||||
namespace Data {
|
||||
class SavedSublist;
|
||||
} // namespace Data
|
||||
|
||||
namespace Ui {
|
||||
class GenericBox;
|
||||
} // namespace Ui
|
||||
|
@ -21,3 +25,6 @@ void CreateModerateMessagesBox(
|
|||
[[nodiscard]] bool CanCreateModerateMessagesBox(const HistoryItemsList &);
|
||||
|
||||
void DeleteChatBox(not_null<Ui::GenericBox*> box, not_null<PeerData*> peer);
|
||||
void DeleteSublistBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Data::SavedSublist*> sublist);
|
||||
|
|
|
@ -714,7 +714,7 @@ void PeerListRow::elementsPaint(
|
|||
}
|
||||
|
||||
QString PeerListRow::generateName() {
|
||||
return peer()->name();
|
||||
return peer()->userpicPaintingPeer()->name();
|
||||
}
|
||||
|
||||
QString PeerListRow::generateShortName() {
|
||||
|
@ -724,12 +724,12 @@ QString PeerListRow::generateShortName() {
|
|||
? tr::lng_replies_messages(tr::now)
|
||||
: _isVerifyCodesChat
|
||||
? tr::lng_verification_codes(tr::now)
|
||||
: peer()->shortName();
|
||||
: peer()->userpicPaintingPeer()->shortName();
|
||||
}
|
||||
|
||||
Ui::PeerUserpicView &PeerListRow::ensureUserpicView() {
|
||||
if (!_userpic.cloud && peer()->hasUserpic()) {
|
||||
_userpic = peer()->createUserpicView();
|
||||
if (!_userpic.cloud && peer()->userpicPaintingPeer()->hasUserpic()) {
|
||||
_userpic = peer()->userpicPaintingPeer()->createUserpicView();
|
||||
}
|
||||
return _userpic;
|
||||
}
|
||||
|
@ -738,7 +738,7 @@ PaintRoundImageCallback PeerListRow::generatePaintUserpicCallback(
|
|||
bool forceRound) {
|
||||
const auto saved = !_savedMessagesStatus.isEmpty();
|
||||
const auto replies = _isRepliesMessagesChat;
|
||||
const auto peer = this->peer();
|
||||
const auto peer = this->peer()->userpicPaintingPeer();
|
||||
auto userpic = saved ? Ui::PeerUserpicView() : ensureUserpicView();
|
||||
if (forceRound && peer->isForum()) {
|
||||
return ForceRoundUserpicCallback(peer);
|
||||
|
|
|
@ -204,6 +204,42 @@ void Changes::topicRemoved(not_null<ForumTopic*> topic) {
|
|||
_topicChanges.drop(topic);
|
||||
}
|
||||
|
||||
void Changes::sublistUpdated(
|
||||
not_null<SavedSublist*> sublist,
|
||||
SublistUpdate::Flags flags) {
|
||||
const auto drop = (flags & SublistUpdate::Flag::Destroyed);
|
||||
_sublistChanges.updated(sublist, flags, drop);
|
||||
if (!drop) {
|
||||
scheduleNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
rpl::producer<SublistUpdate> Changes::sublistUpdates(
|
||||
SublistUpdate::Flags flags) const {
|
||||
return _sublistChanges.updates(flags);
|
||||
}
|
||||
|
||||
rpl::producer<SublistUpdate> Changes::sublistUpdates(
|
||||
not_null<SavedSublist*> sublist,
|
||||
SublistUpdate::Flags flags) const {
|
||||
return _sublistChanges.updates(sublist, flags);
|
||||
}
|
||||
|
||||
rpl::producer<SublistUpdate> Changes::sublistFlagsValue(
|
||||
not_null<SavedSublist*> sublist,
|
||||
SublistUpdate::Flags flags) const {
|
||||
return _sublistChanges.flagsValue(sublist, flags);
|
||||
}
|
||||
|
||||
rpl::producer<SublistUpdate> Changes::realtimeSublistUpdates(
|
||||
SublistUpdate::Flag flag) const {
|
||||
return _sublistChanges.realtimeUpdates(flag);
|
||||
}
|
||||
|
||||
void Changes::sublistRemoved(not_null<SavedSublist*> sublist) {
|
||||
_sublistChanges.drop(sublist);
|
||||
}
|
||||
|
||||
void Changes::messageUpdated(
|
||||
not_null<HistoryItem*> item,
|
||||
MessageUpdate::Flags flags) {
|
||||
|
@ -323,6 +359,7 @@ void Changes::sendNotifications() {
|
|||
_messageChanges.sendNotifications();
|
||||
_entryChanges.sendNotifications();
|
||||
_topicChanges.sendNotifications();
|
||||
_sublistChanges.sendNotifications();
|
||||
_storyChanges.sendNotifications();
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ inline constexpr int CountBit(Flag Last = Flag::LastUsedBit) {
|
|||
namespace Data {
|
||||
|
||||
class ForumTopic;
|
||||
class SavedSublist;
|
||||
class Story;
|
||||
|
||||
struct NameUpdate {
|
||||
|
@ -184,6 +185,25 @@ struct TopicUpdate {
|
|||
|
||||
};
|
||||
|
||||
struct SublistUpdate {
|
||||
enum class Flag : uint32 {
|
||||
None = 0,
|
||||
|
||||
UnreadView = (1U << 1),
|
||||
UnreadReactions = (1U << 2),
|
||||
CloudDraft = (1U << 3),
|
||||
Destroyed = (1U << 4),
|
||||
|
||||
LastUsedBit = (1U << 4),
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
||||
|
||||
not_null<SavedSublist*> sublist;
|
||||
Flags flags = 0;
|
||||
|
||||
};
|
||||
|
||||
struct MessageUpdate {
|
||||
enum class Flag : uint32 {
|
||||
None = 0,
|
||||
|
@ -305,6 +325,21 @@ public:
|
|||
TopicUpdate::Flag flag) const;
|
||||
void topicRemoved(not_null<ForumTopic*> topic);
|
||||
|
||||
void sublistUpdated(
|
||||
not_null<SavedSublist*> sublist,
|
||||
SublistUpdate::Flags flags);
|
||||
[[nodiscard]] rpl::producer<SublistUpdate> sublistUpdates(
|
||||
SublistUpdate::Flags flags) const;
|
||||
[[nodiscard]] rpl::producer<SublistUpdate> sublistUpdates(
|
||||
not_null<SavedSublist*> sublist,
|
||||
SublistUpdate::Flags flags) const;
|
||||
[[nodiscard]] rpl::producer<SublistUpdate> sublistFlagsValue(
|
||||
not_null<SavedSublist*> sublist,
|
||||
SublistUpdate::Flags flags) const;
|
||||
[[nodiscard]] rpl::producer<SublistUpdate> realtimeSublistUpdates(
|
||||
SublistUpdate::Flag flag) const;
|
||||
void sublistRemoved(not_null<SavedSublist*> sublist);
|
||||
|
||||
void messageUpdated(
|
||||
not_null<HistoryItem*> item,
|
||||
MessageUpdate::Flags flags);
|
||||
|
@ -396,6 +431,7 @@ private:
|
|||
Manager<PeerData, PeerUpdate> _peerChanges;
|
||||
Manager<History, HistoryUpdate> _historyChanges;
|
||||
Manager<ForumTopic, TopicUpdate> _topicChanges;
|
||||
Manager<SavedSublist, SublistUpdate> _sublistChanges;
|
||||
Manager<HistoryItem, MessageUpdate> _messageChanges;
|
||||
Manager<Dialogs::Entry, EntryUpdate> _entryChanges;
|
||||
Manager<Story, StoryUpdate> _storyChanges;
|
||||
|
|
|
@ -175,30 +175,31 @@ void Forum::applyTopicDeleted(MsgId rootId) {
|
|||
_topicsDeleted.emplace(rootId);
|
||||
|
||||
const auto i = _topics.find(rootId);
|
||||
if (i != end(_topics)) {
|
||||
const auto raw = i->second.get();
|
||||
Core::App().notifications().clearFromTopic(raw);
|
||||
owner().removeChatListEntry(raw);
|
||||
|
||||
if (ranges::contains(_lastTopics, not_null(raw))) {
|
||||
reorderLastTopics();
|
||||
}
|
||||
|
||||
_topicDestroyed.fire(raw);
|
||||
session().changes().topicUpdated(
|
||||
raw,
|
||||
Data::TopicUpdate::Flag::Destroyed);
|
||||
session().changes().entryUpdated(
|
||||
raw,
|
||||
Data::EntryUpdate::Flag::Destroyed);
|
||||
_topics.erase(i);
|
||||
|
||||
_history->destroyMessagesByTopic(rootId);
|
||||
session().storage().unload(Storage::SharedMediaUnloadThread(
|
||||
_history->peer->id,
|
||||
rootId));
|
||||
_history->setForwardDraft(rootId, PeerId(), {});
|
||||
if (i == end(_topics)) {
|
||||
return;
|
||||
}
|
||||
const auto raw = i->second.get();
|
||||
Core::App().notifications().clearFromTopic(raw);
|
||||
owner().removeChatListEntry(raw);
|
||||
|
||||
if (ranges::contains(_lastTopics, not_null(raw))) {
|
||||
reorderLastTopics();
|
||||
}
|
||||
|
||||
_topicDestroyed.fire(raw);
|
||||
session().changes().topicUpdated(
|
||||
raw,
|
||||
Data::TopicUpdate::Flag::Destroyed);
|
||||
session().changes().entryUpdated(
|
||||
raw,
|
||||
Data::EntryUpdate::Flag::Destroyed);
|
||||
_topics.erase(i);
|
||||
|
||||
_history->destroyMessagesByTopic(rootId);
|
||||
session().storage().unload(Storage::SharedMediaUnloadThread(
|
||||
_history->peer->id,
|
||||
rootId));
|
||||
_history->setForwardDraft(rootId, PeerId(), {});
|
||||
}
|
||||
|
||||
void Forum::reorderLastTopics() {
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_text_entities.h"
|
||||
#include "data/business/data_shortcut_messages.h"
|
||||
#include "data/components/scheduled_messages.h"
|
||||
#include "data/data_saved_sublist.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
|
@ -500,6 +501,24 @@ void Histories::changeDialogUnreadMark(
|
|||
)).send();
|
||||
}
|
||||
|
||||
void Histories::changeSublistUnreadMark(
|
||||
not_null<Data::SavedSublist*> sublist,
|
||||
bool unread) {
|
||||
const auto parent = sublist->parentChat();
|
||||
if (!parent) {
|
||||
return;
|
||||
}
|
||||
sublist->setUnreadMark(unread);
|
||||
|
||||
using Flag = MTPmessages_MarkDialogUnread::Flag;
|
||||
session().api().request(MTPmessages_MarkDialogUnread(
|
||||
MTP_flags(Flag::f_parent_peer
|
||||
| (unread ? Flag::f_unread : Flag(0))),
|
||||
parent->input,
|
||||
MTP_inputDialogPeer(sublist->sublistPeer()->input)
|
||||
)).send();
|
||||
}
|
||||
|
||||
void Histories::requestFakeChatListMessage(
|
||||
not_null<History*> history) {
|
||||
if (_fakeChatListRequests.contains(history)) {
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace Data {
|
|||
class Session;
|
||||
class Folder;
|
||||
struct WebPageDraft;
|
||||
class SavedSublist;
|
||||
|
||||
[[nodiscard]] MTPInputReplyTo ReplyToForMTP(
|
||||
not_null<History*> history,
|
||||
|
@ -71,6 +72,9 @@ public:
|
|||
Fn<void()> callback = nullptr);
|
||||
void dialogEntryApplied(not_null<History*> history);
|
||||
void changeDialogUnreadMark(not_null<History*> history, bool unread);
|
||||
void changeSublistUnreadMark(
|
||||
not_null<Data::SavedSublist*> sublist,
|
||||
bool unread);
|
||||
void requestFakeChatListMessage(not_null<History*> history);
|
||||
|
||||
void requestGroupAround(not_null<HistoryItem*> item);
|
||||
|
|
|
@ -1174,6 +1174,10 @@ not_null<const PeerData*> PeerData::userpicPaintingPeer() const {
|
|||
return const_cast<PeerData*>(this)->userpicPaintingPeer();
|
||||
}
|
||||
|
||||
bool PeerData::userpicForceForumShape() const {
|
||||
return monoforumBroadcast() != nullptr;
|
||||
}
|
||||
|
||||
ChannelData *PeerData::monoforumBroadcast() const {
|
||||
const auto monoforum = asMonoforum();
|
||||
return monoforum ? monoforum->monoforumLink() : nullptr;
|
||||
|
|
|
@ -307,6 +307,7 @@ public:
|
|||
[[nodiscard]] not_null<const PeerData*> migrateToOrMe() const;
|
||||
[[nodiscard]] not_null<PeerData*> userpicPaintingPeer();
|
||||
[[nodiscard]] not_null<const PeerData*> userpicPaintingPeer() const;
|
||||
[[nodiscard]] bool userpicForceForumShape() const;
|
||||
|
||||
// isMonoforum() ? monoforumLink() : nullptr
|
||||
[[nodiscard]] ChannelData *monoforumBroadcast() const;
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_saved_messages.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "core/application.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_user.h"
|
||||
|
@ -17,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history_item.h"
|
||||
#include "history/history_unread_things.h"
|
||||
#include "main/main_session.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
||||
namespace Data {
|
||||
namespace {
|
||||
|
@ -50,11 +52,13 @@ SavedMessages::SavedMessages(
|
|||
|
||||
SavedMessages::~SavedMessages() {
|
||||
auto &changes = session().changes();
|
||||
for (const auto &[peer, sublist] : _sublists) {
|
||||
_owningHistory->setForwardDraft(MsgId(), peer->id, {});
|
||||
if (_owningHistory) {
|
||||
for (const auto &[peer, sublist] : _sublists) {
|
||||
_owningHistory->setForwardDraft(MsgId(), peer->id, {});
|
||||
|
||||
const auto raw = sublist.get();
|
||||
changes.entryRemoved(raw);
|
||||
const auto raw = sublist.get();
|
||||
changes.entryRemoved(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,6 +312,36 @@ void SavedMessages::apply(const MTPDupdateSavedDialogPinned &update) {
|
|||
});
|
||||
}
|
||||
|
||||
void SavedMessages::applySublistDeleted(not_null<PeerData*> sublistPeer) {
|
||||
const auto i = _sublists.find(sublistPeer);
|
||||
if (i == end(_sublists)) {
|
||||
return;
|
||||
}
|
||||
const auto raw = i->second.get();
|
||||
//Core::App().notifications().clearFromTopic(raw); // #TODO monoforum
|
||||
owner().removeChatListEntry(raw);
|
||||
|
||||
if (ranges::contains(_lastSublists, not_null(raw))) {
|
||||
reorderLastSublists();
|
||||
}
|
||||
|
||||
_sublistDestroyed.fire(raw);
|
||||
session().changes().sublistUpdated(
|
||||
raw,
|
||||
Data::SublistUpdate::Flag::Destroyed);
|
||||
session().changes().entryUpdated(
|
||||
raw,
|
||||
Data::EntryUpdate::Flag::Destroyed);
|
||||
_sublists.erase(i);
|
||||
|
||||
const auto history = owningHistory();
|
||||
history->destroyMessagesBySublist(sublistPeer);
|
||||
//session().storage().unload(Storage::SharedMediaUnloadThread(
|
||||
// _history->peer->id,
|
||||
// rootId));
|
||||
history->setForwardDraft(MsgId(), sublistPeer->id, {});
|
||||
}
|
||||
|
||||
void SavedMessages::reorderLastSublists() {
|
||||
if (!_parentChat) {
|
||||
return;
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
|
||||
void apply(const MTPDupdatePinnedSavedDialogs &update);
|
||||
void apply(const MTPDupdateSavedDialogPinned &update);
|
||||
void applySublistDeleted(not_null<PeerData*> sublistPeer);
|
||||
|
||||
void listMessageChanged(HistoryItem *from, HistoryItem *to);
|
||||
[[nodiscard]] int recentSublistsListVersion() const;
|
||||
|
|
|
@ -480,6 +480,15 @@ void SavedSublist::setUnreadCount(std::optional<int> count) {
|
|||
}
|
||||
}
|
||||
|
||||
void SavedSublist::setUnreadMark(bool unread) {
|
||||
if (unreadMark() == unread) {
|
||||
return;
|
||||
}
|
||||
const auto notifier = unreadStateChangeNotifier(
|
||||
!unreadCountCurrent());
|
||||
Thread::setUnreadMarkFlag(unread);
|
||||
}
|
||||
|
||||
bool SavedSublist::unreadCountKnown() const {
|
||||
return !inMonoforum() || _unreadCount.current().has_value();
|
||||
}
|
||||
|
@ -620,6 +629,9 @@ void SavedSublist::readTill(
|
|||
if (!IsServerMsgId(tillId)) {
|
||||
return;
|
||||
}
|
||||
if (unreadMark()) {
|
||||
owner().histories().changeSublistUnreadMark(this, false);
|
||||
}
|
||||
const auto was = computeInboxReadTillFull();
|
||||
const auto now = tillId;
|
||||
if (now < was) {
|
||||
|
@ -713,6 +725,7 @@ void SavedSublist::applyMonoforumDialog(
|
|||
data.vread_inbox_max_id().v,
|
||||
data.vunread_count().v);
|
||||
setOutboxReadTill(data.vread_outbox_max_id().v);
|
||||
setUnreadMark(data.is_unread_mark());
|
||||
applyMaybeLast(topItem);
|
||||
}
|
||||
|
||||
|
@ -1016,10 +1029,16 @@ Dialogs::UnreadState SavedSublist::unreadStateFor(
|
|||
int count,
|
||||
bool known) const {
|
||||
auto result = Dialogs::UnreadState();
|
||||
const auto mark = !count && unreadMark();
|
||||
const auto muted = this->muted();
|
||||
result.messages = count;
|
||||
result.chats = count ? 1 : 0;
|
||||
result.marks = mark ? 1 : 0;
|
||||
result.reactions = unreadReactions().has() ? 1 : 0;
|
||||
result.messagesMuted = muted ? result.messages : 0;
|
||||
result.chatsMuted = muted ? result.chats : 0;
|
||||
result.marksMuted = muted ? result.marks : 0;
|
||||
result.reactionsMuted = muted ? result.reactions : 0;
|
||||
result.known = known;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -58,13 +58,13 @@ public:
|
|||
[[nodiscard]] rpl::producer<> changes() const;
|
||||
[[nodiscard]] std::optional<int> fullCount() const;
|
||||
[[nodiscard]] rpl::producer<int> fullCountValue() const;
|
||||
[[nodiscard]] rpl::producer<std::optional<int>> maybeFullCount() const;
|
||||
void loadFullCount();
|
||||
|
||||
[[nodiscard]] bool unreadCountKnown() const;
|
||||
[[nodiscard]] int unreadCountCurrent() const;
|
||||
[[nodiscard]] int displayedUnreadCount() const;
|
||||
[[nodiscard]] rpl::producer<std::optional<int>> unreadCountValue() const;
|
||||
void setUnreadMark(bool unread);
|
||||
|
||||
void applyMonoforumDialog(
|
||||
const MTPDmonoForumDialog &dialog,
|
||||
|
|
|
@ -95,6 +95,17 @@ HistoryUnreadThings::ConstProxy Thread::unreadReactions() const {
|
|||
};
|
||||
}
|
||||
|
||||
bool Thread::canToggleUnread(bool nowUnread) const {
|
||||
if ((asTopic() || asForum()) && !nowUnread) {
|
||||
return false;
|
||||
} else if (asSublist() && owningHistory()->peer->isSelf()) {
|
||||
return false;
|
||||
} else if (asHistory() && peer()->amMonoforumAdmin()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const base::flat_set<MsgId> &Thread::unreadMentionsIds() const {
|
||||
if (!_unreadThings) {
|
||||
static const auto Result = base::flat_set<MsgId>();
|
||||
|
|
|
@ -80,6 +80,7 @@ public:
|
|||
[[nodiscard]] HistoryUnreadThings::ConstProxy unreadReactions() const;
|
||||
virtual void hasUnreadMentionChanged(bool has) = 0;
|
||||
virtual void hasUnreadReactionChanged(bool has) = 0;
|
||||
bool canToggleUnread(bool nowUnread) const;
|
||||
|
||||
void removeNotification(not_null<HistoryItem*> item);
|
||||
void clearNotifications();
|
||||
|
|
|
@ -287,6 +287,10 @@ void Entry::notifyUnreadStateChange(const UnreadState &wasState) {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (const auto sublist = asSublist()) {
|
||||
session().changes().sublistUpdated(
|
||||
sublist,
|
||||
Data::SublistUpdate::Flag::UnreadView);
|
||||
}
|
||||
updateChatListEntryPostponed();
|
||||
}
|
||||
|
|
|
@ -398,14 +398,18 @@ void History::applyCloudDraft(MsgId topicRootId, PeerId monoforumPeerId) {
|
|||
createLocalDraftFromCloud(topicRootId, monoforumPeerId);
|
||||
if (const auto thread = threadFor(topicRootId, monoforumPeerId)) {
|
||||
thread->updateChatListSortPosition();
|
||||
if (!topicRootId) {
|
||||
session().changes().historyUpdated(
|
||||
this,
|
||||
UpdateFlag::CloudDraft);
|
||||
} else {
|
||||
if (topicRootId) {
|
||||
session().changes().topicUpdated(
|
||||
thread->asTopic(),
|
||||
Data::TopicUpdate::Flag::CloudDraft);
|
||||
} else if (monoforumPeerId) {
|
||||
session().changes().sublistUpdated(
|
||||
thread->asSublist(),
|
||||
Data::SublistUpdate::Flag::CloudDraft);
|
||||
} else {
|
||||
session().changes().historyUpdated(
|
||||
this,
|
||||
UpdateFlag::CloudDraft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -633,6 +637,20 @@ void History::destroyMessagesByTopic(MsgId topicRootId) {
|
|||
}
|
||||
}
|
||||
|
||||
void History::destroyMessagesBySublist(not_null<PeerData*> sublistPeer) {
|
||||
auto toDestroy = std::vector<not_null<HistoryItem*>>();
|
||||
toDestroy.reserve(_items.size());
|
||||
const auto peerId = sublistPeer->id;
|
||||
for (const auto &message : _items) {
|
||||
if (message->sublistPeerId() == peerId) {
|
||||
toDestroy.push_back(message.get());
|
||||
}
|
||||
}
|
||||
for (const auto item : toDestroy) {
|
||||
item->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void History::unpinMessagesFor(MsgId topicRootId) {
|
||||
if (!topicRootId) {
|
||||
session().storage().remove(
|
||||
|
|
|
@ -139,6 +139,7 @@ public:
|
|||
void destroyMessage(not_null<HistoryItem*> item);
|
||||
void destroyMessagesByDates(TimeId minDate, TimeId maxDate);
|
||||
void destroyMessagesByTopic(MsgId topicRootId);
|
||||
void destroyMessagesBySublist(not_null<PeerData*> sublistPeer);
|
||||
|
||||
void unpinMessagesFor(MsgId topicRootId);
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "lang/lang_keys.h"
|
||||
#include "data/components/factchecks.h"
|
||||
#include "data/components/sponsored_messages.h"
|
||||
#include "data/data_saved_sublist.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_channel.h"
|
||||
|
@ -4963,9 +4964,17 @@ auto HistoryInner::DelegateMixin()
|
|||
|
||||
bool CanSendReply(not_null<const HistoryItem*> item) {
|
||||
const auto peer = item->history()->peer;
|
||||
const auto topic = item->topic();
|
||||
return topic
|
||||
? Data::CanSendAnything(topic)
|
||||
: (Data::CanSendAnything(peer)
|
||||
&& (!peer->isChannel() || peer->asChannel()->amIn()));
|
||||
if (const auto topic = item->topic()) {
|
||||
return Data::CanSendAnything(topic);
|
||||
} else if (!Data::CanSendAnything(peer)) {
|
||||
return false;
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
if (const auto sublist = item->savedSublist()) {
|
||||
if (sublist->sublistPeer() == peer) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return channel->amIn();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2151,9 +2151,13 @@ void HistoryItem::addToUnreadThings(HistoryUnreadThings::AddType type) {
|
|||
}
|
||||
}
|
||||
if (reaction) {
|
||||
const auto sublist = this->savedSublist();
|
||||
const auto toHistory = history->unreadReactions().add(id, type);
|
||||
const auto toTopic = topic && topic->unreadReactions().add(id, type);
|
||||
if (toHistory || toTopic) {
|
||||
const auto toSublist = sublist
|
||||
&& sublist->parentChat()
|
||||
&& sublist->unreadReactions().add(id, type);
|
||||
if (toHistory || toTopic || toSublist) {
|
||||
if (type == HistoryUnreadThings::AddType::New) {
|
||||
changes->messageUpdated(
|
||||
this,
|
||||
|
@ -2170,6 +2174,11 @@ void HistoryItem::addToUnreadThings(HistoryUnreadThings::AddType type) {
|
|||
topic,
|
||||
Data::TopicUpdate::Flag::UnreadReactions);
|
||||
}
|
||||
if (toSublist) {
|
||||
changes->sublistUpdated(
|
||||
sublist,
|
||||
Data::SublistUpdate::Flag::UnreadReactions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "history/history_unread_things.h"
|
||||
|
||||
#include "data/data_saved_sublist.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_channel.h"
|
||||
|
@ -38,6 +39,12 @@ template <typename Update>
|
|||
return UpdateFlag<Data::TopicUpdate>(type);
|
||||
}
|
||||
|
||||
[[nodiscard]] Data::SublistUpdate::Flag SublistUpdateFlag(Type type) {
|
||||
Expects(type == Type::Reactions);
|
||||
|
||||
return Data::SublistUpdate::Flag::UnreadReactions;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Proxy::setCount(int count) {
|
||||
|
@ -224,6 +231,10 @@ void Proxy::notifyUpdated() {
|
|||
topic->session().changes().topicUpdated(
|
||||
topic,
|
||||
TopicUpdateFlag(_type));
|
||||
} else if (const auto sublist = _thread->asSublist()) {
|
||||
sublist->session().changes().sublistUpdated(
|
||||
sublist,
|
||||
SublistUpdateFlag(_type));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -366,8 +366,9 @@ void Item::setupTop() {
|
|||
? nullptr
|
||||
: Ui::CreateChild<Ui::UserpicButton>(
|
||||
_top.get(),
|
||||
_thread->peer(),
|
||||
st::previewUserpic);
|
||||
_thread->peer()->userpicPaintingPeer(),
|
||||
st::previewUserpic,
|
||||
_thread->peer()->userpicForceForumShape());
|
||||
if (userpic) {
|
||||
userpic->showSavedMessagesOnSelf(true);
|
||||
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
|
|
@ -47,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/delete_messages_box.h"
|
||||
#include "boxes/send_files_box.h"
|
||||
#include "boxes/premium_limits_box.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "window/window_peer_menu.h"
|
||||
#include "base/call_delayed.h"
|
||||
|
@ -58,6 +59,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "main/main_session.h"
|
||||
#include "main/main_session_settings.h"
|
||||
#include "data/components/scheduled_messages.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_saved_messages.h"
|
||||
#include "data/data_saved_sublist.h"
|
||||
#include "data/data_session.h"
|
||||
|
@ -619,9 +621,7 @@ void ChatWidget::subscribeToTopic() {
|
|||
|
||||
_topic->destroyed(
|
||||
) | rpl::start_with_next([=] {
|
||||
controller()->showBackFromStack(Window::SectionShow(
|
||||
anim::type::normal,
|
||||
anim::activation::background));
|
||||
closeCurrent();
|
||||
}, _topicLifetime);
|
||||
|
||||
if (!_topic->creating()) {
|
||||
|
@ -635,6 +635,17 @@ void ChatWidget::subscribeToTopic() {
|
|||
_cornerButtons.updateUnreadThingsVisibility();
|
||||
}
|
||||
|
||||
void ChatWidget::closeCurrent() {
|
||||
const auto thread = controller()->windowId().chat();
|
||||
if ((_sublist && thread == _sublist) || (_topic && thread == _topic)) {
|
||||
controller()->window().close();
|
||||
} else {
|
||||
controller()->showBackFromStack(Window::SectionShow(
|
||||
anim::type::normal,
|
||||
anim::activation::background));
|
||||
}
|
||||
}
|
||||
|
||||
void ChatWidget::subscribeToPinnedMessages() {
|
||||
using EntryUpdateFlag = Data::EntryUpdate::Flag;
|
||||
session().changes().entryUpdates(
|
||||
|
@ -2496,9 +2507,7 @@ void ChatWidget::setReplies(std::shared_ptr<Data::RepliesList> replies) {
|
|||
refreshUnreadCountBadge(count);
|
||||
}, lifetime());
|
||||
|
||||
refreshUnreadCountBadge(_replies->unreadCountKnown()
|
||||
? _replies->unreadCountCurrent()
|
||||
: std::optional<int>());
|
||||
unreadCountUpdated();
|
||||
|
||||
const auto isTopic = (_topic != nullptr);
|
||||
const auto isTopicCreating = isTopic && _topic->creating();
|
||||
|
@ -2533,14 +2542,62 @@ void ChatWidget::setReplies(std::shared_ptr<Data::RepliesList> replies) {
|
|||
void ChatWidget::subscribeToSublist() {
|
||||
Expects(_sublist != nullptr);
|
||||
|
||||
// Must be done before unreadCountUpdated(), or we auto-close.
|
||||
if (_sublist->unreadMark()) {
|
||||
_sublist->owner().histories().changeSublistUnreadMark(
|
||||
_sublist,
|
||||
false);
|
||||
}
|
||||
|
||||
_sublist->unreadCountValue(
|
||||
) | rpl::start_with_next([=](std::optional<int> count) {
|
||||
refreshUnreadCountBadge(count);
|
||||
}, lifetime());
|
||||
|
||||
refreshUnreadCountBadge(_sublist->unreadCountKnown()
|
||||
? _sublist->unreadCountCurrent()
|
||||
: std::optional<int>());
|
||||
using Flag = Data::SublistUpdate::Flag;
|
||||
session().changes().sublistUpdates(
|
||||
_sublist,
|
||||
Flag::UnreadView | Flag::UnreadReactions | Flag::CloudDraft
|
||||
) | rpl::start_with_next([=](const Data::SublistUpdate &update) {
|
||||
if (update.flags & Flag::UnreadView) {
|
||||
unreadCountUpdated();
|
||||
}
|
||||
if (update.flags & Flag::UnreadReactions) {
|
||||
_cornerButtons.updateUnreadThingsVisibility();
|
||||
}
|
||||
if (update.flags & Flag::CloudDraft) {
|
||||
_composeControls->applyCloudDraft();
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
_sublist->destroyed(
|
||||
) | rpl::start_with_next([=] {
|
||||
closeCurrent();
|
||||
}, lifetime());
|
||||
|
||||
unreadCountUpdated();
|
||||
}
|
||||
|
||||
void ChatWidget::unreadCountUpdated() {
|
||||
if (_sublist && _sublist->unreadMark()) {
|
||||
crl::on_main(this, [=] {
|
||||
const auto guard = Ui::MakeWeak(this);
|
||||
controller()->showPeerHistory(_sublist->owningHistory());
|
||||
if (guard) {
|
||||
closeCurrent();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
refreshUnreadCountBadge(_replies
|
||||
? (_replies->unreadCountKnown()
|
||||
? _replies->unreadCountCurrent()
|
||||
: std::optional<int>())
|
||||
: _sublist
|
||||
? (_sublist->unreadCountKnown()
|
||||
? _sublist->unreadCountCurrent()
|
||||
: std::optional<int>())
|
||||
: std::optional<int>());
|
||||
}
|
||||
}
|
||||
|
||||
void ChatWidget::restoreState(not_null<ChatMemento*> memento) {
|
||||
|
|
|
@ -241,6 +241,8 @@ private:
|
|||
int limitAfter);
|
||||
|
||||
void onScroll();
|
||||
void closeCurrent();
|
||||
void unreadCountUpdated();
|
||||
void updateInnerVisibleArea();
|
||||
void updateControlsGeometry();
|
||||
void updateAdaptiveLayout();
|
||||
|
|
|
@ -590,9 +590,12 @@ void SubsectionTabs::refreshSlice() {
|
|||
});
|
||||
const auto push = [&](not_null<Data::Thread*> thread) {
|
||||
const auto topic = thread->asTopic();
|
||||
const auto sublist = thread->asSublist();
|
||||
slice.push_back({
|
||||
.thread = thread,
|
||||
.badges = thread->chatListBadgesState(),
|
||||
.badges = ((topic || sublist)
|
||||
? thread->chatListBadgesState()
|
||||
: Dialogs::BadgesState()),
|
||||
.iconId = topic ? topic->iconId() : DocumentId(),
|
||||
.name = thread->chatListName(),
|
||||
});
|
||||
|
|
|
@ -940,7 +940,7 @@ void TopBarWidget::refreshInfoButton() {
|
|||
Ui::UserpicButton::Role::Custom,
|
||||
Ui::UserpicButton::Source::PeerPhoto,
|
||||
st::topBarInfoButton,
|
||||
infoPeer->monoforumBroadcast() != nullptr);
|
||||
infoPeer->userpicForceForumShape());
|
||||
info->showSavedMessagesOnSelf(true);
|
||||
_info.destroy();
|
||||
_info = std::move(info);
|
||||
|
|
|
@ -632,7 +632,7 @@ Cover::Cover(
|
|||
Ui::UserpicButton::Role::OpenPhoto,
|
||||
Ui::UserpicButton::Source::PeerPhoto,
|
||||
_st.photo,
|
||||
_peer->monoforumBroadcast() != nullptr))
|
||||
_peer->userpicForceForumShape()))
|
||||
, _changePersonal((role == Role::Info
|
||||
|| topic
|
||||
|| !_peer->isUser()
|
||||
|
|
|
@ -202,10 +202,12 @@ UserpicButton::UserpicButton(
|
|||
UserpicButton::UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<PeerData*> peer,
|
||||
const style::UserpicButton &st)
|
||||
const style::UserpicButton &st,
|
||||
bool forceForumShape)
|
||||
: RippleButton(parent, st.changeButton.ripple)
|
||||
, _st(st)
|
||||
, _peer(peer)
|
||||
, _forceForumShape(forceForumShape)
|
||||
, _role(Role::Custom)
|
||||
, _source(Source::PeerPhoto) {
|
||||
Expects(_role != Role::OpenPhoto);
|
||||
|
|
|
@ -74,7 +74,8 @@ public:
|
|||
UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<PeerData*> peer, // Role::Custom, Source::PeerPhoto
|
||||
const style::UserpicButton &st);
|
||||
const style::UserpicButton &st,
|
||||
bool forceForumShape = false);
|
||||
~UserpicButton();
|
||||
|
||||
enum class ChosenType {
|
||||
|
|
|
@ -499,6 +499,8 @@ void Filler::addTogglePin() {
|
|||
&& !_sublist
|
||||
&& !_topic) {
|
||||
return;
|
||||
} else if (_sublist && !_peer->isSelf()) {
|
||||
return;
|
||||
}
|
||||
const auto controller = _controller;
|
||||
const auto filterId = _request.filterId;
|
||||
|
@ -526,7 +528,7 @@ void Filler::addTogglePin() {
|
|||
}
|
||||
|
||||
void Filler::addToggleMuteSubmenu(bool addSeparator) {
|
||||
if (!_thread || _thread->peer()->isSelf()) {
|
||||
if (!_thread || _thread->peer()->isSelf() || _thread->asSublist()) {
|
||||
return;
|
||||
}
|
||||
PeerMenuAddMuteSubmenuAction(_controller, _thread, _addAction);
|
||||
|
@ -550,16 +552,18 @@ void Filler::addSupportInfo() {
|
|||
}
|
||||
|
||||
void Filler::addInfo() {
|
||||
if (_peer
|
||||
&& (_peer->isSelf()
|
||||
|| _peer->isRepliesChat()
|
||||
|| _peer->isVerifyCodes())) {
|
||||
const auto sublist = _thread ? _thread->asSublist() : nullptr;
|
||||
const auto infoPeer = sublist ? sublist->sublistPeer().get() : _peer;
|
||||
if (infoPeer
|
||||
&& (infoPeer->isSelf()
|
||||
|| infoPeer->isRepliesChat()
|
||||
|| infoPeer->isVerifyCodes())) {
|
||||
return;
|
||||
} else if (!_thread) {
|
||||
return;
|
||||
} else if (_controller->adaptive().isThreeColumn()) {
|
||||
const auto thread = _controller->activeChatCurrent().thread();
|
||||
if (thread && thread == _thread) {
|
||||
if (thread && !thread->asSublist() && thread == _thread) {
|
||||
if (Core::App().settings().thirdSectionInfoEnabled()
|
||||
|| Core::App().settings().tabbedReplacedWithInfo()) {
|
||||
return;
|
||||
|
@ -570,16 +574,16 @@ void Filler::addInfo() {
|
|||
const auto weak = base::make_weak(_thread);
|
||||
const auto text = _thread->asTopic()
|
||||
? tr::lng_context_view_topic(tr::now)
|
||||
: (_peer->isChat() || _peer->isMegagroup())
|
||||
: (infoPeer->isChat() || infoPeer->isMegagroup())
|
||||
? tr::lng_context_view_group(tr::now)
|
||||
: _peer->isUser()
|
||||
: infoPeer->isUser()
|
||||
? tr::lng_context_view_profile(tr::now)
|
||||
: tr::lng_context_view_channel(tr::now);
|
||||
_addAction(text, [=] {
|
||||
if (const auto strong = weak.get()) {
|
||||
controller->showPeerInfo(strong);
|
||||
}
|
||||
}, _peer->isUser() ? &st::menuIconProfile : &st::menuIconInfo);
|
||||
}, infoPeer->isUser() ? &st::menuIconProfile : &st::menuIconInfo);
|
||||
}
|
||||
|
||||
void Filler::addStoryArchive() {
|
||||
|
@ -624,12 +628,9 @@ void Filler::addToggleFolder() {
|
|||
|
||||
void Filler::addToggleUnreadMark() {
|
||||
const auto peer = _peer;
|
||||
const auto history = _request.key.history();
|
||||
if (!_thread) {
|
||||
return;
|
||||
}
|
||||
const auto unread = IsUnreadThread(_thread);
|
||||
if ((_thread->asTopic() || peer->isForum()) && !unread) {
|
||||
const auto history = _request.key.history();
|
||||
if (!_thread || !_thread->canToggleUnread(unread)) {
|
||||
return;
|
||||
}
|
||||
const auto weak = base::make_weak(_thread);
|
||||
|
@ -643,6 +644,8 @@ void Filler::addToggleUnreadMark() {
|
|||
}
|
||||
if (unread) {
|
||||
MarkAsReadThread(thread);
|
||||
} else if (const auto sublist = thread->asSublist()) {
|
||||
peer->owner().histories().changeSublistUnreadMark(sublist, true);
|
||||
} else if (history) {
|
||||
peer->owner().histories().changeDialogUnreadMark(history, true);
|
||||
}
|
||||
|
@ -751,14 +754,16 @@ void Filler::addClearHistory() {
|
|||
}
|
||||
|
||||
void Filler::addDeleteChat() {
|
||||
if (_topic || _peer->isChannel()) {
|
||||
if (_topic || (!_sublist && _peer->isChannel())) {
|
||||
return;
|
||||
}
|
||||
_addAction({
|
||||
.text = (_peer->isUser()
|
||||
.text = ((_peer->isUser() || _sublist)
|
||||
? tr::lng_profile_delete_conversation(tr::now)
|
||||
: tr::lng_profile_clear_and_exit(tr::now)),
|
||||
.handler = DeleteAndLeaveHandler(_controller, _peer),
|
||||
.handler = (_sublist
|
||||
? DeleteSublistHandler(_controller, _sublist)
|
||||
: DeleteAndLeaveHandler(_controller, _peer)),
|
||||
.icon = &st::menuIconDeleteAttention,
|
||||
.isAttention = true,
|
||||
});
|
||||
|
@ -766,7 +771,7 @@ void Filler::addDeleteChat() {
|
|||
|
||||
void Filler::addLeaveChat() {
|
||||
const auto channel = _peer->asChannel();
|
||||
if (_topic || !channel || !channel->amIn()) {
|
||||
if (_topic || _sublist || !channel || !channel->amIn()) {
|
||||
return;
|
||||
}
|
||||
_addAction({
|
||||
|
@ -1263,7 +1268,7 @@ void Filler::addSendGift() {
|
|||
void Filler::fill() {
|
||||
if (_folder) {
|
||||
fillArchiveActions();
|
||||
} else if (_sublist) {
|
||||
} else if (_sublist && _peer->isSelf()) {
|
||||
fillSavedSublistActions();
|
||||
} else switch (_request.section) {
|
||||
case Section::ChatsList: fillChatsListActions(); break;
|
||||
|
@ -3232,6 +3237,19 @@ Fn<void()> DeleteAndLeaveHandler(
|
|||
};
|
||||
}
|
||||
|
||||
Fn<void()> DeleteSublistHandler(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Data::SavedSublist*> sublist) {
|
||||
const auto weak = base::make_weak(sublist.get());
|
||||
return [=] {
|
||||
if (const auto strong = weak.get()) {
|
||||
if (!controller->showFrozenError()) {
|
||||
controller->show(Box(DeleteSublistBox, strong));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void FillDialogsEntryMenu(
|
||||
not_null<SessionController*> controller,
|
||||
Dialogs::EntryState request,
|
||||
|
@ -3345,8 +3363,7 @@ void MarkAsReadThread(not_null<Data::Thread*> thread) {
|
|||
if (!IsUnreadThread(thread)) {
|
||||
return;
|
||||
} else if (const auto forum = thread->asForum()) {
|
||||
forum->enumerateTopics([](
|
||||
not_null<Data::ForumTopic*> topic) {
|
||||
forum->enumerateTopics([](not_null<Data::ForumTopic*> topic) {
|
||||
MarkAsReadThread(topic);
|
||||
});
|
||||
} else if (const auto history = thread->asHistory()) {
|
||||
|
@ -3356,6 +3373,8 @@ void MarkAsReadThread(not_null<Data::Thread*> thread) {
|
|||
}
|
||||
} else if (const auto topic = thread->asTopic()) {
|
||||
topic->readTillEnd();
|
||||
} else if (const auto sublist = thread->asSublist()) {
|
||||
sublist->readTillEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -148,6 +148,9 @@ Fn<void()> ClearHistoryHandler(
|
|||
Fn<void()> DeleteAndLeaveHandler(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<PeerData*> peer);
|
||||
Fn<void()> DeleteSublistHandler(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Data::SavedSublist*> sublist);
|
||||
|
||||
object_ptr<Ui::BoxContent> PrepareChooseRecipientBox(
|
||||
not_null<Main::Session*> session,
|
||||
|
|
|
@ -1309,6 +1309,9 @@ void SessionNavigation::showPeerInfo(
|
|||
const SectionShow ¶ms) {
|
||||
if (const auto topic = thread->asTopic()) {
|
||||
showSection(std::make_shared<Info::Memento>(topic), params);
|
||||
} else if (const auto sublist = thread->asSublist()
|
||||
; sublist && sublist->parentChat()) {
|
||||
showPeerInfo(sublist->sublistPeer()->id, params);
|
||||
} else {
|
||||
showPeerInfo(thread->peer()->id, params);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue