Support anchor jumps.

This commit is contained in:
John Preston 2023-12-05 11:54:46 +04:00
parent 51d5b7bab6
commit 5c428ca502
7 changed files with 53 additions and 16 deletions

View file

@ -7,7 +7,6 @@ var IV = {
frameClickHandler: function(e) {
var target = e.target;
var context = '';
console.log('click', target);
while (target) {
if (target.tagName == 'AUDIO' || target.tagName == 'VIDEO') {
return;
@ -25,16 +24,28 @@ var IV = {
if (!target || !target.hasAttribute('href')) {
return;
}
var base_loc = document.createElement('A');
base_loc.href = window.currentUrl;
if (base_loc.origin != target.origin
|| base_loc.pathname != target.pathname
|| base_loc.search != target.search) {
var base = document.createElement('A');
base.href = window.location.href;
if (base.origin != target.origin
|| base.pathname != target.pathname
|| base.search != target.search) {
IV.notify({
event: 'link_click',
url: target.href,
context: context,
});
} else if (target.hash.length < 2) {
IV.hash = '';
IV.scrollTo(0);
} else {
const name = target.hash.substr(1);
IV.hash = name;
const element = document.getElementsByName(name)[0];
if (element) {
const y = element.getBoundingClientRect().y;
IV.scrollTo(y + document.documentElement.scrollTop);
}
}
e.preventDefault();
},
@ -183,6 +194,8 @@ var IV = {
}
},
init: function () {
IV.hash = window.location.hash.substr(1);
const buttons = document.getElementsByClassName('fixed_button');
for (let i = 0; i < buttons.length; ++i) {
const button = buttons[i];
@ -210,9 +223,9 @@ var IV = {
document.body.removeChild(toast);
}, 3000);
},
toTop: function () {
scrollTo: function (y) {
document.getElementById('bottom_up').classList.add('hidden');
window.scrollTo({ top: 0, behavior: 'smooth' });
window.scrollTo({ top: y || 0, behavior: 'smooth' });
}
};

View file

@ -175,7 +175,7 @@ namespace {
<circle cx="12" cy="6.6" r="1.7"></circle>
</svg>
</button>
<button class="fixed_button hidden" id="bottom_up" onclick="IV.toTop();">
<button class="fixed_button hidden" id="bottom_up" onclick="IV.scrollTo(0);">
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M14.9972363,18 L9.13865768,12.1414214 C9.06055283,12.0633165 9.06055283,11.9366835 9.13865768,11.8585786 L14.9972363,6 L14.9972363,6" transform="translate(11.997236, 12.000000) scale(-1, -1) rotate(-90.000000) translate(-11.997236, -12.000000) "></path>
</svg>
@ -458,7 +458,12 @@ void Controller::showInWindow(
});
raw->init(R"()");
raw->navigateToData("iv/page.html");
auto id = u"iv/page.html"_q;
if (!page.hash.isEmpty()) {
id += '#' + page.hash;
}
raw->navigateToData(id);
}
void Controller::processKey(const QString &key, const QString &modifier) {
@ -487,6 +492,8 @@ void Controller::processLink(const QString &url, const QString &context) {
Event::Type::JoinChannel,
context.mid(joinPrefix.size()),
});
} else if (context.isEmpty()) {
_events.fire({ Event::Type::OpenLink, url });
}
}

View file

@ -38,6 +38,7 @@ public:
Quit,
OpenChannel,
JoinChannel,
OpenLink,
};
Type type = Type::Close;
QString context;

View file

@ -18,6 +18,7 @@ struct Options {
struct Prepared {
QString title;
QByteArray content;
QString hash;
std::vector<QByteArray> resources;
base::flat_map<QByteArray, QByteArray> embeds;
base::flat_set<QByteArray> channelIds;

View file

@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/file_download.h"
#include "storage/storage_domain.h"
#include "ui/boxes/confirm_box.h"
#include "ui/basic_click_handlers.h"
#include "webview/webview_data_stream_memory.h"
#include "webview/webview_interface.h"
#include "window/window_controller.h"
@ -65,7 +66,7 @@ public:
Shown(
std::shared_ptr<Main::SessionShow> show,
not_null<Data*> data,
bool local);
QString hash);
[[nodiscard]] bool showing(
not_null<Main::Session*> session,
@ -163,14 +164,15 @@ private:
Shown::Shown(
std::shared_ptr<Main::SessionShow> show,
not_null<Data*> data,
bool local)
QString hash)
: _session(&show->session())
, _show(show)
, _id(data->id()) {
const auto weak = base::make_weak(this);
const auto base = local ? LookupLocalPath(show) : QString();
const auto base = /*local ? LookupLocalPath(show) : */QString();
data->prepare({ .saveToFolder = base }, [=](Prepared result) {
result.hash = hash;
crl::on_main(weak, [=, result = std::move(result)]() mutable {
_embeds = std::move(result.embeds);
fillChannelJoinedValues(result);
@ -701,12 +703,12 @@ Instance::~Instance() = default;
void Instance::show(
std::shared_ptr<Main::SessionShow> show,
not_null<Data*> data,
bool local) {
QString hash) {
const auto session = &show->session();
if (_shown && _shown->showing(session, data)) {
return;
}
_shown = std::make_unique<Shown>(show, data, local);
_shown = std::make_unique<Shown>(show, data, hash);
_shownSession = session;
_shown->events() | rpl::start_with_next([=](Controller::Event event) {
using Type = Controller::Event::Type;
@ -723,6 +725,9 @@ void Instance::show(
case Type::JoinChannel:
processJoinChannel(event.context);
break;
case Type::OpenLink:
UrlClickHandler::Open(event.context);
break;
}
}, _shown->lifetime());

View file

@ -25,7 +25,7 @@ public:
void show(
std::shared_ptr<Main::SessionShow> show,
not_null<Data*> data,
bool local);
QString hash);
[[nodiscard]] bool hasActiveWindow(
not_null<Main::Session*> session) const;

View file

@ -656,9 +656,14 @@ QByteArray Parser::block(const MTPDpageRelatedArticle &data) {
{ "class", "related-link-content" },
}, inner);
}
const auto webpageId = data.vwebpage_id().v;
const auto context = webpageId
? ("webpage" + QByteArray::number(webpageId))
: QByteArray();
return tag("a", {
{ "class", "related-link" },
{ "href", utf(data.vurl()) },
{ "data-context", context },
}, result);
}
@ -795,8 +800,13 @@ QByteArray Parser::rich(const MTPRichText &text) {
}, [&](const MTPDtextFixed &data) {
return tag("code", rich(data.vtext()));
}, [&](const MTPDtextUrl &data) {
const auto webpageId = data.vwebpage_id().v;
const auto context = webpageId
? ("webpage" + QByteArray::number(webpageId))
: QByteArray();
return tag("a", {
{ "href", utf(data.vurl()) },
{ "data-context", context },
}, rich(data.vtext()));
}, [&](const MTPDtextEmail &data) {
return tag("a", {