mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Implement title and in-IV buttons.
This commit is contained in:
parent
f9299eee2a
commit
f508ad5e75
11 changed files with 416 additions and 42 deletions
|
@ -28,6 +28,100 @@ html.custom_scroll ::-webkit-scrollbar-thumb:hover {
|
|||
background-color: var(--td-scroll-bar-bg-over) !important;
|
||||
}
|
||||
|
||||
.fixed_button {
|
||||
position: fixed;
|
||||
background-color: var(--td-history-to-down-bg);
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
box-shadow: 0 0 4px -2px var(--td-history-to-down-shadow);
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.fixed_button:hover {
|
||||
background-color: var(--td-history-to-down-bg-over);
|
||||
}
|
||||
.fixed_button svg {
|
||||
fill: none;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.fixed_button .ripple .inner {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
transform: scale(0);
|
||||
opacity: 1;
|
||||
animation: ripple 650ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
|
||||
background-color: var(--td-history-to-down-bg-ripple);
|
||||
}
|
||||
.fixed_button .ripple.hiding {
|
||||
animation: fadeOut 200ms linear forwards;
|
||||
}
|
||||
@keyframes ripple {
|
||||
to {
|
||||
transform: scale(2);
|
||||
}
|
||||
}
|
||||
@keyframes fadeOut {
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
#top_menu svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
#top_menu circle {
|
||||
fill: var(--td-history-to-down-fg);
|
||||
}
|
||||
#top_menu:hover circle {
|
||||
fill: var(--td-history-to-down-fg-over);
|
||||
}
|
||||
#top_menu {
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
#top_back path,
|
||||
#bottom_up path {
|
||||
stroke: var(--td-history-to-down-fg);
|
||||
stroke-width: 2;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
#top_back:hover path,
|
||||
#bottom_up:hover path {
|
||||
stroke: var(--td-history-to-down-fg-over);
|
||||
}
|
||||
#top_back {
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
transition: left 200ms linear;
|
||||
}
|
||||
#top_back svg {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
#top_back.hidden {
|
||||
left: -36px;
|
||||
}
|
||||
#bottom_up {
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
transition: bottom 200ms linear;
|
||||
}
|
||||
#bottom_up svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
#bottom_up.hidden {
|
||||
bottom: -36px;
|
||||
}
|
||||
|
||||
article {
|
||||
padding-bottom: 12px;
|
||||
overflow: hidden;
|
||||
|
|
|
@ -25,15 +25,15 @@ var IV = {
|
|||
e.preventDefault();
|
||||
},
|
||||
frameKeyDown: function (e) {
|
||||
let keyW = (e.key === 'w')
|
||||
const keyW = (e.key === 'w')
|
||||
|| (e.code === 'KeyW')
|
||||
|| (e.keyCode === 87);
|
||||
let keyQ = (e.key === 'q')
|
||||
const keyQ = (e.key === 'q')
|
||||
|| (e.code === 'KeyQ')
|
||||
|| (e.keyCode === 81);
|
||||
let keyM = (e.key === 'm')
|
||||
|| (e.code === 'KeyM')
|
||||
|| (e.keyCode === 77);
|
||||
const keyM = (e.key === 'm')
|
||||
|| (e.code === 'KeyM')
|
||||
|| (e.keyCode === 77);
|
||||
if ((e.metaKey || e.ctrlKey) && (keyW || keyQ || keyM)) {
|
||||
e.preventDefault();
|
||||
IV.notify({
|
||||
|
@ -49,13 +49,26 @@ var IV = {
|
|||
});
|
||||
}
|
||||
},
|
||||
frameMouseEnter: function (e) {
|
||||
IV.notify({ event: 'mouseenter' });
|
||||
},
|
||||
frameMouseUp: function (e) {
|
||||
IV.notify({ event: 'mouseup' });
|
||||
},
|
||||
lastScrollTop: 0,
|
||||
frameScrolled: function (e) {
|
||||
const now = document.documentElement.scrollTop;
|
||||
if (now < 100) {
|
||||
document.getElementById('bottom_up').classList.add('hidden');
|
||||
} else if (now > IV.lastScrollTop && now > 200) {
|
||||
document.getElementById('bottom_up').classList.remove('hidden');
|
||||
}
|
||||
IV.lastScrollTop = now;
|
||||
},
|
||||
updateStyles: function (styles) {
|
||||
if (IV.styles !== styles) {
|
||||
console.log('Setting', styles);
|
||||
IV.styles = styles;
|
||||
document.getElementsByTagName('html')[0].style = styles;
|
||||
} else {
|
||||
console.log('Skipping', styles);
|
||||
}
|
||||
},
|
||||
slideshowSlide: function(el, next) {
|
||||
|
@ -72,7 +85,9 @@ var IV = {
|
|||
return false;
|
||||
},
|
||||
initPreBlocks: function() {
|
||||
if (!hljs) return;
|
||||
if (!hljs) {
|
||||
return;
|
||||
}
|
||||
var pres = document.getElementsByTagName('pre');
|
||||
for (var i = 0; i < pres.length; i++) {
|
||||
if (pres[i].hasAttribute('data-language')) {
|
||||
|
@ -102,9 +117,71 @@ var IV = {
|
|||
}, false);
|
||||
})(iframes[i]);
|
||||
}
|
||||
},
|
||||
addRipple: function (button, x, y) {
|
||||
const ripple = document.createElement('span');
|
||||
ripple.classList.add('ripple');
|
||||
|
||||
const inner = document.createElement('span');
|
||||
inner.classList.add('inner');
|
||||
x -= button.offsetLeft;
|
||||
y -= button.offsetTop;
|
||||
|
||||
const mx = button.clientWidth - x;
|
||||
const my = button.clientHeight - y;
|
||||
const sq1 = x * x + y * y;
|
||||
const sq2 = mx * mx + y * y;
|
||||
const sq3 = x * x + my * my;
|
||||
const sq4 = mx * mx + my * my;
|
||||
const radius = Math.sqrt(Math.max(sq1, sq2, sq3, sq4));
|
||||
|
||||
inner.style.width = inner.style.height = `${2 * radius}px`;
|
||||
inner.style.left = `${x - radius}px`;
|
||||
inner.style.top = `${y - radius}px`;
|
||||
inner.classList.add('inner');
|
||||
|
||||
ripple.addEventListener('animationend', function (e) {
|
||||
if (e.animationName === 'fadeOut') {
|
||||
ripple.remove();
|
||||
}
|
||||
});
|
||||
|
||||
ripple.appendChild(inner);
|
||||
button.appendChild(ripple);
|
||||
},
|
||||
stopRipples: function (button) {
|
||||
const ripples = button.getElementsByClassName('ripple');
|
||||
for (var i = 0; i < ripples.length; ++i) {
|
||||
const ripple = ripples[i];
|
||||
if (!ripple.classList.contains('hiding')) {
|
||||
ripple.classList.add('hiding');
|
||||
}
|
||||
}
|
||||
},
|
||||
init: function () {
|
||||
const buttons = document.getElementsByClassName('fixed_button');
|
||||
for (let i = 0; i < buttons.length; ++i) {
|
||||
const button = buttons[i];
|
||||
button.addEventListener('mousedown', function (e) {
|
||||
IV.addRipple(e.currentTarget, e.clientX, e.clientY);
|
||||
});
|
||||
button.addEventListener('mouseup', function (e) {
|
||||
IV.stopRipples(e.currentTarget);
|
||||
});
|
||||
button.addEventListener('mouseleave', function (e) {
|
||||
IV.stopRipples(e.currentTarget);
|
||||
});
|
||||
}
|
||||
},
|
||||
toTop: function () {
|
||||
document.getElementById('bottom_up').classList.add('hidden');
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
};
|
||||
|
||||
document.onclick = IV.frameClickHandler;
|
||||
document.onkeydown = IV.frameKeyDown;
|
||||
document.onmouseenter = IV.frameMouseEnter;
|
||||
document.onmouseup = IV.frameMouseUp;
|
||||
document.onscroll = IV.frameScrolled;
|
||||
window.onmessage = IV.postMessageHandler;
|
||||
|
|
100
Telegram/SourceFiles/iv/iv.style
Normal file
100
Telegram/SourceFiles/iv/iv.style
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
using "ui/basic.style";
|
||||
using "ui/widgets/widgets.style";
|
||||
|
||||
ivTitleHeight: 24px;
|
||||
ivTitleIconShift: point(0px, 0px);
|
||||
ivTitleButton: IconButton(windowTitleButton) {
|
||||
height: ivTitleHeight;
|
||||
iconPosition: ivTitleIconShift;
|
||||
}
|
||||
ivTitleButtonClose: IconButton(windowTitleButtonClose) {
|
||||
height: ivTitleHeight;
|
||||
iconPosition: ivTitleIconShift;
|
||||
}
|
||||
|
||||
ivTitleButtonSize: size(windowTitleButtonWidth, ivTitleHeight);
|
||||
ivTitle: WindowTitle(defaultWindowTitle) {
|
||||
height: ivTitleHeight;
|
||||
style: TextStyle(defaultTextStyle) {
|
||||
font: font(semibold 12px);
|
||||
}
|
||||
shadow: false;
|
||||
minimize: IconButton(ivTitleButton) {
|
||||
icon: icon {
|
||||
{ ivTitleButtonSize, titleButtonBg },
|
||||
{ "title_button_minimize", titleButtonFg, ivTitleIconShift },
|
||||
};
|
||||
iconOver: icon {
|
||||
{ ivTitleButtonSize, titleButtonBgOver },
|
||||
{ "title_button_minimize", titleButtonFgOver, ivTitleIconShift },
|
||||
};
|
||||
}
|
||||
minimizeIconActive: icon {
|
||||
{ ivTitleButtonSize, titleButtonBgActive },
|
||||
{ "title_button_minimize", titleButtonFgActive, ivTitleIconShift },
|
||||
};
|
||||
minimizeIconActiveOver: icon {
|
||||
{ ivTitleButtonSize, titleButtonBgActiveOver },
|
||||
{ "title_button_minimize", titleButtonFgActiveOver, ivTitleIconShift },
|
||||
};
|
||||
maximize: IconButton(windowTitleButton) {
|
||||
icon: icon {
|
||||
{ ivTitleButtonSize, titleButtonBg },
|
||||
{ "title_button_maximize", titleButtonFg, ivTitleIconShift },
|
||||
};
|
||||
iconOver: icon {
|
||||
{ ivTitleButtonSize, titleButtonBgOver },
|
||||
{ "title_button_maximize", titleButtonFgOver, ivTitleIconShift },
|
||||
};
|
||||
}
|
||||
maximizeIconActive: icon {
|
||||
{ ivTitleButtonSize, titleButtonBgActive },
|
||||
{ "title_button_maximize", titleButtonFgActive, ivTitleIconShift },
|
||||
};
|
||||
maximizeIconActiveOver: icon {
|
||||
{ ivTitleButtonSize, titleButtonBgActiveOver },
|
||||
{ "title_button_maximize", titleButtonFgActiveOver, ivTitleIconShift },
|
||||
};
|
||||
restoreIcon: icon {
|
||||
{ ivTitleButtonSize, titleButtonBg },
|
||||
{ "title_button_restore", titleButtonFg, ivTitleIconShift },
|
||||
};
|
||||
restoreIconOver: icon {
|
||||
{ ivTitleButtonSize, titleButtonBgOver },
|
||||
{ "title_button_restore", titleButtonFgOver, ivTitleIconShift },
|
||||
};
|
||||
restoreIconActive: icon {
|
||||
{ ivTitleButtonSize, titleButtonBgActive },
|
||||
{ "title_button_restore", titleButtonFgActive, ivTitleIconShift },
|
||||
};
|
||||
restoreIconActiveOver: icon {
|
||||
{ ivTitleButtonSize, titleButtonBgActiveOver },
|
||||
{ "title_button_restore", titleButtonFgActiveOver, ivTitleIconShift },
|
||||
};
|
||||
close: IconButton(windowTitleButtonClose) {
|
||||
icon: icon {
|
||||
{ ivTitleButtonSize, titleButtonCloseBg },
|
||||
{ "title_button_close", titleButtonCloseFg, ivTitleIconShift },
|
||||
};
|
||||
iconOver: icon {
|
||||
{ ivTitleButtonSize, titleButtonCloseBgOver },
|
||||
{ "title_button_close", titleButtonCloseFgOver, ivTitleIconShift },
|
||||
};
|
||||
}
|
||||
closeIconActive: icon {
|
||||
{ ivTitleButtonSize, titleButtonCloseBgActive },
|
||||
{ "title_button_close", titleButtonCloseFgActive, ivTitleIconShift },
|
||||
};
|
||||
closeIconActiveOver: icon {
|
||||
{ ivTitleButtonSize, titleButtonCloseBgActiveOver },
|
||||
{ "title_button_close", titleButtonCloseFgActiveOver, ivTitleIconShift },
|
||||
};
|
||||
}
|
||||
ivTitleExpandedHeight: 76px;
|
|
@ -11,14 +11,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/invoke_queued.h"
|
||||
#include "iv/iv_data.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/platform/ui_platform_window_title.h"
|
||||
#include "ui/widgets/rp_window.h"
|
||||
#include "ui/painter.h"
|
||||
#include "webview/webview_data_stream_memory.h"
|
||||
#include "webview/webview_embed.h"
|
||||
#include "webview/webview_interface.h"
|
||||
#include "styles/palette.h"
|
||||
|
||||
#include "base/call_delayed.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "styles/style_iv.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_window.h"
|
||||
|
||||
#include <QtCore/QRegularExpression>
|
||||
#include <QtCore/QJsonDocument>
|
||||
|
@ -39,12 +41,23 @@ namespace {
|
|||
{ "window-bg", &st::windowBg },
|
||||
{ "window-bg-over", &st::windowBgOver },
|
||||
{ "window-bg-ripple", &st::windowBgRipple },
|
||||
{ "window-bg-active", &st::windowBgActive },
|
||||
{ "window-fg", &st::windowFg },
|
||||
{ "window-sub-text-fg", &st::windowSubTextFg },
|
||||
{ "window-active-text-fg", &st::windowActiveTextFg },
|
||||
{ "window-bg-active", &st::windowBgActive },
|
||||
{ "window-shadow-fg", &st::windowShadowFg },
|
||||
{ "box-divider-bg", &st::boxDividerBg },
|
||||
{ "box-divider-fg", &st::boxDividerFg },
|
||||
{ "menu-icon-fg", &st::menuIconFg },
|
||||
{ "menu-icon-fg-over", &st::menuIconFgOver },
|
||||
{ "menu-bg", &st::menuBg },
|
||||
{ "menu-bg-over", &st::menuBgOver },
|
||||
{ "history-to-down-fg", &st::historyToDownFg },
|
||||
{ "history-to-down-fg-over", &st::historyToDownFgOver },
|
||||
{ "history-to-down-bg", &st::historyToDownBg },
|
||||
{ "history-to-down-bg-over", &st::historyToDownBgOver },
|
||||
{ "history-to-down-bg-ripple", &st::historyToDownBgRipple },
|
||||
{ "history-to-down-shadow", &st::historyToDownShadow },
|
||||
};
|
||||
static const auto phrases = base::flat_map<QByteArray, tr::phrase<>>{
|
||||
{ "group-call-join", tr::lng_group_call_join },
|
||||
|
@ -124,52 +137,103 @@ Controller::Controller()
|
|||
|
||||
Controller::~Controller() {
|
||||
_webview = nullptr;
|
||||
_title = nullptr;
|
||||
_window = nullptr;
|
||||
}
|
||||
|
||||
void Controller::show(const QString &dataPath, Prepared page) {
|
||||
createWindow();
|
||||
_titleText.setText(st::ivTitle.style, page.title);
|
||||
InvokeQueued(_container, [=, page = std::move(page)]() mutable {
|
||||
showInWindow(dataPath, std::move(page));
|
||||
});
|
||||
}
|
||||
|
||||
void Controller::updateTitleGeometry() {
|
||||
_title->setGeometry(0, 0, _window->width(), st::ivTitle.height);
|
||||
}
|
||||
|
||||
void Controller::paintTitle(Painter &p, QRect clip) {
|
||||
const auto active = _window->isActiveWindow();
|
||||
const auto full = _title->width();
|
||||
p.setPen(active ? st::ivTitle.fgActive : st::ivTitle.fg);
|
||||
const auto available = QRect(
|
||||
_titleLeftSkip,
|
||||
0,
|
||||
full - _titleLeftSkip - _titleRightSkip,
|
||||
_title->height());
|
||||
const auto use = std::min(available.width(), _titleText.maxWidth());
|
||||
const auto center = full
|
||||
- 2 * std::max(_titleLeftSkip, _titleRightSkip);
|
||||
const auto left = (use <= center)
|
||||
? ((full - use) / 2)
|
||||
: (use < available.width() && _titleLeftSkip < _titleRightSkip)
|
||||
? (available.x() + available.width() - use)
|
||||
: available.x();
|
||||
const auto titleTextHeight = st::ivTitle.style.font->height;
|
||||
const auto top = (st::ivTitle.height - titleTextHeight) / 2;
|
||||
_titleText.drawLeftElided(p, left, top, available.width(), full);
|
||||
}
|
||||
|
||||
void Controller::createWindow() {
|
||||
_window = std::make_unique<Ui::RpWindow>();
|
||||
_window->setTitleStyle(st::ivTitle);
|
||||
const auto window = _window.get();
|
||||
|
||||
window->setGeometry({ 200, 200, 600, 800 });
|
||||
_title = std::make_unique<Ui::RpWidget>(window);
|
||||
_title->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
_title->paintRequest() | rpl::start_with_next([=](QRect clip) {
|
||||
auto p = Painter(_title.get());
|
||||
paintTitle(p, clip);
|
||||
}, _title->lifetime());
|
||||
window->widthValue() | rpl::start_with_next([=] {
|
||||
updateTitleGeometry();
|
||||
}, _title->lifetime());
|
||||
|
||||
const auto skip = window->lifetime().make_state<rpl::variable<int>>(0);
|
||||
#ifdef Q_OS_MAC
|
||||
_titleLeftSkip = 8 + 12 + 8 + 12 + 8 + 12 + 8;
|
||||
_titleRightSkip = st::ivTitle.style.font->spacew;
|
||||
#else // Q_OS_MAC
|
||||
using namespace Ui::Platform;
|
||||
TitleControlsLayoutValue(
|
||||
) | rpl::start_with_next([=](TitleControls::Layout layout) {
|
||||
const auto accumulate = [](const auto &list) {
|
||||
auto result = 0;
|
||||
for (const auto control : list) {
|
||||
switch (control) {
|
||||
case TitleControl::Close:
|
||||
result += st::ivTitle.close.width;
|
||||
break;
|
||||
case TitleControl::Minimize:
|
||||
result += st::ivTitle.minimize.width;
|
||||
break;
|
||||
case TitleControl::Maximize:
|
||||
result += st::ivTitle.maximize.width;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const auto space = st::ivTitle.style.font->spacew;
|
||||
_titleLeftSkip = accumulate(layout.left) + space;
|
||||
_titleRightSkip = accumulate(layout.right) + space;
|
||||
_title->update();
|
||||
}, _title->lifetime());
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
window->setGeometry({ 200, 200, 600, 800 });
|
||||
window->setMinimumSize({ st::windowMinWidth, st::windowMinHeight });
|
||||
|
||||
_container = Ui::CreateChild<Ui::RpWidget>(window->body().get());
|
||||
rpl::combine(
|
||||
window->body()->sizeValue(),
|
||||
skip->value()
|
||||
) | rpl::start_with_next([=](QSize size, int skip) {
|
||||
_container->setGeometry(QRect(QPoint(), size).marginsRemoved({ 0, skip, 0, 0 }));
|
||||
_title->heightValue()
|
||||
) | rpl::start_with_next([=](QSize size, int title) {
|
||||
title -= window->body()->y();
|
||||
_container->setGeometry(QRect(QPoint(), size).marginsRemoved(
|
||||
{ 0, title, 0, 0 }));
|
||||
}, _container->lifetime());
|
||||
|
||||
base::call_delayed(5000, window, [=] {
|
||||
const auto animation = window->lifetime().make_state<Ui::Animations::Simple>();
|
||||
animation->start([=] {
|
||||
*skip = animation->value(64);
|
||||
if (!animation->animating()) {
|
||||
base::call_delayed(4000, window, [=] {
|
||||
animation->start([=] {
|
||||
*skip = animation->value(0);
|
||||
}, 64, 0, 200, anim::easeOutCirc);
|
||||
});
|
||||
}
|
||||
}, 0, 64, 200, anim::easeOutCirc);
|
||||
});
|
||||
|
||||
window->body()->paintRequest() | rpl::start_with_next([=](QRect clip) {
|
||||
auto p = QPainter(window->body());
|
||||
p.fillRect(clip, st::windowBg);
|
||||
p.fillRect(clip, QColor(0, 128, 0, 128));
|
||||
}, window->body()->lifetime());
|
||||
|
||||
_container->paintRequest() | rpl::start_with_next([=](QRect clip) {
|
||||
QPainter(_container).fillRect(clip, st::windowBg);
|
||||
}, _container->lifetime());
|
||||
|
@ -237,6 +301,10 @@ void Controller::showInWindow(const QString &dataPath, Prepared page) {
|
|||
} else if (key == u"q"_q && modifier == ctrl) {
|
||||
quit();
|
||||
}
|
||||
} else if (event == u"mouseenter"_q) {
|
||||
window->overrideSystemButtonOver({});
|
||||
} else if (event == u"mouseup"_q) {
|
||||
window->overrideSystemButtonDown({});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,6 +8,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "base/invoke_queued.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/text/text.h"
|
||||
|
||||
class Painter;
|
||||
|
||||
namespace Webview {
|
||||
struct DataRequest;
|
||||
|
@ -49,6 +53,8 @@ public:
|
|||
|
||||
private:
|
||||
void createWindow();
|
||||
void updateTitleGeometry();
|
||||
void paintTitle(Painter &p, QRect clip);
|
||||
void showInWindow(const QString &dataPath, Prepared page);
|
||||
|
||||
void escape();
|
||||
|
@ -56,6 +62,10 @@ private:
|
|||
void quit();
|
||||
|
||||
std::unique_ptr<Ui::RpWindow> _window;
|
||||
std::unique_ptr<Ui::RpWidget> _title;
|
||||
Ui::Text::String _titleText;
|
||||
int _titleLeftSkip = 0;
|
||||
int _titleRightSkip = 0;
|
||||
Ui::RpWidget *_container = nullptr;
|
||||
std::unique_ptr<Webview::Window> _webview;
|
||||
rpl::event_stream<Webview::DataRequest> _dataRequests;
|
||||
|
|
|
@ -45,6 +45,9 @@ Data::Data(const MTPDwebPage &webpage, const MTPPage &page)
|
|||
.webpageDocument = (webpage.vdocument()
|
||||
? *webpage.vdocument()
|
||||
: std::optional<MTPDocument>()),
|
||||
.title = (webpage.vtitle()
|
||||
? qs(*webpage.vtitle())
|
||||
: qs(webpage.vauthor().value_or_empty()))
|
||||
})) {
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ struct Options {
|
|||
};
|
||||
|
||||
struct Prepared {
|
||||
QString title;
|
||||
QByteArray html;
|
||||
std::vector<QByteArray> resources;
|
||||
base::flat_map<QByteArray, QByteArray> embeds;
|
||||
|
|
|
@ -172,6 +172,7 @@ Parser::Parser(const Source &source, const Options &options)
|
|||
: _options(options)
|
||||
, _rtl(source.page.data().is_rtl()) {
|
||||
process(source);
|
||||
_result.title = source.title;
|
||||
_result.html = prepare(page(source.page.data()));
|
||||
}
|
||||
|
||||
|
@ -1003,9 +1004,7 @@ QByteArray Parser::prepare(QByteArray body) {
|
|||
if (_hasEmbeds) {
|
||||
js += "IV.initEmbedBlocks();";
|
||||
}
|
||||
if (!js.isEmpty()) {
|
||||
body += tag("script", js);
|
||||
}
|
||||
body += tag("script", js + "IV.init();");
|
||||
return html(head, body);
|
||||
}
|
||||
|
||||
|
@ -1026,7 +1025,26 @@ QByteArray Parser::html(const QByteArray &head, const QByteArray &body) {
|
|||
<link rel="stylesheet" href=")" + resource("iv/page.css") + R"(" />
|
||||
)"_q + head + R"(
|
||||
</head>
|
||||
<body>)"_q + body + R"(</body>
|
||||
<body>
|
||||
<button class="fixed_button hidden" id="top_back" onclick="IV.back();">
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M17 13L12 18L7 13M12 6L12 17"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="fixed_button" id="top_menu" onclick="IV.menu();">
|
||||
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="8" cy="2.5" r="1.6"></circle>
|
||||
<circle cx="8" cy="8" r="1.6"></circle>
|
||||
<circle cx="8" cy="13.5" r="1.6"></circle>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="fixed_button hidden" id="bottom_up" onclick="IV.toTop();">
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M17 13L12 18L7 13M12 6L12 17"></path>
|
||||
</svg>
|
||||
</button>
|
||||
)"_q + body + R"(
|
||||
</body>
|
||||
</html>
|
||||
)"_q;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ struct Source {
|
|||
MTPPage page;
|
||||
std::optional<MTPPhoto> webpagePhoto;
|
||||
std::optional<MTPDocument> webpageDocument;
|
||||
QString title;
|
||||
};
|
||||
|
||||
[[nodiscard]] Prepared Prepare(
|
||||
|
|
|
@ -38,4 +38,5 @@ PUBLIC
|
|||
PRIVATE
|
||||
desktop-app::lib_webview
|
||||
tdesktop::td_lang
|
||||
tdesktop::td_ui
|
||||
)
|
||||
|
|
|
@ -26,6 +26,7 @@ set(style_files
|
|||
info/boosts/giveaway/giveaway.style
|
||||
info/userpic/info_userpic_builder.style
|
||||
intro/intro.style
|
||||
iv/iv.style
|
||||
media/player/media_player.style
|
||||
passport/passport.style
|
||||
payments/ui/payments.style
|
||||
|
|
Loading…
Add table
Reference in a new issue