Enhance window management and navigation handling
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
- Added `isFullscreen` context to `DashboardNavigation` for improved UI responsiveness. - Updated navigation class logic to conditionally apply styles based on fullscreen state. - Refined window control logic in `window.js` to handle maximize/unmaximize actions more reliably, including asynchronous state synchronization on Windows. - Introduced adjustments for window frame dimensions in `windows-work-area.js` to account for Win32 DWM overhangs, ensuring accurate maximized state detection and clamping.
This commit is contained in:
parent
eb1ee1e82b
commit
d28bed7136
@ -64,7 +64,7 @@ const DashboardNavigation = () => {
|
||||
icon: <ProductionIcon />
|
||||
})
|
||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
||||
const { platform, isElectron, setSidebarViewMenu } =
|
||||
const { platform, isElectron, setSidebarViewMenu, isFullscreen } =
|
||||
useContext(ElectronContext)
|
||||
const { availableUpdate, checkForUpdates } = useAppUpdateContext()
|
||||
const mainMenuItems = useMemo(
|
||||
@ -349,7 +349,7 @@ const DashboardNavigation = () => {
|
||||
<>
|
||||
{isElectron ? (
|
||||
<Flex
|
||||
className={`ant-menu-horizontal ant-menu-light${!notificationCenterVisible ? ' electron-navigation-wrapper electrobun-webkit-app-region-drag' : ''}`}
|
||||
className={`ant-menu-horizontal ant-menu-light${!notificationCenterVisible && !isFullscreen ? ' electron-navigation-wrapper electrobun-webkit-app-region-drag' : ''}`}
|
||||
style={{ lineHeight: '40px', padding: '0 2px 0 2px' }}
|
||||
>
|
||||
{navigationContents}
|
||||
|
||||
@ -184,6 +184,8 @@ function applyWindowsStartupWindowState(window) {
|
||||
|
||||
setTimeout(() => {
|
||||
window.maximize?.()
|
||||
// maximize() settles asynchronously; sync state after the frame updates.
|
||||
setTimeout(() => handleWindowsWindowChange(window), 100)
|
||||
}, WINDOWS_STARTUP_MAXIMIZE_DELAY_MS)
|
||||
}
|
||||
|
||||
@ -339,17 +341,23 @@ export function handleWindowControl(action) {
|
||||
case 'minimize':
|
||||
mainWindow.minimize?.()
|
||||
break
|
||||
case 'maximize':
|
||||
if (mainWindow.isMaximized?.()) {
|
||||
case 'maximize': {
|
||||
const currentlyMaximized = isWindows
|
||||
? isWindowWorkAreaMaximized(mainWindow)
|
||||
: (mainWindow.isMaximized?.() ?? false)
|
||||
|
||||
if (currentlyMaximized) {
|
||||
mainWindow.unmaximize?.()
|
||||
} else {
|
||||
mainWindow.maximize?.()
|
||||
}
|
||||
|
||||
if (isWindows) {
|
||||
handleWindowsWindowChange(mainWindow)
|
||||
// Frame updates after maximize/unmaximize are async on Windows.
|
||||
setTimeout(() => handleWindowsWindowChange(mainWindow), 100)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'fullscreen':
|
||||
if (mainWindow.isFullScreen?.()) {
|
||||
mainWindow.setFullScreen?.(false)
|
||||
|
||||
@ -1,6 +1,15 @@
|
||||
import { Screen } from 'electrobun/bun'
|
||||
|
||||
const FRAME_TOLERANCE_PX = 4
|
||||
// Win32 DWM invisible borders sit outside the client work area; Electrobun's
|
||||
// maximized frame includes those overhangs, so we treat this adjusted rect as
|
||||
// the canonical "maximized to work area" geometry.
|
||||
const WIN32_FRAME_OVERHANG = {
|
||||
x: -8,
|
||||
y: 0,
|
||||
width: 16,
|
||||
height: 8
|
||||
}
|
||||
|
||||
function framesMatch(a, b, tolerance = FRAME_TOLERANCE_PX) {
|
||||
return (
|
||||
@ -11,6 +20,15 @@ function framesMatch(a, b, tolerance = FRAME_TOLERANCE_PX) {
|
||||
)
|
||||
}
|
||||
|
||||
function getMaximizedWorkAreaFrame(workArea) {
|
||||
return {
|
||||
x: workArea.x + WIN32_FRAME_OVERHANG.x,
|
||||
y: workArea.y + WIN32_FRAME_OVERHANG.y,
|
||||
width: workArea.width + WIN32_FRAME_OVERHANG.width,
|
||||
height: workArea.height + WIN32_FRAME_OVERHANG.height
|
||||
}
|
||||
}
|
||||
|
||||
function getFrameCenter(frame) {
|
||||
return {
|
||||
x: frame.x + frame.width / 2,
|
||||
@ -50,7 +68,10 @@ export function isWindowWorkAreaMaximized(window) {
|
||||
|
||||
const frame = window.getFrame()
|
||||
const { workArea } = getDisplayForFrame(frame)
|
||||
return framesMatch(frame, workArea)
|
||||
return (
|
||||
framesMatch(frame, workArea) ||
|
||||
framesMatch(frame, getMaximizedWorkAreaFrame(workArea))
|
||||
)
|
||||
}
|
||||
|
||||
export function clampWindowToWorkArea(window) {
|
||||
@ -69,8 +90,9 @@ export function clampWindowToWorkArea(window) {
|
||||
|
||||
const display = getDisplayForFrame(frame)
|
||||
const { bounds, workArea } = display
|
||||
const maximizedFrame = getMaximizedWorkAreaFrame(workArea)
|
||||
|
||||
if (framesMatch(frame, workArea)) {
|
||||
if (framesMatch(frame, workArea) || framesMatch(frame, maximizedFrame)) {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -78,6 +100,11 @@ export function clampWindowToWorkArea(window) {
|
||||
return false
|
||||
}
|
||||
|
||||
window.setFrame(workArea.x - 8, workArea.y, workArea.width + 16, workArea.height + 8)
|
||||
window.setFrame(
|
||||
maximizedFrame.x,
|
||||
maximizedFrame.y,
|
||||
maximizedFrame.width,
|
||||
maximizedFrame.height
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user