Fixed sized

This commit is contained in:
2026-01-01 16:46:38 +01:00
parent 668aec4062
commit 217ecea74a
2 changed files with 80 additions and 36 deletions

View File

@@ -2,8 +2,8 @@ const { app, BrowserWindow } = require('electron');
function createWindow() { function createWindow() {
const url = process.env.ELECTRON_START_URL || "https://imgfloat.kruhlmann.dev/channels"; const url = process.env.ELECTRON_START_URL || "https://imgfloat.kruhlmann.dev/channels";
const width = Number.parseInt(process.env.ELECTRON_WINDOW_WIDTH, 10) || 1920; const width = Number.parseInt(process.env.ELECTRON_WINDOW_WIDTH, 10) || 960;
const height = Number.parseInt(process.env.ELECTRON_WINDOW_HEIGHT, 10) || 1080; const height = Number.parseInt(process.env.ELECTRON_WINDOW_HEIGHT, 10) || 640;
const win = new BrowserWindow({ const win = new BrowserWindow({
width: width, width: width,
@@ -17,6 +17,65 @@ function createWindow() {
} }
}); });
let canvasSizeInterval;
const clearCanvasSizeInterval = () => {
if (canvasSizeInterval) {
clearInterval(canvasSizeInterval);
canvasSizeInterval = undefined;
}
};
const lockWindowToCanvas = async () => {
if (win.isDestroyed()) {
return false;
}
try {
const size = await win.webContents.executeJavaScript(`(() => {
const canvas = document.getElementById('broadcast-canvas');
if (!canvas || !canvas.width || !canvas.height) {
return null;
}
return { width: Math.round(canvas.width), height: Math.round(canvas.height) };
})();`);
if (size?.width && size?.height) {
const [currentWidth, currentHeight] = win.getSize();
if (currentWidth !== size.width || currentHeight !== size.height) {
win.setSize(size.width, size.height, false);
}
win.setMinimumSize(size.width, size.height);
win.setMaximumSize(size.width, size.height);
win.setResizable(false);
return true;
}
} catch (error) {
// Best-effort sizing; ignore errors from early navigation states.
}
return false;
};
const handleNavigation = (navigationUrl) => {
try {
const { pathname } = new URL(navigationUrl);
const isBroadcast = /\\/view\\/[^/]+\\/broadcast\\/?$/.test(pathname);
if (isBroadcast) {
clearCanvasSizeInterval();
canvasSizeInterval = setInterval(lockWindowToCanvas, 750);
lockWindowToCanvas();
} else {
clearCanvasSizeInterval();
win.setResizable(true);
win.setMinimumSize(320, 240);
win.setMaximumSize(10000, 10000);
win.setSize(width, height, false);
}
} catch {
// Ignore malformed URLs while navigating.
}
};
win.loadURL(url); win.loadURL(url);
win.webContents.on('did-finish-load', () => { win.webContents.on('did-finish-load', () => {
@@ -26,6 +85,10 @@ function createWindow() {
user-select: none; user-select: none;
} }
body {
transition: opacity 120ms ease;
}
a, button, input, select, textarea, option, [role="button"], [role="textbox"] { a, button, input, select, textarea, option, [role="button"], [role="textbox"] {
-webkit-app-region: no-drag; -webkit-app-region: no-drag;
user-select: auto; user-select: auto;
@@ -33,42 +96,32 @@ function createWindow() {
`); `);
win.webContents.executeJavaScript(`(() => { win.webContents.executeJavaScript(`(() => {
const overlayId = 'imgfloat-drag-overlay'; const body = document.body;
if (!document.getElementById(overlayId)) { if (!body) {
const overlay = document.createElement('div'); return;
overlay.id = overlayId;
Object.assign(overlay.style, {
position: 'fixed',
inset: '0',
background: 'rgba(0, 0, 0, 0)',
transition: 'background 120ms ease',
pointerEvents: 'none',
zIndex: '2147483647',
webkitAppRegion: 'drag'
});
document.documentElement.appendChild(overlay);
} }
const defaultOpacity = getComputedStyle(body).opacity || '1';
const overlay = document.getElementById(overlayId);
let timeout; let timeout;
window.__imgfloatShowDragOverlay = () => { window.__imgfloatShowDragOverlay = () => {
if (!overlay) { body.style.opacity = '0.9';
return;
}
overlay.style.background = 'rgba(0, 0, 0, 0.35)';
clearTimeout(timeout); clearTimeout(timeout);
timeout = setTimeout(() => { timeout = setTimeout(() => {
overlay.style.background = 'rgba(0, 0, 0, 0)'; body.style.opacity = defaultOpacity;
}, 150); }, 150);
}; };
})();`); })();`);
handleNavigation(win.webContents.getURL());
}); });
win.on('move', () => { win.on('move', () => {
win.webContents.executeJavaScript('window.__imgfloatShowDragOverlay && window.__imgfloatShowDragOverlay();'); win.webContents.executeJavaScript('window.__imgfloatShowDragOverlay && window.__imgfloatShowDragOverlay();');
}); });
win.webContents.on('did-navigate', (_event, navigationUrl) => handleNavigation(navigationUrl));
win.webContents.on('did-navigate-in-page', (_event, navigationUrl) => handleNavigation(navigationUrl));
win.on('closed', clearCanvasSizeInterval);
} }
app.whenReady().then(() => { app.whenReady().then(() => {

View File

@@ -8,13 +8,6 @@ document.addEventListener("DOMContentLoaded", () => {
return; return;
} }
function keepInputFocused() {
if (document.activeElement !== searchInput) {
searchInput.focus({ preventScroll: true });
searchInput.select();
}
}
let channels = []; let channels = [];
function updateSuggestions(term) { function updateSuggestions(term) {
@@ -44,10 +37,10 @@ document.addEventListener("DOMContentLoaded", () => {
} }
} }
searchInput.focus({ preventScroll: true });
searchInput.select();
searchInput.addEventListener("input", (event) => updateSuggestions(event.target.value || "")); searchInput.addEventListener("input", (event) => updateSuggestions(event.target.value || ""));
searchInput.addEventListener("blur", () => {
requestAnimationFrame(keepInputFocused);
});
searchForm.addEventListener("submit", (event) => { searchForm.addEventListener("submit", (event) => {
event.preventDefault(); event.preventDefault();
@@ -59,7 +52,5 @@ document.addEventListener("DOMContentLoaded", () => {
window.location.href = `/view/${encodeURIComponent(broadcaster)}/broadcast`; window.location.href = `/view/${encodeURIComponent(broadcaster)}/broadcast`;
}); });
keepInputFocused();
window.addEventListener("focus", keepInputFocused);
loadChannels(); loadChannels();
}); });