mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Handle shortcuts in IV.
This commit is contained in:
parent
6d733bb566
commit
212259aae3
7 changed files with 261 additions and 95 deletions
|
@ -1,86 +1,112 @@
|
||||||
var IV = {
|
var IV = {
|
||||||
sendPostMessage: function(data) {
|
notify: function(message) {
|
||||||
try {
|
if (window.external && window.external.invoke) {
|
||||||
window.parent.postMessage(JSON.stringify(data), window.parentOrigin);
|
window.external.invoke(JSON.stringify(message));
|
||||||
} catch(e) {}
|
}
|
||||||
},
|
},
|
||||||
frameClickHandler: function(e) {
|
frameClickHandler: function(e) {
|
||||||
var target = e.target, href;
|
var target = e.target, href;
|
||||||
do {
|
do {
|
||||||
if (target.tagName == 'SUMMARY') return;
|
if (target.tagName == 'SUMMARY') return;
|
||||||
if (target.tagName == 'DETAILS') return;
|
if (target.tagName == 'DETAILS') return;
|
||||||
if (target.tagName == 'LABEL') return;
|
if (target.tagName == 'LABEL') return;
|
||||||
if (target.tagName == 'AUDIO') return;
|
if (target.tagName == 'AUDIO') return;
|
||||||
if (target.tagName == 'A') break;
|
if (target.tagName == 'A') break;
|
||||||
} while (target = target.parentNode);
|
} while (target = target.parentNode);
|
||||||
if (target && target.hasAttribute('href')) {
|
if (target && target.hasAttribute('href')) {
|
||||||
var base_loc = document.createElement('A');
|
var base_loc = document.createElement('A');
|
||||||
base_loc.href = window.currentUrl;
|
base_loc.href = window.currentUrl;
|
||||||
if (base_loc.origin != target.origin ||
|
if (base_loc.origin != target.origin ||
|
||||||
base_loc.pathname != target.pathname ||
|
base_loc.pathname != target.pathname ||
|
||||||
base_loc.search != target.search) {
|
base_loc.search != target.search) {
|
||||||
IV.sendPostMessage({event: 'link_click', url: target.href});
|
IV.notify({ event: 'link_click', url: target.href });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
},
|
},
|
||||||
postMessageHandler: function(event) {
|
frameKeyDown: function (e) {
|
||||||
if (event.source !== window.parent ||
|
let keyW = (e.key === 'w')
|
||||||
event.origin != window.parentOrigin) {
|
|| (e.code === 'KeyW')
|
||||||
return;
|
|| (e.keyCode === 87);
|
||||||
}
|
let keyQ = (e.key === 'q')
|
||||||
try {
|
|| (e.code === 'KeyQ')
|
||||||
var data = JSON.parse(event.data);
|
|| (e.keyCode === 81);
|
||||||
} catch(e) {
|
let keyM = (e.key === 'm')
|
||||||
var data = {};
|
|| (e.code === 'KeyM')
|
||||||
}
|
|| (e.keyCode === 77);
|
||||||
},
|
if ((e.metaKey || e.ctrlKey) && (keyW || keyQ || keyM)) {
|
||||||
slideshowSlide: function(el, next) {
|
e.preventDefault();
|
||||||
var dir = window.getComputedStyle(el, null).direction || 'ltr';
|
IV.notify({
|
||||||
var marginProp = dir == 'rtl' ? 'marginRight' : 'marginLeft';
|
event: 'keydown',
|
||||||
if (next) {
|
modifier: e.ctrlKey ? 'ctrl' : 'cmd',
|
||||||
var s = el.previousSibling.s;
|
key: keyW ? 'w' : keyQ ? 'q' : 'm',
|
||||||
s.value = (+s.value + 1 == s.length) ? 0 : +s.value + 1;
|
});
|
||||||
s.forEach(function(el){ el.checked && el.parentNode.scrollIntoView && el.parentNode.scrollIntoView({behavior: 'smooth', block: 'center', inline: 'center'}); });
|
} else if (e.key === 'Escape' || e.keyCode === 27) {
|
||||||
el.firstChild.style[marginProp] = (-100 * s.value) + '%';
|
e.preventDefault();
|
||||||
} else {
|
IV.notify({
|
||||||
el.form.nextSibling.firstChild.style[marginProp] = (-100 * el.value) + '%';
|
event: 'keydown',
|
||||||
}
|
key: 'escape',
|
||||||
return false;
|
});
|
||||||
},
|
}
|
||||||
initPreBlocks: function() {
|
},
|
||||||
if (!hljs) return;
|
postMessageHandler: function(event) {
|
||||||
var pres = document.getElementsByTagName('pre');
|
if (event.source !== window.parent ||
|
||||||
for (var i = 0; i < pres.length; i++) {
|
event.origin != window.parentOrigin) {
|
||||||
if (pres[i].hasAttribute('data-language')) {
|
return;
|
||||||
hljs.highlightBlock(pres[i]);
|
}
|
||||||
}
|
try {
|
||||||
}
|
var data = JSON.parse(event.data);
|
||||||
},
|
} catch(e) {
|
||||||
initEmbedBlocks: function() {
|
var data = {};
|
||||||
var iframes = document.getElementsByTagName('iframe');
|
}
|
||||||
for (var i = 0; i < iframes.length; i++) {
|
},
|
||||||
(function(iframe) {
|
slideshowSlide: function(el, next) {
|
||||||
window.addEventListener('message', function(event) {
|
var dir = window.getComputedStyle(el, null).direction || 'ltr';
|
||||||
if (event.source !== iframe.contentWindow ||
|
var marginProp = dir == 'rtl' ? 'marginRight' : 'marginLeft';
|
||||||
event.origin != window.origin) {
|
if (next) {
|
||||||
return;
|
var s = el.previousSibling.s;
|
||||||
}
|
s.value = (+s.value + 1 == s.length) ? 0 : +s.value + 1;
|
||||||
try {
|
s.forEach(function(el){ el.checked && el.parentNode.scrollIntoView && el.parentNode.scrollIntoView({behavior: 'smooth', block: 'center', inline: 'center'}); });
|
||||||
var data = JSON.parse(event.data);
|
el.firstChild.style[marginProp] = (-100 * s.value) + '%';
|
||||||
} catch(e) {
|
} else {
|
||||||
var data = {};
|
el.form.nextSibling.firstChild.style[marginProp] = (-100 * el.value) + '%';
|
||||||
}
|
}
|
||||||
if (data.eventType == 'resize_frame') {
|
return false;
|
||||||
if (data.eventData.height) {
|
},
|
||||||
iframe.style.height = data.eventData.height + 'px';
|
initPreBlocks: function() {
|
||||||
}
|
if (!hljs) return;
|
||||||
}
|
var pres = document.getElementsByTagName('pre');
|
||||||
}, false);
|
for (var i = 0; i < pres.length; i++) {
|
||||||
})(iframes[i]);
|
if (pres[i].hasAttribute('data-language')) {
|
||||||
}
|
hljs.highlightBlock(pres[i]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initEmbedBlocks: function() {
|
||||||
|
var iframes = document.getElementsByTagName('iframe');
|
||||||
|
for (var i = 0; i < iframes.length; i++) {
|
||||||
|
(function(iframe) {
|
||||||
|
window.addEventListener('message', function(event) {
|
||||||
|
if (event.source !== iframe.contentWindow ||
|
||||||
|
event.origin != window.origin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var data = JSON.parse(event.data);
|
||||||
|
} catch(e) {
|
||||||
|
var data = {};
|
||||||
|
}
|
||||||
|
if (data.eventType == 'resize_frame') {
|
||||||
|
if (data.eventData.height) {
|
||||||
|
iframe.style.height = data.eventData.height + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
})(iframes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.onclick = IV.frameClickHandler;
|
document.onclick = IV.frameClickHandler;
|
||||||
|
document.onkeydown = IV.frameKeyDown;
|
||||||
window.onmessage = IV.postMessageHandler;
|
window.onmessage = IV.postMessageHandler;
|
||||||
|
|
|
@ -1547,12 +1547,12 @@ bool Application::closeActiveWindow() {
|
||||||
if (_mediaView && _mediaView->isActive()) {
|
if (_mediaView && _mediaView->isActive()) {
|
||||||
_mediaView->close();
|
_mediaView->close();
|
||||||
return true;
|
return true;
|
||||||
} else if (!calls().closeCurrentActiveCall()) {
|
} else if (_iv->closeActive() || calls().closeCurrentActiveCall()) {
|
||||||
if (const auto window = activeWindow()) {
|
return true;
|
||||||
if (window->widget()->isActive()) {
|
} else if (const auto window = activeWindow()) {
|
||||||
window->close();
|
if (window->widget()->isActive()) {
|
||||||
return true;
|
window->close();
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1562,7 +1562,8 @@ bool Application::minimizeActiveWindow() {
|
||||||
if (_mediaView && _mediaView->isActive()) {
|
if (_mediaView && _mediaView->isActive()) {
|
||||||
_mediaView->minimize();
|
_mediaView->minimize();
|
||||||
return true;
|
return true;
|
||||||
} else if (calls().minimizeCurrentActiveCall()) {
|
} else if (_iv->minimizeActive()
|
||||||
|
|| calls().minimizeCurrentActiveCall()) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (const auto window = activeWindow()) {
|
if (const auto window = activeWindow()) {
|
||||||
|
|
|
@ -7,14 +7,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "iv/iv_controller.h"
|
#include "iv/iv_controller.h"
|
||||||
|
|
||||||
|
#include "base/platform/base_platform_info.h"
|
||||||
#include "iv/iv_data.h"
|
#include "iv/iv_data.h"
|
||||||
#include "ui/widgets/rp_window.h"
|
#include "ui/widgets/rp_window.h"
|
||||||
#include "webview/webview_data_stream_memory.h"
|
#include "webview/webview_data_stream_memory.h"
|
||||||
#include "webview/webview_embed.h"
|
#include "webview/webview_embed.h"
|
||||||
#include "webview/webview_interface.h"
|
#include "webview/webview_interface.h"
|
||||||
|
#include "styles/palette.h"
|
||||||
|
|
||||||
#include <QtCore/QRegularExpression>
|
#include <QtCore/QRegularExpression>
|
||||||
|
#include <QtCore/QJsonDocument>
|
||||||
|
#include <QtCore/QJsonObject>
|
||||||
|
#include <QtCore/QJsonValue>
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
|
#include <QtGui/QPainter>
|
||||||
|
|
||||||
namespace Iv {
|
namespace Iv {
|
||||||
|
|
||||||
|
@ -47,22 +53,56 @@ void Controller::show(const QString &dataPath, Prepared page) {
|
||||||
_webview = nullptr;
|
_webview = nullptr;
|
||||||
});
|
});
|
||||||
if (!raw->widget()) {
|
if (!raw->widget()) {
|
||||||
_webview = nullptr;
|
_events.fire(Event::Close);
|
||||||
_window = nullptr;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
window->events(
|
||||||
|
) | rpl::start_with_next([=](not_null<QEvent*> e) {
|
||||||
|
if (e->type() == QEvent::Close) {
|
||||||
|
close();
|
||||||
|
} else if (e->type() == QEvent::KeyPress) {
|
||||||
|
const auto event = static_cast<QKeyEvent*>(e.get());
|
||||||
|
if (event->key() == Qt::Key_Escape) {
|
||||||
|
escape();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, window->lifetime());
|
||||||
raw->widget()->show();
|
raw->widget()->show();
|
||||||
|
|
||||||
container->geometryValue(
|
container->geometryValue(
|
||||||
) | rpl::start_with_next([=](QRect geometry) {
|
) | rpl::start_with_next([=](QRect geometry) {
|
||||||
raw->widget()->setGeometry(geometry);
|
raw->widget()->setGeometry(geometry);
|
||||||
}, _lifetime);
|
}, container->lifetime());
|
||||||
|
|
||||||
|
container->paintRequest() | rpl::start_with_next([=](QRect clip) {
|
||||||
|
QPainter(container).fillRect(clip, st::windowBg);
|
||||||
|
}, container->lifetime());
|
||||||
|
|
||||||
raw->setNavigationStartHandler([=](const QString &uri, bool newWindow) {
|
raw->setNavigationStartHandler([=](const QString &uri, bool newWindow) {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
raw->setNavigationDoneHandler([=](bool success) {
|
raw->setNavigationDoneHandler([=](bool success) {
|
||||||
});
|
});
|
||||||
|
raw->setMessageHandler([=](const QJsonDocument &message) {
|
||||||
|
crl::on_main(_window.get(), [=] {
|
||||||
|
const auto object = message.object();
|
||||||
|
const auto event = object.value("event").toString();
|
||||||
|
if (event == u"keydown"_q) {
|
||||||
|
const auto key = object.value("key").toString();
|
||||||
|
const auto modifier = object.value("modifier").toString();
|
||||||
|
const auto ctrl = Platform::IsMac() ? u"cmd"_q : u"ctrl"_q;
|
||||||
|
if (key == u"escape"_q) {
|
||||||
|
escape();
|
||||||
|
} else if (key == u"w"_q && modifier == ctrl) {
|
||||||
|
close();
|
||||||
|
} else if (key == u"m"_q && modifier == ctrl) {
|
||||||
|
minimize();
|
||||||
|
} else if (key == u"q"_q && modifier == ctrl) {
|
||||||
|
quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
raw->setDataRequestHandler([=](Webview::DataRequest request) {
|
raw->setDataRequestHandler([=](Webview::DataRequest request) {
|
||||||
if (!request.id.starts_with("iv/")) {
|
if (!request.id.starts_with("iv/")) {
|
||||||
_dataRequests.fire(std::move(request));
|
_dataRequests.fire(std::move(request));
|
||||||
|
@ -104,8 +144,27 @@ void Controller::show(const QString &dataPath, Prepared page) {
|
||||||
window->show();
|
window->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<Webview::DataRequest> Controller::dataRequests() const {
|
bool Controller::active() const {
|
||||||
return _dataRequests.events();
|
return _window && _window->isActiveWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::minimize() {
|
||||||
|
if (_window) {
|
||||||
|
_window->setWindowState(_window->windowState()
|
||||||
|
| Qt::WindowMinimized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::escape() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::close() {
|
||||||
|
_events.fire(Event::Close);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::quit() {
|
||||||
|
_events.fire(Event::Quit);
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::lifetime &Controller::lifetime() {
|
rpl::lifetime &Controller::lifetime() {
|
||||||
|
|
|
@ -25,16 +25,34 @@ public:
|
||||||
Controller();
|
Controller();
|
||||||
~Controller();
|
~Controller();
|
||||||
|
|
||||||
void show(const QString &dataPath, Prepared page);
|
enum class Event {
|
||||||
|
Close,
|
||||||
|
Quit,
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<Webview::DataRequest> dataRequests() const;
|
void show(const QString &dataPath, Prepared page);
|
||||||
|
[[nodiscard]] bool active() const;
|
||||||
|
void minimize();
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<Webview::DataRequest> dataRequests() const {
|
||||||
|
return _dataRequests.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<Event> events() const {
|
||||||
|
return _events.events();
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] rpl::lifetime &lifetime();
|
[[nodiscard]] rpl::lifetime &lifetime();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void escape();
|
||||||
|
void close();
|
||||||
|
void quit();
|
||||||
|
|
||||||
std::unique_ptr<Ui::RpWindow> _window;
|
std::unique_ptr<Ui::RpWindow> _window;
|
||||||
std::unique_ptr<Webview::Window> _webview;
|
std::unique_ptr<Webview::Window> _webview;
|
||||||
rpl::event_stream<Webview::DataRequest> _dataRequests;
|
rpl::event_stream<Webview::DataRequest> _dataRequests;
|
||||||
|
rpl::event_stream<Event> _events;
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "iv/iv_instance.h"
|
#include "iv/iv_instance.h"
|
||||||
|
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
|
#include "core/shortcuts.h"
|
||||||
#include "data/data_cloud_file.h"
|
#include "data/data_cloud_file.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
|
@ -63,6 +64,17 @@ public:
|
||||||
not_null<Data*> data) const;
|
not_null<Data*> data) const;
|
||||||
[[nodiscard]] bool showingFrom(not_null<Main::Session*> session) const;
|
[[nodiscard]] bool showingFrom(not_null<Main::Session*> session) const;
|
||||||
[[nodiscard]] bool activeFor(not_null<Main::Session*> session) const;
|
[[nodiscard]] bool activeFor(not_null<Main::Session*> session) const;
|
||||||
|
[[nodiscard]] bool active() const;
|
||||||
|
|
||||||
|
void minimize();
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<Controller::Event> events() const {
|
||||||
|
return _events.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::lifetime &lifetime() {
|
||||||
|
return _lifetime;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct MapPreview {
|
struct MapPreview {
|
||||||
|
@ -131,6 +143,8 @@ private:
|
||||||
std::vector<QByteArray> _resources;
|
std::vector<QByteArray> _resources;
|
||||||
int _resource = -1;
|
int _resource = -1;
|
||||||
|
|
||||||
|
rpl::event_stream<Controller::Event> _events;
|
||||||
|
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -358,6 +372,10 @@ void Shown::writeEmbed(QString id, QString hash) {
|
||||||
|
|
||||||
void Shown::showWindowed(Prepared result) {
|
void Shown::showWindowed(Prepared result) {
|
||||||
_controller = std::make_unique<Controller>();
|
_controller = std::make_unique<Controller>();
|
||||||
|
|
||||||
|
_controller->events(
|
||||||
|
) | rpl::start_to_stream(_events, _controller->lifetime());
|
||||||
|
|
||||||
_controller->dataRequests(
|
_controller->dataRequests(
|
||||||
) | rpl::start_with_next([=](Webview::DataRequest request) {
|
) | rpl::start_with_next([=](Webview::DataRequest request) {
|
||||||
const auto requested = QString::fromStdString(request.id);
|
const auto requested = QString::fromStdString(request.id);
|
||||||
|
@ -372,6 +390,7 @@ void Shown::showWindowed(Prepared result) {
|
||||||
sendEmbed(id.mid(5).toUtf8(), std::move(request));
|
sendEmbed(id.mid(5).toUtf8(), std::move(request));
|
||||||
}
|
}
|
||||||
}, _controller->lifetime());
|
}, _controller->lifetime());
|
||||||
|
|
||||||
const auto domain = &_session->domain();
|
const auto domain = &_session->domain();
|
||||||
_controller->show(domain->local().webviewDataPath(), std::move(result));
|
_controller->show(domain->local().webviewDataPath(), std::move(result));
|
||||||
}
|
}
|
||||||
|
@ -628,6 +647,16 @@ bool Shown::activeFor(not_null<Main::Session*> session) const {
|
||||||
return showingFrom(session) && _controller;
|
return showingFrom(session) && _controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Shown::active() const {
|
||||||
|
return _controller && _controller->active();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shown::minimize() {
|
||||||
|
if (_controller) {
|
||||||
|
_controller->minimize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Instance::Instance() = default;
|
Instance::Instance() = default;
|
||||||
|
|
||||||
Instance::~Instance() = default;
|
Instance::~Instance() = default;
|
||||||
|
@ -641,6 +670,14 @@ void Instance::show(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_shown = std::make_unique<Shown>(show, data, local);
|
_shown = std::make_unique<Shown>(show, data, local);
|
||||||
|
_shown->events() | rpl::start_with_next([=](Controller::Event event) {
|
||||||
|
if (event == Controller::Event::Close) {
|
||||||
|
_shown = nullptr;
|
||||||
|
} else if (event == Controller::Event::Quit) {
|
||||||
|
Shortcuts::Launch(Shortcuts::Command::Quit);
|
||||||
|
}
|
||||||
|
}, _shown->lifetime());
|
||||||
|
|
||||||
if (!_tracking.contains(session)) {
|
if (!_tracking.contains(session)) {
|
||||||
_tracking.emplace(session);
|
_tracking.emplace(session);
|
||||||
session->lifetime().add([=] {
|
session->lifetime().add([=] {
|
||||||
|
@ -656,6 +693,22 @@ bool Instance::hasActiveWindow(not_null<Main::Session*> session) const {
|
||||||
return _shown && _shown->activeFor(session);
|
return _shown && _shown->activeFor(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Instance::closeActive() {
|
||||||
|
if (!_shown || !_shown->active()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_shown = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Instance::minimizeActive() {
|
||||||
|
if (!_shown || !_shown->active()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_shown->minimize();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Instance::closeAll() {
|
void Instance::closeAll() {
|
||||||
_shown = nullptr;
|
_shown = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,9 @@ public:
|
||||||
[[nodiscard]] bool hasActiveWindow(
|
[[nodiscard]] bool hasActiveWindow(
|
||||||
not_null<Main::Session*> session) const;
|
not_null<Main::Session*> session) const;
|
||||||
|
|
||||||
|
bool closeActive();
|
||||||
|
bool minimizeActive();
|
||||||
|
|
||||||
void closeAll();
|
void closeAll();
|
||||||
|
|
||||||
[[nodiscard]] rpl::lifetime &lifetime();
|
[[nodiscard]] rpl::lifetime &lifetime();
|
||||||
|
|
|
@ -20,6 +20,12 @@ PRIVATE
|
||||||
iv/iv_prepare.h
|
iv/iv_prepare.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
nice_target_sources(td_iv ${res_loc}
|
||||||
|
PRIVATE
|
||||||
|
iv_html/page.css
|
||||||
|
iv_html/page.js
|
||||||
|
)
|
||||||
|
|
||||||
target_include_directories(td_iv
|
target_include_directories(td_iv
|
||||||
PUBLIC
|
PUBLIC
|
||||||
${src_loc}
|
${src_loc}
|
||||||
|
|
Loading…
Add table
Reference in a new issue