fix: kiosk toggle sync, load more animation, remove nsis target

This commit is contained in:
2026-03-14 12:48:29 +03:00
parent c31e4a304d
commit 14da54f204
77 changed files with 485 additions and 1424 deletions

107
main.js
View File

@@ -163,6 +163,8 @@ async function createWindow() {
mainWindow = new BrowserWindow({
width: 1280,
height: 800,
kiosk: true,
autoHideMenuBar: true,
webPreferences: {
preload: PRELOAD_PATH,
contextIsolation: true,
@@ -214,17 +216,11 @@ function setLoader() {
loaderView = new WebContentsView({ webPreferences: { contextIsolation: true, nodeIntegration: false } });
addChild(loaderView);
loaderView.setBounds({ x: 0, y: HEADER_H, width, height: height - HEADER_H });
const html = `<html><head><style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#111;display:flex;align-items:center;justify-content:center;height:100vh;transition:opacity 0.25s ease;opacity:0}
body.visible{opacity:1}
.spinner{width:36px;height:36px;border:3px solid rgba(255,255,255,0.1);border-top-color:#E50914;border-radius:50%;animation:spin 0.7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
</style></head><body>
<div class="spinner"></div>
<script>requestAnimationFrame(()=>requestAnimationFrame(()=>document.body.classList.add('visible')))</script>
</body></html>`;
loaderView.webContents.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(html));
if (isDev) {
loaderView.webContents.loadURL(`${RENDERER_URL}/loader.html`);
} else {
loaderView.webContents.loadFile(path.join(__dirname, 'dist', 'loader.html'));
}
}
function removeLoader() {
@@ -237,41 +233,6 @@ function removeLoader() {
// --- Dialogs (WebContentsView overlays) ---
const DIALOG_STYLES = `
*{margin:0;padding:0;box-sizing:border-box}
body{
background:rgba(0,0,0,0);
display:flex;align-items:center;justify-content:center;
height:100vh;
font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
transition:background 0.22s ease;
}
body.visible{background:rgba(0,0,0,0.78)}
body.hiding{background:rgba(0,0,0,0)}
.card{
background:#1c1c1c;border:1px solid rgba(255,255,255,0.1);
border-radius:12px;padding:32px 36px;text-align:center;
min-width:300px;max-width:420px;box-shadow:0 24px 64px rgba(0,0,0,0.8);
opacity:0;transform:scale(0.92) translateY(10px);
transition:opacity 0.22s ease,transform 0.22s cubic-bezier(0.34,1.56,0.64,1);
}
body.visible .card{opacity:1;transform:scale(1) translateY(0)}
body.hiding .card{opacity:0;transform:scale(0.95) translateY(6px)}
.title{font-size:17px;font-weight:700;color:#fff;margin-bottom:10px}
.msg{font-size:13px;color:#999;line-height:1.5;margin-bottom:26px}
.btns{display:flex;gap:10px;justify-content:center}
button{padding:10px 26px;border:none;border-radius:7px;font-size:13px;font-weight:600;cursor:pointer;transition:opacity 0.15s,transform 0.1s}
button:hover{opacity:0.85} button:active{transform:scale(0.97)}
.btn-yes{background:#E50914;color:#fff}
.btn-no,.btn-ok{background:rgba(255,255,255,0.1);color:#ccc}
`;
function dialogFadeIn(view) {
view.webContents.executeJavaScript(
`requestAnimationFrame(()=>requestAnimationFrame(()=>document.body.classList.add('visible')))`
).catch(() => {});
}
function dialogFadeOut(view, cb) {
view.webContents.executeJavaScript(
`document.body.classList.remove('visible');document.body.classList.add('hiding')`
@@ -292,15 +253,13 @@ function makeDialogView() {
function setError(title, text) {
const view = makeDialogView();
errorViews.push(view);
const html = `<html><head><style>${DIALOG_STYLES}</style></head><body>
<div class="card">
<div class="title">${title}</div>
<div class="msg">${text}</div>
<div class="btns"><button class="btn-ok" onclick="window.electron&&window.electron.handleAction('error')">Закрыть</button></div>
</div>
</body></html>`;
view.webContents.once('did-finish-load', () => { addChild(view); dialogFadeIn(view); });
view.webContents.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(html));
const query = new URLSearchParams({ title: title || '', text: text || '' }).toString();
view.webContents.once('did-finish-load', () => { addChild(view); });
if (isDev) {
view.webContents.loadURL(`${RENDERER_URL}/dialog-error.html?${query}`);
} else {
view.webContents.loadFile(path.join(__dirname, 'dist', 'dialog-error.html'), { query: { title: title || '', text: text || '' } });
}
}
function removeError() {
@@ -312,17 +271,13 @@ function removeError() {
function setConfirm(text, actionOnYes) {
const view = makeDialogView();
confirmViews.push({ view, actionOnYes });
const html = `<html><head><style>${DIALOG_STYLES}</style></head><body>
<div class="card">
<div class="msg">${text}</div>
<div class="btns">
<button class="btn-yes" onclick="window.electron&&window.electron.handleAction('confirmYes')">Да</button>
<button class="btn-no" onclick="window.electron&&window.electron.handleAction('confirmNo')">Нет</button>
</div>
</div>
</body></html>`;
view.webContents.once('did-finish-load', () => { addChild(view); dialogFadeIn(view); });
view.webContents.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(html));
const query = new URLSearchParams({ text: text || '' }).toString();
view.webContents.once('did-finish-load', () => { addChild(view); });
if (isDev) {
view.webContents.loadURL(`${RENDERER_URL}/dialog-confirm.html?${query}`);
} else {
view.webContents.loadFile(path.join(__dirname, 'dist', 'dialog-confirm.html'), { query: { text: text || '' } });
}
}
function removeConfirm() {
@@ -835,7 +790,21 @@ ipcMain.on('write-config', (_event, data) => {
}
});
ipcMain.on('confirm', (_event, text, actionOnYes) => setConfirm(text, actionOnYes));
ipcMain.handle('is-kiosk', () => mainWindow.isKiosk());
ipcMain.handle('toggle-kiosk', () => {
if (mainWindow.isKiosk()) {
mainWindow.setKiosk(false);
mainWindow.maximize();
mainWindow.setMenuBarVisibility(false);
return false;
} else {
mainWindow.setKiosk(true);
return true;
}
});
ipcMain.on('confirm',(_event, text, actionOnYes) => setConfirm(text, actionOnYes));
ipcMain.on('action', (_event, action) => {
if (action === 'error') {
@@ -889,8 +858,8 @@ app.whenReady().then(async () => {
} catch (_) {}
enableBlockingInSession(session.defaultSession);
enableBlockingInSession(session.fromPartition('persist:proxy'));
enableBlockingInSession(session.fromPartition('persist:direct'));
getProxySession();
getDirectSession();
await loadExtensions();
await createWindow();
});