Merge tag 'v6.7.4' into dev

This commit is contained in:
AlexeyZavar
2026-04-07 19:39:20 +03:00
138 changed files with 1192 additions and 463 deletions
+1 -11
View File
@@ -116,19 +116,14 @@ void Transcribes::toggle(not_null<HistoryItem*> item) {
}
}
void Transcribes::toggleSummary(
not_null<HistoryItem*> item,
Fn<void()> onPremiumRequired) {
void Transcribes::toggleSummary(not_null<HistoryItem*> item) {
const auto id = item->fullId();
auto i = _summaries.find(id);
if (i == _summaries.end()) {
auto &entry = _summaries.emplace(id).first->second;
entry.onPremiumRequired = std::move(onPremiumRequired);
summarize(item);
} else if (!i->second.loading) {
auto &entry = i->second;
if (entry.result.empty()) {
entry.onPremiumRequired = std::move(onPremiumRequired);
summarize(item);
} else {
entry.shown = entry.premiumRequired ? false : !entry.shown;
@@ -265,7 +260,6 @@ void Transcribes::summarize(not_null<HistoryItem*> item) {
entry.requestId = 0;
entry.loading = false;
entry.premiumRequired = false;
entry.onPremiumRequired = nullptr;
entry.languageId = translatedTo;
entry.result = TextWithEntities(
qs(data.vtext()),
@@ -277,15 +271,11 @@ void Transcribes::summarize(not_null<HistoryItem*> item) {
}).fail([=](const MTP::Error &error) {
auto &entry = _summaries[id];
if (error.type() == u"SUMMARY_FLOOD_PREMIUM"_q) {
if (!entry.premiumRequired && entry.onPremiumRequired) {
entry.onPremiumRequired();
}
entry.premiumRequired = true;
}
entry.requestId = 0;
entry.shown = false;
entry.loading = false;
entry.onPremiumRequired = nullptr;
if (const auto item = _session->data().message(id)) {
_session->data().requestItemTextRefresh(item);
}
+1 -4
View File
@@ -19,7 +19,6 @@ class Session;
namespace Api {
struct SummaryEntry {
Fn<void()> onPremiumRequired = nullptr;
TextWithEntities result;
LanguageId languageId;
bool shown = false;
@@ -45,9 +44,7 @@ public:
void toggle(not_null<HistoryItem*> item);
[[nodiscard]] const Entry &entry(not_null<HistoryItem*> item) const;
void toggleSummary(
not_null<HistoryItem*> item,
Fn<void()> onPremiumRequired);
void toggleSummary(not_null<HistoryItem*> item);
[[nodiscard]] const SummaryEntry &summary(
not_null<const HistoryItem*> item) const;
void checkSummaryToTranslate(FullMsgId id);
+9 -1
View File
@@ -2623,7 +2623,15 @@ void ApiWrap::refreshFileReference(
fail();
}
}, [&](Data::FileOriginPeerPhoto data) {
fail();
const auto peer = _session->data().peer(data.peerId);
if (const auto channel = peer->asChannel()) {
request(MTPchannels_GetFullChannel(
channel->inputChannel()));
} else if (const auto chat = peer->asChat()) {
request(MTPmessages_GetFullChat(chat->inputChat()));
} else {
fail();
}
}, [&](Data::FileOriginStickerSet data) {
const auto isRecentAttached
= (data.setId == Data::Stickers::CloudRecentAttachedSetId);
-2
View File
@@ -254,8 +254,6 @@ void ArchiveHintBox(
box,
tr::lng_archive_hint_button(),
st::defaultActiveButton);
button->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
button->resizeToWidth(box->width()
- st.buttonPadding.left()
- st.buttonPadding.left());
@@ -38,7 +38,6 @@ void AboutSponsoredBox(not_null<Ui::GenericBox*> box) {
st);
button->setBrushOverride(Qt::NoBrush);
button->setPenOverride(QPen(st::historyLinkInFg));
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
rpl::combine(
row->sizeValue(),
button->sizeValue()
@@ -792,10 +792,6 @@ void BackgroundPreviewBox::applyForPeer() {
}), raw->lifetime());
raw->toggle(false, anim::type::normal);
});
forMe->setTextTransform(RoundButton::TextTransform::NoTransform);
forBoth->setTextTransform(RoundButton::TextTransform::NoTransform);
cancel->setTextTransform(RoundButton::TextTransform::NoTransform);
overlay->sizeValue(
) | rpl::on_next([=](QSize size) {
const auto padding = st::backgroundConfirmPadding;
+43
View File
@@ -669,6 +669,41 @@ proxyAboutSponsorPadding: margins(22px, 7px, 22px, 0px);
proxyApplyBoxLabel : FlatLabel(defaultFlatLabel) {
maxHeight: 30px;
}
proxyApplyBoxTable: Table(defaultTable) {
labelMinWidth: 91px;
}
proxyApplyBoxTableMargin: margins(24px, 4px, 24px, 4px);
proxyApplyBoxTableLabelMargin: margins(13px, 10px, 13px, 10px);
proxyApplyBoxTableValueMargin: margins(13px, 9px, 13px, 9px);
proxyApplyBoxValueMultiline: FlatLabel(defaultTableValue) {
minWidth: 128px;
maxHeight: 100px;
style: TextStyle(defaultTextStyle) {
font: font(10px);
linkUnderline: kLinkUnderlineNever;
}
}
proxyApplyBoxSponsorLabel: FlatLabel(defaultFlatLabel) {
textFg: windowBoldFg;
minWidth: 100px;
align: align(top);
style: TextStyle(defaultTextStyle) {
font: font(11px);
}
}
proxyApplyBoxSponsorMargin: margins(13px, 8px, 13px, 8px);
proxyApplyBoxButton: RoundButton(defaultActiveButton) {
height: 38px;
textTop: 10px;
style: semiboldTextStyle;
}
proxyApplyBox: Box(defaultBox) {
buttonPadding: margins(22px, 11px, 22px, 22px);
buttonHeight: 38px;
buttonWide: true;
button: proxyApplyBoxButton;
shadowIgnoreTopSkip: true;
}
markdownLinkFieldPadding: margins(22px, 0px, 22px, 10px);
@@ -1294,3 +1329,11 @@ aiComposeBoxWithSend: Box(aiComposeBox) {
buttonPadding: margins(16px, 12px, 66px, 12px);
}
aiComposeSendButtonSkip: 8px;
aiComposeBoxClose: IconButton(boxTitleClose) {
ripple: defaultRippleAnimation;
}
aiComposeBoxInfoButton: IconButton(boxTitleClose) {
icon: icon {{ "menu/info", boxTitleCloseFg }};
iconOver: icon {{ "menu/info", boxTitleCloseFgOver }};
ripple: defaultRippleAnimation;
}
+34 -12
View File
@@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "settings/sections/settings_premium.h"
#include "spellcheck/platform/platform_language.h"
#include "ui/boxes/about_cocoon_box.h"
#include "ui/boxes/choose_language_box.h"
#include "ui/chat/chat_style.h"
#include "ui/controls/labeled_emoji_tabs.h"
@@ -386,6 +387,7 @@ private:
void updatePinnedTabs(anim::type animated);
void cancelRequest();
void request();
void resetState(CardState state);
void applyResult(Api::ComposeWithAi::Result &&result);
void showError(const QString &error = {});
void notifyLoadingChanged();
@@ -1127,8 +1129,12 @@ void ComposeAiContent::updateTitles() {
? ToTitle(_to, currentTranslateStyleLabel())
: tr::lng_ai_compose_result(tr::now, tr::marked))
: tr::lng_ai_compose_original(tr::now, tr::marked));
const auto emojifyOnlyMode = !hasResult
&& (_mode == ComposeAiMode::Style)
&& (_styleIndex < 0);
_preview->setEmojifyVisible(
hasResult && (_mode != ComposeAiMode::Fix));
(hasResult && (_mode != ComposeAiMode::Fix))
|| emojifyOnlyMode);
_preview->setEmojifyChecked(_emojify);
}
@@ -1154,15 +1160,13 @@ void ComposeAiContent::cancelRequest() {
void ComposeAiContent::request() {
cancelRequest();
if (_mode == ComposeAiMode::Style && _styleIndex < 0) {
if (_mode == ComposeAiMode::Style && _styleIndex < 0 && !_emojify) {
if (_state != CardState::Waiting) {
resetState(CardState::Waiting);
}
return;
}
_state = CardState::Loading;
_result = {};
_preview->setState(CardState::Loading);
notifyLoadingChanged();
updateTitles();
notifyReadyChanged();
resetState(CardState::Loading);
auto request = Api::ComposeWithAi::Request{
.text = _original,
@@ -1174,7 +1178,9 @@ void ComposeAiContent::request() {
request.changeTone = currentTranslateStyle();
break;
case ComposeAiMode::Style:
request.changeTone = _stylesData[_styleIndex].id;
if (_styleIndex >= 0) {
request.changeTone = _stylesData[_styleIndex].id;
}
break;
case ComposeAiMode::Fix:
request.proofread = true;
@@ -1201,6 +1207,15 @@ void ComposeAiContent::request() {
});
}
void ComposeAiContent::resetState(CardState state) {
_state = state;
_result = {};
_preview->setState(state);
notifyLoadingChanged();
updateTitles();
notifyReadyChanged();
}
void ComposeAiContent::applyResult(Api::ComposeWithAi::Result &&result) {
_result = std::move(result.resultText);
if (_result.text.isEmpty()) {
@@ -1397,9 +1412,12 @@ void ComposeAiBox(not_null<Ui::GenericBox*> box, ComposeAiBoxArgs &&args) {
box->setNoContentMargin(true);
box->setWidth(st::boxWideWidth);
const auto session = args.session;
box->addTopButton(st::boxTitleClose, [=] {
box->addTopButton(st::aiComposeBoxClose, [=] {
box->closeBox();
});
box->addTopButton(st::aiComposeBoxInfoButton, [=] {
box->uiShow()->show(Box(Ui::AboutCocoonBox));
});
const auto body = box->verticalLayout();
const auto tabsSkip = QMargins(0, 0, 0, st::aiComposeBoxStyleTabsSkip);
@@ -1493,9 +1511,12 @@ void ComposeAiBox(not_null<Ui::GenericBox*> box, ComposeAiBoxArgs &&args) {
}
*sendButton = nullptr;
box->clearButtons();
box->addTopButton(st::boxTitleClose, [=] {
box->addTopButton(st::aiComposeBoxClose, [=] {
box->closeBox();
});
box->addTopButton(st::aiComposeBoxInfoButton, [=] {
box->uiShow()->show(Box(Ui::AboutCocoonBox));
});
if (*premiumFlooded) {
auto helper = Ui::Text::CustomEmojiHelper();
@@ -1525,7 +1546,8 @@ void ComposeAiBox(not_null<Ui::GenericBox*> box, ComposeAiBoxArgs &&args) {
close();
});
} else if (content->mode() == ComposeAiMode::Style
&& !content->hasStyleSelection()) {
&& !content->hasStyleSelection()
&& !content->hasResult()) {
const auto btn = addApplyButton(
*boxStyleNoSend,
tr::lng_ai_compose_select_style(), nullptr);
+294 -122
View File
@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/call_delayed.h"
#include "base/qthelp_regex.h"
#include "base/qthelp_url.h"
#include "base/weak_ptr.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "core/local_url_handlers.h"
@@ -39,6 +40,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
#include "ui/widgets/popup_menu.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/wrap/table_layout.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/vertical_list.h"
#include "ui/ui_utility.h"
@@ -74,7 +76,7 @@ using ProxyData = MTP::ProxyData;
[[nodiscard]] QString ProxyDataToString(const ProxyData &proxy) {
using Type = ProxyData::Type;
return u"https://t.me/"_q
return u"tg://"_q
+ (proxy.type == Type::Socks5 ? "socks" : "proxy")
+ "?server=" + proxy.host + "&port=" + QString::number(proxy.port)
+ ((proxy.type == Type::Socks5 && !proxy.user.isEmpty())
@@ -151,9 +153,13 @@ void AddProxyFromClipboard(
const auto type = isSocks
? ProxyData::Type::Socks5
: ProxyData::Type::Mtproto;
const auto fields = url_parse_params(
auto fields = url_parse_params(
match->captured(1),
qthelp::UrlParamNameTransform::ToLower);
if (type == ProxyData::Type::Mtproto) {
auto &secret = fields[u"secret"_q];
secret.replace('+', '-').replace('/', '_');
}
const auto proxy = ProxyDataFromFields(type, fields);
if (!proxy) {
const auto status = proxy.status();
@@ -1352,6 +1358,97 @@ void ProxyBox::addLabel(
st::proxyEditTitlePadding);
}
using Connection = MTP::details::AbstractConnection;
using Checker = MTP::details::ConnectionPointer;
void ResetProxyCheckers(Checker &v4, Checker &v6) {
v4 = nullptr;
v6 = nullptr;
}
void DropProxyChecker(Checker &v4, Checker &v6, not_null<Connection*> raw) {
if (v4.get() == raw) {
v4 = nullptr;
} else if (v6.get() == raw) {
v6 = nullptr;
}
}
[[nodiscard]] bool HasProxyCheckers(const Checker &v4, const Checker &v6) {
return v4 || v6;
}
void StartProxyCheck(
not_null<MTP::Instance*> mtproto,
const ProxyData &proxy,
Checker &v4,
Checker &v6,
Fn<void(Connection *raw, int ping)> done,
Fn<void(Connection *raw)> fail) {
using Variants = MTP::DcOptions::Variants;
ResetProxyCheckers(v4, v6);
const auto connType = (proxy.type == ProxyData::Type::Http)
? Variants::Http
: Variants::Tcp;
const auto dcId = mtproto->mainDcId();
const auto setup = [&](Checker &checker, const bytes::vector &secret) {
checker = Connection::Create(
mtproto,
connType,
QThread::currentThread(),
secret,
proxy);
const auto raw = checker.get();
raw->connect(raw, &Connection::connected, [=] {
if (done) {
done(raw, raw->pingTime());
}
});
const auto failed = [=] {
if (fail) {
fail(raw);
}
};
raw->connect(raw, &Connection::disconnected, failed);
raw->connect(raw, &Connection::error, failed);
};
if (proxy.type == ProxyData::Type::Mtproto) {
const auto secret = proxy.secretFromMtprotoPassword();
setup(v4, secret);
v4->connectToServer(
proxy.host,
proxy.port,
secret,
dcId,
false);
return;
}
const auto options = mtproto->dcOptions().lookup(
dcId,
MTP::DcType::Regular,
true);
const auto tryConnect = [&](Checker &checker, Variants::Address address) {
const auto &list = options.data[address][connType];
if (list.empty()
|| ((address == Variants::IPv6)
&& !Core::App().settings().proxy().tryIPv6())) {
checker = nullptr;
return;
}
const auto &endpoint = list.front();
setup(checker, endpoint.secret);
checker->connectToServer(
QString::fromStdString(endpoint.ip),
endpoint.port,
endpoint.secret,
dcId,
false);
};
tryConnect(v4, Variants::IPv4);
tryConnect(v6, Variants::IPv6);
}
} // namespace
ProxiesBoxController::ProxiesBoxController(not_null<Main::Account*> account)
@@ -1416,53 +1513,177 @@ void ProxiesBoxController::ShowApplyConfirmation(
QString()
).replace(UrlEndRegExp, QString());
const auto box = [=](not_null<Ui::GenericBox*> box) {
box->setTitle(tr::lng_proxy_box_title());
if (type == Type::Mtproto) {
box->addRow(object_ptr<Ui::FlatLabel>(
box->setTitle(tr::lng_proxy_box_table_title());
box->setStyle(st::proxyApplyBox);
box->addTopButton(st::boxTitleClose, [=] {
box->closeBox();
});
const auto table = box->addRow(
object_ptr<Ui::TableLayout>(
box,
tr::lng_proxy_sponsor_warning(),
st::boxDividerLabel));
Ui::AddSkip(box->verticalLayout());
Ui::AddSkip(box->verticalLayout());
}
const auto &stL = st::proxyApplyBoxLabel;
const auto &stSubL = st::boxDividerLabel;
const auto add = [&](const QString &s, tr::phrase<> phrase) {
if (!s.isEmpty()) {
box->addRow(object_ptr<Ui::FlatLabel>(box, s, stL));
box->addRow(object_ptr<Ui::FlatLabel>(box, phrase(), stSubL));
Ui::AddSkip(box->verticalLayout());
Ui::AddSkip(box->verticalLayout());
st::proxyApplyBoxTable),
st::proxyApplyBoxTableMargin);
const auto addRow = [&](
rpl::producer<QString> label,
object_ptr<Ui::RpWidget> value) {
table->addRow(
object_ptr<Ui::FlatLabel>(
table,
std::move(label),
table->st().defaultLabel),
std::move(value),
st::proxyApplyBoxTableLabelMargin,
st::proxyApplyBoxTableValueMargin);
};
const auto add = [&](
const QString &value,
rpl::producer<QString> label) {
if (!value.isEmpty()) {
constexpr auto kOneLineCount = 20;
const auto oneLine = value.length() <= kOneLineCount;
auto widget = object_ptr<Ui::FlatLabel>(
table,
rpl::single(Ui::Text::Wrapped(
{ value },
EntityType::Code,
{})),
(oneLine
? table->st().defaultValue
: st::proxyApplyBoxValueMultiline),
st::defaultPopupMenu);
addRow(std::move(label), std::move(widget));
}
};
if (!displayServer.isEmpty()) {
add(displayServer, tr::lng_proxy_box_server);
add(displayServer, tr::lng_proxy_box_server());
}
add(QString::number(proxy.port), tr::lng_proxy_box_port);
add(QString::number(proxy.port), tr::lng_proxy_box_port());
if (type == Type::Socks5) {
add(proxy.user, tr::lng_proxy_box_username);
add(proxy.password, tr::lng_proxy_box_password);
add(proxy.user, tr::lng_proxy_box_username());
add(proxy.password, tr::lng_proxy_box_password());
} else if (type == Type::Mtproto) {
add(proxy.password, tr::lng_proxy_box_secret);
add(proxy.password, tr::lng_proxy_box_secret());
}
const auto enableButton = box->addButton(tr::lng_sure_enable(), [=] {
auto &proxies = Core::App().settings().proxy().list();
if (!ranges::contains(proxies, proxy)) {
proxies.push_back(proxy);
}
Core::App().setCurrentProxy(proxy, ProxyData::Settings::Enabled);
Local::writeSettings();
box->closeBox();
});
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
box->events(
) | rpl::on_next([=](not_null<QEvent*> e) {
{
struct ProxyCheckStatusState {
Checker v4;
Checker v6;
rpl::variable<TextWithEntities> statusValue;
bool finished = false;
};
const auto state
= box->lifetime().make_state<ProxyCheckStatusState>();
state->statusValue = Ui::Text::Link(
tr::lng_proxy_box_check_status(tr::now));
const auto weak = base::make_weak(box);
auto statusWidget = object_ptr<Ui::FlatLabel>(
table,
state->statusValue.value(),
table->st().defaultValue,
st::defaultPopupMenu);
const auto statusLabel = statusWidget.data();
addRow(tr::lng_proxy_box_status(), std::move(statusWidget));
const auto relayout = [=] {
table->resizeToWidth(table->width());
};
const auto setUnavailable = [=] {
state->statusValue = TextWithEntities{
tr::lng_proxy_box_table_unavailable(tr::now),
};
statusLabel->setTextColorOverride(
st::proxyRowStatusFgOffline->c);
relayout();
};
const auto runCheck = [=] {
if (!weak) {
return;
}
const auto account = controller
? &controller->session().account()
: &Core::App().activeAccount();
state->finished = false;
state->statusValue = TextWithEntities{
tr::lng_proxy_box_table_checking(tr::now),
};
statusLabel->setTextColorOverride(st::proxyRowStatusFg->c);
relayout();
StartProxyCheck(
&account->mtp(),
proxy,
state->v4,
state->v6,
[=](Connection *raw, int ping) {
if (!weak || state->finished) {
return;
}
DropProxyChecker(state->v4, state->v6, raw);
state->finished = true;
ResetProxyCheckers(state->v4, state->v6);
state->statusValue = TextWithEntities{
tr::lng_proxy_box_table_available(
tr::now,
lt_ping,
QString::number(ping)),
};
statusLabel->setTextColorOverride(
st::proxyRowStatusFgAvailable->c);
relayout();
},
[=](Connection *raw) {
if (!weak || state->finished) {
return;
}
DropProxyChecker(state->v4, state->v6, raw);
if (!HasProxyCheckers(state->v4, state->v6)) {
state->finished = true;
setUnavailable();
}
});
if (!HasProxyCheckers(state->v4, state->v6)) {
state->finished = true;
setUnavailable();
}
};
statusLabel->setClickHandlerFilter([=](const auto &...) {
runCheck();
return false;
});
}
if (type == Type::Mtproto) {
table->addRow(
object_ptr<Ui::FlatLabel>(
table,
tr::lng_proxy_sponsor_warning(),
st::proxyApplyBoxSponsorLabel),
object_ptr<Ui::RpWidget>(nullptr),
st::proxyApplyBoxSponsorMargin,
st::proxyApplyBoxSponsorMargin);
}
const auto enableButton = box->addButton(
tr::lng_proxy_box_table_button(),
[=] {
auto &proxies = Core::App().settings().proxy().list();
if (!ranges::contains(proxies, proxy)) {
proxies.push_back(proxy);
}
Core::App().setCurrentProxy(
proxy,
ProxyData::Settings::Enabled);
Local::writeSettings();
box->closeBox();
});
enableButton->setFullRadius(true);
box->events() | rpl::on_next([=](not_null<QEvent*> e) {
if ((e->type() != QEvent::KeyPress) || !enableButton) {
return;
}
const auto k = static_cast<QKeyEvent*>(e.get());
if (k->key() == Qt::Key_Enter || k->key() == Qt::Key_Return) {
enableButton->clicked(Qt::KeyboardModifiers(), Qt::LeftButton);
enableButton->clicked({}, Qt::LeftButton);
}
}, box->lifetime());
};
@@ -1481,98 +1702,49 @@ auto ProxiesBoxController::proxySettingsValue() const
}
void ProxiesBoxController::refreshChecker(Item &item) {
using Variants = MTP::DcOptions::Variants;
const auto type = (item.data.type == Type::Http)
? Variants::Http
: Variants::Tcp;
const auto mtproto = &_account->mtp();
const auto dcId = mtproto->mainDcId();
const auto forFiles = false;
item.state = ItemState::Checking;
const auto setup = [&](Checker &checker, const bytes::vector &secret) {
checker = MTP::details::AbstractConnection::Create(
mtproto,
type,
QThread::currentThread(),
secret,
item.data);
setupChecker(item.id, checker);
};
if (item.data.type == Type::Mtproto) {
const auto secret = item.data.secretFromMtprotoPassword();
setup(item.checker, secret);
item.checker->connectToServer(
item.data.host,
item.data.port,
secret,
dcId,
forFiles);
item.checkerv6 = nullptr;
} else {
const auto options = mtproto->dcOptions().lookup(
dcId,
MTP::DcType::Regular,
true);
const auto connect = [&](
Checker &checker,
Variants::Address address) {
const auto &list = options.data[address][type];
if (list.empty()
|| ((address == Variants::IPv6)
&& !Core::App().settings().proxy().tryIPv6())) {
checker = nullptr;
const auto id = item.id;
StartProxyCheck(
&_account->mtp(),
item.data,
item.checker,
item.checkerv6,
[=](Connection *raw, int pingTime) {
const auto item = ranges::find(
_list,
id,
[](const Item &item) { return item.id; });
if (item == end(_list)) {
return;
}
const auto &endpoint = list.front();
setup(checker, endpoint.secret);
checker->connectToServer(
QString::fromStdString(endpoint.ip),
endpoint.port,
endpoint.secret,
dcId,
forFiles);
};
connect(item.checker, Variants::IPv4);
connect(item.checkerv6, Variants::IPv6);
if (!item.checker && !item.checkerv6) {
item.state = ItemState::Unavailable;
}
DropProxyChecker(item->checker, item->checkerv6, raw);
ResetProxyCheckers(item->checker, item->checkerv6);
if (item->state == ItemState::Checking) {
item->state = ItemState::Available;
item->ping = pingTime;
updateView(*item);
}
},
[=](Connection *raw) {
const auto item = ranges::find(
_list,
id,
[](const Item &item) { return item.id; });
if (item == end(_list)) {
return;
}
DropProxyChecker(item->checker, item->checkerv6, raw);
if (!HasProxyCheckers(item->checker, item->checkerv6)
&& item->state == ItemState::Checking) {
item->state = ItemState::Unavailable;
updateView(*item);
}
});
if (!HasProxyCheckers(item.checker, item.checkerv6)) {
item.state = ItemState::Unavailable;
}
}
void ProxiesBoxController::setupChecker(int id, const Checker &checker) {
using Connection = MTP::details::AbstractConnection;
const auto pointer = checker.get();
pointer->connect(pointer, &Connection::connected, [=] {
const auto item = findById(id);
const auto pingTime = pointer->pingTime();
item->checker = nullptr;
item->checkerv6 = nullptr;
if (item->state == ItemState::Checking) {
item->state = ItemState::Available;
item->ping = pingTime;
updateView(*item);
}
});
const auto failed = [=] {
const auto item = findById(id);
if (item->checker == pointer) {
item->checker = nullptr;
} else if (item->checkerv6 == pointer) {
item->checkerv6 = nullptr;
}
if (!item->checker
&& !item->checkerv6
&& item->state == ItemState::Checking) {
item->state = ItemState::Unavailable;
updateView(*item);
}
};
pointer->connect(pointer, &Connection::disconnected, failed);
pointer->connect(pointer, &Connection::error, failed);
}
object_ptr<Ui::BoxContent> ProxiesBoxController::CreateOwningBox(
not_null<Main::Account*> account,
const QString &highlightId) {
@@ -117,7 +117,6 @@ private:
void share(const ProxyData &proxy, bool qr = false);
void saveDelayed();
void refreshChecker(Item &item);
void setupChecker(int id, const Checker &checker);
void replaceItemWith(
std::vector<Item>::iterator which,
@@ -169,7 +169,6 @@ LocalStorageBox::Row::Row(
sizeText(data),
st::localStorageRowSize)
, _clear(this, std::move(clear), st::localStorageClear) {
_clear->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
_clear->setVisible(data.count != 0);
}
@@ -217,7 +217,7 @@ void AddBotToGroupBoxController::addBotToGroup(not_null<PeerData*> chat) {
controller->hideLayer();
controller->showPeerHistory(chat, Way::ClearStack, ShowAtUnreadMsgId);
};
const auto rights = requestedAddAdmin
const auto rights = (requestedAddAdmin && _requestedRights != 0)
? _requestedRights
: (chat->isBroadcast()
&& chat->asBroadcast()->canAddAdmins())
@@ -125,6 +125,7 @@ void CreateManagedBotBox(
tr::lng_create_bot_username_placeholder(),
initialUsername,
QString());
username->setPlaceholderHidden(true);
username->setMaxLength(
Ui::EditPeer::kMaxUsernameLength - int(botSuffixText.size()));
usernameWrap->widthValue() | rpl::on_next([=](int width) {
@@ -133,6 +134,7 @@ void CreateManagedBotBox(
username->heightValue() | rpl::on_next([=](int height) {
usernameWrap->resize(usernameWrap->width(), height);
}, username->lifetime());
username->finishAnimating();
const auto botPrefix = Ui::CreateChild<Ui::FlatLabel>(
username,
@@ -391,10 +393,12 @@ void CreateManagedBotBox(
tr::rich),
u"managed_bots"_q);
}
} else if (MTP::IsFloodError(error)) {
show->showToast(tr::lng_flood_error(tr::now));
} else {
show->showToast(type);
}
}).send();
}).handleFloodErrors().send();
};
QObject::connect(username, &Ui::UsernameInput::changed, [=] {
@@ -1546,7 +1546,6 @@ not_null<Info::Profile::TopBar*> CreateProfilePreview(
}
void ProcessButton(not_null<Ui::RoundButton*> button) {
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
// Raise to be above right emoji from buttons.
crl::on_main(button, [=] { button->raise(); });
}
@@ -2426,10 +2425,12 @@ void EditPeerColorBox(
buttonContainer,
tr::lng_settings_color_apply(),
box->getDelegate()->style().button);
profileButton->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
const auto nameButton = Ui::CreateChild<Ui::RoundButton>(
buttonContainer,
tr::lng_settings_color_apply(),
box->getDelegate()->style().button);
nameButton->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
rpl::combine(
buttonContainer->widthValue(),
profileButton->sizeValue(),
@@ -477,8 +477,6 @@ void SelectFutureOwnerbox(
tr::lng_select_next_owner_box_confirm(),
tr::lng_close()),
st::defaultActiveButton);
button->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
const auto raw = button.data();
rpl::combine(
state->selectionChanges.events() | rpl::map_to(0),
@@ -523,7 +521,6 @@ void SelectFutureOwnerbox(
});
for (const auto &b : { select, cancel, leave }) {
b->setFullRadius(true);
b->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
}
box->setStyle(st::futureOwnerBox);
}
@@ -1985,7 +1985,6 @@ object_ptr<Ui::RpWidget> MakeActiveAuctionRow(
rpl::single(QString()),
st::auctionListRaise),
st::auctionListRaisePadding);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
auto secondsLeft = rpl::duplicate(
value
@@ -1556,10 +1556,12 @@ void StarGiftPreviewBox(
const style::RoundButton &st,
const style::icon &active,
Tab tab) {
auto owned = object_ptr<RoundButton>(buttonsParent, text(), st);
auto owned = object_ptr<RoundButton>(
buttonsParent,
text(),
st);
const auto raw = owned.data();
raw->setTextTransform(RoundButton::TextTransform::NoTransform);
raw->setClickedCallback([=] {
state->tab = tab;
});
@@ -35,7 +35,6 @@ void PrepareFullWidthRoundButton(
not_null<Ui::RoundButton*> button,
not_null<Ui::VerticalLayout*> content,
const style::margins &padding) {
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->setFullRadius(true);
const auto paddingHorizontal = padding.left() + padding.right();
content->widthValue() | rpl::on_next([=](int w) {
@@ -165,7 +164,6 @@ void ShowMatchCodesBox(
(overlay->height() - visible) / 2);
});
}
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->setFullRadius(true);
button->setClickedCallback([=] {
callback(code);
+1
View File
@@ -101,6 +101,7 @@ callButtonLabel: FlatLabel(defaultFlatLabel) {
style: TextStyle(defaultTextStyle) {
font: font(11px);
}
maxHeight: 16px;
}
callAnswer: CallButton {
@@ -258,7 +258,6 @@ void StartRtmpProcess::FillRtmpRows(
wrap.data(),
rpl::duplicate(text),
st::groupCallRtmpCopyButton);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->setClickedCallback(key
? Fn<void()>([=] {
QGuiApplication::clipboard()->setText(state->key.current());
@@ -272,6 +272,8 @@ ChooseSourceProcess::ChooseSourceProcess(
tr::lng_group_call_screen_share_audio(tr::now),
false,
st::desktopCaptureWithAudio)) {
_submit->setTextTransform(RoundButtonTextTransform::ToUpper);
_finish->setTextTransform(RoundButtonTextTransform::ToUpper);
setupPanel();
setupSources();
activate();
@@ -370,6 +372,7 @@ void ChooseSourceProcess::setupPanel() {
_bottom.get(),
tr::lng_cancel(),
st::desktopCaptureCancel);
cancel->setTextTransform(RoundButtonTextTransform::ToUpper);
cancel->setClickedCallback([=] {
_window->close();
});
@@ -207,7 +207,6 @@ PreviewWrap::PreviewWrap(
st::ttlMediaButton);
close->setFullRadius(true);
close->setClickedCallback(closeCallback);
close->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
rpl::combine(
sizeValue(),
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "core/deep_links/deep_links_router.h"
#include "base/qthelp_url.h"
#include "core/deep_links/deep_links_chats.h"
#include "core/deep_links/deep_links_contacts.h"
#include "core/deep_links/deep_links_new.h"
@@ -33,7 +34,7 @@ Context ParseCommand(
for (const auto &pair : query.split('&')) {
const auto eq = pair.indexOf('=');
if (eq > 0) {
result.params[pair.left(eq).toLower()] = pair.mid(eq + 1);
result.params[pair.left(eq).toLower()] = qthelp::url_decode(pair.mid(eq + 1));
} else if (!pair.isEmpty()) {
result.params[pair.toLower()] = QString();
}
@@ -392,6 +392,8 @@ bool ApplyMtprotoProxy(
auto params = url_parse_params(
match->captured(1),
qthelp::UrlParamNameTransform::ToLower);
auto &secret = params[u"secret"_q];
secret.replace('+', '-').replace('/', '_');
ProxiesBoxController::ShowApplyConfirmation(
controller,
MTP::ProxyData::Type::Mtproto,
@@ -464,7 +466,9 @@ bool ShowWallPaper(
const QString &value) {
auto result = ChatAdminRights();
for (const auto &element : value.split(QRegularExpression(u"[+ ]"_q))) {
if (element == u"change_info"_q) {
if (element.isEmpty()) {
continue;
} else if (element == u"change_info"_q) {
result |= ChatAdminRight::ChangeInfo;
} else if (element == u"post_messages"_q) {
result |= ChatAdminRight::PostMessages;
@@ -482,6 +486,12 @@ bool ShowWallPaper(
result |= ChatAdminRight::PinMessages;
} else if (element == u"promote_members"_q) {
result |= ChatAdminRight::AddAdmins;
} else if (element == u"post_stories"_q) {
result |= ChatAdminRight::PostStories;
} else if (element == u"edit_stories"_q) {
result |= ChatAdminRight::EditStories;
} else if (element == u"delete_stories"_q) {
result |= ChatAdminRight::DeleteStories;
} else if (element == u"manage_video_chats"_q) {
result |= ChatAdminRight::ManageCall;
} else if (element == u"manage_direct_messages"_q) {
@@ -491,7 +501,7 @@ bool ShowWallPaper(
} else if (element == u"manage_chat"_q) {
result |= ChatAdminRight::Other;
} else {
return {};
continue;
}
}
return result;
@@ -1940,7 +1950,7 @@ QString TryConvertUrlToLocal(QString url) {
} else if (const auto callMatch = regex_match(u"^call/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"_q, query, matchOptions)) {
const auto slug = callMatch->captured(1);
return u"tg://call?slug="_q + slug;
} else if (const auto newbotMatch = regex_match(u"^newbot/([a-zA-Z0-9\\.\\_]+)(/([a-zA-Z0-9\\.\\_]+))?(\\?(.+))?$"_q, query, matchOptions)) {
} else if (const auto newbotMatch = regex_match(u"^newbot/([a-zA-Z0-9\\.\\_]+)(/([a-zA-Z0-9\\.\\_]*))?(/?\\?(.+))?$"_q, query, matchOptions)) {
const auto manager = newbotMatch->captured(1);
const auto username = newbotMatch->captured(3);
const auto params = newbotMatch->captured(5);
+2 -2
View File
@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D666}"_cs;
constexpr auto AppNameOld = "AyuGram for Windows"_cs;
constexpr auto AppName = "AyuGram Desktop"_cs;
constexpr auto AppFile = "AyuGram"_cs;
constexpr auto AppVersion = 6007002;
constexpr auto AppVersionStr = "6.7.2";
constexpr auto AppVersion = 6007004;
constexpr auto AppVersionStr = "6.7.4";
constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
+18 -1
View File
@@ -174,7 +174,20 @@ struct FileReferenceAccumulator {
});
}
void push(const MTPusers_UserFull &data) {
push(data.data().vfull_user().data().vpersonal_photo());
const auto &full = data.data().vfull_user().data();
push(full.vpersonal_photo());
push(full.vfallback_photo());
push(full.vprofile_photo());
}
void push(const MTPChatFull &data) {
data.match([&](const MTPDchatFull &data) {
push(data.vchat_photo());
}, [&](const MTPDchannelFull &data) {
push(data.vchat_photo());
});
}
void push(const MTPmessages_ChatFull &data) {
push(data.data().vfull_chat());
}
void push(const MTPmessages_RecentStickers &data) {
data.match([&](const MTPDmessages_recentStickers &data) {
@@ -246,6 +259,10 @@ UpdatedFileReferences GetFileReferences(const MTPusers_UserFull &data) {
return GetFileReferencesHelper(data);
}
UpdatedFileReferences GetFileReferences(const MTPmessages_ChatFull &data) {
return GetFileReferencesHelper(data);
}
UpdatedFileReferences GetFileReferences(
const MTPmessages_RecentStickers &data) {
return GetFileReferencesHelper(data);
@@ -208,6 +208,7 @@ struct UpdatedFileReferences {
UpdatedFileReferences GetFileReferences(const MTPmessages_Messages &data);
UpdatedFileReferences GetFileReferences(const MTPphotos_Photos &data);
UpdatedFileReferences GetFileReferences(const MTPusers_UserFull &data);
UpdatedFileReferences GetFileReferences(const MTPmessages_ChatFull &data);
UpdatedFileReferences GetFileReferences(
const MTPmessages_RecentStickers &data);
UpdatedFileReferences GetFileReferences(
+1 -1
View File
@@ -566,7 +566,7 @@ Data::FileOrigin PeerData::userpicOrigin() const {
Data::FileOrigin PeerData::userpicPhotoOrigin() const {
return (isUser() && userpicPhotoId())
? Data::FileOriginUserPhoto(peerToUser(id).bare, userpicPhotoId())
? Data::FileOriginFullUser(peerToUser(id))
: Data::FileOrigin();
}
+5 -1
View File
@@ -919,7 +919,8 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
: Flag())
| (user->starsPerMessage() ? Flag::HasStarsPerMessage : Flag())
| Flag::MessageMoneyRestrictionsKnown
| Flag::RequiresPremiumToWrite;
| Flag::RequiresPremiumToWrite
| Flag::UnofficialSecurityRisk;
user->setFlags((user->flags() & ~mask)
| (update.is_phone_calls_private()
? Flag::PhoneCallsPrivate
@@ -935,6 +936,9 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
| Flag::MessageMoneyRestrictionsKnown
| (update.is_contact_require_premium()
? (Flag::RequiresPremiumToWrite | Flag::HasRequirePremiumToWrite)
: Flag())
| (update.is_unofficial_security_risk()
? Flag::UnofficialSecurityRisk
: Flag()));
user->setIsBlocked(update.is_blocked());
user->setCallsStatus(update.is_phone_calls_private()
+5 -1
View File
@@ -130,7 +130,7 @@ enum class UserDataFlag : uint32 {
DiscardMinPhoto = (1 << 12),
Self = (1 << 13),
Premium = (1 << 14),
//CanReceiveGifts = (1 << 15),
UnofficialSecurityRisk = (1 << 15),
VoiceMessagesForbidden = (1 << 16),
PersonalPhoto = (1 << 17),
StoriesHidden = (1 << 18),
@@ -304,6 +304,10 @@ public:
[[nodiscard]] UserId botManagerId() const;
void setBotManagerId(UserId managerId);
[[nodiscard]] bool unofficialSecurityRisk() const {
return flags() & Flag::UnofficialSecurityRisk;
}
[[nodiscard]] MTPInputUser inputUser() const;
QString firstName;
@@ -4468,8 +4468,6 @@ void InnerWidget::refreshEmpty() {
this,
tr::lng_no_conversations_button(),
st::dialogEmptyButton);
_emptyButton->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
_emptyButton->setVisible(isListVisible);
_emptyButton->setClickedCallback([=, window = _controller] {
window->show(PrepareContactsBox(window));
@@ -131,8 +131,6 @@ not_null<Ui::SlideWrap<Ui::VerticalLayout>*> CreateUnconfirmedAuthContent(
buttons,
tr::lng_unconfirmed_auth_deny(),
st::dialogsUnconfirmedAuthButtonNo);
yes->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
no->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
yes->setClickedCallback([=] {
wrap->toggle(false, anim::type::normal);
base::call_delayed(st::universalDuration, wrap, [=] {
@@ -372,7 +370,6 @@ void TopBarSuggestionContent::setRightButton(
_rightButton->moveToRight(top, top, outer.width());
}, _rightButton->lifetime());
_rightButton->setFullRadius(true);
_rightButton->setTextTransform(RoundButton::TextTransform::NoTransform);
_rightButton->setClickedCallback(std::move(callback));
_rightButton->show();
}
@@ -187,7 +187,6 @@ void PostsSearchIntro::setup() {
rpl::single(QString()),
st::postsSearchIntroButton),
style::al_top);
_button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
_footer = _content->add(
object_ptr<Ui::FlatLabel>(
_content.get(),
@@ -297,7 +297,6 @@ rpl::producer<> ProgressWidget::doneClicks() const {
}
void ProgressWidget::setupBottomButton(not_null<Ui::RoundButton*> button) {
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->show();
sizeValue(
@@ -888,7 +888,6 @@ void SettingsWidget::refreshButtons(
st::defaultBoxButton)
: nullptr;
if (start) {
start->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
start->show();
_startClicks = start->clicks() | rpl::to_empty;
@@ -904,7 +903,6 @@ void SettingsWidget::refreshButtons(
container.get(),
tr::lng_cancel(),
st::defaultBoxButton);
cancel->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
cancel->show();
_cancelClicks = cancel->clicks() | rpl::to_empty;
@@ -182,7 +182,7 @@ FrameGenerator::Frame FrameGenerator::Impl::renderCurrent(
const auto withAlpha = bgra || (srcFormat == AV_PIX_FMT_YUVA420P);
const auto dstPerLine = storage.bytesPerLine();
auto dst = storage.bits() + dx * sizeof(int32) + dy * dstPerLine;
if (srcSize == dstSize && bgra) {
if (bgra && srcSize == dstSize && frame->linesize[0] > 0) {
const auto srcPerLine = frame->linesize[0];
const auto perLine = std::min(srcPerLine, int(dstPerLine));
auto src = frame->data[0];
@@ -691,7 +691,7 @@ QImage CreateFrameStorage(QSize size) {
? (widthAlign - (width % widthAlign))
: 0);
const auto perLine = neededWidth * kPixelBytesSize;
const auto buffer = new uchar[perLine * height + kAlignImageBy];
const auto buffer = new uchar[size_t(perLine) * height + kAlignImageBy];
const auto cleanupData = static_cast<void *>(buffer);
const auto address = reinterpret_cast<uintptr_t>(buffer);
const auto alignedBuffer = buffer + ((address % kAlignImageBy)
@@ -54,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/power_saving.h"
#include "ui/controls/compose_ai_button_factory.h"
#include "ui/controls/emoji_button.h"
#include "ui/controls/send_button.h"
#include "ui/controls/send_as_button.h"
@@ -6075,8 +6076,6 @@ bool HistoryWidget::updateCmdStartShown() {
st::historyBotMenuButton);
orderWidgets();
_botMenu.button->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
_botMenu.button->setFullRadius(true);
_botMenu.button->setClickedCallback([=] {
const auto user = _peer ? _peer->asUser() : nullptr;
@@ -6440,21 +6439,9 @@ bool HistoryWidget::fieldOrDisabledShown() const {
}
bool HistoryWidget::hasEnoughLinesForAi() const {
if (!_history
|| _voiceRecordBar->isActive()
|| !AyuSettings::getInstance().showCocoonAiButtonInMessageField()
|| session().appConfig().aiComposeStyles().empty()) {
return false;
}
const auto &style = _field->st().style;
const auto lineHeight = style.lineHeight
? style.lineHeight
: style.font->height;
const auto margins = _field->fullTextMargins();
const auto contentHeight = _field->height()
- margins.top()
- margins.bottom();
return contentHeight >= (3 * lineHeight);
return _history
&& !_voiceRecordBar->isActive()
&& Ui::HasEnoughLinesForAi(&session(), _field);
}
void HistoryWidget::updateAiButtonVisibility() {
@@ -92,6 +92,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/dropdown_menu.h"
#include "ui/widgets/popup_menu.h"
#include "ui/text/format_values.h"
#include "ui/controls/compose_ai_button_factory.h"
#include "ui/controls/emoji_button.h"
#include "ui/controls/send_button.h"
#include "ui/controls/send_as_button.h"
@@ -3127,7 +3128,6 @@ void SetupRestrictionView(
st->premiumRequired.button);
unlock->show();
unlock->setAttribute(Qt::WA_TransparentForMouseEvents);
unlock->setTextTransform(RoundButton::TextTransform::NoTransform);
unlock->setFullRadius(true);
return unlock;
};
@@ -3698,21 +3698,9 @@ bool ComposeControls::canSendAiComposeDirect() const {
}
bool ComposeControls::hasEnoughLinesForAi() const {
if (!_history
|| _recording.current()
|| !AyuSettings::getInstance().showCocoonAiButtonInMessageField()
|| session().appConfig().aiComposeStyles().empty()) {
return false;
}
const auto &style = _field->st().style;
const auto lineHeight = style.lineHeight
? style.lineHeight
: style.font->height;
const auto margins = _field->fullTextMargins();
const auto contentHeight = _field->height()
- margins.top()
- margins.bottom();
return contentHeight >= (3 * lineHeight);
return _history
&& !_recording.current()
&& Ui::HasEnoughLinesForAi(&session(), _field);
}
bool ComposeControls::updateBotCommandShown() {
@@ -1019,8 +1019,6 @@ BusinessBotStatus::Bar::Bar(QWidget *parent)
_name->setAttribute(Qt::WA_TransparentForMouseEvents);
_status->setAttribute(Qt::WA_TransparentForMouseEvents);
_togglePaused->setFullRadius(true);
_togglePaused->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
_settings->setClickedCallback([=] {
showMenu();
});
@@ -192,7 +192,6 @@ auto WithPinnedTitle(not_null<Main::Session*> session, PinnedId id) {
label->setTextColorOverride(stButton.textFg->c); // Use button's text color for label.
label->setAttribute(Qt::WA_TransparentForMouseEvents);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->setFullRadius(true);
button->setClickedCallback(std::move(clickCallback));
@@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/dropdown_menu.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/shadow.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/text/text_utilities.h"
@@ -56,7 +57,7 @@ void SetupOverlayHideOnEscape(
struct PreviewOverlayState {
base::unique_qptr<Window::MediaPreviewWidget> mediaPreview;
base::unique_qptr<Ui::AbstractButton> clickable;
base::unique_qptr<Ui::DropdownMenu> menu;
base::unique_qptr<Ui::FadeWrap<Ui::DropdownMenu>> menuWrap;
base::unique_qptr<Ui::AbstractButton> background;
base::unique_qptr<Ui::FlatLabel> label;
Fn<void()> extraHide;
@@ -64,7 +65,7 @@ struct PreviewOverlayState {
void clear() {
shutdownGuard.destroy();
menu.reset();
menuWrap.reset();
background.reset();
label.reset();
mediaPreview.reset();
@@ -131,18 +132,23 @@ void SetupPreviewMenu(
const auto mainwidget = controller->widget()->bodyWidget();
if (fillMenu) {
state->mediaPreview->setHideEmoji(true);
state->menu = base::make_unique_q<Ui::DropdownMenu>(
auto menu = object_ptr<Ui::DropdownMenu>(
mainwidget,
st::dropdownMenuWithIcons);
state->menu->setAutoHiding(false);
state->menu->setHiddenCallback(
menu->setAutoHiding(false);
menu->setHiddenCallback(
crl::guard(state->clickable.get(), overlay.hideAll));
fillMenu(state->menu.get());
fillMenu(menu.data());
state->menuWrap = base::make_unique_q<Ui::FadeWrap<Ui::DropdownMenu>>(
mainwidget,
std::move(menu));
state->menuWrap->setDuration(st::defaultToggle.duration);
state->menuWrap->hide(anim::type::instant);
}
const auto menuRaw = state->menu.get();
const auto wrapRaw = state->menuWrap.get();
state->extraHide = [=] {
if (menuRaw) {
menuRaw->hideAnimated();
if (wrapRaw) {
wrapRaw->hide(anim::type::normal);
}
};
@@ -150,7 +156,9 @@ void SetupPreviewMenu(
mainwidget->sizeValue() | rpl::on_next([=](QSize size) {
mediaPreviewRaw->setGeometry(Rect(size));
if (menuRaw) {
if (wrapRaw) {
const auto menuRaw = wrapRaw->entity();
menuRaw->showFast();
const auto gap = st::defaultMenu.itemPadding.top();
const auto menuH = menuRaw->height();
const auto shift = -(gap + menuH) / 2;
@@ -158,9 +166,9 @@ void SetupPreviewMenu(
const auto menuX = (size.width() - menuRaw->width()) / 2;
const auto menuY = mediaPreviewRaw->contentBottom() + gap;
menuRaw->move(menuX, menuY);
menuRaw->showAnimated(Ui::PanelAnimation::Origin::TopLeft);
menuRaw->raise();
wrapRaw->move(menuX, menuY);
wrapRaw->show(anim::type::normal);
wrapRaw->raise();
}
}, mediaPreviewRaw->lifetime());
}
@@ -309,7 +317,7 @@ void ShowWidgetPreview(
struct State {
base::unique_qptr<Ui::RpWidget> preview;
base::unique_qptr<Ui::AbstractButton> clickable;
base::unique_qptr<Ui::DropdownMenu> menu;
base::unique_qptr<Ui::FadeWrap<Ui::DropdownMenu>> menuWrap;
};
const auto state = std::make_shared<State>();
const auto mainwidget = controller->widget()->bodyWidget();
@@ -326,28 +334,33 @@ void ShowWidgetPreview(
const auto hideAll = [=] {
state->clickable->setAttribute(Qt::WA_TransparentForMouseEvents);
if (state->menu) {
state->menu->hideAnimated();
if (state->menuWrap) {
state->menuWrap->hide(anim::type::normal);
}
base::call_delayed(
st::defaultToggle.duration,
[s = state] {
s->preview.reset();
s->menu.reset();
s->menuWrap.reset();
s->clickable.reset();
});
};
SetupOverlayHideOnEscape(state->clickable.get(), hideAll);
state->menu = base::make_unique_q<Ui::DropdownMenu>(
auto menu = object_ptr<Ui::DropdownMenu>(
mainwidget,
st::dropdownMenuWithIcons);
state->menu->setAutoHiding(false);
state->menu->setHiddenCallback(
menu->setAutoHiding(false);
menu->setHiddenCallback(
crl::guard(state->clickable.get(), hideAll));
fillMenu(state->menu.get());
fillMenu(menu.data());
state->menuWrap = base::make_unique_q<Ui::FadeWrap<Ui::DropdownMenu>>(
mainwidget,
std::move(menu));
state->menuWrap->setDuration(st::defaultToggle.duration);
state->menuWrap->hide(anim::type::instant);
const auto menuRaw = state->menu.get();
const auto wrapRaw = state->menuWrap.get();
state->clickable->show();
previewRaw->show();
@@ -363,17 +376,19 @@ void ShowWidgetPreview(
state->clickable->setGeometry(Rect(size));
state->clickable->raise();
const auto menuRaw = wrapRaw->entity();
menuRaw->showFast();
const auto gap = st::defaultMenu.itemPadding.top();
const auto totalH = fullH + gap + menuRaw->height();
const auto previewY = (size.height() - totalH) / 2;
previewRaw->move((size.width() - fullW) / 2, previewY);
previewRaw->raise();
menuRaw->move(
wrapRaw->move(
(size.width() - menuRaw->width()) / 2,
previewY + fullH + gap);
menuRaw->showAnimated(Ui::PanelAnimation::Origin::TopLeft);
menuRaw->raise();
wrapRaw->show(anim::type::normal);
wrapRaw->raise();
}, previewRaw->lifetime());
}
@@ -1751,7 +1751,6 @@ bool ShowScheduledVideoPublished(
widget.get(),
rpl::single(view),
st::processingVideoView);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->show();
rpl::combine(
widget->sizeValue(),
@@ -202,7 +202,6 @@ void StickerToast::showWithTitle(const QString &title) {
widget.get(),
rpl::single(view),
st::historyPremiumViewSet);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->show();
rpl::combine(
widget->sizeValue(),
@@ -73,7 +73,7 @@ void SummaryHeader::update(not_null<Element*> view) {
}
}
if (const auto item = session->data().message(itemId)) {
session->api().transcribes().toggleSummary(item, nullptr);
session->api().transcribes().toggleSummary(item);
}
});
}
@@ -144,6 +144,11 @@ TopBarWidget::TopBarWidget(
, _onlineUpdater([=] { updateOnlineDisplay(); }) {
setAttribute(Qt::WA_OpaquePaintEvent);
_clear->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
_forward->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
_sendNow->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
_delete->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
Lang::Updated(
) | rpl::on_next([=] {
refreshLang();
@@ -1128,7 +1133,7 @@ void TopBarWidget::updateControlsGeometry() {
_messageShot->moveToLeft(buttonsLeft, selectedButtonsTop);
{
const auto large = _forward->height() / 3;
const auto large = st::topBarActionButtonLargeRadius;
const auto &buttonSt = st::defaultActiveButton;
const auto small = buttonSt.radius
? buttonSt.radius
@@ -1526,7 +1531,8 @@ void TopBarWidget::showSelected(SelectedState state) {
_messageShot->finishNumbersAnimation();
}
}
if (visibilityChanged) {
if (visibilityChanged
|| (!wasSelectedState && nowSelectedState)) {
updateControlsVisibility();
}
if (wasSelectedState != nowSelectedState && !_chooseForReportReason) {
@@ -90,10 +90,11 @@ void ShowTopPeersSelector(
const auto contentHeight = int(
st::topPeersSelectorUserpicSize
* (1. + st::topPeersSelectorUserpicExpand));
const auto selectorWidth = contentWidth
+ 2 * st::topPeersSelectorPadding;
const auto selectorHeight = contentHeight
+ 2 * st::topPeersSelectorPadding;
const auto selectorWidth = (peers.size() == 1)
? selectorHeight
: (contentWidth + 2 * st::topPeersSelectorPadding);
struct State {
base::unique_qptr<Ui::PopupSelector> selector;
@@ -159,7 +160,10 @@ void ShowTopPeersSelector(
peers[info.index]->isSelf()
? tr::lng_saved_messages(tr::rich)
: NameValue(peers[info.index]) | rpl::map(tr::rich),
userpicsWidget->width(),
std::max(
userpicsWidget->width(),
st::topPeersSelectorImportantTooltipLabel.minWidth
+ st::lineWidth),
st::topPeersSelectorImportantTooltipLabel),
st::topPeersSelectorImportantTooltip.padding),
st::topPeersSelectorImportantTooltip);
@@ -84,7 +84,8 @@ void TranscribeButton::setLoading(bool loading) {
item,
_lastPaintedPoint.isNull()
? QRect()
: QRect(_lastPaintedPoint, size()));
: (QRect(_lastPaintedPoint, size()))
+ Margins(st::lineWidth));
}
},
st::historyTranscribeRadialAnimation);
@@ -380,7 +381,7 @@ ClickHandlerPtr TranscribeButton::link() {
if (session->premium()) {
auto &transcribes = session->api().transcribes();
return summarize
? transcribes.toggleSummary(item, nullptr)
? transcribes.toggleSummary(item)
: transcribes.toggle(item);
}
const auto my = context.other.value<ClickHandlerContext>();
@@ -409,15 +410,7 @@ ClickHandlerPtr TranscribeButton::link() {
}
}
if (summarize) {
const auto weak = my.sessionWindow;
session->api().transcribes().toggleSummary(item, [=] {
if (const auto strong = weak.get()) {
Settings::ShowPremium(strong, u"summary"_q);
// ShowPremiumPreviewBox(
// strong,
// PremiumFeature::VoiceToText);
}
});
session->api().transcribes().toggleSummary(item);
} else {
session->api().transcribes().toggle(item);
}
@@ -606,7 +606,6 @@ void TranslateBar::showToast(
widget.get(),
rpl::single(buttonText),
st::historyPremiumViewSet);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->show();
rpl::combine(
widget->sizeValue(),
@@ -198,12 +198,14 @@ struct PollThumbnailData {
[[nodiscard]] PollThumbnailData MakePollThumbnail(
not_null<PollData*> poll,
const PollAnswer &answer,
Window::SessionController::MessageContext messageContext);
Window::SessionController::MessageContext messageContext,
Fn<bool()> paused = nullptr);
[[nodiscard]] PollThumbnailData MakePollThumbnail(
not_null<PollData*> poll,
const PollMedia &media,
Window::SessionController::MessageContext messageContext) {
Window::SessionController::MessageContext messageContext,
Fn<bool()> paused = nullptr) {
auto result = PollThumbnailData();
if (!media) {
return result;
@@ -220,7 +222,8 @@ struct PollThumbnailData {
if (media.document->sticker()) {
result.thumbnail = Ui::MakeEmojiThumbnail(
&poll->owner(),
Data::SerializeCustomEmojiId(media.document));
Data::SerializeCustomEmojiId(media.document),
paused);
result.kind = PollThumbnailKind::Emoji;
} else if (media.document->isSong()
|| media.document->isVoiceMessage()) {
@@ -292,8 +295,10 @@ struct PollThumbnailData {
PollThumbnailData MakePollThumbnail(
not_null<PollData*> poll,
const PollAnswer &answer,
Window::SessionController::MessageContext messageContext) {
auto result = MakePollThumbnail(poll, answer.media, messageContext);
Window::SessionController::MessageContext messageContext,
Fn<bool()> paused) {
auto result
= MakePollThumbnail(poll, answer.media, messageContext, paused);
if (result.kind == PollThumbnailKind::Emoji && result.id) {
const auto documentId = DocumentId(result.id);
const auto option = answer.option;
@@ -366,7 +371,8 @@ struct Poll::Answer {
not_null<PollData*> poll,
const PollAnswer &original,
Window::SessionController::MessageContext messageContext,
Fn<void()> repaint);
Fn<void()> repaint,
Fn<bool()> paused);
Ui::Text::String text;
QByteArray option;
@@ -1737,11 +1743,13 @@ void Poll::Answer::fillMedia(
not_null<PollData*> poll,
const PollAnswer &original,
Window::SessionController::MessageContext messageContext,
Fn<void()> repaint) {
Fn<void()> repaint,
Fn<bool()> paused) {
const auto updated = MakePollThumbnail(
poll,
original,
messageContext);
messageContext,
paused);
const auto same = (updated.kind == thumbnailKind)
&& (updated.id == thumbnailId)
&& (updated.rounded == thumbnailRounded);
@@ -2040,7 +2048,11 @@ void Poll::updateTexts() {
options,
Core::TextContext({
.session = &_poll->session(),
.repaint = [=] { repaint(); },
.repaint = [=] {
if (!_parent->delegate()->elementAnimationsPaused()) {
repaint();
}
},
.customEmojiLoopLimit = 2,
}));
}
@@ -2100,7 +2112,11 @@ void Poll::Header::updateDescription() {
}
const auto context = Core::TextContext({
.session = &_owner->_poll->session(),
.repaint = [=] { _owner->_parent->customEmojiRepaint(); },
.repaint = [=] {
if (!_owner->_parent->delegate()->elementAnimationsPaused()) {
_owner->_parent->customEmojiRepaint();
}
},
.customEmojiLoopLimit = 2,
});
_description.setMarkedText(
@@ -2126,7 +2142,11 @@ void Poll::Header::updateSolutionText() {
Ui::ItemTextOptions(_owner->_parent->data()),
Core::TextContext({
.session = &_owner->_poll->session(),
.repaint = [=] { _owner->repaint(); },
.repaint = [=] {
if (!_owner->_parent->delegate()->elementAnimationsPaused()) {
_owner->repaint();
}
},
}));
InitElementTextPart(_owner->_parent, _solutionText);
}
@@ -2138,10 +2158,14 @@ void Poll::Header::updateSolutionMedia() {
.topicRootId = item->topicRootId(),
.monoforumPeerId = item->sublistPeerId(),
};
const auto paused = [=] {
return _owner->_parent->delegate()->elementAnimationsPaused();
};
const auto updated = MakePollThumbnail(
_owner->_poll,
_owner->_poll->solutionMedia,
messageContext);
messageContext,
paused);
if (!updated.thumbnail) {
_solutionMedia = nullptr;
_solutionAttach = nullptr;
@@ -2189,10 +2213,14 @@ void Poll::Header::updateAttachedMedia() {
.topicRootId = item->topicRootId(),
.monoforumPeerId = item->sublistPeerId(),
};
const auto paused = [=] {
return _owner->_parent->delegate()->elementAnimationsPaused();
};
const auto updated = MakePollThumbnail(
_owner->_poll,
_owner->_poll->attachedMedia,
messageContext);
messageContext,
paused);
const auto same = (_attachedMedia->kind == updated.kind)
&& (_attachedMedia->id == updated.id)
&& (_attachedMedia->rounded == updated.rounded);
@@ -2220,8 +2248,8 @@ void Poll::Header::updateAttachedMedia() {
_owner->_parent->data()->fullId());
if (const auto size = photo->size(Data::PhotoSize::Large)) {
_attachedMedia->photoSize = *size;
} else if (const auto size = photo->size(Data::PhotoSize::Thumbnail)) {
_attachedMedia->photoSize = *size;
} else if (const auto s = photo->size(Data::PhotoSize::Thumbnail)) {
_attachedMedia->photoSize = *s;
}
}
if ((updated.kind == PollThumbnailKind::Document
@@ -2238,8 +2266,10 @@ void Poll::Header::updateAttachedMedia() {
if (_attachedMedia->thumbnail) {
_attachedMedia->thumbnail->subscribeToUpdates(
crl::guard(_owner, [=] {
_attachedMediaCache = QImage();
_owner->repaint();
if (!_owner->_parent->delegate()->elementAnimationsPaused()) {
_attachedMediaCache = QImage();
_owner->repaint();
}
}));
}
}
@@ -2421,28 +2451,35 @@ uint16 Poll::Header::solutionSelectionLength() const {
: uint16(0);
}
TextSelection Poll::Header::toSolutionSelection(TextSelection selection) const {
TextSelection Poll::Header::toSolutionSelection(
TextSelection selection) const {
return UnshiftItemSelection(selection, _description);
}
TextSelection Poll::Header::fromSolutionSelection(TextSelection selection) const {
TextSelection Poll::Header::fromSolutionSelection(
TextSelection selection) const {
return ShiftItemSelection(selection, _description);
}
TextSelection Poll::Header::toQuestionSelection(TextSelection selection) const {
TextSelection Poll::Header::toQuestionSelection(
TextSelection selection) const {
return UnshiftItemSelection(
selection,
uint16(_description.length() + solutionSelectionLength()));
}
TextSelection Poll::Header::fromQuestionSelection(TextSelection selection) const {
TextSelection Poll::Header::fromQuestionSelection(
TextSelection selection) const {
return ShiftItemSelection(
selection,
uint16(_description.length() + solutionSelectionLength()));
}
void Poll::Options::checkQuizAnswered() {
if (!_owner->_voted || !_votedFromHere || !_owner->_poll->quiz() || anim::Disabled()) {
if (!_owner->_voted
|| !_votedFromHere
|| !_owner->_poll->quiz()
|| anim::Disabled()) {
return;
}
const auto i = ranges::find(_answers, true, &Answer::chosen);
@@ -2532,10 +2569,21 @@ void Poll::Header::updateRecentVoters() {
void Poll::Options::updateAnswers() {
const auto context = Core::TextContext({
.session = &_owner->_poll->session(),
.repaint = [=] { _owner->repaint(); },
.repaint = [=] {
if (!_owner->_parent->delegate()->elementAnimationsPaused()) {
_owner->repaint();
}
},
.customEmojiLoopLimit = 2,
});
const auto repaintThumbnail = crl::guard(_owner, [=] { _owner->repaint(); });
const auto repaintThumbnail = crl::guard(_owner, [=] {
if (!_owner->_parent->delegate()->elementAnimationsPaused()) {
_owner->repaint();
}
});
const auto paused = [=] {
return _owner->_parent->delegate()->elementAnimationsPaused();
};
const auto item = _owner->_parent->data();
const auto messageContext = Window::SessionController::MessageContext{
.id = item->fullId(),
@@ -2569,7 +2617,12 @@ void Poll::Options::updateAnswers() {
&PollAnswer::option);
Assert(i != end(_owner->_poll->answers));
answer.fillData(_owner->_poll, *i, context);
answer.fillMedia(_owner->_poll, *i, messageContext, repaintThumbnail);
answer.fillMedia(
_owner->_poll,
*i,
messageContext,
repaintThumbnail,
paused);
}
_anyAnswerHasMedia = ranges::any_of(_answers, [](const Answer &a) {
return a.thumbnail != nullptr;
@@ -2586,7 +2639,12 @@ void Poll::Options::updateAnswers() {
&PollAnswer::option);
Assert(i != end(_owner->_poll->answers));
result.fillData(_owner->_poll, *i, context);
result.fillMedia(_owner->_poll, *i, messageContext, repaintThumbnail);
result.fillMedia(
_owner->_poll,
*i,
messageContext,
repaintThumbnail,
paused);
return result;
}) | ranges::to_vector;
@@ -2995,7 +3053,9 @@ void Poll::Header::paintSolutionBlock(
}
if (!_closeSolutionLink) {
_closeSolutionLink = std::make_shared<LambdaClickHandler>(
crl::guard(_owner, [=] { _owner->_headerPart->solutionToggled(false); }));
crl::guard(
_owner,
[=] { _owner->_headerPart->solutionToggled(false); }));
}
const auto &qst = st::historyPagePreview;
@@ -3376,11 +3436,15 @@ void Poll::Options::paintRadio(
const auto o = p.opacity();
if (checkmark < 1.) {
p.setBrush(Qt::NoBrush);
p.setOpacity(o * (over ? st::historyPollRadioOpacityOver : st::historyPollRadioOpacity));
p.setOpacity(o
* (over
? st::historyPollRadioOpacityOver
: st::historyPollRadioOpacity));
}
const auto multiChoice = (_owner->_flags & PollData::Flag::MultiChoice);
const auto rect = QRectF(left, top, radio.diameter, radio.diameter).marginsRemoved(QMarginsF(radio.thickness / 2., radio.thickness / 2., radio.thickness / 2., radio.thickness / 2.));
const auto rect = QRectF(left, top, radio.diameter, radio.diameter)
- Margins(radio.thickness / 2.);
const auto radius = st::historyPollCheckboxRadius;
if (_sendingAnimation && _sendingAnimation->option == answer.option) {
const auto &active = stm->msgServiceFg;
@@ -3427,7 +3491,11 @@ void Poll::Options::paintRadio(
p.drawEllipse(inner);
}
const auto &icon = stm->historyPollChosen;
icon.paint(p, left + (radio.diameter - icon.width()) / 2, top + (radio.diameter - icon.height()) / 2, _owner->width());
icon.paint(
p,
left + (radio.diameter - icon.width()) / 2,
top + (radio.diameter - icon.height()) / 2,
_owner->width());
}
}
@@ -3451,7 +3519,12 @@ void Poll::Options::paintPercent(
p.setFont(st::historyPollPercentFont);
p.setPen(stm->historyTextFg);
const auto pleft = aleft - percentWidth - st::historyPollPercentSkip;
p.drawTextLeft(pleft, top + st::historyPollPercentTop, outerWidth, percent, percentWidth);
p.drawTextLeft(
pleft,
top + st::historyPollPercentTop,
outerWidth,
percent,
percentWidth);
}
void Poll::Options::paintFilling(
@@ -3474,7 +3547,8 @@ void Poll::Options::paintFilling(
const auto thickness = st::historyPollFillingHeight;
const auto max = contentWidth - st::historyPollFillingRight;
const auto size = anim::interpolate(st::historyPollFillingMin, max, filling);
const auto size
= anim::interpolate(st::historyPollFillingMin, max, filling);
const auto radius = st::historyPollFillingRadius;
const auto ftop = top
+ std::max(st::historyPollPercentFont->height, contentHeight)
@@ -3488,7 +3562,10 @@ void Poll::Options::paintFilling(
const auto style = [&] {
if (chosen && !correct) {
return Style::Incorrect;
} else if (chosen && correct && _owner->_poll->quiz() && !context.outbg) {
} else if (chosen
&& correct
&& _owner->_poll->quiz()
&& !context.outbg) {
return Style::Correct;
} else {
return Style::Default;
@@ -3603,7 +3680,8 @@ bool Poll::Options::checkAnimationStart() const {
// Skip initial changes.
return false;
}
const auto result = (_owner->showVotes() != (_owner->_poll->voted() || _owner->_poll->closed()))
const auto result = _owner->showVotes()
!= (_owner->_poll->voted() || _owner->_poll->closed())
|| answerVotesChanged();
if (result) {
saveStateInAnimation();
@@ -449,6 +449,7 @@ private:
rpl::single(QString()),
st::starrefBottomButton);
const auto raw = result.data();
raw->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
rpl::combine(
parent->widthValue(),
raw->widthValue()
@@ -1379,7 +1379,6 @@ void CreateGiveawayBox(
loadingAnimation->showOn(state->confirmButtonBusy.value());
}
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
state->typeValue.value(
) | rpl::on_next([=, raw = button.data()] {
raw->resizeToWidth(box->width()
@@ -203,13 +203,11 @@ void FillShareLink(
wrap,
tr::lng_group_invite_context_copy(),
st::inviteLinkCopy);
copy->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
copy->setClickedCallback(copyLink);
const auto share = CreateChild<Ui::RoundButton>(
wrap,
tr::lng_group_invite_context_share(),
st::inviteLinkShare);
share->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
share->setClickedCallback(shareLink);
wrap->widthValue(
@@ -146,6 +146,7 @@ void AddRecipient(not_null<Ui::GenericBox*> box, const TextWithEntities &t) {
rpl::single(QString()),
st::channelEarnHistoryRecipientButton),
style::al_top);
container->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
const auto label = Ui::CreateChild<Ui::FlatLabel>(
container,
rpl::single(t),
@@ -594,8 +595,6 @@ void InnerWidget::fill() {
container,
tr::lng_channel_earn_learn_close(),
st::defaultActiveButton);
button->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
button->resizeToWidth(box->width()
- st.buttonPadding.left()
- st.buttonPadding.left());
@@ -887,6 +886,7 @@ void InnerWidget::fill() {
stButton),
st::boxRowPadding,
style::al_justify);
button->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
const auto label = Ui::CreateChild<Ui::FlatLabel>(
button,
@@ -1237,6 +1237,7 @@ void InnerWidget::fill() {
? tr::lng_channel_earn_history_out_button()
: tr::lng_box_ok(),
st::defaultActiveButton);
button->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
button->resizeToWidth(box->width()
- st.buttonPadding.left()
- st.buttonPadding.left());
+4
View File
@@ -1074,6 +1074,7 @@ topBarInfo: IconButton(topBarSearch) {
}
topBarInfoActive: icon {{ "top_bar_profile", windowActiveTextFg }};
topBarActionSkip: 10px;
topBarActionButtonLargeRadius: 8px;
topBarInfoButtonSize: size(52px, topBarHeight);
topBarInfoButtonInnerSize: 42px;
@@ -1473,3 +1474,6 @@ infoMusicButtonBottom: 8px;
infoMusicButtonLine: 2px;
memberTagPillPadding: margins(5px, -1px, 5px, 0px);
infoSecurityRiskIconSize: 16px;
infoSecurityRiskIconMargin: margins(0px, 2px, 0px, 0px);
@@ -242,7 +242,7 @@ void FlexibleScrollHelper::setupScrollHandlingWithFilter() {
}
const auto wheel = static_cast<QWheelEvent*>(e.get());
const auto delta = wheel->angleDelta().y();
if (std::abs(delta) != 120) {
if (std::abs(delta) != 120 || (wheel->phase() != Qt::NoScrollPhase)) {
scrollToY(_scroll->scrollTop() - delta);
return base::EventFilterResult::Cancel;
}
@@ -1312,8 +1312,6 @@ void InnerWidget::refreshAbout() {
) | rpl::map([](const QString &text) {
return Ui::Text::IconEmoji(&st::collectionAddIcon).append(text);
}));
button->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
button->setClickedCallback([=] {
editCollectionGifts(collectionId);
});
@@ -2497,7 +2495,6 @@ void Widget::setupBottomButton(int wasBottomHeight) {
bottom,
rpl::single(QString()),
st::collectionEditBox.button);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->setText(tr::lng_gift_collection_add_button(
) | rpl::map([](const QString &text) {
return Ui::Text::IconEmoji(&st::collectionAddIcon).append(text);
@@ -270,8 +270,6 @@ void ListWidget::Inner::setupHistory() {
_scroll.get(),
tr::lng_polls_create_title(),
st::defaultActiveButton);
_newPollButton->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
_newPollButton->setFullRadius(true);
_newPollButton->setClickedCallback([=] {
Window::PeerMenuCreatePoll(
@@ -407,6 +407,7 @@ base::options::toggle ShowChannelJoinedBelowAbout({
st::infoHoursOuter),
st::infoProfileLabeledPadding - st::infoHoursOuterMargin);
const auto button = result->entity();
button->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
const auto inner = Ui::CreateChild<Ui::VerticalLayout>(button);
button->widthValue() | rpl::on_next([=](int width) {
const auto margin = st::infoHoursOuterMargin;
@@ -643,7 +644,6 @@ base::options::toggle ShowChannelJoinedBelowAbout({
labelWrap,
std::move(linkText),
st::defaultTableSmallButton);
link->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
link->setClickedCallback([=] {
state->myTimezone = !state->myTimezone.current();
state->expanded = true;
@@ -897,6 +897,7 @@ void DeleteContactNote(
st::infoProfileLabeledPadding - st::infoHoursOuterMargin);
result->setDuration(st::infoSlideDuration);
const auto button = result->entity();
button->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
auto outer = Ui::CreateChild<Ui::SlideWrap<Ui::VerticalLayout>>(
button,
@@ -2335,7 +2336,6 @@ void DetailsFiller::setupMainApp(bool suppressBottom) {
st::infoOpenApp),
st::infoOpenAppMargin,
style::al_justify);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
const auto user = _peer->asUser();
const auto controller = _controller->parentController();
@@ -33,14 +33,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "api/api_peer_photo.h"
#include "lang/lang_keys.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/format_song_document_name.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/scroll_area.h"
#include "ui/widgets/shadow.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/painter.h"
#include "ui/vertical_list.h"
#include "ui/ui_utility.h"
#include "styles/style_info.h"
@@ -83,6 +86,68 @@ void AddAboutVerification(
}, inner->lifetime());
}
void AddUnofficialSecurityRiskWarning(
not_null<Ui::VerticalLayout*> container,
not_null<UserData*> user) {
const auto content = container->add(
object_ptr<Ui::VerticalLayout>(container));
user->session().changes().peerFlagsValue(
user,
Data::PeerUpdate::Flag::FullInfo
) | rpl::on_next([=] {
while (content->count()) {
delete content->widgetAt(0);
}
if (user->unofficialSecurityRisk()) {
auto helper = Ui::Text::CustomEmojiHelper();
auto icon = helper.paletteDependent({
.factory = [] {
const auto s = st::infoSecurityRiskIconSize;
const auto ratio = style::DevicePixelRatio();
const auto rect = QRect(0, 0, s, s);
auto result = QImage(
rect.size() * ratio,
QImage::Format_ARGB32_Premultiplied);
result.setDevicePixelRatio(ratio);
result.fill(Qt::transparent);
auto p = QPainter(&result);
auto hq = PainterHighQualityEnabler(p);
p.setPen(Qt::NoPen);
p.setBrush(st::attentionButtonFg);
p.drawEllipse(rect);
p.setPen(st::windowFgActive);
p.setFont(st::semiboldFont);
p.drawText(rect, u"!"_q, style::al_center);
p.end();
return result;
},
.margin = st::infoSecurityRiskIconMargin,
});
auto label = object_ptr<Ui::FlatLabel>(
content,
tr::lng_profile_unofficial_warning(
lt_icon,
rpl::single(std::move(icon)),
lt_name,
rpl::single(TextWithEntities{ user->firstName }),
tr::marked),
st::defaultDividerLabel.label,
st::defaultPopupMenu,
helper.context([=] { content->update(); }));
content->add(object_ptr<Ui::DividerLabel>(
content,
std::move(label),
st::defaultBoxDividerLabelPadding,
st::defaultDividerLabel.bar,
RectPart::Top | RectPart::Bottom));
}
content->resizeToWidth(content->width());
}, content->lifetime());
}
} // namespace
InnerWidget::InnerWidget(
@@ -129,6 +194,9 @@ object_ptr<Ui::RpWidget> InnerWidget::setupContent(
auto result = object_ptr<Ui::VerticalLayout>(parent);
setupSavedMusic(result);
if (const auto user = _peer->asUser()) {
AddUnofficialSecurityRiskWarning(result.data(), user);
}
if (_topic && _topic->creating()) {
return result;
}
@@ -103,7 +103,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_menu_icons.h"
#include "styles/style_settings.h"
#include <QGraphicsOpacityEffect>
#include <QtGui/QClipboard>
#include <QtGui/QGuiApplication>
@@ -337,8 +336,10 @@ TopBar::TopBar(
, _statusLabel(std::make_unique<StatusLabel>(_status.data(), _peer))
, _showLastSeen(
this,
tr::lng_status_lastseen_when(),
st::infoProfileTopBarShowLastSeen)
object_ptr<Ui::RoundButton>(
this,
tr::lng_status_lastseen_when(),
st::infoProfileTopBarShowLastSeen))
, _forumButton([&, controller = descriptor.controller] {
const auto topic = _key.topic();
if (!topic) {
@@ -355,7 +356,6 @@ TopBar::TopBar(
.append(' ')
.append(Ui::Text::IconEmoji(&st::textMoreIconEmoji, QString()));
}));
owned->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
owned->setClickedCallback([=, peer = _peer] {
if (const auto forum = peer->forum()) {
if (peer->useSubsectionTabs()) {
@@ -533,14 +533,14 @@ void TopBar::adjustColors(const std::optional<QColor> &edgeColor) {
: shouldOverrideTitle
? std::optional<QColor>(st::groupCallMembersFg->c)
: std::nullopt);
if (!_showLastSeen->isHidden()) {
if (_showLastSeen->toggled()) {
if (shouldOverrideTitle) {
const auto st = mapActionStyle(edgeColor);
_showLastSeen->setBrushOverride(st.bgColor);
_showLastSeen->setTextFgOverride(st.fgColor);
_showLastSeen->entity()->setBrushOverride(st.bgColor);
_showLastSeen->entity()->setTextFgOverride(st.fgColor);
} else {
_showLastSeen->setBrushOverride(std::nullopt);
_showLastSeen->setTextFgOverride(std::nullopt);
_showLastSeen->entity()->setBrushOverride(std::nullopt);
_showLastSeen->entity()->setTextFgOverride(std::nullopt);
}
}
{
@@ -1718,7 +1718,7 @@ void TopBar::updateStatusPosition(float64 progressCurrent) {
_status->hide();
// _starsRating->hide();
_showLastSeen->hide();
_showLastSeen->hide(anim::type::instant);
return;
}
@@ -1728,7 +1728,7 @@ void TopBar::updateStatusPosition(float64 progressCurrent) {
progressCurrent);
const auto totalElementsWidth = _status->width()
+ (_starsRating ? _starsRating->width() : 0)
+ (!_showLastSeen->isHidden() ? _showLastSeen->width() : 0);
+ (_showLastSeen->toggled() ? _showLastSeen->width() : 0);
const auto statusLeft = anim::interpolate(
statusMostLeft(),
(width() - totalElementsWidth) / 2,
@@ -1743,17 +1743,15 @@ void TopBar::updateStatusPosition(float64 progressCurrent) {
_status->moveToLeft(statusLeft + statusShift, statusTop);
if (!_showLastSeen->isHidden()) {
if (_showLastSeen->toggled()) {
_showLastSeen->moveToLeft(
statusLeft
+ statusShift
+ _status->textMaxWidth()
+ st::infoProfileTopBarLastSeenSkip.x(),
statusTop + st::infoProfileTopBarLastSeenSkip.y());
if (_showLastSeenOpacity) {
_showLastSeenOpacity->setOpacity(progressCurrent);
}
_showLastSeen->setAttribute(
_showLastSeen->setOpacity(progressCurrent);
_showLastSeen->entity()->setAttribute(
Qt::WA_TransparentForMouseEvents,
!progressCurrent);
}
@@ -2133,7 +2131,7 @@ void TopBar::setupShowLastSeen(
|| user->isBot()
|| user->isServiceUser()
|| !user->session().premiumPossible()) {
_showLastSeen->hide();
_showLastSeen->hide(anim::type::instant);
return;
}
@@ -2141,7 +2139,7 @@ void TopBar::setupShowLastSeen(
if (user->lastseen().isHiddenByMe()) {
user->updateFullForced();
}
_showLastSeen->hide();
_showLastSeen->hide(anim::type::instant);
return;
}
@@ -2151,13 +2149,13 @@ void TopBar::setupShowLastSeen(
Data::PeerUpdate::Flag::OnlineStatus),
Data::AmPremiumValue(&user->session())
) | rpl::on_next([=](auto, bool premium) {
const auto wasShown = !_showLastSeen->isHidden();
const auto wasShown = _showLastSeen->toggled();
const auto hiddenByMe = user->lastseen().isHiddenByMe();
const auto shown = hiddenByMe
&& !user->lastseen().isOnline(base::unixtime::now())
&& !premium
&& user->session().premiumPossible();
_showLastSeen->setVisible(shown);
_showLastSeen->toggle(shown, anim::type::instant);
if (wasShown && premium && hiddenByMe) {
user->updateFullForced();
}
@@ -2173,16 +2171,11 @@ void TopBar::setupShowLastSeen(
}
}, _showLastSeen->lifetime());
_showLastSeenOpacity = Ui::CreateChild<QGraphicsOpacityEffect>(
_showLastSeen.get());
_showLastSeen->setGraphicsEffect(_showLastSeenOpacity);
_showLastSeenOpacity->setOpacity(0.);
_showLastSeen->setOpacity(0.);
using TextTransform = Ui::RoundButton::TextTransform;
_showLastSeen->setTextTransform(TextTransform::NoTransform);
_showLastSeen->setFullRadius(true);
_showLastSeen->entity()->setFullRadius(true);
_showLastSeen->setClickedCallback([=] {
_showLastSeen->entity()->setClickedCallback([=] {
const auto type = Ui::ShowOrPremium::LastSeen;
controller->show(Box(
Ui::ShowOrPremiumBox,
@@ -52,8 +52,6 @@ struct InfoPeerBadge;
struct FlatLabel;
} //namespace style
class QGraphicsOpacityEffect;
namespace Ui {
class FlatLabel;
class IconButton;
@@ -224,9 +222,8 @@ private:
object_ptr<Ui::FlatLabel> _status;
std::unique_ptr<StatusLabel> _statusLabel;
rpl::variable<int> _statusShift = 0;
object_ptr<Ui::RoundButton> _showLastSeen = { nullptr };
object_ptr<Ui::FadeWrap<Ui::RoundButton>> _showLastSeen = { nullptr };
object_ptr<Ui::RoundButton> _forumButton = { nullptr };
QGraphicsOpacityEffect *_showLastSeenOpacity = nullptr;
std::shared_ptr<style::FlatLabel> _statusSt;
std::shared_ptr<style::InfoPeerBadge> _botVerifySt;
@@ -157,6 +157,7 @@ void ListController::setupUnlock() {
: tr::lng_similar_bots_show_more()),
st::similarChannelsLock,
rpl::single(true));
button->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
button->setClickedCallback([=] {
const auto window = _controller->parentController();
::Settings::ShowPremium(window, u"similar_channels"_q);
@@ -724,8 +724,6 @@ void InnerWidget::refreshEmpty() {
) | rpl::map([](const QString &text) {
return Ui::Text::IconEmoji(&st::collectionAddIcon).append(text);
}));
button->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
button->setClickedCallback([=] {
editAlbumStories(albumId);
});
@@ -231,7 +231,6 @@ void Widget::setupBottomButton(int wasBottomHeight) {
bottom,
rpl::single(QString()),
st::collectionEditBox.button);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->setText(tr::lng_stories_album_add_button(
) | rpl::map([](const QString &text) {
return Ui::Text::IconEmoji(&st::collectionAddIcon).append(text);
@@ -45,7 +45,6 @@ void ShowLayer(
content.get(),
tr::lng_connection_save(),
st::userpicBuilderEmojiButton);
save->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
content->sizeValue(
) | rpl::on_next([=] {
const auto &p = st::userpicBuilderEmojiSavePosiiton;
@@ -514,7 +514,6 @@ void Inner::refreshSwitchPmButton(const CacheEntry *entry) {
if (!_switchPmButton) {
_switchPmButton.create(this, nullptr, st::switchPmButton);
_switchPmButton->show();
_switchPmButton->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
_switchPmButton->addClickHandler([=] { switchPm(); });
}
_switchPmButton->setText(rpl::single(entry->switchPmText));
+3 -2
View File
@@ -93,6 +93,7 @@ Widget::Widget(
this,
account,
rpl::single(true))) {
_settings->entity()->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
controller->setDefaultFloatPlayerDelegate(floatPlayerDelegate());
getData()->country = ComputeNewAccountCountry();
@@ -318,6 +319,7 @@ void Widget::checkUpdateStatus() {
this,
tr::lng_menu_update(),
st::defaultBoxButton));
_update->entity()->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
if (!_showAnimation) {
_update->setVisible(true);
}
@@ -492,6 +494,7 @@ void Widget::showResetButton() {
this,
tr::lng_signin_reset_account(),
st::introResetButton);
entity->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
_resetAccount.create(this, std::move(entity));
_resetAccount->hide(anim::type::instant);
_resetAccount->entity()->setClickedCallback([this] { resetAccount(); });
@@ -722,8 +725,6 @@ void Widget::showControls() {
void Widget::setupNextButton() {
_next->entity()->setClickedCallback([=] { getStep()->submit(); });
_next->entity()->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
_next->entity()->setText(getStep()->nextButtonText(
) | rpl::filter([](const QString &text) {
@@ -108,7 +108,6 @@ public:
tr::lng_background_reset_default(),
st::ivResetZoomLabel);
resetLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
reset->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
reset->setClickedCallback([this] {
_delegate->ivSetZoom(0);
});
@@ -231,7 +231,10 @@ bool FFMpegReaderImplementation::renderFrame(
: _frame->format;
const auto bgra = (format == AV_PIX_FMT_BGRA);
hasAlpha = bgra || (format == AV_PIX_FMT_YUVA420P);
if (_frame->width == toSize.width() && _frame->height == toSize.height() && bgra) {
if (bgra
&& _frame->width == toSize.width()
&& _frame->height == toSize.height()
&& _frame->linesize[0] > 0) {
int32 sbpl = _frame->linesize[0], dbpl = to.bytesPerLine(), bpl = qMin(sbpl, dbpl);
uchar *s = _frame->data[0], *d = to.bits();
for (int32 i = 0, l = _frame->height; i < l; ++i) {
@@ -266,7 +266,6 @@ void Controller::Unsupported::setup(not_null<PeerData*> peer) {
wrap,
tr::ayu_UpdateAyuGram(),
st::storiesUnsupportedUpdate);
_button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
_button->show();
rpl::combine(
@@ -242,6 +242,7 @@ struct State {
rpl::single(QString()),
st.box.button);
const auto raw = result.data();
raw->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
const auto label = Ui::CreateChild<Ui::FlatLabel>(
raw,
@@ -158,7 +158,9 @@ QImage ConvertFrame(
const auto format = AV_PIX_FMT_BGRA;
const auto hasDesiredFormat = (frame->format == format);
if (frameSize == storage.size() && hasDesiredFormat) {
if (hasDesiredFormat
&& frameSize == storage.size()
&& frame->linesize[0] > 0) {
static_assert(sizeof(uint32) == FFmpeg::kPixelBytesSize);
auto to = reinterpret_cast<uint32*>(storage.bits());
auto from = reinterpret_cast<const uint32*>(frame->data[0]);
@@ -373,6 +373,11 @@ auto VideoTrackObject::readFrame(not_null<Frame*> frame) -> FrameResult {
_waitingForData.fire({});
return FrameResult::Waiting;
}
const auto decodedFrame = _stream.decodedFrame.get();
if (int64(decodedFrame->width) * decodedFrame->height > kMaxFrameArea) {
fail(Error::InvalidData);
return FrameResult::Error;
}
const auto position = currentFramePosition();
if (position == kTimeUnknown) {
fail(Error::InvalidData);
@@ -649,7 +654,7 @@ bool VideoTrackObject::tryReadFirstFrame(FFmpeg::Packet &&packet) {
bool VideoTrackObject::processFirstFrame() {
const auto decodedFrame = _stream.decodedFrame.get();
if (decodedFrame->width * decodedFrame->height > kMaxFrameArea) {
if (int64(decodedFrame->width) * decodedFrame->height > kMaxFrameArea) {
return false;
} else if (decodedFrame->hw_frames_ctx) {
if (!_stream.transferredFrame) {
@@ -223,6 +223,19 @@ mediaviewSaveMsgHiding: 2500;
mediaviewSaveMsgStyle: TextStyle(defaultTextStyle) {
font: font(16px);
}
mediaviewChapterPadding: margins(20px, 12px, 20px, 12px);
mediaviewChapterFont: font(15px semibold);
mediaviewChapterShowing: 200;
mediaviewChapterShown: 1500;
mediaviewChapterHiding: 400;
mediaviewChapterArrowSize: 10px;
mediaviewChapterArrowWidth: 6px;
mediaviewChapterArrowShift: 16px;
mediaviewChapterArrowGap: 12px;
mediaviewChapterArrowSlide: 350;
mediaviewChapterArrowPause: 1500;
mediaviewChapterArrowFade: 300;
mediaviewTextPalette: TextPalette(defaultTextPalette) {
linkFg: mediaviewTextLinkFg;
monoFg: mediaviewCaptionFg;
@@ -28,7 +28,8 @@ constexpr auto kRadialLoadingOffset = kNotchOffset + 4;
constexpr auto kThemePreviewOffset = kRadialLoadingOffset + 4;
constexpr auto kDocumentBubbleOffset = kThemePreviewOffset + 4;
constexpr auto kSaveMsgOffset = kDocumentBubbleOffset + 4;
constexpr auto kFooterOffset = kSaveMsgOffset + 4;
constexpr auto kChapterOffset = kSaveMsgOffset + 4;
constexpr auto kFooterOffset = kChapterOffset + 4;
constexpr auto kCaptionOffset = kFooterOffset + 4;
constexpr auto kGroupThumbsOffset = kCaptionOffset + 4;
constexpr auto kControlsOffset = kGroupThumbsOffset + 4;
@@ -724,6 +725,13 @@ void OverlayWidget::RendererGL::paintSaveMsg(QRect outer) {
}, kSaveMsgOffset, true);
}
void OverlayWidget::RendererGL::paintChapter(QRect outer) {
paintUsingRaster(_chapterImage, outer, [&](Painter &&p) {
const auto newOuter = QRect(QPoint(), outer.size());
_owner->paintChapterContent(p, newOuter, newOuter);
}, kChapterOffset, true);
}
void OverlayWidget::RendererGL::paintControlsStart() {
validateControls();
_f->glActiveTexture(GL_TEXTURE0);
@@ -59,6 +59,7 @@ private:
void paintThemePreview(QRect outer) override;
void paintDocumentBubble(QRect outer, QRect icon) override;
void paintSaveMsg(QRect outer) override;
void paintChapter(QRect outer) override;
void paintControlsStart() override;
void paintControl(
Over control,
@@ -144,6 +145,7 @@ private:
Ui::GL::Image _documentBubbleImage;
Ui::GL::Image _themePreviewImage;
Ui::GL::Image _saveMsgImage;
Ui::GL::Image _chapterImage;
Ui::GL::Image _footerImage;
Ui::GL::Image _captionImage;
Ui::GL::Image _groupThumbsImage;
@@ -275,6 +275,12 @@ void OverlayWidget::RendererSW::paintSaveMsg(QRect outer) {
}
}
void OverlayWidget::RendererSW::paintChapter(QRect outer) {
if (outer.intersects(_clipOuter)) {
_owner->paintChapterContent(*_p, outer, _clipOuter);
}
}
void OverlayWidget::RendererSW::paintControlsStart() {
}
@@ -43,6 +43,7 @@ private:
void paintThemePreview(QRect outer) override;
void paintDocumentBubble(QRect outer, QRect icon) override;
void paintSaveMsg(QRect outer) override;
void paintChapter(QRect outer) override;
void paintControlsStart() override;
void paintControl(
Over control,
@@ -33,6 +33,7 @@ public:
virtual void paintThemePreview(QRect outer) = 0;
virtual void paintDocumentBubble(QRect outer, QRect icon) = 0;
virtual void paintSaveMsg(QRect outer) = 0;
virtual void paintChapter(QRect outer) = 0;
virtual void paintControlsStart() = 0;
virtual void paintControl(
Over control,
@@ -607,6 +607,10 @@ OverlayWidget::OverlayWidget()
_saveMsgAnimation.start([=] { updateSaveMsg(); }, 1., 0., delay);
});
_chapterTimer.setCallback([=, delay = st::mediaviewChapterHiding] {
_chapterAnimation.start([=] { updateChapter(); }, 1., 0., delay);
});
_docRectImage = QImage(
st::mediaviewFileSize * style::DevicePixelRatio(),
QImage::Format_ARGB32_Premultiplied);
@@ -1794,12 +1798,10 @@ void OverlayWidget::refreshVoteButton() {
return;
}
if (!_voteButton) {
using TextTransform = Ui::RoundButton::TextTransform;
_voteButton.create(
_body,
tr::lng_polls_submit_votes(),
st::mediaviewVoteButton);
_voteButton->setTextTransform(TextTransform::NoTransform);
const auto effect = Ui::CreateChild<QGraphicsOpacityEffect>(
_voteButton.data());
effect->setOpacity(_controlsOpacity.current());
@@ -3529,6 +3531,12 @@ Data::FileOrigin OverlayWidget::fileOrigin() const {
} else if (_message) {
return _message->fullId();
} else if (_photo && _user) {
const auto dominated = (_user->hasPersonalPhoto()
&& _photo->id == _user->userpicPhotoId())
|| SyncUserFallbackPhotoViewer(_user) == _photo->id;
if (dominated) {
return Data::FileOriginFullUser(peerToUser(_user->id));
}
return Data::FileOriginUserPhoto(peerToUser(_user->id), _photo->id);
} else if (_photo && _peer && _peer->userpicPhotoId() == _photo->id) {
return Data::FileOriginPeerPhoto(_peer->id);
@@ -3544,6 +3552,12 @@ Data::FileOrigin OverlayWidget::fileOrigin(const Entity &entity) const {
}
const auto photo = v::get<not_null<PhotoData*>>(entity.data);
if (_user) {
const auto dominated = (_user->hasPersonalPhoto()
&& photo->id == _user->userpicPhotoId())
|| SyncUserFallbackPhotoViewer(_user) == photo->id;
if (dominated) {
return Data::FileOriginFullUser(peerToUser(_user->id));
}
return Data::FileOriginUserPhoto(peerToUser(_user->id), photo->id);
} else if (_peer && _peer->userpicPhotoId() == photo->id) {
return Data::FileOriginPeerPhoto(_peer->id);
@@ -4904,12 +4918,10 @@ void OverlayWidget::initThemePreview() {
_themePreviewId = 0;
_themePreview = std::move(result);
if (_themePreview) {
using TextTransform = Ui::RoundButton::TextTransform;
_themeApply.create(
_body,
tr::lng_theme_preview_apply(),
st::themePreviewApplyButton);
_themeApply->setTextTransform(TextTransform::NoTransform);
_themeApply->show();
_themeApply->setClickedCallback([=] {
const auto &object = Background()->themeObject();
@@ -4926,7 +4938,6 @@ void OverlayWidget::initThemePreview() {
_body,
tr::lng_cancel(),
st::themePreviewCancelButton);
_themeCancel->setTextTransform(TextTransform::NoTransform);
_themeCancel->show();
_themeCancel->setClickedCallback([this] { close(); });
if (const auto slug = _themeCloudData.slug; !slug.isEmpty()) {
@@ -4934,7 +4945,6 @@ void OverlayWidget::initThemePreview() {
_body,
tr::lng_theme_share(),
st::themePreviewCancelButton);
_themeShare->setTextTransform(TextTransform::NoTransform);
_themeShare->show();
_themeShare->setClickedCallback([=] {
QGuiApplication::clipboard()->setText(
@@ -5254,11 +5264,14 @@ void OverlayWidget::applyVideoQuality(VideoQuality value) {
const auto startStreaming = StartStreaming(false, time);
if (!canInitStreaming() || !initStreaming(startStreaming)) {
redisplayContent();
} else if (_fullScreenVideo != wasFullScreen) {
_fullScreenVideo = wasFullScreen;
if (_streamed->controls) {
_streamed->controls->setInFullScreen(_fullScreenVideo);
} else {
if (_fullScreenVideo != wasFullScreen) {
_fullScreenVideo = wasFullScreen;
if (_streamed->controls) {
_streamed->controls->setInFullScreen(_fullScreenVideo);
}
}
refreshCaption();
}
}
@@ -5732,6 +5745,9 @@ void OverlayWidget::paint(not_null<Renderer*> renderer) {
if (isSaveMsgShown()) {
renderer->paintSaveMsg(_saveMsg);
}
if (isChapterShown()) {
renderer->paintChapter(_chapterRect);
}
const auto opacity = _fullScreenVideo ? 0. : _controlsOpacity.current();
if (opacity > 0) {
@@ -5992,6 +6008,154 @@ void OverlayWidget::paintSaveMsgContent(
p.setOpacity(1);
}
void OverlayWidget::showChapterIndicator(
const QString &name,
int direction) {
if (name.isEmpty()) {
return;
}
_chapterText = name;
const auto font = st::mediaviewChapterFont;
const auto padding = st::mediaviewChapterPadding;
const auto arrowSpace = st::mediaviewChapterArrowWidth
+ st::mediaviewChapterArrowGap;
const auto textWidth = font->width(_chapterText);
const auto w = padding.left()
+ arrowSpace
+ textWidth
+ arrowSpace
+ padding.right();
const auto h = rect::m::sum::v(padding) + font->height;
_chapterRect = QRect(
(width() - w) / 2,
_minUsedTop + (_maxUsedHeight - h) / 2,
w,
h);
if (isChapterShown()) {
_chapterTimer.callOnce(st::mediaviewChapterShown);
} else {
const auto callback = [=](float64 value) {
updateChapter();
if (!_chapterAnimation.animating()) {
_chapterTimer.callOnce(st::mediaviewChapterShown);
}
};
_chapterAnimation.start(
callback,
0.,
1.,
st::mediaviewChapterShowing);
}
_chapterArrows.erase(
ranges::remove_if(
_chapterArrows,
[&](const auto &a) {
return !a->animation.animating()
|| (a->direction != direction);
}),
_chapterArrows.end());
auto arrow = std::make_unique<ChapterArrow>();
arrow->direction = direction;
arrow->animation.start(
[=] { updateChapter(); },
0.,
1.,
st::mediaviewChapterArrowSlide
+ st::mediaviewChapterArrowPause
+ st::mediaviewChapterArrowFade);
_chapterArrows.push_back(std::move(arrow));
updateChapter();
}
void OverlayWidget::paintChapterContent(
Painter &p,
QRect outer,
QRect clip) {
const auto opacity = _chapterAnimation.value(1.);
p.setOpacity(opacity);
Ui::FillRoundRect(
p,
outer,
st::mediaviewSaveMsgBg,
Ui::MediaviewSaveCorners);
const auto font = st::mediaviewChapterFont;
const auto padding = st::mediaviewChapterPadding;
const auto arrowSize = st::mediaviewChapterArrowSize;
const auto arrowWidth = st::mediaviewChapterArrowWidth;
const auto arrowGap = st::mediaviewChapterArrowGap;
const auto textX = outer.x()
+ padding.left()
+ arrowWidth
+ arrowGap;
const auto textY = outer.y() + padding.top();
p.setFont(font);
p.setPen(st::mediaviewSaveMsgFg);
p.drawText(textX, textY + font->ascent, _chapterText);
const auto cy = outer.y() + outer.height() / 2.;
const auto halfH = arrowSize / 2.;
const auto totalDuration = float64(st::mediaviewChapterArrowSlide
+ st::mediaviewChapterArrowPause
+ st::mediaviewChapterArrowFade);
const auto slideEnd = st::mediaviewChapterArrowSlide / totalDuration;
const auto fadeStart = 1. - st::mediaviewChapterArrowFade / totalDuration;
auto hq = PainterHighQualityEnabler(p);
auto pen = QPen(st::mediaviewSaveMsgFg->c);
pen.setWidthF(st::lineWidth * 1.5);
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
p.setPen(pen);
p.setBrush(Qt::NoBrush);
for (const auto &arrow : _chapterArrows) {
if (!arrow->animation.animating()) {
continue;
}
const auto progress = arrow->animation.value(1.);
const auto slideProgress = std::min(progress / slideEnd, 1.);
const auto shift = st::mediaviewChapterArrowShift * slideProgress;
const auto arrowOpacity = (progress <= fadeStart)
? slideProgress
: (1. - progress) / (1. - fadeStart);
p.setOpacity(opacity * arrowOpacity);
auto path = QPainterPath();
if (arrow->direction > 0) {
const auto ax = outer.x()
+ outer.width()
- padding.right()
- arrowGap
- arrowWidth
+ shift;
path.moveTo(ax, cy - halfH);
path.lineTo(ax + arrowWidth, cy);
path.lineTo(ax, cy + halfH);
} else {
const auto ax = outer.x()
+ padding.left()
+ arrowGap
+ arrowWidth
- shift;
path.moveTo(ax, cy - halfH);
path.lineTo(ax - arrowWidth, cy);
path.lineTo(ax, cy + halfH);
}
p.drawPath(path);
}
p.setOpacity(1);
}
bool OverlayWidget::isChapterShown() const {
return _chapterAnimation.animating() || _chapterTimer.isActive();
}
void OverlayWidget::updateChapter() {
update(_chapterRect);
}
bool OverlayWidget::saveControlLocked() const {
const auto story = _stories ? _stories->story() : nullptr;
return story
@@ -6271,6 +6435,34 @@ void OverlayWidget::handleKeyPress(not_null<QKeyEvent*> e) {
} else if (key == Qt::Key_Space) {
playbackPauseResume();
return;
} else if (modifiers.testFlag(Qt::AltModifier)
&& (key == Qt::Key_Left || key == Qt::Key_Right)
&& _streamed->controls
&& _streamed->controls->hasTimestamps()) {
const auto &state = _streamed->instance.info().video.state;
const auto duration = state.duration;
if (duration > 0) {
const auto progress = state.position
/ float64(duration);
const auto &controls = _streamed->controls;
if (key == Qt::Key_Right) {
if (const auto ts = controls->nextTimestamp(progress)) {
activateControls();
restartAtProgress(ts->position);
showChapterIndicator(ts->label, 1);
}
} else {
if (const auto ts = controls->prevTimestamp(progress)) {
activateControls();
restartAtProgress(ts->position);
showChapterIndicator(ts->label, -1);
} else {
activateControls();
restartAtSeekPosition(0);
}
}
}
return;
} else if (_fullScreenVideo) {
if (key == Qt::Key_Escape) {
playbackToggleFullScreen();
@@ -7444,6 +7636,11 @@ void OverlayWidget::clearBeforeHide() {
if (_menu) {
_menu->hideMenu(true);
}
_chapterText = QString();
_chapterRect = QRect();
_chapterAnimation.stop();
_chapterTimer.cancel();
_chapterArrows.clear();
_controlsHideTimer.cancel();
_controlsState = ControlsShown;
_controlsOpacity = anim::value(1);
@@ -517,6 +517,11 @@ private:
bool nonbright = false) const;
[[nodiscard]] bool isSaveMsgShown() const;
void showChapterIndicator(const QString &name, int direction);
void paintChapterContent(Painter &p, QRect outer, QRect clip);
[[nodiscard]] bool isChapterShown() const;
void updateChapter();
void updateOverRect(Over state);
bool updateOverState(Over newState);
float64 overLevel(Over control) const;
@@ -774,6 +779,16 @@ private:
Ui::Animations::Simple _saveMsgAnimation;
base::Timer _saveMsgTimer;
QString _chapterText;
QRect _chapterRect;
Ui::Animations::Simple _chapterAnimation;
base::Timer _chapterTimer;
struct ChapterArrow {
Ui::Animations::Simple animation;
int direction = 0;
};
std::vector<std::unique_ptr<ChapterArrow>> _chapterArrows;
base::flat_map<Over, crl::time> _animations;
base::flat_map<Over, anim::value> _animationOpacities;
@@ -24,6 +24,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Media {
namespace View {
namespace {
constexpr auto kEps = 0.005;
} // namespace
PlaybackControls::PlaybackControls(
QWidget *parent,
@@ -303,6 +308,26 @@ bool PlaybackControls::hasTimestamps() const {
return _timestampLabel != nullptr;
}
auto PlaybackControls::nextTimestamp(float64 progress) const
-> std::optional<TimestampData> {
for (const auto &ts : _timestamps) {
if (ts.position > progress + kEps) {
return ts;
}
}
return std::nullopt;
}
auto PlaybackControls::prevTimestamp(float64 progress) const
-> std::optional<TimestampData> {
for (auto i = int(_timestamps.size()) - 1; i >= 0; --i) {
if (_timestamps[i].position < progress - kEps) {
return _timestamps[i];
}
}
return std::nullopt;
}
void PlaybackControls::updateTimestampLabel() {
if (!_timestampLabel) {
return;
@@ -72,6 +72,10 @@ public:
void setTimestamps(std::vector<TimestampData> timestamps);
void setInFullScreen(bool inFullScreen);
[[nodiscard]] bool hasTimestamps() const;
[[nodiscard]] std::optional<TimestampData> nextTimestamp(
float64 progress) const;
[[nodiscard]] std::optional<TimestampData> prevTimestamp(
float64 progress) const;
[[nodiscard]] bool hasMenu() const;
[[nodiscard]] bool dragging() const;
@@ -331,7 +331,6 @@ PlaybackSponsored::Message::Message(
this,
_aboutSt.ripple,
std::move(allowCloseAt))) {
_about->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
setMouseTracking(true);
populate();
hide();
@@ -249,6 +249,7 @@ void AboutBox(
box,
tr::lng_box_ok(),
st::defaultActiveButton);
button->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
button->resizeToWidth(box->width()
- st.buttonPadding.left()
- st.buttonPadding.left());
@@ -148,8 +148,6 @@ void VerifyBox::setupControls(
button->setFullWidth(w - small.left() - small.right());
}, button->lifetime());
button->setClickedCallback([=] { ::File::OpenUrl(openUrl); });
button->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
}
if (resend) {
auto link = TextWithEntities{ tr::lng_cloud_password_resend(tr::now) };
@@ -238,6 +236,7 @@ PanelEditContact::PanelEditContact(
this,
tr::lng_passport_save_value(),
st::passportPanelSaveValue) {
_done->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
setupControls(data, existing);
}
@@ -222,6 +222,7 @@ PanelEditDocument::PanelEditDocument(
this,
tr::lng_passport_save_value(),
st::passportPanelSaveValue) {
_done->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
setupControls(
&error,
&data,
@@ -248,6 +249,7 @@ PanelEditDocument::PanelEditDocument(
this,
tr::lng_passport_save_value(),
st::passportPanelSaveValue) {
_done->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
setupControls(
nullptr,
nullptr,
@@ -271,6 +273,7 @@ PanelEditDocument::PanelEditDocument(
this,
tr::lng_passport_save_value(),
st::passportPanelSaveValue) {
_done->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
setupControls(&error, &data, nullptr, nullptr, {}, {}, {});
}
@@ -327,6 +327,7 @@ ScanButton::ScanButton(
this,
tr::lng_passport_delete_scan_undo(),
_st.restore)) {
_restore->entity()->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
_delete->toggle(!deleted, anim::type::instant);
_restore->toggle(deleted, anim::type::instant);
}
@@ -41,6 +41,7 @@ PanelForm::PanelForm(
this,
tr::lng_passport_authorize(),
st::passportPanelAuthorize) {
_submit->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
setupControls();
}
@@ -49,6 +49,7 @@ PanelAskPassword::PanelAskPassword(
tr::lng_passport_password_placeholder())
, _submit(this, tr::lng_passport_next(), st::passportPasswordSubmit)
, _forgot(this, tr::lng_signin_recover(tr::now), st::defaultLinkButton) {
_submit->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
connect(_password, &Ui::PasswordInput::submitted, this, [=] {
submit();
});
@@ -229,6 +230,7 @@ void PanelNoPassword::refreshBottom() {
tr::lng_passport_password_create(),
st::defaultBoxButton),
style::al_top);
button->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
button->addClickHandler([=] {
_controller->setupPassword();
});
@@ -241,8 +243,6 @@ void PanelNoPassword::refreshBottom() {
container,
tr::lng_cancel(),
st::defaultBoxButton);
cancel->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
cancel->addClickHandler([=] {
_controller->cancelPasswordSubmit();
});
@@ -250,8 +250,6 @@ void PanelNoPassword::refreshBottom() {
container,
tr::lng_passport_email_validate(),
st::defaultBoxButton);
validate->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
validate->addClickHandler([=] {
_controller->validateRecoveryEmail();
});
@@ -221,6 +221,8 @@ EditCard::EditCard(
this,
tr::lng_cancel(),
st::paymentsPanelButton) {
_submit->setTextTransform(RoundButtonTextTransform::ToUpper);
_cancel->setTextTransform(RoundButtonTextTransform::ToUpper);
setupControls();
}
@@ -52,6 +52,8 @@ EditInformation::EditInformation(
this,
tr::lng_cancel(),
st::paymentsPanelButton) {
_submit->setTextTransform(RoundButtonTextTransform::ToUpper);
_cancel->setTextTransform(RoundButtonTextTransform::ToUpper);
setupControls();
}
@@ -170,13 +170,10 @@ void FormSummary::setupControls() {
setupContent(_layout.get());
if (_submit) {
_submit->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
_submit->addClickHandler([=] {
_delegate->panelSubmit();
});
}
_cancel->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
_cancel->addClickHandler([=] {
_delegate->panelRequestClose();
});
@@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "platform/mac/translate_provider_mac.h"
#ifndef TDESKTOP_DISABLE_SWIFT6
#include "base/weak_ptr.h"
#include "spellcheck/platform/platform_language.h"
#include "translate_provider_mac_swift_bridge.h"
@@ -102,4 +104,19 @@ bool IsTranslateProviderAvailable() {
return TranslateProviderMacSwiftIsAvailable();
}
#else // TDESKTOP_DISABLE_SWIFT6
// Local on-device translation disabled (no Swift 6).
namespace Platform {
std::unique_ptr<Ui::TranslateProvider> CreateTranslateProvider() {
return nullptr;
}
bool IsTranslateProviderAvailable() {
return false;
}
#endif // TDESKTOP_DISABLE_SWIFT6
} // namespace Platform
@@ -174,7 +174,7 @@ void UpdateIcon(const NSStatusItem *status) {
return;
}
const auto appearance = [NSApp effectiveAppearance];
const auto appearance = status.button.effectiveAppearance;
const auto darkMode = [[appearance.name lowercaseString]
containsString:@"dark"];
@@ -232,7 +232,6 @@ not_null<Ui::RoundButton*> AddDoneButton(
st::changePhoneButton),
st::settingLocalPasscodeButtonPadding,
style::al_top);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
return button;
}
@@ -16,6 +16,10 @@ DetailedSettingsButton::DetailedSettingsButton(
, _style(rowStyle)
, _title(0)
, _description(0)
, _toggle(std::make_unique<Ui::ToggleView>(
_style.button.toggle,
false,
[this] { rtlupdate(toggleRect()); }))
, _iconForeground(icon.icon)
, _iconBackground(icon.background)
, _iconBackgroundBrush(std::move(icon.backgroundBrush)) {
@@ -38,10 +42,6 @@ DetailedSettingsButton::DetailedSettingsButton(
kDefaultTextOptions);
refreshLayout();
}, lifetime());
_toggle = std::make_unique<Ui::ToggleView>(
_style.button.toggle,
false,
[this] { rtlupdate(toggleRect()); });
addClickHandler([=] {
if (!_toggleLocked) {
_toggle->setChecked(!_toggle->checked(), anim::type::normal);
@@ -534,7 +534,6 @@ void Credits::setupContent() {
lt_emoji,
rpl::single(Ui::Text::SingleCustomEmoji(u"+"_q)),
tr::marked)));
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
const auto show = controller()->uiShow();
if (isCurrency) {
const auto url = tr::lng_suggest_low_ton_fragment_url(tr::now);
@@ -869,6 +868,7 @@ void BuildCurrencyWithdrawalSection(
stButton),
st::boxRowPadding,
style::al_top);
button->setTextTransform(Ui::RoundButtonTextTransform::ToUpper);
const auto label = Ui::CreateChild<Ui::FlatLabel>(
button,
@@ -186,9 +186,7 @@ FilterRowButton::FilterRowButton(
tr::lng_filters_recommended_add(),
st::settingsFilterAddRecommended)
, _state(description.isEmpty() ? State::Normal : State::Suggested) {
_restore.setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
_restore.setFullRadius(true);
_add.setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
_add.setFullRadius(true);
setup(filter, description.isEmpty()
? ComputeCountString(session, filter)

Some files were not shown because too many files have changed in this diff Show More