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 />
|
icon: <ProductionIcon />
|
||||||
})
|
})
|
||||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
const isMobile = useMediaQuery({ maxWidth: 768 })
|
||||||
const { platform, isElectron, setSidebarViewMenu } =
|
const { platform, isElectron, setSidebarViewMenu, isFullscreen } =
|
||||||
useContext(ElectronContext)
|
useContext(ElectronContext)
|
||||||
const { availableUpdate, checkForUpdates } = useAppUpdateContext()
|
const { availableUpdate, checkForUpdates } = useAppUpdateContext()
|
||||||
const mainMenuItems = useMemo(
|
const mainMenuItems = useMemo(
|
||||||
@ -349,7 +349,7 @@ const DashboardNavigation = () => {
|
|||||||
<>
|
<>
|
||||||
{isElectron ? (
|
{isElectron ? (
|
||||||
<Flex
|
<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' }}
|
style={{ lineHeight: '40px', padding: '0 2px 0 2px' }}
|
||||||
>
|
>
|
||||||
{navigationContents}
|
{navigationContents}
|
||||||
|
|||||||
@ -184,6 +184,8 @@ function applyWindowsStartupWindowState(window) {
|
|||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.maximize?.()
|
window.maximize?.()
|
||||||
|
// maximize() settles asynchronously; sync state after the frame updates.
|
||||||
|
setTimeout(() => handleWindowsWindowChange(window), 100)
|
||||||
}, WINDOWS_STARTUP_MAXIMIZE_DELAY_MS)
|
}, WINDOWS_STARTUP_MAXIMIZE_DELAY_MS)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,17 +341,23 @@ export function handleWindowControl(action) {
|
|||||||
case 'minimize':
|
case 'minimize':
|
||||||
mainWindow.minimize?.()
|
mainWindow.minimize?.()
|
||||||
break
|
break
|
||||||
case 'maximize':
|
case 'maximize': {
|
||||||
if (mainWindow.isMaximized?.()) {
|
const currentlyMaximized = isWindows
|
||||||
|
? isWindowWorkAreaMaximized(mainWindow)
|
||||||
|
: (mainWindow.isMaximized?.() ?? false)
|
||||||
|
|
||||||
|
if (currentlyMaximized) {
|
||||||
mainWindow.unmaximize?.()
|
mainWindow.unmaximize?.()
|
||||||
} else {
|
} else {
|
||||||
mainWindow.maximize?.()
|
mainWindow.maximize?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWindows) {
|
if (isWindows) {
|
||||||
handleWindowsWindowChange(mainWindow)
|
// Frame updates after maximize/unmaximize are async on Windows.
|
||||||
|
setTimeout(() => handleWindowsWindowChange(mainWindow), 100)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
}
|
||||||
case 'fullscreen':
|
case 'fullscreen':
|
||||||
if (mainWindow.isFullScreen?.()) {
|
if (mainWindow.isFullScreen?.()) {
|
||||||
mainWindow.setFullScreen?.(false)
|
mainWindow.setFullScreen?.(false)
|
||||||
|
|||||||
@ -1,6 +1,15 @@
|
|||||||
import { Screen } from 'electrobun/bun'
|
import { Screen } from 'electrobun/bun'
|
||||||
|
|
||||||
const FRAME_TOLERANCE_PX = 4
|
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) {
|
function framesMatch(a, b, tolerance = FRAME_TOLERANCE_PX) {
|
||||||
return (
|
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) {
|
function getFrameCenter(frame) {
|
||||||
return {
|
return {
|
||||||
x: frame.x + frame.width / 2,
|
x: frame.x + frame.width / 2,
|
||||||
@ -50,7 +68,10 @@ export function isWindowWorkAreaMaximized(window) {
|
|||||||
|
|
||||||
const frame = window.getFrame()
|
const frame = window.getFrame()
|
||||||
const { workArea } = getDisplayForFrame(frame)
|
const { workArea } = getDisplayForFrame(frame)
|
||||||
return framesMatch(frame, workArea)
|
return (
|
||||||
|
framesMatch(frame, workArea) ||
|
||||||
|
framesMatch(frame, getMaximizedWorkAreaFrame(workArea))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clampWindowToWorkArea(window) {
|
export function clampWindowToWorkArea(window) {
|
||||||
@ -69,8 +90,9 @@ export function clampWindowToWorkArea(window) {
|
|||||||
|
|
||||||
const display = getDisplayForFrame(frame)
|
const display = getDisplayForFrame(frame)
|
||||||
const { bounds, workArea } = display
|
const { bounds, workArea } = display
|
||||||
|
const maximizedFrame = getMaximizedWorkAreaFrame(workArea)
|
||||||
|
|
||||||
if (framesMatch(frame, workArea)) {
|
if (framesMatch(frame, workArea) || framesMatch(frame, maximizedFrame)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +100,11 @@ export function clampWindowToWorkArea(window) {
|
|||||||
return false
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user