mirror of https://github.com/procxx/kepka.git
Channels list in feed info with leave channel.
This commit is contained in:
parent
f23c23f696
commit
906cb95e67
|
@ -273,7 +273,7 @@ messageActionCustomAction#fae69f56 message:string = MessageAction;
|
||||||
messageActionBotAllowed#abe9affe domain:string = MessageAction;
|
messageActionBotAllowed#abe9affe domain:string = MessageAction;
|
||||||
|
|
||||||
dialog#e4def5db flags:# pinned:flags.2?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage = Dialog;
|
dialog#e4def5db flags:# pinned:flags.2?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage = Dialog;
|
||||||
dialogFeed#907750e4 flags:# pinned:flags.2?true peer:Peer top_message:int feed_id:int feed_other_channels:Vector<int> read_max_position:flags.3?FeedPosition unread_count:int unread_muted_count:int sources_hash:int = Dialog;
|
dialogFeed#36086d42 flags:# pinned:flags.2?true peer:Peer top_message:int feed_id:int feed_other_channels:Vector<int> read_max_position:flags.3?FeedPosition unread_count:int unread_muted_count:int = Dialog;
|
||||||
|
|
||||||
photoEmpty#2331b22d id:long = Photo;
|
photoEmpty#2331b22d id:long = Photo;
|
||||||
photo#9288dd29 flags:# has_stickers:flags.0?true id:long access_hash:long date:int sizes:Vector<PhotoSize> = Photo;
|
photo#9288dd29 flags:# has_stickers:flags.0?true id:long access_hash:long date:int sizes:Vector<PhotoSize> = Photo;
|
||||||
|
@ -1199,11 +1199,11 @@ channels.setStickers#ea8ca4f9 channel:InputChannel stickerset:InputStickerSet =
|
||||||
channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool;
|
channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool;
|
||||||
channels.deleteHistory#af369d42 channel:InputChannel max_id:int = Bool;
|
channels.deleteHistory#af369d42 channel:InputChannel max_id:int = Bool;
|
||||||
channels.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates;
|
channels.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates;
|
||||||
channels.getFeed#18117df2 flags:# offset_to_max_read:flags.3?true feed_id:int offset_position:flags.0?FeedPosition add_offset:int limit:int max_position:flags.1?FeedPosition min_position:flags.2?FeedPosition sources_hash:int hash:int = messages.FeedMessages;
|
channels.getFeed#b90f450 flags:# offset_to_max_read:flags.3?true feed_id:int offset_position:flags.0?FeedPosition add_offset:int limit:int max_position:flags.1?FeedPosition min_position:flags.2?FeedPosition hash:int = messages.FeedMessages;
|
||||||
channels.searchFeed#88325369 feed_id:int q:string offset_date:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
channels.searchFeed#88325369 feed_id:int q:string offset_date:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||||
channels.getFeedSources#d8ce236e flags:# feed_id:flags.0?int hash:int = channels.FeedSources;
|
channels.getFeedSources#d8ce236e flags:# feed_id:flags.0?int hash:int = channels.FeedSources;
|
||||||
channels.changeFeedBroadcast#2528871e flags:# channel:InputChannel feed_id:flags.0?int = Bool;
|
channels.changeFeedBroadcast#ffb37511 flags:# channel:InputChannel feed_id:flags.0?int = Updates;
|
||||||
channels.setFeedBroadcasts#7e91b8f2 feed_id:int channels:Vector<InputChannel> also_newly_joined:Bool = Bool;
|
channels.setFeedBroadcasts#ea80bfae flags:# feed_id:int channels:flags.0?Vector<InputChannel> also_newly_joined:flags.1?Bool = Updates;
|
||||||
channels.readFeed#9c3011d feed_id:int max_position:FeedPosition = Updates;
|
channels.readFeed#9c3011d feed_id:int max_position:FeedPosition = Updates;
|
||||||
|
|
||||||
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
||||||
|
|
|
@ -187,7 +187,8 @@ void ApiWrap::toggleChannelGrouping(
|
||||||
MTP_flags(flags),
|
MTP_flags(flags),
|
||||||
channel->inputChannel,
|
channel->inputChannel,
|
||||||
MTP_int(feedId)
|
MTP_int(feedId)
|
||||||
)).done([=](const MTPBool &result) {
|
)).done([=](const MTPUpdates &result) {
|
||||||
|
applyUpdates(result);
|
||||||
if (group) {
|
if (group) {
|
||||||
channel->setFeed(Auth().data().feed(feedId));
|
channel->setFeed(Auth().data().feed(feedId));
|
||||||
} else {
|
} else {
|
||||||
|
@ -2993,6 +2994,11 @@ void ApiWrap::requestFeedChannels(not_null<Data::Feed*> feed) {
|
||||||
App::feedUsers(data.vusers);
|
App::feedUsers(data.vusers);
|
||||||
App::feedChats(data.vchats);
|
App::feedChats(data.vchats);
|
||||||
|
|
||||||
|
if (data.has_newly_joined_feed()) {
|
||||||
|
_session->data().setDefaultFeedId(
|
||||||
|
data.vnewly_joined_feed.v);
|
||||||
|
}
|
||||||
|
|
||||||
if (feed->channelsLoaded()) {
|
if (feed->channelsLoaded()) {
|
||||||
feedChannelsDone(feed);
|
feedChannelsDone(feed);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3044,7 +3050,6 @@ void ApiWrap::requestFeedMessages(
|
||||||
}
|
}
|
||||||
Unexpected("Direction in PrepareSearchRequest");
|
Unexpected("Direction in PrepareSearchRequest");
|
||||||
}();
|
}();
|
||||||
const auto sourcesHash = feed->channelsHash();
|
|
||||||
const auto hash = int32(0);
|
const auto hash = int32(0);
|
||||||
const auto flags = (messageId && messageId.fullId.channel)
|
const auto flags = (messageId && messageId.fullId.channel)
|
||||||
? MTPchannels_GetFeed::Flag::f_offset_position
|
? MTPchannels_GetFeed::Flag::f_offset_position
|
||||||
|
@ -3060,7 +3065,6 @@ void ApiWrap::requestFeedMessages(
|
||||||
MTP_int(limit),
|
MTP_int(limit),
|
||||||
MTPFeedPosition(),
|
MTPFeedPosition(),
|
||||||
MTPFeedPosition(),
|
MTPFeedPosition(),
|
||||||
MTP_int(sourcesHash),
|
|
||||||
MTP_int(hash)
|
MTP_int(hash)
|
||||||
)).done([=](const MTPmessages_FeedMessages &result) {
|
)).done([=](const MTPmessages_FeedMessages &result) {
|
||||||
const auto key = std::make_tuple(feed, messageId, slice);
|
const auto key = std::make_tuple(feed, messageId, slice);
|
||||||
|
@ -3172,6 +3176,18 @@ void ApiWrap::feedMessagesDone(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApiWrap::saveDefaultFeedId(FeedId id, bool isDefaultFeedId) {
|
||||||
|
if (const auto already = base::take(_saveDefaultFeedIdRequest)) {
|
||||||
|
request(already).cancel();
|
||||||
|
}
|
||||||
|
_saveDefaultFeedIdRequest = request(MTPchannels_SetFeedBroadcasts(
|
||||||
|
MTP_flags(MTPchannels_SetFeedBroadcasts::Flag::f_also_newly_joined),
|
||||||
|
MTP_int(id),
|
||||||
|
MTPVector<MTPInputChannel>(),
|
||||||
|
MTP_bool(isDefaultFeedId)
|
||||||
|
)).send();
|
||||||
|
}
|
||||||
|
|
||||||
void ApiWrap::sendAction(const SendOptions &options) {
|
void ApiWrap::sendAction(const SendOptions &options) {
|
||||||
readServerHistory(options.history);
|
readServerHistory(options.history);
|
||||||
options.history->getReadyFor(ShowAtTheEndMsgId);
|
options.history->getReadyFor(ShowAtTheEndMsgId);
|
||||||
|
|
|
@ -177,6 +177,7 @@ public:
|
||||||
not_null<Data::Feed*> feed,
|
not_null<Data::Feed*> feed,
|
||||||
Data::MessagePosition messageId,
|
Data::MessagePosition messageId,
|
||||||
SliceType slice);
|
SliceType slice);
|
||||||
|
void saveDefaultFeedId(FeedId id, bool isDefaultFeedId);
|
||||||
|
|
||||||
void stickerSetInstalled(uint64 setId) {
|
void stickerSetInstalled(uint64 setId) {
|
||||||
_stickerSetInstalled.fire_copy(setId);
|
_stickerSetInstalled.fire_copy(setId);
|
||||||
|
@ -507,6 +508,7 @@ private:
|
||||||
not_null<Data::Feed*>,
|
not_null<Data::Feed*>,
|
||||||
Data::MessagePosition,
|
Data::MessagePosition,
|
||||||
SliceType>> _feedMessagesRequestsPending;
|
SliceType>> _feedMessagesRequestsPending;
|
||||||
|
mtpRequestId _saveDefaultFeedIdRequest = 0;
|
||||||
|
|
||||||
rpl::event_stream<SendOptions> _sendActions;
|
rpl::event_stream<SendOptions> _sendActions;
|
||||||
|
|
||||||
|
|
|
@ -575,10 +575,14 @@ namespace {
|
||||||
|
|
||||||
cdata->setPhoto(d.vphoto);
|
cdata->setPhoto(d.vphoto);
|
||||||
|
|
||||||
if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn;
|
if (wasInChannel != cdata->amIn()) {
|
||||||
|
update.flags |= UpdateFlag::ChannelAmIn;
|
||||||
|
}
|
||||||
if (canViewAdmins != cdata->canViewAdmins()
|
if (canViewAdmins != cdata->canViewAdmins()
|
||||||
|| canViewMembers != cdata->canViewMembers()
|
|| canViewMembers != cdata->canViewMembers()
|
||||||
|| canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelRightsChanged;
|
|| canAddMembers != cdata->canAddMembers()) {
|
||||||
|
update.flags |= UpdateFlag::ChannelRightsChanged;
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case mtpc_channelForbidden: {
|
case mtpc_channelForbidden: {
|
||||||
auto &d(chat.c_channelForbidden());
|
auto &d(chat.c_channelForbidden());
|
||||||
|
@ -612,10 +616,14 @@ namespace {
|
||||||
cdata->date = 0;
|
cdata->date = 0;
|
||||||
cdata->setMembersCount(0);
|
cdata->setMembersCount(0);
|
||||||
|
|
||||||
if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn;
|
if (wasInChannel != cdata->amIn()) {
|
||||||
|
update.flags |= UpdateFlag::ChannelAmIn;
|
||||||
|
}
|
||||||
if (canViewAdmins != cdata->canViewAdmins()
|
if (canViewAdmins != cdata->canViewAdmins()
|
||||||
|| canViewMembers != cdata->canViewMembers()
|
|| canViewMembers != cdata->canViewMembers()
|
||||||
|| canAddMembers != cdata->canAddMembers()) update.flags |= UpdateFlag::ChannelRightsChanged;
|
|| canAddMembers != cdata->canAddMembers()) {
|
||||||
|
update.flags |= UpdateFlag::ChannelRightsChanged;
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
if (!data) {
|
if (!data) {
|
||||||
|
|
|
@ -84,6 +84,19 @@ void Feed::registerOne(not_null<ChannelData*> channel) {
|
||||||
} else if (lastMessageKnown()) {
|
} else if (lastMessageKnown()) {
|
||||||
_parent->session().api().requestDialogEntry(history);
|
_parent->session().api().requestDialogEntry(history);
|
||||||
}
|
}
|
||||||
|
if (unreadCountKnown()) {
|
||||||
|
if (history->unreadCountKnown()) {
|
||||||
|
// If history unreadCount is known that means that we've
|
||||||
|
// already had the channel information and if it was in the
|
||||||
|
// feed already (not yet known) it wouldn't get here.
|
||||||
|
// That means here we get if we add a new channel to feed.
|
||||||
|
if (const auto count = history->unreadCount()) {
|
||||||
|
unreadCountChanged(count, history->mute() ? count : 0);
|
||||||
|
}
|
||||||
|
} else if (!_settingChannels) {
|
||||||
|
_parent->session().api().requestDialogEntry(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (invisible && _channels.size() > 1) {
|
if (invisible && _channels.size() > 1) {
|
||||||
updateChatListExistence();
|
updateChatListExistence();
|
||||||
for (const auto history : _channels) {
|
for (const auto history : _channels) {
|
||||||
|
@ -105,9 +118,20 @@ void Feed::unregisterOne(not_null<ChannelData*> channel) {
|
||||||
_parent->session().storage().remove(
|
_parent->session().storage().remove(
|
||||||
Storage::FeedMessagesRemoveAll(_id, channel->bareId()));
|
Storage::FeedMessagesRemoveAll(_id, channel->bareId()));
|
||||||
|
|
||||||
if (const auto last = lastMessage()) {
|
if (lastMessageKnown()) {
|
||||||
if (last->history() == history) {
|
if (const auto last = lastMessage()) {
|
||||||
recountLastMessage();
|
if (last->history() == history) {
|
||||||
|
recountLastMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (unreadCountKnown()) {
|
||||||
|
if (history->unreadCountKnown()) {
|
||||||
|
if (const auto delta = -history->unreadCount()) {
|
||||||
|
unreadCountChanged(delta, history->mute() ? delta : 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_parent->session().api().requestDialogEntry(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (visible && _channels.size() < 2) {
|
if (visible && _channels.size() < 2) {
|
||||||
|
@ -188,7 +212,7 @@ void Feed::setChannels(std::vector<not_null<ChannelData*>> channels) {
|
||||||
const auto remove = ranges::view::all(
|
const auto remove = ranges::view::all(
|
||||||
_channels
|
_channels
|
||||||
) | ranges::view::transform([](not_null<History*> history) {
|
) | ranges::view::transform([](not_null<History*> history) {
|
||||||
return history->peer->asChannel();
|
return not_null<ChannelData*>(history->peer->asChannel());
|
||||||
}) | ranges::view::filter([&](not_null<ChannelData*> channel) {
|
}) | ranges::view::filter([&](not_null<ChannelData*> channel) {
|
||||||
return !base::contains(channels, channel);
|
return !base::contains(channels, channel);
|
||||||
}) | ranges::to_vector;
|
}) | ranges::to_vector;
|
||||||
|
@ -201,8 +225,21 @@ void Feed::setChannels(std::vector<not_null<ChannelData*>> channels) {
|
||||||
channel.get(),
|
channel.get(),
|
||||||
[](auto history) { return history->peer->asChannel(); }
|
[](auto history) { return history->peer->asChannel(); }
|
||||||
) == end(_channels);
|
) == end(_channels);
|
||||||
|
}) | ranges::view::transform([](ChannelData *channel) {
|
||||||
|
return not_null<ChannelData*>(channel);
|
||||||
}) | ranges::to_vector;
|
}) | ranges::to_vector;
|
||||||
|
|
||||||
|
changeChannelsList(add, remove);
|
||||||
|
|
||||||
|
setChannelsLoaded(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Feed::changeChannelsList(
|
||||||
|
const std::vector<not_null<ChannelData*>> &add,
|
||||||
|
const std::vector<not_null<ChannelData*>> &remove) {
|
||||||
|
_settingChannels = true;
|
||||||
|
const auto restore = gsl::finally([&] { _settingChannels = false; });
|
||||||
|
|
||||||
for (const auto channel : remove) {
|
for (const auto channel : remove) {
|
||||||
channel->clearFeed();
|
channel->clearFeed();
|
||||||
}
|
}
|
||||||
|
@ -216,14 +253,6 @@ void Feed::setChannels(std::vector<not_null<ChannelData*>> channels) {
|
||||||
channel->setFeed(this);
|
channel->setFeed(this);
|
||||||
}
|
}
|
||||||
_lastMessage = oldLastMessage;
|
_lastMessage = oldLastMessage;
|
||||||
|
|
||||||
_channels.clear();
|
|
||||||
for (const auto channel : channels) {
|
|
||||||
Assert(channel->feed() == this);
|
|
||||||
|
|
||||||
_channels.push_back(App::history(channel));
|
|
||||||
}
|
|
||||||
setChannelsLoaded(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Feed::justUpdateLastMessage(not_null<HistoryItem*> item) {
|
bool Feed::justUpdateLastMessage(not_null<HistoryItem*> item) {
|
||||||
|
@ -328,10 +357,6 @@ void Feed::applyDialog(const MTPDdialogFeed &data) {
|
||||||
if (data.has_read_max_position()) {
|
if (data.has_read_max_position()) {
|
||||||
setUnreadPosition(FeedPositionFromMTP(data.vread_max_position));
|
setUnreadPosition(FeedPositionFromMTP(data.vread_max_position));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channelsHash() != data.vsources_hash.v) {
|
|
||||||
setChannelsLoaded(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Feed::setUnreadCounts(int unreadNonMutedCount, int unreadMutedCount) {
|
void Feed::setUnreadCounts(int unreadNonMutedCount, int unreadMutedCount) {
|
||||||
|
|
|
@ -87,10 +87,14 @@ private:
|
||||||
void setLastMessageFromChannels();
|
void setLastMessageFromChannels();
|
||||||
bool justUpdateLastMessage(not_null<HistoryItem*> item);
|
bool justUpdateLastMessage(not_null<HistoryItem*> item);
|
||||||
void updateChatsListDate();
|
void updateChatsListDate();
|
||||||
|
void changeChannelsList(
|
||||||
|
const std::vector<not_null<ChannelData*>> &add,
|
||||||
|
const std::vector<not_null<ChannelData*>> &remove);
|
||||||
|
|
||||||
FeedId _id = 0;
|
FeedId _id = 0;
|
||||||
not_null<Data::Session*> _parent;
|
not_null<Data::Session*> _parent;
|
||||||
std::vector<not_null<History*>> _channels;
|
std::vector<not_null<History*>> _channels;
|
||||||
|
bool _settingChannels = false;
|
||||||
bool _channelsLoaded = false;
|
bool _channelsLoaded = false;
|
||||||
|
|
||||||
QString _name;
|
QString _name;
|
||||||
|
|
|
@ -60,6 +60,11 @@ void UpdateImage(ImagePtr &old, ImagePtr now) {
|
||||||
Session::Session(not_null<AuthSession*> session)
|
Session::Session(not_null<AuthSession*> session)
|
||||||
: _session(session)
|
: _session(session)
|
||||||
, _groups(this) {
|
, _groups(this) {
|
||||||
|
setupContactViewsViewer();
|
||||||
|
setupChannelLeavingViewer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::setupContactViewsViewer() {
|
||||||
Notify::PeerUpdateViewer(
|
Notify::PeerUpdateViewer(
|
||||||
Notify::PeerUpdate::Flag::UserIsContact
|
Notify::PeerUpdate::Flag::UserIsContact
|
||||||
) | rpl::map([](const Notify::PeerUpdate &update) {
|
) | rpl::map([](const Notify::PeerUpdate &update) {
|
||||||
|
@ -71,6 +76,20 @@ Session::Session(not_null<AuthSession*> session)
|
||||||
}, _lifetime);
|
}, _lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::setupChannelLeavingViewer() {
|
||||||
|
Notify::PeerUpdateViewer(
|
||||||
|
Notify::PeerUpdate::Flag::ChannelAmIn
|
||||||
|
) | rpl::map([](const Notify::PeerUpdate &update) {
|
||||||
|
return update.peer->asChannel();
|
||||||
|
}) | rpl::filter([](ChannelData *channel) {
|
||||||
|
return (channel != nullptr)
|
||||||
|
&& !(channel->amIn())
|
||||||
|
&& (channel->feed() != nullptr);
|
||||||
|
}) | rpl::start_with_next([=](not_null<ChannelData*> channel) {
|
||||||
|
channel->clearFeed();
|
||||||
|
}, _lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
Session::~Session() = default;
|
Session::~Session() = default;
|
||||||
|
|
||||||
template <typename Method>
|
template <typename Method>
|
||||||
|
@ -1447,6 +1466,18 @@ Feed *Session::feedLoaded(FeedId id) {
|
||||||
return (it == end(_feeds)) ? nullptr : it->second.get();
|
return (it == end(_feeds)) ? nullptr : it->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::setDefaultFeedId(FeedId id) {
|
||||||
|
_defaultFeedId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
FeedId Session::defaultFeedId() const {
|
||||||
|
return _defaultFeedId.current();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<FeedId> Session::defaultFeedIdValue() const {
|
||||||
|
return _defaultFeedId.value();
|
||||||
|
}
|
||||||
|
|
||||||
void Session::forgetMedia() {
|
void Session::forgetMedia() {
|
||||||
for (const auto &[id, photo] : _photos) {
|
for (const auto &[id, photo] : _photos) {
|
||||||
photo->forget();
|
photo->forget();
|
||||||
|
|
|
@ -347,6 +347,9 @@ public:
|
||||||
|
|
||||||
not_null<Feed*> feed(FeedId id);
|
not_null<Feed*> feed(FeedId id);
|
||||||
Feed *feedLoaded(FeedId id);
|
Feed *feedLoaded(FeedId id);
|
||||||
|
void setDefaultFeedId(FeedId id);
|
||||||
|
FeedId defaultFeedId() const;
|
||||||
|
rpl::producer<FeedId> defaultFeedIdValue() const;
|
||||||
|
|
||||||
void forgetMedia();
|
void forgetMedia();
|
||||||
|
|
||||||
|
@ -361,6 +364,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setupContactViewsViewer();
|
||||||
|
void setupChannelLeavingViewer();
|
||||||
void photoApplyFields(
|
void photoApplyFields(
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
const MTPPhoto &data);
|
const MTPPhoto &data);
|
||||||
|
@ -517,6 +522,7 @@ private:
|
||||||
|
|
||||||
std::deque<Dialogs::Key> _pinnedDialogs;
|
std::deque<Dialogs::Key> _pinnedDialogs;
|
||||||
base::flat_map<FeedId, std::unique_ptr<Feed>> _feeds;
|
base::flat_map<FeedId, std::unique_ptr<Feed>> _feeds;
|
||||||
|
rpl::variable<FeedId> _defaultFeedId = FeedId();
|
||||||
Groups _groups;
|
Groups _groups;
|
||||||
std::map<
|
std::map<
|
||||||
not_null<const HistoryItem*>,
|
not_null<const HistoryItem*>,
|
||||||
|
|
|
@ -110,6 +110,7 @@ Widget::Widget(
|
||||||
_showNext->setClickedCallback([this] {
|
_showNext->setClickedCallback([this] {
|
||||||
// #TODO feeds show next
|
// #TODO feeds show next
|
||||||
});
|
});
|
||||||
|
_showNext->hide();
|
||||||
|
|
||||||
_feed->unreadPositionChanges(
|
_feed->unreadPositionChanges(
|
||||||
) | rpl::filter([=](const Data::MessagePosition &position) {
|
) | rpl::filter([=](const Data::MessagePosition &position) {
|
||||||
|
@ -463,8 +464,8 @@ void Widget::updateControlsGeometry() {
|
||||||
|
|
||||||
const auto bottom = height();
|
const auto bottom = height();
|
||||||
const auto scrollHeight = bottom
|
const auto scrollHeight = bottom
|
||||||
- _topBar->height()
|
- _topBar->height();
|
||||||
- _showNext->height();
|
// - _showNext->height();
|
||||||
const auto scrollSize = QSize(contentWidth, scrollHeight);
|
const auto scrollSize = QSize(contentWidth, scrollHeight);
|
||||||
if (_scroll->size() != scrollSize) {
|
if (_scroll->size() != scrollSize) {
|
||||||
_skipScrollEvent = true;
|
_skipScrollEvent = true;
|
||||||
|
@ -480,12 +481,12 @@ void Widget::updateControlsGeometry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateScrollDownPosition();
|
updateScrollDownPosition();
|
||||||
const auto fullWidthButtonRect = myrtlrect(
|
//const auto fullWidthButtonRect = myrtlrect(
|
||||||
0,
|
// 0,
|
||||||
bottom - _showNext->height(),
|
// bottom - _showNext->height(),
|
||||||
contentWidth,
|
// contentWidth,
|
||||||
_showNext->height());
|
// _showNext->height());
|
||||||
_showNext->setGeometry(fullWidthButtonRect);
|
//_showNext->setGeometry(fullWidthButtonRect);
|
||||||
|
|
||||||
if (_emptyTextView) {
|
if (_emptyTextView) {
|
||||||
_emptyTextView->resizeGetHeight(width());
|
_emptyTextView->resizeGetHeight(width());
|
||||||
|
@ -515,7 +516,7 @@ void Widget::paintEvent(QPaintEvent *e) {
|
||||||
const auto clip = e->rect();
|
const auto clip = e->rect();
|
||||||
const auto left = 0;
|
const auto left = 0;
|
||||||
const auto top = (height()
|
const auto top = (height()
|
||||||
- _showNext->height()
|
// - _showNext->height()
|
||||||
- _emptyTextView->height()) / 2;
|
- _emptyTextView->height()) / 2;
|
||||||
p.translate(left, top);
|
p.translate(left, top);
|
||||||
_emptyTextView->draw(
|
_emptyTextView->draw(
|
||||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/wrap/padding_wrap.h"
|
#include "ui/wrap/padding_wrap.h"
|
||||||
#include "ui/search_field_controller.h"
|
#include "ui/search_field_controller.h"
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
|
#include "data/data_feed.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "styles/style_info.h"
|
#include "styles/style_info.h"
|
||||||
|
@ -57,16 +58,8 @@ Channels::Channels(
|
||||||
|
|
||||||
int Channels::desiredHeight() const {
|
int Channels::desiredHeight() const {
|
||||||
auto desired = _header ? _header->height() : 0;
|
auto desired = _header ? _header->height() : 0;
|
||||||
//auto count = [this] {
|
desired += st::infoMembersList.item.height
|
||||||
// if (auto chat = _peer->asChat()) {
|
* std::max(int(_feed->channels().size()), _list->fullRowsCount());
|
||||||
// return chat->count;
|
|
||||||
// } else if (auto channel = _peer->asChannel()) {
|
|
||||||
// return channel->membersCount();
|
|
||||||
// }
|
|
||||||
// return 0;
|
|
||||||
//}();
|
|
||||||
//desired += qMax(count, _list->fullRowsCount())
|
|
||||||
// * st::infoMembersList.item.height;
|
|
||||||
return qMax(height(), desired);
|
return qMax(height(), desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +164,7 @@ void Channels::setupList() {
|
||||||
_list = object_ptr<ListWidget>(
|
_list = object_ptr<ListWidget>(
|
||||||
this,
|
this,
|
||||||
_listController.get(),
|
_listController.get(),
|
||||||
st::infoMembersList);
|
st::infoCommonGroupsList);
|
||||||
_list->scrollToRequests(
|
_list->scrollToRequests(
|
||||||
) | rpl::start_with_next([this](Ui::ScrollToRequest request) {
|
) | rpl::start_with_next([this](Ui::ScrollToRequest request) {
|
||||||
auto addmin = (request.ymin < 0 || !_header)
|
auto addmin = (request.ymin < 0 || !_header)
|
||||||
|
|
|
@ -11,12 +11,73 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "auth_session.h"
|
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
|
#include "window/window_peer_menu.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "styles/style_widgets.h"
|
||||||
|
#include "styles/style_info.h"
|
||||||
|
#include "styles/style_boxes.h"
|
||||||
|
|
||||||
namespace Info {
|
namespace Info {
|
||||||
namespace FeedProfile {
|
namespace FeedProfile {
|
||||||
|
|
||||||
|
class ChannelsController::Row final : public PeerListRow {
|
||||||
|
public:
|
||||||
|
Row(not_null<ChannelData*> channel);
|
||||||
|
|
||||||
|
QSize actionSize() const override;
|
||||||
|
QMargins actionMargins() const override;
|
||||||
|
void paintAction(
|
||||||
|
Painter &p,
|
||||||
|
TimeMs ms,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected,
|
||||||
|
bool actionSelected) override;
|
||||||
|
|
||||||
|
not_null<ChannelData*> channel() const {
|
||||||
|
return peer()->asChannel();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
ChannelsController::Row::Row(not_null<ChannelData*> channel)
|
||||||
|
: PeerListRow(channel) {
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize ChannelsController::Row::actionSize() const {
|
||||||
|
return QRect(
|
||||||
|
QPoint(),
|
||||||
|
st::smallCloseIcon.size()).marginsAdded(
|
||||||
|
st::infoFeedLeaveIconMargins).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QMargins ChannelsController::Row::actionMargins() const {
|
||||||
|
return QMargins(
|
||||||
|
0,
|
||||||
|
(st::infoCommonGroupsList.item.height - actionSize().height()) / 2,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChannelsController::Row::paintAction(
|
||||||
|
Painter &p,
|
||||||
|
TimeMs ms,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected,
|
||||||
|
bool actionSelected) {
|
||||||
|
if (selected) {
|
||||||
|
x += st::infoFeedLeaveIconMargins.left();
|
||||||
|
y += st::infoFeedLeaveIconMargins.top();
|
||||||
|
(actionSelected
|
||||||
|
? st::smallCloseIconOver
|
||||||
|
: st::smallCloseIcon).paint(p, x, y, outerWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ChannelsController::ChannelsController(not_null<Controller*> controller)
|
ChannelsController::ChannelsController(not_null<Controller*> controller)
|
||||||
: PeerListController()
|
: PeerListController()
|
||||||
, _controller(controller)
|
, _controller(controller)
|
||||||
|
@ -24,16 +85,16 @@ ChannelsController::ChannelsController(not_null<Controller*> controller)
|
||||||
_controller->setSearchEnabledByContent(false);
|
_controller->setSearchEnabledByContent(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> ChannelsController::createRow(
|
auto ChannelsController::createRow(not_null<ChannelData*> channel)
|
||||||
not_null<PeerData*> peer) {
|
-> std::unique_ptr<Row> {
|
||||||
auto result = std::make_unique<PeerListRow>(peer);
|
auto result = std::make_unique<Row>(channel);
|
||||||
result->setCustomStatus(QString());
|
result->setCustomStatus(QString());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> ChannelsController::createRestoredRow(
|
std::unique_ptr<PeerListRow> ChannelsController::createRestoredRow(
|
||||||
not_null<PeerData*> peer) {
|
not_null<PeerData*> peer) {
|
||||||
return createRow(peer);
|
return createRow(peer->asChannel());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelsController::prepare() {
|
void ChannelsController::prepare() {
|
||||||
|
@ -43,10 +104,7 @@ void ChannelsController::prepare() {
|
||||||
|
|
||||||
rebuildRows();
|
rebuildRows();
|
||||||
using Flag = Data::FeedUpdateFlag;
|
using Flag = Data::FeedUpdateFlag;
|
||||||
rpl::single(
|
Auth().data().feedUpdated(
|
||||||
Data::FeedUpdate{ _feed, Flag::Channels }
|
|
||||||
) | rpl::then(
|
|
||||||
Auth().data().feedUpdated()
|
|
||||||
) | rpl::filter([=](const Data::FeedUpdate &update) {
|
) | rpl::filter([=](const Data::FeedUpdate &update) {
|
||||||
return (update.feed == _feed) && (update.flag == Flag::Channels);
|
return (update.feed == _feed) && (update.flag == Flag::Channels);
|
||||||
}) | rpl::filter([=] {
|
}) | rpl::filter([=] {
|
||||||
|
@ -75,10 +133,11 @@ void ChannelsController::rebuildRows() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto history : channels) {
|
for (const auto history : channels) {
|
||||||
if (auto row = createRow(history->peer)) {
|
if (auto row = createRow(history->peer->asChannel())) {
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
delegate()->peerListRefreshRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PeerListState> ChannelsController::saveState() const {
|
std::unique_ptr<PeerListState> ChannelsController::saveState() const {
|
||||||
|
@ -106,5 +165,9 @@ void ChannelsController::rowClicked(not_null<PeerListRow*> row) {
|
||||||
Window::SectionShow::Way::Forward);
|
Window::SectionShow::Way::Forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChannelsController::rowActionClicked(not_null<PeerListRow*> row) {
|
||||||
|
Window::DeleteAndLeaveHandler(row->peer())();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace FeedProfile
|
} // namespace FeedProfile
|
||||||
} // namespace Info
|
} // namespace Info
|
||||||
|
|
|
@ -27,6 +27,7 @@ public:
|
||||||
|
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
void rowClicked(not_null<PeerListRow*> row) override;
|
void rowClicked(not_null<PeerListRow*> row) override;
|
||||||
|
void rowActionClicked(not_null<PeerListRow*> row) override;
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> createRestoredRow(
|
std::unique_ptr<PeerListRow> createRestoredRow(
|
||||||
not_null<PeerData*> peer) override;
|
not_null<PeerData*> peer) override;
|
||||||
|
@ -35,12 +36,13 @@ public:
|
||||||
void restoreState(std::unique_ptr<PeerListState> state) override;
|
void restoreState(std::unique_ptr<PeerListState> state) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class Row;
|
||||||
struct SavedState : SavedStateBase {
|
struct SavedState : SavedStateBase {
|
||||||
rpl::lifetime lifetime;
|
rpl::lifetime lifetime;
|
||||||
};
|
};
|
||||||
|
|
||||||
void rebuildRows();
|
void rebuildRows();
|
||||||
std::unique_ptr<PeerListRow> createRow(not_null<PeerData*> peer);
|
std::unique_ptr<Row> createRow(not_null<ChannelData*> channel);
|
||||||
|
|
||||||
const not_null<Controller*> _controller;
|
const not_null<Controller*> _controller;
|
||||||
not_null<Data::Feed*> _feed;
|
not_null<Data::Feed*> _feed;
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "info/feed/info_feed_channels_widget.h"
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
|
@ -40,26 +40,26 @@ object_ptr<Ui::RpWidget> InnerWidget::setupContent(
|
||||||
_cover = result->add(object_ptr<Cover>(
|
_cover = result->add(object_ptr<Cover>(
|
||||||
result,
|
result,
|
||||||
_controller));
|
_controller));
|
||||||
//auto details = Profile::SetupFeedDetails(_controller, parent, _feed);
|
auto details = Profile::SetupFeedDetails(_controller, parent, _feed);
|
||||||
//result->add(std::move(details));
|
result->add(std::move(details));
|
||||||
//result->add(object_ptr<BoxContentDivider>(result));
|
result->add(object_ptr<BoxContentDivider>(result));
|
||||||
|
|
||||||
//_channels = result->add(object_ptr<Channels>(
|
_channels = result->add(object_ptr<Channels>(
|
||||||
// result,
|
result,
|
||||||
// _controller)
|
_controller)
|
||||||
//);
|
);
|
||||||
//_channels->scrollToRequests(
|
_channels->scrollToRequests(
|
||||||
//) | rpl::start_with_next([this](Ui::ScrollToRequest request) {
|
) | rpl::start_with_next([this](Ui::ScrollToRequest request) {
|
||||||
// auto min = (request.ymin < 0)
|
auto min = (request.ymin < 0)
|
||||||
// ? request.ymin
|
? request.ymin
|
||||||
// : mapFromGlobal(_channels->mapToGlobal({ 0, request.ymin })).y();
|
: mapFromGlobal(_channels->mapToGlobal({ 0, request.ymin })).y();
|
||||||
// auto max = (request.ymin < 0)
|
auto max = (request.ymin < 0)
|
||||||
// ? mapFromGlobal(_channels->mapToGlobal({ 0, 0 })).y()
|
? mapFromGlobal(_channels->mapToGlobal({ 0, 0 })).y()
|
||||||
// : (request.ymax < 0)
|
: (request.ymax < 0)
|
||||||
// ? request.ymax
|
? request.ymax
|
||||||
// : mapFromGlobal(_channels->mapToGlobal({ 0, request.ymax })).y();
|
: mapFromGlobal(_channels->mapToGlobal({ 0, request.ymax })).y();
|
||||||
// _scrollToRequests.fire({ min, max });
|
_scrollToRequests.fire({ min, max });
|
||||||
//}, _channels->lifetime());
|
}, _channels->lifetime());
|
||||||
|
|
||||||
return std::move(result);
|
return std::move(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -691,3 +691,5 @@ topBarFeedInfoButton: FeedUserpicButton(defaultFeedUserpicButton) {
|
||||||
photoSize: 20px;
|
photoSize: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
infoFeedLeaveIconMargins: margins(10px, 12px, 20px, 10px);
|
||||||
|
|
|
@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include <rpl/flatten_latest.h>
|
#include <rpl/flatten_latest.h>
|
||||||
#include <rpl/combine.h>
|
#include <rpl/combine.h>
|
||||||
#include "data/data_peer_values.h"
|
#include "data/data_peer_values.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "data/data_feed.h"
|
||||||
#include "ui/wrap/vertical_layout.h"
|
#include "ui/wrap/vertical_layout.h"
|
||||||
#include "ui/wrap/padding_wrap.h"
|
#include "ui/wrap/padding_wrap.h"
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
|
@ -580,19 +582,11 @@ void ActionsFiller::addBlockAction(not_null<UserData*> user) {
|
||||||
|
|
||||||
void ActionsFiller::addLeaveChannelAction(
|
void ActionsFiller::addLeaveChannelAction(
|
||||||
not_null<ChannelData*> channel) {
|
not_null<ChannelData*> channel) {
|
||||||
auto callback = [=] {
|
|
||||||
auto text = lang(channel->isMegagroup()
|
|
||||||
? lng_sure_leave_group
|
|
||||||
: lng_sure_leave_channel);
|
|
||||||
Ui::show(Box<ConfirmBox>(text, lang(lng_box_leave), [=] {
|
|
||||||
Auth().api().leaveChannel(channel);
|
|
||||||
}), LayerOption::KeepOther);
|
|
||||||
};
|
|
||||||
AddActionButton(
|
AddActionButton(
|
||||||
_wrap,
|
_wrap,
|
||||||
Lang::Viewer(lng_profile_leave_channel),
|
Lang::Viewer(lng_profile_leave_channel),
|
||||||
AmInChannelValue(channel),
|
AmInChannelValue(channel),
|
||||||
std::move(callback));
|
Window::DeleteAndLeaveHandler(channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionsFiller::addJoinChannelAction(
|
void ActionsFiller::addJoinChannelAction(
|
||||||
|
@ -700,15 +694,20 @@ object_ptr<Ui::RpWidget> FeedDetailsFiller::fill() {
|
||||||
}
|
}
|
||||||
|
|
||||||
object_ptr<Ui::RpWidget> FeedDetailsFiller::setupDefaultToggle() {
|
object_ptr<Ui::RpWidget> FeedDetailsFiller::setupDefaultToggle() {
|
||||||
const auto feed = _feed;
|
using namespace rpl::mappers;
|
||||||
|
const auto feedId = _feed->id();
|
||||||
auto result = object_ptr<Button>(
|
auto result = object_ptr<Button>(
|
||||||
_wrap,
|
_wrap,
|
||||||
Lang::Viewer(lng_info_feed_is_default),
|
Lang::Viewer(lng_info_feed_is_default),
|
||||||
st::infoNotificationsButton);
|
st::infoNotificationsButton);
|
||||||
result->toggleOn(
|
result->toggleOn(
|
||||||
rpl::single(false)// #TODO default
|
Auth().data().defaultFeedIdValue(
|
||||||
|
) | rpl::map(_1 == feedId)
|
||||||
)->addClickHandler([=] {
|
)->addClickHandler([=] {
|
||||||
|
const auto makeDefault = (Auth().data().defaultFeedId() != feedId);
|
||||||
|
const auto defaultFeedId = makeDefault ? feedId : 0;
|
||||||
|
Auth().data().setDefaultFeedId(defaultFeedId);
|
||||||
|
Auth().api().saveDefaultFeedId(feedId, makeDefault);
|
||||||
});
|
});
|
||||||
object_ptr<FloatingIcon>(
|
object_ptr<FloatingIcon>(
|
||||||
result,
|
result,
|
||||||
|
|
Loading…
Reference in New Issue