mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Show correct placeholder in require-premium story reply.
This commit is contained in:
parent
3829ed5880
commit
1cfad14437
11 changed files with 300 additions and 51 deletions
|
@ -3618,10 +3618,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_send_non_premium_text" = "Subscribe to **Premium**\n to message {user}.";
|
"lng_send_non_premium_text" = "Subscribe to **Premium**\n to message {user}.";
|
||||||
"lng_send_non_premium_go" = "Go Premium";
|
"lng_send_non_premium_go" = "Go Premium";
|
||||||
"lng_send_non_premium_story" = "Replies restricted";
|
"lng_send_non_premium_story" = "Replies restricted";
|
||||||
"lng_send_non_premium_unlock" = "Unlock";
|
"lng_send_non_premium_unlock" = "unlock";
|
||||||
"lng_send_non_premium_story_toast" = "You need a **Premium** subscription to reply to **{user}'s** stories.";
|
"lng_send_non_premium_message_toast" = "**{user}** only accepts messages from contacts and {link} subscribers.";
|
||||||
"lng_send_non_premium_message_toast" = "**{user}** only accepts messages from contacts and **Premium** users.";
|
"lng_send_non_premium_message_toast_link" = "Telegram Premium";
|
||||||
"lng_send_non_premium_toast_button" = "View";
|
|
||||||
|
|
||||||
"lng_exceptions_list_title" = "Exceptions";
|
"lng_exceptions_list_title" = "Exceptions";
|
||||||
"lng_removed_list_title" = "Removed users";
|
"lng_removed_list_title" = "Removed users";
|
||||||
|
|
|
@ -208,6 +208,8 @@ ComposeControls {
|
||||||
files: ComposeFiles;
|
files: ComposeFiles;
|
||||||
premium: PremiumLimits;
|
premium: PremiumLimits;
|
||||||
boxField: InputField;
|
boxField: InputField;
|
||||||
|
restrictionLabel: FlatLabel;
|
||||||
|
premiumRequired: ComposePremiumRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReportBox {
|
ReportBox {
|
||||||
|
@ -1218,6 +1220,11 @@ defaultComposeFiles: ComposeFiles {
|
||||||
nameFg: historyFileNameInFg;
|
nameFg: historyFileNameInFg;
|
||||||
statusFg: mediaInFg;
|
statusFg: mediaInFg;
|
||||||
}
|
}
|
||||||
|
defaultRestrictionLabel: FlatLabel(defaultFlatLabel) {
|
||||||
|
minWidth: 12px;
|
||||||
|
textFg: placeholderFg;
|
||||||
|
align: align(top);
|
||||||
|
}
|
||||||
defaultComposeControls: ComposeControls {
|
defaultComposeControls: ComposeControls {
|
||||||
bg: historyComposeAreaBg;
|
bg: historyComposeAreaBg;
|
||||||
radius: 0px;
|
radius: 0px;
|
||||||
|
@ -1234,6 +1241,7 @@ defaultComposeControls: ComposeControls {
|
||||||
files: defaultComposeFiles;
|
files: defaultComposeFiles;
|
||||||
premium: defaultPremiumLimits;
|
premium: defaultPremiumLimits;
|
||||||
boxField: defaultInputField;
|
boxField: defaultInputField;
|
||||||
|
restrictionLabel: defaultRestrictionLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
moreChatsBarHeight: 48px;
|
moreChatsBarHeight: 48px;
|
||||||
|
|
|
@ -34,6 +34,31 @@ struct SendActionUpdate {
|
||||||
bool cancel = false;
|
bool cancel = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class WriteRestrictionType {
|
||||||
|
None,
|
||||||
|
Rights,
|
||||||
|
PremiumRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WriteRestriction {
|
||||||
|
using Type = WriteRestrictionType;
|
||||||
|
|
||||||
|
QString text;
|
||||||
|
QString button;
|
||||||
|
Type type = Type::None;
|
||||||
|
|
||||||
|
[[nodiscard]] bool empty() const {
|
||||||
|
return (type == Type::None);
|
||||||
|
}
|
||||||
|
explicit operator bool() const {
|
||||||
|
return !empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline bool operator==(
|
||||||
|
const WriteRestriction &a,
|
||||||
|
const WriteRestriction &b) = default;
|
||||||
|
};
|
||||||
|
|
||||||
struct SetHistoryArgs {
|
struct SetHistoryArgs {
|
||||||
required<History*> history;
|
required<History*> history;
|
||||||
MsgId topicRootId = 0;
|
MsgId topicRootId = 0;
|
||||||
|
@ -42,7 +67,7 @@ struct SetHistoryArgs {
|
||||||
rpl::producer<int> slowmodeSecondsLeft;
|
rpl::producer<int> slowmodeSecondsLeft;
|
||||||
rpl::producer<bool> sendDisabledBySlowmode;
|
rpl::producer<bool> sendDisabledBySlowmode;
|
||||||
rpl::producer<bool> liked;
|
rpl::producer<bool> liked;
|
||||||
rpl::producer<std::optional<QString>> writeRestriction;
|
rpl::producer<WriteRestriction> writeRestriction;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ReplyNextRequest {
|
struct ReplyNextRequest {
|
||||||
|
|
|
@ -62,7 +62,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "main/session/send_as_peers.h"
|
#include "main/session/send_as_peers.h"
|
||||||
#include "media/audio/media_audio_capture.h"
|
#include "media/audio/media_audio_capture.h"
|
||||||
#include "media/audio/media_audio.h"
|
#include "media/audio/media_audio.h"
|
||||||
|
#include "settings/settings_premium.h"
|
||||||
#include "ui/text/text_options.h"
|
#include "ui/text/text_options.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/ui_utility.h"
|
#include "ui/ui_utility.h"
|
||||||
#include "ui/widgets/fields/input_field.h"
|
#include "ui/widgets/fields/input_field.h"
|
||||||
#include "ui/widgets/dropdown_menu.h"
|
#include "ui/widgets/dropdown_menu.h"
|
||||||
|
@ -800,7 +802,6 @@ ComposeControls::ComposeControls(
|
||||||
: not_null(_ownedSelector.get()))
|
: not_null(_ownedSelector.get()))
|
||||||
, _mode(descriptor.mode)
|
, _mode(descriptor.mode)
|
||||||
, _wrap(std::make_unique<Ui::RpWidget>(parent))
|
, _wrap(std::make_unique<Ui::RpWidget>(parent))
|
||||||
, _writeRestricted(std::make_unique<Ui::RpWidget>(parent))
|
|
||||||
, _send(std::make_shared<Ui::SendButton>(_wrap.get(), _st.send))
|
, _send(std::make_shared<Ui::SendButton>(_wrap.get(), _st.send))
|
||||||
, _like(_features.likes
|
, _like(_features.likes
|
||||||
? Ui::CreateChild<Ui::IconButton>(_wrap.get(), _st.like)
|
? Ui::CreateChild<Ui::IconButton>(_wrap.get(), _st.like)
|
||||||
|
@ -878,7 +879,7 @@ void ComposeControls::setHistory(SetHistoryArgs &&args) {
|
||||||
_sendDisabledBySlowmode = rpl::single(false)
|
_sendDisabledBySlowmode = rpl::single(false)
|
||||||
| rpl::then(std::move(args.sendDisabledBySlowmode));
|
| rpl::then(std::move(args.sendDisabledBySlowmode));
|
||||||
_liked = args.liked ? std::move(args.liked) : rpl::single(false);
|
_liked = args.liked ? std::move(args.liked) : rpl::single(false);
|
||||||
_writeRestriction = rpl::single(std::optional<QString>())
|
_writeRestriction = rpl::single(Controls::WriteRestriction())
|
||||||
| rpl::then(std::move(args.writeRestriction));
|
| rpl::then(std::move(args.writeRestriction));
|
||||||
const auto history = *args.history;
|
const auto history = *args.history;
|
||||||
if (_history == history) {
|
if (_history == history) {
|
||||||
|
@ -892,6 +893,7 @@ void ComposeControls::setHistory(SetHistoryArgs &&args) {
|
||||||
registerDraftSource();
|
registerDraftSource();
|
||||||
_selector->setCurrentPeer(history ? history->peer.get() : nullptr);
|
_selector->setCurrentPeer(history ? history->peer.get() : nullptr);
|
||||||
initWebpageProcess();
|
initWebpageProcess();
|
||||||
|
initWriteRestriction();
|
||||||
initForwardProcess();
|
initForwardProcess();
|
||||||
updateBotCommandShown();
|
updateBotCommandShown();
|
||||||
updateLikeShown();
|
updateLikeShown();
|
||||||
|
@ -941,12 +943,16 @@ PeerData *ComposeControls::sendAsPeer() const {
|
||||||
|
|
||||||
void ComposeControls::move(int x, int y) {
|
void ComposeControls::move(int x, int y) {
|
||||||
_wrap->move(x, y);
|
_wrap->move(x, y);
|
||||||
_writeRestricted->move(x, y);
|
if (_writeRestricted) {
|
||||||
|
_writeRestricted->move(x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::resizeToWidth(int width) {
|
void ComposeControls::resizeToWidth(int width) {
|
||||||
_wrap->resizeToWidth(width);
|
_wrap->resizeToWidth(width);
|
||||||
_writeRestricted->resizeToWidth(width);
|
if (_writeRestricted) {
|
||||||
|
_writeRestricted->resizeToWidth(width);
|
||||||
|
}
|
||||||
updateHeight();
|
updateHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -961,12 +967,12 @@ rpl::producer<int> ComposeControls::height() const {
|
||||||
return rpl::conditional(
|
return rpl::conditional(
|
||||||
_writeRestriction.value() | rpl::map(!_1),
|
_writeRestriction.value() | rpl::map(!_1),
|
||||||
_wrap->heightValue(),
|
_wrap->heightValue(),
|
||||||
_writeRestricted->heightValue());
|
rpl::single(_st.attach.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
int ComposeControls::heightCurrent() const {
|
int ComposeControls::heightCurrent() const {
|
||||||
return _writeRestriction.current()
|
return _writeRestriction.current()
|
||||||
? _writeRestricted->height()
|
? _st.attach.height
|
||||||
: _wrap->height();
|
: _wrap->height();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1120,7 +1126,9 @@ void ComposeControls::showStarted() {
|
||||||
_autocomplete->hideFast();
|
_autocomplete->hideFast();
|
||||||
}
|
}
|
||||||
_wrap->hide();
|
_wrap->hide();
|
||||||
_writeRestricted->hide();
|
if (_writeRestricted) {
|
||||||
|
_writeRestricted->hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::showFinished() {
|
void ComposeControls::showFinished() {
|
||||||
|
@ -1319,7 +1327,8 @@ void ComposeControls::init() {
|
||||||
|
|
||||||
_wrap->paintRequest(
|
_wrap->paintRequest(
|
||||||
) | rpl::start_with_next([=](QRect clip) {
|
) | rpl::start_with_next([=](QRect clip) {
|
||||||
paintBackground(clip);
|
auto p = QPainter(_wrap.get());
|
||||||
|
paintBackground(p, _wrap->rect(), clip);
|
||||||
}, _wrap->lifetime());
|
}, _wrap->lifetime());
|
||||||
|
|
||||||
_header->editMsgIdValue(
|
_header->editMsgIdValue(
|
||||||
|
@ -1466,18 +1475,6 @@ void ComposeControls::clearListenState() {
|
||||||
_voiceRecordBar->clearListenState();
|
_voiceRecordBar->clearListenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::drawRestrictedWrite(QPainter &p, const QString &error) {
|
|
||||||
p.fillRect(_writeRestricted->rect(), st::historyReplyBg);
|
|
||||||
|
|
||||||
p.setFont(st::normalFont);
|
|
||||||
p.setPen(st::windowSubTextFg);
|
|
||||||
p.drawText(
|
|
||||||
_writeRestricted->rect().marginsRemoved(
|
|
||||||
QMargins(st::historySendPadding, 0, st::historySendPadding, 0)),
|
|
||||||
error,
|
|
||||||
style::al_center);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComposeControls::initKeyHandler() {
|
void ComposeControls::initKeyHandler() {
|
||||||
_wrap->events(
|
_wrap->events(
|
||||||
) | rpl::filter([=](not_null<QEvent*> event) {
|
) | rpl::filter([=](not_null<QEvent*> event) {
|
||||||
|
@ -2191,24 +2188,164 @@ void ComposeControls::inlineBotChanged() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetupRestrictionView(
|
||||||
|
not_null<Ui::RpWidget*> widget,
|
||||||
|
not_null<const style::ComposeControls*> st,
|
||||||
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
|
const QString &name,
|
||||||
|
rpl::producer<Controls::WriteRestriction> restriction,
|
||||||
|
Fn<void(QPainter &p, QRect clip)> paintBackground) {
|
||||||
|
struct State {
|
||||||
|
std::unique_ptr<Ui::FlatLabel> label;
|
||||||
|
std::unique_ptr<Ui::AbstractButton> button;
|
||||||
|
std::unique_ptr<Ui::RoundButton> unlock;
|
||||||
|
std::unique_ptr<Ui::RpWidget> icon;
|
||||||
|
Fn<void()> updateGeometries;
|
||||||
|
};
|
||||||
|
const auto state = widget->lifetime().make_state<State>();
|
||||||
|
state->updateGeometries = [=] {
|
||||||
|
if (!state->label) {
|
||||||
|
return;
|
||||||
|
} else if (state->button) {
|
||||||
|
const auto available = widget->width()
|
||||||
|
- st->like.width
|
||||||
|
- st::historySendRight
|
||||||
|
- state->unlock->width()
|
||||||
|
- st->premiumRequired.buttonSkip
|
||||||
|
- st->premiumRequired.position.x();
|
||||||
|
state->label->resizeToWidth(available);
|
||||||
|
state->label->moveToLeft(
|
||||||
|
st->premiumRequired.position.x(),
|
||||||
|
st->premiumRequired.position.y(),
|
||||||
|
widget->width());
|
||||||
|
const auto left = st->premiumRequired.position.x()
|
||||||
|
+ std::min(available, state->label->textMaxWidth())
|
||||||
|
+ st->premiumRequired.buttonSkip;
|
||||||
|
state->unlock->moveToLeft(
|
||||||
|
left,
|
||||||
|
st->premiumRequired.buttonTop,
|
||||||
|
widget->width());
|
||||||
|
state->button->setGeometry(QRect(
|
||||||
|
QPoint(),
|
||||||
|
QSize(left + state->unlock->width(), widget->height())));
|
||||||
|
state->icon->moveToLeft(0, 0, widget->width());
|
||||||
|
} else {
|
||||||
|
const auto left = st::historySendRight;
|
||||||
|
state->label->resizeToWidth(widget->width() - 2 * left);
|
||||||
|
state->label->moveToLeft(
|
||||||
|
left,
|
||||||
|
(widget->height() - state->label->height()) / 2,
|
||||||
|
widget->width());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const auto makeLabel = [=](
|
||||||
|
const QString &text,
|
||||||
|
const style::FlatLabel &st) {
|
||||||
|
auto label = std::make_unique<Ui::FlatLabel>(widget, text, st);
|
||||||
|
label->show();
|
||||||
|
label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
label->heightValue(
|
||||||
|
) | rpl::start_with_next(
|
||||||
|
state->updateGeometries,
|
||||||
|
label->lifetime());
|
||||||
|
return label;
|
||||||
|
};
|
||||||
|
const auto makeUnlock = [=](const QString &text, const QString &name) {
|
||||||
|
using namespace Ui;
|
||||||
|
auto unlock = std::make_unique<RoundButton>(
|
||||||
|
widget,
|
||||||
|
rpl::single(text),
|
||||||
|
st->premiumRequired.button);
|
||||||
|
unlock->show();
|
||||||
|
unlock->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
unlock->setTextTransform(RoundButton::TextTransform::NoTransform);
|
||||||
|
unlock->setFullRadius(true);
|
||||||
|
return unlock;
|
||||||
|
};
|
||||||
|
const auto makeIcon = [=] {
|
||||||
|
auto icon = std::make_unique<Ui::RpWidget>(widget);
|
||||||
|
icon->resize(st->premiumRequired.icon.size());
|
||||||
|
icon->show();
|
||||||
|
icon->paintRequest() | rpl::start_with_next([st, raw = icon.get()] {
|
||||||
|
auto p = QPainter(raw);
|
||||||
|
st->premiumRequired.icon.paint(p, {}, raw->width());
|
||||||
|
}, icon->lifetime());
|
||||||
|
return icon;
|
||||||
|
};
|
||||||
|
std::move(
|
||||||
|
restriction
|
||||||
|
) | rpl::distinct_until_changed(
|
||||||
|
) | rpl::start_with_next([=](Controls::WriteRestriction value) {
|
||||||
|
using Type = Controls::WriteRestriction::Type;
|
||||||
|
if (value.type == Type::Rights) {
|
||||||
|
state->icon = nullptr;
|
||||||
|
state->unlock = nullptr;
|
||||||
|
state->button = nullptr;
|
||||||
|
state->label = makeLabel(value.text, st->restrictionLabel);
|
||||||
|
} else if (value.type == Type::PremiumRequired) {
|
||||||
|
state->icon = makeIcon();
|
||||||
|
state->unlock = makeUnlock(value.button, name);
|
||||||
|
state->button = std::make_unique<Ui::AbstractButton>(widget);
|
||||||
|
state->button->setClickedCallback([=] {
|
||||||
|
::Settings::ShowPremiumPromoToast(
|
||||||
|
show,
|
||||||
|
tr::lng_send_non_premium_message_toast(
|
||||||
|
tr::now,
|
||||||
|
lt_user,
|
||||||
|
TextWithEntities{ name },
|
||||||
|
lt_link,
|
||||||
|
Ui::Text::Link(
|
||||||
|
Ui::Text::Bold(
|
||||||
|
tr::lng_send_non_premium_message_toast_link(
|
||||||
|
tr::now))),
|
||||||
|
Ui::Text::RichLangValue),
|
||||||
|
u"require_premium"_q);
|
||||||
|
});
|
||||||
|
state->label = makeLabel(value.text, st->premiumRequired.label);
|
||||||
|
}
|
||||||
|
}, widget->lifetime());
|
||||||
|
|
||||||
|
widget->sizeValue(
|
||||||
|
) | rpl::start_with_next(state->updateGeometries, widget->lifetime());
|
||||||
|
|
||||||
|
widget->paintRequest() | rpl::start_with_next([=](QRect clip) {
|
||||||
|
auto p = QPainter(widget);
|
||||||
|
paintBackground(p, clip);
|
||||||
|
}, widget->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
void ComposeControls::initWriteRestriction() {
|
void ComposeControls::initWriteRestriction() {
|
||||||
|
if (!_history) {
|
||||||
|
const auto was = base::take(_writeRestricted);
|
||||||
|
updateWrappingVisibility();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_writeRestricted = std::make_unique<Ui::RpWidget>(_parent);
|
||||||
|
_writeRestricted->move(_wrap->pos());
|
||||||
|
_writeRestricted->resizeToWidth(_wrap->widthNoMargins());
|
||||||
|
_writeRestricted->sizeValue() | rpl::start_with_next([=] {
|
||||||
|
if (_like && _like->parentWidget() == _writeRestricted.get()) {
|
||||||
|
updateControlsGeometry(_wrap->size());
|
||||||
|
}
|
||||||
|
}, _writeRestricted->lifetime());
|
||||||
_writeRestricted->resize(
|
_writeRestricted->resize(
|
||||||
_writeRestricted->width(),
|
_writeRestricted->width(),
|
||||||
st::historyUnblock.height);
|
st::historyUnblock.height);
|
||||||
_writeRestricted->paintRequest(
|
const auto background = [=](QPainter &p, QRect clip) {
|
||||||
) | rpl::start_with_next([=] {
|
paintBackground(p, _writeRestricted->rect(), clip);
|
||||||
if (const auto error = _writeRestriction.current()) {
|
};
|
||||||
auto p = Painter(_writeRestricted.get());
|
SetupRestrictionView(
|
||||||
drawRestrictedWrite(p, *error);
|
_writeRestricted.get(),
|
||||||
}
|
&_st,
|
||||||
}, _wrap->lifetime());
|
_show,
|
||||||
|
_history->peer->shortName(),
|
||||||
|
_writeRestriction.value(),
|
||||||
|
background);
|
||||||
|
|
||||||
_writeRestriction.value(
|
_writeRestriction.value(
|
||||||
) | rpl::filter([=] {
|
) | rpl::start_with_next([=] {
|
||||||
return _wrap->isHidden() || _writeRestricted->isHidden();
|
|
||||||
}) | rpl::start_with_next([=] {
|
|
||||||
updateWrappingVisibility();
|
updateWrappingVisibility();
|
||||||
}, _wrap->lifetime());
|
}, _writeRestricted->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::changeFocusedControl() {
|
void ComposeControls::changeFocusedControl() {
|
||||||
|
@ -2261,9 +2398,26 @@ void ComposeControls::initVoiceRecordBar() {
|
||||||
|
|
||||||
void ComposeControls::updateWrappingVisibility() {
|
void ComposeControls::updateWrappingVisibility() {
|
||||||
const auto hidden = _hidden.current();
|
const auto hidden = _hidden.current();
|
||||||
const auto restricted = _writeRestriction.current().has_value();
|
const auto &restriction = _writeRestriction.current();
|
||||||
_writeRestricted->setVisible(!hidden && restricted);
|
const auto restricted = !restriction.empty() && _writeRestricted;
|
||||||
|
if (_writeRestricted) {
|
||||||
|
_writeRestricted->setVisible(!hidden && restricted);
|
||||||
|
}
|
||||||
_wrap->setVisible(!hidden && !restricted);
|
_wrap->setVisible(!hidden && !restricted);
|
||||||
|
using namespace Controls;
|
||||||
|
if (_like) {
|
||||||
|
const auto hidden = _like->isHidden();
|
||||||
|
if (_writeRestricted
|
||||||
|
&& restriction.type == WriteRestrictionType::PremiumRequired) {
|
||||||
|
_like->setParent(_writeRestricted.get());
|
||||||
|
} else {
|
||||||
|
_like->setParent(_wrap.get());
|
||||||
|
}
|
||||||
|
if (!hidden) {
|
||||||
|
_like->show();
|
||||||
|
updateControlsGeometry(_wrap->size());
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!hidden && !restricted) {
|
if (!hidden && !restricted) {
|
||||||
_wrap->raise();
|
_wrap->raise();
|
||||||
}
|
}
|
||||||
|
@ -2363,9 +2517,14 @@ void ComposeControls::updateControlsGeometry(QSize size) {
|
||||||
_tabbedSelectorToggle->moveToRight(right, buttonsTop);
|
_tabbedSelectorToggle->moveToRight(right, buttonsTop);
|
||||||
right += _tabbedSelectorToggle->width();
|
right += _tabbedSelectorToggle->width();
|
||||||
if (_like) {
|
if (_like) {
|
||||||
_like->moveToRight(right, buttonsTop);
|
using Type = Controls::WriteRestrictionType;
|
||||||
if (_likeShown) {
|
if (_writeRestriction.current().type == Type::PremiumRequired) {
|
||||||
right += _like->width();
|
_like->moveToRight(st::historySendRight, 0);
|
||||||
|
} else {
|
||||||
|
_like->moveToRight(right, buttonsTop);
|
||||||
|
if (_likeShown) {
|
||||||
|
right += _like->width();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_botCommandStart) {
|
if (_botCommandStart) {
|
||||||
|
@ -2521,9 +2680,7 @@ void ComposeControls::updateAttachBotsMenu() {
|
||||||
}, _attachBotsMenu->lifetime());
|
}, _attachBotsMenu->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::paintBackground(QRect clip) {
|
void ComposeControls::paintBackground(QPainter &p, QRect full, QRect clip) {
|
||||||
Painter p(_wrap.get());
|
|
||||||
|
|
||||||
if (_backgroundRect) {
|
if (_backgroundRect) {
|
||||||
//p.setCompositionMode(QPainter::CompositionMode_Source);
|
//p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
//p.fillRect(clip, Qt::transparent);
|
//p.fillRect(clip, Qt::transparent);
|
||||||
|
@ -2532,7 +2689,7 @@ void ComposeControls::paintBackground(QRect clip) {
|
||||||
auto hq = PainterHighQualityEnabler(p);
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
p.setBrush(_st.bg);
|
p.setBrush(_st.bg);
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
p.drawRoundedRect(_wrap->rect(), _st.radius, _st.radius);
|
p.drawRoundedRect(full, _st.radius, _st.radius);
|
||||||
} else {
|
} else {
|
||||||
p.fillRect(clip, _st.bg);
|
p.fillRect(clip, _st.bg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -272,7 +272,7 @@ private:
|
||||||
void updateControlsGeometry(QSize size);
|
void updateControlsGeometry(QSize size);
|
||||||
bool updateReplaceMediaButton();
|
bool updateReplaceMediaButton();
|
||||||
void updateOuterGeometry(QRect rect);
|
void updateOuterGeometry(QRect rect);
|
||||||
void paintBackground(QRect clip);
|
void paintBackground(QPainter &p, QRect full, QRect clip);
|
||||||
|
|
||||||
[[nodiscard]] auto computeSendButtonType() const;
|
[[nodiscard]] auto computeSendButtonType() const;
|
||||||
[[nodiscard]] SendMenu::Type sendMenuType() const;
|
[[nodiscard]] SendMenu::Type sendMenuType() const;
|
||||||
|
@ -296,7 +296,6 @@ private:
|
||||||
void setTabbedPanel(std::unique_ptr<ChatHelpers::TabbedPanel> panel);
|
void setTabbedPanel(std::unique_ptr<ChatHelpers::TabbedPanel> panel);
|
||||||
|
|
||||||
bool showRecordButton() const;
|
bool showRecordButton() const;
|
||||||
void drawRestrictedWrite(QPainter &p, const QString &error);
|
|
||||||
bool updateBotCommandShown();
|
bool updateBotCommandShown();
|
||||||
bool updateLikeShown();
|
bool updateLikeShown();
|
||||||
|
|
||||||
|
@ -353,12 +352,12 @@ private:
|
||||||
rpl::variable<int> _slowmodeSecondsLeft;
|
rpl::variable<int> _slowmodeSecondsLeft;
|
||||||
rpl::variable<bool> _sendDisabledBySlowmode;
|
rpl::variable<bool> _sendDisabledBySlowmode;
|
||||||
rpl::variable<bool> _liked;
|
rpl::variable<bool> _liked;
|
||||||
rpl::variable<std::optional<QString>> _writeRestriction;
|
rpl::variable<Controls::WriteRestriction> _writeRestriction;
|
||||||
rpl::variable<bool> _hidden;
|
rpl::variable<bool> _hidden;
|
||||||
Mode _mode = Mode::Normal;
|
Mode _mode = Mode::Normal;
|
||||||
|
|
||||||
const std::unique_ptr<Ui::RpWidget> _wrap;
|
const std::unique_ptr<Ui::RpWidget> _wrap;
|
||||||
const std::unique_ptr<Ui::RpWidget> _writeRestricted;
|
std::unique_ptr<Ui::RpWidget> _writeRestricted;
|
||||||
rpl::event_stream<FullReplyTo> _jumpToItemRequests;
|
rpl::event_stream<FullReplyTo> _jumpToItemRequests;
|
||||||
|
|
||||||
std::optional<Ui::RoundRect> _backgroundRect;
|
std::optional<Ui::RoundRect> _backgroundRect;
|
||||||
|
|
|
@ -699,7 +699,7 @@ void RepliesWidget::setupComposeControls() {
|
||||||
const auto restriction = Data::RestrictionError(
|
const auto restriction = Data::RestrictionError(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
ChatRestriction::SendOther);
|
ChatRestriction::SendOther);
|
||||||
return !canSendAnything
|
auto text = !canSendAnything
|
||||||
? (restriction
|
? (restriction
|
||||||
? restriction
|
? restriction
|
||||||
: topicRestriction
|
: topicRestriction
|
||||||
|
@ -708,6 +708,10 @@ void RepliesWidget::setupComposeControls() {
|
||||||
: topicRestriction
|
: topicRestriction
|
||||||
? std::move(topicRestriction)
|
? std::move(topicRestriction)
|
||||||
: std::optional<QString>();
|
: std::optional<QString>();
|
||||||
|
return text ? Controls::WriteRestriction{
|
||||||
|
.text = std::move(*text),
|
||||||
|
.type = Controls::WriteRestrictionType::Rights,
|
||||||
|
} : Controls::WriteRestriction();
|
||||||
});
|
});
|
||||||
|
|
||||||
_composeControls->setHistory({
|
_composeControls->setHistory({
|
||||||
|
|
|
@ -198,11 +198,15 @@ void ScheduledWidget::setupComposeControls() {
|
||||||
const auto restriction = Data::RestrictionError(
|
const auto restriction = Data::RestrictionError(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
ChatRestriction::SendOther);
|
ChatRestriction::SendOther);
|
||||||
return !canSendAnything
|
auto text = !canSendAnything
|
||||||
? (restriction
|
? (restriction
|
||||||
? restriction
|
? restriction
|
||||||
: tr::lng_group_not_accessible(tr::now))
|
: tr::lng_group_not_accessible(tr::now))
|
||||||
: std::optional<QString>();
|
: std::optional<QString>();
|
||||||
|
return text ? Controls::WriteRestriction{
|
||||||
|
.text = std::move(*text),
|
||||||
|
.type = Controls::WriteRestrictionType::Rights,
|
||||||
|
} : Controls::WriteRestriction();
|
||||||
});
|
});
|
||||||
_composeControls->setHistory({
|
_composeControls->setHistory({
|
||||||
.history = _history.get(),
|
.history = _history.get(),
|
||||||
|
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/stickers/data_custom_emoji.h"
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_message_reaction_id.h"
|
#include "data/data_message_reaction_id.h"
|
||||||
|
#include "data/data_peer_values.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "history/view/controls/compose_controls_common.h"
|
#include "history/view/controls/compose_controls_common.h"
|
||||||
|
@ -663,6 +664,22 @@ void ReplyArea::show(
|
||||||
invalidate_weak_ptrs(&_shownPeerGuard);
|
invalidate_weak_ptrs(&_shownPeerGuard);
|
||||||
const auto peer = data.peer;
|
const auto peer = data.peer;
|
||||||
const auto history = peer ? peer->owner().history(peer).get() : nullptr;
|
const auto history = peer ? peer->owner().history(peer).get() : nullptr;
|
||||||
|
const auto user = peer->asUser();
|
||||||
|
auto writeRestriction = Data::CanSendAnythingValue(
|
||||||
|
peer
|
||||||
|
) | rpl::map([=](bool can) {
|
||||||
|
using namespace HistoryView::Controls;
|
||||||
|
return (can
|
||||||
|
|| !user
|
||||||
|
|| !user->meRequiresPremiumToWrite()
|
||||||
|
|| user->session().premium())
|
||||||
|
? WriteRestriction()
|
||||||
|
: WriteRestriction{
|
||||||
|
.text = tr::lng_send_non_premium_story(tr::now),
|
||||||
|
.button = tr::lng_send_non_premium_unlock(tr::now),
|
||||||
|
.type = WriteRestrictionType::PremiumRequired,
|
||||||
|
};
|
||||||
|
});
|
||||||
_controls->setHistory({
|
_controls->setHistory({
|
||||||
.history = history,
|
.history = history,
|
||||||
.liked = std::move(
|
.liked = std::move(
|
||||||
|
@ -670,6 +687,7 @@ void ReplyArea::show(
|
||||||
) | rpl::map([](const Data::ReactionId &id) {
|
) | rpl::map([](const Data::ReactionId &id) {
|
||||||
return !id.empty();
|
return !id.empty();
|
||||||
}),
|
}),
|
||||||
|
.writeRestriction = std::move(writeRestriction),
|
||||||
});
|
});
|
||||||
_controls->clear();
|
_controls->clear();
|
||||||
const auto hidden = peer
|
const auto hidden = peer
|
||||||
|
|
|
@ -776,6 +776,32 @@ storiesComposeControls: ComposeControls(defaultComposeControls) {
|
||||||
|
|
||||||
menu: storiesPopupMenu;
|
menu: storiesPopupMenu;
|
||||||
}
|
}
|
||||||
|
restrictionLabel: FlatLabel(defaultFlatLabel) {
|
||||||
|
minWidth: 12px;
|
||||||
|
textFg: storiesComposeGrayText;
|
||||||
|
align: align(top);
|
||||||
|
}
|
||||||
|
premiumRequired: ComposePremiumRequired {
|
||||||
|
label: FlatLabel(defaultFlatLabel) {
|
||||||
|
minWidth: 12px;
|
||||||
|
textFg: storiesComposeGrayText;
|
||||||
|
}
|
||||||
|
button: RoundButton(defaultActiveButton) {
|
||||||
|
textFg: storiesComposeWhiteText;
|
||||||
|
textFgOver: storiesComposeWhiteText;
|
||||||
|
textBg: groupCallMembersBgRipple;
|
||||||
|
textBgOver: groupCallMembersBgRipple;
|
||||||
|
width: -12px;
|
||||||
|
height: 18px;
|
||||||
|
textTop: 0px;
|
||||||
|
font: font(12px);
|
||||||
|
ripple: storiesComposeRipple;
|
||||||
|
}
|
||||||
|
buttonSkip: 6px;
|
||||||
|
buttonTop: 14px;
|
||||||
|
position: point(37px, 14px);
|
||||||
|
icon: icon{{ "emoji/premium_lock", storiesComposeGrayIcon, point(13px, 14px) }};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
storiesViewsMenu: PopupMenu(storiesPopupMenuWithIcons) {
|
storiesViewsMenu: PopupMenu(storiesPopupMenuWithIcons) {
|
||||||
scrollPadding: margins(0px, 6px, 0px, 4px);
|
scrollPadding: margins(0px, 6px, 0px, 4px);
|
||||||
|
|
|
@ -1322,6 +1322,7 @@ void ShowPremiumPromoToast(
|
||||||
.text = std::move(textWithLink),
|
.text = std::move(textWithLink),
|
||||||
.st = &st::defaultMultilineToast,
|
.st = &st::defaultMultilineToast,
|
||||||
.duration = Ui::Toast::kDefaultDuration * 2,
|
.duration = Ui::Toast::kDefaultDuration * 2,
|
||||||
|
.adaptive = true,
|
||||||
.multiline = true,
|
.multiline = true,
|
||||||
.filter = crl::guard(&show->session(), [=](
|
.filter = crl::guard(&show->session(), [=](
|
||||||
const ClickHandlerPtr &,
|
const ClickHandlerPtr &,
|
||||||
|
|
|
@ -35,6 +35,14 @@ PremiumCover {
|
||||||
about: FlatLabel;
|
about: FlatLabel;
|
||||||
additionalShadowForDarkThemes: bool;
|
additionalShadowForDarkThemes: bool;
|
||||||
}
|
}
|
||||||
|
ComposePremiumRequired {
|
||||||
|
label: FlatLabel;
|
||||||
|
button: RoundButton;
|
||||||
|
buttonSkip: pixels;
|
||||||
|
buttonTop: pixels;
|
||||||
|
position: point;
|
||||||
|
icon: icon;
|
||||||
|
}
|
||||||
|
|
||||||
premiumAboutTextStyle: TextStyle(defaultTextStyle) {
|
premiumAboutTextStyle: TextStyle(defaultTextStyle) {
|
||||||
font: font(12px);
|
font: font(12px);
|
||||||
|
|
Loading…
Add table
Reference in a new issue