feat: dynamic status bar #94
This commit is contained in:
@@ -32,8 +32,8 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
padding: 0 30px;
|
padding: 0 10px;
|
||||||
column-gap: 20px;
|
column-gap: 10px;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
border-top: 1px solid var(--border-color);
|
border-top: 1px solid var(--border-color);
|
||||||
background: var(--background-color);
|
background: var(--background-color);
|
||||||
@@ -74,6 +74,7 @@
|
|||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
font-family: sans-serif;
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
@@ -186,7 +187,7 @@
|
|||||||
ipcRenderer.send("button-click", { id: e.target.id });
|
ipcRenderer.send("button-click", { id: e.target.id });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
document.querySelectorAll("input").forEach((input) => {
|
document.querySelectorAll("input").forEach((input) => {
|
||||||
input.addEventListener("blur", (e) => {
|
input.addEventListener("blur", (e) => {
|
||||||
ipcRenderer.send("input-blur", { id: e.target.id });
|
ipcRenderer.send("input-blur", { id: e.target.id });
|
||||||
});
|
});
|
||||||
@@ -207,7 +208,7 @@
|
|||||||
});
|
});
|
||||||
ipcRenderer.on("button-hidden", (e, button) => {
|
ipcRenderer.on("button-hidden", (e, button) => {
|
||||||
document.getElementById(button.id).parentNode.classList.toggle("hidden", button.hidden);
|
document.getElementById(button.id).parentNode.classList.toggle("hidden", button.hidden);
|
||||||
});
|
});
|
||||||
ipcRenderer.on("input-readonly", (e, input) => {
|
ipcRenderer.on("input-readonly", (e, input) => {
|
||||||
document.getElementById(input.id).readOnly = input.readonly;
|
document.getElementById(input.id).readOnly = input.readonly;
|
||||||
});
|
});
|
||||||
@@ -216,10 +217,11 @@
|
|||||||
document.getElementById(input.id).placeholder = input.placeholder;
|
document.getElementById(input.id).placeholder = input.placeholder;
|
||||||
});
|
});
|
||||||
ipcRenderer.on("input-select", (e, input) => {
|
ipcRenderer.on("input-select", (e, input) => {
|
||||||
|
window.getSelection()?.removeAllRanges();
|
||||||
if (input.select) {
|
if (input.select) {
|
||||||
document.getElementById(input.id).select();
|
document.getElementById(input.id).select();
|
||||||
} else {
|
} else {
|
||||||
window.getSelection()?.removeAllRanges();
|
document.getElementById(input.id).blur();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ipcRenderer.on("data-theme", (e, data) => {
|
ipcRenderer.on("data-theme", (e, data) => {
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
[data-theme="hidden"] {
|
[data-theme="hidden"] {
|
||||||
--primary-color: rgba(0, 0, 0, 0);
|
|
||||||
--border-color: rgba(0, 0, 0, 0);
|
|
||||||
--background-color: rgba(0, 0, 0, 0);
|
--background-color: rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
[data-theme="dark"] {
|
||||||
|
--primary-color: rgba(229, 229, 229, 1);
|
||||||
|
--background-color: rgba(66, 67, 68, 1);
|
||||||
|
--minimize-color: rgba(52, 199, 89, 1);
|
||||||
|
--fullscreen-color: rgba(255, 149, 0, 1);
|
||||||
|
--terminate-color: rgba(255, 59, 48, 1);
|
||||||
|
}
|
||||||
|
[data-theme="light"] {
|
||||||
|
--primary-color: rgba(26, 26, 26, 1);
|
||||||
|
--background-color: rgba(237, 236, 235, 1);
|
||||||
|
--minimize-color: rgba(52, 199, 89, 1);
|
||||||
|
--fullscreen-color: rgba(255, 149, 0, 1);
|
||||||
|
--terminate-color: rgba(255, 59, 48, 1);
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background: var(--background-color);
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1 1 0%;
|
||||||
|
height: 100vh;
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
position: absolute;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
font-family: sans-serif;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
text-align: center;
|
||||||
|
user-select: none;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
menu {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
height: 100vh;
|
||||||
|
min-width: 116px;
|
||||||
|
padding: 0px 10px;
|
||||||
|
column-gap: 10px;
|
||||||
|
list-style-type: none;
|
||||||
|
background: var(--background-color);
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
svg {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
#minimize > svg {
|
||||||
|
fill: var(--minimize-color);
|
||||||
|
}
|
||||||
|
#fullscreen > svg {
|
||||||
|
fill: var(--fullscreen-color);
|
||||||
|
}
|
||||||
|
#terminate > svg {
|
||||||
|
fill: var(--terminate-color);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1 id="title"></h1>
|
||||||
|
</header>
|
||||||
|
<menu>
|
||||||
|
<li>
|
||||||
|
<button id="minimize">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<title>minus-circle</title>
|
||||||
|
<path d="M17,13H7V11H17M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button id="fullscreen">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<title>chevron-up-circle</title>
|
||||||
|
<path
|
||||||
|
d="M22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2A10,10 0 0,1 22,12M7.4,15.4L12,10.8L16.6,15.4L18,14L12,8L6,14L7.4,15.4Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button id="terminate">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<title>close-circle</title>
|
||||||
|
<path
|
||||||
|
d="M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</menu>
|
||||||
|
<script>
|
||||||
|
const { ipcRenderer } = require("electron");
|
||||||
|
|
||||||
|
const registerSendEvents = () => {
|
||||||
|
document.querySelectorAll("button").forEach((button) => {
|
||||||
|
button.addEventListener("click", (e) => {
|
||||||
|
ipcRenderer.send("button-click", { id: e.target.id });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const registerReceiveEvents = () => {
|
||||||
|
ipcRenderer.on("text-content", (e, text) => {
|
||||||
|
document.getElementById(text.id).textContent = text.content;
|
||||||
|
});
|
||||||
|
ipcRenderer.on("data-theme", (e, data) => {
|
||||||
|
document.documentElement.setAttribute("data-theme", data.theme);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
registerSendEvents();
|
||||||
|
registerReceiveEvents();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+3
-13
@@ -68,16 +68,6 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<menu>
|
<menu>
|
||||||
<li>
|
|
||||||
<button id="keyboard">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
||||||
<title>keyboard-close-outline</title>
|
|
||||||
<path
|
|
||||||
d="M12 23L16 19H8M4 3C2.9 3 2 3.9 2 5V15C2 16.1 2.9 17 4 17H20C21.1 17 22 16.1 22 15V5C22 3.9 21.1 3 20 3H4M4 5H20V15H4V5M5 6V8H7V6H5M8 6V8H10V6H8M11 6V8H13V6H11M14 6V8H16V6H14M17 6V8H19V6H17M5 9V11H7V9H5M8 9V11H10V9H8M11 9V11H13V9H11M14 9V11H16V9H14M17 9V11H19V9H17M8 12V14H16V12H8Z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<button id="fullscreen">
|
<button id="fullscreen">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
@@ -89,11 +79,11 @@
|
|||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button id="minimize">
|
<button id="keyboard">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<title>image-size-select-small</title>
|
<title>keyboard-close-outline</title>
|
||||||
<path
|
<path
|
||||||
d="M23,15H21V17H23V15M23,11H21V13H23V11M23,19H21V21C22,21 23,20 23,19M15,3H13V5H15V3M23,7H21V9H23V7M21,3V5H23C23,4 22,3 21,3M3,21H11V15H1V19A2,2 0 0,0 3,21M3,7H1V9H3V7M15,19H13V21H15V19M19,3H17V5H19V3M19,19H17V21H19V19M3,3C2,3 1,4 1,5H3V3M3,11H1V13H3V11M11,3H9V5H11V3M7,3H5V5H7V3Z"
|
d="M12 23L16 19H8M4 3C2.9 3 2 3.9 2 5V15C2 16.1 2.9 17 4 17H20C21.1 17 22 16.1 22 15V5C22 3.9 21.1 3 20 3H4M4 5H20V15H4V5M5 6V8H7V6H5M8 6V8H10V6H8M11 6V8H13V6H11M14 6V8H16V6H14M17 6V8H19V6H17M5 9V11H7V9H5M8 9V11H10V9H8M11 9V11H13V9H11M14 9V11H16V9H14M17 9V11H19V9H17M8 12V14H16V12H8Z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -65,8 +65,9 @@ const initApp = async () => {
|
|||||||
APP.title = packageJson.title;
|
APP.title = packageJson.title;
|
||||||
APP.version = app.getVersion();
|
APP.version = app.getVersion();
|
||||||
APP.path = app.getAppPath();
|
APP.path = app.getAppPath();
|
||||||
APP.config = app.getPath("userData");
|
APP.icon = path.join(app.getAppPath(), "img", "icon.png");
|
||||||
APP.log = path.join(app.getPath("logs"), "main.log");
|
APP.log = path.join(app.getPath("logs"), "main.log");
|
||||||
|
APP.config = app.getPath("userData");
|
||||||
|
|
||||||
// Set additional update infos
|
// Set additional update infos
|
||||||
APP.homepage = `https://github.com/${packageJson.author}/${packageJson.name}`;
|
APP.homepage = `https://github.com/${packageJson.author}/${packageJson.name}`;
|
||||||
|
|||||||
+179
-57
@@ -3,7 +3,17 @@ const axios = require("axios");
|
|||||||
const https = require("https");
|
const https = require("https");
|
||||||
const hardware = require("./hardware");
|
const hardware = require("./hardware");
|
||||||
const integration = require("./integration");
|
const integration = require("./integration");
|
||||||
const { app, nativeTheme, globalShortcut, ipcMain, session, BaseWindow, WebContentsView } = require("electron");
|
const {
|
||||||
|
app,
|
||||||
|
nativeTheme,
|
||||||
|
globalShortcut,
|
||||||
|
ipcMain,
|
||||||
|
dialog,
|
||||||
|
screen,
|
||||||
|
session,
|
||||||
|
BaseWindow,
|
||||||
|
WebContentsView,
|
||||||
|
} = require("electron");
|
||||||
|
|
||||||
global.WEBVIEW = global.WEBVIEW || {
|
global.WEBVIEW = global.WEBVIEW || {
|
||||||
initialized: false,
|
initialized: false,
|
||||||
@@ -34,7 +44,7 @@ const init = async () => {
|
|||||||
session.defaultSession.clearCache();
|
session.defaultSession.clearCache();
|
||||||
|
|
||||||
// Parse arguments
|
// Parse arguments
|
||||||
const fullscreen = ARGS.app_debug !== "true";
|
const debug = ARGS.app_debug === "true";
|
||||||
const widget = ARGS.web_widget ? ARGS.web_widget === "true" : true;
|
const widget = ARGS.web_widget ? ARGS.web_widget === "true" : true;
|
||||||
const zoom = !isNaN(parseFloat(ARGS.web_zoom)) ? parseFloat(ARGS.web_zoom) : 1.25;
|
const zoom = !isNaN(parseFloat(ARGS.web_zoom)) ? parseFloat(ARGS.web_zoom) : 1.25;
|
||||||
const theme = ["light", "dark"].includes(ARGS.web_theme) ? ARGS.web_theme : "dark";
|
const theme = ["light", "dark"].includes(ARGS.web_theme) ? ARGS.web_theme : "dark";
|
||||||
@@ -48,17 +58,24 @@ const init = async () => {
|
|||||||
WEBVIEW.pagerEnabled = widget;
|
WEBVIEW.pagerEnabled = widget;
|
||||||
WEBVIEW.widgetTheme = theme;
|
WEBVIEW.widgetTheme = theme;
|
||||||
WEBVIEW.widgetEnabled = widget;
|
WEBVIEW.widgetEnabled = widget;
|
||||||
|
WEBVIEW.statusTheme = theme;
|
||||||
|
WEBVIEW.statusEnabled = true;
|
||||||
WEBVIEW.navigationTheme = theme;
|
WEBVIEW.navigationTheme = theme;
|
||||||
WEBVIEW.navigationEnabled = widget;
|
WEBVIEW.navigationEnabled = widget;
|
||||||
nativeTheme.themeSource = WEBVIEW.viewTheme;
|
nativeTheme.themeSource = WEBVIEW.viewTheme;
|
||||||
|
|
||||||
// Init global root window
|
// Init global root window
|
||||||
|
WEBVIEW.display = screen.getPrimaryDisplay().workAreaSize;
|
||||||
WEBVIEW.window = new BaseWindow({
|
WEBVIEW.window = new BaseWindow({
|
||||||
title: APP.title,
|
title: APP.title,
|
||||||
icon: path.join(APP.path, "img", "icon.png"),
|
icon: APP.icon,
|
||||||
fullscreen: fullscreen,
|
fullscreen: !debug,
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
frame: true,
|
frame: debug || !WEBVIEW.statusEnabled,
|
||||||
|
width: Math.floor(WEBVIEW.display.width * 0.9),
|
||||||
|
height: Math.floor(WEBVIEW.display.height * 0.9),
|
||||||
|
minWidth: 136,
|
||||||
|
minHeight: 136,
|
||||||
});
|
});
|
||||||
WEBVIEW.window.setMenuBarVisibility(false);
|
WEBVIEW.window.setMenuBarVisibility(false);
|
||||||
|
|
||||||
@@ -104,6 +121,18 @@ const init = async () => {
|
|||||||
WEBVIEW.window.contentView.addChildView(WEBVIEW.widget);
|
WEBVIEW.window.contentView.addChildView(WEBVIEW.widget);
|
||||||
WEBVIEW.widget.webContents.loadFile(path.join(APP.path, "html", "widget.html"));
|
WEBVIEW.widget.webContents.loadFile(path.join(APP.path, "html", "widget.html"));
|
||||||
|
|
||||||
|
// Init global status
|
||||||
|
WEBVIEW.status = new WebContentsView({
|
||||||
|
transparent: true,
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
contextIsolation: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WEBVIEW.status.setBackgroundColor("#00000000");
|
||||||
|
WEBVIEW.window.contentView.addChildView(WEBVIEW.status);
|
||||||
|
WEBVIEW.status.webContents.loadFile(path.join(APP.path, "html", "status.html"));
|
||||||
|
|
||||||
// Init global navigation
|
// Init global navigation
|
||||||
WEBVIEW.navigation = new WebContentsView({
|
WEBVIEW.navigation = new WebContentsView({
|
||||||
transparent: true,
|
transparent: true,
|
||||||
@@ -116,37 +145,14 @@ const init = async () => {
|
|||||||
WEBVIEW.window.contentView.addChildView(WEBVIEW.navigation);
|
WEBVIEW.window.contentView.addChildView(WEBVIEW.navigation);
|
||||||
WEBVIEW.navigation.webContents.loadFile(path.join(APP.path, "html", "navigation.html"));
|
WEBVIEW.navigation.webContents.loadFile(path.join(APP.path, "html", "navigation.html"));
|
||||||
|
|
||||||
// Register local events
|
// Register global events
|
||||||
await windowEvents();
|
await windowEvents();
|
||||||
await widgetEvents();
|
await widgetEvents();
|
||||||
|
await statusEvents();
|
||||||
await navigationEvents();
|
await navigationEvents();
|
||||||
await viewEvents();
|
await viewEvents();
|
||||||
await appEvents();
|
await appEvents();
|
||||||
|
|
||||||
// Register global events
|
|
||||||
EVENTS.on("reloadView", reloadView);
|
|
||||||
EVENTS.on("updateView", updateView);
|
|
||||||
EVENTS.on("updateDisplay", () => {
|
|
||||||
const status = hardware.getDisplayStatus();
|
|
||||||
if (status) {
|
|
||||||
WEBVIEW.tracker.display[status.toLowerCase()] = new Date();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
EVENTS.on("updateStatus", () => {
|
|
||||||
const visibility = hardware.getKeyboardVisibility();
|
|
||||||
if (visibility === "ON" && (WEBVIEW.window.isFullScreen() || WEBVIEW.window.isMinimized())) {
|
|
||||||
hardware.setKeyboardVisibility("OFF");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
EVENTS.on("updateKeyboard", () => {
|
|
||||||
const visibility = hardware.getKeyboardVisibility();
|
|
||||||
if (visibility === "ON" && WEBVIEW.window.isFullScreen()) {
|
|
||||||
WEBVIEW.window.setStatus("maximized");
|
|
||||||
} else if (visibility === "OFF" && WEBVIEW.window.isMaximized()) {
|
|
||||||
WEBVIEW.window.setStatus("fullscreen");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -184,6 +190,10 @@ const updateView = () => {
|
|||||||
|
|
||||||
// Update window title
|
// Update window title
|
||||||
console.log(`Update View: ${title}`);
|
console.log(`Update View: ${title}`);
|
||||||
|
WEBVIEW.status.webContents.send("text-content", {
|
||||||
|
id: "title",
|
||||||
|
content: title,
|
||||||
|
});
|
||||||
WEBVIEW.window.setTitle(title);
|
WEBVIEW.window.setTitle(title);
|
||||||
|
|
||||||
// Hide all other webviews and show only the active one
|
// Hide all other webviews and show only the active one
|
||||||
@@ -216,6 +226,12 @@ const updateStatus = () => {
|
|||||||
* Updates the widget control.
|
* Updates the widget control.
|
||||||
*/
|
*/
|
||||||
const updateWidget = () => {
|
const updateWidget = () => {
|
||||||
|
// Hide status button
|
||||||
|
WEBVIEW.widget.webContents.send("button-hidden", {
|
||||||
|
id: "fullscreen",
|
||||||
|
hidden: !WEBVIEW.statusEnabled,
|
||||||
|
});
|
||||||
|
|
||||||
// Hide keyboard button
|
// Hide keyboard button
|
||||||
WEBVIEW.widget.webContents.send("button-hidden", {
|
WEBVIEW.widget.webContents.send("button-hidden", {
|
||||||
id: "keyboard",
|
id: "keyboard",
|
||||||
@@ -291,19 +307,32 @@ const updateNavigation = () => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows or hides the webview navigation bar.
|
* Shows or hides the webview navigation bar.
|
||||||
|
*
|
||||||
|
* @param {string} force - Force the navigation bar visibility to 'ON' or 'OFF'.
|
||||||
*/
|
*/
|
||||||
const toggleNavigation = () => {
|
const toggleNavigation = (force = null) => {
|
||||||
|
if (!WEBVIEW.navigationEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const window = WEBVIEW.window.getBounds();
|
const window = WEBVIEW.window.getBounds();
|
||||||
|
const status = WEBVIEW.status.getBounds();
|
||||||
const navigation = WEBVIEW.navigation.getBounds();
|
const navigation = WEBVIEW.navigation.getBounds();
|
||||||
const height = navigation.height > 0 ? 0 : 60;
|
|
||||||
|
// Calculate navigation height
|
||||||
|
const height = force === "ON" ? 50 : force === "OFF" ? 0 : navigation.height > 0 ? 0 : 50;
|
||||||
|
if (height === navigation.height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Show or hide navigation based on height
|
// Show or hide navigation based on height
|
||||||
WEBVIEW.navigation.setBounds({
|
WEBVIEW.navigation.setBounds({
|
||||||
x: 0,
|
x: 0,
|
||||||
y: window.height - height,
|
y: window.height - status.height - height,
|
||||||
width: window.width,
|
width: window.width,
|
||||||
height: height,
|
height: height,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Focus navigation or view
|
||||||
if (height > 0) {
|
if (height > 0) {
|
||||||
WEBVIEW.navigation.webContents.focus();
|
WEBVIEW.navigation.webContents.focus();
|
||||||
} else {
|
} else {
|
||||||
@@ -314,6 +343,36 @@ const toggleNavigation = () => {
|
|||||||
resizeView();
|
resizeView();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows or hides the webview status bar.
|
||||||
|
*
|
||||||
|
* @param {string} force - Force the status bar visibility to 'ON' or 'OFF'.
|
||||||
|
*/
|
||||||
|
const toggleStatus = (force = null) => {
|
||||||
|
if (!WEBVIEW.statusEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const window = WEBVIEW.window.getBounds();
|
||||||
|
const status = WEBVIEW.status.getBounds();
|
||||||
|
|
||||||
|
// Calculate status height
|
||||||
|
const height = force === "ON" ? 40 : force === "OFF" ? 0 : status.height > 0 ? 0 : 40;
|
||||||
|
if (height === status.height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show or hide status based on height
|
||||||
|
WEBVIEW.status.setBounds({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: window.width,
|
||||||
|
height: height,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Resize webview
|
||||||
|
resizeView();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decreases page zoom on the active webview.
|
* Decreases page zoom on the active webview.
|
||||||
*/
|
*/
|
||||||
@@ -413,6 +472,7 @@ const reloadView = () => {
|
|||||||
*/
|
*/
|
||||||
const resizeView = () => {
|
const resizeView = () => {
|
||||||
const window = WEBVIEW.window.getBounds();
|
const window = WEBVIEW.window.getBounds();
|
||||||
|
const status = WEBVIEW.status.getBounds();
|
||||||
const navigation = WEBVIEW.navigation.getBounds();
|
const navigation = WEBVIEW.navigation.getBounds();
|
||||||
const pager = { width: 20, height: window.height };
|
const pager = { width: 20, height: window.height };
|
||||||
const widget = { width: 60, height: 200 };
|
const widget = { width: 60, height: 200 };
|
||||||
@@ -421,9 +481,9 @@ const resizeView = () => {
|
|||||||
WEBVIEW.views.forEach((view) => {
|
WEBVIEW.views.forEach((view) => {
|
||||||
view.setBounds({
|
view.setBounds({
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: status.height,
|
||||||
width: window.width,
|
width: window.width,
|
||||||
height: window.height - navigation.height,
|
height: window.height - status.height - navigation.height,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -431,9 +491,9 @@ const resizeView = () => {
|
|||||||
if (WEBVIEW.pagerEnabled) {
|
if (WEBVIEW.pagerEnabled) {
|
||||||
WEBVIEW.pager.setBounds({
|
WEBVIEW.pager.setBounds({
|
||||||
x: window.width - pager.width,
|
x: window.width - pager.width,
|
||||||
y: 0,
|
y: status.height,
|
||||||
width: pager.width,
|
width: pager.width,
|
||||||
height: pager.height,
|
height: pager.height - status.height - navigation.height,
|
||||||
});
|
});
|
||||||
WEBVIEW.pager.webContents.send("data-theme", { theme: "hidden" });
|
WEBVIEW.pager.webContents.send("data-theme", { theme: "hidden" });
|
||||||
}
|
}
|
||||||
@@ -442,13 +502,24 @@ const resizeView = () => {
|
|||||||
if (WEBVIEW.widgetEnabled) {
|
if (WEBVIEW.widgetEnabled) {
|
||||||
WEBVIEW.widget.setBounds({
|
WEBVIEW.widget.setBounds({
|
||||||
x: window.width - 20,
|
x: window.width - 20,
|
||||||
y: parseInt(window.height / 2 - widget.height / 2, 10),
|
y: status.height + parseInt((window.height - status.height - widget.height) / 2, 10),
|
||||||
width: widget.width,
|
width: widget.width,
|
||||||
height: widget.height,
|
height: widget.height,
|
||||||
});
|
});
|
||||||
WEBVIEW.widget.webContents.send("data-theme", { theme: "hidden" });
|
WEBVIEW.widget.webContents.send("data-theme", { theme: "hidden" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update status size
|
||||||
|
if (WEBVIEW.statusEnabled) {
|
||||||
|
WEBVIEW.status.setBounds({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: window.width,
|
||||||
|
height: status.height,
|
||||||
|
});
|
||||||
|
WEBVIEW.status.webContents.send("data-theme", { theme: WEBVIEW.statusTheme });
|
||||||
|
}
|
||||||
|
|
||||||
// Update navigation size
|
// Update navigation size
|
||||||
if (WEBVIEW.navigationEnabled) {
|
if (WEBVIEW.navigationEnabled) {
|
||||||
WEBVIEW.navigation.setBounds({
|
WEBVIEW.navigation.setBounds({
|
||||||
@@ -472,15 +543,15 @@ const windowEvents = async () => {
|
|||||||
|
|
||||||
// Handle window status updates
|
// Handle window status updates
|
||||||
WEBVIEW.window.setStatus = async (status) => {
|
WEBVIEW.window.setStatus = async (status) => {
|
||||||
const apply = (f, ...args) => {
|
const apply = (func, ...args) => {
|
||||||
f.apply(WEBVIEW.window, args);
|
func.apply(WEBVIEW.window, args);
|
||||||
return new Promise((r) => setTimeout(r, 50));
|
return new Promise((r) => setTimeout(r, 50));
|
||||||
};
|
};
|
||||||
if (WEBVIEW.window.isMinimized()) {
|
if (WEBVIEW.window.isMinimized()) {
|
||||||
await apply(WEBVIEW.window.restore);
|
await apply(WEBVIEW.window.restore);
|
||||||
}
|
}
|
||||||
switch (status.toLowerCase()) {
|
switch (status) {
|
||||||
case "framed":
|
case "Framed":
|
||||||
if (WEBVIEW.window.isFullScreen()) {
|
if (WEBVIEW.window.isFullScreen()) {
|
||||||
await apply(WEBVIEW.window.setFullScreen, false);
|
await apply(WEBVIEW.window.setFullScreen, false);
|
||||||
}
|
}
|
||||||
@@ -488,7 +559,7 @@ const windowEvents = async () => {
|
|||||||
await apply(WEBVIEW.window.unmaximize);
|
await apply(WEBVIEW.window.unmaximize);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "fullscreen":
|
case "Fullscreen":
|
||||||
if (!WEBVIEW.window.isMaximized()) {
|
if (!WEBVIEW.window.isMaximized()) {
|
||||||
await apply(WEBVIEW.window.maximize);
|
await apply(WEBVIEW.window.maximize);
|
||||||
}
|
}
|
||||||
@@ -496,7 +567,7 @@ const windowEvents = async () => {
|
|||||||
await apply(WEBVIEW.window.setFullScreen, true);
|
await apply(WEBVIEW.window.setFullScreen, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "maximized":
|
case "Maximized":
|
||||||
if (WEBVIEW.window.isFullScreen()) {
|
if (WEBVIEW.window.isFullScreen()) {
|
||||||
await apply(WEBVIEW.window.setFullScreen, false);
|
await apply(WEBVIEW.window.setFullScreen, false);
|
||||||
}
|
}
|
||||||
@@ -504,7 +575,7 @@ const windowEvents = async () => {
|
|||||||
await apply(WEBVIEW.window.maximize);
|
await apply(WEBVIEW.window.maximize);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "minimized":
|
case "Minimized":
|
||||||
if (WEBVIEW.window.isFullScreen()) {
|
if (WEBVIEW.window.isFullScreen()) {
|
||||||
await apply(WEBVIEW.window.setFullScreen, false);
|
await apply(WEBVIEW.window.setFullScreen, false);
|
||||||
}
|
}
|
||||||
@@ -512,8 +583,9 @@ const windowEvents = async () => {
|
|||||||
await apply(WEBVIEW.window.minimize);
|
await apply(WEBVIEW.window.minimize);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "terminated":
|
case "Terminated":
|
||||||
app.quit();
|
app.quit();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
WEBVIEW.window.onStatus = () => {
|
WEBVIEW.window.onStatus = () => {
|
||||||
@@ -555,10 +627,7 @@ const windowEvents = async () => {
|
|||||||
|
|
||||||
// Auto-hide navigation
|
// Auto-hide navigation
|
||||||
if (delta > 60) {
|
if (delta > 60) {
|
||||||
const navigation = WEBVIEW.navigation.getBounds();
|
toggleNavigation("OFF");
|
||||||
if (navigation.height > 0) {
|
|
||||||
toggleNavigation();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
};
|
};
|
||||||
@@ -610,19 +679,45 @@ const widgetEvents = async () => {
|
|||||||
WEBVIEW.views[WEBVIEW.viewActive].webContents.focus();
|
WEBVIEW.views[WEBVIEW.viewActive].webContents.focus();
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case "navigation":
|
||||||
|
toggleNavigation();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register status events and handler.
|
||||||
|
*/
|
||||||
|
const statusEvents = async () => {
|
||||||
|
if (!WEBVIEW.statusEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle status button click events
|
||||||
|
ipcMain.on("button-click", (e, button) => {
|
||||||
|
switch (button.id) {
|
||||||
case "fullscreen":
|
case "fullscreen":
|
||||||
if (WEBVIEW.window.isFullScreen()) {
|
if (WEBVIEW.window.isFullScreen()) {
|
||||||
WEBVIEW.window.setStatus("framed");
|
WEBVIEW.window.setStatus("Framed");
|
||||||
} else {
|
} else {
|
||||||
WEBVIEW.window.setStatus("fullscreen");
|
WEBVIEW.window.setStatus("Fullscreen");
|
||||||
}
|
}
|
||||||
WEBVIEW.views[WEBVIEW.viewActive].webContents.focus();
|
WEBVIEW.views[WEBVIEW.viewActive].webContents.focus();
|
||||||
break;
|
break;
|
||||||
case "minimize":
|
case "minimize":
|
||||||
WEBVIEW.window.setStatus("minimized");
|
WEBVIEW.window.setStatus("Minimized");
|
||||||
break;
|
break;
|
||||||
case "navigation":
|
case "terminate":
|
||||||
toggleNavigation();
|
const button = dialog.showMessageBoxSync(WEBVIEW.window, {
|
||||||
|
type: "question",
|
||||||
|
title: "Confirm",
|
||||||
|
message: `\nExit ${APP.title}?`,
|
||||||
|
buttons: ["No", "Yes"],
|
||||||
|
});
|
||||||
|
if (button === 1) {
|
||||||
|
WEBVIEW.window.setStatus("Terminated");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -832,6 +927,33 @@ const viewEvents = async () => {
|
|||||||
* Register app events and handler.
|
* Register app events and handler.
|
||||||
*/
|
*/
|
||||||
const appEvents = async () => {
|
const appEvents = async () => {
|
||||||
|
// Handle global events
|
||||||
|
EVENTS.on("reloadView", reloadView);
|
||||||
|
EVENTS.on("updateView", updateView);
|
||||||
|
EVENTS.on("updateDisplay", () => {
|
||||||
|
const status = hardware.getDisplayStatus();
|
||||||
|
if (status) {
|
||||||
|
WEBVIEW.tracker.display[status.toLowerCase()] = new Date();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
EVENTS.on("updateStatus", () => {
|
||||||
|
const status = WEBVIEW.tracker.status;
|
||||||
|
const visibility = hardware.getKeyboardVisibility();
|
||||||
|
if (visibility === "ON" && ["Fullscreen", "Minimized"].includes(status)) {
|
||||||
|
hardware.setKeyboardVisibility("OFF");
|
||||||
|
}
|
||||||
|
toggleStatus(["Framed", "Minimized"].includes(status) ? "ON" : "OFF");
|
||||||
|
});
|
||||||
|
EVENTS.on("updateKeyboard", () => {
|
||||||
|
const status = WEBVIEW.tracker.status;
|
||||||
|
const visibility = hardware.getKeyboardVisibility();
|
||||||
|
if (visibility === "ON" && ["Fullscreen"].includes(status)) {
|
||||||
|
WEBVIEW.window.setStatus("Maximized");
|
||||||
|
} else if (visibility === "OFF" && ["Maximized"].includes(status)) {
|
||||||
|
WEBVIEW.window.setStatus("Fullscreen");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Handle multiple instances
|
// Handle multiple instances
|
||||||
app.on("second-instance", () => {
|
app.on("second-instance", () => {
|
||||||
if (WEBVIEW.window.isMinimized()) {
|
if (WEBVIEW.window.isMinimized()) {
|
||||||
@@ -840,10 +962,10 @@ const appEvents = async () => {
|
|||||||
WEBVIEW.window.focus();
|
WEBVIEW.window.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle signal and exit events
|
// Handle exit events
|
||||||
app.on("before-quit", () => {
|
app.on("before-quit", () => {
|
||||||
WEBVIEW.tracker.status = "Terminated";
|
WEBVIEW.tracker.status = "Terminated";
|
||||||
console.warn(`${APP.title} Terminated`);
|
console.warn(`${APP.title} ${WEBVIEW.tracker.status}`);
|
||||||
integration.update();
|
integration.update();
|
||||||
});
|
});
|
||||||
process.on("SIGINT", app.quit);
|
process.on("SIGINT", app.quit);
|
||||||
|
|||||||
Reference in New Issue
Block a user