mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Merge tag 'v5.8.2' into dev
This commit is contained in:
@@ -17,9 +17,7 @@ ivMenuToggle: IconButton(defaultIconButton) {
|
||||
|
||||
rippleAreaPosition: point(6px, 6px);
|
||||
rippleAreaSize: 36px;
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: windowBgOver;
|
||||
}
|
||||
ripple: defaultRippleAnimationBgOver;
|
||||
}
|
||||
ivMenuPosition: point(-2px, 40px);
|
||||
ivBackIcon: icon {{ "box_button_back", menuIconColor }};
|
||||
@@ -36,9 +34,7 @@ ivPlusMinusZoom: IconButton(ivMenuToggle) {
|
||||
|
||||
rippleAreaPosition: point(0px, 0px);
|
||||
rippleAreaSize: ivZoomButtonsSize;
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: windowBgOver;
|
||||
}
|
||||
ripple: defaultRippleAnimationBgOver;
|
||||
}
|
||||
ivResetZoomStyle: TextStyle(defaultTextStyle) {
|
||||
font: font(12px);
|
||||
|
||||
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "iv/iv_controller.h"
|
||||
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/qt/qt_key_modifiers.h"
|
||||
#include "base/invoke_queued.h"
|
||||
#include "base/qt_signal_producer.h"
|
||||
#include "base/qthelp_url.h"
|
||||
@@ -21,9 +22,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/menu/menu_action.h"
|
||||
#include "ui/widgets/rp_window.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/tooltip.h"
|
||||
#include "ui/wrap/fade_wrap.h"
|
||||
#include "ui/basic_click_handlers.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/rect.h"
|
||||
#include "ui/webview_helpers.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "webview/webview_data_stream_memory.h"
|
||||
@@ -56,9 +59,13 @@ namespace Iv {
|
||||
namespace {
|
||||
|
||||
constexpr auto kZoomStep = int(10);
|
||||
constexpr auto kZoomSmallStep = int(5);
|
||||
constexpr auto kZoomTinyStep = int(1);
|
||||
constexpr auto kDefaultZoom = int(100);
|
||||
|
||||
class ItemZoom final : public Ui::Menu::Action {
|
||||
class ItemZoom final
|
||||
: public Ui::Menu::Action
|
||||
, public Ui::AbstractTooltipShower {
|
||||
public:
|
||||
ItemZoom(
|
||||
not_null<RpWidget*> parent,
|
||||
@@ -80,43 +87,21 @@ public:
|
||||
|
||||
AbstractButton::setDisabled(true);
|
||||
|
||||
class SmallButton final : public Ui::IconButton {
|
||||
public:
|
||||
SmallButton(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
QChar c,
|
||||
float64 skip,
|
||||
const style::color &color)
|
||||
: Ui::IconButton(parent, st::ivPlusMinusZoom)
|
||||
, _color(color)
|
||||
, _skip(style::ConvertFloatScale(skip))
|
||||
, _c(c) {
|
||||
}
|
||||
|
||||
void paintEvent(QPaintEvent *event) override {
|
||||
auto p = Painter(this);
|
||||
Ui::RippleButton::paintRipple(
|
||||
p,
|
||||
st::ivPlusMinusZoom.rippleAreaPosition);
|
||||
p.setPen(_color);
|
||||
p.setFont(st::normalFont);
|
||||
p.drawText(
|
||||
QRectF(rect()).translated(0, _skip),
|
||||
_c,
|
||||
style::al_center);
|
||||
}
|
||||
|
||||
private:
|
||||
const style::color _color;
|
||||
const float64 _skip;
|
||||
const QChar _c;
|
||||
|
||||
const auto processTooltip = [=](not_null<Ui::RpWidget*> w) {
|
||||
w->events() | rpl::start_with_next([=](not_null<QEvent*> e) {
|
||||
if (e->type() == QEvent::Enter) {
|
||||
Ui::Tooltip::Show(1000, this);
|
||||
} else if (e->type() == QEvent::Leave) {
|
||||
Ui::Tooltip::Hide();
|
||||
}
|
||||
}, w->lifetime());
|
||||
};
|
||||
|
||||
const auto reset = Ui::CreateChild<Ui::RoundButton>(
|
||||
this,
|
||||
rpl::single<QString>(QString()),
|
||||
st::ivResetZoom);
|
||||
processTooltip(reset);
|
||||
const auto resetLabel = Ui::CreateChild<Ui::FlatLabel>(
|
||||
reset,
|
||||
tr::lng_background_reset_default(),
|
||||
@@ -127,25 +112,60 @@ public:
|
||||
_delegate->ivSetZoom(kDefaultZoom);
|
||||
});
|
||||
reset->show();
|
||||
const auto plus = Ui::CreateChild<SmallButton>(
|
||||
const auto plus = Ui::CreateSimpleCircleButton(
|
||||
this,
|
||||
'+',
|
||||
0,
|
||||
_st.itemFg);
|
||||
plus->setClickedCallback([this] {
|
||||
_delegate->ivSetZoom(_delegate->ivZoom() + kZoomStep);
|
||||
st::defaultRippleAnimationBgOver);
|
||||
plus->resize(Size(st::ivZoomButtonsSize));
|
||||
plus->paintRequest() | rpl::start_with_next([=, fg = _st.itemFg] {
|
||||
auto p = QPainter(plus);
|
||||
p.setPen(fg);
|
||||
p.setFont(st::normalFont);
|
||||
p.drawText(plus->rect(), QChar('+'), style::al_center);
|
||||
}, plus->lifetime());
|
||||
processTooltip(plus);
|
||||
const auto step = [] {
|
||||
return base::IsAltPressed()
|
||||
? kZoomTinyStep
|
||||
: base::IsCtrlPressed()
|
||||
? kZoomSmallStep
|
||||
: kZoomStep;
|
||||
};
|
||||
plus->setClickedCallback([this, step] {
|
||||
_delegate->ivSetZoom(_delegate->ivZoom() + step());
|
||||
});
|
||||
plus->show();
|
||||
const auto minus = Ui::CreateChild<SmallButton>(
|
||||
const auto minus = Ui::CreateSimpleCircleButton(
|
||||
this,
|
||||
QChar(0x2013),
|
||||
-1,
|
||||
_st.itemFg);
|
||||
minus->setClickedCallback([this] {
|
||||
_delegate->ivSetZoom(_delegate->ivZoom() - kZoomStep);
|
||||
st::defaultRippleAnimationBgOver);
|
||||
minus->resize(Size(st::ivZoomButtonsSize));
|
||||
minus->paintRequest() | rpl::start_with_next([=, fg = _st.itemFg] {
|
||||
auto p = QPainter(minus);
|
||||
const auto r = minus->rect();
|
||||
p.setPen(fg);
|
||||
p.setFont(st::normalFont);
|
||||
p.drawText(
|
||||
QRectF(r).translated(0, style::ConvertFloatScale(-1)),
|
||||
QChar(0x2013),
|
||||
style::al_center);
|
||||
}, minus->lifetime());
|
||||
processTooltip(minus);
|
||||
minus->setClickedCallback([this, step] {
|
||||
_delegate->ivSetZoom(_delegate->ivZoom() - step());
|
||||
});
|
||||
minus->show();
|
||||
|
||||
{
|
||||
const auto maxWidthText = u"000%"_q;
|
||||
_text.setText(_st.itemStyle, maxWidthText);
|
||||
Ui::Menu::ItemBase::setMinWidth(
|
||||
_text.maxWidth()
|
||||
+ st::ivResetZoomInnerPadding
|
||||
+ resetLabel->width()
|
||||
+ plus->width()
|
||||
+ minus->width()
|
||||
+ _st.itemPadding.right() * 2);
|
||||
}
|
||||
|
||||
_delegate->ivZoomValue(
|
||||
) | rpl::start_with_next([this](int value) {
|
||||
_text.setText(_st.itemStyle, QString::number(value) + '%');
|
||||
@@ -155,7 +175,7 @@ public:
|
||||
rpl::combine(
|
||||
sizeValue(),
|
||||
reset->sizeValue()
|
||||
) | rpl::start_with_next([=, this](const QSize &size, const QSize &) {
|
||||
) | rpl::start_with_next([=](const QSize &size, const QSize &) {
|
||||
reset->setFullWidth(0
|
||||
+ resetLabel->width()
|
||||
+ st::ivResetZoomInnerPadding);
|
||||
@@ -186,6 +206,22 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
QString tooltipText() const override {
|
||||
#ifdef Q_OS_MAC
|
||||
return tr::lng_iv_zoom_tooltip_cmd(tr::now);
|
||||
#else
|
||||
return tr::lng_iv_zoom_tooltip_ctrl(tr::now);
|
||||
#endif
|
||||
}
|
||||
|
||||
QPoint tooltipPos() const override {
|
||||
return QCursor::pos();
|
||||
}
|
||||
|
||||
bool tooltipWindowActive() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const not_null<Delegate*> _delegate;
|
||||
const style::Menu &_st;
|
||||
@@ -349,10 +385,16 @@ Controller::Controller(
|
||||
Fn<ShareBoxResult(ShareBoxDescriptor)> showShareBox)
|
||||
: _delegate(delegate)
|
||||
, _updateStyles([=] {
|
||||
const auto zoom = _delegate->ivZoom();
|
||||
const auto str = Ui::EscapeForScriptString(ComputeStyles(zoom));
|
||||
if (_webview) {
|
||||
const auto webviewZoomController = _webview->zoomController();
|
||||
const auto styleZoom = webviewZoomController
|
||||
? kDefaultZoom
|
||||
: _delegate->ivZoom();
|
||||
const auto str = Ui::EscapeForScriptString(ComputeStyles(styleZoom));
|
||||
_webview->eval("IV.updateStyles('" + str + "');");
|
||||
if (webviewZoomController) {
|
||||
webviewZoomController->setZoom(_delegate->ivZoom());
|
||||
}
|
||||
}
|
||||
})
|
||||
, _showShareBox(std::move(showShareBox)) {
|
||||
@@ -619,6 +661,19 @@ void Controller::createWebview(const Webview::StorageId &storageId) {
|
||||
});
|
||||
const auto raw = _webview.get();
|
||||
|
||||
if (const auto webviewZoomController = raw->zoomController()) {
|
||||
webviewZoomController->zoomValue(
|
||||
) | rpl::start_with_next([this](int value) {
|
||||
if (value > 0) {
|
||||
_delegate->ivSetZoom(value);
|
||||
}
|
||||
}, lifetime());
|
||||
_delegate->ivZoomValue(
|
||||
) | rpl::start_with_next([=](int value) {
|
||||
webviewZoomController->setZoom(value);
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
window->lifetime().add([=] {
|
||||
_ready = false;
|
||||
base::take(_webview);
|
||||
@@ -770,8 +825,12 @@ void Controller::createWebview(const Webview::StorageId &storageId) {
|
||||
|| index >= _pages.size()) {
|
||||
return Webview::DataResult::Failed;
|
||||
}
|
||||
const auto webviewZoomController = _webview->zoomController();
|
||||
const auto styleZoom = webviewZoomController
|
||||
? kDefaultZoom
|
||||
: _delegate->ivZoom();
|
||||
return finishWith(
|
||||
WrapPage(_pages[index], _delegate->ivZoom()),
|
||||
WrapPage(_pages[index], styleZoom),
|
||||
"text/html; charset=utf-8");
|
||||
} else if (id.starts_with("page") && id.ends_with(".json")) {
|
||||
auto index = 0;
|
||||
@@ -942,6 +1001,8 @@ void Controller::processKey(const QString &key, const QString &modifier) {
|
||||
minimize();
|
||||
} else if (key == u"q"_q && modifier == ctrl) {
|
||||
quit();
|
||||
} else if (key == u"0"_q && modifier == ctrl) {
|
||||
_delegate->ivSetZoom(kDefaultZoom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -389,11 +389,17 @@ QByteArray Parser::block(const MTPDpageBlockUnsupported &data) {
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockTitle &data) {
|
||||
return tag("h1", { { "class", "title" } }, rich(data.vtext()));
|
||||
return tag("h1", {
|
||||
{ "class", "title" },
|
||||
{ "dir", "auto" },
|
||||
}, rich(data.vtext()));
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockSubtitle &data) {
|
||||
return tag("h2", { { "class", "subtitle" } }, rich(data.vtext()));
|
||||
return tag("h2", {
|
||||
{ "class", "subtitle" },
|
||||
{ "dir", "auto" },
|
||||
}, rich(data.vtext()));
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockAuthorDate &data) {
|
||||
@@ -401,23 +407,29 @@ QByteArray Parser::block(const MTPDpageBlockAuthorDate &data) {
|
||||
if (const auto date = data.vpublished_date().v) {
|
||||
inner += " \xE2\x80\xA2 " + tag("time", Date(date));
|
||||
}
|
||||
return tag("address", inner);
|
||||
return tag("address", { { "dir", "auto" } }, inner);
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockHeader &data) {
|
||||
return tag("h3", { { "class", "header" } }, rich(data.vtext()));
|
||||
return tag("h3", {
|
||||
{ "class", "header" },
|
||||
{ "dir", "auto" },
|
||||
}, rich(data.vtext()));
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockSubheader &data) {
|
||||
return tag("h4", { { "class", "subheader" } }, rich(data.vtext()));
|
||||
return tag("h4", {
|
||||
{ "class", "subheader" },
|
||||
{ "dir", "auto" },
|
||||
}, rich(data.vtext()));
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockParagraph &data) {
|
||||
return tag("p", rich(data.vtext()));
|
||||
return tag("p", { { "dir", "auto" } }, rich(data.vtext()));
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockPreformatted &data) {
|
||||
auto list = Attributes();
|
||||
auto list = Attributes{ { "dir", "auto" } };
|
||||
const auto language = utf(data.vlanguage());
|
||||
if (!language.isEmpty()) {
|
||||
list.push_back({ "data-language", language });
|
||||
@@ -428,7 +440,10 @@ QByteArray Parser::block(const MTPDpageBlockPreformatted &data) {
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockFooter &data) {
|
||||
return tag("footer", { { "class", "footer" } }, rich(data.vtext()));
|
||||
return tag("footer", {
|
||||
{ "class", "footer" },
|
||||
{ "dir", "auto" },
|
||||
}, rich(data.vtext()));
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockDivider &data) {
|
||||
@@ -447,19 +462,21 @@ QByteArray Parser::block(const MTPDpageBlockBlockquote &data) {
|
||||
const auto caption = rich(data.vcaption());
|
||||
const auto cite = caption.isEmpty()
|
||||
? QByteArray()
|
||||
: tag("cite", caption);
|
||||
return tag("blockquote", rich(data.vtext()) + cite);
|
||||
: tag("cite", { { "dir", "auto" } }, caption);
|
||||
return tag("blockquote", {
|
||||
{ "dir", "auto" }
|
||||
}, rich(data.vtext()) + cite);
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockPullquote &data) {
|
||||
const auto caption = rich(data.vcaption());
|
||||
const auto cite = caption.isEmpty()
|
||||
? QByteArray()
|
||||
: tag("cite", caption);
|
||||
return tag(
|
||||
"div",
|
||||
{ { "class", "pullquote" } },
|
||||
rich(data.vtext()) + cite);
|
||||
: tag("cite", { { "dir", "auto" } }, caption);
|
||||
return tag("div", {
|
||||
{ "class", "pullquote" },
|
||||
{ "dir", "auto" },
|
||||
}, rich(data.vtext()) + cite);
|
||||
}
|
||||
|
||||
QByteArray Parser::block(
|
||||
@@ -763,7 +780,10 @@ QByteArray Parser::block(const MTPDpageBlockAudio &data) {
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockKicker &data) {
|
||||
return tag("h5", { { "class", "kicker" } }, rich(data.vtext()));
|
||||
return tag("h5", {
|
||||
{ "class", "kicker" },
|
||||
{ "dir", "auto" },
|
||||
}, rich(data.vtext()));
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockTable &data) {
|
||||
@@ -780,7 +800,7 @@ QByteArray Parser::block(const MTPDpageBlockTable &data) {
|
||||
}
|
||||
auto title = rich(data.vtitle());
|
||||
if (!title.isEmpty()) {
|
||||
title = tag("caption", title);
|
||||
title = tag("caption", { { "dir", "auto" } }, title);
|
||||
}
|
||||
auto result = tag("table", attibutes, title + list(data.vrows()));
|
||||
result = tag("figure", { { "class", "table" } }, result);
|
||||
@@ -800,7 +820,8 @@ QByteArray Parser::block(const MTPDpageBlockDetails &data) {
|
||||
return tag(
|
||||
"details",
|
||||
attributes,
|
||||
tag("summary", rich(data.vtitle())) + list(data.vblocks()));
|
||||
(tag("summary", { { "dir", "auto" } }, rich(data.vtitle()))
|
||||
+ list(data.vblocks())));
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageBlockRelatedArticles &data) {
|
||||
@@ -810,7 +831,10 @@ QByteArray Parser::block(const MTPDpageBlockRelatedArticles &data) {
|
||||
}
|
||||
auto title = rich(data.vtitle());
|
||||
if (!title.isEmpty()) {
|
||||
title = tag("h4", { { "class", "related-title" } }, title);
|
||||
title = tag("h4", {
|
||||
{ "class", "related-title" },
|
||||
{ "dir", "auto" },
|
||||
}, title);
|
||||
}
|
||||
return tag("section", { { "class", "related" } }, title + result);
|
||||
}
|
||||
@@ -899,7 +923,7 @@ QByteArray Parser::block(const MTPDpageTableCell &data) {
|
||||
} else {
|
||||
style += "vertical-align:top;";
|
||||
}
|
||||
auto attributes = Attributes{ { "style", style } };
|
||||
auto attributes = Attributes{ { "style", style }, { "dir", "auto" } };
|
||||
if (const auto cs = data.vcolspan()) {
|
||||
attributes.push_back({ "colspan", Number(cs->v) });
|
||||
}
|
||||
@@ -910,7 +934,7 @@ QByteArray Parser::block(const MTPDpageTableCell &data) {
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageListItemText &data) {
|
||||
return tag("li", rich(data.vtext()));
|
||||
return tag("li", { { "dir", "auto" } }, rich(data.vtext()));
|
||||
}
|
||||
|
||||
QByteArray Parser::block(const MTPDpageListItemBlocks &data) {
|
||||
@@ -920,7 +944,7 @@ QByteArray Parser::block(const MTPDpageListItemBlocks &data) {
|
||||
QByteArray Parser::block(const MTPDpageListOrderedItemText &data) {
|
||||
return tag(
|
||||
"li",
|
||||
{ { "value", utf(data.vnum()) } },
|
||||
{ { "value", utf(data.vnum()) }, { "dir", "auto" } },
|
||||
rich(data.vtext()));
|
||||
}
|
||||
|
||||
@@ -1073,11 +1097,11 @@ QByteArray Parser::caption(const MTPPageCaption &caption) {
|
||||
auto text = rich(caption.data().vtext());
|
||||
const auto credit = rich(caption.data().vcredit());
|
||||
if (!credit.isEmpty()) {
|
||||
text += tag("cite", credit);
|
||||
text += tag("cite", { { "dir", "auto" } }, credit);
|
||||
} else if (text.isEmpty()) {
|
||||
return QByteArray();
|
||||
}
|
||||
return tag("figcaption", text);
|
||||
return tag("figcaption", { { "dir", "auto" } }, text);
|
||||
}
|
||||
|
||||
Photo Parser::parse(const MTPPhoto &photo) {
|
||||
|
||||
Reference in New Issue
Block a user