Implement comprehensive window resizing and responsive design
Major UX enhancement with full window resize support and responsive layouts: ## Enhanced Electron Window Configuration: - Explicitly enabled resizable and maximizable options - Improved default window size handling - Better titleBar integration for native controls - Maintained minimum size constraints (800x600) ## � Window State Memory System: - Automatically saves and restores window size, position, and maximized state - State persisted in userData/window-state.json - Graceful fallback to defaults if saved state is invalid - Real-time state saving on resize, move, maximize/unmaximize events ## Comprehensive Responsive Design: ### Layout Improvements: - Increased max-width from 800px to 1400px for larger screens - Added min-width constraints to prevent layout breaking - Centered container with appropriate margins ### Media Query Breakpoints: - **Large Screens (1200px+)**: Multi-column layouts, larger fonts, better space utilization - **Medium Screens (900-1199px)**: Balanced layouts with flexible button arrangements - **Small Screens (<899px)**: Compact layouts while maintaining usability - **Ultra-wide (1600px+)**: Enhanced gallery layouts with more columns - **Retina/High-DPI**: Enhanced shadows and visual polish ### Smart Layout Adaptations: - Main action buttons: Row layout on larger screens, column on smaller - Game mode selection: Grid layout on wide screens, stacked on narrow - Image/Audio galleries: Dynamic column counts based on available space - Task display: Optimal sizing for different screen sizes - Management screens: Better use of horizontal space ## User Experience Benefits: - Window size preferences remembered between sessions - Better space utilization on all screen sizes - Improved readability and usability at different resolutions - Native window controls work properly (maximize, resize corners) - Professional desktop app experience with proper window management ## Technical Implementation: - Window state JSON persistence in user data directory - Event-driven state saving (resize, move, maximize events) - CSS Grid and Flexbox for responsive layouts - Media queries for different screen size optimizations - Maintains backward compatibility with existing layouts **Now the app works beautifully at any window size! **
This commit is contained in:
parent
ab26d61904
commit
18a4a7925c
80
main.js
80
main.js
|
|
@ -4,12 +4,67 @@ const fs = require('fs').promises;
|
|||
|
||||
let mainWindow;
|
||||
|
||||
function createWindow() {
|
||||
// Window state management
|
||||
let windowState = {
|
||||
width: 1200,
|
||||
height: 800,
|
||||
x: undefined,
|
||||
y: undefined,
|
||||
isMaximized: false
|
||||
};
|
||||
|
||||
// Load saved window state
|
||||
async function loadWindowState() {
|
||||
try {
|
||||
const stateFile = path.join(app.getPath('userData'), 'window-state.json');
|
||||
const data = await fs.readFile(stateFile, 'utf8');
|
||||
const savedState = JSON.parse(data);
|
||||
|
||||
// Validate saved state
|
||||
if (savedState.width && savedState.height &&
|
||||
savedState.width >= 800 && savedState.height >= 600) {
|
||||
windowState = { ...windowState, ...savedState };
|
||||
}
|
||||
} catch (error) {
|
||||
// File doesn't exist or is invalid, use defaults
|
||||
console.log('Using default window state');
|
||||
}
|
||||
}
|
||||
|
||||
// Save window state
|
||||
async function saveWindowState() {
|
||||
try {
|
||||
if (mainWindow) {
|
||||
const bounds = mainWindow.getBounds();
|
||||
const isMaximized = mainWindow.isMaximized();
|
||||
|
||||
if (!isMaximized) {
|
||||
windowState = { ...bounds, isMaximized: false };
|
||||
} else {
|
||||
windowState.isMaximized = true;
|
||||
}
|
||||
|
||||
const stateFile = path.join(app.getPath('userData'), 'window-state.json');
|
||||
await fs.writeFile(stateFile, JSON.stringify(windowState, null, 2));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to save window state:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function createWindow() {
|
||||
// Load saved window state
|
||||
await loadWindowState();
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
width: windowState.width,
|
||||
height: windowState.height,
|
||||
x: windowState.x,
|
||||
y: windowState.y,
|
||||
minWidth: 800,
|
||||
minHeight: 600,
|
||||
resizable: true,
|
||||
maximizable: true,
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
|
|
@ -17,11 +72,28 @@ function createWindow() {
|
|||
preload: path.join(__dirname, 'preload.js')
|
||||
},
|
||||
icon: path.join(__dirname, 'assets', 'icon.png'),
|
||||
show: false
|
||||
show: false,
|
||||
titleBarStyle: 'default'
|
||||
});
|
||||
|
||||
mainWindow.loadFile('index.html');
|
||||
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
if (windowState.isMaximized) {
|
||||
mainWindow.maximize();
|
||||
}
|
||||
mainWindow.show();
|
||||
});
|
||||
|
||||
// Save window state when it changes
|
||||
mainWindow.on('resize', saveWindowState);
|
||||
mainWindow.on('move', saveWindowState);
|
||||
mainWindow.on('maximize', saveWindowState);
|
||||
mainWindow.on('unmaximize', saveWindowState);
|
||||
|
||||
// Save state before closing
|
||||
mainWindow.on('close', saveWindowState);
|
||||
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
mainWindow.show();
|
||||
});
|
||||
|
|
|
|||
152
styles.css
152
styles.css
|
|
@ -19,9 +19,11 @@ body {
|
|||
border-radius: 15px;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||||
width: 95%;
|
||||
max-width: 800px;
|
||||
max-width: 1400px; /* Increased from 800px for larger screens */
|
||||
min-width: 780px; /* Ensure minimum usable width */
|
||||
min-height: 600px;
|
||||
overflow: hidden;
|
||||
margin: 10px auto; /* Center and add some margin */
|
||||
}
|
||||
|
||||
/* Header */
|
||||
|
|
@ -1738,4 +1740,152 @@ body.theme-monochrome {
|
|||
|
||||
.audio-item[data-category="effects"] .audio-icon::before {
|
||||
content: "🔊";
|
||||
}
|
||||
|
||||
/* ===========================
|
||||
RESPONSIVE DESIGN ENHANCEMENTS
|
||||
=========================== */
|
||||
|
||||
/* Large screens - take advantage of extra space */
|
||||
@media (min-width: 1200px) {
|
||||
.game-container {
|
||||
width: 90%;
|
||||
max-width: 1400px;
|
||||
}
|
||||
|
||||
.game-header h1 {
|
||||
font-size: 2.2em;
|
||||
}
|
||||
|
||||
/* Make better use of horizontal space */
|
||||
.main-actions {
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.main-actions .btn {
|
||||
width: auto;
|
||||
min-width: 200px;
|
||||
max-width: 250px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Multi-column layouts for management screens */
|
||||
.image-gallery, .audio-gallery {
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
/* Game mode selection in columns */
|
||||
.game-mode-options {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Medium screens - balanced layout */
|
||||
@media (min-width: 900px) and (max-width: 1199px) {
|
||||
.game-container {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.main-actions {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.main-actions .btn {
|
||||
width: auto;
|
||||
min-width: 180px;
|
||||
max-width: 220px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Small screens - compact layout */
|
||||
@media (max-width: 899px) {
|
||||
.game-container {
|
||||
width: 98%;
|
||||
margin: 5px auto;
|
||||
border-radius: 10px;
|
||||
min-width: 760px; /* Ensure minimum usability */
|
||||
}
|
||||
|
||||
.game-header {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.game-header h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
.main-actions {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.main-actions .btn {
|
||||
width: 100%;
|
||||
max-width: 280px;
|
||||
}
|
||||
|
||||
/* Compact game mode selection */
|
||||
.game-mode-selection {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.game-mode-option label {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/* Adjust image and audio galleries */
|
||||
.image-gallery, .audio-gallery {
|
||||
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle very wide screens */
|
||||
@media (min-width: 1600px) {
|
||||
.game-container {
|
||||
max-width: 1600px;
|
||||
}
|
||||
|
||||
.game-content {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
/* Use more columns for galleries on wide screens */
|
||||
.image-gallery, .audio-gallery {
|
||||
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure game screen task display scales well */
|
||||
@media (min-width: 1000px) {
|
||||
.task-display {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.task-image {
|
||||
max-height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
/* High DPI / Retina display adjustments */
|
||||
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
|
||||
.game-container {
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.btn {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue