feat(theseus): hold or right-click Back/Forward for the history list
Holding Back or Forward for 450 ms (or right-clicking it) pops a native menu of the tab's history entries in that direction — nearest first, up to 15, titled with the page title and host — and picking one jumps straight to it. A hold swallows the click that would otherwise fire on release, so a long press never also goes back one page.
This commit is contained in:
parent
79b9cf327b
commit
59e6a7e842
3 changed files with 50 additions and 0 deletions
21
chrome.html
21
chrome.html
|
|
@ -559,6 +559,27 @@
|
|||
$("search").addEventListener("keydown", (e) => { if (e.key === "Enter") { const q = $("search").value.trim(); if (q) T.search(q); } });
|
||||
$("back").onclick = () => T.back();
|
||||
$("fwd").onclick = () => T.forward();
|
||||
// Hold Back/Forward (or right-click) for the history list, like Chrome.
|
||||
// A hold longer than 450 ms opens the native menu and swallows the click
|
||||
// that would otherwise fire on release.
|
||||
for (const [id, dir] of [["back", "back"], ["fwd", "forward"]]) {
|
||||
const btn = $(id);
|
||||
let timer = null, held = false;
|
||||
const open = () => {
|
||||
held = true;
|
||||
const r = btn.getBoundingClientRect();
|
||||
T.navHistoryMenu && T.navHistoryMenu(dir, { x: r.left, y: r.bottom });
|
||||
};
|
||||
btn.addEventListener("mousedown", (e) => {
|
||||
if (e.button !== 0 || btn.disabled) return;
|
||||
held = false; clearTimeout(timer); timer = setTimeout(open, 450);
|
||||
});
|
||||
const cancel = () => { clearTimeout(timer); timer = null; };
|
||||
btn.addEventListener("mouseup", cancel);
|
||||
btn.addEventListener("mouseleave", cancel);
|
||||
btn.addEventListener("click", (e) => { if (held) { held = false; e.stopImmediatePropagation(); e.preventDefault(); } }, true);
|
||||
btn.addEventListener("contextmenu", (e) => { e.preventDefault(); if (!btn.disabled) open(); held = false; });
|
||||
}
|
||||
// Shift-click on the reload button = hard reload (bypass cache), same
|
||||
// convention as Chrome/Firefox. Keyboard alternative: Ctrl+Shift+R.
|
||||
$("reload").onclick = (e) => T.reload(e.shiftKey);
|
||||
|
|
|
|||
26
main.js
26
main.js
|
|
@ -4189,6 +4189,32 @@ ipcMain.handle("registry-menu-popup", (e, rect) => {
|
|||
const y = Math.max(0, Math.round(chromeBounds.y + (rect?.y || 0)));
|
||||
popup.popup({ window: win, x, y });
|
||||
});
|
||||
// Back/Forward history menu (press-and-hold or right-click on the buttons).
|
||||
// Lists up to 15 entries in the requested direction, nearest first, from the
|
||||
// active tab's navigation history; picking one jumps straight to it.
|
||||
ipcMain.handle("nav-history-menu", (e, dir, rect) => {
|
||||
if (chrome && e.sender !== chrome.webContents) throw new Error("nav-history-menu: untrusted sender");
|
||||
const t = activeTab(); const wc = t?.view?.webContents;
|
||||
if (!wc) return false;
|
||||
const nh = wc.navigationHistory;
|
||||
const entries = nh.getAllEntries();
|
||||
const cur = nh.getActiveIndex();
|
||||
const picks = [];
|
||||
if (dir === "forward") for (let i = cur + 1; i < entries.length && picks.length < 15; i++) picks.push(i);
|
||||
else for (let i = cur - 1; i >= 0 && picks.length < 15; i--) picks.push(i);
|
||||
if (!picks.length) return false;
|
||||
const label = (en) => {
|
||||
const title = String(en.title || "").trim();
|
||||
let host = ""; try { host = new URL(en.url).host; } catch {}
|
||||
const text = title || en.url || "";
|
||||
return (text.length > 60 ? text.slice(0, 57) + "…" : text) + (host && title ? ` — ${host}` : "");
|
||||
};
|
||||
const template = picks.map((i) => ({ label: label(entries[i]), click: () => { try { nh.goToIndex(i); } catch {} } }));
|
||||
const popup = Menu.buildFromTemplate(template);
|
||||
const chromeBounds = chrome ? chrome.getBounds() : { x: 0, y: 0 };
|
||||
popup.popup({ window: win, x: Math.max(0, Math.round(chromeBounds.x + (rect?.x || 0))), y: Math.max(0, Math.round(chromeBounds.y + (rect?.y || 0))) });
|
||||
return true;
|
||||
});
|
||||
ipcMain.handle("collision-state", () => ({
|
||||
policy: settings.collisionPolicy,
|
||||
byName: collisions.byName,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ contextBridge.exposeInMainWorld("theseus", {
|
|||
goHome: () => ipcRenderer.invoke("go-home"),
|
||||
back: () => ipcRenderer.invoke("go-back"),
|
||||
forward: () => ipcRenderer.invoke("go-forward"),
|
||||
// Press-and-hold / right-click on Back or Forward: native menu of the
|
||||
// tab's history entries in that direction; picking one jumps to it.
|
||||
navHistoryMenu: (dir, rect) => ipcRenderer.invoke("nav-history-menu", dir, rect),
|
||||
reload: (hard) => ipcRenderer.invoke("reload", !!hard),
|
||||
stop: () => ipcRenderer.invoke("stop"),
|
||||
toggleTor: () => ipcRenderer.invoke("toggle-tor"),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue