mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-27 07:52:57 +02:00
Add monoforum sender bar divider.
This commit is contained in:
parent
c6d43a802c
commit
43b4499125
27 changed files with 388 additions and 90 deletions
|
@ -6091,6 +6091,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_forum_messages#other" = "{count} messages";
|
||||
"lng_forum_show_topics_list" = "Show Topics List";
|
||||
|
||||
"lng_monoforum_choose_to_reply" = "Choose a message to reply.";
|
||||
|
||||
"lng_request_peer_requirements" = "Requirements";
|
||||
"lng_request_peer_rights" = "You must have these admin rights: {rights}.";
|
||||
"lng_request_peer_rights_and" = "{rights} and {last}";
|
||||
|
|
|
@ -2936,7 +2936,9 @@ bool EditPeerInfoBox::Available(not_null<PeerData*> peer) {
|
|||
|
||||
// canViewAdmins() is removed, because in supergroups it is
|
||||
// always true and in channels it is equal to canViewBanned().
|
||||
|
||||
if (channel->isMonoforum()) {
|
||||
return false;
|
||||
}
|
||||
return false
|
||||
//|| channel->canViewMembers()
|
||||
//|| channel->canViewAdmins()
|
||||
|
|
|
@ -341,12 +341,6 @@ ChannelData *ChannelData::monoforumLink() const {
|
|||
return _monoforumLink;
|
||||
}
|
||||
|
||||
bool ChannelData::requiresMonoforumPeer() const {
|
||||
return isMonoforum()
|
||||
&& _monoforumLink
|
||||
&& (_monoforumLink->amCreator() || _monoforumLink->hasAdminRights());
|
||||
}
|
||||
|
||||
void ChannelData::setMembersCount(int newMembersCount) {
|
||||
if (_membersCount != newMembersCount) {
|
||||
if (isMegagroup()
|
||||
|
|
|
@ -429,7 +429,6 @@ public:
|
|||
|
||||
void setMonoforumLink(ChannelData *link);
|
||||
[[nodiscard]] ChannelData *monoforumLink() const;
|
||||
[[nodiscard]] bool requiresMonoforumPeer() const;
|
||||
|
||||
void ptsInit(int32 pts) {
|
||||
_ptsWaiter.init(pts);
|
||||
|
|
|
@ -190,18 +190,21 @@ struct SendError {
|
|||
struct Args {
|
||||
QString text;
|
||||
int boostsToLift = 0;
|
||||
bool monoforumAdmin = false;
|
||||
bool premiumToLift = false;
|
||||
bool frozen = false;
|
||||
};
|
||||
SendError(Args &&args)
|
||||
: text(std::move(args.text))
|
||||
, boostsToLift(args.boostsToLift)
|
||||
, monoforumAdmin(args.monoforumAdmin)
|
||||
, premiumToLift(args.premiumToLift)
|
||||
, frozen(args.frozen) {
|
||||
}
|
||||
|
||||
QString text;
|
||||
int boostsToLift = 0;
|
||||
bool monoforumAdmin = false;
|
||||
bool premiumToLift = false;
|
||||
bool frozen = false;
|
||||
|
||||
|
@ -210,7 +213,7 @@ struct SendError {
|
|||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return !text.isEmpty();
|
||||
return monoforumAdmin || !text.isEmpty();
|
||||
}
|
||||
[[nodiscard]] bool has_value() const {
|
||||
return !text.isEmpty();
|
||||
|
|
|
@ -65,8 +65,7 @@ MTPInputReplyTo ReplyToForMTP(
|
|||
: replyTo.monoforumPeerId
|
||||
? history->owner().peer(replyTo.monoforumPeerId).get()
|
||||
: history->session().user().get();
|
||||
const auto replyToMonoforumPeer = (history->peer->isChannel()
|
||||
&& history->peer->asChannel()->requiresMonoforumPeer())
|
||||
const auto replyToMonoforumPeer = history->peer->amMonoforumAdmin()
|
||||
? possibleMonoforumPeer
|
||||
: nullptr;
|
||||
const auto external = replyTo.messageId
|
||||
|
@ -98,8 +97,7 @@ MTPInputReplyTo ReplyToForMTP(
|
|||
(replyToMonoforumPeer
|
||||
? replyToMonoforumPeer->input
|
||||
: MTPInputPeer()));
|
||||
} else if (history->peer->isChannel()
|
||||
&& history->peer->asChannel()->requiresMonoforumPeer()
|
||||
} else if (history->peer->amMonoforumAdmin()
|
||||
&& replyTo.monoforumPeerId) {
|
||||
const auto replyToMonoforumPeer = replyTo.monoforumPeerId
|
||||
? history->owner().peer(replyTo.monoforumPeerId)
|
||||
|
|
|
@ -427,10 +427,12 @@ QImage *PeerData::userpicCloudImage(Ui::PeerUserpicView &view) const {
|
|||
void PeerData::paintUserpic(
|
||||
Painter &p,
|
||||
Ui::PeerUserpicView &view,
|
||||
int x,
|
||||
int y,
|
||||
int size,
|
||||
bool forceCircle) const {
|
||||
const PaintUserpicContext &context) const {
|
||||
if (const auto broadcast = monoforumBroadcast()) {
|
||||
broadcast->paintUserpic(p, view, context);
|
||||
return;
|
||||
}
|
||||
const auto size = context.size;
|
||||
const auto cloud = userpicCloudImage(view);
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
Ui::ValidateUserpicCache(
|
||||
|
@ -438,8 +440,8 @@ void PeerData::paintUserpic(
|
|||
cloud,
|
||||
cloud ? nullptr : ensureEmptyUserpic().get(),
|
||||
size * ratio,
|
||||
!forceCircle && (isForum() || isMonoforum()));
|
||||
p.drawImage(QRect(x, y, size, size), view.cached);
|
||||
context.forumLayout);
|
||||
p.drawImage(QRect(context.position, QSize(size, size)), view.cached);
|
||||
}
|
||||
|
||||
void PeerData::loadUserpic() {
|
||||
|
@ -1118,6 +1120,16 @@ const ChannelData *PeerData::asChannelOrMigrated() const {
|
|||
return migrateTo();
|
||||
}
|
||||
|
||||
ChannelData *PeerData::asMonoforum() {
|
||||
const auto channel = asMegagroup();
|
||||
return (channel && channel->isMonoforum()) ? channel : nullptr;
|
||||
}
|
||||
|
||||
const ChannelData *PeerData::asMonoforum() const {
|
||||
const auto channel = asMegagroup();
|
||||
return (channel && channel->isMonoforum()) ? channel : nullptr;
|
||||
}
|
||||
|
||||
ChatData *PeerData::migrateFrom() const {
|
||||
if (const auto megagroup = asMegagroup()) {
|
||||
return megagroup->amIn()
|
||||
|
@ -1150,6 +1162,16 @@ not_null<const PeerData*> PeerData::migrateToOrMe() const {
|
|||
return this;
|
||||
}
|
||||
|
||||
ChannelData *PeerData::monoforumBroadcast() const {
|
||||
const auto monoforum = asMonoforum();
|
||||
return monoforum ? monoforum->monoforumLink() : nullptr;
|
||||
}
|
||||
|
||||
ChannelData *PeerData::broadcastMonoforum() const {
|
||||
const auto broadcast = asBroadcast();
|
||||
return broadcast ? broadcast->monoforumLink() : nullptr;
|
||||
}
|
||||
|
||||
const QString &PeerData::topBarNameText() const {
|
||||
if (const auto to = migrateTo()) {
|
||||
return to->topBarNameText();
|
||||
|
@ -1572,12 +1594,21 @@ bool PeerData::canManageGroupCall() const {
|
|||
return chat->amCreator()
|
||||
|| (chat->adminRights() & ChatAdminRight::ManageCall);
|
||||
} else if (const auto group = asChannel()) {
|
||||
if (group->isMonoforum()) {
|
||||
return false;
|
||||
}
|
||||
return group->amCreator()
|
||||
|| (group->adminRights() & ChatAdminRight::ManageCall);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PeerData::amMonoforumAdmin() const {
|
||||
const auto broadcast = monoforumBroadcast();
|
||||
return broadcast
|
||||
&& (broadcast->amCreator() || broadcast->hasAdminRights());
|
||||
}
|
||||
|
||||
int PeerData::starsPerMessage() const {
|
||||
if (const auto user = asUser()) {
|
||||
return user->starsPerMessage();
|
||||
|
|
|
@ -277,6 +277,7 @@ public:
|
|||
[[nodiscard]] rpl::producer<bool> slowmodeAppliedValue() const;
|
||||
[[nodiscard]] int slowmodeSecondsLeft() const;
|
||||
[[nodiscard]] bool canManageGroupCall() const;
|
||||
[[nodiscard]] bool amMonoforumAdmin() const;
|
||||
|
||||
[[nodiscard]] int starsPerMessage() const;
|
||||
[[nodiscard]] int starsPerMessageChecked() const;
|
||||
|
@ -297,12 +298,20 @@ public:
|
|||
[[nodiscard]] const ChatData *asChatNotMigrated() const;
|
||||
[[nodiscard]] ChannelData *asChannelOrMigrated();
|
||||
[[nodiscard]] const ChannelData *asChannelOrMigrated() const;
|
||||
[[nodiscard]] ChannelData *asMonoforum();
|
||||
[[nodiscard]] const ChannelData *asMonoforum() const;
|
||||
|
||||
[[nodiscard]] ChatData *migrateFrom() const;
|
||||
[[nodiscard]] ChannelData *migrateTo() const;
|
||||
[[nodiscard]] not_null<PeerData*> migrateToOrMe();
|
||||
[[nodiscard]] not_null<const PeerData*> migrateToOrMe() const;
|
||||
|
||||
// isMonoforum() ? monoforumLink() : nullptr
|
||||
[[nodiscard]] ChannelData *monoforumBroadcast() const;
|
||||
|
||||
// isMonoforum() ? nullptr : monoforumLink()
|
||||
[[nodiscard]] ChannelData *broadcastMonoforum() const;
|
||||
|
||||
void updateFull();
|
||||
void updateFullForced();
|
||||
void fullUpdated();
|
||||
|
@ -332,13 +341,29 @@ public:
|
|||
const ImageLocation &location,
|
||||
bool hasVideo);
|
||||
void setUserpicPhoto(const MTPPhoto &data);
|
||||
|
||||
struct PaintUserpicContext {
|
||||
QPoint position;
|
||||
int size = 0;
|
||||
bool forumLayout = false;
|
||||
};
|
||||
void paintUserpic(
|
||||
Painter &p,
|
||||
Ui::PeerUserpicView &view,
|
||||
const PaintUserpicContext &context) const;
|
||||
void paintUserpic(
|
||||
Painter &p,
|
||||
Ui::PeerUserpicView &view,
|
||||
int x,
|
||||
int y,
|
||||
int size,
|
||||
bool forceCircle = false) const;
|
||||
bool forceCircle = false) const {
|
||||
paintUserpic(p, view, {
|
||||
.position = { x, y },
|
||||
.size = size,
|
||||
.forumLayout = !forceCircle && (isForum() || isMonoforum()),
|
||||
});
|
||||
}
|
||||
void paintUserpicLeft(
|
||||
Painter &p,
|
||||
Ui::PeerUserpicView &view,
|
||||
|
|
|
@ -4657,6 +4657,10 @@ void Session::refreshChatListEntry(Dialogs::Key key) {
|
|||
if (const auto forum = history->peer->forum()) {
|
||||
forum->preloadTopics();
|
||||
}
|
||||
if (history->peer->isMonoforum()
|
||||
&& !history->peer->monoforumBroadcast()) {
|
||||
history->peer->updateFull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -941,7 +941,7 @@ void Widget::chosenRow(const ChosenRow &row) {
|
|||
}
|
||||
return;
|
||||
} else if (history
|
||||
&& history->isMonoforum()
|
||||
&& history->peer->amMonoforumAdmin()
|
||||
&& !row.message.fullId
|
||||
&& !controller()->adaptive().isOneColumn()) {
|
||||
const auto monoforum = history->peer->monoforum();
|
||||
|
|
|
@ -2789,7 +2789,10 @@ bool History::shouldBeInChatList() const {
|
|||
} else if (isPinnedDialog(FilterId())) {
|
||||
return true;
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
if (!channel->amIn()) {
|
||||
if (channel->isMonoforum()) {
|
||||
return !lastMessageKnown()
|
||||
|| (lastMessage() != nullptr);
|
||||
} else if (!channel->amIn()) {
|
||||
return isTopPromoted();
|
||||
}
|
||||
} else if (const auto chat = peer->asChat()) {
|
||||
|
|
|
@ -3770,8 +3770,7 @@ void HistoryItem::createComponents(CreateConfig &&config) {
|
|||
} else if (config.inlineMarkup) {
|
||||
mask |= HistoryMessageReplyMarkup::Bit();
|
||||
}
|
||||
const auto requiresMonoforumPeer = _history->peer->isChannel()
|
||||
&& _history->peer->asChannel()->requiresMonoforumPeer();
|
||||
const auto requiresMonoforumPeer = _history->peer->amMonoforumAdmin();
|
||||
if (_history->peer->isSelf()
|
||||
|| config.savedSublistPeer
|
||||
|| requiresMonoforumPeer) {
|
||||
|
|
|
@ -57,7 +57,7 @@ struct BotKeyboardButton;
|
|||
extern const char kOptionFastButtonsMode[];
|
||||
[[nodiscard]] bool FastButtonsMode();
|
||||
|
||||
struct HistoryMessageVia : public RuntimeComponent<HistoryMessageVia, HistoryItem> {
|
||||
struct HistoryMessageVia : RuntimeComponent<HistoryMessageVia, HistoryItem> {
|
||||
void create(not_null<Data::Session*> owner, UserId userId);
|
||||
void resize(int32 availw) const;
|
||||
|
||||
|
@ -68,7 +68,8 @@ struct HistoryMessageVia : public RuntimeComponent<HistoryMessageVia, HistoryIte
|
|||
ClickHandlerPtr link;
|
||||
};
|
||||
|
||||
struct HistoryMessageViews : public RuntimeComponent<HistoryMessageViews, HistoryItem> {
|
||||
struct HistoryMessageViews
|
||||
: RuntimeComponent<HistoryMessageViews, HistoryItem> {
|
||||
static constexpr auto kMaxRecentRepliers = 3;
|
||||
|
||||
struct Part {
|
||||
|
@ -87,13 +88,15 @@ struct HistoryMessageViews : public RuntimeComponent<HistoryMessageViews, Histor
|
|||
int forwardsCount = 0;
|
||||
};
|
||||
|
||||
struct HistoryMessageSigned : public RuntimeComponent<HistoryMessageSigned, HistoryItem> {
|
||||
struct HistoryMessageSigned
|
||||
: RuntimeComponent<HistoryMessageSigned, HistoryItem> {
|
||||
QString author;
|
||||
UserData *viaBusinessBot = nullptr;
|
||||
bool isAnonymousRank = false;
|
||||
};
|
||||
|
||||
struct HistoryMessageEdited : public RuntimeComponent<HistoryMessageEdited, HistoryItem> {
|
||||
struct HistoryMessageEdited
|
||||
: RuntimeComponent<HistoryMessageEdited, HistoryItem> {
|
||||
TimeId date = 0;
|
||||
};
|
||||
|
||||
|
@ -134,7 +137,8 @@ private:
|
|||
|
||||
};
|
||||
|
||||
struct HistoryMessageForwarded : public RuntimeComponent<HistoryMessageForwarded, HistoryItem> {
|
||||
struct HistoryMessageForwarded
|
||||
: RuntimeComponent<HistoryMessageForwarded, HistoryItem> {
|
||||
void create(
|
||||
const HistoryMessageVia *via,
|
||||
not_null<const HistoryItem*> item) const;
|
||||
|
@ -162,12 +166,14 @@ struct HistoryMessageForwarded : public RuntimeComponent<HistoryMessageForwarded
|
|||
bool story = false;
|
||||
};
|
||||
|
||||
struct HistoryMessageSavedMediaData : public RuntimeComponent<HistoryMessageSavedMediaData, HistoryItem> {
|
||||
struct HistoryMessageSavedMediaData
|
||||
: RuntimeComponent<HistoryMessageSavedMediaData, HistoryItem> {
|
||||
TextWithEntities text;
|
||||
std::unique_ptr<Data::Media> media;
|
||||
};
|
||||
|
||||
struct HistoryMessageSaved : public RuntimeComponent<HistoryMessageSaved, HistoryItem> {
|
||||
struct HistoryMessageSaved
|
||||
: RuntimeComponent<HistoryMessageSaved, HistoryItem> {
|
||||
Data::SavedSublist *sublist = nullptr;
|
||||
};
|
||||
|
||||
|
@ -274,7 +280,7 @@ struct ReplyFields {
|
|||
const MTPInputReplyTo &reply);
|
||||
|
||||
struct HistoryMessageReply
|
||||
: public RuntimeComponent<HistoryMessageReply, HistoryItem> {
|
||||
: RuntimeComponent<HistoryMessageReply, HistoryItem> {
|
||||
HistoryMessageReply();
|
||||
HistoryMessageReply(const HistoryMessageReply &other) = delete;
|
||||
HistoryMessageReply(HistoryMessageReply &&other) = delete;
|
||||
|
@ -358,7 +364,7 @@ private:
|
|||
};
|
||||
|
||||
struct HistoryMessageTranslation
|
||||
: public RuntimeComponent<HistoryMessageTranslation, HistoryItem> {
|
||||
: RuntimeComponent<HistoryMessageTranslation, HistoryItem> {
|
||||
TextWithEntities text;
|
||||
LanguageId to;
|
||||
bool requested = false;
|
||||
|
@ -367,7 +373,7 @@ struct HistoryMessageTranslation
|
|||
};
|
||||
|
||||
struct HistoryMessageReplyMarkup
|
||||
: public RuntimeComponent<HistoryMessageReplyMarkup, HistoryItem> {
|
||||
: RuntimeComponent<HistoryMessageReplyMarkup, HistoryItem> {
|
||||
using Button = HistoryMessageMarkupButton;
|
||||
|
||||
void createForwarded(const HistoryMessageReplyMarkup &original);
|
||||
|
@ -565,7 +571,7 @@ private:
|
|||
|
||||
// Special type of Component for the channel actions log.
|
||||
struct HistoryMessageLogEntryOriginal
|
||||
: public RuntimeComponent<HistoryMessageLogEntryOriginal, HistoryItem> {
|
||||
: RuntimeComponent<HistoryMessageLogEntryOriginal, HistoryItem> {
|
||||
HistoryMessageLogEntryOriginal();
|
||||
HistoryMessageLogEntryOriginal(HistoryMessageLogEntryOriginal &&other);
|
||||
HistoryMessageLogEntryOriginal &operator=(HistoryMessageLogEntryOriginal &&other);
|
||||
|
@ -597,19 +603,19 @@ struct MessageFactcheck {
|
|||
const tl::conditional<MTPFactCheck> &factcheck);
|
||||
|
||||
struct HistoryMessageFactcheck
|
||||
: public RuntimeComponent<HistoryMessageFactcheck, HistoryItem> {
|
||||
: RuntimeComponent<HistoryMessageFactcheck, HistoryItem> {
|
||||
MessageFactcheck data;
|
||||
WebPageData *page = nullptr;
|
||||
bool requested = false;
|
||||
};
|
||||
|
||||
struct HistoryMessageRestrictions
|
||||
: public RuntimeComponent<HistoryMessageRestrictions, HistoryItem> {
|
||||
: RuntimeComponent<HistoryMessageRestrictions, HistoryItem> {
|
||||
std::vector<Data::UnavailableReason> reasons;
|
||||
};
|
||||
|
||||
struct HistoryServiceData
|
||||
: public RuntimeComponent<HistoryServiceData, HistoryItem> {
|
||||
: RuntimeComponent<HistoryServiceData, HistoryItem> {
|
||||
std::vector<ClickHandlerPtr> textLinks;
|
||||
};
|
||||
|
||||
|
@ -625,13 +631,13 @@ struct HistoryServiceDependentData {
|
|||
};
|
||||
|
||||
struct HistoryServicePinned
|
||||
: public RuntimeComponent<HistoryServicePinned, HistoryItem>
|
||||
, public HistoryServiceDependentData {
|
||||
: RuntimeComponent<HistoryServicePinned, HistoryItem>
|
||||
, HistoryServiceDependentData {
|
||||
};
|
||||
|
||||
struct HistoryServiceTopicInfo
|
||||
: public RuntimeComponent<HistoryServiceTopicInfo, HistoryItem>
|
||||
, public HistoryServiceDependentData {
|
||||
: RuntimeComponent<HistoryServiceTopicInfo, HistoryItem>
|
||||
, HistoryServiceDependentData {
|
||||
QString title;
|
||||
DocumentId iconId = 0;
|
||||
bool closed = false;
|
||||
|
@ -652,14 +658,14 @@ struct HistoryServiceTopicInfo
|
|||
};
|
||||
|
||||
struct HistoryServiceGameScore
|
||||
: public RuntimeComponent<HistoryServiceGameScore, HistoryItem>
|
||||
, public HistoryServiceDependentData {
|
||||
: RuntimeComponent<HistoryServiceGameScore, HistoryItem>
|
||||
, HistoryServiceDependentData {
|
||||
int score = 0;
|
||||
};
|
||||
|
||||
struct HistoryServicePayment
|
||||
: public RuntimeComponent<HistoryServicePayment, HistoryItem>
|
||||
, public HistoryServiceDependentData {
|
||||
: RuntimeComponent<HistoryServicePayment, HistoryItem>
|
||||
, HistoryServiceDependentData {
|
||||
QString slug;
|
||||
TextWithEntities amount;
|
||||
ClickHandlerPtr invoiceLink;
|
||||
|
@ -669,22 +675,22 @@ struct HistoryServicePayment
|
|||
};
|
||||
|
||||
struct HistoryServiceSameBackground
|
||||
: public RuntimeComponent<HistoryServiceSameBackground, HistoryItem>
|
||||
, public HistoryServiceDependentData {
|
||||
: RuntimeComponent<HistoryServiceSameBackground, HistoryItem>
|
||||
, HistoryServiceDependentData {
|
||||
};
|
||||
|
||||
struct HistoryServiceGiveawayResults
|
||||
: public RuntimeComponent<HistoryServiceGiveawayResults, HistoryItem>
|
||||
, public HistoryServiceDependentData {
|
||||
: RuntimeComponent<HistoryServiceGiveawayResults, HistoryItem>
|
||||
, HistoryServiceDependentData {
|
||||
};
|
||||
|
||||
struct HistoryServiceCustomLink
|
||||
: public RuntimeComponent<HistoryServiceCustomLink, HistoryItem> {
|
||||
: RuntimeComponent<HistoryServiceCustomLink, HistoryItem> {
|
||||
ClickHandlerPtr link;
|
||||
};
|
||||
|
||||
struct HistoryServicePaymentRefund
|
||||
: public RuntimeComponent<HistoryServicePaymentRefund, HistoryItem> {
|
||||
: RuntimeComponent<HistoryServicePaymentRefund, HistoryItem> {
|
||||
ClickHandlerPtr link;
|
||||
PeerData *peer = nullptr;
|
||||
QString transactionId;
|
||||
|
@ -707,7 +713,7 @@ struct TimeToLiveSingleView {
|
|||
};
|
||||
|
||||
struct HistoryServiceSelfDestruct
|
||||
: public RuntimeComponent<HistoryServiceSelfDestruct, HistoryItem> {
|
||||
: RuntimeComponent<HistoryServiceSelfDestruct, HistoryItem> {
|
||||
using Type = HistorySelfDestructType;
|
||||
|
||||
Type type = Type::Photo;
|
||||
|
@ -716,24 +722,25 @@ struct HistoryServiceSelfDestruct
|
|||
};
|
||||
|
||||
struct HistoryServiceOngoingCall
|
||||
: public RuntimeComponent<HistoryServiceOngoingCall, HistoryItem> {
|
||||
: RuntimeComponent<HistoryServiceOngoingCall, HistoryItem> {
|
||||
CallId id = 0;
|
||||
ClickHandlerPtr link;
|
||||
rpl::lifetime lifetime;
|
||||
};
|
||||
|
||||
struct HistoryServiceChatThemeChange
|
||||
: public RuntimeComponent<HistoryServiceChatThemeChange, HistoryItem> {
|
||||
: RuntimeComponent<HistoryServiceChatThemeChange, HistoryItem> {
|
||||
ClickHandlerPtr link;
|
||||
};
|
||||
|
||||
struct HistoryServiceTTLChange
|
||||
: public RuntimeComponent<HistoryServiceTTLChange, HistoryItem> {
|
||||
: RuntimeComponent<HistoryServiceTTLChange, HistoryItem> {
|
||||
ClickHandlerPtr link;
|
||||
};
|
||||
|
||||
class FileClickHandler;
|
||||
struct HistoryDocumentThumbed : public RuntimeComponent<HistoryDocumentThumbed, HistoryView::Document> {
|
||||
struct HistoryDocumentThumbed
|
||||
: RuntimeComponent<HistoryDocumentThumbed, HistoryView::Document> {
|
||||
std::shared_ptr<FileClickHandler> linksavel;
|
||||
std::shared_ptr<FileClickHandler> linkopenwithl;
|
||||
std::shared_ptr<FileClickHandler> linkcancell;
|
||||
|
@ -745,13 +752,15 @@ struct HistoryDocumentThumbed : public RuntimeComponent<HistoryDocumentThumbed,
|
|||
mutable bool blurred : 1 = false;
|
||||
};
|
||||
|
||||
struct HistoryDocumentCaptioned : public RuntimeComponent<HistoryDocumentCaptioned, HistoryView::Document> {
|
||||
struct HistoryDocumentCaptioned
|
||||
: RuntimeComponent<HistoryDocumentCaptioned, HistoryView::Document> {
|
||||
HistoryDocumentCaptioned();
|
||||
|
||||
Ui::Text::String caption;
|
||||
};
|
||||
|
||||
struct HistoryDocumentNamed : public RuntimeComponent<HistoryDocumentNamed, HistoryView::Document> {
|
||||
struct HistoryDocumentNamed
|
||||
: RuntimeComponent<HistoryDocumentNamed, HistoryView::Document> {
|
||||
Ui::Text::String name;
|
||||
};
|
||||
|
||||
|
@ -763,7 +772,8 @@ struct HistoryDocumentVoicePlayback {
|
|||
Ui::Animations::Basic progressAnimation;
|
||||
};
|
||||
|
||||
class HistoryDocumentVoice : public RuntimeComponent<HistoryDocumentVoice, HistoryView::Document> {
|
||||
class HistoryDocumentVoice
|
||||
: public RuntimeComponent<HistoryDocumentVoice, HistoryView::Document> {
|
||||
// We don't use float64 because components should align to pointer even on 32bit systems.
|
||||
static constexpr float64 kFloatToIntMultiplier = 65536.;
|
||||
|
||||
|
|
|
@ -6633,6 +6633,12 @@ int HistoryWidget::countAutomaticScrollTop() {
|
|||
}
|
||||
|
||||
Data::SendError HistoryWidget::computeSendRestriction() const {
|
||||
if (!_canSendMessages && _peer->amMonoforumAdmin()) {
|
||||
return Data::SendError({
|
||||
.text = tr::lng_monoforum_choose_to_reply(tr::now),
|
||||
.monoforumAdmin = true,
|
||||
});
|
||||
}
|
||||
const auto allWithoutPolls = Data::AllSendRestrictions()
|
||||
& ~ChatRestriction::SendPolls;
|
||||
return (_peer && !Data::CanSendAnyOf(_peer, allWithoutPolls))
|
||||
|
@ -8753,10 +8759,17 @@ bool HistoryWidget::updateCanSendMessage() {
|
|||
const auto topic = resolveReplyToTopic();
|
||||
const auto allWithoutPolls = Data::AllSendRestrictions()
|
||||
& ~ChatRestriction::SendPolls;
|
||||
const auto newCanSendMessages = topic
|
||||
const auto onlyReplies = _peer->amMonoforumAdmin();
|
||||
const auto restrictedOnlyReplies = onlyReplies
|
||||
&& (!_replyTo.messageId || _replyTo.messageId.peer != _peer->id);
|
||||
const auto newCanSendMessages = restrictedOnlyReplies
|
||||
? false
|
||||
: topic
|
||||
? Data::CanSendAnyOf(topic, allWithoutPolls)
|
||||
: Data::CanSendAnyOf(_peer, allWithoutPolls);
|
||||
const auto newCanSendTexts = topic
|
||||
const auto newCanSendTexts = restrictedOnlyReplies
|
||||
? false
|
||||
: topic
|
||||
? Data::CanSend(topic, ChatRestriction::SendOther)
|
||||
: Data::CanSend(_peer, ChatRestriction::SendOther);
|
||||
if (_canSendMessages == newCanSendMessages
|
||||
|
|
|
@ -2702,7 +2702,11 @@ QRect ChatWidget::floatPlayerAvailableRect() {
|
|||
}
|
||||
|
||||
Context ChatWidget::listContext() {
|
||||
return _sublist ? Context::SavedSublist : Context::Replies;
|
||||
return !_sublist
|
||||
? Context::Replies
|
||||
: _sublist->parentChat()
|
||||
? Context::Monoforum
|
||||
: Context::SavedSublist;
|
||||
}
|
||||
|
||||
bool ChatWidget::listScrollTo(int top, bool syntetic) {
|
||||
|
@ -2883,9 +2887,7 @@ void ChatWidget::listMarkReadTill(not_null<HistoryItem*> item) {
|
|||
|
||||
void ChatWidget::listMarkContentsRead(
|
||||
const base::flat_set<not_null<HistoryItem*>> &items) {
|
||||
if (!_sublist) {
|
||||
session().api().markContentsRead(items);
|
||||
}
|
||||
}
|
||||
|
||||
MessagesBarData ChatWidget::listMessagesBar(
|
||||
|
|
|
@ -41,6 +41,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/painter.h"
|
||||
#include "ui/rect.h"
|
||||
#include "data/components/sponsored_messages.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_saved_sublist.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_forum.h"
|
||||
#include "data/data_forum_topic.h"
|
||||
|
@ -475,6 +477,83 @@ void DateBadge::paint(
|
|||
ServiceMessagePainter::PaintDate(p, st, text, width, y, w, chatWide);
|
||||
}
|
||||
|
||||
void MonoforumSenderBar::init(
|
||||
not_null<PeerData*> parentChat,
|
||||
not_null<PeerData*> peer) {
|
||||
author = peer;
|
||||
text.setText(st::semiboldTextStyle, peer->name());
|
||||
const auto skip = st::monoforumBarUserpicSkip;
|
||||
const auto userpic = st::msgServicePadding.top()
|
||||
+ st::msgServiceFont->height
|
||||
+ st::msgServicePadding.bottom()
|
||||
- 2 * skip;
|
||||
width = skip + userpic + skip * 2 + text.maxWidth() + st::msgServicePadding.right();
|
||||
}
|
||||
|
||||
int MonoforumSenderBar::height() const {
|
||||
return st::msgServiceMargin.top()
|
||||
+ st::msgServicePadding.top()
|
||||
+ st::msgServiceFont->height
|
||||
+ st::msgServicePadding.bottom()
|
||||
+ st::msgServiceMargin.bottom();
|
||||
}
|
||||
|
||||
void MonoforumSenderBar::paint(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide) const {
|
||||
Expects(author != nullptr);
|
||||
|
||||
int left = st::msgServiceMargin.left();
|
||||
const auto maxwidth = chatWide
|
||||
? std::min(w, WideChatWidth())
|
||||
: w;
|
||||
w = maxwidth - st::msgServiceMargin.left() - st::msgServiceMargin.left();
|
||||
|
||||
const auto use = std::min(w, width);
|
||||
|
||||
left += (w - use) / 2;
|
||||
int h = st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom();
|
||||
ServiceMessagePainter::PaintBubble(
|
||||
p,
|
||||
st->msgServiceBg(),
|
||||
st->serviceBgCornersNormal(),
|
||||
QRect(left, y + st::msgServiceMargin.top(), use, h));
|
||||
|
||||
const auto skip = st::monoforumBarUserpicSkip;
|
||||
{
|
||||
auto pen = st->msgServiceBg()->p;
|
||||
pen.setWidthF(skip);
|
||||
pen.setCapStyle(Qt::RoundCap);
|
||||
pen.setDashPattern({ 2., 2. });
|
||||
p.setPen(pen);
|
||||
const auto top = y + st::msgServiceMargin.top() + (h / 2);
|
||||
p.drawLine(0, top, left, top);
|
||||
p.drawLine(left + use, top, 2 * w, top);
|
||||
}
|
||||
|
||||
const auto userpic = st::msgServicePadding.top()
|
||||
+ st::msgServiceFont->height
|
||||
+ st::msgServicePadding.bottom()
|
||||
- 2 * skip;
|
||||
const auto available = use - (skip + userpic + skip * 2 + st::msgServicePadding.right());
|
||||
|
||||
author->paintUserpic(p, view, left + skip, y + st::msgServiceMargin.top() + skip, userpic);
|
||||
|
||||
p.setFont(st::msgServiceFont);
|
||||
p.setPen(st->msgServiceFg());
|
||||
text.draw(p, {
|
||||
.position = {
|
||||
left + skip + userpic + skip * 2,
|
||||
y + st::msgServiceMargin.top() + st::msgServicePadding.top(),
|
||||
},
|
||||
.availableWidth = available,
|
||||
.elisionLines = 1,
|
||||
});
|
||||
}
|
||||
|
||||
void ServicePreMessage::init(PreparedServiceText string) {
|
||||
text = Ui::Text::String(
|
||||
st::serviceTextStyle,
|
||||
|
@ -1220,6 +1299,7 @@ void Element::validateTextSkipBlock(bool has, int width, int height) {
|
|||
}
|
||||
|
||||
void Element::previousInBlocksChanged() {
|
||||
recountMonoforumSenderBarInBlocks();
|
||||
recountDisplayDateInBlocks();
|
||||
recountAttachToPreviousInBlocks();
|
||||
}
|
||||
|
@ -1255,7 +1335,8 @@ bool Element::computeIsAttachToPrevious(not_null<Element*> previous) {
|
|||
const auto item = data();
|
||||
if (!Has<DateBadge>()
|
||||
&& !Has<UnreadBar>()
|
||||
&& !Has<ServicePreMessage>()) {
|
||||
&& !Has<ServicePreMessage>()
|
||||
&& !Has<MonoforumSenderBar>()) {
|
||||
const auto prev = previous->data();
|
||||
const auto previousMarkup = prev->inlineReplyMarkup();
|
||||
const auto possible = (std::abs(prev->date() - item->date())
|
||||
|
@ -1385,6 +1466,37 @@ void Element::recountAttachToPreviousInBlocks() {
|
|||
setAttachToPrevious(attachToPrevious, previous);
|
||||
}
|
||||
|
||||
void Element::recountMonoforumSenderBarInBlocks() {
|
||||
const auto item = data();
|
||||
const auto sublist = item->savedSublist();
|
||||
const auto parentChat = sublist ? sublist->parentChat() : nullptr;
|
||||
const auto barPeer = [&]() -> PeerData* {
|
||||
if (!parentChat
|
||||
|| isHidden()
|
||||
|| item->isEmpty()
|
||||
|| item->isSponsored()) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto peer = sublist->peer();
|
||||
if (const auto previous = previousDisplayedInBlocks()) {
|
||||
const auto prev = previous->data();
|
||||
if (const auto prevSublist = prev->savedSublist()) {
|
||||
Assert(prevSublist->parentChat() == parentChat);
|
||||
if (prevSublist->peer() == peer) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return peer;
|
||||
}();
|
||||
if (barPeer && !Has<MonoforumSenderBar>()) {
|
||||
AddComponents(MonoforumSenderBar::Bit());
|
||||
Get<MonoforumSenderBar>()->init(parentChat, barPeer);
|
||||
} else if (!barPeer && Has<MonoforumSenderBar>()) {
|
||||
RemoveComponents(MonoforumSenderBar::Bit());
|
||||
}
|
||||
}
|
||||
|
||||
void Element::recountDisplayDateInBlocks() {
|
||||
setDisplayDate([&] {
|
||||
const auto item = data();
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/runtime_composer.h"
|
||||
#include "base/flags.h"
|
||||
#include "base/weak_ptr.h"
|
||||
#include "ui/userpic_view.h"
|
||||
|
||||
class History;
|
||||
class HistoryBlock;
|
||||
|
@ -58,6 +59,7 @@ enum class Context : char {
|
|||
Pinned,
|
||||
AdminLog,
|
||||
ContactPreview,
|
||||
Monoforum,
|
||||
SavedSublist,
|
||||
TTLViewer,
|
||||
ShortcutMessages,
|
||||
|
@ -220,7 +222,7 @@ QString DateTooltipText(not_null<Element*> view);
|
|||
|
||||
// Any HistoryView::Element can have this Component for
|
||||
// displaying the unread messages bar above the message.
|
||||
struct UnreadBar : public RuntimeComponent<UnreadBar, Element> {
|
||||
struct UnreadBar : RuntimeComponent<UnreadBar, Element> {
|
||||
void init(const QString &string);
|
||||
|
||||
static int height();
|
||||
|
@ -241,7 +243,7 @@ struct UnreadBar : public RuntimeComponent<UnreadBar, Element> {
|
|||
|
||||
// Any HistoryView::Element can have this Component for
|
||||
// displaying the day mark above the message.
|
||||
struct DateBadge : public RuntimeComponent<DateBadge, Element> {
|
||||
struct DateBadge : RuntimeComponent<DateBadge, Element> {
|
||||
void init(const QString &date);
|
||||
|
||||
int height() const;
|
||||
|
@ -257,10 +259,27 @@ struct DateBadge : public RuntimeComponent<DateBadge, Element> {
|
|||
|
||||
};
|
||||
|
||||
struct MonoforumSenderBar : RuntimeComponent<MonoforumSenderBar, Element> {
|
||||
void init(not_null<PeerData*> parentChat, not_null<PeerData*> peer);
|
||||
|
||||
int height() const;
|
||||
void paint(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide) const;
|
||||
|
||||
PeerData *author = nullptr;
|
||||
Ui::Text::String text;
|
||||
ClickHandlerPtr link;
|
||||
mutable Ui::PeerUserpicView view;
|
||||
int width = 0;
|
||||
};
|
||||
|
||||
// Any HistoryView::Element can have this Component for
|
||||
// displaying some text in layout of a service message above the message.
|
||||
struct ServicePreMessage
|
||||
: public RuntimeComponent<ServicePreMessage, Element> {
|
||||
struct ServicePreMessage : RuntimeComponent<ServicePreMessage, Element> {
|
||||
void init(PreparedServiceText string);
|
||||
|
||||
int resizeToWidth(int newWidth, bool chatWide);
|
||||
|
@ -281,7 +300,7 @@ struct ServicePreMessage
|
|||
|
||||
};
|
||||
|
||||
struct FakeBotAboutTop : public RuntimeComponent<FakeBotAboutTop, Element> {
|
||||
struct FakeBotAboutTop : RuntimeComponent<FakeBotAboutTop, Element> {
|
||||
void init();
|
||||
|
||||
Ui::Text::String text;
|
||||
|
@ -289,7 +308,7 @@ struct FakeBotAboutTop : public RuntimeComponent<FakeBotAboutTop, Element> {
|
|||
int height = 0;
|
||||
};
|
||||
|
||||
struct PurchasedTag : public RuntimeComponent<PurchasedTag, Element> {
|
||||
struct PurchasedTag : RuntimeComponent<PurchasedTag, Element> {
|
||||
Ui::Text::String text;
|
||||
};
|
||||
|
||||
|
@ -629,14 +648,17 @@ protected:
|
|||
std::unique_ptr<Reactions::InlineList> _reactions;
|
||||
|
||||
private:
|
||||
void recountMonoforumSenderBarInBlocks();
|
||||
|
||||
// This should be called only from previousInBlocksChanged()
|
||||
// to add required bits to the Composer mask
|
||||
// after that always use Has<DateBadge>().
|
||||
void recountDisplayDateInBlocks();
|
||||
|
||||
// This should be called only from previousInBlocksChanged() or when
|
||||
// DateBadge or UnreadBar bit is changed in the Composer mask
|
||||
// then the result should be cached in a client side flag
|
||||
// DateBadge or UnreadBar or MonoforumSenderBar bit
|
||||
// is changed in the Composer mask then the result
|
||||
// should be cached in a client side flag
|
||||
// HistoryView::Element::Flag::AttachedToPrevious.
|
||||
void recountAttachToPreviousInBlocks();
|
||||
|
||||
|
|
|
@ -1088,6 +1088,9 @@ int Message::marginTop() const {
|
|||
if (const auto bar = Get<UnreadBar>()) {
|
||||
result += bar->height();
|
||||
}
|
||||
if (const auto monoforumBar = Get<MonoforumSenderBar>()) {
|
||||
result += monoforumBar->height();
|
||||
}
|
||||
if (const auto service = Get<ServicePreMessage>()) {
|
||||
result += service->height;
|
||||
}
|
||||
|
@ -1146,6 +1149,27 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
|||
}
|
||||
}
|
||||
|
||||
if (const auto monoforumBar = Get<MonoforumSenderBar>()) {
|
||||
auto barh = monoforumBar->height();
|
||||
auto skip = 0;
|
||||
if (const auto date = Get<DateBadge>()) {
|
||||
skip += date->height();
|
||||
}
|
||||
if (const auto bar = Get<UnreadBar>()) {
|
||||
skip += bar->height();
|
||||
}
|
||||
if (context.clip.intersects(QRect(0, skip, width(), barh))) {
|
||||
p.translate(0, skip);
|
||||
monoforumBar->paint(
|
||||
p,
|
||||
context.st,
|
||||
0,
|
||||
width(),
|
||||
delegate()->elementIsChatWide());
|
||||
p.translate(0, -skip);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto service = Get<ServicePreMessage>()) {
|
||||
service->paint(p, context, g, delegate()->elementIsChatWide());
|
||||
}
|
||||
|
@ -2458,6 +2482,8 @@ bool Message::hasFromPhoto() const {
|
|||
switch (context()) {
|
||||
case Context::AdminLog:
|
||||
return true;
|
||||
case Context::Monoforum:
|
||||
return delegate()->elementIsChatWide();
|
||||
case Context::History:
|
||||
case Context::ChatPreview:
|
||||
case Context::TTLViewer:
|
||||
|
@ -3685,6 +3711,8 @@ bool Message::hasFromName() const {
|
|||
switch (context()) {
|
||||
case Context::AdminLog:
|
||||
return true;
|
||||
case Context::Monoforum:
|
||||
return false;
|
||||
case Context::History:
|
||||
case Context::ChatPreview:
|
||||
case Context::TTLViewer:
|
||||
|
@ -3953,6 +3981,8 @@ bool Message::displayFastShare() const {
|
|||
bool Message::displayGoToOriginal() const {
|
||||
if (isPinnedContext()) {
|
||||
return !hasOutLayout();
|
||||
} else if (context() == Context::Monoforum) {
|
||||
return false;
|
||||
}
|
||||
const auto item = data();
|
||||
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
|
||||
|
|
|
@ -35,8 +35,7 @@ class InlineList;
|
|||
} // namespace Reactions
|
||||
|
||||
// Special type of Component for the channel actions log.
|
||||
struct LogEntryOriginal
|
||||
: public RuntimeComponent<LogEntryOriginal, Element> {
|
||||
struct LogEntryOriginal : RuntimeComponent<LogEntryOriginal, Element> {
|
||||
LogEntryOriginal();
|
||||
LogEntryOriginal(LogEntryOriginal &&other);
|
||||
LogEntryOriginal &operator=(LogEntryOriginal &&other);
|
||||
|
@ -45,13 +44,12 @@ struct LogEntryOriginal
|
|||
std::unique_ptr<WebPage> page;
|
||||
};
|
||||
|
||||
struct Factcheck
|
||||
: public RuntimeComponent<Factcheck, Element> {
|
||||
struct Factcheck : RuntimeComponent<Factcheck, Element> {
|
||||
std::unique_ptr<WebPage> page;
|
||||
bool expanded = false;
|
||||
};
|
||||
|
||||
struct PsaTooltipState : public RuntimeComponent<PsaTooltipState, Element> {
|
||||
struct PsaTooltipState : RuntimeComponent<PsaTooltipState, Element> {
|
||||
QString type;
|
||||
mutable ClickHandlerPtr link;
|
||||
mutable Ui::Animations::Simple buttonVisibleAnimation;
|
||||
|
|
|
@ -452,6 +452,9 @@ QSize Service::performCountCurrentSize(int newWidth) {
|
|||
if (const auto bar = Get<UnreadBar>()) {
|
||||
newHeight += bar->height();
|
||||
}
|
||||
if (const auto monoforumBar = Get<MonoforumSenderBar>()) {
|
||||
newHeight += monoforumBar->height();
|
||||
}
|
||||
|
||||
data()->resolveDependent();
|
||||
|
||||
|
@ -525,6 +528,9 @@ int Service::marginTop() const {
|
|||
if (const auto bar = Get<UnreadBar>()) {
|
||||
result += bar->height();
|
||||
}
|
||||
if (const auto monoforumBar = Get<MonoforumSenderBar>()) {
|
||||
result += monoforumBar->height();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -557,6 +563,27 @@ void Service::draw(Painter &p, const PaintContext &context) const {
|
|||
}
|
||||
}
|
||||
|
||||
if (const auto monoforumBar = Get<MonoforumSenderBar>()) {
|
||||
auto barh = monoforumBar->height();
|
||||
auto skip = 0;
|
||||
if (const auto date = Get<DateBadge>()) {
|
||||
skip += date->height();
|
||||
}
|
||||
if (const auto bar = Get<UnreadBar>()) {
|
||||
skip += bar->height();
|
||||
}
|
||||
if (context.clip.intersects(QRect(0, skip, width(), barh))) {
|
||||
p.translate(0, skip);
|
||||
monoforumBar->paint(
|
||||
p,
|
||||
context.st,
|
||||
0,
|
||||
width(),
|
||||
delegate()->elementIsChatWide());
|
||||
p.translate(0, -skip);
|
||||
}
|
||||
}
|
||||
|
||||
if (isHidden()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -492,6 +492,9 @@ void TopBarWidget::paintTopBar(Painter &p) {
|
|||
? history->peer.get()
|
||||
: sublist ? sublist->peer().get()
|
||||
: nullptr;
|
||||
const auto broadcastForMonoforum = history
|
||||
? history->peer->monoforumBroadcast()
|
||||
: nullptr;
|
||||
if (topic && _activeChat.section == Section::Replies) {
|
||||
p.setPen(st::dialogsNameFg);
|
||||
topic->chatListNameText().drawElided(
|
||||
|
@ -515,9 +518,12 @@ void TopBarWidget::paintTopBar(Painter &p) {
|
|||
}
|
||||
} else if (folder
|
||||
|| (peer && (peer->sharedMediaInfo() || peer->isVerifyCodes()))
|
||||
|| broadcastForMonoforum
|
||||
|| (_activeChat.section == Section::Scheduled)
|
||||
|| (_activeChat.section == Section::Pinned)) {
|
||||
auto text = (_activeChat.section == Section::Scheduled)
|
||||
auto text = broadcastForMonoforum
|
||||
? broadcastForMonoforum->name() + u" Messages"_q AssertIsDebug()
|
||||
: (_activeChat.section == Section::Scheduled)
|
||||
? ((peer && peer->isSelf())
|
||||
? tr::lng_reminder_messages(tr::now)
|
||||
: tr::lng_scheduled_messages(tr::now))
|
||||
|
|
|
@ -628,10 +628,13 @@ Cover::Cover(
|
|||
: object_ptr<Ui::UserpicButton>(
|
||||
this,
|
||||
controller,
|
||||
_peer,
|
||||
(_peer->monoforumBroadcast()
|
||||
? _peer->monoforumBroadcast()
|
||||
: _peer),
|
||||
Ui::UserpicButton::Role::OpenPhoto,
|
||||
Ui::UserpicButton::Source::PeerPhoto,
|
||||
_st.photo))
|
||||
_st.photo,
|
||||
_peer->monoforumBroadcast() != nullptr))
|
||||
, _changePersonal((role == Role::Info
|
||||
|| topic
|
||||
|| !_peer->isUser()
|
||||
|
@ -647,6 +650,9 @@ Cover::Cover(
|
|||
, _showLastSeen(this, tr::lng_status_lastseen_when(), _st.showLastSeen)
|
||||
, _refreshStatusTimer([this] { refreshStatusText(); }) {
|
||||
_peer->updateFull();
|
||||
if (const auto broadcast = _peer->monoforumBroadcast()) {
|
||||
broadcast->updateFull();
|
||||
}
|
||||
|
||||
_name->setSelectable(true);
|
||||
_name->setContextCopyText(tr::lng_profile_copy_fullname(tr::now));
|
||||
|
@ -979,6 +985,12 @@ void Cover::refreshStatusText() {
|
|||
chat->count,
|
||||
int(chat->participants.size()));
|
||||
return { .text = ChatStatusText(fullCount, onlineCount, true) };
|
||||
} else if (auto broadcast = _peer->monoforumBroadcast()) {
|
||||
auto result = ChatStatusText(
|
||||
qMax(broadcast->membersCount(), 1),
|
||||
0,
|
||||
false);
|
||||
return TextWithEntities{ .text = result };
|
||||
} else if (auto channel = _peer->asChannel()) {
|
||||
const auto onlineCount = _onlineCount.current();
|
||||
const auto fullCount = qMax(channel->membersCount(), 1);
|
||||
|
|
|
@ -99,8 +99,10 @@ object_ptr<Ui::RpWidget> InnerWidget::setupContent(
|
|||
result->add(std::move(actions));
|
||||
}
|
||||
if (_peer->isChat() || _peer->isMegagroup()) {
|
||||
if (!_peer->isMonoforum()) {
|
||||
setupMembers(result.data());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
struct Info : public RuntimeComponent<Info, LayoutItemBase> {
|
||||
struct Info : RuntimeComponent<Info, LayoutItemBase> {
|
||||
int top = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ msgReplyBarSize: size(2px, 36px);
|
|||
msgReplyBarSkip: 10px;
|
||||
msgServicePadding: margins(12px, 3px, 12px, 4px);
|
||||
msgServiceMargin: margins(10px, 10px, 10px, 2px);
|
||||
monoforumBarUserpicSkip: 2px;
|
||||
|
||||
msgDateSpace: 12px;
|
||||
msgDateDelta: point(2px, 5px);
|
||||
|
|
|
@ -180,12 +180,14 @@ UserpicButton::UserpicButton(
|
|||
not_null<PeerData*> peer,
|
||||
Role role,
|
||||
Source source,
|
||||
const style::UserpicButton &st)
|
||||
const style::UserpicButton &st,
|
||||
bool forceForumShape)
|
||||
: RippleButton(parent, st.changeButton.ripple)
|
||||
, _st(st)
|
||||
, _controller(controller)
|
||||
, _window(&controller->window())
|
||||
, _peer(peer)
|
||||
, _forceForumShape(forceForumShape)
|
||||
, _role(role)
|
||||
, _source(source) {
|
||||
if (_source == Source::Custom) {
|
||||
|
|
|
@ -69,7 +69,8 @@ public:
|
|||
not_null<PeerData*> peer,
|
||||
Role role,
|
||||
Source source,
|
||||
const style::UserpicButton &st);
|
||||
const style::UserpicButton &st,
|
||||
bool forceForumShape = false);
|
||||
UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<PeerData*> peer, // Role::Custom, Source::PeerPhoto
|
||||
|
|
Loading…
Add table
Reference in a new issue