feat(window): maximize toggle + drag-zone fix + minWidth bump
- Средняя кнопка тайтлбара теперь toggle maximize/restore (была hide-to-tray, но иконка Square вводила в заблуждение — выглядит как нативная maximize). Double-click по тайтлбару тоже работает. - Иконка свапается Square ↔ Copy в зависимости от max-state, aria-label локализован (titlebar.maximize_aria / restore_aria). - Новый IPC: toggleMaximizeMain, isMaximizedMain (invoke), evtMaximizeChanged (event main → renderer на maximize/unmaximize). - Фикс drag-зоны: titlebar-nodrag перенесён с обёртки правого кластера на сами кнопки. Из-за flex-1 basis-0 пустое место слева от кнопок раньше было no-drag — окно нельзя было ухватить рядом. - minWidth/minHeight окна 900x600 → 1100x700, чтобы Tailwind lg: всегда срабатывал (4 hero-stat в один ряд, heatmap без скролла). - CLAUDE.md: контекст проекта для будущих сессий Claude Code (стек, архитектура, команды, релиз, тех. долг, чего не делать).
This commit is contained in:
@@ -176,6 +176,17 @@ export function registerIpc(): void {
|
||||
BrowserWindow.fromWebContents(event.sender)?.minimize()
|
||||
})
|
||||
|
||||
ipcMain.on(IPC.toggleMaximizeMain, (event) => {
|
||||
const win = BrowserWindow.fromWebContents(event.sender)
|
||||
if (!win) return
|
||||
if (win.isMaximized()) win.unmaximize()
|
||||
else win.maximize()
|
||||
})
|
||||
|
||||
ipcMain.handle(IPC.isMaximizedMain, (event) => {
|
||||
return BrowserWindow.fromWebContents(event.sender)?.isMaximized() ?? false
|
||||
})
|
||||
|
||||
ipcMain.on(IPC.closeMain, () => {
|
||||
const main = getMainWindow()
|
||||
if (!main) return
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BrowserWindow, shell, screen, app, nativeImage } from 'electron'
|
||||
import { IPC } from '../shared/ipc'
|
||||
import { existsSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
|
||||
@@ -90,8 +91,13 @@ export function createMainWindow(showImmediately = true): BrowserWindow {
|
||||
const win = new BrowserWindow({
|
||||
width: 1100,
|
||||
height: 720,
|
||||
minWidth: 900,
|
||||
minHeight: 600,
|
||||
// Минимум подобран так, чтобы:
|
||||
// - срабатывал Tailwind `lg:` (≥1024px) → 4 hero-stat в один ряд, а не 2×2
|
||||
// - сайдбар (256px) + контент (max-w-5xl, padding lg:px-10) помещались без
|
||||
// горизонтального скролла heatmap'а и карточек упражнений
|
||||
// - по вертикали оставался запас на header + stats + heatmap без обрезки
|
||||
minWidth: 1100,
|
||||
minHeight: 700,
|
||||
show: false,
|
||||
frame: false,
|
||||
backgroundColor: '#0f1117',
|
||||
@@ -110,6 +116,16 @@ export function createMainWindow(showImmediately = true): BrowserWindow {
|
||||
if (showImmediately) win.show()
|
||||
})
|
||||
|
||||
// Сообщаем рендереру об изменении max-состояния, чтобы он мог менять
|
||||
// иконку (квадрат ↔ «двойной квадрат») в кастомном тайтлбаре.
|
||||
const emitMaxState = (maximized: boolean): void => {
|
||||
if (!win.isDestroyed()) {
|
||||
win.webContents.send(IPC.evtMaximizeChanged, maximized)
|
||||
}
|
||||
}
|
||||
win.on('maximize', () => emitMaxState(true))
|
||||
win.on('unmaximize', () => emitMaxState(false))
|
||||
|
||||
installSafeNavigation(win)
|
||||
|
||||
loadRoute(win, 'main')
|
||||
|
||||
Reference in New Issue
Block a user