feat: basic keyboard navigation #46

This commit is contained in:
leukipp
2025-08-31 11:41:12 +02:00
parent d0ea377ead
commit f4ca7bc412
2 changed files with 120 additions and 32 deletions
+11 -1
View File
@@ -91,7 +91,17 @@
</button>
</li>
<li>
<button id="pager">
<button id="previous">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<title>page-previous</title>
<path
d="M4,21H19A2,2 0 0,0 21,19V13H17V15L13,12L17,9V11H21V5A2,2 0 0,0 19,3H4A2,2 0 0,0 2,5V19A2,2 0 0,0 4,21M4,15H8V17H4V15M4,11H11V13H4V11M4,7H11V9H4V7M21,11H24V13H21V11Z"
/>
</svg>
</button>
</li>
<li>
<button id="next">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<title>page-next</title>
<path
+109 -31
View File
@@ -2,7 +2,7 @@ const path = require("path");
const axios = require("axios");
const hardware = require("./hardware");
const integration = require("./integration");
const { app, screen, nativeTheme, ipcMain, session, BaseWindow, WebContentsView } = require("electron");
const { app, nativeTheme, globalShortcut, ipcMain, session, BaseWindow, WebContentsView } = require("electron");
const Events = require("events");
global.WEBVIEW = global.WEBVIEW || {
@@ -11,7 +11,6 @@ global.WEBVIEW = global.WEBVIEW || {
status: null,
locked: false,
pointer: {
position: {},
time: new Date(),
},
};
@@ -109,7 +108,7 @@ const init = async () => {
windowEvents();
widgetEvents();
navigationEvents();
domEvents();
viewEvents();
appEvents();
return true;
@@ -188,10 +187,24 @@ const updateNavigation = () => {
const defaultUrl = WEBVIEW.viewUrls[WEBVIEW.viewActive];
const currentUrl = view.webContents.getURL();
// Hide pager button
// Hide pager buttons
WEBVIEW.navigation.webContents.send("button-hidden", {
id: "pager",
hidden: WEBVIEW.viewUrls.length < 3,
id: "previous",
hidden: WEBVIEW.viewUrls.length <= 2,
});
WEBVIEW.navigation.webContents.send("button-hidden", {
id: "next",
hidden: WEBVIEW.viewUrls.length <= 2,
});
// Disable pager buttons
WEBVIEW.navigation.webContents.send("button-disabled", {
id: "previous",
disabled: WEBVIEW.viewActive <= 1,
});
WEBVIEW.navigation.webContents.send("button-disabled", {
id: "next",
disabled: WEBVIEW.viewActive >= WEBVIEW.viewUrls.length - 1,
});
// Update url text
@@ -242,6 +255,24 @@ const toggleNavigation = () => {
resizeView();
};
/**
* Decreases page zoom on the active webview.
*/
const zoomMinus = () => {
const view = WEBVIEW.views[WEBVIEW.viewActive];
view.webContents.setZoomFactor(Math.max(0.25, view.webContents.getZoomFactor() - 0.1));
update();
};
/**
* Increases page zoom on the active webview.
*/
const zoomPlus = () => {
const view = WEBVIEW.views[WEBVIEW.viewActive];
view.webContents.setZoomFactor(Math.min(4.0, view.webContents.getZoomFactor() + 0.1));
update();
};
/**
* Navigates backward in the history of the active webview.
*/
@@ -263,10 +294,18 @@ const historyForward = () => {
};
/**
* Activates the next webview or cycles back to the first.
* Activates the previous webview page.
*/
const previousView = () => {
if (WEBVIEW.viewActive > 1) WEBVIEW.viewActive--;
updateView();
};
/**
* Activates the next webview page.
*/
const nextView = () => {
WEBVIEW.viewActive = (WEBVIEW.viewActive + 1) % WEBVIEW.views.length || 1;
if (WEBVIEW.viewActive < WEBVIEW.views.length - 1) WEBVIEW.viewActive++;
updateView();
};
@@ -360,32 +399,42 @@ const windowEvents = () => {
WEBVIEW.window.on("enter-full-screen", update);
WEBVIEW.window.on("leave-full-screen", update);
// Handle window touch events for activity tracking
// Handle global shortcut events
globalShortcut.register("F5", () => {
reloadView();
});
globalShortcut.register("Control+Left", () => {
previousView();
});
globalShortcut.register("Control+Right", () => {
nextView();
});
globalShortcut.register("Control+numsub", () => {
zoomMinus();
});
globalShortcut.register("Control+numadd", () => {
zoomPlus();
});
globalShortcut.register("Alt+Left", () => {
historyBackward();
});
globalShortcut.register("Alt+Right", () => {
historyForward();
});
// Handle window touch events
setInterval(() => {
const now = new Date();
const then = WEBVIEW.pointer.time;
const delta = Math.abs(now - then) / 1000;
const posNew = screen.getCursorScreenPoint();
const posOld = WEBVIEW.pointer.position;
// Cursor movement detected
if (posOld.x !== posNew.x || posOld.y !== posNew.y) {
WEBVIEW.pointer.time = now;
// Update integration sensor
if (delta > 30) {
console.log("Update Last Active");
integration.update();
}
} else if (delta > 60) {
const navigation = WEBVIEW.navigation.getBounds();
// Auto-hide navigation
if (delta > 60) {
const navigation = WEBVIEW.navigation.getBounds();
if (navigation.height > 0) {
toggleNavigation();
}
}
WEBVIEW.pointer.position = posNew;
}, 1000);
};
@@ -534,7 +583,11 @@ const navigationEvents = () => {
ipcMain.on("button-click", (e, button) => {
const view = WEBVIEW.views[WEBVIEW.viewActive];
switch (button.id) {
case "pager":
case "previous":
previousView();
hardware.setKeyboardVisibility("OFF");
break;
case "next":
nextView();
hardware.setKeyboardVisibility("OFF");
break;
@@ -543,14 +596,12 @@ const navigationEvents = () => {
hardware.setKeyboardVisibility("OFF");
break;
case "minus":
view.webContents.setZoomFactor(Math.max(0.25, view.webContents.getZoomFactor() - 0.1));
zoomMinus();
hardware.setKeyboardVisibility("OFF");
updateView();
break;
case "plus":
view.webContents.setZoomFactor(Math.min(4.0, view.webContents.getZoomFactor() + 0.1));
zoomPlus();
hardware.setKeyboardVisibility("OFF");
updateView();
break;
case "backward":
historyBackward();
@@ -565,9 +616,9 @@ const navigationEvents = () => {
};
/**
* Register dom events and handler.
* Register view events and handler.
*/
const domEvents = () => {
const viewEvents = () => {
const ready = [];
WEBVIEW.views.forEach((view, i) => {
// Enable webview touch emulation
@@ -623,6 +674,33 @@ const domEvents = () => {
view.webContents.on("did-navigate", () => {
update();
});
// Handle webview mouse events
view.webContents.on("before-mouse-event", (event, mouse) => {
const now = new Date();
const then = WEBVIEW.pointer.time;
const delta = Math.abs(now - then) / 1000;
WEBVIEW.pointer.time = now;
switch (mouse.type) {
case "mouseMove":
if (delta > 30) {
console.log("Update Last Active");
integration.update();
}
break;
case "mouseDown":
switch (mouse.button) {
case "back":
historyBackward();
break;
case "forward":
historyForward();
break;
}
break;
}
});
});
};